| @@ -140,9 +140,9 @@ dependencies = [ | |||
| [[package]] | |||
| name = "cc" | |||
| version = "1.0.65" | |||
| version = "1.0.66" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15" | |||
| checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" | |||
| [[package]] | |||
| name = "cfg-if" | |||
| @@ -178,15 +178,6 @@ dependencies = [ | |||
| "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]] | |||
| name = "cocoa" | |||
| version = "0.23.0" | |||
| @@ -738,7 +729,7 @@ dependencies = [ | |||
| "glyph_brush_draw_cache", | |||
| "glyph_brush_layout", | |||
| "log", | |||
| "ordered-float 1.1.0", | |||
| "ordered-float 1.1.1", | |||
| "rustc-hash", | |||
| "twox-hash", | |||
| ] | |||
| @@ -881,15 +872,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" | |||
| [[package]] | |||
| name = "libc" | |||
| version = "0.2.80" | |||
| version = "0.2.81" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" | |||
| checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" | |||
| [[package]] | |||
| name = "libloading" | |||
| version = "0.6.5" | |||
| version = "0.6.6" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "1090080fe06ec2648d0da3881d9453d97e71a45f00eb179af7fdd7e3f686fdb0" | |||
| checksum = "e9367bdfa836b7e3cf895867f7a570283444da90562980ec2263d6e1569b16bc" | |||
| dependencies = [ | |||
| "cfg-if 1.0.0", | |||
| "winapi 0.3.9", | |||
| @@ -1012,9 +1003,9 @@ dependencies = [ | |||
| [[package]] | |||
| name = "mio" | |||
| version = "0.6.22" | |||
| version = "0.6.23" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" | |||
| checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" | |||
| dependencies = [ | |||
| "cfg-if 0.1.10", | |||
| "fuchsia-zircon", | |||
| @@ -1043,9 +1034,9 @@ dependencies = [ | |||
| [[package]] | |||
| name = "miow" | |||
| version = "0.2.1" | |||
| version = "0.2.2" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" | |||
| checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" | |||
| dependencies = [ | |||
| "kernel32-sys", | |||
| "net2", | |||
| @@ -1106,9 +1097,9 @@ checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" | |||
| [[package]] | |||
| name = "net2" | |||
| version = "0.2.35" | |||
| version = "0.2.36" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" | |||
| checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02" | |||
| dependencies = [ | |||
| "cfg-if 0.1.10", | |||
| "libc", | |||
| @@ -1215,18 +1206,18 @@ checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" | |||
| [[package]] | |||
| name = "ordered-float" | |||
| version = "1.1.0" | |||
| version = "1.1.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "3741934be594d77de1c8461ebcbbe866f585ea616a9753aa78f2bdc69f0e4579" | |||
| checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" | |||
| dependencies = [ | |||
| "num-traits", | |||
| ] | |||
| [[package]] | |||
| name = "ordered-float" | |||
| version = "2.0.0" | |||
| version = "2.0.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "9fe9037165d7023b1228bc4ae9a2fa1a2b0095eca6c2998c624723dfd01314a5" | |||
| checksum = "dacdec97876ef3ede8c50efc429220641a0b11ba0048b4b0c357bccbc47c5204" | |||
| dependencies = [ | |||
| "num-traits", | |||
| ] | |||
| @@ -1271,12 +1262,11 @@ dependencies = [ | |||
| [[package]] | |||
| name = "parking_lot_core" | |||
| version = "0.8.0" | |||
| version = "0.8.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" | |||
| checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0" | |||
| dependencies = [ | |||
| "cfg-if 0.1.10", | |||
| "cloudabi", | |||
| "cfg-if 1.0.0", | |||
| "instant", | |||
| "libc", | |||
| "redox_syscall", | |||
| @@ -1523,9 +1513,12 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" | |||
| [[package]] | |||
| name = "serde" | |||
| version = "1.0.117" | |||
| version = "1.0.118" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" | |||
| checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" | |||
| dependencies = [ | |||
| "serde_derive", | |||
| ] | |||
| [[package]] | |||
| name = "serde-value" | |||
| @@ -1533,7 +1526,7 @@ version = "0.6.0" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "5a65a7291a8a568adcae4c10a677ebcedbc6c9cec91c054dee2ce40b0e3290eb" | |||
| dependencies = [ | |||
| "ordered-float 1.1.0", | |||
| "ordered-float 1.1.1", | |||
| "serde", | |||
| ] | |||
| @@ -1621,9 +1614,12 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" | |||
| [[package]] | |||
| name = "smallvec" | |||
| version = "1.5.0" | |||
| version = "1.5.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "7acad6f34eb9e8a259d3283d1e8c1d34d7415943d4895f65cc73813c7396fc85" | |||
| checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75" | |||
| dependencies = [ | |||
| "serde", | |||
| ] | |||
| [[package]] | |||
| name = "smithay-client-toolkit" | |||
| @@ -1657,11 +1653,14 @@ dependencies = [ | |||
| "log", | |||
| "log4rs", | |||
| "num_cpus", | |||
| "ordered-float 2.0.0", | |||
| "ordered-float 2.0.1", | |||
| "rand", | |||
| "serde", | |||
| "serde_json", | |||
| "serde_yaml", | |||
| "shred", | |||
| "shrev", | |||
| "smallvec", | |||
| "specs", | |||
| "thiserror", | |||
| "tokio", | |||
| @@ -1699,9 +1698,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" | |||
| [[package]] | |||
| name = "syn" | |||
| version = "1.0.50" | |||
| version = "1.0.53" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "443b4178719c5a851e1bde36ce12da21d74a0e60b4d982ec3385a933c812f0f6" | |||
| checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68" | |||
| dependencies = [ | |||
| "proc-macro2", | |||
| "quote", | |||
| @@ -1761,9 +1760,9 @@ dependencies = [ | |||
| [[package]] | |||
| name = "tokio" | |||
| version = "0.3.4" | |||
| version = "0.3.5" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "9dfe2523e6fa84ddf5e688151d4e5fddc51678de9752c6512a24714c23818d61" | |||
| checksum = "a12a3eb39ee2c231be64487f1fcbe726c8f2514876a55480a5ab8559fc374252" | |||
| dependencies = [ | |||
| "autocfg", | |||
| "pin-project-lite", | |||
| @@ -2046,6 +2045,7 @@ dependencies = [ | |||
| "parking_lot", | |||
| "percent-encoding", | |||
| "raw-window-handle", | |||
| "serde", | |||
| "smithay-client-toolkit", | |||
| "wayland-client", | |||
| "winapi 0.3.9", | |||
| @@ -8,16 +8,19 @@ edition = "2018" | |||
| futures = "0.3" | |||
| gl = { version = "0.1", features = [ "use_log_crate" ] } | |||
| glc = "0.1" | |||
| glutin = "0.25" | |||
| glutin = { version = "0.25", features = [ "serde" ] } | |||
| glyph_brush = "0.7" | |||
| log = { version = "0.4", features = [ "max_level_trace", "release_max_level_warn" ] } | |||
| log4rs = "0.13" | |||
| num_cpus = "1.13" | |||
| ordered-float = "2.0" | |||
| rand = "0.7" | |||
| serde = { version = "1.0", features = ["derive"] } | |||
| serde_json = "1.0" | |||
| serde_yaml = "0.8" | |||
| shred = { version = "0.10", features = [ "shred-derive" ] } | |||
| shrev = "1.1" | |||
| smallvec = { version = "1.5", features = [ "serde" ] } | |||
| specs = "0.16" | |||
| thiserror = "1.0" | |||
| 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::{ | |||
| dpi::{PhysicalPosition, PhysicalSize}, | |||
| event_loop::EventLoop, | |||
| window::Window as GlutinWindow, | |||
| window::WindowBuilder, | |||
| monitor::VideoMode, | |||
| window::{Fullscreen, Window as GlutinWindow, WindowBuilder}, | |||
| Api, ContextBuilder, ContextWrapper, GlProfile, GlRequest, PossiblyCurrent, | |||
| }; | |||
| use log::info; | |||
| use log::{error, info}; | |||
| use crate::Error; | |||
| use super::super::resources::Config; | |||
| pub struct Window { | |||
| context: ContextWrapper<PossiblyCurrent, GlutinWindow>, | |||
| } | |||
| 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 context = loop { | |||
| let multisampling = match multisampling.next() { | |||
| Some(multisampling) => multisampling, | |||
| Some(multisampling) => *multisampling, | |||
| None => return Err(Error::CreateContext), | |||
| }; | |||
| if config.video.multisampling < multisampling { | |||
| continue; | |||
| } | |||
| info!("Create OpenGL context (multisampling={})", multisampling); | |||
| let window_builder = WindowBuilder::new() | |||
| .with_title("space-crush") | |||
| .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() | |||
| .with_double_buffer(Some(true)) | |||
| .with_hardware_acceleration(Some(true)) | |||
| .with_pixel_format(24, 8) | |||
| .with_multisampling(*multisampling) | |||
| .with_multisampling(multisampling) | |||
| .with_vsync(false) | |||
| .with_gl(GlRequest::Specific(Api::OpenGl, (4, 5))) | |||
| .with_gl_profile(GlProfile::Core) | |||
| @@ -68,6 +119,3 @@ impl Window { | |||
| Ok(()) | |||
| } | |||
| } | |||
| const WINDOW_WIDTH: u32 = 1280; | |||
| const WINDOW_HEIGHT: u32 = 720; | |||
| @@ -9,7 +9,7 @@ use crate::Error; | |||
| use misc::{Events, TextManager, Window}; | |||
| use render::{Debug, Init, Test}; | |||
| use resources::{Camera, Geometry, State}; | |||
| use resources::{Camera, Config, Geometry, State}; | |||
| use systems::StateUpdate; | |||
| pub struct App<'a, 'b> { | |||
| @@ -21,9 +21,11 @@ pub struct App<'a, 'b> { | |||
| impl<'a, 'b> App<'a, 'b> { | |||
| pub fn new(world: &mut World) -> Result<Self, Error> { | |||
| let config = Config::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(Geometry::new()?); | |||
| world.insert(State::default()); | |||
| @@ -11,8 +11,8 @@ use specs::{prelude::*, ReadExpect, System, World, WriteExpect}; | |||
| use crate::Error; | |||
| use super::super::{ | |||
| misc::{MouseEvent, VirtualKeyCode, WorldHelper}, | |||
| resources::{Camera, Geometry, State}, | |||
| misc::{MouseEvent, WorldHelper}, | |||
| resources::{Camera, Config, Geometry, State}, | |||
| }; | |||
| pub struct Init { | |||
| @@ -42,6 +42,7 @@ impl Init { | |||
| pub struct InitData<'a> { | |||
| camera: WriteExpect<'a, Camera>, | |||
| state: ReadExpect<'a, State>, | |||
| config: ReadExpect<'a, Config>, | |||
| geometry: ReadExpect<'a, Geometry>, | |||
| mouse_events: ReadExpect<'a, EventChannel<MouseEvent>>, | |||
| } | |||
| @@ -53,6 +54,7 @@ impl<'a> System<'a> for Init { | |||
| let InitData { | |||
| mut camera, | |||
| state, | |||
| config, | |||
| geometry, | |||
| mouse_events, | |||
| } = data; | |||
| @@ -72,7 +74,8 @@ impl<'a> System<'a> for Init { | |||
| let events = mouse_events.read(&mut self.mouse_event_id); | |||
| for event in events { | |||
| 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()) | |||
| * Matrix4f::scale(z.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 */ | |||
| 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 { | |||
| 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); | |||
| if let Err(err) = camera.update_with(move |v| m * v) { | |||
| error!("Error while moving camera: {}", err); | |||
| @@ -110,16 +112,3 @@ impl<'a> System<'a> for Init { | |||
| 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 config; | |||
| mod geometry; | |||
| mod state; | |||
| pub use camera::Camera; | |||
| pub use config::Config; | |||
| pub use geometry::Geometry; | |||
| pub use state::State; | |||
| @@ -1,6 +1,7 @@ | |||
| #![allow(dead_code)] | |||
| use std::collections::HashSet; | |||
| use std::iter::IntoIterator; | |||
| use super::super::misc::{MouseButton, VirtualKeyCode}; | |||
| @@ -9,37 +10,50 @@ pub struct State { | |||
| pub mouse_pos: (f32, f32), | |||
| pub resolution: (u32, u32), | |||
| 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 { | |||
| 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) { | |||
| if value { | |||
| self.key_states.insert(KeyState::KeyCode(code)); | |||
| self.key_states.insert(code); | |||
| } else { | |||
| self.key_states.remove(&KeyState::KeyCode(code)); | |||
| self.key_states.remove(&code); | |||
| } | |||
| } | |||
| pub fn set_button_state(&mut self, button: MouseButton, value: bool) { | |||
| if value { | |||
| self.key_states.insert(KeyState::MouseButton(button)); | |||
| self.button_states.insert(button); | |||
| } 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 glutin::{ContextError as GlutinContextError, CreationError as GlutinCreationError}; | |||
| 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 vfs::VfsError; | |||
| use vfs_zip::Error as VfsZipError; | |||
| @@ -19,8 +20,11 @@ pub enum Error { | |||
| #[error("VFS ZIP Error: {0}")] | |||
| VfsZipError(VfsZipError), | |||
| #[error("YML Error: {0}")] | |||
| YmlError(YmlError), | |||
| #[error("JSON Error: {0}")] | |||
| JsonError(JsonError), | |||
| #[error("YAML Error: {0}")] | |||
| YamlError(YamlError), | |||
| #[error("GLC Error: {0}")] | |||
| 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> { | |||
| let mut config = String::default(); | |||
| vfs.join("resources/log4rs.yml")? | |||
| vfs.join("log4rs.yml")? | |||
| .open_file()? | |||
| .read_to_string(&mut config)?; | |||