1pub mod bbox;
2pub mod geometry;
3pub mod light;
4pub mod linedef;
5pub mod meta;
6pub mod mini;
7pub mod particle;
8pub mod pixelsource;
9pub mod sector;
10pub mod softrig;
11pub mod surface;
12pub mod tile;
13pub mod vertex;
14
15use crate::{
16 BBox, Keyform, MapMini, PixelSource, ShapeFXGraph, SoftRig, SoftRigAnimator, Surface, Terrain,
17 Value, ValueContainer,
18};
19use codegridfx::Module;
20use indexmap::IndexMap;
21use std::collections::VecDeque;
22use theframework::prelude::{FxHashMap, FxHashSet};
23
24use linedef::*;
25use sector::*;
26use serde::{Deserialize, Serialize};
27use uuid::Uuid;
28use vek::{Vec2, Vec3, Vec4};
29use vertex::*;
30
31use crate::{Entity, Item, Light};
32
33#[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Copy)]
34pub enum MapCamera {
35 TwoD,
36 ThreeDIso,
37 ThreeDFirstPerson,
38}
39
40#[derive(Serialize, Deserialize, PartialEq, Clone, Debug, Copy)]
41pub enum MapToolType {
42 General,
43 Selection,
44 Vertex,
45 Linedef,
46 Sector,
47 Effects,
48 Rect,
49 Game,
50 MiniMap,
51 World,
52}
53
54#[derive(Serialize, Deserialize, Clone, Debug)]
55pub struct Map {
56 #[serde(default)]
57 pub id: Uuid,
58 pub name: String,
59
60 pub offset: Vec2<f32>,
61 pub grid_size: f32,
62 pub subdivisions: f32,
63
64 #[serde(default)]
65 pub terrain: Terrain,
66
67 #[serde(skip)]
69 pub possible_polygon: Vec<u32>,
70
71 #[serde(skip)]
73 pub curr_grid_pos: Option<Vec2<f32>>,
74 #[serde(skip)]
75 pub curr_mouse_pos: Option<Vec2<f32>>,
76 #[serde(skip)]
77 pub curr_rectangle: Option<(Vec2<f32>, Vec2<f32>)>,
78
79 pub vertices: Vec<Vertex>,
80 pub linedefs: Vec<Linedef>,
81 pub sectors: Vec<Sector>,
82
83 #[serde(default)]
84 pub shapefx_graphs: IndexMap<Uuid, ShapeFXGraph>,
85
86 pub sky_texture: Option<Uuid>,
87
88 pub camera: MapCamera,
90 #[serde(skip)]
91 pub camera_xz: Option<Vec2<f32>>,
92 #[serde(skip)]
93 pub look_at_xz: Option<Vec2<f32>>,
94
95 pub lights: Vec<Light>,
97
98 pub entities: Vec<Entity>,
100
101 pub items: Vec<Item>,
103
104 pub selected_vertices: Vec<u32>,
106 pub selected_linedefs: Vec<u32>,
107 pub selected_sectors: Vec<u32>,
108
109 pub selected_entity_item: Option<Uuid>,
110
111 #[serde(default)]
113 pub properties: ValueContainer,
114
115 #[serde(default)]
117 pub softrigs: IndexMap<Uuid, SoftRig>,
118
119 #[serde(skip)]
121 pub editing_rig: Option<Uuid>,
122
123 #[serde(skip)]
125 pub soft_animator: Option<SoftRigAnimator>,
126
127 #[serde(default)]
129 pub surfaces: IndexMap<Uuid, Surface>,
130
131 #[serde(default)]
133 pub profiles: FxHashMap<Uuid, Map>,
134
135 #[serde(default)]
137 pub shaders: IndexMap<Uuid, Module>,
138
139 #[serde(default)]
142 pub changed: u32,
143}
144
145impl Default for Map {
146 fn default() -> Self {
147 Self::new()
148 }
149}
150
151impl Map {
152 pub fn new() -> Self {
153 Self {
154 id: Uuid::new_v4(),
155 name: "New Map".to_string(),
156
157 offset: Vec2::zero(),
158 grid_size: 30.0,
159 subdivisions: 1.0,
160
161 terrain: Terrain::default(),
162
163 possible_polygon: vec![],
164 curr_grid_pos: None,
165 curr_mouse_pos: None,
166 curr_rectangle: None,
167
168 vertices: vec![],
169 linedefs: vec![],
170 sectors: vec![],
171
172 shapefx_graphs: IndexMap::default(),
173 sky_texture: None,
174
175 camera: MapCamera::TwoD,
176 camera_xz: None,
177 look_at_xz: None,
178
179 lights: vec![],
180 entities: vec![],
181 items: vec![],
182
183 selected_vertices: vec![],
184 selected_linedefs: vec![],
185 selected_sectors: vec![],
186
187 selected_entity_item: None,
188
189 properties: ValueContainer::default(),
190 softrigs: IndexMap::default(),
191 editing_rig: None,
192 soft_animator: None,
193
194 surfaces: IndexMap::default(),
195 profiles: FxHashMap::default(),
196 shaders: IndexMap::default(),
197
198 changed: 0,
199 }
200 }
201
202 pub fn clear_temp(&mut self) {
204 self.possible_polygon = vec![];
205 self.curr_grid_pos = None;
206 self.curr_rectangle = None;
207 }
208
209 pub fn clear_selection(&mut self) {
211 self.selected_vertices = vec![];
212 self.selected_linedefs = vec![];
213 self.selected_sectors = vec![];
214 self.selected_entity_item = None;
215 }
216
217 pub fn get_surface_for_sector_id(&self, sector_id: u32) -> Option<&Surface> {
219 self.surfaces
220 .values()
221 .find(|surface| surface.sector_id == sector_id)
222 }
223
224 pub fn get_surface_for_sector_id_mut(&mut self, sector_id: u32) -> Option<&mut Surface> {
226 self.surfaces
227 .values_mut()
228 .find(|surface| surface.sector_id == sector_id)
229 }
230
231 pub fn update_surfaces(&mut self) {
233 let mut surfaces = std::mem::take(&mut self.surfaces);
234 for (_id, surface) in surfaces.iter_mut() {
235 surface.calculate_geometry(self);
236 }
237 self.surfaces = surfaces;
238 }
239
240 pub fn as_mini(&self, blocking_tiles: &FxHashSet<Uuid>) -> MapMini {
242 let mut linedefs: Vec<CompiledLinedef> = vec![];
243 let mut occluded_sectors: Vec<(BBox, f32)> = vec![];
244
245 let mut blocked_tiles = FxHashSet::default();
246
247 for sector in self.sectors.iter() {
248 let mut add_it = false;
249
250 let occlusion = sector.properties.get_float_default("occlusion", 1.0);
252 if occlusion < 1.0 {
253 let mut bbox = sector.bounding_box(self);
254 bbox.expand(Vec2::new(0.1, 0.1));
255 occluded_sectors.push((bbox, occlusion));
256 }
257
258 if sector.layer.is_some() {
259 let render_mode = sector.properties.contains("rect");
260 if render_mode {
261 add_it = false;
262 }
263 match sector.properties.get_default_source() {
265 Some(PixelSource::TileId(id)) => {
266 if blocking_tiles.contains(id) {
267 add_it = true;
268 if let Some(center) = sector.center(self) {
269 blocked_tiles.insert(center.map(|c| (c.floor()) as i32));
270 }
271 }
272 }
273 Some(PixelSource::MaterialId(id)) => {
274 if blocking_tiles.contains(id) {
275 add_it = true;
276 }
277 }
278 _ => {}
279 }
280 }
281
282 if add_it {
283 for linedef_id in sector.linedefs.iter() {
284 if let Some(linedef) = self.find_linedef(*linedef_id) {
285 if let Some(start) = self.find_vertex(linedef.start_vertex) {
286 if let Some(end) = self.find_vertex(linedef.end_vertex) {
287 let sy = start.as_vec3_world().y;
288 let ey = end.as_vec3_world().y;
289 if sy == 0.0 && ey == 0.0 {
290 let cl = CompiledLinedef::new(
291 start.as_vec2(),
292 end.as_vec2(),
293 linedef.properties.get_float_default("wall_width", 0.0),
294 linedef.properties.get_float_default("wall_height", 0.0),
295 );
296 linedefs.push(cl);
297 }
298 }
299 }
300 }
301 }
302 }
303 }
304
305 for l in self.linedefs.iter() {
306 if l.sector_ids.is_empty() {
307 let wall_height = l.properties.get_float_default("wall_height", 0.0);
308 let mut add_it = false;
309
310 match l.properties.get("source") {
312 Some(Value::Source(PixelSource::TileId(id))) => {
313 if blocking_tiles.contains(id) {
314 add_it = true;
315 }
316 }
317 Some(Value::Source(PixelSource::MaterialId(id))) => {
318 if blocking_tiles.contains(id) {
319 add_it = true;
320 }
321 }
322 _ => {}
323 }
324
325 if add_it {
326 if let Some(start) = self.find_vertex(l.start_vertex) {
327 if let Some(end) = self.find_vertex(l.end_vertex) {
328 let sy = start.as_vec3_world().y;
329 let ey = end.as_vec3_world().y;
330 if sy == 0.0 && ey == 0.0 {
331 let cl = CompiledLinedef::new(
332 start.as_vec2(),
333 end.as_vec2(),
334 l.properties.get_float_default("wall_width", 0.0),
335 wall_height,
336 );
337 linedefs.push(cl);
338 }
339 }
340 }
341 }
342 }
343 }
344
345 let mut mini = MapMini::new(self.offset, self.grid_size, linedefs, occluded_sectors);
346 mini.blocked_tiles = blocked_tiles;
347 mini
348 }
349
350 pub fn bbox(&self) -> BBox {
352 let min_x = self
354 .vertices
355 .iter()
356 .map(|v| v.x)
357 .fold(f32::INFINITY, f32::min);
358 let max_x = self
359 .vertices
360 .iter()
361 .map(|v| v.x)
362 .fold(f32::NEG_INFINITY, f32::max);
363 let min_y = self
364 .vertices
365 .iter()
366 .map(|v| v.y)
367 .fold(f32::INFINITY, f32::min);
368 let max_y = self
369 .vertices
370 .iter()
371 .map(|v| v.y)
372 .fold(f32::NEG_INFINITY, f32::max);
373 BBox {
374 min: Vec2::new(min_x, min_y),
375 max: Vec2::new(max_x, max_y),
376 }
377 }
378
379 pub fn bounding_box(&self) -> Option<Vec4<f32>> {
381 if self.vertices.is_empty() {
382 return None; }
384
385 let min_x = self
387 .vertices
388 .iter()
389 .map(|v| v.x)
390 .fold(f32::INFINITY, f32::min);
391 let max_x = self
392 .vertices
393 .iter()
394 .map(|v| v.x)
395 .fold(f32::NEG_INFINITY, f32::max);
396 let min_y = self
397 .vertices
398 .iter()
399 .map(|v| v.y)
400 .fold(f32::INFINITY, f32::min);
401 let max_y = self
402 .vertices
403 .iter()
404 .map(|v| v.y)
405 .fold(f32::NEG_INFINITY, f32::max);
406
407 let width = max_x - min_x;
409 let height = max_y - min_y;
410
411 Some(Vec4::new(min_x, min_y, width, height))
413 }
414
415 pub fn tick(&mut self, delta_time: f32) {
417 if let Some(anim) = &mut self.soft_animator {
418 anim.tick(delta_time);
419 }
420 }
421
422 pub fn get_vertex(&self, vertex_id: u32) -> Option<Vec2<f32>> {
424 let base = self.vertices.iter().find(|v| v.id == vertex_id)?;
426 let base_pos = Vec2::new(base.x, base.y);
427
428 if let Some(animator) = &self.soft_animator {
430 if let Some(rig) = animator.get_blended_rig(self) {
431 if let Some((_, pos)) = rig
432 .keyforms
433 .first()
434 .and_then(|key| key.vertex_positions.iter().find(|(id, _)| *id == vertex_id))
435 {
436 return Some(*pos);
437 }
438 }
439 }
440
441 if self.soft_animator.is_none() {
443 if let Some(rig_id) = self.editing_rig {
444 if let Some(rig) = self.softrigs.get(&rig_id) {
445 for keyform in &rig.keyforms {
446 if let Some((_, pos)) = keyform
447 .vertex_positions
448 .iter()
449 .find(|(id, _)| *id == vertex_id)
450 {
451 return Some(*pos);
452 }
453 }
454 }
455 }
456 }
457
458 Some(base_pos)
460 }
461
462 pub fn get_vertex_3d(&self, vertex_id: u32) -> Option<Vec3<f32>> {
464 let base = self.vertices.iter().find(|v| v.id == vertex_id)?;
466 let base_pos = Vec3::new(base.x, base.z, base.y);
467
468 Some(base_pos)
500 }
501
502 pub fn update_vertex(&mut self, vertex_id: u32, new_position: Vec2<f32>) {
505 if let Some(rig_id) = self.editing_rig {
507 if let Some(rig) = self.softrigs.get_mut(&rig_id) {
508 for keyform in &mut rig.keyforms {
510 if let Some(entry) = keyform
511 .vertex_positions
512 .iter_mut()
513 .find(|(id, _)| *id == vertex_id)
514 {
515 entry.1 = new_position;
516 return;
517 }
518 }
519
520 let new_keyform = Keyform {
522 vertex_positions: vec![(vertex_id, new_position)],
523 };
524
525 rig.keyforms.push(new_keyform);
526 return;
527 }
528 }
529
530 if let Some(v) = self.vertices.iter_mut().find(|v| v.id == vertex_id) {
532 v.x = new_position.x;
533 v.y = new_position.y;
534 }
535 }
536
537 pub fn add_vertex_at(&mut self, mut x: f32, mut y: f32) -> u32 {
539 let subdivisions = 1.0 / self.subdivisions;
540
541 x = (x / subdivisions).round() * subdivisions;
542 y = (y / subdivisions).round() * subdivisions;
543
544 if let Some(id) = self.find_vertex_at(x, y) {
546 return id;
547 }
548
549 if let Some(id) = self.find_free_vertex_id() {
550 let vertex = Vertex::new(id, x, y);
551 self.vertices.push(vertex);
552 id
553 } else {
554 println!("No free vertex ID available");
555 0
556 }
557 }
558
559 pub fn add_vertex_at_3d(&mut self, mut x: f32, mut y: f32, mut z: f32, snap: bool) -> u32 {
561 if snap {
563 let subdivisions = 1.0 / self.subdivisions;
564 x = (x / subdivisions).round() * subdivisions;
565 y = (y / subdivisions).round() * subdivisions;
566 z = (z / subdivisions).round() * subdivisions;
567 }
568
569 if let Some(id) = self.find_vertex_at_3d(x, y, z) {
571 return id;
572 }
573
574 if let Some(id) = self.find_free_vertex_id() {
576 let vertex = Vertex::new_3d(id, x, y, z);
577 self.vertices.push(vertex);
578 id
579 } else {
580 println!("No free vertex ID available");
581 0
582 }
583 }
584
585 pub fn find_vertex_at_3d(&self, x: f32, y: f32, z: f32) -> Option<u32> {
587 self.vertices
588 .iter()
589 .find(|v| v.x == x && v.y == y && v.z == z)
590 .map(|v| v.id)
591 }
592
593 pub fn find_vertex_at(&self, x: f32, y: f32) -> Option<u32> {
595 self.vertices
596 .iter()
597 .find(|v| v.x == x && v.y == y)
598 .map(|v| v.id)
599 }
600
601 pub fn find_vertex(&self, id: u32) -> Option<&Vertex> {
603 self.vertices.iter().find(|vertex| vertex.id == id)
604 }
605
606 pub fn find_vertex_mut(&mut self, id: u32) -> Option<&mut Vertex> {
608 self.vertices.iter_mut().find(|vertex| vertex.id == id)
609 }
610
611 pub fn find_linedef(&self, id: u32) -> Option<&Linedef> {
613 self.linedefs.iter().find(|linedef| linedef.id == id)
614 }
615
616 pub fn find_linedef_mut(&mut self, id: u32) -> Option<&mut Linedef> {
618 self.linedefs.iter_mut().find(|linedef| linedef.id == id)
619 }
620
621 pub fn find_sector(&self, id: u32) -> Option<&Sector> {
623 self.sectors.iter().find(|sector| sector.id == id)
624 }
625
626 pub fn find_sector_mut(&mut self, id: u32) -> Option<&mut Sector> {
628 self.sectors.iter_mut().find(|sector| sector.id == id)
629 }
630
631 pub fn create_linedef(&mut self, start_vertex: u32, end_vertex: u32) -> (u32, Option<u32>) {
633 let mut sector_id: Option<u32> = None;
634
635 if let Some(existing) = self
637 .linedefs
638 .iter()
639 .find(|l| l.start_vertex == start_vertex && l.end_vertex == end_vertex)
640 {
641 let id = existing.id;
642 if let Some(polygon) = self.find_directed_cycle_from_edge(id) {
643 self.possible_polygon = polygon;
644 sector_id = self.create_sector_from_polygon();
645 }
646 return (id, sector_id);
647 }
648
649 if let Some(id) = self.find_free_linedef_id() {
651 let linedef = Linedef::new(id, start_vertex, end_vertex);
652 self.linedefs.push(linedef);
653
654 if let Some(polygon) = self.find_directed_cycle_from_edge(id) {
655 self.possible_polygon = polygon;
656
657 if let Some(sid) = self.create_sector_from_polygon() {
658 if let Some(linedef) = self.find_linedef_mut(id) {
659 if !linedef.sector_ids.contains(&sid) {
662 linedef.sector_ids.push(sid);
663 }
664 }
665 sector_id = Some(sid);
666 }
667 }
668 (id, sector_id)
669 } else {
670 println!("No free linedef ID available");
671 (0, None)
672 }
673 }
674 pub fn create_linedef_manual(&mut self, start_vertex: u32, end_vertex: u32) -> u32 {
678 if let Some(existing) = self
680 .linedefs
681 .iter()
682 .find(|l| l.start_vertex == start_vertex && l.end_vertex == end_vertex)
683 {
684 let id = existing.id;
685 if !self.possible_polygon.contains(&id) {
687 self.possible_polygon.push(id);
688 }
689 return id;
690 }
691
692 if let Some(id) = self.find_free_linedef_id() {
694 let linedef = Linedef::new(id, start_vertex, end_vertex);
695 self.linedefs.push(linedef);
696
697 self.possible_polygon.push(id);
699 id
700 } else {
701 println!("No free linedef ID available");
702 0
703 }
704 }
705
706 pub fn close_polygon_manual(&mut self) -> Option<u32> {
709 if self.test_for_closed_polygon() {
710 self.create_sector_from_polygon()
711 } else {
712 None
713 }
714 }
715
716 pub fn is_vertex_in_rect_sector(&self, vertex_id: u32) -> bool {
718 self.sectors.iter().any(|sector| {
719 if sector.properties.contains("rect") {
720 sector.linedefs.iter().any(|&line_id| {
721 if let Some(line) = self.find_linedef(line_id) {
722 line.start_vertex == vertex_id || line.end_vertex == vertex_id
723 } else {
724 false
725 }
726 })
727 } else {
728 false
729 }
730 })
731 }
732
733 pub fn duplicate_vertex(&mut self, vertex_id: u32) -> Option<u32> {
735 if let Some(vertex) = self.find_vertex(vertex_id) {
736 let new_id = self.find_free_vertex_id()?;
737 let mut new_vertex = vertex.clone();
738 new_vertex.id = new_id;
739 self.vertices.push(new_vertex);
740 Some(new_id)
741 } else {
742 None
743 }
744 }
745
746 pub fn replace_vertex_in_sector(
748 &mut self,
749 sector_id: u32,
750 old_vertex_id: u32,
751 new_vertex_id: u32,
752 ) {
753 if let Some(sector) = self.find_sector(sector_id) {
754 let linedef_ids: Vec<u32> = sector.linedefs.clone();
755 for linedef_id in linedef_ids {
756 if let Some(linedef) = self.find_linedef(linedef_id) {
757 let is_shared = linedef.sector_ids.len() > 1
759 || self
760 .sectors
761 .iter()
762 .any(|s| s.id != sector_id && s.linedefs.contains(&linedef_id));
763
764 let needs_vertex_change = linedef.start_vertex == old_vertex_id
765 || linedef.end_vertex == old_vertex_id;
766
767 if is_shared && needs_vertex_change {
768 let new_start = if linedef.start_vertex == old_vertex_id {
770 new_vertex_id
771 } else {
772 linedef.start_vertex
773 };
774 let new_end = if linedef.end_vertex == old_vertex_id {
775 new_vertex_id
776 } else {
777 linedef.end_vertex
778 };
779
780 if let Some(new_linedef_id) = self.find_free_linedef_id() {
781 let mut new_linedef = linedef.clone();
782 new_linedef.id = new_linedef_id;
783 new_linedef.start_vertex = new_start;
784 new_linedef.end_vertex = new_end;
785 new_linedef.sector_ids = vec![sector_id];
786 self.linedefs.push(new_linedef);
787
788 if let Some(old_linedef) = self.find_linedef_mut(linedef_id) {
790 old_linedef.sector_ids.retain(|&sid| sid != sector_id);
791 }
792
793 if let Some(sector) = self.find_sector_mut(sector_id) {
795 if let Some(pos) =
796 sector.linedefs.iter().position(|&id| id == linedef_id)
797 {
798 sector.linedefs[pos] = new_linedef_id;
799 }
800 }
801 }
802 } else if needs_vertex_change {
803 if let Some(linedef) = self.find_linedef_mut(linedef_id) {
805 if linedef.start_vertex == old_vertex_id {
806 linedef.start_vertex = new_vertex_id;
807 }
808 if linedef.end_vertex == old_vertex_id {
809 linedef.end_vertex = new_vertex_id;
810 }
811 }
812 }
813 }
814 }
815 }
816 }
817 fn find_directed_cycle_from_edge(&self, edge_id: u32) -> Option<Vec<u32>> {
820 let edge = self.find_linedef(edge_id)?;
821
822 let path = self.find_directed_path(edge.end_vertex, edge.start_vertex, edge_id)?;
824
825 if path.len() + 1 < 3 {
827 return None;
828 }
829
830 let mut cycle = path;
831 cycle.push(edge_id);
832 Some(cycle)
833 }
834
835 fn find_directed_path(&self, from: u32, to: u32, skip_edge: u32) -> Option<Vec<u32>> {
838 let mut queue = VecDeque::new();
839 let mut visited = FxHashSet::default();
840 let mut parent: FxHashMap<u32, (u32, u32)> = FxHashMap::default(); queue.push_back(from);
843 visited.insert(from);
844
845 while let Some(v) = queue.pop_front() {
846 for edge in self.linedefs.iter().filter(|e| e.start_vertex == v) {
848 if edge.id == skip_edge {
849 continue;
850 }
851 let next = edge.end_vertex;
852
853 if visited.contains(&next) {
854 continue;
855 }
856
857 parent.insert(next, (v, edge.id));
858
859 if next == to {
860 let mut path = Vec::new();
862 let mut current = to;
863 while let Some((prev_vertex, edge_id)) = parent.get(¤t) {
864 path.push(*edge_id);
865 if *prev_vertex == from {
866 break;
867 }
868 current = *prev_vertex;
869 }
870 path.reverse();
871 return Some(path);
872 }
873
874 visited.insert(next);
875 queue.push_back(next);
876 }
877 }
878
879 None
880 }
881
882 pub fn test_for_closed_polygon(&self) -> bool {
884 if self.possible_polygon.len() < 3 {
885 return false; }
887
888 if let Some(first_linedef) = self.find_linedef(self.possible_polygon[0]) {
889 if let Some(last_linedef) =
890 self.find_linedef(self.possible_polygon[self.possible_polygon.len() - 1])
891 {
892 return last_linedef.end_vertex == first_linedef.start_vertex;
894 }
895 }
896 false
897 }
898
899 pub fn create_sector_from_polygon(&mut self) -> Option<u32> {
901 if !self.test_for_closed_polygon() {
902 return None;
904 }
905
906 if self
908 .find_sector_by_linedefs(&self.possible_polygon)
909 .is_some()
910 {
911 self.possible_polygon.clear();
915 return None;
916 }
917
918 if let Some(sector_id) = self.find_free_sector_id() {
920 for &id in &self.possible_polygon {
921 if let Some(linedef) = self.linedefs.iter_mut().find(|l| l.id == id) {
922 if !linedef.sector_ids.contains(§or_id) {
924 linedef.sector_ids.push(sector_id);
925 }
926 }
927 }
928
929 let sector = Sector::new(sector_id, self.possible_polygon.clone());
930 self.sectors.push(sector);
931
932 self.possible_polygon.clear();
933 Some(sector_id)
934 } else {
935 None
936 }
937 }
938
939 fn find_sector_by_linedefs(&self, linedefs: &[u32]) -> Option<u32> {
941 for sector in &self.sectors {
942 if sector.linedefs.len() == linedefs.len()
943 && sector.linedefs.iter().all(|id| linedefs.contains(id))
944 {
945 return Some(sector.id);
946 }
947 }
948 None
949 }
950
951 pub fn delete_elements(&mut self, vertex_ids: &[u32], linedef_ids: &[u32], sector_ids: &[u32]) {
953 let mut all_linedef_ids = linedef_ids.to_vec();
954 let all_vertex_ids = vertex_ids.to_vec();
955
956 if !sector_ids.is_empty() {
958 for sector in &self.sectors {
959 if sector_ids.contains(§or.id) {
960 for &linedef_id in §or.linedefs {
961 let used_in_sector_linedefs = self.sectors.iter().any(|s| {
964 s.id != sector.id
965 && !sector_ids.contains(&s.id)
966 && s.linedefs.contains(&linedef_id)
967 });
968
969 let used_in_linedef_sector_ids =
970 if let Some(linedef) = self.find_linedef(linedef_id) {
971 linedef
972 .sector_ids
973 .iter()
974 .any(|&sid| sid != sector.id && !sector_ids.contains(&sid))
975 } else {
976 false
977 };
978
979 let used_elsewhere = used_in_sector_linedefs || used_in_linedef_sector_ids;
980
981 if !used_elsewhere && !all_linedef_ids.contains(&linedef_id) {
982 all_linedef_ids.push(linedef_id);
983 }
984 }
985 }
986 }
987 }
988 if !sector_ids.is_empty() {
1009 self.sectors
1010 .retain(|sector| !sector_ids.contains(§or.id));
1011
1012 let mut surfaces_to_remove: Vec<uuid::Uuid> = Vec::new();
1014 for (surf_id, surf) in self.surfaces.iter() {
1015 if sector_ids.contains(&surf.sector_id) {
1016 if let Some(profile_id) = surf.profile {
1017 self.profiles.remove(&profile_id);
1018 }
1019 surfaces_to_remove.push(*surf_id);
1020 }
1021 }
1022
1023 for sid in surfaces_to_remove {
1024 let _ = self.surfaces.shift_remove(&sid);
1025 }
1026
1027 for linedef in &mut self.linedefs {
1030 linedef.sector_ids.retain(|sid| !sector_ids.contains(sid));
1032 }
1033 }
1034
1035 for &vertex_id in &all_vertex_ids {
1037 for linedef in &self.linedefs {
1038 if (linedef.start_vertex == vertex_id || linedef.end_vertex == vertex_id)
1039 && !all_linedef_ids.contains(&linedef.id)
1040 {
1041 all_linedef_ids.push(linedef.id);
1042 }
1043 }
1044 }
1045
1046 if !all_linedef_ids.is_empty() {
1048 self.linedefs
1049 .retain(|linedef| !all_linedef_ids.contains(&linedef.id));
1050 }
1051
1052 self.cleanup_sectors();
1053
1054 if !all_vertex_ids.is_empty() {
1056 self.vertices
1057 .retain(|vertex| !all_vertex_ids.contains(&vertex.id));
1058 }
1059 self.sanitize();
1061 }
1062
1063 fn cleanup_sectors(&mut self) {
1065 let valid_linedef_ids: std::collections::HashSet<u32> =
1066 self.linedefs.iter().map(|l| l.id).collect();
1067
1068 for sector in &mut self.sectors {
1069 sector
1070 .linedefs
1071 .retain(|linedef_id| valid_linedef_ids.contains(linedef_id));
1072 }
1073
1074 self.sectors.retain(|sector| !sector.linedefs.is_empty());
1076 }
1077
1078 pub fn is_linedef_in_closed_polygon(&self, linedef_id: u32) -> bool {
1080 self.sectors
1081 .iter()
1082 .any(|sector| sector.linedefs.contains(&linedef_id))
1083 }
1084
1085 pub fn add_to_selection(&mut self, vertices: Vec<u32>, linedefs: Vec<u32>, sectors: Vec<u32>) {
1087 for v in &vertices {
1088 if !self.selected_vertices.contains(v) {
1089 self.selected_vertices.push(*v);
1090 }
1091 }
1092 for l in &linedefs {
1093 if !self.selected_linedefs.contains(l) {
1094 self.selected_linedefs.push(*l);
1095 }
1096 }
1097 for s in §ors {
1098 if !self.selected_sectors.contains(s) {
1099 self.selected_sectors.push(*s);
1100 }
1101 }
1102 }
1103
1104 pub fn remove_from_selection(
1106 &mut self,
1107 vertices: Vec<u32>,
1108 linedefs: Vec<u32>,
1109 sectors: Vec<u32>,
1110 ) {
1111 for v in &vertices {
1112 self.selected_vertices.retain(|&selected| selected != *v);
1113 }
1114 for l in &linedefs {
1115 self.selected_linedefs.retain(|&selected| selected != *l);
1116 }
1117 for s in §ors {
1118 self.selected_sectors.retain(|&selected| selected != *s);
1119 }
1120 }
1121
1122 pub fn sorted_sectors_by_area(&self) -> Vec<&Sector> {
1124 let mut sectors_with_areas: Vec<(&Sector, f32)> = self
1125 .sectors
1126 .iter()
1127 .map(|sector| (sector, sector.area(self))) .collect();
1129
1130 sectors_with_areas
1132 .sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
1133
1134 sectors_with_areas
1136 .into_iter()
1137 .map(|(sector, _)| sector)
1138 .collect()
1139 }
1140
1141 pub fn add_midpoint(&mut self, linedef_id: u32) -> Option<u32> {
1143 let linedef = self.find_linedef(linedef_id)?.clone(); let start_vertex = self.find_vertex(linedef.start_vertex)?.clone();
1146 let end_vertex = self.find_vertex(linedef.end_vertex)?.clone();
1147
1148 let midpoint = Vec3::new(
1150 (start_vertex.x + end_vertex.x) / 2.0,
1151 (start_vertex.y + end_vertex.y) / 2.0,
1152 (start_vertex.z + end_vertex.z) / 2.0,
1153 );
1154
1155 let new_vertex_id = self.add_vertex_at_3d(midpoint.x, midpoint.y, midpoint.z, false);
1157
1158 let mut new_linedef_1 = Linedef::new(
1160 linedef_id, linedef.start_vertex,
1162 new_vertex_id,
1163 );
1164 let mut new_linedef_2 = Linedef::new(
1165 self.linedefs.len() as u32, new_vertex_id,
1167 linedef.end_vertex,
1168 );
1169
1170 new_linedef_1.properties = linedef.properties.clone();
1172 new_linedef_2.properties = linedef.properties.clone();
1173
1174 for sector in self.sectors.iter_mut() {
1176 if let Some(position) = sector.linedefs.iter().position(|&id| id == linedef_id) {
1177 sector.linedefs.splice(
1179 position..=position, [new_linedef_1.id, new_linedef_2.id].iter().cloned(), );
1182 }
1183 }
1184
1185 if let Some(index) = self.linedefs.iter().position(|l| l.id == linedef_id) {
1187 self.linedefs[index] = new_linedef_1; }
1189 self.linedefs.push(new_linedef_2); Some(new_vertex_id)
1193 }
1194
1195 pub fn find_sectors_with_vertex_indices(&self, vertex_indices: &[u32; 4]) -> Vec<u32> {
1198 let mut matching_sectors = Vec::new();
1199
1200 let mut new_vertex_set = vertex_indices.to_vec();
1201 new_vertex_set.sort();
1202
1203 for sector in &self.sectors {
1204 let mut sector_vertex_indices = Vec::new();
1205
1206 for &linedef_id in §or.linedefs {
1207 if let Some(linedef) = self.find_linedef(linedef_id) {
1208 sector_vertex_indices.push(linedef.start_vertex);
1209 sector_vertex_indices.push(linedef.end_vertex);
1210 }
1211 }
1212
1213 sector_vertex_indices.sort();
1215 sector_vertex_indices.dedup();
1216
1217 if sector_vertex_indices == new_vertex_set {
1219 matching_sectors.push(sector.id);
1220 }
1221 }
1222
1223 matching_sectors
1224 }
1225
1226 pub fn find_sector_at(&self, position: Vec2<f32>) -> Option<&Sector> {
1228 self.sectors
1229 .iter()
1230 .find(|s| s.is_inside(self, position) && s.layer.is_none())
1231 }
1232
1233 pub fn debug_print_vertices(&self) {
1235 for vertex in &self.vertices {
1236 let current_position = self
1237 .get_vertex(vertex.id)
1238 .unwrap_or(Vec2::new(vertex.x, vertex.y));
1239 println!(
1240 "Vertex ID: {}, Base: ({}, {}), Animated: ({}, {})",
1241 vertex.id, vertex.x, vertex.y, current_position.x, current_position.y
1242 );
1243 }
1244 }
1245
1246 pub fn info(&self) -> String {
1248 format!(
1249 "V {}, L {}, S {}",
1250 self.vertices.len(),
1251 self.linedefs.len(),
1252 self.sectors.len()
1253 )
1254 }
1255
1256 pub fn sanitize(&mut self) {
1260 let valid_vertex_ids: std::collections::HashSet<u32> =
1262 self.vertices.iter().map(|v| v.id).collect();
1263
1264 let mut orphaned_linedef_ids = Vec::new();
1265
1266 for linedef in &self.linedefs {
1267 if !valid_vertex_ids.contains(&linedef.start_vertex)
1268 || !valid_vertex_ids.contains(&linedef.end_vertex)
1269 {
1270 println!(
1271 "Sanitizing: removing orphaned linedef {} (references vertices {} -> {})",
1272 linedef.id, linedef.start_vertex, linedef.end_vertex
1273 );
1274 orphaned_linedef_ids.push(linedef.id);
1275 }
1276 }
1277
1278 if !orphaned_linedef_ids.is_empty() {
1279 self.linedefs
1280 .retain(|linedef| !orphaned_linedef_ids.contains(&linedef.id));
1281
1282 let sectors_before: std::collections::HashSet<u32> =
1284 self.sectors.iter().map(|s| s.id).collect();
1285
1286 self.cleanup_sectors();
1288
1289 let sectors_after: std::collections::HashSet<u32> =
1291 self.sectors.iter().map(|s| s.id).collect();
1292 let removed_sector_ids: Vec<u32> =
1293 sectors_before.difference(§ors_after).copied().collect();
1294
1295 if !removed_sector_ids.is_empty() {
1297 let mut surfaces_to_remove: Vec<uuid::Uuid> = Vec::new();
1298 for (surf_id, surf) in self.surfaces.iter() {
1299 if removed_sector_ids.contains(&surf.sector_id) {
1300 if let Some(profile_id) = surf.profile {
1301 self.profiles.remove(&profile_id);
1302 }
1303 surfaces_to_remove.push(*surf_id);
1304 }
1305 }
1306
1307 for sid in surfaces_to_remove {
1308 let _ = self.surfaces.shift_remove(&sid);
1309 }
1310
1311 println!(
1312 "Sanitized: removed {} sector(s) and their surfaces",
1313 removed_sector_ids.len()
1314 );
1315 }
1316
1317 println!(
1318 "Sanitized: removed {} orphaned linedef(s)",
1319 orphaned_linedef_ids.len()
1320 );
1321 }
1322
1323 let mut invalid_sectors = Vec::new();
1325 for sector in &self.sectors {
1326 if sector.linedefs.len() < 3 {
1328 println!(
1329 "Sanitizing: sector {} has only {} linedef(s), need at least 3",
1330 sector.id,
1331 sector.linedefs.len()
1332 );
1333 invalid_sectors.push(sector.id);
1334 continue;
1335 }
1336
1337 let mut has_invalid_linedef = false;
1339 for &linedef_id in §or.linedefs {
1340 if let Some(linedef) = self.find_linedef(linedef_id) {
1341 if self.find_vertex(linedef.start_vertex).is_none()
1342 || self.find_vertex(linedef.end_vertex).is_none()
1343 {
1344 println!(
1345 "Sanitizing: sector {} has linedef {} with invalid vertices",
1346 sector.id, linedef_id
1347 );
1348 has_invalid_linedef = true;
1349 break;
1350 }
1351 } else {
1352 println!(
1353 "Sanitizing: sector {} references non-existent linedef {}",
1354 sector.id, linedef_id
1355 );
1356 has_invalid_linedef = true;
1357 break;
1358 }
1359 }
1360 if has_invalid_linedef {
1361 invalid_sectors.push(sector.id);
1362 continue;
1363 }
1364
1365 if let Some(first_linedef) = self.find_linedef(sector.linedefs[0]) {
1367 if let Some(last_linedef) =
1368 self.find_linedef(sector.linedefs[sector.linedefs.len() - 1])
1369 {
1370 if last_linedef.end_vertex != first_linedef.start_vertex {
1371 println!(
1372 "Sanitizing: sector {} does not form a closed loop (last vertex {} != first vertex {})",
1373 sector.id, last_linedef.end_vertex, first_linedef.start_vertex
1374 );
1375 invalid_sectors.push(sector.id);
1376 continue;
1377 }
1378 }
1379 }
1380
1381 let mut has_zero_length = false;
1383 for &linedef_id in §or.linedefs {
1384 if let Some(linedef) = self.find_linedef(linedef_id) {
1385 if linedef.start_vertex == linedef.end_vertex {
1386 println!(
1387 "Sanitizing: sector {} has linedef {} with same start and end vertex {}",
1388 sector.id, linedef_id, linedef.start_vertex
1389 );
1390 has_zero_length = true;
1391 break;
1392 }
1393 }
1394 }
1395 if has_zero_length {
1396 invalid_sectors.push(sector.id);
1397 continue;
1398 }
1399
1400 let mut has_invalid_coords = false;
1402 for &linedef_id in §or.linedefs {
1403 if let Some(linedef) = self.find_linedef(linedef_id) {
1404 if let Some(start_v) = self.find_vertex(linedef.start_vertex) {
1405 if !start_v.x.is_finite()
1406 || !start_v.y.is_finite()
1407 || !start_v.z.is_finite()
1408 {
1409 println!(
1410 "Sanitizing: sector {} has vertex {} with invalid coordinates: ({}, {}, {})",
1411 sector.id, linedef.start_vertex, start_v.x, start_v.y, start_v.z
1412 );
1413 has_invalid_coords = true;
1414 break;
1415 }
1416 }
1417 if let Some(end_v) = self.find_vertex(linedef.end_vertex) {
1418 if !end_v.x.is_finite() || !end_v.y.is_finite() || !end_v.z.is_finite() {
1419 println!(
1420 "Sanitizing: sector {} has vertex {} with invalid coordinates: ({}, {}, {})",
1421 sector.id, linedef.end_vertex, end_v.x, end_v.y, end_v.z
1422 );
1423 has_invalid_coords = true;
1424 break;
1425 }
1426 }
1427 }
1428 }
1429 if has_invalid_coords {
1430 invalid_sectors.push(sector.id);
1431 }
1432 }
1433
1434 if !invalid_sectors.is_empty() {
1436 let mut surfaces_to_remove: Vec<uuid::Uuid> = Vec::new();
1438 for (surf_id, surf) in self.surfaces.iter() {
1439 if invalid_sectors.contains(&surf.sector_id) {
1440 if let Some(profile_id) = surf.profile {
1441 self.profiles.remove(&profile_id);
1442 }
1443 surfaces_to_remove.push(*surf_id);
1444 }
1445 }
1446
1447 for sid in surfaces_to_remove {
1448 let _ = self.surfaces.shift_remove(&sid);
1449 }
1450
1451 self.sectors.retain(|s| !invalid_sectors.contains(&s.id));
1452
1453 println!(
1454 "Sanitized: removed {} invalid sector(s)",
1455 invalid_sectors.len()
1456 );
1457 }
1458
1459 self.update_surfaces();
1461
1462 let mut invalid_surface_sectors = Vec::new();
1463 for (_surface_id, surface) in &self.surfaces {
1464 if !surface.is_valid() {
1465 println!(
1466 "Sanitizing: sector {} has surface with invalid transform (NaN/Inf)",
1467 surface.sector_id
1468 );
1469 invalid_surface_sectors.push(surface.sector_id);
1470 }
1471 }
1472
1473 if !invalid_surface_sectors.is_empty() {
1475 let mut surfaces_to_remove: Vec<uuid::Uuid> = Vec::new();
1477 for (surf_id, surf) in self.surfaces.iter() {
1478 if invalid_surface_sectors.contains(&surf.sector_id) {
1479 if let Some(profile_id) = surf.profile {
1480 self.profiles.remove(&profile_id);
1481 }
1482 surfaces_to_remove.push(*surf_id);
1483 }
1484 }
1485
1486 for sid in surfaces_to_remove {
1487 let _ = self.surfaces.shift_remove(&sid);
1488 }
1489
1490 self.sectors
1492 .retain(|s| !invalid_surface_sectors.contains(&s.id));
1493
1494 println!(
1495 "Sanitized: removed {} sector(s) with invalid surfaces",
1496 invalid_surface_sectors.len()
1497 );
1498 }
1499
1500 for linedef in &mut self.linedefs {
1502 linedef.sector_ids.clear();
1503 }
1504
1505 let mut associations: FxHashMap<u32, Vec<u32>> = FxHashMap::default();
1507 for sector in &self.sectors {
1508 let sector_id = sector.id;
1509 for &linedef_id in §or.linedefs {
1510 associations
1511 .entry(linedef_id)
1512 .or_insert_with(Vec::new)
1513 .push(sector_id);
1514 }
1515 }
1516
1517 for (linedef_id, sector_ids) in associations {
1519 if let Some(linedef) = self.linedefs.iter_mut().find(|l| l.id == linedef_id) {
1520 linedef.sector_ids = sector_ids;
1521 }
1522 }
1523 }
1524
1525 pub fn associate_linedefs_with_sectors(&mut self) {
1527 self.sanitize();
1528 }
1529
1530 pub fn is_linedef_in_rect(&self, linedef_id: u32) -> bool {
1549 for sector in &self.sectors {
1550 if sector.layer.is_none() {
1551 continue;
1552 }
1553
1554 if sector.linedefs.contains(&linedef_id) {
1555 return true;
1556 }
1557 }
1558 false
1559 }
1560
1561 pub fn find_free_vertex_id(&self) -> Option<u32> {
1563 (0..).find(|&id| !self.vertices.iter().any(|v| v.id == id))
1564 }
1565
1566 pub fn find_free_linedef_id(&self) -> Option<u32> {
1568 (0..).find(|&id| !self.linedefs.iter().any(|l| l.id == id))
1569 }
1570
1571 pub fn find_free_sector_id(&self) -> Option<u32> {
1573 (0..).find(|&id| !self.sectors.iter().any(|s| s.id == id))
1574 }
1575
1576 pub fn has_selection(&self) -> bool {
1578 !self.selected_vertices.is_empty()
1579 || !self.selected_linedefs.is_empty()
1580 || !self.selected_sectors.is_empty()
1581 }
1582
1583 pub fn is_empty(&self) -> bool {
1585 self.vertices.is_empty() && self.linedefs.is_empty() && self.sectors.is_empty()
1586 }
1587
1588 pub fn copy_selected(&mut self, cut: bool) -> Map {
1590 let mut clipboard = Map::new();
1591
1592 let mut old_to_new_vertex: FxHashMap<u32, u32> = FxHashMap::default();
1593 let mut old_to_new_linedef: FxHashMap<u32, u32> = FxHashMap::default();
1594 let mut vertex_ids: FxHashSet<u32> = FxHashSet::default();
1597 let mut linedef_ids: FxHashSet<u32> = self.selected_linedefs.iter().copied().collect();
1598 let sector_ids: FxHashSet<u32> = self.selected_sectors.iter().copied().collect();
1599
1600 for sid in §or_ids {
1602 if let Some(sector) = self.find_sector(*sid) {
1603 for &lid in §or.linedefs {
1604 linedef_ids.insert(lid);
1605 }
1606 }
1607 }
1608
1609 for lid in &linedef_ids {
1611 if let Some(ld) = self.find_linedef(*lid) {
1612 vertex_ids.insert(ld.start_vertex);
1613 vertex_ids.insert(ld.end_vertex);
1614 }
1615 }
1616
1617 for &vid in &self.selected_vertices {
1619 vertex_ids.insert(vid);
1620 }
1621
1622 let copied_vertices: Vec<Vertex> = vertex_ids
1624 .iter()
1625 .filter_map(|id| self.find_vertex(*id).cloned())
1626 .collect();
1627
1628 if copied_vertices.is_empty() {
1629 return clipboard;
1630 }
1631
1632 let min_x = copied_vertices
1633 .iter()
1634 .map(|v| v.x)
1635 .fold(f32::INFINITY, f32::min);
1636 let min_y = copied_vertices
1637 .iter()
1638 .map(|v| v.y)
1639 .fold(f32::INFINITY, f32::min);
1640 let offset = Vec2::new(min_x, min_y);
1641
1642 for old in copied_vertices {
1644 if let Some(new_id) = clipboard.find_free_vertex_id() {
1645 let mut new_v = old.clone();
1646 new_v.id = new_id;
1647 new_v.x -= offset.x;
1648 new_v.y -= offset.y;
1649 old_to_new_vertex.insert(old.id, new_id);
1650 clipboard.vertices.push(new_v);
1651 }
1652 }
1653
1654 for old_id in &linedef_ids {
1656 if let Some(ld) = self.find_linedef(*old_id).cloned() {
1657 if let Some(new_id) = clipboard.find_free_linedef_id() {
1658 let mut new_ld = ld.clone();
1659 new_ld.id = new_id;
1660 new_ld.start_vertex = *old_to_new_vertex.get(&ld.start_vertex).unwrap();
1661 new_ld.end_vertex = *old_to_new_vertex.get(&ld.end_vertex).unwrap();
1662 new_ld.sector_ids.clear();
1663 old_to_new_linedef.insert(ld.id, new_id);
1664 clipboard.linedefs.push(new_ld);
1665 }
1666 }
1667 }
1668
1669 for sid in §or_ids {
1671 if let Some(s) = self.find_sector(*sid).cloned() {
1672 if s.linedefs.iter().all(|id| linedef_ids.contains(id)) {
1673 if let Some(new_id) = clipboard.find_free_sector_id() {
1674 let mut new_s = s.clone();
1675 new_s.id = new_id;
1676 new_s.linedefs = s
1677 .linedefs
1678 .iter()
1679 .map(|id| *old_to_new_linedef.get(id).unwrap())
1680 .collect();
1681
1682 for &old_lid in &s.linedefs {
1684 if let Some(&new_lid) = old_to_new_linedef.get(&old_lid) {
1685 if let Some(ld) =
1686 clipboard.linedefs.iter_mut().find(|l| l.id == new_lid)
1687 {
1688 if !ld.sector_ids.contains(&new_id) {
1689 ld.sector_ids.push(new_id);
1690 }
1691 }
1692 }
1693 }
1694
1695 clipboard.sectors.push(new_s);
1696 }
1697 }
1698 }
1699 }
1700
1701 if cut {
1703 self.delete_elements(
1704 &vertex_ids.iter().copied().collect::<Vec<_>>(),
1705 &linedef_ids.iter().copied().collect::<Vec<_>>(),
1706 §or_ids.iter().copied().collect::<Vec<_>>(),
1707 );
1708 self.clear_selection();
1709 }
1710
1711 clipboard
1712 }
1713
1714 pub fn paste_at_position(&mut self, local_map: &Map, position: Vec2<f32>) {
1716 let mut vertex_map = FxHashMap::default();
1717 let mut linedef_map = FxHashMap::default();
1718 let mut pasted_sector_ids: Vec<u32> = Vec::new();
1719
1720 self.clear_selection();
1721
1722 for v in &local_map.vertices {
1724 if let Some(new_id) = self.find_free_vertex_id() {
1725 let mut new_v = v.clone();
1726 new_v.id = new_id;
1727 new_v.x += position.x;
1728 new_v.y += position.y;
1729 self.vertices.push(new_v);
1730 self.selected_vertices.push(new_id);
1731 vertex_map.insert(v.id, new_id);
1732 }
1733 }
1734
1735 for l in &local_map.linedefs {
1737 if let Some(new_id) = self.find_free_linedef_id() {
1738 let mut new_l = l.clone();
1739 new_l.id = new_id;
1740 new_l.creator_id = Uuid::new_v4();
1741 new_l.start_vertex = *vertex_map.get(&l.start_vertex).unwrap();
1742 new_l.end_vertex = *vertex_map.get(&l.end_vertex).unwrap();
1743 new_l.sector_ids.clear();
1745 self.linedefs.push(new_l);
1746 self.selected_linedefs.push(new_id);
1747 linedef_map.insert(l.id, new_id);
1748 }
1749 }
1750
1751 for s in &local_map.sectors {
1753 if let Some(new_id) = self.find_free_sector_id() {
1754 let mut new_s = s.clone();
1755 new_s.id = new_id;
1756 new_s.creator_id = Uuid::new_v4();
1757 new_s.linedefs = s
1758 .linedefs
1759 .iter()
1760 .map(|id| *linedef_map.get(id).unwrap())
1761 .collect();
1762
1763 for old_lid in &s.linedefs {
1765 if let Some(&new_lid) = linedef_map.get(old_lid) {
1766 if let Some(ld) = self.linedefs.iter_mut().find(|l| l.id == new_lid) {
1767 if !ld.sector_ids.contains(&new_id) {
1769 ld.sector_ids.push(new_id);
1770 }
1771 }
1772 }
1773 }
1774
1775 self.sectors.push(new_s);
1776 self.selected_sectors.push(new_id);
1777 pasted_sector_ids.push(new_id);
1778 }
1779 }
1780
1781 for sector_id in pasted_sector_ids {
1783 if self.get_surface_for_sector_id(sector_id).is_none() {
1784 let mut surface = Surface::new(sector_id);
1785 surface.calculate_geometry(self);
1786 self.surfaces.insert(surface.id, surface);
1787 }
1788 }
1789 }
1790
1791 pub fn geometry_clone(&self) -> Map {
1793 Map {
1794 id: Uuid::new_v4(),
1795 name: format!("{} (geometry_clone)", self.name),
1796
1797 offset: self.offset,
1798 grid_size: self.grid_size,
1799 subdivisions: self.subdivisions,
1800
1801 terrain: Terrain::default(),
1802
1803 possible_polygon: vec![],
1804 curr_grid_pos: None,
1805 curr_mouse_pos: None,
1806 curr_rectangle: None,
1807
1808 vertices: self.vertices.clone(),
1809 linedefs: self.linedefs.clone(),
1810 sectors: self.sectors.clone(),
1811
1812 shapefx_graphs: self.shapefx_graphs.clone(),
1813 sky_texture: None,
1814
1815 camera: self.camera,
1816 camera_xz: None,
1817 look_at_xz: None,
1818
1819 lights: vec![],
1820 entities: vec![],
1821 items: vec![],
1822
1823 selected_vertices: vec![],
1824 selected_linedefs: vec![],
1825 selected_sectors: vec![],
1826
1827 selected_entity_item: None,
1828
1829 properties: ValueContainer::default(),
1830 softrigs: IndexMap::default(),
1831 editing_rig: None,
1832 soft_animator: None,
1833
1834 surfaces: IndexMap::default(),
1835 profiles: FxHashMap::default(),
1836 shaders: IndexMap::default(),
1837
1838 changed: 0,
1839 }
1840 }
1841
1842 pub fn extract_chunk_geometry(&self, bbox: BBox) -> Map {
1844 let mut result = Map::new();
1845
1846 let mut vertex_map: FxHashMap<u32, u32> = FxHashMap::default();
1847 let mut linedef_map: FxHashMap<u32, u32> = FxHashMap::default();
1848
1849 for l in &self.linedefs {
1851 if let (Some(start), Some(end)) = (
1852 self.get_vertex(l.start_vertex),
1853 self.get_vertex(l.end_vertex),
1854 ) {
1855 if bbox.contains(start) || bbox.contains(end) || bbox.line_intersects(start, end) {
1857 let new_id = result.find_free_linedef_id().unwrap_or(l.id);
1858 let mut l_clone = l.clone();
1859 l_clone.id = new_id;
1860 l_clone.sector_ids.clear();
1861 result.linedefs.push(l_clone);
1862 linedef_map.insert(l.id, new_id);
1863
1864 for vid in &[l.start_vertex, l.end_vertex] {
1866 if !vertex_map.contains_key(vid) {
1867 if let Some(v) = self.find_vertex(*vid) {
1868 let new_vid = result.find_free_vertex_id().unwrap_or(v.id);
1869 let mut v_clone = v.clone();
1870 v_clone.id = new_vid;
1871 result.vertices.push(v_clone);
1872 vertex_map.insert(*vid, new_vid);
1873 }
1874 }
1875 }
1876
1877 if let Some(ld) = result.linedefs.last_mut() {
1879 ld.start_vertex = vertex_map[&l.start_vertex];
1880 ld.end_vertex = vertex_map[&l.end_vertex];
1881 }
1882 }
1883 }
1884 }
1885
1886 for s in &self.sectors {
1888 if s.linedefs.iter().any(|lid| linedef_map.contains_key(lid)) {
1889 let new_id = result.find_free_sector_id().unwrap_or(s.id);
1890 let mut s_clone = s.clone();
1891 s_clone.id = new_id;
1892 s_clone.linedefs = s
1893 .linedefs
1894 .iter()
1895 .filter_map(|lid| linedef_map.get(lid).copied())
1896 .collect();
1897
1898 for lid in &s.linedefs {
1900 if let Some(&new_lid) = linedef_map.get(lid) {
1901 if let Some(ld) = result.linedefs.iter_mut().find(|l| l.id == new_lid) {
1902 if !ld.sector_ids.contains(&new_id) {
1904 ld.sector_ids.push(new_id);
1905 }
1906 }
1907 }
1908 }
1909
1910 result.sectors.push(s_clone);
1911 }
1912 }
1913
1914 result
1915 }
1916
1917 fn is_point_in_sector(&self, point: Vec2<f32>, sector_id: u32) -> bool {
1919 if let Some(sector) = self.find_sector(sector_id) {
1920 let mut vertices = Vec::new();
1921 for &linedef_id in §or.linedefs {
1922 if let Some(linedef) = self.find_linedef(linedef_id) {
1923 if let Some(vertex) = self.find_vertex(linedef.start_vertex) {
1924 vertices.push(Vec2::new(vertex.x, vertex.y));
1925 }
1926 }
1927 }
1928
1929 let mut inside = false;
1931 let mut j = vertices.len() - 1;
1932 for i in 0..vertices.len() {
1933 if ((vertices[i].y > point.y) != (vertices[j].y > point.y))
1934 && (point.x
1935 < (vertices[j].x - vertices[i].x) * (point.y - vertices[i].y)
1936 / (vertices[j].y - vertices[i].y)
1937 + vertices[i].x)
1938 {
1939 inside = !inside;
1940 }
1941 j = i;
1942 }
1943 inside
1944 } else {
1945 false
1946 }
1947 }
1948
1949 pub fn find_embedded_sectors(&self, container_sector_id: u32) -> Vec<u32> {
1951 let mut embedded = Vec::new();
1952
1953 for sector in &self.sectors {
1954 if sector.id == container_sector_id {
1955 continue; }
1957
1958 if sector.linedefs.is_empty() {
1959 continue;
1960 }
1961
1962 let mut vertices = Vec::new();
1964 for &linedef_id in §or.linedefs {
1965 if let Some(linedef) = self.find_linedef(linedef_id) {
1966 if let Some(vertex) = self.find_vertex(linedef.start_vertex) {
1967 vertices.push(Vec2::new(vertex.x, vertex.y));
1968 }
1969 if let Some(vertex) = self.find_vertex(linedef.end_vertex) {
1970 vertices.push(Vec2::new(vertex.x, vertex.y));
1971 }
1972 }
1973 }
1974
1975 if vertices.is_empty() {
1976 continue;
1977 }
1978
1979 let mut centroid = Vec2::new(0.0, 0.0);
1981 for vertex in &vertices {
1982 centroid.x += vertex.x;
1983 centroid.y += vertex.y;
1984 }
1985 centroid.x /= vertices.len() as f32;
1986 centroid.y /= vertices.len() as f32;
1987
1988 if self.is_point_in_sector(centroid, container_sector_id) {
1990 embedded.push(sector.id);
1991 }
1992 }
1993
1994 embedded
1995 }
1996}