parent
0491ac6198
commit
4aa0222a1f
@ -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…
Reference in new issue