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

New backend foundation #308

Merged
merged 35 commits into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c968c77
next
Nazariglez Dec 2, 2023
3c17292
out of destruction, we pave the path to creation
Nazariglez Dec 3, 2023
e6ed2e5
New framework core (#300)
Nazariglez Jan 17, 2024
184d8b3
out of destruction, we pave the path to creation
Nazariglez Dec 3, 2023
f02598b
new backend foundation
Nazariglez Jan 17, 2024
f416105
wip
Nazariglez Jan 17, 2024
78c56ef
empty backend can run now
Nazariglez Jan 18, 2024
95801f6
minor change
Nazariglez Jan 21, 2024
09b86d1
wip: winit
Nazariglez Jan 21, 2024
65fda44
fixes
Nazariglez Jan 21, 2024
af2c593
winit backend compiling (although pretty broken)
Nazariglez Jan 22, 2024
519a33a
example window_open
Nazariglez Jan 22, 2024
924f1d7
some window examples
Nazariglez Jan 22, 2024
a14fd1c
rename windows to window_by_id
Nazariglez Jan 23, 2024
d8522ec
window_initial_position example
Nazariglez Jan 23, 2024
a9b7ac8
wip new winit event loop
Nazariglez Jan 25, 2024
5c303f7
fixed events core
Nazariglez Feb 2, 2024
c55efbd
added gfx crate
Nazariglez Feb 2, 2024
3255e78
wip gfx
Nazariglez Feb 2, 2024
b9bfed7
cleaned up some errors
Nazariglez Feb 3, 2024
e736fd4
sick of lifetimes
Nazariglez Feb 3, 2024
aedd6bc
wip: I hate WGPU and rust right now
Nazariglez Feb 3, 2024
75cfeab
it finally compiles...
Nazariglez Feb 6, 2024
923b6bc
fmt
Nazariglez Feb 6, 2024
e6b5a8f
added gfx_triangle example
Nazariglez Feb 6, 2024
c83cbfa
deps
Nazariglez Jun 8, 2024
1585711
next
Nazariglez Dec 2, 2023
c7ed0c2
out of destruction, we pave the path to creation
Nazariglez Dec 3, 2023
8b6678b
New framework core (#300)
Nazariglez Jan 17, 2024
d5d0e03
new backend foundation
Nazariglez Jan 17, 2024
29abb27
wip: winit
Nazariglez Jan 21, 2024
eaaeb86
added gfx crate
Nazariglez Feb 2, 2024
8fa41e7
draw2d wip
Nazariglez Feb 20, 2024
fd0f531
simple spritebatch
Nazariglez Feb 20, 2024
1cb6e17
minor fixes
Nazariglez Jun 8, 2024
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
2,475 changes: 2,247 additions & 228 deletions Cargo.lock

Large diffs are not rendered by default.

47 changes: 34 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ description = "A simple portable multimedia layer to create apps or games easily
members = [
"crates/notan_core",
"crates/notan_macro2",
"xtask"
"crates/notan_app2",
"crates/notan_gfx",
"xtask",
]

[workspace.package]
Expand All @@ -31,15 +33,17 @@ edition = "2021"
[workspace.dependencies]
notan_core = { path = "crates/notan_core" }
notan_macro2 = { path = "crates/notan_macro2" }
notan_math = { path = "crates/notan_math" }
notan_app2 = { path = "crates/notan_app2" }
notan_gfx = { path = "crates/notan_gfx" }
notan_draw = { path = "crates/notan_draw" }
#notan_input = { path = "crates/notan_input" }
#notan_app = { path = "crates/notan_app" }
#notan_macro = { path = "crates/notan_macro" }
#notan_math = { path = "crates/notan_math" }
#notan_graphics = { path = "crates/notan_graphics" }
#notan_utils = { path = "crates/notan_utils" }
#notan_log = { path = "crates/notan_log" }
#notan_glyph = { path = "crates/notan_glyph" }
#notan_draw = { path = "crates/notan_draw" }
#notan_backend = { path = "crates/notan_backend" }
#notan_egui = { path = "crates/notan_egui" }
#notan_text = { path = "crates/notan_text" }
Expand All @@ -58,28 +62,32 @@ bytemuck = "1.14.0"
anymap = "0.12.1"
arrayvec = "0.7.4"
raw-window-handle = "0.6.0"
bitflags = "2.4.2"
serde = { version = "1.0", features = ["serde_derive"] }
image = { version = "0.24.7", default-features = false, features = ["jpeg", "png", "ico"] }
image = { version = "0.24.8", default-features = false, features = ["jpeg", "png", "ico"] }

# wasm deps
wasm-bindgen = "0.2.89"
wasm-bindgen-futures = "0.4.39"
futures-util = "0.3.29"
web-sys = "0.3.66"
js-sys = "0.3.65"
wasm-bindgen = "0.2.90"
wasm-bindgen-futures = "0.4.40"
futures-util = "0.3.30"
web-sys = "0.3.67"
js-sys = "0.3.67"
cfg_aliases = "0.2.0"

[dependencies]
notan_core.workspace = true
notan_macro2.workspace = true
notan_app2.workspace = true
notan_math.workspace = true
notan_gfx = { workspace = true, optional = true }
notan_draw = { workspace = true, optional = true }
#notan_input.workspace = true
#notan_app.workspace = true
#notan_macro.workspace = true
#notan_math.workspace = true
#notan_graphics.workspace = true
#notan_utils.workspace = true
#notan_log = { workspace = true, optional = true }
#notan_glyph = { workspace = true, optional = true }
#notan_draw = { workspace = true, optional = true }
#notan_backend = { workspace = true, optional = true }
#notan_egui = { workspace = true, optional = true }
#notan_text = { workspace = true, optional = true }
Expand All @@ -88,6 +96,20 @@ notan_macro2.workspace = true
#notan_random = { workspace = true, optional = true }

[features]
default = ["limited_core_events", "winit", "gfx", "wgpu"]
# uses winit as backend
winit = ["notan_app2/winit"]
# enabled gfx module
gfx = ["notan_gfx"]
# uses wgpu as renderer
wgpu = ["notan_gfx?/wgpu"]
# allow to serialize and deserialize internal types with serde
serde = ["notan_core/serde", "notan_app2/serde"]
# use arrayvec instead of vec when possible
limited_core_events = ["notan_core/limited_events"]
#enabled draw2d features
draw2d = ["notan_draw", "gfx"]

#default = ["backend", "log", "draw", "random", "glsl-to-spirv"]
#backend = ["notan_backend"]
#log = ["notan_log"]
Expand Down Expand Up @@ -115,5 +137,4 @@ lto = true

[dev-dependencies]
egui_demo_lib = "0.27.2"
bytemuck = "1.14.0"

bytemuck.workspace = true
24 changes: 24 additions & 0 deletions crates/notan_app2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "notan_app2"
version.workspace = true
authors.workspace = true
edition.workspace = true
homepage.workspace = true
repository.workspace = true
license.workspace = true
readme = "README.md"
description = "Default backend for Notan's app"

[dependencies]
notan_core.workspace = true

log.workspace = true
hashbrown.workspace = true
raw-window-handle.workspace = true
serde = { workspace = true, optional = true }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
winit = { version = "0.29.10", optional = true }

[build-dependencies]
cfg_aliases.workspace = true
9 changes: 9 additions & 0 deletions crates/notan_app2/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use cfg_aliases::cfg_aliases;

fn main() {
cfg_aliases! {
is_web: { target_arch = "wasm32" },
is_winit: { all(not(is_web), feature = "winit") },
is_empty: { all(not(is_web), not(is_winit)) }
}
}
86 changes: 86 additions & 0 deletions crates/notan_app2/src/app.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use crate::{AppConfig, Manager, Window};
use hashbrown::hash_map::{Values, ValuesMut};
use notan_core::window::{NotanApp, WindowConfig, WindowId};
use notan_core::Plugin;

pub struct App {
pub manager: Manager,
main_window: Option<WindowId>,
window_ids: Vec<WindowId>,
}

impl App {
pub fn new() -> Result<Self, String> {
Ok(Self {
manager: Manager::new()?,
main_window: None,
window_ids: vec![],
})
}

pub fn config() -> AppConfig {
AppConfig::default()
}

pub fn create_window(&mut self, attrs: WindowConfig) -> Result<WindowId, String> {
let id = self.manager.create(attrs)?;
self.window_ids.push(id);

// set this as main windows if there is no one
if self.main_window.is_none() {
self.main_window = Some(id);
}

Ok(id)
}

pub fn window_by_id(&mut self, id: WindowId) -> Option<&mut Window> {
self.manager.window(id)
}

pub fn window(&mut self) -> Option<&mut Window> {
self.main_window.and_then(|id| self.window_by_id(id))
}

pub fn set_main_window(&mut self, win_id: WindowId) {
self.main_window = Some(win_id);
}

pub fn window_ids(&self) -> &[WindowId] {
&self.window_ids
}

pub fn windows(&self) -> Values<'_, WindowId, Window> {
self.manager.windows.values()
}

pub fn windows_mut(&mut self) -> ValuesMut<'_, WindowId, Window> {
self.manager.windows.values_mut()
}

pub fn close(&mut self, id: WindowId) {
let closed = self.manager.close(id);
if closed {
// remove from the window_id list
let pos = self
.window_ids
.iter()
.position(|stored_id| *stored_id == id);

if let Some(pos) = pos {
self.window_ids.remove(pos);
}

// set main window as none if this was the main window
if self.main_window == Some(id) {
self.main_window = None;
}
}
}

pub fn exit(&mut self) {
self.manager.exit();
}
}

