diff --git a/studio/src/ui/inspector.rs b/studio/src/ui/inspector.rs index 74a60c6..2514498 100644 --- a/studio/src/ui/inspector.rs +++ b/studio/src/ui/inspector.rs @@ -1,9 +1,161 @@ -use bevy::prelude::*; +use std::{any::Any, marker::PhantomData}; + +use bevy::{prelude::*, reflect::{serde::ReflectSerializer, DynamicStruct, GetTypeRegistration}, utils::HashMap}; +use serde::{Deserialize, Serialize}; +use serde_json::*; +use space_editor::space_prefab::component::MeshPrimitivePrefab; + +use crate::interaction::Selected; pub struct InspectorPlugin; impl Plugin for InspectorPlugin { fn build(&self, app: &mut App) { - + app.init_resource::(); + app.add_event::(); + + app.configure_sets(Update, ( + InspectorSystem::DetectChanges, + InspectorSystem::PerComponentCollect, + InspectorSystem::CollectChanges, + ).chain()); + + app.add_systems(Update, update_description.in_set(InspectorSystem::CollectChanges)); + + app.register_inspect::(); + app.register_inspect::(); + app.register_inspect::(); + + + } -} \ No newline at end of file +} + +trait AppInspectable { + fn register_inspect(&mut self); +} + +impl AppInspectable for App { + fn register_inspect(&mut self) { + self + .register_type::() + .add_event::>() + .add_systems(Update, ( + update_inspect_by_select_change::, + update_inspect_by_remove::, + update_inspect_by_change:: + ).in_set(InspectorSystem::DetectChanges)) + .add_systems(Update, auto_serialize_system::.in_set(InspectorSystem::PerComponentCollect)); + } +} + +#[derive(SystemSet, Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum InspectorSystem { + DetectChanges, + PerComponentCollect, + CollectChanges, +} + +#[derive(Event, Clone, Copy)] +pub struct UpdateInspect { + _phantom: PhantomData, +} + +#[derive(Event)] +pub struct UpdateEntityDescription; + +impl Default for UpdateInspect { + fn default() -> Self { + Self { _phantom: PhantomData } + } +} + +#[derive(Resource, Serialize, Deserialize, Default, Clone)] +pub struct EntityDescription { + pub components: HashMap, +} + +fn update_inspect_by_select_change( + mut ev_inspect : EventWriter>, + q_added: Query<(), Added>, + q_removed: RemovedComponents, +) { + if !q_added.is_empty() { + ev_inspect.send(UpdateInspect::::default()); + } + + if !q_removed.is_empty() { + ev_inspect.send(UpdateInspect::::default()); + } +} + +fn update_inspect_by_remove( + mut ev_inspect : EventWriter>, + mut q_t_removed : RemovedComponents, +) { + if let Some(t) = q_t_removed.iter().next() { + ev_inspect.send(UpdateInspect::::default()); + } +} + +fn update_inspect_by_change( + mut ev_inspect : EventWriter>, + q_t_changed : Query<&T, (With, Changed)>, +) { + if let Some(_) = q_t_changed.iter().next() { + ev_inspect.send(UpdateInspect::::default()); + } +} + +fn auto_serialize_system( + q_t : Query<&T, With>, + mut description : ResMut, + registry : Res, + mut ev_inspect : EventReader>, + mut ev_update_description : EventWriter, +) { + if ev_inspect.is_empty() { + return; + } + + ev_inspect.clear(); + + if let Some(t) = q_t.iter().next() { + let registry = registry.read(); + let json = serde_json::to_value(ReflectSerializer::new(t, ®istry)).unwrap(); + info!("json: {:?}", json.to_string()); + description.components.insert(T::get_type_registration().type_info().type_path().to_string(), json); + } else { + description.components.remove(T::get_type_registration().type_info().type_path()); + } + + ev_update_description.send(UpdateEntityDescription); +} + +fn auto_handle_inspect( + mut assets : Res>, +) { + +} + +fn update_description( + mut description : ResMut, + mut ev_update_description : EventReader, +) { + if ev_update_description.is_empty() { + return; + } + + ev_update_description.clear(); + + let values = description.components.iter().map(|(name, v)| { + let mut value = Value::Object(Map::new()); + value.as_object_mut().unwrap().insert("name".to_string(), Value::String(name.to_string())); + value.as_object_mut().unwrap().insert("value".to_string(), v[name].clone()); + value + }).collect::>(); + + //Write pretty json + info!("description: {}", serde_json::to_string_pretty(&values).unwrap()); +} + diff --git a/studio/src/ui/mod.rs b/studio/src/ui/mod.rs index b712713..d3f0385 100644 --- a/studio/src/ui/mod.rs +++ b/studio/src/ui/mod.rs @@ -3,6 +3,8 @@ use bevy::prelude::*; use self::fps::FpsCounterPlugin; mod fps; + +#[cfg(feature = "wasm")] pub mod inspector; pub struct UiLayerPlugin; @@ -10,5 +12,8 @@ pub struct UiLayerPlugin; impl Plugin for UiLayerPlugin { fn build(&self, app: &mut App) { app.add_plugins(FpsCounterPlugin); + + #[cfg(feature = "wasm")] + app.add_plugins(inspector::InspectorPlugin); } } diff --git a/studio/src/wasm/conv.rs b/studio/src/wasm/conv.rs index e2ae1db..3c176ad 100644 --- a/studio/src/wasm/conv.rs +++ b/studio/src/wasm/conv.rs @@ -23,27 +23,6 @@ export interface ITransform { export type Transform = BevyObject<"Transform", ITransform>; export type GlobalTransform = BevyObject<"GlobalTransform", ITransform>; -export enum MeshPrimitivePrefabType { - Cube, - Plane, - Sphere, - Capsule, - Torus, - Icosphere, -} - -export type MeshPrimitivePrefab = BevyObject<"MeshPrimitivePrefab", MeshPrimitivePrefabType>; - -export type Color = [number, number, number, number]; - -export type BaseColor = BevyObject<"BaseColor", Color>; - -export interface IStandartMaterial { - baseColor: BaseColor; -} - -expoort type Material = BevyObject<"StandartMaterial", IMaterial>; - "#;