Add more events and colors

This commit is contained in:
JMS55 2023-12-22 21:36:05 -08:00
parent 7fb22892cc
commit 9bb8a27bb7
6 changed files with 88 additions and 33 deletions

View file

@ -49,8 +49,6 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> El
world.spawn_empty();
});
let (spawn_entity_hovered, enter, exit) = use_hover(cx);
render! {
node {
onclick: move |_| selected_entity.set(None),
@ -60,8 +58,8 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> El
} else {
rsx! {
for (entity, name) in entities {
node {
onclick: move |event| {
Button {
onclick: move |event: Event<()>| {
if Some(entity) == ***selected_entity {
selected_entity.set(None);
} else {
@ -69,8 +67,9 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> El
}
event.stop_propagation();
},
padding: "8",
background_color: if Some(entity) == ***selected_entity { INDIGO_600 } else { NEUTRAL_800 },
base_color: if Some(entity) == ***selected_entity { Some(VIOLET_700) } else { None },
click_color: if Some(entity) == ***selected_entity { Some(VIOLET_400) } else { None },
hover_color: if Some(entity) == ***selected_entity { Some(VIOLET_500) } else { None },
match name.name {
Some(name) => format!("{name}"),
_ => format!("Entity ({:?})", name.entity)
@ -79,19 +78,12 @@ fn SceneTree<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>) -> El
}
}
}
node {
onclick: move |event| {
Button {
onclick: move |event: Event<()>| {
spawn_entity();
event.stop_propagation();
},
onmouse_enter: enter,
onmouse_exit: exit,
padding: "8",
background_color: if spawn_entity_hovered { NEUTRAL_600 } else { NEUTRAL_800 },
text {
text: "Spawn Entity",
text_size: "18"
}
text { text: "Spawn Entity", text_size: "18" }
}
}
}
@ -140,3 +132,38 @@ fn EntityInspector<'a>(cx: Scope, selected_entity: &'a UseState<Option<Entity>>)
}
}
}
#[allow(non_snake_case)]
fn Button<'a>(cx: Scope<'a, ButtonProps<'a>>) -> Element<'a> {
let clicked = use_state(cx, || false);
let hovered = use_state(cx, || false);
let background_color = if **clicked {
cx.props.click_color.unwrap_or(NEUTRAL_500)
} else if **hovered {
cx.props.hover_color.unwrap_or(NEUTRAL_600)
} else {
cx.props.base_color.unwrap_or(NEUTRAL_800)
};
render! {
node {
onclick: move |event| cx.props.onclick.call(event),
onclick_down: |_| clicked.set(true),
onclick_up: |_| clicked.set(false),
onmouse_enter: |_| hovered.set(true),
onmouse_exit: |_| { hovered.set(false); clicked.set(false) },
padding: "8",
background_color: background_color,
&cx.props.children
}
}
}
#[derive(Props)]
struct ButtonProps<'a> {
onclick: EventHandler<'a, Event<()>>,
base_color: Option<&'a str>,
click_color: Option<&'a str>,
hover_color: Option<&'a str>,
children: Element<'a>,
}

View file

@ -1,6 +1,27 @@
// Tailwind v3.4.0 https://tailwindcss.com/docs/customizing-colors
pub const NEUTRAL_50: &'static str = "#fafafa";
pub const NEUTRAL_100: &'static str = "#f5f5f5";
pub const NEUTRAL_200: &'static str = "#e5e5e5";
pub const NEUTRAL_300: &'static str = "#d4d4d4";
pub const NEUTRAL_400: &'static str = "#a3a3a3";
pub const NEUTRAL_500: &'static str = "#737373";
pub const NEUTRAL_600: &'static str = "#525252";
pub const NEUTRAL_800: &'static str = "#27272a";
pub const NEUTRAL_700: &'static str = "#404040";
pub const NEUTRAL_800: &'static str = "#262626";
pub const NEUTRAL_900: &'static str = "#171717";
pub const NEUTRAL_950: &'static str = "#0a0a0a";
pub const INDIGO_600: &'static str = "#4f46e5";
pub const VIOLET_50: &'static str = "#f5f3ff";
pub const VIOLET_100: &'static str = "#ede9fe";
pub const VIOLET_200: &'static str = "#ddd6fe";
pub const VIOLET_300: &'static str = "#c4b5fd";
pub const VIOLET_400: &'static str = "#a78bfa";
pub const VIOLET_500: &'static str = "#8b5cf6";
pub const VIOLET_600: &'static str = "#7c3aed";
pub const VIOLET_700: &'static str = "#6d28d9";
pub const VIOLET_800: &'static str = "#5b21b6";
pub const VIOLET_900: &'static str = "#4c1d95";
pub const VIOLET_950: &'static str = "#2e1065";

View file

