From acc9c7d5d05e85f8612946f4285324d3dfad4a13 Mon Sep 17 00:00:00 2001
From: StarArawn <toasterthegamer@gmail.com>
Date: Sun, 5 Dec 2021 11:06:03 -0500
Subject: [PATCH] Working on getting global state working.

---
 assets/panel.png                              | Bin 0 -> 1215 bytes
 bevy_kayak_ui/src/bevy_context.rs             |   9 +--
 bevy_kayak_ui/src/lib.rs                      |  73 ++++++++++++------
 .../src/render/unified/font/extract.rs        |   2 +-
 .../src/render/unified/quad/extract.rs        |   2 +-
 kayak_components/src/image.rs                 |  15 ++++
 kayak_core/src/context.rs                     |  17 +++-
 kayak_core/src/lib.rs                         |  11 ++-
 kayak_core/src/render_command.rs              |   3 +
 kayak_core/src/render_primitive.rs            |   4 +
 10 files changed, 97 insertions(+), 39 deletions(-)
 create mode 100644 assets/panel.png
 create mode 100644 kayak_components/src/image.rs

diff --git a/assets/panel.png b/assets/panel.png
new file mode 100644
index 0000000000000000000000000000000000000000..739934c54b3e2103ddc44c3283f03c9dc08ac4a5
GIT binary patch
literal 1215
zcmV;w1VH<VP)<h;3K|Lk000e1NJLTq004jh004jp1^@s6!#-il00001b5ch_0Itp)
z=>Px(c}YY;RCt{2ozHRVFc60~nOvzOGaNEBkQ)_IK`NkxbU+2+<^~Lh%%qAOC?M~U
zNN-W(KNtg!e&09qCVqg$TKm&#g(dm!?e*o$K$6Yw(;mVB=&`TsZvmK@Evw4R%+|A+
znVGE)2irbB_bzN%RY&KV*-7X3DRVuW#j@A4nLRBQCzlt_^>&8WhT6Ta>m$2@t>HVy
zsE5?<v3zs)_WJU**?ro+u1~H|_?rY@A4P!G;b7aJH;3}^{+@mPaXueh=9qlEzuV({
z-e_lzKDOt|yY)4PYfX=z7K`X>Gqd|}LI@G(l3w_&E5ehrCA{YU`hR`P^`8wQ3&J=>
zaAT3$;O+3fzW;URK>Qb_l{z)NeW{a%I4e|i5Q1-U{`;;)>i9NB6M&f=g`6SAT$9v6
z=Qt@B0X)~f{w{kwQ2;(89{Q!>LcIa!R_>*_WJ|qOBut}m+6cX`FA@R%G9_I@A90VK
z1j2Oi5!pw8Y!b+C0OgSz2AUoFdeklerb(|P5XvVf1Oy<?F9A$(%np~MH3A@p@@W*n
zkQ*oP_s9wWr|XavKrUNE6lKyG0j7Ru56**Opg65v0Aas;S|b2qzkC`6fb%sV2N0mG
zEB_?`T7G%7<#a><aiRduSq}iy$G3j(>(M5K!u0S{-F?@dofOKP!1Bnge=xhy!Vs7?
zowI^L69iB=T|eiO1Qt#%^j~ac5d1w5fH({T1xWJ%hJj+RG6>A9V`UJd03G-#SR8Ty
zh#&xQ$N>Z)2M~uG03rxL90VW^NuVIDw}V*^s0CesI1B>?VHgMz_6QOuI|^WdXqkkD
z-T6~65uj{3a{%@SERQCCvR%9&o!iCJ`pcs!uY1V7ND`<+V+6S6Gw<Mf@I#O|o!i9G
z9h40_g$i-<BV%a&<wFi24gwH|okGPS0*HeE#6bY!AOLX?fH>?HE(p7Yi^E2d5J3Rq
zAOLY#8YT!!!yv*aK#1NegP?4(T>ue42O@wtL;!J!0ODjL0E<I)=v*8M<<Yr395g`y
z;vfJ4(x-=e5P&!cK!CPApAdiubODeB0f@u2Z~@Z(pK0M@r2T*E%^<dgDIabJi^J_;
zakw2U4!46Lf&j!p079I+Q6!WP0uToQh=Tyci2_(w)h+FSE8>04R<YvH1&G7F072Lx
z1R@APoMPt#FtOzrUmv~a1Nf7sUZJUd>Z6&Q@50~SIY3&8Qxbu{sJ5j~>V&%KTo=&P
z1%!%jE99D_4sWw*N`k!=x%%lfDKyuzZe5{WT~ZqArXbj<;C<QJ1^9Jj>6)@zKTy&~
zp<r9izP7b+rPJg)|DGp4J$!XI*w(#~R;G9U6k1l!4ppane4V5XHvHfFI!1u)^K<-g
zQ_G(UP4<KcF*SRyP5Sirv_68b&CKrJUSGa8yH8tI)zKSJF2UFPy8hn<tY<S@xi?ma
zLrfOZ<M?@ZeD1XJ@SVQwQ_F3#d#G(=l;_L1bbW<mZ)<AzvZ}t1f69pw0QA_`wLNTh
dpR5cP<{v6bh=U}asq6p%002ovPDHLkV1n3OFF*hQ

literal 0
HcmV?d00001

diff --git a/bevy_kayak_ui/src/bevy_context.rs b/bevy_kayak_ui/src/bevy_context.rs
index 0c2c974..6708d8e 100644
--- a/bevy_kayak_ui/src/bevy_context.rs
+++ b/bevy_kayak_ui/src/bevy_context.rs
@@ -6,11 +6,11 @@ use kayak_core::{
     styles::{Style, StyleProp, Units},
 };
 
-pub struct BevyContext {
-    pub kayak_context: Arc<RwLock<KayakContext>>,
+pub struct BevyContext<'a> {
+    pub kayak_context: Arc<RwLock<KayakContext<'a>>>,
 }
 
-impl BevyContext {
+impl<'a> BevyContext<'a> {
     pub fn new<F: Fn(&mut Style, &mut KayakContext)>(width: f32, height: f32, f: F) -> Self {
         let mut app_styles = Style {
             render_command: StyleProp::Value(RenderCommand::Window),
@@ -23,9 +23,6 @@ impl BevyContext {
 
         if let Ok(mut kayak_context) = kayak_context.write() {
             f(&mut app_styles, &mut kayak_context);
-
-            kayak_context.render();
-
             kayak_context.widget_manager.dirty(true);
         }
 
diff --git a/bevy_kayak_ui/src/lib.rs b/bevy_kayak_ui/src/lib.rs
index fee1bbc..ced7953 100644
--- a/bevy_kayak_ui/src/lib.rs
+++ b/bevy_kayak_ui/src/lib.rs
@@ -1,7 +1,9 @@
 use bevy::{
     input::{mouse::MouseButtonInput, ElementState},
     math::Vec2,
-    prelude::{EventReader, MouseButton, Plugin, Res, ResMut},
+    prelude::{
+        EventReader, IntoExclusiveSystem, IntoSystem, MouseButton, Mut, Plugin, Res, ResMut, World,
+    },
     render2::color::Color,
     window::{CursorMoved, Windows},
 };
@@ -12,7 +14,7 @@ mod render;
 
 pub use bevy_context::BevyContext;
 pub use camera::*;
-use kayak_core::InputEvent;
+use kayak_core::{context::GlobalState, InputEvent};
 
 #[derive(Default)]
 pub struct BevyKayakUIPlugin;
@@ -21,7 +23,7 @@ impl Plugin for BevyKayakUIPlugin {
     fn build(&self, app: &mut bevy::prelude::App) {
         app.add_plugin(render::BevyKayakUIRenderPlugin)
             .add_plugin(camera::KayakUICameraPlugin)
-            .add_system(update);
+            .add_system(update.exclusive_system());
     }
 }
 
@@ -29,40 +31,61 @@ pub(crate) fn to_bevy_color(color: &kayak_core::color::Color) -> Color {
     Color::rgba(color.r, color.g, color.b, color.a)
 }
 
-pub fn update(
-    bevy_context: ResMut<BevyContext>,
-    mut cursor_moved_events: EventReader<CursorMoved>,
-    mut mouse_button_input_events: EventReader<MouseButtonInput>,
-    windows: Res<Windows>,
-) {
-    let window_size = if let Some(window) = windows.get_primary() {
-        Vec2::new(window.width(), window.height())
-    } else {
-        panic!("Couldn't find primary window!");
+pub struct WrappedWorld<'a> {
+    world: &'a mut World,
+}
+
+impl<'a> GlobalState for WrappedWorld<'a> {}
+
+pub fn update(world: &mut World) {
+    let window_size = {
+        let windows = world.get_resource::<Windows>().unwrap();
+        if let Some(window) = windows.get_primary() {
+            Vec2::new(window.width(), window.height())
+        } else {
+            panic!("Couldn't find primary window!");
+        }
     };
 
+    let bevy_context = world.remove_resource::<BevyContext<'static>>().unwrap();
     if let Ok(mut context) = bevy_context.kayak_context.write() {
-        context.render();
+        let mut wrapped_world = WrappedWorld { world };
+        context.render(&mut wrapped_world);
+    }
 
+    if let Ok(mut context) = bevy_context.kayak_context.write() {
         let mut input_events = Vec::new();
-        for event in cursor_moved_events.iter() {
-            input_events.push(InputEvent::MouseMoved((
-                event.position.x as f32,
-                window_size.y - event.position.y as f32,
-            )));
+
+        {
+            let mut cursor_moved_events = world
+                .get_resource_mut::<EventReader<CursorMoved>>()
+                .unwrap();
+            for event in cursor_moved_events.iter() {
+                input_events.push(InputEvent::MouseMoved((
+                    event.position.x as f32,
+                    window_size.y - event.position.y as f32,
+                )));
+            }
         }
 
-        for event in mouse_button_input_events.iter() {
-            match event.button {
-                MouseButton::Left => {
-                    if event.state == ElementState::Pressed {
-                        input_events.push(InputEvent::MouseLeftClick);
+        {
+            let mut mouse_button_input_events = world
+                .get_resource_mut::<EventReader<MouseButtonInput>>()
+                .unwrap();
+            for event in mouse_button_input_events.iter() {
+                match event.button {
+                    MouseButton::Left => {
+                        if event.state == ElementState::Pressed {
+                            input_events.push(InputEvent::MouseLeftClick);
+                        }
                     }
+                    _ => {}
                 }
-                _ => {}
             }
         }
 
         context.process_events(input_events);
     }
+
+    world.insert_resource(bevy_context);
 }
diff --git a/bevy_kayak_ui/src/render/unified/font/extract.rs b/bevy_kayak_ui/src/render/unified/font/extract.rs
index ce8844d..585f124 100644
--- a/bevy_kayak_ui/src/render/unified/font/extract.rs
+++ b/bevy_kayak_ui/src/render/unified/font/extract.rs
@@ -14,7 +14,7 @@ use super::{font::KayakFont, font_mapping::FontMapping};
 
 pub fn extract_texts(
     mut commands: Commands,
-    context: Res<BevyContext>,
+    context: Res<BevyContext<'static>>,
     mut fonts: ResMut<Assets<KayakFont>>,
     font_mapping: Res<FontMapping>,
 ) {
diff --git a/bevy_kayak_ui/src/render/unified/quad/extract.rs b/bevy_kayak_ui/src/render/unified/quad/extract.rs
index 20a4c8e..1290ae5 100644
--- a/bevy_kayak_ui/src/render/unified/quad/extract.rs
+++ b/bevy_kayak_ui/src/render/unified/quad/extract.rs
@@ -10,7 +10,7 @@ use crate::{
     to_bevy_color, BevyContext,
 };
 
-pub fn extract_quads(mut commands: Commands, context: Res<BevyContext>) {
+pub fn extract_quads(mut commands: Commands, context: Res<BevyContext<'static>>) {
     let render_commands = if let Ok(context) = context.kayak_context.read() {
         context.widget_manager.build_render_primitives()
     } else {
diff --git a/kayak_components/src/image.rs b/kayak_components/src/image.rs
new file mode 100644
index 0000000..f67f293
--- /dev/null
+++ b/kayak_components/src/image.rs
@@ -0,0 +1,15 @@
+use kayak_core::{component, rsx, Render, Update};
+
+#[component]
+pub fn Image<Children: Render + Update + Clone>(handle: u16, children: Children) {
+    *styles = Some(Style {
+        render_command: StyleProp::Value(RenderCommand::Image { handle }),
+        ..styles.clone().unwrap_or_default()
+    });
+
+    rsx! {
+        <>
+            {children}
+        </>
+    }
+}
diff --git a/kayak_core/src/context.rs b/kayak_core/src/context.rs
index b18aa0e..bcd89da 100644
--- a/kayak_core/src/context.rs
+++ b/kayak_core/src/context.rs
@@ -1,17 +1,21 @@
 use std::collections::HashMap;
 
+use as_any::AsAny;
 use resources::Ref;
 
 use crate::{node::NodeIndex, widget_manager::WidgetManager, Event, EventType, Index, InputEvent};
 
-pub struct KayakContext {
+pub trait GlobalState: Send + Sync {}
+
+pub struct KayakContext<'a> {
     component_states: HashMap<crate::Index, resources::Resources>,
     current_id: crate::Index,
     pub widget_manager: WidgetManager,
     last_mouse_position: (f32, f32),
+    global_state: Option<&'a mut dyn GlobalState>,
 }
 
-impl std::fmt::Debug for KayakContext {
+impl<'a> std::fmt::Debug for KayakContext<'a> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("KayakContext")
             .field("current_id", &self.current_id)
@@ -19,13 +23,14 @@ impl std::fmt::Debug for KayakContext {
     }
 }
 
-impl KayakContext {
+impl<'a> KayakContext<'a> {
     pub fn new() -> Self {
         Self {
             component_states: HashMap::new(),
             current_id: crate::Index::default(),
             widget_manager: WidgetManager::new(),
             last_mouse_position: (0.0, 0.0),
+            global_state: None,
         }
     }
 
@@ -78,7 +83,9 @@ impl KayakContext {
         }
     }
 
-    pub fn render(&mut self) {
+    pub fn render(&mut self, global_state: &'a mut dyn GlobalState) {
+        self.global_state = Some(global_state);
+
         let dirty_nodes = self.widget_manager.dirty_nodes.clone();
         for node_index in dirty_nodes {
             if self
@@ -97,6 +104,8 @@ impl KayakContext {
 
         self.widget_manager.render();
         self.widget_manager.calculate_layout();
+
+        self.global_state = None;
     }
 
     pub fn process_events(&mut self, input_events: Vec<InputEvent>) {
diff --git a/kayak_core/src/lib.rs b/kayak_core/src/lib.rs
index 47009cc..268b555 100644
--- a/kayak_core/src/lib.rs
+++ b/kayak_core/src/lib.rs
@@ -22,8 +22,15 @@ pub use input_event::*;
 pub use kayak_render_macros::{render, rsx, widget};
 pub use widget::Widget;
 
-pub type Children =
-    Option<Arc<dyn Fn(Option<crate::Index>, &mut crate::context::KayakContext) + Send + Sync>>;
+pub type Children = Option<
+    Arc<
+        dyn for<'global_state> Fn(
+                Option<crate::Index>,
+                &mut crate::context::KayakContext,
+            ) + Send
+            + Sync,
+    >,
+>;
 
 #[derive(Clone)]
 pub struct OnEvent(
diff --git a/kayak_core/src/render_command.rs b/kayak_core/src/render_command.rs
index 31f034e..cb6839f 100644
--- a/kayak_core/src/render_command.rs
+++ b/kayak_core/src/render_command.rs
@@ -9,6 +9,9 @@ pub enum RenderCommand {
         size: f32,
         font: u16,
     },
+    Image {
+        handle: u16,
+    },
 }
 
 impl Default for RenderCommand {
diff --git a/kayak_core/src/render_primitive.rs b/kayak_core/src/render_primitive.rs
index 3208f6c..433c216 100644
--- a/kayak_core/src/render_primitive.rs
+++ b/kayak_core/src/render_primitive.rs
@@ -23,6 +23,9 @@ pub enum RenderPrimitive {
         content: String,
         font: u16,
     },
+    Image {
+        handle: u16,
+    },
 }
 
 impl RenderPrimitive {
@@ -68,6 +71,7 @@ impl From<&Style> for RenderPrimitive {
                 content,
                 font,
             },
+            RenderCommand::Image { handle } => Self::Image { handle },
         }
     }
 }
-- 
GitLab