add more tiles to gui, with controls to rotate between variants in a group
This commit is contained in:
parent
175d01cb03
commit
bf82d1455f
3 changed files with 195 additions and 72 deletions
162
src/main.rs
162
src/main.rs
|
@ -4,7 +4,12 @@ use std::{
|
|||
ops::Rem,
|
||||
};
|
||||
|
||||
use marble_engine::{board::Board, parse, tile::Tile, tile_to_char, Machine};
|
||||
use marble_engine::{
|
||||
board::Board,
|
||||
parse,
|
||||
tile::{Direction, GateType, MathOp, MirrorType, PTile, Tile},
|
||||
tile_from_char, Machine,
|
||||
};
|
||||
use raylib::prelude::*;
|
||||
|
||||
mod marble_engine;
|
||||
|
@ -21,6 +26,10 @@ struct Game {
|
|||
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,
|
||||
input_text_selected: bool,
|
||||
sim_speed: f32,
|
||||
time_since_step: f32,
|
||||
|
@ -30,8 +39,12 @@ struct Game {
|
|||
enum Tool {
|
||||
None,
|
||||
SetTile(Tile),
|
||||
// Erase,
|
||||
// Select,
|
||||
Math,
|
||||
Gate,
|
||||
Arrow,
|
||||
Mirror,
|
||||
Number,
|
||||
// SelectArea,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
@ -65,6 +78,8 @@ fn main() {
|
|||
.title("good window title")
|
||||
.build();
|
||||
rl.set_target_fps(60);
|
||||
rl.set_window_min_size(640, 480);
|
||||
rl.set_mouse_cursor(MouseCursor::MOUSE_CURSOR_CROSSHAIR);
|
||||
rl.set_exit_key(None);
|
||||
|
||||
let mut textures: HashMap<String, Texture2D> = HashMap::new();
|
||||
|
@ -97,6 +112,10 @@ impl Game {
|
|||
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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,6 +128,44 @@ impl Game {
|
|||
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::None => (),
|
||||
Tool::SetTile(_) => (),
|
||||
Tool::Number => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn input(&mut self, rl: &RaylibHandle) {
|
||||
if self.sim_state == SimState::Running {
|
||||
self.time_since_step += rl.get_frame_time();
|
||||
|
@ -237,32 +294,53 @@ impl Game {
|
|||
border,
|
||||
);
|
||||
};
|
||||
tool_button((0, -1), "eraser", Tool::SetTile(tile_to_char(' ')));
|
||||
tool_button((0, -1), "eraser", Tool::SetTile(tile_from_char(' ')));
|
||||
tool_button((1, -1), "", Tool::None);
|
||||
|
||||
tool_button((0, 0), "marble", Tool::SetTile(tile_to_char('o')));
|
||||
tool_button((0, 1), "block", Tool::SetTile(tile_to_char('#')));
|
||||
tool_button((0, 2), "bag_off", Tool::SetTile(tile_to_char('B')));
|
||||
tool_button((0, 3), "trigger_off", Tool::SetTile(tile_to_char('*')));
|
||||
tool_button((0, 4), "input_off", Tool::SetTile(tile_to_char('I')));
|
||||
tool_button((0, 5), "output_off", Tool::SetTile(tile_to_char('P')));
|
||||
tool_button((0, 6), "flipper_off", Tool::SetTile(tile_to_char('F')));
|
||||
tool_button((0, 0), "marble", Tool::SetTile(tile_from_char('o')));
|
||||
tool_button((0, 1), "block", Tool::SetTile(tile_from_char('#')));
|
||||
tool_button((0, 2), "bag_off", Tool::SetTile(tile_from_char('B')));
|
||||
tool_button((0, 3), "trigger_off", Tool::SetTile(tile_from_char('*')));
|
||||
tool_button((0, 4), "input_off", Tool::SetTile(tile_from_char('I')));
|
||||
tool_button((0, 5), "output_off", Tool::SetTile(tile_from_char('P')));
|
||||
tool_button((0, 6), "flipper_off", Tool::SetTile(tile_from_char('F')));
|
||||
|
||||
tool_button(
|
||||
(1, 0),
|
||||
"wire_horizontal_off",
|
||||
Tool::SetTile(tile_to_char('-')),
|
||||
Tool::SetTile(tile_from_char('-')),
|
||||
);
|
||||
tool_button(
|
||||
(1, 1),
|
||||
"wire_vertical_off",
|
||||
Tool::SetTile(tile_to_char('|')),
|
||||
Tool::SetTile(tile_from_char('|')),
|
||||
);
|
||||
tool_button((1, 2), "wire_cross_off", Tool::SetTile(tile_to_char('+')));
|
||||
tool_button((1, 3), "arrow_up", Tool::SetTile(tile_to_char('^')));
|
||||
tool_button((1, 4), "arrow_down", Tool::SetTile(tile_to_char('v')));
|
||||
tool_button((1, 5), "arrow_left", Tool::SetTile(tile_to_char('<')));
|
||||
tool_button((1, 6), "arrow_right", Tool::SetTile(tile_to_char('>')));
|
||||
tool_button((1, 2), "wire_cross_off", Tool::SetTile(tile_from_char('+')));
|
||||
tool_button(
|
||||
(1, 3),
|
||||
&Tile::Arrow(self.tool_menu_arrow).texture(),
|
||||
Tool::Arrow,
|
||||
);
|
||||
tool_button(
|
||||
(1, 4),
|
||||
&Tile::Mirror(self.tool_menu_mirror).texture(),
|
||||
Tool::Mirror,
|
||||
);
|
||||
tool_button(
|
||||
(1, 5),
|
||||
&Tile::Powerable(PTile::Math(self.tool_menu_math), false).texture(),
|
||||
Tool::Math,
|
||||
);
|
||||
tool_button(
|
||||
(1, 6),
|
||||
&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 && mouse_pos.y < footer_top {
|
||||
|
@ -271,17 +349,53 @@ impl Game {
|
|||
|
||||
let tile_screen_pos = tile_pos * (16 << self.zoom) as f32 + self.view_offset;
|
||||
|
||||
if let Tool::SetTile(tile) = self.active_tool {
|
||||
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::Arrow => self.tool_menu_arrow.arrow_texture_name().into(),
|
||||
Tool::Mirror => self.tool_menu_mirror.texture_name().into(),
|
||||
Tool::Number => todo!(),
|
||||
};
|
||||
|
||||
let tex = textures
|
||||
.get(&tex)
|
||||
.unwrap_or_else(|| textures.get("missing").unwrap());
|
||||
d.draw_texture_ex(
|
||||
textures.get("selection").unwrap(),
|
||||
tex,
|
||||
tile_screen_pos,
|
||||
0.,
|
||||
(1 << self.zoom) as f32,
|
||||
Color::new(255, 255, 255, 150),
|
||||
Color::new(255, 255, 255, 100),
|
||||
);
|
||||
|
||||
if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) {
|
||||
self.source_board.set(tile_pos.into(), tile)
|
||||
}
|
||||
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::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::Number => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,10 +58,6 @@ impl Machine {
|
|||
&self.input
|
||||
}
|
||||
|
||||
pub fn input_mut(&mut self) -> &mut Vec<u8> {
|
||||
&mut self.input
|
||||
}
|
||||
|
||||
pub fn set_input(&mut self, bytes: Vec<u8>) {
|
||||
self.input_index = self.input_index.min(bytes.len());
|
||||
self.input = bytes;
|
||||
|
@ -327,7 +323,7 @@ pub fn parse(source: &str) -> Board {
|
|||
width = width.max(line.len());
|
||||
let mut tiles = Vec::new();
|
||||
for char in line.chars() {
|
||||
tiles.push(tile_to_char(char));
|
||||
tiles.push(tile_from_char(char));
|
||||
}
|
||||
rows.push(tiles);
|
||||
}
|
||||
|
@ -338,7 +334,7 @@ pub fn parse(source: &str) -> Board {
|
|||
Board::new(rows)
|
||||
}
|
||||
|
||||
pub const fn tile_to_char(c: char) -> Tile {
|
||||
pub const fn tile_from_char(c: char) -> Tile {
|
||||
match c {
|
||||
'o' => Tile::Marble {
|
||||
value: 0,
|
||||
|
@ -367,7 +363,7 @@ pub const fn tile_to_char(c: char) -> Tile {
|
|||
'D' => Tile::Powerable(PTile::Math(MathOp::Div), false),
|
||||
'R' => Tile::Powerable(PTile::Math(MathOp::Rem), false),
|
||||
'B' => Tile::Powerable(PTile::Bag, false),
|
||||
d @ '0'..='9' => Tile::Digit(d as u8),
|
||||
d @ '0'..='9' => Tile::Digit(d as u8 - b'0'),
|
||||
'#' => Tile::Block,
|
||||
' ' => Tile::Blank,
|
||||
_ => Tile::Blank,
|
||||
|
|
|
@ -85,50 +85,15 @@ impl Tile {
|
|||
Tile::Blank => "transparent",
|
||||
Tile::Block => "block",
|
||||
Tile::Marble { value: _, dir: _ } => "marble",
|
||||
Tile::Digit(n) => match n {
|
||||
b'0' => "digit_0",
|
||||
b'1' => "digit_1",
|
||||
b'2' => "digit_2",
|
||||
b'3' => "digit_3",
|
||||
b'4' => "digit_4",
|
||||
b'5' => "digit_5",
|
||||
b'6' => "digit_6",
|
||||
b'7' => "digit_7",
|
||||
b'8' => "digit_8",
|
||||
b'9' => "digit_9",
|
||||
_ => unreachable!("invalid digit"),
|
||||
},
|
||||
Tile::Mirror(mirror) => match mirror {
|
||||
MirrorType::Forward => "mirror_forward",
|
||||
MirrorType::Back => "mirror_back",
|
||||
},
|
||||
Tile::Arrow(dir) => match dir {
|
||||
Direction::Up => "arrow_up",
|
||||
Direction::Down => "arrow_down",
|
||||
Direction::Left => "arrow_left",
|
||||
Direction::Right => "arrow_right",
|
||||
},
|
||||
Tile::Digit(n) => return format!("digit_{n}"),
|
||||
Tile::Mirror(mirror) => mirror.texture_name(),
|
||||
Tile::Arrow(dir) => dir.arrow_texture_name(),
|
||||
Tile::Powerable(tile, state) => {
|
||||
let root = match tile {
|
||||
PTile::Trigger => "trigger",
|
||||
PTile::Wire(wire) => match wire {
|
||||
WireType::Vertical => "wire_vertical",
|
||||
WireType::Horizontal => "wire_horizontal",
|
||||
WireType::Cross => "wire_cross",
|
||||
},
|
||||
PTile::Gate(gate) => match gate {
|
||||
GateType::LessThan => "lt",
|
||||
GateType::GreaterThan => "gt",
|
||||
GateType::Equal => "eq",
|
||||
GateType::NotEqual => "neq",
|
||||
},
|
||||
PTile::Math(math_op) => match math_op {
|
||||
MathOp::Add => "add",
|
||||
MathOp::Sub => "sub",
|
||||
MathOp::Mul => "mul",
|
||||
MathOp::Div => "div",
|
||||
MathOp::Rem => "rem",
|
||||
},
|
||||
PTile::Wire(wire) => wire.texture_name(),
|
||||
PTile::Gate(gate) => gate.texture_name(),
|
||||
PTile::Math(math_op) => math_op.texture_name(),
|
||||
PTile::Bag => "bag",
|
||||
PTile::Flipper => "flipper",
|
||||
PTile::Input => "input",
|
||||
|
@ -180,6 +145,15 @@ impl Direction {
|
|||
}
|
||||
pos
|
||||
}
|
||||
|
||||
pub const fn arrow_texture_name(&self) -> &'static str {
|
||||
match self {
|
||||
Direction::Up => "arrow_up",
|
||||
Direction::Down => "arrow_down",
|
||||
Direction::Left => "arrow_left",
|
||||
Direction::Right => "arrow_right",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WireType {
|
||||
|
@ -190,6 +164,14 @@ impl WireType {
|
|||
WireType::Cross => &Direction::ALL,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn texture_name(&self) -> &'static str {
|
||||
match self {
|
||||
WireType::Vertical => "wire_vertical",
|
||||
WireType::Horizontal => "wire_horizontal",
|
||||
WireType::Cross => "wire_cross",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MirrorType {
|
||||
|
@ -209,4 +191,35 @@ impl MirrorType {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn texture_name(&self) -> &'static str {
|
||||
match self {
|
||||
MirrorType::Forward => "mirror_forward",
|
||||
MirrorType::Back => "mirror_back",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MathOp {
|
||||
pub const fn texture_name(&self) -> &'static str {
|
||||
match self {
|
||||
MathOp::Add => "add",
|
||||
MathOp::Sub => "sub",
|
||||
MathOp::Mul => "mul",
|
||||
MathOp::Div => "div",
|
||||
MathOp::Rem => "rem",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GateType {
|
||||
pub const fn texture_name(&self) -> &'static str {
|
||||
match self {
|
||||
GateType::LessThan => "lt",
|
||||
GateType::GreaterThan => "gt",
|
||||
GateType::Equal => "eq",
|
||||
GateType::NotEqual => "neq",
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue