2023-12-13 03:47:14 +00:00
|
|
|
use bevy::{
|
|
|
|
app::{App, Startup},
|
2023-12-17 05:21:32 +00:00
|
|
|
core::{DebugName, Name},
|
2023-12-13 03:47:14 +00:00
|
|
|
core_pipeline::core_2d::Camera2dBundle,
|
2023-12-17 05:33:13 +00:00
|
|
|
ecs::{entity::Entity, query::Without, system::Commands, world::World},
|
2023-12-13 03:47:14 +00:00
|
|
|
ui::{node_bundles::NodeBundle, Node},
|
|
|
|
DefaultPlugins,
|
|
|
|
};
|
|
|
|
use bevy_dioxus::{
|
|
|
|
bevy_mod_picking::DefaultPickingPlugins, colors::*, dioxus::prelude::*, hooks::*,
|
|
|
|
DioxusUiBundle, DioxusUiPlugin, DioxusUiRoot,
|
|
|
|
};
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
App::new()
|
|
|
|
.add_plugins((DefaultPlugins, DioxusUiPlugin, DefaultPickingPlugins))
|
|
|
|
.add_systems(Startup, |mut commands: Commands| {
|
|
|
|
commands.spawn(DioxusUiBundle {
|
2023-12-16 20:54:01 +00:00
|
|
|
dioxus_ui_root: DioxusUiRoot(Editor),
|
2023-12-13 03:47:14 +00:00
|
|
|
node_bundle: NodeBundle::default(),
|
|
|
|
});
|
2023-12-17 05:21:32 +00:00
|
|
|
commands.spawn((Camera2dBundle::default(), Name::new("Camera")));
|
2023-12-13 03:47:14 +00:00
|
|
|
})
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[component]
|
|
|
|
fn Editor(cx: Scope) -> Element {
|
2023-12-16 04:31:00 +00:00
|
|
|
// TODO: When selected entity is despawned, need to reset this to None
|
2023-12-13 03:47:14 +00:00
|
|
|
let selected_entity = use_state(cx, || Option::<Entity>::None);
|
|
|
|
|
|
|
|
render! {
|
2023-12-17 04:59:19 +00:00
|
|
|
div {
|
|
|
|
width: "100vw",
|
|
|
|
height: "100vh",
|
|
|
|
justify_content: "space-between",
|
|
|
|
SceneTree { selected_entity: selected_entity }
|
|
|
|
EntityInspector { selected_entity: selected_entity }
|
|
|
|
}
|
2023-12-13 03:47:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[component]
|
|
|
|
fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> Element {
|
|
|
|
let entities = use_query_filtered::<(Entity, DebugName), Without<Node>>(cx);
|
|
|
|
let entities = entities.query();
|
|
|
|
let mut entities = entities.into_iter().collect::<Vec<_>>();
|
|
|
|
entities.sort_by_key(|(entity, _)| *entity);
|
|
|
|
|
2023-12-17 05:33:13 +00:00
|
|
|
let spawn_entity = use_system(cx, |world: &mut World| {
|
|
|
|
world.spawn_empty();
|
|
|
|
});
|
|
|
|
|
2023-12-13 03:47:14 +00:00
|
|
|
render! {
|
|
|
|
div {
|
2023-12-16 04:31:00 +00:00
|
|
|
onclick: move |_| selected_entity.set(None),
|
2023-12-13 03:47:14 +00:00
|
|
|
flex_direction: "column",
|
|
|
|
if entities.is_empty() {
|
|
|
|
rsx! { "No entities exist" }
|
|
|
|
} else {
|
|
|
|
rsx! {
|
|
|
|
for (entity, name) in entities {
|
|
|
|
div {
|
|
|
|
onclick: move |_| selected_entity.set(Some(entity)),
|
2023-12-17 05:21:32 +00:00
|
|
|
padding: "8",
|
2023-12-13 03:47:14 +00:00
|
|
|
background_color: if Some(entity) == ***selected_entity { INDIGO_600 } else { NEUTRAL_800 },
|
2023-12-17 05:21:32 +00:00
|
|
|
match name.name {
|
|
|
|
Some(name) => format!("{name}"),
|
|
|
|
_ => format!("Entity ({:?})", name.entity)
|
|
|
|
}
|
2023-12-13 03:47:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-12-17 05:33:13 +00:00
|
|
|
div {
|
|
|
|
onclick: move |_| spawn_entity(),
|
|
|
|
padding: "8",
|
|
|
|
background_color: NEUTRAL_800,
|
|
|
|
"Spawn Entity"
|
|
|
|
}
|
2023-12-13 03:47:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[component]
|
|
|
|
fn EntityInspector<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> Element {
|
|
|
|
render! {
|
|
|
|
if selected_entity.is_none() {
|
|
|
|
"Select an entity to view its components"
|
|
|
|
} else {
|
|
|
|
"TODO: Component widgets"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|