impl Plugin for App {}
64 changes: 64 additions & 0 deletions crates/notan_app2/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::{runner, App};
use notan_core::events;
use notan_core::window::{NotanWindow, WindowAction, WindowConfig, WindowEvent};
use notan_core::{AppBuilder, AppState, BuildConfig};

pub struct AppConfig {
main_window: Option<WindowConfig>,
auto_redraw: bool,
}

impl Default for AppConfig {
fn default() -> Self {
Self {
main_window: Some(Default::default()),
auto_redraw: true,
}
}
}

impl AppConfig {
pub fn with_windowless(mut self) -> Self {
self.main_window = None;
self
}

pub fn with_window(mut self, attrs: WindowConfig) -> Self {
self.main_window = Some(attrs);
self
}
}

impl<S: AppState> BuildConfig<S> for AppConfig {
fn apply(&mut self, builder: AppBuilder<S>) -> Result<AppBuilder<S>, String> {
let mut app = App::new()?;

// Initialize main windows if is not windowless mode
if let Some(attrs) = self.main_window.take() {
let id = app.create_window(attrs)?;
log::info!("Window '{:?}' created.", id);
}

// Call request_draw on each frame
let builder = if self.auto_redraw {
builder.on(|_: &events::UpdateEvent, app: &mut App| {
app.windows_mut().for_each(|win| win.request_redraw())
})
} else {
builder
};

// Read windows event to set main window and close app when all windows are closed
let builder = builder.on(|evt: &WindowEvent, app: &mut App| match evt.action {
WindowAction::Close => {
if app.window_ids().is_empty() {
app.exit();
}
}
_ => {}
});

// let's add the windows plugin
Ok(builder.add_plugin(app).with_runner(runner))
}
}
44 changes: 44 additions & 0 deletions crates/notan_app2/src/empty/manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use super::window::Window;
use hashbrown::HashMap;
use notan_core::window::{CursorIcon, NotanApp, WindowConfig, WindowId};

