Start doing a bare basic rendering of nodes in a game tree

This commit is contained in:
Savanni D'Gerinel 2024-03-31 14:09:48 -04:00
parent 46b25cc6c5
commit b982f2c1cc
2 changed files with 25 additions and 41 deletions

View File

@ -241,7 +241,7 @@ pub struct Tree<T> {
#[derive(Debug)] #[derive(Debug)]
pub struct Node<T> { pub struct Node<T> {
id: usize, pub id: usize,
node: T, node: T,
parent: Option<usize>, parent: Option<usize>,
depth: usize, depth: usize,
@ -355,7 +355,7 @@ impl<T> Tree<T> {
width width
} }
fn bfs_iter<'a>(&'a self) -> BFSIter<T> { pub fn bfs_iter<'a>(&'a self) -> BFSIter<T> {
let mut queue = VecDeque::new(); let mut queue = VecDeque::new();
queue.push_back(&self.nodes[0]); queue.push_back(&self.nodes[0]);
BFSIter { tree: self, queue } BFSIter { tree: self, queue }

View File

@ -66,8 +66,29 @@ impl ReviewTree {
s s
} }
pub fn redraw(&self, _ctx: &Context, _width: i32, _height: i32) { pub fn redraw(&self, ctx: &Context, _width: i32, _height: i32) {
// Implement the tree-drawing algorithm here println!("redraw");
let tree: &Option<Tree<Uuid>> = &self.imp().tree.borrow();
match tree {
Some(ref tree) => {
for node in tree.bfs_iter() {
// draw a circle given the coordinates of the nodes
// I don't know the indent. How do I keep track of that? Do I track the position of
// the parent? do I need to just make it more intrinsically a part of the position
// code?
ctx.set_source_rgb(0.7, 0.7, 0.7);
let (row, column) = tree.position(0, node.id);
println!("[{}] {} x {}", node.id, row, column);
let y = (row as f64) * 20. + 10.;
let x = (column as f64) * 20. + 10.;
ctx.arc(x, y, 5., 0., 2. * std::f64::consts::PI);
let _ = ctx.stroke();
}
}
None => {
// if there is no tree present, then there's nothing to draw!
}
}
} }
} }
@ -110,43 +131,6 @@ struct Tree {
} }
*/ */
// Given a node, do a postorder traversal to figure out the width of the node based on all of its
// children. This is equivalent to the widest of all of its children at all depths.
//
// There are some collapse rules that I could take into account here, but that I haven't figured
// out yet. If two nodes are side by side, and one of them has some wide children but the other has
// no children, then they are effectively the same width. The second node only needs to be moved
// out if it has children that would overlap the children of the first node.
//
// My algorithm right now is likely to generate unnecessarily wide trees in a complex game review.
#[allow(dead_code)]
fn node_width(node: &GameNode) -> usize {
let children: &Vec<GameNode> = match node {
GameNode::MoveNode(mn) => &mn.children,
GameNode::SetupNode(sn) => &sn.children,
};
if children.is_empty() {
return 1;
}
// If there is more than one child, run node_width on each one and add them together.
children
.iter()
.fold(0, |acc, child| acc + node_width(child))
}
// Since I know the width of a node, now I want to figure out its placement in the larger scheme of
// things.
//
// One thought I have is that I could just develop a grid virtually and start placing nodes.
// Whenever I notice a collision, I can just move the node over. But I'd like to see if I can be a
// bit smarter than doing it as just a vec into which I place things, as though it's a game board.
// So, given a game node, I want to figure out it's position along the X axis.
//
// Just having the node is greatly insufficient. I can get better results if I'm calculating the
// position of its children.
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;