mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/exe/edit.rs')
-rw-r--r--src/exe/edit.rs113
1 files changed, 111 insertions, 2 deletions
diff --git a/src/exe/edit.rs b/src/exe/edit.rs
index 051394b..d24108f 100644
--- a/src/exe/edit.rs
+++ b/src/exe/edit.rs
@@ -6,7 +6,7 @@ use std::fs;
use crate::block::{BlockRegistry, build_registry, Rotation};
use crate::data::dynamic::DynData;
use crate::data::{DataRead, Serializer, DataWrite, base64};
-use crate::data::schematic::{Schematic, SchematicSerializer};
+use crate::data::schematic::{ResizeError, Schematic, SchematicSerializer};
use crate::exe::print::print_schematic;
use crate::exe::print_err;
use crate::exe::args::{self, ArgCount, ArgOption, OptionHandler};
@@ -227,7 +227,7 @@ impl<'l> Tokenizer<'l>
enum Command
{
- Help, New, Input, Load, Place, Rotate, Mirror, Remove, Print, Dump, Save, Quit
+ Help, New, Input, Load, Place, Rotate, Mirror, Move, Resize, Remove, Print, Dump, Save, Quit
}
impl Command
@@ -243,6 +243,8 @@ impl Command
Self::Place => println!("{:<indent$}Places a block if enough space is available", "\"place\":"),
Self::Rotate => println!("{:<indent$}Rotates the schematic (CCW) in increments of 90 degrees", "\"rotate\":"),
Self::Mirror => println!("{:<indent$}Mirrors the schematic horizontally or vertically", "\"mirror\":"),
+ Self::Move => println!("{:<indent$}Moves all blocks by a certain offset", "\"move\":"),
+ Self::Resize => println!("{:<indent$}Resizes the schematic and offsets it", "\"resize\":"),
Self::Remove => println!("{:<indent$}Removes blocks at a position or within a region", "\"remove\":"),
Self::Print => println!("{:<indent$}Prints the schematic in a visual representation", "\"print\":"),
Self::Dump => println!("{:<indent$}Prints the schematic as a base-64 encoded string", "\"dump\":"),
@@ -267,6 +269,8 @@ impl Command
},
Self::Rotate => println!(r#"{:indent$} Usage: "rotate" <angle>"#, ""),
Self::Mirror => println!(r#"{:indent$} Usage: "mirror" <axis>"#, ""),
+ Self::Move => println!(r#"{:indent$} Usage: "move" <dx> <dy>"#, ""),
+ Self::Resize => println!(r#"{:indent$} Usage: "resize" <width> <height> [<dx> <dy>]"#, ""),
Self::Remove => println!(r#"{:indent$} Usage: "remove" <x0> <y0> [<x1> <y1>]"#, ""),
Self::Print | Self::Dump => (),
Self::Save => println!(r#"{:indent$} Usage: "save" <save path>"#, ""),
@@ -598,6 +602,111 @@ fn interpret(state: &mut State, cmd: &str)
schematic.mirror(x, y);
state.unsaved = true;
},
+ Some("move") =>
+ {
+ let Some(ref mut schematic) = state.schematic
+ else
+ {
+ eprintln!(r#"Command "move" requires an active schematic (see "help")"#);
+ return;
+ };
+ let dx = parse_num!(Move, tokens, "dx", i16);
+ let dy = parse_num!(Move, tokens, "dy", i16);
+ if tokens.remainder().is_some()
+ {
+ eprintln!(r#"Too many parameters for "move""#);
+ Command::Move.print_usage(0);
+ return;
+ }
+ if dx != 0 && dy != 0
+ {
+ if let Err(e) = schematic.resize(dx, dy, schematic.get_width(), schematic.get_height())
+ {
+ match e
+ {
+ ResizeError::XOffset{dx, old_w, new_w} =>
+ {
+ debug_assert_eq!(old_w, new_w);
+ eprintln!("Invalid horizontal move {dx} not in ]-{old_w}, {new_w}[");
+ },
+ ResizeError::YOffset{dy, old_h, new_h} =>
+ {
+ debug_assert_eq!(old_h, new_h);
+ eprintln!("Invalid vertical move {dy} not in ]-{old_h}, {new_h}[");
+ },
+ ResizeError::Truncated{right, top, left, bottom} =>
+ {
+ eprint!("Move would truncate schematic: ");
+ let mut first = true;
+ if right > 0
+ {
+ eprint!("{}right: {right}", if first {""} else {", "});
+ first = false;
+ }
+ if top > 0
+ {
+ eprint!("{}top: {top}", if first {""} else {", "});
+ first = false;
+ }
+ if left > 0
+ {
+ eprint!("{}left: {left}", if first {""} else {", "});
+ first = false;
+ }
+ if bottom > 0
+ {
+ eprint!("{}bottom: {bottom}", if first {""} else {", "});
+ first = false;
+ }
+ if first {eprintln!("<unknown>");} else {eprintln!();}
+ },
+ _ => print_err!(e, "Unexpected resize error (for {dx} / {dy})")
+ }
+ }
+ else {state.unsaved = true;}
+ }
+ },
+ Some("resize") =>
+ {
+ let Some(ref mut schematic) = state.schematic
+ else
+ {
+ eprintln!(r#"Command "resize" requires an active schematic (see "help")"#);
+ return;
+ };
+ let w = parse_num!(Resize, tokens, "width", u16);
+ if w == 0
+ {
+ eprintln!("Schematic width must be positive");
+ return;
+ }
+ let h = parse_num!(Resize, tokens, "height", u16);
+ if h == 0
+ {
+ eprintln!("Schematic height must be positive");
+ return;
+ }
+ let (dx, dy) = if let arg @ Some(..) = tokens.next()
+ {
+ let dx = parse_num!(Resize, "dx", <i16>::from(arg));
+ let dy = parse_num!(Resize, tokens, "dy", i16);
+ (dx, dy)
+ }
+ else {(0, 0)};
+ if tokens.remainder().is_some()
+ {
+ eprintln!(r#"Too many parameters for "resize""#);
+ Command::Resize.print_usage(0);
+ return;
+ }
+ if w != schematic.get_width() || h != schematic.get_height() || dx != 0 || dy != 0
+ {
+ if let Err(e) = schematic.resize(dx, dy, w, h)
+ {
+ print_err!(e, "Could not resize schematic");
+ }
+ }
+ },
Some("remove") =>
{
let Some(ref mut schematic) = state.schematic