├── .cargo └── config.toml ├── .gitattributes ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── bht │ ├── d │ │ ├── all.bht.ron │ │ ├── any.bht.ron │ │ ├── any_repeat.bht.ron │ │ ├── any_subtree.bht.ron │ │ ├── defaults.bht.ron │ │ ├── delay.bht.ron │ │ ├── gate_blackboard.bht.ron │ │ ├── gate_true.bht.ron │ │ ├── repeat_repeater.bht.ron │ │ ├── repeater.bht.ron │ │ ├── sequence.bht.ron │ │ ├── subtree_gate.bht.ron │ │ ├── timeout.bht.ron │ │ └── zero_timers.bht.ron │ └── u │ │ ├── basketball.bht.ron │ │ ├── bt_first_created.bht.ron │ │ └── bt_second_created.bht.ron ├── fonts │ ├── DejaVuSans.ttf │ ├── FiraMono-Medium.ttf │ ├── FiraSans-Bold.ttf │ ├── JetBrainsMono-ExtraLight.ttf │ └── UbuntuMono-R.ttf ├── models │ ├── character │ │ ├── X_Bot │ │ │ ├── Character.fbx │ │ │ ├── Character.glb │ │ │ ├── Goalkeeper_Idle.fbx │ │ │ ├── Goalkeeper_Idle.glb │ │ │ ├── Martelo_Do_Chau.fbx │ │ │ └── Martelo_Do_Chau.glb │ │ ├── Y_Bot │ │ │ ├── Character.fbx │ │ │ ├── Character.glb │ │ │ ├── Goalkeeper_Idle.fbx │ │ │ └── Goalkeeper_Idle.glb │ │ └── rig.txt │ ├── cube │ │ ├── cube.bin │ │ └── cube.gltf │ ├── metric_box │ │ ├── albedo_metric_box_1x1.png │ │ ├── metric_box_1x1.bin │ │ ├── metric_box_1x1.blend │ │ └── metric_box_1x1.gltf │ ├── metric_plane │ │ ├── albedo_metric_plane_8x8.png │ │ ├── metric_plane_8x8.bin │ │ ├── metric_plane_8x8.blend │ │ └── metric_plane_8x8.gltf │ ├── monkey │ │ └── Monkey.gltf │ └── sphere │ │ ├── sphere.bin │ │ └── sphere.gltf ├── scripts │ ├── false.rhai │ └── true.rhai ├── shaders │ ├── lines.wgsl │ ├── pointcloud.wgsl │ ├── video_material.wgsl │ └── voxels.wgsl ├── textures │ ├── circle_alpha.png │ └── metric_512x512.png ├── videos │ ├── mov_bbb.mp4 │ ├── robot.gif │ ├── robot.webp │ └── video.html └── web │ ├── sound.js │ └── styles.css ├── crates ├── egui_node_graph │ ├── Cargo.toml │ └── src │ │ ├── color_hex_utils.rs │ │ ├── editor_ui.rs │ │ ├── error.rs │ │ ├── graph.rs │ │ ├── graph_impls.rs │ │ ├── id_type.rs │ │ ├── index_impls.rs │ │ ├── lib.rs │ │ ├── node_finder.rs │ │ ├── traits.rs │ │ ├── ui_state.rs │ │ └── utils.rs ├── simula_action │ ├── Cargo.toml │ ├── simula_action_macro │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── src │ │ ├── action.rs │ │ ├── axis.rs │ │ └── lib.rs │ └── tests │ │ └── action.rs ├── simula_behavior │ ├── Cargo.toml │ ├── README.md │ ├── simula_behavior_macro │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── src │ │ ├── actions │ │ │ ├── debug.rs │ │ │ ├── mod.rs │ │ │ └── wait.rs │ │ ├── asset.rs │ │ ├── composites │ │ │ ├── all.rs │ │ │ ├── any.rs │ │ │ ├── mod.rs │ │ │ ├── selector.rs │ │ │ └── sequencer.rs │ │ ├── decorators │ │ │ ├── delay.rs │ │ │ ├── guard.rs │ │ │ ├── identity.rs │ │ │ ├── inverter.rs │ │ │ ├── mod.rs │ │ │ ├── repeater.rs │ │ │ ├── subtree.rs │ │ │ ├── succeeder.rs │ │ │ └── timeout.rs │ │ ├── inspector │ │ │ ├── behavior.rs │ │ │ ├── graph.rs │ │ │ ├── menu.rs │ │ │ ├── mod.rs │ │ │ ├── property.rs │ │ │ ├── utils.rs │ │ │ └── window.rs │ │ ├── lib.rs │ │ ├── property.rs │ │ ├── protocol.rs │ │ ├── server.rs │ │ └── test.rs │ └── tests │ │ ├── all.rs │ │ ├── any.rs │ │ ├── identity.rs │ │ ├── inverter.rs │ │ ├── repeater.rs │ │ ├── selector.rs │ │ ├── sequencer.rs │ │ └── succeeder.rs ├── simula_cad │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── shapes │ │ ├── mod.rs │ │ └── star.rs ├── simula_camera │ ├── Cargo.toml │ ├── flycam.rs │ ├── lib.rs │ └── orbitcam.rs ├── simula_core │ ├── Cargo.toml │ └── src │ │ ├── ease.rs │ │ ├── epath.rs │ │ ├── force_graph.rs │ │ ├── lib.rs │ │ ├── map_range.rs │ │ ├── prng.rs │ │ ├── ray.rs │ │ ├── signal │ │ ├── controller.rs │ │ ├── generator.rs │ │ └── mod.rs │ │ └── spline.rs ├── simula_inspector │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── world.rs ├── simula_octree │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── plen.rs ├── simula_script │ ├── Cargo.toml │ └── src │ │ ├── asset.rs │ │ └── lib.rs ├── simula_sdf │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ ├── ndshape.rs │ │ └── surface.rs ├── simula_surrealdb │ ├── Cargo.toml │ ├── src │ │ ├── client.rs │ │ ├── lib.rs │ │ └── server.rs │ └── test.srqlnb ├── simula_video │ ├── Cargo.toml │ └── src │ │ ├── gif.rs │ │ ├── gst_sink.rs │ │ ├── gst_src.rs │ │ ├── lib.rs │ │ ├── material.rs │ │ ├── raw_src.rs │ │ ├── rt.rs │ │ ├── video.js │ │ ├── video.rs │ │ └── webp.rs └── simula_viz │ ├── Cargo.toml │ └── src │ ├── axes.rs │ ├── ease.rs │ ├── follow_ui.rs │ ├── force_graph.rs │ ├── grid.rs │ ├── lib.rs │ ├── lines.rs │ ├── lookat.rs │ ├── pointcloud.rs │ ├── rod.rs │ ├── signal.rs │ ├── spline.rs │ └── voxel.rs ├── docs ├── Simula__main.gif ├── behaviors.gif ├── control_signals.png ├── easings_functions.png ├── force_graph_function.png ├── p2p.png ├── signal_generators.png ├── splash.png └── splash_old.png ├── export.sh ├── run.sh ├── rustfmt.toml ├── src └── lib.rs └── tools ├── character_physics ├── Cargo.toml ├── assets └── src │ └── main.rs ├── empty ├── Cargo.toml ├── assets ├── index.html └── src │ └── main.rs ├── sandbox ├── Cargo.toml ├── Trunk.toml ├── assets ├── index.html └── src │ ├── main.rs │ └── monkey.rs ├── scripting ├── Cargo.toml ├── Trunk.toml ├── assets ├── index.html └── src │ ├── derived_behavior.rs │ ├── implemented_behavior.rs │ └── main.rs ├── sdf_csg ├── Cargo.toml ├── assets └── src │ └── main.rs ├── splines ├── Cargo.toml ├── assets └── src │ └── main.rs ├── surreal ├── Cargo.toml ├── Trunk.toml ├── assets ├── index.html └── src │ └── main.rs └── video_player ├── Cargo.toml ├── assets └── src └── main.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.wasm32-unknown-unknown] 2 | runner = "wasm-server-runner" 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | assets/adroid-res/** filter=lfs diff=lfs merge=lfs -text 2 | assets/branding/** filter=lfs diff=lfs merge=lfs -text 3 | assets/fonts/** filter=lfs diff=lfs merge=lfs -text 4 | assets/models/** filter=lfs diff=lfs merge=lfs -text 5 | assets/sounds/** filter=lfs diff=lfs merge=lfs -text 6 | assets/textures/** filter=lfs diff=lfs merge=lfs -text 7 | assets/videos/** filter=lfs diff=lfs merge=lfs -text 8 | 9 | *.glb filter=lfs diff=lfs merge=lfs -text 10 | *.bin filter=lfs diff=lfs merge=lfs -text 11 | *.jpg filter=lfs diff=lfs merge=lfs -text 12 | *.png filter=lfs diff=lfs merge=lfs -text 13 | *.kra filter=lfs diff=lfs merge=lfs -text 14 | *.gif filter=lfs diff=lfs merge=lfs -text 15 | *.mp4 filter=lfs diff=lfs merge=lfs -text 16 | *.webp filter=lfs diff=lfs merge=lfs -text 17 | *.blend filter=lfs diff=lfs merge=lfs -text 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .DS_Store 3 | /.vscode 4 | dist/ 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simula" 3 | version = "0.6.0" 4 | edition = "2021" 5 | 6 | [workspace] 7 | members = ["crates/*", "tools/*"] 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) Alex Rozgo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simula - Simbotic 2 | 3 | ## 3D engine for vectorizing meta-layers for XR experiences 4 | So much of AI is about compressing reality to a small vector space, like a video game in reverse. 5 | 6 | ![Simula splash](docs/splash.png) 7 | 8 | ![Simula splash gif](docs/Simula__main.gif) 9 | 10 | ### Behaviors AI 11 | ![Simula splash gif](docs/behaviors.gif) 12 | 13 | ### Easings Function 14 | 15 | ![Easings Function](docs/easings_functions.png) 16 | 17 | ### Signal Generators 18 | 19 | ![Signal Generators](docs/signal_generators.png) 20 | 21 | ### Control Signals 22 | 23 | ![Control Signals](docs/control_signals.png) 24 | 25 | ### Force Graph Function 26 | 27 | ![Force Graph Function](docs/force_graph_function.png) 28 | 29 | ## WASM 30 | To add WASM support to your Rust installation. Using Rustup: 31 | ``` 32 | rustup target install wasm32-unknown-unknown 33 | ``` 34 | 35 | Now, to run your project in the browser. 36 | ``` 37 | wasm-server-runner 38 | ``` 39 | 40 | The easiest and most automatic way to get started is the wasm-server-runner tool. 41 | 42 | Install it: 43 | ``` 44 | cargo install wasm-server-runner 45 | ``` 46 | 47 | Set up cargo to use it, in `.cargo/config.toml` (in your project folder, or globally in your user home folder): 48 | ``` 49 | [target.wasm32-unknown-unknown] 50 | runner = "wasm-server-runner" 51 | ``` 52 | 53 | Alternatively, you can also set the runner using an environment variable: 54 | 55 | ``` 56 | export CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-server-runner 57 | ``` 58 | 59 | Now you can just run your simulation with: 60 | ``` 61 | cargo run --target wasm32-unknown-unknown 62 | ``` 63 | 64 | It will automatically run a minimal local webserver and open your simulation in your browser. 65 | 66 | ### Trunk 67 | ``` 68 | trunk --config tools/sandbox/Trunk.toml serve 69 | ``` 70 | 71 | ## GStreamer 72 | 73 | ### Ubuntu 74 | ``` 75 | cargo run --release -p sandbox --features gif,gst 76 | ``` 77 | 78 | ### OSX 79 | To get started with GStreamer in macOS, both the runtime and development packages, where they must be installed via the official GStreamer website: https://gstreamer.freedesktop.org/download/#macos 80 | 81 | In addition to install GStreamer, also it’s necessary install GStreamer plugins via Homebrew: 82 | ``` 83 | brew install gst-plugins-base 84 | ``` 85 | ``` 86 | brew install gst-plugins-rs 87 | ``` 88 | After installation, you also need to install `pkg-config` (e.g. via Homebrew) and set the `PKG_CONFIG_PATH` environment variable 89 | ``` 90 | export PKG_CONFIG_PATH="/Library/Frameworks/GStreamer.framework/Versions/1.0/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" 91 | ``` 92 | And finally run this command in the projects terminal 93 | ``` 94 | DYLD_LIBRARY_PATH=/Library/Frameworks/GStreamer.framework/Versions/1.0/lib cargo run --release -p sandbox --features gif,gst 95 | ``` 96 | 97 | ## SurrealDB 98 | 99 | Connect to a surreal db, or launch a local surreal repo: 100 | ``` 101 | cargo run --release -- start -u root -p root 102 | ``` 103 | 104 | SQL Repl 105 | ``` 106 | ./target/release/surreal sql -e ws://127.0.0.1:8000 -u root -p root --ns default --db default --pretty 107 | ``` 108 | -------------------------------------------------------------------------------- /assets/bht/d/all.bht.ron: -------------------------------------------------------------------------------- 1 | ("Loop Forever", Repeater(( 2 | repeat: Forever, 3 | )), [ 4 | ("Wait and do", Sequencer(( 5 | random: false, 6 | )), [ 7 | ("Wait a bit", Wait(( 8 | duration: ( 9 | prop: Value(5.0), 10 | ), 11 | fail: ( 12 | prop: Value(false), 13 | ), 14 | )), [], ( 15 | pos: (600.0, 0.0), 16 | )), 17 | ("⇉ All", All(()), [ 18 | ("Do a thing", Debug(( 19 | message: ( 20 | prop: Value(""), 21 | ), 22 | fail: ( 23 | prop: Value(false), 24 | ), 25 | duration: ( 26 | prop: Value(5.0), 27 | ), 28 | )), [], ( 29 | pos: (800.0, 200.0), 30 | )), 31 | ("Do another", Debug(( 32 | message: ( 33 | prop: Value(""), 34 | ), 35 | fail: ( 36 | prop: Value(false), 37 | ), 38 | duration: ( 39 | prop: Value(2.0), 40 | ), 41 | )), [], ( 42 | pos: (800.0, 400.0), 43 | )), 44 | ("Do more", Debug(( 45 | message: ( 46 | prop: Value(""), 47 | ), 48 | fail: ( 49 | prop: Value(false), 50 | ), 51 | duration: ( 52 | prop: Value(8.0), 53 | ), 54 | )), [], ( 55 | pos: (800.0, 600.0), 56 | )), 57 | ("Wait and do", Sequencer(( 58 | random: false, 59 | )), [ 60 | ("Wait a bit", Wait(( 61 | duration: ( 62 | prop: Value(2.0), 63 | ), 64 | fail: ( 65 | prop: Value(false), 66 | ), 67 | )), [], ( 68 | pos: (1000.0, 800.0), 69 | )), 70 | ("⇉ All", All(()), [ 71 | ("Do a thing", Debug(( 72 | message: ( 73 | prop: Value(""), 74 | ), 75 | fail: ( 76 | prop: Value(false), 77 | ), 78 | duration: ( 79 | prop: Value(5.0), 80 | ), 81 | )), [], ( 82 | pos: (1200.0, 1000.0), 83 | )), 84 | ("Do another", Debug(( 85 | message: ( 86 | prop: Value(""), 87 | ), 88 | fail: ( 89 | prop: Value(false), 90 | ), 91 | duration: ( 92 | prop: Value(2.0), 93 | ), 94 | )), [], ( 95 | pos: (1200.0, 1200.0), 96 | )), 97 | ("Do more", Debug(( 98 | message: ( 99 | prop: Value(""), 100 | ), 101 | fail: ( 102 | prop: Value(false), 103 | ), 104 | duration: ( 105 | prop: Value(8.0), 106 | ), 107 | )), [], ( 108 | pos: (1200.0, 1400.0), 109 | )), 110 | ], ( 111 | pos: (1000.0, 1000.0), 112 | )), 113 | ], ( 114 | pos: (800.0, 800.0), 115 | )), 116 | ], ( 117 | pos: (600.0, 200.0), 118 | )), 119 | ], ( 120 | pos: (400.0, 0.0), 121 | )), 122 | ], ( 123 | pos: (200.0, 0.0), 124 | )) -------------------------------------------------------------------------------- /assets/bht/d/any_subtree.bht.ron: -------------------------------------------------------------------------------- 1 | ("Repeat Forever", Repeater(( 2 | repeat: Forever, 3 | )), [ 4 | ("Wait and do", Sequencer(( 5 | random: false, 6 | )), [ 7 | ("Wait a bit", Wait(( 8 | duration: ( 9 | prop: Value(5.0), 10 | ), 11 | fail: ( 12 | prop: Value(false), 13 | ), 14 | )), [], ( 15 | pos: (600.0, 0.0), 16 | )), 17 | ("Run until any good", Any(()), [ 18 | ("Do a thing", Debug(( 19 | message: ( 20 | prop: Value(""), 21 | ), 22 | fail: ( 23 | prop: Value(false), 24 | ), 25 | duration: ( 26 | prop: Value(5.0), 27 | ), 28 | )), [], ( 29 | pos: (800.0, 200.0), 30 | )), 31 | ("Do another", Debug(( 32 | message: ( 33 | prop: Value(""), 34 | ), 35 | fail: ( 36 | prop: Value(true), 37 | ), 38 | duration: ( 39 | prop: Value(2.0), 40 | ), 41 | )), [], ( 42 | pos: (800.0, 400.0), 43 | )), 44 | ("Do more", Debug(( 45 | message: ( 46 | prop: Value(""), 47 | ), 48 | fail: ( 49 | prop: Value(false), 50 | ), 51 | duration: ( 52 | prop: Value(8.0), 53 | ), 54 | )), [], ( 55 | pos: (800.0, 600.0), 56 | )), 57 | ("Wait and do", Sequencer(( 58 | random: false, 59 | )), [ 60 | ("Wait a bit", Wait(( 61 | duration: ( 62 | prop: Value(2.0), 63 | ), 64 | fail: ( 65 | prop: Value(false), 66 | ), 67 | )), [], ( 68 | pos: (1000.0, 800.0), 69 | )), 70 | ("Run until any good", Any(()), [ 71 | ("Do a thing", Debug(( 72 | message: ( 73 | prop: Value(""), 74 | ), 75 | fail: ( 76 | prop: Value(false), 77 | ), 78 | duration: ( 79 | prop: Value(5.0), 80 | ), 81 | )), [], ( 82 | pos: (1200.0, 1000.0), 83 | )), 84 | ("Do another", Debug(( 85 | message: ( 86 | prop: Value(""), 87 | ), 88 | fail: ( 89 | prop: Value(true), 90 | ), 91 | duration: ( 92 | prop: Value(2.0), 93 | ), 94 | )), [], ( 95 | pos: (1200.0, 1200.0), 96 | )), 97 | ("Do more", Debug(( 98 | message: ( 99 | prop: Value(""), 100 | ), 101 | fail: ( 102 | prop: Value(false), 103 | ), 104 | duration: ( 105 | prop: Value(8.0), 106 | ), 107 | )), [], ( 108 | pos: (1200.0, 1400.0), 109 | )), 110 | ], ( 111 | pos: (1000.0, 1000.0), 112 | )), 113 | ], ( 114 | pos: (800.0, 800.0), 115 | )), 116 | ("Wait a bit", Wait(( 117 | duration: ( 118 | prop: Value(5.0), 119 | ), 120 | fail: ( 121 | prop: Value(false), 122 | ), 123 | )), [], ( 124 | pos: (800.0, 1600.0), 125 | )), 126 | ("🏃 Subtree", Subtree(( 127 | asset: "bht/d/defaults.bht.ron", 128 | unload: true, 129 | )), [], ( 130 | pos: (739.5188, 1792.3486), 131 | )), 132 | ], ( 133 | pos: (600.0, 200.0), 134 | )), 135 | ], ( 136 | pos: (400.0, 0.0), 137 | )), 138 | ], ( 139 | pos: (200.0, 0.0), 140 | )) -------------------------------------------------------------------------------- /assets/bht/d/defaults.bht.ron: -------------------------------------------------------------------------------- 1 | ("Simple sequence", Sequencer(( 2 | random: false, 3 | )), [ 4 | ("Dont fail", Debug(( 5 | message: ( 6 | prop: Value(""), 7 | ), 8 | fail: ( 9 | prop: Value(false), 10 | ), 11 | duration: ( 12 | prop: Value(0.0), 13 | ), 14 | )), [], ( 15 | pos: (400.0, 0.0), 16 | )), 17 | ("Take some time", Wait(( 18 | duration: ( 19 | prop: Value(1.5), 20 | ), 21 | fail: ( 22 | prop: Value(false), 23 | ), 24 | )), [], ( 25 | pos: (400.0, 200.0), 26 | )), 27 | ("Say Hello", Debug(( 28 | message: ( 29 | prop: Value("Hello World"), 30 | ), 31 | fail: ( 32 | prop: Value(false), 33 | ), 34 | duration: ( 35 | prop: Value(0.0), 36 | ), 37 | )), [], ( 38 | pos: (400.0, 400.0), 39 | )), 40 | ], ( 41 | pos: (200.0, 0.0), 42 | )) -------------------------------------------------------------------------------- /assets/bht/d/delay.bht.ron: -------------------------------------------------------------------------------- 1 | ("Loop forever", Repeater(( 2 | repeat: Forever, 3 | )), [ 4 | ("Delay", Delay(( 5 | duration: ( 6 | prop: Value(5.0), 7 | ), 8 | )), [ 9 | ("Do a thing", Debug(( 10 | message: ( 11 | prop: Value("I\'m doing a great thing!"), 12 | ), 13 | fail: ( 14 | prop: Value(false), 15 | ), 16 | duration: ( 17 | prop: Value(0.0), 18 | ), 19 | )), [], ( 20 | pos: (600.0, 0.0), 21 | )), 22 | ], ( 23 | pos: (400.0, 0.0), 24 | )), 25 | ], ( 26 | pos: (200.0, 0.0), 27 | )) -------------------------------------------------------------------------------- /assets/bht/d/gate_blackboard.bht.ron: -------------------------------------------------------------------------------- 1 | ("Loop guard", Repeater(( 2 | repeat: Forever, 3 | )), [ 4 | ("Delay", Delay(( 5 | duration: ( 6 | prop: Value(5.0), 7 | ), 8 | )), [ 9 | ("Can do?", Guard(( 10 | condition: ( 11 | prop: Eval( 12 | eval: "print(blackboard.state); blackboard.state = blackboard.state + 1; blackboard.state < 3", 13 | ), 14 | ), 15 | )), [ 16 | ("Do a thing", Debug(( 17 | message: ( 18 | prop: Value("I\'m doing a thing"), 19 | ), 20 | fail: ( 21 | prop: Value(false), 22 | ), 23 | duration: ( 24 | prop: Value(0.0), 25 | ), 26 | )), [], ( 27 | pos: (800.0, 0.0), 28 | )), 29 | ], ( 30 | pos: (600.0, 0.0), 31 | )), 32 | ], ( 33 | pos: (400.0, 0.0), 34 | )), 35 | ], ( 36 | pos: (200.0, 0.0), 37 | )) -------------------------------------------------------------------------------- /assets/bht/d/gate_true.bht.ron: -------------------------------------------------------------------------------- 1 | ("Loop Guard", Repeater(( 2 | repeat: Forever, 3 | )), [ 4 | ("Delay", Delay(( 5 | duration: ( 6 | prop: Value(5.0), 7 | ), 8 | )), [ 9 | ("Can do?", Guard(( 10 | condition: ( 11 | prop: Eval( 12 | eval: "2 + 2 == 4", 13 | ), 14 | ), 15 | )), [ 16 | ("Do a thing", Debug(( 17 | message: ( 18 | prop: Value("I\'m doing a thing"), 19 | ), 20 | fail: ( 21 | prop: Value(false), 22 | ), 23 | duration: ( 24 | prop: Value(0.0), 25 | ), 26 | )), [], ( 27 | pos: (800.0, 0.0), 28 | )), 29 | ], ( 30 | pos: (600.0, 0.0), 31 | )), 32 | ], ( 33 | pos: (400.0, 0.0), 34 | )), 35 | ], ( 36 | pos: (200.0, 0.0), 37 | )) -------------------------------------------------------------------------------- /assets/bht/d/repeat_repeater.bht.ron: -------------------------------------------------------------------------------- 1 | ("Loop forever", Repeater(( 2 | repeat: Times(10), 3 | )), [ 4 | ("Repeat List", Any(()), [ 5 | ("Repeater 1", Repeater(( 6 | repeat: Times(3), 7 | )), [ 8 | ("Delay", Delay(( 9 | duration: ( 10 | prop: Value(1.0), 11 | ), 12 | )), [ 13 | ("Do a thing 1", Debug(( 14 | message: ( 15 | prop: Value("Doing #1"), 16 | ), 17 | fail: ( 18 | prop: Value(false), 19 | ), 20 | duration: ( 21 | prop: Value(0.0), 22 | ), 23 | )), [], ( 24 | pos: (1000.0, 0.0), 25 | )), 26 | ], ( 27 | pos: (800.0, 0.0), 28 | )), 29 | ], ( 30 | pos: (600.0, 0.0), 31 | )), 32 | ("Repeater 2", Repeater(( 33 | repeat: Times(5), 34 | )), [ 35 | ("Delay", Delay(( 36 | duration: ( 37 | prop: Value(1.0), 38 | ), 39 | )), [ 40 | ("Do a thing 2", Debug(( 41 | message: ( 42 | prop: Value("Doing #2"), 43 | ), 44 | fail: ( 45 | prop: Value(false), 46 | ), 47 | duration: ( 48 | prop: Value(0.0), 49 | ), 50 | )), [], ( 51 | pos: (1000.0, 200.0), 52 | )), 53 | ], ( 54 | pos: (800.0, 200.0), 55 | )), 56 | ], ( 57 | pos: (600.0, 200.0), 58 | )), 59 | ], ( 60 | pos: (400.0, 0.0), 61 | )), 62 | ], ( 63 | pos: (200.0, 0.0), 64 | )) -------------------------------------------------------------------------------- /assets/bht/d/repeater.bht.ron: -------------------------------------------------------------------------------- 1 | ("Do a few times", Repeater(( 2 | repeat: Times(10), 3 | )), [ 4 | ("Say hi", Debug(( 5 | message: ( 6 | prop: Value("Hello, from DebugMessage0!"), 7 | ), 8 | fail: ( 9 | prop: Value(false), 10 | ), 11 | duration: ( 12 | prop: Value(0.0), 13 | ), 14 | )), [], ( 15 | pos: (400.0, 0.0), 16 | )), 17 | ], ( 18 | pos: (200.0, 0.0), 19 | )) -------------------------------------------------------------------------------- /assets/bht/d/sequence.bht.ron: -------------------------------------------------------------------------------- 1 | ("Loop forever", Repeater(( 2 | repeat: Forever, 3 | )), [ 4 | ("Do in this order", Sequencer(( 5 | random: false, 6 | )), [ 7 | ("Do a thing", Debug(( 8 | message: ( 9 | prop: Value(""), 10 | ), 11 | fail: ( 12 | prop: Value(false), 13 | ), 14 | duration: ( 15 | prop: Value(1.0), 16 | ), 17 | )), [], ( 18 | pos: (600.0, 0.0), 19 | )), 20 | ("Do another", Debug(( 21 | message: ( 22 | prop: Value(""), 23 | ), 24 | fail: ( 25 | prop: Value(false), 26 | ), 27 | duration: ( 28 | prop: Value(0.0), 29 | ), 30 | )), [], ( 31 | pos: (600.0, 200.0), 32 | )), 33 | ("Do side work", Selector(( 34 | random: true, 35 | )), [ 36 | ("A little side work", Debug(( 37 | message: ( 38 | prop: Value(""), 39 | ), 40 | fail: ( 41 | prop: Value(false), 42 | ), 43 | duration: ( 44 | prop: Value(1.0), 45 | ), 46 | )), [], ( 47 | pos: (800.0, 400.0), 48 | )), 49 | ("Flip it", Inverter(()), [ 50 | ("Another side work", Debug(( 51 | message: ( 52 | prop: Value(""), 53 | ), 54 | fail: ( 55 | prop: Value(false), 56 | ), 57 | duration: ( 58 | prop: Value(1.0), 59 | ), 60 | )), [], ( 61 | pos: (1000.0, 600.0), 62 | )), 63 | ], ( 64 | pos: (800.0, 600.0), 65 | )), 66 | ], ( 67 | pos: (600.0, 400.0), 68 | )), 69 | ("Rest for a bit", Selector(( 70 | random: true, 71 | )), [ 72 | ("Browser", Debug(( 73 | message: ( 74 | prop: Value(""), 75 | ), 76 | fail: ( 77 | prop: Value(false), 78 | ), 79 | duration: ( 80 | prop: Value(1.0), 81 | ), 82 | )), [], ( 83 | pos: (800.0, 800.0), 84 | )), 85 | ("Sleep", Debug(( 86 | message: ( 87 | prop: Value(""), 88 | ), 89 | fail: ( 90 | prop: Value(false), 91 | ), 92 | duration: ( 93 | prop: Value(3.0), 94 | ), 95 | )), [], ( 96 | pos: (800.0, 1000.0), 97 | )), 98 | ("Go on vacation", Sequencer(( 99 | random: false, 100 | )), [ 101 | ("Sit on the beach", Debug(( 102 | message: ( 103 | prop: Value(""), 104 | ), 105 | fail: ( 106 | prop: Value(false), 107 | ), 108 | duration: ( 109 | prop: Value(1.0), 110 | ), 111 | )), [], ( 112 | pos: (1000.0, 1200.0), 113 | )), 114 | ("Go back to work", Debug(( 115 | message: ( 116 | prop: Value(""), 117 | ), 118 | fail: ( 119 | prop: Value(false), 120 | ), 121 | duration: ( 122 | prop: Value(3.0), 123 | ), 124 | )), [], ( 125 | pos: (1000.0, 1400.0), 126 | )), 127 | ], ( 128 | pos: (800.0, 1200.0), 129 | )), 130 | ], ( 131 | pos: (600.0, 800.0), 132 | )), 133 | ], ( 134 | pos: (400.0, 0.0), 135 | )), 136 | ], ( 137 | pos: (200.0, 0.0), 138 | )) -------------------------------------------------------------------------------- /assets/bht/d/subtree_gate.bht.ron: -------------------------------------------------------------------------------- 1 | ("Loop forever", Repeater(( 2 | repeat: Forever, 3 | )), [ 4 | ("Delay", Delay(( 5 | duration: ( 6 | prop: Value(5.0), 7 | ), 8 | )), [ 9 | ("Subtree with gate", Subtree(( 10 | asset: "bht/d/gate_blackboard.bht.ron", 11 | unload: true, 12 | )), [], ( 13 | pos: (600.0, 0.0), 14 | )), 15 | ], ( 16 | pos: (400.0, 0.0), 17 | )), 18 | ], ( 19 | pos: (200.0, 0.0), 20 | )) -------------------------------------------------------------------------------- /assets/bht/d/timeout.bht.ron: -------------------------------------------------------------------------------- 1 | ("⇉ Any", Any(()), [ 2 | ("🕓 Timeout", Timeout(( 3 | duration: ( 4 | prop: Value(5.0), 5 | ), 6 | )), [ 7 | ("⌛ Wait", Wait(( 8 | duration: ( 9 | prop: Value(10.0), 10 | ), 11 | fail: ( 12 | prop: Value(false), 13 | ), 14 | )), [], ( 15 | pos: (600.0, 0.0), 16 | )), 17 | ], ( 18 | pos: (400.0, 0.0), 19 | )), 20 | ("⌛ Wait", Wait(( 21 | duration: ( 22 | prop: Value(10.0), 23 | ), 24 | fail: ( 25 | prop: Value(false), 26 | ), 27 | )), [], ( 28 | pos: (400.0, 200.0), 29 | )), 30 | ], ( 31 | pos: (200.0, 0.0), 32 | )) -------------------------------------------------------------------------------- /assets/bht/d/zero_timers.bht.ron: -------------------------------------------------------------------------------- 1 | ("Repeater", Repeater(( 2 | repeat: Times(0), 3 | )), [ 4 | ("⌛ Delay", Delay(( 5 | duration: ( 6 | prop: Value(5.0), 7 | ), 8 | )), [ 9 | ("⌛ Delay", Delay(( 10 | duration: ( 11 | prop: Value(0.0), 12 | ), 13 | )), [ 14 | ("➡ Sequencer", Sequencer(( 15 | random: false, 16 | )), [ 17 | ("👁 Debug", Debug(( 18 | message: ( 19 | prop: Value(""), 20 | ), 21 | fail: ( 22 | prop: Value(false), 23 | ), 24 | duration: ( 25 | prop: Value(0.0), 26 | ), 27 | )), [], ( 28 | pos: (1000.0, 0.0), 29 | )), 30 | ("⌛ Wait", Wait(( 31 | duration: ( 32 | prop: Value(0.0), 33 | ), 34 | fail: ( 35 | prop: Value(false), 36 | ), 37 | )), [], ( 38 | pos: (1000.0, 200.0), 39 | )), 40 | ], ( 41 | pos: (800.0, 0.0), 42 | )), 43 | ], ( 44 | pos: (600.0, 0.0), 45 | )), 46 | ], ( 47 | pos: (400.0, 0.0), 48 | )), 49 | ], ( 50 | pos: (200.0, 0.0), 51 | )) -------------------------------------------------------------------------------- /assets/bht/u/bt_first_created.bht.ron: -------------------------------------------------------------------------------- 1 | ("➡ Sequencer", Sequencer(( 2 | random: false, 3 | )), [ 4 | ("Maybe something else", Debug(( 5 | message: ( 6 | prop: Value("a"), 7 | ), 8 | fail: ( 9 | prop: Value(false), 10 | ), 11 | duration: ( 12 | prop: Value(0.0), 13 | ), 14 | )), [], ( 15 | pos: (400.0, 0.0), 16 | )), 17 | ("👁 Debug", Debug(( 18 | message: ( 19 | prop: Value("b"), 20 | ), 21 | fail: ( 22 | prop: Value(false), 23 | ), 24 | duration: ( 25 | prop: Value(0.0), 26 | ), 27 | )), [], ( 28 | pos: (400.0, 200.0), 29 | )), 30 | ("⌛ Wait", Wait(( 31 | duration: ( 32 | prop: Value(5.0), 33 | ), 34 | fail: ( 35 | prop: Value(false), 36 | ), 37 | )), [], ( 38 | pos: (400.0, 400.0), 39 | )), 40 | ("❓ Selector", Selector(( 41 | random: false, 42 | )), [ 43 | ("⌛ Delay", Delay(( 44 | duration: ( 45 | prop: Value(2.0), 46 | ), 47 | )), [ 48 | ("👁 Debug is cool", Debug(( 49 | message: ( 50 | prop: Value(""), 51 | ), 52 | fail: ( 53 | prop: Value(true), 54 | ), 55 | duration: ( 56 | prop: Value(0.0), 57 | ), 58 | )), [], ( 59 | pos: (800.0, 600.0), 60 | )), 61 | ], ( 62 | pos: (600.0, 600.0), 63 | )), 64 | ("⌛ Delay", Delay(( 65 | duration: ( 66 | prop: Value(5.0), 67 | ), 68 | )), [ 69 | ("👁 Debug", Debug(( 70 | message: ( 71 | prop: Value(""), 72 | ), 73 | fail: ( 74 | prop: Value(true), 75 | ), 76 | duration: ( 77 | prop: Value(0.0), 78 | ), 79 | )), [], ( 80 | pos: (800.0, 800.0), 81 | )), 82 | ], ( 83 | pos: (600.0, 800.0), 84 | )), 85 | ("⇉ All", All(()), [ 86 | ("⌛ Wait", Wait(( 87 | duration: ( 88 | prop: Value(5.0), 89 | ), 90 | fail: ( 91 | prop: Value(false), 92 | ), 93 | )), [], ( 94 | pos: (800.0, 1000.0), 95 | )), 96 | ("⌛ Wait", Wait(( 97 | duration: ( 98 | prop: Value(1.0), 99 | ), 100 | fail: ( 101 | prop: Value(false), 102 | ), 103 | )), [], ( 104 | pos: (800.0, 1200.0), 105 | )), 106 | ("⌛ Wait", Wait(( 107 | duration: ( 108 | prop: Value(3.0), 109 | ), 110 | fail: ( 111 | prop: Value(false), 112 | ), 113 | )), [], ( 114 | pos: (800.0, 1400.0), 115 | )), 116 | ], ( 117 | pos: (600.0, 1000.0), 118 | )), 119 | ], ( 120 | pos: (400.0, 600.0), 121 | )), 122 | ("⌛ Wait", Wait(( 123 | duration: ( 124 | prop: Value(5.0), 125 | ), 126 | fail: ( 127 | prop: Value(false), 128 | ), 129 | )), [], ( 130 | pos: (400.0, 1600.0), 131 | )), 132 | ], ( 133 | pos: (200.0, 0.0), 134 | )) -------------------------------------------------------------------------------- /assets/bht/u/bt_second_created.bht.ron: -------------------------------------------------------------------------------- 1 | ("❓ Selector", Selector(( 2 | random: false, 3 | )), [ 4 | ("⌛ Delay", Delay(( 5 | duration: ( 6 | prop: Value(0.0), 7 | ), 8 | )), [ 9 | ("👁 Debug", Debug(( 10 | message: ( 11 | prop: Value("pepe"), 12 | ), 13 | fail: ( 14 | prop: Value(false), 15 | ), 16 | duration: ( 17 | prop: Value(0.0), 18 | ), 19 | )), [], ( 20 | pos: (600.0, 0.0), 21 | )), 22 | ], ( 23 | pos: (400.0, 0.0), 24 | )), 25 | ("~ Inverter", Inverter(()), [], ( 26 | pos: (400.0, 200.0), 27 | )), 28 | ], ( 29 | pos: (200.0, 0.0), 30 | )) -------------------------------------------------------------------------------- /assets/fonts/DejaVuSans.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7da195a74c55bef988d0d48f9508bd5d849425c1770dba5d7bfc6ce9ed848954 3 | size 757076 4 | -------------------------------------------------------------------------------- /assets/fonts/FiraMono-Medium.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5f9173ce3d05fadef74c7eed06570d54e4f75bd0cd9860726fb2987a7f848292 3 | size 173516 4 | -------------------------------------------------------------------------------- /assets/fonts/FiraSans-Bold.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:12b632bf96ea4e760691f345ef7743c549ca387a018681e11094fcf6146244f1 3 | size 438028 4 | -------------------------------------------------------------------------------- /assets/fonts/JetBrainsMono-ExtraLight.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8391e7ec13e8ba758c1838f56bccd973228ccf4dc74aa5bffe9525b9147b12f8 3 | size 274144 4 | -------------------------------------------------------------------------------- /assets/fonts/UbuntuMono-R.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b35dd9d2131d5d83a9b87fe9ad22c6288fa3d17688d43302c14da29812417d63 3 | size 205748 4 | -------------------------------------------------------------------------------- /assets/models/character/X_Bot/Character.fbx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0f521e8b4c780b7ce40b5f83715e060f24a7fd89896887165b4c5d23df901175 3 | size 1750032 4 | -------------------------------------------------------------------------------- /assets/models/character/X_Bot/Character.glb: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8a56f7385469cf10d2d58dab10b79f207d7d95df95adc3baab98bcdf6462386c 3 | size 1924348 4 | -------------------------------------------------------------------------------- /assets/models/character/X_Bot/Goalkeeper_Idle.fbx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9d10ce165146be3fedc975cb5c6905fb48b96f6148b9a0dc1d5c212d19f811bb 3 | size 672464 4 | -------------------------------------------------------------------------------- /assets/models/character/X_Bot/Goalkeeper_Idle.glb: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:86b8e14487e2e8ab81f4e34b2d1b53fc600fe8bd15996c4710624b6aafe723f9 3 | size 149120 4 | -------------------------------------------------------------------------------- /assets/models/character/X_Bot/Martelo_Do_Chau.fbx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ff50379a363fca983df2fed009b103ff10d8eebef0c43cf96faa6cf8393fe87a 3 | size 607088 4 | -------------------------------------------------------------------------------- /assets/models/character/X_Bot/Martelo_Do_Chau.glb: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:78a4d2530675c93e2e8e38962bfd40c4f873c863a7232982426d911a39989f7b 3 | size 108352 4 | -------------------------------------------------------------------------------- /assets/models/character/Y_Bot/Character.fbx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:926b4155cb6e9925f32ffb42dbaa2e90916aac5a51f0faa2ee636981f2e4201f 3 | size 1982368 4 | -------------------------------------------------------------------------------- /assets/models/character/Y_Bot/Character.glb: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5994be1f82f41f39fd013f3e155479c80fcad2fae89f3c43a736d9f2bb401dfd 3 | size 2348840 4 | -------------------------------------------------------------------------------- /assets/models/character/Y_Bot/Goalkeeper_Idle.fbx: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8fe5d9aa8f0b2df0ac89f359e412a7cf0129323e398fb3fe8c0b931fdfa8a2c3 3 | size 671184 4 | -------------------------------------------------------------------------------- /assets/models/character/Y_Bot/Goalkeeper_Idle.glb: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d911cbf8531241cc9f8e8d52b68f8532b66b0b09f61bff2d7b3bdb772aa4387c 3 | size 149256 4 | -------------------------------------------------------------------------------- /assets/models/character/rig.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5b882aaaf3f43ad67b05c889e7c5a04adf27c2c145d5a66d26919949fb0fbfad 3 | size 2029 4 | -------------------------------------------------------------------------------- /assets/models/cube/cube.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:60f0cc476d265c1fff27ac1e8bbcd6faa1f0fc05b55506503ed2277be9a14952 3 | size 840 4 | -------------------------------------------------------------------------------- /assets/models/cube/cube.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c0accae58581306ca98348c0ed9efbe82597426c198a95dc292407fa038083bf 3 | size 2667 4 | -------------------------------------------------------------------------------- /assets/models/metric_box/albedo_metric_box_1x1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dd7f655bdfa59419367b985c68a1caaaa54139c530f23f83ef334f8a75b2ca80 3 | size 4163 4 | -------------------------------------------------------------------------------- /assets/models/metric_box/metric_box_1x1.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7ec123e9c63263e8d0231c4e2ac8196bee66f11619ba7c38ed5c10c0fe65f2ff 3 | size 1224 4 | -------------------------------------------------------------------------------- /assets/models/metric_box/metric_box_1x1.blend: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:60e09e0e23507d74e84b39afe83bfcd69f7bebb5bf736171003abef19f379f88 3 | size 631252 4 | -------------------------------------------------------------------------------- /assets/models/metric_box/metric_box_1x1.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:43b51f1b41eea8cbefc33a706ef84bbb8e6cb44d2ada30e504e08f01ad98086a 3 | size 3298 4 | -------------------------------------------------------------------------------- /assets/models/metric_plane/albedo_metric_plane_8x8.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3e02b4a4d0a909b5037b8f48eb234a9a339a97508be700ca869bada64703135c 3 | size 381462 4 | -------------------------------------------------------------------------------- /assets/models/metric_plane/metric_plane_8x8.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:953f906047136715450102f46193020a4a8556065e8863e098a6c18a7557f22a 3 | size 204 4 | -------------------------------------------------------------------------------- /assets/models/metric_plane/metric_plane_8x8.blend: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:66f4bc0ed3761052bb80500fb29d99a0927fea249664763cf439133d34609fb3 3 | size 637720 4 | -------------------------------------------------------------------------------- /assets/models/metric_plane/metric_plane_8x8.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d9676f08080e6d3e15d45fb7f29e3b76cd8086889d1f95a86aab9a37aa484bf6 3 | size 3384 4 | -------------------------------------------------------------------------------- /assets/models/monkey/Monkey.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f590d064ea1d9c257e4d48fe01247a187b7858ad9529d00c5346730924843efc 3 | size 120168 4 | -------------------------------------------------------------------------------- /assets/models/sphere/sphere.bin: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cabd9d79e35a8da522994d906c616c95109f8cfc807d0229c919b1854d9f2d9e 3 | size 92384 4 | -------------------------------------------------------------------------------- /assets/models/sphere/sphere.gltf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d5cd88cf7bcde3fc38824870a9f9321affbbceefcc7784e61ae27f13191ecd8f 3 | size 2152 4 | -------------------------------------------------------------------------------- /assets/scripts/false.rhai: -------------------------------------------------------------------------------- 1 | false -------------------------------------------------------------------------------- /assets/scripts/true.rhai: -------------------------------------------------------------------------------- 1 | true -------------------------------------------------------------------------------- /assets/shaders/lines.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_pbr::mesh_view_bindings 2 | #import bevy_pbr::mesh_types 3 | 4 | // struct LinesMaterial; 5 | // [[group(1), binding(0)]] 6 | // var material: LinesMaterial; 7 | 8 | @group(2) @binding(0) 9 | var mesh: Mesh; 10 | 11 | struct Vertex { 12 | @location(0) position: vec3, 13 | @location(1) color: vec4, 14 | }; 15 | 16 | struct VertexOutput { 17 | @builtin(position) clip_position: vec4, 18 | @location(0) color: vec4, 19 | }; 20 | 21 | @vertex 22 | fn vertex(vertex: Vertex) -> VertexOutput { 23 | var out: VertexOutput; 24 | let world_position = mesh.model * vec4(vertex.position, 1.0); 25 | out.clip_position = view.view_proj * world_position; 26 | 27 | let color = vertex.color; 28 | out.color = color; 29 | 30 | return out; 31 | } 32 | 33 | @fragment 34 | fn fragment(in: VertexOutput) -> @location(0) vec4 { 35 | return vec4(in.color.rgb, 1.0); 36 | } 37 | -------------------------------------------------------------------------------- /assets/shaders/pointcloud.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_pbr::mesh_view_bindings 2 | #import bevy_pbr::mesh_types 3 | 4 | 5 | @group(1) @binding(0) 6 | var mesh: Mesh; 7 | 8 | struct Vertex { 9 | @location(0) position: vec3, 10 | @location(1) normal: vec3, 11 | @location(2) uv: vec2, 12 | 13 | @location(3) i_pos_scale: vec4, 14 | @location(4) i_color: vec4, 15 | }; 16 | 17 | struct VertexOutput { 18 | @builtin(position) clip_position: vec4, 19 | @location(0) color: vec4, 20 | }; 21 | 22 | @vertex 23 | fn vertex(vertex: Vertex) -> VertexOutput { 24 | let position = vertex.position * vertex.i_pos_scale.w + vertex.i_pos_scale.xyz; 25 | let world_position = mesh.model * vec4(position, 1.0); 26 | 27 | var out: VertexOutput; 28 | out.clip_position = view.view_proj * world_position; 29 | out.color = vertex.i_color; 30 | return out; 31 | } 32 | 33 | @fragment 34 | fn fragment(in: VertexOutput) -> @location(0) vec4 { 35 | return in.color; 36 | } 37 | -------------------------------------------------------------------------------- /assets/shaders/video_material.wgsl: -------------------------------------------------------------------------------- 1 | struct VideoMaterial { 2 | color: vec4, 3 | alpha_scaler: f32, 4 | }; 5 | 6 | @group(1) @binding(0) 7 | var material: VideoMaterial; 8 | @group(1) @binding(1) 9 | var base_color_texture: texture_2d; 10 | @group(1) @binding(2) 11 | var base_color_sampler: sampler; 12 | 13 | @fragment 14 | fn fragment( 15 | #import bevy_pbr::mesh_vertex_output 16 | ) -> @location(0) vec4 { 17 | let x_flipped_uv = vec2(1.0 - uv.x, uv.y); 18 | let tex_color = textureSample(base_color_texture, base_color_sampler, x_flipped_uv); 19 | let color = material.color.rgb * tex_color.rgb; 20 | let alpha = material.color.a * tex_color.a * material.alpha_scaler; 21 | return vec4(color.rgb, alpha); 22 | } 23 | -------------------------------------------------------------------------------- /assets/shaders/voxels.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_pbr::mesh_view_bindings 2 | #import bevy_pbr::mesh_types 3 | 4 | @group(2) @binding(0) 5 | var mesh: Mesh; 6 | 7 | struct Vertex { 8 | @location(0) position: vec3, 9 | @location(1) normal: vec3, 10 | @location(2) uv: vec2, 11 | @location(3) color: vec4, 12 | }; 13 | 14 | struct VertexOutput { 15 | @builtin(position) clip_position: vec4, 16 | @location(0) color: vec4, 17 | }; 18 | 19 | @vertex 20 | fn vertex(vertex: Vertex) -> VertexOutput { 21 | let world_position = mesh.model * vec4(vertex.position, 1.0); 22 | let world_normal = (mesh.inverse_transpose_model * vec4(vertex.normal, 0.0)).xyz; 23 | var out: VertexOutput; 24 | out.clip_position = view.view_proj * world_position; 25 | 26 | var color = vec4(vertex.color.rgb * (dot(world_normal, normalize(vec3(0.2, 1.0, 0.1))) * 0.25 + 0.75), vertex.color.a); 27 | out.color = color; 28 | 29 | return out; 30 | } 31 | 32 | // 1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0 33 | // 13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0 34 | // 4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0 35 | // 16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0 36 | 37 | struct FragmentInput { 38 | @builtin(front_facing) is_front: bool, 39 | @builtin(position) frag_coord: vec4, 40 | @location(0) color: vec4, 41 | }; 42 | 43 | @fragment 44 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 45 | 46 | var threshold = array, 4>( 47 | array( 1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0), 48 | array(13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0), 49 | array( 4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0), 50 | array(16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0) 51 | ); 52 | 53 | let xy = vec2(fract(in.frag_coord.xy / 4.0) * 4.0); 54 | let alpha = in.color.a - threshold[xy.x][xy.y]; 55 | if (alpha < 0.0) { 56 | discard; 57 | } 58 | 59 | return vec4(in.color.rgb, 1.0); 60 | } 61 | -------------------------------------------------------------------------------- /assets/textures/circle_alpha.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:39fa28cec616bfeeb0d04c0652ef8df3fa494c2871846362539f986706a7568a 3 | size 5079 4 | -------------------------------------------------------------------------------- /assets/textures/metric_512x512.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a994c73e964bc554c8c816c2b941a48161226427c394524fdce57f1cedccea6b 3 | size 75749 4 | -------------------------------------------------------------------------------- /assets/videos/mov_bbb.mp4: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3bb938fb70049e3e45f533b37ccae995ae96516e04c2f35b0c1142e47b2a39c1 3 | size 788493 4 | -------------------------------------------------------------------------------- /assets/videos/robot.gif: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c25294c0814d183fe57d7d155d995b85b555970adf6bad2c3e39112bfb7c09b5 3 | size 1625622 4 | -------------------------------------------------------------------------------- /assets/videos/robot.webp: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a27120bb3cb5e53425b4a684862e516ba3caf71f81f28c05366a3f80e2473c18 3 | size 529496 4 | -------------------------------------------------------------------------------- /assets/videos/video.html: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3d07c2949a66d211bd36265ba18f4465f9ecb872416674f9c76ae023ab8ab2c4 3 | size 200 4 | -------------------------------------------------------------------------------- /assets/web/sound.js: -------------------------------------------------------------------------------- 1 | // Insert hack to make sound autoplay on Chrome as soon as the user interacts with the tab: 2 | // https://developers.google.com/web/updates/2018/11/web-audio-autoplay#moving-forward 3 | 4 | // the following function keeps track of all AudioContexts and resumes them on the first user 5 | // interaction with the page. If the function is called and all contexts are already running, 6 | // it will remove itself from all event listeners. 7 | (function () { 8 | // An array of all contexts to resume on the page 9 | const audioContextList = []; 10 | 11 | // An array of various user interaction events we should listen for 12 | const userInputEventNames = [ 13 | "click", 14 | "contextmenu", 15 | "auxclick", 16 | "dblclick", 17 | "mousedown", 18 | "mouseup", 19 | "pointerup", 20 | "touchend", 21 | "keydown", 22 | "keyup", 23 | ]; 24 | 25 | // A proxy object to intercept AudioContexts and 26 | // add them to the array for tracking and resuming later 27 | self.AudioContext = new Proxy(self.AudioContext, { 28 | construct(target, args) { 29 | const result = new target(...args); 30 | audioContextList.push(result); 31 | return result; 32 | }, 33 | }); 34 | 35 | // To resume all AudioContexts being tracked 36 | function resumeAllContexts(_event) { 37 | let count = 0; 38 | 39 | audioContextList.forEach((context) => { 40 | if (context.state !== "running") { 41 | context.resume(); 42 | } else { 43 | count++; 44 | } 45 | }); 46 | 47 | // If all the AudioContexts have now resumed then we unbind all 48 | // the event listeners from the page to prevent unnecessary resume attempts 49 | // Checking count > 0 ensures that the user interaction happens AFTER the game started up 50 | if (count > 0 && count === audioContextList.length) { 51 | userInputEventNames.forEach((eventName) => { 52 | document.removeEventListener(eventName, resumeAllContexts); 53 | }); 54 | } 55 | } 56 | 57 | // We bind the resume function for each user interaction 58 | // event on the page 59 | userInputEventNames.forEach((eventName) => { 60 | document.addEventListener(eventName, resumeAllContexts); 61 | }); 62 | })(); 63 | -------------------------------------------------------------------------------- /assets/web/styles.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | height: 100%; 3 | } 4 | 5 | body { 6 | background: repeating-linear-gradient( 7 | 135deg, 8 | black 0, 9 | black 2px, 10 | white 2px, 11 | white 20px 12 | ); 13 | margin: 0; 14 | } 15 | 16 | .game-container { 17 | width: 100%; 18 | height: 100%; 19 | display: flex; 20 | justify-content: center; 21 | align-items: center; 22 | } 23 | 24 | #bevy { 25 | background-color: white; 26 | width: 800px; 27 | height: 600px; 28 | } 29 | -------------------------------------------------------------------------------- /crates/egui_node_graph/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "egui_node_graph" 3 | description = "A helper library to create interactive node graphs using egui" 4 | homepage = "https://github.com/setzer22/egui_node_graph" 5 | repository = "https://github.com/setzer22/egui_node_graph" 6 | license = "MIT" 7 | version = "0.4.0" 8 | keywords = ["ui", "egui", "graph", "node"] 9 | authors = ["setzer22"] 10 | edition = "2021" 11 | 12 | [features] 13 | persistence = ["serde", "slotmap/serde", "smallvec/serde", "egui/persistence"] 14 | 15 | [dependencies] 16 | egui = { version = "0.21.0" } 17 | slotmap = { version = "1.0" } 18 | smallvec = { version = "1.10.0" } 19 | serde = { version = "1.0", optional = true, features = ["derive"] } 20 | thiserror = "1.0" 21 | -------------------------------------------------------------------------------- /crates/egui_node_graph/src/color_hex_utils.rs: -------------------------------------------------------------------------------- 1 | use egui::Color32; 2 | 3 | /// Converts a hex string with a leading '#' into a egui::Color32. 4 | /// - The first three channels are interpreted as R, G, B. 5 | /// - The fourth channel, if present, is used as the alpha value. 6 | /// - Both upper and lowercase characters can be used for the hex values. 7 | /// 8 | /// *Adapted from: https://docs.rs/raster/0.1.0/src/raster/lib.rs.html#425-725. 9 | /// Credit goes to original authors.* 10 | pub fn color_from_hex(hex: &str) -> Result { 11 | // Convert a hex string to decimal. Eg. "00" -> 0. "FF" -> 255. 12 | fn _hex_dec(hex_string: &str) -> Result { 13 | match u8::from_str_radix(hex_string, 16) { 14 | Ok(o) => Ok(o), 15 | Err(e) => Err(format!("Error parsing hex: {}", e)), 16 | } 17 | } 18 | 19 | if hex.len() == 9 && hex.starts_with('#') { 20 | // #FFFFFFFF (Red Green Blue Alpha) 21 | return Ok(Color32::from_rgba_premultiplied( 22 | _hex_dec(&hex[1..3])?, 23 | _hex_dec(&hex[3..5])?, 24 | _hex_dec(&hex[5..7])?, 25 | _hex_dec(&hex[7..9])?, 26 | )); 27 | } else if hex.len() == 7 && hex.starts_with('#') { 28 | // #FFFFFF (Red Green Blue) 29 | return Ok(Color32::from_rgb( 30 | _hex_dec(&hex[1..3])?, 31 | _hex_dec(&hex[3..5])?, 32 | _hex_dec(&hex[5..7])?, 33 | )); 34 | } 35 | 36 | Err(format!( 37 | "Error parsing hex: {}. Example of valid formats: #FFFFFF or #ffffffff", 38 | hex 39 | )) 40 | } 41 | 42 | /// Converts a Color32 into its canonical hexadecimal representation. 43 | /// - The color string will be preceded by '#'. 44 | /// - If the alpha channel is completely opaque, it will be ommitted. 45 | /// - Characters from 'a' to 'f' will be written in lowercase. 46 | #[allow(dead_code)] 47 | pub fn color_to_hex(color: Color32) -> String { 48 | if color.a() < 255 { 49 | format!( 50 | "#{:02x?}{:02x?}{:02x?}{:02x?}", 51 | color.r(), 52 | color.g(), 53 | color.b(), 54 | color.a() 55 | ) 56 | } else { 57 | format!("#{:02x?}{:02x?}{:02x?}", color.r(), color.g(), color.b()) 58 | } 59 | } 60 | 61 | #[cfg(test)] 62 | mod tests { 63 | use super::*; 64 | 65 | #[test] 66 | pub fn test_color_from_and_to_hex() { 67 | assert_eq!( 68 | color_from_hex("#00ff00").unwrap(), 69 | Color32::from_rgb(0, 255, 0) 70 | ); 71 | assert_eq!( 72 | color_from_hex("#5577AA").unwrap(), 73 | Color32::from_rgb(85, 119, 170) 74 | ); 75 | assert_eq!( 76 | color_from_hex("#E2e2e277").unwrap(), 77 | Color32::from_rgba_premultiplied(226, 226, 226, 119) 78 | ); 79 | assert!(color_from_hex("abcdefgh").is_err()); 80 | 81 | assert_eq!( 82 | color_to_hex(Color32::from_rgb(0, 255, 0)), 83 | "#00ff00".to_string() 84 | ); 85 | assert_eq!( 86 | color_to_hex(Color32::from_rgb(85, 119, 170)), 87 | "#5577aa".to_string() 88 | ); 89 | assert_eq!( 90 | color_to_hex(Color32::from_rgba_premultiplied(226, 226, 226, 119)), 91 | "#e2e2e277".to_string() 92 | ); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /crates/egui_node_graph/src/error.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(Debug, thiserror::Error)] 4 | pub enum EguiGraphError { 5 | #[error("Node {0:?} has no parameter named {1}")] 6 | NoParameterNamed(NodeId, String), 7 | 8 | #[error("Parameter {0:?} was not found in the graph.")] 9 | InvalidParameterId(AnyParameterId), 10 | } 11 | -------------------------------------------------------------------------------- /crates/egui_node_graph/src/graph.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[cfg(feature = "persistence")] 4 | use serde::{Deserialize, Serialize}; 5 | 6 | /// A node inside the [`Graph`]. Nodes have input and output parameters, stored 7 | /// as ids. They also contain a custom `NodeData` struct with whatever data the 8 | /// user wants to store per-node. 9 | #[derive(Debug, Clone)] 10 | #[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))] 11 | pub struct Node { 12 | pub id: NodeId, 13 | pub label: String, 14 | pub inputs: Vec<(String, InputId)>, 15 | pub outputs: Vec<(String, OutputId)>, 16 | pub user_data: NodeData, 17 | } 18 | 19 | /// The three kinds of input params. These describe how the graph must behave 20 | /// with respect to inline widgets and connections for this parameter. 21 | #[derive(Debug, Clone, Copy)] 22 | #[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))] 23 | pub enum InputParamKind { 24 | /// No constant value can be set. Only incoming connections can produce it 25 | ConnectionOnly, 26 | /// Only a constant value can be set. No incoming connections accepted. 27 | ConstantOnly, 28 | /// Both incoming connections and constants are accepted. Connections take 29 | /// precedence over the constant values. 30 | ConnectionOrConstant, 31 | } 32 | 33 | #[cfg(feature = "persistence")] 34 | fn shown_inline_default() -> bool { 35 | true 36 | } 37 | 38 | /// An input parameter. Input parameters are inside a node, and represent data 39 | /// that this node receives. Unlike their [`OutputParam`] counterparts, input 40 | /// parameters also display an inline widget which allows setting its "value". 41 | /// The `DataType` generic parameter is used to restrict the range of input 42 | /// connections for this parameter, and the `ValueType` is use to represent the 43 | /// data for the inline widget (i.e. constant) value. 44 | #[derive(Debug, Clone)] 45 | #[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))] 46 | pub struct InputParam { 47 | pub id: InputId, 48 | /// The data type of this node. Used to determine incoming connections. This 49 | /// should always match the type of the InputParamValue, but the property is 50 | /// not actually enforced. 51 | pub typ: DataType, 52 | /// The constant value stored in this parameter. 53 | pub value: ValueType, 54 | /// The input kind. See [`InputParamKind`] 55 | pub kind: InputParamKind, 56 | /// Back-reference to the node containing this parameter. 57 | pub node: NodeId, 58 | /// When true, the node is shown inline inside the node graph. 59 | #[cfg_attr(feature = "persistence", serde(default = "shown_inline_default"))] 60 | pub shown_inline: bool, 61 | } 62 | 63 | /// An output parameter. Output parameters are inside a node, and represent the 64 | /// data that the node produces. Output parameters can be linked to the input 65 | /// parameters of other nodes. Unlike an [`InputParam`], output parameters 66 | /// cannot have a constant inline value. 67 | #[derive(Debug, Clone)] 68 | #[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))] 69 | pub struct OutputParam { 70 | pub id: OutputId, 71 | /// Back-reference to the node containing this parameter. 72 | pub node: NodeId, 73 | pub typ: DataType, 74 | } 75 | 76 | /// The graph, containing nodes, input parameters and output parameters. Because 77 | /// graphs are full of self-referential structures, this type uses the `slotmap` 78 | /// crate to represent all the inner references in the data. 79 | #[derive(Debug, Clone)] 80 | #[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))] 81 | pub struct Graph { 82 | /// The [`Node`]s of the graph 83 | pub nodes: SlotMap>, 84 | /// The [`InputParam`]s of the graph 85 | pub inputs: SlotMap>, 86 | /// The [`OutputParam`]s of the graph 87 | pub outputs: SlotMap>, 88 | // Connects the input of a node, to the output of its predecessor that 89 | // produces it 90 | pub connections: SecondaryMap, 91 | } 92 | -------------------------------------------------------------------------------- /crates/egui_node_graph/src/id_type.rs: -------------------------------------------------------------------------------- 1 | slotmap::new_key_type! { pub struct NodeId; } 2 | slotmap::new_key_type! { pub struct InputId; } 3 | slotmap::new_key_type! { pub struct OutputId; } 4 | 5 | #[cfg_attr(feature = "persistence", derive(serde::Serialize, serde::Deserialize))] 6 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] 7 | pub enum AnyParameterId { 8 | Input(InputId), 9 | Output(OutputId), 10 | } 11 | 12 | impl AnyParameterId { 13 | pub fn assume_input(&self) -> InputId { 14 | match self { 15 | AnyParameterId::Input(input) => *input, 16 | AnyParameterId::Output(output) => panic!("{:?} is not an InputId", output), 17 | } 18 | } 19 | pub fn assume_output(&self) -> OutputId { 20 | match self { 21 | AnyParameterId::Output(output) => *output, 22 | AnyParameterId::Input(input) => panic!("{:?} is not an OutputId", input), 23 | } 24 | } 25 | } 26 | 27 | impl From for AnyParameterId { 28 | fn from(output: OutputId) -> Self { 29 | Self::Output(output) 30 | } 31 | } 32 | 33 | impl From for AnyParameterId { 34 | fn from(input: InputId) -> Self { 35 | Self::Input(input) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/egui_node_graph/src/index_impls.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | macro_rules! impl_index_traits { 4 | ($id_type:ty, $output_type:ty, $arena:ident) => { 5 | impl std::ops::Index<$id_type> for Graph { 6 | type Output = $output_type; 7 | 8 | fn index(&self, index: $id_type) -> &Self::Output { 9 | self.$arena.get(index).unwrap_or_else(|| { 10 | panic!( 11 | "{} index error for {:?}. Has the value been deleted?", 12 | stringify!($id_type), 13 | index 14 | ) 15 | }) 16 | } 17 | } 18 | 19 | impl std::ops::IndexMut<$id_type> for Graph { 20 | fn index_mut(&mut self, index: $id_type) -> &mut Self::Output { 21 | self.$arena.get_mut(index).unwrap_or_else(|| { 22 | panic!( 23 | "{} index error for {:?}. Has the value been deleted?", 24 | stringify!($id_type), 25 | index 26 | ) 27 | }) 28 | } 29 | } 30 | }; 31 | } 32 | 33 | impl_index_traits!(NodeId, Node, nodes); 34 | impl_index_traits!(InputId, InputParam, inputs); 35 | impl_index_traits!(OutputId, OutputParam, outputs); 36 | -------------------------------------------------------------------------------- /crates/egui_node_graph/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![forbid(unsafe_code)] 2 | 3 | use slotmap::{SecondaryMap, SlotMap}; 4 | 5 | pub type SVec = smallvec::SmallVec<[T; 4]>; 6 | 7 | /// Contains the main definitions for the node graph model. 8 | pub mod graph; 9 | pub use graph::*; 10 | 11 | /// Type declarations for the different id types (node, input, output) 12 | pub mod id_type; 13 | pub use id_type::*; 14 | 15 | /// Implements the index trait for the Graph type, allowing indexing by all 16 | /// three id types 17 | pub mod index_impls; 18 | 19 | /// Implementing the main methods for the `Graph` 20 | pub mod graph_impls; 21 | 22 | /// Custom error types, crate-wide 23 | pub mod error; 24 | pub use error::*; 25 | 26 | /// The main struct in the library, contains all the necessary state to draw the 27 | /// UI graph 28 | pub mod ui_state; 29 | pub use ui_state::*; 30 | 31 | /// The node finder is a tiny widget allowing to create new node types 32 | pub mod node_finder; 33 | pub use node_finder::*; 34 | 35 | /// The inner details of the egui implementation. Most egui code lives here. 36 | pub mod editor_ui; 37 | pub use editor_ui::*; 38 | 39 | /// Several traits that must be implemented by the user to customize the 40 | /// behavior of this library. 41 | pub mod traits; 42 | pub use traits::*; 43 | 44 | mod utils; 45 | 46 | mod color_hex_utils; 47 | -------------------------------------------------------------------------------- /crates/egui_node_graph/src/ui_state.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use std::marker::PhantomData; 3 | 4 | #[cfg(feature = "persistence")] 5 | use serde::{Deserialize, Serialize}; 6 | 7 | #[derive(Default, Copy, Clone)] 8 | #[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))] 9 | pub struct PanZoom { 10 | pub pan: egui::Vec2, 11 | pub zoom: f32, 12 | } 13 | 14 | #[derive(Clone)] 15 | #[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))] 16 | pub struct GraphEditorState { 17 | pub graph: Graph, 18 | /// Nodes are drawn in this order. Draw order is important because nodes 19 | /// that are drawn last are on top. 20 | pub node_order: Vec, 21 | /// An ongoing connection interaction: The mouse has dragged away from a 22 | /// port and the user is holding the click 23 | pub connection_in_progress: Option<(NodeId, AnyParameterId)>, 24 | /// The currently selected node. Some interface actions depend on the 25 | /// currently selected node. 26 | pub selected_nodes: Vec, 27 | /// The mouse drag start position for an ongoing box selection. 28 | pub ongoing_box_selection: Option, 29 | /// The position of each node. 30 | pub node_positions: SecondaryMap, 31 | /// The node finder is used to create new nodes. 32 | pub node_finder: Option>, 33 | /// The panning of the graph viewport. 34 | pub pan_zoom: PanZoom, 35 | pub _user_state: PhantomData UserState>, 36 | /// Is the graph allowing editing? 37 | pub editing: bool, 38 | } 39 | 40 | impl 41 | GraphEditorState 42 | { 43 | pub fn new(default_zoom: f32) -> Self { 44 | Self { 45 | pan_zoom: PanZoom { 46 | pan: egui::Vec2::ZERO, 47 | zoom: default_zoom, 48 | }, 49 | ..Default::default() 50 | } 51 | } 52 | } 53 | impl Default 54 | for GraphEditorState 55 | { 56 | fn default() -> Self { 57 | Self { 58 | graph: Default::default(), 59 | node_order: Default::default(), 60 | connection_in_progress: Default::default(), 61 | selected_nodes: Default::default(), 62 | ongoing_box_selection: Default::default(), 63 | node_positions: Default::default(), 64 | node_finder: Default::default(), 65 | pan_zoom: Default::default(), 66 | _user_state: Default::default(), 67 | editing: true, 68 | } 69 | } 70 | } 71 | 72 | impl PanZoom { 73 | pub fn adjust_zoom( 74 | &mut self, 75 | zoom_delta: f32, 76 | point: egui::Vec2, 77 | zoom_min: f32, 78 | zoom_max: f32, 79 | ) { 80 | let zoom_clamped = (self.zoom + zoom_delta).clamp(zoom_min, zoom_max); 81 | let zoom_delta = zoom_clamped - self.zoom; 82 | 83 | self.zoom += zoom_delta; 84 | self.pan += point * zoom_delta; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /crates/egui_node_graph/src/utils.rs: -------------------------------------------------------------------------------- 1 | pub trait ColorUtils { 2 | /// Multiplies the color rgb values by `factor`, keeping alpha untouched. 3 | fn lighten(&self, factor: f32) -> Self; 4 | } 5 | 6 | impl ColorUtils for egui::Color32 { 7 | fn lighten(&self, factor: f32) -> Self { 8 | egui::Color32::from_rgba_premultiplied( 9 | (self.r() as f32 * factor) as u8, 10 | (self.g() as f32 * factor) as u8, 11 | (self.b() as f32 * factor) as u8, 12 | self.a(), 13 | ) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/simula_action/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simula_action" 3 | version = "0.1.0" 4 | edition = "2021" 5 | authors = ["Alex Rozgo "] 6 | 7 | [dependencies] 8 | bevy = { version = "0.10", features = ["serialize"] } 9 | bevy_egui = "0.20" 10 | simula_core = { path = "../../crates/simula_core" } 11 | serde = { version = "1.0", features = ["derive"] } 12 | ron = "0.8" 13 | simula_action_macro = { path = "../../crates/simula_action/simula_action_macro" } 14 | 15 | [dev-dependencies] 16 | 17 | -------------------------------------------------------------------------------- /crates/simula_action/simula_action_macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simula_action_macro" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | proc-macro = true 8 | 9 | [dependencies] 10 | syn = "1.0" 11 | quote = "1.0" 12 | -------------------------------------------------------------------------------- /crates/simula_action/simula_action_macro/src/lib.rs: -------------------------------------------------------------------------------- 1 | use proc_macro::TokenStream; 2 | use quote::quote; 3 | 4 | #[proc_macro_derive(InputDerive)] 5 | pub fn input_action_macro_derive(input: TokenStream) -> TokenStream { 6 | // Construct a representation of Rust code as a syntax tree 7 | // that we can manipulate 8 | let ast = syn::parse(input).unwrap(); 9 | 10 | // Build the trait implementation 11 | impl_input_action_macro(&ast) 12 | } 13 | 14 | fn impl_input_action_macro(ast: &syn::DeriveInput) -> TokenStream { 15 | let name = &ast.ident; 16 | let gen = quote! { 17 | impl PepeDerive for #name { 18 | fn hello_input_action() { 19 | println!("Hello, Macro! My name is {}!", stringify!(#name)); 20 | } 21 | } 22 | }; 23 | gen.into() 24 | } 25 | 26 | #[proc_macro_derive(KeyboardInput)] 27 | pub fn keyboard_intput_macro_derive(input: TokenStream) -> TokenStream { 28 | // Construct a representation of Rust code as a syntax tree 29 | // that we can manipulate 30 | let ast = syn::parse(input).unwrap(); 31 | 32 | // Build the trait implementation 33 | impl_keyboard_input_macro(&ast) 34 | } 35 | 36 | fn impl_keyboard_input_macro(ast: &syn::DeriveInput) -> TokenStream { 37 | let name = &ast.ident; 38 | let gen = quote! { 39 | impl Key for #name { 40 | const KEYCODE: KeyCode = KeyCode::#name; 41 | } 42 | }; 43 | gen.into() 44 | } 45 | -------------------------------------------------------------------------------- /crates/simula_action/src/axis.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::*, reflect::FromReflect, utils::HashMap}; 2 | use std::hash::Hash; 3 | 4 | /// Stores the position data of the input devices of type `T`. 5 | /// 6 | /// The values are stored as `f32`s, which range from [`ActionAxis::MIN`] to [`ActionAxis::MAX`], inclusive. 7 | #[derive(Debug, Clone, Component, Reflect)] 8 | #[reflect(Component)] 9 | pub struct ActionAxis { 10 | /// The name of the axis. 11 | name: String, 12 | /// The position data of the input devices. 13 | axis: HashMap, 14 | } 15 | 16 | impl Default for ActionAxis 17 | where 18 | T: Eq + Hash + Clone + Send + Sync + 'static + FromReflect, 19 | { 20 | fn default() -> Self { 21 | ActionAxis { 22 | name: std::any::type_name::().to_string(), 23 | axis: HashMap::default(), 24 | } 25 | } 26 | } 27 | 28 | impl ActionAxis 29 | where 30 | T: Eq + Hash + Clone + Send + Sync + 'static + FromReflect, 31 | { 32 | /// The smallest possible axis value. 33 | pub const MIN: f32 = -1.0; 34 | 35 | /// The largest possible axis value. 36 | pub const MAX: f32 = 1.0; 37 | 38 | /// The name of the axis. 39 | pub fn name(&self) -> &str { 40 | &self.name 41 | } 42 | 43 | /// Sets the position data of the `input_device` to `position_data`. 44 | /// 45 | /// The `position_data` is clamped to be between [`ActionAxis::MIN`] and [`ActionAxis::MAX`], inclusive. 46 | /// 47 | /// If the `input_device`: 48 | /// - was present before, the position data is updated, and the old value is returned. 49 | /// - wasn't present before, [None] is returned. 50 | pub fn set(&mut self, input_device: T, position_data: f32) -> Option { 51 | let new_position_data = position_data.clamp(Self::MIN, Self::MAX); 52 | self.axis.insert(input_device, new_position_data) 53 | } 54 | 55 | /// Returns a position data corresponding to the `input_device`. 56 | pub fn get(&self, input_device: T) -> Option { 57 | self.axis.get(&input_device).copied() 58 | } 59 | 60 | /// Removes the position data of the `input_device`, returning the position data if the input device was previously set. 61 | pub fn remove(&mut self, input_device: T) -> Option { 62 | self.axis.remove(&input_device) 63 | } 64 | 65 | /// Remove all position data. 66 | pub fn clear(&mut self) { 67 | self.axis.clear(); 68 | } 69 | } 70 | 71 | #[cfg(test)] 72 | mod tests { 73 | use super::*; 74 | use bevy::input::gamepad::{Gamepad, GamepadButton, GamepadButtonType}; 75 | 76 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Reflect, FromReflect)] 77 | pub enum TestGamepad { 78 | Gamepad(GamepadButton), 79 | } 80 | 81 | #[test] 82 | fn test_axis_set() { 83 | let cases = [ 84 | (-1.5, Some(-1.0)), 85 | (-1.1, Some(-1.0)), 86 | (-1.0, Some(-1.0)), 87 | (-0.9, Some(-0.9)), 88 | (-0.1, Some(-0.1)), 89 | (0.0, Some(0.0)), 90 | (0.1, Some(0.1)), 91 | (0.9, Some(0.9)), 92 | (1.0, Some(1.0)), 93 | (1.1, Some(1.0)), 94 | (1.6, Some(1.0)), 95 | ]; 96 | 97 | for (value, expected) in cases { 98 | let gamepad_button = TestGamepad::Gamepad(GamepadButton::new( 99 | Gamepad::new(1), 100 | GamepadButtonType::RightTrigger, 101 | )); 102 | let mut axis = ActionAxis::::default(); 103 | 104 | axis.set(gamepad_button, value); 105 | 106 | let actual = axis.get(gamepad_button); 107 | assert_eq!(expected, actual); 108 | } 109 | } 110 | 111 | #[test] 112 | fn test_axis_remove() { 113 | let cases = [-1.0, -0.9, -0.1, 0.0, 0.1, 0.9, 1.0]; 114 | 115 | for value in cases { 116 | let gamepad_button = TestGamepad::Gamepad(GamepadButton::new( 117 | Gamepad::new(1), 118 | GamepadButtonType::RightTrigger, 119 | )); 120 | let mut axis = ActionAxis::::default(); 121 | 122 | axis.set(gamepad_button, value); 123 | assert!(axis.get(gamepad_button).is_some()); 124 | 125 | axis.remove(gamepad_button); 126 | let actual = axis.get(gamepad_button); 127 | let expected = None; 128 | 129 | assert_eq!(expected, actual); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /crates/simula_action/tests/action.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /crates/simula_behavior/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simula_behavior" 3 | version = "0.1.0" 4 | edition = "2021" 5 | authors = ["Alex Rozgo "] 6 | 7 | [dependencies] 8 | bevy = { version = "0.10" } 9 | bevy-inspector-egui = "0.18" 10 | 11 | egui_node_graph = { path = "../../crates/egui_node_graph" } 12 | 13 | simula_core = { path = "../../crates/simula_core" } 14 | simula_script = { path = "../../crates/simula_script" } 15 | simula_inspector = { path = "../../crates/simula_inspector" } 16 | 17 | simula_behavior_macro = { path = "../../crates/simula_behavior/simula_behavior_macro" } 18 | 19 | rand = "0.8.5" 20 | serde = { version = "1.0", features = ["derive"] } 21 | ron = "0.8" 22 | # serde_yaml = "0.9" 23 | pretty-type-name = "1.0" 24 | anyhow = "1.0" 25 | strum = { version = "0.24", features = ["derive"] } 26 | crossbeam-channel = "0.5.0" 27 | 28 | [dev-dependencies] 29 | -------------------------------------------------------------------------------- /crates/simula_behavior/simula_behavior_macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simula_behavior_macro" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | proc-macro = true 8 | 9 | [dependencies] 10 | syn = { version = "1.0", features = ["full"] } 11 | quote = "1.0" 12 | -------------------------------------------------------------------------------- /crates/simula_behavior/src/actions/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod debug; 2 | pub mod wait; 3 | 4 | pub use debug::Debug; 5 | pub use wait::Wait; 6 | -------------------------------------------------------------------------------- /crates/simula_behavior/src/actions/wait.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use crate::property_ui_readonly; 3 | use bevy::prelude::*; 4 | use bevy_inspector_egui::prelude::*; 5 | use serde::{Deserialize, Serialize}; 6 | 7 | /// A wait will succeed after a specified amount of time. 8 | #[derive( 9 | Debug, Default, Component, Reflect, FromReflect, Clone, Deserialize, Serialize, InspectorOptions, 10 | )] 11 | #[reflect(InspectorOptions)] 12 | pub struct Wait { 13 | #[serde(default)] 14 | pub duration: BehaviorPropGeneric, 15 | #[serde(default)] 16 | pub fail: BehaviorPropGeneric, 17 | #[serde(skip)] 18 | pub start: f64, 19 | #[serde(skip)] 20 | pub ticks: u64, 21 | } 22 | 23 | impl BehaviorSpec for Wait { 24 | const TYPE: BehaviorType = BehaviorType::Action; 25 | const NAME: &'static str = "Wait"; 26 | const ICON: &'static str = "⌛"; 27 | const DESC: &'static str = "Wait for a specified amount of time and then complete with \ 28 | success or failure."; 29 | } 30 | 31 | impl BehaviorUI for Wait { 32 | fn ui( 33 | &mut self, 34 | _label: Option<&str>, 35 | state: Option, 36 | ui: &mut bevy_inspector_egui::egui::Ui, 37 | type_registry: &bevy::reflect::TypeRegistry, 38 | ) -> bool { 39 | let mut changed = false; 40 | changed |= behavior_ui!(self, fail, state, ui, type_registry); 41 | changed |= behavior_ui!(self, duration, state, ui, type_registry); 42 | changed 43 | } 44 | 45 | fn ui_readonly( 46 | &self, 47 | _label: Option<&str>, 48 | state: Option, 49 | ui: &mut bevy_inspector_egui::egui::Ui, 50 | type_registry: &bevy::reflect::TypeRegistry, 51 | ) { 52 | behavior_ui_readonly!(self, fail, state, ui, type_registry); 53 | behavior_ui_readonly!(self, duration, state, ui, type_registry); 54 | match state { 55 | Some(_) => { 56 | property_ui_readonly!(self, start, state, ui, type_registry); 57 | property_ui_readonly!(self, ticks, state, ui, type_registry); 58 | } 59 | _ => {} 60 | } 61 | } 62 | } 63 | 64 | pub fn run( 65 | time: Res