mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-17 00:13:17 +00:00
Custom unpack with custom vnode
This commit is contained in:
+11
-214
@@ -1,7 +1,6 @@
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::{sync::{Arc, Mutex, RwLock}, thread::yield_now};
|
||||
|
||||
use bevy::{ecs::world::unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell}, prelude::*, reflect::TypeData, utils::{hashbrown::HashMap, tracing::field}, window::PrimaryWindow};
|
||||
use dioxus::{prelude::*, rsx::*};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use space_editor::{prelude::Selected, space_editor_ui::inspector::inspect};
|
||||
use wasm_bindgen::JsCast;
|
||||
@@ -9,7 +8,7 @@ use web_sys::HtmlElement;
|
||||
|
||||
use crate::{ui::inspector::wasm::notify_dom_changed, wasm::{StaticBuffer, WasmMessageBuffer}};
|
||||
|
||||
use super::utils::{ComponentProp, InspectedEntity};
|
||||
use super::utils::{show_reflect, ComponentProp, InspectedEntity, VComponent, VNode};
|
||||
|
||||
pub struct InspectorPlugin;
|
||||
|
||||
@@ -56,213 +55,6 @@ impl InspectorFunctions {
|
||||
}
|
||||
|
||||
|
||||
fn web_inspector(cx: Scope<InspectedEntity>) -> dioxus::core::Element {
|
||||
|
||||
let e = cx.props;
|
||||
|
||||
let components = e.components.iter().map(|c: &Box<dyn Reflect>| ComponentProp { component: c.clone_value() }).collect::<Vec<_>>();
|
||||
let components_rendered = components.iter().map(|c : &ComponentProp| {
|
||||
rsx! {
|
||||
web_reflect { component: c.component.clone_value() }
|
||||
}
|
||||
});
|
||||
|
||||
if e.id.is_none() {
|
||||
render! {
|
||||
div {
|
||||
"No entity selected"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let id_name = format!("{:?}", e.id.unwrap());
|
||||
render! {
|
||||
div {
|
||||
id_name,
|
||||
components_rendered
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn web_reflect(cx: Scope<ComponentProp>) -> dioxus::core::Element {
|
||||
|
||||
//registered components
|
||||
if cx.props.component.represents::<Name>() {
|
||||
let name = <Name as FromReflect>::from_reflect(cx.props.component.as_ref()).unwrap();
|
||||
return render! {
|
||||
div {
|
||||
p { name.as_str() }
|
||||
}
|
||||
};
|
||||
}else if cx.props.component.represents::<Transform>() {
|
||||
let transform = <Transform as FromReflect>::from_reflect(cx.props.component.as_ref()).unwrap();
|
||||
let euler = transform.rotation.to_euler(EulerRot::XYZ);
|
||||
return render! {
|
||||
div {
|
||||
"style" : "flex-direction: column; display: flex; ",
|
||||
"Transform\n",
|
||||
format!("pos: {:.2} {:.2} {:.2}\n", transform.translation.x, transform.translation.y, transform.translation.z),
|
||||
format!("rot: {:.2} {:.2} {:.2}\n", euler.0, euler.1, euler.2),
|
||||
format!("scale: {:.2} {:.2} {:.2}\n", transform.scale.x, transform.scale.y, transform.scale.z)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let res = match cx.props.component.reflect_ref() {
|
||||
|
||||
bevy::reflect::ReflectRef::Struct(v) => {
|
||||
let field_count = v.field_len();
|
||||
|
||||
render! {
|
||||
div {
|
||||
p { v.type_name().split("::").last().unwrap() },
|
||||
(0..field_count).map(|i| {
|
||||
let field = v.field_at(i).unwrap();
|
||||
render! {
|
||||
format!("{}: ", v.name_at(i).unwrap()),
|
||||
web_reflect { component: field.clone_value() }
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
bevy::reflect::ReflectRef::TupleStruct(v) => {
|
||||
let field_count = v.field_len();
|
||||
|
||||
render! {
|
||||
div {
|
||||
p { v.type_name().split("::").last().unwrap(), },
|
||||
v.iter_fields().map(|field| {
|
||||
render! {
|
||||
web_reflect { component: field.clone_value() }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
bevy::reflect::ReflectRef::Tuple(_) => {
|
||||
render! {
|
||||
div {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
bevy::reflect::ReflectRef::List(_) => {
|
||||
render! {
|
||||
div {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
bevy::reflect::ReflectRef::Array(_) => {
|
||||
render! {
|
||||
div {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
bevy::reflect::ReflectRef::Map(_) => {
|
||||
render! {
|
||||
div {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
bevy::reflect::ReflectRef::Enum(_) => {
|
||||
render! {
|
||||
div {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
bevy::reflect::ReflectRef::Value(v) => {
|
||||
if let Some(v) = v.downcast_ref::<String>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<f32>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<f64>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<bool>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<i32>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<i64>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<u32>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<u64>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<u8>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<u16>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<i8>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else if let Some(v) = v.downcast_ref::<i16>() {
|
||||
render! {
|
||||
div {
|
||||
format!("{:?}", v)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
render! {
|
||||
div {
|
||||
"Not implemented reflect type"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
fn show_selected(
|
||||
world: &mut World
|
||||
) {
|
||||
@@ -282,15 +74,20 @@ fn show_selected(
|
||||
let mut cell = InspectedEntity::none();
|
||||
cell.id = Some(e.id());
|
||||
cell.components = functions.get_reflect_copy(&e);
|
||||
|
||||
|
||||
let mut dom = VirtualDom::new_with_props(web_inspector, cell);
|
||||
let vnode = VNode::Component(VComponent {
|
||||
tag: "div".to_string(),
|
||||
attributes: vec![
|
||||
|
||||
],
|
||||
children: cell.components.into_iter().map(|c| show_reflect(c.as_ref())).filter_map(|c| c).collect(),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let muts = dom.rebuild();
|
||||
|
||||
let q_window = world.query_filtered::<&Window, With<PrimaryWindow>>().single(world);
|
||||
|
||||
let _ = notify_dom_changed(q_window, serde_json::to_string(&muts).unwrap());
|
||||
let _ = notify_dom_changed(q_window, serde_json::to_string(&vnode).unwrap());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+224
-4
@@ -1,14 +1,234 @@
|
||||
|
||||
use bevy::prelude::*;
|
||||
use dioxus::prelude::*;
|
||||
use bevy::{prelude::*, utils::HashMap};
|
||||
use ::serde::{Serialize, Deserialize};
|
||||
use uuid::*;
|
||||
|
||||
trait NodeProp : Clone + PartialEq {
|
||||
|
||||
}
|
||||
|
||||
fn check_predefined(r : &dyn Reflect) -> Option<VNode> {
|
||||
if let Some(name) = r.downcast_ref::<Name>() {
|
||||
Some(VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "text".to_string()),
|
||||
("value".to_string(), name.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
}))
|
||||
} else if let Some(transform) = r.downcast_ref::<Transform>() {
|
||||
Some(VNode::Component(VComponent {
|
||||
tag: "div".to_string(),
|
||||
attributes: vec![],
|
||||
children: vec![
|
||||
VNode::Text("Pos: ".to_string()),
|
||||
show_reflect(&transform.translation).unwrap(),
|
||||
VNode::Text("Rot: ".to_string()),
|
||||
show_reflect(&transform.rotation).unwrap(),
|
||||
VNode::Text("Scale: ".to_string()),
|
||||
show_reflect(&transform.scale).unwrap(),
|
||||
],
|
||||
onchange: None
|
||||
}))
|
||||
} else if let Some(quat) = r.downcast_ref::<Quat>() {
|
||||
let euler = quat.to_euler(EulerRot::XYZ);
|
||||
Some(VNode::Component(VComponent {
|
||||
tag: "div".to_string(),
|
||||
attributes: vec![],
|
||||
children: vec![
|
||||
VNode::Text("X: ".to_string()),
|
||||
VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "number".to_string()),
|
||||
("value".to_string(), euler.0.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
}),
|
||||
VNode::Text("Y: ".to_string()),
|
||||
VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "number".to_string()),
|
||||
("value".to_string(), euler.1.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
}),
|
||||
VNode::Text("Z: ".to_string()),
|
||||
VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "number".to_string()),
|
||||
("value".to_string(), euler.2.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
})
|
||||
],
|
||||
onchange: None
|
||||
}))
|
||||
}
|
||||
else if let Some(vec) = r.downcast_ref::<Vec3>() {
|
||||
Some(VNode::Component(VComponent {
|
||||
tag: "div".to_string(),
|
||||
attributes: vec![],
|
||||
children: vec![
|
||||
VNode::Text("X: ".to_string()),
|
||||
VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "number".to_string()),
|
||||
("value".to_string(), vec.x.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
}),
|
||||
VNode::Text("Y: ".to_string()),
|
||||
VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "number".to_string()),
|
||||
("value".to_string(), vec.y.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
}),
|
||||
VNode::Text("Z: ".to_string()),
|
||||
VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "number".to_string()),
|
||||
("value".to_string(), vec.z.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
})
|
||||
],
|
||||
onchange: None
|
||||
}))
|
||||
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show_reflect(r : &dyn Reflect) -> Option<VNode> {
|
||||
|
||||
if let Some(vnode) = check_predefined(r) {
|
||||
return Some(vnode);
|
||||
}
|
||||
|
||||
match r.reflect_ref() {
|
||||
bevy::reflect::ReflectRef::Struct(v) => {
|
||||
None
|
||||
|
||||
},
|
||||
bevy::reflect::ReflectRef::TupleStruct(_) => {
|
||||
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) => {
|
||||
if let Some(s) = v.downcast_ref::<String>() {
|
||||
Some(VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "text".to_string()),
|
||||
("value".to_string(), s.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
}))
|
||||
} else if let Some(b) = v.downcast_ref::<bool>() {
|
||||
Some(VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "checkbox".to_string()),
|
||||
("value".to_string(), b.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
}))
|
||||
} else if let Some(i) = v.downcast_ref::<i32>() {
|
||||
Some(VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "number".to_string()),
|
||||
("value".to_string(), i.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
}))
|
||||
} else if let Some(f) = v.downcast_ref::<f32>() {
|
||||
Some(VNode::Component(VComponent {
|
||||
tag: "input".to_string(),
|
||||
attributes: vec![
|
||||
("type".to_string(), "number".to_string()),
|
||||
("value".to_string(), f.to_string()),
|
||||
],
|
||||
children: vec![],
|
||||
onchange: None
|
||||
}))
|
||||
} else {
|
||||
Some(VNode::Text(format!("{:?}", v)))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + PartialEq> NodeProp for T {}
|
||||
|
||||
pub fn show_string(s : &str) -> Option<VNode> {
|
||||
Some(VNode::Text(s.to_string())
|
||||
)}
|
||||
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize, Default)]
|
||||
pub struct VComponent {
|
||||
pub tag: String,
|
||||
pub attributes: Vec<(String, String)>,
|
||||
pub children: Vec<VNode>,
|
||||
pub onchange: Option<String> // event name if onchange is set
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum VNode {
|
||||
Text(String),
|
||||
Component(VComponent),
|
||||
}
|
||||
|
||||
struct Element<P: NodeProp> {
|
||||
last_prop: Option<P>,
|
||||
last_elements: Vec<VNode>,
|
||||
prop_event : HashMap<String, Box<dyn FnMut(&mut P, &str)>>,
|
||||
|
||||
}
|
||||
|
||||
struct VirtualDom {
|
||||
|
||||
}
|
||||
|
||||
#[derive(Props)]
|
||||
pub struct InspectedEntity {
|
||||
pub id: Option<Entity>,
|
||||
pub components: Vec<Box<dyn Reflect>>,
|
||||
}
|
||||
|
||||
#[derive(Props)]
|
||||
pub struct ComponentProp {
|
||||
pub component: Box<dyn Reflect>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user