├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── lut │ └── my_group_lut.txt ├── meshes │ ├── my_mesh.obj │ └── my_mesh.txt ├── shaders │ ├── bounding_box.wgsl │ ├── button.wgsl │ ├── controls.wgsl │ ├── ends.wgsl │ ├── fill_mesh.wgsl │ ├── mids.wgsl │ ├── road_mesh.wgsl │ ├── selecting.wgsl │ └── ui.wgsl ├── sounds │ ├── group.ogg │ ├── latch.ogg │ └── unlatch.ogg └── textures │ ├── bin.png │ ├── car.png │ ├── controls_off.png │ ├── controls_on.png │ ├── copter.png │ ├── heli.png │ ├── heli_button.png │ ├── hide.png │ ├── load.png │ ├── lut.png │ ├── mesh.png │ ├── redo.png │ ├── road_icon.png │ ├── road_texture.png │ ├── save.png │ ├── scale_down.png │ ├── scale_up.png │ ├── selection.png │ ├── show_anchors.png │ ├── single_lane_road.png │ ├── sound_off.png │ ├── sound_on.png │ └── undo.png ├── crates └── bevy_pen_tool_plugin │ ├── Cargo.toml │ ├── assets │ ├── lut │ │ └── my_group_lut.txt │ ├── meshes │ │ ├── my_mesh.obj │ │ ├── my_mesh.txt │ │ ├── my_mesh0.meta │ │ ├── my_mesh0.obj │ │ ├── my_mesh1.meta │ │ ├── my_mesh1.obj │ │ ├── my_mesh2.meta │ │ └── my_mesh2.obj │ ├── shaders │ │ ├── bounding_box.wgsl │ │ ├── button.wgsl │ │ ├── controls.wgsl │ │ ├── ends.wgsl │ │ ├── fill_mesh.wgsl │ │ ├── mids.wgsl │ │ ├── road_mesh.wgsl │ │ ├── selecting.wgsl │ │ └── ui.wgsl │ ├── sounds │ │ ├── group.ogg │ │ ├── latch.ogg │ │ └── unlatch.ogg │ └── textures │ │ ├── bin.png │ │ ├── branding_icon.png │ │ ├── car.png │ │ ├── controls_off.png │ │ ├── controls_on.png │ │ ├── copter.png │ │ ├── heli.png │ │ ├── heli_button.png │ │ ├── hide.png │ │ ├── load.png │ │ ├── lut.png │ │ ├── mesh.png │ │ ├── redo.png │ │ ├── road_icon.png │ │ ├── road_texture.png │ │ ├── save.png │ │ ├── scale_down.png │ │ ├── scale_up.png │ │ ├── selection.png │ │ ├── show_anchors.png │ │ ├── single_lane_road.png │ │ ├── sound_off.png │ │ ├── sound_on.png │ │ └── undo.png │ ├── crates │ └── bevy_pen_tool_model │ │ ├── Cargo.toml │ │ └── src │ │ ├── inputs │ │ ├── buttons.rs │ │ ├── inputs.rs │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── materials.rs │ │ ├── mesh │ │ ├── material_mesh.rs │ │ ├── mesh_making.rs │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── model │ │ ├── bezier.rs │ │ ├── group.rs │ │ ├── mod.rs │ │ └── util.rs │ │ └── spawner │ │ ├── bezier_spawner.rs │ │ ├── mod.rs │ │ ├── others_spawner.rs │ │ └── ui_spawner.rs │ ├── examples │ ├── blank.rs │ ├── breakout.rs │ ├── complex_test1.rs │ ├── delete_test.rs │ ├── latch_test.rs │ ├── latch_then_delete_test.rs │ ├── move_test.rs │ ├── redo_delete_latched_test.rs │ ├── redo_delete_test.rs │ ├── redo_latch_test.rs │ ├── redo_move_test.rs │ ├── redo_unlatch_test.rs │ ├── undo_delete_latched_test.rs │ ├── undo_delete_test.rs │ ├── undo_latch_test.rs │ ├── undo_latch_then_move_test.rs │ ├── undo_move_test.rs │ ├── undo_unlatch_test.rs │ └── unlatch_test.rs │ ├── saved │ ├── groups │ │ ├── my_group0.group │ │ ├── my_group1.group │ │ ├── my_group2.group │ │ └── my_group3.group │ ├── look_up_tables │ │ ├── my_group0.lut │ │ ├── my_group1.lut │ │ ├── my_group2.lut │ │ └── my_group3.lut │ ├── my_mesh0.meta │ └── my_mesh0.obj │ └── src │ ├── actions.rs │ ├── io.rs │ ├── lib.rs │ ├── moves.rs │ ├── pen.rs │ ├── plugin.rs │ ├── plugin.rs:120:10 │ ├── plugin.rs:153:5 │ └── undo.rs ├── examples └── simple_animation.rs ├── saved ├── groups │ └── my_group0.group └── look_up_tables │ └── my_group0.lut └── src ├── cam.rs └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | crates/*/target 3 | crates/*/Cargo.lock 4 | **/*.rs.bk 5 | Cargo.lock 6 | /.vscode 7 | function.svg 8 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bevy_pen_tool" 3 | version = "0.3.0" 4 | edition = "2021" 5 | authors = ["Eliot Bolduc "] 6 | categories = ["animation", "ui", "game-development", "mesh", "bezier-curves"] 7 | 8 | [workspace] 9 | members = ["crates/*"] 10 | 11 | [dependencies] 12 | bevy = { git = "https://github.com/bevyengine/bevy", rev = "6a1ba9c" } 13 | bevy_pen_tool_plugin = { path = "crates/bevy_pen_tool_plugin", version = "0.3.0" } 14 | 15 | serde_json = "1.0.59" 16 | serde = { version = "1", features = ["derive"] } 17 | lyon = "0.17.5" 18 | rfd = "0.5.1" 19 | 20 | 21 | [[example]] 22 | name = "simple_animation" 23 | path = "examples/simple_animation.rs" 24 | 25 | 26 | [[example]] 27 | name = "mesh_making" 28 | path = "examples/mesh_making.rs" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | bevy_pen_tool is dual-licensed under either 2 | 3 | * MIT License (docs/LICENSE-MIT or http://opensource.org/licenses/MIT) 4 | * Apache License, Version 2.0 (docs/LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) 5 | 6 | at your option. 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bevy_pen_tool 2 | A Bevy Engine plugin for making 2D paths, smooth animations, meshes and roads with Bezier curves. 3 | 4 | 5 | 6 | ![bevy_pen_tool](https://user-images.githubusercontent.com/6177048/137658210-387c304a-469c-4f65-a4a8-4612f39656cb.gif) 7 | 8 | 9 | ## Controls 10 | 11 | | Icon | Keys | Description | 12 | | --- | --- | --- | 13 | | ![scale_up](https://user-images.githubusercontent.com/6177048/137652103-02a4b95b-61de-491a-92da-3ef74cf97498.png) | Left Control + Mousescroll up | Scale UI and curves up | 14 | | ![scale_down](https://user-images.githubusercontent.com/6177048/137652111-6d3e13aa-bca9-40d5-9a06-222cad9c23bf.png) | Left Control + Mousescroll down | Scale UI and curves down | 15 | | ![spawn_curve](https://user-images.githubusercontent.com/6177048/137652140-605744c5-e9a0-4c8d-ad8a-1c47dcb7db7c.png) | Left Shift + Click | Spawn curve | 16 | | ![select](https://user-images.githubusercontent.com/6177048/137652978-98319770-9cb2-43c2-af6f-3fbd05048626.png) | Left Crtl + Drag | Select curves | 17 | | ![group](https://user-images.githubusercontent.com/6177048/137652145-adb487b7-c45d-4aa5-8a20-ddd45829dc2d.png) | Left Control + G | Group selected curves | 18 | | ![latch](https://user-images.githubusercontent.com/6177048/137652149-a604ed8d-83bb-4d2d-973c-05658c12ae6b.png) | Left Shift + Left Control + Drag | Latch a curve to another curve by dragging a free anchor close to another free anchor | 19 | | ![unlatch](https://user-images.githubusercontent.com/6177048/137652201-3a6880c3-c149-4ff1-bc27-b8132bf52fc2.png) | Space + Drag | Unlatch anchors that were latched together. | 20 | | ![hide_anchors](https://user-images.githubusercontent.com/6177048/137652205-d915eb15-88ea-45da-92a0-3d3680a56ea1.png) | H | Hide anchors and control points | 21 | | ![save](https://user-images.githubusercontent.com/6177048/137652208-a7d843b7-6adc-414b-b0d7-126afd4f809f.png) | Left Control + S | Save set of existing individual curves (does not currently preserve groups or latches) | 22 | | ![load](https://user-images.githubusercontent.com/6177048/137652246-69c1309e-2486-496c-acbc-852a255476d2.png) | Left Control + L | Load set of saved curves (does not currently preserve groups or latches)| 23 | | ![hide_ctrls](https://user-images.githubusercontent.com/6177048/137652249-81669e44-42b8-4775-afe5-071c248713ef.png) | Left Control + Left Shift + H | Hide the control points | 24 | | ![lut](https://user-images.githubusercontent.com/6177048/137652254-f62c0d1b-d323-4ec6-b51f-c86b3f21f390.png) | Left Shift + T | Compute look-up table (linearizes animations) | 25 | | ![sound](https://user-images.githubusercontent.com/6177048/137652277-c43ace61-723b-409b-b48b-5521238c5e4d.png) | None | Toggle sound | 26 | | ![bin](https://user-images.githubusercontent.com/6177048/137652281-a461da81-bbd0-4728-a80f-7bb19849a149.png) | Select curves or group + Delete | Delete curves or group | 27 | | ![road](https://user-images.githubusercontent.com/6177048/137652369-0bd832a9-9c03-42a3-9dc6-b840f45c86dd.png) | None | Spawn road on curve group | 28 | | ![mesh](https://user-images.githubusercontent.com/6177048/137652366-ffc53243-0df9-4e84-a0ab-3985c3c59302.png) | None | Spawn mesh inside curve group | 29 | | ![heli](https://user-images.githubusercontent.com/6177048/137652364-67eedf2b-8283-43b0-a2e6-e80e97f5cb89.png) | None | Spawn animated helicopter on curve group | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | ## Setup 40 | Clone the repo, copy and paste the crate called "bevy_pen_tool_plugin" from the "crates" folder in the repo to the directory for your project, and add "bevy_pen_tool_plugin" as a local dependency in Cargo.toml. Refer to main.rs and Cargo.toml for futher details. 41 | 42 | ## How to 43 | A typical sequence of actions using the plugin would be as follows: 44 | 1. Spawn curves 45 | 2. Latch them together 46 | 3. Group the latched curves (cannot be ungrouped) 47 | 4. Move anchors and control points to desired position 48 | 5. Compute the look-up table 49 | 6. Save 50 | 51 | A user can save and load the data structure for a group of Bezier curves -- called Group in the code -- in JSON format. The default directory for saving groups is "./saved/groups/", and the file extension is a custom one: ".group". Meshes can be saved in well-known ".obj" format, and their default save directory is "./saved/meshes". The one save button prompts a file dialog window for each data structure that can be saved in the current session. 52 | 53 | There are two important parameters to tweak and they are both located in a Resource called "Globals" 54 | 1. group_lut_num_points: the number of elements in the generated look-up table (more yields smoother animations/meshes) 55 | 2. road_width: the width of the road meshes. 56 | Refer to main.rs to see how to modify these parameters. 57 | 58 | When the control points, shown as arrow tips, are hidden, the plugin places them almost exactly on top of the anchors. In this mode of operation, one can draw an arbitrary polygon and generate the corresponding mesh. 59 | 60 | 61 | ## Notes 62 | bevy_pen_tool, in its current form, 63 | - attemps to follow Bevy's latest release 64 | - does not work with a Perspective Camera (only Orthographic) 65 | - cannot save multiple groups at once, only a single one 66 | - deletes everything on the canvas before loading a group of Bezier curves 67 | 68 | 69 | 70 | ## TODO 71 | - ability to move whole group 72 | - select and delete mesh 73 | - saving multiple groups 74 | - ruler tool 75 | - no guarantees, but maybe a 3D version 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /assets/lut/my_group_lut.txt: -------------------------------------------------------------------------------- 1 | { 2 | "path_length": 428.1096, 3 | "lut": [ 4 | [ 5 | 75.65233, 6 | 39.556183 7 | ], 8 | [ 9 | 72.01289, 10 | 41.803123 11 | ], 12 | [ 13 | 68.362915, 14 | 44.096 15 | ], 16 | [ 17 | 64.69503, 18 | 46.38355 19 | ], 20 | [ 21 | 60.96675, 22 | 48.55714 23 | ], 24 | [ 25 | 57.097446, 26 | 50.436615 27 | ], 28 | [ 29 | 53.02274, 30 | 51.872326 31 | ], 32 | [ 33 | 48.81086, 34 | 52.877003 35 | ], 36 | [ 37 | 44.526196, 38 | 53.59042 39 | ], 40 | [ 41 | 40.21482, 42 | 54.131462 43 | ], 44 | [ 45 | 35.9449, 46 | 54.568584 47 | ], 48 | [ 49 | 31.578703, 50 | 54.956856 51 | ], 52 | [ 53 | 27.303383, 54 | 55.303116 55 | ], 56 | [ 57 | 23.013409, 58 | 55.63055 59 | ], 60 | [ 61 | 18.65934, 62 | 55.940235 63 | ], 64 | [ 65 | 14.319022, 66 | 56.206467 67 | ], 68 | [ 69 | 10.015079, 70 | 56.400143 71 | ], 72 | [ 73 | 5.7276764, 74 | 56.483486 75 | ], 76 | [ 77 | 1.4044715, 78 | 56.399513 79 | ], 80 | [ 81 | -2.8902009, 82 | 56.069515 83 | ], 84 | [ 85 | -7.175977, 86 | 55.388382 87 | ], 88 | [ 89 | -11.349323, 90 | 54.25954 91 | ], 92 | [ 93 | -15.346702, 94 | 52.619118 95 | ], 96 | [ 97 | -19.087698, 98 | 50.49095 99 | ], 100 | [ 101 | -22.580011, 102 | 47.940342 103 | ], 104 | [ 105 | -25.837492, 106 | 45.07297 107 | ], 108 | [ 109 | -28.87856, 110 | 42.004547 111 | ], 112 | [ 113 | -31.774286, 114 | 38.778038 115 | ], 116 | [ 117 | -34.534866, 118 | 35.45809 119 | ], 120 | [ 121 | -37.023205, 122 | 31.963879 123 | ], 124 | [ 125 | -39.030937, 126 | 28.109638 127 | ], 128 | [ 129 | -40.03539, 130 | 23.95207 131 | ], 132 | [ 133 | -39.45558, 134 | 19.690819 135 | ], 136 | [ 137 | -37.4672, 138 | 15.864918 139 | ], 140 | [ 141 | -34.84456, 142 | 12.398328 143 | ], 144 | [ 145 | -32.14081, 146 | 9.034119 147 | ], 148 | [ 149 | -29.641071, 150 | 5.535929 151 | ], 152 | [ 153 | -27.522795, 154 | 1.7246153 155 | ], 156 | [ 157 | -26.004349, 158 | -2.283932 159 | ], 160 | [ 161 | -25.100025, 162 | -6.540269 163 | ], 164 | [ 165 | -24.785923, 166 | -10.851115 167 | ], 168 | [ 169 | -24.939764, 170 | -15.152214 171 | ], 172 | [ 173 | -25.491756, 174 | -19.419937 175 | ], 176 | [ 177 | -26.353035, 178 | -23.687748 179 | ], 180 | [ 181 | -27.371073, 182 | -27.87349 183 | ], 184 | [ 185 | -28.377975, 186 | -32.06019 187 | ], 188 | [ 189 | -29.119171, 190 | -36.320457 191 | ], 192 | [ 193 | -29.175243, 194 | -40.62201 195 | ], 196 | [ 197 | -28.026714, 198 | -44.778515 199 | ], 200 | [ 201 | -25.572914, 202 | -48.319138 203 | ], 204 | [ 205 | -22.258396, 206 | -51.12602 207 | ], 208 | [ 209 | -18.566418, 210 | -53.325382 211 | ], 212 | [ 213 | -14.570167, 214 | -55.170868 215 | ], 216 | [ 217 | -10.564711, 218 | -56.65694 219 | ], 220 | [ 221 | -6.401764, 222 | -57.888123 223 | ], 224 | [ 225 | -2.1682618, 226 | -58.855682 227 | ], 228 | [ 229 | 2.1173413, 230 | -59.58005 231 | ], 232 | [ 233 | 6.3365107, 234 | -60.073086 235 | ], 236 | [ 237 | 10.701572, 238 | -60.380867 239 | ], 240 | [ 241 | 15.032694, 242 | -60.507065 243 | ], 244 | [ 245 | 19.360605, 246 | -60.476456 247 | ], 248 | [ 249 | 23.649405, 250 | -60.31088 251 | ], 252 | [ 253 | 27.991518, 254 | -60.024494 255 | ], 256 | [ 257 | 32.291748, 258 | -59.640804 259 | ], 260 | [ 261 | 36.535103, 262 | -59.18198 263 | ], 264 | [ 265 | 40.86112, 266 | -58.651028 267 | ], 268 | [ 269 | 45.155296, 270 | -58.081936 271 | ], 272 | [ 273 | 49.408665, 274 | -57.5016 275 | ], 276 | [ 277 | 53.696774, 278 | -56.931488 279 | ], 280 | [ 281 | 57.97665, 282 | -56.421738 283 | ], 284 | [ 285 | 62.24278, 286 | -56.040802 287 | ], 288 | [ 289 | 66.59136, 290 | -55.633682 291 | ], 292 | [ 293 | 70.80036, 294 | -54.682873 295 | ], 296 | [ 297 | 74.86487, 298 | -53.177204 299 | ], 300 | [ 301 | 78.67168, 302 | -51.180874 303 | ], 304 | [ 305 | 82.21802, 306 | -48.731552 307 | ], 308 | [ 309 | 85.49883, 310 | -45.86038 311 | ], 312 | [ 313 | 88.44644, 314 | -42.666767 315 | ], 316 | [ 317 | 91.03071, 318 | -39.25362 319 | ], 320 | [ 321 | 93.326256, 322 | -35.581696 323 | ], 324 | [ 325 | 95.30631, 326 | -31.742237 327 | ], 328 | [ 329 | 97.00451, 330 | -27.72329 331 | ], 332 | [ 333 | 98.38413, 334 | -23.692299 335 | ], 336 | [ 337 | 99.52025, 338 | -19.507515 339 | ], 340 | [ 341 | 100.40977, 342 | -15.211164 343 | ], 344 | [ 345 | 101.04274, 346 | -10.983979 347 | ], 348 | [ 349 | 101.46067, 350 | -6.6748033 351 | ], 352 | [ 353 | 101.61834, 354 | -2.3440204 355 | ], 356 | [ 357 | 101.46939, 358 | 1.995478 359 | ], 360 | [ 361 | 100.97136, 362 | 6.270068 363 | ], 364 | [ 365 | 100.074196, 366 | 10.504586 367 | ], 368 | [ 369 | 98.761986, 370 | 14.586327 371 | ], 372 | [ 373 | 97.007965, 374 | 18.522402 375 | ], 376 | [ 377 | 94.82377, 378 | 22.259634 379 | ], 380 | [ 381 | 92.25176, 382 | 25.754744 383 | ], 384 | [ 385 | 89.347855, 386 | 28.99271 387 | ], 388 | [ 389 | 86.21853, 390 | 31.937885 391 | ], 392 | [ 393 | 82.874695, 394 | 34.657955 395 | ], 396 | [ 397 | 79.3612, 398 | 37.176285 399 | ], 400 | [ 401 | 75.688644, 402 | 39.534027 403 | ] 404 | ] 405 | } -------------------------------------------------------------------------------- /assets/meshes/my_mesh.obj: -------------------------------------------------------------------------------- 1 | o My_mesh 2 | v 15.032694 -60.507065 0.000000 3 | v 19.360605 -60.476456 0.000000 4 | v 10.701572 -60.380867 0.000000 5 | v 23.649405 -60.310879 0.000000 6 | v 6.336511 -60.073086 0.000000 7 | v 27.991518 -60.024494 0.000000 8 | v 32.291748 -59.640804 0.000000 9 | v 2.117341 -59.580051 0.000000 10 | v 36.535103 -59.181980 0.000000 11 | v -2.168262 -58.855682 0.000000 12 | v 40.861118 -58.651028 0.000000 13 | v 45.155296 -58.081936 0.000000 14 | v -6.401764 -57.888123 0.000000 15 | v 49.408665 -57.501598 0.000000 16 | v 53.696774 -56.931488 0.000000 17 | v -10.564711 -56.656940 0.000000 18 | v 57.976650 -56.421738 0.000000 19 | v 62.242779 -56.040802 0.000000 20 | v 66.591362 -55.633682 0.000000 21 | v -14.570167 -55.170868 0.000000 22 | v 70.800362 -54.682873 0.000000 23 | v -18.566418 -53.325382 0.000000 24 | v 74.864868 -53.177204 0.000000 25 | v 78.671677 -51.180874 0.000000 26 | v -22.258396 -51.126019 0.000000 27 | v 82.218018 -48.731552 0.000000 28 | v -25.572914 -48.319138 0.000000 29 | v 85.498833 -45.860378 0.000000 30 | v -28.026714 -44.778515 0.000000 31 | v 88.446442 -42.666767 0.000000 32 | v -29.175243 -40.622009 0.000000 33 | v 91.030708 -39.253620 0.000000 34 | v -29.119171 -36.320457 0.000000 35 | v 93.326256 -35.581696 0.000000 36 | v -28.377975 -32.060188 0.000000 37 | v 95.306313 -31.742237 0.000000 38 | v -27.371073 -27.873489 0.000000 39 | v 97.004509 -27.723289 0.000000 40 | v 98.384132 -23.692299 0.000000 41 | v -26.353035 -23.687748 0.000000 42 | v 99.520248 -19.507515 0.000000 43 | v -25.491756 -19.419937 0.000000 44 | v 100.409767 -15.211164 0.000000 45 | v -24.939764 -15.152214 0.000000 46 | v 101.042740 -10.983979 0.000000 47 | v -24.785923 -10.851115 0.000000 48 | v 101.460670 -6.674803 0.000000 49 | v -25.100025 -6.540269 0.000000 50 | v 101.618340 -2.344020 0.000000 51 | v -26.004349 -2.283932 0.000000 52 | v -27.522795 1.724615 0.000000 53 | v 101.469391 1.995478 0.000000 54 | v -29.641071 5.535929 0.000000 55 | v 100.971359 6.270068 0.000000 56 | v -32.140808 9.034119 0.000000 57 | v 100.074196 10.504586 0.000000 58 | v -34.844559 12.398328 0.000000 59 | v 98.761986 14.586327 0.000000 60 | v -37.467201 15.864918 0.000000 61 | v 97.007965 18.522402 0.000000 62 | v -39.455582 19.690819 0.000000 63 | v 94.823769 22.259634 0.000000 64 | v -40.035389 23.952070 0.000000 65 | v 92.251762 25.754744 0.000000 66 | v -39.030937 28.109638 0.000000 67 | v 89.347855 28.992710 0.000000 68 | v 86.218529 31.937885 0.000000 69 | v -37.023205 31.963879 0.000000 70 | v 82.874695 34.657955 0.000000 71 | v -34.534866 35.458092 0.000000 72 | v 79.361198 37.176285 0.000000 73 | v -31.774286 38.778038 0.000000 74 | v 75.688644 39.534027 0.000000 75 | v 75.652328 39.556183 0.000000 76 | v 72.012894 41.803123 0.000000 77 | v -28.878559 42.004547 0.000000 78 | v 68.362915 44.096001 0.000000 79 | v -25.837492 45.072971 0.000000 80 | v 64.695030 46.383549 0.000000 81 | v -22.580011 47.940342 0.000000 82 | v 60.966751 48.557140 0.000000 83 | v 57.097446 50.436615 0.000000 84 | v -19.087698 50.490952 0.000000 85 | v 53.022739 51.872326 0.000000 86 | v -15.346702 52.619118 0.000000 87 | v 48.810860 52.877003 0.000000 88 | v 44.526196 53.590420 0.000000 89 | v 40.214821 54.131462 0.000000 90 | v -11.349323 54.259541 0.000000 91 | v 35.944901 54.568584 0.000000 92 | v 31.578703 54.956856 0.000000 93 | v 27.303383 55.303116 0.000000 94 | v -7.175977 55.388382 0.000000 95 | v 23.013409 55.630550 0.000000 96 | v 18.659340 55.940235 0.000000 97 | v -2.890201 56.069515 0.000000 98 | v 14.319022 56.206467 0.000000 99 | v 1.404472 56.399513 0.000000 100 | v 10.015079 56.400143 0.000000 101 | v 5.727676 56.483486 0.000000 102 | vn 0.000000 0.000000 1.000000 103 | f 100/100/1 98/98/1 99/99/1 104 | f 99/99/1 98/98/1 75/75/1 105 | f 98/98/1 72/72/1 75/75/1 106 | f 88/88/1 94/94/1 75/75/1 107 | f 88/88/1 75/75/1 82/82/1 108 | f 94/94/1 97/97/1 75/75/1 109 | f 94/94/1 88/88/1 91/91/1 110 | f 88/88/1 82/82/1 86/86/1 111 | f 82/82/1 75/75/1 79/79/1 112 | f 97/97/1 99/99/1 75/75/1 113 | f 97/97/1 94/94/1 95/95/1 114 | f 94/94/1 91/91/1 92/92/1 115 | f 91/91/1 88/88/1 90/90/1 116 | f 88/88/1 86/86/1 87/87/1 117 | f 86/86/1 82/82/1 84/84/1 118 | f 82/82/1 79/79/1 81/81/1 119 | f 79/79/1 75/75/1 77/77/1 120 | f 96/96/1 83/83/1 72/72/1 121 | f 96/96/1 89/89/1 83/83/1 122 | f 83/83/1 78/78/1 72/72/1 123 | f 98/98/1 96/96/1 72/72/1 124 | f 96/96/1 93/93/1 89/89/1 125 | f 89/89/1 85/85/1 83/83/1 126 | f 83/83/1 80/80/1 78/78/1 127 | f 78/78/1 76/76/1 72/72/1 128 | f 75/75/1 72/72/1 74/74/1 129 | f 74/74/1 72/72/1 49/49/1 130 | f 66/66/1 73/73/1 49/49/1 131 | f 66/66/1 49/49/1 58/58/1 132 | f 73/73/1 66/66/1 69/69/1 133 | f 66/66/1 58/58/1 62/62/1 134 | f 58/58/1 49/49/1 54/54/1 135 | f 73/73/1 74/74/1 49/49/1 136 | f 73/73/1 69/69/1 71/71/1 137 | f 69/69/1 66/66/1 67/67/1 138 | f 66/66/1 62/62/1 64/64/1 139 | f 62/62/1 58/58/1 60/60/1 140 | f 58/58/1 54/54/1 56/56/1 141 | f 54/54/1 49/49/1 52/52/1 142 | f 72/72/1 55/55/1 49/49/1 143 | f 72/72/1 63/63/1 55/55/1 144 | f 72/72/1 68/68/1 63/63/1 145 | f 63/63/1 59/59/1 55/55/1 146 | f 72/72/1 70/70/1 68/68/1 147 | f 68/68/1 65/65/1 63/63/1 148 | f 63/63/1 61/61/1 59/59/1 149 | f 59/59/1 57/57/1 55/55/1 150 | f 55/55/1 53/53/1 49/49/1 151 | f 53/53/1 51/51/1 49/49/1 152 | f 51/51/1 50/50/1 49/49/1 153 | f 50/50/1 48/48/1 49/49/1 154 | f 49/49/1 48/48/1 17/17/1 155 | f 45/45/1 17/17/1 30/30/1 156 | f 45/45/1 30/30/1 38/38/1 157 | f 30/30/1 17/17/1 23/23/1 158 | f 45/45/1 49/49/1 17/17/1 159 | f 45/45/1 38/38/1 41/41/1 160 | f 38/38/1 30/30/1 34/34/1 161 | f 30/30/1 23/23/1 26/26/1 162 | f 23/23/1 17/17/1 19/19/1 163 | f 49/49/1 45/45/1 47/47/1 164 | f 45/45/1 41/41/1 43/43/1 165 | f 41/41/1 38/38/1 39/39/1 166 | f 38/38/1 34/34/1 36/36/1 167 | f 34/34/1 30/30/1 32/32/1 168 | f 30/30/1 26/26/1 28/28/1 169 | f 26/26/1 23/23/1 24/24/1 170 | f 23/23/1 19/19/1 21/21/1 171 | f 19/19/1 17/17/1 18/18/1 172 | f 48/48/1 46/46/1 17/17/1 173 | f 46/46/1 44/44/1 17/17/1 174 | f 44/44/1 42/42/1 17/17/1 175 | f 42/42/1 40/40/1 17/17/1 176 | f 40/40/1 16/16/1 17/17/1 177 | f 35/35/1 27/27/1 16/16/1 178 | f 40/40/1 35/35/1 16/16/1 179 | f 35/35/1 31/31/1 27/27/1 180 | f 27/27/1 22/22/1 16/16/1 181 | f 40/40/1 37/37/1 35/35/1 182 | f 35/35/1 33/33/1 31/31/1 183 | f 31/31/1 29/29/1 27/27/1 184 | f 27/27/1 25/25/1 22/22/1 185 | f 22/22/1 20/20/1 16/16/1 186 | f 17/17/1 16/16/1 15/15/1 187 | f 16/16/1 13/13/1 15/15/1 188 | f 15/15/1 13/13/1 14/14/1 189 | f 14/14/1 13/13/1 2/2/1 190 | f 9/9/1 12/12/1 2/2/1 191 | f 9/9/1 2/2/1 6/6/1 192 | f 12/12/1 14/14/1 2/2/1 193 | f 12/12/1 9/9/1 11/11/1 194 | f 9/9/1 6/6/1 7/7/1 195 | f 6/6/1 2/2/1 4/4/1 196 | f 13/13/1 3/3/1 2/2/1 197 | f 13/13/1 8/8/1 3/3/1 198 | f 13/13/1 10/10/1 8/8/1 199 | f 8/8/1 5/5/1 3/3/1 200 | f 3/3/1 1/1/1 2/2/1 201 | -------------------------------------------------------------------------------- /assets/shaders/bounding_box.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct UiMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | 18 | @group(1) @binding(0) 19 | var material: UiMat; 20 | 21 | 22 | struct Vertex { 23 | @location(0) position: vec3, 24 | @location(1) normal: vec3, 25 | @location(2) uv: vec2, 26 | #ifdef VERTEX_TANGENTS 27 | @location(3) tangent: vec4, 28 | #endif 29 | }; 30 | 31 | struct VertexOutput { 32 | @builtin(position) clip_position: vec4, 33 | @location(0) world_position: vec4, 34 | @location(1) world_normal: vec3, 35 | @location(2) uv: vec2, 36 | #ifdef VERTEX_TANGENTS 37 | @location(3) world_tangent: vec4, 38 | #endif 39 | }; 40 | 41 | @group(0) @binding(0) 42 | var view: View; 43 | 44 | 45 | @group(2) @binding(0) 46 | var mesh: Mesh2d; 47 | 48 | @vertex 49 | fn vertex(vertex: Vertex) -> VertexOutput { 50 | let world_position = mesh.model * vec4(vertex.position, 1.0); 51 | 52 | var out: VertexOutput; 53 | out.uv = vertex.uv; 54 | out.world_position = world_position; 55 | out.clip_position = view.view_proj * world_position; 56 | out.world_normal = mat3x3( 57 | mesh.inverse_transpose_model[0].xyz, 58 | mesh.inverse_transpose_model[1].xyz, 59 | mesh.inverse_transpose_model[2].xyz 60 | ) * vertex.normal; 61 | #ifdef VERTEX_TANGENTS 62 | out.world_tangent = vec4( 63 | mat3x3( 64 | mesh.model[0].xyz, 65 | mesh.model[1].xyz, 66 | mesh.model[2].xyz 67 | ) * vertex.tangent.xyz, 68 | vertex.tangent.w 69 | ); 70 | #endif 71 | return out; 72 | } 73 | 74 | struct FragmentInput { 75 | @builtin(front_facing) is_front: bool, 76 | @location(0) world_position: vec4, 77 | @location(1) world_normal: vec3, 78 | @location(2) uv: vec2, 79 | #ifdef VERTEX_TANGENTS 80 | @location(3) world_tangent: vec4, 81 | #endif 82 | }; 83 | 84 | @fragment 85 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 86 | 87 | let aspect_ratio = material.size.y / material.size.x ; 88 | 89 | var uv_original: vec2 = in.uv - vec2(0.5); 90 | // uv_original.y = uv_original.y * aspect_ratio ; 91 | 92 | let cx = material.size.x / 42.0; 93 | let cy = material.size.y / 42.0; 94 | 95 | let p = 0.5 - 0.05 / 1.1; 96 | let bb_size = 0.1; 97 | 98 | let zoo = material.zoom / 0.08; 99 | 100 | let width = 0.0051; 101 | let sw = 0.0025 * zoo; 102 | 103 | let w = sw / cx; 104 | let m = p + w; 105 | let l = p-w; 106 | let q = width / cx; 107 | 108 | let xdo = smoothstep( m+q, l+q, abs(uv_original.x ) ); 109 | let xdi = 1.0 - smoothstep( m-q, l-q, abs(uv_original.x ) ); 110 | 111 | let p = 0.5 - 0.05 / 1.0 - bb_size / cx; 112 | let w = sw / cx; 113 | let m = p + w; 114 | let l = p-w; 115 | let q = width / cx; 116 | // let xda = 1 -smoothstep( m+q, l+q, (0.5-abs(uv_original.x) )/1.1 ); 117 | let xda= 1.0 - smoothstep( m+q, l+q, abs(uv_original.x ) ); 118 | // xda = 1 - step(uv.x*material.size.x, material.size.x/2 - 10.0 ); 119 | // xda = step(uv.x*material.size.x, material.size.x*0.9/2 ); 120 | 121 | let p = 0.5 - 0.05 / 1.1; 122 | let w = sw / cy; 123 | let m = p + w; 124 | let l = p-w; 125 | let q = width / cy; 126 | 127 | let ydi = 1.0 - smoothstep( m-q, l-q, abs(uv_original.y ) ); 128 | let ydo = smoothstep( m+q, l+q, abs(uv_original.y ) ); 129 | 130 | 131 | let p = 0.5 - 0.05 / 1.0 - bb_size / cy; 132 | let w = sw / cy; 133 | let m = p + w; 134 | let l = p-w; 135 | let q = width / cy; 136 | // let yda = smoothstep( p, p-0.01, 0.5 - abs(uv_original.y ) ); 137 | let yda= 1.0 - smoothstep( m+q, l+q, abs(uv_original.y ) ); 138 | // yda = step(0.5 - abs(uv_original.y ), p ); 139 | 140 | 141 | let xd = xdi * xdo * ydo * xda * yda; 142 | let yd = ydi * ydo * xdo * xda * yda; 143 | 144 | 145 | let red = vec4(0.0, 0.0, 0.0, 0.00); 146 | let color2 = material.color; 147 | // color2.a = 0.3; 148 | 149 | let rect = mix( red ,color2 , min(yd + xd, 1.0)); 150 | // let rect = mix( red ,color2 , xda); 151 | 152 | 153 | 154 | 155 | return rect; 156 | // return vec4(1.0, 0.0, 0.0, 1.0); 157 | 158 | } -------------------------------------------------------------------------------- /assets/shaders/button.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct ButtonMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | @group(1) @binding(0) 18 | var material: ButtonMat; 19 | 20 | 21 | struct Vertex { 22 | @location(0) position: vec3, 23 | @location(1) normal: vec3, 24 | @location(2) uv: vec2, 25 | #ifdef VERTEX_TANGENTS 26 | @location(3) tangent: vec4, 27 | #endif 28 | }; 29 | 30 | struct VertexOutput { 31 | @builtin(position) clip_position: vec4, 32 | @location(0) world_position: vec4, 33 | @location(1) world_normal: vec3, 34 | @location(2) uv: vec2, 35 | #ifdef VERTEX_TANGENTS 36 | @location(3) world_tangent: vec4, 37 | #endif 38 | }; 39 | 40 | 41 | @group(0) @binding(0) 42 | var view: View; 43 | 44 | 45 | @group(2) @binding(0) 46 | var mesh: Mesh2d; 47 | 48 | @vertex 49 | fn vertex(vertex: Vertex) -> VertexOutput { 50 | let world_position = mesh.model * vec4(vertex.position, 1.0); 51 | 52 | var out: VertexOutput; 53 | out.uv = vertex.uv; 54 | out.world_position = world_position; 55 | out.clip_position = view.view_proj * world_position; 56 | out.world_normal = mat3x3( 57 | mesh.inverse_transpose_model[0].xyz, 58 | mesh.inverse_transpose_model[1].xyz, 59 | mesh.inverse_transpose_model[2].xyz 60 | ) * vertex.normal; 61 | #ifdef VERTEX_TANGENTS 62 | out.world_tangent = vec4( 63 | mat3x3( 64 | mesh.model[0].xyz, 65 | mesh.model[1].xyz, 66 | mesh.model[2].xyz 67 | ) * vertex.tangent.xyz, 68 | vertex.tangent.w 69 | ); 70 | #endif 71 | return out; 72 | } 73 | 74 | struct FragmentInput { 75 | @builtin(front_facing) is_front: bool, 76 | @location(0) world_position: vec4, 77 | @location(1) world_normal: vec3, 78 | @location(2) uv: vec2, 79 | #ifdef VERTEX_TANGENTS 80 | @location(3) world_tangent: vec4, 81 | #endif 82 | }; 83 | 84 | 85 | 86 | 87 | fn sdBox(p: vec2, b: vec2) -> f32 { 88 | let d = abs(p) - b; 89 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 90 | } 91 | 92 | fn sdCircle(p: vec2, r: f32) -> f32 { 93 | return length(p) - r; 94 | } 95 | 96 | fn fromLinear(linearRGB: vec4) -> vec4 97 | { 98 | let cutoff: vec4 = vec4(linearRGB < vec4(0.0031308)); 99 | let higher: vec4 = vec4(1.055)*pow(linearRGB, vec4(1.0/2.4)) - vec4(0.055); 100 | let lower: vec4 = linearRGB * vec4(12.92); 101 | 102 | return mix(higher, lower, cutoff); 103 | } 104 | 105 | // // Converts a color from sRGB gamma to linear light gamma 106 | fn toLinear(sRGB: vec4) -> vec4 107 | { 108 | let cutoff = vec4(sRGB < vec4(0.04045)); 109 | let higher = pow((sRGB + vec4(0.055))/vec4(1.055), vec4(2.4)); 110 | let lower = sRGB/vec4(12.92); 111 | 112 | return mix(higher, lower, cutoff); 113 | } 114 | 115 | 116 | @fragment 117 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 118 | 119 | let aspect_ratio = material.size.y / material.size.x ; 120 | 121 | var uv_original: vec2 = in.uv - vec2(0.5); 122 | uv_original.x = uv_original.x * aspect_ratio ; 123 | 124 | let margin = 0.2; 125 | var d = sdBox( uv_original, vec2(0.5 - margin , 0.5*aspect_ratio - margin ) ); 126 | let offset = 0.1; 127 | d = smoothstep(0.01+offset, -0.01+offset, d); 128 | 129 | 130 | let other_color = vec4(.0, .0, .0, 0.0); 131 | let white = vec4(1.0, 1.0, 1.0, 1.0); 132 | let yellow = vec4(0.6, 0.75, 0.04, 1.0); 133 | let red = vec4(0.8, 0.45, 0.04, 1.0); 134 | 135 | var bg_color = material.clearcolor; 136 | bg_color.a = 0.0; 137 | 138 | var rect = mix( material.color , bg_color , 1. - d ); 139 | let rect_memory = rect; 140 | 141 | 142 | 143 | // add white contour when color is selected 144 | if (material.hovered > 0.5) { 145 | let r = 0.3; // size 146 | let w = 0.06; // contour width 147 | var d = sdBox( uv_original, vec2(r,r) ); 148 | let c = 0.15; // contour roundness 149 | let b = 0.03; // smoothing 150 | let s1 = smoothstep(-b+w+c, b+w+c, d); 151 | let s2 = smoothstep(-b-w+c, b-w+c, d); 152 | 153 | d = (1.-s1) * (s2); 154 | 155 | rect = mix( white , other_color , 1. - d ); 156 | rect = mix(rect_memory, rect, d); 157 | } 158 | 159 | 160 | if (material.hovered > 0.9) { 161 | let r = 0.3; // size 162 | let w = 0.03; // contour width 163 | var d = sdBox( uv_original, vec2(r,r) ); 164 | let c = 0.15; // contour roundness 165 | let b = 0.03; // smoothing 166 | let s1 = smoothstep(-b+w+c, b+w+c, d); 167 | let s2 = smoothstep(-b-w+c, b-w+c, d); 168 | 169 | d = (1.-s1) * (s2); 170 | 171 | let rect_hover = mix( yellow , other_color , 1. - d ); 172 | rect = mix(rect, rect_hover, d); 173 | } else if (material.hovered>0.7) // if pressed 174 | { 175 | let r = 0.3; // size 176 | let w = 0.03; // contour width 177 | var d = sdBox( uv_original, vec2(r,r) ); 178 | let c = 0.15; // contour roundness 179 | let b = 0.03; // smoothing 180 | let s1 = smoothstep(-b+w+c, b+w+c, d); 181 | let s2 = smoothstep(-b-w+c, b-w+c, d); 182 | 183 | d = (1.-s1) * (s2); 184 | 185 | let rect_hover = mix( red , other_color , 1. - d ); 186 | rect = mix(rect, rect_hover, d); 187 | } 188 | 189 | // rect = vec4(rect.xyz * 0.5, 1.0); 190 | // rect.w = 1.0; 191 | 192 | 193 | return toLinear( rect); 194 | } 195 | -------------------------------------------------------------------------------- /assets/shaders/controls.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct UiMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | 18 | @group(1) @binding(0) 19 | var material: UiMat; 20 | 21 | 22 | struct Vertex { 23 | @location(0) position: vec3, 24 | @location(1) normal: vec3, 25 | @location(2) uv: vec2, 26 | #ifdef VERTEX_TANGENTS 27 | @location(3) tangent: vec4, 28 | #endif 29 | }; 30 | 31 | struct VertexOutput { 32 | @builtin(position) clip_position: vec4, 33 | @location(0) world_position: vec4, 34 | @location(1) world_normal: vec3, 35 | @location(2) uv: vec2, 36 | #ifdef VERTEX_TANGENTS 37 | @location(3) world_tangent: vec4, 38 | #endif 39 | }; 40 | 41 | 42 | @group(0) @binding(0) 43 | var view: View; 44 | 45 | 46 | @group(2) @binding(0) 47 | var mesh: Mesh2d; 48 | 49 | fn sdTriangle( p: vec2, p0: vec2, p1: vec2, p2: vec2 ) -> f32 50 | { 51 | let e0 = p1-p0; 52 | let e1 = p2-p1; 53 | let e2 = p0-p2; 54 | let v0 = p -p0; 55 | let v1 = p -p1; 56 | let v2 = p -p2; 57 | let pq0 = v0 - e0*clamp( dot(v0,e0)/dot(e0,e0), 0.0, 1.0 ); 58 | let pq1 = v1 - e1*clamp( dot(v1,e1)/dot(e1,e1), 0.0, 1.0 ); 59 | let pq2 = v2 - e2*clamp( dot(v2,e2)/dot(e2,e2), 0.0, 1.0 ); 60 | let s = sign( e0.x*e2.y - e0.y*e2.x ); 61 | let d = min(min(vec2(dot(pq0,pq0), s*(v0.x*e0.y-v0.y*e0.x)), 62 | vec2(dot(pq1,pq1), s*(v1.x*e1.y-v1.y*e1.x))), 63 | vec2(dot(pq2,pq2), s*(v2.x*e2.y-v2.y*e2.x))); 64 | return -sqrt(d.x)*sign(d.y); 65 | } 66 | 67 | 68 | @vertex 69 | fn vertex(vertex: Vertex) -> VertexOutput { 70 | let world_position = mesh.model * vec4(vertex.position, 1.0); 71 | 72 | var out: VertexOutput; 73 | out.uv = vertex.uv; 74 | out.world_position = world_position; 75 | out.clip_position = view.view_proj * world_position; 76 | out.world_normal = mat3x3( 77 | mesh.inverse_transpose_model[0].xyz, 78 | mesh.inverse_transpose_model[1].xyz, 79 | mesh.inverse_transpose_model[2].xyz 80 | ) * vertex.normal; 81 | #ifdef VERTEX_TANGENTS 82 | out.world_tangent = vec4( 83 | mat3x3( 84 | mesh.model[0].xyz, 85 | mesh.model[1].xyz, 86 | mesh.model[2].xyz 87 | ) * vertex.tangent.xyz, 88 | vertex.tangent.w 89 | ); 90 | #endif 91 | return out; 92 | } 93 | 94 | struct FragmentInput { 95 | @builtin(front_facing) is_front: bool, 96 | @location(0) world_position: vec4, 97 | @location(1) world_normal: vec3, 98 | @location(2) uv: vec2, 99 | #ifdef VERTEX_TANGENTS 100 | @location(3) world_tangent: vec4, 101 | #endif 102 | }; 103 | 104 | fn sdBox(p: vec2, b: vec2) -> f32 { 105 | let d = abs(p) - b; 106 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 107 | } 108 | 109 | fn sdCircle(p: vec2, r: f32) -> f32 { 110 | return length(p) - r; 111 | } 112 | 113 | 114 | 115 | @fragment 116 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 117 | 118 | let aspect_ratio = material.size.y / material.size.x ; 119 | 120 | var uv_original: vec2 = in.uv - vec2(0.5); 121 | uv_original.y = uv_original.y * aspect_ratio ; 122 | 123 | // let pos = vec2(0.5, 0.5); 124 | // let uv_original = (Vertex_Uv.xy-pos); 125 | 126 | 127 | 128 | let p0 = vec2(0.0, -0.4); 129 | let p1 = vec2(0.4, 0.4); 130 | let p2 = vec2(-0.4, 0.4); 131 | var d0 = sdTriangle( uv_original, p0, p1, p2 ); 132 | 133 | let zoo = material.zoom / 0.08 / 5.; 134 | let w = -0.02 * zoo; 135 | d0 = smoothstep(-w, w, d0); 136 | 137 | let p3 = vec2(0.0, -0.0); 138 | let p4 = vec2(0.4, 0.45); 139 | let p5 = vec2(-0.4, 0.45); 140 | 141 | var d1 = sdTriangle( uv_original, p3, p4, p5 ); 142 | d1 = smoothstep(-w, w, d1); 143 | 144 | 145 | let d = d0 * (1.0 - d1); 146 | 147 | // let color_with_t = material.color; 148 | 149 | var bg_color = material.clearcolor; 150 | bg_color.a = 0.0; 151 | 152 | let circle = mix( material.color, bg_color, 1.0 - d ); 153 | 154 | 155 | // o_Target = circle; 156 | 157 | 158 | 159 | return circle; 160 | // return vec4(1.0, 1.0, 1.0, 1.0); 161 | } 162 | -------------------------------------------------------------------------------- /assets/shaders/ends.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct UiMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | 18 | @group(1) @binding(0) 19 | var material: UiMat; 20 | 21 | 22 | struct Vertex { 23 | @location(0) position: vec3, 24 | @location(1) normal: vec3, 25 | @location(2) uv: vec2, 26 | #ifdef VERTEX_TANGENTS 27 | @location(3) tangent: vec4, 28 | #endif 29 | }; 30 | 31 | struct VertexOutput { 32 | @builtin(position) clip_position: vec4, 33 | @location(0) world_position: vec4, 34 | @location(1) world_normal: vec3, 35 | @location(2) uv: vec2, 36 | #ifdef VERTEX_TANGENTS 37 | @location(3) world_tangent: vec4, 38 | #endif 39 | }; 40 | 41 | 42 | @group(0) @binding(0) 43 | var view: View; 44 | 45 | 46 | @group(2) @binding(0) 47 | var mesh: Mesh2d; 48 | 49 | @vertex 50 | fn vertex(vertex: Vertex) -> VertexOutput { 51 | let world_position = mesh.model * vec4(vertex.position, 1.0); 52 | 53 | var out: VertexOutput; 54 | out.uv = vertex.uv; 55 | out.world_position = world_position; 56 | out.clip_position = view.view_proj * world_position; 57 | out.world_normal = mat3x3( 58 | mesh.inverse_transpose_model[0].xyz, 59 | mesh.inverse_transpose_model[1].xyz, 60 | mesh.inverse_transpose_model[2].xyz 61 | ) * vertex.normal; 62 | #ifdef VERTEX_TANGENTS 63 | out.world_tangent = vec4( 64 | mat3x3( 65 | mesh.model[0].xyz, 66 | mesh.model[1].xyz, 67 | mesh.model[2].xyz 68 | ) * vertex.tangent.xyz, 69 | vertex.tangent.w 70 | ); 71 | #endif 72 | return out; 73 | } 74 | 75 | struct FragmentInput { 76 | @builtin(front_facing) is_front: bool, 77 | @location(0) world_position: vec4, 78 | @location(1) world_normal: vec3, 79 | @location(2) uv: vec2, 80 | #ifdef VERTEX_TANGENTS 81 | @location(3) world_tangent: vec4, 82 | #endif 83 | }; 84 | 85 | 86 | fn sdBox(p: vec2, b: vec2) -> f32 { 87 | let d = abs(p) - b; 88 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 89 | } 90 | 91 | fn sdCircle(p: vec2, r: f32) -> f32 { 92 | return length(p) - r; 93 | } 94 | 95 | 96 | 97 | @fragment 98 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 99 | 100 | let aspect_ratio = material.size.y / material.size.x ; 101 | 102 | var uv_original: vec2 = (in.uv - vec2(0.5)); 103 | uv_original.x = uv_original.x / 2.0 ; 104 | 105 | 106 | // let zoo = material.zoom / 0.08; 107 | let zoo = 1.0; 108 | let w = -0.03 * zoo; 109 | 110 | let offset = 0.5; 111 | 112 | var d0 = sdCircle( uv_original - offset * vec2(0.5,0.), 0.5 ); 113 | d0 = smoothstep(-w, w, d0); 114 | 115 | var d1 = sdCircle( uv_original - offset * vec2(0.5, 0.), 0.3 / (1.0 + pow(zoo, 0.5))); 116 | d1 = smoothstep(-w, w, d1); 117 | 118 | let d = 1. - d0 * (1. - d1); 119 | 120 | 121 | var color_with_t = material.color; 122 | 123 | 124 | var bg_color = material.clearcolor; 125 | bg_color.a = 0.0; 126 | let circle = mix( color_with_t ,bg_color , d ); 127 | 128 | return circle; 129 | } 130 | 131 | 132 | 133 | // void main( ) 134 | // { 135 | // vec2 pos = vec2(0.5, 0.5); 136 | // vec2 uv_original = (Vertex_Uv.xy-pos); 137 | // uv_original.x = (uv_original.x -0.5) / 2.0; 138 | 139 | // float zoo = zoom / 0.08; 140 | // float w = -0.03 * zoo; 141 | 142 | // float d0 = sdCircle( uv_original, 0.5 ); 143 | // d0 = smoothstep(-w, w, d0); 144 | 145 | // float d1 = sdCircle( uv_original, 0.3 / (1 + pow(zoo, 0.5))); 146 | // d1 = smoothstep(-w, w, d1); 147 | 148 | // float d = 1 - d0 * (1- d1); 149 | 150 | 151 | // // makes the middle quads disappear close to the ends 152 | // float transparency = smoothstep( 0.0, 0.05, 0.5-abs(t-0.5)); 153 | // vec4 color_with_t = color; 154 | // color_with_t.a = transparency; 155 | 156 | // // vec4 other_color = vec4(110. / 255., 127. / 255., 128. / 255., 0.0); 157 | // vec4 bg_color = clear_color; 158 | // bg_color.a = 0.0; 159 | // vec4 circle = mix( color_with_t ,bg_color , d ); 160 | 161 | 162 | // o_Target = circle; 163 | // } 164 | -------------------------------------------------------------------------------- /assets/shaders/fill_mesh.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | // [[group(0), binding(0)]] 5 | 6 | @group(0) @binding(0) 7 | var view: View; 8 | 9 | 10 | @group(1) @binding(0) 11 | var mesh: Mesh2d; 12 | 13 | 14 | 15 | 16 | struct Vertex { 17 | @location(0) position: vec3, 18 | @location(1) color: vec4, 19 | @location(2) uv: vec2, 20 | 21 | }; 22 | 23 | struct VertexOutput { 24 | @builtin(position) clip_position: vec4, 25 | @location(0) color: vec4, 26 | @location(1) uv: vec2, 27 | }; 28 | 29 | /// Entry point for the vertex shader 30 | @vertex 31 | fn vertex(vertex: Vertex) -> VertexOutput { 32 | var out: VertexOutput; 33 | // Project the world position of the mesh into screen position 34 | out.clip_position = view.view_proj * mesh.model * vec4(vertex.position, 1.0); 35 | out.color = vertex.color; 36 | out.uv = vertex.uv; 37 | return out; 38 | } 39 | 40 | fn fromLinear(linearRGB: vec4) -> vec4 41 | { 42 | let cutoff: vec4 = vec4(linearRGB < vec4(0.0031308)); 43 | let higher: vec4 = vec4(1.055)*pow(linearRGB, vec4(1.0/2.4)) - vec4(0.055); 44 | let lower: vec4 = linearRGB * vec4(12.92); 45 | 46 | return mix(higher, lower, cutoff); 47 | } 48 | 49 | // // Converts a color from sRGB gamma to linear light gamma 50 | fn toLinear(sRGB: vec4) -> vec4 51 | { 52 | let cutoff = vec4(sRGB < vec4(0.04045)); 53 | let higher = pow((sRGB + vec4(0.055))/vec4(1.055), vec4(2.4)); 54 | let lower = sRGB/vec4(12.92); 55 | 56 | return mix(higher, lower, cutoff); 57 | } 58 | 59 | // The input of the fragment shader must correspond to the output of the vertex shader for all `location`s 60 | struct FragmentInput { 61 | // The color is interpolated between vertices by default 62 | @location(0) color: vec4, 63 | @location(1) uv: vec2, 64 | }; 65 | /// Entry point for the fragment shader 66 | @fragment 67 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 68 | return toLinear(in.color); 69 | // return vec4(1.0,1.0, 0.0, 1.0); 70 | } -------------------------------------------------------------------------------- /assets/shaders/mids.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | struct UiMat { 7 | color: vec4, 8 | clearcolor: vec4, 9 | t: f32, 10 | zoom: f32, 11 | size: vec2, 12 | hovered: f32, 13 | }; 14 | 15 | @group(1) @binding(0) 16 | var material: UiMat; 17 | 18 | struct Vertex { 19 | @location(0) position: vec3, 20 | @location(1) normal: vec3, 21 | @location(2) uv: vec2, 22 | #ifdef VERTEX_TANGENTS 23 | @location(3) tangent: vec4, 24 | #endif 25 | }; 26 | 27 | struct VertexOutput { 28 | @builtin(position) clip_position: vec4, 29 | @location(0) world_position: vec4, 30 | @location(1) world_normal: vec3, 31 | @location(2) uv: vec2, 32 | #ifdef VERTEX_TANGENTS 33 | @location(3) world_tangent: vec4, 34 | #endif 35 | }; 36 | 37 | 38 | 39 | @group(0) @binding(0) 40 | var view: View; 41 | 42 | 43 | @group(2) @binding(0) 44 | var mesh: Mesh2d; 45 | 46 | @vertex 47 | fn vertex(vertex: Vertex) -> VertexOutput { 48 | let world_position = mesh.model * vec4(vertex.position, 1.0); 49 | 50 | var out: VertexOutput; 51 | out.uv = vertex.uv; 52 | out.world_position = world_position; 53 | out.clip_position = view.view_proj * world_position; 54 | out.world_normal = mat3x3( 55 | mesh.inverse_transpose_model[0].xyz, 56 | mesh.inverse_transpose_model[1].xyz, 57 | mesh.inverse_transpose_model[2].xyz 58 | ) * vertex.normal; 59 | #ifdef VERTEX_TANGENTS 60 | out.world_tangent = vec4( 61 | mat3x3( 62 | mesh.model[0].xyz, 63 | mesh.model[1].xyz, 64 | mesh.model[2].xyz 65 | ) * vertex.tangent.xyz, 66 | vertex.tangent.w 67 | ); 68 | #endif 69 | return out; 70 | } 71 | 72 | struct FragmentInput { 73 | @builtin(front_facing) is_front: bool, 74 | @location(0) world_position: vec4, 75 | @location(1) world_normal: vec3, 76 | @location(2) uv: vec2, 77 | #ifdef VERTEX_TANGENTS 78 | @location(3) world_tangent: vec4, 79 | #endif 80 | }; 81 | 82 | 83 | fn sdBox(p: vec2, b: vec2) -> f32 { 84 | let d = abs(p) - b; 85 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 86 | } 87 | 88 | fn sdCircle(p: vec2, r: f32) -> f32 { 89 | return length(p) - r; 90 | } 91 | 92 | 93 | @fragment 94 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 95 | 96 | let aspect_ratio = material.size.y / material.size.x ; 97 | 98 | var uv_original: vec2 = (in.uv - vec2(0.5)); 99 | // uv_original.x = uv_original.x / 2.0 ; 100 | 101 | 102 | // let zoo = material.zoom / 0.08; 103 | let zoo = 1.0; 104 | let w = -0.03 * zoo; 105 | 106 | let offset = 0.0; 107 | 108 | let radius = 0.5; 109 | 110 | var d0 = sdCircle( uv_original - offset * vec2(0.5,0.), radius ); 111 | d0 = smoothstep(-w, w, d0); 112 | 113 | var d1 = sdCircle( uv_original - offset * vec2(0.5, 0.), radius * 0.5 ); 114 | d1 = smoothstep(-w, w, d1); 115 | 116 | let d = 1. - d0 * (1. - d1); 117 | 118 | 119 | var color_with_t = material.color; 120 | color_with_t.a = smoothstep(0.0, 0.1, material.t) * smoothstep(0.0, 0.1, 1.0 - material.t) ; 121 | 122 | var bg_color = material.clearcolor; 123 | bg_color.a = 0.0; 124 | 125 | 126 | let circle = mix( color_with_t ,bg_color , d ); 127 | // 128 | 129 | 130 | return circle; 131 | } 132 | 133 | 134 | -------------------------------------------------------------------------------- /assets/shaders/road_mesh.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_pbr::mesh_view_bindings 2 | 3 | @group(1) @binding(0) 4 | var sprite_texture: texture_2d; 5 | @group(1) @binding(1) 6 | var sprite_sampler: sampler; 7 | 8 | @fragment 9 | fn fragment( 10 | @builtin(position) position: vec4, 11 | #import bevy_sprite::mesh2d_vertex_output 12 | ) -> @location(0) vec4 { 13 | var color = textureSample(sprite_texture, sprite_sampler, uv); 14 | 15 | return color; 16 | } -------------------------------------------------------------------------------- /assets/shaders/selecting.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct UiMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | @group(1) @binding(0) 18 | var material: UiMat; 19 | 20 | 21 | struct Vertex { 22 | @location(0) position: vec3, 23 | @location(1) normal: vec3, 24 | @location(2) uv: vec2, 25 | #ifdef VERTEX_TANGENTS 26 | @location(3) tangent: vec4, 27 | #endif 28 | }; 29 | 30 | struct VertexOutput { 31 | @builtin(position) clip_position: vec4, 32 | @location(0) world_position: vec4, 33 | @location(1) world_normal: vec3, 34 | @location(2) uv: vec2, 35 | #ifdef VERTEX_TANGENTS 36 | @location(3) world_tangent: vec4, 37 | #endif 38 | }; 39 | 40 | @group(0) @binding(0) 41 | var view: View; 42 | 43 | 44 | @group(2) @binding(0) 45 | var mesh: Mesh2d; 46 | 47 | @vertex 48 | fn vertex(vertex: Vertex) -> VertexOutput { 49 | let world_position = mesh.model * vec4(vertex.position, 1.0); 50 | 51 | var out: VertexOutput; 52 | out.uv = vertex.uv; 53 | out.world_position = world_position; 54 | out.clip_position = view.view_proj * world_position; 55 | out.world_normal = mat3x3( 56 | mesh.inverse_transpose_model[0].xyz, 57 | mesh.inverse_transpose_model[1].xyz, 58 | mesh.inverse_transpose_model[2].xyz 59 | ) * vertex.normal; 60 | #ifdef VERTEX_TANGENTS 61 | out.world_tangent = vec4( 62 | mat3x3( 63 | mesh.model[0].xyz, 64 | mesh.model[1].xyz, 65 | mesh.model[2].xyz 66 | ) * vertex.tangent.xyz, 67 | vertex.tangent.w 68 | ); 69 | #endif 70 | return out; 71 | } 72 | 73 | struct FragmentInput { 74 | @builtin(front_facing) is_front: bool, 75 | @location(0) world_position: vec4, 76 | @location(1) world_normal: vec3, 77 | @location(2) uv: vec2, 78 | #ifdef VERTEX_TANGENTS 79 | @location(3) world_tangent: vec4, 80 | #endif 81 | }; 82 | 83 | fn sdBox(p: vec2, b: vec2) -> f32 { 84 | let d = abs(p) - b; 85 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 86 | } 87 | 88 | fn sdCircle(p: vec2, r: f32) -> f32 { 89 | return length(p) - r; 90 | } 91 | 92 | 93 | 94 | @fragment 95 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 96 | let aspect_ratio = material.size.y / material.size.x ; 97 | 98 | var uv_original: vec2 = in.uv - vec2(0.5); 99 | // uv_original.y = uv_original.y * aspect_ratio ; 100 | 101 | 102 | 103 | let cx = material.size.x / 42.0; 104 | let cy = material.size.y / 42.0; 105 | 106 | let p = 0.5 - 0.05 / 1.1; 107 | let bb_size = 0.1; 108 | 109 | let zoo = material.zoom / 0.08; 110 | 111 | let width = 0.00251 * 0.5; 112 | let sw = 0.0025 * zoo * 1.0; 113 | 114 | let w = sw / cx; 115 | let m = p + w; 116 | let l = p-w; 117 | let q = width / cx; 118 | 119 | let xdo = smoothstep( m+q, l+q, abs(uv_original.x ) ); 120 | let xdi = 1.0 - smoothstep( m-q, l-q, abs(uv_original.x ) ); 121 | 122 | let p = 0.5 - 0.05 / 1. - bb_size/cx; 123 | let w = sw / cx; 124 | let m = p + w; 125 | let l = p-w; 126 | let q = width / cx; 127 | 128 | // let xda= 1 - smoothstep( m+q, l+q, abs(uv.x ) ); 129 | 130 | 131 | let p = 0.5 - 0.05 / 1.1; 132 | let w = sw / cy; 133 | let m = p + w; 134 | let l = p-w; 135 | let q = width / cy; 136 | 137 | let ydi = 1.0 - smoothstep( m-q, l-q, abs(uv_original.y ) ); 138 | let ydo = smoothstep( m+q, l+q, abs(uv_original.y ) ); 139 | 140 | 141 | // p = 0.5 - 0.05/1. - bb_size/cy; 142 | // w = sw / cy; 143 | // m = p + w; 144 | // l = p-w; 145 | // q = width / cy; 146 | // // let yda = smoothstep( p, p-0.01, 0.5 - abs(uv.y ) ); 147 | // let yda= 1 - smoothstep( m+q, l+q, abs(uv.y ) ); 148 | // // yda = step(0.5 - abs(uv.y ), p ); 149 | 150 | 151 | let xd = xdi * xdo * ydo; // * xda * yda; 152 | let yd = ydi * ydo * xdo; // * xda * yda; 153 | 154 | 155 | let red = vec4(0.0, 0.0, 0.0, 0.00); 156 | let color2 = material.color; 157 | // color2.a = 0.3; 158 | 159 | let rect = mix( red ,color2 , min(yd + xd, 1.0)); 160 | // vec4 rect = mix( red ,color2 , xda); 161 | 162 | // o_Target = rect; 163 | 164 | 165 | return rect; 166 | // return vec4(1.0, 1.0, 1.0, 1.0); 167 | } 168 | 169 | -------------------------------------------------------------------------------- /assets/shaders/ui.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct UiMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | @group(1) @binding(0) 18 | var material: UiMat; 19 | 20 | 21 | struct Vertex { 22 | @location(0) position: vec3, 23 | @location(1) normal: vec3, 24 | @location(2) uv: vec2, 25 | #ifdef VERTEX_TANGENTS 26 | @location(3) tangent: vec4, 27 | #endif 28 | }; 29 | 30 | struct VertexOutput { 31 | @builtin(position) clip_position: vec4, 32 | @location(0) world_position: vec4, 33 | @location(1) world_normal: vec3, 34 | @location(2) uv: vec2, 35 | #ifdef VERTEX_TANGENTS 36 | @location(3) world_tangent: vec4, 37 | #endif 38 | }; 39 | 40 | 41 | @group(0) @binding(0) 42 | var view: View; 43 | 44 | 45 | @group(2) @binding(0) 46 | var mesh: Mesh2d; 47 | 48 | @vertex 49 | fn vertex(vertex: Vertex) -> VertexOutput { 50 | let world_position = mesh.model * vec4(vertex.position, 1.0); 51 | 52 | var out: VertexOutput; 53 | out.uv = vertex.uv; 54 | out.world_position = world_position; 55 | out.clip_position = view.view_proj * world_position; 56 | out.world_normal = mat3x3( 57 | mesh.inverse_transpose_model[0].xyz, 58 | mesh.inverse_transpose_model[1].xyz, 59 | mesh.inverse_transpose_model[2].xyz 60 | ) * vertex.normal; 61 | #ifdef VERTEX_TANGENTS 62 | out.world_tangent = vec4( 63 | mat3x3( 64 | mesh.model[0].xyz, 65 | mesh.model[1].xyz, 66 | mesh.model[2].xyz 67 | ) * vertex.tangent.xyz, 68 | vertex.tangent.w 69 | ); 70 | #endif 71 | return out; 72 | } 73 | 74 | struct FragmentInput { 75 | @builtin(front_facing) is_front: bool, 76 | @location(0) world_position: vec4, 77 | @location(1) world_normal: vec3, 78 | @location(2) uv: vec2, 79 | #ifdef VERTEX_TANGENTS 80 | @location(3) world_tangent: vec4, 81 | #endif 82 | }; 83 | 84 | fn sdBox(p: vec2, b: vec2) -> f32 { 85 | let d = abs(p) - b; 86 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 87 | } 88 | 89 | fn sdCircle(p: vec2, r: f32) -> f32 { 90 | return length(p) - r; 91 | } 92 | 93 | 94 | 95 | @fragment 96 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 97 | 98 | let aspect_ratio = material.size.y / material.size.x ; 99 | 100 | var uv_original: vec2 = in.uv - vec2(0.5); 101 | uv_original.y = uv_original.y * aspect_ratio ; 102 | 103 | 104 | let margin = 0.15; 105 | var d = sdBox( uv_original, vec2(0.5 - margin , 0.5*aspect_ratio - margin ) ); 106 | let offset = 0.1; 107 | d = smoothstep(0.01+offset, -0.01+offset, d); 108 | 109 | var bg_color = (material.clearcolor); 110 | bg_color.a = 0.0; 111 | 112 | var color_mod = (material.color); 113 | color_mod.a = 0.3; 114 | 115 | var rect = mix( color_mod , bg_color , 1.0 - d ); 116 | 117 | 118 | return rect; 119 | } 120 | -------------------------------------------------------------------------------- /assets/sounds/group.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/sounds/group.ogg -------------------------------------------------------------------------------- /assets/sounds/latch.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/sounds/latch.ogg -------------------------------------------------------------------------------- /assets/sounds/unlatch.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/sounds/unlatch.ogg -------------------------------------------------------------------------------- /assets/textures/bin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/bin.png -------------------------------------------------------------------------------- /assets/textures/car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/car.png -------------------------------------------------------------------------------- /assets/textures/controls_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/controls_off.png -------------------------------------------------------------------------------- /assets/textures/controls_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/controls_on.png -------------------------------------------------------------------------------- /assets/textures/copter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/copter.png -------------------------------------------------------------------------------- /assets/textures/heli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/heli.png -------------------------------------------------------------------------------- /assets/textures/heli_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/heli_button.png -------------------------------------------------------------------------------- /assets/textures/hide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/hide.png -------------------------------------------------------------------------------- /assets/textures/load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/load.png -------------------------------------------------------------------------------- /assets/textures/lut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/lut.png -------------------------------------------------------------------------------- /assets/textures/mesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/mesh.png -------------------------------------------------------------------------------- /assets/textures/redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/redo.png -------------------------------------------------------------------------------- /assets/textures/road_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/road_icon.png -------------------------------------------------------------------------------- /assets/textures/road_texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/road_texture.png -------------------------------------------------------------------------------- /assets/textures/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/save.png -------------------------------------------------------------------------------- /assets/textures/scale_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/scale_down.png -------------------------------------------------------------------------------- /assets/textures/scale_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/scale_up.png -------------------------------------------------------------------------------- /assets/textures/selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/selection.png -------------------------------------------------------------------------------- /assets/textures/show_anchors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/show_anchors.png -------------------------------------------------------------------------------- /assets/textures/single_lane_road.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/single_lane_road.png -------------------------------------------------------------------------------- /assets/textures/sound_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/sound_off.png -------------------------------------------------------------------------------- /assets/textures/sound_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/sound_on.png -------------------------------------------------------------------------------- /assets/textures/undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/assets/textures/undo.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bevy_pen_tool_plugin" 3 | version = "0.3.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | # bevy = { git = "https://github.com/bevyengine/bevy", rev = "6a1ba9c" } 10 | bevy = "0.8" 11 | bevy_pen_tool_model = {path = "crates/bevy_pen_tool_model"} 12 | 13 | flo_curves = "0.5" 14 | serde_json = "1.0.59" 15 | itertools = "0.10.1" 16 | serde = { version = "1", features = ["derive"] } 17 | rand = "0.8" 18 | plotlib = "0.5.1" 19 | lyon = "0.17.5" 20 | obj-exporter = "0.2.0" 21 | rfd = "0.5.1" 22 | bevy-inspector-egui = "0.12" 23 | once_cell = "1.13.0" 24 | bevy_egui = "0.15" 25 | bevy_obj = "0.8" 26 | 27 | 28 | [[example]] 29 | name = "blank" 30 | path = "examples/blank.rs" 31 | 32 | [[example]] 33 | name = "breakout" 34 | path = "examples/breakout.rs" 35 | 36 | [[example]] 37 | name = "move_test" 38 | path = "examples/move_test.rs" 39 | 40 | [[example]] 41 | name = "latch_test" 42 | path = "examples/latch_test.rs" 43 | 44 | [[example]] 45 | name = "unlatch_test" 46 | path = "examples/unlatch_test.rs" 47 | 48 | [[example]] 49 | name = "delete_test" 50 | path = "examples/delete_test.rs" 51 | 52 | [[example]] 53 | name = "complex_test1" 54 | path = "examples/complex_test1.rs" 55 | 56 | [[example]] 57 | name = "latch_then_delete_test" 58 | path = "examples/latch_then_delete_test.rs" 59 | 60 | [[example]] 61 | name = "undo_latch_test" 62 | path = "examples/undo_latch_test.rs" 63 | 64 | [[example]] 65 | name = "undo_move_test" 66 | path = "examples/undo_move_test.rs" 67 | 68 | [[example]] 69 | name = "undo_unlatch_test" 70 | path = "examples/undo_unlatch_test.rs" 71 | 72 | [[example]] 73 | name = "redo_latch_test" 74 | path = "examples/redo_latch_test.rs" 75 | 76 | [[example]] 77 | name = "redo_delete_test" 78 | path = "examples/redo_delete_test.rs" 79 | 80 | [[example]] 81 | name = "redo_move_test" 82 | path = "examples/redo_move_test.rs" 83 | 84 | [[example]] 85 | name = "redo_unlatch_test" 86 | path = "examples/redo_unlatch_test.rs" 87 | 88 | [[example]] 89 | name = "undo_delete_latched_test" 90 | path = "examples/undo_delete_latched_test.rs" 91 | 92 | [[example]] 93 | name = "redo_delete_latched_test" 94 | path = "examples/redo_delete_latched_test.rs" 95 | 96 | 97 | [[example]] 98 | name = "undo_latch_then_move_test" 99 | path = "examples/undo_latch_then_move_test.rs" 100 | 101 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/lut/my_group_lut.txt: -------------------------------------------------------------------------------- 1 | { 2 | "path_length": 428.1096, 3 | "lut": [ 4 | [ 5 | 75.65233, 6 | 39.556183 7 | ], 8 | [ 9 | 72.01289, 10 | 41.803123 11 | ], 12 | [ 13 | 68.362915, 14 | 44.096 15 | ], 16 | [ 17 | 64.69503, 18 | 46.38355 19 | ], 20 | [ 21 | 60.96675, 22 | 48.55714 23 | ], 24 | [ 25 | 57.097446, 26 | 50.436615 27 | ], 28 | [ 29 | 53.02274, 30 | 51.872326 31 | ], 32 | [ 33 | 48.81086, 34 | 52.877003 35 | ], 36 | [ 37 | 44.526196, 38 | 53.59042 39 | ], 40 | [ 41 | 40.21482, 42 | 54.131462 43 | ], 44 | [ 45 | 35.9449, 46 | 54.568584 47 | ], 48 | [ 49 | 31.578703, 50 | 54.956856 51 | ], 52 | [ 53 | 27.303383, 54 | 55.303116 55 | ], 56 | [ 57 | 23.013409, 58 | 55.63055 59 | ], 60 | [ 61 | 18.65934, 62 | 55.940235 63 | ], 64 | [ 65 | 14.319022, 66 | 56.206467 67 | ], 68 | [ 69 | 10.015079, 70 | 56.400143 71 | ], 72 | [ 73 | 5.7276764, 74 | 56.483486 75 | ], 76 | [ 77 | 1.4044715, 78 | 56.399513 79 | ], 80 | [ 81 | -2.8902009, 82 | 56.069515 83 | ], 84 | [ 85 | -7.175977, 86 | 55.388382 87 | ], 88 | [ 89 | -11.349323, 90 | 54.25954 91 | ], 92 | [ 93 | -15.346702, 94 | 52.619118 95 | ], 96 | [ 97 | -19.087698, 98 | 50.49095 99 | ], 100 | [ 101 | -22.580011, 102 | 47.940342 103 | ], 104 | [ 105 | -25.837492, 106 | 45.07297 107 | ], 108 | [ 109 | -28.87856, 110 | 42.004547 111 | ], 112 | [ 113 | -31.774286, 114 | 38.778038 115 | ], 116 | [ 117 | -34.534866, 118 | 35.45809 119 | ], 120 | [ 121 | -37.023205, 122 | 31.963879 123 | ], 124 | [ 125 | -39.030937, 126 | 28.109638 127 | ], 128 | [ 129 | -40.03539, 130 | 23.95207 131 | ], 132 | [ 133 | -39.45558, 134 | 19.690819 135 | ], 136 | [ 137 | -37.4672, 138 | 15.864918 139 | ], 140 | [ 141 | -34.84456, 142 | 12.398328 143 | ], 144 | [ 145 | -32.14081, 146 | 9.034119 147 | ], 148 | [ 149 | -29.641071, 150 | 5.535929 151 | ], 152 | [ 153 | -27.522795, 154 | 1.7246153 155 | ], 156 | [ 157 | -26.004349, 158 | -2.283932 159 | ], 160 | [ 161 | -25.100025, 162 | -6.540269 163 | ], 164 | [ 165 | -24.785923, 166 | -10.851115 167 | ], 168 | [ 169 | -24.939764, 170 | -15.152214 171 | ], 172 | [ 173 | -25.491756, 174 | -19.419937 175 | ], 176 | [ 177 | -26.353035, 178 | -23.687748 179 | ], 180 | [ 181 | -27.371073, 182 | -27.87349 183 | ], 184 | [ 185 | -28.377975, 186 | -32.06019 187 | ], 188 | [ 189 | -29.119171, 190 | -36.320457 191 | ], 192 | [ 193 | -29.175243, 194 | -40.62201 195 | ], 196 | [ 197 | -28.026714, 198 | -44.778515 199 | ], 200 | [ 201 | -25.572914, 202 | -48.319138 203 | ], 204 | [ 205 | -22.258396, 206 | -51.12602 207 | ], 208 | [ 209 | -18.566418, 210 | -53.325382 211 | ], 212 | [ 213 | -14.570167, 214 | -55.170868 215 | ], 216 | [ 217 | -10.564711, 218 | -56.65694 219 | ], 220 | [ 221 | -6.401764, 222 | -57.888123 223 | ], 224 | [ 225 | -2.1682618, 226 | -58.855682 227 | ], 228 | [ 229 | 2.1173413, 230 | -59.58005 231 | ], 232 | [ 233 | 6.3365107, 234 | -60.073086 235 | ], 236 | [ 237 | 10.701572, 238 | -60.380867 239 | ], 240 | [ 241 | 15.032694, 242 | -60.507065 243 | ], 244 | [ 245 | 19.360605, 246 | -60.476456 247 | ], 248 | [ 249 | 23.649405, 250 | -60.31088 251 | ], 252 | [ 253 | 27.991518, 254 | -60.024494 255 | ], 256 | [ 257 | 32.291748, 258 | -59.640804 259 | ], 260 | [ 261 | 36.535103, 262 | -59.18198 263 | ], 264 | [ 265 | 40.86112, 266 | -58.651028 267 | ], 268 | [ 269 | 45.155296, 270 | -58.081936 271 | ], 272 | [ 273 | 49.408665, 274 | -57.5016 275 | ], 276 | [ 277 | 53.696774, 278 | -56.931488 279 | ], 280 | [ 281 | 57.97665, 282 | -56.421738 283 | ], 284 | [ 285 | 62.24278, 286 | -56.040802 287 | ], 288 | [ 289 | 66.59136, 290 | -55.633682 291 | ], 292 | [ 293 | 70.80036, 294 | -54.682873 295 | ], 296 | [ 297 | 74.86487, 298 | -53.177204 299 | ], 300 | [ 301 | 78.67168, 302 | -51.180874 303 | ], 304 | [ 305 | 82.21802, 306 | -48.731552 307 | ], 308 | [ 309 | 85.49883, 310 | -45.86038 311 | ], 312 | [ 313 | 88.44644, 314 | -42.666767 315 | ], 316 | [ 317 | 91.03071, 318 | -39.25362 319 | ], 320 | [ 321 | 93.326256, 322 | -35.581696 323 | ], 324 | [ 325 | 95.30631, 326 | -31.742237 327 | ], 328 | [ 329 | 97.00451, 330 | -27.72329 331 | ], 332 | [ 333 | 98.38413, 334 | -23.692299 335 | ], 336 | [ 337 | 99.52025, 338 | -19.507515 339 | ], 340 | [ 341 | 100.40977, 342 | -15.211164 343 | ], 344 | [ 345 | 101.04274, 346 | -10.983979 347 | ], 348 | [ 349 | 101.46067, 350 | -6.6748033 351 | ], 352 | [ 353 | 101.61834, 354 | -2.3440204 355 | ], 356 | [ 357 | 101.46939, 358 | 1.995478 359 | ], 360 | [ 361 | 100.97136, 362 | 6.270068 363 | ], 364 | [ 365 | 100.074196, 366 | 10.504586 367 | ], 368 | [ 369 | 98.761986, 370 | 14.586327 371 | ], 372 | [ 373 | 97.007965, 374 | 18.522402 375 | ], 376 | [ 377 | 94.82377, 378 | 22.259634 379 | ], 380 | [ 381 | 92.25176, 382 | 25.754744 383 | ], 384 | [ 385 | 89.347855, 386 | 28.99271 387 | ], 388 | [ 389 | 86.21853, 390 | 31.937885 391 | ], 392 | [ 393 | 82.874695, 394 | 34.657955 395 | ], 396 | [ 397 | 79.3612, 398 | 37.176285 399 | ], 400 | [ 401 | 75.688644, 402 | 39.534027 403 | ] 404 | ] 405 | } -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/meshes/my_mesh.obj: -------------------------------------------------------------------------------- 1 | o My_mesh 2 | v 15.032694 -60.507065 0.000000 3 | v 19.360605 -60.476456 0.000000 4 | v 10.701572 -60.380867 0.000000 5 | v 23.649405 -60.310879 0.000000 6 | v 6.336511 -60.073086 0.000000 7 | v 27.991518 -60.024494 0.000000 8 | v 32.291748 -59.640804 0.000000 9 | v 2.117341 -59.580051 0.000000 10 | v 36.535103 -59.181980 0.000000 11 | v -2.168262 -58.855682 0.000000 12 | v 40.861118 -58.651028 0.000000 13 | v 45.155296 -58.081936 0.000000 14 | v -6.401764 -57.888123 0.000000 15 | v 49.408665 -57.501598 0.000000 16 | v 53.696774 -56.931488 0.000000 17 | v -10.564711 -56.656940 0.000000 18 | v 57.976650 -56.421738 0.000000 19 | v 62.242779 -56.040802 0.000000 20 | v 66.591362 -55.633682 0.000000 21 | v -14.570167 -55.170868 0.000000 22 | v 70.800362 -54.682873 0.000000 23 | v -18.566418 -53.325382 0.000000 24 | v 74.864868 -53.177204 0.000000 25 | v 78.671677 -51.180874 0.000000 26 | v -22.258396 -51.126019 0.000000 27 | v 82.218018 -48.731552 0.000000 28 | v -25.572914 -48.319138 0.000000 29 | v 85.498833 -45.860378 0.000000 30 | v -28.026714 -44.778515 0.000000 31 | v 88.446442 -42.666767 0.000000 32 | v -29.175243 -40.622009 0.000000 33 | v 91.030708 -39.253620 0.000000 34 | v -29.119171 -36.320457 0.000000 35 | v 93.326256 -35.581696 0.000000 36 | v -28.377975 -32.060188 0.000000 37 | v 95.306313 -31.742237 0.000000 38 | v -27.371073 -27.873489 0.000000 39 | v 97.004509 -27.723289 0.000000 40 | v 98.384132 -23.692299 0.000000 41 | v -26.353035 -23.687748 0.000000 42 | v 99.520248 -19.507515 0.000000 43 | v -25.491756 -19.419937 0.000000 44 | v 100.409767 -15.211164 0.000000 45 | v -24.939764 -15.152214 0.000000 46 | v 101.042740 -10.983979 0.000000 47 | v -24.785923 -10.851115 0.000000 48 | v 101.460670 -6.674803 0.000000 49 | v -25.100025 -6.540269 0.000000 50 | v 101.618340 -2.344020 0.000000 51 | v -26.004349 -2.283932 0.000000 52 | v -27.522795 1.724615 0.000000 53 | v 101.469391 1.995478 0.000000 54 | v -29.641071 5.535929 0.000000 55 | v 100.971359 6.270068 0.000000 56 | v -32.140808 9.034119 0.000000 57 | v 100.074196 10.504586 0.000000 58 | v -34.844559 12.398328 0.000000 59 | v 98.761986 14.586327 0.000000 60 | v -37.467201 15.864918 0.000000 61 | v 97.007965 18.522402 0.000000 62 | v -39.455582 19.690819 0.000000 63 | v 94.823769 22.259634 0.000000 64 | v -40.035389 23.952070 0.000000 65 | v 92.251762 25.754744 0.000000 66 | v -39.030937 28.109638 0.000000 67 | v 89.347855 28.992710 0.000000 68 | v 86.218529 31.937885 0.000000 69 | v -37.023205 31.963879 0.000000 70 | v 82.874695 34.657955 0.000000 71 | v -34.534866 35.458092 0.000000 72 | v 79.361198 37.176285 0.000000 73 | v -31.774286 38.778038 0.000000 74 | v 75.688644 39.534027 0.000000 75 | v 75.652328 39.556183 0.000000 76 | v 72.012894 41.803123 0.000000 77 | v -28.878559 42.004547 0.000000 78 | v 68.362915 44.096001 0.000000 79 | v -25.837492 45.072971 0.000000 80 | v 64.695030 46.383549 0.000000 81 | v -22.580011 47.940342 0.000000 82 | v 60.966751 48.557140 0.000000 83 | v 57.097446 50.436615 0.000000 84 | v -19.087698 50.490952 0.000000 85 | v 53.022739 51.872326 0.000000 86 | v -15.346702 52.619118 0.000000 87 | v 48.810860 52.877003 0.000000 88 | v 44.526196 53.590420 0.000000 89 | v 40.214821 54.131462 0.000000 90 | v -11.349323 54.259541 0.000000 91 | v 35.944901 54.568584 0.000000 92 | v 31.578703 54.956856 0.000000 93 | v 27.303383 55.303116 0.000000 94 | v -7.175977 55.388382 0.000000 95 | v 23.013409 55.630550 0.000000 96 | v 18.659340 55.940235 0.000000 97 | v -2.890201 56.069515 0.000000 98 | v 14.319022 56.206467 0.000000 99 | v 1.404472 56.399513 0.000000 100 | v 10.015079 56.400143 0.000000 101 | v 5.727676 56.483486 0.000000 102 | vn 0.000000 0.000000 1.000000 103 | f 100/100/1 98/98/1 99/99/1 104 | f 99/99/1 98/98/1 75/75/1 105 | f 98/98/1 72/72/1 75/75/1 106 | f 88/88/1 94/94/1 75/75/1 107 | f 88/88/1 75/75/1 82/82/1 108 | f 94/94/1 97/97/1 75/75/1 109 | f 94/94/1 88/88/1 91/91/1 110 | f 88/88/1 82/82/1 86/86/1 111 | f 82/82/1 75/75/1 79/79/1 112 | f 97/97/1 99/99/1 75/75/1 113 | f 97/97/1 94/94/1 95/95/1 114 | f 94/94/1 91/91/1 92/92/1 115 | f 91/91/1 88/88/1 90/90/1 116 | f 88/88/1 86/86/1 87/87/1 117 | f 86/86/1 82/82/1 84/84/1 118 | f 82/82/1 79/79/1 81/81/1 119 | f 79/79/1 75/75/1 77/77/1 120 | f 96/96/1 83/83/1 72/72/1 121 | f 96/96/1 89/89/1 83/83/1 122 | f 83/83/1 78/78/1 72/72/1 123 | f 98/98/1 96/96/1 72/72/1 124 | f 96/96/1 93/93/1 89/89/1 125 | f 89/89/1 85/85/1 83/83/1 126 | f 83/83/1 80/80/1 78/78/1 127 | f 78/78/1 76/76/1 72/72/1 128 | f 75/75/1 72/72/1 74/74/1 129 | f 74/74/1 72/72/1 49/49/1 130 | f 66/66/1 73/73/1 49/49/1 131 | f 66/66/1 49/49/1 58/58/1 132 | f 73/73/1 66/66/1 69/69/1 133 | f 66/66/1 58/58/1 62/62/1 134 | f 58/58/1 49/49/1 54/54/1 135 | f 73/73/1 74/74/1 49/49/1 136 | f 73/73/1 69/69/1 71/71/1 137 | f 69/69/1 66/66/1 67/67/1 138 | f 66/66/1 62/62/1 64/64/1 139 | f 62/62/1 58/58/1 60/60/1 140 | f 58/58/1 54/54/1 56/56/1 141 | f 54/54/1 49/49/1 52/52/1 142 | f 72/72/1 55/55/1 49/49/1 143 | f 72/72/1 63/63/1 55/55/1 144 | f 72/72/1 68/68/1 63/63/1 145 | f 63/63/1 59/59/1 55/55/1 146 | f 72/72/1 70/70/1 68/68/1 147 | f 68/68/1 65/65/1 63/63/1 148 | f 63/63/1 61/61/1 59/59/1 149 | f 59/59/1 57/57/1 55/55/1 150 | f 55/55/1 53/53/1 49/49/1 151 | f 53/53/1 51/51/1 49/49/1 152 | f 51/51/1 50/50/1 49/49/1 153 | f 50/50/1 48/48/1 49/49/1 154 | f 49/49/1 48/48/1 17/17/1 155 | f 45/45/1 17/17/1 30/30/1 156 | f 45/45/1 30/30/1 38/38/1 157 | f 30/30/1 17/17/1 23/23/1 158 | f 45/45/1 49/49/1 17/17/1 159 | f 45/45/1 38/38/1 41/41/1 160 | f 38/38/1 30/30/1 34/34/1 161 | f 30/30/1 23/23/1 26/26/1 162 | f 23/23/1 17/17/1 19/19/1 163 | f 49/49/1 45/45/1 47/47/1 164 | f 45/45/1 41/41/1 43/43/1 165 | f 41/41/1 38/38/1 39/39/1 166 | f 38/38/1 34/34/1 36/36/1 167 | f 34/34/1 30/30/1 32/32/1 168 | f 30/30/1 26/26/1 28/28/1 169 | f 26/26/1 23/23/1 24/24/1 170 | f 23/23/1 19/19/1 21/21/1 171 | f 19/19/1 17/17/1 18/18/1 172 | f 48/48/1 46/46/1 17/17/1 173 | f 46/46/1 44/44/1 17/17/1 174 | f 44/44/1 42/42/1 17/17/1 175 | f 42/42/1 40/40/1 17/17/1 176 | f 40/40/1 16/16/1 17/17/1 177 | f 35/35/1 27/27/1 16/16/1 178 | f 40/40/1 35/35/1 16/16/1 179 | f 35/35/1 31/31/1 27/27/1 180 | f 27/27/1 22/22/1 16/16/1 181 | f 40/40/1 37/37/1 35/35/1 182 | f 35/35/1 33/33/1 31/31/1 183 | f 31/31/1 29/29/1 27/27/1 184 | f 27/27/1 25/25/1 22/22/1 185 | f 22/22/1 20/20/1 16/16/1 186 | f 17/17/1 16/16/1 15/15/1 187 | f 16/16/1 13/13/1 15/15/1 188 | f 15/15/1 13/13/1 14/14/1 189 | f 14/14/1 13/13/1 2/2/1 190 | f 9/9/1 12/12/1 2/2/1 191 | f 9/9/1 2/2/1 6/6/1 192 | f 12/12/1 14/14/1 2/2/1 193 | f 12/12/1 9/9/1 11/11/1 194 | f 9/9/1 6/6/1 7/7/1 195 | f 6/6/1 2/2/1 4/4/1 196 | f 13/13/1 3/3/1 2/2/1 197 | f 13/13/1 8/8/1 3/3/1 198 | f 13/13/1 10/10/1 8/8/1 199 | f 8/8/1 5/5/1 3/3/1 200 | f 3/3/1 1/1/1 2/2/1 201 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/meshes/my_mesh0.meta: -------------------------------------------------------------------------------- 1 | { 2 | "center_of_mass": [ 3 | 117.62484, 4 | -27.992126 5 | ], 6 | "position": [ 7 | 117.62484, 8 | -27.992126 9 | ], 10 | "bounding_box": [ 11 | [ 12 | -133.32657, 13 | -103.21933 14 | ], 15 | [ 16 | 86.17742, 17 | 157.52303 18 | ] 19 | ], 20 | "color": [ 21 | 0.93333334, 22 | 0.8901961, 23 | 0.90588236, 24 | 1.0 25 | ] 26 | } -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/meshes/my_mesh0.obj: -------------------------------------------------------------------------------- 1 | # Blender v3.0.0 OBJ File: '' 2 | # www.blender.org 3 | o Cube 4 | v -100.0 100.0 100.0 5 | v -100.0 -100.0 100.0 6 | v -100.0 100.0 -100.0 7 | v -100.0 -100.0 -100.0 8 | v 100.0 100.0 100.0 9 | v 100.0 -100.0 100.0 10 | v 100.0 100.0 -100.0 11 | v 100.0 -100.0 -100.0 12 | vt 0.875000 0.500000 13 | vt 0.625000 0.750000 14 | vt 0.625000 0.500000 15 | vt 0.375000 1.0 16 | vt 0.375000 0.750000 17 | vt 0.625000 0.000000 18 | vt 0.375000 0.250000 19 | vt 0.375000 0.000000 20 | vt 0.375000 0.500000 21 | vt 0.125000 0.750000 22 | vt 0.125000 0.500000 23 | vt 0.625000 0.250000 24 | vt 0.875000 0.750000 25 | vt 0.625000 1.0 26 | vn 0.0000 1.0000 0.0000 27 | vn 0.0000 0.0000 -1.0000 28 | vn 1.0000 0.0000 0.0000 29 | vn 0.0000 -1.0000 0.0000 30 | vn -1.0000 0.0000 0.0000 31 | vn 0.0000 0.0000 1.0000 32 | f 5/1/1 3/2/1 1/3/1 33 | f 3/2/2 8/4/2 4/5/2 34 | f 7/6/3 6/7/3 8/8/3 35 | f 2/9/4 8/10/4 6/11/4 36 | f 1/3/5 4/5/5 2/9/5 37 | f 5/12/6 2/9/6 6/7/6 38 | f 5/1/1 7/13/1 3/2/1 39 | f 3/2/2 7/14/2 8/4/2 40 | f 7/6/3 5/12/3 6/7/3 41 | f 2/9/4 4/5/4 8/10/4 42 | f 1/3/5 3/2/5 4/5/5 43 | f 5/12/6 1/3/6 2/9/6 -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/meshes/my_mesh1.meta: -------------------------------------------------------------------------------- 1 | { 2 | "center_of_mass": [ 3 | 178.12445, 4 | -8.62852 5 | ], 6 | "position": [ 7 | 178.12445, 8 | -8.62852 9 | ], 10 | "bounding_box": [ 11 | [ 12 | -182.96767, 13 | -77.27092 14 | ], 15 | [ 16 | 135.1539, 17 | 144.44583 18 | ] 19 | ], 20 | "color": [ 21 | 0.93333334, 22 | 0.8901961, 23 | 0.90588236, 24 | 1.0 25 | ] 26 | } -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/meshes/my_mesh2.meta: -------------------------------------------------------------------------------- 1 | { 2 | "center_of_mass": [ 3 | 61.646286, 4 | -16.06076 5 | ], 6 | "position": [ 7 | 61.646286, 8 | -16.06076 9 | ], 10 | "bounding_box": [ 11 | [ 12 | -172.79593, 13 | -167.74068 14 | ], 15 | [ 16 | 306.7033, 17 | 245.52939 18 | ] 19 | ], 20 | "color": [ 21 | 0.93333334, 22 | 0.8901961, 23 | 0.90588236, 24 | 1.0 25 | ] 26 | } -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/meshes/my_mesh2.obj: -------------------------------------------------------------------------------- 1 | o My_mesh 2 | v 153.754456 -167.740677 0.000000 3 | v 168.719299 -167.622849 0.000000 4 | v 138.868240 -166.679718 0.000000 5 | v 124.021057 -165.018372 0.000000 6 | v 109.219604 -162.991379 0.000000 7 | v 185.340179 -161.591492 0.000000 8 | v 94.459610 -160.722031 0.000000 9 | v 79.721390 -158.283005 0.000000 10 | v 65.006554 -155.725830 0.000000 11 | v 198.509842 -154.268845 0.000000 12 | v 50.305695 -153.086746 0.000000 13 | v 35.613060 -150.394730 0.000000 14 | v 212.090408 -147.996506 0.000000 15 | v 20.927353 -147.675049 0.000000 16 | v 6.241966 -144.949799 0.000000 17 | v -8.446220 -142.241165 0.000000 18 | v 225.629166 -141.702515 0.000000 19 | v -23.142792 -139.571976 0.000000 20 | v -37.849049 -136.968872 0.000000 21 | v 238.999008 -135.036041 0.000000 22 | v -52.574642 -134.462448 0.000000 23 | v -67.322975 -132.093826 0.000000 24 | v -157.182617 -130.308289 0.000000 25 | v -82.095016 -129.920624 0.000000 26 | v -96.918549 -128.026581 0.000000 27 | v 252.056442 -127.777222 0.000000 28 | v -141.631348 -126.627167 0.000000 29 | v -111.782043 -126.561752 0.000000 30 | v -126.697746 -125.821899 0.000000 31 | v 264.630432 -119.718948 0.000000 32 | v -159.186432 -115.565109 0.000000 33 | v 276.481323 -110.633278 0.000000 34 | v -159.102722 -100.625511 0.000000 35 | v 287.233887 -100.279480 0.000000 36 | v 296.323425 -88.452080 0.000000 37 | v -158.436539 -85.701065 0.000000 38 | v 302.999268 -75.122887 0.000000 39 | v -157.475525 -70.793182 0.000000 40 | v 306.541199 -60.654915 0.000000 41 | v -156.337616 -55.898293 0.000000 42 | v 306.703308 -45.753555 0.000000 43 | v -155.086212 -41.013119 0.000000 44 | v 303.859436 -31.101856 0.000000 45 | v -153.761475 -26.136948 0.000000 46 | v 298.690735 -17.104057 0.000000 47 | v -152.391602 -11.264229 0.000000 48 | v 291.826782 -3.856258 0.000000 49 | v -150.999222 3.606922 0.000000 50 | v 283.725464 8.689524 0.000000 51 | v -149.604187 18.479309 0.000000 52 | v 274.709229 20.607109 0.000000 53 | v 265.013184 31.961323 0.000000 54 | v -148.226257 33.351669 0.000000 55 | v 254.784225 42.836380 0.000000 56 | v -146.886475 48.226826 0.000000 57 | v 244.125687 53.301308 0.000000 58 | v -145.610107 63.107964 0.000000 59 | v 233.118179 63.406986 0.000000 60 | v 221.834274 73.185715 0.000000 61 | v -144.430756 77.999306 0.000000 62 | v 210.310715 82.682098 0.000000 63 | v 198.579666 91.929092 0.000000 64 | v -143.398697 92.902168 0.000000 65 | v 186.669907 100.951569 0.000000 66 | v -142.598938 107.819778 0.000000 67 | v 174.615433 109.763000 0.000000 68 | v 162.425369 118.389198 0.000000 69 | v -142.206375 122.753731 0.000000 70 | v 150.113434 126.847267 0.000000 71 | v 137.692841 135.150757 0.000000 72 | v -142.746887 137.678574 0.000000 73 | v 125.184601 143.305222 0.000000 74 | v -153.041443 144.543716 0.000000 75 | v -149.415955 146.383926 0.000000 76 | v -164.061951 153.660233 0.000000 77 | v 108.869080 153.664246 0.000000 78 | v 96.166290 161.524368 0.000000 79 | v -169.814163 167.439026 0.000000 80 | v 83.381348 169.243240 0.000000 81 | v 70.506409 176.808716 0.000000 82 | v -172.674744 182.095535 0.000000 83 | v 57.528320 184.208893 0.000000 84 | v 44.448898 191.420059 0.000000 85 | v -172.795929 197.010391 0.000000 86 | v 31.260910 198.419968 0.000000 87 | v 17.941811 205.189178 0.000000 88 | v -169.721191 211.592819 0.000000 89 | v 4.492920 211.689362 0.000000 90 | v -9.094692 217.879745 0.000000 91 | v -22.844662 223.715164 0.000000 92 | v -162.831909 224.779663 0.000000 93 | v -36.768887 229.130066 0.000000 94 | v -50.872200 234.036591 0.000000 95 | v -152.126740 235.102463 0.000000 96 | v -65.173683 238.323837 0.000000 97 | v -138.784821 241.682068 0.000000 98 | v -79.698479 241.838531 0.000000 99 | v -94.419075 244.350067 0.000000 100 | v -124.215538 244.880585 0.000000 101 | v -109.288300 245.529388 0.000000 102 | vt 0.000000 0.000000 103 | vn 0.000000 0.000000 1.000000 104 | f 100 99 98 105 | f 99 74 98 106 | f 98 74 72 107 | f 98 72 86 108 | f 98 86 92 109 | f 86 72 80 110 | f 98 92 95 111 | f 92 86 89 112 | f 86 80 83 113 | f 80 72 77 114 | f 98 95 97 115 | f 95 92 93 116 | f 92 89 90 117 | f 89 86 88 118 | f 86 83 85 119 | f 83 80 82 120 | f 80 77 79 121 | f 77 72 76 122 | f 96 84 74 123 | f 96 91 84 124 | f 84 78 74 125 | f 99 96 74 126 | f 96 94 91 127 | f 91 87 84 128 | f 84 81 78 129 | f 78 75 74 130 | f 74 71 72 131 | f 72 71 30 132 | f 59 72 30 133 | f 59 30 45 134 | f 72 59 66 135 | f 59 45 52 136 | f 45 30 37 137 | f 72 66 69 138 | f 66 59 62 139 | f 59 52 56 140 | f 52 45 49 141 | f 45 37 41 142 | f 37 30 34 143 | f 72 69 70 144 | f 69 66 67 145 | f 66 62 64 146 | f 62 59 61 147 | f 59 56 58 148 | f 56 52 54 149 | f 52 49 51 150 | f 49 45 47 151 | f 45 41 43 152 | f 41 37 39 153 | f 37 34 35 154 | f 34 30 32 155 | f 71 68 30 156 | f 68 65 30 157 | f 65 63 30 158 | f 63 60 30 159 | f 60 57 30 160 | f 57 55 30 161 | f 55 53 30 162 | f 53 50 30 163 | f 50 31 30 164 | f 48 40 31 165 | f 48 44 40 166 | f 40 36 31 167 | f 50 48 31 168 | f 48 46 44 169 | f 44 42 40 170 | f 40 38 36 171 | f 36 33 31 172 | f 31 29 30 173 | f 31 27 29 174 | f 31 23 27 175 | f 75 73 74 176 | f 30 29 26 177 | f 29 28 26 178 | f 28 25 26 179 | f 26 25 20 180 | f 25 24 20 181 | f 24 22 20 182 | f 22 21 20 183 | f 21 19 20 184 | f 20 19 17 185 | f 19 18 17 186 | f 18 16 17 187 | f 17 16 13 188 | f 16 15 13 189 | f 15 3 13 190 | f 14 8 3 191 | f 14 11 8 192 | f 8 5 3 193 | f 15 14 3 194 | f 14 12 11 195 | f 11 9 8 196 | f 8 7 5 197 | f 5 4 3 198 | f 13 3 10 199 | f 10 3 2 200 | f 10 2 6 201 | f 3 1 2 202 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/shaders/bounding_box.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct UiMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | 18 | @group(1) @binding(0) 19 | var material: UiMat; 20 | 21 | 22 | struct Vertex { 23 | @location(0) position: vec3, 24 | @location(1) normal: vec3, 25 | @location(2) uv: vec2, 26 | #ifdef VERTEX_TANGENTS 27 | @location(3) tangent: vec4, 28 | #endif 29 | }; 30 | 31 | struct VertexOutput { 32 | @builtin(position) clip_position: vec4, 33 | @location(0) world_position: vec4, 34 | @location(1) world_normal: vec3, 35 | @location(2) uv: vec2, 36 | #ifdef VERTEX_TANGENTS 37 | @location(3) world_tangent: vec4, 38 | #endif 39 | }; 40 | 41 | @group(0) @binding(0) 42 | var view: View; 43 | 44 | 45 | @group(2) @binding(0) 46 | var mesh: Mesh2d; 47 | 48 | @vertex 49 | fn vertex(vertex: Vertex) -> VertexOutput { 50 | let world_position = mesh.model * vec4(vertex.position, 1.0); 51 | 52 | var out: VertexOutput; 53 | out.uv = vertex.uv; 54 | out.world_position = world_position; 55 | out.clip_position = view.view_proj * world_position; 56 | out.world_normal = mat3x3( 57 | mesh.inverse_transpose_model[0].xyz, 58 | mesh.inverse_transpose_model[1].xyz, 59 | mesh.inverse_transpose_model[2].xyz 60 | ) * vertex.normal; 61 | #ifdef VERTEX_TANGENTS 62 | out.world_tangent = vec4( 63 | mat3x3( 64 | mesh.model[0].xyz, 65 | mesh.model[1].xyz, 66 | mesh.model[2].xyz 67 | ) * vertex.tangent.xyz, 68 | vertex.tangent.w 69 | ); 70 | #endif 71 | return out; 72 | } 73 | 74 | struct FragmentInput { 75 | @builtin(front_facing) is_front: bool, 76 | @location(0) world_position: vec4, 77 | @location(1) world_normal: vec3, 78 | @location(2) uv: vec2, 79 | #ifdef VERTEX_TANGENTS 80 | @location(3) world_tangent: vec4, 81 | #endif 82 | }; 83 | 84 | @fragment 85 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 86 | 87 | let aspect_ratio = material.size.y / material.size.x ; 88 | 89 | var uv_original: vec2 = in.uv - vec2(0.5); 90 | // uv_original.y = uv_original.y * aspect_ratio ; 91 | 92 | let cx = material.size.x / 42.0; 93 | let cy = material.size.y / 42.0; 94 | 95 | let p = 0.5 - 0.05 / 1.1; 96 | let bb_size = 0.1; 97 | 98 | let zoo = material.zoom / 0.08; 99 | 100 | let width = 0.0051; 101 | let sw = 0.0025 * zoo; 102 | 103 | let w = sw / cx; 104 | let m = p + w; 105 | let l = p-w; 106 | let q = width / cx; 107 | 108 | let xdo = smoothstep( m+q, l+q, abs(uv_original.x ) ); 109 | let xdi = 1.0 - smoothstep( m-q, l-q, abs(uv_original.x ) ); 110 | 111 | let p = 0.5 - 0.05 / 1.0 - bb_size / cx; 112 | let w = sw / cx; 113 | let m = p + w; 114 | let l = p-w; 115 | let q = width / cx; 116 | // let xda = 1 -smoothstep( m+q, l+q, (0.5-abs(uv_original.x) )/1.1 ); 117 | let xda= 1.0 - smoothstep( m+q, l+q, abs(uv_original.x ) ); 118 | // xda = 1 - step(uv.x*material.size.x, material.size.x/2 - 10.0 ); 119 | // xda = step(uv.x*material.size.x, material.size.x*0.9/2 ); 120 | 121 | let p = 0.5 - 0.05 / 1.1; 122 | let w = sw / cy; 123 | let m = p + w; 124 | let l = p-w; 125 | let q = width / cy; 126 | 127 | let ydi = 1.0 - smoothstep( m-q, l-q, abs(uv_original.y ) ); 128 | let ydo = smoothstep( m+q, l+q, abs(uv_original.y ) ); 129 | 130 | 131 | let p = 0.5 - 0.05 / 1.0 - bb_size / cy; 132 | let w = sw / cy; 133 | let m = p + w; 134 | let l = p-w; 135 | let q = width / cy; 136 | // let yda = smoothstep( p, p-0.01, 0.5 - abs(uv_original.y ) ); 137 | let yda= 1.0 - smoothstep( m+q, l+q, abs(uv_original.y ) ); 138 | // yda = step(0.5 - abs(uv_original.y ), p ); 139 | 140 | 141 | let xd = xdi * xdo * ydo * xda * yda; 142 | let yd = ydi * ydo * xdo * xda * yda; 143 | 144 | 145 | let red = vec4(0.0, 0.0, 0.0, 0.00); 146 | let color2 = material.color; 147 | // color2.a = 0.3; 148 | 149 | let rect = mix( red ,color2 , min(yd + xd, 1.0)); 150 | // let rect = mix( red ,color2 , xda); 151 | 152 | 153 | 154 | 155 | return rect; 156 | // return vec4(1.0, 0.0, 0.0, 1.0); 157 | 158 | } -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/shaders/button.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct ButtonMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | @group(1) @binding(0) 18 | var material: ButtonMat; 19 | 20 | 21 | struct Vertex { 22 | @location(0) position: vec3, 23 | @location(1) normal: vec3, 24 | @location(2) uv: vec2, 25 | #ifdef VERTEX_TANGENTS 26 | @location(3) tangent: vec4, 27 | #endif 28 | }; 29 | 30 | struct VertexOutput { 31 | @builtin(position) clip_position: vec4, 32 | @location(0) world_position: vec4, 33 | @location(1) world_normal: vec3, 34 | @location(2) uv: vec2, 35 | #ifdef VERTEX_TANGENTS 36 | @location(3) world_tangent: vec4, 37 | #endif 38 | }; 39 | 40 | 41 | @group(0) @binding(0) 42 | var view: View; 43 | 44 | 45 | @group(2) @binding(0) 46 | var mesh: Mesh2d; 47 | 48 | @vertex 49 | fn vertex(vertex: Vertex) -> VertexOutput { 50 | let world_position = mesh.model * vec4(vertex.position, 1.0); 51 | 52 | var out: VertexOutput; 53 | out.uv = vertex.uv; 54 | out.world_position = world_position; 55 | out.clip_position = view.view_proj * world_position; 56 | out.world_normal = mat3x3( 57 | mesh.inverse_transpose_model[0].xyz, 58 | mesh.inverse_transpose_model[1].xyz, 59 | mesh.inverse_transpose_model[2].xyz 60 | ) * vertex.normal; 61 | #ifdef VERTEX_TANGENTS 62 | out.world_tangent = vec4( 63 | mat3x3( 64 | mesh.model[0].xyz, 65 | mesh.model[1].xyz, 66 | mesh.model[2].xyz 67 | ) * vertex.tangent.xyz, 68 | vertex.tangent.w 69 | ); 70 | #endif 71 | return out; 72 | } 73 | 74 | struct FragmentInput { 75 | @builtin(front_facing) is_front: bool, 76 | @location(0) world_position: vec4, 77 | @location(1) world_normal: vec3, 78 | @location(2) uv: vec2, 79 | #ifdef VERTEX_TANGENTS 80 | @location(3) world_tangent: vec4, 81 | #endif 82 | }; 83 | 84 | 85 | 86 | 87 | fn sdBox(p: vec2, b: vec2) -> f32 { 88 | let d = abs(p) - b; 89 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 90 | } 91 | 92 | fn sdCircle(p: vec2, r: f32) -> f32 { 93 | return length(p) - r; 94 | } 95 | 96 | fn fromLinear(linearRGB: vec4) -> vec4 97 | { 98 | let cutoff: vec4 = vec4(linearRGB < vec4(0.0031308)); 99 | let higher: vec4 = vec4(1.055)*pow(linearRGB, vec4(1.0/2.4)) - vec4(0.055); 100 | let lower: vec4 = linearRGB * vec4(12.92); 101 | 102 | return mix(higher, lower, cutoff); 103 | } 104 | 105 | // // Converts a color from sRGB gamma to linear light gamma 106 | fn toLinear(sRGB: vec4) -> vec4 107 | { 108 | let cutoff = vec4(sRGB < vec4(0.04045)); 109 | let higher = pow((sRGB + vec4(0.055))/vec4(1.055), vec4(2.4)); 110 | let lower = sRGB/vec4(12.92); 111 | 112 | return mix(higher, lower, cutoff); 113 | } 114 | 115 | 116 | @fragment 117 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 118 | 119 | let aspect_ratio = material.size.y / material.size.x ; 120 | 121 | var uv_original: vec2 = in.uv - vec2(0.5); 122 | uv_original.x = uv_original.x * aspect_ratio ; 123 | 124 | let margin = 0.2; 125 | var d = sdBox( uv_original, vec2(0.5 - margin , 0.5*aspect_ratio - margin ) ); 126 | let offset = 0.1; 127 | d = smoothstep(0.01+offset, -0.01+offset, d); 128 | 129 | 130 | let other_color = vec4(.0, .0, .0, 0.0); 131 | let white = vec4(1.0, 1.0, 1.0, 1.0); 132 | let yellow = vec4(0.6, 0.75, 0.04, 1.0); 133 | let red = vec4(0.8, 0.45, 0.04, 1.0); 134 | 135 | var bg_color = material.clearcolor; 136 | bg_color.a = 0.0; 137 | 138 | var rect = mix( material.color , bg_color , 1. - d ); 139 | let rect_memory = rect; 140 | 141 | 142 | 143 | // add white contour when color is selected 144 | if (material.hovered > 0.5) { 145 | let r = 0.3; // size 146 | let w = 0.06; // contour width 147 | var d = sdBox( uv_original, vec2(r,r) ); 148 | let c = 0.15; // contour roundness 149 | let b = 0.03; // smoothing 150 | let s1 = smoothstep(-b+w+c, b+w+c, d); 151 | let s2 = smoothstep(-b-w+c, b-w+c, d); 152 | 153 | d = (1.-s1) * (s2); 154 | 155 | rect = mix( white , other_color , 1. - d ); 156 | rect = mix(rect_memory, rect, d); 157 | } 158 | 159 | 160 | if (material.hovered > 0.9) { 161 | let r = 0.3; // size 162 | let w = 0.03; // contour width 163 | var d = sdBox( uv_original, vec2(r,r) ); 164 | let c = 0.15; // contour roundness 165 | let b = 0.03; // smoothing 166 | let s1 = smoothstep(-b+w+c, b+w+c, d); 167 | let s2 = smoothstep(-b-w+c, b-w+c, d); 168 | 169 | d = (1.-s1) * (s2); 170 | 171 | let rect_hover = mix( yellow , other_color , 1. - d ); 172 | rect = mix(rect, rect_hover, d); 173 | } else if (material.hovered>0.7) // if pressed 174 | { 175 | let r = 0.3; // size 176 | let w = 0.03; // contour width 177 | var d = sdBox( uv_original, vec2(r,r) ); 178 | let c = 0.15; // contour roundness 179 | let b = 0.03; // smoothing 180 | let s1 = smoothstep(-b+w+c, b+w+c, d); 181 | let s2 = smoothstep(-b-w+c, b-w+c, d); 182 | 183 | d = (1.-s1) * (s2); 184 | 185 | let rect_hover = mix( red , other_color , 1. - d ); 186 | rect = mix(rect, rect_hover, d); 187 | } 188 | 189 | if (material.t > 0.5) { 190 | let r = 0.3; // size 191 | let w = 0.06; // contour width 192 | var d = sdBox( uv_original, vec2(r,r) ); 193 | let c = 0.15; // contour roundness 194 | let b = 0.03; // smoothing 195 | let s1 = smoothstep(-b+w+c, b+w+c, d); 196 | let s2 = smoothstep(-b-w+c, b-w+c, d); 197 | 198 | d = (1.-s1) * (s2); 199 | 200 | rect = mix( white , other_color , 1. - d ); 201 | rect = mix(rect_memory, rect, d); 202 | } 203 | 204 | 205 | 206 | // rect = vec4(rect.xyz * 0.5, 1.0); 207 | // rect.w = 1.0; 208 | 209 | 210 | return toLinear( rect); 211 | } 212 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/shaders/controls.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct UiMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | 18 | @group(1) @binding(0) 19 | var material: UiMat; 20 | 21 | 22 | struct Vertex { 23 | @location(0) position: vec3, 24 | @location(1) normal: vec3, 25 | @location(2) uv: vec2, 26 | #ifdef VERTEX_TANGENTS 27 | @location(3) tangent: vec4, 28 | #endif 29 | }; 30 | 31 | struct VertexOutput { 32 | @builtin(position) clip_position: vec4, 33 | @location(0) world_position: vec4, 34 | @location(1) world_normal: vec3, 35 | @location(2) uv: vec2, 36 | #ifdef VERTEX_TANGENTS 37 | @location(3) world_tangent: vec4, 38 | #endif 39 | }; 40 | 41 | 42 | @group(0) @binding(0) 43 | var view: View; 44 | 45 | 46 | @group(2) @binding(0) 47 | var mesh: Mesh2d; 48 | 49 | fn sdTriangle( p: vec2, p0: vec2, p1: vec2, p2: vec2 ) -> f32 50 | { 51 | let e0 = p1-p0; 52 | let e1 = p2-p1; 53 | let e2 = p0-p2; 54 | let v0 = p -p0; 55 | let v1 = p -p1; 56 | let v2 = p -p2; 57 | let pq0 = v0 - e0*clamp( dot(v0,e0)/dot(e0,e0), 0.0, 1.0 ); 58 | let pq1 = v1 - e1*clamp( dot(v1,e1)/dot(e1,e1), 0.0, 1.0 ); 59 | let pq2 = v2 - e2*clamp( dot(v2,e2)/dot(e2,e2), 0.0, 1.0 ); 60 | let s = sign( e0.x*e2.y - e0.y*e2.x ); 61 | let d = min(min(vec2(dot(pq0,pq0), s*(v0.x*e0.y-v0.y*e0.x)), 62 | vec2(dot(pq1,pq1), s*(v1.x*e1.y-v1.y*e1.x))), 63 | vec2(dot(pq2,pq2), s*(v2.x*e2.y-v2.y*e2.x))); 64 | return -sqrt(d.x)*sign(d.y); 65 | } 66 | 67 | 68 | @vertex 69 | fn vertex(vertex: Vertex) -> VertexOutput { 70 | let world_position = mesh.model * vec4(vertex.position, 1.0); 71 | 72 | var out: VertexOutput; 73 | out.uv = vertex.uv; 74 | out.world_position = world_position; 75 | out.clip_position = view.view_proj * world_position; 76 | out.world_normal = mat3x3( 77 | mesh.inverse_transpose_model[0].xyz, 78 | mesh.inverse_transpose_model[1].xyz, 79 | mesh.inverse_transpose_model[2].xyz 80 | ) * vertex.normal; 81 | #ifdef VERTEX_TANGENTS 82 | out.world_tangent = vec4( 83 | mat3x3( 84 | mesh.model[0].xyz, 85 | mesh.model[1].xyz, 86 | mesh.model[2].xyz 87 | ) * vertex.tangent.xyz, 88 | vertex.tangent.w 89 | ); 90 | #endif 91 | return out; 92 | } 93 | 94 | struct FragmentInput { 95 | @builtin(front_facing) is_front: bool, 96 | @location(0) world_position: vec4, 97 | @location(1) world_normal: vec3, 98 | @location(2) uv: vec2, 99 | #ifdef VERTEX_TANGENTS 100 | @location(3) world_tangent: vec4, 101 | #endif 102 | }; 103 | 104 | fn sdBox(p: vec2, b: vec2) -> f32 { 105 | let d = abs(p) - b; 106 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 107 | } 108 | 109 | fn sdCircle(p: vec2, r: f32) -> f32 { 110 | return length(p) - r; 111 | } 112 | 113 | 114 | 115 | @fragment 116 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 117 | 118 | let aspect_ratio = material.size.y / material.size.x ; 119 | 120 | var uv_original: vec2 = in.uv - vec2(0.5); 121 | uv_original.y = uv_original.y * aspect_ratio ; 122 | 123 | // let pos = vec2(0.5, 0.5); 124 | // let uv_original = (Vertex_Uv.xy-pos); 125 | 126 | 127 | 128 | let p0 = vec2(0.0, -0.4); 129 | let p1 = vec2(0.4, 0.4); 130 | let p2 = vec2(-0.4, 0.4); 131 | var d0 = sdTriangle( uv_original, p0, p1, p2 ); 132 | 133 | let zoo = material.zoom / 0.08 / 5.; 134 | let w = -0.02 * zoo; 135 | d0 = smoothstep(-w, w, d0); 136 | 137 | let p3 = vec2(0.0, -0.0); 138 | let p4 = vec2(0.4, 0.45); 139 | let p5 = vec2(-0.4, 0.45); 140 | 141 | var d1 = sdTriangle( uv_original, p3, p4, p5 ); 142 | d1 = smoothstep(-w, w, d1); 143 | 144 | 145 | let d = d0 * (1.0 - d1); 146 | 147 | // let color_with_t = material.color; 148 | 149 | var bg_color = material.clearcolor; 150 | bg_color.a = 0.0; 151 | 152 | let circle = mix( material.color, bg_color, 1.0 - d ); 153 | 154 | 155 | // o_Target = circle; 156 | 157 | 158 | 159 | return circle; 160 | // return vec4(1.0, 1.0, 1.0, 1.0); 161 | } 162 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/shaders/ends.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct UiMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | 18 | @group(1) @binding(0) 19 | var material: UiMat; 20 | 21 | 22 | struct Vertex { 23 | @location(0) position: vec3, 24 | @location(1) normal: vec3, 25 | @location(2) uv: vec2, 26 | #ifdef VERTEX_TANGENTS 27 | @location(3) tangent: vec4, 28 | #endif 29 | }; 30 | 31 | struct VertexOutput { 32 | @builtin(position) clip_position: vec4, 33 | @location(0) world_position: vec4, 34 | @location(1) world_normal: vec3, 35 | @location(2) uv: vec2, 36 | #ifdef VERTEX_TANGENTS 37 | @location(3) world_tangent: vec4, 38 | #endif 39 | }; 40 | 41 | 42 | @group(0) @binding(0) 43 | var view: View; 44 | 45 | 46 | @group(2) @binding(0) 47 | var mesh: Mesh2d; 48 | 49 | @vertex 50 | fn vertex(vertex: Vertex) -> VertexOutput { 51 | let world_position = mesh.model * vec4(vertex.position, 1.0); 52 | 53 | var out: VertexOutput; 54 | out.uv = vertex.uv; 55 | out.world_position = world_position; 56 | out.clip_position = view.view_proj * world_position; 57 | out.world_normal = mat3x3( 58 | mesh.inverse_transpose_model[0].xyz, 59 | mesh.inverse_transpose_model[1].xyz, 60 | mesh.inverse_transpose_model[2].xyz 61 | ) * vertex.normal; 62 | #ifdef VERTEX_TANGENTS 63 | out.world_tangent = vec4( 64 | mat3x3( 65 | mesh.model[0].xyz, 66 | mesh.model[1].xyz, 67 | mesh.model[2].xyz 68 | ) * vertex.tangent.xyz, 69 | vertex.tangent.w 70 | ); 71 | #endif 72 | return out; 73 | } 74 | 75 | struct FragmentInput { 76 | @builtin(front_facing) is_front: bool, 77 | @location(0) world_position: vec4, 78 | @location(1) world_normal: vec3, 79 | @location(2) uv: vec2, 80 | #ifdef VERTEX_TANGENTS 81 | @location(3) world_tangent: vec4, 82 | #endif 83 | }; 84 | 85 | 86 | fn sdBox(p: vec2, b: vec2) -> f32 { 87 | let d = abs(p) - b; 88 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 89 | } 90 | 91 | fn sdCircle(p: vec2, r: f32) -> f32 { 92 | return length(p) - r; 93 | } 94 | 95 | 96 | 97 | @fragment 98 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 99 | 100 | let aspect_ratio = material.size.y / material.size.x ; 101 | 102 | var uv_original: vec2 = (in.uv - vec2(0.5)); 103 | uv_original.x = uv_original.x / 2.0 ; 104 | 105 | 106 | // let zoo = material.zoom / 0.08; 107 | let zoo = 1.0; 108 | let w = -0.03 * zoo; 109 | 110 | let offset = 0.5; 111 | 112 | var d0 = sdCircle( uv_original - offset * vec2(0.5,0.), 0.5 ); 113 | d0 = smoothstep(-w, w, d0); 114 | 115 | var d1 = sdCircle( uv_original - offset * vec2(0.5, 0.), 0.3 / (1.0 + pow(zoo, 0.5))); 116 | d1 = smoothstep(-w, w, d1); 117 | 118 | let d = 1. - d0 * (1. - d1); 119 | 120 | 121 | var color_with_t = material.color; 122 | 123 | 124 | var bg_color = material.clearcolor; 125 | bg_color.a = 0.0; 126 | let circle = mix( color_with_t ,bg_color , d ); 127 | 128 | return circle; 129 | } 130 | 131 | 132 | 133 | // void main( ) 134 | // { 135 | // vec2 pos = vec2(0.5, 0.5); 136 | // vec2 uv_original = (Vertex_Uv.xy-pos); 137 | // uv_original.x = (uv_original.x -0.5) / 2.0; 138 | 139 | // float zoo = zoom / 0.08; 140 | // float w = -0.03 * zoo; 141 | 142 | // float d0 = sdCircle( uv_original, 0.5 ); 143 | // d0 = smoothstep(-w, w, d0); 144 | 145 | // float d1 = sdCircle( uv_original, 0.3 / (1 + pow(zoo, 0.5))); 146 | // d1 = smoothstep(-w, w, d1); 147 | 148 | // float d = 1 - d0 * (1- d1); 149 | 150 | 151 | // // makes the middle quads disappear close to the ends 152 | // float transparency = smoothstep( 0.0, 0.05, 0.5-abs(t-0.5)); 153 | // vec4 color_with_t = color; 154 | // color_with_t.a = transparency; 155 | 156 | // // vec4 other_color = vec4(110. / 255., 127. / 255., 128. / 255., 0.0); 157 | // vec4 bg_color = clear_color; 158 | // bg_color.a = 0.0; 159 | // vec4 circle = mix( color_with_t ,bg_color , d ); 160 | 161 | 162 | // o_Target = circle; 163 | // } 164 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/shaders/fill_mesh.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_pbr::mesh_view_bindings 2 | 3 | // This uniform is not needed here, as color attributes are being sent. 4 | // But in the future, the uniform will be used to highlight selected 5 | // fill meshes 6 | struct FillMat { 7 | color: vec4, 8 | center_of_mass: vec2, 9 | show_com: f32, 10 | }; 11 | 12 | @group(1) @binding(0) 13 | var uni: FillMat; 14 | 15 | // // Converts a color from sRGB gamma to linear light gamma 16 | fn toLinear(sRGB: vec4) -> vec4 17 | { 18 | let cutoff = vec4(sRGB < vec4(0.04045)); 19 | let higher = pow((sRGB + vec4(0.055))/vec4(1.055), vec4(2.4)); 20 | let lower = sRGB/vec4(12.92); 21 | return mix(higher, lower, cutoff); 22 | } 23 | 24 | @fragment 25 | fn fragment( 26 | @builtin(position) position: vec4, 27 | #import bevy_sprite::mesh2d_vertex_output 28 | ) -> @location(0) vec4 { 29 | if length(world_position.xy - uni.center_of_mass) < 10.0 && uni.show_com > 0.5 { 30 | let selector_color = vec4(0.0, 0.0, 0.0, 0.5); 31 | let mixed_color = mix(uni.color, selector_color, 0.2); 32 | return mixed_color; 33 | } 34 | return toLinear(uni.color); 35 | } -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/shaders/mids.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | struct UiMat { 7 | color: vec4, 8 | clearcolor: vec4, 9 | t: f32, 10 | zoom: f32, 11 | size: vec2, 12 | hovered: f32, 13 | }; 14 | 15 | @group(1) @binding(0) 16 | var material: UiMat; 17 | 18 | struct Vertex { 19 | @location(0) position: vec3, 20 | @location(1) normal: vec3, 21 | @location(2) uv: vec2, 22 | #ifdef VERTEX_TANGENTS 23 | @location(3) tangent: vec4, 24 | #endif 25 | }; 26 | 27 | struct VertexOutput { 28 | @builtin(position) clip_position: vec4, 29 | @location(0) world_position: vec4, 30 | @location(1) world_normal: vec3, 31 | @location(2) uv: vec2, 32 | #ifdef VERTEX_TANGENTS 33 | @location(3) world_tangent: vec4, 34 | #endif 35 | }; 36 | 37 | 38 | 39 | @group(0) @binding(0) 40 | var view: View; 41 | 42 | 43 | @group(2) @binding(0) 44 | var mesh: Mesh2d; 45 | 46 | @vertex 47 | fn vertex(vertex: Vertex) -> VertexOutput { 48 | let world_position = mesh.model * vec4(vertex.position, 1.0); 49 | 50 | var out: VertexOutput; 51 | out.uv = vertex.uv; 52 | out.world_position = world_position; 53 | out.clip_position = view.view_proj * world_position; 54 | out.world_normal = mat3x3( 55 | mesh.inverse_transpose_model[0].xyz, 56 | mesh.inverse_transpose_model[1].xyz, 57 | mesh.inverse_transpose_model[2].xyz 58 | ) * vertex.normal; 59 | #ifdef VERTEX_TANGENTS 60 | out.world_tangent = vec4( 61 | mat3x3( 62 | mesh.model[0].xyz, 63 | mesh.model[1].xyz, 64 | mesh.model[2].xyz 65 | ) * vertex.tangent.xyz, 66 | vertex.tangent.w 67 | ); 68 | #endif 69 | return out; 70 | } 71 | 72 | struct FragmentInput { 73 | @builtin(front_facing) is_front: bool, 74 | @location(0) world_position: vec4, 75 | @location(1) world_normal: vec3, 76 | @location(2) uv: vec2, 77 | #ifdef VERTEX_TANGENTS 78 | @location(3) world_tangent: vec4, 79 | #endif 80 | }; 81 | 82 | 83 | fn sdBox(p: vec2, b: vec2) -> f32 { 84 | let d = abs(p) - b; 85 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 86 | } 87 | 88 | fn sdCircle(p: vec2, r: f32) -> f32 { 89 | return length(p) - r; 90 | } 91 | 92 | 93 | @fragment 94 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 95 | 96 | let aspect_ratio = material.size.y / material.size.x ; 97 | 98 | var uv_original: vec2 = (in.uv - vec2(0.5)); 99 | // uv_original.x = uv_original.x / 2.0 ; 100 | 101 | 102 | // let zoo = material.zoom / 0.08; 103 | let zoo = 1.0; 104 | let w = -0.03 * zoo; 105 | 106 | let offset = 0.0; 107 | 108 | let radius = 0.5; 109 | 110 | var d0 = sdCircle( uv_original - offset * vec2(0.5,0.), radius ); 111 | d0 = smoothstep(-w, w, d0); 112 | 113 | var d1 = sdCircle( uv_original - offset * vec2(0.5, 0.), radius * 0.5 ); 114 | d1 = smoothstep(-w, w, d1); 115 | 116 | let d = 1. - d0 * (1. - d1); 117 | 118 | 119 | var color_with_t = material.color; 120 | color_with_t.a = smoothstep(0.0, 0.1, material.t) * smoothstep(0.0, 0.1, 1.0 - material.t) ; 121 | 122 | var bg_color = material.clearcolor; 123 | bg_color.a = 0.0; 124 | 125 | 126 | let circle = mix( color_with_t ,bg_color , d ); 127 | // 128 | 129 | 130 | return circle; 131 | } 132 | 133 | 134 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/shaders/road_mesh.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_pbr::mesh_view_bindings 2 | 3 | @group(1) @binding(0) 4 | var sprite_texture: texture_2d; 5 | @group(1) @binding(1) 6 | var sprite_sampler: sampler; 7 | 8 | struct RoadMat { 9 | center_of_mass: vec2, 10 | show_com: f32, 11 | }; 12 | 13 | @group(1) @binding(2) 14 | var uni: RoadMat; 15 | 16 | 17 | @fragment 18 | fn fragment( 19 | @builtin(position) position: vec4, 20 | #import bevy_sprite::mesh2d_vertex_output 21 | ) -> @location(0) vec4 { 22 | var color = textureSample(sprite_texture, sprite_sampler, uv); 23 | if uni.show_com > 0.5 { 24 | let selector_color = vec4(0.5, 0.5, 0.5, 0.5); 25 | let mixed_color = mix(color, selector_color, 0.2); 26 | return mixed_color; 27 | } 28 | return color; 29 | } -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/shaders/selecting.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct UiMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | @group(1) @binding(0) 18 | var material: UiMat; 19 | 20 | 21 | struct Vertex { 22 | @location(0) position: vec3, 23 | @location(1) normal: vec3, 24 | @location(2) uv: vec2, 25 | #ifdef VERTEX_TANGENTS 26 | @location(3) tangent: vec4, 27 | #endif 28 | }; 29 | 30 | struct VertexOutput { 31 | @builtin(position) clip_position: vec4, 32 | @location(0) world_position: vec4, 33 | @location(1) world_normal: vec3, 34 | @location(2) uv: vec2, 35 | #ifdef VERTEX_TANGENTS 36 | @location(3) world_tangent: vec4, 37 | #endif 38 | }; 39 | 40 | @group(0) @binding(0) 41 | var view: View; 42 | 43 | 44 | @group(2) @binding(0) 45 | var mesh: Mesh2d; 46 | 47 | @vertex 48 | fn vertex(vertex: Vertex) -> VertexOutput { 49 | let world_position = mesh.model * vec4(vertex.position, 1.0); 50 | 51 | var out: VertexOutput; 52 | out.uv = vertex.uv; 53 | out.world_position = world_position; 54 | out.clip_position = view.view_proj * world_position; 55 | out.world_normal = mat3x3( 56 | mesh.inverse_transpose_model[0].xyz, 57 | mesh.inverse_transpose_model[1].xyz, 58 | mesh.inverse_transpose_model[2].xyz 59 | ) * vertex.normal; 60 | #ifdef VERTEX_TANGENTS 61 | out.world_tangent = vec4( 62 | mat3x3( 63 | mesh.model[0].xyz, 64 | mesh.model[1].xyz, 65 | mesh.model[2].xyz 66 | ) * vertex.tangent.xyz, 67 | vertex.tangent.w 68 | ); 69 | #endif 70 | return out; 71 | } 72 | 73 | struct FragmentInput { 74 | @builtin(front_facing) is_front: bool, 75 | @location(0) world_position: vec4, 76 | @location(1) world_normal: vec3, 77 | @location(2) uv: vec2, 78 | #ifdef VERTEX_TANGENTS 79 | @location(3) world_tangent: vec4, 80 | #endif 81 | }; 82 | 83 | fn sdBox(p: vec2, b: vec2) -> f32 { 84 | let d = abs(p) - b; 85 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 86 | } 87 | 88 | fn sdCircle(p: vec2, r: f32) -> f32 { 89 | return length(p) - r; 90 | } 91 | 92 | 93 | 94 | @fragment 95 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 96 | let aspect_ratio = material.size.y / material.size.x ; 97 | 98 | var uv_original: vec2 = in.uv - vec2(0.5); 99 | // uv_original.y = uv_original.y * aspect_ratio ; 100 | 101 | 102 | 103 | let cx = material.size.x / 42.0; 104 | let cy = material.size.y / 42.0; 105 | 106 | let p = 0.5 - 0.05 / 1.1; 107 | let bb_size = 0.1; 108 | 109 | let zoo = material.zoom / 0.08; 110 | 111 | let width = 0.00251 * 0.5; 112 | let sw = 0.0025 * zoo * 1.0; 113 | 114 | let w = sw / cx; 115 | let m = p + w; 116 | let l = p-w; 117 | let q = width / cx; 118 | 119 | let xdo = smoothstep( m+q, l+q, abs(uv_original.x ) ); 120 | let xdi = 1.0 - smoothstep( m-q, l-q, abs(uv_original.x ) ); 121 | 122 | let p = 0.5 - 0.05 / 1. - bb_size/cx; 123 | let w = sw / cx; 124 | let m = p + w; 125 | let l = p-w; 126 | let q = width / cx; 127 | 128 | // let xda= 1 - smoothstep( m+q, l+q, abs(uv.x ) ); 129 | 130 | 131 | let p = 0.5 - 0.05 / 1.1; 132 | let w = sw / cy; 133 | let m = p + w; 134 | let l = p-w; 135 | let q = width / cy; 136 | 137 | let ydi = 1.0 - smoothstep( m-q, l-q, abs(uv_original.y ) ); 138 | let ydo = smoothstep( m+q, l+q, abs(uv_original.y ) ); 139 | 140 | 141 | // p = 0.5 - 0.05/1. - bb_size/cy; 142 | // w = sw / cy; 143 | // m = p + w; 144 | // l = p-w; 145 | // q = width / cy; 146 | // // let yda = smoothstep( p, p-0.01, 0.5 - abs(uv.y ) ); 147 | // let yda= 1 - smoothstep( m+q, l+q, abs(uv.y ) ); 148 | // // yda = step(0.5 - abs(uv.y ), p ); 149 | 150 | 151 | let xd = xdi * xdo * ydo; // * xda * yda; 152 | let yd = ydi * ydo * xdo; // * xda * yda; 153 | 154 | 155 | let red = vec4(0.0, 0.0, 0.0, 0.00); 156 | let color2 = material.color; 157 | // color2.a = 0.3; 158 | 159 | let rect = mix( red ,color2 , min(yd + xd, 1.0)); 160 | // vec4 rect = mix( red ,color2 , xda); 161 | 162 | // o_Target = rect; 163 | 164 | 165 | return rect; 166 | // return vec4(1.0, 1.0, 1.0, 1.0); 167 | } 168 | 169 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/shaders/ui.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_types 3 | 4 | 5 | 6 | 7 | struct UiMat { 8 | color: vec4, 9 | clearcolor: vec4, 10 | t: f32, 11 | zoom: f32, 12 | size: vec2, 13 | hovered: f32, 14 | }; 15 | 16 | 17 | @group(1) @binding(0) 18 | var material: UiMat; 19 | 20 | 21 | struct Vertex { 22 | @location(0) position: vec3, 23 | @location(1) normal: vec3, 24 | @location(2) uv: vec2, 25 | #ifdef VERTEX_TANGENTS 26 | @location(3) tangent: vec4, 27 | #endif 28 | }; 29 | 30 | struct VertexOutput { 31 | @builtin(position) clip_position: vec4, 32 | @location(0) world_position: vec4, 33 | @location(1) world_normal: vec3, 34 | @location(2) uv: vec2, 35 | #ifdef VERTEX_TANGENTS 36 | @location(3) world_tangent: vec4, 37 | #endif 38 | }; 39 | 40 | 41 | @group(0) @binding(0) 42 | var view: View; 43 | 44 | 45 | @group(2) @binding(0) 46 | var mesh: Mesh2d; 47 | 48 | @vertex 49 | fn vertex(vertex: Vertex) -> VertexOutput { 50 | let world_position = mesh.model * vec4(vertex.position, 1.0); 51 | 52 | var out: VertexOutput; 53 | out.uv = vertex.uv; 54 | out.world_position = world_position; 55 | out.clip_position = view.view_proj * world_position; 56 | out.world_normal = mat3x3( 57 | mesh.inverse_transpose_model[0].xyz, 58 | mesh.inverse_transpose_model[1].xyz, 59 | mesh.inverse_transpose_model[2].xyz 60 | ) * vertex.normal; 61 | #ifdef VERTEX_TANGENTS 62 | out.world_tangent = vec4( 63 | mat3x3( 64 | mesh.model[0].xyz, 65 | mesh.model[1].xyz, 66 | mesh.model[2].xyz 67 | ) * vertex.tangent.xyz, 68 | vertex.tangent.w 69 | ); 70 | #endif 71 | return out; 72 | } 73 | 74 | struct FragmentInput { 75 | @builtin(front_facing) is_front: bool, 76 | @location(0) world_position: vec4, 77 | @location(1) world_normal: vec3, 78 | @location(2) uv: vec2, 79 | #ifdef VERTEX_TANGENTS 80 | @location(3) world_tangent: vec4, 81 | #endif 82 | }; 83 | 84 | fn sdBox(p: vec2, b: vec2) -> f32 { 85 | let d = abs(p) - b; 86 | return length(max(d, vec2(0.))) + min(max(d.x, d.y), 0.); 87 | } 88 | 89 | fn sdCircle(p: vec2, r: f32) -> f32 { 90 | return length(p) - r; 91 | } 92 | 93 | 94 | 95 | @fragment 96 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 97 | 98 | let aspect_ratio = material.size.y / material.size.x ; 99 | 100 | var uv_original: vec2 = in.uv - vec2(0.5); 101 | uv_original.y = uv_original.y * aspect_ratio ; 102 | 103 | 104 | let margin = 0.15; 105 | var d = sdBox( uv_original, vec2(0.5 - margin , 0.5*aspect_ratio - margin ) ); 106 | let offset = 0.1; 107 | d = smoothstep(0.01+offset, -0.01+offset, d); 108 | 109 | var bg_color = (material.clearcolor); 110 | bg_color.a = 0.0; 111 | 112 | var color_mod = (material.color); 113 | color_mod.a = 0.3; 114 | 115 | var rect = mix( color_mod , bg_color , 1.0 - d ); 116 | 117 | 118 | return rect; 119 | } 120 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/sounds/group.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/sounds/group.ogg -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/sounds/latch.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/sounds/latch.ogg -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/sounds/unlatch.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/sounds/unlatch.ogg -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/bin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/bin.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/branding_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/branding_icon.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/car.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/controls_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/controls_off.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/controls_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/controls_on.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/copter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/copter.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/heli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/heli.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/heli_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/heli_button.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/hide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/hide.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/load.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/lut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/lut.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/mesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/mesh.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/redo.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/road_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/road_icon.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/road_texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/road_texture.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/save.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/scale_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/scale_down.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/scale_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/scale_up.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/selection.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/show_anchors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/show_anchors.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/single_lane_road.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/single_lane_road.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/sound_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/sound_off.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/sound_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/sound_on.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/assets/textures/undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/assets/textures/undo.png -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/crates/bevy_pen_tool_model/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bevy_pen_tool_model" 3 | version = "0.3.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | # bevy = { git = "https://github.com/bevyengine/bevy", rev = "6a1ba9c" } 10 | bevy = "0.8" 11 | flo_curves = "0.5" 12 | serde_json = "1.0.59" 13 | itertools = "0.10.1" 14 | serde = { version = "1", features = ["derive"] } 15 | rand = "0.8.0" 16 | plotlib = "0.5.1" 17 | lyon = "0.17.5" 18 | obj-exporter = "0.2.0" 19 | rfd = "0.5.1" 20 | bevy-inspector-egui = "0.12" 21 | bevy_obj = "0.8" 22 | 23 | 24 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/crates/bevy_pen_tool_model/src/inputs/mod.rs: -------------------------------------------------------------------------------- 1 | mod buttons; 2 | mod inputs; 3 | 4 | pub use buttons::*; 5 | pub use inputs::*; 6 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/crates/bevy_pen_tool_model/src/materials.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::*, reflect::TypeUuid, render::render_resource::*, sprite::Material2d}; 2 | 3 | #[macro_export] 4 | macro_rules! make_mat { 5 | ($( $name_of_mat:ident, $gpu_name_of_mat:ident, $vert_shader:expr, $frag_shader:expr, $uuid:expr ),*) => { 6 | 7 | $( 8 | #[derive(TypeUuid, Debug, Clone, AsBindGroup)] 9 | #[uuid = $uuid] 10 | #[allow(non_snake_case)] 11 | pub struct $name_of_mat { 12 | #[uniform(0)] 13 | pub color: Vec4, 14 | #[uniform(0)] 15 | pub clearcolor: Vec4, 16 | #[uniform(0)] 17 | pub t: f32, // Bezier t-value for MiddleQuads, but is used for other purposes elsewhere 18 | #[uniform(0)] 19 | pub zoom: f32, 20 | #[uniform(0)] 21 | pub size: Vec2, 22 | #[uniform(0)] 23 | pub hovered: f32, 24 | } 25 | 26 | impl Default for $name_of_mat { 27 | fn default() -> Self { 28 | 29 | Self { 30 | color: Color::hex("F87575").unwrap().into(), 31 | t: 0.5, 32 | zoom: 0.15, 33 | size: Vec2::new(1.0, 1.0), 34 | clearcolor: Color::hex("6e7f80").unwrap().into(), 35 | hovered: 0.0, 36 | } 37 | } 38 | } 39 | 40 | impl Material2d for $name_of_mat { 41 | fn fragment_shader() -> ShaderRef { 42 | $frag_shader.into() 43 | } 44 | } 45 | 46 | )* 47 | } 48 | } 49 | 50 | make_mat![ 51 | UiMat, 52 | GpuUiMat, 53 | "shaders/bezier.vert", 54 | "shaders/ui.wgsl", 55 | "6cf5ad10-8906-45d9-b29b-eba9ec6c0de8" 56 | ]; 57 | 58 | make_mat![ 59 | SelectionMat, 60 | GpuSelectionMat, 61 | "shaders/bezier.vert", 62 | "shaders/bounding_box.wgsl", 63 | "3e08866c-0b8a-437e-8bce-37733b21137e" 64 | ]; 65 | 66 | make_mat![ 67 | SelectingMat, 68 | GpuSelectingMat, 69 | "shaders/bezier.vert", 70 | "shaders/selecting.wgsl", 71 | "4e08866c-0b8a-437e-8bce-37733b21137e" 72 | ]; 73 | 74 | make_mat![ 75 | ButtonMat, 76 | GpuButtonMat, 77 | "shaders/bezier.vert", 78 | "shaders/button.wgsl", 79 | "5e08866c-0b8a-437e-8bce-37733b21137e" 80 | ]; 81 | 82 | make_mat![ 83 | BezierEndsMat, 84 | GpuBezierEnds, 85 | "shaders/bezier.vert", 86 | "shaders/ends.wgsl", 87 | "6e08866c-0b8a-437e-8bce-37733b21137e" 88 | ]; 89 | 90 | make_mat![ 91 | BezierControlsMat, 92 | GpuBezierControlsMat, 93 | "shaders/bezier.vert", 94 | "shaders/controls.wgsl", 95 | "7e08866c-0b8a-437e-8bce-37733b21137e" 96 | ]; 97 | 98 | make_mat![ 99 | BezierMidMat, 100 | GpuUiBezierMidMat, 101 | "shaders/bezier.vert", 102 | "shaders/mids.wgsl", 103 | "8e08866c-0b8a-437e-8bce-37733b21137e" 104 | ]; 105 | 106 | make_mat![ 107 | FillMat, 108 | GpuFillMat, 109 | "shaders/bezier.vert", 110 | "shaders/mids.wgsl", 111 | "9e08866c-0b8a-437e-8bce-37733b21137e" 112 | ]; 113 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/crates/bevy_pen_tool_model/src/mesh/material_mesh.rs: -------------------------------------------------------------------------------- 1 | use bevy::{ 2 | prelude::*, 3 | reflect::TypeUuid, 4 | render::render_resource::{AsBindGroup, ShaderRef}, 5 | sprite::{Material2d, Material2dPlugin}, 6 | }; 7 | 8 | #[derive(AsBindGroup, TypeUuid, Debug, Clone, Component, Default)] 9 | #[uuid = "f690fdae-d598-45ab-8225-97e2a3f95a4b"] 10 | pub struct RoadMesh2dMaterial { 11 | #[texture(0)] 12 | #[sampler(1)] 13 | pub road_texture: Handle, 14 | #[uniform(2)] 15 | pub center_of_mass: Vec2, 16 | #[uniform(2)] 17 | pub show_com: f32, 18 | } 19 | 20 | pub struct RoadMesh2dPlugin; 21 | 22 | impl Plugin for RoadMesh2dPlugin { 23 | fn build(&self, app: &mut App) { 24 | app.add_plugin(Material2dPlugin::::default()); 25 | } 26 | } 27 | 28 | impl Material2d for RoadMesh2dMaterial { 29 | fn fragment_shader() -> ShaderRef { 30 | "shaders/road_mesh.wgsl".into() 31 | } 32 | } 33 | 34 | #[derive(AsBindGroup, TypeUuid, Debug, Clone, Component, Default)] 35 | #[uuid = "f690fdae-d598-45ab-1684-97e2a3f95a9a"] 36 | pub struct FillMesh2dMaterial { 37 | #[uniform(0)] 38 | pub color: Vec4, 39 | #[uniform(0)] 40 | pub center_of_mass: Vec2, 41 | #[uniform(0)] 42 | pub show_com: f32, 43 | } 44 | 45 | pub struct FillMesh2dPlugin; 46 | 47 | impl Plugin for FillMesh2dPlugin { 48 | fn build(&self, app: &mut App) { 49 | app.add_plugin(Material2dPlugin::::default()); 50 | } 51 | } 52 | 53 | impl Material2d for FillMesh2dMaterial { 54 | fn fragment_shader() -> ShaderRef { 55 | "shaders/fill_mesh.wgsl".into() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/crates/bevy_pen_tool_model/src/mesh/mod.rs: -------------------------------------------------------------------------------- 1 | mod material_mesh; 2 | mod mesh_making; 3 | 4 | pub use material_mesh::*; 5 | pub use mesh_making::*; 6 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/crates/bevy_pen_tool_model/src/mod.rs: -------------------------------------------------------------------------------- 1 | mod bezier_spawner; 2 | mod materials; 3 | mod mesh_making; 4 | mod others_spawner; 5 | mod road_mesh; 6 | mod ui_spawner; 7 | 8 | pub use bezier_spawner::*; 9 | pub use materials::*; 10 | pub use mesh_making::*; 11 | pub use others_spawner::*; 12 | pub use road_mesh::*; 13 | pub use ui_spawner::*; 14 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/crates/bevy_pen_tool_model/src/model/mod.rs: -------------------------------------------------------------------------------- 1 | mod bezier; 2 | mod group; 3 | pub mod util; 4 | 5 | pub use bezier::*; 6 | pub use group::*; 7 | pub use util::*; 8 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/crates/bevy_pen_tool_model/src/spawner/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bezier_spawner; 2 | pub mod others_spawner; 3 | pub mod ui_spawner; 4 | 5 | pub use bezier_spawner::*; 6 | pub use others_spawner::*; 7 | pub use ui_spawner::*; 8 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/blank.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{BevyPenToolPlugin, Bezier, Globals}; 3 | 4 | // use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}; 5 | use bevy::{prelude::*, render::camera::OrthographicProjection}; 6 | // TODO: 7 | // - add enabled/disabled to buttons 8 | // - bug in officiate_latch_partnership(..) at let handle_entity_2 = maps.bezier_map[&latch.latched_to_id.into()].clone(); 9 | // perhaps the bug involves deletion and redo but I'm not sure 10 | 11 | // long-term 12 | // - compatibility with multiple groups 13 | // - Attach UI to a UI camera -- waiting for UI to be compatible with shaders 14 | 15 | fn main() { 16 | App::new() 17 | .insert_resource(WindowDescriptor { 18 | title: "pen".to_string(), 19 | width: 1200., 20 | height: 800., 21 | // vsync: true, 22 | ..Default::default() 23 | }) 24 | // .add_plugin(LogDiagnosticsPlugin::default()) 25 | // .add_plugin(FrameTimeDiagnosticsPlugin::default()) 26 | .add_plugins(DefaultPlugins) 27 | .add_plugin(CamPlugin) 28 | .add_startup_system(camera_setup) 29 | .add_plugin(BevyPenToolPlugin) 30 | .add_system(tests) 31 | .run(); 32 | } 33 | 34 | fn camera_setup(mut commands: Commands, mut globals: ResMut) { 35 | // 36 | // bevy_pen_tool is not compatible with a Perspective Camera 37 | commands 38 | .spawn_bundle(Camera2dBundle { 39 | transform: Transform::from_translation(Vec3::new(00.0, 0.0, 1.0)) 40 | .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y), 41 | projection: OrthographicProjection { 42 | scale: 1.0, 43 | far: 100000.0, 44 | near: -100000.0, 45 | ..Default::default() 46 | }, 47 | ..Default::default() 48 | }) 49 | .insert(Cam::default()); 50 | 51 | // sets the number of rows in the animation position look-up table. More points will 52 | // make an animation smoother, but will take more space in memory 53 | globals.group_lut_num_points = 100; 54 | globals.road_width = 8.0; 55 | } 56 | 57 | fn tests(keyboard_input: Res>, mut _bezier_curves: ResMut>) { 58 | if keyboard_input.just_pressed(KeyCode::V) { 59 | println!("test: {:?}", 123); 60 | } 61 | } 62 | 63 | #[derive(Component)] 64 | pub struct Cam { 65 | pub speed: f32, 66 | pub key_left: KeyCode, 67 | pub key_right: KeyCode, 68 | pub key_up: KeyCode, 69 | pub key_down: KeyCode, 70 | pub enabled: bool, 71 | } 72 | impl Default for Cam { 73 | fn default() -> Self { 74 | Self { 75 | speed: 3.0, 76 | key_up: KeyCode::W, 77 | key_down: KeyCode::S, 78 | key_left: KeyCode::A, 79 | key_right: KeyCode::D, 80 | enabled: true, 81 | } 82 | } 83 | } 84 | 85 | pub struct CamPlugin; 86 | 87 | impl Plugin for CamPlugin { 88 | fn build(&self, app: &mut App) { 89 | app.add_system(camera_movevement_system); 90 | // .add_system(zoom_camera.system()); 91 | } 92 | } 93 | 94 | pub fn movement_axis(input: &Res>, plus: KeyCode, minus: KeyCode) -> f32 { 95 | let mut axis = 0.0; 96 | if input.pressed(plus) && !input.pressed(KeyCode::LControl) && !input.pressed(KeyCode::LShift) { 97 | axis += 1.0; 98 | } 99 | if input.pressed(minus) && !input.pressed(KeyCode::LControl) && !input.pressed(KeyCode::LShift) 100 | { 101 | axis -= 1.0; 102 | } 103 | return axis; 104 | } 105 | 106 | pub fn camera_movevement_system( 107 | keyboard_input: Res>, 108 | // mut query: Query<(&Cam, &mut Transform)>, 109 | mut transforms: ParamSet<( 110 | Query<(&Cam, &mut Transform)>, 111 | Query<(&mut UiBoard, &mut Transform)>, 112 | )>, 113 | // mouse_button_input: Res>, 114 | // mut query_ui: Query<&mut Transform, With>, 115 | ) { 116 | let mut cam_query = transforms.p0(); 117 | let mut velocity = Vec3::ZERO; 118 | let mut do_move_cam = false; 119 | for (cam, mut transform) in cam_query.iter_mut() { 120 | let (axis_side, axis_up) = if cam.enabled { 121 | ( 122 | movement_axis(&keyboard_input, cam.key_right, cam.key_left), 123 | movement_axis(&keyboard_input, cam.key_up, cam.key_down), 124 | ) 125 | } else { 126 | (0.0, 0.0) 127 | }; 128 | 129 | if axis_side.abs() > 0.0000001 || axis_up.abs() > 0.0000001 { 130 | do_move_cam = true; 131 | } 132 | 133 | velocity = Vec3::new(axis_side * cam.speed, axis_up * cam.speed, 0.0); 134 | 135 | transform.translation += velocity; 136 | } 137 | for (mut ui_board, mut ui_transform) in transforms.p1().iter_mut() { 138 | ui_transform.translation += velocity; 139 | if do_move_cam { 140 | ui_board.previous_position = ui_transform.translation.truncate(); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/complex_test1.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | // cargo run --release --features bevy/dynamic --example delete_test 8 | // cargo run --release --features bevy/dynamic --example latch_test 9 | // cargo run --release --features bevy/dynamic --example latch_then_delete_test 10 | // cargo run --release --features bevy/dynamic --example move_test 11 | // cargo run --release --features bevy/dynamic --example redo_delete_latched_test 12 | // cargo run --release --features bevy/dynamic --example redo_delete_test 13 | // cargo run --release --features bevy/dynamic --example redo_latch_test 14 | // cargo run --release --features bevy/dynamic --example redo_move_test 15 | // cargo run --release --features bevy/dynamic --example redo_unlatch_test 16 | // cargo run --release --features bevy/dynamic --example undo_delete_latched_test 17 | // cargo run --release --features bevy/dynamic --example undo_delete_test 18 | // cargo run --release --features bevy/dynamic --example undo_latch_test 19 | // cargo run --release --features bevy/dynamic --example undo_latch_then_move_test 20 | // cargo run --release --features bevy/dynamic --example undo_move_test 21 | // cargo run --release --features bevy/dynamic --example undo_unlatch_test 22 | // cargo run --release --features bevy/dynamic --example unlatch_test 23 | 24 | fn main() { 25 | let mut app = App::new(); 26 | app.insert_resource(BezierTestHashed(HashMap::new())) 27 | .add_plugins(DefaultPlugins) 28 | .add_plugin(BevyPenToolPlugin) 29 | .add_system(update_bez); 30 | 31 | // Run systems once 32 | app.update(); 33 | 34 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 35 | 36 | let positions1 = BezierPositions::ZERO; 37 | let positions2 = BezierPositions::ZERO; 38 | 39 | let id1 = pen_commands.spawn(positions1); 40 | let id2 = pen_commands.spawn(positions2); 41 | 42 | // the app needs some time to perform the tasks, 43 | // since they are event and asset based 44 | app.update(); 45 | app.update(); 46 | app.update(); 47 | 48 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 49 | 50 | let latch1 = CurveIdEdge { 51 | id: id1, 52 | anchor_edge: AnchorEdge::Start, 53 | }; 54 | let latch2 = CurveIdEdge { 55 | id: id2, 56 | anchor_edge: AnchorEdge::Start, 57 | }; 58 | 59 | pen_commands.latch(latch1, latch2); 60 | 61 | pen_commands.delete(id1); 62 | 63 | app.update(); 64 | app.update(); 65 | app.update(); 66 | app.update(); 67 | app.update(); 68 | app.update(); 69 | app.update(); 70 | app.update(); 71 | 72 | let bezier_curves = app.world.resource::(); 73 | 74 | let bezier = bezier_curves.0.get(&id2).unwrap(); 75 | assert_eq!(bezier.latches, HashMap::new()); 76 | // for id in maps.bezier_map.keys() { 77 | // let bezier = bezier_curves.0.get(&id).unwrap(); 78 | // assert_eq!(bezier.latches, HashMap::new()); 79 | // } 80 | println!("complex_test1 passed"); 81 | } 82 | 83 | pub struct BezierTestHashed(pub HashMap); 84 | 85 | pub fn update_bez( 86 | bezier_curves: Res>, 87 | mut bezier_curves_test: ResMut, 88 | ) { 89 | // if bezier_curves.is_changed() { 90 | for (handle_id, bez) in bezier_curves.iter() { 91 | let id = BezierId(handle_id); 92 | bezier_curves_test.0.insert(id, bez.clone()); 93 | } 94 | // } 95 | } 96 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/delete_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | fn main() { 8 | let mut app = App::new(); 9 | app.insert_resource(BezierTestHashed(HashMap::new())) 10 | .add_plugins(DefaultPlugins) 11 | .add_plugin(BevyPenToolPlugin) 12 | .add_system(update_bez); 13 | 14 | app.update(); 15 | 16 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 17 | let positions1 = BezierPositions::ZERO; 18 | let id1 = pen_commands.spawn(positions1); 19 | 20 | app.update(); 21 | app.update(); 22 | app.update(); 23 | 24 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 25 | pen_commands.delete(id1); 26 | 27 | // it takes six frames for the deletion to be processed. 28 | // multiple events are involved 29 | app.update(); 30 | app.update(); 31 | app.update(); 32 | app.update(); 33 | app.update(); 34 | app.update(); 35 | 36 | let bezier_curves = app.world.resource::(); 37 | 38 | assert!(bezier_curves.0.is_empty()); 39 | println!("delete_test passed"); 40 | } 41 | 42 | pub struct BezierTestHashed(pub HashMap); 43 | 44 | pub fn update_bez( 45 | bezier_curves: Res>, 46 | mut bezier_curves_test: ResMut, 47 | ) { 48 | bezier_curves_test.0 = HashMap::new(); 49 | info!("update_bez: {}", bezier_curves.iter().count()); 50 | for (handle_id, bez) in bezier_curves.iter() { 51 | let id = BezierId(handle_id); 52 | bezier_curves_test.0.insert(id, bez.clone()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/latch_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | pub struct TargetLatches(pub HashMap); 8 | 9 | fn main() { 10 | let mut app = App::new(); 11 | app.insert_resource(BezierTestHashed(HashMap::new())) 12 | .insert_resource(TargetLatches(HashMap::new())) 13 | .add_plugins(DefaultPlugins) 14 | .add_plugin(BevyPenToolPlugin) 15 | .add_system(update_bez); 16 | 17 | // Add Score resource 18 | 19 | // Run systems once 20 | app.update(); 21 | 22 | // // TODO: here, we have to create related systems that will do the logic PenCommands, 23 | // // but we can enter the actual values here inside the #[test] 24 | 25 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 26 | // initiate a BezierPositions 27 | let positions1 = BezierPositions::ZERO; 28 | let positions2 = BezierPositions::ZERO; 29 | 30 | let id1 = pen_commands.spawn(positions1); 31 | let id2 = pen_commands.spawn(positions2); 32 | 33 | // the app needs some time to perform the tasks, 34 | // since they are event and asset based 35 | app.update(); 36 | app.update(); 37 | app.update(); 38 | 39 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 40 | 41 | let latch1 = CurveIdEdge { 42 | id: id1, 43 | anchor_edge: AnchorEdge::Start, 44 | }; 45 | let latch2 = CurveIdEdge { 46 | id: id2, 47 | anchor_edge: AnchorEdge::Start, 48 | }; 49 | 50 | pen_commands.latch(latch1, latch2); 51 | 52 | let mut target_latches = app.world.get_resource_mut::().unwrap(); 53 | 54 | target_latches.0.insert(latch1, latch2); 55 | 56 | // pen_commands.unlatch( 57 | // CurveIdEdge { 58 | // id: id1, 59 | // anchor_edge: AnchorEdge::Start, 60 | // }, 61 | // CurveIdEdge { 62 | // id: id2, 63 | // anchor_edge: AnchorEdge::Start, 64 | // }, 65 | // ); 66 | 67 | app.update(); 68 | app.update(); 69 | app.update(); 70 | 71 | // let maps = app.world.resource::(); 72 | let bezier_curves = app.world.resource::(); 73 | let target_latches = app.world.resource::(); 74 | 75 | // pub latches: HashMap, 76 | for ( 77 | CurveIdEdge { 78 | id: id1, 79 | anchor_edge: anchor_edge1, 80 | }, 81 | target_latch, 82 | ) in target_latches.0.iter() 83 | { 84 | // let entity_handle1 = maps.bezier_map.get(&id1).unwrap(); 85 | let bezier = bezier_curves.0.get(&id1).unwrap(); 86 | let latch_data1 = bezier.latches.get(&anchor_edge1).unwrap(); 87 | 88 | let actual_latch = CurveIdEdge { 89 | id: latch_data1.latched_to_id, 90 | anchor_edge: latch_data1.partners_edge, 91 | }; 92 | 93 | // let bezier_state = BezierState::from(bezier); 94 | assert_eq!(&actual_latch, target_latch); 95 | } 96 | println!("latch_test passed"); 97 | } 98 | 99 | pub struct BezierTestHashed(pub HashMap); 100 | 101 | pub fn update_bez( 102 | bezier_curves: Res>, 103 | mut bezier_curves_test: ResMut, 104 | ) { 105 | // if bezier_curves.is_changed() { 106 | for (handle_id, bez) in bezier_curves.iter() { 107 | let id = BezierId(handle_id); 108 | bezier_curves_test.0.insert(id, bez.clone()); 109 | } 110 | // } 111 | } 112 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/latch_then_delete_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | fn main() { 8 | let mut app = App::new(); 9 | app.insert_resource(BezierTestHashed(HashMap::new())) 10 | .add_plugins(DefaultPlugins) 11 | .add_plugin(BevyPenToolPlugin) 12 | .add_system(update_bez); 13 | 14 | app.update(); 15 | 16 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 17 | 18 | let positions1 = BezierPositions::ZERO; 19 | let positions2 = BezierPositions::ZERO; 20 | 21 | let id1 = pen_commands.spawn(positions1); 22 | let id2 = pen_commands.spawn(positions2); 23 | 24 | // the app needs some time to perform the tasks, 25 | // since they are event and asset based 26 | app.update(); 27 | app.update(); 28 | app.update(); 29 | app.update(); 30 | app.update(); 31 | app.update(); 32 | 33 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 34 | 35 | let latch1 = CurveIdEdge { 36 | id: id1, 37 | anchor_edge: AnchorEdge::Start, 38 | }; 39 | let latch2 = CurveIdEdge { 40 | id: id2, 41 | anchor_edge: AnchorEdge::Start, 42 | }; 43 | 44 | pen_commands.latch(latch1, latch2); 45 | 46 | app.update(); 47 | app.update(); 48 | app.update(); 49 | 50 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 51 | 52 | pen_commands.delete(id1); 53 | 54 | app.update(); 55 | app.update(); 56 | app.update(); 57 | app.update(); 58 | app.update(); 59 | app.update(); 60 | 61 | let bezier_curves = app.world.resource::(); 62 | 63 | let bezier = bezier_curves.0.get(&id2).unwrap(); 64 | 65 | // latch is cleared after partner is deleted 66 | assert_eq!(bezier.latches, HashMap::new()); 67 | 68 | // the bezier curve is deleted from the Assets 69 | assert!(bezier_curves.0.iter().count() == 1); 70 | 71 | println!("latch_then_delete_test passed"); 72 | } 73 | 74 | pub struct BezierTestHashed(pub HashMap); 75 | 76 | pub fn update_bez( 77 | bezier_curves: Res>, 78 | mut bezier_curves_test: ResMut, 79 | ) { 80 | bezier_curves_test.0.clear(); 81 | for (handle_id, bez) in bezier_curves.iter() { 82 | let id = BezierId(handle_id); 83 | bezier_curves_test.0.insert(id, bez.clone()); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/move_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | #[derive(Default, PartialEq)] 8 | // pub(crate) struct TestState(Vec); 9 | 10 | // #[derive(Default, PartialEq)] 11 | // pub(crate) struct BezierState { 12 | // pub positions: BezierPositions, 13 | // pub previous_positions: BezierPositions, 14 | // pub id: BezierId, 15 | // pub latches: HashMap, 16 | // pub potential_latch: Option, 17 | // pub group: Option, 18 | // } 19 | 20 | // impl From<&Bezier> for BezierState { 21 | // fn from(bezier: &Bezier) -> Self { 22 | // Self { 23 | // positions: bezier.positions, 24 | // previous_positions: bezier.previous_positions, 25 | // id: bezier.id, 26 | // latches: bezier.latches.clone(), 27 | // potential_latch: bezier.potential_latch.clone(), 28 | // group: bezier.group, 29 | // } 30 | // } 31 | // } 32 | 33 | pub struct TargetPositions(pub HashMap); 34 | fn main() { 35 | let mut app = App::new(); 36 | app.insert_resource(BezierTestHashed(HashMap::new())) 37 | .add_plugins(DefaultPlugins) 38 | .add_plugin(BevyPenToolPlugin) 39 | .insert_resource(TargetPositions(HashMap::new())) 40 | .add_system(update_bez); 41 | 42 | // Add Score resource 43 | 44 | // Run systems once 45 | app.update(); 46 | 47 | // // TODO: here, we have to create related systems that will do the logic PenCommands, 48 | // // but we can enter the actual values here inside the #[test] 49 | 50 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 51 | // initiate a BezierPositions 52 | let mut positions1 = BezierPositions { 53 | start: Vec2::new(200., -100.), 54 | end: Vec2::new(100., 100.), 55 | control_start: Vec2::new(0., 100.), 56 | control_end: Vec2::new(100., 100.), 57 | }; 58 | 59 | let id1 = pen_commands.spawn(positions1); 60 | 61 | let positions2 = BezierPositions { 62 | start: Vec2::ZERO, 63 | end: Vec2::new(-100., -100.), 64 | control_start: Vec2::new(0., -100.), 65 | control_end: Vec2::new(100., -200.), 66 | }; 67 | 68 | let id2 = pen_commands.spawn(positions2); 69 | 70 | // the app needs some time to perform the tasks, 71 | // since they are event and asset based 72 | app.update(); 73 | app.update(); 74 | app.update(); 75 | 76 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 77 | pen_commands.move_anchor(id1, Anchor::Start, Vec2::ZERO); 78 | 79 | // pen_commands.latch( 80 | // CurveIdEdge { 81 | // id: id1, 82 | // anchor_edge: AnchorEdge::Start, 83 | // }, 84 | // CurveIdEdge { 85 | // id: id2, 86 | // anchor_edge: AnchorEdge::Start, 87 | // }, 88 | // ); 89 | 90 | // pen_commands.unlatch( 91 | // CurveIdEdge { 92 | // id: id1, 93 | // anchor_edge: AnchorEdge::Start, 94 | // }, 95 | // CurveIdEdge { 96 | // id: id2, 97 | // anchor_edge: AnchorEdge::Start, 98 | // }, 99 | // ); 100 | 101 | let mut target_positions = app.world.get_resource_mut::().unwrap(); 102 | 103 | positions1 = BezierPositions { 104 | start: Vec2::ZERO, 105 | end: Vec2::new(100., 100.), 106 | control_start: Vec2::new(0., 100.) - Vec2::new(200., -100.), // moves with start 107 | control_end: Vec2::new(100., 100.), 108 | }; 109 | 110 | target_positions.0.insert(id1, positions1); 111 | target_positions.0.insert(id2, positions2); 112 | 113 | app.update(); 114 | app.update(); 115 | app.update(); 116 | 117 | let bezier_curves = app.world.resource::(); 118 | let target_positions = app.world.resource::(); 119 | 120 | for (id, target_pos) in target_positions.0.iter() { 121 | let bezier = bezier_curves.0.get(&id).unwrap(); 122 | // let bezier_state = BezierState::from(bezier); 123 | assert_eq!(&bezier.positions, target_pos); 124 | } 125 | println!("move_test passed"); 126 | } 127 | 128 | pub struct BezierTestHashed(pub HashMap); 129 | 130 | pub fn update_bez( 131 | bezier_curves: Res>, 132 | mut bezier_curves_test: ResMut, 133 | ) { 134 | // if bezier_curves.is_changed() { 135 | for (handle_id, bez) in bezier_curves.iter() { 136 | let id = BezierId(handle_id); 137 | bezier_curves_test.0.insert(id, bez.clone()); 138 | } 139 | // } 140 | } 141 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/redo_delete_latched_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | pub struct TargetLatches(pub HashMap); 8 | 9 | fn main() { 10 | let mut app = App::new(); 11 | app.insert_resource(BezierTestHashed(HashMap::new())) 12 | .add_plugins(DefaultPlugins) 13 | .add_plugin(BevyPenToolPlugin) 14 | .add_system(update_bez); 15 | 16 | app.update(); 17 | 18 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 19 | 20 | let positions1 = BezierPositions::ZERO; 21 | let positions2 = BezierPositions::ZERO; 22 | 23 | let id1 = pen_commands.spawn(positions1); 24 | let id2 = pen_commands.spawn(positions2); 25 | 26 | app.update(); 27 | app.update(); 28 | app.update(); 29 | 30 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 31 | 32 | let latch1 = CurveIdEdge { 33 | id: id1, 34 | anchor_edge: AnchorEdge::Start, 35 | }; 36 | let latch2 = CurveIdEdge { 37 | id: id2, 38 | anchor_edge: AnchorEdge::Start, 39 | }; 40 | 41 | pen_commands.latch(latch1, latch2); 42 | 43 | app.update(); 44 | app.update(); 45 | app.update(); 46 | 47 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 48 | pen_commands.delete(id1); 49 | 50 | app.update(); 51 | app.update(); 52 | app.update(); 53 | app.update(); 54 | app.update(); 55 | app.update(); 56 | 57 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 58 | pen_commands.undo(); 59 | 60 | app.update(); 61 | app.update(); 62 | app.update(); 63 | app.update(); 64 | app.update(); 65 | app.update(); 66 | 67 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 68 | pen_commands.redo(); 69 | 70 | app.update(); 71 | app.update(); 72 | app.update(); 73 | app.update(); 74 | app.update(); 75 | app.update(); 76 | 77 | let bezier_curves = app.world.resource::(); 78 | 79 | let bezier = bezier_curves.0.get(&id2).unwrap(); 80 | 81 | assert!(bezier.latches.is_empty()); 82 | 83 | println!("redo_delete_latched_test passed"); 84 | } 85 | 86 | pub struct BezierTestHashed(pub HashMap); 87 | 88 | pub fn update_bez( 89 | bezier_curves: Res>, 90 | mut bezier_curves_test: ResMut, 91 | ) { 92 | // if bezier_curves.is_changed() { 93 | for (handle_id, bez) in bezier_curves.iter() { 94 | let id = BezierId(handle_id); 95 | bezier_curves_test.0.insert(id, bez.clone()); 96 | } 97 | // } 98 | } 99 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/redo_delete_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | fn main() { 8 | let mut app = App::new(); 9 | app.insert_resource(BezierTestHashed(HashMap::new())) 10 | .add_plugins(DefaultPlugins) 11 | .add_plugin(BevyPenToolPlugin) 12 | .add_system(update_bez); 13 | 14 | app.update(); 15 | 16 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 17 | let positions1 = BezierPositions::ZERO; 18 | let id1 = pen_commands.spawn(positions1); 19 | 20 | app.update(); 21 | app.update(); 22 | app.update(); 23 | 24 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 25 | pen_commands.delete(id1); 26 | 27 | // it takes six frames for the deletion to be processed. 28 | // multiple events are involved 29 | app.update(); 30 | app.update(); 31 | app.update(); 32 | app.update(); 33 | app.update(); 34 | app.update(); 35 | 36 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 37 | pen_commands.undo(); 38 | 39 | app.update(); 40 | app.update(); 41 | app.update(); 42 | 43 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 44 | pen_commands.redo(); 45 | 46 | app.update(); 47 | app.update(); 48 | app.update(); 49 | app.update(); 50 | app.update(); 51 | app.update(); 52 | 53 | let bezier_curves = app.world.resource::(); 54 | // let bezier = bezier_curves.0.get(&id1).unwrap(); 55 | 56 | assert!(bezier_curves.0.is_empty()); 57 | println!("redo_delete_test passed"); 58 | } 59 | 60 | pub struct BezierTestHashed(pub HashMap); 61 | 62 | pub fn update_bez( 63 | bezier_curves: Res>, 64 | mut bezier_curves_test: ResMut, 65 | ) { 66 | bezier_curves_test.0 = HashMap::new(); 67 | info!("update_bez: {}", bezier_curves.iter().count()); 68 | for (handle_id, bez) in bezier_curves.iter() { 69 | let id = BezierId(handle_id); 70 | bezier_curves_test.0.insert(id, bez.clone()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/redo_latch_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | pub struct TargetLatches(pub HashMap); 8 | 9 | fn main() { 10 | let mut app = App::new(); 11 | app.insert_resource(BezierTestHashed(HashMap::new())) 12 | .insert_resource(TargetLatches(HashMap::new())) 13 | .add_plugins(DefaultPlugins) 14 | .add_plugin(BevyPenToolPlugin) 15 | .add_system(update_bez); 16 | 17 | app.update(); 18 | 19 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 20 | 21 | let positions1 = BezierPositions::ZERO; 22 | let positions2 = BezierPositions::ZERO; 23 | 24 | let id1 = pen_commands.spawn(positions1); 25 | let id2 = pen_commands.spawn(positions2); 26 | 27 | app.update(); 28 | app.update(); 29 | app.update(); 30 | 31 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 32 | 33 | let latch1 = CurveIdEdge { 34 | id: id1, 35 | anchor_edge: AnchorEdge::Start, 36 | }; 37 | let latch2 = CurveIdEdge { 38 | id: id2, 39 | anchor_edge: AnchorEdge::Start, 40 | }; 41 | 42 | pen_commands.latch(latch1, latch2); 43 | 44 | let mut target_latches = app.world.get_resource_mut::().unwrap(); 45 | 46 | target_latches.0.insert(latch1, latch2); 47 | 48 | app.update(); 49 | app.update(); 50 | app.update(); 51 | 52 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 53 | pen_commands.undo(); 54 | 55 | app.update(); 56 | app.update(); 57 | app.update(); 58 | 59 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 60 | pen_commands.redo(); 61 | 62 | app.update(); 63 | app.update(); 64 | app.update(); 65 | app.update(); 66 | app.update(); 67 | app.update(); 68 | 69 | let bezier_curves = app.world.resource::(); 70 | let target_latches = app.world.resource::(); 71 | 72 | // pub latches: HashMap, 73 | for ( 74 | CurveIdEdge { 75 | id: id1, 76 | anchor_edge: anchor_edge1, 77 | }, 78 | target_latch, 79 | ) in target_latches.0.iter() 80 | { 81 | // let entity_handle1 = maps.bezier_map.get(&id1).unwrap(); 82 | let bezier = bezier_curves.0.get(&id1).unwrap(); 83 | let latch_data1 = bezier.latches.get(&anchor_edge1).unwrap(); 84 | 85 | let actual_latch = CurveIdEdge { 86 | id: latch_data1.latched_to_id, 87 | anchor_edge: latch_data1.partners_edge, 88 | }; 89 | 90 | // let bezier_state = BezierState::from(bezier); 91 | assert_eq!(&actual_latch, target_latch); 92 | } 93 | 94 | println!("redo_latch_test passed"); 95 | } 96 | 97 | pub struct BezierTestHashed(pub HashMap); 98 | 99 | pub fn update_bez( 100 | bezier_curves: Res>, 101 | mut bezier_curves_test: ResMut, 102 | ) { 103 | // if bezier_curves.is_changed() { 104 | for (handle_id, bez) in bezier_curves.iter() { 105 | let id = BezierId(handle_id); 106 | bezier_curves_test.0.insert(id, bez.clone()); 107 | } 108 | // } 109 | } 110 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/redo_move_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | fn main() { 8 | let mut app = App::new(); 9 | app.insert_resource(BezierTestHashed(HashMap::new())) 10 | .add_plugins(DefaultPlugins) 11 | .add_plugin(BevyPenToolPlugin) 12 | .add_system(update_bez); 13 | 14 | app.update(); 15 | 16 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 17 | 18 | let positions1 = BezierPositions::ZERO; 19 | let positions2 = BezierPositions::ZERO; 20 | 21 | let id1 = pen_commands.spawn(positions1); 22 | let id2 = pen_commands.spawn(positions2); 23 | 24 | // the app needs some time to perform the tasks, 25 | // since they are event and asset based 26 | app.update(); 27 | app.update(); 28 | app.update(); 29 | app.update(); 30 | app.update(); 31 | app.update(); 32 | 33 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 34 | 35 | let pos1 = Vec2::new(200., -100.); 36 | pen_commands.move_anchor(id1, Anchor::Start, pos1); 37 | 38 | app.update(); 39 | app.update(); 40 | app.update(); 41 | 42 | let bezier_curves = app.world.resource::(); 43 | let bezier = bezier_curves.0.get(&id1).unwrap(); 44 | assert_eq!(bezier.positions.start, pos1); 45 | 46 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 47 | pen_commands.undo(); 48 | 49 | app.update(); 50 | app.update(); 51 | app.update(); 52 | 53 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 54 | pen_commands.redo(); 55 | 56 | app.update(); 57 | app.update(); 58 | app.update(); 59 | app.update(); 60 | app.update(); 61 | app.update(); 62 | 63 | let bezier_curves = app.world.resource::(); 64 | let bezier = bezier_curves.0.get(&id2).unwrap(); 65 | 66 | assert_eq!(bezier.positions.start, pos1); 67 | 68 | println!("redo_move_test passed"); 69 | } 70 | 71 | pub struct BezierTestHashed(pub HashMap); 72 | 73 | pub fn update_bez( 74 | bezier_curves: Res>, 75 | mut bezier_curves_test: ResMut, 76 | ) { 77 | bezier_curves_test.0.clear(); 78 | for (handle_id, bez) in bezier_curves.iter() { 79 | let id = BezierId(handle_id); 80 | bezier_curves_test.0.insert(id, bez.clone()); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/redo_unlatch_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | pub struct TargetLatches(pub HashMap); 8 | 9 | fn main() { 10 | let mut app = App::new(); 11 | app.insert_resource(BezierTestHashed(HashMap::new())) 12 | .insert_resource(TargetLatches(HashMap::new())) 13 | .add_plugins(DefaultPlugins) 14 | .add_plugin(BevyPenToolPlugin) 15 | .add_system(update_bez); 16 | 17 | // Run systems once 18 | app.update(); 19 | 20 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 21 | 22 | let positions1 = BezierPositions::ZERO; 23 | let positions2 = BezierPositions::ZERO; 24 | 25 | let id1 = pen_commands.spawn(positions1); 26 | let id2 = pen_commands.spawn(positions2); 27 | 28 | // the app needs some time to perform the tasks, 29 | // since they are event and asset based 30 | app.update(); 31 | app.update(); 32 | app.update(); 33 | 34 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 35 | 36 | let latch1 = CurveIdEdge { 37 | id: id1, 38 | anchor_edge: AnchorEdge::Start, 39 | }; 40 | let latch2 = CurveIdEdge { 41 | id: id2, 42 | anchor_edge: AnchorEdge::Start, 43 | }; 44 | 45 | pen_commands.latch(latch1, latch2); 46 | 47 | // let mut target_latches = app.world.get_resource_mut::().unwrap(); 48 | 49 | // target_latches.0.insert(latch1, latch2); 50 | 51 | app.update(); 52 | app.update(); 53 | app.update(); 54 | 55 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 56 | pen_commands.unlatch( 57 | CurveIdEdge { 58 | id: id1, 59 | anchor_edge: AnchorEdge::Start, 60 | }, 61 | CurveIdEdge { 62 | id: id2, 63 | anchor_edge: AnchorEdge::Start, 64 | }, 65 | ); 66 | 67 | app.update(); 68 | app.update(); 69 | app.update(); 70 | 71 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 72 | pen_commands.undo(); 73 | 74 | app.update(); 75 | app.update(); 76 | app.update(); 77 | 78 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 79 | pen_commands.redo(); 80 | 81 | app.update(); 82 | app.update(); 83 | app.update(); 84 | 85 | // let maps = app.world.resource::(); 86 | let bezier_curves = app.world.resource::(); 87 | let bezier1 = bezier_curves.0.get(&id1).unwrap(); 88 | let bezier2 = bezier_curves.0.get(&id2).unwrap(); 89 | 90 | assert!(bezier1.latches.is_empty()); 91 | assert!(bezier2.latches.is_empty()); 92 | 93 | println!("redo_unlatch_test passed"); 94 | } 95 | 96 | pub struct BezierTestHashed(pub HashMap); 97 | 98 | pub fn update_bez( 99 | bezier_curves: Res>, 100 | mut bezier_curves_test: ResMut, 101 | ) { 102 | // if bezier_curves.is_changed() { 103 | for (handle_id, bez) in bezier_curves.iter() { 104 | let id = BezierId(handle_id); 105 | bezier_curves_test.0.insert(id, bez.clone()); 106 | } 107 | // } 108 | } 109 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/undo_delete_latched_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | pub struct TargetLatches(pub HashMap); 8 | 9 | fn main() { 10 | let mut app = App::new(); 11 | app.insert_resource(BezierTestHashed(HashMap::new())) 12 | .insert_resource(TargetLatches(HashMap::new())) 13 | .add_plugins(DefaultPlugins) 14 | .add_plugin(BevyPenToolPlugin) 15 | .add_system(update_bez); 16 | 17 | app.update(); 18 | 19 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 20 | 21 | let positions1 = BezierPositions::ZERO; 22 | let positions2 = BezierPositions::ZERO; 23 | 24 | let id1 = pen_commands.spawn(positions1); 25 | let id2 = pen_commands.spawn(positions2); 26 | 27 | app.update(); 28 | app.update(); 29 | app.update(); 30 | 31 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 32 | 33 | let latch1 = CurveIdEdge { 34 | id: id1, 35 | anchor_edge: AnchorEdge::Start, 36 | }; 37 | let latch2 = CurveIdEdge { 38 | id: id2, 39 | anchor_edge: AnchorEdge::Start, 40 | }; 41 | 42 | pen_commands.latch(latch1, latch2); 43 | 44 | let mut target_latches = app.world.get_resource_mut::().unwrap(); 45 | 46 | target_latches.0.insert(latch1, latch2); 47 | 48 | app.update(); 49 | app.update(); 50 | app.update(); 51 | 52 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 53 | pen_commands.delete(id1); 54 | 55 | app.update(); 56 | app.update(); 57 | app.update(); 58 | app.update(); 59 | app.update(); 60 | app.update(); 61 | 62 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 63 | pen_commands.undo(); 64 | 65 | app.update(); 66 | app.update(); 67 | app.update(); 68 | app.update(); 69 | app.update(); 70 | app.update(); 71 | 72 | let bezier_curves = app.world.resource::(); 73 | let target_latches = app.world.resource::(); 74 | 75 | // pub latches: HashMap, 76 | for ( 77 | CurveIdEdge { 78 | id: id1, 79 | anchor_edge: anchor_edge1, 80 | }, 81 | target_latch, 82 | ) in target_latches.0.iter() 83 | { 84 | // let entity_handle1 = maps.bezier_map.get(&id1).unwrap(); 85 | let bezier = bezier_curves.0.get(&id1).unwrap(); 86 | let latch_data1 = bezier.latches.get(&anchor_edge1).unwrap(); 87 | 88 | let actual_latch = CurveIdEdge { 89 | id: latch_data1.latched_to_id, 90 | anchor_edge: latch_data1.partners_edge, 91 | }; 92 | 93 | // let bezier_state = BezierState::from(bezier); 94 | assert_eq!(&actual_latch, target_latch); 95 | } 96 | 97 | println!("undo_delete_latched_test passed"); 98 | } 99 | 100 | pub struct BezierTestHashed(pub HashMap); 101 | 102 | pub fn update_bez( 103 | bezier_curves: Res>, 104 | mut bezier_curves_test: ResMut, 105 | ) { 106 | // if bezier_curves.is_changed() { 107 | for (handle_id, bez) in bezier_curves.iter() { 108 | let id = BezierId(handle_id); 109 | bezier_curves_test.0.insert(id, bez.clone()); 110 | } 111 | // } 112 | } 113 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/undo_delete_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | fn main() { 8 | let mut app = App::new(); 9 | app.insert_resource(BezierTestHashed(HashMap::new())) 10 | .add_plugins(DefaultPlugins) 11 | .add_plugin(BevyPenToolPlugin) 12 | .add_system(update_bez); 13 | 14 | app.update(); 15 | 16 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 17 | let positions1 = BezierPositions::ZERO; 18 | let id1 = pen_commands.spawn(positions1); 19 | 20 | app.update(); 21 | app.update(); 22 | app.update(); 23 | 24 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 25 | pen_commands.delete(id1); 26 | 27 | // it takes around six frames for the deletion to be processed. 28 | // multiple events are involved 29 | app.update(); 30 | app.update(); 31 | app.update(); 32 | app.update(); 33 | app.update(); 34 | app.update(); 35 | 36 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 37 | pen_commands.undo(); 38 | 39 | app.update(); 40 | app.update(); 41 | app.update(); 42 | 43 | let bezier_curves = app.world.resource::(); 44 | let bezier = bezier_curves.0.get(&id1).unwrap(); 45 | 46 | assert_eq!(bezier.id, id1); 47 | println!("undo_delete_test passed"); 48 | } 49 | 50 | pub struct BezierTestHashed(pub HashMap); 51 | 52 | pub fn update_bez( 53 | bezier_curves: Res>, 54 | mut bezier_curves_test: ResMut, 55 | ) { 56 | bezier_curves_test.0 = HashMap::new(); 57 | info!("update_bez: {}", bezier_curves.iter().count()); 58 | for (handle_id, bez) in bezier_curves.iter() { 59 | let id = BezierId(handle_id); 60 | bezier_curves_test.0.insert(id, bez.clone()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/undo_latch_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | pub struct TargetLatches(pub HashMap); 8 | 9 | fn main() { 10 | let mut app = App::new(); 11 | app.insert_resource(BezierTestHashed(HashMap::new())) 12 | .insert_resource(TargetLatches(HashMap::new())) 13 | .add_plugins(DefaultPlugins) 14 | .add_plugin(BevyPenToolPlugin) 15 | .add_system(update_bez); 16 | 17 | app.update(); 18 | 19 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 20 | 21 | let positions1 = BezierPositions::ZERO; 22 | let positions2 = BezierPositions::ZERO; 23 | 24 | let id1 = pen_commands.spawn(positions1); 25 | let id2 = pen_commands.spawn(positions2); 26 | 27 | app.update(); 28 | app.update(); 29 | app.update(); 30 | 31 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 32 | 33 | let latch1 = CurveIdEdge { 34 | id: id1, 35 | anchor_edge: AnchorEdge::Start, 36 | }; 37 | let latch2 = CurveIdEdge { 38 | id: id2, 39 | anchor_edge: AnchorEdge::Start, 40 | }; 41 | 42 | pen_commands.latch(latch1, latch2); 43 | 44 | app.update(); 45 | app.update(); 46 | app.update(); 47 | 48 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 49 | pen_commands.undo(); 50 | 51 | app.update(); 52 | app.update(); 53 | app.update(); 54 | 55 | let bezier_curves = app.world.resource::(); 56 | 57 | for (_id, bezier) in bezier_curves.0.iter() { 58 | assert!(bezier.latches.is_empty()); 59 | } 60 | println!("undo_latch_test passed"); 61 | } 62 | 63 | pub struct BezierTestHashed(pub HashMap); 64 | 65 | pub fn update_bez( 66 | bezier_curves: Res>, 67 | mut bezier_curves_test: ResMut, 68 | ) { 69 | // if bezier_curves.is_changed() { 70 | for (handle_id, bez) in bezier_curves.iter() { 71 | let id = BezierId(handle_id); 72 | bezier_curves_test.0.insert(id, bez.clone()); 73 | } 74 | // } 75 | } 76 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/undo_latch_then_move_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | pub struct TargetLatches(pub HashMap); 8 | 9 | fn main() { 10 | let mut app = App::new(); 11 | app.insert_resource(BezierTestHashed(HashMap::new())) 12 | .insert_resource(TargetLatches(HashMap::new())) 13 | .add_plugins(DefaultPlugins) 14 | .add_plugin(BevyPenToolPlugin) 15 | .add_system(update_bez); 16 | 17 | app.update(); 18 | 19 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 20 | 21 | let positions1 = BezierPositions::ZERO; 22 | let positions2 = BezierPositions::ZERO; 23 | 24 | let id1 = pen_commands.spawn(positions1); 25 | let id2 = pen_commands.spawn(positions2); 26 | 27 | app.update(); 28 | app.update(); 29 | app.update(); 30 | 31 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 32 | 33 | let latch1 = CurveIdEdge { 34 | id: id1, 35 | anchor_edge: AnchorEdge::Start, 36 | }; 37 | let latch2 = CurveIdEdge { 38 | id: id2, 39 | anchor_edge: AnchorEdge::Start, 40 | }; 41 | 42 | pen_commands.latch(latch1, latch2); 43 | 44 | app.update(); 45 | app.update(); 46 | app.update(); 47 | 48 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 49 | pen_commands.undo(); 50 | 51 | app.update(); 52 | app.update(); 53 | app.update(); 54 | app.update(); 55 | app.update(); 56 | app.update(); 57 | 58 | let bezier_curves = app.world.resource::(); 59 | 60 | for (_id, bezier) in bezier_curves.0.iter() { 61 | assert!(bezier.latches.is_empty()); 62 | } 63 | 64 | app.update(); 65 | app.update(); 66 | app.update(); 67 | 68 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 69 | pen_commands.move_anchor(id2, Anchor::Start, Vec2::new(-100., -100.)); 70 | pen_commands.move_anchor(id1, Anchor::Start, Vec2::new(100., 100.)); 71 | 72 | let bezier_curves = app.world.resource::(); 73 | for (_id, bezier) in bezier_curves.0.iter() { 74 | assert!(bezier.latches.is_empty()); 75 | } 76 | 77 | println!("undo_latch_then_move_test passed!"); 78 | } 79 | 80 | pub struct BezierTestHashed(pub HashMap); 81 | 82 | pub fn update_bez( 83 | bezier_curves: Res>, 84 | mut bezier_curves_test: ResMut, 85 | ) { 86 | // if bezier_curves.is_changed() { 87 | for (handle_id, bez) in bezier_curves.iter() { 88 | let id = BezierId(handle_id); 89 | bezier_curves_test.0.insert(id, bez.clone()); 90 | } 91 | // } 92 | } 93 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/undo_move_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | fn main() { 8 | let mut app = App::new(); 9 | app.insert_resource(BezierTestHashed(HashMap::new())) 10 | .add_plugins(DefaultPlugins) 11 | .add_plugin(BevyPenToolPlugin) 12 | .add_system(update_bez); 13 | 14 | app.update(); 15 | 16 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 17 | 18 | let positions1 = BezierPositions::ZERO; 19 | let positions2 = BezierPositions::ZERO; 20 | 21 | let id1 = pen_commands.spawn(positions1); 22 | let id2 = pen_commands.spawn(positions2); 23 | 24 | // the app needs some time to perform the tasks, 25 | // since they are event and asset based 26 | app.update(); 27 | app.update(); 28 | app.update(); 29 | app.update(); 30 | app.update(); 31 | app.update(); 32 | 33 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 34 | 35 | let pos1 = Vec2::new(200., -100.); 36 | pen_commands.move_anchor(id1, Anchor::Start, pos1); 37 | 38 | app.update(); 39 | app.update(); 40 | app.update(); 41 | 42 | let bezier_curves = app.world.resource::(); 43 | let bezier = bezier_curves.0.get(&id1).unwrap(); 44 | assert_eq!(bezier.positions.start, pos1); 45 | 46 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 47 | pen_commands.undo(); 48 | 49 | app.update(); 50 | app.update(); 51 | app.update(); 52 | 53 | let bezier_curves = app.world.resource::(); 54 | let bezier = bezier_curves.0.get(&id2).unwrap(); 55 | 56 | assert_eq!(bezier.positions.start, Vec2::ZERO); 57 | 58 | println!("undo_move_test passed"); 59 | } 60 | 61 | pub struct BezierTestHashed(pub HashMap); 62 | 63 | pub fn update_bez( 64 | bezier_curves: Res>, 65 | mut bezier_curves_test: ResMut, 66 | ) { 67 | bezier_curves_test.0.clear(); 68 | for (handle_id, bez) in bezier_curves.iter() { 69 | let id = BezierId(handle_id); 70 | bezier_curves_test.0.insert(id, bez.clone()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/undo_unlatch_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | pub struct TargetLatches(pub HashMap); 8 | 9 | fn main() { 10 | let mut app = App::new(); 11 | app.insert_resource(BezierTestHashed(HashMap::new())) 12 | .insert_resource(TargetLatches(HashMap::new())) 13 | .add_plugins(DefaultPlugins) 14 | .add_plugin(BevyPenToolPlugin) 15 | .add_system(update_bez); 16 | 17 | // Run systems once 18 | app.update(); 19 | 20 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 21 | 22 | let positions1 = BezierPositions::ZERO; 23 | let positions2 = BezierPositions::ZERO; 24 | 25 | let id1 = pen_commands.spawn(positions1); 26 | let id2 = pen_commands.spawn(positions2); 27 | 28 | // the app needs some time to perform the tasks, 29 | // since they are event and asset based 30 | app.update(); 31 | app.update(); 32 | app.update(); 33 | 34 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 35 | 36 | let latch1 = CurveIdEdge { 37 | id: id1, 38 | anchor_edge: AnchorEdge::Start, 39 | }; 40 | let latch2 = CurveIdEdge { 41 | id: id2, 42 | anchor_edge: AnchorEdge::Start, 43 | }; 44 | 45 | pen_commands.latch(latch1, latch2); 46 | 47 | // let mut target_latches = app.world.get_resource_mut::().unwrap(); 48 | 49 | // target_latches.0.insert(latch1, latch2); 50 | 51 | app.update(); 52 | app.update(); 53 | app.update(); 54 | 55 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 56 | pen_commands.unlatch( 57 | CurveIdEdge { 58 | id: id1, 59 | anchor_edge: AnchorEdge::Start, 60 | }, 61 | CurveIdEdge { 62 | id: id2, 63 | anchor_edge: AnchorEdge::Start, 64 | }, 65 | ); 66 | 67 | app.update(); 68 | app.update(); 69 | app.update(); 70 | 71 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 72 | pen_commands.undo(); 73 | 74 | app.update(); 75 | app.update(); 76 | app.update(); 77 | 78 | // let maps = app.world.resource::(); 79 | let bezier_curves = app.world.resource::(); 80 | let bezier1 = bezier_curves.0.get(&id1).unwrap(); 81 | let bezier2 = bezier_curves.0.get(&id2).unwrap(); 82 | 83 | let expected_latch_data1 = LatchData { 84 | latched_to_id: id2, 85 | partners_edge: AnchorEdge::Start, 86 | self_edge: AnchorEdge::Start, 87 | }; 88 | let expected_latch_data2 = LatchData { 89 | latched_to_id: id1, 90 | partners_edge: AnchorEdge::Start, 91 | self_edge: AnchorEdge::Start, 92 | }; 93 | 94 | assert_eq!(bezier1.latches[&AnchorEdge::Start], expected_latch_data1); 95 | assert_eq!(bezier2.latches[&AnchorEdge::Start], expected_latch_data2); 96 | 97 | println!("undo_unlatch_test passed"); 98 | } 99 | 100 | pub struct BezierTestHashed(pub HashMap); 101 | 102 | pub fn update_bez( 103 | bezier_curves: Res>, 104 | mut bezier_curves_test: ResMut, 105 | ) { 106 | // if bezier_curves.is_changed() { 107 | for (handle_id, bez) in bezier_curves.iter() { 108 | let id = BezierId(handle_id); 109 | bezier_curves_test.0.insert(id, bez.clone()); 110 | } 111 | // } 112 | } 113 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/examples/unlatch_test.rs: -------------------------------------------------------------------------------- 1 | use bevy_pen_tool_model::model::*; 2 | use bevy_pen_tool_plugin::{pen::*, BevyPenToolPlugin, Bezier}; 3 | 4 | use bevy::prelude::*; 5 | use std::collections::HashMap; 6 | 7 | fn main() { 8 | let mut app = App::new(); 9 | app.insert_resource(BezierTestHashed(HashMap::new())) 10 | .add_plugins(DefaultPlugins) 11 | .add_plugin(BevyPenToolPlugin) 12 | .add_system(update_bez); 13 | 14 | // Run systems once 15 | app.update(); 16 | 17 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 18 | 19 | let positions1 = BezierPositions::ZERO; 20 | let positions2 = BezierPositions::ZERO; 21 | 22 | let id1 = pen_commands.spawn(positions1); 23 | let id2 = pen_commands.spawn(positions2); 24 | 25 | // the app needs some time to perform the tasks, 26 | // since they are event and asset based 27 | app.update(); 28 | app.update(); 29 | app.update(); 30 | 31 | let mut pen_commands = app.world.get_resource_mut::().unwrap(); 32 | 33 | let latch1 = CurveIdEdge { 34 | id: id1, 35 | anchor_edge: AnchorEdge::Start, 36 | }; 37 | let latch2 = CurveIdEdge { 38 | id: id2, 39 | anchor_edge: AnchorEdge::Start, 40 | }; 41 | 42 | pen_commands.latch(latch1, latch2); 43 | 44 | pen_commands.unlatch( 45 | CurveIdEdge { 46 | id: id1, 47 | anchor_edge: AnchorEdge::Start, 48 | }, 49 | CurveIdEdge { 50 | id: id2, 51 | anchor_edge: AnchorEdge::Start, 52 | }, 53 | ); 54 | 55 | app.update(); 56 | app.update(); 57 | app.update(); 58 | 59 | let maps = app.world.resource::(); 60 | let bezier_curves = app.world.resource::(); 61 | 62 | for id in maps.bezier_map.keys() { 63 | let bezier = bezier_curves.0.get(&id).unwrap(); 64 | assert_eq!(bezier.latches, HashMap::new()); 65 | } 66 | println!("unlatch_test passed"); 67 | } 68 | 69 | pub struct BezierTestHashed(pub HashMap); 70 | 71 | pub fn update_bez( 72 | bezier_curves: Res>, 73 | mut bezier_curves_test: ResMut, 74 | ) { 75 | // if bezier_curves.is_changed() { 76 | for (handle_id, bez) in bezier_curves.iter() { 77 | let id = BezierId(handle_id); 78 | bezier_curves_test.0.insert(id, bez.clone()); 79 | } 80 | // } 81 | } 82 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/saved/look_up_tables/my_group1.lut: -------------------------------------------------------------------------------- 1 | { 2 | "path_length": 572.8567, 3 | "lut": [ 4 | [ 5 | -51.486256, 6 | -128.86377 7 | ], 8 | [ 9 | -48.163536, 10 | -124.20693 11 | ], 12 | [ 13 | -45.41073, 14 | -119.18625 15 | ], 16 | [ 17 | -43.030228, 18 | -113.97663 19 | ], 20 | [ 21 | -40.909645, 22 | -108.655045 23 | ], 24 | [ 25 | -38.97991, 26 | -103.26091 27 | ], 28 | [ 29 | -37.19549, 30 | -97.81678 31 | ], 32 | [ 33 | -35.524593, 34 | -92.33666 35 | ], 36 | [ 37 | -33.943943, 38 | -86.82981 39 | ], 40 | [ 41 | -32.43583, 42 | -81.30267 43 | ], 44 | [ 45 | -30.986307, 46 | -75.759926 47 | ], 48 | [ 49 | -29.58405, 50 | -70.2051 51 | ], 52 | [ 53 | -28.219597, 54 | -64.64095 55 | ], 56 | [ 57 | -26.884893, 58 | -59.069942 59 | ], 60 | [ 61 | -25.572765, 62 | -53.49383 63 | ], 64 | [ 65 | -24.27666, 66 | -47.913815 67 | ], 68 | [ 69 | -22.990591, 70 | -42.33136 71 | ], 72 | [ 73 | -21.708614, 74 | -36.746815 75 | ], 76 | [ 77 | -20.42556, 78 | -31.163322 79 | ], 80 | [ 81 | -19.13566, 82 | -25.581614 83 | ], 84 | [ 85 | -17.833052, 86 | -20.002876 87 | ], 88 | [ 89 | -16.511564, 90 | -14.428636 91 | ], 92 | [ 93 | -15.164467, 94 | -8.860625 95 | ], 96 | [ 97 | -13.784232, 98 | -3.3008854 99 | ], 100 | [ 101 | -12.362214, 102 | 2.2481015 103 | ], 104 | [ 105 | -10.888222, 106 | 7.783206 107 | ], 108 | [ 109 | -9.349522, 110 | 13.301705 111 | ], 112 | [ 113 | -7.73075, 114 | 18.797764 115 | ], 116 | [ 117 | -6.012042, 118 | 24.263548 119 | ], 120 | [ 121 | -4.166724, 122 | 29.688053 123 | ], 124 | [ 125 | -2.1575909, 126 | 35.054188 127 | ], 128 | [ 129 | 0.069998875, 130 | 40.33347 131 | ], 132 | [ 133 | 2.6015453, 134 | 45.47372 135 | ], 136 | [ 137 | 5.5813518, 138 | 50.36619 139 | ], 140 | [ 141 | 11.21359, 142 | 55.95841 143 | ], 144 | [ 145 | 16.779678, 146 | 55.811657 147 | ], 148 | [ 149 | 21.641697, 150 | 52.798298 151 | ], 152 | [ 153 | 25.76078, 154 | 48.818237 155 | ], 156 | [ 157 | 29.430595, 158 | 44.410473 159 | ], 160 | [ 161 | 32.790985, 162 | 39.772987 163 | ], 164 | [ 165 | 35.933075, 166 | 34.977318 167 | ], 168 | [ 169 | 38.899242, 170 | 30.078978 171 | ], 172 | [ 173 | 41.72856, 174 | 25.093521 175 | ], 176 | [ 177 | 44.437412, 178 | 20.048384 179 | ], 180 | [ 181 | 47.04715, 182 | 14.945268 183 | ], 184 | [ 185 | 49.564762, 186 | 9.80186 187 | ], 188 | [ 189 | 52.0035, 190 | 4.6154304 191 | ], 192 | [ 193 | 54.36631, 194 | -0.6011989 195 | ], 196 | [ 197 | 56.66186, 198 | -5.85202 199 | ], 200 | [ 201 | 58.8912, 202 | -11.127454 203 | ], 204 | [ 205 | 61.059875, 206 | -16.431177 207 | ], 208 | [ 209 | 63.168217, 210 | -21.756775 211 | ], 212 | [ 213 | 65.21919, 214 | -27.10639 215 | ], 216 | [ 217 | 67.212845, 218 | -32.476635 219 | ], 220 | [ 221 | 69.15007, 222 | -37.86798 223 | ], 224 | [ 225 | 71.03046, 226 | -43.279125 227 | ], 228 | [ 229 | 72.85339, 230 | -48.709854 231 | ], 232 | [ 233 | 74.617805, 234 | -54.16048 235 | ], 236 | [ 237 | 76.32141, 238 | -59.629642 239 | ], 240 | [ 241 | 77.96214, 242 | -65.11893 243 | ], 244 | [ 245 | 79.53612, 246 | -70.62678 247 | ], 248 | [ 249 | 81.03952, 250 | -76.155266 251 | ], 252 | [ 253 | 82.46641, 254 | -81.70321 255 | ], 256 | [ 257 | 83.81011, 258 | -87.27252 259 | ], 260 | [ 261 | 85.06147, 262 | -92.86306 263 | ], 264 | [ 265 | 86.20888, 266 | -98.47574 267 | ], 268 | [ 269 | 87.23718, 270 | -104.11231 271 | ], 272 | [ 273 | 88.1253, 274 | -109.771095 275 | ], 276 | [ 277 | 88.845, 278 | -115.45669 279 | ], 280 | [ 281 | 89.353615, 282 | -121.16068 283 | ], 284 | [ 285 | 89.58765, 286 | -126.88945 287 | ], 288 | [ 289 | 89.440575, 290 | -132.61069 291 | ], 292 | [ 293 | 88.71667, 294 | -138.30246 295 | ], 296 | [ 297 | 87.02489, 298 | -143.75058 299 | ], 300 | [ 301 | 82.5027, 302 | -149.16069 303 | ], 304 | [ 305 | 77.504814, 306 | -151.92642 307 | ], 308 | [ 309 | 72.01564, 310 | -153.53526 311 | ], 312 | [ 313 | 66.34059, 314 | -154.28934 315 | ], 316 | [ 317 | 60.615513, 318 | -154.4445 319 | ], 320 | [ 321 | 54.893547, 322 | -154.17772 323 | ], 324 | [ 325 | 49.193314, 326 | -153.60796 327 | ], 328 | [ 329 | 43.519306, 330 | -152.81729 331 | ], 332 | [ 333 | 37.87015, 334 | -151.86475 335 | ], 336 | [ 337 | 32.24206, 338 | -150.79474 339 | ], 340 | [ 341 | 26.630295, 342 | -149.64246 343 | ], 344 | [ 345 | 21.029758, 346 | -148.43718 347 | ], 348 | [ 349 | 15.435279, 350 | -147.2047 351 | ], 352 | [ 353 | 9.8408375, 354 | -145.96883 355 | ], 356 | [ 357 | 4.2424626, 358 | -144.7536 359 | ], 360 | [ 361 | -1.3656616, 362 | -143.58379 363 | ], 364 | [ 365 | -6.988588, 366 | -142.48709 367 | ], 368 | [ 369 | -12.631094, 370 | -141.49606 371 | ], 372 | [ 373 | -18.297224, 374 | -140.65091 375 | ], 376 | [ 377 | -23.989206, 378 | -140.0039 379 | ], 380 | [ 381 | -29.704992, 382 | -139.626 383 | ], 384 | [ 385 | -35.43247, 386 | -139.61786 387 | ], 388 | [ 389 | -41.135674, 390 | -140.1265 391 | ], 392 | [ 393 | -46.7222, 394 | -141.36626 395 | ], 396 | [ 397 | -51.976448, 398 | -143.61778 399 | ], 400 | [ 401 | -56.47668, 402 | -147.09529 403 | ] 404 | ] 405 | } -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/saved/my_mesh0.meta: -------------------------------------------------------------------------------- 1 | { 2 | "center_of_mass": [ 3 | 169.96753, 4 | -100.139465 5 | ], 6 | "position": [ 7 | 169.96753, 8 | -100.139465 9 | ], 10 | "bounding_box": [ 11 | [ 12 | -269.45856, 13 | -155.62021 14 | ], 15 | [ 16 | 258.25967, 17 | 217.88959 18 | ] 19 | ], 20 | "color": [ 21 | 0.93333334, 22 | 0.8901961, 23 | 0.90588236, 24 | 1.0 25 | ] 26 | } -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/saved/my_mesh0.obj: -------------------------------------------------------------------------------- 1 | o My_mesh 2 | v 208.991455 -155.620209 0.000000 3 | v 194.396057 -154.421600 0.000000 4 | v 179.905640 -152.238098 0.000000 5 | v 165.497070 -149.556610 0.000000 6 | v 226.428864 -149.287064 0.000000 7 | v 151.148621 -146.566589 0.000000 8 | v 136.845551 -143.364838 0.000000 9 | v 122.577728 -140.008759 0.000000 10 | v 233.852417 -136.631195 0.000000 11 | v 108.337860 -136.535843 0.000000 12 | v 94.120392 -132.972305 0.000000 13 | v 79.920990 -129.337524 0.000000 14 | v 65.736206 -125.646408 0.000000 15 | v 239.827942 -123.258408 0.000000 16 | v 51.563141 -121.910919 0.000000 17 | v 37.399323 -118.140961 0.000000 18 | v 23.242599 -114.345016 0.000000 19 | v 9.091019 -110.530579 0.000000 20 | v 244.848389 -109.493210 0.000000 21 | v -5.057190 -106.704514 0.000000 22 | v -19.203735 -102.873230 0.000000 23 | v -33.350327 -99.042984 0.000000 24 | v 249.047455 -95.453735 0.000000 25 | v -47.499207 -95.219879 0.000000 26 | v -61.652031 -91.410400 0.000000 27 | v -75.810593 -87.621460 0.000000 28 | v -89.976860 -83.860718 0.000000 29 | v 252.469788 -81.204300 0.000000 30 | v -104.153023 -80.136795 0.000000 31 | v -118.341599 -76.459839 0.000000 32 | v -132.545532 -72.842133 0.000000 33 | v -146.768387 -69.299042 0.000000 34 | v 255.121887 -66.791397 0.000000 35 | v -161.014587 -65.850555 0.000000 36 | v -175.289795 -62.523819 0.000000 37 | v -189.601578 -59.357773 0.000000 38 | v -203.960358 -56.412262 0.000000 39 | v -218.381195 -53.788727 0.000000 40 | v -261.406128 -53.584808 0.000000 41 | v -266.268860 -53.159637 0.000000 42 | v 256.989777 -52.256027 0.000000 43 | v -232.886108 -51.687180 0.000000 44 | v -247.501587 -50.629761 0.000000 45 | v -269.333679 -38.923279 0.000000 46 | v 258.046997 -37.639481 0.000000 47 | v -269.458557 -24.273933 0.000000 48 | v 258.259674 -22.986519 0.000000 49 | v -268.382782 -9.658340 0.000000 50 | v 257.590271 -8.347618 0.000000 51 | v -266.452667 4.869141 0.000000 52 | v 256.001068 6.219810 0.000000 53 | v -263.801788 19.282639 0.000000 54 | v 253.457947 20.650955 0.000000 55 | v -260.490326 33.558922 0.000000 56 | v 249.934479 34.874229 0.000000 57 | v -256.544373 47.672993 0.000000 58 | v 245.415558 48.812992 0.000000 59 | v -251.970917 61.596340 0.000000 60 | v 239.901031 62.388557 0.000000 61 | v -246.765198 75.295753 0.000000 62 | v 233.407684 75.524117 0.000000 63 | v 225.969910 88.149124 0.000000 64 | v -240.914856 88.732361 0.000000 65 | v 217.638306 100.203377 0.000000 66 | v -234.402649 101.860764 0.000000 67 | v 208.476807 111.640144 0.000000 68 | v -227.209045 114.628235 0.000000 69 | v 198.558441 122.427750 0.000000 70 | v -219.314438 126.974220 0.000000 71 | v 187.960846 132.549637 0.000000 72 | v -210.701996 138.830170 0.000000 73 | v 176.762268 142.003036 0.000000 74 | v -201.360550 150.120178 0.000000 75 | v 165.038605 150.796417 0.000000 76 | v 152.861481 158.946930 0.000000 77 | v -191.288086 160.762543 0.000000 78 | v 140.292755 166.480316 0.000000 79 | v -180.494949 170.672668 0.000000 80 | v 127.389130 173.425140 0.000000 81 | v -169.006683 179.767288 0.000000 82 | v 114.200134 179.812225 0.000000 83 | v 100.768768 185.673279 0.000000 84 | v -156.865692 187.969742 0.000000 85 | v 87.131989 191.039841 0.000000 86 | v -144.130966 195.215851 0.000000 87 | v 73.321365 195.942505 0.000000 88 | v 59.363815 200.410522 0.000000 89 | v -130.875748 201.459137 0.000000 90 | v 45.282242 204.471558 0.000000 91 | v -117.183197 206.674301 0.000000 92 | v 27.481293 208.989014 0.000000 93 | v -103.140968 210.858521 0.000000 94 | v 13.143356 212.022949 0.000000 95 | v -88.835579 214.030029 0.000000 96 | v -1.303375 214.486176 0.000000 97 | v -74.347717 216.224823 0.000000 98 | v -15.842621 216.324432 0.000000 99 | v -30.451752 217.479385 0.000000 100 | v -59.749023 217.492096 0.000000 101 | v -45.100403 217.889587 0.000000 102 | vn 0.000000 0.000000 1.000000 103 | f 100/100/1 99/99/1 98/98/1 104 | f 99/99/1 42/42/1 98/98/1 105 | f 98/98/1 42/42/1 41/41/1 106 | f 74/74/1 87/87/1 41/41/1 107 | f 74/74/1 41/41/1 59/59/1 108 | f 87/87/1 95/95/1 41/41/1 109 | f 87/87/1 74/74/1 81/81/1 110 | f 74/74/1 59/59/1 66/66/1 111 | f 59/59/1 41/41/1 51/51/1 112 | f 95/95/1 98/98/1 41/41/1 113 | f 95/95/1 87/87/1 91/91/1 114 | f 87/87/1 81/81/1 84/84/1 115 | f 81/81/1 74/74/1 77/77/1 116 | f 74/74/1 66/66/1 70/70/1 117 | f 66/66/1 59/59/1 62/62/1 118 | f 59/59/1 51/51/1 55/55/1 119 | f 51/51/1 41/41/1 47/47/1 120 | f 98/98/1 95/95/1 97/97/1 121 | f 95/95/1 91/91/1 93/93/1 122 | f 91/91/1 87/87/1 89/89/1 123 | f 87/87/1 84/84/1 86/86/1 124 | f 84/84/1 81/81/1 82/82/1 125 | f 81/81/1 77/77/1 79/79/1 126 | f 77/77/1 74/74/1 75/75/1 127 | f 74/74/1 70/70/1 72/72/1 128 | f 70/70/1 66/66/1 68/68/1 129 | f 66/66/1 62/62/1 64/64/1 130 | f 62/62/1 59/59/1 61/61/1 131 | f 59/59/1 55/55/1 57/57/1 132 | f 55/55/1 51/51/1 53/53/1 133 | f 51/51/1 47/47/1 49/49/1 134 | f 47/47/1 41/41/1 45/45/1 135 | f 92/92/1 73/73/1 42/42/1 136 | f 73/73/1 56/56/1 42/42/1 137 | f 92/92/1 83/83/1 73/73/1 138 | f 73/73/1 65/65/1 56/56/1 139 | f 56/56/1 48/48/1 42/42/1 140 | f 96/96/1 92/92/1 42/42/1 141 | f 92/92/1 88/88/1 83/83/1 142 | f 83/83/1 78/78/1 73/73/1 143 | f 73/73/1 69/69/1 65/65/1 144 | f 65/65/1 60/60/1 56/56/1 145 | f 56/56/1 52/52/1 48/48/1 146 | f 48/48/1 44/44/1 42/42/1 147 | f 99/99/1 96/96/1 42/42/1 148 | f 96/96/1 94/94/1 92/92/1 149 | f 92/92/1 90/90/1 88/88/1 150 | f 88/88/1 85/85/1 83/83/1 151 | f 83/83/1 80/80/1 78/78/1 152 | f 78/78/1 76/76/1 73/73/1 153 | f 73/73/1 71/71/1 69/69/1 154 | f 69/69/1 67/67/1 65/65/1 155 | f 65/65/1 63/63/1 60/60/1 156 | f 60/60/1 58/58/1 56/56/1 157 | f 56/56/1 54/54/1 52/52/1 158 | f 52/52/1 50/50/1 48/48/1 159 | f 48/48/1 46/46/1 44/44/1 160 | f 44/44/1 43/43/1 42/42/1 161 | f 42/42/1 38/38/1 41/41/1 162 | f 41/41/1 38/38/1 33/33/1 163 | f 38/38/1 37/37/1 33/33/1 164 | f 37/37/1 36/36/1 33/33/1 165 | f 36/36/1 35/35/1 33/33/1 166 | f 35/35/1 34/34/1 33/33/1 167 | f 34/34/1 32/32/1 33/33/1 168 | f 33/33/1 32/32/1 28/28/1 169 | f 32/32/1 31/31/1 28/28/1 170 | f 31/31/1 30/30/1 28/28/1 171 | f 30/30/1 29/29/1 28/28/1 172 | f 29/29/1 27/27/1 28/28/1 173 | f 28/28/1 27/27/1 23/23/1 174 | f 27/27/1 26/26/1 23/23/1 175 | f 26/26/1 25/25/1 23/23/1 176 | f 25/25/1 24/24/1 23/23/1 177 | f 24/24/1 22/22/1 23/23/1 178 | f 23/23/1 22/22/1 19/19/1 179 | f 22/22/1 21/21/1 19/19/1 180 | f 21/21/1 6/6/1 19/19/1 181 | f 21/21/1 16/16/1 6/6/1 182 | f 16/16/1 11/11/1 6/6/1 183 | f 21/21/1 18/18/1 16/16/1 184 | f 16/16/1 13/13/1 11/11/1 185 | f 11/11/1 8/8/1 6/6/1 186 | f 21/21/1 20/20/1 18/18/1 187 | f 18/18/1 17/17/1 16/16/1 188 | f 16/16/1 15/15/1 13/13/1 189 | f 13/13/1 12/12/1 11/11/1 190 | f 11/11/1 10/10/1 8/8/1 191 | f 8/8/1 7/7/1 6/6/1 192 | f 19/19/1 6/6/1 5/5/1 193 | f 14/14/1 19/19/1 5/5/1 194 | f 14/14/1 5/5/1 9/9/1 195 | f 6/6/1 4/4/1 5/5/1 196 | f 5/5/1 4/4/1 1/1/1 197 | f 4/4/1 3/3/1 1/1/1 198 | f 3/3/1 2/2/1 1/1/1 199 | f 44/44/1 40/40/1 43/43/1 200 | f 43/43/1 40/40/1 39/39/1 201 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod actions; 2 | pub mod io; 3 | pub mod moves; 4 | pub mod pen; 5 | pub mod plugin; 6 | pub mod undo; 7 | 8 | pub use actions::*; 9 | pub use bevy_pen_tool_model::*; 10 | pub use io::*; 11 | pub use moves::*; 12 | pub use pen::*; 13 | pub use plugin::*; 14 | pub use undo::*; 15 | -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/src/plugin.rs:120:10: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/src/plugin.rs:120:10 -------------------------------------------------------------------------------- /crates/bevy_pen_tool_plugin/src/plugin.rs:153:5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliotbo/bevy_pen_tool/f8ff007d0d046421f03f202ec8156d53c53982aa/crates/bevy_pen_tool_plugin/src/plugin.rs:153:5 -------------------------------------------------------------------------------- /examples/simple_animation.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::*, render::camera::OrthographicProjection}; 2 | 3 | use serde::Deserialize; 4 | use std::io::Read; 5 | 6 | // 7 | // 8 | // 9 | // This example shows how to load a look-up table created with bevy_pen_tool 10 | // and how to run the corresponding animation totally independently of bevy_pen_tool 11 | // 12 | // 13 | // 14 | 15 | // data structure for the look-up table that will be deserialized (read from disk) 16 | #[derive(Deserialize)] 17 | struct Lut { 18 | path_length: f32, 19 | lut: Vec, 20 | } 21 | 22 | impl Lut { 23 | // loads a look-up table that was saved in assets/lut using bevy_pen_tool 24 | fn load() -> Lut { 25 | let lut_path = "saved/look_up_tables/my_group0.lut"; 26 | let mut file = std::fs::File::open(lut_path).unwrap(); 27 | let mut contents = String::new(); 28 | file.read_to_string(&mut contents).unwrap(); 29 | let loaded_lut: Lut = serde_json::from_str(&contents).unwrap(); 30 | return loaded_lut; 31 | } 32 | } 33 | 34 | fn main() { 35 | App::new() 36 | .add_plugins(DefaultPlugins) 37 | // 38 | // insert the look-up table as a resource. 39 | .insert_resource(Lut::load()) 40 | .add_startup_system(camera_setup) 41 | .add_startup_system(spawn_quad) 42 | .add_system(follow_path) 43 | .run(); 44 | } 45 | 46 | fn camera_setup(mut commands: Commands) { 47 | // 48 | // bevy_pen_tool is not compatible with Perspective Cameras 49 | commands.spawn_bundle(Camera2dBundle { 50 | transform: Transform::from_translation(Vec3::new(00.0, 0.0, 10.0)) 51 | .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y), 52 | projection: OrthographicProjection { 53 | scale: 0.19, 54 | far: 100000.0, 55 | near: -100000.0, 56 | ..Default::default() 57 | }, 58 | ..Default::default() 59 | }); 60 | } 61 | 62 | #[derive(Component)] 63 | struct Animation; 64 | 65 | fn spawn_quad(mut commands: Commands, mut materials: ResMut>, lut: Res) { 66 | // spawn sprite that will be animated 67 | commands 68 | .spawn_bundle(SpriteBundle { 69 | // material: materials.add(Color::rgb(0.5, 0.5, 1.0).into()), 70 | transform: Transform::from_xyz(0.0, -0.0, 0.0), 71 | sprite: Sprite { 72 | color: Color::BLACK, 73 | custom_size: Some(Vec2::new(10.0, 10.0)), 74 | ..Default::default() 75 | }, 76 | 77 | ..Default::default() 78 | }) 79 | // needed so that follow_path() can query the Sprite and animate it 80 | .insert(Animation); 81 | 82 | // show points from look-up table 83 | for position in lut.lut.iter() { 84 | commands.spawn_bundle(SpriteBundle { 85 | // material: materials.add(Color::rgb(0.7, 0.5, 1.0).into()), 86 | transform: Transform::from_translation(position.extend(-50.0)), 87 | // sprite: Sprite::new(Vec2::new(1.0, 1.0)), 88 | sprite: Sprite { 89 | color: Color::GREEN, 90 | custom_size: Some(Vec2::new(1.0, 1.0)), 91 | ..Default::default() 92 | }, 93 | 94 | ..Default::default() 95 | }); 96 | } 97 | } 98 | 99 | fn compute_position_with_lut(t: f32, lut: &Lut) -> Vec2 { 100 | let lut = lut.lut.clone(); 101 | 102 | // indexing 103 | let idx_f64 = t * (lut.len() - 1) as f32; 104 | let p1 = lut[(idx_f64 as usize)]; 105 | let p2 = lut[idx_f64 as usize + 1]; 106 | let rem = idx_f64 % 1.0; 107 | 108 | // interpolation 109 | let position = p1 + rem * (p2 - p1); //interpolate_vec2(p1, p2, rem); 110 | return position; 111 | } 112 | 113 | fn follow_path(mut query: Query<(&mut Transform, &Animation)>, time: Res