169 lines
7.0 KiB
Rust
169 lines
7.0 KiB
Rust
use core::fmt;
|
|
use std::rc::Rc;
|
|
|
|
use bevy::{
|
|
prelude::{Camera, Commands, Component, Entity, GlobalTransform, Query, ResMut, Transform},
|
|
render::camera::Projection,
|
|
};
|
|
use bevy_egui::EguiContext;
|
|
use block_mesh::Voxel;
|
|
use common::space::{
|
|
level_tile::LevelTile,
|
|
three_dimensional::{
|
|
hash_map_container::VoxelHashMapLayer,
|
|
traits::{DefaultVoxel, VoxelContainer},
|
|
},
|
|
two_dimensional::depth_tiles::Direction,
|
|
};
|
|
use egui::{mutex::Mutex, Button, CollapsingHeader, Ui};
|
|
|
|
use smooth_bevy_cameras::LookTransform;
|
|
use common::strum::IntoEnumIterator;
|
|
|
|
use crate::{
|
|
components::{mutable_mesh::MutableMesh, named::Named, property_pane::PropertyPane},
|
|
systems::{layer_spawner::{LayerSpawnerCommand}, generic_command_queue::CommandQueue},
|
|
voxels::layers::traits::VoxelLayer,
|
|
};
|
|
|
|
use super::util::{bevy_quat_controls, bevy_vec3_controls};
|
|
|
|
pub fn properties_ui(
|
|
commands: Commands,
|
|
layer_spawner_commands: ResMut<CommandQueue<LayerSpawnerCommand>>,
|
|
mut egui_context: ResMut<EguiContext>,
|
|
mut property_pane_query: Query<(&mut PropertyPane, Entity)>,
|
|
mut camera_query: Query<(&mut Camera, &mut Projection, &mut LookTransform)>,
|
|
mut transform_query: Query<(&mut Transform, &mut GlobalTransform)>,
|
|
mut tile_hashmap_layer_query: Query<(
|
|
&mut VoxelHashMapLayer<LevelTile>,
|
|
&mut Named,
|
|
&mut MutableMesh,
|
|
)>,
|
|
) {
|
|
// in case we want to send commands from multiple places in the ui
|
|
let _commands = Rc::new(Mutex::new(commands));
|
|
let layer_spawner_commands = Rc::new(Mutex::new(layer_spawner_commands));
|
|
|
|
for (mut property_pane, entity) in property_pane_query.iter_mut() {
|
|
egui::Window::new(&property_pane.title)
|
|
.open(&mut property_pane.is_open)
|
|
.min_width(400.0)
|
|
.resizable(true)
|
|
.vscroll(true)
|
|
.show(egui_context.ctx_mut(), |ui| {
|
|
voxel_layer_properties(
|
|
layer_spawner_commands.clone(),
|
|
ui,
|
|
entity,
|
|
&mut tile_hashmap_layer_query,
|
|
);
|
|
if let Ok((_camera, projection, mut look_transform)) = camera_query.get_mut(entity)
|
|
{
|
|
let _heading =
|
|
CollapsingHeader::new("Camera")
|
|
.default_open(true)
|
|
.show(ui, |ui| {
|
|
match projection.into_inner() {
|
|
Projection::Perspective(_perspective) => {}
|
|
Projection::Orthographic(orthographic) => {
|
|
ui.add(
|
|
egui::DragValue::new(&mut orthographic.scale)
|
|
.speed(1)
|
|
.prefix("orthographic scale:"),
|
|
);
|
|
}
|
|
}
|
|
ui.add(
|
|
egui::DragValue::new(&mut look_transform.eye.x)
|
|
.speed(0.2)
|
|
.prefix("eye x:"),
|
|
);
|
|
ui.add(
|
|
egui::DragValue::new(&mut look_transform.eye.y)
|
|
.speed(0.2)
|
|
.prefix("eye y:"),
|
|
);
|
|
ui.add(
|
|
egui::DragValue::new(&mut look_transform.eye.z)
|
|
.speed(0.2)
|
|
.prefix("eye z:"),
|
|
);
|
|
});
|
|
}
|
|
if let Ok((mut transform, global_transform)) = transform_query.get_mut(entity) {
|
|
let _heading =
|
|
CollapsingHeader::new("Transform")
|
|
.default_open(true)
|
|
.show(ui, |ui| {
|
|
bevy_vec3_controls(ui, &mut transform.translation, "pos");
|
|
bevy_quat_controls(ui, &mut transform.rotation, "rot");
|
|
bevy_vec3_controls(ui, &mut transform.scale, "scale");
|
|
});
|
|
let _heading = CollapsingHeader::new("GlobalTransform")
|
|
.default_open(true)
|
|
.show(ui, |ui| {
|
|
let (mut scale, mut rotation, mut translation) =
|
|
global_transform.to_scale_rotation_translation();
|
|
bevy_vec3_controls(ui, &mut translation, "pos");
|
|
bevy_quat_controls(ui, &mut rotation, "rot");
|
|
bevy_vec3_controls(ui, &mut scale, "scale");
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
fn voxel_layer_properties<TLayer, TVoxel>(
|
|
layer_spawner_commands: Rc<Mutex<ResMut<CommandQueue<LayerSpawnerCommand>>>>,
|
|
ui: &mut Ui,
|
|
entity: Entity,
|
|
layer_query: &mut Query<(&mut TLayer, &mut Named, &mut MutableMesh)>,
|
|
) where
|
|
TLayer: VoxelLayer<TVoxel> + VoxelContainer<TVoxel> + Component,
|
|
TVoxel: Voxel + DefaultVoxel + Copy + Send + Sync + fmt::Debug,
|
|
{
|
|
if let Ok((layer, named, _mutable_mesh)) = layer_query.get_mut(entity) {
|
|
let _layer = layer.into_inner();
|
|
CollapsingHeader::new("Generic Voxel Layer")
|
|
.default_open(true)
|
|
.show(ui, |ui| {
|
|
ui.horizontal(|ui| {
|
|
for dir in Direction::iter() {
|
|
if ui.add(Button::new(format!("project {:?}", dir))).clicked() {
|
|
layer_spawner_commands.lock().add(
|
|
LayerSpawnerCommand::FromTileProjectedLayer {
|
|
name: format!("{} - {:?} proj", named.name, dir),
|
|
source_layer: entity,
|
|
direction: dir,
|
|
},
|
|
)
|
|
};
|
|
}
|
|
});
|
|
|
|
ui.separator();
|
|
|
|
if ui.button("Export projected tiles").clicked() {
|
|
layer_spawner_commands.lock().add(
|
|
LayerSpawnerCommand::ExportProjectedTilesToml { name: named.name.to_string(), source_layer: entity }
|
|
);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
pub fn clean_up_closed_panes(
|
|
mut commands: Commands,
|
|
mut property_pane_query: Query<(&mut PropertyPane, Entity)>,
|
|
) {
|
|
for (mut pane, entity) in property_pane_query.iter_mut() {
|
|
if pane.closable && !pane.is_open {
|
|
commands.entity(entity).remove::<PropertyPane>();
|
|
} else if !pane.closable && !pane.is_open {
|
|
// reopen it. don't allow closing this one
|
|
pane.is_open = true;
|
|
}
|
|
}
|
|
}
|