Skip to content

Commit

Permalink
Enable context dependent app initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
hakolao committed Apr 4, 2024
1 parent 777e341 commit bf762d5
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 48 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Example:
```rust
fn main() {
Glass::new(MyApp, GlassConfig::default()).run();
// Or if you want to avoid Device dependent Option<T> types within your app
Glass::new_and_run(GlassConfig::default(), |e, context| MyApp::new(context));
}

// Organize your app in anyway you like
Expand Down
80 changes: 34 additions & 46 deletions examples/egui_gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@ use glass::{
window::GlassWindow, Glass, GlassApp, GlassConfig, GlassContext, GlassError, RenderData,
};
use wgpu::{CommandEncoder, StoreOp, TextureView};
use winit::{
event::Event,
event_loop::{EventLoop, EventLoopWindowTarget},
};
use winit::{event::Event, event_loop::EventLoopWindowTarget};

fn main() -> Result<(), GlassError> {
Glass::new(GuiApp::default(), GlassConfig::default()).run()
Glass::new_and_run(GlassConfig::default(), |event_loop, context| {
Box::new(GuiApp {
gui: GuiState::new(event_loop, context),
})
})
}

impl GlassApp for GuiApp {
fn start(&mut self, event_loop: &EventLoop<()>, context: &mut GlassContext) {
initialize_gui_app(self, context, event_loop);
}

fn input(
&mut self,
context: &mut GlassContext,
Expand All @@ -34,15 +31,8 @@ impl GlassApp for GuiApp {
}
}

#[derive(Default)]
struct GuiApp {
gui: Option<GuiState>,
}

impl GuiApp {
fn gui(&mut self) -> &mut GuiState {
self.gui.as_mut().unwrap()
}
gui: GuiState,
}

struct GuiState {
Expand All @@ -53,33 +43,31 @@ struct GuiState {
ui_app: DemoWindows,
}

fn initialize_gui_app(
app: &mut GuiApp,
context: &mut GlassContext,
event_loop: &EventLoopWindowTarget<()>,
) {
let ctx = egui::Context::default();
let pixels_per_point = context.primary_render_window().window().scale_factor() as f32;
let egui_winit = egui_winit::State::new(
ctx.clone(),
ViewportId::ROOT,
event_loop,
Some(pixels_per_point),
Some(context.device().limits().max_texture_dimension_2d as usize),
);
let renderer = egui_wgpu::Renderer::new(
context.device(),
GlassWindow::default_surface_format(),
None,
1,
);
app.gui = Some(GuiState {
egui_ctx: ctx,
egui_winit,
renderer,
repaint: false,
ui_app: egui_demo_lib::DemoWindows::default(),
});
impl GuiState {
fn new(event_loop: &EventLoopWindowTarget<()>, context: &mut GlassContext) -> GuiState {
let ctx = egui::Context::default();
let pixels_per_point = context.primary_render_window().window().scale_factor() as f32;
let egui_winit = egui_winit::State::new(
ctx.clone(),
ViewportId::ROOT,
event_loop,
Some(pixels_per_point),
Some(context.device().limits().max_texture_dimension_2d as usize),
);
let renderer = egui_wgpu::Renderer::new(
context.device(),
GlassWindow::default_surface_format(),
None,
1,
);
GuiState {
egui_ctx: ctx,
egui_winit,
renderer,
repaint: false,
ui_app: egui_demo_lib::DemoWindows::default(),
}
}
}

fn update_egui_with_winit_event(app: &mut GuiApp, context: &mut GlassContext, event: &Event<()>) {
Expand All @@ -89,7 +77,7 @@ fn update_egui_with_winit_event(app: &mut GuiApp, context: &mut GlassContext, ev
event,
..
} => {
let gui = app.gui();
let gui = &mut app.gui;
if let Some(window) = context.render_window(*window_id) {
let EventResponse {
consumed,
Expand Down Expand Up @@ -132,7 +120,7 @@ fn render_egui(
egui_winit,
ui_app,
..
} = app.gui();
} = &mut app.gui;
let raw_input = egui_winit.take_egui_input(window.window());
let FullOutput {
shapes,
Expand Down
30 changes: 28 additions & 2 deletions src/glass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,38 @@ impl Glass {
}
}

pub fn run(mut self) -> Result<(), GlassError> {
pub fn run(self) -> Result<(), GlassError> {
let event_loop = match EventLoop::new() {
Ok(e) => e,
Err(e) => return Err(GlassError::EventLoopError(e)),
};
let mut context = GlassContext::new(&event_loop, self.config.clone())?;
let context = GlassContext::new(&event_loop, self.config.clone())?;
self.run_inner(event_loop, context)
}

/// This is useful, if you want to avoid `Option<T>` within your app for anything that depends
/// on `Device` context
pub fn new_and_run(
config: GlassConfig,
mut app_create_fn: impl FnMut(&EventLoop<()>, &mut GlassContext) -> Box<dyn GlassApp>,
) -> Result<(), GlassError> {
let event_loop = match EventLoop::new() {
Ok(e) => e,
Err(e) => return Err(GlassError::EventLoopError(e)),
};
let mut context = GlassContext::new(&event_loop, config.clone())?;
Glass {
app: app_create_fn(&event_loop, &mut context),
config,
}
.run_inner(event_loop, context)
}

fn run_inner(
mut self,
event_loop: EventLoop<()>,
mut context: GlassContext,
) -> Result<(), GlassError> {
self.app.start(&event_loop, &mut context);
let mut runner_state = RunnerState::default();
// Run update at start
Expand Down

0 comments on commit bf762d5

Please sign in to comment.