@@ -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)?; | |||