| @@ -140,9 +140,9 @@ dependencies = [ | |||||
| [[package]] | [[package]] | ||||
| name = "cc" | name = "cc" | ||||
| version = "1.0.65" | |||||
| version = "1.0.66" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15" | |||||
| checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" | |||||
| [[package]] | [[package]] | ||||
| name = "cfg-if" | name = "cfg-if" | ||||
| @@ -178,15 +178,6 @@ dependencies = [ | |||||
| "winapi 0.3.9", | "winapi 0.3.9", | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "cloudabi" | |||||
| version = "0.1.0" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||||
| checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" | |||||
| dependencies = [ | |||||
| "bitflags", | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "cocoa" | name = "cocoa" | ||||
| version = "0.23.0" | version = "0.23.0" | ||||
| @@ -738,7 +729,7 @@ dependencies = [ | |||||
| "glyph_brush_draw_cache", | "glyph_brush_draw_cache", | ||||
| "glyph_brush_layout", | "glyph_brush_layout", | ||||
| "log", | "log", | ||||
| "ordered-float 1.1.0", | |||||
| "ordered-float 1.1.1", | |||||
| "rustc-hash", | "rustc-hash", | ||||
| "twox-hash", | "twox-hash", | ||||
| ] | ] | ||||
| @@ -881,15 +872,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" | |||||
| [[package]] | [[package]] | ||||
| name = "libc" | name = "libc" | ||||
| version = "0.2.80" | |||||
| version = "0.2.81" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" | |||||
| checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" | |||||
| [[package]] | [[package]] | ||||
| name = "libloading" | name = "libloading" | ||||
| version = "0.6.5" | |||||
| version = "0.6.6" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1090080fe06ec2648d0da3881d9453d97e71a45f00eb179af7fdd7e3f686fdb0" | |||||
| checksum = "e9367bdfa836b7e3cf895867f7a570283444da90562980ec2263d6e1569b16bc" | |||||
| dependencies = [ | dependencies = [ | ||||
| "cfg-if 1.0.0", | "cfg-if 1.0.0", | ||||
| "winapi 0.3.9", | "winapi 0.3.9", | ||||
| @@ -1012,9 +1003,9 @@ dependencies = [ | |||||
| [[package]] | [[package]] | ||||
| name = "mio" | name = "mio" | ||||
| version = "0.6.22" | |||||
| version = "0.6.23" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" | |||||
| checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" | |||||
| dependencies = [ | dependencies = [ | ||||
| "cfg-if 0.1.10", | "cfg-if 0.1.10", | ||||
| "fuchsia-zircon", | "fuchsia-zircon", | ||||
| @@ -1043,9 +1034,9 @@ dependencies = [ | |||||
| [[package]] | [[package]] | ||||
| name = "miow" | name = "miow" | ||||
| version = "0.2.1" | |||||
| version = "0.2.2" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" | |||||
| checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" | |||||
| dependencies = [ | dependencies = [ | ||||
| "kernel32-sys", | "kernel32-sys", | ||||
| "net2", | "net2", | ||||
| @@ -1106,9 +1097,9 @@ checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" | |||||
| [[package]] | [[package]] | ||||
| name = "net2" | name = "net2" | ||||
| version = "0.2.35" | |||||
| version = "0.2.36" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" | |||||
| checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02" | |||||
| dependencies = [ | dependencies = [ | ||||
| "cfg-if 0.1.10", | "cfg-if 0.1.10", | ||||
| "libc", | "libc", | ||||
| @@ -1215,18 +1206,18 @@ checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" | |||||
| [[package]] | [[package]] | ||||
| name = "ordered-float" | name = "ordered-float" | ||||
| version = "1.1.0" | |||||
| version = "1.1.1" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3741934be594d77de1c8461ebcbbe866f585ea616a9753aa78f2bdc69f0e4579" | |||||
| checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" | |||||
| dependencies = [ | dependencies = [ | ||||
| "num-traits", | "num-traits", | ||||
| ] | ] | ||||
| [[package]] | [[package]] | ||||
| name = "ordered-float" | name = "ordered-float" | ||||
| version = "2.0.0" | |||||
| version = "2.0.1" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9fe9037165d7023b1228bc4ae9a2fa1a2b0095eca6c2998c624723dfd01314a5" | |||||
| checksum = "dacdec97876ef3ede8c50efc429220641a0b11ba0048b4b0c357bccbc47c5204" | |||||
| dependencies = [ | dependencies = [ | ||||
| "num-traits", | "num-traits", | ||||
| ] | ] | ||||
| @@ -1271,12 +1262,11 @@ dependencies = [ | |||||
| [[package]] | [[package]] | ||||
| name = "parking_lot_core" | name = "parking_lot_core" | ||||
| version = "0.8.0" | |||||
| version = "0.8.1" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" | |||||
| checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0" | |||||
| dependencies = [ | dependencies = [ | ||||
| "cfg-if 0.1.10", | |||||
| "cloudabi", | |||||
| "cfg-if 1.0.0", | |||||
| "instant", | "instant", | ||||
| "libc", | "libc", | ||||
| "redox_syscall", | "redox_syscall", | ||||
| @@ -1523,9 +1513,12 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" | |||||
| [[package]] | [[package]] | ||||
| name = "serde" | name = "serde" | ||||
| version = "1.0.117" | |||||
| version = "1.0.118" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" | |||||
| checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" | |||||
| dependencies = [ | |||||
| "serde_derive", | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "serde-value" | name = "serde-value" | ||||
| @@ -1533,7 +1526,7 @@ version = "0.6.0" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5a65a7291a8a568adcae4c10a677ebcedbc6c9cec91c054dee2ce40b0e3290eb" | checksum = "5a65a7291a8a568adcae4c10a677ebcedbc6c9cec91c054dee2ce40b0e3290eb" | ||||
| dependencies = [ | dependencies = [ | ||||
| "ordered-float 1.1.0", | |||||
| "ordered-float 1.1.1", | |||||
| "serde", | "serde", | ||||
| ] | ] | ||||
| @@ -1621,9 +1614,12 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" | |||||
| [[package]] | [[package]] | ||||
| name = "smallvec" | name = "smallvec" | ||||
| version = "1.5.0" | |||||
| version = "1.5.1" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7acad6f34eb9e8a259d3283d1e8c1d34d7415943d4895f65cc73813c7396fc85" | |||||
| checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75" | |||||
| dependencies = [ | |||||
| "serde", | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "smithay-client-toolkit" | name = "smithay-client-toolkit" | ||||
| @@ -1657,11 +1653,14 @@ dependencies = [ | |||||
| "log", | "log", | ||||
| "log4rs", | "log4rs", | ||||
| "num_cpus", | "num_cpus", | ||||
| "ordered-float 2.0.0", | |||||
| "ordered-float 2.0.1", | |||||
| "rand", | "rand", | ||||
| "serde", | |||||
| "serde_json", | |||||
| "serde_yaml", | "serde_yaml", | ||||
| "shred", | "shred", | ||||
| "shrev", | "shrev", | ||||
| "smallvec", | |||||
| "specs", | "specs", | ||||
| "thiserror", | "thiserror", | ||||
| "tokio", | "tokio", | ||||
| @@ -1699,9 +1698,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" | |||||
| [[package]] | [[package]] | ||||
| name = "syn" | name = "syn" | ||||
| version = "1.0.50" | |||||
| version = "1.0.53" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "443b4178719c5a851e1bde36ce12da21d74a0e60b4d982ec3385a933c812f0f6" | |||||
| checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68" | |||||
| dependencies = [ | dependencies = [ | ||||
| "proc-macro2", | "proc-macro2", | ||||
| "quote", | "quote", | ||||
| @@ -1761,9 +1760,9 @@ dependencies = [ | |||||
| [[package]] | [[package]] | ||||
| name = "tokio" | name = "tokio" | ||||
| version = "0.3.4" | |||||
| version = "0.3.5" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9dfe2523e6fa84ddf5e688151d4e5fddc51678de9752c6512a24714c23818d61" | |||||
| checksum = "a12a3eb39ee2c231be64487f1fcbe726c8f2514876a55480a5ab8559fc374252" | |||||
| dependencies = [ | dependencies = [ | ||||
| "autocfg", | "autocfg", | ||||
| "pin-project-lite", | "pin-project-lite", | ||||
| @@ -2046,6 +2045,7 @@ dependencies = [ | |||||
| "parking_lot", | "parking_lot", | ||||
| "percent-encoding", | "percent-encoding", | ||||
| "raw-window-handle", | "raw-window-handle", | ||||
| "serde", | |||||
| "smithay-client-toolkit", | "smithay-client-toolkit", | ||||
| "wayland-client", | "wayland-client", | ||||
| "winapi 0.3.9", | "winapi 0.3.9", | ||||
| @@ -8,16 +8,19 @@ edition = "2018" | |||||
| futures = "0.3" | futures = "0.3" | ||||
| gl = { version = "0.1", features = [ "use_log_crate" ] } | gl = { version = "0.1", features = [ "use_log_crate" ] } | ||||
| glc = "0.1" | glc = "0.1" | ||||
| glutin = "0.25" | |||||
| glutin = { version = "0.25", features = [ "serde" ] } | |||||
| glyph_brush = "0.7" | glyph_brush = "0.7" | ||||
| log = { version = "0.4", features = [ "max_level_trace", "release_max_level_warn" ] } | log = { version = "0.4", features = [ "max_level_trace", "release_max_level_warn" ] } | ||||
| log4rs = "0.13" | log4rs = "0.13" | ||||
| num_cpus = "1.13" | num_cpus = "1.13" | ||||
| ordered-float = "2.0" | ordered-float = "2.0" | ||||
| rand = "0.7" | rand = "0.7" | ||||
| serde = { version = "1.0", features = ["derive"] } | |||||
| serde_json = "1.0" | |||||
| serde_yaml = "0.8" | serde_yaml = "0.8" | ||||
| shred = { version = "0.10", features = [ "shred-derive" ] } | shred = { version = "0.10", features = [ "shred-derive" ] } | ||||
| shrev = "1.1" | shrev = "1.1" | ||||
| smallvec = { version = "1.5", features = [ "serde" ] } | |||||
| specs = "0.16" | specs = "0.16" | ||||
| thiserror = "1.0" | thiserror = "1.0" | ||||
| tokio = "0.3" | tokio = "0.3" | ||||
| @@ -0,0 +1,31 @@ | |||||
| { | |||||
| "video": { | |||||
| "resolution": [ | |||||
| 1280, | |||||
| 720 | |||||
| ], | |||||
| "multisampling": 16, | |||||
| "fullscreen": false, | |||||
| "windowed": true | |||||
| }, | |||||
| "input": { | |||||
| "key_camera_move_up": [ | |||||
| "W", | |||||
| "Up" | |||||
| ], | |||||
| "key_camera_move_down": [ | |||||
| "S", | |||||
| "Down" | |||||
| ], | |||||
| "key_camera_move_left": [ | |||||
| "A", | |||||
| "Left" | |||||
| ], | |||||
| "key_camera_move_right": [ | |||||
| "D", | |||||
| "Right" | |||||
| ], | |||||
| "speed_camera_move": 1.0, | |||||
| "speed_camera_zoom": 100.0 | |||||
| } | |||||
| } | |||||
| @@ -1,38 +1,89 @@ | |||||
| use glutin::{ | use glutin::{ | ||||
| dpi::{PhysicalPosition, PhysicalSize}, | dpi::{PhysicalPosition, PhysicalSize}, | ||||
| event_loop::EventLoop, | event_loop::EventLoop, | ||||
| window::Window as GlutinWindow, | |||||
| window::WindowBuilder, | |||||
| monitor::VideoMode, | |||||
| window::{Fullscreen, Window as GlutinWindow, WindowBuilder}, | |||||
| Api, ContextBuilder, ContextWrapper, GlProfile, GlRequest, PossiblyCurrent, | Api, ContextBuilder, ContextWrapper, GlProfile, GlRequest, PossiblyCurrent, | ||||
| }; | }; | ||||
| use log::info; | |||||
| use log::{error, info}; | |||||
| use crate::Error; | use crate::Error; | ||||
| use super::super::resources::Config; | |||||
| pub struct Window { | pub struct Window { | ||||
| context: ContextWrapper<PossiblyCurrent, GlutinWindow>, | context: ContextWrapper<PossiblyCurrent, GlutinWindow>, | ||||
| } | } | ||||
| impl Window { | impl Window { | ||||
| pub fn new<T>(event_loop: &EventLoop<T>) -> Result<Self, Error> { | |||||
| pub fn new<T>(event_loop: &EventLoop<T>, config: &Config) -> Result<Self, Error> { | |||||
| let monitor = event_loop | |||||
| .primary_monitor() | |||||
| .or_else(|| event_loop.available_monitors().next()); | |||||
| let (fullscreen, border) = match (config.video.windowed, config.video.fullscreen) { | |||||
| (false, true) => { | |||||
| let mut video_mode: Option<VideoMode> = None; | |||||
| if let Some(monitor) = monitor { | |||||
| for mode in monitor.video_modes() { | |||||
| video_mode = Some(match video_mode { | |||||
| Some(current) => { | |||||
| if mode.size().width <= config.video.resolution.0 | |||||
| && mode.size().height <= config.video.resolution.1 | |||||
| && mode.size().width >= current.size().width | |||||
| && mode.size().height >= current.size().height | |||||
| && mode.bit_depth() >= current.bit_depth() | |||||
| && mode.refresh_rate() >= current.refresh_rate() | |||||
| { | |||||
| mode | |||||
| } else { | |||||
| current | |||||
| } | |||||
| } | |||||
| None => mode, | |||||
| }); | |||||
| } | |||||
| } | |||||
| match video_mode { | |||||
| Some(video_mode) => (Some(Fullscreen::Exclusive(video_mode)), false), | |||||
| None => { | |||||
| error!("Unable to find video mode for exclusive fullscreen!"); | |||||
| (Some(Fullscreen::Borderless(None)), false) | |||||
| } | |||||
| } | |||||
| } | |||||
| (true, true) => (Some(Fullscreen::Borderless(None)), false), | |||||
| (false, false) => (None, false), | |||||
| (true, false) => (None, true), | |||||
| }; | |||||
| let mut multisampling = [16u16, 8, 4, 2, 1, 0].iter(); | let mut multisampling = [16u16, 8, 4, 2, 1, 0].iter(); | ||||
| let context = loop { | let context = loop { | ||||
| let multisampling = match multisampling.next() { | let multisampling = match multisampling.next() { | ||||
| Some(multisampling) => multisampling, | |||||
| Some(multisampling) => *multisampling, | |||||
| None => return Err(Error::CreateContext), | None => return Err(Error::CreateContext), | ||||
| }; | }; | ||||
| if config.video.multisampling < multisampling { | |||||
| continue; | |||||
| } | |||||
| info!("Create OpenGL context (multisampling={})", multisampling); | info!("Create OpenGL context (multisampling={})", multisampling); | ||||
| let window_builder = WindowBuilder::new() | let window_builder = WindowBuilder::new() | ||||
| .with_title("space-crush") | .with_title("space-crush") | ||||
| .with_visible(true) | .with_visible(true) | ||||
| .with_inner_size(PhysicalSize::new(WINDOW_WIDTH, WINDOW_HEIGHT)); | |||||
| .with_decorations(border) | |||||
| .with_fullscreen(fullscreen.clone()) | |||||
| .with_inner_size::<PhysicalSize<u32>>(config.video.resolution.into()); | |||||
| let ret = ContextBuilder::new() | let ret = ContextBuilder::new() | ||||
| .with_double_buffer(Some(true)) | .with_double_buffer(Some(true)) | ||||
| .with_hardware_acceleration(Some(true)) | .with_hardware_acceleration(Some(true)) | ||||
| .with_pixel_format(24, 8) | .with_pixel_format(24, 8) | ||||
| .with_multisampling(*multisampling) | |||||
| .with_multisampling(multisampling) | |||||
| .with_vsync(false) | .with_vsync(false) | ||||
| .with_gl(GlRequest::Specific(Api::OpenGl, (4, 5))) | .with_gl(GlRequest::Specific(Api::OpenGl, (4, 5))) | ||||
| .with_gl_profile(GlProfile::Core) | .with_gl_profile(GlProfile::Core) | ||||
| @@ -68,6 +119,3 @@ impl Window { | |||||
| Ok(()) | Ok(()) | ||||
| } | } | ||||
| } | } | ||||
| const WINDOW_WIDTH: u32 = 1280; | |||||
| const WINDOW_HEIGHT: u32 = 720; | |||||
| @@ -9,7 +9,7 @@ use crate::Error; | |||||
| use misc::{Events, TextManager, Window}; | use misc::{Events, TextManager, Window}; | ||||
| use render::{Debug, Init, Test}; | use render::{Debug, Init, Test}; | ||||
| use resources::{Camera, Geometry, State}; | |||||
| use resources::{Camera, Config, Geometry, State}; | |||||
| use systems::StateUpdate; | use systems::StateUpdate; | ||||
| pub struct App<'a, 'b> { | pub struct App<'a, 'b> { | ||||
| @@ -21,9 +21,11 @@ pub struct App<'a, 'b> { | |||||
| impl<'a, 'b> App<'a, 'b> { | impl<'a, 'b> App<'a, 'b> { | ||||
| pub fn new(world: &mut World) -> Result<Self, Error> { | pub fn new(world: &mut World) -> Result<Self, Error> { | ||||
| let config = Config::new(world)?; | |||||
| let events = Events::new(world); | let events = Events::new(world); | ||||
| let window = Window::new(events.handle())?; | |||||
| let window = Window::new(events.handle(), &config)?; | |||||
| world.insert(config); | |||||
| world.insert(Camera::new()?); | world.insert(Camera::new()?); | ||||
| world.insert(Geometry::new()?); | world.insert(Geometry::new()?); | ||||
| world.insert(State::default()); | world.insert(State::default()); | ||||
| @@ -11,8 +11,8 @@ use specs::{prelude::*, ReadExpect, System, World, WriteExpect}; | |||||
| use crate::Error; | use crate::Error; | ||||
| use super::super::{ | use super::super::{ | ||||
| misc::{MouseEvent, VirtualKeyCode, WorldHelper}, | |||||
| resources::{Camera, Geometry, State}, | |||||
| misc::{MouseEvent, WorldHelper}, | |||||
| resources::{Camera, Config, Geometry, State}, | |||||
| }; | }; | ||||
| pub struct Init { | pub struct Init { | ||||
| @@ -42,6 +42,7 @@ impl Init { | |||||
| pub struct InitData<'a> { | pub struct InitData<'a> { | ||||
| camera: WriteExpect<'a, Camera>, | camera: WriteExpect<'a, Camera>, | ||||
| state: ReadExpect<'a, State>, | state: ReadExpect<'a, State>, | ||||
| config: ReadExpect<'a, Config>, | |||||
| geometry: ReadExpect<'a, Geometry>, | geometry: ReadExpect<'a, Geometry>, | ||||
| mouse_events: ReadExpect<'a, EventChannel<MouseEvent>>, | mouse_events: ReadExpect<'a, EventChannel<MouseEvent>>, | ||||
| } | } | ||||
| @@ -53,6 +54,7 @@ impl<'a> System<'a> for Init { | |||||
| let InitData { | let InitData { | ||||
| mut camera, | mut camera, | ||||
| state, | state, | ||||
| config, | |||||
| geometry, | geometry, | ||||
| mouse_events, | mouse_events, | ||||
| } = data; | } = data; | ||||
| @@ -72,7 +74,8 @@ impl<'a> System<'a> for Init { | |||||
| let events = mouse_events.read(&mut self.mouse_event_id); | let events = mouse_events.read(&mut self.mouse_event_id); | ||||
| for event in events { | for event in events { | ||||
| if let MouseEvent::ScrollY(delta) = event { | if let MouseEvent::ScrollY(delta) = event { | ||||
| let z = CAMERA_ZOOM_SPEED / (CAMERA_ZOOM_SPEED - delta); | |||||
| let s = config.input.speed_camera_zoom; | |||||
| let z = s / (s - delta); | |||||
| let m = Matrix4f::translate((state.mouse_pos.0, state.mouse_pos.1, 0.0).into()) | let m = Matrix4f::translate((state.mouse_pos.0, state.mouse_pos.1, 0.0).into()) | ||||
| * Matrix4f::scale(z.into()) | * Matrix4f::scale(z.into()) | ||||
| * Matrix4f::translate((-state.mouse_pos.0, -state.mouse_pos.1, 0.0).into()); | * Matrix4f::translate((-state.mouse_pos.0, -state.mouse_pos.1, 0.0).into()); | ||||
| @@ -84,20 +87,19 @@ impl<'a> System<'a> for Init { | |||||
| } | } | ||||
| /* move camera */ | /* move camera */ | ||||
| let up = state.key_state(KEY_CAMERA_UP) || state.key_state(KEY_CAMERA_UP_ALT); | |||||
| let down = state.key_state(KEY_CAMERA_DOWN) || state.key_state(KEY_CAMERA_DOWN_ALT); | |||||
| let left = state.key_state(KEY_CAMERA_LEFT) || state.key_state(KEY_CAMERA_LEFT_ALT); | |||||
| let right = state.key_state(KEY_CAMERA_RIGHT) || state.key_state(KEY_CAMERA_RIGHT_ALT); | |||||
| let translate = Vector3f::new( | |||||
| if left { CAMERA_MOVE_SPEED_KEY } else { 0.0 } | |||||
| + if right { -CAMERA_MOVE_SPEED_KEY } else { 0.0 }, | |||||
| if up { -CAMERA_MOVE_SPEED_KEY } else { 0.0 } | |||||
| + if down { CAMERA_MOVE_SPEED_KEY } else { 0.0 }, | |||||
| 0.0, | |||||
| ); | |||||
| let up = state.key_state(&config.input.key_camera_move_up); | |||||
| let down = state.key_state(&config.input.key_camera_move_down); | |||||
| let left = state.key_state(&config.input.key_camera_move_left); | |||||
| let right = state.key_state(&config.input.key_camera_move_right); | |||||
| if up || down || left || right { | if up || down || left || right { | ||||
| let s = config.input.speed_camera_move; | |||||
| let translate = Vector3f::new( | |||||
| if left { s } else { 0.0 } + if right { -s } else { 0.0 }, | |||||
| if up { -s } else { 0.0 } + if down { s } else { 0.0 }, | |||||
| 0.0, | |||||
| ); | |||||
| let m = Matrix4f::translate(translate); | let m = Matrix4f::translate(translate); | ||||
| if let Err(err) = camera.update_with(move |v| m * v) { | if let Err(err) = camera.update_with(move |v| m * v) { | ||||
| error!("Error while moving camera: {}", err); | error!("Error while moving camera: {}", err); | ||||
| @@ -110,16 +112,3 @@ impl<'a> System<'a> for Init { | |||||
| self.program.unbind(); | self.program.unbind(); | ||||
| } | } | ||||
| } | } | ||||
| const CAMERA_MOVE_SPEED_KEY: f32 = 2.0; | |||||
| const CAMERA_ZOOM_SPEED: f32 = 100.0; | |||||
| const KEY_CAMERA_UP: VirtualKeyCode = VirtualKeyCode::Up; | |||||
| const KEY_CAMERA_DOWN: VirtualKeyCode = VirtualKeyCode::Down; | |||||
| const KEY_CAMERA_LEFT: VirtualKeyCode = VirtualKeyCode::Left; | |||||
| const KEY_CAMERA_RIGHT: VirtualKeyCode = VirtualKeyCode::Right; | |||||
| const KEY_CAMERA_UP_ALT: VirtualKeyCode = VirtualKeyCode::W; | |||||
| const KEY_CAMERA_DOWN_ALT: VirtualKeyCode = VirtualKeyCode::S; | |||||
| const KEY_CAMERA_LEFT_ALT: VirtualKeyCode = VirtualKeyCode::A; | |||||
| const KEY_CAMERA_RIGHT_ALT: VirtualKeyCode = VirtualKeyCode::D; | |||||
| @@ -0,0 +1,137 @@ | |||||
| use log::warn; | |||||
| use serde::{Deserialize, Serialize}; | |||||
| use serde_json::from_reader; | |||||
| use smallvec::{smallvec, SmallVec}; | |||||
| use specs::World; | |||||
| use crate::{misc::Vfs, Error}; | |||||
| use super::super::misc::{VirtualKeyCode, WorldHelper}; | |||||
| #[derive(Debug, Default, Serialize, Deserialize)] | |||||
| pub struct Config { | |||||
| #[serde(default)] | |||||
| pub video: Video, | |||||
| #[serde(default)] | |||||
| pub input: Input, | |||||
| } | |||||
| #[derive(Debug, Serialize, Deserialize)] | |||||
| pub struct Video { | |||||
| #[serde(default = "defaults::resolution")] | |||||
| pub resolution: (u32, u32), | |||||
| #[serde(default = "defaults::multisampling")] | |||||
| pub multisampling: u16, | |||||
| #[serde(default = "defaults::fullscreen")] | |||||
| pub fullscreen: bool, | |||||
| #[serde(default = "defaults::windowed")] | |||||
| pub windowed: bool, | |||||
| } | |||||
| #[derive(Debug, Serialize, Deserialize)] | |||||
| pub struct Input { | |||||
| #[serde(default = "defaults::key_camera_move_up")] | |||||
| pub key_camera_move_up: VirtualKeyCodes, | |||||
| #[serde(default = "defaults::key_camera_move_down")] | |||||
| pub key_camera_move_down: VirtualKeyCodes, | |||||
| #[serde(default = "defaults::key_camera_move_left")] | |||||
| pub key_camera_move_left: VirtualKeyCodes, | |||||
| #[serde(default = "defaults::key_camera_move_right")] | |||||
| pub key_camera_move_right: VirtualKeyCodes, | |||||
| #[serde(default = "defaults::speed_camera_move")] | |||||
| pub speed_camera_move: f32, | |||||
| #[serde(default = "defaults::speed_camera_zoom")] | |||||
| pub speed_camera_zoom: f32, | |||||
| } | |||||
| type VirtualKeyCodes = SmallVec<[VirtualKeyCode; 2]>; | |||||
| impl Config { | |||||
| pub fn new(world: &World) -> Result<Self, Error> { | |||||
| let vfs = world.resource::<Vfs>()?; | |||||
| let config = match vfs.join("config.json")?.open_file() { | |||||
| Ok(mut file) => from_reader(&mut file)?, | |||||
| Err(err) => { | |||||
| warn!( | |||||
| "Unable to load config file, falling back to default config: {}", | |||||
| err | |||||
| ); | |||||
| Config::default() | |||||
| } | |||||
| }; | |||||
| Ok(config) | |||||
| } | |||||
| } | |||||
| impl Default for Video { | |||||
| fn default() -> Self { | |||||
| Self { | |||||
| resolution: defaults::resolution(), | |||||
| multisampling: defaults::multisampling(), | |||||
| fullscreen: defaults::fullscreen(), | |||||
| windowed: defaults::windowed(), | |||||
| } | |||||
| } | |||||
| } | |||||
| impl Default for Input { | |||||
| fn default() -> Self { | |||||
| Self { | |||||
| key_camera_move_up: defaults::key_camera_move_up(), | |||||
| key_camera_move_down: defaults::key_camera_move_down(), | |||||
| key_camera_move_left: defaults::key_camera_move_left(), | |||||
| key_camera_move_right: defaults::key_camera_move_right(), | |||||
| speed_camera_move: defaults::speed_camera_move(), | |||||
| speed_camera_zoom: defaults::speed_camera_zoom(), | |||||
| } | |||||
| } | |||||
| } | |||||
| mod defaults { | |||||
| use super::*; | |||||
| pub fn resolution() -> (u32, u32) { | |||||
| (1280, 720) | |||||
| } | |||||
| pub fn multisampling() -> u16 { | |||||
| 0 | |||||
| } | |||||
| pub fn fullscreen() -> bool { | |||||
| true | |||||
| } | |||||
| pub fn windowed() -> bool { | |||||
| true | |||||
| } | |||||
| pub fn key_camera_move_up() -> VirtualKeyCodes { | |||||
| smallvec![VirtualKeyCode::W, VirtualKeyCode::Up] | |||||
| } | |||||
| pub fn key_camera_move_down() -> VirtualKeyCodes { | |||||
| smallvec![VirtualKeyCode::S, VirtualKeyCode::Down] | |||||
| } | |||||
| pub fn key_camera_move_left() -> VirtualKeyCodes { | |||||
| smallvec![VirtualKeyCode::A, VirtualKeyCode::Left] | |||||
| } | |||||
| pub fn key_camera_move_right() -> VirtualKeyCodes { | |||||
| smallvec![VirtualKeyCode::D, VirtualKeyCode::Right] | |||||
| } | |||||
| pub fn speed_camera_move() -> f32 { | |||||
| 2.0 | |||||
| } | |||||
| pub fn speed_camera_zoom() -> f32 { | |||||
| 100.0 | |||||
| } | |||||
| } | |||||
| @@ -1,7 +1,9 @@ | |||||
| mod camera; | mod camera; | ||||
| mod config; | |||||
| mod geometry; | mod geometry; | ||||
| mod state; | mod state; | ||||
| pub use camera::Camera; | pub use camera::Camera; | ||||
| pub use config::Config; | |||||
| pub use geometry::Geometry; | pub use geometry::Geometry; | ||||
| pub use state::State; | pub use state::State; | ||||
| @@ -1,6 +1,7 @@ | |||||
| #![allow(dead_code)] | #![allow(dead_code)] | ||||
| use std::collections::HashSet; | use std::collections::HashSet; | ||||
| use std::iter::IntoIterator; | |||||
| use super::super::misc::{MouseButton, VirtualKeyCode}; | use super::super::misc::{MouseButton, VirtualKeyCode}; | ||||
| @@ -9,37 +10,50 @@ pub struct State { | |||||
| pub mouse_pos: (f32, f32), | pub mouse_pos: (f32, f32), | ||||
| pub resolution: (u32, u32), | pub resolution: (u32, u32), | ||||
| pub close_requested: bool, | pub close_requested: bool, | ||||
| pub key_states: HashSet<KeyState>, | |||||
| } | |||||
| #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] | |||||
| pub enum KeyState { | |||||
| KeyCode(VirtualKeyCode), | |||||
| MouseButton(MouseButton), | |||||
| pub key_states: HashSet<VirtualKeyCode>, | |||||
| pub button_states: HashSet<MouseButton>, | |||||
| } | } | ||||
| impl State { | impl State { | ||||
| pub fn key_state(&self, code: VirtualKeyCode) -> bool { | |||||
| self.key_states.contains(&KeyState::KeyCode(code)) | |||||
| pub fn key_state<'a, I>(&self, codes: I) -> bool | |||||
| where | |||||
| I: IntoIterator<Item = &'a VirtualKeyCode>, | |||||
| { | |||||
| for code in codes.into_iter() { | |||||
| if self.key_states.contains(code) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| false | |||||
| } | } | ||||
| pub fn button_state(&self, button: MouseButton) -> bool { | |||||
| self.key_states.contains(&KeyState::MouseButton(button)) | |||||
| pub fn button_state<'a, I>(&self, buttons: I) -> bool | |||||
| where | |||||
| I: IntoIterator<Item = &'a MouseButton>, | |||||
| { | |||||
| for button in buttons.into_iter() { | |||||
| if self.button_states.contains(button) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| false | |||||
| } | } | ||||
| pub fn set_key_state(&mut self, code: VirtualKeyCode, value: bool) { | pub fn set_key_state(&mut self, code: VirtualKeyCode, value: bool) { | ||||
| if value { | if value { | ||||
| self.key_states.insert(KeyState::KeyCode(code)); | |||||
| self.key_states.insert(code); | |||||
| } else { | } else { | ||||
| self.key_states.remove(&KeyState::KeyCode(code)); | |||||
| self.key_states.remove(&code); | |||||
| } | } | ||||
| } | } | ||||
| pub fn set_button_state(&mut self, button: MouseButton, value: bool) { | pub fn set_button_state(&mut self, button: MouseButton, value: bool) { | ||||
| if value { | if value { | ||||
| self.key_states.insert(KeyState::MouseButton(button)); | |||||
| self.button_states.insert(button); | |||||
| } else { | } else { | ||||
| self.key_states.remove(&KeyState::MouseButton(button)); | |||||
| self.button_states.remove(&button); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -3,7 +3,8 @@ use std::io::Error as IoError; | |||||
| use glc::error::Error as GlcError; | use glc::error::Error as GlcError; | ||||
| use glutin::{ContextError as GlutinContextError, CreationError as GlutinCreationError}; | use glutin::{ContextError as GlutinContextError, CreationError as GlutinCreationError}; | ||||
| use glyph_brush::ab_glyph::InvalidFont; | use glyph_brush::ab_glyph::InvalidFont; | ||||
| use serde_yaml::Error as YmlError; | |||||
| use serde_json::Error as JsonError; | |||||
| use serde_yaml::Error as YamlError; | |||||
| use thiserror::Error; | use thiserror::Error; | ||||
| use vfs::VfsError; | use vfs::VfsError; | ||||
| use vfs_zip::Error as VfsZipError; | use vfs_zip::Error as VfsZipError; | ||||
| @@ -19,8 +20,11 @@ pub enum Error { | |||||
| #[error("VFS ZIP Error: {0}")] | #[error("VFS ZIP Error: {0}")] | ||||
| VfsZipError(VfsZipError), | VfsZipError(VfsZipError), | ||||
| #[error("YML Error: {0}")] | |||||
| YmlError(YmlError), | |||||
| #[error("JSON Error: {0}")] | |||||
| JsonError(JsonError), | |||||
| #[error("YAML Error: {0}")] | |||||
| YamlError(YamlError), | |||||
| #[error("GLC Error: {0}")] | #[error("GLC Error: {0}")] | ||||
| GlcError(GlcError), | GlcError(GlcError), | ||||
| @@ -65,9 +69,15 @@ impl From<VfsZipError> for Error { | |||||
| } | } | ||||
| } | } | ||||
| impl From<YmlError> for Error { | |||||
| fn from(err: YmlError) -> Self { | |||||
| Self::YmlError(err) | |||||
| impl From<JsonError> for Error { | |||||
| fn from(err: JsonError) -> Self { | |||||
| Self::JsonError(err) | |||||
| } | |||||
| } | |||||
| impl From<YamlError> for Error { | |||||
| fn from(err: YamlError) -> Self { | |||||
| Self::YamlError(err) | |||||
| } | } | ||||
| } | } | ||||
| @@ -35,7 +35,7 @@ pub fn init(vfs: &Vfs) { | |||||
| fn load_from_file(vfs: &Vfs) -> Result<Config, Error> { | fn load_from_file(vfs: &Vfs) -> Result<Config, Error> { | ||||
| let mut config = String::default(); | let mut config = String::default(); | ||||
| vfs.join("resources/log4rs.yml")? | |||||
| vfs.join("log4rs.yml")? | |||||
| .open_file()? | .open_file()? | ||||
| .read_to_string(&mut config)?; | .read_to_string(&mut config)?; | ||||