mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
bundling exclusive editor-like plugins together in one meta plugin,
edit_mode
This commit is contained in:
parent
f5201bbfa6
commit
da46544e99
@ -66,3 +66,74 @@ classification.rs floodfill.rs map_edits.rs show_activity
|
||||
color_picker.rs follow.rs mod.rs show_owner.rs traffic_signal_editor.rs
|
||||
debug_objects.rs geom_validation.rs neighborhood_summary.rs show_route.rs turn_cycler.rs
|
||||
diff_all.rs hider.rs road_editor.rs sim_controls.rs warp.rs
|
||||
|
||||
|
||||
|
||||
Gah, bite this off in slow pieces. First find layer-like things... things that
|
||||
draw/hide stuff. Tend to have very simple activate/deactive controls. No sim interaction.
|
||||
|
||||
Or maybe with the exclusive editors...
|
||||
- in the short term, could make a plugin that just delegates to a smaller list
|
||||
- except some are per-map and some are not
|
||||
- wouldnt need that concept if we dont store plugins when
|
||||
theyre inactive and have a notion of what can simultaneously
|
||||
be active...
|
||||
- figure out what other plugins are valid alongside the exclusive editors...
|
||||
- should activating an editor reset toggleable layers and hidden stuff? that's debug state...
|
||||
- when is moving via mouse still valid? color picker (right?), neighborhood, road/intersection editors
|
||||
- intersection and road editors... just debug. and actually, is that even true?
|
||||
- running a sim / doing time travel shouldnt be valid
|
||||
|
||||
|
||||
debug stuff: toggleable layers, hider, geom validation, floodfill
|
||||
|
||||
alright maybe we actually do have lots of exclusive states...
|
||||
- the exclusive editors
|
||||
- note that if we're running an A/B test, none of these are valid! cant edit stuff during a/b test... just run.
|
||||
- explore
|
||||
- sim controls | time travel
|
||||
- bunch of nonblocking stuff... chokepoints, classification, debug, diff all, diff trip, floodfill, follow...
|
||||
- different keys to deactivate them? :P
|
||||
- some blocking stuff... search, warp. when these're around, run them first
|
||||
|
||||
|
||||
- dir structure... all the exclusive stuff side-by-side, and then a shared/ for stuff that might apply during different states
|
||||
- the exclusive editors: a_b_tests.rs draw_neighborhoods.rs map_edits.rs scenarios.rs traffic_signal_editor.rs
|
||||
color_picker.rs road_editor.rs stop_sign_editor.rs
|
||||
|
||||
|
||||
|
||||
|
||||
maybe as an initial step, can we get rid of plugins per map vs per UI and just have one or the other?
|
||||
|
||||
- every plugin per map?
|
||||
- toggleable layers then arent shared... fine
|
||||
- logs is per UI? whoa, that's actually maybe messy!
|
||||
- sim ctrl, diff world/trip does need to be independent though.
|
||||
- every plugin per UI?
|
||||
- when we load a new map from edits, still have to replace the world.
|
||||
- would have to argue that no plugin that keeps per-map state can run during A/B test mode!
|
||||
- or rather, that we cant swap while any of those plugins hold state!
|
||||
- show owner, turn cycler, debug, follow (need to recalculate)
|
||||
- time travel (needs a/b support generally)
|
||||
- show route (totally valid to swap while this is going... grrr.)
|
||||
|
||||
|
||||
|
||||
maybe step 1...
|
||||
- make a single 'Mode' for exclusive editors
|
||||
- skip it if a secondary sim is present (aka in A/B mode)
|
||||
- it lives per UI, because of above condition
|
||||
- for now, impl it as a hierarchial plugin itself that just delegates
|
||||
- keep plugin trait for each of em for convenience in edit mode, though.
|
||||
|
||||
- each of the editors can stop having inactive state. have new() that returns option
|
||||
|
||||
and probably step 2...
|
||||
- make a single 'Mode' for normal exploration
|
||||
- let a bunch of plugins run non-exclusively there, as relevant
|
||||
- and still have a single blocking plugin possible, like warp
|
||||
|
||||
and step 3...
|
||||
- dismantle the plugin abstraction in UI and probably also the trait. do something different for modes.
|
||||
- clean up event vs new_event
|
||||
|
@ -20,7 +20,7 @@ impl ABTestManager {
|
||||
|
||||
impl Plugin for ABTestManager {
|
||||
// May return a new primary and secondary UI
|
||||
fn event(&mut self, ctx: PluginCtx) -> bool {
|
||||
fn new_event(&mut self, ctx: &mut PluginCtx) -> bool {
|
||||
let selected = ctx.primary.current_selection;
|
||||
|
||||
let mut new_state: Option<ABTestManager> = None;
|
||||
@ -47,8 +47,8 @@ impl Plugin for ABTestManager {
|
||||
let ((new_primary, new_primary_plugins), new_secondary) =
|
||||
launch_test(test, ctx.kml, &ctx.primary.current_flags);
|
||||
*ctx.primary = new_primary;
|
||||
ctx.primary_plugins.map(|p_plugins| {
|
||||
*p_plugins = new_primary_plugins;
|
||||
ctx.primary_plugins.as_mut().map(|p_plugins| {
|
||||
**p_plugins = new_primary_plugins;
|
||||
});
|
||||
*ctx.secondary = Some(new_secondary);
|
||||
new_state = Some(ABTestManager::Inactive);
|
@ -26,8 +26,8 @@ impl ColorPicker {
|
||||
}
|
||||
|
||||
impl Plugin for ColorPicker {
|
||||
fn event(&mut self, ctx: PluginCtx) -> bool {
|
||||
let (input, canvas, cs) = (ctx.input, ctx.canvas, ctx.cs);
|
||||
fn new_event(&mut self, ctx: &mut PluginCtx) -> bool {
|
||||
let (input, canvas, cs) = (&mut ctx.input, &ctx.canvas, &mut ctx.cs);
|
||||
|
||||
let mut new_state: Option<ColorPicker> = None;
|
||||
match self {
|
@ -26,9 +26,13 @@ impl DrawNeighborhoodState {
|
||||
}
|
||||
|
||||
impl Plugin for DrawNeighborhoodState {
|
||||
fn event(&mut self, ctx: PluginCtx) -> bool {
|
||||
let (input, canvas, map, osd) =
|
||||
(ctx.input, ctx.canvas, &ctx.primary.map, &mut ctx.hints.osd);
|
||||
fn new_event(&mut self, ctx: &mut PluginCtx) -> bool {
|
||||
let (input, canvas, map, osd) = (
|
||||
&mut ctx.input,
|
||||
&ctx.canvas,
|
||||
&ctx.primary.map,
|
||||
&mut ctx.hints.osd,
|
||||
);
|
||||
let gps_bounds = map.get_gps_bounds();
|
||||
|
||||
// TODO This can easily be outside of the map boundary...
|
@ -18,7 +18,7 @@ impl EditsManager {
|
||||
}
|
||||
|
||||
impl Plugin for EditsManager {
|
||||
fn event(&mut self, ctx: PluginCtx) -> bool {
|
||||
fn new_event(&mut self, ctx: &mut PluginCtx) -> bool {
|
||||
let mut new_state: Option<EditsManager> = None;
|
||||
match self {
|
||||
EditsManager::Inactive => {
|
||||
@ -46,8 +46,8 @@ impl Plugin for EditsManager {
|
||||
}
|
||||
if let Some((p, plugins)) = new_primary {
|
||||
*ctx.primary = p;
|
||||
ctx.primary_plugins.map(|p_plugins| {
|
||||
*p_plugins = plugins;
|
||||
ctx.primary_plugins.as_mut().map(|p_plugins| {
|
||||
**p_plugins = plugins;
|
||||
});
|
||||
}
|
||||
}
|
8
editor/src/plugins/edit/mod.rs
Normal file
8
editor/src/plugins/edit/mod.rs
Normal file
@ -0,0 +1,8 @@
|
||||
pub mod a_b_tests;
|
||||
pub mod color_picker;
|
||||
pub mod draw_neighborhoods;
|
||||
pub mod map_edits;
|
||||
pub mod road_editor;
|
||||
pub mod scenarios;
|
||||
pub mod stop_sign_editor;
|
||||
pub mod traffic_signal_editor;
|
@ -14,9 +14,9 @@ impl RoadEditor {
|
||||
}
|
||||
|
||||
impl Plugin for RoadEditor {
|
||||
fn event(&mut self, ctx: PluginCtx) -> bool {
|
||||
fn new_event(&mut self, ctx: &mut PluginCtx) -> bool {
|
||||
let (input, selected, map, draw_map, sim) = (
|
||||
ctx.input,
|
||||
&mut ctx.input,
|
||||
ctx.primary.current_selection,
|
||||
&mut ctx.primary.map,
|
||||
&mut ctx.primary.draw_map,
|
@ -22,8 +22,8 @@ impl ScenarioManager {
|
||||
}
|
||||
|
||||
impl Plugin for ScenarioManager {
|
||||
fn event(&mut self, ctx: PluginCtx) -> bool {
|
||||
let (input, map, sim) = (ctx.input, &ctx.primary.map, &mut ctx.primary.sim);
|
||||
fn new_event(&mut self, ctx: &mut PluginCtx) -> bool {
|
||||
let (input, map, sim) = (&mut ctx.input, &ctx.primary.map, &mut ctx.primary.sim);
|
||||
|
||||
let mut new_state: Option<ScenarioManager> = None;
|
||||
match self {
|
||||
@ -53,6 +53,7 @@ impl Plugin for ScenarioManager {
|
||||
));
|
||||
} else if input.key_pressed(Key::I, "instantiate this scenario") {
|
||||
scenario.instantiate(sim, map);
|
||||
new_state = Some(ScenarioManager::Inactive);
|
||||
} else if scroller.event(input) {
|
||||
new_state = Some(ScenarioManager::Inactive);
|
||||
}
|
@ -25,8 +25,8 @@ impl StopSignEditor {
|
||||
}
|
||||
|
||||
impl Plugin for StopSignEditor {
|
||||
fn event(&mut self, mut ctx: PluginCtx) -> bool {
|
||||
let input = ctx.input;
|
||||
fn new_event(&mut self, ctx: &mut PluginCtx) -> bool {
|
||||
let input = &mut ctx.input;
|
||||
let map = &mut ctx.primary.map;
|
||||
let selected = ctx.primary.current_selection;
|
||||
|
@ -36,8 +36,8 @@ impl TrafficSignalEditor {
|
||||
}
|
||||
|
||||
impl Plugin for TrafficSignalEditor {
|
||||
fn event(&mut self, ctx: PluginCtx) -> bool {
|
||||
let input = ctx.input;
|
||||
fn new_event(&mut self, ctx: &mut PluginCtx) -> bool {
|
||||
let input = &mut ctx.input;
|
||||
let selected = ctx.primary.current_selection;
|
||||
|
||||
let inactive = match self {
|
129
editor/src/plugins/edit_mode.rs
Normal file
129
editor/src/plugins/edit_mode.rs
Normal file
@ -0,0 +1,129 @@
|
||||
use ezgui::{Color, GfxCtx};
|
||||
use map_model::IntersectionID;
|
||||
use objects::{Ctx, ID};
|
||||
use plugins;
|
||||
use plugins::edit::stop_sign_editor::StopSignEditor;
|
||||
use plugins::edit::traffic_signal_editor::TrafficSignalEditor;
|
||||
use plugins::{Plugin, PluginCtx};
|
||||
|
||||
pub struct EditMode {
|
||||
active_plugin: Option<Box<Plugin>>,
|
||||
}
|
||||
|
||||
impl EditMode {
|
||||
pub fn new() -> EditMode {
|
||||
EditMode {
|
||||
active_plugin: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show_turn_icons(&self, id: IntersectionID) -> bool {
|
||||
if let Some(p) = self
|
||||
.active_plugin
|
||||
.as_ref()
|
||||
.and_then(|p| p.downcast_ref::<StopSignEditor>().ok())
|
||||
{
|
||||
return p.show_turn_icons(id);
|
||||
}
|
||||
if let Some(p) = self
|
||||
.active_plugin
|
||||
.as_ref()
|
||||
.and_then(|p| p.downcast_ref::<TrafficSignalEditor>().ok())
|
||||
{
|
||||
return p.show_turn_icons(id);
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Plugin for EditMode {
|
||||
fn event(&mut self, mut ctx: PluginCtx) -> bool {
|
||||
if self.active_plugin.is_some() {
|
||||
if self.active_plugin.as_mut().unwrap().new_event(&mut ctx) {
|
||||
return true;
|
||||
} else {
|
||||
self.active_plugin = None;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Something higher-level should not even invoke EditMode while we're in A/B test
|
||||
// mode.
|
||||
if ctx.secondary.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO Make better constructors
|
||||
{
|
||||
let mut x = plugins::edit::a_b_tests::ABTestManager::new();
|
||||
if x.new_event(&mut ctx) {
|
||||
self.active_plugin = Some(Box::new(x));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
let mut x = plugins::edit::color_picker::ColorPicker::new();
|
||||
if x.new_event(&mut ctx) {
|
||||
self.active_plugin = Some(Box::new(x));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
let mut x = plugins::edit::draw_neighborhoods::DrawNeighborhoodState::new();
|
||||
if x.new_event(&mut ctx) {
|
||||
self.active_plugin = Some(Box::new(x));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
let mut x = plugins::edit::map_edits::EditsManager::new();
|
||||
if x.new_event(&mut ctx) {
|
||||
self.active_plugin = Some(Box::new(x));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
let mut x = plugins::edit::road_editor::RoadEditor::new();
|
||||
if x.new_event(&mut ctx) {
|
||||
self.active_plugin = Some(Box::new(x));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
let mut x = plugins::edit::scenarios::ScenarioManager::new();
|
||||
if x.new_event(&mut ctx) {
|
||||
self.active_plugin = Some(Box::new(x));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
let mut x = StopSignEditor::new();
|
||||
if x.new_event(&mut ctx) {
|
||||
self.active_plugin = Some(Box::new(x));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
let mut x = TrafficSignalEditor::new();
|
||||
if x.new_event(&mut ctx) {
|
||||
self.active_plugin = Some(Box::new(x));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, ctx: Ctx) {
|
||||
if let Some(ref plugin) = self.active_plugin {
|
||||
plugin.draw(g, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
fn color_for(&self, obj: ID, ctx: Ctx) -> Option<Color> {
|
||||
if let Some(ref plugin) = self.active_plugin {
|
||||
return plugin.color_for(obj, ctx);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
@ -1,30 +1,24 @@
|
||||
pub mod a_b_tests;
|
||||
pub mod chokepoints;
|
||||
pub mod classification;
|
||||
pub mod color_picker;
|
||||
pub mod debug_objects;
|
||||
pub mod diff_all;
|
||||
pub mod diff_worlds;
|
||||
pub mod draw_neighborhoods;
|
||||
pub mod edit;
|
||||
pub mod edit_mode;
|
||||
pub mod floodfill;
|
||||
pub mod follow;
|
||||
pub mod geom_validation;
|
||||
pub mod hider;
|
||||
pub mod layers;
|
||||
pub mod logs;
|
||||
pub mod map_edits;
|
||||
pub mod neighborhood_summary;
|
||||
pub mod road_editor;
|
||||
pub mod scenarios;
|
||||
pub mod search;
|
||||
pub mod show_activity;
|
||||
pub mod show_owner;
|
||||
pub mod show_route;
|
||||
pub mod sim_controls;
|
||||
pub mod steep;
|
||||
pub mod stop_sign_editor;
|
||||
pub mod time_travel;
|
||||
pub mod traffic_signal_editor;
|
||||
pub mod turn_cycler;
|
||||
pub mod warp;
|
||||
|
||||
@ -44,7 +38,15 @@ pub trait Plugin: Any {
|
||||
|
||||
fn draw(&self, _g: &mut GfxCtx, _ctx: Ctx) {}
|
||||
|
||||
fn event(&mut self, ctx: PluginCtx) -> bool;
|
||||
// True if active
|
||||
fn event(&mut self, _ctx: PluginCtx) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
// TODO Such hacks
|
||||
fn new_event(&mut self, _ctx: &mut PluginCtx) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
downcast!(Plugin);
|
||||
|
@ -11,9 +11,9 @@ use map_model::{BuildingID, IntersectionID, LaneID, Map};
|
||||
use objects::{Ctx, RenderingHints, ID, ROOT_MENU};
|
||||
use piston::input::Key;
|
||||
use plugins;
|
||||
use plugins::edit_mode::EditMode;
|
||||
use plugins::hider::Hider;
|
||||
use plugins::layers::ToggleableLayers;
|
||||
use plugins::stop_sign_editor::StopSignEditor;
|
||||
use plugins::time_travel::TimeTravel;
|
||||
use plugins::Plugin;
|
||||
use render::{DrawMap, RenderOptions};
|
||||
@ -181,22 +181,12 @@ impl PluginsPerMap {
|
||||
&self.list[1]
|
||||
}
|
||||
|
||||
fn stop_sign_editor(&self) -> &StopSignEditor {
|
||||
self.list[2].downcast_ref::<StopSignEditor>().unwrap()
|
||||
}
|
||||
|
||||
fn traffic_signal_editor(&self) -> &plugins::traffic_signal_editor::TrafficSignalEditor {
|
||||
self.list[3]
|
||||
.downcast_ref::<plugins::traffic_signal_editor::TrafficSignalEditor>()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn turn_cycler(&self) -> &Box<Plugin> {
|
||||
&self.list[4]
|
||||
&self.list[2]
|
||||
}
|
||||
|
||||
fn time_travel(&self) -> &TimeTravel {
|
||||
self.list[5].downcast_ref::<TimeTravel>().unwrap()
|
||||
self.list[3].downcast_ref::<TimeTravel>().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,8 +232,6 @@ impl PerMapUI {
|
||||
list: vec![
|
||||
Box::new(Hider::new()),
|
||||
Box::new(plugins::show_owner::ShowOwnerState::new()),
|
||||
Box::new(StopSignEditor::new()),
|
||||
Box::new(plugins::traffic_signal_editor::TrafficSignalEditor::new()),
|
||||
Box::new(plugins::turn_cycler::TurnCyclerState::new()),
|
||||
Box::new(plugins::time_travel::TimeTravel::new()),
|
||||
Box::new(plugins::debug_objects::DebugObjectsState::new()),
|
||||
@ -253,8 +241,6 @@ impl PerMapUI {
|
||||
Box::new(plugins::floodfill::Floodfiller::new()),
|
||||
Box::new(steepness_viz),
|
||||
Box::new(plugins::geom_validation::Validator::new()),
|
||||
Box::new(plugins::draw_neighborhoods::DrawNeighborhoodState::new()),
|
||||
Box::new(plugins::scenarios::ScenarioManager::new()),
|
||||
Box::new(plugins::chokepoints::ChokepointsFinder::new()),
|
||||
Box::new(neighborhood_summary),
|
||||
],
|
||||
@ -269,12 +255,16 @@ struct PluginsPerUI {
|
||||
}
|
||||
|
||||
impl PluginsPerUI {
|
||||
fn edit_mode(&self) -> &EditMode {
|
||||
self.list[0].downcast_ref::<EditMode>().unwrap()
|
||||
}
|
||||
|
||||
fn layers(&self) -> &ToggleableLayers {
|
||||
self.list[0].downcast_ref::<ToggleableLayers>().unwrap()
|
||||
self.list[1].downcast_ref::<ToggleableLayers>().unwrap()
|
||||
}
|
||||
|
||||
fn layers_mut(&mut self) -> &mut ToggleableLayers {
|
||||
self.list[0].downcast_mut::<ToggleableLayers>().unwrap()
|
||||
self.list[1].downcast_mut::<ToggleableLayers>().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,17 +281,14 @@ impl UI {
|
||||
|
||||
plugins: PluginsPerUI {
|
||||
list: vec![
|
||||
Box::new(EditMode::new()),
|
||||
Box::new(ToggleableLayers::new()),
|
||||
Box::new(plugins::search::SearchState::new()),
|
||||
Box::new(plugins::warp::WarpState::new()),
|
||||
Box::new(plugins::classification::OsmClassifier::new()),
|
||||
Box::new(plugins::color_picker::ColorPicker::new()),
|
||||
Box::new(plugins::a_b_tests::ABTestManager::new()),
|
||||
Box::new(logs),
|
||||
Box::new(plugins::diff_all::DiffAllState::new()),
|
||||
Box::new(plugins::diff_worlds::DiffWorldsState::new()),
|
||||
Box::new(plugins::road_editor::RoadEditor::new()),
|
||||
Box::new(plugins::map_edits::EditsManager::new()),
|
||||
Box::new(plugins::sim_controls::SimController::new()),
|
||||
],
|
||||
},
|
||||
@ -530,11 +517,7 @@ pub trait ShowTurnIcons {
|
||||
impl ShowTurnIcons for UI {
|
||||
fn show_icons_for(&self, id: IntersectionID) -> bool {
|
||||
self.plugins.layers().show_all_turn_icons.is_enabled()
|
||||
|| self.primary_plugins.stop_sign_editor().show_turn_icons(id)
|
||||
|| self
|
||||
.primary_plugins
|
||||
.traffic_signal_editor()
|
||||
.show_turn_icons(id)
|
||||
|| self.plugins.edit_mode().show_turn_icons(id)
|
||||
|| {
|
||||
if let Some(ID::Turn(t)) = self.primary.current_selection {
|
||||
t.parent == id
|
||||
|
Loading…
Reference in New Issue
Block a user