Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

making default functions to closures #899

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 65 additions & 16 deletions nannou/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,74 @@ use winit;
use winit::event_loop::ControlFlow;

/// The user function type for initialising their model.
pub type ModelFn<Model> = fn(&App) -> Model;
pub type ModelFn<Model> = Arc<dyn Fn(&App) -> Model>;
#[macro_export]
macro_rules! model {
($e:expr) => {
{ std::sync::Arc::new($e) }
}
}


/// The user function type for updating their model in accordance with some event.
pub type EventFn<Model, Event> = fn(&App, &mut Model, Event);
pub type EventFn<Model, Event> = Arc<dyn Fn(&App, &mut Model, Event)>;
#[macro_export]
macro_rules! event {
($e:expr) => {
{
use std::sync::Arc;
Arc::new($e)
}
}
}

/// The user function type for updating the user model within the application loop.
pub type UpdateFn<Model> = fn(&App, &mut Model, Update);
pub type UpdateFn<Model> = Arc<dyn Fn(&App, &mut Model, Update)>;
#[macro_export]
macro_rules! update {
($e:expr) => {
{
use std::sync::Arc;
Arc::new($e)
}
}
}

/// The user function type for drawing their model to the surface of a single window.
pub type ViewFn<Model> = fn(&App, &Model, Frame);
pub type ViewFn<Model> = Arc<dyn Fn(&App, &Model, Frame)>;
#[macro_export]
macro_rules! view {
($e:expr) => {
{
use std::sync::Arc;
Arc::new($e)
}
}
}

/// A shorthand version of `ViewFn` for sketches where the user does not need a model.
pub type SketchViewFn = fn(&App, Frame);
pub type SketchViewFn = Arc<dyn Fn(&App, Frame)>;
#[macro_export]
macro_rules! sketch_view {
($e:expr) => {
{
use std::sync::Arc;
Arc::new($e)
}
}
}

/// The user function type allowing them to consume the `model` when the application exits.
pub type ExitFn<Model> = fn(&App, Model);
pub type ExitFn<Model> = Arc<dyn Fn(&App, Model)>;
#[macro_export]
macro_rules! exit {
($e:expr) => {
{
use std::sync::Arc;
Arc::new($e)
}
}
}

/// The **App**'s view function.
enum View<Model = ()> {
Expand Down Expand Up @@ -548,7 +600,7 @@ impl Builder<(), Event> {
/// This is useful for late night hack sessions where you just don't care about all that other
/// stuff, you just want to play around with some ideas or make something pretty.
pub fn sketch(view: SketchViewFn) -> SketchBuilder<Event> {
let mut builder = Builder::new(default_model);
let mut builder = Builder::new(model!(default_model));
builder.default_view = Some(View::Sketch(view));
builder.create_default_window = true;
SketchBuilder { builder }
Expand Down Expand Up @@ -1028,7 +1080,7 @@ impl EventLoopWindowTarget {
// This method is solely used during `window::Builder::build` to allow for
pub(crate) fn as_ref(&self) -> &winit::event_loop::EventLoopWindowTarget<()> {
match *self {
EventLoopWindowTarget::Owned(ref event_loop) => (&**event_loop),
EventLoopWindowTarget::Owned(ref event_loop) => &**event_loop,
EventLoopWindowTarget::Pointer(ptr) => {
// This cast is safe, assuming that the `App`'s `EventLoopWindowTarget` will only
// ever be in the `Pointer` state while the pointer is valid - that is, during the
Expand Down Expand Up @@ -1100,9 +1152,6 @@ fn run_loop<M, E>(
if let Some(model) = model.as_mut() {
let loop_mode = app.loop_mode();
let now = Instant::now();
let mut do_update = |loop_state: &mut LoopState| {
apply_update(&mut app, model, event_fn, update_fn, loop_state, now);
};
match loop_mode {
LoopMode::NTimes { number_of_updates }
if loop_state.total_updates >= number_of_updates as u64 => {}
Expand All @@ -1114,7 +1163,7 @@ fn run_loop<M, E>(
// LoopMode::Wait { updates_before_waiting } =>
// if loop_state.updates_since_event > updates_before_waiting as u64 => {}
_ => {
do_update(&mut loop_state);
apply_update(&mut app, model, event_fn.clone(), update_fn.clone(), &mut loop_state, now);
},
}
}
Expand Down Expand Up @@ -1231,13 +1280,13 @@ fn run_loop<M, E>(
(*raw_view)(&app, &model, raw_frame);
}
None => match default_view {
Some(View::Sketch(view)) => {
Some(View::Sketch(ref view)) => {
let data = frame_data.as_ref().expect("missing `frame_data`");
let frame =
Frame::new_empty(raw_frame, &data.render, &data.capture);
view(&app, frame);
}
Some(View::WithModel(view)) => {
Some(View::WithModel(ref view)) => {
let data = frame_data.as_ref().expect("missing `frame_data`");
let frame =
Frame::new_empty(raw_frame, &data.render, &data.capture);
Expand Down Expand Up @@ -1330,7 +1379,7 @@ fn run_loop<M, E>(

// Process the event with the user's functions and see if we need to exit.
if let Some(model) = model.as_mut() {
exit |= process_and_emit_winit_event::<M, E>(&mut app, model, event_fn, &event);
exit |= process_and_emit_winit_event::<M, E>(&mut app, model, event_fn.clone(), &event);
}

// Set the control flow based on the loop mode.
Expand All @@ -1348,7 +1397,7 @@ fn run_loop<M, E>(
// If we need to exit, call the user's function and update control flow.
if exit {
if let Some(model) = model.take() {
if let Some(exit_fn) = exit_fn {
if let Some(exit_fn) = exit_fn.clone() {
exit_fn(&app, model);
}
}
Expand Down
3 changes: 2 additions & 1 deletion nannou_egui_demo_app/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use nannou::prelude::*;
use nannou::{model, update};
use nannou_egui::{egui_wgpu_backend::epi::App as EguiApp, Egui};

fn main() {
nannou::app(model).update(update).run();
nannou::app(model!(model)).update(update!(update)).run();
}

struct Model {
Expand Down