make single spawn work from bldg to bldg or driving lane to driving lane

This commit is contained in:
Dustin Carlino 2019-01-21 11:14:22 -08:00
parent 998c27ddff
commit f58f8a7ef1
2 changed files with 101 additions and 51 deletions

View File

@ -3,10 +3,9 @@
## Quick n easy
- interactively spawn a car/ped somewhere to test this easily
- start to end of driving lanes
- stop disabling mouseover at low zoom when in this mode
- pathfinding or trace or something is wrong for walking; the last line sometimes has the wrong distance
- actually spawn stuff
- stop disabling mouseover at low zoom when in this mode
- then back to zorder for cars/peds
- try showing traffic signals by little boxes at the end of lanes

View File

@ -2,27 +2,36 @@ use crate::objects::{Ctx, ID};
use crate::plugins::{Plugin, PluginCtx};
use dimensioned::si;
use ezgui::{Color, GfxCtx, Key};
use map_model::{BuildingID, PathRequest, Pathfinder, Trace, LANE_THICKNESS};
use map_model::{BuildingID, LaneID, PathRequest, Pathfinder, Position, Trace, LANE_THICKNESS};
use std::f64;
pub struct SpawnAgent {
from_bldg: BuildingID,
maybe_goal: Option<(BuildingID, Option<Trace>)>,
// TODO Don't like the duplicated logic here.
pub enum SpawnAgent {
Walking(BuildingID, Option<(BuildingID, Option<Trace>)>),
Driving(LaneID, Option<(LaneID, Option<Trace>)>),
}
impl SpawnAgent {
pub fn new(ctx: &mut PluginCtx) -> Option<SpawnAgent> {
if let Some(ID::Building(id)) = ctx.primary.current_selection {
if ctx
.input
.contextual_action(Key::F3, "spawn an agent starting here")
{
return Some(SpawnAgent {
from_bldg: id,
maybe_goal: None,
});
match ctx.primary.current_selection {
Some(ID::Building(id)) => {
if ctx
.input
.contextual_action(Key::F3, "spawn an agent starting here")
{
return Some(SpawnAgent::Walking(id, None));
}
}
Some(ID::Lane(id)) => {
if ctx.primary.map.get_l(id).is_driving()
&& ctx
.input
.contextual_action(Key::F3, "spawn an agent starting here")
{
return Some(SpawnAgent::Driving(id, None));
}
}
_ => {}
}
None
}
@ -35,54 +44,96 @@ impl Plugin for SpawnAgent {
return false;
}
// TODO disabling mouseover at low zoom is actually annoying now
if let Some(ID::Building(id)) = ctx.primary.current_selection {
if self
.maybe_goal
.as_ref()
.map(|(b, _)| *b != id)
.unwrap_or(true)
{
self.maybe_goal = Some((id, None));
match self {
SpawnAgent::Walking(ref raw_from, ref maybe_to) => {
let from = raw_from.clone();
// TODO disabling mouseover at low zoom is actually annoying now
if let Some(ID::Building(id)) = ctx.primary.current_selection {
if maybe_to.as_ref().map(|(b, _)| *b != id).unwrap_or(true) {
*self = SpawnAgent::Walking(from, Some((id, None)));
let map = &ctx.primary.map;
let start = map.get_b(self.from_bldg).front_path.sidewalk;
if let Some(path) = Pathfinder::shortest_distance(
map,
PathRequest {
start,
end: map.get_b(id).front_path.sidewalk,
can_use_bike_lanes: false,
can_use_bus_lanes: false,
},
) {
self.maybe_goal =
Some((id, path.trace(map, start.dist_along(), f64::MAX * si::M)));
let map = &ctx.primary.map;
let start = map.get_b(from).front_path.sidewalk;
if let Some(path) = Pathfinder::shortest_distance(
map,
PathRequest {
start,
end: map.get_b(id).front_path.sidewalk,
can_use_bike_lanes: false,
can_use_bus_lanes: false,
},
) {
*self = SpawnAgent::Walking(
from,
Some((id, path.trace(map, start.dist_along(), f64::MAX * si::M))),
);
}
}
if ctx.input.contextual_action(Key::F3, "end the agent here") {
// TODO spawn em
return false;
}
} else {
*self = SpawnAgent::Walking(from, None);
}
}
} else {
self.maybe_goal = None;
}
SpawnAgent::Driving(ref raw_from, ref maybe_to) => {
let from = raw_from.clone();
// TODO disabling mouseover at low zoom is actually annoying now
if let Some(ID::Lane(id)) = ctx.primary.current_selection {
// TODO Ideally we'd also check id is a driving lane and short-circuit here,
// but just let pathfinding take care of it
if maybe_to.as_ref().map(|(l, _)| *l != id).unwrap_or(true) {
*self = SpawnAgent::Driving(from, Some((id, None)));
if self.maybe_goal.is_some() && ctx.input.contextual_action(Key::F3, "end the agent here") {
// TODO spawn em
return false;
}
let map = &ctx.primary.map;
if let Some(path) = Pathfinder::shortest_distance(
map,
PathRequest {
start: Position::new(from, 0.0 * si::M),
end: Position::new(id, map.get_l(id).length()),
can_use_bike_lanes: false,
can_use_bus_lanes: false,
},
) {
*self = SpawnAgent::Driving(
from,
Some((id, path.trace(map, 0.0 * si::M, f64::MAX * si::M))),
);
}
}
if ctx.input.contextual_action(Key::F3, "end the agent here") {
// TODO spawn em
return false;
}
} else {
*self = SpawnAgent::Driving(from, None);
}
}
};
true
}
fn draw(&self, g: &mut GfxCtx, ctx: &Ctx) {
if let Some((_, Some(ref trace))) = self.maybe_goal {
g.draw_polygon(ctx.cs.get("route"), &trace.make_polygons(LANE_THICKNESS));
match self {
SpawnAgent::Walking(_, Some((_, Some(ref trace))))
| SpawnAgent::Driving(_, Some((_, Some(ref trace)))) => {
g.draw_polygon(ctx.cs.get("route"), &trace.make_polygons(LANE_THICKNESS));
}
_ => {}
}
}
fn color_for(&self, obj: ID, ctx: &Ctx) -> Option<Color> {
if ID::Building(self.from_bldg) == obj {
Some(ctx.cs.get("selected"))
} else {
None
match (self, obj) {
(SpawnAgent::Walking(b1, _), ID::Building(b2)) if *b1 == b2 => {
Some(ctx.cs.get("selected"))
}
(SpawnAgent::Driving(l1, _), ID::Lane(l2)) if *l1 == l2 => Some(ctx.cs.get("selected")),
_ => None,
}
}
}