D src/draw.rs => src/draw.rs +0 -408
@@ 1,408 0,0 @@
-use macroquad::prelude::*;
-use crate::textures::AssetStore;
-
-/// A UI item that can be rendered
-pub trait Widget {
- /// Message types returned from the event loop
- type Event;
- /// Callback used to redraw the component
- async fn draw(&self, assets: &AssetStore);
- /// Callback used to perform background tasks
- /// e.g. keyboard input
- /// NOTE: this is currently not being run asynchronously
- /// when running large operations, spawn a separate thread
- fn ev_loop(&mut self) -> Self::Event;
- // returns the width and height of the widget
- fn get_dimensions(&self) -> (f32, f32);
-}
-
-/// UI Widget
-/// used to draw centered text
-pub struct CenteredText {
- /// middle of widget (along the x axis)
- /// set in percent of the display width
- x: f32,
- /// middle of widget (along the y axis)
- /// set in percent of the display height
- y: f32,
- /// the text to draw
- text: String,
- /// custom font size to use
- /// default is 60
- font_size: Option<u16>,
- /// the font to use
- /// defaults to macroquad default font
- font: Option<Font>,
- /// text color
- /// defaults to white
- color: Option<Color>
-}
-impl CenteredText {
- /// create new centered-text widget
- pub fn new(text: &str, x: f32, y: f32) -> Self {
- Self {
- x,
- y,
- text: text.to_string(),
- font_size: None,
- font: None,
- color: None
- }
- }
- /// changes the text of the widget
- pub fn set_text(self, text: &str) -> Self {
- Self {
- text: text.to_string(),
- ..self
- }
- }
- /// sets the font size
- pub fn with_font_size(self, font_size: u16) -> Self {
- Self {
- font_size: Some(font_size),
- ..self
- }
- }
- /// sets the font
- pub fn with_font(self, font: Font) -> Self {
- Self {
- font: Some(font),
- ..self
- }
- }
- /// sets a custom color
- pub fn with_color(self, color: Color) -> Self {
- Self {
- color: Some(color),
- ..self
- }
- }
-}
-impl Widget for CenteredText {
- type Event = bool;
- async fn draw(&self, assets: &AssetStore) {
- let (x,y) = (screen_width() * self.x, screen_height() * self.y);
-
- let mut title_params = TextParams {
- font_size: self.font_size.unwrap_or(60),
- color: self.color.unwrap_or(WHITE),
- ..Default::default()
- };
- if let Some(font) = self.font {
- title_params.font = font;
- }
- let title_center = get_text_center(
- &self.text,
- self.font,
- self.font_size.unwrap_or(60),
- 1.0,
- 0.0);
- draw_text_ex(
- &self.text,
- x - title_center.x,
- y- title_center.y,
- title_params);
- }
- fn ev_loop(&mut self) -> Self::Event {
- true
- }
- fn get_dimensions(&self) -> (f32, f32) {
- let text_dim: TextDimensions = measure_text(
- &self.text,
- self.font,
- self.font_size.unwrap_or(60),
- 1.0);
- (text_dim.width, text_dim.height)
- }
-}
-
-/// A button event send from the Button widget ev-loop
-/// i.e WideButton
-pub enum ButtonEvent {
- /// nothing happened
- None,
- /// user clicked on button with left mouse button
- LeftClick,
- /// user clicked on button with right mouse button
- RightClick
-}
-/// UI Widget
-/// a clickable button with text on it
-pub struct TextButton {
- /// the text on the button
- text: String,
- /// middle of button (x axis)
- /// specified in perfect of screen width
- x: f32,
- /// middle of button (y-axis)
- /// specified in perfect of screen height
- y: f32,
- /// the font used to draw the text
- font: Option<Font>,
- /// custom font color
- font_color: Option<Color>,
- /// custom font size to use
- font_size: Option<u16>,
- /// true if mouse is over button
- hovered: bool
-}
-impl TextButton {
- /// creates a new text button widget
- pub fn new(text: &str, x: f32, y: f32) -> Self {
- Self {
- text: text.to_string(),
- x,
- y,
- font: None,
- font_color: None,
- font_size: None,
- hovered: false
- }
- }
- /// sets the custom font
- pub fn with_font(self, font: Font) -> Self {
- Self {
- font: Some(font),
- ..self
- }
- }
- /// sets the font color
- pub fn with_font_color(self, color: Color) -> Self {
- Self {
- font_color: Some(color),
- ..self
- }
- }
- /// sets the font size
- pub fn with_font_size(self, size: u16) -> Self {
- Self {
- font_size: Some(size),
- ..self
- }
- }
-}
-impl Widget for TextButton {
- type Event = ButtonEvent;
- fn get_dimensions(&self) -> (f32, f32) {
- let text_dim: TextDimensions = measure_text(
- &self.text,
- self.font,
- self.font_size.unwrap_or(60),
- 1.0);
- (text_dim.width + 30.0, text_dim.height+20.0)
- }
- async fn draw(&self, assets: &AssetStore) {
- let (x,y) = (screen_width() * self.x, screen_height() * self.y);
- let (width, height) = self.get_dimensions();
-
- draw_texture_ex(
- if self.hovered { assets.ui.long_button.1 } else { assets.ui.long_button.0 },
- x - width / 2.0,
- y - height / 2.0,
- WHITE,
- DrawTextureParams {
- dest_size: Some(Vec2::new(width, height)),
- source: None,
- rotation: 0.0,
- flip_x: false,
- flip_y: false,
- pivot: None
- });
-
- let text_center = get_text_center(
- &self.text,
- self.font,
- self.font_size.unwrap_or(60),
- 1.0,
- 0.0);
- draw_text_ex(
- &self.text,
- x - text_center.x,
- y - text_center.y,
- TextParams {
- font_size: self.font_size.unwrap_or(60),
- color: self.font_color.unwrap_or(WHITE),
- ..Default::default()
- });
- }
- fn ev_loop(&mut self) -> Self::Event {
- self.hovered = false;
-
- let (width, height) = self.get_dimensions();
-
- let (mx, my) = mouse_position();
- let (x,y) = (screen_width() * self.x, screen_height() * self.y);
-
- if mx >= x - width/2.0 && mx <= x + width/2.0
- && my >= y - height/2.0 && my <= y + height/2.0 {
- self.hovered = true;
-
- if is_mouse_button_pressed(MouseButton::Left) {
- return Self::Event::LeftClick;
- }
- if is_mouse_button_pressed(MouseButton::Right) {
- return Self::Event::RightClick;
- }
- }
-
-
- Self::Event::None
- }
-}
-
-
-/// A widget similar to a button,
-/// but it can be selected
-/// and will stay selected
-pub struct SelectableText {
- /// the text on the button
- text: String,
- /// middle of button (x axis)
- /// specified in perfect of screen width
- x: f32,
- /// middle of button (y-axis)
- /// specified in perfect of screen height
- y: f32,
- /// the font used to draw the text
- font: Option<Font>,
- /// custom font color
- /// defaults to white
- font_color: Option<Color>,
- /// custom font size to use
- font_size: Option<u16>,
- /// true if widget option is selected
- selected: bool,
- /// if the widget is visible or not
- visible: bool
-}
-impl SelectableText {
- /// creates a new text button widget
- pub fn new(text: &str, x: f32, y: f32) -> Self {
- Self {
- text: text.to_string(),
- x,
- y,
- font: None,
- font_color: None,
- font_size: None,
- selected: false,
- visible: true
- }
- }
- /// set the visibility
- pub fn with_visibility(self, vis: bool) -> Self {
- Self {
- visible: vis,
- ..self
- }
- }
- /// sets the custom font
- pub fn with_font(self, font: Font) -> Self {
- Self {
- font: Some(font),
- ..self
- }
- }
- /// sets the font color
- pub fn with_font_color(self, color: Color) -> Self {
- Self {
- font_color: Some(color),
- ..self
- }
- }
- /// sets the font size
- pub fn with_font_size(self, size: u16) -> Self {
- Self {
- font_size: Some(size),
- ..self
- }
- }
- /// selects or unselects the Widget
- pub fn set_selected(&mut self, state: bool) {
- self.selected = state;
- }
- /// updates the widget text
- pub fn set_text(&mut self, text: &str) {
- self.text = text.to_string();
- }
- /// updates the widget visibility
- pub fn set_visibility(&mut self, vis: bool) {
- self.visible = vis;
- }
-}
-impl Widget for SelectableText {
- type Event = ButtonEvent;
- fn get_dimensions(&self) -> (f32, f32) {
- let text_dim: TextDimensions = measure_text(
- &self.text,
- self.font,
- self.font_size.unwrap_or(60),
- 1.0);
- (text_dim.width + 30.0, text_dim.height+20.0)
- }
- async fn draw(&self, assets: &AssetStore) {
- if !self.visible {
- return;
- }
-
- let (x,y) = (screen_width() * self.x, screen_height() * self.y);
- let (width, height) = self.get_dimensions();
-
- let mut bg = assets.ui.panel_brown.0;
- if self.selected {
- // draw blue background
- bg = assets.ui.panel_blue.0;
- }
- // draw background
- draw_texture_ex(
- bg,
- x - width/2.0,
- y - height/2.0,
- WHITE,
- DrawTextureParams {
- dest_size: Some(Vec2::new(width, height)),
- ..Default::default()
- }
- );
-
- let text_center = get_text_center(
- &self.text,
- self.font,
- self.font_size.unwrap_or(60),
- 1.0,
- 0.0);
- draw_text_ex(
- &self.text,
- x - text_center.x,
- y - text_center.y,
- TextParams {
- font_size: self.font_size.unwrap_or(60),
- color: self.font_color.unwrap_or(WHITE),
- ..Default::default()
- });
- }
- fn ev_loop(&mut self) -> Self::Event {
- if !self.visible {
- return Self::Event::None;
- }
-
- let (width, height) = self.get_dimensions();
-
- let (mx, my) = mouse_position();
- let (x,y) = (screen_width() * self.x, screen_height() * self.y);
-
- if mx >= x - width/2.0 && mx <= x + width/2.0
- && my >= y - height/2.0 && my <= y + height/2.0 {
- if is_mouse_button_pressed(MouseButton::Left) {
- return Self::Event::LeftClick;
- }
- if is_mouse_button_pressed(MouseButton::Right) {
- return Self::Event::RightClick;
- }
- }
-
-
- Self::Event::None
-
- }
-}
A src/ui/centered_text.rs => src/ui/centered_text.rs +104 -0
@@ 0,0 1,104 @@
+use macroquad::prelude::*;
+use crate::textures::AssetStore;
+use super::Widget;
+
+/// UI Widget
+/// used to draw centered text
+pub struct CenteredText {
+ /// middle of widget (along the x axis)
+ /// set in percent of the display width
+ x: f32,
+ /// middle of widget (along the y axis)
+ /// set in percent of the display height
+ y: f32,
+ /// the text to draw
+ text: String,
+ /// custom font size to use
+ /// default is 60
+ font_size: Option<u16>,
+ /// the font to use
+ /// defaults to macroquad default font
+ font: Option<Font>,
+ /// text color
+ /// defaults to white
+ color: Option<Color>
+}
+impl CenteredText {
+ /// create new centered-text widget
+ pub fn new(text: &str, x: f32, y: f32) -> Self {
+ Self {
+ x,
+ y,
+ text: text.to_string(),
+ font_size: None,
+ font: None,
+ color: None
+ }
+ }
+ /// sets the font size
+ #[allow(dead_code)]
+ pub fn with_font_size(self, font_size: u16) -> Self {
+ Self {
+ font_size: Some(font_size),
+ ..self
+ }
+ }
+ /// sets the font
+ #[allow(dead_code)]
+ pub fn with_font(self, font: Font) -> Self {
+ Self {
+ font: Some(font),
+ ..self
+ }
+ }
+ /// sets a custom color
+ #[allow(dead_code)]
+ pub fn with_color(self, color: Color) -> Self {
+ Self {
+ color: Some(color),
+ ..self
+ }
+ }
+ /// updates the text of this widget
+ #[allow(dead_code)]
+ pub fn set_text(&mut self, text: &str) {
+ self.text = text.to_string();
+ }
+}
+impl Widget for CenteredText {
+ type Event = bool;
+ async fn draw(&self, _assets: &AssetStore) {
+ let (x,y) = (screen_width() * self.x, screen_height() * self.y);
+
+ let mut title_params = TextParams {
+ font_size: self.font_size.unwrap_or(60),
+ color: self.color.unwrap_or(WHITE),
+ ..Default::default()
+ };
+ if let Some(font) = self.font {
+ title_params.font = font;
+ }
+ let title_center = get_text_center(
+ &self.text,
+ self.font,
+ self.font_size.unwrap_or(60),
+ 1.0,
+ 0.0);
+ draw_text_ex(
+ &self.text,
+ x - title_center.x,
+ y- title_center.y,
+ title_params);
+ }
+ fn ev_loop(&mut self) -> Self::Event {
+ true
+ }
+ fn get_dimensions(&self) -> (f32, f32) {
+ let text_dim: TextDimensions = measure_text(
+ &self.text,
+ self.font,
+ self.font_size.unwrap_or(60),
+ 1.0);
+ (text_dim.width, text_dim.height)
+ }
+}
A src/ui/item_frame.rs => src/ui/item_frame.rs +181 -0
@@ 0,0 1,181 @@
+use macroquad::prelude::*;
+use crate::textures::AssetStore;
+use crate::game::blocks::Block;
+use crate::game::types::Direction;
+use super::{Widget, ButtonEvent, CenteredText};
+
+pub struct ItemFrame {
+ /// middle of button (x axis)
+ /// specified in perfect of screen width
+ x: f32,
+ /// middle of button (y-axis)
+ /// specified in perfect of screen height
+ y: f32,
+ /// the block shown in the frame
+ block: Option<Block>,
+ /// should contain the item amount (when not in sandbox mode)
+ /// should be None in sandbox mode
+ amount: Option<usize>,
+ /// width/height of frame in
+ /// percent of smallest display size
+ size: f32,
+ /// true if widget option is selected
+ selected: bool,
+ /// widget used to display count
+ widget_amount: CenteredText,
+ /// the direciton the block is facing
+ direction: Direction
+}
+impl ItemFrame {
+ type Event = ButtonEvent;
+ /// creates a new widget
+ pub fn new(x: f32, y:f32, size: f32) -> Self {
+ Self {
+ x,
+ y,
+ size,
+ amount: None,
+ selected: false,
+ block: None,
+ direction: Direction::North,
+ widget_amount: CenteredText::new("", x, y)
+ .with_font_size(30)
+ }
+ }
+ /// adds a block to the item frame
+ #[allow(dead_code)]
+ pub fn with_block(self, block: Block, amount: Option<usize>) -> Self {
+ let mut this = Self {
+ block: Some(block),
+ amount,
+ ..self
+ };
+ if let Some(amount) = amount {
+ this.widget_amount.set_text(&format!("{}", amount));
+ } else {
+ this.widget_amount.set_text("inf");
+ }
+
+ this
+ }
+ /// changes the block inside the frame
+ #[allow(dead_code)]
+ pub fn change_block(&mut self, block: Block, amount: Option<usize>) {
+ self.block = Some(block);
+ self.amount = amount;
+
+ if let Some(amount) = amount {
+ self.widget_amount.set_text(&format!("{}", amount));
+ } else {
+ self.widget_amount.set_text("inf");
+ }
+ }
+ /// empties the item frame
+ #[allow(dead_code)]
+ pub fn empty(&mut self) {
+ self.block = None;
+ self.amount = None;
+ }
+ /// set widget selected state
+ #[allow(dead_code)]
+ pub fn set_selected(&mut self, state: bool) {
+ self.selected = state;
+ }
+ /// update block, direction and amount in one go
+ #[allow(dead_code)]
+ pub fn update(&mut self, selected: &Option<Block>, direction: &Direction, amount: &Option<usize>) {
+ if let Some(block) = selected {
+ self.block = Some(block.clone());
+ self.amount = Some(0);
+ self.amount = *amount;
+ } else {
+ self.block = None;
+ self.amount = None;
+ }
+ self.direction = direction.clone();
+ }
+}
+impl Widget for ItemFrame {
+ type Event = ButtonEvent;
+ fn get_dimensions(&self) -> (f32, f32) {
+ let smallest = if screen_width() < screen_height() { screen_width() } else { screen_height() };
+ (self.size * smallest, self.size * smallest)
+ }
+ async fn draw(&self, assets: &AssetStore) {
+ let (x,y) = (screen_width() * self.x, screen_height() * self.y);
+ let (size, _) = self.get_dimensions();
+
+ let mut bg = assets.ui.panel_brown.0;
+ if self.selected {
+ // selected block
+ // draw blue background
+ bg = assets.ui.panel_blue.0;
+ }
+ // draw background
+ draw_texture_ex(
+ bg,
+ x - size/2.0,
+ y - size/2.0,
+ WHITE,
+ DrawTextureParams {
+ dest_size: Some(Vec2::new(size, size)),
+ ..Default::default()
+ }
+ );
+
+ // draw brown foreground
+ {
+ let scale = size/100.0;
+ let dim = scale * 93.0;
+ draw_texture_ex(
+ assets.ui.panel_brown.1,
+ x - dim/2.0,
+ y - dim/2.0,
+ WHITE,
+ DrawTextureParams {
+ dest_size: Some(Vec2::new(dim, dim)),
+ ..Default::default()
+ }
+ );
+ }
+
+ if let Some(block) = &self.block {
+ // draw block
+ let width = size * 2.0/3.0;
+ let height = (width * 352.0) / 256.0;
+ draw_texture_ex(
+ block.get_texture().await.get_dir(&self.direction),
+ x - width / 2.0,
+ y - (height * 238.0)/352.0,
+
+ WHITE,
+ DrawTextureParams {
+ dest_size: Some(Vec2::new(
+ width,
+ height)),
+ ..Default::default()
+ }
+ );
+ // draw amount
+ self.widget_amount.draw(&assets).await;
+ }
+ }
+ fn ev_loop(&mut self) -> Self::Event {
+ let (width, height) = self.get_dimensions();
+
+ let (mx, my) = mouse_position();
+ let (x,y) = (screen_width() * self.x, screen_height() * self.y);
+
+ if mx >= x - width/2.0 && mx <= x + width/2.0
+ && my >= y - height/2.0 && my <= y + height/2.0 {
+ if is_mouse_button_pressed(MouseButton::Left) {
+ return Self::Event::LeftClick;
+ }
+ if is_mouse_button_pressed(MouseButton::Right) {
+ return Self::Event::RightClick;
+ }
+ }
+
+ Self::Event::None
+ }
+}
A src/ui/mod.rs => src/ui/mod.rs +38 -0
@@ 0,0 1,38 @@
+use macroquad::prelude::*;
+use crate::textures::AssetStore;
+
+mod centered_text;
+mod item_frame;
+mod selectable_text;
+mod text_button;
+
+pub use centered_text::CenteredText;
+pub use item_frame::ItemFrame;
+pub use selectable_text::SelectableText;
+pub use text_button::TextButton;
+
+/// A button event send from the Button widget ev-loop
+/// i.e WideButton
+pub enum ButtonEvent {
+ /// nothing happened
+ None,
+ /// user clicked on button with left mouse button
+ LeftClick,
+ /// user clicked on button with right mouse button
+ RightClick
+}
+
+/// A UI item that can be rendered
+pub trait Widget {
+ /// Message types returned from the event loop
+ type Event;
+ /// Callback used to redraw the component
+ async fn draw(&self, assets: &AssetStore);
+ /// Callback used to perform background tasks
+ /// e.g. keyboard input
+ /// NOTE: this is currently not being run asynchronously
+ /// when running large operations, spawn a separate thread
+ fn ev_loop(&mut self) -> Self::Event;
+ // returns the width and height of the widget
+ fn get_dimensions(&self) -> (f32, f32);
+}
A src/ui/selectable_text.rs => src/ui/selectable_text.rs +171 -0
@@ 0,0 1,171 @@
+use macroquad::prelude::*;
+use crate::textures::AssetStore;
+use super::{Widget, ButtonEvent};
+
+/// A widget similar to a button,
+/// but it can be selected
+/// and will stay selected
+pub struct SelectableText {
+ /// the text on the button
+ text: String,
+ /// middle of button (x axis)
+ /// specified in perfect of screen width
+ x: f32,
+ /// middle of button (y-axis)
+ /// specified in perfect of screen height
+ y: f32,
+ /// the font used to draw the text
+ font: Option<Font>,
+ /// custom font color
+ /// defaults to white
+ font_color: Option<Color>,
+ /// custom font size to use
+ font_size: Option<u16>,
+ /// true if widget option is selected
+ selected: bool,
+ /// if the widget is visible or not
+ visible: bool
+}
+impl SelectableText {
+ /// creates a new text button widget
+ pub fn new(text: &str, x: f32, y: f32) -> Self {
+ Self {
+ text: text.to_string(),
+ x,
+ y,
+ font: None,
+ font_color: None,
+ font_size: None,
+ selected: false,
+ visible: true
+ }
+ }
+ /// set the visibility
+ #[allow(dead_code)]
+ pub fn with_visibility(self, vis: bool) -> Self {
+ Self {
+ visible: vis,
+ ..self
+ }
+ }
+ /// sets the custom font
+ #[allow(dead_code)]
+ pub fn with_font(self, font: Font) -> Self {
+ Self {
+ font: Some(font),
+ ..self
+ }
+ }
+ /// sets the font color
+ #[allow(dead_code)]
+ pub fn with_font_color(self, color: Color) -> Self {
+ Self {
+ font_color: Some(color),
+ ..self
+ }
+ }
+ /// sets the font size
+ #[allow(dead_code)]
+ pub fn with_font_size(self, size: u16) -> Self {
+ Self {
+ font_size: Some(size),
+ ..self
+ }
+ }
+ /// selects or unselects the Widget
+ #[allow(dead_code)]
+ pub fn set_selected(&mut self, state: bool) {
+ self.selected = state;
+ }
+ /// updates the widget text
+ #[allow(dead_code)]
+ pub fn set_text(&mut self, text: &str) {
+ self.text = text.to_string();
+ }
+ /// updates the widget visibility
+ #[allow(dead_code)]
+ pub fn set_visibility(&mut self, vis: bool) {
+ self.visible = vis;
+ }
+ /// returns the text currently displayed on widget
+ #[allow(dead_code)]
+ pub fn get_text(&self) -> &str {
+ &self.text
+ }
+}
+impl Widget for SelectableText {
+ type Event = ButtonEvent;
+ fn get_dimensions(&self) -> (f32, f32) {
+ let text_dim: TextDimensions = measure_text(
+ &self.text,
+ self.font,
+ self.font_size.unwrap_or(60),
+ 1.0);
+ (text_dim.width + 30.0, text_dim.height+20.0)
+ }
+ async fn draw(&self, assets: &AssetStore) {
+ if !self.visible {
+ return;
+ }
+
+ let (x,y) = (screen_width() * self.x, screen_height() * self.y);
+ let (width, height) = self.get_dimensions();
+
+ let mut bg = assets.ui.panel_brown.0;
+ if self.selected {
+ // draw blue background
+ bg = assets.ui.panel_blue.0;
+ }
+ // draw background
+ draw_texture_ex(
+ bg,
+ x - width/2.0,
+ y - height/2.0,
+ WHITE,
+ DrawTextureParams {
+ dest_size: Some(Vec2::new(width, height)),
+ ..Default::default()
+ }
+ );
+
+ let text_center = get_text_center(
+ &self.text,
+ self.font,
+ self.font_size.unwrap_or(60),
+ 1.0,
+ 0.0);
+ draw_text_ex(
+ &self.text,
+ x - text_center.x,
+ y - text_center.y,
+ TextParams {
+ font_size: self.font_size.unwrap_or(60),
+ color: self.font_color.unwrap_or(WHITE),
+ ..Default::default()
+ });
+ }
+ fn ev_loop(&mut self) -> Self::Event {
+ if !self.visible {
+ return Self::Event::None;
+ }
+
+ let (width, height) = self.get_dimensions();
+
+ let (mx, my) = mouse_position();
+ let (x,y) = (screen_width() * self.x, screen_height() * self.y);
+
+ if mx >= x - width/2.0 && mx <= x + width/2.0
+ && my >= y - height/2.0 && my <= y + height/2.0 {
+ if is_mouse_button_pressed(MouseButton::Left) {
+ return Self::Event::LeftClick;
+ }
+ if is_mouse_button_pressed(MouseButton::Right) {
+ return Self::Event::RightClick;
+ }
+ }
+
+
+ Self::Event::None
+
+ }
+}
A src/ui/text_button.rs => src/ui/text_button.rs +135 -0
@@ 0,0 1,135 @@
+use macroquad::prelude::*;
+use crate::textures::AssetStore;
+use super::{Widget, ButtonEvent};
+
+/// UI Widget
+/// a clickable button with text on it
+pub struct TextButton {
+ /// the text on the button
+ text: String,
+ /// middle of button (x axis)
+ /// specified in perfect of screen width
+ x: f32,
+ /// middle of button (y-axis)
+ /// specified in perfect of screen height
+ y: f32,
+ /// the font used to draw the text
+ font: Option<Font>,
+ /// custom font color
+ font_color: Option<Color>,
+ /// custom font size to use
+ font_size: Option<u16>,
+ /// true if mouse is over button
+ hovered: bool
+}
+impl TextButton {
+ /// creates a new text button widget
+ pub fn new(text: &str, x: f32, y: f32) -> Self {
+ Self {
+ text: text.to_string(),
+ x,
+ y,
+ font: None,
+ font_color: None,
+ font_size: None,
+ hovered: false
+ }
+ }
+ /// sets the custom font
+ #[allow(dead_code)]
+ pub fn with_font(self, font: Font) -> Self {
+ Self {
+ font: Some(font),
+ ..self
+ }
+ }
+ /// sets the font color
+ #[allow(dead_code)]
+ pub fn with_font_color(self, color: Color) -> Self {
+ Self {
+ font_color: Some(color),
+ ..self
+ }
+ }
+ /// sets the font size
+ #[allow(dead_code)]
+ pub fn with_font_size(self, size: u16) -> Self {
+ Self {
+ font_size: Some(size),
+ ..self
+ }
+ }
+ /// updates the widget text
+ #[allow(dead_code)]
+ pub fn set_text(&mut self, text: &str) {
+ self.text = text.to_string();
+ }
+}
+impl Widget for TextButton {
+ type Event = ButtonEvent;
+ fn get_dimensions(&self) -> (f32, f32) {
+ let text_dim: TextDimensions = measure_text(
+ &self.text,
+ self.font,
+ self.font_size.unwrap_or(60),
+ 1.0);
+ (text_dim.width + 30.0, text_dim.height+20.0)
+ }
+ async fn draw(&self, assets: &AssetStore) {
+ let (x,y) = (screen_width() * self.x, screen_height() * self.y);
+ let (width, height) = self.get_dimensions();
+
+ draw_texture_ex(
+ if self.hovered { assets.ui.long_button.1 } else { assets.ui.long_button.0 },
+ x - width / 2.0,
+ y - height / 2.0,
+ WHITE,
+ DrawTextureParams {
+ dest_size: Some(Vec2::new(width, height)),
+ source: None,
+ rotation: 0.0,
+ flip_x: false,
+ flip_y: false,
+ pivot: None
+ });
+
+ let text_center = get_text_center(
+ &self.text,
+ self.font,
+ self.font_size.unwrap_or(60),
+ 1.0,
+ 0.0);
+ draw_text_ex(
+ &self.text,
+ x - text_center.x,
+ y - text_center.y,
+ TextParams {
+ font_size: self.font_size.unwrap_or(60),
+ color: self.font_color.unwrap_or(WHITE),
+ ..Default::default()
+ });
+ }
+ fn ev_loop(&mut self) -> Self::Event {
+ self.hovered = false;
+
+ let (width, height) = self.get_dimensions();
+
+ let (mx, my) = mouse_position();
+ let (x,y) = (screen_width() * self.x, screen_height() * self.y);
+
+ if mx >= x - width/2.0 && mx <= x + width/2.0
+ && my >= y - height/2.0 && my <= y + height/2.0 {
+ self.hovered = true;
+
+ if is_mouse_button_pressed(MouseButton::Left) {
+ return Self::Event::LeftClick;
+ }
+ if is_mouse_button_pressed(MouseButton::Right) {
+ return Self::Event::RightClick;
+ }
+ }
+
+
+ Self::Event::None
+ }
+}