@ -9,8 +9,8 @@ use bevy::{
utils::{HashMap, HashSet},
};
use dioxus::{
core::{Event, ScopeId, ScopeState},
hooks::{use_on_destroy, use_state},
core::{ScopeId, ScopeState},
hooks::use_on_destroy,
};
#[derive(Default)]
@ -124,15 +124,6 @@ where
.0
}
pub fn use_hover<'a>(
cx: &'a ScopeState,
) -> (bool, impl FnMut(Event<()>) + 'a, impl FnMut(Event<()>) + 'a) {
let hovered = use_state(cx, || false);
let on_mouse_enter = |_| hovered.set(true);
let on_mouse_exit = |_| hovered.set(false);
(*hovered.get(), on_mouse_enter, on_mouse_exit)
}
pub struct DioxusUiQuery<'a, Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery> {
query_state: QueryState<Q, F>,
world_cell: UnsafeWorldCell<'a>,

View file

@ -7,7 +7,7 @@ use bevy::{
ui::RelativeCursorPosition,
utils::EntityHashSet,
};
use bevy_mod_picking::events::{Click, Out, Over, Pointer};
use bevy_mod_picking::events::{Click, Down, Out, Over, Pointer, Up};
use dioxus::core::ScopeState;
use std::{any::Any, mem, rc::Rc};
@ -16,6 +16,8 @@ use std::{any::Any, mem, rc::Rc};
#[derive(Resource, Default)]
pub struct EventReaders {
click: ManualEventReader<Pointer<Click>>,
click_down: ManualEventReader<Pointer<Down>>,
click_up: ManualEventReader<Pointer<Up>>,
mouse_over: ManualEventReader<Pointer<Over>>,
mouse_out: ManualEventReader<Pointer<Out>>,
mouse_enter: ManualEventReader<MouseEnter>,
@ -26,6 +28,8 @@ impl EventReaders {
pub fn get_dioxus_events(
&mut self,
click: &Events<Pointer<Click>>,
click_down: &Events<Pointer<Down>>,
click_up: &Events<Pointer<Up>>,
mouse_over: &Events<Pointer<Over>>,
mouse_out: &Events<Pointer<Out>>,
mouse_enter: &Events<MouseEnter>,
@ -35,6 +39,12 @@ impl EventReaders {
for event in self.click.read(click) {
events.push((event.target, "click", Rc::new(()), true));
}
for event in self.click_down.read(click_down) {
events.push((event.target, "click_down", Rc::new(()), true));
}
for event in self.click_up.read(click_up) {
events.push((event.target, "click_up", Rc::new(()), true));
}
for event in self.mouse_over.read(mouse_over) {
events.push((event.target, "mouse_over", Rc::new(()), false));
}
@ -54,6 +64,8 @@ impl EventReaders {
pub fn is_supported_event(event: &str) -> bool {
match event {
"click" => true,
"click_down" => true,
"click_up" => true,
"mouse_over" => true,
"mouse_out" => true,
"mouse_enter" => true,
@ -66,6 +78,8 @@ pub mod events {
super::impl_event! [
();
onclick
onclick_down
onclick_up
onmouse_over
onmouse_out
onmouse_enter

View file

@ -1,10 +1,10 @@
mod apply_mutations;
pub mod colors;
mod deferred_system;
mod ecs_hooks;
mod elements;
#[macro_use]
mod events;
mod hooks;
#[cfg(feature = "hot_reload")]
mod hot_reload;
mod parse_attributes;
@ -13,8 +13,8 @@ mod tick;
use self::{
apply_mutations::BevyTemplate,
deferred_system::DeferredSystemRegistry,
ecs_hooks::EcsSubscriptions,
events::{generate_mouse_enter_leave_events, EventReaders, MouseEnter, MouseExit},
hooks::EcsSubscriptions,
tick::tick_dioxus_ui,
};
use bevy::{
@ -27,8 +27,8 @@ use bevy::{
use dioxus::core::{Element, ElementId, Scope, VirtualDom};
pub mod prelude {
pub use super::ecs_hooks::*;
pub use super::elements::*;
pub use super::hooks::*;
pub use super::{DioxusUiBundle, DioxusUiPlugin, DioxusUiRoot};
pub use dioxus;
pub use dioxus::prelude::*;

View file

@ -1,6 +1,6 @@
use crate::{
apply_mutations::apply_mutations, deferred_system::DeferredSystemRegistry,
events::EventReaders, hooks::EcsContext, DioxusUiRoot, UiContext, UiRoot,
ecs_hooks::EcsContext, events::EventReaders, DioxusUiRoot, UiContext, UiRoot,
};
use bevy::{
ecs::{
@ -23,6 +23,8 @@ pub fn tick_dioxus_ui(world: &mut World) {
world.resource(),
world.resource(),
world.resource(),
world.resource(),
world.resource(),
)
});