#[derive(Default)]
pub struct Manager {
pub(crate) windows: HashMap<WindowId, Window>,
pub(crate) request_exit: bool,
}

impl NotanApp<Window> for Manager {
fn new() -> Result<Self, String> {
Ok(Default::default())
}

fn create(&mut self, attrs: WindowConfig) -> Result<WindowId, String> {
let count = self.windows.len();
let id: WindowId = (count as u64).into();
let win = Window {
id,
size: attrs.size.unwrap_or((800, 600)),
position: attrs.position.unwrap_or((0, 0)),
title: attrs.title.clone(),
cursor: CursorIcon::Default,
resizable: attrs.resizable,
min_size: None,
max_size: None,
};
self.windows.insert(id, win);
Ok(id)
}

fn window(&mut self, id: WindowId) -> Option<&mut Window> {
self.windows.get_mut(&id)
}

fn close(&mut self, id: WindowId) -> bool {
self.windows.remove(&id).is_some()
}

fn exit(&mut self) {
self.request_exit = true;
}
}
9 changes: 9 additions & 0 deletions crates/notan_app2/src/empty/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![cfg(is_empty)]

mod manager;
mod runner;
mod window;

pub use manager::*;
pub use runner::*;
pub use window::*;
27 changes: 27 additions & 0 deletions crates/notan_app2/src/empty/runner.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::app::App;
use notan_core::{AppState, System};

pub fn runner<S: AppState>(mut app: System<S>) -> Result<(), String> {
app.init();

loop {
app.frame_start();
app.update();

let request_exit = app
.get_mut_plugin::<App>()
.ok_or_else(|| "Cannot find Platform plugin.")?
.manager
.request_exit;

app.frame_end();

if request_exit {
break;
}
}

app.close();

Ok(())
}
Loading
Loading