aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--games/rstnode/rst-client/src/graphics/mod.rs4
-rw-r--r--games/rstnode/rst-client/src/graphics/vector2.rs82
-rw-r--r--games/rstnode/rst-client/src/input.rs23
-rw-r--r--games/rstnode/rst-client/src/main.rs9
-rw-r--r--games/rstnode/rst-client/src/state.rs16
-rw-r--r--games/rstnode/rst-client/src/viewport.rs63
6 files changed, 187 insertions, 10 deletions
diff --git a/games/rstnode/rst-client/src/graphics/mod.rs b/games/rstnode/rst-client/src/graphics/mod.rs
index 095e66f1ad1f..a7ba676ecc6b 100644
--- a/games/rstnode/rst-client/src/graphics/mod.rs
+++ b/games/rstnode/rst-client/src/graphics/mod.rs
@@ -8,8 +8,12 @@
pub mod entities;
pub mod ui;
+mod vector2;
+pub use vector2::*;
+
use crate::state::ClientState;
use ggez::{Context, GameResult};
+use std::ops::{Add, Mul, Sub};
/// A utility module to include everything required to implement a
/// graphics entity
diff --git a/games/rstnode/rst-client/src/graphics/vector2.rs b/games/rstnode/rst-client/src/graphics/vector2.rs
new file mode 100644
index 000000000000..5204e77fa443
--- /dev/null
+++ b/games/rstnode/rst-client/src/graphics/vector2.rs
@@ -0,0 +1,82 @@
+use std::fmt::{self, Display, Formatter};
+use std::ops::{Add, Mul, Sub, SubAssign};
+
+/// Just a vector
+#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd)]
+pub struct Vector2 {
+ pub x: f32,
+ pub y: f32,
+}
+
+impl Display for Vector2 {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "[{}, {}]", self.x, self.y)
+ }
+}
+
+impl Vector2 {
+ pub fn new(x: f32, y: f32) -> Self {
+ Self { x, y }
+ }
+
+ pub fn abs(self) -> Self {
+ Self {
+ x: self.x.abs(),
+ y: self.y.abs(),
+ }
+ }
+}
+
+impl Sub for Vector2 {
+ type Output = Vector2;
+
+ fn sub(self, o: Vector2) -> Self::Output {
+ Vector2 {
+ x: self.x - o.x,
+ y: self.y - o.y,
+ }
+ }
+}
+
+impl SubAssign for Vector2 {
+ fn sub_assign(&mut self, o: Self) {
+ *self = Self {
+ x: self.x - o.x,
+ y: self.y - o.y,
+ }
+ }
+}
+
+impl Add for Vector2 {
+ type Output = Vector2;
+
+ fn add(self, o: Vector2) -> Self::Output {
+ Vector2 {
+ x: self.x + o.x,
+ y: self.y + o.y,
+ }
+ }
+}
+
+impl Mul for Vector2 {
+ type Output = Vector2;
+
+ fn mul(self, o: Vector2) -> Self::Output {
+ Vector2 {
+ x: self.x * o.x,
+ y: self.y * o.y,
+ }
+ }
+}
+
+impl From<Vector2> for mint::Point2<f32> {
+ fn from(v: Vector2) -> Self {
+ [v.x, v.y].into()
+ }
+}
+
+impl From<mint::Point2<f32>> for Vector2 {
+ fn from(v: mint::Point2<f32>) -> Self {
+ Self { x: v.x, y: v.y }
+ }
+}
diff --git a/games/rstnode/rst-client/src/input.rs b/games/rstnode/rst-client/src/input.rs
index 4e901b8ade06..281386986434 100644
--- a/games/rstnode/rst-client/src/input.rs
+++ b/games/rstnode/rst-client/src/input.rs
@@ -1,50 +1,55 @@
//! Advanced input handler
+use crate::{graphics::Vector2, viewport::Viewport};
use ggez::{
event::EventHandler,
input::mouse::{self, MouseButton},
Context, GameResult,
};
-use mint::Point2;
pub struct InputHandle {
/// The mouse position on the viewport
- pub mouse_pos: Point2<f32>,
+ pub mouse_pos: Vector2,
/// Whether the left mouse button is pressed this frame
pub left_pressed: bool,
+ /// Whether the middle mouse button is pressed this frame
+ pub middle_pressed: bool,
/// Whether the right mouse button is pressed this frame
pub right_pressed: bool,
/// Set when pressing left mouse and unset when releasing it
- pub drag_point: Option<Point2<f32>>,
+ pub drag_point: Option<Vector2>,
}
impl InputHandle {
pub fn new() -> Self {
Self {
- mouse_pos: [0.0, 0.0].into(),
+ mouse_pos: Vector2::new(0.0, 0.0),
left_pressed: false,
+ middle_pressed: false,
right_pressed: false,
drag_point: None,
}
}
/// Get the unprojected mouse coordinates
- pub fn unproject(&self) -> Point2<f32> {
- self.mouse_pos.clone();
+ pub fn unproject(&self, vp: &Viewport) -> Vector2 {
+ // self.mouse_pos.clone() - vp.start().clone()
+
todo!()
}
}
impl EventHandler for InputHandle {
fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
- self.mouse_pos = mouse::position(&ctx);
+ self.mouse_pos = mouse::position(&ctx).into();
self.left_pressed = mouse::button_pressed(ctx, MouseButton::Left);
+ self.middle_pressed = mouse::button_pressed(ctx, MouseButton::Middle);
self.right_pressed = mouse::button_pressed(ctx, MouseButton::Right);
// Only set the drag_point once and unset when we release Left button
- if self.left_pressed && self.drag_point.is_none() {
+ if self.middle_pressed && self.drag_point.is_none() {
self.drag_point = Some(self.mouse_pos.clone());
- } else if !self.left_pressed {
+ } else if !self.middle_pressed {
self.drag_point = None;
}
diff --git a/games/rstnode/rst-client/src/main.rs b/games/rstnode/rst-client/src/main.rs
index aa86de26c952..a6ba4a59cdc1 100644
--- a/games/rstnode/rst-client/src/main.rs
+++ b/games/rstnode/rst-client/src/main.rs
@@ -14,6 +14,7 @@ mod input;
mod log;
mod settings;
mod state;
+mod viewport;
mod window;
#[allow(unused)]
@@ -36,7 +37,13 @@ fn main() {
// Load assets tree
let assets =
assets::load_tree(window.ctx(), &settings).unwrap_or_else(|e| fatal!("LoadError: {}!", e));
- let state = ClientState::new(settings, assets);
+ // Create the client state
+ let mut state = ClientState::new(settings, assets);
+
+ // Initialise the viewport first!
+ state.viewport().init(window.ctx());
+
+ // Window goes brrrr
window.run(state)
}
diff --git a/games/rstnode/rst-client/src/state.rs b/games/rstnode/rst-client/src/state.rs
index b1b5e89f3d13..d3b5bbcc3d7b 100644
--- a/games/rstnode/rst-client/src/state.rs
+++ b/games/rstnode/rst-client/src/state.rs
@@ -7,6 +7,7 @@ use crate::{
Renderer,
},
input::InputHandle,
+ viewport::Viewport,
GameSettings,
};
use ggez::{event::EventHandler, graphics, Context, GameResult};
@@ -17,6 +18,7 @@ pub struct ClientState {
assets: Assets,
settings: GameSettings,
input: InputHandle,
+ vp: Viewport,
// Game state
node: NodeRndr,
@@ -27,6 +29,7 @@ impl ClientState {
Self {
assets,
settings,
+ vp: Viewport::new(),
input: InputHandle::new(),
node: NodeRndr {
loc: Coordinates(512.0, 512.0),
@@ -49,6 +52,10 @@ impl ClientState {
}
}
+ pub fn viewport(&mut self) -> &mut Viewport {
+ &mut self.vp
+ }
+
pub fn assets(&self) -> &Assets {
&self.assets
}
@@ -56,7 +63,16 @@ impl ClientState {
impl EventHandler for ClientState {
fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
+ // TODO: get simulation updates
+
+ // Get new input state
self.input.update(ctx)?;
+
+ // Apply inputs to viewpoirt
+ self.vp.apply(ctx, &self.input)?;
+
+ // Update viewport
+ self.vp.update(ctx)?;
Ok(())
}
diff --git a/games/rstnode/rst-client/src/viewport.rs b/games/rstnode/rst-client/src/viewport.rs
new file mode 100644
index 000000000000..3f9e803e387b
--- /dev/null
+++ b/games/rstnode/rst-client/src/viewport.rs
@@ -0,0 +1,63 @@
+//! Viewport utilities
+
+use crate::{graphics::Vector2, input::InputHandle};
+use ggez::{
+ error::GameResult,
+ graphics::{self, Rect},
+ Context,
+};
+
+#[derive(Default)]
+pub struct Viewport {
+ start: Vector2,
+ prev_start: Vector2,
+ size: Vector2,
+}
+
+impl Viewport {
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ pub fn start(&self) -> &Vector2 {
+ &self.start
+ }
+
+ /// Must be called at least once before calling
+ /// [`update`](Self::update)
+ pub fn init(&mut self, ctx: &mut Context) {
+ let Rect { x, y, w, h } = graphics::screen_coordinates(&ctx);
+ self.start = Vector2::new(x, y);
+ self.prev_start = self.start;
+ self.size = Vector2::new(w, h);
+ }
+
+ /// Update the game state with the curent viewport data
+ pub fn update(&self, ctx: &mut Context) -> GameResult<()> {
+ graphics::set_screen_coordinates(
+ ctx,
+ Rect {
+ x: self.start.x,
+ y: self.start.y,
+ w: self.size.x,
+ h: self.size.y,
+ },
+ )?;
+
+ Ok(())
+ }
+
+ /// Apply changes from the input handle to the viewport
+ pub fn apply(&mut self, _: &mut Context, input: &InputHandle) -> GameResult<()> {
+ if input.middle_pressed {
+ let drag = input.drag_point.as_ref().unwrap().clone();
+ let pos = input.mouse_pos.clone();
+ self.start = self.prev_start + (drag - pos);
+ debug!("Changing VP start: {}", self.start);
+ } else {
+ self.prev_start = self.start;
+ }
+
+ Ok(())
+ }
+}