From d056b8b3af99cf732be4cf09158f1d94375ba62f Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Sun, 1 Feb 2026 15:42:16 -0800 Subject: [PATCH 01/22] Physics Layers --- Cargo.lock | 20 +- crates/bevy_map_core/src/lib.rs | 2 + crates/bevy_map_core/src/physics_layers.rs | 128 +++++++++ crates/bevy_map_core/src/tileset.rs | 101 ++++---- crates/bevy_map_editor/src/lib.rs | 19 +- crates/bevy_map_editor/src/render/mod.rs | 38 ++- crates/bevy_map_editor/src/ui/mod.rs | 3 + .../bevy_map_editor/src/ui/tileset_editor.rs | 244 ++++++++++++++++-- 8 files changed, 457 insertions(+), 98 deletions(-) create mode 100644 crates/bevy_map_core/src/physics_layers.rs diff --git a/Cargo.lock b/Cargo.lock index 4a8f430..fc85285 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1299,7 +1299,7 @@ dependencies = [ [[package]] name = "bevy_map" -version = "0.3.1" +version = "0.4.0" dependencies = [ "bevy", "bevy_map_animation", @@ -1313,7 +1313,7 @@ dependencies = [ [[package]] name = "bevy_map_animation" -version = "0.3.1" +version = "0.4.0" dependencies = [ "bevy", "serde", @@ -1323,7 +1323,7 @@ dependencies = [ [[package]] name = "bevy_map_autotile" -version = "0.3.1" +version = "0.4.0" dependencies = [ "bevy_map_core", "log", @@ -1335,7 +1335,7 @@ dependencies = [ [[package]] name = "bevy_map_codegen" -version = "0.3.1" +version = "0.4.0" dependencies = [ "bevy_map_core", "bevy_map_schema", @@ -1349,7 +1349,7 @@ dependencies = [ [[package]] name = "bevy_map_core" -version = "0.3.1" +version = "0.4.0" dependencies = [ "bevy", "bevy_map_animation", @@ -1361,7 +1361,7 @@ dependencies = [ [[package]] name = "bevy_map_derive" -version = "0.3.1" +version = "0.4.0" dependencies = [ "proc-macro2", "quote", @@ -1370,7 +1370,7 @@ dependencies = [ [[package]] name = "bevy_map_dialogue" -version = "0.3.1" +version = "0.4.0" dependencies = [ "bevy", "serde", @@ -1380,7 +1380,7 @@ dependencies = [ [[package]] name = "bevy_map_editor" -version = "0.3.1" +version = "0.4.0" dependencies = [ "bevy", "bevy_ecs_tilemap", @@ -1416,7 +1416,7 @@ dependencies = [ [[package]] name = "bevy_map_runtime" -version = "0.3.1" +version = "0.4.0" dependencies = [ "avian2d", "bevy", @@ -1433,7 +1433,7 @@ dependencies = [ [[package]] name = "bevy_map_schema" -version = "0.3.1" +version = "0.4.0" dependencies = [ "bevy_map_core", "serde", diff --git a/crates/bevy_map_core/src/lib.rs b/crates/bevy_map_core/src/lib.rs index 59d86d2..7a811e3 100644 --- a/crates/bevy_map_core/src/lib.rs +++ b/crates/bevy_map_core/src/lib.rs @@ -14,11 +14,13 @@ mod entity; mod entity_type_config; mod layer; mod level; +mod physics_layers; mod project; mod tileset; mod value; mod world; +pub use physics_layers::{PhysicsLayers, PhysicsLayerSet}; pub use collision::{CollisionData, CollisionShape, OneWayDirection, PhysicsBody}; pub use entity::{ ComponentOverrides, EntityInstance, InputOverrides, PhysicsOverrides, SpriteOverrides, diff --git a/crates/bevy_map_core/src/physics_layers.rs b/crates/bevy_map_core/src/physics_layers.rs new file mode 100644 index 0000000..76cea25 --- /dev/null +++ b/crates/bevy_map_core/src/physics_layers.rs @@ -0,0 +1,128 @@ +//! Physics Layers Config for Bevy Map Editor + +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use uuid::Uuid; + +use crate::{CollisionData, CollisionShape, OneWayDirection}; + +/// Configuration for autotiling in a project +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct PhysicsLayers { + /// All physics layers in the tileset + pub layers: Vec, +} + + + + +impl PhysicsLayers { + pub fn new() -> Self { + Self { + layers: Vec::new(), + } + } + + /// Add a physics layer set + pub fn add_physics_layer(&mut self, physics_layer: PhysicsLayerSet) { + self.layers.push(physics_layer); + } + + /// Get physics layer set by ID + pub fn get_physics_layer(&self, id: Uuid) -> Option<&PhysicsLayerSet> { + self.layers.iter().find(|ts| ts.id == id) + } + + /// Get mutable physics layer set by ID + pub fn get_physics_layer_mut(&mut self, id: Uuid) -> Option<&mut PhysicsLayerSet> { + self.layers.iter_mut().find(|ts| ts.id == id) + } + + /// Remove physics layer set by ID + pub fn remove_physics_layer(&mut self, id: Uuid) -> Option { + if let Some(pos) = self.layers.iter().position(|ts| ts.id == id) { + Some(self.layers.remove(pos)) + } else { + None + } + } +} + +/// A physics layer set attached to a tileset +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PhysicsLayerSet { + pub id: Uuid, + pub name: String, + + #[serde(default)] + pub debug_color: [u8; 3], + + pub layer: u8, + pub mask: u32, + + /// Physics assignments for each tile (tile_index -> CollisionData) + pub tile_physics: HashMap, +} + + +impl PhysicsLayerSet { + /// Create a new physics layer set + pub fn new(name: String, layer: u8, mask: u32, debug_color: [u8; 3]) -> Self { + Self { + id: Uuid::new_v4(), + name, + debug_color, + layer, + mask, + tile_physics: HashMap::new(), + } + } + + + /// Assign collision data to a tile index + pub fn assign_tile_physics(&mut self, tile_index: u32, collision: CollisionData) { + self.tile_physics.insert(tile_index, collision); + } + + /// Get collision data for a tile index + pub fn get_tile_physics(&self, tile_index: u32) -> Option<&CollisionData> { + self.tile_physics.get(&tile_index) + } + + pub fn set_tile_physics_shape(&mut self, tile_index: u32, shape: CollisionShape) { + if let Some(collision_data) = self.tile_physics.get_mut(&tile_index) { + collision_data.shape = shape; + } else { + self.tile_physics.insert( + tile_index, + CollisionData { + shape, + body_type: Default::default(), + one_way: Default::default(), + layer: self.layer, + mask: self.mask, + }, + ); + } + } + + pub fn set_tile_physics_one_way(&mut self, tile_index: u32, direction: OneWayDirection) { + if let Some(collision_data) = self.tile_physics.get_mut(&tile_index) { + collision_data.one_way = direction; + } + } + + pub fn update_all_tile_physics_layer(&mut self, layer: u8) { + self.layer = layer; + for collision_data in self.tile_physics.values_mut() { + collision_data.layer = layer; + } + } + + pub fn update_all_tile_physics_mask(&mut self, mask: u32) { + self.mask = mask; + for collision_data in self.tile_physics.values_mut() { + collision_data.mask = mask; + } + } +} \ No newline at end of file diff --git a/crates/bevy_map_core/src/tileset.rs b/crates/bevy_map_core/src/tileset.rs index 016082d..334f19a 100644 --- a/crates/bevy_map_core/src/tileset.rs +++ b/crates/bevy_map_core/src/tileset.rs @@ -1,6 +1,7 @@ //! Tileset configuration with multi-image support use crate::collision::{CollisionData, CollisionShape, OneWayDirection}; +use crate::physics_layers::PhysicsLayers; use serde::{Deserialize, Deserializer, Serialize}; use std::collections::HashMap; use uuid::Uuid; @@ -216,6 +217,9 @@ pub struct Tileset { /// Multiple image sources #[serde(default)] pub images: Vec, + /// Collision layers configuration + #[serde(default)] + pub physics_layers: PhysicsLayers, /// Per-tile properties (collision, animation, custom data) #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub tile_properties: HashMap, @@ -239,6 +243,7 @@ impl Tileset { name, tile_size, images: vec![image], + physics_layers: PhysicsLayers::new(), tile_properties: HashMap::new(), path: Some(path), columns, @@ -253,6 +258,7 @@ impl Tileset { name, tile_size, images: Vec::new(), + physics_layers: PhysicsLayers::new(), tile_properties: HashMap::new(), path: None, columns: 0, @@ -280,76 +286,77 @@ impl Tileset { } /// Check if a tile has collision - pub fn tile_has_collision(&self, tile_index: u32) -> bool { - self.tile_properties - .get(&tile_index) - .map(|p| p.has_collision()) - .unwrap_or(false) + pub fn tile_has_collision(&self, tile_index: u32, physics_layer: Uuid) -> bool { + + if let Some(physics_layer_set) = self.physics_layers.get_physics_layer(physics_layer) { + physics_layer_set.tile_physics.get(&tile_index).map(|p| p.has_collision()).unwrap_or(false) + } else { + false + } } /// Get collision data for a tile - pub fn get_tile_collision(&self, tile_index: u32) -> Option<&CollisionData> { - self.tile_properties.get(&tile_index).map(|p| &p.collision) + pub fn get_tile_collision(&self, tile_index: u32, physics_layer: Uuid) -> Option<&CollisionData> { + if let Some(physics_layer_set) = self.physics_layers.get_physics_layer(physics_layer) { + physics_layer_set.tile_physics.get(&tile_index) + } else { + None + } } /// Set collision data for a tile - pub fn set_tile_collision(&mut self, tile_index: u32, collision: CollisionData) { - let props = self.get_tile_properties_mut(tile_index); - props.collision = collision; - // Clean up if properties are now empty - if props.is_empty() { - self.tile_properties.remove(&tile_index); + pub fn set_tile_collision(&mut self, tile_index: u32, collision: CollisionData, physics_layer: Uuid) { + if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { + physics_layer_set.tile_physics.insert(tile_index, collision); + println!("set tile {} collision for physics layer {:?}", tile_index, physics_layer); } } /// Set full collision for a tile (convenience method) - pub fn set_tile_full_collision(&mut self, tile_index: u32, has_collision: bool) { - let collision = if has_collision { - CollisionData::full() + pub fn set_tile_full_collision(&mut self, tile_index: u32, has_collision: bool, physics_layer: Uuid) { + if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { + let collision = if has_collision { + CollisionData::full() + } else { + CollisionData::none() + }; + physics_layer_set.tile_physics.insert(tile_index, collision); + + println!("set tile {} collision for physics layer {:?}", tile_index, physics_layer); + } else { - CollisionData::none() - }; - self.set_tile_collision(tile_index, collision); + println!("Warning: Physics layer {:?} not found", physics_layer); + } + } /// Set collision shape for a tile (preserving other collision properties) - pub fn set_tile_collision_shape(&mut self, tile_index: u32, shape: CollisionShape) { - let props = self.get_tile_properties_mut(tile_index); - props.collision.shape = shape; - // Clean up if properties are now empty - if props.is_empty() { - self.tile_properties.remove(&tile_index); - } + pub fn set_tile_collision_shape(&mut self, tile_index: u32, shape: CollisionShape, physics_layer: Uuid) { + if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { + physics_layer_set.set_tile_physics_shape(tile_index, shape); + println!("set tile {} collision for physics layer {:?}", tile_index, physics_layer); + }; } /// Set one-way direction for a tile collision - pub fn set_tile_one_way(&mut self, tile_index: u32, direction: OneWayDirection) { - let props = self.get_tile_properties_mut(tile_index); - props.collision.one_way = direction; - // Clean up if properties are now empty - if props.is_empty() { - self.tile_properties.remove(&tile_index); - } + pub fn set_tile_one_way(&mut self, tile_index: u32, direction: OneWayDirection, physics_layer: Uuid) { + if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { + physics_layer_set.set_tile_physics_one_way(tile_index, direction); + }; } /// Set collision layer for a tile - pub fn set_tile_collision_layer(&mut self, tile_index: u32, layer: u8) { - let props = self.get_tile_properties_mut(tile_index); - props.collision.layer = layer; - // Clean up if properties are now empty - if props.is_empty() { - self.tile_properties.remove(&tile_index); - } + pub fn set_tile_collision_layer(&mut self, tile_index: u32, layer: u8, physics_layer: Uuid) { + if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { + physics_layer_set.update_all_tile_physics_layer(layer); + }; } /// Set collision mask for a tile - pub fn set_tile_collision_mask(&mut self, tile_index: u32, mask: u32) { - let props = self.get_tile_properties_mut(tile_index); - props.collision.mask = mask; - // Clean up if properties are now empty - if props.is_empty() { - self.tile_properties.remove(&tile_index); - } + pub fn set_tile_collision_mask(&mut self, tile_index: u32, mask: u32, physics_layer: Uuid) { + if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { + physics_layer_set.update_all_tile_physics_mask(mask); + }; } /// Migrate legacy single-image format to multi-image format diff --git a/crates/bevy_map_editor/src/lib.rs b/crates/bevy_map_editor/src/lib.rs index c7e9142..6ff482b 100644 --- a/crates/bevy_map_editor/src/lib.rs +++ b/crates/bevy_map_editor/src/lib.rs @@ -300,7 +300,7 @@ impl Default for EditorStateConfig { fn default() -> Self { Self { show_grid: true, - show_collisions: false, + show_collisions: true, snap_to_grid: true, initial_zoom: 1.0, initial_tool: EditorTool::Select, @@ -588,6 +588,13 @@ pub struct EditorState { pub show_tileset_editor: bool, pub tileset_editor_state: TilesetEditorState, + // Physics Layer Editor + pub show_add_physics_layer_set_dialog: bool, + pub new_physics_layer_name: String, + pub new_physics_layer_mask: u32, + pub new_physics_layer_layer: u8, + pub new_physics_layer_debug_color: Color, + // SpriteSheet Editor (for spritesheet setup: image loading, grid config) pub show_spritesheet_editor: bool, pub spritesheet_editor_state: SpriteSheetEditorState, @@ -706,7 +713,7 @@ impl Default for EditorState { current_tool: EditorTool::Select, tool_mode: ToolMode::Point, show_grid: true, - show_collisions: false, + show_collisions: true, snap_to_grid: true, zoom: 1.0, camera_offset: bevy::math::Vec2::ZERO, @@ -769,6 +776,14 @@ impl Default for EditorState { show_tileset_editor: false, tileset_editor_state: TilesetEditorState::default(), + show_add_physics_layer_set_dialog: false, + new_physics_layer_name: String::new(), + new_physics_layer_mask: 0, + new_physics_layer_layer: 0, + new_physics_layer_debug_color: Color::srgba(0.2, 0.6, 1.0, 0.3), + + + show_spritesheet_editor: false, spritesheet_editor_state: SpriteSheetEditorState::new(), diff --git a/crates/bevy_map_editor/src/render/mod.rs b/crates/bevy_map_editor/src/render/mod.rs index 1ccf1a8..9a37e37 100644 --- a/crates/bevy_map_editor/src/render/mod.rs +++ b/crates/bevy_map_editor/src/render/mod.rs @@ -920,21 +920,33 @@ fn sync_collision_rendering( let idx = (y * level.width + x) as usize; if let Some(&Some(tile_index)) = tiles.get(idx) { // Check if this tile has collision - if let Some(props) = tileset.get_tile_properties(tile_index) { - if props.collision.has_collision() { - // Spawn collision overlay sprite(s) - spawn_collision_overlay( - &mut commands, - &mut cache, - &props.collision.shape, - x, - y, - tile_size, - layer_idx, - collision_color, - ); + + for physics_layer in tileset.physics_layers.layers.iter() { + if let Some(collision) = tileset.get_tile_collision(tile_index, physics_layer.id) { + if collision.has_collision() { + + let color = Color::srgba_u8( + physics_layer.debug_color[0] , + physics_layer.debug_color[1] , + physics_layer.debug_color[2], + 200, // Alpha value + ); + // Spawn collision overlay sprite(s) + spawn_collision_overlay( + &mut commands, + &mut cache, + &collision.shape, + x, + y, + tile_size, + layer_idx, + color, + ); + } } + } + } } } diff --git a/crates/bevy_map_editor/src/ui/mod.rs b/crates/bevy_map_editor/src/ui/mod.rs index 6e0b188..e1ffca7 100644 --- a/crates/bevy_map_editor/src/ui/mod.rs +++ b/crates/bevy_map_editor/src/ui/mod.rs @@ -1421,6 +1421,9 @@ fn render_ui( terrain::render_new_terrain_set_dialog(ctx, &mut editor_state, &mut project); terrain::render_add_terrain_to_set_dialog(ctx, &mut editor_state, &mut project); + // Physics dialogs + tileset_editor::render_new_physics_layer_set_dialog(ctx, &mut editor_state, &mut project); + // New level dialog (for World View) if let Some(params) = render_new_level_dialog(ctx, &mut editor_state) { let new_level = bevy_map_core::Level::new_at( diff --git a/crates/bevy_map_editor/src/ui/tileset_editor.rs b/crates/bevy_map_editor/src/ui/tileset_editor.rs index a881b46..9222f5f 100644 --- a/crates/bevy_map_editor/src/ui/tileset_editor.rs +++ b/crates/bevy_map_editor/src/ui/tileset_editor.rs @@ -8,9 +8,11 @@ //! - Clicking assigns the selected terrain to that zone of that tile //! - Visual overlays show assigned terrain with curved boundaries +use bevy::color::Color; use bevy_egui::egui::{self, Color32, Pos2, Shape}; use bevy_map_autotile::terrain::Color as TerrainColor; use bevy_map_autotile::TerrainSetType; +use bevy_map_core::PhysicsLayerSet; use std::f32::consts::PI; use super::{find_base_tile_for_position, EditorTheme, TilesetTextureCache}; @@ -525,6 +527,7 @@ pub struct CollisionDragState { /// State for the collision editor within the tileset editor pub struct CollisionEditorState { + pub selected_physics_layer: Option, /// Currently selected tile for collision editing pub selected_tile: Option, /// Zoom level for the tile preview canvas (default 8.0 = 256px for 32px tiles) @@ -546,6 +549,7 @@ pub struct CollisionEditorState { impl Default for CollisionEditorState { fn default() -> Self { Self { + selected_physics_layer: None, selected_tile: None, preview_zoom: 8.0, grid_zoom: 1.0, @@ -1204,6 +1208,11 @@ fn render_tile_properties_tab( return; }; + let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer else { + ui.label("No physics layer selected"); + return; + }; + // Clone tileset data to avoid borrow conflicts let tileset_data = project .tilesets @@ -1270,7 +1279,7 @@ fn render_tile_properties_tab( if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - tileset.set_tile_full_collision(tile_idx, has_collision); + tileset.set_tile_full_collision(tile_idx, has_collision, physics_layer_id); project.mark_dirty(); } } @@ -1955,6 +1964,41 @@ fn render_collision_tab( return; } + + egui::SidePanel::left("Physics_list_panel") + .resizable(true) + .show_inside(ui, |ui| { + egui::ScrollArea::vertical() + .auto_shrink([false, false]) + .show(ui, |ui| { + ui.heading("Physics Layer Sets"); + + // List terrain sets for this tileset + let physics_layers = project.tilesets.iter().find(|t| t.id == tileset_id).map(|t| &t.physics_layers); + + if let Some(physics_layers) = physics_layers { + for p in physics_layers.layers.iter() { + ui.horizontal(|ui| { + let selected = editor_state.tileset_editor_state.collision_editor.selected_physics_layer == Some(p.id); + if ui.selectable_label(selected, &p.name).clicked() { + editor_state.tileset_editor_state.collision_editor.selected_physics_layer = Some(p.id); + } + ui.small(format!("Layer: {} Mask: {}", p.layer, p.mask)); + }); + } + } + + ui.separator(); + + ui.horizontal(|ui| { + if ui.button("+ New Set").clicked() { + // TODO: Show dialog to create new physics layer set + editor_state.show_add_physics_layer_set_dialog = true; + } + }); + }); + }); + // Three-panel layout with resizable splitters // Left panel: Tile selector grid (resizable) egui::SidePanel::left("collision_tile_list") @@ -2118,6 +2162,19 @@ fn render_collision_tile_selector( let display_size = egui::vec2(tile_size * zoom, tile_size * zoom); let mut virtual_offset = 0u32; + let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer else { + ui.label("No physics layer selected"); + return; + }; + + let Some(physics_color) = project.tilesets.iter().find(|t| t.id == tileset_id) + .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) + .map(|layer| layer.debug_color) + else { + ui.label("Physics layer not found"); + return; + }; + for image in images { let texture_id = cache .and_then(|c| c.loaded.get(&image.id)) @@ -2147,8 +2204,10 @@ fn render_collision_tile_selector( // Get collision shape for this tile (if any) let collision_shape = tileset - .and_then(|t| t.get_tile_properties(virtual_index)) - .map(|p| p.collision.shape.clone()); + .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) + .and_then(|layer| layer.get_tile_physics(virtual_index)) + .map(|data| data.shape.clone()); + let (rect, response) = ui.allocate_exact_size(display_size, egui::Sense::click()); @@ -2192,7 +2251,7 @@ fn render_collision_tile_selector( // Draw collision shape preview on tile if let Some(ref shape) = collision_shape { - draw_collision_shape_on_canvas(ui.painter(), rect, shape); + draw_collision_shape_on_canvas(ui.painter(), rect, shape, physics_color); } if response.clicked() { @@ -2247,6 +2306,19 @@ fn render_collision_canvas( return; }; + let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer else { + ui.label("No physics layer selected"); + return; + }; + + let Some(physics_color) = project.tilesets.iter().find(|t| t.id == tileset_id) + .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) + .map(|layer| layer.debug_color) + else { + ui.label("Physics layer not found"); + return; + }; + let zoom = collision_state.preview_zoom; let canvas_size = egui::vec2(tile_size * zoom, tile_size * zoom); @@ -2327,10 +2399,12 @@ fn render_collision_canvas( // 3. Get current collision data (after input handling may have modified it) let tileset = project.tilesets.iter().find(|t| t.id == tileset_id); let collision_data = tileset - .and_then(|t| t.get_tile_properties(tile_idx)) - .map(|p| p.collision.clone()) + .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) + .and_then(|layer| layer.get_tile_physics(tile_idx)) + .map(|data| data.clone()) .unwrap_or_default(); + // 4. Draw collision shape overlay (skip if dragging vertex - preview handles it) let is_dragging_vertex = matches!( &editor_state @@ -2343,7 +2417,7 @@ fn render_collision_canvas( }) ); if !is_dragging_vertex { - draw_collision_shape_on_canvas(ui.painter(), canvas_rect, &collision_data.shape); + draw_collision_shape_on_canvas(ui.painter(), canvas_rect, &collision_data.shape, physics_color); } // 5. Draw drag handles in select mode (skip if dragging vertex - preview handles it) @@ -2372,9 +2446,10 @@ fn draw_collision_shape_on_canvas( painter: &egui::Painter, canvas_rect: egui::Rect, shape: &bevy_map_core::CollisionShape, + color: [u8; 3], ) { - let fill = Color32::from_rgba_unmultiplied(0, 150, 255, 80); - let stroke = egui::Stroke::new(2.0, Color32::from_rgb(0, 120, 255)); + let fill = Color32::from_rgba_unmultiplied(color[0], color[1], color[2], 80); + let stroke = egui::Stroke::new(2.0, Color32::from_rgb(color[0], color[1], color[2])); match shape { bevy_map_core::CollisionShape::None => {} @@ -2484,6 +2559,10 @@ fn handle_collision_canvas_input( .collision_editor .drawing_mode; + let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer else { + return; + }; + // Handle double-click to finish polygon (Polygon mode) if response.double_clicked() && drawing_mode == CollisionDrawMode::Polygon { let polygon_points = &editor_state @@ -2496,8 +2575,10 @@ fn handle_collision_canvas_input( points: polygon_points.clone(), }; if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - tileset.set_tile_collision_shape(tile_idx, shape); - project.mark_dirty(); + if let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer { + tileset.set_tile_collision_shape(tile_idx, shape, physics_layer_id); + project.mark_dirty(); + } } editor_state .tileset_editor_state @@ -2660,8 +2741,10 @@ fn handle_collision_canvas_input( if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - tileset.set_tile_collision_shape(tile_idx, shape); - project.mark_dirty(); + if let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer { + tileset.set_tile_collision_shape(tile_idx, shape, physics_layer_id); + project.mark_dirty(); + } } } } @@ -2678,8 +2761,10 @@ fn handle_collision_canvas_input( if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - tileset.set_tile_collision_shape(tile_idx, shape); - project.mark_dirty(); + if let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer { + tileset.set_tile_collision_shape(tile_idx, shape, physics_layer_id); + project.mark_dirty(); + } } } } @@ -2752,9 +2837,21 @@ fn handle_collision_canvas_input( CollisionDragOperation::MoveVertex { index, .. } => { // Draw the polygon with the dragged vertex at its new position if let Some(tileset) = project.tilesets.iter().find(|t| t.id == tileset_id) { - if let Some(props) = tileset.get_tile_properties(tile_idx) { + + let collision_shape = tileset.physics_layers.get_physics_layer(physics_layer_id) + .and_then(|layer| layer.get_tile_physics(tile_idx)) + .map(|data| data.shape.clone()); + + let Some(physics_color) = + tileset.physics_layers.get_physics_layer(physics_layer_id) + .map(|layer| layer.debug_color) + else { + return; + }; + + if let Some(shape) = collision_shape { if let bevy_map_core::CollisionShape::Polygon { points } = - &props.collision.shape + &shape { // Create a temporary copy with the moved vertex let mut preview_points = points.clone(); @@ -2773,6 +2870,7 @@ fn handle_collision_canvas_input( ui.painter(), canvas_rect, &preview_shape, + physics_color ); draw_collision_handles(ui.painter(), canvas_rect, &preview_shape); } @@ -2961,13 +3059,20 @@ fn render_collision_properties( return; }; + let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer else { + ui.label("No physics layer selected"); + return; + }; + ui.heading("Properties"); // Get current collision data let tileset = project.tilesets.iter().find(|t| t.id == tileset_id); + let collision_data = tileset - .and_then(|t| t.get_tile_properties(tile_idx)) - .map(|p| p.collision.clone()) + .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) + .and_then(|layer| layer.get_tile_physics(tile_idx)) + .map(|data| data.clone()) .unwrap_or_default(); // Shape info @@ -3000,7 +3105,7 @@ fn render_collision_properties( if one_way != collision_data.one_way { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - tileset.set_tile_one_way(tile_idx, one_way); + tileset.set_tile_one_way(tile_idx, one_way, physics_layer_id); project.mark_dirty(); } } @@ -3014,7 +3119,7 @@ fn render_collision_properties( .changed() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - tileset.set_tile_collision_layer(tile_idx, layer); + tileset.set_tile_collision_layer(tile_idx, layer, physics_layer_id); project.mark_dirty(); } } @@ -3029,7 +3134,7 @@ fn render_collision_properties( .changed() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - tileset.set_tile_collision_mask(tile_idx, mask); + tileset.set_tile_collision_mask(tile_idx, mask, physics_layer_id); project.mark_dirty(); } } @@ -3040,15 +3145,19 @@ fn render_collision_properties( // Action buttons if ui.button("Set Full Collision").clicked() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - tileset.set_tile_collision_shape(tile_idx, bevy_map_core::CollisionShape::Full); - project.mark_dirty(); + if let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer { + tileset.set_tile_collision_shape(tile_idx, bevy_map_core::CollisionShape::Full, physics_layer_id); + project.mark_dirty(); + } } } if ui.button("Clear Collision").clicked() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - tileset.set_tile_collision_shape(tile_idx, bevy_map_core::CollisionShape::None); - project.mark_dirty(); + if let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer { + tileset.set_tile_collision_shape(tile_idx, bevy_map_core::CollisionShape::None, physics_layer_id); + project.mark_dirty(); + } } } } @@ -3141,3 +3250,86 @@ fn point_to_segment_distance(p: &[f32; 2], a: &[f32; 2], b: &[f32; 2]) -> f32 { let dy = p[1] - closest[1]; (dx * dx + dy * dy).sqrt() } + + + + + +/// Render the new physics layer set dialog (Tiled-compatible) +pub fn render_new_physics_layer_set_dialog( + ctx: &egui::Context, + editor_state: &mut EditorState, + project: &mut Project, +) { + if !editor_state.show_add_physics_layer_set_dialog { + return; + } + + let Some(tileset_id) = editor_state.selected_tileset else { + return; + }; + + egui::Window::new("New Physics Layer Set") + .collapsible(false) + .resizable(false) + .show(ctx, |ui| { + ui.horizontal(|ui| { + ui.label("Name:"); + ui.text_edit_singleline(&mut editor_state.new_physics_layer_name); + }); + + // Color picker + let default_color = [0, 140, 255u8]; // Default blue + let mut rgb = [(editor_state.new_physics_layer_debug_color.to_srgba().red * 255.0) as u8, + (editor_state.new_physics_layer_debug_color.to_srgba().green * 255.0) as u8, + (editor_state.new_physics_layer_debug_color.to_srgba().blue * 255.0) as u8]; + ui.label("Color:"); + if egui::color_picker::color_edit_button_srgb(ui, &mut rgb).changed() { + editor_state.new_physics_layer_debug_color = Color::srgba(rgb[0] as f32 / 255.0, rgb[1] as f32 / 255.0, rgb[2] as f32 / 255.0, 0.3); + } + + ui.horizontal(|ui| { + ui.label("Layer:"); + ui.add(egui::DragValue::new(&mut editor_state.new_physics_layer_layer)); + }); + + ui.horizontal(|ui| { + ui.label("Mask:"); + ui.add(egui::DragValue::new(&mut editor_state.new_physics_layer_mask)); + }); + + + + ui.separator(); + + ui.horizontal(|ui| { + if ui.button("Create").clicked() { + let srgba = editor_state.new_physics_layer_debug_color.to_srgba(); + let debug_color = [ + (srgba.red * 255.0) as u8, + (srgba.green * 255.0) as u8, + (srgba.blue * 255.0) as u8, + ]; + let physics_layer_set = PhysicsLayerSet::new( + editor_state.new_physics_layer_name.clone(), + editor_state.new_physics_layer_layer, + editor_state.new_physics_layer_mask, + debug_color, + ); + let tileset = project.tilesets.iter_mut().find(|t| t.id == tileset_id); + if let Some(tileset) = tileset { + tileset + .physics_layers + .layers + .push(physics_layer_set); + }; + project.mark_dirty(); + editor_state.show_add_physics_layer_set_dialog = false; + editor_state.new_physics_layer_name = String::new(); + } + if ui.button("Cancel").clicked() { + editor_state.show_add_physics_layer_set_dialog = false; + } + }); + }); +} From 3e212ef8a6a69ff6ce7cfa29f97994969974a853 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Sun, 1 Feb 2026 15:46:35 -0800 Subject: [PATCH 02/22] Cargo fmt --- crates/bevy_map_core/src/lib.rs | 2 +- crates/bevy_map_core/src/physics_layers.rs | 11 +- crates/bevy_map_core/src/tileset.rs | 58 ++++-- crates/bevy_map_editor/src/lib.rs | 2 - crates/bevy_map_editor/src/render/mod.rs | 11 +- .../bevy_map_editor/src/ui/tileset_editor.rs | 174 +++++++++++++----- 6 files changed, 180 insertions(+), 78 deletions(-) diff --git a/crates/bevy_map_core/src/lib.rs b/crates/bevy_map_core/src/lib.rs index 7a811e3..f17cfac 100644 --- a/crates/bevy_map_core/src/lib.rs +++ b/crates/bevy_map_core/src/lib.rs @@ -20,7 +20,6 @@ mod tileset; mod value; mod world; -pub use physics_layers::{PhysicsLayers, PhysicsLayerSet}; pub use collision::{CollisionData, CollisionShape, OneWayDirection, PhysicsBody}; pub use entity::{ ComponentOverrides, EntityInstance, InputOverrides, PhysicsOverrides, SpriteOverrides, @@ -34,6 +33,7 @@ pub use layer::{ LayerData, LayerType, OCCUPIED_CELL, TILE_FLIP_MASK, TILE_FLIP_X, TILE_FLIP_Y, TILE_INDEX_MASK, }; pub use level::Level; +pub use physics_layers::{PhysicsLayerSet, PhysicsLayers}; pub use project::{EditorProject, MapProject, MapProjectBuilder}; pub use tileset::{TileProperties, Tileset, TilesetImage}; pub use value::Value; diff --git a/crates/bevy_map_core/src/physics_layers.rs b/crates/bevy_map_core/src/physics_layers.rs index 76cea25..44a3c93 100644 --- a/crates/bevy_map_core/src/physics_layers.rs +++ b/crates/bevy_map_core/src/physics_layers.rs @@ -13,14 +13,9 @@ pub struct PhysicsLayers { pub layers: Vec, } - - - impl PhysicsLayers { pub fn new() -> Self { - Self { - layers: Vec::new(), - } + Self { layers: Vec::new() } } /// Add a physics layer set @@ -64,7 +59,6 @@ pub struct PhysicsLayerSet { pub tile_physics: HashMap, } - impl PhysicsLayerSet { /// Create a new physics layer set pub fn new(name: String, layer: u8, mask: u32, debug_color: [u8; 3]) -> Self { @@ -78,7 +72,6 @@ impl PhysicsLayerSet { } } - /// Assign collision data to a tile index pub fn assign_tile_physics(&mut self, tile_index: u32, collision: CollisionData) { self.tile_physics.insert(tile_index, collision); @@ -125,4 +118,4 @@ impl PhysicsLayerSet { collision_data.mask = mask; } } -} \ No newline at end of file +} diff --git a/crates/bevy_map_core/src/tileset.rs b/crates/bevy_map_core/src/tileset.rs index 334f19a..2ee4233 100644 --- a/crates/bevy_map_core/src/tileset.rs +++ b/crates/bevy_map_core/src/tileset.rs @@ -287,16 +287,23 @@ impl Tileset { /// Check if a tile has collision pub fn tile_has_collision(&self, tile_index: u32, physics_layer: Uuid) -> bool { - if let Some(physics_layer_set) = self.physics_layers.get_physics_layer(physics_layer) { - physics_layer_set.tile_physics.get(&tile_index).map(|p| p.has_collision()).unwrap_or(false) + physics_layer_set + .tile_physics + .get(&tile_index) + .map(|p| p.has_collision()) + .unwrap_or(false) } else { false } } /// Get collision data for a tile - pub fn get_tile_collision(&self, tile_index: u32, physics_layer: Uuid) -> Option<&CollisionData> { + pub fn get_tile_collision( + &self, + tile_index: u32, + physics_layer: Uuid, + ) -> Option<&CollisionData> { if let Some(physics_layer_set) = self.physics_layers.get_physics_layer(physics_layer) { physics_layer_set.tile_physics.get(&tile_index) } else { @@ -305,15 +312,28 @@ impl Tileset { } /// Set collision data for a tile - pub fn set_tile_collision(&mut self, tile_index: u32, collision: CollisionData, physics_layer: Uuid) { + pub fn set_tile_collision( + &mut self, + tile_index: u32, + collision: CollisionData, + physics_layer: Uuid, + ) { if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { physics_layer_set.tile_physics.insert(tile_index, collision); - println!("set tile {} collision for physics layer {:?}", tile_index, physics_layer); + println!( + "set tile {} collision for physics layer {:?}", + tile_index, physics_layer + ); } } /// Set full collision for a tile (convenience method) - pub fn set_tile_full_collision(&mut self, tile_index: u32, has_collision: bool, physics_layer: Uuid) { + pub fn set_tile_full_collision( + &mut self, + tile_index: u32, + has_collision: bool, + physics_layer: Uuid, + ) { if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { let collision = if has_collision { CollisionData::full() @@ -322,24 +342,38 @@ impl Tileset { }; physics_layer_set.tile_physics.insert(tile_index, collision); - println!("set tile {} collision for physics layer {:?}", tile_index, physics_layer); - + println!( + "set tile {} collision for physics layer {:?}", + tile_index, physics_layer + ); } else { println!("Warning: Physics layer {:?} not found", physics_layer); } - } /// Set collision shape for a tile (preserving other collision properties) - pub fn set_tile_collision_shape(&mut self, tile_index: u32, shape: CollisionShape, physics_layer: Uuid) { + pub fn set_tile_collision_shape( + &mut self, + tile_index: u32, + shape: CollisionShape, + physics_layer: Uuid, + ) { if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { physics_layer_set.set_tile_physics_shape(tile_index, shape); - println!("set tile {} collision for physics layer {:?}", tile_index, physics_layer); + println!( + "set tile {} collision for physics layer {:?}", + tile_index, physics_layer + ); }; } /// Set one-way direction for a tile collision - pub fn set_tile_one_way(&mut self, tile_index: u32, direction: OneWayDirection, physics_layer: Uuid) { + pub fn set_tile_one_way( + &mut self, + tile_index: u32, + direction: OneWayDirection, + physics_layer: Uuid, + ) { if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { physics_layer_set.set_tile_physics_one_way(tile_index, direction); }; diff --git a/crates/bevy_map_editor/src/lib.rs b/crates/bevy_map_editor/src/lib.rs index 6ff482b..78fd74b 100644 --- a/crates/bevy_map_editor/src/lib.rs +++ b/crates/bevy_map_editor/src/lib.rs @@ -782,8 +782,6 @@ impl Default for EditorState { new_physics_layer_layer: 0, new_physics_layer_debug_color: Color::srgba(0.2, 0.6, 1.0, 0.3), - - show_spritesheet_editor: false, spritesheet_editor_state: SpriteSheetEditorState::new(), diff --git a/crates/bevy_map_editor/src/render/mod.rs b/crates/bevy_map_editor/src/render/mod.rs index 9a37e37..f519bed 100644 --- a/crates/bevy_map_editor/src/render/mod.rs +++ b/crates/bevy_map_editor/src/render/mod.rs @@ -922,12 +922,13 @@ fn sync_collision_rendering( // Check if this tile has collision for physics_layer in tileset.physics_layers.layers.iter() { - if let Some(collision) = tileset.get_tile_collision(tile_index, physics_layer.id) { + if let Some(collision) = + tileset.get_tile_collision(tile_index, physics_layer.id) + { if collision.has_collision() { - let color = Color::srgba_u8( - physics_layer.debug_color[0] , - physics_layer.debug_color[1] , + physics_layer.debug_color[0], + physics_layer.debug_color[1], physics_layer.debug_color[2], 200, // Alpha value ); @@ -944,9 +945,7 @@ fn sync_collision_rendering( ); } } - } - } } } diff --git a/crates/bevy_map_editor/src/ui/tileset_editor.rs b/crates/bevy_map_editor/src/ui/tileset_editor.rs index 9222f5f..01098ef 100644 --- a/crates/bevy_map_editor/src/ui/tileset_editor.rs +++ b/crates/bevy_map_editor/src/ui/tileset_editor.rs @@ -1208,7 +1208,11 @@ fn render_tile_properties_tab( return; }; - let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer else { + let Some(physics_layer_id) = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + else { ui.label("No physics layer selected"); return; }; @@ -1279,7 +1283,11 @@ fn render_tile_properties_tab( if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - tileset.set_tile_full_collision(tile_idx, has_collision, physics_layer_id); + tileset.set_tile_full_collision( + tile_idx, + has_collision, + physics_layer_id, + ); project.mark_dirty(); } } @@ -1964,7 +1972,6 @@ fn render_collision_tab( return; } - egui::SidePanel::left("Physics_list_panel") .resizable(true) .show_inside(ui, |ui| { @@ -1974,14 +1981,25 @@ fn render_collision_tab( ui.heading("Physics Layer Sets"); // List terrain sets for this tileset - let physics_layers = project.tilesets.iter().find(|t| t.id == tileset_id).map(|t| &t.physics_layers); - + let physics_layers = project + .tilesets + .iter() + .find(|t| t.id == tileset_id) + .map(|t| &t.physics_layers); + if let Some(physics_layers) = physics_layers { for p in physics_layers.layers.iter() { ui.horizontal(|ui| { - let selected = editor_state.tileset_editor_state.collision_editor.selected_physics_layer == Some(p.id); + let selected = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + == Some(p.id); if ui.selectable_label(selected, &p.name).clicked() { - editor_state.tileset_editor_state.collision_editor.selected_physics_layer = Some(p.id); + editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer = Some(p.id); } ui.small(format!("Layer: {} Mask: {}", p.layer, p.mask)); }); @@ -2162,12 +2180,19 @@ fn render_collision_tile_selector( let display_size = egui::vec2(tile_size * zoom, tile_size * zoom); let mut virtual_offset = 0u32; - let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer else { + let Some(physics_layer_id) = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + else { ui.label("No physics layer selected"); return; }; - let Some(physics_color) = project.tilesets.iter().find(|t| t.id == tileset_id) + let Some(physics_color) = project + .tilesets + .iter() + .find(|t| t.id == tileset_id) .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) .map(|layer| layer.debug_color) else { @@ -2207,7 +2232,6 @@ fn render_collision_tile_selector( .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) .and_then(|layer| layer.get_tile_physics(virtual_index)) .map(|data| data.shape.clone()); - let (rect, response) = ui.allocate_exact_size(display_size, egui::Sense::click()); @@ -2251,7 +2275,12 @@ fn render_collision_tile_selector( // Draw collision shape preview on tile if let Some(ref shape) = collision_shape { - draw_collision_shape_on_canvas(ui.painter(), rect, shape, physics_color); + draw_collision_shape_on_canvas( + ui.painter(), + rect, + shape, + physics_color, + ); } if response.clicked() { @@ -2306,12 +2335,19 @@ fn render_collision_canvas( return; }; - let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer else { + let Some(physics_layer_id) = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + else { ui.label("No physics layer selected"); return; }; - let Some(physics_color) = project.tilesets.iter().find(|t| t.id == tileset_id) + let Some(physics_color) = project + .tilesets + .iter() + .find(|t| t.id == tileset_id) .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) .map(|layer| layer.debug_color) else { @@ -2404,7 +2440,6 @@ fn render_collision_canvas( .map(|data| data.clone()) .unwrap_or_default(); - // 4. Draw collision shape overlay (skip if dragging vertex - preview handles it) let is_dragging_vertex = matches!( &editor_state @@ -2417,7 +2452,12 @@ fn render_collision_canvas( }) ); if !is_dragging_vertex { - draw_collision_shape_on_canvas(ui.painter(), canvas_rect, &collision_data.shape, physics_color); + draw_collision_shape_on_canvas( + ui.painter(), + canvas_rect, + &collision_data.shape, + physics_color, + ); } // 5. Draw drag handles in select mode (skip if dragging vertex - preview handles it) @@ -2559,7 +2599,11 @@ fn handle_collision_canvas_input( .collision_editor .drawing_mode; - let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer else { + let Some(physics_layer_id) = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + else { return; }; @@ -2575,7 +2619,11 @@ fn handle_collision_canvas_input( points: polygon_points.clone(), }; if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - if let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer { + if let Some(physics_layer_id) = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + { tileset.set_tile_collision_shape(tile_idx, shape, physics_layer_id); project.mark_dirty(); } @@ -2741,7 +2789,11 @@ fn handle_collision_canvas_input( if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - if let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer { + if let Some(physics_layer_id) = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + { tileset.set_tile_collision_shape(tile_idx, shape, physics_layer_id); project.mark_dirty(); } @@ -2761,7 +2813,11 @@ fn handle_collision_canvas_input( if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - if let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer { + if let Some(physics_layer_id) = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + { tileset.set_tile_collision_shape(tile_idx, shape, physics_layer_id); project.mark_dirty(); } @@ -2837,22 +2893,22 @@ fn handle_collision_canvas_input( CollisionDragOperation::MoveVertex { index, .. } => { // Draw the polygon with the dragged vertex at its new position if let Some(tileset) = project.tilesets.iter().find(|t| t.id == tileset_id) { - - let collision_shape = tileset.physics_layers.get_physics_layer(physics_layer_id) + let collision_shape = tileset + .physics_layers + .get_physics_layer(physics_layer_id) .and_then(|layer| layer.get_tile_physics(tile_idx)) .map(|data| data.shape.clone()); - let Some(physics_color) = - tileset.physics_layers.get_physics_layer(physics_layer_id) + let Some(physics_color) = tileset + .physics_layers + .get_physics_layer(physics_layer_id) .map(|layer| layer.debug_color) else { return; }; if let Some(shape) = collision_shape { - if let bevy_map_core::CollisionShape::Polygon { points } = - &shape - { + if let bevy_map_core::CollisionShape::Polygon { points } = &shape { // Create a temporary copy with the moved vertex let mut preview_points = points.clone(); if *index < preview_points.len() { @@ -2870,7 +2926,7 @@ fn handle_collision_canvas_input( ui.painter(), canvas_rect, &preview_shape, - physics_color + physics_color, ); draw_collision_handles(ui.painter(), canvas_rect, &preview_shape); } @@ -3059,7 +3115,11 @@ fn render_collision_properties( return; }; - let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer else { + let Some(physics_layer_id) = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + else { ui.label("No physics layer selected"); return; }; @@ -3145,8 +3205,16 @@ fn render_collision_properties( // Action buttons if ui.button("Set Full Collision").clicked() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - if let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer { - tileset.set_tile_collision_shape(tile_idx, bevy_map_core::CollisionShape::Full, physics_layer_id); + if let Some(physics_layer_id) = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + { + tileset.set_tile_collision_shape( + tile_idx, + bevy_map_core::CollisionShape::Full, + physics_layer_id, + ); project.mark_dirty(); } } @@ -3154,8 +3222,16 @@ fn render_collision_properties( if ui.button("Clear Collision").clicked() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - if let Some(physics_layer_id) = editor_state.tileset_editor_state.collision_editor.selected_physics_layer { - tileset.set_tile_collision_shape(tile_idx, bevy_map_core::CollisionShape::None, physics_layer_id); + if let Some(physics_layer_id) = editor_state + .tileset_editor_state + .collision_editor + .selected_physics_layer + { + tileset.set_tile_collision_shape( + tile_idx, + bevy_map_core::CollisionShape::None, + physics_layer_id, + ); project.mark_dirty(); } } @@ -3251,10 +3327,6 @@ fn point_to_segment_distance(p: &[f32; 2], a: &[f32; 2], b: &[f32; 2]) -> f32 { (dx * dx + dy * dy).sqrt() } - - - - /// Render the new physics layer set dialog (Tiled-compatible) pub fn render_new_physics_layer_set_dialog( ctx: &egui::Context, @@ -3280,26 +3352,35 @@ pub fn render_new_physics_layer_set_dialog( // Color picker let default_color = [0, 140, 255u8]; // Default blue - let mut rgb = [(editor_state.new_physics_layer_debug_color.to_srgba().red * 255.0) as u8, - (editor_state.new_physics_layer_debug_color.to_srgba().green * 255.0) as u8, - (editor_state.new_physics_layer_debug_color.to_srgba().blue * 255.0) as u8]; + let mut rgb = [ + (editor_state.new_physics_layer_debug_color.to_srgba().red * 255.0) as u8, + (editor_state.new_physics_layer_debug_color.to_srgba().green * 255.0) as u8, + (editor_state.new_physics_layer_debug_color.to_srgba().blue * 255.0) as u8, + ]; ui.label("Color:"); if egui::color_picker::color_edit_button_srgb(ui, &mut rgb).changed() { - editor_state.new_physics_layer_debug_color = Color::srgba(rgb[0] as f32 / 255.0, rgb[1] as f32 / 255.0, rgb[2] as f32 / 255.0, 0.3); + editor_state.new_physics_layer_debug_color = Color::srgba( + rgb[0] as f32 / 255.0, + rgb[1] as f32 / 255.0, + rgb[2] as f32 / 255.0, + 0.3, + ); } ui.horizontal(|ui| { ui.label("Layer:"); - ui.add(egui::DragValue::new(&mut editor_state.new_physics_layer_layer)); + ui.add(egui::DragValue::new( + &mut editor_state.new_physics_layer_layer, + )); }); ui.horizontal(|ui| { ui.label("Mask:"); - ui.add(egui::DragValue::new(&mut editor_state.new_physics_layer_mask)); + ui.add(egui::DragValue::new( + &mut editor_state.new_physics_layer_mask, + )); }); - - ui.separator(); ui.horizontal(|ui| { @@ -3318,10 +3399,7 @@ pub fn render_new_physics_layer_set_dialog( ); let tileset = project.tilesets.iter_mut().find(|t| t.id == tileset_id); if let Some(tileset) = tileset { - tileset - .physics_layers - .layers - .push(physics_layer_set); + tileset.physics_layers.layers.push(physics_layer_set); }; project.mark_dirty(); editor_state.show_add_physics_layer_set_dialog = false; From 6dde8eadbe3a96f8e55ba7442217d11f59c4fa96 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Sun, 1 Feb 2026 19:22:58 -0800 Subject: [PATCH 03/22] Click and Drag --- crates/bevy_map_core/src/physics_layers.rs | 5 + .../bevy_map_editor/src/ui/tileset_editor.rs | 129 +++++++++++------- 2 files changed, 84 insertions(+), 50 deletions(-) diff --git a/crates/bevy_map_core/src/physics_layers.rs b/crates/bevy_map_core/src/physics_layers.rs index 44a3c93..f1fb9a4 100644 --- a/crates/bevy_map_core/src/physics_layers.rs +++ b/crates/bevy_map_core/src/physics_layers.rs @@ -82,6 +82,11 @@ impl PhysicsLayerSet { self.tile_physics.get(&tile_index) } + /// Get collision data for a tile index + pub fn get_tile_physics_mut(&mut self, tile_index: u32) -> Option<&mut CollisionData> { + self.tile_physics.get_mut(&tile_index) + } + pub fn set_tile_physics_shape(&mut self, tile_index: u32, shape: CollisionShape) { if let Some(collision_data) = self.tile_physics.get_mut(&tile_index) { collision_data.shape = shape; diff --git a/crates/bevy_map_editor/src/ui/tileset_editor.rs b/crates/bevy_map_editor/src/ui/tileset_editor.rs index 01098ef..616af4b 100644 --- a/crates/bevy_map_editor/src/ui/tileset_editor.rs +++ b/crates/bevy_map_editor/src/ui/tileset_editor.rs @@ -2715,24 +2715,34 @@ fn handle_collision_canvas_input( // Check if starting drag on a polygon vertex handle if let Some(tileset) = project.tilesets.iter().find(|t| t.id == tileset_id) { - if let Some(props) = tileset.get_tile_properties(tile_idx) { - if let bevy_map_core::CollisionShape::Polygon { points } = - &props.collision.shape + + if let Some(physics_layer) = tileset + .physics_layers + .get_physics_layer(physics_layer_id) + { + if let Some(props) = + physics_layer.tile_physics.get(&tile_idx) { - if let Some(vertex_idx) = - hit_test_polygon_vertex(canvas_rect, points, pointer_pos, 8.0) + let shape = &props.shape; + + if let bevy_map_core::CollisionShape::Polygon { points } = + &shape { - editor_state - .tileset_editor_state - .collision_editor - .drag_state = Some(CollisionDragState { - start_pos: normalized, - current_pos: normalized, - operation: CollisionDragOperation::MoveVertex { - index: vertex_idx, - original: points[vertex_idx], - }, - }); + if let Some(vertex_idx) = + hit_test_polygon_vertex(canvas_rect, points, pointer_pos, 8.0) + { + editor_state + .tileset_editor_state + .collision_editor + .drag_state = Some(CollisionDragState { + start_pos: normalized, + current_pos: normalized, + operation: CollisionDragOperation::MoveVertex { + index: vertex_idx, + original: points[vertex_idx], + }, + }); + } } } } @@ -2834,13 +2844,22 @@ fn handle_collision_canvas_input( // Update the polygon vertex in the tileset if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - if let Some(props) = tileset.tile_properties.get_mut(&tile_idx) { - if let bevy_map_core::CollisionShape::Polygon { points } = - &mut props.collision.shape + if let Some(physics_layer) = tileset + .physics_layers + .get_physics_layer_mut(physics_layer_id) + { + if let Some(props) = + physics_layer.tile_physics.get_mut(&tile_idx) { - if index < points.len() { - points[index] = clamped; - project.mark_dirty(); + let mut shape = &mut props.shape; + + if let bevy_map_core::CollisionShape::Polygon { points } = + &mut shape + { + if index < points.len() { + points[index] = clamped; + project.mark_dirty(); + } } } } @@ -2943,19 +2962,26 @@ fn handle_collision_canvas_input( let normalized = canvas_point_to_normalized(canvas_rect, pointer_pos); // Check if on existing vertex - let vertex_idx = if let Some(tileset) = - project.tilesets.iter().find(|t| t.id == tileset_id) - { - tileset.get_tile_properties(tile_idx).and_then(|p| { - if let bevy_map_core::CollisionShape::Polygon { points } = &p.collision.shape { - hit_test_polygon_vertex(canvas_rect, points, pointer_pos, 8.0) + let vertex_idx = + if let Some(tileset) = project.tilesets.iter().find(|t| t.id == tileset_id) { + let collision_shape = tileset + .physics_layers + .get_physics_layer(physics_layer_id) + .and_then(|layer| layer.get_tile_physics(tile_idx)) + .map(|data| data.shape.clone()); + + if let Some(shape) = collision_shape { + if let bevy_map_core::CollisionShape::Polygon { points } = &shape { + hit_test_polygon_vertex(canvas_rect, points, pointer_pos, 8.0) + } else { + None + } } else { None } - }) - } else { - None - }; + } else { + None + }; editor_state .tileset_editor_state @@ -2987,13 +3013,8 @@ fn handle_collision_canvas_input( .tilesets .iter() .find(|t| t.id == tileset_id) - .and_then(|t| t.get_tile_properties(tile_idx)) - .map(|p| { - matches!( - p.collision.shape, - bevy_map_core::CollisionShape::Polygon { .. } - ) - }) + .and_then(|t| t.get_tile_collision(tile_idx, physics_layer_id)) + .map(|p| matches!(p.shape, bevy_map_core::CollisionShape::Polygon { .. })) .unwrap_or(false); if is_polygon { @@ -3001,18 +3022,26 @@ fn handle_collision_canvas_input( if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - if let Some(props) = tileset.tile_properties.get_mut(&tile_idx) { - if let bevy_map_core::CollisionShape::Polygon { points } = - &mut props.collision.shape + if let Some(physics_layer) = tileset + .physics_layers + .get_physics_layer_mut(physics_layer_id) + { + if let Some(props) = + physics_layer.tile_physics.get_mut(&tile_idx) { - let clamped = [ - menu_pos[0].clamp(0.0, 1.0), - menu_pos[1].clamp(0.0, 1.0), - ]; - let insert_idx = - find_best_insertion_index(points, &clamped); - points.insert(insert_idx, clamped); - project.mark_dirty(); + let mut shape = &mut props.shape; + if let bevy_map_core::CollisionShape::Polygon { points } = + &mut shape + { + let clamped = [ + menu_pos[0].clamp(0.0, 1.0), + menu_pos[1].clamp(0.0, 1.0), + ]; + let insert_idx = + find_best_insertion_index(points, &clamped); + points.insert(insert_idx, clamped); + project.mark_dirty(); + } } } } From 94527c8bdfc5707602c5d15c598c7cec0f3e330f Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Sun, 1 Feb 2026 19:25:59 -0800 Subject: [PATCH 04/22] Runtime Update --- crates/bevy_map_runtime/src/collision.rs | 37 ++++++++++++++---------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/crates/bevy_map_runtime/src/collision.rs b/crates/bevy_map_runtime/src/collision.rs index a1c67d0..09088e3 100644 --- a/crates/bevy_map_runtime/src/collision.rs +++ b/crates/bevy_map_runtime/src/collision.rs @@ -124,22 +124,27 @@ pub fn spawn_tile_colliders( let idx = (y * level.width + x) as usize; if let Some(&Some(tile_index)) = tiles.get(idx) { // Check if this tile has collision - if let Some(props) = tileset.get_tile_properties(tile_index) { - if props.collision.has_collision() { - spawn_collider_for_tile( - &mut commands, - map_entity, - &props.collision, - x, - y, - tile_size, - &map_size, - &grid_size, - &tilemap_tile_size, - &map_type, - &anchor, - ); - total_colliders += 1; + for physics_layer in tileset.physics_layers.layers.iter() { + + if let Some(collision) = + physics_layer.get_tile_physics(tile_index) + { + if collision.has_collision() { + spawn_collider_for_tile( + &mut commands, + map_entity, + collision, + x, + y, + tile_size, + &map_size, + &grid_size, + &tilemap_tile_size, + &map_type, + &anchor, + ); + total_colliders += 1; + } } } } From 5e4658fed5a4f22e95bb2b7006582f57e3b0e4e2 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Sun, 1 Feb 2026 20:10:18 -0800 Subject: [PATCH 05/22] More layer_z diff --- crates/bevy_map_editor/src/render/mod.rs | 8 ++++---- crates/bevy_map_editor/src/ui/tileset_editor.rs | 8 ++++---- crates/bevy_map_runtime/src/lib.rs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/bevy_map_editor/src/render/mod.rs b/crates/bevy_map_editor/src/render/mod.rs index f519bed..a7a246a 100644 --- a/crates/bevy_map_editor/src/render/mod.rs +++ b/crates/bevy_map_editor/src/render/mod.rs @@ -382,7 +382,7 @@ fn spawn_level_tilemaps( // Z-offset: layer_index * 0.1 + image_index * 0.01 // This ensures proper ordering: all images in layer 0 render before layer 1 - let layer_z = layer_index as f32 * 0.1 + image_index as f32 * 0.01; + let layer_z = 10.0 *layer_index as f32 + image_index as f32 * 0.01; // Insert TilemapBundle first (which includes Visibility internally) // Use BottomLeft anchor so tiles at (0,0) start at world origin @@ -462,7 +462,7 @@ fn spawn_level_tilemaps( let world_y = y as f32 * tile_size_f32 + origin_y as f32; // Z-offset slightly above regular tiles in same layer - let layer_z = layer_index as f32 * 0.1 + image_index as f32 * 0.01 + 0.001; + let layer_z = layer_index as f32 * 10.0 + image_index as f32 * 0.01 + 0.001; let sprite_entity = commands .spawn(( @@ -612,7 +612,7 @@ pub fn update_tile( // World position: place sprite so origin aligns with grid cell corner let world_x = x as f32 * tile_size_f32 + origin_x as f32; let world_y = y as f32 * tile_size_f32 + origin_y as f32; - let layer_z = layer_index as f32 * 0.1 + image_index as f32 * 0.01 + 0.001; + let layer_z = layer_index as f32 * 10.0 + image_index as f32 * 0.01 + 0.001; let sprite_entity = commands .spawn(( @@ -682,7 +682,7 @@ pub fn update_tile( let tile_storage = TileStorage::empty(map_size); let tilemap_entity = commands.spawn_empty().id(); - let layer_z = layer_index as f32 * 0.1 + image_index as f32 * 0.01; + let layer_z = layer_index as f32 * 10.0 + image_index as f32 * 0.01; let layer_visible = layer.visible; commands.entity(tilemap_entity).insert(( diff --git a/crates/bevy_map_editor/src/ui/tileset_editor.rs b/crates/bevy_map_editor/src/ui/tileset_editor.rs index 616af4b..2eca8d2 100644 --- a/crates/bevy_map_editor/src/ui/tileset_editor.rs +++ b/crates/bevy_map_editor/src/ui/tileset_editor.rs @@ -1361,7 +1361,7 @@ fn render_tile_properties_tab( ui.horizontal(|ui| { ui.label("Layer:"); if ui - .add(egui::DragValue::new(&mut layer).range(0..=31)) + .add(egui::DragValue::new(&mut layer)) .changed() { if let Some(tileset) = @@ -1379,7 +1379,7 @@ fn render_tile_properties_tab( ui.horizontal(|ui| { ui.label("Mask:"); if ui - .add(egui::DragValue::new(&mut mask).range(0..=31)) + .add(egui::DragValue::new(&mut mask)) .changed() { if let Some(tileset) = @@ -3204,7 +3204,7 @@ fn render_collision_properties( ui.horizontal(|ui| { ui.label("Layer:"); if ui - .add(egui::DragValue::new(&mut layer).range(0..=31)) + .add(egui::DragValue::new(&mut layer)) .changed() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { @@ -3219,7 +3219,7 @@ fn render_collision_properties( ui.horizontal(|ui| { ui.label("Mask:"); if ui - .add(egui::DragValue::new(&mut mask).range(0..=31)) + .add(egui::DragValue::new(&mut mask)) .changed() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index bae4c91..e86859c 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -1031,7 +1031,7 @@ pub fn spawn_map( let map_type = TilemapType::Square; // Calculate layer z-offset based on layer index - let layer_z = layer_index as f32 * 0.1; + let layer_z = layer_index as f32 * 10.0; commands.entity(tilemap_entity).insert(( TilemapBundle { @@ -1283,7 +1283,7 @@ pub fn spawn_map_project( // Z-offset: layer_index * 0.1 + image_index * 0.01 // This ensures proper ordering: all images in layer 0 render before layer 1 - let layer_z = layer_index as f32 * 0.1 + image_index as f32 * 0.01; + let layer_z = layer_index as f32 * 10.0 + image_index as f32 * 0.01; commands.entity(tilemap_entity).insert(( TilemapBundle { From 6158bd20ab9858a657cb7ed8aea97b14a7feb0ca Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Sun, 1 Feb 2026 20:55:34 -0800 Subject: [PATCH 06/22] DisableGraphics --- crates/bevy_map_runtime/src/lib.rs | 69 ++++++++++++++++++------------ 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index e86859c..537466d 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -254,6 +254,10 @@ impl Plugin for MapRuntimePlugin { #[derive(Component)] pub struct MapHandle(pub Handle); + +#[derive(Component, Clone, Copy)] +pub struct DisableGraphics; + /// Marker component for the root entity of a spawned map /// /// This is added automatically when a map is spawned. It tracks the source @@ -289,51 +293,60 @@ fn handle_map_handle_spawning( mut commands: Commands, asset_server: Res, map_assets: Res>, - mut query: Query<(Entity, &MapHandle, &mut MapHandleState, Option<&Transform>)>, + mut query: Query<(Entity, &MapHandle, &mut MapHandleState, Option<&Transform>, Has)>, entity_registry: Res, mut map_dialogues: ResMut, ) { - for (entity, map_handle, mut state, _transform) in query.iter_mut() { + for (entity, map_handle, mut state, _transform, has_disable_graphics) in query.iter_mut() { // Check if asset is loaded let Some(project) = map_assets.get(&map_handle.0) else { continue; }; + // Start loading textures if we haven't if !state.loading_textures { - info!( - "MapProject '{}' loaded, queueing texture loads...", - project.level.name - ); - let mut textures = TilesetTextures::new(); - textures.load_from_project(project, &asset_server); - info!( - "Queued {} tileset images, {} sprite sheets for loading", - textures.images.len(), - textures.sprite_sheet_images.len() - ); - state.textures = Some(textures); - state.loading_textures = true; + + if !has_disable_graphics { + info!( + "MapProject '{}' loaded, queueing texture loads...", + project.level.name + ); + let mut textures = TilesetTextures::new(); + textures.load_from_project(project, &asset_server); + info!( + "Queued {} tileset images, {} sprite sheets for loading", + textures.images.len(), + textures.sprite_sheet_images.len() + ); + state.textures = Some(textures); + state.loading_textures = true; + } else { + state.textures = None; + state.loading_textures = true; + } + } // Check if all textures are loaded let Some(textures) = &state.textures else { continue; }; - - if !textures.all_loaded(&asset_server) { - // Log loading state periodically (only once per second to avoid spam) - static LAST_LOG: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); - let now = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_secs(); - let last = LAST_LOG.load(std::sync::atomic::Ordering::Relaxed); - if now > last { - LAST_LOG.store(now, std::sync::atomic::Ordering::Relaxed); - textures.log_loading_state(&asset_server); + if !has_disable_graphics { + if !textures.all_loaded(&asset_server) { + // Log loading state periodically (only once per second to avoid spam) + static LAST_LOG: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); + let now = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs(); + let last = LAST_LOG.load(std::sync::atomic::Ordering::Relaxed); + if now > last { + LAST_LOG.store(now, std::sync::atomic::Ordering::Relaxed); + textures.log_loading_state(&asset_server); + } + continue; } - continue; } // Don't spawn if already spawned From c13ccac6503b8da3d3b52c02503f8cfb18c12442 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Mon, 2 Feb 2026 16:13:25 -0800 Subject: [PATCH 07/22] Disable Renderer --- crates/bevy_map_runtime/src/lib.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index 537466d..6fbd79b 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -327,12 +327,11 @@ fn handle_map_handle_spawning( } } - - // Check if all textures are loaded - let Some(textures) = &state.textures else { - continue; - }; if !has_disable_graphics { + // Check if all textures are loaded + let Some(textures) = &state.textures else { + continue; + }; if !textures.all_loaded(&asset_server) { // Log loading state periodically (only once per second to avoid spam) static LAST_LOG: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); From 977691d59d106f479b0fc2e2b91a8633eb5d5ff2 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Mon, 2 Feb 2026 16:16:07 -0800 Subject: [PATCH 08/22] Disable Renderer --- crates/bevy_map_runtime/src/lib.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index 6fbd79b..fac023a 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -322,16 +322,21 @@ fn handle_map_handle_spawning( state.textures = Some(textures); state.loading_textures = true; } else { - state.textures = None; + state.textures = Some(TilesetTextures::new()); state.loading_textures = true; } } + + // Check if all textures are loaded + let Some(textures) = &state.textures else { + + + continue; + }; + + if !has_disable_graphics { - // Check if all textures are loaded - let Some(textures) = &state.textures else { - continue; - }; if !textures.all_loaded(&asset_server) { // Log loading state periodically (only once per second to avoid spam) static LAST_LOG: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); From 6eb88d327c6b6fcf3adc2000a2c00b96dffaf4fa Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Mon, 2 Feb 2026 16:20:19 -0800 Subject: [PATCH 09/22] printouts debugging --- crates/bevy_map_runtime/src/lib.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index fac023a..75d1857 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -303,6 +303,8 @@ fn handle_map_handle_spawning( continue; }; + println!("print 1"); + // Start loading textures if we haven't if !state.loading_textures { @@ -327,6 +329,7 @@ fn handle_map_handle_spawning( } } + println!("print 2"); // Check if all textures are loaded let Some(textures) = &state.textures else { @@ -335,6 +338,8 @@ fn handle_map_handle_spawning( continue; }; + println!("print 3"); + if !has_disable_graphics { if !textures.all_loaded(&asset_server) { @@ -353,11 +358,15 @@ fn handle_map_handle_spawning( } } + println!("print 4"); + // Don't spawn if already spawned if state.spawned { continue; } + println!("print 5"); + info!( "Spawning map '{}' with {} layers, {} tilesets", project.level.name, @@ -365,6 +374,9 @@ fn handle_map_handle_spawning( project.tilesets.len() ); + + println!("print 6"); + // Load dialogues from the project map_dialogues.load_from_project(project); @@ -376,14 +388,20 @@ fn handle_map_handle_spawning( Some(&entity_registry), ); + println!("print 7"); + // Add MapRoot marker and make it a child commands.entity(map_entity).insert(MapRoot { handle: map_handle.0.clone(), textures: textures.clone(), }); + println!("print 8"); + commands.entity(entity).add_child(map_entity); + println!("print 9"); + state.spawned = true; info!("Spawned map: {}", project.level.name); } From 50d692e46b0dae129585be8e79dd83ba1148bfa3 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Mon, 2 Feb 2026 19:31:11 -0800 Subject: [PATCH 10/22] undo --- crates/bevy_map_runtime/src/lib.rs | 88 +++++++++--------------------- 1 file changed, 27 insertions(+), 61 deletions(-) diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index 75d1857..1dfbd72 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -255,9 +255,6 @@ impl Plugin for MapRuntimePlugin { pub struct MapHandle(pub Handle); -#[derive(Component, Clone, Copy)] -pub struct DisableGraphics; - /// Marker component for the root entity of a spawned map /// /// This is added automatically when a map is spawned. It tracks the source @@ -293,80 +290,58 @@ fn handle_map_handle_spawning( mut commands: Commands, asset_server: Res, map_assets: Res>, - mut query: Query<(Entity, &MapHandle, &mut MapHandleState, Option<&Transform>, Has)>, + mut query: Query<(Entity, &MapHandle, &mut MapHandleState, Option<&Transform>)>, entity_registry: Res, mut map_dialogues: ResMut, ) { - for (entity, map_handle, mut state, _transform, has_disable_graphics) in query.iter_mut() { + for (entity, map_handle, mut state, _transform) in query.iter_mut() { // Check if asset is loaded let Some(project) = map_assets.get(&map_handle.0) else { continue; }; - println!("print 1"); - - // Start loading textures if we haven't if !state.loading_textures { - - if !has_disable_graphics { - info!( - "MapProject '{}' loaded, queueing texture loads...", - project.level.name - ); - let mut textures = TilesetTextures::new(); - textures.load_from_project(project, &asset_server); - info!( - "Queued {} tileset images, {} sprite sheets for loading", - textures.images.len(), - textures.sprite_sheet_images.len() - ); - state.textures = Some(textures); - state.loading_textures = true; - } else { - state.textures = Some(TilesetTextures::new()); - state.loading_textures = true; - } - + info!( + "MapProject '{}' loaded, queueing texture loads...", + project.level.name + ); + let mut textures = TilesetTextures::new(); + textures.load_from_project(project, &asset_server); + info!( + "Queued {} tileset images, {} sprite sheets for loading", + textures.images.len(), + textures.sprite_sheet_images.len() + ); + state.textures = Some(textures); + state.loading_textures = true; } - println!("print 2"); // Check if all textures are loaded let Some(textures) = &state.textures else { - - continue; }; - println!("print 3"); - - - if !has_disable_graphics { - if !textures.all_loaded(&asset_server) { - // Log loading state periodically (only once per second to avoid spam) - static LAST_LOG: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); - let now = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_secs(); - let last = LAST_LOG.load(std::sync::atomic::Ordering::Relaxed); - if now > last { - LAST_LOG.store(now, std::sync::atomic::Ordering::Relaxed); - textures.log_loading_state(&asset_server); - } - continue; + if !textures.all_loaded(&asset_server) { + // Log loading state periodically (only once per second to avoid spam) + static LAST_LOG: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); + let now = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs(); + let last = LAST_LOG.load(std::sync::atomic::Ordering::Relaxed); + if now > last { + LAST_LOG.store(now, std::sync::atomic::Ordering::Relaxed); + textures.log_loading_state(&asset_server); } + continue; } - println!("print 4"); - // Don't spawn if already spawned if state.spawned { continue; } - println!("print 5"); - info!( "Spawning map '{}' with {} layers, {} tilesets", project.level.name, @@ -374,9 +349,6 @@ fn handle_map_handle_spawning( project.tilesets.len() ); - - println!("print 6"); - // Load dialogues from the project map_dialogues.load_from_project(project); @@ -388,20 +360,14 @@ fn handle_map_handle_spawning( Some(&entity_registry), ); - println!("print 7"); - // Add MapRoot marker and make it a child commands.entity(map_entity).insert(MapRoot { handle: map_handle.0.clone(), textures: textures.clone(), }); - println!("print 8"); - commands.entity(entity).add_child(map_entity); - println!("print 9"); - state.spawned = true; info!("Spawned map: {}", project.level.name); } From 9287261c0e7053129dbe5958cf4fa9b4e1d3af18 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Tue, 3 Feb 2026 19:19:47 -0800 Subject: [PATCH 11/22] cargo fmt --- .../src/bin/bevy_map_editor.rs | 66 +++++++++---------- crates/bevy_map_editor/src/render/mod.rs | 2 +- .../bevy_map_editor/src/ui/tileset_editor.rs | 44 ++++--------- crates/bevy_map_runtime/src/collision.rs | 4 +- crates/bevy_map_runtime/src/lib.rs | 1 - 5 files changed, 47 insertions(+), 70 deletions(-) diff --git a/crates/bevy_map_editor/src/bin/bevy_map_editor.rs b/crates/bevy_map_editor/src/bin/bevy_map_editor.rs index 83adc68..d878c33 100644 --- a/crates/bevy_map_editor/src/bin/bevy_map_editor.rs +++ b/crates/bevy_map_editor/src/bin/bevy_map_editor.rs @@ -22,20 +22,20 @@ fn main() { let window_width = preferences.window_width.unwrap_or(1920.0) as u32; let window_height = preferences.window_height.unwrap_or(1080.0) as u32; - let window_position = match (preferences.window_x, preferences.window_y) { - (Some(x), Some(y)) => WindowPosition::At(IVec2::new(x, y)), - _ => WindowPosition::Automatic, - }; + // let window_position = match (preferences.window_x, preferences.window_y) { + // (Some(x), Some(y)) => WindowPosition::At(IVec2::new(x, y)), + // _ => WindowPosition::Automatic, + // }; - let window_mode = match preferences.window_mode.as_deref() { - Some("borderless_fullscreen") => { - WindowMode::BorderlessFullscreen(MonitorSelection::Current) - } - Some("fullscreen") => { - WindowMode::Fullscreen(MonitorSelection::Current, VideoModeSelection::Current) - } - _ => WindowMode::Windowed, - }; + // let window_mode = match preferences.window_mode.as_deref() { + // Some("borderless_fullscreen") => { + // WindowMode::BorderlessFullscreen(MonitorSelection::Current) + // } + // Some("fullscreen") => { + // WindowMode::Fullscreen(MonitorSelection::Current, VideoModeSelection::Current) + // } + // _ => WindowMode::Windowed, + // }; App::new() .add_plugins( @@ -46,8 +46,8 @@ fn main() { // High DPI support: prevent OS-level scaling that causes blurriness resolution: WindowResolution::new(window_width, window_height) .with_scale_factor_override(1.0), - position: window_position, - mode: window_mode, + // position: window_position, + // mode: window_mode, ..default() }), ..default() @@ -119,15 +119,15 @@ fn save_window_state_on_change( if let Ok(window) = windows.single() { preferences.window_width = Some(window.resolution.width()); preferences.window_height = Some(window.resolution.height()); - if let WindowPosition::At(pos) = window.position { - preferences.window_x = Some(pos.x); - preferences.window_y = Some(pos.y); - } - preferences.window_mode = Some(match window.mode { - WindowMode::BorderlessFullscreen(_) => "borderless_fullscreen".to_string(), - WindowMode::Fullscreen(_, _) => "fullscreen".to_string(), - _ => "windowed".to_string(), - }); + // if let WindowPosition::At(pos) = window.position { + // preferences.window_x = Some(pos.x); + // preferences.window_y = Some(pos.y); + // } + // preferences.window_mode = Some(match window.mode { + // WindowMode::BorderlessFullscreen(_) => "borderless_fullscreen".to_string(), + // WindowMode::Fullscreen(_, _) => "fullscreen".to_string(), + // _ => "windowed".to_string(), + // }); if let Err(e) = preferences.save() { error!("Failed to save window state to preferences: {}", e); } @@ -146,15 +146,15 @@ fn save_window_size_on_exit( if let Ok(window) = windows.single() { preferences.window_width = Some(window.resolution.width()); preferences.window_height = Some(window.resolution.height()); - if let WindowPosition::At(pos) = window.position { - preferences.window_x = Some(pos.x); - preferences.window_y = Some(pos.y); - } - preferences.window_mode = Some(match window.mode { - WindowMode::BorderlessFullscreen(_) => "borderless_fullscreen".to_string(), - WindowMode::Fullscreen(_, _) => "fullscreen".to_string(), - _ => "windowed".to_string(), - }); + // if let WindowPosition::At(pos) = window.position { + // preferences.window_x = Some(pos.x); + // preferences.window_y = Some(pos.y); + // } + // preferences.window_mode = Some(match window.mode { + // WindowMode::BorderlessFullscreen(_) => "borderless_fullscreen".to_string(), + // WindowMode::Fullscreen(_, _) => "fullscreen".to_string(), + // _ => "windowed".to_string(), + // }); if let Err(e) = preferences.save() { error!("Failed to save window size to preferences: {}", e); } diff --git a/crates/bevy_map_editor/src/render/mod.rs b/crates/bevy_map_editor/src/render/mod.rs index a7a246a..9e9df95 100644 --- a/crates/bevy_map_editor/src/render/mod.rs +++ b/crates/bevy_map_editor/src/render/mod.rs @@ -382,7 +382,7 @@ fn spawn_level_tilemaps( // Z-offset: layer_index * 0.1 + image_index * 0.01 // This ensures proper ordering: all images in layer 0 render before layer 1 - let layer_z = 10.0 *layer_index as f32 + image_index as f32 * 0.01; + let layer_z = 10.0 * layer_index as f32 + image_index as f32 * 0.01; // Insert TilemapBundle first (which includes Visibility internally) // Use BottomLeft anchor so tiles at (0,0) start at world origin diff --git a/crates/bevy_map_editor/src/ui/tileset_editor.rs b/crates/bevy_map_editor/src/ui/tileset_editor.rs index 2eca8d2..72f4e3e 100644 --- a/crates/bevy_map_editor/src/ui/tileset_editor.rs +++ b/crates/bevy_map_editor/src/ui/tileset_editor.rs @@ -1360,10 +1360,7 @@ fn render_tile_properties_tab( let mut layer = collision_data.layer; ui.horizontal(|ui| { ui.label("Layer:"); - if ui - .add(egui::DragValue::new(&mut layer)) - .changed() - { + if ui.add(egui::DragValue::new(&mut layer)).changed() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { @@ -1378,10 +1375,7 @@ fn render_tile_properties_tab( let mut mask = collision_data.mask; ui.horizontal(|ui| { ui.label("Mask:"); - if ui - .add(egui::DragValue::new(&mut mask)) - .changed() - { + if ui.add(egui::DragValue::new(&mut mask)).changed() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { @@ -2715,19 +2709,13 @@ fn handle_collision_canvas_input( // Check if starting drag on a polygon vertex handle if let Some(tileset) = project.tilesets.iter().find(|t| t.id == tileset_id) { - - if let Some(physics_layer) = tileset - .physics_layers - .get_physics_layer(physics_layer_id) + if let Some(physics_layer) = + tileset.physics_layers.get_physics_layer(physics_layer_id) { - if let Some(props) = - physics_layer.tile_physics.get(&tile_idx) - { + if let Some(props) = physics_layer.tile_physics.get(&tile_idx) { let shape = &props.shape; - if let bevy_map_core::CollisionShape::Polygon { points } = - &shape - { + if let bevy_map_core::CollisionShape::Polygon { points } = &shape { if let Some(vertex_idx) = hit_test_polygon_vertex(canvas_rect, points, pointer_pos, 8.0) { @@ -2845,14 +2833,12 @@ fn handle_collision_canvas_input( if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { if let Some(physics_layer) = tileset - .physics_layers - .get_physics_layer_mut(physics_layer_id) + .physics_layers + .get_physics_layer_mut(physics_layer_id) { - if let Some(props) = - physics_layer.tile_physics.get_mut(&tile_idx) - { + if let Some(props) = physics_layer.tile_physics.get_mut(&tile_idx) { let mut shape = &mut props.shape; - + if let bevy_map_core::CollisionShape::Polygon { points } = &mut shape { @@ -3203,10 +3189,7 @@ fn render_collision_properties( let mut layer = collision_data.layer; ui.horizontal(|ui| { ui.label("Layer:"); - if ui - .add(egui::DragValue::new(&mut layer)) - .changed() - { + if ui.add(egui::DragValue::new(&mut layer)).changed() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { tileset.set_tile_collision_layer(tile_idx, layer, physics_layer_id); project.mark_dirty(); @@ -3218,10 +3201,7 @@ fn render_collision_properties( let mut mask = collision_data.mask; ui.horizontal(|ui| { ui.label("Mask:"); - if ui - .add(egui::DragValue::new(&mut mask)) - .changed() - { + if ui.add(egui::DragValue::new(&mut mask)).changed() { if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { tileset.set_tile_collision_mask(tile_idx, mask, physics_layer_id); project.mark_dirty(); diff --git a/crates/bevy_map_runtime/src/collision.rs b/crates/bevy_map_runtime/src/collision.rs index 09088e3..a28caee 100644 --- a/crates/bevy_map_runtime/src/collision.rs +++ b/crates/bevy_map_runtime/src/collision.rs @@ -125,9 +125,7 @@ pub fn spawn_tile_colliders( if let Some(&Some(tile_index)) = tiles.get(idx) { // Check if this tile has collision for physics_layer in tileset.physics_layers.layers.iter() { - - if let Some(collision) = - physics_layer.get_tile_physics(tile_index) + if let Some(collision) = physics_layer.get_tile_physics(tile_index) { if collision.has_collision() { spawn_collider_for_tile( diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index 1dfbd72..e86859c 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -254,7 +254,6 @@ impl Plugin for MapRuntimePlugin { #[derive(Component)] pub struct MapHandle(pub Handle); - /// Marker component for the root entity of a spawned map /// /// This is added automatically when a map is spawned. It tracks the source From fb75369a019e79aece8b6ffc6ad610ddf955b0d2 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Tue, 3 Feb 2026 19:24:07 -0800 Subject: [PATCH 12/22] Update bevy_map_editor.rs --- .../src/bin/bevy_map_editor.rs | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/crates/bevy_map_editor/src/bin/bevy_map_editor.rs b/crates/bevy_map_editor/src/bin/bevy_map_editor.rs index d878c33..998c76d 100644 --- a/crates/bevy_map_editor/src/bin/bevy_map_editor.rs +++ b/crates/bevy_map_editor/src/bin/bevy_map_editor.rs @@ -22,20 +22,20 @@ fn main() { let window_width = preferences.window_width.unwrap_or(1920.0) as u32; let window_height = preferences.window_height.unwrap_or(1080.0) as u32; - // let window_position = match (preferences.window_x, preferences.window_y) { - // (Some(x), Some(y)) => WindowPosition::At(IVec2::new(x, y)), - // _ => WindowPosition::Automatic, - // }; + let window_position = match (preferences.window_x, preferences.window_y) { + (Some(x), Some(y)) => WindowPosition::At(IVec2::new(x, y)), + _ => WindowPosition::Automatic, + }; - // let window_mode = match preferences.window_mode.as_deref() { - // Some("borderless_fullscreen") => { - // WindowMode::BorderlessFullscreen(MonitorSelection::Current) - // } - // Some("fullscreen") => { - // WindowMode::Fullscreen(MonitorSelection::Current, VideoModeSelection::Current) - // } - // _ => WindowMode::Windowed, - // }; + let window_mode = match preferences.window_mode.as_deref() { + Some("borderless_fullscreen") => { + WindowMode::BorderlessFullscreen(MonitorSelection::Current) + } + Some("fullscreen") => { + WindowMode::Fullscreen(MonitorSelection::Current, VideoModeSelection::Current) + } + _ => WindowMode::Windowed, + }; App::new() .add_plugins( @@ -119,15 +119,15 @@ fn save_window_state_on_change( if let Ok(window) = windows.single() { preferences.window_width = Some(window.resolution.width()); preferences.window_height = Some(window.resolution.height()); - // if let WindowPosition::At(pos) = window.position { - // preferences.window_x = Some(pos.x); - // preferences.window_y = Some(pos.y); - // } - // preferences.window_mode = Some(match window.mode { - // WindowMode::BorderlessFullscreen(_) => "borderless_fullscreen".to_string(), - // WindowMode::Fullscreen(_, _) => "fullscreen".to_string(), - // _ => "windowed".to_string(), - // }); + if let WindowPosition::At(pos) = window.position { + preferences.window_x = Some(pos.x); + preferences.window_y = Some(pos.y); + } + preferences.window_mode = Some(match window.mode { + WindowMode::BorderlessFullscreen(_) => "borderless_fullscreen".to_string(), + WindowMode::Fullscreen(_, _) => "fullscreen".to_string(), + _ => "windowed".to_string(), + }); if let Err(e) = preferences.save() { error!("Failed to save window state to preferences: {}", e); } @@ -146,15 +146,15 @@ fn save_window_size_on_exit( if let Ok(window) = windows.single() { preferences.window_width = Some(window.resolution.width()); preferences.window_height = Some(window.resolution.height()); - // if let WindowPosition::At(pos) = window.position { - // preferences.window_x = Some(pos.x); - // preferences.window_y = Some(pos.y); - // } - // preferences.window_mode = Some(match window.mode { - // WindowMode::BorderlessFullscreen(_) => "borderless_fullscreen".to_string(), - // WindowMode::Fullscreen(_, _) => "fullscreen".to_string(), - // _ => "windowed".to_string(), - // }); + if let WindowPosition::At(pos) = window.position { + preferences.window_x = Some(pos.x); + preferences.window_y = Some(pos.y); + } + preferences.window_mode = Some(match window.mode { + WindowMode::BorderlessFullscreen(_) => "borderless_fullscreen".to_string(), + WindowMode::Fullscreen(_, _) => "fullscreen".to_string(), + _ => "windowed".to_string(), + }); if let Err(e) = preferences.save() { error!("Failed to save window size to preferences: {}", e); } From e5c9b35891e7294363f929d27b1ca925f31d04a7 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Tue, 3 Feb 2026 19:31:36 -0800 Subject: [PATCH 13/22] fix unused code --- crates/bevy_map_core/src/tileset.rs | 4 ++-- crates/bevy_map_editor/src/bin/bevy_map_editor.rs | 4 ++-- crates/bevy_map_editor/src/render/mod.rs | 2 -- crates/bevy_map_editor/src/ui/tileset_editor.rs | 1 - 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/crates/bevy_map_core/src/tileset.rs b/crates/bevy_map_core/src/tileset.rs index 2ee4233..c9d2f69 100644 --- a/crates/bevy_map_core/src/tileset.rs +++ b/crates/bevy_map_core/src/tileset.rs @@ -380,14 +380,14 @@ impl Tileset { } /// Set collision layer for a tile - pub fn set_tile_collision_layer(&mut self, tile_index: u32, layer: u8, physics_layer: Uuid) { + pub fn set_tile_collision_layer(&mut self, _tile_index: u32, layer: u8, physics_layer: Uuid) { if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { physics_layer_set.update_all_tile_physics_layer(layer); }; } /// Set collision mask for a tile - pub fn set_tile_collision_mask(&mut self, tile_index: u32, mask: u32, physics_layer: Uuid) { + pub fn set_tile_collision_mask(&mut self, _tile_index: u32, mask: u32, physics_layer: Uuid) { if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { physics_layer_set.update_all_tile_physics_mask(mask); }; diff --git a/crates/bevy_map_editor/src/bin/bevy_map_editor.rs b/crates/bevy_map_editor/src/bin/bevy_map_editor.rs index 998c76d..83adc68 100644 --- a/crates/bevy_map_editor/src/bin/bevy_map_editor.rs +++ b/crates/bevy_map_editor/src/bin/bevy_map_editor.rs @@ -46,8 +46,8 @@ fn main() { // High DPI support: prevent OS-level scaling that causes blurriness resolution: WindowResolution::new(window_width, window_height) .with_scale_factor_override(1.0), - // position: window_position, - // mode: window_mode, + position: window_position, + mode: window_mode, ..default() }), ..default() diff --git a/crates/bevy_map_editor/src/render/mod.rs b/crates/bevy_map_editor/src/render/mod.rs index 075b622..5039401 100644 --- a/crates/bevy_map_editor/src/render/mod.rs +++ b/crates/bevy_map_editor/src/render/mod.rs @@ -907,8 +907,6 @@ fn sync_collision_rendering( return; }; - let collision_color = Color::srgba(0.0, 0.6, 1.0, 0.3); - // Iterate through tile layers for (layer_idx, layer) in level.layers.iter().enumerate() { if !layer.visible { diff --git a/crates/bevy_map_editor/src/ui/tileset_editor.rs b/crates/bevy_map_editor/src/ui/tileset_editor.rs index 72f4e3e..12bafae 100644 --- a/crates/bevy_map_editor/src/ui/tileset_editor.rs +++ b/crates/bevy_map_editor/src/ui/tileset_editor.rs @@ -3360,7 +3360,6 @@ pub fn render_new_physics_layer_set_dialog( }); // Color picker - let default_color = [0, 140, 255u8]; // Default blue let mut rgb = [ (editor_state.new_physics_layer_debug_color.to_srgba().red * 255.0) as u8, (editor_state.new_physics_layer_debug_color.to_srgba().green * 255.0) as u8, From 614d3d2591a25258d5ba2dd20cd90e990f9cf47d Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Tue, 3 Feb 2026 19:35:13 -0800 Subject: [PATCH 14/22] Update Cargo.lock --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc85285..9fe7278 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1299,7 +1299,7 @@ dependencies = [ [[package]] name = "bevy_map" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bevy", "bevy_map_animation", @@ -1313,7 +1313,7 @@ dependencies = [ [[package]] name = "bevy_map_animation" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bevy", "serde", @@ -1323,7 +1323,7 @@ dependencies = [ [[package]] name = "bevy_map_autotile" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bevy_map_core", "log", @@ -1335,7 +1335,7 @@ dependencies = [ [[package]] name = "bevy_map_codegen" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bevy_map_core", "bevy_map_schema", @@ -1349,7 +1349,7 @@ dependencies = [ [[package]] name = "bevy_map_core" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bevy", "bevy_map_animation", @@ -1361,7 +1361,7 @@ dependencies = [ [[package]] name = "bevy_map_derive" -version = "0.4.0" +version = "0.5.0" dependencies = [ "proc-macro2", "quote", @@ -1370,7 +1370,7 @@ dependencies = [ [[package]] name = "bevy_map_dialogue" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bevy", "serde", @@ -1380,7 +1380,7 @@ dependencies = [ [[package]] name = "bevy_map_editor" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bevy", "bevy_ecs_tilemap", @@ -1416,7 +1416,7 @@ dependencies = [ [[package]] name = "bevy_map_runtime" -version = "0.4.0" +version = "0.5.0" dependencies = [ "avian2d", "bevy", @@ -1433,7 +1433,7 @@ dependencies = [ [[package]] name = "bevy_map_schema" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bevy_map_core", "serde", From 5601f3e91dbe5bb37aa1068d9024ba882c3ff0e2 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Tue, 3 Feb 2026 19:35:51 -0800 Subject: [PATCH 15/22] Update tileset_editor.rs --- crates/bevy_map_editor/src/ui/tileset_editor.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/bevy_map_editor/src/ui/tileset_editor.rs b/crates/bevy_map_editor/src/ui/tileset_editor.rs index 12bafae..142f692 100644 --- a/crates/bevy_map_editor/src/ui/tileset_editor.rs +++ b/crates/bevy_map_editor/src/ui/tileset_editor.rs @@ -2430,8 +2430,7 @@ fn render_collision_canvas( let tileset = project.tilesets.iter().find(|t| t.id == tileset_id); let collision_data = tileset .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) - .and_then(|layer| layer.get_tile_physics(tile_idx)) - .map(|data| data.clone()) + .and_then(|layer| layer.get_tile_physics(tile_idx)).cloned() .unwrap_or_default(); // 4. Draw collision shape overlay (skip if dragging vertex - preview handles it) @@ -3146,8 +3145,7 @@ fn render_collision_properties( let collision_data = tileset .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) - .and_then(|layer| layer.get_tile_physics(tile_idx)) - .map(|data| data.clone()) + .and_then(|layer| layer.get_tile_physics(tile_idx)).cloned() .unwrap_or_default(); // Shape info From cc7f266bfed7e7cca44f98d54e1fa302f24d1a30 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Tue, 3 Feb 2026 19:37:53 -0800 Subject: [PATCH 16/22] Update tileset_editor.rs --- crates/bevy_map_editor/src/ui/tileset_editor.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/bevy_map_editor/src/ui/tileset_editor.rs b/crates/bevy_map_editor/src/ui/tileset_editor.rs index 142f692..baaa0d8 100644 --- a/crates/bevy_map_editor/src/ui/tileset_editor.rs +++ b/crates/bevy_map_editor/src/ui/tileset_editor.rs @@ -2430,7 +2430,8 @@ fn render_collision_canvas( let tileset = project.tilesets.iter().find(|t| t.id == tileset_id); let collision_data = tileset .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) - .and_then(|layer| layer.get_tile_physics(tile_idx)).cloned() + .and_then(|layer| layer.get_tile_physics(tile_idx)) + .cloned() .unwrap_or_default(); // 4. Draw collision shape overlay (skip if dragging vertex - preview handles it) @@ -3145,7 +3146,8 @@ fn render_collision_properties( let collision_data = tileset .and_then(|t| t.physics_layers.get_physics_layer(physics_layer_id)) - .and_then(|layer| layer.get_tile_physics(tile_idx)).cloned() + .and_then(|layer| layer.get_tile_physics(tile_idx)) + .cloned() .unwrap_or_default(); // Shape info From d8e0195ce884f486d90431e11c5c940190bad715 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Thu, 5 Feb 2026 21:19:56 -0800 Subject: [PATCH 17/22] Update lib.rs --- crates/bevy_map_runtime/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index e86859c..845882a 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -66,6 +66,8 @@ use bevy::asset::AssetEvent; use bevy::ecs::message::{Message, MessageReader, MessageWriter}; +use bevy::ecs::query::Spawned; +use bevy::ecs::spawn; use bevy::prelude::*; use bevy_ecs_tilemap::prelude::*; use bevy_map_core::MapProject; @@ -292,6 +294,7 @@ fn handle_map_handle_spawning( mut query: Query<(Entity, &MapHandle, &mut MapHandleState, Option<&Transform>)>, entity_registry: Res, mut map_dialogues: ResMut, + mut map_spawn_event: MessageWriter, ) { for (entity, map_handle, mut state, _transform) in query.iter_mut() { // Check if asset is loaded @@ -359,6 +362,13 @@ fn handle_map_handle_spawning( Some(&entity_registry), ); + map_spawn_event.write(SpawnMapEvent { + level: project.level.clone(), + transform: Transform::default(), + tile_size: textures.tile_size, + tileset_textures: Vec::new(), + }); + // Add MapRoot marker and make it a child commands.entity(map_entity).insert(MapRoot { handle: map_handle.0.clone(), From 5d65af2292c8562a5c0f4dff10afb7e70505db64 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Thu, 5 Feb 2026 21:42:57 -0800 Subject: [PATCH 18/22] Update lib.rs --- crates/bevy_map_runtime/src/lib.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index 845882a..c03f6bb 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -294,7 +294,7 @@ fn handle_map_handle_spawning( mut query: Query<(Entity, &MapHandle, &mut MapHandleState, Option<&Transform>)>, entity_registry: Res, mut map_dialogues: ResMut, - mut map_spawn_event: MessageWriter, + // mut map_spawn_event: MessageWriter, ) { for (entity, map_handle, mut state, _transform) in query.iter_mut() { // Check if asset is loaded @@ -362,12 +362,12 @@ fn handle_map_handle_spawning( Some(&entity_registry), ); - map_spawn_event.write(SpawnMapEvent { - level: project.level.clone(), - transform: Transform::default(), - tile_size: textures.tile_size, - tileset_textures: Vec::new(), - }); + // map_spawn_event.write(SpawnMapEvent { + // level: project.level.clone(), + // transform: Transform::default(), + // tile_size: textures.tile_size, + // tileset_textures: Vec::new(), + // }); // Add MapRoot marker and make it a child commands.entity(map_entity).insert(MapRoot { From c46da42f5d42f8fd7e2017816f41fe7d065f0a69 Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Thu, 5 Feb 2026 22:01:30 -0800 Subject: [PATCH 19/22] Update lib.rs --- crates/bevy_map_runtime/src/lib.rs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index c03f6bb..34ddce6 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -294,7 +294,7 @@ fn handle_map_handle_spawning( mut query: Query<(Entity, &MapHandle, &mut MapHandleState, Option<&Transform>)>, entity_registry: Res, mut map_dialogues: ResMut, - // mut map_spawn_event: MessageWriter, + mut map_spawn_event: MessageWriter, ) { for (entity, map_handle, mut state, _transform) in query.iter_mut() { // Check if asset is loaded @@ -362,12 +362,7 @@ fn handle_map_handle_spawning( Some(&entity_registry), ); - // map_spawn_event.write(SpawnMapEvent { - // level: project.level.clone(), - // transform: Transform::default(), - // tile_size: textures.tile_size, - // tileset_textures: Vec::new(), - // }); + // Add MapRoot marker and make it a child commands.entity(map_entity).insert(MapRoot { @@ -1127,16 +1122,16 @@ fn handle_spawn_map_project_events( ) { for event in spawn_events.read() { // Load dialogues from the project - map_dialogues.load_from_project(&event.project); - - let map_entity = spawn_map_project( - &mut commands, - &event.project, - &event.textures, - event.transform, - Some(&entity_registry), - ); - spawned_events.write(MapSpawnedEvent { map_entity }); + // map_dialogues.load_from_project(&event.project); + + // let map_entity = spawn_map_project( + // &mut commands, + // &event.project, + // &event.textures, + // event.transform, + // Some(&entity_registry), + // ); + // spawned_events.write(MapSpawnedEvent { map_entity }); } } From 00eeb0a36067f42e6331d3a9b439e6101f5d2b0c Mon Sep 17 00:00:00 2001 From: Elizabeth Suehr Date: Thu, 5 Feb 2026 22:10:23 -0800 Subject: [PATCH 20/22] Update lib.rs --- crates/bevy_map_runtime/src/lib.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index 34ddce6..3793fc5 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -362,7 +362,12 @@ fn handle_map_handle_spawning( Some(&entity_registry), ); - + map_spawn_event.write(SpawnMapEvent { + level: project.level.clone(), + transform: Transform::default(), + tile_size: textures.tile_size, + tileset_textures: Vec::new(), + }); // Add MapRoot marker and make it a child commands.entity(map_entity).insert(MapRoot { @@ -947,15 +952,15 @@ fn handle_spawn_map_events( entity_registry: Res, ) { for event in spawn_events.read() { - let map_entity = spawn_map( - &mut commands, - &event.level, - event.tile_size, - &event.tileset_textures, - event.transform, - Some(&entity_registry), - ); - spawned_events.write(MapSpawnedEvent { map_entity }); + // let map_entity = spawn_map( + // &mut commands, + // &event.level, + // event.tile_size, + // &event.tileset_textures, + // event.transform, + // Some(&entity_registry), + // ); + // spawned_events.write(MapSpawnedEvent { map_entity }); } } From aa7e4b758b94167654293826205ef1b5e0654f1b Mon Sep 17 00:00:00 2001 From: elizabeth-suehr Date: Sun, 8 Feb 2026 18:13:24 -0800 Subject: [PATCH 21/22] Address PR changes --- crates/bevy_map_core/src/entity_type_config.rs | 1 - crates/bevy_map_core/src/level.rs | 3 +++ crates/bevy_map_core/src/physics_layers.rs | 2 +- crates/bevy_map_core/src/tileset.rs | 17 +---------------- crates/bevy_map_editor/src/lib.rs | 2 +- crates/bevy_map_editor/src/render/mod.rs | 8 ++++---- crates/bevy_map_editor/src/ui/tileset_editor.rs | 10 ++-------- crates/bevy_map_runtime/src/lib.rs | 4 ++-- 8 files changed, 14 insertions(+), 33 deletions(-) diff --git a/crates/bevy_map_core/src/entity_type_config.rs b/crates/bevy_map_core/src/entity_type_config.rs index 9ba7d70..b252e95 100644 --- a/crates/bevy_map_core/src/entity_type_config.rs +++ b/crates/bevy_map_core/src/entity_type_config.rs @@ -491,7 +491,6 @@ mod tests { }; let json = serde_json::to_string_pretty(&config).unwrap(); - println!("Serialized config:\n{}", json); let deserialized: EntityTypeConfig = serde_json::from_str(&json).unwrap(); assert!(deserialized.physics.is_some()); diff --git a/crates/bevy_map_core/src/level.rs b/crates/bevy_map_core/src/level.rs index be41955..4fe7e04 100644 --- a/crates/bevy_map_core/src/level.rs +++ b/crates/bevy_map_core/src/level.rs @@ -11,6 +11,7 @@ pub struct Level { pub name: String, pub width: u32, pub height: u32, + pub z_height: f32, pub layers: Vec, pub entities: Vec, /// World X position in pixels (for world view) @@ -32,6 +33,7 @@ impl Level { name, width, height, + z_height: 0.1, // Default z-height layers: Vec::new(), entities: Vec::new(), world_x: 0, @@ -47,6 +49,7 @@ impl Level { name, width, height, + z_height: 0.1, // Default z-height layers: Vec::new(), entities: Vec::new(), world_x, diff --git a/crates/bevy_map_core/src/physics_layers.rs b/crates/bevy_map_core/src/physics_layers.rs index f1fb9a4..5ba4741 100644 --- a/crates/bevy_map_core/src/physics_layers.rs +++ b/crates/bevy_map_core/src/physics_layers.rs @@ -6,7 +6,7 @@ use uuid::Uuid; use crate::{CollisionData, CollisionShape, OneWayDirection}; -/// Configuration for autotiling in a project +/// Holds all physics layers for a tileset, allowing multiple physics configurations per tileset #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct PhysicsLayers { /// All physics layers in the tileset diff --git a/crates/bevy_map_core/src/tileset.rs b/crates/bevy_map_core/src/tileset.rs index c9d2f69..f167206 100644 --- a/crates/bevy_map_core/src/tileset.rs +++ b/crates/bevy_map_core/src/tileset.rs @@ -320,10 +320,6 @@ impl Tileset { ) { if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { physics_layer_set.tile_physics.insert(tile_index, collision); - println!( - "set tile {} collision for physics layer {:?}", - tile_index, physics_layer - ); } } @@ -341,14 +337,7 @@ impl Tileset { CollisionData::none() }; physics_layer_set.tile_physics.insert(tile_index, collision); - - println!( - "set tile {} collision for physics layer {:?}", - tile_index, physics_layer - ); - } else { - println!("Warning: Physics layer {:?} not found", physics_layer); - } + } } /// Set collision shape for a tile (preserving other collision properties) @@ -360,10 +349,6 @@ impl Tileset { ) { if let Some(physics_layer_set) = self.physics_layers.get_physics_layer_mut(physics_layer) { physics_layer_set.set_tile_physics_shape(tile_index, shape); - println!( - "set tile {} collision for physics layer {:?}", - tile_index, physics_layer - ); }; } diff --git a/crates/bevy_map_editor/src/lib.rs b/crates/bevy_map_editor/src/lib.rs index 78fd74b..cfc7360 100644 --- a/crates/bevy_map_editor/src/lib.rs +++ b/crates/bevy_map_editor/src/lib.rs @@ -300,7 +300,7 @@ impl Default for EditorStateConfig { fn default() -> Self { Self { show_grid: true, - show_collisions: true, + show_collisions: false, snap_to_grid: true, initial_zoom: 1.0, initial_tool: EditorTool::Select, diff --git a/crates/bevy_map_editor/src/render/mod.rs b/crates/bevy_map_editor/src/render/mod.rs index 5039401..e98db41 100644 --- a/crates/bevy_map_editor/src/render/mod.rs +++ b/crates/bevy_map_editor/src/render/mod.rs @@ -394,7 +394,7 @@ fn spawn_level_tilemaps( // Z-offset: layer_index * 0.1 + image_index * 0.01 // This ensures proper ordering: all images in layer 0 render before layer 1 - let layer_z = 10.0 * layer_index as f32 + image_index as f32 * 0.01; + let layer_z = level.z_height * layer_index as f32 + image_index as f32 * 0.01; // Insert TilemapBundle first (which includes Visibility internally) // Use BottomLeft anchor so tiles at (0,0) start at world origin @@ -474,7 +474,7 @@ fn spawn_level_tilemaps( let world_y = y as f32 * tile_size_f32 + origin_y as f32; // Z-offset slightly above regular tiles in same layer - let layer_z = layer_index as f32 * 10.0 + image_index as f32 * 0.01 + 0.001; + let layer_z = layer_index as f32 * level.z_height + image_index as f32 * 0.01 + 0.001; let sprite_entity = commands .spawn(( @@ -624,7 +624,7 @@ pub fn update_tile( // World position: place sprite so origin aligns with grid cell corner let world_x = x as f32 * tile_size_f32 + origin_x as f32; let world_y = y as f32 * tile_size_f32 + origin_y as f32; - let layer_z = layer_index as f32 * 10.0 + image_index as f32 * 0.01 + 0.001; + let layer_z = layer_index as f32 * level.z_height + image_index as f32 * 0.01 + 0.001; let sprite_entity = commands .spawn(( @@ -694,7 +694,7 @@ pub fn update_tile( let tile_storage = TileStorage::empty(map_size); let tilemap_entity = commands.spawn_empty().id(); - let layer_z = layer_index as f32 * 10.0 + image_index as f32 * 0.01; + let layer_z = layer_index as f32 * level.z_height + image_index as f32 * 0.01; let layer_visible = layer.visible; commands.entity(tilemap_entity).insert(( diff --git a/crates/bevy_map_editor/src/ui/tileset_editor.rs b/crates/bevy_map_editor/src/ui/tileset_editor.rs index baaa0d8..155cc25 100644 --- a/crates/bevy_map_editor/src/ui/tileset_editor.rs +++ b/crates/bevy_map_editor/src/ui/tileset_editor.rs @@ -2613,14 +2613,8 @@ fn handle_collision_canvas_input( points: polygon_points.clone(), }; if let Some(tileset) = project.tilesets.iter_mut().find(|t| t.id == tileset_id) { - if let Some(physics_layer_id) = editor_state - .tileset_editor_state - .collision_editor - .selected_physics_layer - { - tileset.set_tile_collision_shape(tile_idx, shape, physics_layer_id); - project.mark_dirty(); - } + tileset.set_tile_collision_shape(tile_idx, shape, physics_layer_id); + project.mark_dirty(); } editor_state .tileset_editor_state diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index 3793fc5..ecc800a 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -1041,7 +1041,7 @@ pub fn spawn_map( let map_type = TilemapType::Square; // Calculate layer z-offset based on layer index - let layer_z = layer_index as f32 * 10.0; + let layer_z = layer_index as f32 * level.z_height; commands.entity(tilemap_entity).insert(( TilemapBundle { @@ -1293,7 +1293,7 @@ pub fn spawn_map_project( // Z-offset: layer_index * 0.1 + image_index * 0.01 // This ensures proper ordering: all images in layer 0 render before layer 1 - let layer_z = layer_index as f32 * 10.0 + image_index as f32 * 0.01; + let layer_z = layer_index as f32 * level.z_height + image_index as f32 * 0.01; commands.entity(tilemap_entity).insert(( TilemapBundle { From de721c4fa2e6da55ca78c32c9e9f1d66cb2bd5fe Mon Sep 17 00:00:00 2001 From: elizabeth-suehr Date: Sun, 8 Feb 2026 18:15:15 -0800 Subject: [PATCH 22/22] cargo fmt and clippy fix --- crates/bevy_map_core/src/level.rs | 4 ++-- crates/bevy_map_core/src/tileset.rs | 2 +- crates/bevy_map_editor/src/render/mod.rs | 6 ++++-- crates/bevy_map_runtime/src/lib.rs | 20 +++++++++----------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/bevy_map_core/src/level.rs b/crates/bevy_map_core/src/level.rs index 4fe7e04..d3a119b 100644 --- a/crates/bevy_map_core/src/level.rs +++ b/crates/bevy_map_core/src/level.rs @@ -33,7 +33,7 @@ impl Level { name, width, height, - z_height: 0.1, // Default z-height + z_height: 0.1, // Default z-height layers: Vec::new(), entities: Vec::new(), world_x: 0, @@ -49,7 +49,7 @@ impl Level { name, width, height, - z_height: 0.1, // Default z-height + z_height: 0.1, // Default z-height layers: Vec::new(), entities: Vec::new(), world_x, diff --git a/crates/bevy_map_core/src/tileset.rs b/crates/bevy_map_core/src/tileset.rs index f167206..49540e4 100644 --- a/crates/bevy_map_core/src/tileset.rs +++ b/crates/bevy_map_core/src/tileset.rs @@ -337,7 +337,7 @@ impl Tileset { CollisionData::none() }; physics_layer_set.tile_physics.insert(tile_index, collision); - } + } } /// Set collision shape for a tile (preserving other collision properties) diff --git a/crates/bevy_map_editor/src/render/mod.rs b/crates/bevy_map_editor/src/render/mod.rs index e98db41..ef64cf6 100644 --- a/crates/bevy_map_editor/src/render/mod.rs +++ b/crates/bevy_map_editor/src/render/mod.rs @@ -624,7 +624,8 @@ pub fn update_tile( // World position: place sprite so origin aligns with grid cell corner let world_x = x as f32 * tile_size_f32 + origin_x as f32; let world_y = y as f32 * tile_size_f32 + origin_y as f32; - let layer_z = layer_index as f32 * level.z_height + image_index as f32 * 0.01 + 0.001; + let layer_z = + layer_index as f32 * level.z_height + image_index as f32 * 0.01 + 0.001; let sprite_entity = commands .spawn(( @@ -694,7 +695,8 @@ pub fn update_tile( let tile_storage = TileStorage::empty(map_size); let tilemap_entity = commands.spawn_empty().id(); - let layer_z = layer_index as f32 * level.z_height + image_index as f32 * 0.01; + let layer_z = + layer_index as f32 * level.z_height + image_index as f32 * 0.01; let layer_visible = layer.visible; commands.entity(tilemap_entity).insert(( diff --git a/crates/bevy_map_runtime/src/lib.rs b/crates/bevy_map_runtime/src/lib.rs index ecc800a..cf09e63 100644 --- a/crates/bevy_map_runtime/src/lib.rs +++ b/crates/bevy_map_runtime/src/lib.rs @@ -66,8 +66,6 @@ use bevy::asset::AssetEvent; use bevy::ecs::message::{Message, MessageReader, MessageWriter}; -use bevy::ecs::query::Spawned; -use bevy::ecs::spawn; use bevy::prelude::*; use bevy_ecs_tilemap::prelude::*; use bevy_map_core::MapProject; @@ -946,12 +944,12 @@ pub struct RuntimeMap { pub struct MapLayerIndex(pub usize); fn handle_spawn_map_events( - mut commands: Commands, + _commands: Commands, mut spawn_events: MessageReader, - mut spawned_events: MessageWriter, - entity_registry: Res, + _spawned_events: MessageWriter, + _entity_registry: Res, ) { - for event in spawn_events.read() { + for _event in spawn_events.read() { // let map_entity = spawn_map( // &mut commands, // &event.level, @@ -1119,13 +1117,13 @@ pub struct SpawnMapProjectEvent { } fn handle_spawn_map_project_events( - mut commands: Commands, + _commands: Commands, mut spawn_events: MessageReader, - mut spawned_events: MessageWriter, - entity_registry: Res, - mut map_dialogues: ResMut, + _spawned_events: MessageWriter, + _entity_registry: Res, + _map_dialogues: ResMut, ) { - for event in spawn_events.read() { + for _event in spawn_events.read() { // Load dialogues from the project // map_dialogues.load_from_project(&event.project);