this repo has no description
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

🍱 Continue Schedule Hell

+509 -210
+1
Cargo.lock
··· 2087 2087 dependencies = [ 2088 2088 "itertools 0.14.0", 2089 2089 "rand 0.9.2", 2090 + "schedule-hell", 2090 2091 "shapemaker", 2091 2092 ] 2092 2093
+1 -1
Justfile
··· 5 5 s *args: 6 6 just schedule-hell {{args}} 7 7 8 - backbone *args: 8 + endfirstbreak *args: 9 9 just schedule-hell --marker "\"end first break\"" {{args}} 10 10 11 11 [working-directory: 'examples/schedule-hell']
+8 -1
bacon.toml
··· 10 10 11 11 [keybindings] 12 12 r = "refresh" 13 - 13 + ctrl-s = "toggle-pause" 14 14 15 15 [jobs.playground] 16 16 workdir = "examples/playground" 17 17 watch = ["examples/playground/src/**"] 18 18 command = ["cargo", "run", "--"] 19 + need_stdout = true 19 20 20 21 [jobs.specimen] 21 22 workdir = "examples/specimen" ··· 26 27 workdir = "examples/dna-analysis-machine" 27 28 watch = ["examples/dna-analysis-machine/src/**"] 28 29 command = ["cargo", "run", "--"] 30 + 31 + [jobs.doctest] 32 + workdir = "." 33 + watch = ["src/**"] 34 + command = ["cargo", "test", "--doc"] 35 + need_stdout = true
+1
examples/playground/Cargo.toml
··· 7 7 itertools = "0.14.0" 8 8 rand = "0.9.2" 9 9 shapemaker = { version = "1.2.2", path = "../.." } 10 + schedule-hell = { path = "../schedule-hell" }
+68 -61
examples/playground/result.svg
··· 1 - <svg height="470" viewBox="-10 -10 470 470" width="470" xmlns="http://www.w3.org/2000/svg"> 2 - <rect fill="#000000" height="470" width="470" x="-10" y="-10"/> 1 + <svg height="510" viewBox="-30 -30 860 510" width="860" xmlns="http://www.w3.org/2000/svg"> 2 + <rect fill="#000000" height="510" width="860" x="-30" y="-30"/> 3 3 <g class="layer" data-layer="dices_bg"> 4 - <line data-object="dices_bg--anon-0" stroke-width="0.5" x1="150" x2="300" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 5 - <line data-object="dices_bg--anon-1" stroke-width="0.5" x1="300" x2="300" y1="150" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 6 - <line data-object="dices_bg--anon-10" stroke-width="0.5" x1="150" x2="0" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 7 - <line data-object="dices_bg--anon-11" stroke-width="0.5" x1="0" x2="0" y1="300" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 8 - <line data-object="dices_bg--anon-12" stroke-width="0.5" x1="300" x2="450" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 9 - <line data-object="dices_bg--anon-13" stroke-width="0.5" x1="450" x2="450" y1="150" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 10 - <line data-object="dices_bg--anon-14" stroke-width="0.5" x1="450" x2="300" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 11 - <line data-object="dices_bg--anon-15" stroke-width="0.5" x1="300" x2="300" y1="300" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 12 - <line data-object="dices_bg--anon-16" stroke-width="0.5" x1="150" x2="300" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 13 - <line data-object="dices_bg--anon-17" stroke-width="0.5" x1="300" x2="300" y1="300" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 14 - <line data-object="dices_bg--anon-18" stroke-width="0.5" x1="300" x2="150" y1="450" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 15 - <line data-object="dices_bg--anon-19" stroke-width="0.5" x1="150" x2="150" y1="450" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 16 - <line data-object="dices_bg--anon-2" stroke-width="0.5" x1="300" x2="150" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 17 - <line data-object="dices_bg--anon-20" stroke-width="0.5" x1="300" x2="450" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 18 - <line data-object="dices_bg--anon-21" stroke-width="0.5" x1="450" x2="450" y1="300" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 19 - <line data-object="dices_bg--anon-22" stroke-width="0.5" x1="450" x2="300" y1="450" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 20 - <line data-object="dices_bg--anon-23" stroke-width="0.5" x1="300" x2="300" y1="450" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 21 - <line data-object="dices_bg--anon-3" stroke-width="0.5" x1="150" x2="150" y1="300" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 22 - <line data-object="dices_bg--anon-4" stroke-width="0.5" x1="150" x2="300" y1="0" y2="0" style="stroke: #81a0a8; fill: transparent;"/> 23 - <line data-object="dices_bg--anon-5" stroke-width="0.5" x1="300" x2="300" y1="0" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 24 - <line data-object="dices_bg--anon-6" stroke-width="0.5" x1="300" x2="150" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 25 - <line data-object="dices_bg--anon-7" stroke-width="0.5" x1="150" x2="150" y1="150" y2="0" style="stroke: #81a0a8; fill: transparent;"/> 26 - <line data-object="dices_bg--anon-8" stroke-width="0.5" x1="0" x2="150" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 27 - <line data-object="dices_bg--anon-9" stroke-width="0.5" x1="150" x2="150" y1="150" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 4 + <line data-object="dices_bg--anon-0" stroke-width="0.5" x1="300" x2="450" y1="0" y2="0" style="stroke: #81a0a8; fill: transparent;"/> 5 + <line data-object="dices_bg--anon-1" stroke-width="0.5" x1="450" x2="450" y1="0" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 6 + <line data-object="dices_bg--anon-10" stroke-width="0.5" x1="450" x2="300" y1="450" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 7 + <line data-object="dices_bg--anon-11" stroke-width="0.5" x1="300" x2="300" y1="450" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 8 + <line data-object="dices_bg--anon-12" stroke-width="0.5" x1="150" x2="300" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 9 + <line data-object="dices_bg--anon-13" stroke-width="0.5" x1="300" x2="300" y1="150" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 10 + <line data-object="dices_bg--anon-14" stroke-width="0.5" x1="300" x2="150" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 11 + <line data-object="dices_bg--anon-15" stroke-width="0.5" x1="150" x2="150" y1="300" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 12 + <line data-object="dices_bg--anon-16" stroke-width="0.5" x1="450" x2="600" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 13 + <line data-object="dices_bg--anon-17" stroke-width="0.5" x1="600" x2="600" y1="150" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 14 + <line data-object="dices_bg--anon-18" stroke-width="0.5" x1="600" x2="450" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 15 + <line data-object="dices_bg--anon-19" stroke-width="0.5" x1="450" x2="450" y1="300" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 16 + <line data-object="dices_bg--anon-2" stroke-width="0.5" x1="450" x2="300" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 17 + <line data-object="dices_bg--anon-20" stroke-width="0.5" x1="450" x2="600" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 18 + <line data-object="dices_bg--anon-21" stroke-width="0.5" x1="600" x2="600" y1="300" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 19 + <line data-object="dices_bg--anon-22" stroke-width="0.5" x1="600" x2="450" y1="450" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 20 + <line data-object="dices_bg--anon-23" stroke-width="0.5" x1="450" x2="450" y1="450" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 21 + <line data-object="dices_bg--anon-3" stroke-width="0.5" x1="300" x2="300" y1="150" y2="0" style="stroke: #81a0a8; fill: transparent;"/> 22 + <line data-object="dices_bg--anon-4" stroke-width="0.5" x1="300" x2="450" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 23 + <line data-object="dices_bg--anon-5" stroke-width="0.5" x1="450" x2="450" y1="150" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 24 + <line data-object="dices_bg--anon-6" stroke-width="0.5" x1="450" x2="300" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 25 + <line data-object="dices_bg--anon-7" stroke-width="0.5" x1="300" x2="300" y1="300" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 26 + <line data-object="dices_bg--anon-8" stroke-width="0.5" x1="300" x2="450" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 27 + <line data-object="dices_bg--anon-9" stroke-width="0.5" x1="450" x2="450" y1="300" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 28 + </g><g class="layer" data-layer="connections"> 29 + <line data-object="connections--anon-0" stroke-width="3" x1="575" x2="475" y1="175" y2="175" style="stroke: #4fecec; fill: transparent;"/> 30 + <line data-object="connections--anon-1" stroke-width="3" x1="475" x2="475" y1="175" y2="275" style="stroke: #4fecec; fill: transparent;"/> 31 + <line data-object="connections--anon-10" stroke-width="3" x1="425" x2="475" y1="425" y2="325" style="stroke: #4fecec; fill: transparent;"/> 32 + <line data-object="connections--anon-11" stroke-width="3" x1="475" x2="475" y1="325" y2="375" style="stroke: #4fecec; fill: transparent;"/> 33 + <line data-object="connections--anon-12" stroke-width="3" x1="475" x2="475" y1="375" y2="425" style="stroke: #4fecec; fill: transparent;"/> 34 + <line data-object="connections--anon-13" stroke-width="3" x1="475" x2="575" y1="425" y2="425" style="stroke: #4fecec; fill: transparent;"/> 35 + <line data-object="connections--anon-14" stroke-width="3" x1="575" x2="575" y1="425" y2="375" style="stroke: #4fecec; fill: transparent;"/> 36 + <line data-object="connections--anon-15" stroke-width="3" x1="475" x2="375" y1="325" y2="375" style="stroke: #4fecec; fill: transparent;"/> 37 + <line data-object="connections--anon-16" stroke-width="3" x1="325" x2="425" y1="25" y2="125" style="stroke: #4fecec; fill: transparent;"/> 38 + <line data-object="connections--anon-2" stroke-width="3" x1="475" x2="525" y1="275" y2="225" style="stroke: #4fecec; fill: transparent;"/> 39 + <line data-object="connections--anon-3" stroke-width="3" x1="525" x2="575" y1="225" y2="275" style="stroke: #4fecec; fill: transparent;"/> 40 + <line data-object="connections--anon-4" stroke-width="3" x1="575" x2="575" y1="275" y2="325" style="stroke: #4fecec; fill: transparent;"/> 41 + <line data-object="connections--anon-5" stroke-width="3" x1="275" x2="375" y1="275" y2="225" style="stroke: #4fecec; fill: transparent;"/> 42 + <line data-object="connections--anon-6" stroke-width="3" x1="375" x2="325" y1="225" y2="325" style="stroke: #4fecec; fill: transparent;"/> 43 + <line data-object="connections--anon-7" stroke-width="3" x1="325" x2="175" y1="325" y2="275" style="stroke: #4fecec; fill: transparent;"/> 44 + <line data-object="connections--anon-8" stroke-width="3" x1="175" x2="175" y1="275" y2="175" style="stroke: #4fecec; fill: transparent;"/> 45 + <line data-object="connections--anon-9" stroke-width="3" x1="175" x2="275" y1="175" y2="175" style="stroke: #4fecec; fill: transparent;"/> 28 46 </g><g class="layer" data-layer="dices"> 29 - <circle cx="225" cy="225" data-object="dices--anon-0" r="7" style="fill: #ffffff;"/> 30 - <circle cx="175" cy="25" data-object="dices--anon-1" r="7" style="fill: #ffffff;"/> 31 - <circle cx="425" cy="275" data-object="dices--anon-10" r="7" style="fill: #ffffff;"/> 32 - <circle cx="425" cy="175" data-object="dices--anon-11" r="7" style="fill: #ffffff;"/> 33 - <circle cx="175" cy="325" data-object="dices--anon-12" r="7" style="fill: #ffffff;"/> 34 - <circle cx="225" cy="375" data-object="dices--anon-13" r="7" style="fill: #ffffff;"/> 35 - <circle cx="275" cy="425" data-object="dices--anon-14" r="7" style="fill: #ffffff;"/> 36 - <circle cx="325" cy="325" data-object="dices--anon-15" r="7" style="fill: #ffffff;"/> 37 - <circle cx="325" cy="375" data-object="dices--anon-16" r="7" style="fill: #ffffff;"/> 38 - <circle cx="325" cy="425" data-object="dices--anon-17" r="7" style="fill: #ffffff;"/> 39 - <circle cx="425" cy="425" data-object="dices--anon-18" r="7" style="fill: #ffffff;"/> 40 - <circle cx="425" cy="375" data-object="dices--anon-19" r="7" style="fill: #ffffff;"/> 41 - <circle cx="275" cy="125" data-object="dices--anon-2" r="7" style="fill: #ffffff;"/> 42 - <circle cx="425" cy="325" data-object="dices--anon-20" r="7" style="fill: #ffffff;"/> 43 - <circle cx="25" cy="175" data-object="dices--anon-3" r="7" style="fill: #ffffff;"/> 44 - <circle cx="25" cy="275" data-object="dices--anon-4" r="7" style="fill: #ffffff;"/> 45 - <circle cx="125" cy="275" data-object="dices--anon-5" r="7" style="fill: #ffffff;"/> 46 - <circle cx="125" cy="175" data-object="dices--anon-6" r="7" style="fill: #ffffff;"/> 47 - <circle cx="325" cy="175" data-object="dices--anon-7" r="7" style="fill: #ffffff;"/> 48 - <circle cx="325" cy="275" data-object="dices--anon-8" r="7" style="fill: #ffffff;"/> 49 - <circle cx="375" cy="225" data-object="dices--anon-9" r="7" style="fill: #ffffff;"/> 50 - </g><g class="layer" data-layer="connections"> 51 - <line data-object="connections--anon-0" stroke-width="3" x1="425" x2="425" y1="325" y2="175" style="stroke: #4fecec; fill: transparent;"/> 52 - <line data-object="connections--anon-1" stroke-width="3" x1="425" x2="325" y1="175" y2="325" style="stroke: #4fecec; fill: transparent;"/> 53 - <line data-object="connections--anon-10" stroke-width="3" x1="225" x2="325" y1="375" y2="275" style="stroke: #4fecec; fill: transparent;"/> 54 - <line data-object="connections--anon-2" stroke-width="3" x1="175" x2="325" y1="325" y2="275" style="stroke: #4fecec; fill: transparent;"/> 55 - <line data-object="connections--anon-3" stroke-width="3" x1="25" x2="125" y1="275" y2="275" style="stroke: #4fecec; fill: transparent;"/> 56 - <line data-object="connections--anon-4" stroke-width="3" x1="325" x2="175" y1="425" y2="325" style="stroke: #4fecec; fill: transparent;"/> 57 - <line data-object="connections--anon-5" stroke-width="3" x1="425" x2="375" y1="275" y2="225" style="stroke: #4fecec; fill: transparent;"/> 58 - <line data-object="connections--anon-6" stroke-width="3" x1="125" x2="25" y1="275" y2="275" style="stroke: #4fecec; fill: transparent;"/> 59 - <line data-object="connections--anon-7" stroke-width="3" x1="425" x2="425" y1="375" y2="275" style="stroke: #4fecec; fill: transparent;"/> 60 - <line data-object="connections--anon-8" stroke-width="3" x1="425" x2="325" y1="425" y2="275" style="stroke: #4fecec; fill: transparent;"/> 61 - <line data-object="connections--anon-9" stroke-width="3" x1="325" x2="375" y1="325" y2="225" style="stroke: #4fecec; fill: transparent;"/> 62 - </g><g class="layer" data-layer="root"/> 63 - <defs /> 47 + <circle cx="325" cy="25" data-object="dices--anon-0" r="7" style="fill: #ffffff;"/> 48 + <circle cx="425" cy="125" data-object="dices--anon-1" r="7" style="fill: #ffffff;"/> 49 + <circle cx="475" cy="175" data-object="dices--anon-10" r="7" style="fill: #ffffff;"/> 50 + <circle cx="475" cy="275" data-object="dices--anon-11" r="7" style="fill: #ffffff;"/> 51 + <circle cx="525" cy="225" data-object="dices--anon-12" r="7" style="fill: #ffffff;"/> 52 + <circle cx="575" cy="275" data-object="dices--anon-13" r="7" style="fill: #ffffff;"/> 53 + <circle cx="575" cy="175" data-object="dices--anon-14" r="7" style="fill: #ffffff;"/> 54 + <circle cx="475" cy="325" data-object="dices--anon-15" r="7" style="fill: #ffffff;"/> 55 + <circle cx="475" cy="375" data-object="dices--anon-16" r="7" style="fill: #ffffff;"/> 56 + <circle cx="475" cy="425" data-object="dices--anon-17" r="7" style="fill: #ffffff;"/> 57 + <circle cx="575" cy="325" data-object="dices--anon-18" r="7" style="fill: #ffffff;"/> 58 + <circle cx="575" cy="375" data-object="dices--anon-19" r="7" style="fill: #ffffff;"/> 59 + <circle cx="375" cy="225" data-object="dices--anon-2" r="7" style="fill: #ffffff;"/> 60 + <circle cx="575" cy="425" data-object="dices--anon-20" r="7" style="fill: #ffffff;"/> 61 + <circle cx="325" cy="325" data-object="dices--anon-3" r="7" style="fill: #ffffff;"/> 62 + <circle cx="375" cy="375" data-object="dices--anon-4" r="7" style="fill: #ffffff;"/> 63 + <circle cx="425" cy="425" data-object="dices--anon-5" r="7" style="fill: #ffffff;"/> 64 + <circle cx="175" cy="175" data-object="dices--anon-6" r="7" style="fill: #ffffff;"/> 65 + <circle cx="175" cy="275" data-object="dices--anon-7" r="7" style="fill: #ffffff;"/> 66 + <circle cx="275" cy="275" data-object="dices--anon-8" r="7" style="fill: #ffffff;"/> 67 + <circle cx="275" cy="175" data-object="dices--anon-9" r="7" style="fill: #ffffff;"/> 68 + </g><g class="layer" data-layer="root"> 69 + <text data-object="root--seed" dominant-baseline="hanging" font-family="Inconsolata" font-size="10pt" text-anchor="start" x="0" y="0" style="fill: #ffffff;"> 70 + seed 57</text></g><defs /> 64 71 </svg>
+22 -129
examples/playground/src/main.rs
··· 1 1 use itertools::Itertools; 2 - use rand::{Rng, seq::IteratorRandom}; 2 + use rand::{ 3 + Rng, SeedableRng, 4 + rngs::StdRng, 5 + seq::{IndexedRandom, IteratorRandom}, 6 + }; 3 7 use shapemaker::*; 4 - 5 - const DICES_GRID: Grid = Grid(3, 3); 6 8 7 9 fn main() { 8 - let mut rng = rand::rng(); 9 - let mut canvas = Canvas::new(9, 9); 10 - canvas.object_sizes.small_circle_radius = 7.0; 11 - canvas.colormap = ColorMapping { 12 - black: "#000000".into(), 13 - white: "#ffffff".into(), 14 - red: "#cf0a2b".into(), 15 - green: "#22e753".into(), 16 - blue: "#2734e6".into(), 17 - yellow: "#f8e21e".into(), 18 - orange: "#f05811".into(), 19 - purple: "#6a24ec".into(), 20 - brown: "#a05634".into(), 21 - pink: "#e92e76".into(), 22 - gray: "#81a0a8".into(), 23 - cyan: "#4fecec".into(), 24 - }; 10 + let seed = (0..100u64).choose(&mut rand::rng()).unwrap(); 11 + // let seed = 84; 12 + let mut rng = StdRng::seed_from_u64(seed); 13 + let mut canvas = Canvas::new(16, 9); 14 + canvas.outer_padding = 30; 25 15 26 - dice(&mut canvas, (1, 1), vec![(1, 1)]); 27 - dice(&mut canvas, (1, 0), vec![(0, 0), (2, 2)]); 28 - dice(&mut canvas, (0, 1), vec![(0, 0), (0, 2), (2, 2), (2, 0)]); 29 - dice( 30 - &mut canvas, 31 - (2, 1), 32 - vec![(0, 0), (0, 2), (1, 1), (2, 2), (2, 0)], 33 - ); 34 - dice(&mut canvas, (1, 2), vec![(0, 0), (1, 1), (2, 2)]); 35 - dice( 36 - &mut canvas, 37 - (2, 2), 38 - vec![(0, 0), (0, 1), (0, 2), (2, 2), (2, 1), (2, 0)], 39 - ); 16 + schedule_hell::scenes::dices::setup(&mut canvas); 40 17 41 - let dice_dots: Vec<_> = canvas 42 - .layer("dices") 43 - .unwrap() 44 - .objects 45 - .iter() 46 - .map(|(_, dot)| dot.region().center()) 47 - .collect(); 18 + schedule_hell::scenes::dices::place_dice(&mut canvas, (2, 0), 2); 19 + schedule_hell::scenes::dices::place_dice(&mut canvas, (2, 1), 1); 20 + schedule_hell::scenes::dices::place_dice(&mut canvas, (2, 2), 3); 21 + schedule_hell::scenes::dices::place_dice(&mut canvas, (1, 1), 4); 22 + schedule_hell::scenes::dices::place_dice(&mut canvas, (3, 1), 5); 23 + schedule_hell::scenes::dices::place_dice(&mut canvas, (3, 2), 6); 48 24 49 - let connections = canvas.layer_or_empty("connections"); 25 + schedule_hell::scenes::dices::iterate(&mut canvas, &mut rng); 50 26 51 - for &point in &dice_dots { 52 - if rng.random_bool(0.5) { 53 - continue; 54 - } 55 - 56 - // Find another point that's not connected yet 57 - let other_point = dice_dots 58 - .iter() 59 - .filter(|&&p| p != point) 60 - .filter(|&&p| p.distance_to(&point).norm() <= 5.0) 61 - .filter(|&&p| { 62 - !connections.has_object_that(|co| match co.shape { 63 - Line(..) => co.shape.intersects_with(Line(point, p, 0.)), 64 - _ => false, 65 - }) 66 - }) 67 - .choose(&mut rng); 68 - 69 - if let Some(&other_point) = other_point { 70 - connections.add_anon( 71 - Line(point, other_point, 3.0).colored(Cyan), // .opacified(0.5) 72 - // .filtered(Filter::glow(10.0)), 73 - ); 74 - } 75 - } 76 - 77 - // let world = canvas.world_region.clone(); 78 - // let grid = canvas.layer_or_empty("grid"); 79 - // for (p, _, _) in world.top_edge().tuples() { 80 - // grid.add_anon(Line(p.with_y(0), p.with_y(9), 1.0).colored(Gray)); 81 - // } 82 - // for (p, _, _) in world.left_edge().tuples() { 83 - // grid.add_anon(Line(p.with_x(0), p.with_x(9), 1.0).colored(Gray)); 84 - // } 85 - // grid.add_anon(Line(P(0, 9), P(9, 9), 1.0).colored(Gray)); 86 - // grid.add_anon(Line(P(9, 0), P(9, 9), 1.0).colored(Gray)); 87 - 88 - canvas.reorder_layers(vec!["connections", "dices", "dices_bg"]); 27 + canvas.root().add( 28 + "seed", 29 + Text(CornerPoint(0, 0), format!("seed {seed}"), 10.0).colored(White), 30 + ); 89 31 90 32 canvas 91 33 .render_to_svg_file("result.svg") 92 34 .expect("Could not write SVG"); 93 35 } 94 - 95 - fn dice( 96 - canvas: &mut Canvas, 97 - place_at: (usize, usize), 98 - dots_at: Vec<(usize, usize)>, 99 - ) { 100 - for (x, y) in dots_at { 101 - let at = Point::Center(x, y) 102 - .translated_by(Point::from(place_at).coords_from(&DICES_GRID)); 103 - 104 - canvas 105 - .layer_or_empty("dices") 106 - .add_anon(SmallCircle(at).colored(White)); 107 - } 108 - 109 - let dicebox = Region::from_topleft( 110 - Point::from(place_at).coords_from(&DICES_GRID), 111 - DICES_GRID.size(), 112 - ) 113 - .unwrap(); 114 - 115 - canvas.layer_or_empty("dices_bg").add_many_anon( 116 - dicebox 117 - .corners() 118 - .iter() 119 - .circular_tuple_windows() 120 - .map(|(&s, &e)| Line(s, e, 0.5).colored(Gray)), 121 - ); 122 - } 123 - 124 - struct Grid(usize, usize); 125 - 126 - trait GridSnappable { 127 - // fn snapped_to(&self, grid: &Grid) -> Self; 128 - // fn snap_to(&mut self, grid: &Grid); 129 - fn coords_from(&self, grid: &Grid) -> Self; 130 - } 131 - 132 - impl GridSnappable for Point { 133 - fn coords_from(&self, Grid(sx, sy): &Grid) -> Self { 134 - self.with(self.x() * sx, self.y() * sy) 135 - } 136 - } 137 - 138 - impl Grid { 139 - fn size(&self) -> (usize, usize) { 140 - (self.0, self.1) 141 - } 142 - }
+73
examples/schedule-hell/result.svg
··· 1 + <svg height="470" viewBox="-10 -10 820 470" width="820" xmlns="http://www.w3.org/2000/svg"> 2 + <rect fill="#000000" height="470" width="820" x="-10" y="-10"/> 3 + <g class="layer" data-layer="dices_bg"> 4 + <line data-object="dices_bg--anon-0" stroke-width="0.5" x1="300" x2="450" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 5 + <line data-object="dices_bg--anon-1" stroke-width="0.5" x1="450" x2="450" y1="150" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 6 + <line data-object="dices_bg--anon-10" stroke-width="0.5" x1="450" x2="300" y1="450" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 7 + <line data-object="dices_bg--anon-11" stroke-width="0.5" x1="300" x2="300" y1="450" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 8 + <line data-object="dices_bg--anon-12" stroke-width="0.5" x1="150" x2="300" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 9 + <line data-object="dices_bg--anon-13" stroke-width="0.5" x1="300" x2="300" y1="150" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 10 + <line data-object="dices_bg--anon-14" stroke-width="0.5" x1="300" x2="150" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 11 + <line data-object="dices_bg--anon-15" stroke-width="0.5" x1="150" x2="150" y1="300" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 12 + <line data-object="dices_bg--anon-16" stroke-width="0.5" x1="450" x2="600" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 13 + <line data-object="dices_bg--anon-17" stroke-width="0.5" x1="600" x2="600" y1="150" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 14 + <line data-object="dices_bg--anon-18" stroke-width="0.5" x1="600" x2="450" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 15 + <line data-object="dices_bg--anon-19" stroke-width="0.5" x1="450" x2="450" y1="300" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 16 + <line data-object="dices_bg--anon-2" stroke-width="0.5" x1="450" x2="300" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 17 + <line data-object="dices_bg--anon-20" stroke-width="0.5" x1="450" x2="600" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 18 + <line data-object="dices_bg--anon-21" stroke-width="0.5" x1="600" x2="600" y1="300" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 19 + <line data-object="dices_bg--anon-22" stroke-width="0.5" x1="600" x2="450" y1="450" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 20 + <line data-object="dices_bg--anon-23" stroke-width="0.5" x1="450" x2="450" y1="450" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 21 + <line data-object="dices_bg--anon-3" stroke-width="0.5" x1="300" x2="300" y1="300" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 22 + <line data-object="dices_bg--anon-4" stroke-width="0.5" x1="300" x2="450" y1="0" y2="0" style="stroke: #81a0a8; fill: transparent;"/> 23 + <line data-object="dices_bg--anon-5" stroke-width="0.5" x1="450" x2="450" y1="0" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 24 + <line data-object="dices_bg--anon-6" stroke-width="0.5" x1="450" x2="300" y1="150" y2="150" style="stroke: #81a0a8; fill: transparent;"/> 25 + <line data-object="dices_bg--anon-7" stroke-width="0.5" x1="300" x2="300" y1="150" y2="0" style="stroke: #81a0a8; fill: transparent;"/> 26 + <line data-object="dices_bg--anon-8" stroke-width="0.5" x1="300" x2="450" y1="300" y2="300" style="stroke: #81a0a8; fill: transparent;"/> 27 + <line data-object="dices_bg--anon-9" stroke-width="0.5" x1="450" x2="450" y1="300" y2="450" style="stroke: #81a0a8; fill: transparent;"/> 28 + </g><g class="layer" data-layer="connections"> 29 + <line data-object="connections--anon-0" stroke-width="3" x1="475" x2="375" y1="325" y2="225" style="stroke: #4fecec; fill: transparent;"/> 30 + <line data-object="connections--anon-1" stroke-width="3" x1="375" x2="325" y1="225" y2="25" style="stroke: #4fecec; fill: transparent;"/> 31 + <line data-object="connections--anon-10" stroke-width="3" x1="575" x2="575" y1="325" y2="375" style="stroke: #4fecec; fill: transparent;"/> 32 + <line data-object="connections--anon-11" stroke-width="3" x1="575" x2="575" y1="375" y2="425" style="stroke: #4fecec; fill: transparent;"/> 33 + <line data-object="connections--anon-12" stroke-width="3" x1="375" x2="325" y1="375" y2="325" style="stroke: #4fecec; fill: transparent;"/> 34 + <line data-object="connections--anon-13" stroke-width="3" x1="325" x2="375" y1="325" y2="375" style="stroke: #4fecec; fill: transparent;"/> 35 + <line data-object="connections--anon-14" stroke-width="3" x1="375" x2="425" y1="375" y2="425" style="stroke: #4fecec; fill: transparent;"/> 36 + <line data-object="connections--anon-15" stroke-width="3" x1="425" x2="175" y1="425" y2="175" style="stroke: #4fecec; fill: transparent;"/> 37 + <line data-object="connections--anon-16" stroke-width="3" x1="175" x2="175" y1="175" y2="275" style="stroke: #4fecec; fill: transparent;"/> 38 + <line data-object="connections--anon-17" stroke-width="3" x1="275" x2="275" y1="175" y2="175" style="stroke: #4fecec; fill: transparent;"/> 39 + <line data-object="connections--anon-18" stroke-width="3" x1="175" x2="275" y1="175" y2="275" style="stroke: #4fecec; fill: transparent;"/> 40 + <line data-object="connections--anon-2" stroke-width="3" x1="325" x2="475" y1="25" y2="175" style="stroke: #4fecec; fill: transparent;"/> 41 + <line data-object="connections--anon-3" stroke-width="3" x1="475" x2="475" y1="175" y2="275" style="stroke: #4fecec; fill: transparent;"/> 42 + <line data-object="connections--anon-4" stroke-width="3" x1="475" x2="525" y1="275" y2="225" style="stroke: #4fecec; fill: transparent;"/> 43 + <line data-object="connections--anon-5" stroke-width="3" x1="525" x2="575" y1="225" y2="175" style="stroke: #4fecec; fill: transparent;"/> 44 + <line data-object="connections--anon-6" stroke-width="3" x1="575" x2="575" y1="175" y2="275" style="stroke: #4fecec; fill: transparent;"/> 45 + <line data-object="connections--anon-7" stroke-width="3" x1="575" x2="475" y1="275" y2="375" style="stroke: #4fecec; fill: transparent;"/> 46 + <line data-object="connections--anon-8" stroke-width="3" x1="475" x2="475" y1="375" y2="425" style="stroke: #4fecec; fill: transparent;"/> 47 + <line data-object="connections--anon-9" stroke-width="3" x1="475" x2="575" y1="425" y2="325" style="stroke: #4fecec; fill: transparent;"/> 48 + </g><g class="layer" data-layer="dices"> 49 + <circle cx="375" cy="225" data-object="dices--anon-0" r="7" style="fill: #ffffff;"/> 50 + <circle cx="325" cy="25" data-object="dices--anon-1" r="7" style="fill: #ffffff;"/> 51 + <circle cx="475" cy="175" data-object="dices--anon-10" r="7" style="fill: #ffffff;"/> 52 + <circle cx="475" cy="275" data-object="dices--anon-11" r="7" style="fill: #ffffff;"/> 53 + <circle cx="525" cy="225" data-object="dices--anon-12" r="7" style="fill: #ffffff;"/> 54 + <circle cx="575" cy="275" data-object="dices--anon-13" r="7" style="fill: #ffffff;"/> 55 + <circle cx="575" cy="175" data-object="dices--anon-14" r="7" style="fill: #ffffff;"/> 56 + <circle cx="475" cy="325" data-object="dices--anon-15" r="7" style="fill: #ffffff;"/> 57 + <circle cx="475" cy="375" data-object="dices--anon-16" r="7" style="fill: #ffffff;"/> 58 + <circle cx="475" cy="425" data-object="dices--anon-17" r="7" style="fill: #ffffff;"/> 59 + <circle cx="575" cy="325" data-object="dices--anon-18" r="7" style="fill: #ffffff;"/> 60 + <circle cx="575" cy="375" data-object="dices--anon-19" r="7" style="fill: #ffffff;"/> 61 + <circle cx="425" cy="125" data-object="dices--anon-2" r="7" style="fill: #ffffff;"/> 62 + <circle cx="575" cy="425" data-object="dices--anon-20" r="7" style="fill: #ffffff;"/> 63 + <circle cx="325" cy="325" data-object="dices--anon-3" r="7" style="fill: #ffffff;"/> 64 + <circle cx="375" cy="375" data-object="dices--anon-4" r="7" style="fill: #ffffff;"/> 65 + <circle cx="425" cy="425" data-object="dices--anon-5" r="7" style="fill: #ffffff;"/> 66 + <circle cx="175" cy="175" data-object="dices--anon-6" r="7" style="fill: #ffffff;"/> 67 + <circle cx="175" cy="275" data-object="dices--anon-7" r="7" style="fill: #ffffff;"/> 68 + <circle cx="275" cy="275" data-object="dices--anon-8" r="7" style="fill: #ffffff;"/> 69 + <circle cx="275" cy="175" data-object="dices--anon-9" r="7" style="fill: #ffffff;"/> 70 + </g><g class="layer" data-layer="root"> 71 + <text data-object="root--credits text" dominant-baseline="hanging" font-family="Inconsolata" font-size="12pt" text-anchor="start" x="100" y="100" style="fill: #ffffff;"> 72 + Postamble / Schedule Hell</text></g><defs /> 73 + </svg>
examples/schedule-hell/schedule-hell-final.mp4

This is a binary file and will not be displayed.

examples/schedule-hell/schedule-hell-ok.mp4

This is a binary file and will not be displayed.

+23
examples/schedule-hell/src/lib.rs
··· 1 + pub mod scenes; 2 + 3 + use rand::{SeedableRng, rngs::SmallRng}; 4 + use shapemaker::*; 5 + 6 + pub struct State { 7 + pub bass_pattern_at: Region, 8 + pub kick_color: Color, 9 + pub rng: SmallRng, 10 + pub cranks: u32, 11 + } 12 + 13 + impl Default for State { 14 + fn default() -> Self { 15 + Self { 16 + bass_pattern_at: Region::from_topleft(CornerPoint(1, 1), (2, 2)) 17 + .unwrap(), 18 + kick_color: Color::White, 19 + rng: SmallRng::seed_from_u64(0), 20 + cranks: 0, 21 + } 22 + } 23 + }
+3 -18
examples/schedule-hell/src/main.rs
··· 3 3 use anyhow::anyhow; 4 4 use itertools::Itertools; 5 5 use rand::{SeedableRng, rngs::SmallRng}; 6 + use schedule_hell::State; 6 7 use shapemaker::{ui::Log, *}; 7 8 use std::{fs, path::PathBuf, time::Duration}; 8 9 9 - pub struct State { 10 - bass_pattern_at: Region, 11 - kick_color: Color, 12 - rng: SmallRng, 13 - cranks: u32, 14 - } 15 10 16 - impl Default for State { 17 - fn default() -> Self { 18 - Self { 19 - bass_pattern_at: Region::from_topleft(CornerPoint(1, 1), (2, 2)) 20 - .unwrap(), 21 - kick_color: Color::White, 22 - rng: SmallRng::seed_from_u64(0), 23 - cranks: 0, 24 - } 25 - } 26 - } 27 11 28 12 #[tokio::main] 29 13 pub async fn main() { ··· 84 68 .with_init_scene(scenes::intro()) 85 69 .with_marked_scene(scenes::first_break()) 86 70 .with_scene(scenes::backbone()) 71 + .with_scene(scenes::dices()) 87 72 .assign_scene_to("end of first break", "intro") 88 73 .assign_scene_to("second break", "starry sky") 89 74 // "end first break" means "end of second break" lol 90 - .assign_scene_to("end first break", "backbone") 75 + .assign_scene_to("end first break", "dices") 91 76 // Credits // 92 77 .when_remaining(10, &|canvas, _| { 93 78 let world = canvas.world_region;
+307
examples/schedule-hell/src/scenes/dices.rs
··· 1 + use itertools::Itertools; 2 + use rand::{ 3 + Rng, SeedableRng, 4 + rngs::{SmallRng, StdRng}, 5 + seq::{IndexedRandom, IteratorRandom}, 6 + }; 7 + use shapemaker::*; 8 + 9 + use crate::State; 10 + 11 + pub const DICES_GRID: Grid = Grid(3, 3); 12 + 13 + pub fn dices() -> Scene<State> { 14 + Scene::<State>::new("dices") 15 + .init(&|canvas, ctx| { 16 + ctx.extra.cranks = 0; 17 + setup(canvas); 18 + 19 + Ok(()) 20 + }) 21 + .each_n_frame(4, &|canvas, ctx| { 22 + match ctx.extra.cranks { 23 + 0 => place_dice(canvas, (2, 1), 1), 24 + 1 => place_dice(canvas, (2, 0), 2), 25 + 2 => place_dice(canvas, (2, 2), 3), 26 + 3 => place_dice(canvas, (1, 1), 4), 27 + 4 => place_dice(canvas, (3, 1), 5), 28 + 5 => place_dice(canvas, (3, 2), 6), 29 + _ => return Ok(()), 30 + } 31 + 32 + ctx.extra.cranks += 1; 33 + 34 + Ok(()) 35 + }) 36 + .on_note("brokenup", &|canvas, ctx| { 37 + if ctx.extra.cranks < 6 { 38 + return Ok(()); 39 + } 40 + 41 + iterate(canvas, &mut ctx.extra.rng); 42 + 43 + Ok(()) 44 + }) 45 + } 46 + 47 + pub fn setup(canvas: &mut Canvas) { 48 + // canvas.set_grid_size( 49 + // canvas.grid_size.0 * DICES_GRID.0, 50 + // canvas.grid_size.1 * DICES_GRID.1, 51 + // ); 52 + canvas.object_sizes.small_circle_radius = 7.0; 53 + canvas.colormap = ColorMapping { 54 + black: "#000000".into(), 55 + white: "#ffffff".into(), 56 + red: "#cf0a2b".into(), 57 + green: "#22e753".into(), 58 + blue: "#2734e6".into(), 59 + yellow: "#f8e21e".into(), 60 + orange: "#f05811".into(), 61 + purple: "#6a24ec".into(), 62 + brown: "#a05634".into(), 63 + pink: "#e92e76".into(), 64 + gray: "#81a0a8".into(), 65 + cyan: "#4fecec".into(), 66 + }; 67 + } 68 + 69 + pub fn place_dice(canvas: &mut Canvas, at: (usize, usize), value: usize) { 70 + canvas.add_dice( 71 + at, 72 + match value { 73 + 1 => vec![(1, 1)], 74 + 2 => vec![(0, 0), (2, 2)], 75 + 3 => vec![(0, 0), (1, 1), (2, 2)], 76 + 4 => vec![(0, 0), (0, 2), (2, 2), (2, 0)], 77 + 5 => vec![(0, 0), (0, 2), (1, 1), (2, 2), (2, 0)], 78 + 6 => vec![(0, 0), (0, 1), (0, 2), (2, 0), (2, 1), (2, 2)], 79 + _ => panic!("These dices are six-sided"), 80 + }, 81 + ); 82 + } 83 + 84 + pub fn iterate(canvas: &mut Canvas, rng: &mut impl Rng) { 85 + canvas.layer_or_empty("connections").clear(); 86 + 87 + let connection_groups_count = (1..=5).choose(rng).unwrap(); 88 + 89 + let dice_dots: Vec<_> = canvas 90 + .layer("dices") 91 + .unwrap() 92 + .objects_sorted_owned() 93 + .collect(); 94 + 95 + let dice_dots_positions: Vec<_> = dice_dots 96 + .iter() 97 + .map(|(_, dot)| dot.region().center()) 98 + .collect(); 99 + 100 + let mut group_seeds = vec![*dice_dots_positions.choose(rng).unwrap()]; 101 + 102 + for _ in 1..connection_groups_count { 103 + let seed = dice_dots_positions 104 + .iter() 105 + .filter(|p| { 106 + group_seeds 107 + .iter() 108 + .all(|seed| p.distance_to(seed).norm() >= 5.0) 109 + }) 110 + .choose(rng) 111 + .cloned(); 112 + 113 + if let Some(seed) = seed { 114 + group_seeds.push(seed); 115 + } 116 + } 117 + 118 + for &seed in &group_seeds { 119 + canvas 120 + .layer_or_empty("debug") 121 + .add_anon(SmallCircle(seed).colored(Red)); 122 + } 123 + 124 + for &seed in &group_seeds { 125 + let mut point_before = seed; 126 + 127 + let group_points: Vec<_> = dice_dots 128 + .iter() 129 + .map(|(_, o)| o) 130 + .filter(|o| { 131 + let closest_seed = group_seeds 132 + .iter() 133 + .min_by_key(|&&s| { 134 + (o.shape.position().as_centered().distance_to(&s).norm() 135 + * 100.0) as usize 136 + }) 137 + .unwrap(); 138 + 139 + closest_seed == &seed 140 + }) 141 + .filter(|o| o.shape.position().as_centered() != seed) 142 + .map(|o| o.shape.position().as_centered()) 143 + .collect(); 144 + 145 + let mut points_to_connect = group_points.clone(); 146 + 147 + for &point in &points_to_connect { 148 + canvas 149 + .layer("debug") 150 + .unwrap() 151 + .add_anon(Line(point, seed, 0.5).colored(Gray)); 152 + } 153 + 154 + let mut backtrack_attempts = 0; 155 + 156 + while !points_to_connect.is_empty() { 157 + let candidates: Vec<_> = points_to_connect 158 + .iter() 159 + .filter(|&&p| { 160 + !canvas.layer_or_empty("connections").has_object_that( 161 + |line| match line.shape { 162 + ref line @ Line(..) => { 163 + !line.meets_endpoint_of_line(point_before) 164 + && !line.meets_endpoint_of_line(p) 165 + && Line(point_before, p, 1.0) 166 + .intersects_with(line.clone()) 167 + } 168 + _ => false, 169 + }, 170 + ) 171 + }) 172 + .collect(); 173 + 174 + let next_point = candidates 175 + .chunk_by(|a, b| { 176 + point_before.distance_to(a).norm() as usize 177 + == point_before.distance_to(b).norm() as usize 178 + }) 179 + .next() 180 + .and_then(|closest_points| closest_points.choose(rng)) 181 + .cloned() 182 + .cloned(); 183 + 184 + if let Some(next_point) = next_point { 185 + // println!( 186 + // "{seed} Connecting {point_before} to {next_point} from {points_to_connect:?}" 187 + // ); 188 + canvas 189 + .layer_unchecked("connections") 190 + .add_anon(Line(point_before, next_point, 3.0).colored(Cyan)); 191 + points_to_connect.retain(|&p| p != next_point); 192 + point_before = next_point; 193 + } else { 194 + canvas 195 + .layer_unchecked("debug") 196 + .add_anon(SmallCircle(point_before).colored(Orange)); 197 + 198 + for &candidate in &points_to_connect { 199 + let collision = canvas 200 + .layer_unchecked("connections") 201 + .find_object(|line| match line.shape { 202 + ref line @ Line(..) => { 203 + !line.meets_endpoint_of_line(point_before) 204 + && !line.meets_endpoint_of_line(candidate) 205 + && Line(point_before, candidate, 1.0) 206 + .intersects_with(line.clone()) 207 + } 208 + _ => false, 209 + }) 210 + .cloned(); 211 + 212 + if let Some(Object { 213 + shape: Line(s, e, _), 214 + .. 215 + }) = collision 216 + { 217 + // println!( 218 + // "{seed} Could not connect {point_before} to {candidate}, collides with line {s} to {e}" 219 + // ); 220 + 221 + canvas 222 + .layer_unchecked("debug") 223 + .add_anon(Line(s, e, 1.0).colored(Orange)); 224 + } 225 + } 226 + 227 + if backtrack_attempts > 10 { 228 + // println!( 229 + // "{seed} Giving up on this group after {backtrack_attempts} backtrack attempts" 230 + // ); 231 + break; 232 + } 233 + 234 + backtrack_attempts += 1; 235 + point_before = group_points.iter().choose(rng).cloned().unwrap(); 236 + // println!("{seed} Trying again from {point_before}"); 237 + } 238 + } 239 + } 240 + 241 + canvas.reorder_layers(vec!["debug", "dices", "connections", "dices_bg"]); 242 + 243 + canvas.remove_layer("debug"); 244 + 245 + canvas 246 + .render_to_svg_file("result.svg") 247 + .expect("Could not write SVG"); 248 + } 249 + 250 + trait MyCanvas { 251 + fn add_dice( 252 + &mut self, 253 + place_at: (usize, usize), 254 + dots_at: Vec<(usize, usize)>, 255 + ); 256 + } 257 + 258 + impl MyCanvas for Canvas { 259 + fn add_dice( 260 + &mut self, 261 + place_at: (usize, usize), 262 + dots_at: Vec<(usize, usize)>, 263 + ) { 264 + // println!("Adding dice at {place_at:?} with dots at {dots_at:?}"); 265 + for (x, y) in dots_at { 266 + let at = Point::Center(x, y) 267 + .translated_by(Point::from(place_at).coords_from(&DICES_GRID)); 268 + 269 + self.layer_or_empty("dices") 270 + .add_anon(SmallCircle(at).colored(White)); 271 + } 272 + 273 + let dicebox = Region::from_topleft( 274 + Point::from(place_at).coords_from(&DICES_GRID), 275 + DICES_GRID.size(), 276 + ) 277 + .unwrap(); 278 + 279 + self.layer_or_empty("dices_bg").add_many_anon( 280 + dicebox 281 + .corners() 282 + .iter() 283 + .circular_tuple_windows() 284 + .map(|(&s, &e)| Line(s, e, 0.5).colored(Gray)), 285 + ); 286 + } 287 + } 288 + 289 + pub struct Grid(pub usize, pub usize); 290 + 291 + trait GridSnappable { 292 + // fn snapped_to(&self, grid: &Grid) -> Self; 293 + // fn snap_to(&mut self, grid: &Grid); 294 + fn coords_from(&self, grid: &Grid) -> Self; 295 + } 296 + 297 + impl GridSnappable for Point { 298 + fn coords_from(&self, Grid(sx, sy): &Grid) -> Self { 299 + self.with(self.x() * sx, self.y() * sy) 300 + } 301 + } 302 + 303 + impl Grid { 304 + fn size(&self) -> (usize, usize) { 305 + (self.0, self.1) 306 + } 307 + }
+2
examples/schedule-hell/src/scenes/mod.rs
··· 6 6 pub use starry_sky::starry_sky; 7 7 pub mod backbone; 8 8 pub use backbone::backbone; 9 + pub mod dices; 10 + pub use dices::dices;