use dip::{bevy::log::LogPlugin, prelude::*}; fn main() { App::new() // Step 7. Put it all together .add_plugin(DesktopPlugin::::new(Root)) // ui_state attribute macro automatically generates UiStatePlugin .add_plugin(UiStatePlugin) // automatically generated by ui_action macro .add_plugin(UiActionPlugin) .add_plugin(LogPlugin) .add_system(handle_increment) .add_system(handle_decrement) .add_system(handle_reset) .run(); } #[allow(non_snake_case)] fn Root(cx: Scope) -> Element { // Step 5. Select state let count = use_read(&cx, COUNT); let disabled = count.value == 0; let window = use_window::(&cx); cx.render(rsx! { h1 { "Counter Example" } p { "count: {count.value}" } button { // Step 6. Dispatch the action ! onclick: move |_| window.send(UiAction::decrement()), disabled: "{disabled}", "-", } button { onclick: move |_| window.send(UiAction::reset()), disabled: "{disabled}", "Reset" } button { onclick: move |_| window.send(UiAction::increment()), "+", } }) } // Step 1. Define UiState // Name each root state with key and provide a type for it. Each state needs to be a named custom type (either struct or enum). If you want to provide primitive type (i.e. u32) or standard type like String, then try to wrap it in a custom struct like `Count` in this example. // This limitation exists because underneath the hood, `ui_state` macro automatically generates code that insert each // root state as resource in bevy world. If you provide the same type between resources, // then systems cannot determine which resource you're querying to. #[ui_state] struct UiState { count: Count, } #[derive(Clone, Debug, Default)] pub struct Count { value: u32, } // Step 2. Define actions #[derive(Clone, Debug)] pub struct Increment; #[derive(Clone, Debug)] pub struct Decrement; #[derive(Clone, Debug)] pub struct Reset; // Step 3. Implement action creators // `struct #action_creator_impl_name;` is automatically generated by ui_action macro so you don't // need to define it. Each method should return one of the actions you defined in step 2. #[ui_action] impl ActionCreator { fn increment() -> Increment { Increment } fn decrement() -> Decrement { Decrement } fn reset() -> Reset { Reset } } // Step 4. Implement systems to handle each action you defined in step 2 fn handle_increment(mut events: EventReader, mut count: ResMut) { for _ in events.iter() { info!("🧠 Increment"); // 5. Mutate root state resource. // Once all system gets run concurrently, dip rerenders root component with the new state. count.value += 1; } } fn handle_decrement(mut events: EventReader, mut count: ResMut) { for _ in events.iter() { info!("🧠 Decrement"); count.value -= 1; } } fn handle_reset(mut events: EventReader, mut count: ResMut) { for _ in events.iter() { info!("🧠 Reset"); count.value = 0; } }