Compare commits
3 commits
b9f76bb486
...
c5328126b3
Author | SHA1 | Date | |
---|---|---|---|
c5328126b3 | |||
b5600b301d | |||
6fc41bdb17 |
5 changed files with 365 additions and 214 deletions
|
@ -4,7 +4,6 @@
|
|||
logic mostly like https://git.crispypin.cc/CrispyPin/marble
|
||||
|
||||
## todo
|
||||
- show level info in editor
|
||||
- comments
|
||||
- accessibility
|
||||
- ui scaling
|
||||
|
|
382
src/editor.rs
382
src/editor.rs
|
@ -21,8 +21,8 @@ use crate::{
|
|||
const HEADER_HEIGHT: i32 = 40;
|
||||
const FOOTER_HEIGHT: i32 = 95;
|
||||
const SIDEBAR_WIDTH: i32 = 200 + 32 * 2 + 5 * 4;
|
||||
const POPUP_WIDTH: i32 = 320;
|
||||
const POPUP_HEIGHT: i32 = 165;
|
||||
const END_POPUP_WIDTH: i32 = 320;
|
||||
const END_POPUP_HEIGHT: i32 = 165;
|
||||
|
||||
const MAX_ZOOM: f32 = 8.;
|
||||
const MIN_ZOOM: f32 = 0.25;
|
||||
|
@ -56,9 +56,11 @@ pub struct Editor {
|
|||
exit_state: ExitState,
|
||||
exit_menu: bool,
|
||||
total_steps: usize,
|
||||
popup: EndPopup,
|
||||
popup: Popup,
|
||||
score: Option<Score>,
|
||||
tooltip: Tooltip,
|
||||
mouse: MouseInput,
|
||||
info_text: ShapedText,
|
||||
|
||||
blueprints: Vec<Blueprint>,
|
||||
selected_blueprint: usize,
|
||||
|
@ -80,10 +82,12 @@ enum Action {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum EndPopup {
|
||||
enum Popup {
|
||||
None,
|
||||
Success,
|
||||
Failure,
|
||||
LevelInfo,
|
||||
PauseMenu,
|
||||
Dismissed,
|
||||
}
|
||||
|
||||
|
@ -134,6 +138,8 @@ impl Editor {
|
|||
input_as_text = i.input().is_text();
|
||||
machine.set_input(i.input().as_bytes().to_owned());
|
||||
}
|
||||
let mut info_text = ShapedText::new(20);
|
||||
info_text.set_text(level.description());
|
||||
|
||||
Self {
|
||||
source_board: Board::parse(&solution.board),
|
||||
|
@ -158,7 +164,8 @@ impl Editor {
|
|||
level,
|
||||
exit_state: ExitState::Dont,
|
||||
exit_menu: false,
|
||||
popup: EndPopup::None,
|
||||
popup: Popup::None,
|
||||
info_text,
|
||||
score: solution.score,
|
||||
total_steps: 0,
|
||||
blueprints: get_blueprints(),
|
||||
|
@ -172,6 +179,7 @@ impl Editor {
|
|||
undo_history: Vec::new(),
|
||||
undo_index: 0,
|
||||
tooltip: Tooltip::default(),
|
||||
mouse: MouseInput::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -292,18 +300,18 @@ impl Editor {
|
|||
self.machine.step();
|
||||
|
||||
if let Some(i) = self.stage {
|
||||
if self.popup != EndPopup::None {
|
||||
self.popup = EndPopup::Dismissed;
|
||||
if self.popup != Popup::None {
|
||||
self.popup = Popup::Dismissed;
|
||||
}
|
||||
let stage = &self.level.stages()[i];
|
||||
if self.popup == EndPopup::None {
|
||||
if self.popup == Popup::None {
|
||||
if stage.output().as_bytes() == self.machine.output() {
|
||||
if i + 1 < self.level.stages().len() {
|
||||
self.stage = Some(i + 1);
|
||||
self.total_steps += self.machine.step_count();
|
||||
self.reset_machine();
|
||||
} else {
|
||||
self.popup = EndPopup::Success;
|
||||
self.popup = Popup::Success;
|
||||
println!("completed in {:?}", self.start_time.elapsed());
|
||||
self.exit_state = ExitState::Save;
|
||||
self.sim_state = SimState::Stepping;
|
||||
|
@ -313,7 +321,7 @@ impl Editor {
|
|||
});
|
||||
}
|
||||
} else if !stage.output().as_bytes().starts_with(self.machine.output()) {
|
||||
self.popup = EndPopup::Failure;
|
||||
self.popup = Popup::Failure;
|
||||
self.sim_state = SimState::Stepping;
|
||||
}
|
||||
}
|
||||
|
@ -435,9 +443,15 @@ impl Editor {
|
|||
}
|
||||
|
||||
pub fn update(&mut self, rl: &RaylibHandle) {
|
||||
self.tooltip.init_frame(rl);
|
||||
self.mouse = MouseInput::get(rl);
|
||||
if !matches!(self.popup, Popup::None | Popup::Dismissed) {
|
||||
self.mouse.clear();
|
||||
}
|
||||
|
||||
if rl.is_key_pressed(KeyboardKey::KEY_ESCAPE) {
|
||||
self.sim_state = SimState::Editing;
|
||||
self.popup = EndPopup::None;
|
||||
self.popup = Popup::None;
|
||||
}
|
||||
if self.sim_state == SimState::Running {
|
||||
self.time_since_step += rl.get_frame_time();
|
||||
|
@ -478,27 +492,26 @@ impl Editor {
|
|||
}
|
||||
SimState::Running => {
|
||||
self.sim_state = SimState::Editing;
|
||||
self.popup = EndPopup::None;
|
||||
self.popup = Popup::None;
|
||||
}
|
||||
SimState::Stepping => self.sim_state = SimState::Running,
|
||||
}
|
||||
}
|
||||
|
||||
let mouse_pos = rl.get_mouse_position();
|
||||
let mouse_pos = self.mouse.pos();
|
||||
if (self.active_tool != Tool::Blueprint
|
||||
|| self.sim_state != SimState::Editing
|
||||
|| mouse_pos.x > SIDEBAR_WIDTH as f32)
|
||||
&& mouse_pos.y > HEADER_HEIGHT as f32
|
||||
&& (mouse_pos.y as i32) < (rl.get_screen_height() - FOOTER_HEIGHT)
|
||||
{
|
||||
if rl.get_mouse_wheel_move() > 0. {
|
||||
self.zoom_in(rl);
|
||||
}
|
||||
if rl.get_mouse_wheel_move() < 0. {
|
||||
self.zoom_out(rl);
|
||||
match self.mouse.scroll() {
|
||||
Some(Scroll::Up) => self.zoom_in(rl),
|
||||
Some(Scroll::Down) => self.zoom_out(rl),
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
if rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_RIGHT) {
|
||||
if self.mouse.right_hold() {
|
||||
let speed = if rl.is_key_down(KeyboardKey::KEY_LEFT_SHIFT) {
|
||||
4.
|
||||
} else {
|
||||
|
@ -562,105 +575,151 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
|
||||
self.tooltip.init_frame(d);
|
||||
|
||||
self.draw_board(d, textures);
|
||||
self.board_overlay(d, textures);
|
||||
self.draw_bottom_bar(d, textures);
|
||||
self.draw_top_bar(d, textures);
|
||||
|
||||
if self.active_tool == Tool::Blueprint {
|
||||
let sidebar_height = d.get_screen_height() - FOOTER_HEIGHT - HEADER_HEIGHT - 40;
|
||||
self.draw_blueprint_sidebar(d, textures);
|
||||
}
|
||||
|
||||
self.mouse = MouseInput::get(d);
|
||||
|
||||
if !matches!(self.popup, Popup::None | Popup::Dismissed) {
|
||||
self.tooltip.reset();
|
||||
d.draw_rectangle(
|
||||
0,
|
||||
HEADER_HEIGHT + 20,
|
||||
SIDEBAR_WIDTH,
|
||||
sidebar_height,
|
||||
Color::new(32, 32, 32, 255),
|
||||
0,
|
||||
d.get_screen_width(),
|
||||
d.get_screen_height(),
|
||||
Color::new(100, 100, 100, 120),
|
||||
);
|
||||
d.draw_text("Blueprints", 10, HEADER_HEIGHT + 30, 20, Color::WHITE);
|
||||
let mut y = HEADER_HEIGHT + 60;
|
||||
let blueprints_shown = (sidebar_height as usize - 45) / 37;
|
||||
let end = self
|
||||
.blueprints
|
||||
.len()
|
||||
.min(blueprints_shown + self.blueprint_scroll);
|
||||
for (i, b) in self.blueprints[self.blueprint_scroll..end]
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
{
|
||||
let i = i + self.blueprint_scroll;
|
||||
self.tooltip.add(5, y, 32, 32, "Delete");
|
||||
if simple_button(d, 5, y, 32, 32) {
|
||||
b.remove_file();
|
||||
self.blueprints.remove(i);
|
||||
break;
|
||||
}
|
||||
draw_scaled_texture(d, textures.get("rubbish"), 5, y, 2.);
|
||||
let is_selected = self.selected_blueprint == i;
|
||||
let mut text_selected = is_selected && self.blueprint_name_selected;
|
||||
text_input(
|
||||
d,
|
||||
Rectangle::new(42., y as f32, 200., 32.),
|
||||
&mut b.name,
|
||||
&mut text_selected,
|
||||
32,
|
||||
is_selected,
|
||||
);
|
||||
if is_selected {
|
||||
self.blueprint_name_selected = text_selected;
|
||||
}
|
||||
self.tooltip.add(42 + 205, y, 32, 32, "Select");
|
||||
simple_option_button(d, 42 + 205, y, 32, 32, i, &mut self.selected_blueprint);
|
||||
}
|
||||
|
||||
d.draw_texture_ex(
|
||||
textures.get("blueprint"),
|
||||
Vector2::new((42 + 205) as f32, y as f32),
|
||||
0.,
|
||||
2.,
|
||||
Color::new(255, 255, 255, if is_selected { 255 } else { 150 }),
|
||||
);
|
||||
y += 37;
|
||||
match self.popup {
|
||||
Popup::Success | Popup::Failure => {
|
||||
self.draw_end_popup(d, textures);
|
||||
}
|
||||
Popup::LevelInfo => {
|
||||
let bounds = screen_centered_rect_dyn(d, 100, 100);
|
||||
d.draw_rectangle_rec(bounds, BG_MEDIUM);
|
||||
d.draw_text(self.level.name(), 110, 110, 30, Color::LIGHTBLUE);
|
||||
self.info_text.update_width(d, bounds.width as i32 - 20);
|
||||
self.info_text.draw(d, 110, 140);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.tooltip.draw(d);
|
||||
}
|
||||
|
||||
if matches!(self.popup, EndPopup::Success | EndPopup::Failure) {
|
||||
let x = d.get_screen_width() / 2 - POPUP_WIDTH / 2;
|
||||
let y = d.get_screen_height() / 2 - POPUP_HEIGHT / 2;
|
||||
d.draw_rectangle(x, y, POPUP_WIDTH, POPUP_HEIGHT, BG_DARK);
|
||||
if self.popup == EndPopup::Success {
|
||||
d.draw_text("Level Complete!", x + 45, y + 10, 30, Color::LIME);
|
||||
if let Some(score) = &self.score {
|
||||
d.draw_text("cycles", x + 15, y + 45, 20, Color::WHITE);
|
||||
draw_usize(d, textures, score.cycles, x + 10, y + 70, 9, 2);
|
||||
d.draw_text("tiles", x + 215, y + 45, 20, Color::WHITE);
|
||||
draw_usize(d, textures, score.tiles, x + 210, y + 70, 5, 2);
|
||||
}
|
||||
if simple_button(d, x + 10, y + 110, 140, 45) {
|
||||
self.popup = EndPopup::Dismissed;
|
||||
}
|
||||
d.draw_text("continue\nediting", x + 15, y + 115, 20, Color::WHITE);
|
||||
|
||||
if simple_button(d, x + POPUP_WIDTH / 2 + 5, y + 110, 140, 45) {
|
||||
self.exit_state = ExitState::ExitAndSave;
|
||||
}
|
||||
d.draw_text(
|
||||
"return to\nlevel list",
|
||||
x + POPUP_WIDTH / 2 + 10,
|
||||
y + 115,
|
||||
20,
|
||||
Color::WHITE,
|
||||
);
|
||||
} else {
|
||||
d.draw_text("Level Failed!", x + 45, y + 10, 30, Color::RED);
|
||||
d.draw_text("incorrect output", x + 45, y + 45, 20, Color::WHITE);
|
||||
if simple_button(d, x + 10, y + 110, 300, 25) {
|
||||
self.popup = EndPopup::Dismissed;
|
||||
}
|
||||
d.draw_text("ok :(", x + 15, y + 115, 20, Color::WHITE);
|
||||
fn draw_blueprint_sidebar(&mut self, d: &mut RaylibDrawHandle, textures: &Textures) {
|
||||
let sidebar_height = d.get_screen_height() - FOOTER_HEIGHT - HEADER_HEIGHT - 40;
|
||||
d.draw_rectangle(
|
||||
0,
|
||||
HEADER_HEIGHT + 20,
|
||||
SIDEBAR_WIDTH,
|
||||
sidebar_height,
|
||||
Color::new(32, 32, 32, 255),
|
||||
);
|
||||
d.draw_text("Blueprints", 10, HEADER_HEIGHT + 30, 20, Color::WHITE);
|
||||
let mut y = HEADER_HEIGHT + 60;
|
||||
let blueprints_shown = (sidebar_height as usize - 45) / 37;
|
||||
let end = self
|
||||
.blueprints
|
||||
.len()
|
||||
.min(blueprints_shown + self.blueprint_scroll);
|
||||
for (i, b) in self.blueprints[self.blueprint_scroll..end]
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
{
|
||||
let i = i + self.blueprint_scroll;
|
||||
self.tooltip.add(5, y, 32, 32, "Delete");
|
||||
if simple_button(d, &self.mouse, 5, y, 32, 32) {
|
||||
b.remove_file();
|
||||
self.blueprints.remove(i);
|
||||
break;
|
||||
}
|
||||
draw_scaled_texture(d, textures.get("rubbish"), 5, y, 2.);
|
||||
let is_selected = self.selected_blueprint == i;
|
||||
let mut text_selected = is_selected && self.blueprint_name_selected;
|
||||
text_input(
|
||||
d,
|
||||
&self.mouse,
|
||||
Rectangle::new(42., y as f32, 200., 32.),
|
||||
&mut b.name,
|
||||
&mut text_selected,
|
||||
32,
|
||||
is_selected,
|
||||
);
|
||||
if is_selected {
|
||||
self.blueprint_name_selected = text_selected;
|
||||
}
|
||||
self.tooltip.add(42 + 205, y, 32, 32, "Select");
|
||||
simple_option_button(
|
||||
d,
|
||||
&self.mouse,
|
||||
42 + 205,
|
||||
y,
|
||||
32,
|
||||
32,
|
||||
i,
|
||||
&mut self.selected_blueprint,
|
||||
);
|
||||
|
||||
d.draw_texture_ex(
|
||||
textures.get("blueprint"),
|
||||
Vector2::new((42 + 205) as f32, y as f32),
|
||||
0.,
|
||||
2.,
|
||||
Color::new(255, 255, 255, if is_selected { 255 } else { 150 }),
|
||||
);
|
||||
y += 37;
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_end_popup(&mut self, d: &mut RaylibDrawHandle, textures: &Textures) {
|
||||
let x = d.get_screen_width() / 2 - END_POPUP_WIDTH / 2;
|
||||
let y = d.get_screen_height() / 2 - END_POPUP_HEIGHT / 2;
|
||||
d.draw_rectangle(x, y, END_POPUP_WIDTH, END_POPUP_HEIGHT, BG_DARK);
|
||||
if self.popup == Popup::Success {
|
||||
d.draw_text("Level Complete!", x + 45, y + 10, 30, Color::LIME);
|
||||
if let Some(score) = &self.score {
|
||||
d.draw_text("cycles", x + 15, y + 45, 20, Color::WHITE);
|
||||
draw_usize(d, textures, score.cycles, x + 10, y + 70, 9, 2);
|
||||
d.draw_text("tiles", x + 215, y + 45, 20, Color::WHITE);
|
||||
draw_usize(d, textures, score.tiles, x + 210, y + 70, 5, 2);
|
||||
}
|
||||
if simple_button(d, &self.mouse, x + 10, y + 110, 140, 45) {
|
||||
self.popup = Popup::Dismissed;
|
||||
}
|
||||
d.draw_text("continue\nediting", x + 15, y + 115, 20, Color::WHITE);
|
||||
|
||||
if simple_button(
|
||||
d,
|
||||
&self.mouse,
|
||||
x + END_POPUP_WIDTH / 2 + 5,
|
||||
y + 110,
|
||||
140,
|
||||
45,
|
||||
) {
|
||||
self.exit_state = ExitState::ExitAndSave;
|
||||
}
|
||||
d.draw_text(
|
||||
"return to\nlevel list",
|
||||
x + END_POPUP_WIDTH / 2 + 10,
|
||||
y + 115,
|
||||
20,
|
||||
Color::WHITE,
|
||||
);
|
||||
} else {
|
||||
d.draw_text("Level Failed!", x + 45, y + 10, 30, Color::RED);
|
||||
d.draw_text("incorrect output", x + 45, y + 45, 20, Color::WHITE);
|
||||
if simple_button(d, &self.mouse, x + 10, y + 110, 300, 25) {
|
||||
self.popup = Popup::Dismissed;
|
||||
}
|
||||
d.draw_text("ok :(", x + 15, y + 115, 20, Color::WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -675,32 +734,37 @@ impl Editor {
|
|||
);
|
||||
|
||||
if self.exit_menu {
|
||||
if simple_button(d, 4, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 4, 4, 32, 32) {
|
||||
self.exit_state = ExitState::ExitAndSave;
|
||||
}
|
||||
self.tooltip.add(4, 4, 32, 32, "exit");
|
||||
draw_scaled_texture(d, textures.get("exit"), 4, 4, 2.);
|
||||
if simple_button(d, 38, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 40, 4, 32, 32) {
|
||||
self.exit_menu = false;
|
||||
}
|
||||
draw_scaled_texture(d, textures.get("cancel"), 38, 4, 2.);
|
||||
self.tooltip.add(38, 4, 32, 32, "cancel");
|
||||
draw_scaled_texture(d, textures.get("cancel"), 40, 4, 2.);
|
||||
self.tooltip.add(40, 4, 32, 32, "cancel");
|
||||
} else {
|
||||
if simple_button(d, 4, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 4, 4, 32, 32) {
|
||||
self.exit_menu = true;
|
||||
}
|
||||
self.tooltip.add(4, 4, 32, 32, "exit");
|
||||
draw_scaled_texture(d, textures.get("exit"), 4, 4, 2.);
|
||||
if simple_button(d, 38, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 40, 4, 32, 32) {
|
||||
self.exit_state = ExitState::Save;
|
||||
}
|
||||
draw_scaled_texture(d, textures.get("save"), 38, 4, 2.);
|
||||
self.tooltip.add(38, 4, 32, 32, "save");
|
||||
draw_scaled_texture(d, textures.get("save"), 40, 4, 2.);
|
||||
self.tooltip.add(40, 4, 32, 32, "save");
|
||||
}
|
||||
|
||||
if simple_button(d, &self.mouse, 76, 5, 60, 30) {
|
||||
self.popup = Popup::LevelInfo;
|
||||
}
|
||||
d.draw_text("info", 80, 10, 20, Color::WHITE);
|
||||
|
||||
if self.sim_state == SimState::Editing {
|
||||
self.tooltip.add(150, 4, 32, 32, "Undo");
|
||||
if simple_button(d, 150, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 150, 4, 32, 32) {
|
||||
self.undo()
|
||||
}
|
||||
let undo_icon = if self.undo_index > 0 {
|
||||
|
@ -711,7 +775,7 @@ impl Editor {
|
|||
draw_scaled_texture(d, textures.get(undo_icon), 150, 4, 2.);
|
||||
|
||||
self.tooltip.add(186, 4, 32, 32, "Redo");
|
||||
if simple_button(d, 186, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 186, 4, 32, 32) {
|
||||
self.redo()
|
||||
}
|
||||
let redo_icon = if self.undo_index < self.undo_history.len() {
|
||||
|
@ -723,7 +787,7 @@ impl Editor {
|
|||
}
|
||||
|
||||
self.tooltip.add(223, 4, 32, 32, "Toggle overlay");
|
||||
if simple_button(d, 223, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 223, 4, 32, 32) {
|
||||
self.draw_overlay = !self.draw_overlay;
|
||||
}
|
||||
let overlay_btn_icon = if self.draw_overlay {
|
||||
|
@ -735,13 +799,13 @@ impl Editor {
|
|||
|
||||
if self.sim_state == SimState::Running {
|
||||
self.tooltip.add(260, 4, 32, 32, "Pause");
|
||||
if simple_button(d, 260, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 260, 4, 32, 32) {
|
||||
self.sim_state = SimState::Stepping;
|
||||
}
|
||||
draw_scaled_texture(d, textures.get("pause"), 260, 4, 2.);
|
||||
} else {
|
||||
self.tooltip.add(260, 4, 32, 32, "Start");
|
||||
if simple_button(d, 260, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 260, 4, 32, 32) {
|
||||
if self.sim_state == SimState::Editing {
|
||||
self.init_sim()
|
||||
}
|
||||
|
@ -752,22 +816,32 @@ impl Editor {
|
|||
|
||||
if self.sim_state != SimState::Editing {
|
||||
self.tooltip.add(296, 4, 32, 32, "Stop");
|
||||
if simple_button(d, 296, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 296, 4, 32, 32) {
|
||||
self.sim_state = SimState::Editing;
|
||||
self.popup = EndPopup::None;
|
||||
self.popup = Popup::None;
|
||||
}
|
||||
draw_scaled_texture(d, textures.get("stop"), 296, 4, 2.);
|
||||
}
|
||||
|
||||
self.tooltip.add(332, 4, 32, 32, "Step");
|
||||
if simple_button(d, 332, 4, 32, 32) {
|
||||
if simple_button(d, &self.mouse, 332, 4, 32, 32) {
|
||||
self.step_pressed();
|
||||
}
|
||||
draw_scaled_texture(d, textures.get("step"), 332, 4, 2.);
|
||||
|
||||
self.tooltip.add(368, 4, 48, 32, "Speed");
|
||||
draw_usize(d, textures, 1 << self.sim_speed, 368, 4, SPEED_DIGITS, 1);
|
||||
slider(d, &mut self.sim_speed, 0, MAX_SPEED_POWER, 368, 24, 48, 12);
|
||||
slider(
|
||||
d,
|
||||
&self.mouse,
|
||||
&mut self.sim_speed,
|
||||
0,
|
||||
MAX_SPEED_POWER,
|
||||
368,
|
||||
24,
|
||||
48,
|
||||
12,
|
||||
);
|
||||
|
||||
self.tooltip.add(420, 4, 180, 32, "Steps");
|
||||
draw_usize(d, textures, self.machine.step_count(), 420, 4, 9, 2);
|
||||
|
@ -781,7 +855,7 @@ impl Editor {
|
|||
draw_usize(d, textures, self.max_step_time as usize, 260, 60, 9, 1);
|
||||
|
||||
d.draw_text("input:", 603, 8, 10, Color::WHITE);
|
||||
if simple_button(d, 600, 20, 35, 15) {
|
||||
if simple_button(d, &self.mouse, 600, 20, 35, 15) {
|
||||
self.input_as_text = !self.input_as_text
|
||||
}
|
||||
let input_mode_text = if self.input_as_text { "text" } else { "bytes" };
|
||||
|
@ -800,6 +874,7 @@ impl Editor {
|
|||
}
|
||||
if text_input(
|
||||
d,
|
||||
&self.mouse,
|
||||
Rectangle::new(input_x as f32, 5., (width - input_x - 5) as f32, 30.),
|
||||
&mut input_text,
|
||||
&mut self.input_text_selected,
|
||||
|
@ -853,6 +928,7 @@ impl Editor {
|
|||
hide_tile_tools = true;
|
||||
text_input(
|
||||
d,
|
||||
&self.mouse,
|
||||
Rectangle::new(100., footer_top + 10., 240., 30.),
|
||||
&mut self.new_blueprint_name,
|
||||
&mut self.blueprint_name_selected,
|
||||
|
@ -862,19 +938,21 @@ impl Editor {
|
|||
let y = footer_top as i32 + 49;
|
||||
|
||||
self.tooltip.add(100, y, 40, 40, "Cancel");
|
||||
if simple_button(d, 100, y, 40, 40) || d.is_key_pressed(KeyboardKey::KEY_ESCAPE) {
|
||||
if simple_button(d, &self.mouse, 100, y, 40, 40)
|
||||
|| d.is_key_pressed(KeyboardKey::KEY_ESCAPE)
|
||||
{
|
||||
self.active_tool = Tool::SelectArea(Selection::default());
|
||||
}
|
||||
draw_scaled_texture(d, textures.get("cancel"), 104, y + 4, 2.);
|
||||
|
||||
self.tooltip.add(144, y, 40, 40, "Save blueprint");
|
||||
if simple_button(d, 144, y, 40, 40) {
|
||||
if simple_button(d, &self.mouse, 144, y, 40, 40) {
|
||||
self.save_blueprint(selection);
|
||||
}
|
||||
draw_scaled_texture(d, textures.get("save"), 148, y + 4, 2.);
|
||||
|
||||
self.tooltip.add(188, y, 40, 40, "Copy");
|
||||
if simple_button(d, 188, y, 40, 40)
|
||||
if simple_button(d, &self.mouse, 188, y, 40, 40)
|
||||
|| (d.is_key_pressed(KeyboardKey::KEY_C)
|
||||
&& d.is_key_down(KeyboardKey::KEY_LEFT_CONTROL))
|
||||
{
|
||||
|
@ -884,7 +962,7 @@ impl Editor {
|
|||
draw_scaled_texture(d, textures.get("copy"), 192, y + 4, 2.);
|
||||
|
||||
self.tooltip.add(232, y, 40, 40, "Delete");
|
||||
if simple_button(d, 232, y, 40, 40) {
|
||||
if simple_button(d, &self.mouse, 232, y, 40, 40) {
|
||||
let min = selection.0.min(selection.1);
|
||||
let max = selection.0.max(selection.1);
|
||||
let board =
|
||||
|
@ -894,7 +972,6 @@ impl Editor {
|
|||
draw_scaled_texture(d, textures.get("eraser"), 236, y + 4, 2.);
|
||||
}
|
||||
|
||||
let mouse_pos = d.get_mouse_position();
|
||||
let mut tool_button =
|
||||
|(row, col): (i32, i32), texture: &str, tooltip: &'static str, tool_option: Tool| {
|
||||
let border = 4.;
|
||||
|
@ -906,22 +983,20 @@ impl Editor {
|
|||
x: 100. + col as f32 * grid_size - if col < 0 { 10. } else { 0. },
|
||||
y: footer_top + 5. + row as f32 * grid_size,
|
||||
};
|
||||
texture_option_button(
|
||||
self.tooltip.add_rec(
|
||||
Rectangle::new(pos.x, pos.y, button_size, button_size),
|
||||
tooltip,
|
||||
);
|
||||
scrollable_texture_option_button(
|
||||
d,
|
||||
&self.mouse,
|
||||
pos,
|
||||
textures.get(texture),
|
||||
tool_option,
|
||||
&mut self.active_tool,
|
||||
tex_size,
|
||||
border,
|
||||
);
|
||||
let bounds = Rectangle::new(pos.x, pos.y, button_size, button_size);
|
||||
self.tooltip.add_rec(bounds, tooltip);
|
||||
if bounds.check_collision_point_rec(mouse_pos) {
|
||||
get_scroll(d)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
)
|
||||
};
|
||||
tool_button((0, -2), "eraser", "Eraser", Tool::Erase);
|
||||
tool_button(
|
||||
|
@ -1042,7 +1117,7 @@ impl Editor {
|
|||
let output_cell_width = 43;
|
||||
let output_cells = (d.get_screen_width() - output_x) as usize / output_cell_width as usize;
|
||||
|
||||
if simple_button(d, output_x, y + 70, 65, 15) {
|
||||
if simple_button(d, &self.mouse, output_x, y + 70, 65, 15) {
|
||||
self.output_as_text = !self.output_as_text
|
||||
}
|
||||
let output_mode_text = if self.output_as_text {
|
||||
|
@ -1101,8 +1176,7 @@ impl Editor {
|
|||
|
||||
fn board_overlay(&mut self, d: &mut RaylibDrawHandle, textures: &Textures) {
|
||||
let footer_top = (d.get_screen_height() - FOOTER_HEIGHT) as f32;
|
||||
let mouse_pos = d.get_mouse_position();
|
||||
let scroll_delta = d.get_mouse_wheel_move();
|
||||
|
||||
let tile_size = TILE_TEXTURE_SIZE * self.zoom;
|
||||
if self.sim_state == SimState::Editing {
|
||||
if let Some(board) = &self.pasting_board {
|
||||
|
@ -1110,18 +1184,18 @@ impl Editor {
|
|||
self.pasting_board = None;
|
||||
return;
|
||||
}
|
||||
if mouse_pos.y < footer_top && mouse_pos.y > HEADER_HEIGHT as f32 {
|
||||
if self.mouse.pos().y < footer_top && self.mouse.pos().y > HEADER_HEIGHT as f32 {
|
||||
let view_offset = Vector2::new(
|
||||
self.view_offset.x.rem(tile_size),
|
||||
self.view_offset.y.rem(tile_size),
|
||||
);
|
||||
let mut offset = mouse_pos - view_offset;
|
||||
let mut offset = self.mouse.pos() - view_offset;
|
||||
offset.x -= offset.x.rem(tile_size);
|
||||
offset.y -= offset.y.rem(tile_size);
|
||||
offset += view_offset;
|
||||
board.draw(d, textures, offset, self.zoom);
|
||||
if d.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT) {
|
||||
let tile_pos = (mouse_pos - self.view_offset) / tile_size;
|
||||
if self.mouse.left_click() {
|
||||
let tile_pos = (self.mouse.pos() - self.view_offset) / tile_size;
|
||||
let tile_pos = Vector2::new(tile_pos.x.floor(), tile_pos.y.floor());
|
||||
let board = self.pasting_board.take().unwrap();
|
||||
self.set_area(tile_pos.into(), board);
|
||||
|
@ -1157,8 +1231,8 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
}
|
||||
if mouse_pos.y < footer_top && mouse_pos.y > HEADER_HEIGHT as f32 {
|
||||
let tile_pos = (mouse_pos - self.view_offset) / tile_size;
|
||||
if self.mouse.pos().y < footer_top && self.mouse.pos().y > HEADER_HEIGHT as f32 {
|
||||
let tile_pos = (self.mouse.pos() - self.view_offset) / tile_size;
|
||||
let tile_pos = Vector2::new(tile_pos.x.floor(), tile_pos.y.floor());
|
||||
|
||||
let tile_screen_pos = self.pos_to_screen(tile_pos);
|
||||
|
@ -1192,7 +1266,7 @@ impl Editor {
|
|||
Color::new(255, 255, 255, 100),
|
||||
);
|
||||
}
|
||||
if d.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT) {
|
||||
if self.mouse.left_click() {
|
||||
let pos = tile_pos.into();
|
||||
match self.active_tool {
|
||||
Tool::None | Tool::Erase | Tool::SelectArea(_) => (),
|
||||
|
@ -1215,7 +1289,7 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
Tool::Blueprint => {
|
||||
if mouse_pos.x > SIDEBAR_WIDTH as f32 {
|
||||
if self.mouse.pos().x > SIDEBAR_WIDTH as f32 {
|
||||
if let Some(bp) = self.blueprints.get(self.selected_blueprint) {
|
||||
let board = bp.get_board().unwrap().clone();
|
||||
self.set_area(pos, board);
|
||||
|
@ -1224,13 +1298,11 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
}
|
||||
if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT)
|
||||
&& self.active_tool == Tool::Erase
|
||||
{
|
||||
if self.mouse.left_hold() && self.active_tool == Tool::Erase {
|
||||
self.set_tile(tile_pos.into(), Tile::BLANK);
|
||||
}
|
||||
if let Tool::SelectArea(selection) = &mut self.active_tool {
|
||||
if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) {
|
||||
if self.mouse.left_hold() {
|
||||
if selection.is_selecting {
|
||||
if let Some((_start, end)) = &mut selection.area {
|
||||
*end = tile_pos.into();
|
||||
|
@ -1241,7 +1313,7 @@ impl Editor {
|
|||
selection.area = Some((tile_pos.into(), tile_pos.into()));
|
||||
selection.is_selecting = true;
|
||||
}
|
||||
} else if d.is_mouse_button_released(MouseButton::MOUSE_BUTTON_LEFT) {
|
||||
} else if self.mouse.left_release() {
|
||||
selection.is_selecting = false;
|
||||
}
|
||||
}
|
||||
|
@ -1251,18 +1323,20 @@ impl Editor {
|
|||
self.view_offset.x.rem(tile_size),
|
||||
self.view_offset.y.rem(tile_size),
|
||||
);
|
||||
let mut offset = mouse_pos - view_offset;
|
||||
let mut offset = self.mouse.pos() - view_offset;
|
||||
offset.x -= offset.x.rem(tile_size);
|
||||
offset.y -= offset.y.rem(tile_size);
|
||||
offset += view_offset;
|
||||
bp.convert_board().draw(d, textures, offset, self.zoom);
|
||||
}
|
||||
if mouse_pos.x < SIDEBAR_WIDTH as f32 {
|
||||
if scroll_delta < 0.
|
||||
if self.mouse.pos().x < SIDEBAR_WIDTH as f32 {
|
||||
if self.mouse.scroll() == Some(Scroll::Down)
|
||||
&& self.blueprint_scroll < self.blueprints.len().saturating_sub(5)
|
||||
{
|
||||
self.blueprint_scroll += 1;
|
||||
} else if scroll_delta > 0. && self.blueprint_scroll > 0 {
|
||||
} else if self.mouse.scroll() == Some(Scroll::Up)
|
||||
&& self.blueprint_scroll > 0
|
||||
{
|
||||
self.blueprint_scroll -= 1;
|
||||
}
|
||||
}
|
||||
|
|
28
src/main.rs
28
src/main.rs
|
@ -123,19 +123,16 @@ impl Game {
|
|||
let level_list_width = (d.get_screen_width() / 3).min(400);
|
||||
let screen_height = d.get_screen_height();
|
||||
d.draw_rectangle(0, 0, level_list_width, screen_height, BG_MEDIUM);
|
||||
|
||||
let clicked = d.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT);
|
||||
let mouse_pos = d.get_mouse_position();
|
||||
let scroll_delta = d.get_mouse_wheel_move();
|
||||
let mouse = MouseInput::get(d);
|
||||
|
||||
const ENTRY_SPACING: i32 = 65;
|
||||
let fit_on_screen = (d.get_screen_height() / ENTRY_SPACING) as usize;
|
||||
let max_scroll = self.levels.len().saturating_sub(fit_on_screen);
|
||||
if mouse_pos.x < level_list_width as f32 {
|
||||
if scroll_delta < 0. && self.level_scroll < max_scroll {
|
||||
if mouse.pos().x < level_list_width as f32 {
|
||||
if mouse.scroll() == Some(Scroll::Down) && self.level_scroll < max_scroll {
|
||||
self.level_scroll += 1;
|
||||
}
|
||||
if scroll_delta > 0. && self.level_scroll > 0 {
|
||||
if mouse.scroll() == Some(Scroll::Up) && self.level_scroll > 0 {
|
||||
self.level_scroll -= 1;
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +146,7 @@ impl Game {
|
|||
width: level_list_width as f32 - 10.,
|
||||
height: ENTRY_SPACING as f32 - 5.,
|
||||
};
|
||||
let clicked_this = clicked && bounds.check_collision_point_rec(mouse_pos);
|
||||
let clicked_this = mouse.left_click() && mouse.is_over(bounds);
|
||||
match level {
|
||||
LevelListEntry::Chapter(title, level_count) => {
|
||||
d.draw_rectangle_rec(bounds, BG_DARK);
|
||||
|
@ -210,6 +207,7 @@ impl Game {
|
|||
for (solution_index, solution) in solutions.iter().enumerate() {
|
||||
if simple_option_button(
|
||||
d,
|
||||
&mouse,
|
||||
level_list_width + 10,
|
||||
solution_y,
|
||||
entry_width,
|
||||
|
@ -242,7 +240,14 @@ impl Game {
|
|||
}
|
||||
|
||||
let next_id = get_free_id(solutions, Solution::id);
|
||||
if simple_button(d, level_list_width + 10, solution_y, entry_width, 30) {
|
||||
if simple_button(
|
||||
d,
|
||||
&mouse,
|
||||
level_list_width + 10,
|
||||
solution_y,
|
||||
entry_width,
|
||||
30,
|
||||
) {
|
||||
self.selected_solution = solutions.len();
|
||||
solutions.push(Solution::new(level, next_id));
|
||||
}
|
||||
|
@ -259,6 +264,7 @@ impl Game {
|
|||
let bounds = Rectangle::new(column_x as f32, y as f32, 220., 30.);
|
||||
if text_input(
|
||||
d,
|
||||
&mouse,
|
||||
bounds,
|
||||
&mut solution.name,
|
||||
&mut self.editing_solution_name,
|
||||
|
@ -270,7 +276,7 @@ impl Game {
|
|||
let id_text = format!("{}", solution.id());
|
||||
d.draw_text(&id_text, column_x, y + 35, 10, Color::GRAY);
|
||||
|
||||
if simple_button(d, column_x, y + 50, 220, 30) {
|
||||
if simple_button(d, &mouse, column_x, y + 50, 220, 30) {
|
||||
let cloned = solution.new_copy(next_id);
|
||||
self.selected_solution = solutions.len();
|
||||
solutions.push(cloned);
|
||||
|
@ -278,7 +284,7 @@ impl Game {
|
|||
}
|
||||
d.draw_text("clone", column_x + 5, y + 55, 20, Color::WHITE);
|
||||
|
||||
if simple_button(d, column_x, y + 85, 220, 30) {
|
||||
if simple_button(d, &mouse, column_x, y + 85, 220, 30) {
|
||||
let mut editor = Editor::new(solution.clone(), level.clone());
|
||||
editor.center_view(d);
|
||||
self.open_editor = Some(editor);
|
||||
|
|
84
src/ui.rs
84
src/ui.rs
|
@ -1,6 +1,6 @@
|
|||
use std::ops::Range;
|
||||
|
||||
use crate::{draw_scaled_texture, theme::*, Textures};
|
||||
use crate::{draw_scaled_texture, theme::*, MouseInput, Scroll, Textures};
|
||||
use raylib::prelude::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -99,7 +99,7 @@ pub struct Tooltip {
|
|||
}
|
||||
|
||||
impl Tooltip {
|
||||
pub fn init_frame(&mut self, d: &mut RaylibDrawHandle) {
|
||||
pub fn init_frame(&mut self, d: &RaylibHandle) {
|
||||
let p = d.get_mouse_position();
|
||||
*self = Self {
|
||||
text: None,
|
||||
|
@ -120,6 +120,10 @@ impl Tooltip {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.text = None;
|
||||
}
|
||||
|
||||
pub fn add_rec(&mut self, bounds: Rectangle, text: &'static str) {
|
||||
self.add(
|
||||
bounds.x as i32,
|
||||
|
@ -153,8 +157,15 @@ impl Tooltip {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn simple_button(d: &mut RaylibDrawHandle, x: i32, y: i32, width: i32, height: i32) -> bool {
|
||||
let mouse_pos = d.get_mouse_position();
|
||||
pub fn simple_button(
|
||||
d: &mut RaylibDrawHandle,
|
||||
mouse: &MouseInput,
|
||||
x: i32,
|
||||
y: i32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> bool {
|
||||
let mouse_pos = mouse.pos();
|
||||
let bounds = Rectangle {
|
||||
x: x as f32,
|
||||
y: y as f32,
|
||||
|
@ -162,13 +173,14 @@ pub fn simple_button(d: &mut RaylibDrawHandle, x: i32, y: i32, width: i32, heigh
|
|||
height: height as f32,
|
||||
};
|
||||
let hover = bounds.check_collision_point_rec(mouse_pos);
|
||||
let pressed = hover && d.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT);
|
||||
let pressed = hover && mouse.left_click();
|
||||
d.draw_rectangle(x, y, width, height, widget_bg(hover));
|
||||
pressed
|
||||
}
|
||||
|
||||
pub fn simple_option_button<T>(
|
||||
d: &mut RaylibDrawHandle,
|
||||
mouse: &MouseInput,
|
||||
x: i32,
|
||||
y: i32,
|
||||
width: i32,
|
||||
|
@ -181,12 +193,8 @@ where
|
|||
{
|
||||
let bounds = Rectangle::new(x as f32, y as f32, width as f32, height as f32);
|
||||
d.draw_rectangle_rec(bounds, widget_bg(&option == current));
|
||||
let mouse_pos = d.get_mouse_position();
|
||||
let mut changed = false;
|
||||
if d.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT)
|
||||
&& bounds.check_collision_point_rec(mouse_pos)
|
||||
&& current != &option
|
||||
{
|
||||
if mouse.left_click() && mouse.is_over(bounds) && current != &option {
|
||||
*current = option;
|
||||
changed = true;
|
||||
}
|
||||
|
@ -195,6 +203,7 @@ where
|
|||
|
||||
pub fn text_input(
|
||||
d: &mut RaylibDrawHandle,
|
||||
mouse: &MouseInput,
|
||||
bounds: Rectangle,
|
||||
text: &mut String,
|
||||
is_selected: &mut bool,
|
||||
|
@ -224,11 +233,7 @@ pub fn text_input(
|
|||
20,
|
||||
Color::WHITE,
|
||||
);
|
||||
let mouse_pos = d.get_mouse_position();
|
||||
if editable
|
||||
&& d.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT)
|
||||
&& (bounds.check_collision_point_rec(mouse_pos) || *is_selected)
|
||||
{
|
||||
if editable && mouse.left_click() && (mouse.is_over(bounds) || *is_selected) {
|
||||
*is_selected = !*is_selected;
|
||||
}
|
||||
|
||||
|
@ -256,16 +261,17 @@ pub fn text_input(
|
|||
changed
|
||||
}
|
||||
|
||||
pub fn texture_option_button<T>(
|
||||
pub fn scrollable_texture_option_button<T>(
|
||||
d: &mut RaylibDrawHandle,
|
||||
mouse: &MouseInput,
|
||||
pos: Vector2,
|
||||
texture: &Texture2D,
|
||||
option: T,
|
||||
current: &mut T,
|
||||
tex_size: f32,
|
||||
border: f32,
|
||||
// tooltip
|
||||
) where
|
||||
) -> Option<Scroll>
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
let bounds = Rectangle {
|
||||
|
@ -289,13 +295,13 @@ pub fn texture_option_button<T>(
|
|||
tex_size / texture.width as f32,
|
||||
Color::WHITE,
|
||||
);
|
||||
|
||||
let mouse_pos = d.get_mouse_position();
|
||||
if d.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT)
|
||||
&& bounds.check_collision_point_rec(mouse_pos)
|
||||
{
|
||||
*current = option;
|
||||
if mouse.is_over(bounds) {
|
||||
if mouse.left_click() {
|
||||
*current = option;
|
||||
}
|
||||
return mouse.scroll();
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn draw_usize(
|
||||
|
@ -350,6 +356,7 @@ pub fn draw_usize_small(
|
|||
|
||||
pub fn slider(
|
||||
d: &mut RaylibDrawHandle,
|
||||
mouse: &MouseInput,
|
||||
value: &mut u8,
|
||||
min: u8,
|
||||
max: u8,
|
||||
|
@ -362,38 +369,19 @@ pub fn slider(
|
|||
let percent = (*value - min + 1) as f32 / (max - min + 1) as f32;
|
||||
d.draw_rectangle(x, y, width, height, BG_WIDGET);
|
||||
d.draw_rectangle(x, y, (width as f32 * percent) as i32, height, Color::CYAN);
|
||||
let mouse_pos = d.get_mouse_position();
|
||||
let bounds = Rectangle::new(x as f32, y as f32, width as f32, height as f32);
|
||||
if bounds.check_collision_point_rec(mouse_pos) {
|
||||
if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) {
|
||||
let percent = (mouse_pos.x - bounds.x) / bounds.width;
|
||||
if mouse.is_over(bounds) {
|
||||
if mouse.left_hold() {
|
||||
let percent = (mouse.pos().x - bounds.x) / bounds.width;
|
||||
let new_value = min + (percent * (max - min + 1) as f32) as u8;
|
||||
if *value != new_value {
|
||||
*value = new_value;
|
||||
}
|
||||
} else if d.get_mouse_wheel_move() > 0.5 && *value < max {
|
||||
} else if mouse.scroll() == Some(Scroll::Up) && *value < max {
|
||||
*value += 1;
|
||||
} else if d.get_mouse_wheel_move() < -0.5 && *value > min {
|
||||
} else if mouse.scroll() == Some(Scroll::Down) && *value > min {
|
||||
*value -= 1;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Scroll {
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
||||
pub fn get_scroll(rl: &RaylibHandle) -> Option<Scroll> {
|
||||
const SCROLL_THRESHOLD: f32 = 0.5;
|
||||
let value = rl.get_mouse_wheel_move();
|
||||
if value > SCROLL_THRESHOLD {
|
||||
Some(Scroll::Up)
|
||||
} else if value < -SCROLL_THRESHOLD {
|
||||
Some(Scroll::Down)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
84
src/util.rs
84
src/util.rs
|
@ -50,3 +50,87 @@ pub fn get_free_id<T>(items: &[T], id_fn: fn(&T) -> usize) -> usize {
|
|||
}
|
||||
id
|
||||
}
|
||||
|
||||
pub fn screen_centered_rect_dyn(rl: &RaylibHandle, margin_x: i32, margin_y: i32) -> Rectangle {
|
||||
let w = rl.get_screen_width();
|
||||
let h = rl.get_screen_height();
|
||||
Rectangle {
|
||||
x: margin_x as f32,
|
||||
y: margin_y as f32,
|
||||
width: (w - margin_x * 2) as f32,
|
||||
height: (h - margin_y * 2) as f32,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MouseInput {
|
||||
pos: Vector2,
|
||||
left_click: bool,
|
||||
left_hold: bool,
|
||||
left_release: bool,
|
||||
right_hold: bool,
|
||||
scroll: Option<Scroll>,
|
||||
}
|
||||
|
||||
impl MouseInput {
|
||||
pub fn get(rl: &RaylibHandle) -> Self {
|
||||
Self {
|
||||
pos: rl.get_mouse_position(),
|
||||
left_click: rl.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT),
|
||||
left_hold: rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT),
|
||||
left_release: rl.is_mouse_button_released(MouseButton::MOUSE_BUTTON_LEFT),
|
||||
right_hold: rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_RIGHT),
|
||||
scroll: get_scroll(rl),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_over(&self, rect: Rectangle) -> bool {
|
||||
rect.check_collision_point_rec(self.pos)
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
*self = Self::default();
|
||||
}
|
||||
|
||||
pub fn pos(&self) -> Vector2 {
|
||||
self.pos
|
||||
}
|
||||
|
||||
pub fn left_click(&self) -> bool {
|
||||
self.left_click
|
||||
}
|
||||
|
||||
pub fn left_hold(&self) -> bool {
|
||||
self.left_hold
|
||||
}
|
||||
|
||||
pub fn left_release(&self) -> bool {
|
||||
self.left_release
|
||||
}
|
||||
|
||||
pub fn right_hold(&self) -> bool {
|
||||
self.right_hold
|
||||
}
|
||||
|
||||
pub fn scroll(&self) -> Option<Scroll> {
|
||||
self.scroll
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Scroll {
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
||||
pub fn get_scroll(rl: &RaylibHandle) -> Option<Scroll> {
|
||||
const SCROLL_THRESHOLD: f32 = 0.5;
|
||||
let value = rl.get_mouse_wheel_move();
|
||||
if value > SCROLL_THRESHOLD {
|
||||
Some(Scroll::Up)
|
||||
} else if value < -SCROLL_THRESHOLD {
|
||||
Some(Scroll::Down)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue