more synthetic fixes: redo mouseover when model changes, avoid panic

with 0-len new road line, fix reused IDs, fix contains_pt for
some precomputed polygons
This commit is contained in:
Dustin Carlino 2019-09-12 09:54:12 -07:00
parent 92a4f304f7
commit 353d89cd25
5 changed files with 37 additions and 16 deletions

View File

@ -51,9 +51,6 @@ impl<ID: ObjectID> World<ID> {
}
pub fn handle_mouseover(&mut self, ctx: &EventCtx) {
if !ctx.redo_mouseover() {
return;
}
self.current_selection = None;
let cursor = if let Some(pt) = ctx.canvas.get_cursor_in_map_space() {
@ -111,6 +108,6 @@ impl<ID: ObjectID> World<ID> {
pub fn delete_obj(&mut self, id: ID) {
let obj = self.objects.remove(&id).unwrap();
self.quadtree.remove(obj.quadtree_id);
self.quadtree.remove(obj.quadtree_id).unwrap();
}
}

View File

@ -76,7 +76,9 @@ impl GUI for UI {
ref mut osd,
} => {
{
self.world.handle_mouseover(ctx);
if ctx.redo_mouseover() {
self.world.handle_mouseover(ctx);
}
let len = self.hints.hints.len();
let mut txt = Text::prompt("Fix Map Geometry");
@ -284,7 +286,9 @@ impl GUI for UI {
}
State::BanTurnsBetween { from, ref mut osd } => {
ctx.canvas.handle_event(ctx.input);
self.world.handle_mouseover(ctx);
if ctx.redo_mouseover() {
self.world.handle_mouseover(ctx);
}
if ctx.input.key_pressed(Key::Escape, "cancel") {
self.state = State::main(ctx);

View File

@ -148,7 +148,7 @@ impl Polygon {
top_left.offset(width, height),
top_left.offset(Distance::ZERO, height),
],
indices: vec![0, 1, 2, 2, 3, 0],
indices: vec![0, 1, 2, 0, 2, 3],
}
}

View File

@ -38,6 +38,8 @@ pub struct Model {
intersections: BTreeMap<StableIntersectionID, Intersection>,
roads: BTreeMap<StableRoadID, Road>,
buildings: BTreeMap<BuildingID, Building>,
// Never reuse IDs, and don't worry about being sequential
id_counter: usize,
world: World<ID>,
}
@ -137,6 +139,7 @@ impl Model {
intersections: BTreeMap::new(),
roads: BTreeMap::new(),
buildings: BTreeMap::new(),
id_counter: 0,
world: World::new(&Bounds::new()),
}
}
@ -263,6 +266,7 @@ impl Model {
roads: HashSet::new(),
};
m.intersections.insert(*id, i);
m.id_counter = m.id_counter.max(id.0 + 1);
}
for (id, r) in &data.roads {
@ -279,6 +283,7 @@ impl Model {
);
m.intersections.get_mut(&i1).unwrap().roads.insert(*id);
m.intersections.get_mut(&i2).unwrap().roads.insert(*id);
m.id_counter = m.id_counter.max(id.0 + 1);
}
if !exclude_bldgs {
@ -288,6 +293,7 @@ impl Model {
center: b.polygon.center(),
};
m.buildings.insert(idx, b);
m.id_counter = m.id_counter.max(idx + 1);
}
}
@ -328,7 +334,8 @@ impl Model {
}
pub fn create_i(&mut self, center: Pt2D, prerender: &Prerender) {
let id = StableIntersectionID(self.intersections.len());
let id = StableIntersectionID(self.id_counter);
self.id_counter += 1;
self.intersections.insert(
id,
Intersection {
@ -431,7 +438,8 @@ impl Model {
println!("Road already exists");
return;
}
let id = StableRoadID(self.roads.len());
let id = StableRoadID(self.id_counter);
self.id_counter += 1;
self.roads.insert(
id,
Road {
@ -514,7 +522,8 @@ impl Model {
}
pub fn create_b(&mut self, center: Pt2D, prerender: &Prerender) {
let id = self.buildings.len();
let id = self.id_counter;
self.id_counter += 1;
self.buildings.insert(
id,
Building {

View File

@ -40,7 +40,9 @@ impl UI {
impl GUI for UI {
fn event(&mut self, ctx: &mut EventCtx) -> EventLoopMode {
ctx.canvas.handle_event(ctx.input);
self.model.handle_mouseover(ctx);
if ctx.redo_mouseover() {
self.model.handle_mouseover(ctx);
}
let cursor = {
if let Some(c) = ctx.canvas.get_cursor_in_map_space() {
@ -99,10 +101,12 @@ impl GUI for UI {
State::CreatingRoad(i1) => {
if ctx.input.key_pressed(Key::Escape, "stop defining road") {
self.state = State::Viewing;
self.model.handle_mouseover(ctx);
} else if let Some(ID::Intersection(i2)) = self.model.get_selection() {
if i1 != i2 && ctx.input.key_pressed(Key::R, "finalize road") {
self.model.create_road(i1, i2, ctx.prerender);
self.state = State::Viewing;
self.model.handle_mouseover(ctx);
}
}
}
@ -113,8 +117,10 @@ impl GUI for UI {
{
self.model.edit_lanes(id, s, ctx.prerender);
self.state = State::Viewing;
self.model.handle_mouseover(ctx);
} else if wizard.aborted() {
self.state = State::Viewing;
self.model.handle_mouseover(ctx);
}
}
State::SavingModel(ref mut wizard) => {
@ -134,6 +140,7 @@ impl GUI for UI {
self.state = State::CreatingRoad(i);
} else if ctx.input.key_pressed(Key::Backspace, "delete intersection") {
self.model.remove_i(i);
self.model.handle_mouseover(ctx);
} else if ctx.input.key_pressed(Key::T, "toggle intersection type") {
self.model.toggle_i_type(i, ctx.prerender);
} else if ctx.input.key_pressed(Key::L, "label intersection") {
@ -144,6 +151,7 @@ impl GUI for UI {
self.state = State::MovingBuilding(b);
} else if ctx.input.key_pressed(Key::Backspace, "delete building") {
self.model.remove_b(b);
self.model.handle_mouseover(ctx);
} else if ctx.input.key_pressed(Key::L, "label building") {
self.state = State::LabelingBuilding(b, Wizard::new());
}
@ -153,6 +161,7 @@ impl GUI for UI {
.key_pressed(Key::Backspace, &format!("delete road {}", r))
{
self.model.remove_road(r);
self.model.handle_mouseover(ctx);
} else if ctx.input.key_pressed(Key::E, "edit lanes") {
self.state = State::EditingRoad(r, Wizard::new());
} else if ctx.input.key_pressed(Key::S, "swap lanes") {
@ -170,8 +179,12 @@ impl GUI for UI {
}
} else if ctx.input.key_pressed(Key::I, "create intersection") {
self.model.create_i(cursor, ctx.prerender);
self.model.handle_mouseover(ctx);
// TODO Silly bug: Mouseover doesn't actually work! I think the cursor being
// dead-center messes up the precomputed triangles.
} else if ctx.input.key_pressed(Key::B, "create building") {
self.model.create_b(cursor, ctx.prerender);
self.model.handle_mouseover(ctx);
}
}
}
@ -187,11 +200,9 @@ impl GUI for UI {
match self.state {
State::CreatingRoad(i1) => {
if let Some(cursor) = g.get_cursor_in_map_space() {
g.draw_line(
Color::GREEN,
Distance::meters(5.0),
&Line::new(self.model.get_i_center(i1), cursor),
);
if let Some(l) = Line::maybe_new(self.model.get_i_center(i1), cursor) {
g.draw_line(Color::GREEN, Distance::meters(5.0), &l);
}
}
}
State::LabelingBuilding(_, ref wizard)