mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-28 08:58:07 +00:00
Custom unpack with custom vnode
This commit is contained in:
@@ -2,22 +2,30 @@ import { type InspectorDomChanged } from "dist/studio/studio";
|
|||||||
|
|
||||||
console.log("Hello, World!");
|
console.log("Hello, World!");
|
||||||
|
|
||||||
|
function unpack_vnode(
|
||||||
function load_child(stack : any[], child_path : number[]) {
|
vnode: any
|
||||||
// iterate through each number and get that child
|
) {
|
||||||
var node : any = stack[stack.length - 1];
|
if (vnode["Text"] != undefined) {
|
||||||
for (const ptr of child_path) {
|
var text_element = document.createTextNode(vnode["Text"]);
|
||||||
var steps = ptr;
|
return text_element;
|
||||||
var m = 0;
|
} else if (vnode["Component"] != undefined) {
|
||||||
for (node = node.firstChild; m < steps; m++) {
|
var node_data = vnode["Component"];
|
||||||
node = node.nextSibling;
|
var element = document.createElement(node_data["tag"]);
|
||||||
|
//apply attributes
|
||||||
|
for (var i = 0; i < node_data["attributes"].length; i++) {
|
||||||
|
var attr = node_data["attributes"][i];
|
||||||
|
element.setAttribute(attr[0], attr[1]);
|
||||||
}
|
}
|
||||||
|
//apply children
|
||||||
|
if (node_data["children"] != undefined) {
|
||||||
|
for (var j = 0; j < node_data["children"].length; j++) {
|
||||||
|
var child = node_data["children"][j];
|
||||||
|
var child_element = unpack_vnode(child);
|
||||||
|
element.appendChild(child_element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
function laod_template(edit : any, stack : any[]) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function apply_muts(
|
function apply_muts(
|
||||||
@@ -41,134 +49,10 @@ function apply_muts(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var vdom = JSON.parse(event.detail);
|
var vdom = JSON.parse(event.detail);
|
||||||
var templates = vdom["templates"];
|
|
||||||
var edits = vdom["edits"];
|
|
||||||
|
|
||||||
console.log("edits", edits);
|
|
||||||
console.log("templates", templates);
|
|
||||||
|
|
||||||
var element_stack = [];
|
|
||||||
var nodes : any = {}
|
|
||||||
|
|
||||||
|
|
||||||
|
var element = unpack_vnode(vdom);
|
||||||
|
root.appendChild(element);
|
||||||
|
|
||||||
nodes[0] = document.createElement("div");
|
|
||||||
root.appendChild(nodes[0]);
|
|
||||||
element_stack.push(root);
|
|
||||||
|
|
||||||
//loop through edits
|
|
||||||
for (const edit of edits) {
|
|
||||||
|
|
||||||
var type = edit["type"];
|
|
||||||
if (type == "LoadTemplate") {
|
|
||||||
// var index = edit["index"];
|
|
||||||
// var template_name = edit["name"];
|
|
||||||
// var id = edit["id"];
|
|
||||||
|
|
||||||
// var target_root = null;
|
|
||||||
// for (const template of templates) {
|
|
||||||
// if (template["name"] == template_name) {
|
|
||||||
// target_root = template["roots"][index];
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (target_root == null) {
|
|
||||||
// console.log("template not found:", template_name);
|
|
||||||
// continue;
|
|
||||||
// } else {
|
|
||||||
// target_root["id"] = id;
|
|
||||||
// element_stack.push(target_root);
|
|
||||||
// }
|
|
||||||
|
|
||||||
var id = edit["id"];
|
|
||||||
var index = edit["index"];
|
|
||||||
var template_name = edit["name"];
|
|
||||||
|
|
||||||
var template_node = null;
|
|
||||||
for (const template of templates) {
|
|
||||||
if (template["name"] == template_name) {
|
|
||||||
template_node = template["roots"][index];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (template_node == null) {
|
|
||||||
console.log("template not found:", template_name);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
var node = recursive_render(null, template_node);
|
|
||||||
nodes[id] = node;
|
|
||||||
element_stack.push(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (type == "AppendChildren") {
|
|
||||||
// var id = edit["id"];
|
|
||||||
// var count = edit["m"];
|
|
||||||
// if (id == 0) {
|
|
||||||
// for (var i = 0; i < count; i++) {
|
|
||||||
// var current_element = element_stack.pop();
|
|
||||||
// element_tree.push(current_element);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// //TODO
|
|
||||||
// }
|
|
||||||
|
|
||||||
var id = edit["id"];
|
|
||||||
var many = edit["m"];
|
|
||||||
|
|
||||||
var target_node = nodes[id];
|
|
||||||
|
|
||||||
let append_nodes = element_stack.splice(element_stack.length - many);
|
|
||||||
|
|
||||||
for (var i = 0; i < many; i++) {
|
|
||||||
target_node.appendChild(append_nodes[i]);
|
|
||||||
}
|
|
||||||
} else if (type == "HydrateText") {
|
|
||||||
// var child_path = edit["path"];
|
|
||||||
// var target_node = element_stack[element_stack.length - 1];
|
|
||||||
|
|
||||||
// for (const path of child_path) {
|
|
||||||
// target_node = target_node["children"][path];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (target_node == null) {
|
|
||||||
// console.log("target_node not found:", child_path);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //add text node to target_node
|
|
||||||
// if (target_node["children"] == undefined) {
|
|
||||||
// target_node["children"] = [];
|
|
||||||
// }
|
|
||||||
// target_node["children"].push({type: "Text", text: edit["value"], id: edit["id"]});
|
|
||||||
|
|
||||||
var node : HTMLElement = load_child(element_stack, edit["path"]);
|
|
||||||
if (node) {
|
|
||||||
node.textContent = edit["value"];
|
|
||||||
} else {
|
|
||||||
console.log("node not found:", edit["path"]);
|
|
||||||
}
|
|
||||||
} else if (type == "ReplacePlaceholder") {
|
|
||||||
var child_path = edit["path"];
|
|
||||||
var manu = edit["m"];
|
|
||||||
|
|
||||||
var els = [];
|
|
||||||
for (var i = 0; i < manu; i++) {
|
|
||||||
var el = element_stack.pop();
|
|
||||||
els.push(el);
|
|
||||||
}
|
|
||||||
els.reverse();
|
|
||||||
var target_node = load_child(element_stack, child_path);
|
|
||||||
target_node.replaceWith(...els);
|
|
||||||
console.log("")
|
|
||||||
} else if (type == "CreateTextNode") {
|
|
||||||
var text_node : any = document.createTextNode(edit["value"]);
|
|
||||||
nodes[edit["id"]] = text_node;
|
|
||||||
element_stack.push(text_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.log('Selection has been cleared.');
|
console.log('Selection has been cleared.');
|
||||||
}
|
}
|
||||||
@@ -177,66 +61,8 @@ function apply_muts(
|
|||||||
document.addEventListener('inspector-dom-changed', (event: CustomEvent) => {
|
document.addEventListener('inspector-dom-changed', (event: CustomEvent) => {
|
||||||
// Cast the event to the InspectorDomChanged type to access its details in TypeScript
|
// Cast the event to the InspectorDomChanged type to access its details in TypeScript
|
||||||
const customEvent = event as InspectorDomChanged;
|
const customEvent = event as InspectorDomChanged;
|
||||||
|
console.log(customEvent);
|
||||||
// Now you can access the detail property, which is either a string or null
|
// Now you can access the detail property, which is either a string or null
|
||||||
apply_muts(customEvent);
|
apply_muts(customEvent);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export interface VdomElement {
|
|
||||||
id?: number;
|
|
||||||
type?: string;
|
|
||||||
text?: string;
|
|
||||||
tag?: string;
|
|
||||||
namespace?: string;
|
|
||||||
attrs?: any[];
|
|
||||||
children?: VdomElement[];
|
|
||||||
}
|
|
||||||
|
|
||||||
function recursive_render(
|
|
||||||
root: HTMLElement | null,
|
|
||||||
element: VdomElement,
|
|
||||||
) {
|
|
||||||
//create element
|
|
||||||
var tag = element["tag"];
|
|
||||||
if (element.type == "Text") {
|
|
||||||
tag = "div";
|
|
||||||
} else if (element.type == "Dynamic") {
|
|
||||||
tag = "div";
|
|
||||||
}
|
|
||||||
|
|
||||||
var new_element = document.createElement(element["tag"] as string);
|
|
||||||
|
|
||||||
//set text
|
|
||||||
if (element.text != undefined) {
|
|
||||||
new_element.textContent = element.text;
|
|
||||||
}
|
|
||||||
|
|
||||||
//set id
|
|
||||||
if (element.id != undefined) {
|
|
||||||
new_element.id = element.id.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
//set attrs
|
|
||||||
if (element.attrs != undefined) {
|
|
||||||
for (const attr of element.attrs) {
|
|
||||||
var name = attr["name"];
|
|
||||||
var value = attr["value"];
|
|
||||||
new_element.setAttribute(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//parent to root
|
|
||||||
if (root != null) {
|
|
||||||
root.appendChild(new_element);
|
|
||||||
}
|
|
||||||
|
|
||||||
//render children
|
|
||||||
if (element["children"] != undefined) {
|
|
||||||
for (const child of element["children"]) {
|
|
||||||
recursive_render(new_element, child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new_element;
|
|
||||||
}
|
|
||||||
+3
-7
@@ -22,7 +22,7 @@ bitflags = "2.4.0"
|
|||||||
console_error_panic_hook = { version = "0.1.7", optional = true }
|
console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||||
js-sys = { version = "0.3.65", optional = true }
|
js-sys = { version = "0.3.65", optional = true }
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
serde = { version = "1.0.192", optional = true }
|
serde = { version = "1.0.192", optional = true, features = ["derive"] }
|
||||||
serde-wasm-bindgen = { version = "0.6.1", optional = true }
|
serde-wasm-bindgen = { version = "0.6.1", optional = true }
|
||||||
serde_json = { version = "1.0.108", optional = true }
|
serde_json = { version = "1.0.108", optional = true }
|
||||||
studio-bvh = { path = "../studio-bvh" }
|
studio-bvh = { path = "../studio-bvh" }
|
||||||
@@ -39,11 +39,9 @@ web-sys = { version = "0.3.65", optional = true, features = [
|
|||||||
] }
|
] }
|
||||||
space_editor = {git = "https://github.com/rewin123/space_editor", rev = "ce83f86dc902787ab16213f3209276a784654df6"}
|
space_editor = {git = "https://github.com/rewin123/space_editor", rev = "ce83f86dc902787ab16213f3209276a784654df6"}
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
dioxus = "0.4.3"
|
|
||||||
futures-util = "0.3.30"
|
|
||||||
sledgehammer_bindgen = { version = "0.3.1", default-features = false, optional = true }
|
|
||||||
sledgehammer_utils = { version = "0.2", optional = true }
|
|
||||||
pretty-type-name = "1.0.1"
|
pretty-type-name = "1.0.1"
|
||||||
|
async-channel = "2.2.0"
|
||||||
|
uuid = { version = "1.3.0", features = ["v4"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
wasm = [
|
wasm = [
|
||||||
@@ -54,8 +52,6 @@ wasm = [
|
|||||||
"dep:serde-wasm-bindgen",
|
"dep:serde-wasm-bindgen",
|
||||||
"dep:web-sys",
|
"dep:web-sys",
|
||||||
"bevy_rapier3d/wasm-bindgen",
|
"bevy_rapier3d/wasm-bindgen",
|
||||||
"dep:sledgehammer_bindgen",
|
|
||||||
"dep:sledgehammer_utils",
|
|
||||||
]
|
]
|
||||||
desktop = []
|
desktop = []
|
||||||
|
|
||||||
|
|||||||
+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 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 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;
|
||||||
@@ -9,7 +8,7 @@ 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::{ComponentProp, InspectedEntity};
|
use super::utils::{show_reflect, ComponentProp, InspectedEntity, VComponent, VNode};
|
||||||
|
|
||||||
pub struct InspectorPlugin;
|
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(
|
fn show_selected(
|
||||||
world: &mut World
|
world: &mut World
|
||||||
) {
|
) {
|
||||||
@@ -282,15 +74,20 @@ fn show_selected(
|
|||||||
let mut cell = InspectedEntity::none();
|
let mut cell = InspectedEntity::none();
|
||||||
cell.id = Some(e.id());
|
cell.id = Some(e.id());
|
||||||
cell.components = functions.get_reflect_copy(&e);
|
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 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 bevy::{prelude::*, utils::HashMap};
|
||||||
use dioxus::prelude::*;
|
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 struct InspectedEntity {
|
||||||
pub id: Option<Entity>,
|
pub id: Option<Entity>,
|
||||||
pub components: Vec<Box<dyn Reflect>>,
|
pub components: Vec<Box<dyn Reflect>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Props)]
|
|
||||||
pub struct ComponentProp {
|
pub struct ComponentProp {
|
||||||
pub component: Box<dyn Reflect>,
|
pub component: Box<dyn Reflect>,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user