aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/book-export/src/diagram_svg.rs2
-rw-r--r--server/data/src/book/diagram_layout.rs107
-rw-r--r--server/tools/src/diagram_dot.rs5
3 files changed, 61 insertions, 53 deletions
diff --git a/server/book-export/src/diagram_svg.rs b/server/book-export/src/diagram_svg.rs
index d006ce78..a9a2c0a6 100644
--- a/server/book-export/src/diagram_svg.rs
+++ b/server/book-export/src/diagram_svg.rs
@@ -106,7 +106,7 @@ fn node_edge_connect_pos(src: &DiagramNode, dst: &DiagramNode) -> Vec2 {
) {
src.position + dir * HSIZE // circle
} else {
- src.position + dir / dir.y.abs() * HSIZE // square (only +Y and -Y sides)
+ src.position + dir / dir.y.abs().max(dir.x.abs()) * HSIZE // square (only +Y and -Y sides)
}
}
diff --git a/server/data/src/book/diagram_layout.rs b/server/data/src/book/diagram_layout.rs
index 29240b69..cd929f44 100644
--- a/server/data/src/book/diagram_layout.rs
+++ b/server/data/src/book/diagram_layout.rs
@@ -16,15 +16,12 @@
*/
-use anyhow::{Result, anyhow};
-use hurrycurry_protocol::{book::Diagram, glam::Vec2};
-use serde::Deserialize;
-use std::{
- collections::BTreeMap,
- fmt::Write as W2,
- io::Write,
- process::{Command, Stdio},
+use anyhow::Result;
+use hurrycurry_protocol::{
+ book::Diagram,
+ glam::{Vec2, vec2},
};
+use std::collections::{BTreeMap, BTreeSet};
pub struct Layout {
pub nodes: BTreeMap<String, Vec2>,
@@ -32,52 +29,62 @@ pub struct Layout {
}
pub fn diagram_layout(diagram: &mut Diagram) -> Result<()> {
- // seems to have problems with a single node
- if diagram.nodes.len() < 2 {
- return Ok(());
- }
+ let mut graph = Graph {
+ vertices: (0..diagram.nodes.len())
+ .map(|i| vec2(i as f32, i as f32) * 30.)
+ .collect(),
+ edges: diagram.edges.iter().map(|e| (e.src, e.dst)).collect(),
+ };
- let mut child = Command::new("dot")
- .arg("-Tjson")
- .arg("-Kdot")
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .spawn()?;
+ graph.layout();
- let mut out = String::new();
- writeln!(out, "digraph {{")?;
- for (i, _) in diagram.nodes.iter().enumerate() {
- writeln!(out, "k{i} [width=1, height=1]")?;
- }
- for edge in &diagram.edges {
- writeln!(out, "k{} -> k{}", edge.src, edge.dst)?;
- }
- writeln!(out, "}}")?;
+ diagram
+ .nodes
+ .iter_mut()
+ .zip(graph.vertices.iter())
+ .for_each(|(n, v)| n.position = *v);
- child.stdin.as_mut().unwrap().write_all(out.as_bytes())?;
- let output = child.wait_with_output()?;
+ Ok(())
+}
- #[derive(Deserialize)]
- struct Out {
- objects: Vec<Object>,
- }
- #[derive(Deserialize)]
- struct Object {
- name: String,
- pos: String,
- }
- let graph: Out = serde_json::from_slice(&output.stdout)?;
- for o in graph.objects {
- let pos = o.pos.split_once(",").ok_or(anyhow!("malformed position"))?;
- let pos = Vec2::new(pos.0.parse()?, pos.1.parse()?);
+pub struct Graph {
+ pub vertices: Vec<Vec2>,
+ pub edges: Vec<(usize, usize)>,
+}
+impl Graph {
+ pub fn layout(&mut self) {
+ let mut layers = Vec::new();
+ let mut previous_layers = BTreeSet::new();
- let index = o
- .name
- .strip_prefix("k")
- .ok_or(anyhow!("invalid node name"))?
- .parse::<usize>()?;
- diagram.nodes[index].position = pos
- }
+ let mut to_insert = Vec::new();
+ to_insert.extend(0..self.vertices.len());
- Ok(())
+ while !to_insert.is_empty() {
+ let mut next_layer = Vec::new();
+ to_insert.retain(|&vi| {
+ for &(src, dst) in &self.edges {
+ if src == vi && !previous_layers.contains(&dst) {
+ return true;
+ }
+ }
+ next_layer.push(vi);
+ false
+ });
+ previous_layers.extend(next_layer.iter().copied());
+ layers.push(next_layer);
+ }
+
+ for y in 0..layers.iter().len() {
+ let mut layer = layers[y].clone();
+ layer.sort_by_cached_key(|&vi| {
+ self.edges
+ .iter()
+ .find(|&&(src, _)| src == vi)
+ .map_or(0, |&(_, dst)| (self.vertices[dst].x * 100.) as i64)
+ });
+ for (x, &vi) in layer.iter().enumerate() {
+ self.vertices[vi] = vec2(x as f32 - layer.len() as f32 / 2., y as f32) * 100.;
+ }
+ }
+ }
}
diff --git a/server/tools/src/diagram_dot.rs b/server/tools/src/diagram_dot.rs
index 307fa470..33b1a1fb 100644
--- a/server/tools/src/diagram_dot.rs
+++ b/server/tools/src/diagram_dot.rs
@@ -31,6 +31,7 @@ pub fn diagram_dot_svg(data: &Gamedata, diagram: &Diagram) -> Result<String> {
let mut child = Command::new("dot")
.arg("-Tsvg")
.arg("-Knop2")
+ .current_dir("target/book")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
@@ -59,7 +60,7 @@ pub fn diagram_dot(data: &Gamedata, diagram: &Diagram, use_position: bool) -> Re
}
Message::Item(item_index) => {
attrs.push(format!(
- "image=\"/tmp/items/{}.png\"",
+ "image=\"items/{}.png\"",
data.item_name(*item_index)
));
attrs.push("imagescale=true".to_owned());
@@ -70,7 +71,7 @@ pub fn diagram_dot(data: &Gamedata, diagram: &Diagram, use_position: bool) -> Re
}
Message::Tile(tile_index) => {
attrs.push(format!(
- "image=\"/tmp/tiles/{}.png\"",
+ "image=\"tiles/{}.png\"",
data.tile_name(*tile_index)
));
attrs.push("imagescale=true".to_owned());