This commit is contained in:
rewin
2024-02-19 20:39:03 +03:00
parent c104e01adc
commit a5ffacdf2c
4 changed files with 264 additions and 221 deletions
+1 -3
View File
@@ -6,9 +6,7 @@ use wasm_bindgen::prelude::*;
pub struct BlockingPlugin; pub struct BlockingPlugin;
impl Plugin for BlockingPlugin { impl Plugin for BlockingPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {}
}
} }
#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = test_blocking))] #[cfg_attr(feature = "wasm", wasm_bindgen(js_name = test_blocking))]
+1 -1
View File
@@ -8,6 +8,7 @@ use bevy_web_asset::WebAssetPlugin;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
mod anim; mod anim;
pub mod blocking;
mod bvh; mod bvh;
mod camera_controller; mod camera_controller;
mod debug; mod debug;
@@ -23,7 +24,6 @@ mod scene;
mod skybox; mod skybox;
mod ui; mod ui;
pub mod viewport; pub mod viewport;
pub mod blocking;
mod world_grid; mod world_grid;
+84 -48
View File
@@ -1,63 +1,93 @@
use std::{any::Any, sync::{Arc, Mutex, RwLock}, thread::yield_now}; use std::{
any::Any,
sync::{Arc, Mutex, RwLock},
thread::yield_now,
};
use bevy::{ecs::{component::ComponentId, world::unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell}}, prelude::*, reflect::{ReflectFromPtr, TypeData}, utils::{hashbrown::HashMap, tracing::field}, window::PrimaryWindow}; use bevy::{
ecs::{
component::ComponentId,
world::unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell},
},
prelude::*,
reflect::{ReflectFromPtr, TypeData},
utils::{hashbrown::HashMap, tracing::field},
window::PrimaryWindow,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use space_editor::{prelude::Selected, space_editor_ui::inspector::inspect}; use space_editor::{prelude::Selected, space_editor_ui::inspector::inspect};
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
use web_sys::HtmlElement; use web_sys::HtmlElement;
use crate::{ui::inspector::wasm::notify_dom_changed, wasm::{StaticBuffer, WasmMessageBuffer}}; use crate::{
ui::inspector::wasm::notify_dom_changed,
wasm::{StaticBuffer, WasmMessageBuffer},
};
use super::utils::{show_reflect, ComponentProp, Element, InspectedEntity, ReflectChange, VComponent, VNode, VirtualDom}; use super::utils::{
show_reflect, ComponentProp, Element, InspectedEntity, ReflectChange, VComponent, VNode,
VirtualDom,
};
pub struct InspectorPlugin; pub struct InspectorPlugin;
impl Plugin for InspectorPlugin { impl Plugin for InspectorPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.init_resource::<InspectorFunctions>(); app.init_resource::<InspectorFunctions>();
app.add_systems(Update, show_selected); app.add_systems(Update, show_selected);
app.world.resource_mut::<InspectorFunctions>().add_simple::<Name>(); app.world
app.world.resource_mut::<InspectorFunctions>().add_simple::<Transform>(); .resource_mut::<InspectorFunctions>()
.add_simple::<Name>();
app.world
.resource_mut::<InspectorFunctions>()
.add_simple::<Transform>();
} }
} }
#[derive(Resource, Default)] #[derive(Resource, Default)]
struct InspectorFunctions { struct InspectorFunctions {
get_reflects: Vec<Box<dyn FnMut(&UnsafeEntityCell<'_>) -> Option<Box<dyn Reflect>> + Send + Sync>> get_reflects:
Vec<Box<dyn FnMut(&UnsafeEntityCell<'_>) -> Option<Box<dyn Reflect>> + Send + Sync>>,
} }
impl InspectorFunctions { impl InspectorFunctions {
fn add_getter<F: FnMut(&UnsafeEntityCell<'_>) -> Option<Box<dyn Reflect>> + Send + Sync + 'static>(&mut self, f: F) { fn add_getter<
F: FnMut(&UnsafeEntityCell<'_>) -> Option<Box<dyn Reflect>> + Send + Sync + 'static,
>(
&mut self,
f: F,
) {
self.get_reflects.push(Box::new(f)); self.get_reflects.push(Box::new(f));
} }
fn add_simple<T>(&mut self) where T: bevy::prelude::Component + Reflect + FromReflect + 'static { fn add_simple<T>(&mut self)
where
T: bevy::prelude::Component + Reflect + FromReflect + 'static,
{
unsafe { unsafe {
self.add_getter( self.add_getter(|cell| {
|cell| { if let Some(val) = cell.get::<T>() {
if let Some(val) = cell.get::<T>() { Some(Box::new(<T as FromReflect>::from_reflect(val).unwrap())
Some(Box::new(<T as FromReflect>::from_reflect(val).unwrap()) as Box<dyn Reflect>) as Box<dyn Reflect>)
} else { } else {
None None
}
} }
) })
} }
} }
fn get_reflect_copy(&mut self, cell: &UnsafeEntityCell<'_>) -> Vec<Box<dyn Reflect>> { fn get_reflect_copy(&mut self, cell: &UnsafeEntityCell<'_>) -> Vec<Box<dyn Reflect>> {
self.get_reflects.iter_mut().map(|f| (*f)(cell)).flatten().collect() self.get_reflects
.iter_mut()
.map(|f| (*f)(cell))
.flatten()
.collect()
} }
} }
fn show_selected(world: &mut World) {
fn show_selected(
world: &mut World
) {
if !world.is_resource_added::<VirtualDom>() { if !world.is_resource_added::<VirtualDom>() {
world.init_resource::<VirtualDom>(); world.init_resource::<VirtualDom>();
} }
@@ -66,11 +96,11 @@ fn show_selected(
let mut virtial_dom = cell.get_resource_mut::<VirtualDom>().unwrap(); let mut virtial_dom = cell.get_resource_mut::<VirtualDom>().unwrap();
let Some(selection) = cell.get_resource::<crate::interaction::Selection>() else { let Some(selection) = cell.get_resource::<crate::interaction::Selection>() else {
let muts = virtial_dom.render(None); let muts = virtial_dom.render(None);
let q_window = cell.world_mut().query_filtered::<&Window, With<PrimaryWindow>>().single(cell.world()); let q_window = cell
.world_mut()
.query_filtered::<&Window, With<PrimaryWindow>>()
.single(cell.world());
let _ = notify_dom_changed(q_window, serde_json::to_string(&muts).unwrap()); let _ = notify_dom_changed(q_window, serde_json::to_string(&muts).unwrap());
return; return;
@@ -86,11 +116,12 @@ fn show_selected(
if let Some(changes) = super::utils::wasm::ONCHAGE_BUFFER.take_message() { if let Some(changes) = super::utils::wasm::ONCHAGE_BUFFER.take_message() {
for (id, value) in changes { for (id, value) in changes {
info!("change: {} : {}", id, value); info!("change: {} : {}", id, value);
virtial_dom.on_change_events.execute(cell.world_mut(), id, value); virtial_dom
.on_change_events
.execute(cell.world_mut(), id, value);
} }
} }
let mut inspected = InspectedEntity::none(); let mut inspected = InspectedEntity::none();
inspected.id = Some(e.id()); inspected.id = Some(e.id());
inspected.components = functions.get_reflect_copy(&e); inspected.components = functions.get_reflect_copy(&e);
@@ -101,17 +132,29 @@ fn show_selected(
let element = Element::Component(super::utils::Component { let element = Element::Component(super::utils::Component {
tag: "div".to_string(), tag: "div".to_string(),
attributes: vec![ attributes: vec![
("style".to_string(), "display: flex; flex-direction: column; height: 100%; overflow: auto;".to_string()), (
("class".to_string(), "inspector".to_string()) "style".to_string(),
"display: flex; flex-direction: column; height: 100%; overflow: auto;"
.to_string(),
),
("class".to_string(), "inspector".to_string()),
], ],
children: inspected.components.into_iter().map(|c| { children: inspected
.components
.into_iter()
.map(|c| {
show_reflect( show_reflect(
c.as_ref(), c.as_ref(),
ReflectChange { ReflectChange {
entity_id: id, entity_id: id,
reflect_path: "".to_string(), reflect_path: "".to_string(),
compoent_id: format!("{:?}", components.get_id(c.get_represented_type_info().unwrap().type_id()).unwrap()), compoent_id: format!(
} "{:?}",
components
.get_id(c.get_represented_type_info().unwrap().type_id())
.unwrap()
),
},
) )
}) })
.filter_map(|v| v) .filter_map(|v| v)
@@ -121,22 +164,21 @@ fn show_selected(
let muts = virtial_dom.render(Some(element)); let muts = virtial_dom.render(Some(element));
let q_window = cell
let q_window = cell.world_mut().query_filtered::<&Window, With<PrimaryWindow>>().single(cell.world()); .world_mut()
.query_filtered::<&Window, With<PrimaryWindow>>()
.single(cell.world());
let _ = notify_dom_changed(q_window, serde_json::to_string(&muts).unwrap()); let _ = notify_dom_changed(q_window, serde_json::to_string(&muts).unwrap());
} }
} }
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
mod wasm { mod wasm {
use crate::wasm::*;
use bevy::{prelude::*, window::PrimaryWindow}; use bevy::{prelude::*, window::PrimaryWindow};
use serde_json::json; use serde_json::json;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use crate::wasm::*;
use super::*; use super::*;
@@ -158,13 +200,7 @@ declare global {
} }
"#; "#;
pub(super) fn notify_dom_changed( pub(super) fn notify_dom_changed(q_window: &Window, msg: String) -> Result<(), String> {
q_window: &Window,
msg : String,
) -> Result<(), String> {
wasm::dispatch_to_js(q_window, "inspector-dom-changed", &msg) wasm::dispatch_to_js(q_window, "inspector-dom-changed", &msg)
} }
} }
+169 -160
View File
@@ -1,32 +1,33 @@
use std::any::Any; use std::any::Any;
use ::serde::{Deserialize, Serialize};
use bevy::{ecs::component::ComponentId, prelude::*, reflect::ReflectFromPtr, utils::HashMap}; use bevy::{ecs::component::ComponentId, prelude::*, reflect::ReflectFromPtr, utils::HashMap};
use ::serde::{Serialize, Deserialize};
use uuid::*; use uuid::*;
trait NodeProp : Clone + PartialEq { trait NodeProp: Clone + PartialEq {}
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub enum Mutation { pub enum Mutation {
SetAttibute{id : String, attribute : String, value : String}, SetAttibute {
id: String,
attribute: String,
value: String,
},
ReplaceAll(VNode), ReplaceAll(VNode),
RemoveAll RemoveAll,
} }
#[derive(Default)] #[derive(Default)]
pub struct Component { pub struct Component {
pub tag : String, pub tag: String,
pub attributes : Vec<(String, String)>, pub attributes: Vec<(String, String)>,
pub children : Vec<Element>, pub children: Vec<Element>,
pub onchange: Option<Box<dyn WebEventExecutor + Send + Sync>> pub onchange: Option<Box<dyn WebEventExecutor + Send + Sync>>,
} }
pub enum Element { pub enum Element {
Text(String), Text(String),
Component(Component) Component(Component),
} }
pub trait WebEventExecutor { pub trait WebEventExecutor {
@@ -35,15 +36,15 @@ pub trait WebEventExecutor {
#[derive(Default)] #[derive(Default)]
pub struct WebEventStorage { pub struct WebEventStorage {
pub events : HashMap<String, Box<dyn WebEventExecutor + Send + Sync>>, pub events: HashMap<String, Box<dyn WebEventExecutor + Send + Sync>>,
} }
impl WebEventStorage { impl WebEventStorage {
pub fn add_event(&mut self, id : String, event : Box<dyn WebEventExecutor + Send + Sync>) { pub fn add_event(&mut self, id: String, event: Box<dyn WebEventExecutor + Send + Sync>) {
self.events.insert(id, event); self.events.insert(id, event);
} }
pub fn execute(&mut self, world: &mut World, id : String, data : String) { pub fn execute(&mut self, world: &mut World, id: String, data: String) {
if let Some(event) = self.events.get_mut(&id) { if let Some(event) = self.events.get_mut(&id) {
event.execute(world, data); event.execute(world, data);
} else { } else {
@@ -54,12 +55,11 @@ impl WebEventStorage {
#[derive(Default, Resource)] #[derive(Default, Resource)]
pub struct VirtualDom { pub struct VirtualDom {
last_node : Option<VNode>, last_node: Option<VNode>,
pub on_change_events: WebEventStorage, pub on_change_events: WebEventStorage,
} }
impl VirtualDom { impl VirtualDom {
pub fn render(&mut self, element: Option<Element>) -> Vec<Mutation> { pub fn render(&mut self, element: Option<Element>) -> Vec<Mutation> {
let mut id_counter = 0; let mut id_counter = 0;
@@ -71,11 +71,10 @@ impl VirtualDom {
} }
} }
fn recursive_unpack_element(&mut self, counter : &mut usize, element : Element) -> VNode { fn recursive_unpack_element(&mut self, counter: &mut usize, element: Element) -> VNode {
match element { match element {
Element::Text(text) => VNode::Text(text), Element::Text(text) => VNode::Text(text),
Element::Component(component) => { Element::Component(component) => {
let id = format!("node_{}", *counter); let id = format!("node_{}", *counter);
*counter += 1; *counter += 1;
@@ -90,20 +89,22 @@ impl VirtualDom {
attributes: component.attributes.into_iter().collect(), attributes: component.attributes.into_iter().collect(),
id: Some(id), id: Some(id),
onchange: onchange_enabled, onchange: onchange_enabled,
children: component.children.into_iter().map(|e| self.recursive_unpack_element(counter, e)).collect() children: component
.children
.into_iter()
.map(|e| self.recursive_unpack_element(counter, e))
.collect(),
}) })
}, }
} }
} }
pub fn create_mutations(&mut self, node : VNode) -> Vec<Mutation> { pub fn create_mutations(&mut self, node: VNode) -> Vec<Mutation> {
if self.last_node == Some(node.clone()) { if self.last_node == Some(node.clone()) {
return vec![] return vec![];
} else { } else {
if let Some(last_node) = &self.last_node { if let Some(last_node) = &self.last_node {
if last_node.is_same_structure(&node) { if last_node.is_same_structure(&node) {
let muts = node.get_same_structure_muts(&last_node); let muts = node.get_same_structure_muts(&last_node);
self.last_node = Some(node.clone()); self.last_node = Some(node.clone());
return muts; return muts;
@@ -111,7 +112,7 @@ impl VirtualDom {
} }
self.last_node = Some(node.clone()); self.last_node = Some(node.clone());
return vec![Mutation::ReplaceAll(node)] return vec![Mutation::ReplaceAll(node)];
} }
} }
} }
@@ -125,7 +126,7 @@ pub mod wasm {
pub static ONCHAGE_BUFFER: WasmMessageBuffer<Vec<(String, String)>> = WasmMessageBuffer::new(); pub static ONCHAGE_BUFFER: WasmMessageBuffer<Vec<(String, String)>> = WasmMessageBuffer::new();
#[wasm_bindgen(js_name = register_new_change)] #[wasm_bindgen(js_name = register_new_change)]
pub fn register_new_change(id : String, value : String) { pub fn register_new_change(id: String, value: String) {
let mut data = ONCHAGE_BUFFER.take_message().unwrap_or_default(); let mut data = ONCHAGE_BUFFER.take_message().unwrap_or_default();
data.push((id, value)); data.push((id, value));
ONCHAGE_BUFFER.write_message(data); ONCHAGE_BUFFER.write_message(data);
@@ -133,11 +134,11 @@ pub mod wasm {
} }
struct ReflectValueExecutor { struct ReflectValueExecutor {
change : ReflectChange change: ReflectChange,
} }
impl From<ReflectChange> for ReflectValueExecutor { impl From<ReflectChange> for ReflectValueExecutor {
fn from(change : ReflectChange) -> Self { fn from(change: ReflectChange) -> Self {
ReflectValueExecutor { change } ReflectValueExecutor { change }
} }
} }
@@ -146,18 +147,33 @@ impl WebEventExecutor for ReflectValueExecutor {
fn execute(&mut self, world: &mut World, value: String) { fn execute(&mut self, world: &mut World, value: String) {
unsafe { unsafe {
let world = world.as_unsafe_world_cell(); let world = world.as_unsafe_world_cell();
let app_type_registry: &AppTypeRegistry = world.get_resource::<AppTypeRegistry>().unwrap(); let app_type_registry: &AppTypeRegistry =
world.get_resource::<AppTypeRegistry>().unwrap();
let type_registry = app_type_registry.read(); let type_registry = app_type_registry.read();
let mut e = world.get_entity(self.change.entity_id).unwrap(); let mut e = world.get_entity(self.change.entity_id).unwrap();
let c_id = ComponentId::new( let c_id = ComponentId::new(
self.change.compoent_id.split('(').nth(1).unwrap().split(')').next().unwrap().parse().unwrap() self.change
.compoent_id
.split('(')
.nth(1)
.unwrap()
.split(')')
.next()
.unwrap()
.parse()
.unwrap(),
); );
if let Some(mut c) = e.get_mut_by_id(c_id) { if let Some(mut c) = e.get_mut_by_id(c_id) {
let mut refl = type_registry
let mut refl = type_registry.get_type_data::<ReflectFromPtr>(world.components().get_info_unchecked(c_id).type_id().unwrap()) .get_type_data::<ReflectFromPtr>(
world
.components()
.get_info_unchecked(c_id)
.type_id()
.unwrap(),
)
.unwrap() .unwrap()
.as_reflect_mut(c.as_mut()); .as_reflect_mut(c.as_mut());
@@ -200,8 +216,8 @@ impl WebEventExecutor for ReflectValueExecutor {
} }
struct EntityChangeExecutor { struct EntityChangeExecutor {
entity : Entity, entity: Entity,
func : Box<dyn Fn(&mut World, Entity, String) + Send + Sync>, func: Box<dyn Fn(&mut World, Entity, String) + Send + Sync>,
} }
impl WebEventExecutor for EntityChangeExecutor { impl WebEventExecutor for EntityChangeExecutor {
@@ -211,50 +227,58 @@ impl WebEventExecutor for EntityChangeExecutor {
} }
impl EntityChangeExecutor { impl EntityChangeExecutor {
fn new(entity : Entity, func : impl Fn(&mut World, Entity, String) + Send + Sync + 'static) -> Self { fn new(
EntityChangeExecutor { entity, func : Box::new(func) } entity: Entity,
func: impl Fn(&mut World, Entity, String) + Send + Sync + 'static,
) -> Self {
EntityChangeExecutor {
entity,
func: Box::new(func),
}
} }
fn new_boxed(entity : Entity, func : impl Fn(&mut World, Entity, String) + Send + Sync + 'static) -> Box<Self> { fn new_boxed(
entity: Entity,
func: impl Fn(&mut World, Entity, String) + Send + Sync + 'static,
) -> Box<Self> {
Box::new(EntityChangeExecutor::new(entity, func)) Box::new(EntityChangeExecutor::new(entity, func))
} }
} }
fn euler_to_degrees(euler : (f32, f32, f32)) -> (f32, f32, f32) { fn euler_to_degrees(euler: (f32, f32, f32)) -> (f32, f32, f32) {
( (
euler.0.to_degrees(), euler.0.to_degrees(),
euler.1.to_degrees(), euler.1.to_degrees(),
euler.2.to_degrees() euler.2.to_degrees(),
) )
} }
fn degrees_to_euler(degrees : (f32, f32, f32)) -> (f32, f32, f32) { fn degrees_to_euler(degrees: (f32, f32, f32)) -> (f32, f32, f32) {
( (
degrees.0.to_radians(), degrees.0.to_radians(),
degrees.1.to_radians(), degrees.1.to_radians(),
degrees.2.to_radians() degrees.2.to_radians(),
) )
} }
fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option<Element> { fn check_predefined(r: &dyn Reflect, onchange: ReflectChange) -> Option<Element> {
if let Some(name) = r.downcast_ref::<Name>() { if let Some(name) = r.downcast_ref::<Name>() {
Some(Element::Component(Component { Some(Element::Component(Component {
tag: "div".to_string(), tag: "div".to_string(),
attributes: vec![ attributes: vec![(
("style".to_string(), "font-weight: bold; font-size: 24px".to_string()), "style".to_string(),
], "font-weight: bold; font-size: 24px".to_string(),
children: vec![ )],
Element::Text(format!("{}", &name)), children: vec![Element::Text(format!("{}", &name))],
], onchange: None,
onchange: None
})) }))
} else if let Some(transform) = r.downcast_ref::<Transform>() { } else if let Some(transform) = r.downcast_ref::<Transform>() {
Some(Element::Component(Component { Some(Element::Component(Component {
tag: "div".to_string(), tag: "div".to_string(),
attributes: vec![ attributes: vec![(
("style".to_string(), "display: flex; flex-direction: column".to_string()), "style".to_string(),
], "display: flex; flex-direction: column".to_string(),
)],
children: vec![ children: vec![
Element::Text("Pos: ".to_string()), Element::Text("Pos: ".to_string()),
show_reflect(&transform.translation, onchange.add_path("translation")).unwrap(), show_reflect(&transform.translation, onchange.add_path("translation")).unwrap(),
@@ -263,31 +287,33 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option<Elemen
Element::Text("Scale: ".to_string()), Element::Text("Scale: ".to_string()),
show_reflect(&transform.scale, onchange.add_path("scale")).unwrap(), show_reflect(&transform.scale, onchange.add_path("scale")).unwrap(),
], ],
onchange: None onchange: None,
})) }))
} else if let Some(quat) = r.downcast_ref::<Quat>() { } else if let Some(quat) = r.downcast_ref::<Quat>() {
let euler = quat.to_euler(EulerRot::XYZ); let euler = quat.to_euler(EulerRot::XYZ);
let degrees = euler_to_degrees(euler); let degrees = euler_to_degrees(euler);
Some(Element::Component(Component { Some(Element::Component(Component {
tag: "div".to_string(), tag: "div".to_string(),
attributes: vec![ attributes: vec![("class".to_string(), "struct-grid".to_string())],
("class".to_string(), "struct-grid".to_string()),
],
children: vec![ children: vec![
Element::Text("X: ".to_string()), Element::Text("X: ".to_string()),
Element::Component(Component { Element::Component(Component {
tag: "input".to_string(), tag: "input".to_string(),
attributes: vec![ attributes: vec![
("type".to_string(), "number".to_string()), ("type".to_string(), "number".to_string()),
("value".to_string(), format!("{:.2}",degrees.0)), ("value".to_string(), format!("{:.2}", degrees.0)),
("step".to_string(), "0.01".to_string()), ("step".to_string(), "0.01".to_string()),
], ],
children: vec![], children: vec![],
onchange: Some(EntityChangeExecutor::new_boxed( onchange: Some(EntityChangeExecutor::new_boxed(
onchange.entity_id, onchange.entity_id,
|world : &mut World, entity, value : String| { |world: &mut World, entity, value: String| {
let Some(mut value) = value.parse::<f32>().ok() else { return; }; let Some(mut value) = value.parse::<f32>().ok() else {
if value == -180.0 { value = 180.0; } return;
};
if value == -180.0 {
value = 180.0;
}
let value = value.to_radians(); let value = value.to_radians();
let mut e = world.get_entity_mut(entity).unwrap(); let mut e = world.get_entity_mut(entity).unwrap();
@@ -296,24 +322,29 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option<Elemen
return; return;
} }
let euler = transform.rotation.to_euler(EulerRot::XYZ); let euler = transform.rotation.to_euler(EulerRot::XYZ);
transform.rotation = Quat::from_euler(EulerRot::XYZ, value, euler.1, euler.2); transform.rotation =
} Quat::from_euler(EulerRot::XYZ, value, euler.1, euler.2);
)) },
)),
}), }),
Element::Text("Y: ".to_string()), Element::Text("Y: ".to_string()),
Element::Component(Component { Element::Component(Component {
tag: "input".to_string(), tag: "input".to_string(),
attributes: vec![ attributes: vec![
("type".to_string(), "number".to_string()), ("type".to_string(), "number".to_string()),
("value".to_string(), format!("{:.2}",degrees.1)), ("value".to_string(), format!("{:.2}", degrees.1)),
("step".to_string(), "0.01".to_string()), ("step".to_string(), "0.01".to_string()),
], ],
children: vec![], children: vec![],
onchange: Some(EntityChangeExecutor::new_boxed( onchange: Some(EntityChangeExecutor::new_boxed(
onchange.entity_id, onchange.entity_id,
|world : &mut World, entity, value : String| { |world: &mut World, entity, value: String| {
let Some(mut value) = value.parse::<f32>().ok() else { return; }; let Some(mut value) = value.parse::<f32>().ok() else {
if value == -180.0 { value = 180.0; } return;
};
if value == -180.0 {
value = 180.0;
}
let mut e = world.get_entity_mut(entity).unwrap(); let mut e = world.get_entity_mut(entity).unwrap();
let mut transform = e.get_mut::<Transform>().unwrap(); let mut transform = e.get_mut::<Transform>().unwrap();
if transform.is_changed() { if transform.is_changed() {
@@ -321,24 +352,29 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option<Elemen
} }
let value = value.to_radians(); let value = value.to_radians();
let euler = transform.rotation.to_euler(EulerRot::XYZ); let euler = transform.rotation.to_euler(EulerRot::XYZ);
transform.rotation = transform.rotation * Quat::from_axis_angle(Vec3::Y, value - euler.1); transform.rotation = transform.rotation
} * Quat::from_axis_angle(Vec3::Y, value - euler.1);
)) },
)),
}), }),
Element::Text("Z: ".to_string()), Element::Text("Z: ".to_string()),
Element::Component(Component { Element::Component(Component {
tag: "input".to_string(), tag: "input".to_string(),
attributes: vec![ attributes: vec![
("type".to_string(), "number".to_string()), ("type".to_string(), "number".to_string()),
("value".to_string(), format!("{:.2}",degrees.2)), ("value".to_string(), format!("{:.2}", degrees.2)),
("step".to_string(), "0.01".to_string()), ("step".to_string(), "0.01".to_string()),
], ],
children: vec![], children: vec![],
onchange: Some(EntityChangeExecutor::new_boxed( onchange: Some(EntityChangeExecutor::new_boxed(
onchange.entity_id, onchange.entity_id,
|world : &mut World, entity, value : String| { |world: &mut World, entity, value: String| {
let Some(mut value) = value.parse::<f32>().ok() else { return; }; let Some(mut value) = value.parse::<f32>().ok() else {
if value == -180.0 { value = 180.0; } return;
};
if value == -180.0 {
value = 180.0;
}
let value = value.to_radians(); let value = value.to_radians();
let mut e = world.get_entity_mut(entity).unwrap(); let mut e = world.get_entity_mut(entity).unwrap();
let mut transform = e.get_mut::<Transform>().unwrap(); let mut transform = e.get_mut::<Transform>().unwrap();
@@ -346,20 +382,18 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option<Elemen
return; return;
} }
let euler = transform.rotation.to_euler(EulerRot::XYZ); let euler = transform.rotation.to_euler(EulerRot::XYZ);
transform.rotation = Quat::from_euler(EulerRot::XYZ, euler.0, euler.1, value); transform.rotation =
} Quat::from_euler(EulerRot::XYZ, euler.0, euler.1, value);
)) },
}) )),
}),
], ],
onchange: None onchange: None,
})) }))
} } else if let Some(vec) = r.downcast_ref::<Vec3>() {
else if let Some(vec) = r.downcast_ref::<Vec3>() {
Some(Element::Component(Component { Some(Element::Component(Component {
tag: "div".to_string(), tag: "div".to_string(),
attributes: vec![ attributes: vec![("class".to_string(), "struct-grid".to_string())],
("class".to_string(), "struct-grid".to_string()),
],
children: vec![ children: vec![
Element::Text("X: ".to_string()), Element::Text("X: ".to_string()),
Element::Component(Component { Element::Component(Component {
@@ -368,10 +402,9 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option<Elemen
("type".to_string(), "number".to_string()), ("type".to_string(), "number".to_string()),
("value".to_string(), format!("{:.2}", vec.x)), ("value".to_string(), format!("{:.2}", vec.x)),
("step".to_string(), "0.01".to_string()), ("step".to_string(), "0.01".to_string()),
], ],
children: vec![], children: vec![],
onchange: Some(Box::new(ReflectValueExecutor::from(onchange.add_path("x")))) onchange: Some(Box::new(ReflectValueExecutor::from(onchange.add_path("x")))),
}), }),
Element::Text("Y: ".to_string()), Element::Text("Y: ".to_string()),
Element::Component(Component { Element::Component(Component {
@@ -382,7 +415,7 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option<Elemen
("step".to_string(), "0.01".to_string()), ("step".to_string(), "0.01".to_string()),
], ],
children: vec![], children: vec![],
onchange: Some(Box::new(ReflectValueExecutor::from(onchange.add_path("y")))) onchange: Some(Box::new(ReflectValueExecutor::from(onchange.add_path("y")))),
}), }),
Element::Text("Z: ".to_string()), Element::Text("Z: ".to_string()),
Element::Component(Component { Element::Component(Component {
@@ -393,46 +426,29 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option<Elemen
("step".to_string(), "0.01".to_string()), ("step".to_string(), "0.01".to_string()),
], ],
children: vec![], children: vec![],
onchange: Some(Box::new(ReflectValueExecutor::from(onchange.add_path("z")))) onchange: Some(Box::new(ReflectValueExecutor::from(onchange.add_path("z")))),
}) }),
], ],
onchange: None onchange: None,
})) }))
} else { } else {
None None
} }
} }
pub fn show_reflect(r : &dyn Reflect, reflect: ReflectChange) -> Option<Element> { pub fn show_reflect(r: &dyn Reflect, reflect: ReflectChange) -> Option<Element> {
if let Some(vnode) = check_predefined(r, reflect.clone()) { if let Some(vnode) = check_predefined(r, reflect.clone()) {
return Some(vnode); return Some(vnode);
} }
match r.reflect_ref() { match r.reflect_ref() {
bevy::reflect::ReflectRef::Struct(v) => { bevy::reflect::ReflectRef::Struct(v) => None,
None bevy::reflect::ReflectRef::TupleStruct(_) => None,
bevy::reflect::ReflectRef::Tuple(_) => None,
}, bevy::reflect::ReflectRef::List(_) => None,
bevy::reflect::ReflectRef::TupleStruct(_) => { bevy::reflect::ReflectRef::Array(_) => None,
None bevy::reflect::ReflectRef::Map(_) => None,
}, bevy::reflect::ReflectRef::Enum(_) => None,
bevy::reflect::ReflectRef::Tuple(_) => {
None
},
bevy::reflect::ReflectRef::List(_) => {
None
},
bevy::reflect::ReflectRef::Array(_) => {
None
},
bevy::reflect::ReflectRef::Map(_) => {
None
},
bevy::reflect::ReflectRef::Enum(_) => {
None
},
bevy::reflect::ReflectRef::Value(v) => { bevy::reflect::ReflectRef::Value(v) => {
if let Some(s) = v.downcast_ref::<String>() { if let Some(s) = v.downcast_ref::<String>() {
Some(Element::Component(Component { Some(Element::Component(Component {
@@ -442,7 +458,7 @@ pub fn show_reflect(r : &dyn Reflect, reflect: ReflectChange) -> Option<Element>
("value".to_string(), s.to_string()), ("value".to_string(), s.to_string()),
], ],
children: vec![], children: vec![],
onchange: Some(Box::new(ReflectValueExecutor::from(reflect))) onchange: Some(Box::new(ReflectValueExecutor::from(reflect))),
})) }))
} else if let Some(b) = v.downcast_ref::<bool>() { } else if let Some(b) = v.downcast_ref::<bool>() {
Some(Element::Component(Component { Some(Element::Component(Component {
@@ -452,7 +468,7 @@ pub fn show_reflect(r : &dyn Reflect, reflect: ReflectChange) -> Option<Element>
("value".to_string(), b.to_string()), ("value".to_string(), b.to_string()),
], ],
children: vec![], children: vec![],
onchange: Some(Box::new(ReflectValueExecutor::from(reflect))) onchange: Some(Box::new(ReflectValueExecutor::from(reflect))),
})) }))
} else if let Some(i) = v.downcast_ref::<i32>() { } else if let Some(i) = v.downcast_ref::<i32>() {
Some(Element::Component(Component { Some(Element::Component(Component {
@@ -462,7 +478,7 @@ pub fn show_reflect(r : &dyn Reflect, reflect: ReflectChange) -> Option<Element>
("value".to_string(), i.to_string()), ("value".to_string(), i.to_string()),
], ],
children: vec![], children: vec![],
onchange: Some(Box::new(ReflectValueExecutor::from(reflect))) onchange: Some(Box::new(ReflectValueExecutor::from(reflect))),
})) }))
} else if let Some(f) = v.downcast_ref::<f32>() { } else if let Some(f) = v.downcast_ref::<f32>() {
Some(Element::Component(Component { Some(Element::Component(Component {
@@ -472,20 +488,20 @@ pub fn show_reflect(r : &dyn Reflect, reflect: ReflectChange) -> Option<Element>
("value".to_string(), f.to_string()), ("value".to_string(), f.to_string()),
], ],
children: vec![], children: vec![],
onchange: Some(Box::new(ReflectValueExecutor::from(reflect))) onchange: Some(Box::new(ReflectValueExecutor::from(reflect))),
})) }))
} else { } else {
Some(Element::Text(format!("{:?}", v))) Some(Element::Text(format!("{:?}", v)))
} }
}, }
} }
} }
impl<T: Clone + PartialEq> NodeProp for T {} impl<T: Clone + PartialEq> NodeProp for T {}
pub fn show_string(s : &str) -> Option<VNode> { pub fn show_string(s: &str) -> Option<VNode> {
Some(VNode::Text(s.to_string()) Some(VNode::Text(s.to_string()))
)} }
#[derive(Clone, PartialEq, Serialize, Deserialize, Default)] #[derive(Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct VComponent { pub struct VComponent {
@@ -503,47 +519,41 @@ pub enum VNode {
} }
impl VNode { impl VNode {
pub fn is_same_structure(&self, other : &VNode) -> bool { pub fn is_same_structure(&self, other: &VNode) -> bool {
match (self, other) { match (self, other) {
(VNode::Text(s1), VNode::Text(s2)) => s1 == s2, (VNode::Text(s1), VNode::Text(s2)) => s1 == s2,
(VNode::Text(_), VNode::Component(_)) => false, (VNode::Text(_), VNode::Component(_)) => false,
(VNode::Component(_), VNode::Text(_)) => false, (VNode::Component(_), VNode::Text(_)) => false,
(VNode::Component(c1), VNode::Component(c2)) => { (VNode::Component(c1), VNode::Component(c2)) => {
if c1.tag != c2.tag { if c1.tag != c2.tag {
return false return false;
} else if c1.children.len() != c2.children.len() { } else if c1.children.len() != c2.children.len() {
return false return false;
} else { } else {
for i in 0..c1.children.len() { for i in 0..c1.children.len() {
if !c1.children[i].is_same_structure(&c2.children[i]) { if !c1.children[i].is_same_structure(&c2.children[i]) {
return false return false;
} }
} }
return true return true;
} }
}, }
} }
} }
pub fn get_same_structure_muts(&self, older : &VNode) -> Vec<Mutation> { pub fn get_same_structure_muts(&self, older: &VNode) -> Vec<Mutation> {
let mut res = vec![]; let mut res = vec![];
match (self, older) { match (self, older) {
(VNode::Text(s1), VNode::Text(s2)) => { (VNode::Text(s1), VNode::Text(s2)) => res,
res (VNode::Text(_), VNode::Component(_)) => res,
} (VNode::Component(_), VNode::Text(_)) => res,
(VNode::Text(_), VNode::Component(_)) => {
res
}
(VNode::Component(_), VNode::Text(_)) => {
res
}
(VNode::Component(new), VNode::Component(old)) => { (VNode::Component(new), VNode::Component(old)) => {
for idx in 0..new.attributes.len() { for idx in 0..new.attributes.len() {
if new.attributes.get(idx) != old.attributes.get(idx) { if new.attributes.get(idx) != old.attributes.get(idx) {
res.push(Mutation::SetAttibute { res.push(Mutation::SetAttibute {
id: old.id.as_ref().unwrap().clone(), id: old.id.as_ref().unwrap().clone(),
attribute: new.attributes[idx].0.clone(), attribute: new.attributes[idx].0.clone(),
value: new.attributes[idx].1.clone() value: new.attributes[idx].1.clone(),
}); });
} }
} }
@@ -568,24 +578,24 @@ pub struct ComponentProp {
impl Clone for ComponentProp { impl Clone for ComponentProp {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
component: self.component.clone_value() component: self.component.clone_value(),
} }
} }
} }
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
pub struct ReflectChange { pub struct ReflectChange {
pub entity_id : Entity, pub entity_id: Entity,
pub reflect_path: String, pub reflect_path: String,
pub compoent_id: String pub compoent_id: String,
} }
impl ReflectChange { impl ReflectChange {
pub fn add_path(&self, path : &str) -> ReflectChange { pub fn add_path(&self, path: &str) -> ReflectChange {
ReflectChange { ReflectChange {
entity_id : self.entity_id, entity_id: self.entity_id,
compoent_id : self.compoent_id.clone(), compoent_id: self.compoent_id.clone(),
reflect_path : format!("{}.{}", self.reflect_path, path) reflect_path: format!("{}.{}", self.reflect_path, path),
} }
} }
@@ -600,7 +610,7 @@ impl<'a> PartialEq for ComponentProp {
} }
} }
pub fn recursive_reflect_eq(a : &dyn Reflect, b : &dyn Reflect) -> bool { pub fn recursive_reflect_eq(a: &dyn Reflect, b: &dyn Reflect) -> bool {
let ref_a = a.reflect_ref(); let ref_a = a.reflect_ref();
let ref_b = b.reflect_ref(); let ref_b = b.reflect_ref();
@@ -619,7 +629,7 @@ pub fn recursive_reflect_eq(a : &dyn Reflect, b : &dyn Reflect) -> bool {
return false; return false;
} }
} }
}, }
bevy::reflect::ReflectRef::TupleStruct(a) => { bevy::reflect::ReflectRef::TupleStruct(a) => {
let bevy::reflect::ReflectRef::TupleStruct(b) = b.reflect_ref() else { let bevy::reflect::ReflectRef::TupleStruct(b) = b.reflect_ref() else {
return false; return false;
@@ -634,7 +644,7 @@ pub fn recursive_reflect_eq(a : &dyn Reflect, b : &dyn Reflect) -> bool {
return false; return false;
} }
} }
}, }
bevy::reflect::ReflectRef::Tuple(a) => { bevy::reflect::ReflectRef::Tuple(a) => {
let bevy::reflect::ReflectRef::Tuple(b) = b.reflect_ref() else { let bevy::reflect::ReflectRef::Tuple(b) = b.reflect_ref() else {
return false; return false;
@@ -649,7 +659,7 @@ pub fn recursive_reflect_eq(a : &dyn Reflect, b : &dyn Reflect) -> bool {
return false; return false;
} }
} }
}, }
bevy::reflect::ReflectRef::List(a) => { bevy::reflect::ReflectRef::List(a) => {
let bevy::reflect::ReflectRef::List(b) = b.reflect_ref() else { let bevy::reflect::ReflectRef::List(b) = b.reflect_ref() else {
return false; return false;
@@ -664,7 +674,7 @@ pub fn recursive_reflect_eq(a : &dyn Reflect, b : &dyn Reflect) -> bool {
return false; return false;
} }
} }
}, }
bevy::reflect::ReflectRef::Array(a) => { bevy::reflect::ReflectRef::Array(a) => {
let bevy::reflect::ReflectRef::Array(b) = b.reflect_ref() else { let bevy::reflect::ReflectRef::Array(b) = b.reflect_ref() else {
return false; return false;
@@ -679,7 +689,7 @@ pub fn recursive_reflect_eq(a : &dyn Reflect, b : &dyn Reflect) -> bool {
return false; return false;
} }
} }
}, }
bevy::reflect::ReflectRef::Map(a) => { bevy::reflect::ReflectRef::Map(a) => {
let bevy::reflect::ReflectRef::Map(b) = b.reflect_ref() else { let bevy::reflect::ReflectRef::Map(b) = b.reflect_ref() else {
return false; return false;
@@ -699,7 +709,7 @@ pub fn recursive_reflect_eq(a : &dyn Reflect, b : &dyn Reflect) -> bool {
return false; return false;
} }
} }
}, }
bevy::reflect::ReflectRef::Enum(a) => { bevy::reflect::ReflectRef::Enum(a) => {
let bevy::reflect::ReflectRef::Enum(b) = b.reflect_ref() else { let bevy::reflect::ReflectRef::Enum(b) = b.reflect_ref() else {
return false; return false;
@@ -718,7 +728,7 @@ pub fn recursive_reflect_eq(a : &dyn Reflect, b : &dyn Reflect) -> bool {
return false; return false;
} }
} }
}, }
bevy::reflect::ReflectRef::Value(a) => { bevy::reflect::ReflectRef::Value(a) => {
let bevy::reflect::ReflectRef::Value(b) = b.reflect_ref() else { let bevy::reflect::ReflectRef::Value(b) = b.reflect_ref() else {
return false; return false;
@@ -729,7 +739,7 @@ pub fn recursive_reflect_eq(a : &dyn Reflect, b : &dyn Reflect) -> bool {
} else { } else {
return false; return false;
} }
}, }
} }
false false
@@ -746,7 +756,6 @@ impl PartialEq for InspectedEntity {
} }
for i in 0..self.components.len() { for i in 0..self.components.len() {
if !recursive_reflect_eq(self.components[i].as_ref(), other.components[i].as_ref()) { if !recursive_reflect_eq(self.components[i].as_ref(), other.components[i].as_ref()) {
return false; return false;
} }