Draw the grid and a grain of sand
This commit is contained in:
parent
c27ce7fe80
commit
2323443378
|
@ -1,38 +1,122 @@
|
||||||
use cairo::Context;
|
|
||||||
use glib::Object;
|
use glib::Object;
|
||||||
use gtk::{prelude::*, subclass::prelude::*};
|
use gtk::{prelude::*, subclass::prelude::*};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
const WIDTH: i32 = 600;
|
const WIDTH: usize = 601;
|
||||||
const HEIGHT: i32 = 600;
|
const HEIGHT: usize = 601;
|
||||||
|
const CELL_SIZE: usize = 10;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct SandPrivate;
|
pub struct SandViewPrivate {
|
||||||
|
area: RefCell<SandArea>,
|
||||||
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
impl ObjectSubclass for SandPrivate {
|
impl ObjectSubclass for SandViewPrivate {
|
||||||
const NAME: &'static str = "Sand";
|
const NAME: &'static str = "SandView";
|
||||||
type Type = Sand;
|
type Type = SandView;
|
||||||
type ParentType = gtk::DrawingArea;
|
type ParentType = gtk::DrawingArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl for SandPrivate {}
|
impl ObjectImpl for SandViewPrivate {}
|
||||||
impl WidgetImpl for SandPrivate {}
|
impl WidgetImpl for SandViewPrivate {}
|
||||||
impl DrawingAreaImpl for SandPrivate {}
|
impl DrawingAreaImpl for SandViewPrivate {}
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct Sand(ObjectSubclass<SandPrivate>) @extends gtk::DrawingArea, gtk::Widget;
|
pub struct SandView(ObjectSubclass<SandViewPrivate>) @extends gtk::DrawingArea, gtk::Widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sand {
|
impl Default for SandView {
|
||||||
pub fn new() -> Self {
|
fn default() -> Self {
|
||||||
let s: Self = Object::builder().build();
|
let s: Self = Object::builder().build();
|
||||||
s.set_width_request(WIDTH);
|
s.set_width_request(WIDTH as i32);
|
||||||
s.set_height_request(HEIGHT);
|
s.set_height_request(HEIGHT as i32);
|
||||||
|
|
||||||
|
s.set_draw_func({
|
||||||
|
let s = s.clone();
|
||||||
|
move |_, context, width, height| {
|
||||||
|
println!("{} {}", width, height);
|
||||||
|
context.set_source_rgb(0., 0., 0.);
|
||||||
|
let _ = context.paint();
|
||||||
|
context.set_source_rgb(0.1, 0.1, 0.1);
|
||||||
|
for x in (0..width).step_by(CELL_SIZE) {
|
||||||
|
context.move_to(x as f64, 0.);
|
||||||
|
context.line_to(x as f64, HEIGHT as f64);
|
||||||
|
}
|
||||||
|
for y in (0..height).step_by(CELL_SIZE) {
|
||||||
|
context.move_to(0., y as f64);
|
||||||
|
context.line_to(WIDTH as f64, y as f64);
|
||||||
|
}
|
||||||
|
let _ = context.stroke();
|
||||||
|
|
||||||
|
let area = s.imp().area.borrow();
|
||||||
|
for x in 0..area.width {
|
||||||
|
for y in 0..area.height {
|
||||||
|
if area.grain(x, y) {
|
||||||
|
context.set_source_rgb(0.8, 0.8, 0.8);
|
||||||
|
} else {
|
||||||
|
context.set_source_rgb(0., 0., 0.);
|
||||||
|
}
|
||||||
|
context.rectangle(
|
||||||
|
(x * CELL_SIZE + 1) as f64,
|
||||||
|
(y * CELL_SIZE + 1) as f64,
|
||||||
|
(CELL_SIZE - 2) as f64,
|
||||||
|
(CELL_SIZE - 2) as f64,
|
||||||
|
);
|
||||||
|
let _ = context.fill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SandView {
|
||||||
|
fn set_area(&self, area: SandArea) {
|
||||||
|
*self.imp().area.borrow_mut() = area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct SandArea {
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
grains: Vec<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SandArea {
|
||||||
|
fn default() -> Self {
|
||||||
|
let width = WIDTH / CELL_SIZE;
|
||||||
|
let height = HEIGHT / CELL_SIZE;
|
||||||
|
Self {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
grains: vec![false; width * height],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SandArea {
|
||||||
|
pub fn add_grain(&mut self, x: usize, y: usize) {
|
||||||
|
let addr = self.addr(x, y);
|
||||||
|
self.grains[addr] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grain(&self, x: usize, y: usize) -> bool {
|
||||||
|
self.grains[self.addr(x, y)]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tick(self) -> Self {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addr(&self, x: usize, y: usize) -> usize {
|
||||||
|
y * self.width + x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let app = gtk::Application::builder()
|
let app = gtk::Application::builder()
|
||||||
.application_id("com.luminescent-dreams.falling-sand")
|
.application_id("com.luminescent-dreams.falling-sand")
|
||||||
|
@ -42,9 +126,12 @@ fn main() {
|
||||||
let window = gtk::ApplicationWindow::new(app);
|
let window = gtk::ApplicationWindow::new(app);
|
||||||
window.present();
|
window.present();
|
||||||
|
|
||||||
let sand = Sand::new();
|
let view = SandView::default();
|
||||||
|
let mut sand_area = SandArea::default();
|
||||||
|
sand_area.add_grain(20, 20);
|
||||||
|
view.set_area(sand_area.clone());
|
||||||
|
|
||||||
window.set_child(Some(&sand));
|
window.set_child(Some(&view));
|
||||||
});
|
});
|
||||||
|
|
||||||
app.run();
|
app.run();
|
||||||
|
|
Loading…
Reference in New Issue