aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock18
-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
4 files changed, 70 insertions, 62 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6d8daaf3..6f1db32a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -831,11 +831,11 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "glam"
-version = "0.30.5"
+version = "0.30.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2d1aab06663bdce00d6ca5e5ed586ec8d18033a771906c993a1e3755b368d85"
+checksum = "e12d847aeb25f41be4c0ec9587d624e9cd631bc007a8fd7ce3f5851e064c6460"
dependencies = [
- "serde",
+ "serde_core",
]
[[package]]
@@ -2386,9 +2386,9 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.225"
+version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
@@ -2396,18 +2396,18 @@ dependencies = [
[[package]]
name = "serde_core"
-version = "1.0.225"
+version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.225"
+version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
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());