mindustry logic execution, map- and schematic- parsing and rendering
add linePoly
bendn 2023-10-14
parent 5cb812b · commit d4364ae
-rw-r--r--lemu/Cargo.toml4
-rw-r--r--lemu/src/instructions/draw.rs56
-rw-r--r--lemu/src/parser/mod.rs20
3 files changed, 70 insertions, 10 deletions
diff --git a/lemu/Cargo.toml b/lemu/Cargo.toml
index 13604c0..5985dad 100644
--- a/lemu/Cargo.toml
+++ b/lemu/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemu"
-version = "0.2.12"
+version = "0.2.13"
edition = "2021"
description = "M-LOG runner"
authors = ["bend-n <[email protected]>"]
@@ -12,7 +12,7 @@ keywords = ["mindustry", "logic", "emulator", "executor"]
[dependencies]
thiserror = "1.0"
enum_dispatch = "0.3"
-fimg = { version = "0.4.10", default-features = false }
+fimg = { version = "0.4.16", default-features = false }
logos = "0.13.0"
rust-fuzzy-search = { version = "0.1.1", optional = true }
beef = "0.5"
diff --git a/lemu/src/instructions/draw.rs b/lemu/src/instructions/draw.rs
index 1e57447..fc93d8f 100644
--- a/lemu/src/instructions/draw.rs
+++ b/lemu/src/instructions/draw.rs
@@ -8,7 +8,7 @@ use fimg::Image;
use std::fmt::{self, Display as Disp, Formatter};
pub const INSTRS: &[&str] = &[
- "clear", "color", "col", "stroke", "line", "rect", "lineRect", "triangle", "poly",
+ "clear", "color", "col", "stroke", "line", "rect", "lineRect", "triangle", "poly", "linePoly",
];
#[enum_dispatch]
@@ -32,6 +32,7 @@ pub enum DrawInstr<'v> {
SetColor(SetColor<'v>),
SetStroke(SetStroke<'v>),
Poly(Poly<'v>),
+ LinePoly(LinePoly<'v>),
}
impl Disp for DrawInstr<'_> {
@@ -45,6 +46,7 @@ impl Disp for DrawInstr<'_> {
Self::SetColor(i) => write!(f, "{i}"),
Self::SetStroke(i) => write!(f, "{i}"),
Self::Poly(i) => write!(f, "{i}"),
+ Self::LinePoly(i) => write!(f, "{i}"),
}
}
}
@@ -54,7 +56,6 @@ pub struct Clear<'v> {
pub r: LAddress<'v>,
pub g: LAddress<'v>,
pub b: LAddress<'v>,
- pub a: LAddress<'v>,
}
impl<'v> DrawInstruction<'v> for Clear<'v> {
@@ -67,16 +68,16 @@ impl<'v> DrawInstruction<'v> for Clear<'v> {
}
};
}
- let (r, g, b, a) = (u8!(r), u8!(g), u8!(b), u8!(a));
+ let (r, g, b) = (u8!(r), u8!(g), u8!(b));
for [r2, g2, b2, a2] in image.chunked_mut() {
- (*r2, *b2, *g2, *a2) = (r, g, b, a);
+ (*r2, *b2, *g2, *a2) = (r, g, b, 255);
}
}
}
impl Disp for Clear<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
- write!(f, "draw clear {} {} {} {}", self.r, self.g, self.b, self.a)
+ write!(f, "draw clear {} {} {}", self.r, self.g, self.b)
}
}
@@ -306,6 +307,51 @@ impl Disp for Poly<'_> {
}
}
+#[derive(Debug)]
+pub struct LinePoly<'v> {
+ pub(crate) pos: Point<'v>,
+ pub(crate) sides: LAddress<'v>,
+ pub(crate) radius: LAddress<'v>,
+ pub(crate) rot: LAddress<'v>,
+}
+
+impl<'v> DrawInstruction<'v> for LinePoly<'v> {
+ fn draw(
+ &self,
+ mem: &mut LRegistry<'v>,
+ image: &mut Image<&mut [u8], 4>,
+ state: &mut DisplayState,
+ ) {
+ let sides = get_num!(mem.get(&self.sides)).round() as usize;
+ if sides < 90 {
+ image.border_poly(
+ map!(point!([email protected]), |n| n as f32),
+ sides,
+ get_num!(mem.get(&self.radius)) as f32,
+ get_num!(mem.get(&self.rot)) as f32,
+ state.stroke as f32,
+ state.col(),
+ );
+ } else {
+ image.border_circle(
+ map!(point!([email protected]), |n: f64| n.round() as i32),
+ get_num!(mem.get(&self.radius)).round() as i32,
+ state.col(),
+ );
+ }
+ }
+}
+
+impl Disp for LinePoly<'_> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "draw linePoly {} {} {} {} {}",
+ self.pos.0, self.pos.1, self.sides, self.radius, self.rot
+ )
+ }
+}
+
#[derive(Debug, Default)]
pub struct Flush {
pub(crate) display: Display,
diff --git a/lemu/src/parser/mod.rs b/lemu/src/parser/mod.rs
index 53c2940..1091a82 100644
--- a/lemu/src/parser/mod.rs
+++ b/lemu/src/parser/mod.rs
@@ -6,7 +6,10 @@ pub use error::Error;
use super::{
executor::{ExecutorBuilderInternal, Instruction, UPInstr},
instructions::{
- draw::{Clear, Flush, Line, Poly, RectBordered, RectFilled, SetColor, SetStroke, Triangle},
+ draw::{
+ Clear, Flush, Line, LinePoly, Poly, RectBordered, RectFilled, SetColor, SetStroke,
+ Triangle,
+ },
io::{Print, Read, Write},
AlwaysJump, ConditionOp, DynJump, End, Instr, Jump, MathOp1, MathOp2, Op1, Op2, Set, Stop,
},
@@ -327,6 +330,8 @@ pub fn parse<'source, W: Wr>(
yeet!(ExpectedIdent(dty));
};
#[rustfmt::skip]
+ macro_rules! three { ($a:expr) => { ($a, $a, $a) }; }
+ #[rustfmt::skip]
macro_rules! four { ($a:expr) => { ($a, $a, $a, $a) }; }
#[rustfmt::skip]
macro_rules! five { ($a:expr) => { ($a, $a, $a, $a, $a) }; }
@@ -334,8 +339,8 @@ pub fn parse<'source, W: Wr>(
macro_rules! six { ($a:expr) => { ($a, $a, $a, $a, $a, $a) }; }
match instr {
"clear" => {
- let (r, g, b, a) = four! { take_numvar!(tok!()?)? };
- executor.draw(Clear { r, g, b, a });
+ let (r, g, b) = three! { take_numvar!(tok!()?)? };
+ executor.draw(Clear { r, g, b });
}
"color" => {
let (r, g, b, a) = four! { take_numvar!(tok!()?)? };
@@ -396,6 +401,15 @@ pub fn parse<'source, W: Wr>(
rot,
})
}
+ "linePoly" => {
+ let (x, y, sides, radius, rot) = five! { take_numvar!(tok!()?)? };
+ executor.draw(LinePoly {
+ pos: (x, y),
+ sides,
+ radius,
+ rot,
+ })
+ }
// image is WONTFIX
i => yeet!(UnsupportedImageOp(i)),
}