diff --git a/studio-frontend/src/dioxus-machine.ts b/studio-frontend/src/dioxus-machine.ts index 51d571e..5bf8991 100644 --- a/studio-frontend/src/dioxus-machine.ts +++ b/studio-frontend/src/dioxus-machine.ts @@ -2,6 +2,7 @@ import { register_new_change, type InspectorDomChanged } from "@storyteller/stud console.log("Hello, World!"); + function unpack_vnode( vnode: any ) { @@ -29,7 +30,7 @@ function unpack_vnode( } //add onchange hook if input if (node_data["onchange"] == true) { - element.onchange = (event: Event) => { + element.oninput = (event: Event) => { var input = event.target as HTMLInputElement; const id = input.getAttribute("id"); if (id != null) { @@ -75,6 +76,35 @@ function apply_muts( root.removeChild(root.firstChild); } root.appendChild(element); + } else if (mut["SetAttibute"] != undefined) { + let m = mut["SetAttibute"]; + let id = m["id"]; + let value = m["value"]; + let attribute = m["attribute"]; + let element = shadowroot?.getElementById(id); + if (!element) { + console.log("element not found", id); + } else { + if (attribute == "value") { + var input = element as HTMLInputElement; + if (input) { + input.value = value; + //update input value + // Create a new 'input' event + const event = new Event('input', { + bubbles: true, + cancelable: true, + }); + + // Dispatch the event + input.dispatchEvent(event); + + console.log("input value updated", value); + continue; + } + } + element.setAttribute(attribute, value); + } } } diff --git a/studio/src/ui/inspector.rs b/studio/src/ui/inspector.rs index 5bdc8b0..7329a83 100644 --- a/studio/src/ui/inspector.rs +++ b/studio/src/ui/inspector.rs @@ -74,8 +74,6 @@ fn show_selected( let mut virtial_dom = cell.get_resource_mut::().unwrap(); let app_type_registry = cell.get_resource::().unwrap(); - let app_type_registry = app_type_registry.read(); - let e = cell.get_entity(selected_entity).unwrap(); if let Some(changes) = super::utils::wasm::ONCHAGE_BUFFER.take_message() { @@ -92,7 +90,7 @@ fn show_selected( let id = e.id(); - let components = cell.components().clone(); + let components = cell.components(); let element = Element::Component(super::utils::Component { tag: "div".to_string(), attributes: vec![ diff --git a/studio/src/ui/utils.rs b/studio/src/ui/utils.rs index 2ba1d27..98765ab 100644 --- a/studio/src/ui/utils.rs +++ b/studio/src/ui/utils.rs @@ -11,6 +11,7 @@ trait NodeProp : Clone + PartialEq { #[derive(Serialize, Deserialize)] pub enum Mutation { + SetAttibute{id : String, attribute : String, value : String}, ReplaceAll(VNode), RemoveAll } @@ -64,9 +65,9 @@ impl VirtualDom { if let Some(element) = element { let node = self.recursive_unpack_element(&mut id_counter, element); - return self.create_mutations(Some(node)); + return self.create_mutations(node); } else { - return self.create_mutations(None); + return self.create_mutations(VNode::Text("".to_string())); } } @@ -86,7 +87,7 @@ impl VirtualDom { VNode::Component(VComponent { tag: component.tag, - attributes: component.attributes, + attributes: component.attributes.into_iter().collect(), id: Some(id), onchange: onchange_enabled, children: component.children.into_iter().map(|e| self.recursive_unpack_element(counter, e)).collect() @@ -95,12 +96,22 @@ impl VirtualDom { } } - pub fn create_mutations(&mut self, node : Option) -> Vec { - if self.last_node == node { + pub fn create_mutations(&mut self, node : VNode) -> Vec { + if self.last_node == Some(node.clone()) { return vec![] } else { - self.last_node = node.clone(); - return vec![Mutation::ReplaceAll(node.unwrap())] + + if let Some(last_node) = &self.last_node { + if last_node.is_same_structure(&node) { + + let muts = node.get_same_structure_muts(&last_node); + self.last_node = Some(node.clone()); + return muts; + } + } + + self.last_node = Some(node.clone()); + return vec![Mutation::ReplaceAll(node)] } } } @@ -174,6 +185,27 @@ impl WebEventExecutor for ReflectValueExecutor { } } +struct EntityChangeExecutor { + entity : Entity, + func : Box, +} + +impl WebEventExecutor for EntityChangeExecutor { + fn execute(&mut self, world: &mut World, value: String) { + (self.func)(world, self.entity, value); + } +} + +impl EntityChangeExecutor { + fn new(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 { + Box::new(EntityChangeExecutor::new(entity, func)) + } +} + fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option { if let Some(name) = r.downcast_ref::() { Some(Element::Component(Component { @@ -214,7 +246,15 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option().unwrap(); + let euler = transform.rotation.to_euler(EulerRot::XYZ); + transform.rotation = Quat::from_euler(EulerRot::XYZ, value.parse().unwrap(), euler.1, euler.2); + } + )) }), Element::Text("Y: ".to_string()), Element::Component(Component { @@ -382,6 +422,60 @@ pub enum VNode { Component(VComponent), } +impl VNode { + pub fn is_same_structure(&self, other : &VNode) -> bool { + match (self, other) { + (VNode::Text(s1), VNode::Text(s2)) => s1 == s2, + (VNode::Text(_), VNode::Component(_)) => false, + (VNode::Component(_), VNode::Text(_)) => false, + (VNode::Component(c1), VNode::Component(c2)) => { + if c1.tag != c2.tag { + return false + } else if c1.children.len() != c2.children.len() { + return false + } else { + for i in 0..c1.children.len() { + if !c1.children[i].is_same_structure(&c2.children[i]) { + return false + } + } + return true + } + }, + } + } + + pub fn get_same_structure_muts(&self, older : &VNode) -> Vec { + let mut res = vec![]; + match (self, older) { + (VNode::Text(s1), VNode::Text(s2)) => { + res + } + (VNode::Text(_), VNode::Component(_)) => { + res + } + (VNode::Component(_), VNode::Text(_)) => { + res + } + (VNode::Component(new), VNode::Component(old)) => { + for idx in 0..new.attributes.len() { + if new.attributes.get(idx) != old.attributes.get(idx) { + res.push(Mutation::SetAttibute { + id: old.id.as_ref().unwrap().clone(), + attribute: new.attributes[idx].0.clone(), + value: new.attributes[idx].1.clone() + }); + } + } + for i in 0..new.children.len() { + res.append(&mut new.children[i].get_same_structure_muts(&old.children[i])); + } + res + } + } + } +} + pub struct InspectedEntity { pub id: Option, pub components: Vec>,