move editor/game logic to module
This commit is contained in:
parent
0738e658db
commit
d332bd30f3
3 changed files with 416 additions and 406 deletions
411
src/editor.rs
Normal file
411
src/editor.rs
Normal file
|
@ -0,0 +1,411 @@
|
|||
use std::ops::Rem;
|
||||
|
||||
use raylib::prelude::*;
|
||||
|
||||
use crate::{
|
||||
marble_engine::{
|
||||
board::{Board, Pos},
|
||||
tile::{Direction, GateType, MathOp, MirrorType, PTile, Tile, WireType},
|
||||
Machine,
|
||||
},
|
||||
text_input, texture_button, Textures,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Game {
|
||||
source_board: Board,
|
||||
machine: Machine,
|
||||
sim_state: SimState,
|
||||
view_offset: Vector2,
|
||||
zoom: i32,
|
||||
output_as_text: bool,
|
||||
input_as_text: bool,
|
||||
active_tool: Tool,
|
||||
tool_menu_math: MathOp,
|
||||
tool_menu_gate: GateType,
|
||||
tool_menu_arrow: Direction,
|
||||
tool_menu_mirror: MirrorType,
|
||||
tool_menu_wire: WireType,
|
||||
input_text_selected: bool,
|
||||
sim_speed: f32,
|
||||
time_since_step: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Tool {
|
||||
None,
|
||||
SetTile(Tile),
|
||||
Digits(Option<Pos>),
|
||||
Math,
|
||||
Gate,
|
||||
Wire,
|
||||
Arrow,
|
||||
Mirror,
|
||||
// SelectArea,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
enum SimState {
|
||||
Editing,
|
||||
Running,
|
||||
Stepping,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
pub fn new_sandbox() -> Self {
|
||||
Self {
|
||||
source_board: Board::new_empty(16, 16),
|
||||
machine: Machine::new_empty(1),
|
||||
sim_state: SimState::Editing,
|
||||
view_offset: Vector2::zero(),
|
||||
zoom: 1,
|
||||
active_tool: Tool::None,
|
||||
output_as_text: false,
|
||||
input_as_text: false,
|
||||
input_text_selected: false,
|
||||
sim_speed: 8.,
|
||||
time_since_step: 0.,
|
||||
tool_menu_math: MathOp::Add,
|
||||
tool_menu_gate: GateType::Equal,
|
||||
tool_menu_arrow: Direction::Right,
|
||||
tool_menu_mirror: MirrorType::Forward,
|
||||
tool_menu_wire: WireType::Vertical,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_board(&mut self, board: Board) {
|
||||
self.source_board = board;
|
||||
}
|
||||
|
||||
fn start_sim(&mut self) {
|
||||
self.machine.reset();
|
||||
self.machine.set_board(self.source_board.clone());
|
||||
}
|
||||
|
||||
fn rotate_tool(&mut self, shift: bool) {
|
||||
match &self.active_tool {
|
||||
Tool::Math => {
|
||||
self.tool_menu_math = match self.tool_menu_math {
|
||||
MathOp::Add => MathOp::Sub,
|
||||
MathOp::Sub => MathOp::Mul,
|
||||
MathOp::Mul => MathOp::Div,
|
||||
MathOp::Div => MathOp::Rem,
|
||||
MathOp::Rem => MathOp::Add,
|
||||
}
|
||||
}
|
||||
Tool::Gate => {
|
||||
self.tool_menu_gate = match self.tool_menu_gate {
|
||||
GateType::LessThan => GateType::GreaterThan,
|
||||
GateType::GreaterThan => GateType::Equal,
|
||||
GateType::Equal => GateType::NotEqual,
|
||||
GateType::NotEqual => GateType::LessThan,
|
||||
}
|
||||
}
|
||||
Tool::Arrow => {
|
||||
self.tool_menu_arrow = if shift {
|
||||
self.tool_menu_arrow.left()
|
||||
} else {
|
||||
self.tool_menu_arrow.right()
|
||||
}
|
||||
}
|
||||
Tool::Mirror => {
|
||||
self.tool_menu_mirror = match self.tool_menu_mirror {
|
||||
MirrorType::Forward => MirrorType::Back,
|
||||
MirrorType::Back => MirrorType::Forward,
|
||||
}
|
||||
}
|
||||
Tool::Wire => {
|
||||
self.tool_menu_wire = match self.tool_menu_wire {
|
||||
WireType::Vertical => WireType::Horizontal,
|
||||
WireType::Horizontal => WireType::Cross,
|
||||
WireType::Cross => WireType::Vertical,
|
||||
}
|
||||
}
|
||||
Tool::None => (),
|
||||
Tool::SetTile(_) => (),
|
||||
Tool::Digits(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn input(&mut self, rl: &RaylibHandle) {
|
||||
if self.sim_state == SimState::Running {
|
||||
self.time_since_step += rl.get_frame_time();
|
||||
if self.time_since_step > 1. / self.sim_speed {
|
||||
self.time_since_step = 0.;
|
||||
self.machine.step();
|
||||
}
|
||||
}
|
||||
if rl.is_key_pressed(KeyboardKey::KEY_SPACE) {
|
||||
match self.sim_state {
|
||||
SimState::Editing => {
|
||||
self.start_sim();
|
||||
self.machine.step();
|
||||
}
|
||||
SimState::Running => (),
|
||||
SimState::Stepping => self.machine.step(),
|
||||
}
|
||||
self.sim_state = SimState::Stepping;
|
||||
}
|
||||
if rl.is_key_pressed(KeyboardKey::KEY_ESCAPE) {
|
||||
self.sim_state = SimState::Editing;
|
||||
}
|
||||
if rl.is_key_pressed(KeyboardKey::KEY_ENTER) {
|
||||
match self.sim_state {
|
||||
SimState::Editing => {
|
||||
self.start_sim();
|
||||
self.sim_state = SimState::Running;
|
||||
}
|
||||
SimState::Running => self.sim_state = SimState::Editing,
|
||||
SimState::Stepping => self.sim_state = SimState::Running,
|
||||
}
|
||||
}
|
||||
|
||||
if rl.get_mouse_wheel_move() > 0. && self.zoom < 3 {
|
||||
self.zoom += 1;
|
||||
}
|
||||
if rl.get_mouse_wheel_move() < 0. && self.zoom > 0 {
|
||||
self.zoom -= 1;
|
||||
}
|
||||
if rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_MIDDLE) {
|
||||
self.view_offset += rl.get_mouse_delta()
|
||||
}
|
||||
if rl.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_RIGHT) {
|
||||
self.view_offset = Vector2::zero();
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_board(&self, d: &mut RaylibDrawHandle, textures: &Textures) {
|
||||
if self.sim_state == SimState::Editing {
|
||||
self.source_board
|
||||
.draw(d, textures, self.view_offset, self.zoom);
|
||||
} else {
|
||||
self.machine
|
||||
.board()
|
||||
.draw(d, textures, self.view_offset, self.zoom);
|
||||
self.machine
|
||||
.draw_marble_values(d, self.view_offset, self.zoom);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, d: &mut RaylibDrawHandle, textures: &Textures) {
|
||||
self.draw_board(d, textures);
|
||||
|
||||
let height = d.get_screen_height();
|
||||
let footer_height = 95;
|
||||
let footer_top = (height - footer_height) as f32;
|
||||
d.draw_rectangle(
|
||||
0,
|
||||
height - footer_height,
|
||||
d.get_screen_width(),
|
||||
footer_height,
|
||||
Color::new(32, 32, 32, 255),
|
||||
);
|
||||
|
||||
let tile_size = (16 << self.zoom) as f32;
|
||||
let grid_spill_x = (self.view_offset.x).rem(tile_size) - tile_size;
|
||||
let grid_spill_y = (self.view_offset.y).rem(tile_size) - tile_size;
|
||||
d.gui_grid(
|
||||
Rectangle::new(
|
||||
grid_spill_x,
|
||||
grid_spill_y,
|
||||
d.get_screen_width() as f32 * 2.,
|
||||
height as f32 - grid_spill_y - footer_height as f32,
|
||||
),
|
||||
None,
|
||||
tile_size,
|
||||
1,
|
||||
);
|
||||
|
||||
d.gui_check_box(
|
||||
Rectangle::new(5., footer_top + 5., 25., 25.),
|
||||
Some(rstr!("output as text")),
|
||||
&mut self.output_as_text,
|
||||
);
|
||||
let out_text = if self.output_as_text {
|
||||
String::from_utf8_lossy(self.machine.output()).to_string()
|
||||
} else {
|
||||
format!("{:?}", self.machine.output())
|
||||
};
|
||||
d.draw_text(&out_text, 5, footer_top as i32 + 35, 20, Color::WHITE);
|
||||
|
||||
let mut input_text = String::from_utf8_lossy(self.machine.input()).to_string();
|
||||
if text_input(
|
||||
d,
|
||||
Rectangle::new(5., footer_top + 60., 200., 25.),
|
||||
&mut input_text,
|
||||
&mut self.input_text_selected,
|
||||
) {
|
||||
self.machine.set_input(input_text.into_bytes());
|
||||
}
|
||||
|
||||
let mut tool_button = |(row, col): (i32, i32), texture: &str, tool_option: Tool| {
|
||||
let border = 4.;
|
||||
let gap = 2.;
|
||||
let bound_offset = 32. + gap * 2. + border * 2.;
|
||||
texture_button(
|
||||
d,
|
||||
Vector2 {
|
||||
x: 320. + col as f32 * bound_offset - if col < 0 { 15. } else { 0. },
|
||||
y: footer_top + 5. + row as f32 * bound_offset,
|
||||
},
|
||||
textures.get(texture),
|
||||
tool_option,
|
||||
&mut self.active_tool,
|
||||
32.,
|
||||
border,
|
||||
);
|
||||
};
|
||||
tool_button((0, -2), "eraser", Tool::SetTile(Tile::from_char(' ')));
|
||||
tool_button((0, -1), "digit_tool", Tool::Digits(None));
|
||||
tool_button((1, -1), "transparent", Tool::None);
|
||||
|
||||
tool_button((0, 0), "block", Tool::SetTile(Tile::from_char('#')));
|
||||
tool_button((0, 1), "bag_off", Tool::SetTile(Tile::from_char('B')));
|
||||
tool_button((0, 2), "trigger_off", Tool::SetTile(Tile::from_char('*')));
|
||||
tool_button((0, 3), "input_off", Tool::SetTile(Tile::from_char('I')));
|
||||
tool_button((0, 4), "output_off", Tool::SetTile(Tile::from_char('P')));
|
||||
tool_button((0, 5), "flipper_off", Tool::SetTile(Tile::from_char('F')));
|
||||
|
||||
tool_button((1, 0), "marble", Tool::SetTile(Tile::from_char('o')));
|
||||
tool_button(
|
||||
(1, 1),
|
||||
&Tile::Powerable(PTile::Wire(self.tool_menu_wire), false).texture(),
|
||||
Tool::Wire,
|
||||
);
|
||||
|
||||
tool_button(
|
||||
(1, 2),
|
||||
&Tile::Arrow(self.tool_menu_arrow).texture(),
|
||||
Tool::Arrow,
|
||||
);
|
||||
tool_button(
|
||||
(1, 3),
|
||||
&Tile::Mirror(self.tool_menu_mirror).texture(),
|
||||
Tool::Mirror,
|
||||
);
|
||||
tool_button(
|
||||
(1, 4),
|
||||
&Tile::Powerable(PTile::Math(self.tool_menu_math), false).texture(),
|
||||
Tool::Math,
|
||||
);
|
||||
tool_button(
|
||||
(1, 5),
|
||||
&Tile::Powerable(PTile::Gate(self.tool_menu_gate), false).texture(),
|
||||
Tool::Gate,
|
||||
);
|
||||
|
||||
let is_shift = d.is_key_down(KeyboardKey::KEY_LEFT_SHIFT);
|
||||
if d.is_key_pressed(KeyboardKey::KEY_R) {
|
||||
self.rotate_tool(is_shift);
|
||||
}
|
||||
|
||||
let mouse_pos = d.get_mouse_position();
|
||||
if self.sim_state == SimState::Editing {
|
||||
if let Tool::Digits(Some(pos)) = &mut self.active_tool {
|
||||
let tile_screen_pos = pos.to_vec() * (16 << self.zoom) as f32 + self.view_offset;
|
||||
d.draw_texture_ex(
|
||||
textures.get("selection"),
|
||||
tile_screen_pos,
|
||||
0.,
|
||||
(1 << self.zoom) as f32,
|
||||
Color::new(255, 180, 20, 255),
|
||||
);
|
||||
for n in 0..10 {
|
||||
if d.is_key_pressed(unsafe {
|
||||
std::mem::transmute(KeyboardKey::KEY_ZERO as u32 + n)
|
||||
}) {
|
||||
self.source_board.set(*pos, Tile::Digit(n as u8));
|
||||
}
|
||||
}
|
||||
if d.is_key_pressed(KeyboardKey::KEY_LEFT) {
|
||||
pos.x -= 1;
|
||||
}
|
||||
if d.is_key_pressed(KeyboardKey::KEY_RIGHT) {
|
||||
pos.x += 1;
|
||||
}
|
||||
if d.is_key_pressed(KeyboardKey::KEY_UP) {
|
||||
pos.y -= 1;
|
||||
}
|
||||
if d.is_key_pressed(KeyboardKey::KEY_DOWN) {
|
||||
pos.y += 1;
|
||||
}
|
||||
}
|
||||
if mouse_pos.y < footer_top {
|
||||
let tile_pos = (mouse_pos - self.view_offset) / (16 << self.zoom) as f32;
|
||||
let tile_pos = Vector2::new(tile_pos.x.floor(), tile_pos.y.floor());
|
||||
|
||||
let tile_screen_pos = tile_pos * (16 << self.zoom) as f32 + self.view_offset;
|
||||
|
||||
if self.active_tool != Tool::None {
|
||||
let tex = match self.active_tool {
|
||||
Tool::None => unreachable!(),
|
||||
Tool::SetTile(t) => {
|
||||
if t == Tile::Blank {
|
||||
"selection".into()
|
||||
} else {
|
||||
t.texture()
|
||||
}
|
||||
}
|
||||
Tool::Math => format!("{}_off", self.tool_menu_math.texture_name()),
|
||||
Tool::Gate => format!("{}_off", self.tool_menu_gate.texture_name()),
|
||||
Tool::Wire => format!("{}_off", self.tool_menu_wire.texture_name()),
|
||||
Tool::Arrow => self.tool_menu_arrow.arrow_texture_name().into(),
|
||||
Tool::Mirror => self.tool_menu_mirror.texture_name().into(),
|
||||
Tool::Digits(_) => "selection".into(),
|
||||
};
|
||||
|
||||
d.draw_texture_ex(
|
||||
textures.get(&tex),
|
||||
tile_screen_pos,
|
||||
0.,
|
||||
(1 << self.zoom) as f32,
|
||||
Color::new(255, 255, 255, 100),
|
||||
);
|
||||
}
|
||||
if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) {
|
||||
match self.active_tool {
|
||||
Tool::None => (),
|
||||
Tool::SetTile(tile) => self.source_board.set(tile_pos.into(), tile),
|
||||
Tool::Math => self.source_board.set(
|
||||
tile_pos.into(),
|
||||
Tile::Powerable(PTile::Math(self.tool_menu_math), false),
|
||||
),
|
||||
Tool::Gate => self.source_board.set(
|
||||
tile_pos.into(),
|
||||
Tile::Powerable(PTile::Gate(self.tool_menu_gate), false),
|
||||
),
|
||||
Tool::Wire => self.source_board.set(
|
||||
tile_pos.into(),
|
||||
Tile::Powerable(PTile::Wire(self.tool_menu_wire), false),
|
||||
),
|
||||
Tool::Arrow => self
|
||||
.source_board
|
||||
.set(tile_pos.into(), Tile::Arrow(self.tool_menu_arrow)),
|
||||
Tool::Mirror => self
|
||||
.source_board
|
||||
.set(tile_pos.into(), Tile::Mirror(self.tool_menu_mirror)),
|
||||
Tool::Digits(_pos) => {
|
||||
self.active_tool = Tool::Digits(Some(tile_pos.into()));
|
||||
if let Some(tile) = self.source_board.get_mut(tile_pos.into()) {
|
||||
if let Tile::Digit(_) = tile {
|
||||
} else {
|
||||
*tile = Tile::Digit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Tool {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::SetTile(l0), Self::SetTile(r0)) => l0 == r0,
|
||||
(Self::Digits(_), Self::Digits(_)) => true,
|
||||
_ => ::core::mem::discriminant(self) == ::core::mem::discriminant(other),
|
||||
}
|
||||
}
|
||||
}
|
409
src/main.rs
409
src/main.rs
|
@ -1,56 +1,14 @@
|
|||
use std::{fs::read_to_string, ops::Rem};
|
||||
use std::fs::read_to_string;
|
||||
|
||||
use marble_engine::{
|
||||
board::{Board, Pos},
|
||||
tile::{Direction, GateType, MathOp, MirrorType, PTile, Tile, WireType},
|
||||
Machine,
|
||||
};
|
||||
use editor::Game;
|
||||
use marble_engine::board::Board;
|
||||
use raylib::prelude::*;
|
||||
|
||||
mod editor;
|
||||
mod marble_engine;
|
||||
mod util;
|
||||
use util::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Game {
|
||||
source_board: Board,
|
||||
machine: Machine,
|
||||
sim_state: SimState,
|
||||
view_offset: Vector2,
|
||||
zoom: i32,
|
||||
output_as_text: bool,
|
||||
input_as_text: bool,
|
||||
active_tool: Tool,
|
||||
tool_menu_math: MathOp,
|
||||
tool_menu_gate: GateType,
|
||||
tool_menu_arrow: Direction,
|
||||
tool_menu_mirror: MirrorType,
|
||||
tool_menu_wire: WireType,
|
||||
input_text_selected: bool,
|
||||
sim_speed: f32,
|
||||
time_since_step: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Tool {
|
||||
None,
|
||||
SetTile(Tile),
|
||||
Digits(Option<Pos>),
|
||||
Math,
|
||||
Gate,
|
||||
Wire,
|
||||
Arrow,
|
||||
Mirror,
|
||||
// SelectArea,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
enum SimState {
|
||||
Editing,
|
||||
Running,
|
||||
Stepping,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (mut rl, thread) = raylib::init()
|
||||
.resizable()
|
||||
|
@ -74,363 +32,6 @@ fn main() {
|
|||
game.input(&rl);
|
||||
let mut d = rl.begin_drawing(&thread);
|
||||
d.clear_background(Color::new(64, 64, 64, 255));
|
||||
game.gui(&mut d, &textures);
|
||||
}
|
||||
}
|
||||
|
||||
impl Game {
|
||||
fn new_sandbox() -> Self {
|
||||
Self {
|
||||
source_board: Board::new_empty(16, 16),
|
||||
machine: Machine::new_empty(1),
|
||||
sim_state: SimState::Editing,
|
||||
view_offset: Vector2::zero(),
|
||||
zoom: 1,
|
||||
active_tool: Tool::None,
|
||||
output_as_text: false,
|
||||
input_as_text: false,
|
||||
input_text_selected: false,
|
||||
sim_speed: 8.,
|
||||
time_since_step: 0.,
|
||||
tool_menu_math: MathOp::Add,
|
||||
tool_menu_gate: GateType::Equal,
|
||||
tool_menu_arrow: Direction::Right,
|
||||
tool_menu_mirror: MirrorType::Forward,
|
||||
tool_menu_wire: WireType::Vertical,
|
||||
}
|
||||
}
|
||||
|
||||
fn load_board(&mut self, board: Board) {
|
||||
self.source_board = board;
|
||||
}
|
||||
|
||||
fn start_sim(&mut self) {
|
||||
self.machine.reset();
|
||||
self.machine.set_board(self.source_board.clone());
|
||||
}
|
||||
|
||||
fn rotate_tool(&mut self, shift: bool) {
|
||||
match &self.active_tool {
|
||||
Tool::Math => {
|
||||
self.tool_menu_math = match self.tool_menu_math {
|
||||
MathOp::Add => MathOp::Sub,
|
||||
MathOp::Sub => MathOp::Mul,
|
||||
MathOp::Mul => MathOp::Div,
|
||||
MathOp::Div => MathOp::Rem,
|
||||
MathOp::Rem => MathOp::Add,
|
||||
}
|
||||
}
|
||||
Tool::Gate => {
|
||||
self.tool_menu_gate = match self.tool_menu_gate {
|
||||
GateType::LessThan => GateType::GreaterThan,
|
||||
GateType::GreaterThan => GateType::Equal,
|
||||
GateType::Equal => GateType::NotEqual,
|
||||
GateType::NotEqual => GateType::LessThan,
|
||||
}
|
||||
}
|
||||
Tool::Arrow => {
|
||||
self.tool_menu_arrow = if shift {
|
||||
self.tool_menu_arrow.left()
|
||||
} else {
|
||||
self.tool_menu_arrow.right()
|
||||
}
|
||||
}
|
||||
Tool::Mirror => {
|
||||
self.tool_menu_mirror = match self.tool_menu_mirror {
|
||||
MirrorType::Forward => MirrorType::Back,
|
||||
MirrorType::Back => MirrorType::Forward,
|
||||
}
|
||||
}
|
||||
Tool::Wire => {
|
||||
self.tool_menu_wire = match self.tool_menu_wire {
|
||||
WireType::Vertical => WireType::Horizontal,
|
||||
WireType::Horizontal => WireType::Cross,
|
||||
WireType::Cross => WireType::Vertical,
|
||||
}
|
||||
}
|
||||
Tool::None => (),
|
||||
Tool::SetTile(_) => (),
|
||||
Tool::Digits(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn input(&mut self, rl: &RaylibHandle) {
|
||||
if self.sim_state == SimState::Running {
|
||||
self.time_since_step += rl.get_frame_time();
|
||||
if self.time_since_step > 1. / self.sim_speed {
|
||||
self.time_since_step = 0.;
|
||||
self.machine.step();
|
||||
}
|
||||
}
|
||||
if rl.is_key_pressed(KeyboardKey::KEY_SPACE) {
|
||||
match self.sim_state {
|
||||
SimState::Editing => {
|
||||
self.start_sim();
|
||||
self.machine.step();
|
||||
}
|
||||
SimState::Running => (),
|
||||
SimState::Stepping => self.machine.step(),
|
||||
}
|
||||
self.sim_state = SimState::Stepping;
|
||||
}
|
||||
if rl.is_key_pressed(KeyboardKey::KEY_ESCAPE) {
|
||||
self.sim_state = SimState::Editing;
|
||||
}
|
||||
if rl.is_key_pressed(KeyboardKey::KEY_ENTER) {
|
||||
match self.sim_state {
|
||||
SimState::Editing => {
|
||||
self.start_sim();
|
||||
self.sim_state = SimState::Running;
|
||||
}
|
||||
SimState::Running => self.sim_state = SimState::Editing,
|
||||
SimState::Stepping => self.sim_state = SimState::Running,
|
||||
}
|
||||
}
|
||||
|
||||
if rl.get_mouse_wheel_move() > 0. && self.zoom < 3 {
|
||||
self.zoom += 1;
|
||||
}
|
||||
if rl.get_mouse_wheel_move() < 0. && self.zoom > 0 {
|
||||
self.zoom -= 1;
|
||||
}
|
||||
if rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_MIDDLE) {
|
||||
self.view_offset += rl.get_mouse_delta()
|
||||
}
|
||||
if rl.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_RIGHT) {
|
||||
self.view_offset = Vector2::zero();
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_board(&self, d: &mut RaylibDrawHandle, textures: &Textures) {
|
||||
if self.sim_state == SimState::Editing {
|
||||
self.source_board
|
||||
.draw(d, textures, self.view_offset, self.zoom);
|
||||
} else {
|
||||
self.machine
|
||||
.board()
|
||||
.draw(d, textures, self.view_offset, self.zoom);
|
||||
self.machine
|
||||
.draw_marble_values(d, self.view_offset, self.zoom);
|
||||
}
|
||||
}
|
||||
|
||||
fn gui(&mut self, d: &mut RaylibDrawHandle, textures: &Textures) {
|
||||
self.draw_board(d, textures);
|
||||
|
||||
let height = d.get_screen_height();
|
||||
let footer_height = 95;
|
||||
let footer_top = (height - footer_height) as f32;
|
||||
d.draw_rectangle(
|
||||
0,
|
||||
height - footer_height,
|
||||
d.get_screen_width(),
|
||||
footer_height,
|
||||
Color::new(32, 32, 32, 255),
|
||||
);
|
||||
|
||||
let tile_size = (16 << self.zoom) as f32;
|
||||
let grid_spill_x = (self.view_offset.x).rem(tile_size) - tile_size;
|
||||
let grid_spill_y = (self.view_offset.y).rem(tile_size) - tile_size;
|
||||
d.gui_grid(
|
||||
Rectangle::new(
|
||||
grid_spill_x,
|
||||
grid_spill_y,
|
||||
d.get_screen_width() as f32 * 2.,
|
||||
height as f32 - grid_spill_y - footer_height as f32,
|
||||
),
|
||||
None,
|
||||
tile_size,
|
||||
1,
|
||||
);
|
||||
|
||||
d.gui_check_box(
|
||||
Rectangle::new(5., footer_top + 5., 25., 25.),
|
||||
Some(rstr!("output as text")),
|
||||
&mut self.output_as_text,
|
||||
);
|
||||
let out_text = if self.output_as_text {
|
||||
String::from_utf8_lossy(self.machine.output()).to_string()
|
||||
} else {
|
||||
format!("{:?}", self.machine.output())
|
||||
};
|
||||
d.draw_text(&out_text, 5, footer_top as i32 + 35, 20, Color::WHITE);
|
||||
|
||||
let mut input_text = String::from_utf8_lossy(self.machine.input()).to_string();
|
||||
if text_input(
|
||||
d,
|
||||
Rectangle::new(5., footer_top + 60., 200., 25.),
|
||||
&mut input_text,
|
||||
&mut self.input_text_selected,
|
||||
) {
|
||||
self.machine.set_input(input_text.into_bytes());
|
||||
}
|
||||
|
||||
let mut tool_button = |(row, col): (i32, i32), texture: &str, tool_option: Tool| {
|
||||
let border = 4.;
|
||||
let gap = 2.;
|
||||
let bound_offset = 32. + gap * 2. + border * 2.;
|
||||
texture_button(
|
||||
d,
|
||||
Vector2 {
|
||||
x: 320. + col as f32 * bound_offset - if col < 0 { 15. } else { 0. },
|
||||
y: footer_top + 5. + row as f32 * bound_offset,
|
||||
},
|
||||
textures.get(texture),
|
||||
tool_option,
|
||||
&mut self.active_tool,
|
||||
32.,
|
||||
border,
|
||||
);
|
||||
};
|
||||
tool_button((0, -2), "eraser", Tool::SetTile(Tile::from_char(' ')));
|
||||
tool_button((0, -1), "digit_tool", Tool::Digits(None));
|
||||
tool_button((1, -1), "transparent", Tool::None);
|
||||
|
||||
tool_button((0, 0), "block", Tool::SetTile(Tile::from_char('#')));
|
||||
tool_button((0, 1), "bag_off", Tool::SetTile(Tile::from_char('B')));
|
||||
tool_button((0, 2), "trigger_off", Tool::SetTile(Tile::from_char('*')));
|
||||
tool_button((0, 3), "input_off", Tool::SetTile(Tile::from_char('I')));
|
||||
tool_button((0, 4), "output_off", Tool::SetTile(Tile::from_char('P')));
|
||||
tool_button((0, 5), "flipper_off", Tool::SetTile(Tile::from_char('F')));
|
||||
|
||||
tool_button((1, 0), "marble", Tool::SetTile(Tile::from_char('o')));
|
||||
tool_button(
|
||||
(1, 1),
|
||||
&Tile::Powerable(PTile::Wire(self.tool_menu_wire), false).texture(),
|
||||
Tool::Wire,
|
||||
);
|
||||
|
||||
tool_button(
|
||||
(1, 2),
|
||||
&Tile::Arrow(self.tool_menu_arrow).texture(),
|
||||
Tool::Arrow,
|
||||
);
|
||||
tool_button(
|
||||
(1, 3),
|
||||
&Tile::Mirror(self.tool_menu_mirror).texture(),
|
||||
Tool::Mirror,
|
||||
);
|
||||
tool_button(
|
||||
(1, 4),
|
||||
&Tile::Powerable(PTile::Math(self.tool_menu_math), false).texture(),
|
||||
Tool::Math,
|
||||
);
|
||||
tool_button(
|
||||
(1, 5),
|
||||
&Tile::Powerable(PTile::Gate(self.tool_menu_gate), false).texture(),
|
||||
Tool::Gate,
|
||||
);
|
||||
|
||||
let is_shift = d.is_key_down(KeyboardKey::KEY_LEFT_SHIFT);
|
||||
if d.is_key_pressed(KeyboardKey::KEY_R) {
|
||||
self.rotate_tool(is_shift);
|
||||
}
|
||||
|
||||
let mouse_pos = d.get_mouse_position();
|
||||
if self.sim_state == SimState::Editing {
|
||||
if let Tool::Digits(Some(pos)) = &mut self.active_tool {
|
||||
let tile_screen_pos = pos.to_vec() * (16 << self.zoom) as f32 + self.view_offset;
|
||||
d.draw_texture_ex(
|
||||
textures.get("selection"),
|
||||
tile_screen_pos,
|
||||
0.,
|
||||
(1 << self.zoom) as f32,
|
||||
Color::new(255, 180, 20, 255),
|
||||
);
|
||||
for n in 0..10 {
|
||||
if d.is_key_pressed(unsafe { std::mem::transmute(KeyboardKey::KEY_ZERO as u32 + n) }) {
|
||||
self.source_board.set(*pos, Tile::Digit(n as u8));
|
||||
}
|
||||
}
|
||||
if d.is_key_pressed(KeyboardKey::KEY_LEFT) {
|
||||
pos.x -= 1;
|
||||
}
|
||||
if d.is_key_pressed(KeyboardKey::KEY_RIGHT) {
|
||||
pos.x += 1;
|
||||
}
|
||||
if d.is_key_pressed(KeyboardKey::KEY_UP) {
|
||||
pos.y -= 1;
|
||||
}
|
||||
if d.is_key_pressed(KeyboardKey::KEY_DOWN) {
|
||||
pos.y += 1;
|
||||
}
|
||||
}
|
||||
if mouse_pos.y < footer_top {
|
||||
let tile_pos = (mouse_pos - self.view_offset) / (16 << self.zoom) as f32;
|
||||
let tile_pos = Vector2::new(tile_pos.x.floor(), tile_pos.y.floor());
|
||||
|
||||
let tile_screen_pos = tile_pos * (16 << self.zoom) as f32 + self.view_offset;
|
||||
|
||||
if self.active_tool != Tool::None {
|
||||
let tex = match self.active_tool {
|
||||
Tool::None => unreachable!(),
|
||||
Tool::SetTile(t) => {
|
||||
if t == Tile::Blank {
|
||||
"selection".into()
|
||||
} else {
|
||||
t.texture()
|
||||
}
|
||||
}
|
||||
Tool::Math => format!("{}_off", self.tool_menu_math.texture_name()),
|
||||
Tool::Gate => format!("{}_off", self.tool_menu_gate.texture_name()),
|
||||
Tool::Wire => format!("{}_off", self.tool_menu_wire.texture_name()),
|
||||
Tool::Arrow => self.tool_menu_arrow.arrow_texture_name().into(),
|
||||
Tool::Mirror => self.tool_menu_mirror.texture_name().into(),
|
||||
Tool::Digits(_) => "selection".into(),
|
||||
};
|
||||
|
||||
d.draw_texture_ex(
|
||||
textures.get(&tex),
|
||||
tile_screen_pos,
|
||||
0.,
|
||||
(1 << self.zoom) as f32,
|
||||
Color::new(255, 255, 255, 100),
|
||||
);
|
||||
}
|
||||
if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) {
|
||||
match self.active_tool {
|
||||
Tool::None => (),
|
||||
Tool::SetTile(tile) => self.source_board.set(tile_pos.into(), tile),
|
||||
Tool::Math => self.source_board.set(
|
||||
tile_pos.into(),
|
||||
Tile::Powerable(PTile::Math(self.tool_menu_math), false),
|
||||
),
|
||||
Tool::Gate => self.source_board.set(
|
||||
tile_pos.into(),
|
||||
Tile::Powerable(PTile::Gate(self.tool_menu_gate), false),
|
||||
),
|
||||
Tool::Wire => self.source_board.set(
|
||||
tile_pos.into(),
|
||||
Tile::Powerable(PTile::Wire(self.tool_menu_wire), false),
|
||||
),
|
||||
Tool::Arrow => self
|
||||
.source_board
|
||||
.set(tile_pos.into(), Tile::Arrow(self.tool_menu_arrow)),
|
||||
Tool::Mirror => self
|
||||
.source_board
|
||||
.set(tile_pos.into(), Tile::Mirror(self.tool_menu_mirror)),
|
||||
Tool::Digits(_pos) => {
|
||||
self.active_tool = Tool::Digits(Some(tile_pos.into()));
|
||||
if let Some(tile) = self.source_board.get_mut(tile_pos.into()) {
|
||||
if let Tile::Digit(_) = tile {
|
||||
} else {
|
||||
*tile = Tile::Digit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Tool{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::SetTile(l0), Self::SetTile(r0)) => l0 == r0,
|
||||
(Self::Digits(_), Self::Digits(_)) => true,
|
||||
_ => ::core::mem::discriminant(self) == ::core::mem::discriminant(other),
|
||||
}
|
||||
game.draw(&mut d, &textures);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -257,6 +257,4 @@ impl GateType {
|
|||
GateType::NotEqual => "neq",
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue