From 27e933fbf877a535b5b718b5b7c58ec1acb295ed Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Fri, 2 Aug 2019 22:01:43 +0200 Subject: [PATCH] replace small_spawn with something to instantiate any scenario for the map --- docs/design/notes/geometry.md | 17 +++++ editor/src/sandbox/mod.rs | 6 +- editor/src/sandbox/spawner.rs | 114 +++++++++++++++++++++++++--------- sim/src/make/scenario.rs | 12 ++++ 4 files changed, 118 insertions(+), 31 deletions(-) diff --git a/docs/design/notes/geometry.md b/docs/design/notes/geometry.md index ff96cd69cb..fcc159aea5 100644 --- a/docs/design/notes/geometry.md +++ b/docs/design/notes/geometry.md @@ -105,3 +105,20 @@ https://www.reddit.com/r/gamedev/comments/2yfyi5/drawing_lines_is_hard/ https://blog.mapbox.com/drawing-antialiased-lines-with-opengl-8766f34192dc http://artgrammer.blogspot.com/2011/07/drawing-polylines-by-tessellation.html https://www.reddit.com/r/GraphicsProgramming/ + + +- are all the sources of doubling back strangely just directly fixable in the geom? +- keep miter joins, but limit how far out we can explode? +- bevel joins + - outlines miss bevels on one edge + - now there are little gaps between adjacent lanes + - slow! + - some bugs that cover a thick triangular area + - refactor all the methods... confusing. +- ideas + - https://stackoverflow.com/questions/5641769/how-to-draw-an-outline-around-any-line + - http://old.cescg.org/CESCG99/SKrivograd/ + - https://www.codeproject.com/Articles/226569/Drawing-polylines-by-tessellation + - https://stackoverflow.com/questions/36475254/polylines-outline-construction-drawing-thick-polylines + - https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader + - https://stackoverflow.com/questions/687173/how-do-i-render-thick-2d-lines-as-polygons diff --git a/editor/src/sandbox/mod.rs b/editor/src/sandbox/mod.rs index 6e42dcf245..9e44d85e33 100644 --- a/editor/src/sandbox/mod.rs +++ b/editor/src/sandbox/mod.rs @@ -47,7 +47,7 @@ impl SandboxMode { (hotkey(Key::Y), "load previous sim state"), (hotkey(Key::U), "load next sim state"), (hotkey(Key::X), "reset sim"), - (hotkey(Key::S), "seed the sim with agents"), + (hotkey(Key::S), "start a scenario"), ], vec![ // TODO Strange to always have this. Really it's a case of stacked modal? @@ -96,8 +96,8 @@ impl State for SandboxMode { return t; } - if let Some(spawner) = spawner::AgentSpawner::new(ctx, ui, &mut self.menu) { - return Transition::Push(Box::new(spawner)); + if let Some(new_state) = spawner::AgentSpawner::new(ctx, ui, &mut self.menu) { + return Transition::Push(new_state); } if let Some(explorer) = RouteExplorer::new(ctx, ui) { return Transition::Push(Box::new(explorer)); diff --git a/editor/src/sandbox/spawner.rs b/editor/src/sandbox/spawner.rs index 54935951f4..df54ca67c3 100644 --- a/editor/src/sandbox/spawner.rs +++ b/editor/src/sandbox/spawner.rs @@ -4,10 +4,11 @@ use crate::helpers::ID; use crate::render::DrawOptions; use crate::ui::{ShowEverything, UI}; use abstutil::Timer; -use ezgui::{hotkey, EventCtx, GfxCtx, Key, ModalMenu}; +use ezgui::{hotkey, EventCtx, GfxCtx, Key, ModalMenu, Wizard, WrappedWizard}; use geom::{Duration, PolyLine}; use map_model::{ - BuildingID, IntersectionID, IntersectionType, LaneType, PathRequest, Position, LANE_THICKNESS, + BuildingID, IntersectionID, IntersectionType, LaneType, Map, PathRequest, Position, + LANE_THICKNESS, }; use rand::seq::SliceRandom; use rand::Rng; @@ -38,7 +39,7 @@ impl AgentSpawner { ctx: &mut EventCtx, ui: &mut UI, sandbox_menu: &mut ModalMenu, - ) -> Option { + ) -> Option> { let menu = ModalMenu::new( "Agent Spawner", vec![vec![(hotkey(Key::Escape), "quit")]], @@ -51,22 +52,22 @@ impl AgentSpawner { .input .contextual_action(Key::F3, "spawn a pedestrian starting here") { - return Some(AgentSpawner { + return Some(Box::new(AgentSpawner { menu, from: Source::Walking(id), maybe_goal: None, - }); + })); } if let Some(pos) = Position::bldg_via_driving(id, map) { if ctx .input .contextual_action(Key::F4, "spawn a car starting here") { - return Some(AgentSpawner { + return Some(Box::new(AgentSpawner { menu, from: Source::Driving(pos), maybe_goal: None, - }); + })); } } } @@ -76,11 +77,11 @@ impl AgentSpawner { .input .contextual_action(Key::F3, "spawn an agent starting here") { - return Some(AgentSpawner { + return Some(Box::new(AgentSpawner { menu, from: Source::Driving(Position::new(id, map.get_l(id).length() / 2.0)), maybe_goal: None, - }); + })); } } Some(ID::Intersection(i)) => { @@ -92,25 +93,10 @@ impl AgentSpawner { } } None => { - if ui.primary.sim.is_empty() { - if sandbox_menu.action("seed the sim with agents") { - // TODO This covers up the map. :\ - ctx.loading_screen("seed sim with agents", |_, timer| { - let map = &ui.primary.map; - let s = if let Some(n) = ui.primary.current_flags.num_agents { - Scenario::scaled_run(map, n) - } else { - Scenario::small_run(map) - }; - s.instantiate( - &mut ui.primary.sim, - map, - &mut ui.primary.current_flags.sim_flags.make_rng(), - timer, - ); - ui.primary.sim.step(map, SMALL_DT); - }); - } + if ui.primary.sim.is_empty() && sandbox_menu.action("start a scenario") { + return Some(Box::new(InstantiateScenario { + wizard: Wizard::new(), + })); } } _ => {} @@ -371,3 +357,75 @@ fn spawn_agents_around(i: IntersectionID, ui: &mut UI, ctx: &EventCtx) { sim.step(map, SMALL_DT); ui.recalculate_current_selection(ctx); } + +// TODO Dedupe with code from mission/mod.rs. +struct InstantiateScenario { + wizard: Wizard, +} + +impl State for InstantiateScenario { + fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition { + if let Some(scenario) = pick_scenario( + ui.primary.current_flags.num_agents, + &ui.primary.map, + &mut self.wizard.wrap(ctx), + ) { + ctx.loading_screen("instantiate scenario", |_, timer| { + scenario.instantiate( + &mut ui.primary.sim, + &ui.primary.map, + &mut ui.primary.current_flags.sim_flags.make_rng(), + timer, + ); + ui.primary.sim.step(&ui.primary.map, SMALL_DT); + }); + return Transition::Pop; + } else if self.wizard.aborted() { + return Transition::Pop; + } + Transition::Keep + } + + fn draw(&self, g: &mut GfxCtx, _: &UI) { + self.wizard.draw(g); + } +} + +fn pick_scenario( + num_agents: Option, + map: &Map, + wizard: &mut WrappedWizard, +) -> Option { + let builtin = if let Some(n) = num_agents { + format!("random scenario with {} agents", n) + } else { + "random scenario with some agents".to_string() + }; + let map_name = map.get_name().to_string(); + let (_, scenario_name) = wizard.choose_something_no_keys::( + "Instantiate which scenario?", + Box::new(move || { + let mut list = vec![ + (builtin.clone(), "builtin".to_string()), + ("just buses".to_string(), "just buses".to_string()), + ]; + list.extend(abstutil::list_all_objects("scenarios", &map_name)); + list + }), + )?; + Some(if scenario_name == "builtin" { + if let Some(n) = num_agents { + Scenario::scaled_run(map, n) + } else { + Scenario::small_run(map) + } + } else if scenario_name == "just buses" { + Scenario::empty(map) + } else { + abstutil::read_binary( + &format!("../data/scenarios/{}/{}.bin", map.get_name(), scenario_name), + &mut Timer::throwaway(), + ) + .unwrap() + }) +} diff --git a/sim/src/make/scenario.rs b/sim/src/make/scenario.rs index 67bedd28e5..11dde2971c 100644 --- a/sim/src/make/scenario.rs +++ b/sim/src/make/scenario.rs @@ -249,6 +249,18 @@ impl Scenario { s } + // Just buses. + pub fn empty(map: &Map) -> Scenario { + Scenario { + scenario_name: "just buses".to_string(), + map_name: map.get_name().to_string(), + seed_parked_cars: Vec::new(), + spawn_over_time: Vec::new(), + border_spawn_over_time: Vec::new(), + individ_trips: Vec::new(), + } + } + // No border agents here, because making the count work is hard. pub fn scaled_run(map: &Map, num_agents: usize) -> Scenario { Scenario {