@@ -1,9 +0,0 @@ | |||
[submodule "asparit"] | |||
path = asparit | |||
url = git@github.com:Bergmann89/asparit.git | |||
[submodule "async-ecs"] | |||
path = async-ecs | |||
url = git@github.com:Bergmann89/async-ecs.git | |||
[submodule "async-ecs-derive"] | |||
path = async-ecs-derive | |||
url = git@github.com:Bergmann89/async-ecs-derive.git |
@@ -8,9 +8,9 @@ checksum = "d9fe5e32de01730eb1f6b7f5b51c17e03e2325bf40a74f754f04f130043affff" | |||
[[package]] | |||
name = "ahash" | |||
version = "0.4.6" | |||
version = "0.3.8" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "f6789e291be47ace86a60303502173d84af8327e3627ecf334356ee0f87a164c" | |||
checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" | |||
[[package]] | |||
name = "aho-corasick" | |||
@@ -41,39 +41,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" | |||
[[package]] | |||
name = "asparit" | |||
version = "0.1.0" | |||
dependencies = [ | |||
"futures", | |||
"num_cpus", | |||
"rayon-core", | |||
"tokio", | |||
] | |||
[[package]] | |||
name = "async-ecs" | |||
version = "0.1.0" | |||
dependencies = [ | |||
"asparit", | |||
"async-ecs-derive", | |||
"crossbeam-queue", | |||
"futures", | |||
"hashbrown", | |||
"hibitset", | |||
"log", | |||
"mopa", | |||
"thiserror", | |||
"tokio", | |||
] | |||
[[package]] | |||
name = "async-ecs-derive" | |||
version = "0.1.0" | |||
dependencies = [ | |||
"proc-macro2", | |||
"quote", | |||
"syn", | |||
] | |||
name = "arrayvec" | |||
version = "0.5.2" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" | |||
[[package]] | |||
name = "atom" | |||
@@ -116,12 +87,6 @@ version = "1.3.4" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" | |||
[[package]] | |||
name = "bytes" | |||
version = "0.6.0" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "e0dcbc35f504eb6fc275a6d20e4ebcda18cf50d40ba6fabff8c711fa16cb3b16" | |||
[[package]] | |||
name = "calloop" | |||
version = "0.6.5" | |||
@@ -294,7 +259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" | |||
dependencies = [ | |||
"cfg-if 1.0.0", | |||
"crossbeam-utils", | |||
"crossbeam-utils 0.8.1", | |||
] | |||
[[package]] | |||
@@ -305,18 +270,18 @@ checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" | |||
dependencies = [ | |||
"cfg-if 1.0.0", | |||
"crossbeam-epoch", | |||
"crossbeam-utils", | |||
"crossbeam-utils 0.8.1", | |||
] | |||
[[package]] | |||
name = "crossbeam-epoch" | |||
version = "0.9.0" | |||
version = "0.9.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f" | |||
checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" | |||
dependencies = [ | |||
"cfg-if 1.0.0", | |||
"const_fn", | |||
"crossbeam-utils", | |||
"crossbeam-utils 0.8.1", | |||
"lazy_static", | |||
"memoffset", | |||
"scopeguard", | |||
@@ -324,23 +289,34 @@ dependencies = [ | |||
[[package]] | |||
name = "crossbeam-queue" | |||
version = "0.3.0" | |||
version = "0.2.3" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "6b2a58563f049aa3bae172bc4120f093b5901161c629f280a1f40ba55317d774" | |||
checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" | |||
dependencies = [ | |||
"cfg-if 1.0.0", | |||
"crossbeam-utils", | |||
"cfg-if 0.1.10", | |||
"crossbeam-utils 0.7.2", | |||
"maybe-uninit", | |||
] | |||
[[package]] | |||
name = "crossbeam-utils" | |||
version = "0.8.0" | |||
version = "0.7.2" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" | |||
dependencies = [ | |||
"autocfg", | |||
"cfg-if 0.1.10", | |||
"lazy_static", | |||
] | |||
[[package]] | |||
name = "crossbeam-utils" | |||
version = "0.8.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" | |||
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" | |||
dependencies = [ | |||
"autocfg", | |||
"cfg-if 1.0.0", | |||
"const_fn", | |||
"lazy_static", | |||
] | |||
@@ -411,6 +387,12 @@ version = "1.2.0" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" | |||
[[package]] | |||
name = "either" | |||
version = "1.6.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" | |||
[[package]] | |||
name = "env_logger" | |||
version = "0.8.2" | |||
@@ -670,11 +652,12 @@ dependencies = [ | |||
[[package]] | |||
name = "hashbrown" | |||
version = "0.9.1" | |||
version = "0.7.2" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" | |||
checksum = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf" | |||
dependencies = [ | |||
"ahash", | |||
"autocfg", | |||
] | |||
[[package]] | |||
@@ -693,6 +676,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "93a1bb8316a44459a7d14253c4d28dd7395cbd23cc04a68c46e851b8e46d64b1" | |||
dependencies = [ | |||
"atom", | |||
"rayon", | |||
] | |||
[[package]] | |||
@@ -826,9 +810,9 @@ dependencies = [ | |||
[[package]] | |||
name = "memoffset" | |||
version = "0.5.6" | |||
version = "0.6.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" | |||
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" | |||
dependencies = [ | |||
"autocfg", | |||
] | |||
@@ -846,25 +830,12 @@ dependencies = [ | |||
"kernel32-sys", | |||
"libc", | |||
"log", | |||
"miow 0.2.1", | |||
"miow", | |||
"net2", | |||
"slab", | |||
"winapi 0.2.8", | |||
] | |||
[[package]] | |||
name = "mio" | |||
version = "0.7.6" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "f33bc887064ef1fd66020c9adfc45bb9f33d75a42096c81e7c56c65b75dd1a8b" | |||
dependencies = [ | |||
"libc", | |||
"log", | |||
"miow 0.3.6", | |||
"ntapi", | |||
"winapi 0.3.9", | |||
] | |||
[[package]] | |||
name = "mio-extras" | |||
version = "2.0.6" | |||
@@ -873,7 +844,7 @@ checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" | |||
dependencies = [ | |||
"lazycell", | |||
"log", | |||
"mio 0.6.22", | |||
"mio", | |||
"slab", | |||
] | |||
@@ -889,16 +860,6 @@ dependencies = [ | |||
"ws2_32-sys", | |||
] | |||
[[package]] | |||
name = "miow" | |||
version = "0.3.6" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" | |||
dependencies = [ | |||
"socket2", | |||
"winapi 0.3.9", | |||
] | |||
[[package]] | |||
name = "mopa" | |||
version = "0.2.2" | |||
@@ -975,21 +936,22 @@ dependencies = [ | |||
[[package]] | |||
name = "nom" | |||
version = "6.0.1" | |||
version = "5.1.2" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0" | |||
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" | |||
dependencies = [ | |||
"memchr", | |||
"version_check", | |||
] | |||
[[package]] | |||
name = "ntapi" | |||
version = "0.3.6" | |||
name = "nom" | |||
version = "6.0.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" | |||
checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0" | |||
dependencies = [ | |||
"winapi 0.3.9", | |||
"memchr", | |||
"version_check", | |||
] | |||
[[package]] | |||
@@ -1222,6 +1184,18 @@ dependencies = [ | |||
"libc", | |||
] | |||
[[package]] | |||
name = "rayon" | |||
version = "1.5.0" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" | |||
dependencies = [ | |||
"autocfg", | |||
"crossbeam-deque", | |||
"either", | |||
"rayon-core", | |||
] | |||
[[package]] | |||
name = "rayon-core" | |||
version = "1.9.0" | |||
@@ -1230,7 +1204,7 @@ checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" | |||
dependencies = [ | |||
"crossbeam-channel", | |||
"crossbeam-deque", | |||
"crossbeam-utils", | |||
"crossbeam-utils 0.8.1", | |||
"lazy_static", | |||
"num_cpus", | |||
] | |||
@@ -1307,14 +1281,25 @@ dependencies = [ | |||
] | |||
[[package]] | |||
name = "signal-hook-registry" | |||
version = "1.2.2" | |||
name = "shred" | |||
version = "0.10.2" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab" | |||
checksum = "c5f08237e667ac94ad20f8878b5943d91a93ccb231428446c57c21c57779016d" | |||
dependencies = [ | |||
"libc", | |||
"arrayvec", | |||
"hashbrown", | |||
"mopa", | |||
"rayon", | |||
"smallvec", | |||
"tynm", | |||
] | |||
[[package]] | |||
name = "shrev" | |||
version = "1.1.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "b5752e017e03af9d735b4b069f53b7a7fd90fefafa04d8bd0c25581b0bff437f" | |||
[[package]] | |||
name = "slab" | |||
version = "0.4.2" | |||
@@ -1347,25 +1332,10 @@ dependencies = [ | |||
"wayland-protocols", | |||
] | |||
[[package]] | |||
name = "socket2" | |||
version = "0.3.17" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902" | |||
dependencies = [ | |||
"cfg-if 1.0.0", | |||
"libc", | |||
"redox_syscall", | |||
"winapi 0.3.9", | |||
] | |||
[[package]] | |||
name = "space-crush" | |||
version = "0.1.0" | |||
dependencies = [ | |||
"asparit", | |||
"async-ecs", | |||
"async-ecs-derive", | |||
"env_logger", | |||
"futures", | |||
"gl", | |||
@@ -1374,10 +1344,28 @@ dependencies = [ | |||
"log", | |||
"num_cpus", | |||
"rand", | |||
"shrev", | |||
"specs", | |||
"thiserror", | |||
"tokio", | |||
] | |||
[[package]] | |||
name = "specs" | |||
version = "0.16.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "fff28a29366aff703d5da8a7e2c8875dc8453ac1118f842cbc0fa70c7db51240" | |||
dependencies = [ | |||
"crossbeam-queue", | |||
"hashbrown", | |||
"hibitset", | |||
"log", | |||
"rayon", | |||
"shred", | |||
"shrev", | |||
"tuple_utils", | |||
] | |||
[[package]] | |||
name = "strsim" | |||
version = "0.9.3" | |||
@@ -1440,30 +1428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "9dfe2523e6fa84ddf5e688151d4e5fddc51678de9752c6512a24714c23818d61" | |||
dependencies = [ | |||
"autocfg", | |||
"bytes", | |||
"futures-core", | |||
"lazy_static", | |||
"libc", | |||
"memchr", | |||
"mio 0.7.6", | |||
"num_cpus", | |||
"parking_lot", | |||
"pin-project-lite", | |||
"signal-hook-registry", | |||
"slab", | |||
"tokio-macros", | |||
"winapi 0.3.9", | |||
] | |||
[[package]] | |||
name = "tokio-macros" | |||
version = "0.3.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "21d30fdbb5dc2d8f91049691aa1a9d4d4ae422a21c334ce8936e5886d30c5c45" | |||
dependencies = [ | |||
"proc-macro2", | |||
"quote", | |||
"syn", | |||
] | |||
[[package]] | |||
@@ -1481,6 +1446,21 @@ version = "0.6.2" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" | |||
[[package]] | |||
name = "tuple_utils" | |||
version = "0.3.0" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "44834418e2c5b16f47bedf35c28e148db099187dd5feee6367fb2525863af4f1" | |||
[[package]] | |||
name = "tynm" | |||
version = "0.1.6" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "a4df2caa2dc9c3d1f7641ba981f4cd40ab229775aa7aeb834c9ab2850d50623d" | |||
dependencies = [ | |||
"nom 5.1.2", | |||
] | |||
[[package]] | |||
name = "unicode-xid" | |||
version = "0.2.1" | |||
@@ -1652,7 +1632,7 @@ dependencies = [ | |||
"lazy_static", | |||
"libc", | |||
"log", | |||
"mio 0.6.22", | |||
"mio", | |||
"mio-extras", | |||
"ndk", | |||
"ndk-glue", | |||
@@ -1695,7 +1675,7 @@ version = "0.3.3" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "3a9a231574ae78801646617cefd13bfe94be907c0e4fa979cfd8b770aa3c5d08" | |||
dependencies = [ | |||
"nom", | |||
"nom 6.0.1", | |||
] | |||
[[package]] | |||
@@ -1,8 +1,5 @@ | |||
[workspace] | |||
members = [ | |||
"asparit", | |||
"async-ecs", | |||
"async-ecs-derive", | |||
"gl", | |||
"glc", | |||
"space-crush", | |||
@@ -12,9 +9,6 @@ default-members = [ | |||
] | |||
[patch.crates-io] | |||
asparit = { path = "./asparit" } | |||
async-ecs = { path = "./async-ecs" } | |||
async-ecs-derive = { path = "./async-ecs-derive" } | |||
gl = { path = "./gl" } | |||
glc = { path = "./glc" } | |||
space-crush = { path = "./space-crush" } |
@@ -1 +0,0 @@ | |||
Subproject commit e3d7c56297232aa66e720cc0766b1c25bc11420d |
@@ -1 +0,0 @@ | |||
Subproject commit b2e25967b55b968d8955d285a67fceaa6a257271 |
@@ -1 +0,0 @@ | |||
Subproject commit 7a33669aa8f000d15e56209dcf93f81112f08a24 |
@@ -30,7 +30,7 @@ fn main() { | |||
}, | |||
}; | |||
Registry::new(Api::Gl, (4, 5), Profile::Core, Fallbacks::All, []) | |||
Registry::new(Api::Gl, (4, 5), Profile::Compatibility, Fallbacks::All, []) | |||
.write_bindings(generator, &mut file) | |||
.unwrap(); | |||
} | |||
@@ -94,10 +94,11 @@ pub struct Shader { | |||
} | |||
impl Shader { | |||
pub fn from_string(type_: Type, source: String) -> Result<Self, Error> { | |||
pub fn from_string(type_: Type, mut source: String) -> Result<Self, Error> { | |||
let id = gl::create_shader(type_.as_enum()); | |||
let id = Error::err_if(&0, id)?; | |||
source.push('\0'); | |||
let source = source.as_ptr() as *const i8; | |||
let source: *const *const i8 = &source; | |||
@@ -5,16 +5,15 @@ authors = ["Bergmann89 <info@bergmann89.de>"] | |||
edition = "2018" | |||
[dependencies] | |||
asparit = { version = "0.1", default-features = false, features = [ "tokio-executor" ] } | |||
async-ecs = "0.1" | |||
async-ecs-derive = "0.1" | |||
env_logger = "0.8" | |||
futures = "0.3" | |||
gl = { version = "0.1", features = [ "use_log_crate", "generate_debug" ] } | |||
gl = { version = "0.1", features = [ "use_log_crate" ] } | |||
glc = "0.1" | |||
glutin = "0.25" | |||
log = { version = "0.4", features = [ "max_level_trace", "release_max_level_warn" ] } | |||
num_cpus = "1.13" | |||
rand = "0.7" | |||
shrev = "1.1" | |||
specs = "0.16" | |||
thiserror = "1.0" | |||
tokio = "0.3" |
@@ -1,26 +0,0 @@ | |||
use async_ecs::{Dispatcher, World}; | |||
use crate::{render::Background, Error}; | |||
pub struct App { | |||
world: World, | |||
dispatcher: Dispatcher, | |||
} | |||
impl App { | |||
pub fn new() -> Result<Self, Error> { | |||
let mut world = World::default(); | |||
let dispatcher = Dispatcher::setup_builder(&mut world) | |||
.with_local(Background::new()?, "render_background", &[])? | |||
.build(); | |||
Ok(Self { world, dispatcher }) | |||
} | |||
pub async fn progress(&mut self) -> Result<(), Error> { | |||
self.dispatcher.dispatch(&self.world).await?; | |||
self.world.maintain().await; | |||
Ok(()) | |||
} | |||
} |
@@ -0,0 +1,56 @@ | |||
use glutin::{ | |||
event::{Event, WindowEvent as GlutinWindowEvent}, | |||
event_loop::{ControlFlow, EventLoop}, | |||
platform::desktop::EventLoopExtDesktop, | |||
}; | |||
use shrev::EventChannel; | |||
use specs::World; | |||
pub struct Events { | |||
event_loop: EventLoop<()>, | |||
} | |||
impl Events { | |||
pub fn new(world: &mut World) -> Self { | |||
world.insert(EventChannel::<WindowEvent>::default()); | |||
Self { | |||
event_loop: EventLoop::new(), | |||
} | |||
} | |||
} | |||
impl Events { | |||
pub fn handle(&self) -> &EventLoop<()> { | |||
&self.event_loop | |||
} | |||
pub fn process(&mut self, world: &World) { | |||
let mut channel = world.fetch_mut::<EventChannel<WindowEvent>>(); | |||
self.event_loop.run_return(|event, _target, flow_control| { | |||
*flow_control = ControlFlow::Poll; | |||
match event { | |||
Event::MainEventsCleared | Event::RedrawRequested(_) => { | |||
*flow_control = ControlFlow::Exit; | |||
} | |||
Event::WindowEvent { event, .. } => match event { | |||
GlutinWindowEvent::Resized(pos) => { | |||
channel.single_write(WindowEvent::Resize(pos.width, pos.height)); | |||
} | |||
GlutinWindowEvent::CloseRequested => { | |||
channel.single_write(WindowEvent::Close); | |||
} | |||
_ => (), | |||
}, | |||
_ => (), | |||
} | |||
}); | |||
} | |||
} | |||
pub enum WindowEvent { | |||
Resize(u32, u32), | |||
Close, | |||
} |
@@ -0,0 +1,58 @@ | |||
use std::mem::size_of; | |||
use glc::{ | |||
array_buffer::{ArrayBuffer, Target, Usage}, | |||
misc::Bindable, | |||
vertex_array::{DataType, VertexArray}, | |||
}; | |||
use crate::Error; | |||
pub struct Geometry { | |||
quad: VertexArray, | |||
} | |||
impl Geometry { | |||
pub fn new() -> Result<Self, Error> { | |||
Ok(Self { | |||
quad: create_quad_array()?, | |||
}) | |||
} | |||
pub fn render_quad(&self) { | |||
self.quad.bind(); | |||
gl::draw_arrays(gl::TRIANGLE_FAN, 0, 4); | |||
self.quad.unbind(); | |||
} | |||
} | |||
#[repr(C, packed)] | |||
#[derive(Debug, Copy, Clone, PartialEq)] | |||
struct Vertex { | |||
pub x: f32, | |||
pub y: f32, | |||
} | |||
fn create_quad_array() -> Result<VertexArray, Error> { | |||
let vertices = &[ | |||
Vertex { x: -1.0, y: -1.0 }, | |||
Vertex { x: 1.0, y: -1.0 }, | |||
Vertex { x: 1.0, y: 1.0 }, | |||
Vertex { x: -1.0, y: 1.0 }, | |||
]; | |||
const STRIDE_POS: gl::GLsizei = size_of::<Vertex>() as gl::GLsizei; | |||
const OFFSET_POS: gl::GLsizei = 0; | |||
let mut array_buffer = ArrayBuffer::new(Target::ArrayBuffer)?; | |||
array_buffer.buffer_data(Usage::StaticDraw, vertices)?; | |||
let vertex_array = VertexArray::builder() | |||
.bind_buffer(array_buffer) | |||
.vertex_attrib_pointer(0, 2, DataType::Float, false, STRIDE_POS, OFFSET_POS)? | |||
.build()?; | |||
Ok(vertex_array) | |||
} |
@@ -0,0 +1,3 @@ | |||
pub mod events; | |||
pub mod geometry; | |||
pub mod window; |
@@ -0,0 +1,52 @@ | |||
use glutin::{ | |||
dpi::{PhysicalPosition, PhysicalSize}, | |||
event_loop::EventLoop, | |||
window::Window as GlutinWindow, | |||
window::WindowBuilder, | |||
Api, ContextBuilder, ContextWrapper, GlProfile, GlRequest, PossiblyCurrent, | |||
}; | |||
use crate::Error; | |||
pub struct Window { | |||
context: ContextWrapper<PossiblyCurrent, GlutinWindow>, | |||
} | |||
impl Window { | |||
pub fn new<T>(event_loop: &EventLoop<T>) -> Result<Self, Error> { | |||
let window_builder = WindowBuilder::new() | |||
.with_title("space-crush") | |||
.with_visible(true) | |||
.with_inner_size(PhysicalSize::new(WINDOW_WIDTH, WINDOW_HEIGHT)); | |||
let context = ContextBuilder::new() | |||
.with_double_buffer(Some(true)) | |||
.with_hardware_acceleration(Some(true)) | |||
.with_pixel_format(24, 8) | |||
.with_vsync(true) | |||
.with_gl(GlRequest::Specific(Api::OpenGl, (4, 5))) | |||
.with_gl_profile(GlProfile::Core) | |||
.build_windowed(window_builder, event_loop)?; | |||
let window = context.window(); | |||
let window_size = window.outer_size(); | |||
let monitor_size = window.current_monitor().unwrap().size(); | |||
window.set_outer_position(PhysicalPosition::new( | |||
(monitor_size.width - window_size.width) / 2, | |||
(monitor_size.height - window_size.height) / 2, | |||
)); | |||
let context = unsafe { context.make_current().unwrap() }; | |||
gl::load_with(|s| context.get_proc_address(s)); | |||
Ok(Self { context }) | |||
} | |||
pub fn swap_buffers(&self) -> Result<(), Error> { | |||
self.context.swap_buffers()?; | |||
Ok(()) | |||
} | |||
} | |||
const WINDOW_WIDTH: u32 = 1280; | |||
const WINDOW_HEIGHT: u32 = 720; |
@@ -0,0 +1,55 @@ | |||
mod misc; | |||
mod render; | |||
mod systems; | |||
use specs::{Dispatcher, DispatcherBuilder, World}; | |||
use crate::Error; | |||
use misc::{events::Events, geometry::Geometry, window::Window}; | |||
use render::Background; | |||
use systems::{State, StateUpdate}; | |||
pub struct App<'a, 'b> { | |||
is_running: bool, | |||
events: Events, | |||
window: Window, | |||
dispatcher: Dispatcher<'a, 'b>, | |||
} | |||
impl<'a, 'b> App<'a, 'b> { | |||
pub fn new(world: &mut World) -> Result<Self, Error> { | |||
let events = Events::new(world); | |||
let window = Window::new(events.handle())?; | |||
let mut dispatcher = DispatcherBuilder::new() | |||
.with(StateUpdate::new(world), "state_update", &[]) | |||
.with_thread_local(Background::new(world)?) | |||
.build(); | |||
dispatcher.setup(world); | |||
world.insert(Geometry::new()?); | |||
Ok(Self { | |||
is_running: true, | |||
events, | |||
window, | |||
dispatcher, | |||
}) | |||
} | |||
pub fn is_running(&self) -> bool { | |||
self.is_running | |||
} | |||
pub fn process(&mut self, world: &World) -> Result<(), Error> { | |||
self.events.process(world); | |||
self.dispatcher.dispatch(world); | |||
self.window.swap_buffers()?; | |||
self.is_running = !world.fetch::<State>().close_requested; | |||
Ok(()) | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
use glc::{ | |||
misc::Bindable, | |||
shader::{Program, Shader, Type}, | |||
}; | |||
use shrev::{EventChannel, ReaderId}; | |||
use specs::{ReadExpect, System, World}; | |||
use crate::Error; | |||
use super::super::misc::{events::WindowEvent, geometry::Geometry}; | |||
pub struct Background { | |||
program: Program, | |||
window_events_id: ReaderId<WindowEvent>, | |||
} | |||
impl Background { | |||
pub fn new(world: &mut World) -> Result<Self, Error> { | |||
let shaders = vec![ | |||
(Type::Vertex, include_str!("shader/noise.vert")), | |||
(Type::Fragment, include_str!("shader/noise.frag")), | |||
]; | |||
let program = Program::from_shaders_result( | |||
shaders | |||
.into_iter() | |||
.map(|(t, s)| Shader::from_string(t, s.into())), | |||
)?; | |||
let window_events_id = world | |||
.fetch_mut::<EventChannel<WindowEvent>>() | |||
.register_reader(); | |||
Ok(Self { | |||
program, | |||
window_events_id, | |||
}) | |||
} | |||
} | |||
impl<'a> System<'a> for Background { | |||
type SystemData = ( | |||
ReadExpect<'a, Geometry>, | |||
ReadExpect<'a, EventChannel<WindowEvent>>, | |||
); | |||
fn run(&mut self, (geometry, window_events): Self::SystemData) { | |||
let events = window_events.read(&mut self.window_events_id); | |||
for event in events { | |||
if let WindowEvent::Resize(w, h) = event { | |||
gl::viewport(0, 0, *w as gl::GLsizei, *h as gl::GLsizei); | |||
} | |||
} | |||
self.program.bind(); | |||
geometry.render_quad(); | |||
self.program.unbind(); | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
#version 450 core | |||
layout(pixel_center_integer) in vec4 gl_FragCoord; | |||
out vec4 Color; | |||
const float NOISE_RANGE = 0.02; | |||
const float NOISE_BASE = 0.05; | |||
float random(vec4 seed) | |||
{ | |||
return fract(sin(dot(seed, vec4(12.9898, 78.233, 45.164, 53.1324))) * 43758.5453); | |||
} | |||
void main() | |||
{ | |||
float rnd = random(gl_FragCoord); | |||
vec3 rbg = vec3(NOISE_BASE + NOISE_RANGE * rnd); | |||
Color = vec4(rbg, 1.0); | |||
} |
@@ -0,0 +1,8 @@ | |||
#version 450 core | |||
layout (location = 0) in vec3 Position; | |||
void main() | |||
{ | |||
gl_Position = vec4(Position, 1.0); | |||
} |
@@ -0,0 +1,3 @@ | |||
mod state; | |||
pub use state::{State, StateUpdate}; |
@@ -0,0 +1,49 @@ | |||
use shrev::{EventChannel, ReaderId}; | |||
use specs::{ReadExpect, System, World, Write}; | |||
use super::super::misc::events::WindowEvent; | |||
/* State */ | |||
#[derive(Default)] | |||
pub struct State { | |||
pub close_requested: bool, | |||
pub window_width: u32, | |||
pub window_height: u32, | |||
} | |||
/* StateUpdate*/ | |||
pub struct StateUpdate { | |||
window_events_id: ReaderId<WindowEvent>, | |||
} | |||
impl StateUpdate { | |||
pub fn new(world: &mut World) -> Self { | |||
let window_events_id = world | |||
.fetch_mut::<EventChannel<WindowEvent>>() | |||
.register_reader(); | |||
Self { window_events_id } | |||
} | |||
} | |||
impl<'a> System<'a> for StateUpdate { | |||
type SystemData = (Write<'a, State>, ReadExpect<'a, EventChannel<WindowEvent>>); | |||
fn run(&mut self, (mut state, window_events): Self::SystemData) { | |||
let events = window_events.read(&mut self.window_events_id); | |||
for event in events { | |||
match event { | |||
WindowEvent::Resize(w, h) => { | |||
state.window_width = *w; | |||
state.window_height = *h; | |||
} | |||
WindowEvent::Close => { | |||
state.close_requested = true; | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,6 +1,5 @@ | |||
use async_ecs::dispatcher::Error as DispatcherError; | |||
use glc::error::Error as GlcError; | |||
use glutin::CreationError as GlutinCreationError; | |||
use glutin::{ContextError as GlutinContextError, CreationError as GlutinCreationError}; | |||
use thiserror::Error; | |||
#[derive(Debug, Error)] | |||
@@ -8,8 +7,8 @@ pub enum Error { | |||
#[error("GLC Error: {0}")] | |||
GlcError(GlcError), | |||
#[error("ECS Dispatcher Error: {0}")] | |||
DispatcherError(DispatcherError), | |||
#[error("glutin Context Error: {0}")] | |||
GlutinContextError(GlutinContextError), | |||
#[error("glutin Creation Error: {0}")] | |||
GlutinCreationError(GlutinCreationError), | |||
@@ -21,9 +20,9 @@ impl From<GlcError> for Error { | |||
} | |||
} | |||
impl From<DispatcherError> for Error { | |||
fn from(err: DispatcherError) -> Self { | |||
Self::DispatcherError(err) | |||
impl From<GlutinContextError> for Error { | |||
fn from(err: GlutinContextError) -> Self { | |||
Self::GlutinContextError(err) | |||
} | |||
} | |||
@@ -1,6 +1,7 @@ | |||
mod app; | |||
mod error; | |||
mod render; | |||
mod server; | |||
pub use app::App; | |||
pub use error::Error; | |||
pub use server::Server; |
@@ -1,93 +1,36 @@ | |||
use glutin::{ | |||
dpi::{PhysicalPosition, PhysicalSize}, | |||
event::{Event, WindowEvent}, | |||
event_loop::{ControlFlow, EventLoop}, | |||
platform::desktop::EventLoopExtDesktop, | |||
window::WindowBuilder, | |||
ContextBuilder, GlProfile, | |||
}; | |||
use log::{error, info}; | |||
use tokio::{runtime::Builder, task::LocalSet}; | |||
use specs::{World, WorldExt}; | |||
use space_crush::{App, Error}; | |||
use space_crush::{App, Error, Server}; | |||
fn main() { | |||
fn main() -> Result<(), Error> { | |||
env_logger::builder() | |||
.filter_level(log::LevelFilter::Trace) | |||
.format_timestamp_nanos() | |||
.init(); | |||
let rt = Builder::new_multi_thread() | |||
.worker_threads(num_cpus::get() + 4) | |||
.enable_all() | |||
.build() | |||
.unwrap(); | |||
info!("Application started"); | |||
if let Err(err) = rt.block_on(async move { LocalSet::new().run_until(run()).await }) { | |||
error!("Error while executinr application: {}", err); | |||
} | |||
} | |||
async fn run() -> Result<(), Error> { | |||
let mut event_loop = EventLoop::new(); | |||
let window_builder = WindowBuilder::new() | |||
.with_title("space-crush") | |||
.with_visible(true) | |||
.with_inner_size(PhysicalSize::new(WINDOW_WIDTH, WINDOW_HEIGHT)); | |||
let context = ContextBuilder::new() | |||
.with_double_buffer(Some(true)) | |||
.with_hardware_acceleration(Some(true)) | |||
.with_pixel_format(24, 8) | |||
.with_vsync(true) | |||
.with_gl_profile(GlProfile::Core) | |||
.build_windowed(window_builder, &event_loop)?; | |||
let window = context.window(); | |||
let window_size = window.outer_size(); | |||
let monitor_size = window.current_monitor().unwrap().size(); | |||
window.set_outer_position(PhysicalPosition::new( | |||
(monitor_size.width - window_size.width) / 2, | |||
(monitor_size.height - window_size.height) / 2, | |||
)); | |||
let context = unsafe { context.make_current().unwrap() }; | |||
gl::load_with(|s| context.get_proc_address(s)); | |||
let mut run = true; | |||
let mut app = App::new()?; | |||
if let Err(err) = run() { | |||
error!("Error while executing application: {}", err); | |||
loop { | |||
event_loop.run_return(|event, _target, flow_control| { | |||
*flow_control = ControlFlow::Poll; | |||
return Err(err); | |||
} | |||
match event { | |||
Event::WindowEvent { | |||
event: WindowEvent::CloseRequested, | |||
.. | |||
} => { | |||
run = false; | |||
*flow_control = ControlFlow::Exit; | |||
} | |||
Event::MainEventsCleared | Event::RedrawRequested(_) => { | |||
*flow_control = ControlFlow::Exit; | |||
} | |||
_ => (), | |||
} | |||
}); | |||
info!("Application exited"); | |||
if !run { | |||
break; | |||
} | |||
Ok(()) | |||
} | |||
app.progress().await?; | |||
fn run() -> Result<(), Error> { | |||
let mut world = World::new(); | |||
let mut server = Server::new(&mut world); | |||
let mut app = App::new(&mut world)?; | |||
context.swap_buffers().unwrap(); | |||
while app.is_running() { | |||
server.process(&world); | |||
app.process(&world)?; | |||
} | |||
info!("finished"); | |||
Ok(()) | |||
} | |||
const WINDOW_WIDTH: u32 = 1280; | |||
const WINDOW_HEIGHT: u32 = 720; |
@@ -1,95 +0,0 @@ | |||
use std::mem::size_of; | |||
use async_ecs::System; | |||
use glc::{ | |||
array_buffer::{ArrayBuffer, Target, Usage}, | |||
shader::{Program, Shader, Type}, | |||
vertex_array::{DataType, VertexArray}, | |||
}; | |||
use crate::Error; | |||
pub struct Background { | |||
program: Program, | |||
vertex_array: VertexArray, | |||
} | |||
impl Background { | |||
pub fn new() -> Result<Self, Error> { | |||
let shaders = vec![(Type::Fragment, include_str!("shader/noise.frag"))]; | |||
let program = Program::from_shaders_result( | |||
shaders | |||
.into_iter() | |||
.map(|(t, s)| Shader::from_string(t, s.into())), | |||
)?; | |||
let mut array_buffer = ArrayBuffer::new(Target::ArrayBuffer)?; | |||
array_buffer.buffer_size(Usage::StaticDraw, 4 * size_of::<Vertex>())?; | |||
{ | |||
let mut buf = array_buffer.map_mut(false)?; | |||
buf[0] = Vertex { | |||
x: -1.0, | |||
y: -1.0, | |||
s: -1.0, | |||
t: -1.0, | |||
}; | |||
buf[1] = Vertex { | |||
x: 1.0, | |||
y: -1.0, | |||
s: 1.0, | |||
t: -1.0, | |||
}; | |||
buf[2] = Vertex { | |||
x: 1.0, | |||
y: 1.0, | |||
s: 1.0, | |||
t: 1.0, | |||
}; | |||
buf[3] = Vertex { | |||
x: -1.0, | |||
y: 1.0, | |||
s: -1.0, | |||
t: 1.0, | |||
}; | |||
} | |||
const STRIDE_POS: gl::GLsizei = size_of::<Vertex>() as gl::GLsizei; | |||
const STRIDE_TEX: gl::GLsizei = size_of::<Vertex>() as gl::GLsizei; | |||
const OFFSET_POS: gl::GLsizei = 0; | |||
const OFFSET_TEX: gl::GLsizei = 2 * size_of::<f32>() as gl::GLsizei; | |||
let vertex_array = VertexArray::builder() | |||
.bind_buffer(array_buffer) | |||
.vertex_attrib_pointer(0, 2, DataType::Float, false, STRIDE_POS, OFFSET_POS)? | |||
.vertex_attrib_pointer(1, 2, DataType::Float, false, STRIDE_TEX, OFFSET_TEX)? | |||
.build()?; | |||
Ok(Self { | |||
program, | |||
vertex_array, | |||
}) | |||
} | |||
} | |||
impl<'a> System<'a> for Background { | |||
type SystemData = (); | |||
fn run(&mut self, (): Self::SystemData) { | |||
let _program = &self.program; | |||
let _vertex_array = &self.vertex_array; | |||
gl::clear_color(0.1, 0.1, 0.1, 1.0); | |||
gl::clear(gl::COLOR_BUFFER_BIT); | |||
} | |||
} | |||
#[repr(C, packed)] | |||
#[derive(Debug, Copy, Clone, PartialEq)] | |||
struct Vertex { | |||
pub x: f32, | |||
pub y: f32, | |||
pub s: f32, | |||
pub t: f32, | |||
} |
@@ -1,17 +0,0 @@ | |||
const float NOISE_RANGE = 0.05; | |||
const float NOISE_BASE = 0.05; | |||
float random(vec4 seed) | |||
{ | |||
return fract(sin(dot(seed, vec4(12.9898, 78.233, 45.164, 53.1324))) * 43758.5453); | |||
} | |||
void main(void) | |||
{ | |||
float rnd = random(gl_ModelViewProjectionMatrix * gl_FragCoord); | |||
vec4 color = vec4(NOISE_BASE + NOISE_RANGE * rnd); | |||
color.a = 1.0; | |||
gl_FragColor = color; | |||
} |
@@ -0,0 +1,15 @@ | |||
use specs::World; | |||
pub struct Server {} | |||
impl Server { | |||
pub fn new(world: &mut World) -> Self { | |||
let _world = world; | |||
Self {} | |||
} | |||
pub fn process(&mut self, world: &World) { | |||
let _world = world; | |||
} | |||
} |