mirror of
https://github.com/a-b-street/abstreet.git
synced 2025-01-03 12:03:30 +03:00
add in a shim to collect contextual actions. just silently pass-through to old behavior for now.
This commit is contained in:
parent
14f4dc2e3c
commit
061aed2624
@ -176,9 +176,9 @@ impl State for ABTestMode {
|
||||
.and_then(|id| id.agent_id())
|
||||
{
|
||||
if let Some(trip) = ui.primary.sim.agent_to_trip(agent) {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::B, format!("Show {}'s parallel world", agent))
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::B, format!("Show {}'s parallel world", agent))
|
||||
{
|
||||
self.diff_trip = Some(DiffOneTrip::new(
|
||||
trip,
|
||||
|
@ -39,10 +39,7 @@ impl AgentTools {
|
||||
.and_then(|id| id.agent_id())
|
||||
{
|
||||
if let Some(trip) = ui.primary.sim.agent_to_trip(agent) {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::F, format!("follow {}", agent))
|
||||
{
|
||||
if ui.per_obj.action(ctx, Key::F, format!("follow {}", agent)) {
|
||||
self.following = Some((
|
||||
trip,
|
||||
ui.primary
|
||||
@ -123,10 +120,7 @@ impl AgentTools {
|
||||
.and_then(|id| id.agent_id())
|
||||
.and_then(|agent| ui.primary.sim.agent_to_trip(agent))
|
||||
{
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::T, format!("explore {}", trip))
|
||||
{
|
||||
if ui.per_obj.action(ctx, Key::T, format!("explore {}", trip)) {
|
||||
return Some(Transition::Push(Box::new(TripExplorer::new(trip, ctx, ui))));
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ impl CommonState {
|
||||
}
|
||||
|
||||
if let Some(ref id) = ui.primary.current_selection {
|
||||
if ctx.input.contextual_action(Key::I, "info") || ctx.normal_left_click() {
|
||||
if ui.per_obj.action(ctx, Key::I, "info") || ctx.normal_left_click() {
|
||||
return Some(Transition::Push(Box::new(info::InfoPanel::new(
|
||||
id.clone(),
|
||||
ui,
|
||||
|
@ -20,7 +20,7 @@ impl RouteExplorer {
|
||||
.and_then(|id| id.agent_id())?;
|
||||
let path = ui.primary.sim.get_path(agent)?.clone();
|
||||
|
||||
if !ctx.input.contextual_action(Key::E, "explore route") {
|
||||
if !ui.per_obj.action(ctx, Key::E, "explore route") {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -52,9 +52,9 @@ impl RouteViewer {
|
||||
if let RouteViewer::Hovering(_, agent, _) = self {
|
||||
// If there's a current route, then there must be a trip.
|
||||
let trip = ui.primary.sim.agent_to_trip(*agent).unwrap();
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::R, format!("show {}'s route", agent))
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::R, format!("show {}'s route", agent))
|
||||
{
|
||||
*self = show_route(trip, ui, ctx);
|
||||
menu.push_action(hotkey(Key::R), "stop showing agent's route", ctx);
|
||||
|
@ -18,17 +18,17 @@ impl TurnCyclerState {
|
||||
if let TurnCyclerState::CycleTurns(current, idx) = self {
|
||||
if *current != id {
|
||||
*self = TurnCyclerState::ShowLane(id);
|
||||
} else if ctx
|
||||
.input
|
||||
.contextual_action(Key::Z, "cycle through this lane's turns")
|
||||
} else if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::Z, "cycle through this lane's turns")
|
||||
{
|
||||
*self = TurnCyclerState::CycleTurns(id, *idx + 1);
|
||||
}
|
||||
} else {
|
||||
*self = TurnCyclerState::ShowLane(id);
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::Z, "cycle through this lane's turns")
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::Z, "cycle through this lane's turns")
|
||||
{
|
||||
*self = TurnCyclerState::CycleTurns(id, 0);
|
||||
}
|
||||
@ -36,9 +36,9 @@ impl TurnCyclerState {
|
||||
}
|
||||
Some(ID::Intersection(i)) => {
|
||||
if let Some(ref signal) = ui.primary.map.maybe_get_traffic_signal(i) {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::F, "show full traffic signal diagram")
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::F, "show full traffic signal diagram")
|
||||
{
|
||||
ui.primary.current_selection = None;
|
||||
let (idx, _, _) =
|
||||
|
@ -20,14 +20,11 @@ impl Floodfiller {
|
||||
if !lt.supports_any_movement() {
|
||||
return None;
|
||||
}
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::F, "floodfill from this lane")
|
||||
{
|
||||
if ui.per_obj.action(ctx, Key::F, "floodfill from this lane") {
|
||||
find_reachable_from(l, map)
|
||||
} else if ctx
|
||||
.input
|
||||
.contextual_action(Key::S, "show strongly-connected components")
|
||||
} else if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::S, "show strongly-connected components")
|
||||
{
|
||||
let constraints = PathConstraints::from_lt(lt);
|
||||
let (good, bad) = connectivity::find_scc(map, constraints);
|
||||
|
@ -188,10 +188,7 @@ impl State for DebugMode {
|
||||
match ui.primary.current_selection {
|
||||
Some(ID::Lane(_)) | Some(ID::Intersection(_)) | Some(ID::ExtraShape(_)) => {
|
||||
let id = ui.primary.current_selection.clone().unwrap();
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::H, format!("hide {:?}", id))
|
||||
{
|
||||
if ui.per_obj.action(ctx, Key::H, format!("hide {:?}", id)) {
|
||||
println!("Hiding {:?}", id);
|
||||
ui.primary.current_selection = None;
|
||||
if self.hidden.is_empty() {
|
||||
@ -212,17 +209,14 @@ impl State for DebugMode {
|
||||
}
|
||||
|
||||
if let Some(ID::Car(id)) = ui.primary.current_selection {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::Backspace, "forcibly kill this car")
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::Backspace, "forcibly kill this car")
|
||||
{
|
||||
ui.primary.sim.kill_stuck_car(id, &ui.primary.map);
|
||||
ui.primary.sim.step(&ui.primary.map, Duration::seconds(0.1));
|
||||
ui.primary.current_selection = None;
|
||||
} else if ctx
|
||||
.input
|
||||
.contextual_action(Key::G, "find front of blockage")
|
||||
{
|
||||
} else if ui.per_obj.action(ctx, Key::G, "find front of blockage") {
|
||||
return Transition::Push(msg(
|
||||
"Blockage results",
|
||||
vec![format!(
|
||||
|
@ -26,7 +26,7 @@ impl ObjectDebugger {
|
||||
}
|
||||
|
||||
if let Some(ref id) = ui.primary.current_selection {
|
||||
if ctx.input.contextual_action(Key::D, "debug") {
|
||||
if ui.per_obj.action(ctx, Key::D, "debug") {
|
||||
dump_debug(
|
||||
id.clone(),
|
||||
&ui.primary.map,
|
||||
|
@ -22,9 +22,9 @@ impl PolygonDebugger {
|
||||
match ui.primary.current_selection {
|
||||
Some(ID::Intersection(id)) => {
|
||||
let i = ui.primary.map.get_i(id);
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::X, "debug intersection geometry")
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::X, "debug intersection geometry")
|
||||
{
|
||||
let pts = i.polygon.points();
|
||||
let mut pts_without_last = pts.clone();
|
||||
@ -40,10 +40,7 @@ impl PolygonDebugger {
|
||||
),
|
||||
center: Some(Pt2D::center(&pts_without_last)),
|
||||
});
|
||||
} else if ctx
|
||||
.input
|
||||
.contextual_action(Key::F2, "debug sidewalk corners")
|
||||
{
|
||||
} else if ui.per_obj.action(ctx, Key::F2, "debug sidewalk corners") {
|
||||
return Some(PolygonDebugger {
|
||||
slider: WarpingItemSlider::new(
|
||||
calculate_corners(
|
||||
@ -63,7 +60,7 @@ impl PolygonDebugger {
|
||||
}
|
||||
}
|
||||
Some(ID::Lane(id)) => {
|
||||
if ctx.input.contextual_action(Key::X, "debug lane geometry") {
|
||||
if ui.per_obj.action(ctx, Key::X, "debug lane geometry") {
|
||||
return Some(PolygonDebugger {
|
||||
slider: WarpingItemSlider::new(
|
||||
ui.primary
|
||||
@ -80,7 +77,10 @@ impl PolygonDebugger {
|
||||
),
|
||||
center: None,
|
||||
});
|
||||
} else if ctx.input.contextual_action(Key::F2, "debug lane triangles") {
|
||||
} else if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::F2, "debug lane triangles geometry")
|
||||
{
|
||||
return Some(PolygonDebugger {
|
||||
slider: WarpingItemSlider::new(
|
||||
ui.primary
|
||||
@ -106,7 +106,7 @@ impl PolygonDebugger {
|
||||
}
|
||||
}
|
||||
Some(ID::Area(id)) => {
|
||||
if ctx.input.contextual_action(Key::X, "debug area geometry") {
|
||||
if ui.per_obj.action(ctx, Key::X, "debug area geometry") {
|
||||
let pts = &ui.primary.map.get_a(id).polygon.points();
|
||||
let center = if pts[0] == *pts.last().unwrap() {
|
||||
// TODO The center looks really wrong for Volunteer Park and others, but I
|
||||
@ -126,7 +126,7 @@ impl PolygonDebugger {
|
||||
),
|
||||
center: Some(center),
|
||||
});
|
||||
} else if ctx.input.contextual_action(Key::F2, "debug area triangles") {
|
||||
} else if ui.per_obj.action(ctx, Key::F2, "debug area triangles") {
|
||||
return Some(PolygonDebugger {
|
||||
slider: WarpingItemSlider::new(
|
||||
ui.primary
|
||||
|
@ -160,10 +160,7 @@ impl LaneEditor {
|
||||
|
||||
if let Some(ID::Lane(l)) = ui.primary.current_selection {
|
||||
if let Some(idx) = self.active_idx {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::Space, &self.brushes[idx].label)
|
||||
{
|
||||
if ui.per_obj.action(ctx, Key::Space, &self.brushes[idx].label) {
|
||||
// These errors are universal.
|
||||
if ui.primary.map.get_l(l).is_sidewalk() {
|
||||
return Some(Transition::Push(msg(
|
||||
@ -192,15 +189,15 @@ impl LaneEditor {
|
||||
}
|
||||
}
|
||||
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::U, "bulk edit lanes on this road")
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::U, "bulk edit lanes on this road")
|
||||
{
|
||||
return Some(Transition::Push(make_bulk_edit_lanes(
|
||||
ui.primary.map.get_l(l).parent,
|
||||
)));
|
||||
} else if let Some(lt) = ui.primary.map.get_edits().original_lts.get(&l) {
|
||||
if ctx.input.contextual_action(Key::R, "revert") {
|
||||
if ui.per_obj.action(ctx, Key::R, "revert") {
|
||||
if let Some(err) = can_change_lane_type(l, *lt, &ui.primary.map) {
|
||||
return Some(Transition::Push(msg("Error", vec![err])));
|
||||
}
|
||||
@ -214,7 +211,7 @@ impl LaneEditor {
|
||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, edits);
|
||||
}
|
||||
} else if ui.primary.map.get_edits().reversed_lanes.contains(&l) {
|
||||
if ctx.input.contextual_action(Key::R, "revert") {
|
||||
if ui.per_obj.action(ctx, Key::R, "revert") {
|
||||
match (self.brushes[self.reverse_idx].apply)(&ui.primary.map, l) {
|
||||
Ok(Some(cmd)) => {
|
||||
let mut edits = ui.primary.map.get_edits().clone();
|
||||
@ -232,9 +229,9 @@ impl LaneEditor {
|
||||
// Woo, a special case! The construction tool also applies to intersections.
|
||||
if let Some(ID::Intersection(i)) = ui.primary.current_selection {
|
||||
if self.active_idx == Some(self.construction_idx)
|
||||
&& ctx
|
||||
.input
|
||||
.contextual_action(Key::Space, &self.brushes[self.construction_idx].label)
|
||||
&& ui
|
||||
.per_obj
|
||||
.action(ctx, Key::Space, &self.brushes[self.construction_idx].label)
|
||||
{
|
||||
let it = ui.primary.map.get_i(i).intersection_type;
|
||||
if it != IntersectionType::Construction && it != IntersectionType::Border {
|
||||
|
@ -188,9 +188,9 @@ impl State for EditMode {
|
||||
if let Some(ID::Intersection(id)) = ui.primary.current_selection {
|
||||
if ui.primary.map.maybe_get_stop_sign(id).is_some() {
|
||||
if self.mode.can_edit_stop_signs()
|
||||
&& ctx
|
||||
.input
|
||||
.contextual_action(Key::E, format!("edit stop signs for {}", id))
|
||||
&& ui
|
||||
.per_obj
|
||||
.action(ctx, Key::E, format!("edit stop signs for {}", id))
|
||||
{
|
||||
return Transition::Push(Box::new(stop_signs::StopSignEditor::new(
|
||||
id, ctx, ui,
|
||||
@ -201,7 +201,7 @@ impl State for EditMode {
|
||||
.get_edits()
|
||||
.changed_intersections
|
||||
.contains(&id)
|
||||
&& ctx.input.contextual_action(Key::R, "revert")
|
||||
&& ui.per_obj.action(ctx, Key::R, "revert")
|
||||
{
|
||||
let mut edits = ui.primary.map.get_edits().clone();
|
||||
edits
|
||||
@ -214,9 +214,9 @@ impl State for EditMode {
|
||||
}
|
||||
}
|
||||
if ui.primary.map.maybe_get_traffic_signal(id).is_some() {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::E, format!("edit traffic signal for {}", id))
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::E, format!("edit traffic signal for {}", id))
|
||||
{
|
||||
return Transition::Push(Box::new(traffic_signals::TrafficSignalEditor::new(
|
||||
id, ctx, ui,
|
||||
@ -227,7 +227,7 @@ impl State for EditMode {
|
||||
.get_edits()
|
||||
.changed_intersections
|
||||
.contains(&id)
|
||||
&& ctx.input.contextual_action(Key::R, "revert")
|
||||
&& ui.per_obj.action(ctx, Key::R, "revert")
|
||||
{
|
||||
let mut edits = ui.primary.map.get_edits().clone();
|
||||
edits
|
||||
@ -240,8 +240,7 @@ impl State for EditMode {
|
||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, edits);
|
||||
}
|
||||
}
|
||||
if ui.primary.map.get_i(id).is_closed() && ctx.input.contextual_action(Key::R, "revert")
|
||||
{
|
||||
if ui.primary.map.get_i(id).is_closed() && ui.per_obj.action(ctx, Key::R, "revert") {
|
||||
let mut edits = ui.primary.map.get_edits().clone();
|
||||
edits
|
||||
.commands
|
||||
|
@ -67,7 +67,7 @@ impl State for StopSignEditor {
|
||||
}
|
||||
|
||||
if let Some(r) = self.selected_sign {
|
||||
if ctx.input.contextual_action(Key::Space, "toggle stop sign") {
|
||||
if ui.per_obj.action(ctx, Key::Space, "toggle stop sign") {
|
||||
let mut sign = ui.primary.map.get_stop_sign(self.id).clone();
|
||||
sign.flip_sign(r);
|
||||
|
||||
|
@ -110,7 +110,8 @@ impl State for TrafficSignalEditor {
|
||||
}
|
||||
};
|
||||
if let Some(pri) = next_priority {
|
||||
if ctx.input.contextual_action(
|
||||
if ui.per_obj.action(
|
||||
ctx,
|
||||
Key::Space,
|
||||
format!(
|
||||
"toggle from {:?} to {:?}",
|
||||
|
@ -12,8 +12,8 @@ use ezgui::{
|
||||
// top-level game states.
|
||||
pub struct Game {
|
||||
// A stack of states
|
||||
pub states: Vec<Box<dyn State>>,
|
||||
pub ui: UI,
|
||||
states: Vec<Box<dyn State>>,
|
||||
ui: UI,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
|
@ -7,6 +7,7 @@ mod game;
|
||||
mod helpers;
|
||||
mod managed;
|
||||
mod mission;
|
||||
mod obj_actions;
|
||||
mod options;
|
||||
mod pregame;
|
||||
mod render;
|
||||
|
@ -203,7 +203,7 @@ impl State for ScenarioManager {
|
||||
let from = self.trips_from_bldg.get(b);
|
||||
let to = self.trips_to_bldg.get(b);
|
||||
if !from.is_empty() || !to.is_empty() {
|
||||
if ctx.input.contextual_action(Key::T, "browse trips") {
|
||||
if ui.per_obj.action(ctx, Key::T, "browse trips") {
|
||||
// TODO Avoid the clone? Just happens once though.
|
||||
let mut all_trips = from.clone();
|
||||
all_trips.extend(to);
|
||||
@ -215,9 +215,7 @@ impl State for ScenarioManager {
|
||||
OD::Bldg(b),
|
||||
));
|
||||
} else if self.demand.is_none()
|
||||
&& ctx
|
||||
.input
|
||||
.contextual_action(Key::P, "show trips to and from")
|
||||
&& ui.per_obj.action(ctx, Key::P, "show trips to and from")
|
||||
{
|
||||
self.demand = Some(show_demand(&self.scenario, from, to, OD::Bldg(b), ui, ctx));
|
||||
self.menu
|
||||
@ -228,7 +226,7 @@ impl State for ScenarioManager {
|
||||
let from = self.trips_from_border.get(i);
|
||||
let to = self.trips_to_border.get(i);
|
||||
if !from.is_empty() || !to.is_empty() {
|
||||
if ctx.input.contextual_action(Key::T, "browse trips") {
|
||||
if ui.per_obj.action(ctx, Key::T, "browse trips") {
|
||||
// TODO Avoid the clone? Just happens once though.
|
||||
let mut all_trips = from.clone();
|
||||
all_trips.extend(to);
|
||||
@ -240,9 +238,7 @@ impl State for ScenarioManager {
|
||||
OD::Border(i),
|
||||
));
|
||||
} else if self.demand.is_none()
|
||||
&& ctx
|
||||
.input
|
||||
.contextual_action(Key::P, "show trips to and from")
|
||||
&& ui.per_obj.action(ctx, Key::P, "show trips to and from")
|
||||
{
|
||||
self.demand = Some(show_demand(
|
||||
&self.scenario,
|
||||
|
13
game/src/obj_actions.rs
Normal file
13
game/src/obj_actions.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use ezgui::{EventCtx, Key};
|
||||
|
||||
pub struct PerObjectActions {}
|
||||
|
||||
impl PerObjectActions {
|
||||
pub fn new() -> PerObjectActions {
|
||||
PerObjectActions {}
|
||||
}
|
||||
|
||||
pub fn action<S: Into<String>>(&self, ctx: &mut EventCtx, key: Key, label: S) -> bool {
|
||||
ctx.input.contextual_action(key, label)
|
||||
}
|
||||
}
|
@ -100,7 +100,7 @@ impl BusRouteExplorer {
|
||||
if routes.is_empty() {
|
||||
return None;
|
||||
}
|
||||
if !ctx.input.contextual_action(Key::E, "explore bus route") {
|
||||
if !ui.per_obj.action(ctx, Key::E, "explore bus route") {
|
||||
return None;
|
||||
}
|
||||
if routes.len() == 1 {
|
||||
|
@ -47,11 +47,7 @@ impl AgentSpawner {
|
||||
match ui.primary.current_selection {
|
||||
Some(ID::Building(id)) => {
|
||||
let spots = ui.primary.sim.get_free_offstreet_spots(id);
|
||||
if !spots.is_empty()
|
||||
&& ctx
|
||||
.input
|
||||
.contextual_action(Key::F6, "seed a parked car here")
|
||||
{
|
||||
if !spots.is_empty() && ui.per_obj.action(ctx, Key::F6, "seed a parked car here") {
|
||||
let mut rng = ui.primary.current_flags.sim_flags.make_rng();
|
||||
ui.primary.sim.seed_parked_car(
|
||||
Scenario::rand_car(&mut rng),
|
||||
@ -60,10 +56,11 @@ impl AgentSpawner {
|
||||
);
|
||||
return None;
|
||||
}
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::F3, "spawn a pedestrian starting here just walking")
|
||||
{
|
||||
if ui.per_obj.action(
|
||||
ctx,
|
||||
Key::F3,
|
||||
"spawn a pedestrian starting here just walking",
|
||||
) {
|
||||
return Some(Box::new(AgentSpawner {
|
||||
menu: ModalMenu::new(
|
||||
"Agent Spawner",
|
||||
@ -77,7 +74,8 @@ impl AgentSpawner {
|
||||
let parked = ui.primary.sim.get_parked_cars_by_owner(id);
|
||||
// TODO Check if it's claimed... Haha if it is, MaybeUsingParkedCar still snags it!
|
||||
if !parked.is_empty()
|
||||
&& ctx.input.contextual_action(
|
||||
&& ui.per_obj.action(
|
||||
ctx,
|
||||
Key::F5,
|
||||
"spawn a pedestrian here using an owned parked car",
|
||||
)
|
||||
@ -93,10 +91,7 @@ impl AgentSpawner {
|
||||
}));
|
||||
}
|
||||
if let Some(pos) = Position::bldg_via_driving(id, map) {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::F4, "spawn a car starting here")
|
||||
{
|
||||
if ui.per_obj.action(ctx, Key::F4, "spawn a car starting here") {
|
||||
return Some(Box::new(AgentSpawner {
|
||||
menu: ModalMenu::new(
|
||||
"Agent Spawner",
|
||||
@ -109,9 +104,9 @@ impl AgentSpawner {
|
||||
}
|
||||
}
|
||||
if let Some(pos) = Position::bldg_via_biking(id, map) {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::F7, "spawn a bike starting here")
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::F7, "spawn a bike starting here")
|
||||
{
|
||||
return Some(Box::new(AgentSpawner {
|
||||
menu: ModalMenu::new(
|
||||
@ -127,9 +122,7 @@ impl AgentSpawner {
|
||||
}
|
||||
Some(ID::Lane(id)) => {
|
||||
if map.get_l(id).is_driving()
|
||||
&& ctx
|
||||
.input
|
||||
.contextual_action(Key::F3, "spawn a car starting here")
|
||||
&& ui.per_obj.action(ctx, Key::F3, "spawn a car starting here")
|
||||
{
|
||||
return Some(Box::new(AgentSpawner {
|
||||
menu: ModalMenu::new(
|
||||
@ -141,9 +134,9 @@ impl AgentSpawner {
|
||||
maybe_goal: None,
|
||||
}));
|
||||
} else if map.get_l(id).is_sidewalk()
|
||||
&& ctx
|
||||
.input
|
||||
.contextual_action(Key::F3, "spawn a pedestrian starting here")
|
||||
&& ui
|
||||
.per_obj
|
||||
.action(ctx, Key::F3, "spawn a pedestrian starting here")
|
||||
{
|
||||
return Some(Box::new(AgentSpawner {
|
||||
menu: ModalMenu::new(
|
||||
@ -160,9 +153,9 @@ impl AgentSpawner {
|
||||
}
|
||||
}
|
||||
Some(ID::Intersection(i)) => {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::Z, "spawn agents around this intersection")
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::Z, "spawn agents around this intersection")
|
||||
{
|
||||
spawn_agents_around(i, ui, ctx);
|
||||
}
|
||||
@ -253,7 +246,7 @@ impl State for AgentSpawner {
|
||||
}
|
||||
}
|
||||
|
||||
if self.maybe_goal.is_some() && ctx.input.contextual_action(Key::F3, "end the agent here") {
|
||||
if self.maybe_goal.is_some() && ui.per_obj.action(ctx, Key::F3, "end the agent here") {
|
||||
let mut rng = ui.primary.current_flags.sim_flags.make_rng();
|
||||
let sim = &mut ui.primary.sim;
|
||||
let err = schedule_trip(
|
||||
@ -504,9 +497,9 @@ impl SpawnManyAgents {
|
||||
pub fn new(ctx: &mut EventCtx, ui: &mut UI) -> Option<Box<dyn State>> {
|
||||
if let Some(ID::Lane(l)) = ui.primary.current_selection {
|
||||
if ui.primary.map.get_l(l).is_driving()
|
||||
&& ctx
|
||||
.input
|
||||
.contextual_action(Key::F2, "spawn many cars starting here")
|
||||
&& ui
|
||||
.per_obj
|
||||
.action(ctx, Key::F2, "spawn many cars starting here")
|
||||
{
|
||||
return Some(Box::new(SpawnManyAgents {
|
||||
menu: ModalMenu::new(
|
||||
@ -581,7 +574,7 @@ impl State for SpawnManyAgents {
|
||||
|
||||
if self.maybe_goal.is_some()
|
||||
&& self.schedule.is_none()
|
||||
&& ctx.input.contextual_action(Key::F2, "end the swarm here")
|
||||
&& ui.per_obj.action(ctx, Key::F2, "end the swarm here")
|
||||
{
|
||||
return Transition::Push(WizardState::new(Box::new(move |wiz, ctx, _| {
|
||||
let mut wizard = wiz.wrap(ctx);
|
||||
|
@ -84,13 +84,10 @@ impl State for SandboxMode {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
{
|
||||
let mut txt = Text::new();
|
||||
txt.add(Line(""));
|
||||
{
|
||||
let edits = ui.primary.map.get_edits();
|
||||
txt.add(Line(format!("Edits: {}", edits.edits_name)));
|
||||
if edits.dirty {
|
||||
txt.append(Line("*"));
|
||||
}
|
||||
let edits = ui.primary.map.get_edits();
|
||||
txt.add(Line(format!("Edits: {}", edits.edits_name)));
|
||||
if edits.dirty {
|
||||
txt.append(Line("*"));
|
||||
}
|
||||
self.menu.set_info(ctx, txt);
|
||||
}
|
||||
@ -209,9 +206,11 @@ impl State for SandboxMode {
|
||||
.map(|p| p.vehicle.id)
|
||||
.collect::<Vec<_>>();
|
||||
if !cars.is_empty()
|
||||
&& ctx
|
||||
.input
|
||||
.contextual_action(Key::P, format!("examine {} cars parked here", cars.len()))
|
||||
&& ui.per_obj.action(
|
||||
ctx,
|
||||
Key::P,
|
||||
format!("examine {} cars parked here", cars.len()),
|
||||
)
|
||||
{
|
||||
return Transition::Push(WizardState::new(Box::new(move |wiz, ctx, _| {
|
||||
let _id = wiz.wrap(ctx).choose("Examine which car?", || {
|
||||
@ -224,9 +223,9 @@ impl State for SandboxMode {
|
||||
}
|
||||
}
|
||||
if let Some(ID::Lane(l)) = ui.primary.current_selection {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::T, "throughput over 1-hour buckets")
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::T, "throughput over 1-hour buckets")
|
||||
{
|
||||
let r = ui.primary.map.get_l(l).parent;
|
||||
let bucket = Duration::hours(1);
|
||||
@ -234,20 +233,17 @@ impl State for SandboxMode {
|
||||
}
|
||||
}
|
||||
if let Some(ID::Intersection(i)) = ui.primary.current_selection {
|
||||
if ctx
|
||||
.input
|
||||
.contextual_action(Key::T, "throughput over 1-hour buckets")
|
||||
if ui
|
||||
.per_obj
|
||||
.action(ctx, Key::T, "throughput over 1-hour buckets")
|
||||
{
|
||||
let bucket = Duration::hours(1);
|
||||
self.overlay = Overlays::intersection_throughput(i, bucket, ctx, ui);
|
||||
} else if ctx
|
||||
.input
|
||||
.contextual_action(Key::D, "delay over 1-hour buckets")
|
||||
{
|
||||
} else if ui.per_obj.action(ctx, Key::D, "delay over 1-hour buckets") {
|
||||
let bucket = Duration::hours(1);
|
||||
self.overlay = Overlays::intersection_delay_over_time(i, bucket, ctx, ui);
|
||||
} else if ui.primary.map.get_i(i).is_traffic_signal()
|
||||
&& ctx.input.contextual_action(Key::E, "show current demand")
|
||||
&& ui.per_obj.action(ctx, Key::E, "show current demand")
|
||||
{
|
||||
self.overlay = Overlays::intersection_demand(i, ctx, ui);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::helpers::{ColorScheme, ID};
|
||||
use crate::obj_actions::PerObjectActions;
|
||||
use crate::options::Options;
|
||||
use crate::render::{
|
||||
draw_vehicle, AgentCache, AgentColorScheme, DrawCtx, DrawMap, DrawOptions, DrawPedCrowd,
|
||||
@ -18,6 +19,8 @@ pub struct UI {
|
||||
pub cs: ColorScheme,
|
||||
pub agent_cs: AgentColorScheme,
|
||||
pub opts: Options,
|
||||
|
||||
pub per_obj: PerObjectActions,
|
||||
}
|
||||
|
||||
impl UI {
|
||||
@ -77,6 +80,7 @@ impl UI {
|
||||
cs,
|
||||
agent_cs: AgentColorScheme::ByID,
|
||||
opts,
|
||||
per_obj: PerObjectActions::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user