separate state from rsc

This commit is contained in:
2026-01-01 22:18:08 -05:00
parent 462c0e6416
commit 5da1e9e767
22 changed files with 373 additions and 492 deletions

View File

@@ -1,7 +1,10 @@
use crate::prelude::*;
use arboard::Clipboard;
use iris_core::util::forget_mut;
use std::{marker::Sized, sync::Arc, time::Instant};
use std::{
marker::{PhantomData, Sized},
sync::Arc,
time::Instant,
};
use winit::{
event::{Ime, WindowEvent},
event_loop::{ActiveEventLoop, EventLoopProxy},
@@ -49,53 +52,97 @@ impl DefaultUiState {
}
}
pub trait HasDefaultUiState: Sized + 'static + HasUi {
fn get(&self) -> &DefaultUiState;
fn get_mut(&mut self) -> &mut DefaultUiState;
fn ui_state(&self) -> &DefaultUiState {
HasDefaultUiState::get(self)
}
fn ui_state_mut(&mut self) -> &mut DefaultUiState {
HasDefaultUiState::get_mut(self)
}
fn ui_with_state(&mut self) -> (&mut Ui, &mut DefaultUiState) {
// as long as you're not doing anything actually unhinged this should always work safely
(
unsafe { forget_mut(self.ui_mut()) },
HasDefaultUiState::get_mut(self),
)
}
pub trait HasAppEvent {
type Event: 'static;
}
pub trait DefaultAppState: RunEvents + HasDefaultUiState {
type Event: 'static = ();
fn new(ui_state: DefaultUiState, proxy: Proxy<Self::Event>) -> Self;
impl<T> HasAppEvent for T {
type Event = ();
}
pub trait HasDefaultUiState: Sized + 'static + HasAppEvent {
fn default_state(&self) -> &DefaultUiState;
fn default_state_mut(&mut self) -> &mut DefaultUiState;
}
pub trait DefaultAppState: HasDefaultUiState {
fn new(ui_state: DefaultUiState, rsc: &mut DefaultRsc<Self>, proxy: Proxy<Self::Event>)
-> Self;
#[allow(unused_variables)]
fn event(&mut self, event: Self::Event) {}
fn event(&mut self, event: Self::Event, rsc: &mut DefaultRsc<Self>) {}
#[allow(unused_variables)]
fn exit(&mut self) {}
fn exit(&mut self, rsc: &mut DefaultRsc<Self>) {}
#[allow(unused_variables)]
fn window_event(&mut self, event: WindowEvent) {}
fn window_event(&mut self, event: WindowEvent, rsc: &mut DefaultRsc<Self>) {}
fn window_attributes() -> WindowAttributes {
Default::default()
}
}
impl<State: DefaultAppState> AppState for State {
pub struct DefaultRsc<State> {
pub ui: Ui,
pub events: EventManager<Self>,
_state: PhantomData<State>,
}
impl<State> Default for DefaultRsc<State> {
fn default() -> Self {
Self {
ui: Default::default(),
events: Default::default(),
_state: Default::default(),
}
}
}
impl<State> HasUi for DefaultRsc<State> {
fn ui(&self) -> &Ui {
&self.ui
}
fn ui_mut(&mut self) -> &mut Ui {
&mut self.ui
}
}
impl<State: 'static> HasEvents for DefaultRsc<State> {
type State = State;
fn events(&self) -> &EventManager<Self> {
&self.events
}
fn events_mut(&mut self) -> &mut EventManager<Self> {
&mut self.events
}
}
pub struct DefaultApp<State: DefaultAppState> {
rsc: DefaultRsc<State>,
state: State,
}
// impl StateLike for DefaultRsc<State> {
// }
//
impl<State: DefaultAppState> AppState for DefaultApp<State> {
type Event = State::Event;
fn new(event_loop: &ActiveEventLoop, proxy: EventLoopProxy<Self::Event>) -> Self {
let window = event_loop.create_window(Self::window_attributes()).unwrap();
Self::new(DefaultUiState::new(window), proxy)
let window = event_loop
.create_window(State::window_attributes())
.unwrap();
let mut rsc = DefaultRsc::default();
let state = State::new(DefaultUiState::new(window), &mut rsc, proxy);
Self { rsc, state }
}
fn event(&mut self, event: Self::Event, _: &ActiveEventLoop) {
self.event(event);
self.state.event(event, &mut self.rsc);
}
fn window_event(&mut self, event: WindowEvent, event_loop: &ActiveEventLoop) {
let events = unsafe { forget_mut(self.events_mut()) };
let ui_state = HasDefaultUiState::get_mut(self);
let ui_state = self.state.default_state_mut();
let input_changed = ui_state.input.event(&event);
let cursor_state = ui_state.cursor_state().clone();
let old = ui_state.focus;
@@ -104,9 +151,11 @@ impl<State: DefaultAppState> AppState for State {
}
if input_changed {
let window_size = ui_state.window_size();
self.run_sensors(&cursor_state, window_size);
self.rsc
.run_sensors(&mut self.state, &cursor_state, window_size);
}
let (mut ui, mut ui_state) = self.ui_with_state();
let ui = &mut self.rsc.ui;
let ui_state = self.state.default_state_mut();
if old != ui_state.focus
&& let Some(old) = old
{
@@ -115,7 +164,7 @@ impl<State: DefaultAppState> AppState for State {
match &event {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => {
ui.update(events);
ui.update(&mut self.rsc.events);
ui_state.renderer.update(ui);
ui_state.renderer.draw();
}
@@ -134,13 +183,13 @@ impl<State: DefaultAppState> AppState for State {
ui_state.window.set_ime_allowed(false);
}
TextInputResult::Submit => {
self.run_event::<Submit>(sel, &mut ());
self.rsc.run_event::<Submit>(sel, &mut (), &mut self.state);
}
TextInputResult::Paste => {
if let Ok(t) = ui_state.clipboard.get_text() {
text.insert(&t);
}
self.run_event::<Edited>(sel, &mut ());
self.rsc.run_event::<Edited>(sel, &mut (), &mut self.state);
}
TextInputResult::Copy(text) => {
if let Err(err) = ui_state.clipboard.set_text(text) {
@@ -148,7 +197,7 @@ impl<State: DefaultAppState> AppState for State {
}
}
TextInputResult::Used => {
self.run_event::<Edited>(sel, &mut ());
self.rsc.run_event::<Edited>(sel, &mut (), &mut self.state);
}
TextInputResult::Unused => {}
}
@@ -172,15 +221,15 @@ impl<State: DefaultAppState> AppState for State {
}
_ => (),
}
self.window_event(event);
(ui, ui_state) = self.ui_with_state();
if ui.needs_redraw() {
self.state.window_event(event, &mut self.rsc);
let ui_state = self.state.default_state_mut();
if self.rsc.ui.needs_redraw() {
ui_state.renderer.window().request_redraw();
}
ui_state.input.end_frame();
}
fn exit(&mut self) {
self.exit();
self.state.exit(&mut self.rsc);
}
}