rstnode: basic ui abstraction (text button)

wip/yesman
Katharina Fey 3 years ago
parent 0491ac6198
commit 4aa0222a1f
Signed by: kookie
GPG Key ID: 90734A9E619C8A6C
  1. 27
      games/rstnode/rst-client/src/color.rs
  2. 50
      games/rstnode/rst-client/src/editor/mod.rs
  3. 109
      games/rstnode/rst-client/src/ui/button.rs
  4. 4
      games/rstnode/rst-client/src/ui/mod.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,
}
}
}

@ -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)
}
}

@ -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(())
}
}

@ -0,0 +1,4 @@
//! Use ggez to render various UI elements and component clusters
mod button;
pub use button::*;
Loading…
Cancel
Save