2019-04-26 02:02:40 +03:00
|
|
|
mod chokepoints;
|
2019-04-26 02:35:09 +03:00
|
|
|
mod connected_roads;
|
2019-04-26 02:40:26 +03:00
|
|
|
mod objects;
|
2019-04-26 02:24:10 +03:00
|
|
|
mod polygons;
|
2019-04-26 02:02:40 +03:00
|
|
|
|
2019-04-26 01:50:16 +03:00
|
|
|
use crate::game::{GameState, Mode};
|
2019-04-26 02:02:40 +03:00
|
|
|
use crate::objects::ID;
|
2019-04-26 02:56:38 +03:00
|
|
|
use crate::ui::ShowObject;
|
2019-04-26 02:16:21 +03:00
|
|
|
use ezgui::{Color, EventCtx, EventLoopMode, GfxCtx, Key, Text, Wizard};
|
|
|
|
use map_model::RoadID;
|
|
|
|
use std::collections::{HashMap, HashSet};
|
2019-04-26 01:50:16 +03:00
|
|
|
|
|
|
|
pub struct DebugMode {
|
|
|
|
state: State,
|
2019-04-26 02:02:40 +03:00
|
|
|
chokepoints: Option<chokepoints::ChokepointsFinder>,
|
2019-04-26 02:16:21 +03:00
|
|
|
show_original_roads: HashSet<RoadID>,
|
2019-04-26 02:35:09 +03:00
|
|
|
connected_roads: connected_roads::ShowConnectedRoads,
|
2019-04-26 02:40:26 +03:00
|
|
|
objects: objects::ObjectDebugger,
|
2019-04-26 08:07:48 +03:00
|
|
|
hidden: HashSet<ID>,
|
2019-04-26 01:50:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
enum State {
|
|
|
|
Exploring,
|
2019-04-26 02:24:10 +03:00
|
|
|
Polygons(polygons::PolygonDebugger),
|
2019-04-26 01:50:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl DebugMode {
|
|
|
|
pub fn new() -> DebugMode {
|
|
|
|
DebugMode {
|
|
|
|
state: State::Exploring,
|
2019-04-26 02:02:40 +03:00
|
|
|
chokepoints: None,
|
2019-04-26 02:16:21 +03:00
|
|
|
show_original_roads: HashSet::new(),
|
2019-04-26 02:35:09 +03:00
|
|
|
connected_roads: connected_roads::ShowConnectedRoads::new(),
|
2019-04-26 02:40:26 +03:00
|
|
|
objects: objects::ObjectDebugger::new(),
|
2019-04-26 08:07:48 +03:00
|
|
|
hidden: HashSet::new(),
|
2019-04-26 01:50:16 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn event(state: &mut GameState, ctx: &mut EventCtx) -> EventLoopMode {
|
|
|
|
match state.mode {
|
|
|
|
Mode::Debug(ref mut mode) => {
|
2019-04-26 02:24:10 +03:00
|
|
|
match mode.state {
|
|
|
|
State::Exploring => {
|
|
|
|
ctx.canvas.handle_event(ctx.input);
|
|
|
|
state.ui.state.primary.current_selection =
|
|
|
|
state
|
|
|
|
.ui
|
2019-04-26 02:56:38 +03:00
|
|
|
.handle_mouseover(ctx, None, &state.ui.state.primary.sim, mode);
|
2019-04-26 01:50:16 +03:00
|
|
|
|
2019-04-26 02:24:10 +03:00
|
|
|
let mut txt = Text::new();
|
|
|
|
txt.add_styled_line(
|
|
|
|
"Debug Mode".to_string(),
|
|
|
|
None,
|
|
|
|
Some(Color::BLUE),
|
|
|
|
None,
|
|
|
|
);
|
|
|
|
if mode.chokepoints.is_some() {
|
|
|
|
txt.add_line("Showing chokepoints".to_string());
|
|
|
|
}
|
|
|
|
if !mode.show_original_roads.is_empty() {
|
|
|
|
txt.add_line(format!(
|
|
|
|
"Showing {} original roads",
|
|
|
|
mode.show_original_roads.len()
|
|
|
|
));
|
|
|
|
}
|
2019-04-26 08:07:48 +03:00
|
|
|
if !mode.hidden.is_empty() {
|
|
|
|
txt.add_line(format!("Hiding {} things", mode.hidden.len()));
|
|
|
|
}
|
2019-04-26 02:24:10 +03:00
|
|
|
ctx.input
|
|
|
|
.set_mode_with_new_prompt("Debug Mode", txt, ctx.canvas);
|
|
|
|
if ctx.input.modal_action("quit") {
|
|
|
|
state.mode = Mode::SplashScreen(Wizard::new(), None);
|
|
|
|
return EventLoopMode::InputOnly;
|
|
|
|
}
|
2019-04-26 02:02:40 +03:00
|
|
|
|
2019-04-26 02:24:10 +03:00
|
|
|
if ctx.input.modal_action("show/hide chokepoints") {
|
|
|
|
if mode.chokepoints.is_some() {
|
|
|
|
mode.chokepoints = None;
|
|
|
|
} else {
|
|
|
|
// TODO Nothing will actually exist. ;)
|
|
|
|
mode.chokepoints = Some(chokepoints::ChokepointsFinder::new(
|
|
|
|
&state.ui.state.primary.sim,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !mode.show_original_roads.is_empty() {
|
|
|
|
if ctx.input.modal_action("clear original roads shown") {
|
|
|
|
mode.show_original_roads.clear();
|
|
|
|
}
|
|
|
|
}
|
2019-04-26 08:07:48 +03:00
|
|
|
if !mode.hidden.is_empty() {
|
|
|
|
if ctx.input.modal_action("unhide everything") {
|
|
|
|
mode.hidden.clear();
|
|
|
|
// TODO recalculate current_selection
|
|
|
|
}
|
|
|
|
}
|
|
|
|
match state.ui.state.primary.current_selection {
|
|
|
|
Some(ID::Lane(_))
|
|
|
|
| Some(ID::Intersection(_))
|
|
|
|
| Some(ID::ExtraShape(_)) => {
|
|
|
|
let id = state.ui.state.primary.current_selection.unwrap();
|
|
|
|
if ctx
|
|
|
|
.input
|
|
|
|
.contextual_action(Key::H, &format!("hide {:?}", id))
|
|
|
|
{
|
|
|
|
println!("Hiding {:?}", id);
|
|
|
|
//*ctx.recalculate_current_selection = true;
|
|
|
|
state.ui.state.primary.current_selection = None;
|
|
|
|
mode.hidden.insert(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2019-04-26 02:24:10 +03:00
|
|
|
|
|
|
|
if let Some(ID::Lane(l)) = state.ui.state.primary.current_selection {
|
|
|
|
let id = state.ui.state.primary.map.get_l(l).parent;
|
|
|
|
if ctx.input.contextual_action(
|
|
|
|
Key::V,
|
|
|
|
&format!("show original geometry of {:?}", id),
|
|
|
|
) {
|
|
|
|
mode.show_original_roads.insert(id);
|
|
|
|
}
|
|
|
|
}
|
2019-04-26 02:35:09 +03:00
|
|
|
mode.connected_roads.event(ctx, &state.ui);
|
2019-04-26 02:40:26 +03:00
|
|
|
mode.objects.event(ctx, &state.ui);
|
2019-04-26 02:24:10 +03:00
|
|
|
|
|
|
|
if let Some(debugger) = polygons::PolygonDebugger::new(ctx, &state.ui) {
|
|
|
|
mode.state = State::Polygons(debugger);
|
|
|
|
}
|
2019-04-26 02:16:21 +03:00
|
|
|
|
2019-04-26 02:24:10 +03:00
|
|
|
EventLoopMode::InputOnly
|
|
|
|
}
|
|
|
|
State::Polygons(ref mut debugger) => {
|
|
|
|
if debugger.event(ctx) {
|
|
|
|
mode.state = State::Exploring;
|
|
|
|
}
|
|
|
|
EventLoopMode::InputOnly
|
2019-04-26 02:16:21 +03:00
|
|
|
}
|
|
|
|
}
|
2019-04-26 01:50:16 +03:00
|
|
|
}
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn draw(state: &GameState, g: &mut GfxCtx) {
|
|
|
|
match state.mode {
|
|
|
|
Mode::Debug(ref mode) => match mode.state {
|
|
|
|
State::Exploring => {
|
2019-04-26 02:02:40 +03:00
|
|
|
let mut color_overrides = HashMap::new();
|
|
|
|
if let Some(ref chokepoints) = mode.chokepoints {
|
|
|
|
let color = state.ui.state.cs.get_def("chokepoint", Color::RED);
|
|
|
|
for l in &chokepoints.lanes {
|
|
|
|
color_overrides.insert(ID::Lane(*l), color);
|
|
|
|
}
|
|
|
|
for i in &chokepoints.intersections {
|
|
|
|
color_overrides.insert(ID::Intersection(*i), color);
|
|
|
|
}
|
|
|
|
}
|
2019-04-26 02:35:09 +03:00
|
|
|
for l in &mode.connected_roads.lanes {
|
|
|
|
color_overrides.insert(
|
|
|
|
ID::Lane(*l),
|
|
|
|
state
|
|
|
|
.ui
|
|
|
|
.state
|
|
|
|
.cs
|
|
|
|
.get("something associated with something else"),
|
|
|
|
);
|
|
|
|
}
|
2019-04-26 01:50:16 +03:00
|
|
|
state
|
|
|
|
.ui
|
2019-04-26 02:56:38 +03:00
|
|
|
.new_draw(g, None, color_overrides, &state.ui.state.primary.sim, mode);
|
2019-04-26 02:16:21 +03:00
|
|
|
|
|
|
|
for id in &mode.show_original_roads {
|
|
|
|
let r = state.ui.state.primary.map.get_r(*id);
|
|
|
|
if let Some(pair) = r.get_center_for_side(true) {
|
|
|
|
let (pl, width) = pair.unwrap();
|
|
|
|
g.draw_polygon(
|
|
|
|
state
|
|
|
|
.ui
|
|
|
|
.state
|
|
|
|
.cs
|
|
|
|
.get_def("original road forwards", Color::RED.alpha(0.5)),
|
|
|
|
&pl.make_polygons(width),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if let Some(pair) = r.get_center_for_side(false) {
|
|
|
|
let (pl, width) = pair.unwrap();
|
|
|
|
g.draw_polygon(
|
|
|
|
state
|
|
|
|
.ui
|
|
|
|
.state
|
|
|
|
.cs
|
|
|
|
.get_def("original road backwards", Color::BLUE.alpha(0.5)),
|
|
|
|
&pl.make_polygons(width),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2019-04-26 02:40:26 +03:00
|
|
|
|
|
|
|
mode.objects.draw(g, &state.ui);
|
2019-04-26 01:50:16 +03:00
|
|
|
}
|
2019-04-26 02:24:10 +03:00
|
|
|
State::Polygons(ref debugger) => {
|
|
|
|
state
|
|
|
|
.ui
|
2019-04-26 02:56:38 +03:00
|
|
|
.new_draw(g, None, HashMap::new(), &state.ui.state.primary.sim, mode);
|
2019-04-26 02:24:10 +03:00
|
|
|
debugger.draw(g, &state.ui);
|
|
|
|
}
|
2019-04-26 01:50:16 +03:00
|
|
|
},
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-26 02:56:38 +03:00
|
|
|
|
|
|
|
impl ShowObject for DebugMode {
|
|
|
|
fn show(&self, obj: ID) -> bool {
|
2019-04-26 08:07:48 +03:00
|
|
|
!self.hidden.contains(&obj)
|
2019-04-26 02:56:38 +03:00
|
|
|
}
|
|
|
|
}
|