save & load groups, add copy rule cells
This commit is contained in:
parent
f23c06f5d7
commit
ac9685b2d5
2 changed files with 64 additions and 24 deletions
|
@ -362,7 +362,7 @@ impl Dish {
|
||||||
let mut old_state = Vec::new();
|
let mut old_state = Vec::new();
|
||||||
for dy in 0..height {
|
for dy in 0..height {
|
||||||
for dx in 0..width {
|
for dx in 0..width {
|
||||||
old_state.push(self.get_cell(dx, dy).unwrap());
|
old_state.push(self.get_cell(x + dx, y + dy).unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,7 @@ use eframe::{
|
||||||
epaint::Hsva,
|
epaint::Hsva,
|
||||||
NativeOptions,
|
NativeOptions,
|
||||||
};
|
};
|
||||||
use egui::{
|
use egui::PointerButton;
|
||||||
menu::{SubMenu, SubMenuButton},
|
|
||||||
popup, Layout, PointerButton,
|
|
||||||
};
|
|
||||||
use native_dialog::FileDialog;
|
use native_dialog::FileDialog;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -68,6 +65,7 @@ impl UScope {
|
||||||
let out = json!({
|
let out = json!({
|
||||||
"cell_types": self.cell_types,
|
"cell_types": self.cell_types,
|
||||||
"rules": self.dish.rules,
|
"rules": self.dish.rules,
|
||||||
|
"groups": self.dish.cell_groups,
|
||||||
});
|
});
|
||||||
let out = serde_json::to_string(&out).ok()?;
|
let out = serde_json::to_string(&out).ok()?;
|
||||||
let mut file = File::create(path).ok()?;
|
let mut file = File::create(path).ok()?;
|
||||||
|
@ -85,9 +83,11 @@ impl UScope {
|
||||||
let s = fs::read_to_string(path).ok()?;
|
let s = fs::read_to_string(path).ok()?;
|
||||||
let data: Value = serde_json::from_str(&s).ok()?;
|
let data: Value = serde_json::from_str(&s).ok()?;
|
||||||
let cell_types = serde_json::from_value(data["cell_types"].clone()).ok()?;
|
let cell_types = serde_json::from_value(data["cell_types"].clone()).ok()?;
|
||||||
|
let groups = serde_json::from_value(data["groups"].clone()).ok()?;
|
||||||
let rules = serde_json::from_value(data["rules"].clone()).ok()?;
|
let rules = serde_json::from_value(data["rules"].clone()).ok()?;
|
||||||
self.cell_types = cell_types;
|
self.cell_types = cell_types;
|
||||||
self.dish.rules = rules;
|
self.dish.rules = rules;
|
||||||
|
self.dish.cell_groups = groups;
|
||||||
self.dish.update_rules();
|
self.dish.update_rules();
|
||||||
}
|
}
|
||||||
Some(())
|
Some(())
|
||||||
|
@ -215,6 +215,8 @@ fn paint_chunk(painter: Painter, chunk: &Chunk, cells: &[CellData], grid: bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSIZE: f32 = 24.;
|
const CSIZE: f32 = 24.;
|
||||||
|
const RESIZE_BUTTON_WIDTH: f32 = 8.;
|
||||||
|
|
||||||
const OUTLINE: (f32, Color32) = (2., Color32::GRAY);
|
const OUTLINE: (f32, Color32) = (2., Color32::GRAY);
|
||||||
fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData], groups: &[Vec<Cell>]) {
|
fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData], groups: &[Vec<Cell>]) {
|
||||||
ui.checkbox(&mut rule.enabled, "enable rule");
|
ui.checkbox(&mut rule.enabled, "enable rule");
|
||||||
|
@ -233,31 +235,41 @@ fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData], groups: &[Vec<C
|
||||||
|
|
||||||
let cells_y = rule.height();
|
let cells_y = rule.height();
|
||||||
let cells_x = rule.width();
|
let cells_x = rule.width();
|
||||||
let margin = 8.;
|
|
||||||
let patt_width = CSIZE * cells_x as f32;
|
let patt_width = CSIZE * cells_x as f32;
|
||||||
let patt_height = CSIZE * cells_y as f32;
|
let patt_height = CSIZE * cells_y as f32;
|
||||||
|
|
||||||
let (_, bounds) = ui.allocate_space(Vec2::new(
|
let (_, bounds) = ui.allocate_space(Vec2::new(
|
||||||
patt_width * 2. + margin * 4. + CSIZE,
|
patt_width * 2. + RESIZE_BUTTON_WIDTH * 4. + CSIZE,
|
||||||
patt_height + margin * 2.,
|
patt_height + RESIZE_BUTTON_WIDTH * 2.,
|
||||||
));
|
));
|
||||||
|
|
||||||
let from_cells_rect = Rect::from_min_size(
|
let from_cells_rect = Rect::from_min_size(
|
||||||
bounds.min + Vec2::splat(margin),
|
bounds.min + Vec2::splat(RESIZE_BUTTON_WIDTH),
|
||||||
Vec2::new(patt_width, patt_height),
|
Vec2::new(patt_width, patt_height),
|
||||||
);
|
);
|
||||||
let to_cells_rect = Rect::from_min_size(
|
let to_cells_rect = Rect::from_min_size(
|
||||||
bounds.min + Vec2::splat(margin) + Vec2::X * (patt_width + margin * 2. + CSIZE),
|
bounds.min
|
||||||
|
+ Vec2::splat(RESIZE_BUTTON_WIDTH)
|
||||||
|
+ Vec2::X * (patt_width + RESIZE_BUTTON_WIDTH * 2. + CSIZE),
|
||||||
Vec2::new(patt_width, patt_height),
|
Vec2::new(patt_width, patt_height),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut overlay_lines = Vec::new();
|
||||||
for x in 0..cells_x {
|
for x in 0..cells_x {
|
||||||
for y in 0..cells_y {
|
for y in 0..cells_y {
|
||||||
let (left, right) = rule.get_mut(x, y);
|
let (left, right) = rule.get_mut(x, y);
|
||||||
let changed_left =
|
let changed_left =
|
||||||
rule_cell_edit_from(ui, from_cells_rect.min, left, x, y, cells, groups);
|
rule_cell_edit_from(ui, from_cells_rect.min, left, x, y, cells, groups);
|
||||||
let changed_right =
|
let changed_right = rule_cell_edit_to(
|
||||||
rule_cell_edit_to(ui, to_cells_rect.min, right, x, y, cells, groups);
|
ui,
|
||||||
|
to_cells_rect.min,
|
||||||
|
right,
|
||||||
|
(x, y),
|
||||||
|
cells,
|
||||||
|
groups,
|
||||||
|
(cells_x, cells_y),
|
||||||
|
&mut overlay_lines,
|
||||||
|
);
|
||||||
if changed_left || changed_right {
|
if changed_left || changed_right {
|
||||||
rule.generate_variants();
|
rule.generate_variants();
|
||||||
}
|
}
|
||||||
|
@ -286,7 +298,12 @@ fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData], groups: &[Vec<C
|
||||||
|
|
||||||
result.clicked()
|
result.clicked()
|
||||||
};
|
};
|
||||||
if resize_box(bounds.min.x, bounds.min.y + margin, margin, patt_height) {
|
if resize_box(
|
||||||
|
bounds.min.x,
|
||||||
|
bounds.min.y + RESIZE_BUTTON_WIDTH,
|
||||||
|
RESIZE_BUTTON_WIDTH,
|
||||||
|
patt_height,
|
||||||
|
) {
|
||||||
if delete_mode {
|
if delete_mode {
|
||||||
rule.resize(Rule::SHRINK_LEFT);
|
rule.resize(Rule::SHRINK_LEFT);
|
||||||
} else {
|
} else {
|
||||||
|
@ -295,8 +312,8 @@ fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData], groups: &[Vec<C
|
||||||
}
|
}
|
||||||
if resize_box(
|
if resize_box(
|
||||||
from_cells_rect.max.x,
|
from_cells_rect.max.x,
|
||||||
bounds.min.y + margin,
|
bounds.min.y + RESIZE_BUTTON_WIDTH,
|
||||||
margin,
|
RESIZE_BUTTON_WIDTH,
|
||||||
patt_height,
|
patt_height,
|
||||||
) {
|
) {
|
||||||
if delete_mode {
|
if delete_mode {
|
||||||
|
@ -305,7 +322,12 @@ fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData], groups: &[Vec<C
|
||||||
rule.resize(Rule::EXTEND_RIGHT);
|
rule.resize(Rule::EXTEND_RIGHT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if resize_box(bounds.min.x + margin, bounds.min.y, patt_width, margin) {
|
if resize_box(
|
||||||
|
bounds.min.x + RESIZE_BUTTON_WIDTH,
|
||||||
|
bounds.min.y,
|
||||||
|
patt_width,
|
||||||
|
RESIZE_BUTTON_WIDTH,
|
||||||
|
) {
|
||||||
if delete_mode {
|
if delete_mode {
|
||||||
rule.resize(Rule::SHRINK_UP);
|
rule.resize(Rule::SHRINK_UP);
|
||||||
} else {
|
} else {
|
||||||
|
@ -313,10 +335,10 @@ fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData], groups: &[Vec<C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if resize_box(
|
if resize_box(
|
||||||
bounds.min.x + margin,
|
bounds.min.x + RESIZE_BUTTON_WIDTH,
|
||||||
bounds.max.y - margin,
|
bounds.max.y - RESIZE_BUTTON_WIDTH,
|
||||||
patt_width,
|
patt_width,
|
||||||
margin,
|
RESIZE_BUTTON_WIDTH,
|
||||||
) {
|
) {
|
||||||
if delete_mode {
|
if delete_mode {
|
||||||
rule.resize(Rule::SHRINK_DOWN);
|
rule.resize(Rule::SHRINK_DOWN);
|
||||||
|
@ -324,6 +346,10 @@ fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData], groups: &[Vec<C
|
||||||
rule.resize(Rule::EXTEND_DOWN);
|
rule.resize(Rule::EXTEND_DOWN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (a, b) in overlay_lines {
|
||||||
|
ui.painter().line_segment([a, b], (2., Color32::WHITE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rule_cell_edit_from(
|
fn rule_cell_edit_from(
|
||||||
|
@ -394,10 +420,11 @@ fn rule_cell_edit_to(
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
origin: Pos2,
|
origin: Pos2,
|
||||||
rule: &mut RuleCellTo,
|
rule: &mut RuleCellTo,
|
||||||
x: usize,
|
(x, y): (usize, usize),
|
||||||
y: usize,
|
|
||||||
cells: &[CellData],
|
cells: &[CellData],
|
||||||
groups: &[Vec<Cell>],
|
groups: &[Vec<Cell>],
|
||||||
|
(rule_width, rule_height): (usize, usize),
|
||||||
|
overlay_lines: &mut Vec<(Pos2, Pos2)>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
let rect = Rect::from_min_size(
|
let rect = Rect::from_min_size(
|
||||||
|
@ -420,7 +447,15 @@ fn rule_cell_edit_to(
|
||||||
let group = &groups[*group_id];
|
let group = &groups[*group_id];
|
||||||
draw_group(ui, rect, group, cells);
|
draw_group(ui, rect, group, cells);
|
||||||
}
|
}
|
||||||
RuleCellTo::Copy(_) => todo!(),
|
RuleCellTo::Copy(index) => {
|
||||||
|
let this = rect.center();
|
||||||
|
let x = *index % rule_width;
|
||||||
|
let y = *index / rule_width;
|
||||||
|
let target = origin + Vec2::from((x as f32, y as f32)) * CSIZE
|
||||||
|
- Vec2::X * (CSIZE * (rule_width as f32 + 1.) + RESIZE_BUTTON_WIDTH * 2.)
|
||||||
|
+ Vec2::splat(CSIZE) * 0.5;
|
||||||
|
overlay_lines.push((this, target));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cycle_colors {
|
if cycle_colors {
|
||||||
|
@ -436,7 +471,10 @@ fn rule_cell_edit_to(
|
||||||
*group_id %= groups.len();
|
*group_id %= groups.len();
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
RuleCellTo::Copy(_) => todo!(),
|
RuleCellTo::Copy(index) => {
|
||||||
|
*index = (*index + 1) % (rule_width * rule_height);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,9 +488,11 @@ fn rule_cell_edit_to(
|
||||||
*rule = RuleCellTo::GroupRandom(0);
|
*rule = RuleCellTo::GroupRandom(0);
|
||||||
}
|
}
|
||||||
RuleCellTo::GroupRandom(_) => {
|
RuleCellTo::GroupRandom(_) => {
|
||||||
|
*rule = RuleCellTo::Copy(0);
|
||||||
|
}
|
||||||
|
RuleCellTo::Copy(_) => {
|
||||||
*rule = RuleCellTo::None;
|
*rule = RuleCellTo::None;
|
||||||
}
|
}
|
||||||
RuleCellTo::Copy(_) => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changed
|
changed
|
||||||
|
|
Loading…
Reference in a new issue