Compare commits
3 commits
e066025836
...
bb8b272ed4
Author | SHA1 | Date | |
---|---|---|---|
bb8b272ed4 | |||
84e64fe719 | |||
970eb402a2 |
2 changed files with 267 additions and 145 deletions
370
petri/src/lib.rs
370
petri/src/lib.rs
|
@ -18,12 +18,61 @@ pub struct Chunk {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Rule {
|
pub struct Rule {
|
||||||
pub from: RulePattern,
|
base: SubRule,
|
||||||
pub to: RulePattern,
|
variants: Vec<SubRule>,
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
// probability: u8
|
// probability: u8
|
||||||
// flip:
|
pub flip_h: bool,
|
||||||
// rotate:
|
pub flip_v: bool,
|
||||||
|
pub rotate: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
struct SubRule {
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
contents: Vec<(Option<Cell>, Option<Cell>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubRule {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
width: 1,
|
||||||
|
height: 1,
|
||||||
|
contents: vec![(None, None)],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self, x: usize, y: usize) -> (Option<Cell>, Option<Cell>) {
|
||||||
|
if x >= self.width || y >= self.height {
|
||||||
|
(None, None)
|
||||||
|
} else {
|
||||||
|
self.contents[x + self.width * y].clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mut(&mut self, x: usize, y: usize) -> &mut (Option<Cell>, Option<Cell>) {
|
||||||
|
assert!(x < self.width || y < self.height);
|
||||||
|
&mut self.contents[x + self.width * y]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_both(&mut self, x: usize, y: usize, cells: (Option<Cell>, Option<Cell>)) {
|
||||||
|
if x < self.width && y < self.height {
|
||||||
|
self.contents[x + self.width * y] = cells;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_from(&mut self, x: usize, y: usize, cell: Option<Cell>) {
|
||||||
|
if x < self.width && y < self.height {
|
||||||
|
self.contents[x + self.width * y].0 = cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_to(&mut self, x: usize, y: usize, cell: Option<Cell>) {
|
||||||
|
if x < self.width && y < self.height {
|
||||||
|
self.contents[x + self.width * y].1 = cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResizeParam = (isize, isize, isize, isize);
|
type ResizeParam = (isize, isize, isize, isize);
|
||||||
|
@ -40,22 +89,136 @@ impl Rule {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
from: RulePattern::new(),
|
base: SubRule::new(),
|
||||||
to: RulePattern::new(),
|
variants: Vec::new(),
|
||||||
|
flip_h: false,
|
||||||
|
flip_v: false,
|
||||||
|
rotate: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, x: usize, y: usize) -> (Option<Cell>, Option<Cell>) {
|
||||||
|
self.base.get(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut(&mut self, x: usize, y: usize) -> &mut (Option<Cell>, Option<Cell>) {
|
||||||
|
self.base.get_mut(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_from(&mut self, x: usize, y: usize, cell: Option<Cell>) {
|
||||||
|
self.base.set_from(x, y, cell);
|
||||||
|
self.generate_variants();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_to(&mut self, x: usize, y: usize, cell: Option<Cell>) {
|
||||||
|
self.base.set_to(x, y, cell);
|
||||||
|
self.generate_variants();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn height(&self) -> usize {
|
||||||
|
self.base.height
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn width(&self) -> usize {
|
||||||
|
self.base.width
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, params: ResizeParam) {
|
pub fn resize(&mut self, params: ResizeParam) {
|
||||||
let (dw, dh, dx, dy) = params;
|
let (dw, dh, dx, dy) = params;
|
||||||
self.from.resize(dw, dh, dx, dy);
|
|
||||||
self.to.resize(dw, dh, dx, dy);
|
let new_width = self.base.width.saturating_add_signed(dw);
|
||||||
|
let new_height = self.base.height.saturating_add_signed(dh);
|
||||||
|
if new_width < 1 || new_height < 1 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut new_contents = vec![(None, None); new_width * new_height];
|
||||||
|
|
||||||
|
for nx in 0..new_width {
|
||||||
|
let oldx = nx.wrapping_add_signed(dx);
|
||||||
|
for ny in 0..new_height {
|
||||||
|
let oldy = ny.wrapping_add_signed(dy);
|
||||||
|
new_contents[nx + new_width * ny] = self.get(oldx, oldy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.base.contents = new_contents;
|
||||||
|
self.base.height = new_height;
|
||||||
|
self.base.width = new_width;
|
||||||
|
self.generate_variants();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_variants(&mut self) {
|
||||||
|
self.variants.clear();
|
||||||
|
self.variants.push(self.base.clone());
|
||||||
|
|
||||||
|
fn transform_variants(variants: &mut Vec<SubRule>, f: fn(&SubRule) -> SubRule) {
|
||||||
|
let mut new = Vec::new();
|
||||||
|
for v in variants.iter() {
|
||||||
|
let new_variant = f(v);
|
||||||
|
if !variants.contains(&new_variant) {
|
||||||
|
new.push(new_variant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
variants.extend_from_slice(&new);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.flip_h {
|
||||||
|
transform_variants(&mut self.variants, |b| {
|
||||||
|
let mut new = b.clone();
|
||||||
|
for y in 0..new.height {
|
||||||
|
for x in 0..new.width {
|
||||||
|
let old = b.get(new.width - x - 1, y);
|
||||||
|
new.set_both(x, y, old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if self.flip_v {
|
||||||
|
transform_variants(&mut self.variants, |b| {
|
||||||
|
let mut new = b.clone();
|
||||||
|
for y in 0..new.height {
|
||||||
|
for x in 0..new.width {
|
||||||
|
let old = b.get(x, new.height - y - 1);
|
||||||
|
new.set_both(x, y, old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if self.rotate {
|
||||||
|
// 180° rotations (same as flipping x and y)
|
||||||
|
transform_variants(&mut self.variants, |b| {
|
||||||
|
let mut new = b.clone();
|
||||||
|
for y in 0..new.height {
|
||||||
|
for x in 0..new.width {
|
||||||
|
let old = b.get(new.width - x - 1, new.height - y - 1);
|
||||||
|
new.set_both(x, y, old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new
|
||||||
|
});
|
||||||
|
// 90° rotations
|
||||||
|
transform_variants(&mut self.variants, |b| {
|
||||||
|
let mut new = b.clone();
|
||||||
|
new.height = b.width;
|
||||||
|
new.width = b.height;
|
||||||
|
for y in 0..new.height {
|
||||||
|
for x in 0..new.width {
|
||||||
|
let old = b.get(y, x);
|
||||||
|
new.set_both(x, y, old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Chunk {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
contents: vec![[Cell::EMPTY; CHUNK_SIZE]; CHUNK_SIZE]
|
contents: vec![[Cell(0); CHUNK_SIZE]; CHUNK_SIZE]
|
||||||
.into_boxed_slice()
|
.into_boxed_slice()
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
@ -84,50 +247,43 @@ impl Chunk {
|
||||||
|
|
||||||
impl Dish {
|
impl Dish {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
let mut default_rules = vec![
|
||||||
|
Rule {
|
||||||
|
enabled: true,
|
||||||
|
base: SubRule {
|
||||||
|
width: 1,
|
||||||
|
height: 2,
|
||||||
|
contents: vec![
|
||||||
|
(Some(Cell(1)), Some(Cell(0))),
|
||||||
|
(Some(Cell(0)), Some(Cell(1))),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
..Rule::new()
|
||||||
|
},
|
||||||
|
Rule {
|
||||||
|
enabled: true,
|
||||||
|
base: SubRule {
|
||||||
|
width: 2,
|
||||||
|
height: 2,
|
||||||
|
contents: vec![
|
||||||
|
(Some(Cell(1)), Some(Cell(0))),
|
||||||
|
(None, None),
|
||||||
|
(Some(Cell(1)), None),
|
||||||
|
(Some(Cell(0)), Some(Cell(1))),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
flip_h: true,
|
||||||
|
..Rule::new()
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for rule in &mut default_rules {
|
||||||
|
rule.generate_variants()
|
||||||
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
chunk: Chunk::new().fill_random(),
|
chunk: Chunk::new().fill_random(),
|
||||||
|
rules: default_rules,
|
||||||
rules: vec![
|
|
||||||
Rule {
|
|
||||||
enabled: true,
|
|
||||||
from: RulePattern {
|
|
||||||
width: 1,
|
|
||||||
height: 2,
|
|
||||||
contents: vec![Some(Cell(1)), Some(Cell(0))],
|
|
||||||
},
|
|
||||||
to: RulePattern {
|
|
||||||
width: 1,
|
|
||||||
height: 2,
|
|
||||||
contents: vec![Some(Cell(0)), Some(Cell(1))],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Rule {
|
|
||||||
enabled: true,
|
|
||||||
from: RulePattern {
|
|
||||||
width: 2,
|
|
||||||
height: 2,
|
|
||||||
contents: vec![Some(Cell(1)), None, Some(Cell(1)), Some(Cell(0))],
|
|
||||||
},
|
|
||||||
to: RulePattern {
|
|
||||||
width: 2,
|
|
||||||
height: 2,
|
|
||||||
contents: vec![Some(Cell(0)), None, Some(Cell(1)), Some(Cell(1))],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Rule {
|
|
||||||
enabled: true,
|
|
||||||
from: RulePattern {
|
|
||||||
width: 2,
|
|
||||||
height: 2,
|
|
||||||
contents: vec![None, Some(Cell(1)), Some(Cell(0)), Some(Cell(1))],
|
|
||||||
},
|
|
||||||
to: RulePattern {
|
|
||||||
width: 2,
|
|
||||||
height: 2,
|
|
||||||
contents: vec![None, Some(Cell(0)), Some(Cell(1)), Some(Cell(1))],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,31 +309,48 @@ impl Dish {
|
||||||
|
|
||||||
fn fire_rule(&mut self, rule_index: usize, x: usize, y: usize) {
|
fn fire_rule(&mut self, rule_index: usize, x: usize, y: usize) {
|
||||||
let rule = &self.rules[rule_index];
|
let rule = &self.rules[rule_index];
|
||||||
let width = rule.to.width;
|
// find matching variants
|
||||||
let height = rule.to.height;
|
let mut matching_variants = Vec::new();
|
||||||
// check is match
|
for (i, v) in rule.variants.iter().enumerate() {
|
||||||
for dx in 0..width {
|
if self.subrule_matches(x, y, v) {
|
||||||
for dy in 0..height {
|
matching_variants.push(i);
|
||||||
let x = x + dx;
|
|
||||||
let y = y + dy;
|
|
||||||
if let Some(rule_cell) = rule.from.get(dx, dy) {
|
|
||||||
if self.get_cell(x, y) != Some(rule_cell) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if matching_variants.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let variant_index = random::<usize>() % matching_variants.len();
|
||||||
|
let variant = rule.variants[matching_variants[variant_index]].clone();
|
||||||
|
|
||||||
|
let width = variant.width;
|
||||||
|
let height = variant.height;
|
||||||
for dx in 0..width {
|
for dx in 0..width {
|
||||||
for dy in 0..height {
|
for dy in 0..height {
|
||||||
let x = x + dx;
|
let x = x + dx;
|
||||||
let y = y + dy;
|
let y = y + dy;
|
||||||
if let Some(rule_cell) = &self.rules[rule_index].to.get(dx, dy) {
|
if let Some(rule_cell) = variant.get(dx, dy).1 {
|
||||||
self.set_cell(x, y, rule_cell.clone());
|
self.set_cell(x, y, rule_cell.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn subrule_matches(&self, x: usize, y: usize, subrule: &SubRule) -> bool {
|
||||||
|
for dx in 0..subrule.width {
|
||||||
|
for dy in 0..subrule.height {
|
||||||
|
let x = x + dx;
|
||||||
|
let y = y + dy;
|
||||||
|
if let Some(rule_cell) = subrule.get(dx, dy).0 {
|
||||||
|
if self.get_cell(x, y) != Some(rule_cell) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
//todo isize
|
//todo isize
|
||||||
pub fn get_cell(&self, x: usize, y: usize) -> Option<Cell> {
|
pub fn get_cell(&self, x: usize, y: usize) -> Option<Cell> {
|
||||||
if x >= CHUNK_SIZE || y >= CHUNK_SIZE {
|
if x >= CHUNK_SIZE || y >= CHUNK_SIZE {
|
||||||
|
@ -196,76 +369,7 @@ impl Dish {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct RulePattern {
|
|
||||||
width: usize,
|
|
||||||
height: usize,
|
|
||||||
contents: Vec<Option<Cell>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RulePattern {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
width: 1,
|
|
||||||
height: 1,
|
|
||||||
contents: vec![None],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(&self, x: usize, y: usize) -> Option<Cell> {
|
|
||||||
if x >= self.width || y >= self.height {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
self.contents[x + self.width * y].clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut Cell> {
|
|
||||||
if x >= self.width || y >= self.height {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
self.contents[x + self.width * y].as_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(&mut self, x: usize, y: usize, cell: Option<Cell>) {
|
|
||||||
if x < self.width && y < self.height {
|
|
||||||
self.contents[x + self.width * y] = cell
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn height(&self) -> usize {
|
|
||||||
self.height
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn width(&self) -> usize {
|
|
||||||
self.width
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resize(&mut self, dw: isize, dh: isize, dx: isize, dy: isize) {
|
|
||||||
let new_width = self.width.saturating_add_signed(dw);
|
|
||||||
let new_height = self.height.saturating_add_signed(dh);
|
|
||||||
if new_width < 1 || new_height < 1 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut new_contents = vec![None; new_width * new_height];
|
|
||||||
|
|
||||||
for nx in 0..new_width {
|
|
||||||
let oldx = nx.wrapping_add_signed(dx);
|
|
||||||
for ny in 0..new_height {
|
|
||||||
let oldy = ny.wrapping_add_signed(dy);
|
|
||||||
new_contents[nx + new_width * ny] = self.get(oldx, oldy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.contents = new_contents;
|
|
||||||
self.height = new_height;
|
|
||||||
self.width = new_width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Cell {
|
impl Cell {
|
||||||
pub const EMPTY: Self = Cell(0);
|
|
||||||
pub fn id(&self) -> usize {
|
pub fn id(&self) -> usize {
|
||||||
self.0 as usize
|
self.0 as usize
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use eframe::{
|
||||||
epaint::Hsva,
|
epaint::Hsva,
|
||||||
NativeOptions,
|
NativeOptions,
|
||||||
};
|
};
|
||||||
use petri::{Cell, Chunk, Dish, Rule, RulePattern, CHUNK_SIZE};
|
use petri::{Cell, Chunk, Dish, Rule, CHUNK_SIZE};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -122,12 +122,21 @@ fn paint_chunk(painter: Painter, chunk: &Chunk, cells: &[CellData]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSIZE: f32 = 24.;
|
const CSIZE: f32 = 24.;
|
||||||
const OUTLINE: (f32, Color32) = (3., Color32::GRAY);
|
const OUTLINE: (f32, Color32) = (2., Color32::GRAY);
|
||||||
fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData]) {
|
fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData]) {
|
||||||
ui.checkbox(&mut rule.enabled, "enable rule");
|
ui.checkbox(&mut rule.enabled, "enable rule");
|
||||||
|
if ui.checkbox(&mut rule.flip_h, "flip H").changed() {
|
||||||
|
rule.generate_variants();
|
||||||
|
}
|
||||||
|
if ui.checkbox(&mut rule.flip_v, "flip V").changed() {
|
||||||
|
rule.generate_variants();
|
||||||
|
}
|
||||||
|
if ui.checkbox(&mut rule.rotate, "rotate").changed() {
|
||||||
|
rule.generate_variants();
|
||||||
|
}
|
||||||
|
|
||||||
let cells_y = rule.from.height();
|
let cells_y = rule.height();
|
||||||
let cells_x = rule.from.width();
|
let cells_x = rule.width();
|
||||||
let margin = 8.;
|
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;
|
||||||
|
@ -148,8 +157,12 @@ fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData]) {
|
||||||
|
|
||||||
for x in 0..cells_x {
|
for x in 0..cells_x {
|
||||||
for y in 0..cells_y {
|
for y in 0..cells_y {
|
||||||
rule_cell_edit(ui, from_cells_rect.min, &mut rule.from, x, y, cells);
|
let (left, right) = rule.get_mut(x, y);
|
||||||
rule_cell_edit(ui, to_cells_rect.min, &mut rule.to, x, y, cells);
|
let changed_left = rule_cell_edit(ui, from_cells_rect.min, left, x, y, cells);
|
||||||
|
let changed_right = rule_cell_edit(ui, to_cells_rect.min, right, x, y, cells);
|
||||||
|
if changed_left || changed_right {
|
||||||
|
rule.generate_variants();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,28 +231,33 @@ fn rule_editor(ui: &mut Ui, rule: &mut Rule, cells: &[CellData]) {
|
||||||
fn rule_cell_edit(
|
fn rule_cell_edit(
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
origin: Pos2,
|
origin: Pos2,
|
||||||
rule: &mut RulePattern,
|
rule: &mut Option<Cell>,
|
||||||
x: usize,
|
x: usize,
|
||||||
y: usize,
|
y: usize,
|
||||||
cells: &[CellData],
|
cells: &[CellData],
|
||||||
) {
|
) -> bool {
|
||||||
|
let mut changed = false;
|
||||||
let rect = Rect::from_min_size(
|
let rect = Rect::from_min_size(
|
||||||
origin + Vec2::from((x as f32, y as f32)) * CSIZE,
|
origin + Vec2::from((x as f32, y as f32)) * CSIZE,
|
||||||
Vec2::splat(CSIZE),
|
Vec2::splat(CSIZE),
|
||||||
);
|
);
|
||||||
let aabb = ui.allocate_rect(rect, Sense::click());
|
let aabb = ui.allocate_rect(rect, Sense::click());
|
||||||
if let Some(cell) = rule.get_mut(x, y) {
|
if let Some(cell) = rule {
|
||||||
let color = cells[cell.id()].color;
|
let color = cells[cell.id()].color;
|
||||||
ui.painter().rect(rect, 2., color, OUTLINE);
|
ui.painter()
|
||||||
|
.rect(rect.shrink(OUTLINE.0 / 2.), 0., color, OUTLINE);
|
||||||
if aabb.clicked() {
|
if aabb.clicked() {
|
||||||
|
changed = true;
|
||||||
cell.0 += 1;
|
cell.0 += 1;
|
||||||
if cell.0 as usize == cells.len() {
|
if cell.0 as usize == cells.len() {
|
||||||
rule.set(x, y, None);
|
*rule = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if aabb.clicked() {
|
} else if aabb.clicked() {
|
||||||
rule.set(x, y, Some(Cell(0)));
|
*rule = Some(Cell(0));
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
|
changed
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CellData {
|
impl CellData {
|
||||||
|
|
Loading…
Reference in a new issue