diff --git a/flake.lock b/flake.lock index fad6c0a..5c66945 100644 --- a/flake.lock +++ b/flake.lock @@ -17,11 +17,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1678972866, - "narHash": "sha256-YV8BcNWfNVgS449B6hFYFUg4kwVIQMNehZP+FNDs1LY=", + "lastModified": 1680122840, + "narHash": "sha256-zCQ/9iFHzCW5JMYkkHMwgK1/1/kTMgCMHq4THPINpAU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "cd34d6ed7ba7d5c4e44b04a53dc97edb52f2766c", + "rev": "a575c243c23e2851b78c00e9fa245232926ec32f", "type": "github" }, "original": { @@ -52,7 +52,7 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "narHash": "sha256-03Opt2yu4E/AIFjvlgib0/nhMn6B4B/t/nvwS2bzOGw=", + "narHash": "sha256-o28gi3WKSsVeXg3wDSR2kGpawrDO5lzGG4eUsLTPglw=", "type": "tarball", "url": "https://github.com/oxalica/rust-overlay/archive/master.tar.gz" }, @@ -70,11 +70,11 @@ }, "unstable": { "locked": { - "lastModified": 1678898370, - "narHash": "sha256-xTICr1j+uat5hk9FyuPOFGxpWHdJRibwZC+ATi0RbtE=", + "lastModified": 1680125544, + "narHash": "sha256-mlqo1r+TZUOuypWdrZHluxWL+E5WzXlUXNZ9Y0WLDFU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ac718d02867a84b42522a0ece52d841188208f2c", + "rev": "9a6aabc4740790ef3bbb246b86d029ccf6759658", "type": "github" }, "original": { diff --git a/kifu/kifu-core/src/types.rs b/kifu/kifu-core/src/types.rs index 5c8e959..e37992a 100644 --- a/kifu/kifu-core/src/types.rs +++ b/kifu/kifu-core/src/types.rs @@ -1,12 +1,12 @@ use std::time::Duration; -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub enum Color { Black, White, } -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct Size { pub width: u8, pub height: u8, diff --git a/kifu/kifu-gtk/src/ui/goban.rs b/kifu/kifu-gtk/src/ui/goban.rs index de38732..2da7cb3 100644 --- a/kifu/kifu-gtk/src/ui/goban.rs +++ b/kifu/kifu-gtk/src/ui/goban.rs @@ -6,11 +6,18 @@ use std::{cell::RefCell, rc::Rc}; const WIDTH: i32 = 800; const HEIGHT: i32 = 800; -#[derive(Default)] +#[derive(Clone, Default, PartialEq)] +struct Addr { + row: u8, + column: u8, +} + pub struct GobanPrivate { drawing_area: gtk::DrawingArea, + current_player: Rc>, goban: Rc>, + cursor_location: Rc>, } #[glib::object_subclass] @@ -18,6 +25,15 @@ impl ObjectSubclass for GobanPrivate { const NAME: &'static str = "Goban"; type Type = Goban; type ParentType = gtk::Grid; + + fn new() -> GobanPrivate { + GobanPrivate { + drawing_area: Default::default(), + current_player: Rc::new(RefCell::new(Color::Black)), + goban: Default::default(), + cursor_location: Default::default(), + } + } } impl ObjectImpl for GobanPrivate { @@ -26,6 +42,8 @@ impl ObjectImpl for GobanPrivate { self.drawing_area.set_height_request(HEIGHT); let goban = self.goban.clone(); + let cursor_location = self.cursor_location.clone(); + let current_player = self.current_player.clone(); self.drawing_area .set_draw_func(move |_, context, width, height| { let goban = goban.borrow(); @@ -72,7 +90,36 @@ impl ObjectImpl for GobanPrivate { }; }) }); + + let cursor = cursor_location.borrow(); + pen.ghost_stone(context, cursor.row, cursor.column, *current_player.borrow()); }); + + let motion_controller = gtk::EventControllerMotion::new(); + { + let goban = self.goban.clone(); + let cursor = self.cursor_location.clone(); + let drawing_area = self.drawing_area.clone(); + motion_controller.connect_motion(move |_, x, y| { + let goban = goban.borrow(); + let mut cursor = cursor.borrow_mut(); + let hspace_between = ((WIDTH - 40) as f64) / ((goban.size.width - 1) as f64); + let vspace_between = ((HEIGHT - 40) as f64) / ((goban.size.height - 1) as f64); + + let addr = Addr { + column: ((x.round() - 20.) / hspace_between).round() as u8, + row: ((y.round() - 20.) / vspace_between).round() as u8, + }; + + if *cursor != addr { + println!("redrawing with cursor at {} {}", addr.row, addr.column); + *cursor = addr; + drawing_area.queue_draw(); + } + }); + } + + self.drawing_area.add_controller(motion_controller); } } impl WidgetImpl for GobanPrivate {} @@ -93,6 +140,10 @@ impl Goban { *self.imp().goban.borrow_mut() = goban; self.imp().drawing_area.queue_draw(); } + + pub fn set_current_player(&self, color: Color) { + *self.imp().current_player.borrow_mut() = color; + } } struct Pen { @@ -128,4 +179,19 @@ impl Pen { ); let _ = context.fill(); } + + fn ghost_stone(&self, context: &cairo::Context, row: u8, col: u8, color: Color) { + match color { + Color::White => context.set_source_rgba(0.9, 0.9, 0.9, 0.5), + Color::Black => context.set_source_rgba(0.0, 0.0, 0.0, 0.5), + }; + context.arc( + 20.0 + (col as f64) * self.hspace_between, + 20.0 + (row as f64) * self.vspace_between, + 25.0, + 0.0, + 2.0 * std::f64::consts::PI, + ); + let _ = context.fill(); + } } diff --git a/kifu/kifu-gtk/src/ui/playing_field.rs b/kifu/kifu-gtk/src/ui/playing_field.rs index 15236a0..7ca1589 100644 --- a/kifu/kifu-gtk/src/ui/playing_field.rs +++ b/kifu/kifu-gtk/src/ui/playing_field.rs @@ -82,6 +82,7 @@ impl PlayingField { *s.imp().player_card_white.borrow_mut() = Some(player_card_white); *s.imp().player_card_black.borrow_mut() = Some(player_card_black); *s.imp().chat.borrow_mut() = Some(chat); + s.imp().goban.set_current_player(view.current_player); s }