aboutsummaryrefslogtreecommitdiff
path: root/games
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2021-02-20 19:29:08 +0100
committerKatharina Fey <kookie@spacekookie.de>2021-02-21 16:20:21 +0100
commit4aa0222a1fb78aa66e6efd1179a1901d728dbfb8 (patch)
tree69ce1ae191edd0354a6e68a2b872f6fe6c7c3d7c /games
parent0491ac6198b4fa2946d799c5661286b8bd3c88de (diff)
rstnode: basic ui abstraction (text button)
Diffstat (limited to 'games')
-rw-r--r--games/rstnode/rst-client/src/color.rs27
-rw-r--r--games/rstnode/rst-client/src/editor/mod.rs50
-rw-r--r--games/rstnode/rst-client/src/ui/button.rs109
-rw-r--r--games/rstnode/rst-client/src/ui/mod.rs4
4 files changed, 189 insertions, 1 deletions
diff --git a/games/rstnode/rst-client/src/color.rs b/games/rstnode/rst-client/src/color.rs
index 4fbd7519dcd0..65c32974ac81 100644
--- a/games/rstnode/rst-client/src/color.rs
+++ b/games/rstnode/rst-client/src/color.rs
@@ -1,7 +1,32 @@
use ggez::graphics::Color as EzColor;
use rst_core::data::Color;
-
pub fn to(Color(r, g, b): Color) -> EzColor {
EzColor::from_rgb(r, g, b)
}
+
+/// A utility for manipulating colours
+pub trait ColorUtils {
+ fn darken(&self, factor: u8) -> Self;
+ fn brighten(&self, factor: u8) -> Self;
+}
+
+impl ColorUtils for EzColor {
+ fn darken(&self, factor: u8) -> Self {
+ Self {
+ r: self.r / factor as f32,
+ g: self.g / factor as f32,
+ b: self.b / factor as f32,
+ a: self.a,
+ }
+ }
+
+ fn brighten(&self, factor: u8) -> Self {
+ Self {
+ r: self.r * factor as f32,
+ g: self.g * factor as f32,
+ b: self.b * factor as f32,
+ a: self.a,
+ }
+ }
+}
diff --git a/games/rstnode/rst-client/src/editor/mod.rs b/games/rstnode/rst-client/src/editor/mod.rs
new file mode 100644
index 000000000000..ba7867017535
--- /dev/null
+++ b/games/rstnode/rst-client/src/editor/mod.rs
@@ -0,0 +1,50 @@
+use crate::{assets::Assets, input::InputHandle, ui::Button, viewport::Viewport, GameSettings};
+use ggez::{
+ event::{EventHandler, MouseButton},
+ graphics::{self, Color},
+ Context, GameResult,
+};
+
+pub struct EditorState {
+ assets: Assets,
+ settings: GameSettings,
+ input: InputHandle,
+ vp: Viewport,
+ btn: Button,
+}
+
+impl EditorState {
+ pub fn new(settings: GameSettings, assets: Assets) -> Self {
+ info!("Initialising map editor state");
+ Self {
+ assets,
+ settings,
+ vp: Viewport::new(),
+ input: InputHandle::new(),
+ btn: Button::new(
+ (25.0, 25.0).into(),
+ (250.0, 125.0).into(),
+ Some("Create Node".into()),
+ Color::from_rgb(50, 50, 50),
+ ),
+ }
+ }
+}
+
+impl EventHandler for EditorState {
+ fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
+ Ok(())
+ }
+
+ fn mouse_button_down_event(&mut self, ctx: &mut Context, btn: MouseButton, x: f32, y: f32) {
+ self.btn.mouse_button_down_event(ctx, btn, x, y)
+ }
+
+ fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
+ graphics::clear(ctx, graphics::Color::from_rgb(15, 15, 15));
+
+ self.btn.draw(ctx)?;
+
+ graphics::present(ctx)
+ }
+}
diff --git a/games/rstnode/rst-client/src/ui/button.rs b/games/rstnode/rst-client/src/ui/button.rs
new file mode 100644
index 000000000000..9d51b0271cbc
--- /dev/null
+++ b/games/rstnode/rst-client/src/ui/button.rs
@@ -0,0 +1,109 @@
+use crate::color::ColorUtils;
+use ggez::graphics::{self, Align, Color, DrawMode, DrawParam, Drawable, MeshBuilder, Rect, Text};
+use ggez::{
+ event::{EventHandler, MouseButton},
+ Context, GameResult,
+};
+use rst_core::data::Pos;
+use std::collections::HashMap;
+
+/// A button with next that can be clicked to run some code
+pub struct Button {
+ pos: Pos,
+ size: Pos,
+ text: Option<String>,
+ color_base: Color,
+ color_trim: Color,
+ cbs: HashMap<MouseButton, Box<dyn FnMut() -> ()>>,
+}
+
+impl Button {
+ /// Create a new button
+ pub fn new(
+ pos: Pos,
+ size: Pos,
+ text: impl Into<Option<String>>,
+ color: impl Into<Color>,
+ ) -> Self {
+ let color = color.into();
+
+ Self {
+ pos,
+ size,
+ text: text.into(),
+ color_base: color.clone(),
+ color_trim: color.brighten(2),
+ cbs: HashMap::new(),
+ }
+ }
+
+ /// Register an on-click listening closure
+ pub fn on_click<C: FnMut() -> () + 'static>(&mut self, btn: MouseButton, cb: C) {
+ self.cbs.insert(btn, Box::new(cb));
+ }
+
+ /// Create a button with text which auto-infers its required size
+ pub fn auto(pos: Pos, text: String, color: impl Into<Color>) -> Self {
+ todo!()
+ }
+
+ fn boundry_check(&self, x: f32, y: f32) -> bool {
+ self.pos.x < x
+ && (self.pos.x + self.size.x) > x
+ && self.pos.y < y
+ && (self.pos.y + self.size.y) > y
+ }
+}
+
+impl EventHandler for Button {
+ fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
+ Ok(())
+ }
+
+ fn mouse_button_down_event(&mut self, _ctx: &mut Context, btn: MouseButton, x: f32, y: f32) {
+ if self.boundry_check(x, y) {
+ trace!("Triggering button state");
+ std::mem::swap(&mut self.color_base, &mut self.color_trim);
+ if let Some(ref mut callback) = self.cbs.get_mut(&btn) {
+ callback();
+ }
+ }
+ }
+
+ fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
+ let mut mb = MeshBuilder::new();
+ let bounds = Rect {
+ x: self.pos.x,
+ y: self.pos.y,
+ w: self.size.x,
+ h: self.size.y,
+ };
+
+ // Create the basic building blocks
+ let rect = mb
+ .rectangle(DrawMode::fill(), bounds, self.color_base.clone())?
+ .build(ctx)?;
+ let frame = mb
+ .rectangle(DrawMode::stroke(2.0), bounds, self.color_trim.clone())?
+ .build(ctx)?;
+
+ rect.draw(ctx, DrawParam::new())?;
+ frame.draw(ctx, DrawParam::new())?;
+
+ if let Some(ref text) = self.text {
+ let Pos { x, y } = self.pos;
+ let Pos { x: w, y: h } = self.size;
+
+ let mut text = Text::new(text.clone());
+ text.draw(
+ ctx,
+ DrawParam::new().dest([
+ x + (w / 2.0 - text.width(ctx) / 2.0),
+ y + (h / 2.0 - text.height(ctx) / 2.0),
+ ]),
+ )?;
+ }
+
+ Ok(())
+ }
+}
diff --git a/games/rstnode/rst-client/src/ui/mod.rs b/games/rstnode/rst-client/src/ui/mod.rs
new file mode 100644
index 000000000000..449f04efc1e7
--- /dev/null
+++ b/games/rstnode/rst-client/src/ui/mod.rs
@@ -0,0 +1,4 @@
+//! Use ggez to render various UI elements and component clusters
+
+mod button;
+pub use button::*;