Compare commits
2 Commits
master
...
controller
| Author | SHA1 | Date | |
|---|---|---|---|
| e9bd89c8a5 | |||
| 9c55f69a91 |
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "gamenite"
|
name = "gamenite"
|
||||||
description = "A graph library for board games"
|
description = "A graph library for board games"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
homepage = "https://git.danejohnson.org/dane/gamenite"
|
homepage = "https://git.danejohnson.org/dane/gamenite"
|
||||||
|
|||||||
@@ -102,10 +102,8 @@ impl eframe::App for BoardBuilderApp {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
CentralPanel::default().show(ctx, |ui| {
|
CentralPanel::default().show(ctx, |ui| {
|
||||||
ScrollArea::both().show(ui, |ui| {
|
|
||||||
if let Some(texture) = self.texture.as_ref() {
|
if let Some(texture) = self.texture.as_ref() {
|
||||||
let raw_image = self.image.as_ref().expect("Texture without an image");
|
let size = ui.available_size();
|
||||||
let size = Vec2::new(raw_image.width() as f32, raw_image.height() as f32);
|
|
||||||
let (response, painter) = ui.allocate_painter(size, Sense::click());
|
let (response, painter) = ui.allocate_painter(size, Sense::click());
|
||||||
let image = widgets::Image::new(texture, size);
|
let image = widgets::Image::new(texture, size);
|
||||||
image.paint_at(ui, response.rect);
|
image.paint_at(ui, response.rect);
|
||||||
@@ -123,7 +121,6 @@ impl eframe::App for BoardBuilderApp {
|
|||||||
self.dispatch_click(btn, x, y);
|
self.dispatch_click(btn, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
self.create_node_dialog.ui(ctx);
|
self.create_node_dialog.ui(ctx);
|
||||||
@@ -143,7 +140,6 @@ impl BoardBuilderApp {
|
|||||||
|
|
||||||
BoardBuilderApp::default()
|
BoardBuilderApp::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_image_file(&mut self, ctx: &Context, image_file: &Path) -> Result<(), image::ImageError> {
|
fn load_image_file(&mut self, ctx: &Context, image_file: &Path) -> Result<(), image::ImageError> {
|
||||||
let image = image::io::Reader::open(image_file)?.decode()?;
|
let image = image::io::Reader::open(image_file)?.decode()?;
|
||||||
self.load_image(ctx, image);
|
self.load_image(ctx, image);
|
||||||
|
|||||||
99
src/controller.rs
Normal file
99
src/controller.rs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
use std::sync::mpsc;
|
||||||
|
use mpsc::{ Sender, Receiver, SendError, RecvError };
|
||||||
|
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
pub struct Controller<M> {
|
||||||
|
server: Option<Server<M>>,
|
||||||
|
clients: VecDeque<Client<M>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Server<M> {
|
||||||
|
txs: Vec<Sender<M>>,
|
||||||
|
rxs: Vec<Receiver<M>>,
|
||||||
|
info: Receiver<(usize, M)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Client<M> {
|
||||||
|
pub idx: usize,
|
||||||
|
tx: Sender<M>,
|
||||||
|
rx: Receiver<M>,
|
||||||
|
info: Sender<(usize, M)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M> Controller<M> {
|
||||||
|
pub fn new(n: usize) -> Self {
|
||||||
|
let (info_tx, info_rx) = mpsc::channel::<(usize, M)>();
|
||||||
|
let mut c = Controller {
|
||||||
|
server: Some(Server {
|
||||||
|
txs: Vec::new(),
|
||||||
|
rxs: Vec::new(),
|
||||||
|
info: info_rx,
|
||||||
|
}),
|
||||||
|
clients: VecDeque::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for idx in 0..n {
|
||||||
|
let (server_tx, client_rx) = mpsc::channel();
|
||||||
|
let (client_tx, server_rx) = mpsc::channel();
|
||||||
|
match c.server.as_mut() {
|
||||||
|
Some(s) => {
|
||||||
|
s.txs.push(server_tx);
|
||||||
|
s.rxs.push(server_rx);
|
||||||
|
},
|
||||||
|
None => unreachable!(),
|
||||||
|
}
|
||||||
|
c.clients.push_back(Client {
|
||||||
|
idx,
|
||||||
|
tx: client_tx,
|
||||||
|
rx: client_rx,
|
||||||
|
info: info_tx.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn server(&mut self) -> Option<Server<M>> {
|
||||||
|
self.server.take()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn client(&mut self) -> Option<Client<M>> {
|
||||||
|
self.clients.pop_front()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M> Server<M> {
|
||||||
|
pub fn send(&self, idx: usize, msg: M) -> Result<(), SendError<M>> {
|
||||||
|
self.txs[idx].send(msg)
|
||||||
|
}
|
||||||
|
pub fn recv(&self, idx: usize) -> Result<M, RecvError> {
|
||||||
|
self.rxs[idx].recv()
|
||||||
|
}
|
||||||
|
pub fn info(&self) -> Result<(usize, M), RecvError> {
|
||||||
|
self.info.recv()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <M> Server<M>
|
||||||
|
where M: Clone {
|
||||||
|
pub fn broadcast(&self, msg: M) -> Result<(), SendError<M>> {
|
||||||
|
for tx in &self.txs {
|
||||||
|
tx.send(M::clone(&msg))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M> Client<M> {
|
||||||
|
pub fn send(&self, m: M) -> Result<(), SendError<M>> {
|
||||||
|
self.tx.send(m)
|
||||||
|
}
|
||||||
|
pub fn recv(&self) -> Result<M, RecvError> {
|
||||||
|
self.rx.recv()
|
||||||
|
}
|
||||||
|
pub fn info(&self, msg: M) -> Result<(), SendError<(usize, M)>> {
|
||||||
|
self.info.send((self.idx, msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
//! Finally, we provide an [io] package to facilitate loading and saving these boards, and a related image to
|
//! Finally, we provide an [io] package to facilitate loading and saving these boards, and a related image to
|
||||||
//! a compressed file.
|
//! a compressed file.
|
||||||
pub mod io;
|
pub mod io;
|
||||||
|
pub mod controller;
|
||||||
|
|
||||||
use serde::{ Serialize, Deserialize };
|
use serde::{ Serialize, Deserialize };
|
||||||
use std::collections::{ HashMap, HashSet };
|
use std::collections::{ HashMap, HashSet };
|
||||||
|
|||||||
Reference in New Issue
Block a user