mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
inline some signal editor controls
This commit is contained in:
parent
8f17bc9227
commit
32afd5663b
@ -47,27 +47,27 @@ fn read_file(path: &str) -> Vec<(String, String)> {
|
|||||||
|
|
||||||
// Look for the opening "
|
// Look for the opening "
|
||||||
while !src.starts_with("\"") {
|
while !src.starts_with("\"") {
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
}
|
}
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
|
|
||||||
// Read the key until the closing "
|
// Read the key until the closing "
|
||||||
let mut key = String::new();
|
let mut key = String::new();
|
||||||
while !src.starts_with("\"") {
|
while !src.starts_with("\"") {
|
||||||
key.push(src.chars().next().unwrap());
|
key.push(src.chars().next().unwrap());
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
}
|
}
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
|
|
||||||
// Look for the ,
|
// Look for the ,
|
||||||
while !src.starts_with(",") {
|
while !src.starts_with(",") {
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
}
|
}
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
|
|
||||||
// Look for the Color
|
// Look for the Color
|
||||||
while !src.starts_with("Color") {
|
while !src.starts_with("Color") {
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the ()'s to be mismatched, meaning we found the ) of the get_def()
|
// Wait for the ()'s to be mismatched, meaning we found the ) of the get_def()
|
||||||
@ -82,21 +82,30 @@ fn read_file(path: &str) -> Vec<(String, String)> {
|
|||||||
if counter == -1 {
|
if counter == -1 {
|
||||||
value.pop();
|
value.pop();
|
||||||
entries.push((key, value));
|
entries.push((key, value));
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if src.starts_with(",") && counter == 0 {
|
} else if src.starts_with(",") && counter == 0 {
|
||||||
value.pop();
|
value.pop();
|
||||||
entries.push((key, value));
|
entries.push((key, value));
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
src = src[1..].to_string();
|
shift(&mut src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entries
|
entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn shift(s: &mut String) {
|
||||||
|
*s = s
|
||||||
|
.chars()
|
||||||
|
.next()
|
||||||
|
.map(|c| &s[c.len_utf8()..])
|
||||||
|
.unwrap_or("")
|
||||||
|
.to_string();
|
||||||
|
}
|
||||||
|
@ -2,14 +2,14 @@ use crate::common::CommonState;
|
|||||||
use crate::edit::apply_map_edits;
|
use crate::edit::apply_map_edits;
|
||||||
use crate::game::{msg, State, Transition, WizardState};
|
use crate::game::{msg, State, Transition, WizardState};
|
||||||
use crate::helpers::list_names;
|
use crate::helpers::list_names;
|
||||||
use crate::managed::Outcome;
|
use crate::managed::{Composite, Outcome};
|
||||||
use crate::render::{draw_signal_phase, DrawOptions, DrawTurnGroup, BIG_ARROW_THICKNESS};
|
use crate::render::{draw_signal_phase, DrawOptions, DrawTurnGroup, BIG_ARROW_THICKNESS};
|
||||||
use crate::sandbox::{spawn_agents_around, SpeedControls, TimePanel};
|
use crate::sandbox::{spawn_agents_around, SpeedControls, TimePanel};
|
||||||
use crate::ui::{ShowEverything, UI};
|
use crate::ui::{ShowEverything, UI};
|
||||||
use abstutil::Timer;
|
use abstutil::Timer;
|
||||||
use ezgui::{
|
use ezgui::{
|
||||||
hotkey, lctrl, Button, Choice, Color, Composite, DrawBoth, EventCtx, EventLoopMode, GeomBatch,
|
hotkey, lctrl, Button, Choice, Color, DrawBoth, EventCtx, EventLoopMode, GeomBatch, GfxCtx,
|
||||||
GfxCtx, HorizontalAlignment, Key, Line, ManagedWidget, ModalMenu, Text, VerticalAlignment,
|
HorizontalAlignment, Key, Line, ManagedWidget, ModalMenu, Text, VerticalAlignment,
|
||||||
};
|
};
|
||||||
use geom::{Duration, Polygon};
|
use geom::{Duration, Polygon};
|
||||||
use map_model::{ControlTrafficSignal, EditCmd, IntersectionID, Phase, TurnGroupID, TurnPriority};
|
use map_model::{ControlTrafficSignal, EditCmd, IntersectionID, Phase, TurnGroupID, TurnPriority};
|
||||||
@ -20,7 +20,7 @@ use std::collections::BTreeSet;
|
|||||||
pub struct TrafficSignalEditor {
|
pub struct TrafficSignalEditor {
|
||||||
i: IntersectionID,
|
i: IntersectionID,
|
||||||
current_phase: usize,
|
current_phase: usize,
|
||||||
composite: Composite,
|
composite: ezgui::Composite,
|
||||||
|
|
||||||
menu: ModalMenu,
|
menu: ModalMenu,
|
||||||
groups: Vec<DrawTurnGroup>,
|
groups: Vec<DrawTurnGroup>,
|
||||||
@ -48,18 +48,6 @@ impl TrafficSignalEditor {
|
|||||||
(lctrl(Key::Y), "redo"),
|
(lctrl(Key::Y), "redo"),
|
||||||
(hotkey(Key::UpArrow), "select previous phase"),
|
(hotkey(Key::UpArrow), "select previous phase"),
|
||||||
(hotkey(Key::DownArrow), "select next phase"),
|
(hotkey(Key::DownArrow), "select next phase"),
|
||||||
(hotkey(Key::D), "change phase duration"),
|
|
||||||
(hotkey(Key::K), "move current phase up"),
|
|
||||||
(hotkey(Key::J), "move current phase down"),
|
|
||||||
(hotkey(Key::Backspace), "delete current phase"),
|
|
||||||
(hotkey(Key::N), "add a new empty phase"),
|
|
||||||
(hotkey(Key::R), "reset to original"),
|
|
||||||
(hotkey(Key::P), "choose a preset signal"),
|
|
||||||
(
|
|
||||||
hotkey(Key::B),
|
|
||||||
"convert to dedicated pedestrian scramble signal",
|
|
||||||
),
|
|
||||||
(hotkey(Key::O), "change signal offset"),
|
|
||||||
(lctrl(Key::P), "preview changes"),
|
(lctrl(Key::P), "preview changes"),
|
||||||
(hotkey(Key::Escape), "quit"),
|
(hotkey(Key::Escape), "quit"),
|
||||||
],
|
],
|
||||||
@ -88,6 +76,8 @@ impl TrafficSignalEditor {
|
|||||||
|
|
||||||
impl State for TrafficSignalEditor {
|
impl State for TrafficSignalEditor {
|
||||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||||
|
let orig_signal = ui.primary.map.get_traffic_signal(self.i);
|
||||||
|
|
||||||
self.menu.event(ctx);
|
self.menu.event(ctx);
|
||||||
self.menu.set_info(
|
self.menu.set_info(
|
||||||
ctx,
|
ctx,
|
||||||
@ -106,9 +96,89 @@ impl State for TrafficSignalEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match self.composite.event(ctx) {
|
match self.composite.event(ctx) {
|
||||||
Some(ezgui::Outcome::Clicked(x)) => {
|
Some(ezgui::Outcome::Clicked(x)) => match x {
|
||||||
self.change_phase(x["phase ".len()..].parse::<usize>().unwrap() - 1, ui, ctx);
|
x if x == "Edit offset" => {
|
||||||
}
|
return Transition::Push(change_offset(orig_signal.offset));
|
||||||
|
}
|
||||||
|
x if x == "Reset to default" => {
|
||||||
|
let new_signal =
|
||||||
|
ControlTrafficSignal::get_possible_policies(&ui.primary.map, self.i)
|
||||||
|
.remove(0)
|
||||||
|
.1;
|
||||||
|
self.command_stack.push(orig_signal.clone());
|
||||||
|
self.redo_stack.clear();
|
||||||
|
change_traffic_signal(new_signal, ui, ctx);
|
||||||
|
self.change_phase(0, ui, ctx);
|
||||||
|
return Transition::Keep;
|
||||||
|
}
|
||||||
|
x if x == "Use preset" => {
|
||||||
|
return Transition::Push(change_preset(self.i));
|
||||||
|
}
|
||||||
|
x if x == "Make all-walk" => {
|
||||||
|
let mut new_signal = orig_signal.clone();
|
||||||
|
new_signal.convert_to_ped_scramble(&ui.primary.map);
|
||||||
|
self.command_stack.push(orig_signal.clone());
|
||||||
|
self.redo_stack.clear();
|
||||||
|
change_traffic_signal(new_signal, ui, ctx);
|
||||||
|
self.change_phase(0, ui, ctx);
|
||||||
|
return Transition::Keep;
|
||||||
|
}
|
||||||
|
x if x.starts_with("change duration of #") => {
|
||||||
|
let idx = x["change duration of #".len()..].parse::<usize>().unwrap() - 1;
|
||||||
|
return Transition::Push(change_phase_duration(
|
||||||
|
idx,
|
||||||
|
orig_signal.phases[idx].duration,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
x if x.starts_with("delete phase #") => {
|
||||||
|
let idx = x["delete phase #".len()..].parse::<usize>().unwrap() - 1;
|
||||||
|
let mut new_signal = orig_signal.clone();
|
||||||
|
new_signal.phases.remove(idx);
|
||||||
|
let num_phases = new_signal.phases.len();
|
||||||
|
self.command_stack.push(orig_signal.clone());
|
||||||
|
self.redo_stack.clear();
|
||||||
|
change_traffic_signal(new_signal, ui, ctx);
|
||||||
|
// Don't use change_phase; it tries to preserve scroll
|
||||||
|
self.current_phase = if idx == num_phases { idx - 1 } else { idx };
|
||||||
|
self.composite = make_diagram(self.i, self.current_phase, ui, ctx);
|
||||||
|
return Transition::Keep;
|
||||||
|
}
|
||||||
|
x if x.starts_with("move up phase #") => {
|
||||||
|
let idx = x["move up phase #".len()..].parse::<usize>().unwrap() - 1;
|
||||||
|
let mut new_signal = orig_signal.clone();
|
||||||
|
new_signal.phases.swap(idx, idx - 1);
|
||||||
|
self.command_stack.push(orig_signal.clone());
|
||||||
|
self.redo_stack.clear();
|
||||||
|
change_traffic_signal(new_signal, ui, ctx);
|
||||||
|
self.change_phase(idx - 1, ui, ctx);
|
||||||
|
return Transition::Keep;
|
||||||
|
}
|
||||||
|
x if x.starts_with("move down phase #") => {
|
||||||
|
let idx = x["move down phase #".len()..].parse::<usize>().unwrap() - 1;
|
||||||
|
let mut new_signal = orig_signal.clone();
|
||||||
|
new_signal.phases.swap(idx, idx + 1);
|
||||||
|
self.command_stack.push(orig_signal.clone());
|
||||||
|
self.redo_stack.clear();
|
||||||
|
change_traffic_signal(new_signal, ui, ctx);
|
||||||
|
self.change_phase(idx + 1, ui, ctx);
|
||||||
|
return Transition::Keep;
|
||||||
|
}
|
||||||
|
x if x.starts_with("add new phase after #") => {
|
||||||
|
let idx = x["add new phase after #".len()..].parse::<usize>().unwrap() - 1;
|
||||||
|
let mut new_signal = orig_signal.clone();
|
||||||
|
new_signal.phases.insert(idx + 1, Phase::new());
|
||||||
|
self.command_stack.push(orig_signal.clone());
|
||||||
|
self.redo_stack.clear();
|
||||||
|
change_traffic_signal(new_signal, ui, ctx);
|
||||||
|
self.change_phase(idx + 1, ui, ctx);
|
||||||
|
return Transition::Keep;
|
||||||
|
}
|
||||||
|
x if x.starts_with("phase ") => {
|
||||||
|
let idx = x["phase ".len()..].parse::<usize>().unwrap() - 1;
|
||||||
|
self.change_phase(idx, ui, ctx);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,8 +194,6 @@ impl State for TrafficSignalEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let orig_signal = ui.primary.map.get_traffic_signal(self.i);
|
|
||||||
|
|
||||||
if let Some(id) = self.group_selected {
|
if let Some(id) = self.group_selected {
|
||||||
let mut new_signal = orig_signal.clone();
|
let mut new_signal = orig_signal.clone();
|
||||||
let phase = &mut new_signal.phases[self.current_phase];
|
let phase = &mut new_signal.phases[self.current_phase];
|
||||||
@ -177,24 +245,7 @@ impl State for TrafficSignalEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO We're missing the edits here...
|
// TODO We're missing the edits here...
|
||||||
if self.menu.action("change phase duration") {
|
if !self.command_stack.is_empty() && self.menu.action("undo") {
|
||||||
return Transition::Push(change_phase_duration(
|
|
||||||
orig_signal.phases[self.current_phase].duration,
|
|
||||||
));
|
|
||||||
} else if self.menu.action("change signal offset") {
|
|
||||||
return Transition::Push(change_offset(orig_signal.offset));
|
|
||||||
} else if self.menu.action("choose a preset signal") {
|
|
||||||
return Transition::Push(change_preset(self.i));
|
|
||||||
} else if self.menu.action("reset to original") {
|
|
||||||
let new_signal = ControlTrafficSignal::get_possible_policies(&ui.primary.map, self.i)
|
|
||||||
.remove(0)
|
|
||||||
.1;
|
|
||||||
self.command_stack.push(orig_signal.clone());
|
|
||||||
self.redo_stack.clear();
|
|
||||||
change_traffic_signal(new_signal, ui, ctx);
|
|
||||||
self.change_phase(0, ui, ctx);
|
|
||||||
return Transition::Keep;
|
|
||||||
} else if !self.command_stack.is_empty() && self.menu.action("undo") {
|
|
||||||
self.redo_stack.push(orig_signal.clone());
|
self.redo_stack.push(orig_signal.clone());
|
||||||
change_traffic_signal(self.command_stack.pop().unwrap(), ui, ctx);
|
change_traffic_signal(self.command_stack.pop().unwrap(), ui, ctx);
|
||||||
self.change_phase(0, ui, ctx);
|
self.change_phase(0, ui, ctx);
|
||||||
@ -206,71 +257,6 @@ impl State for TrafficSignalEditor {
|
|||||||
return Transition::Keep;
|
return Transition::Keep;
|
||||||
}
|
}
|
||||||
|
|
||||||
let has_sidewalks = ui
|
|
||||||
.primary
|
|
||||||
.map
|
|
||||||
.get_turns_in_intersection(self.i)
|
|
||||||
.iter()
|
|
||||||
.any(|t| t.between_sidewalks());
|
|
||||||
|
|
||||||
if self.current_phase != 0 && self.menu.action("move current phase up") {
|
|
||||||
let mut new_signal = orig_signal.clone();
|
|
||||||
new_signal
|
|
||||||
.phases
|
|
||||||
.swap(self.current_phase, self.current_phase - 1);
|
|
||||||
self.command_stack.push(orig_signal.clone());
|
|
||||||
self.redo_stack.clear();
|
|
||||||
change_traffic_signal(new_signal, ui, ctx);
|
|
||||||
self.change_phase(self.current_phase - 1, ui, ctx);
|
|
||||||
} else if self.current_phase != orig_signal.phases.len() - 1
|
|
||||||
&& self.menu.action("move current phase down")
|
|
||||||
{
|
|
||||||
let mut new_signal = orig_signal.clone();
|
|
||||||
new_signal
|
|
||||||
.phases
|
|
||||||
.swap(self.current_phase, self.current_phase + 1);
|
|
||||||
self.command_stack.push(orig_signal.clone());
|
|
||||||
self.redo_stack.clear();
|
|
||||||
change_traffic_signal(new_signal, ui, ctx);
|
|
||||||
self.change_phase(self.current_phase + 1, ui, ctx);
|
|
||||||
} else if orig_signal.phases.len() > 1 && self.menu.action("delete current phase") {
|
|
||||||
let mut new_signal = orig_signal.clone();
|
|
||||||
new_signal.phases.remove(self.current_phase);
|
|
||||||
let num_phases = new_signal.phases.len();
|
|
||||||
self.command_stack.push(orig_signal.clone());
|
|
||||||
self.redo_stack.clear();
|
|
||||||
change_traffic_signal(new_signal, ui, ctx);
|
|
||||||
self.change_phase(
|
|
||||||
if self.current_phase == num_phases {
|
|
||||||
self.current_phase - 1
|
|
||||||
} else {
|
|
||||||
self.current_phase
|
|
||||||
},
|
|
||||||
ui,
|
|
||||||
ctx,
|
|
||||||
);
|
|
||||||
} else if self.menu.action("add a new empty phase") {
|
|
||||||
let mut new_signal = orig_signal.clone();
|
|
||||||
new_signal
|
|
||||||
.phases
|
|
||||||
.insert(self.current_phase + 1, Phase::new());
|
|
||||||
self.command_stack.push(orig_signal.clone());
|
|
||||||
self.redo_stack.clear();
|
|
||||||
change_traffic_signal(new_signal, ui, ctx);
|
|
||||||
self.change_phase(self.current_phase + 1, ui, ctx);
|
|
||||||
} else if has_sidewalks
|
|
||||||
&& self
|
|
||||||
.menu
|
|
||||||
.action("convert to dedicated pedestrian scramble signal")
|
|
||||||
{
|
|
||||||
let mut new_signal = orig_signal.clone();
|
|
||||||
new_signal.convert_to_ped_scramble(&ui.primary.map);
|
|
||||||
self.command_stack.push(orig_signal.clone());
|
|
||||||
self.redo_stack.clear();
|
|
||||||
change_traffic_signal(new_signal, ui, ctx);
|
|
||||||
self.change_phase(0, ui, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.menu.action("preview changes") {
|
if self.menu.action("preview changes") {
|
||||||
// TODO These're expensive clones :(
|
// TODO These're expensive clones :(
|
||||||
return Transition::Push(make_previewer(
|
return Transition::Push(make_previewer(
|
||||||
@ -283,6 +269,10 @@ impl State for TrafficSignalEditor {
|
|||||||
Transition::Keep
|
Transition::Keep
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_default_ui(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn draw(&self, g: &mut GfxCtx, ui: &UI) {
|
fn draw(&self, g: &mut GfxCtx, ui: &UI) {
|
||||||
{
|
{
|
||||||
let mut opts = DrawOptions::new();
|
let mut opts = DrawOptions::new();
|
||||||
@ -348,7 +338,12 @@ impl State for TrafficSignalEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_diagram(i: IntersectionID, selected: usize, ui: &UI, ctx: &mut EventCtx) -> Composite {
|
fn make_diagram(
|
||||||
|
i: IntersectionID,
|
||||||
|
selected: usize,
|
||||||
|
ui: &UI,
|
||||||
|
ctx: &mut EventCtx,
|
||||||
|
) -> ezgui::Composite {
|
||||||
// Slightly inaccurate -- the turn rendering may slightly exceed the intersection polygon --
|
// Slightly inaccurate -- the turn rendering may slightly exceed the intersection polygon --
|
||||||
// but this is close enough.
|
// but this is close enough.
|
||||||
let bounds = ui.primary.map.get_i(i).polygon.get_bounds();
|
let bounds = ui.primary.map.get_i(i).polygon.get_bounds();
|
||||||
@ -360,39 +355,75 @@ fn make_diagram(i: IntersectionID, selected: usize, ui: &UI, ctx: &mut EventCtx)
|
|||||||
);
|
);
|
||||||
|
|
||||||
let signal = ui.primary.map.get_traffic_signal(i);
|
let signal = ui.primary.map.get_traffic_signal(i);
|
||||||
let mut col = vec![ManagedWidget::draw_text(ctx, {
|
let mut col = vec![
|
||||||
let mut txt = Text::new();
|
ManagedWidget::draw_text(ctx, {
|
||||||
txt.add(Line(i.to_string()).roboto());
|
let mut txt = Text::new();
|
||||||
let road_names = ui
|
txt.add(Line(i.to_string()).roboto());
|
||||||
.primary
|
let road_names = ui
|
||||||
.map
|
.primary
|
||||||
.get_i(i)
|
.map
|
||||||
.roads
|
.get_i(i)
|
||||||
.iter()
|
.roads
|
||||||
.map(|r| ui.primary.map.get_r(*r).get_name())
|
.iter()
|
||||||
.collect::<BTreeSet<_>>();
|
.map(|r| ui.primary.map.get_r(*r).get_name())
|
||||||
// TODO Some kind of reusable TextStyle thing
|
.collect::<BTreeSet<_>>();
|
||||||
txt.add(Line("").roboto().size(21).fg(Color::WHITE.alpha(0.54)));
|
// TODO Some kind of reusable TextStyle thing
|
||||||
list_names(
|
txt.add(Line("").roboto().size(21).fg(Color::WHITE.alpha(0.54)));
|
||||||
&mut txt,
|
list_names(
|
||||||
|l| l.roboto().fg(Color::WHITE.alpha(0.54)),
|
&mut txt,
|
||||||
road_names,
|
|l| l.roboto().fg(Color::WHITE.alpha(0.54)),
|
||||||
);
|
road_names,
|
||||||
txt.add(Line(format!("{} phases", signal.phases.len())));
|
);
|
||||||
txt.add(Line(""));
|
txt.add(Line(format!("{} phases", signal.phases.len())));
|
||||||
txt.add(Line(format!("Signal offset: {}", signal.offset)));
|
txt.add(Line(""));
|
||||||
txt.add(Line(format!("One cycle lasts {}", signal.cycle_length())));
|
txt.add(Line(format!("Signal offset: {}", signal.offset)));
|
||||||
txt
|
txt.add(Line(format!("One cycle lasts {}", signal.cycle_length())));
|
||||||
})];
|
txt
|
||||||
|
}),
|
||||||
|
Composite::text_button(ctx, "Edit offset", hotkey(Key::O)),
|
||||||
|
// TODO Icons
|
||||||
|
Composite::text_button(ctx, "Reset to default", hotkey(Key::R)),
|
||||||
|
Composite::text_button(ctx, "Use preset", hotkey(Key::P)),
|
||||||
|
];
|
||||||
|
let has_sidewalks = ui
|
||||||
|
.primary
|
||||||
|
.map
|
||||||
|
.get_turns_in_intersection(i)
|
||||||
|
.iter()
|
||||||
|
.any(|t| t.between_sidewalks());
|
||||||
|
if has_sidewalks {
|
||||||
|
col.push(Composite::text_button(ctx, "Make all-walk", hotkey(Key::B)));
|
||||||
|
}
|
||||||
|
|
||||||
for (idx, phase) in signal.phases.iter().enumerate() {
|
for (idx, phase) in signal.phases.iter().enumerate() {
|
||||||
col.push(
|
let mut row = vec![
|
||||||
ManagedWidget::row(vec![
|
ManagedWidget::draw_text(ctx, Text::from(Line(format!("#{}", idx + 1)))),
|
||||||
ManagedWidget::draw_text(ctx, Text::from(Line(format!("#{}", idx + 1)))),
|
ManagedWidget::draw_text(ctx, Text::from(Line(phase.duration.to_string()))),
|
||||||
ManagedWidget::draw_text(ctx, Text::from(Line(phase.duration.to_string()))),
|
Composite::svg_button(
|
||||||
])
|
ctx,
|
||||||
.margin(5)
|
"assets/tools/edit.svg",
|
||||||
.evenly_spaced(),
|
&format!("change duration of #{}", idx + 1),
|
||||||
);
|
if selected == idx {
|
||||||
|
hotkey(Key::D)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
if signal.phases.len() > 1 {
|
||||||
|
// TODO Trash can icon
|
||||||
|
row.push(Composite::text_button(
|
||||||
|
ctx,
|
||||||
|
&format!("delete phase #{}", idx + 1),
|
||||||
|
if selected == idx {
|
||||||
|
hotkey(Key::Backspace)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
col.push(ManagedWidget::row(row).margin(5).evenly_spaced());
|
||||||
|
|
||||||
let mut orig_batch = GeomBatch::new();
|
let mut orig_batch = GeomBatch::new();
|
||||||
draw_signal_phase(phase, i, None, &mut orig_batch, &ui.draw_ctx());
|
draw_signal_phase(phase, i, None, &mut orig_batch, &ui.draw_ctx());
|
||||||
@ -417,7 +448,33 @@ fn make_diagram(i: IntersectionID, selected: usize, ui: &UI, ctx: &mut EventCtx)
|
|||||||
hovered.push(Color::RED.alpha(0.95), bbox.clone());
|
hovered.push(Color::RED.alpha(0.95), bbox.clone());
|
||||||
hovered.append(normal.clone());
|
hovered.append(normal.clone());
|
||||||
|
|
||||||
col.push(
|
let mut move_phase = Vec::new();
|
||||||
|
if idx != 0 {
|
||||||
|
move_phase.push(Composite::detailed_text_button(
|
||||||
|
ctx,
|
||||||
|
Text::from(Line("↑").fg(Color::BLACK)),
|
||||||
|
if selected == idx {
|
||||||
|
hotkey(Key::K)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
&format!("move up phase #{}", idx + 1),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if idx != signal.phases.len() - 1 {
|
||||||
|
move_phase.push(Composite::detailed_text_button(
|
||||||
|
ctx,
|
||||||
|
Text::from(Line("↓").fg(Color::BLACK)),
|
||||||
|
if selected == idx {
|
||||||
|
hotkey(Key::J)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
&format!("move down phase #{}", idx + 1),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
col.push(ManagedWidget::row(vec![
|
||||||
ManagedWidget::btn(Button::new(
|
ManagedWidget::btn(Button::new(
|
||||||
DrawBoth::new(ctx, normal, Vec::new()),
|
DrawBoth::new(ctx, normal, Vec::new()),
|
||||||
DrawBoth::new(ctx, hovered, Vec::new()),
|
DrawBoth::new(ctx, hovered, Vec::new()),
|
||||||
@ -426,10 +483,16 @@ fn make_diagram(i: IntersectionID, selected: usize, ui: &UI, ctx: &mut EventCtx)
|
|||||||
bbox.clone(),
|
bbox.clone(),
|
||||||
))
|
))
|
||||||
.margin(5),
|
.margin(5),
|
||||||
);
|
ManagedWidget::col(move_phase),
|
||||||
|
]));
|
||||||
|
col.push(Composite::text_button(
|
||||||
|
ctx,
|
||||||
|
&format!("add new phase after #{}", idx + 1),
|
||||||
|
None,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Composite::new(ManagedWidget::col(col).bg(Color::hex("#545454")))
|
ezgui::Composite::new(ManagedWidget::col(col).bg(Color::hex("#545454")))
|
||||||
.aligned(HorizontalAlignment::Left, VerticalAlignment::Top)
|
.aligned(HorizontalAlignment::Left, VerticalAlignment::Top)
|
||||||
.build_scrollable(ctx)
|
.build_scrollable(ctx)
|
||||||
}
|
}
|
||||||
@ -453,7 +516,7 @@ fn change_traffic_signal(signal: ControlTrafficSignal, ui: &mut UI, ctx: &mut Ev
|
|||||||
apply_map_edits(&mut ui.primary, &ui.cs, ctx, edits);
|
apply_map_edits(&mut ui.primary, &ui.cs, ctx, edits);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_phase_duration(current_duration: Duration) -> Box<dyn State> {
|
fn change_phase_duration(idx: usize, current_duration: Duration) -> Box<dyn State> {
|
||||||
WizardState::new(Box::new(move |wiz, ctx, _| {
|
WizardState::new(Box::new(move |wiz, ctx, _| {
|
||||||
let new_duration = wiz.wrap(ctx).input_something(
|
let new_duration = wiz.wrap(ctx).input_something(
|
||||||
"How long should this phase be (seconds)?",
|
"How long should this phase be (seconds)?",
|
||||||
@ -469,9 +532,9 @@ fn change_phase_duration(current_duration: Duration) -> Box<dyn State> {
|
|||||||
let mut signal = ui.primary.map.get_traffic_signal(editor.i).clone();
|
let mut signal = ui.primary.map.get_traffic_signal(editor.i).clone();
|
||||||
editor.command_stack.push(signal.clone());
|
editor.command_stack.push(signal.clone());
|
||||||
editor.redo_stack.clear();
|
editor.redo_stack.clear();
|
||||||
signal.phases[editor.current_phase].duration = Duration::seconds(new_duration as f64);
|
signal.phases[idx].duration = Duration::seconds(new_duration as f64);
|
||||||
change_traffic_signal(signal, ui, ctx);
|
change_traffic_signal(signal, ui, ctx);
|
||||||
editor.change_phase(editor.current_phase, ui, ctx);
|
editor.change_phase(idx, ui, ctx);
|
||||||
})))
|
})))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -517,7 +580,7 @@ fn change_preset(i: IntersectionID) -> Box<dyn State> {
|
|||||||
|
|
||||||
fn check_for_missing_groups(
|
fn check_for_missing_groups(
|
||||||
mut signal: ControlTrafficSignal,
|
mut signal: ControlTrafficSignal,
|
||||||
composite: &mut Composite,
|
composite: &mut ezgui::Composite,
|
||||||
ui: &mut UI,
|
ui: &mut UI,
|
||||||
ctx: &mut EventCtx,
|
ctx: &mut EventCtx,
|
||||||
) -> Transition {
|
) -> Transition {
|
||||||
|
Loading…
Reference in New Issue
Block a user