├── .cargo └── config.toml ├── .github ├── FUNDING.yml └── workflows │ ├── book.yml │ ├── publish.yml │ └── test.yml ├── .gitignore ├── .vscode └── settings.json ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── crates ├── forky_bevy │ ├── Cargo.toml │ └── src │ │ ├── extensions │ │ ├── app.rs │ │ ├── app_res.rs │ │ ├── global_transform.rs │ │ ├── map.rs │ │ ├── mod.rs │ │ ├── pose.rs │ │ ├── quat.rs │ │ ├── transform_x.rs │ │ └── vec3.rs │ │ ├── lib.rs │ │ └── systems │ │ ├── exit_system.rs │ │ └── mod.rs ├── forky_cli │ ├── Cargo.toml │ ├── README.md │ ├── examples │ │ ├── cli.rs │ │ └── swap_mouse.rs │ └── src │ │ ├── common │ │ ├── auto_mod.rs │ │ ├── for_each_directory.rs │ │ ├── forky_cli.rs │ │ ├── mod.rs │ │ └── watch.rs │ │ ├── key │ │ ├── auto_key_command.rs │ │ ├── input_command.rs │ │ ├── input_sequence.rs │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── main.rs │ │ ├── server │ │ ├── _self_signed_certs │ │ │ ├── cert.pem │ │ │ ├── key.pem │ │ │ └── mod.rs │ │ ├── address.rs │ │ ├── mod.rs │ │ ├── proxy.rs │ │ ├── serve.rs │ │ └── tls.rs │ │ ├── style │ │ ├── cli_all.rs │ │ ├── command_all.rs │ │ ├── command_file.rs │ │ ├── index_files.rs │ │ ├── lightning.rs │ │ ├── mod.rs │ │ ├── style_command.rs │ │ └── type_files.rs │ │ └── utils │ │ ├── mod.rs │ │ └── path_buf.rs ├── forky_core │ ├── Cargo.toml │ └── src │ │ ├── extensions │ │ ├── duration.rs │ │ ├── mod.rs │ │ ├── option.rs │ │ ├── path_buf_ext.rs │ │ ├── path_ext.rs │ │ ├── result_x.rs │ │ ├── str_x.rs │ │ ├── string.rs │ │ └── vec.rs │ │ ├── forky_event │ │ ├── forky_event.rs │ │ └── mod.rs │ │ ├── graph │ │ ├── mod.rs │ │ └── node.rs │ │ ├── lib.rs │ │ ├── math │ │ ├── constants.rs │ │ └── mod.rs │ │ ├── math_f64 │ │ ├── constants.rs │ │ ├── funcs.rs │ │ └── mod.rs │ │ ├── style │ │ └── mod.rs │ │ └── utils │ │ ├── async_utils.rs │ │ ├── mod.rs │ │ └── random.rs ├── forky_esp │ ├── Cargo.toml │ └── src │ │ ├── __extensions │ │ ├── mod.rs │ │ └── rgb.rs │ │ ├── _core │ │ ├── _esp_device.rs │ │ ├── _led_controller_rgb.rs │ │ ├── _led_controller_rgbw.rs │ │ ├── _logger.rs │ │ ├── _smart_leds_adapter_rgbw.rs │ │ ├── _timer.rs │ │ └── mod.rs │ │ ├── entry │ │ ├── device.rs │ │ ├── hello_led.rs │ │ ├── hello_led_strip.rs │ │ ├── hello_world.rs │ │ └── mod.rs │ │ ├── lib.rs │ │ └── main.rs ├── forky_fs │ ├── Cargo.toml │ ├── src │ │ ├── cli │ │ │ ├── fs_watcher.rs │ │ │ ├── mod.rs │ │ │ └── subcommand.rs │ │ ├── fs │ │ │ ├── fs_async_utils.rs │ │ │ ├── fs_error.rs │ │ │ ├── fs_ext.rs │ │ │ ├── mod.rs │ │ │ ├── read_dir.rs │ │ │ └── read_file.rs │ │ ├── lib.rs │ │ └── utility │ │ │ ├── cli_args │ │ │ ├── misc.rs │ │ │ └── mod.rs │ │ │ ├── command.rs │ │ │ ├── mod.rs │ │ │ ├── process │ │ │ ├── child_x.rs │ │ │ └── mod.rs │ │ │ └── terminal │ │ │ ├── misc.rs │ │ │ ├── mod.rs │ │ │ └── redirect_io.rs │ └── test_dir │ │ ├── _ignored_dir │ │ └── mod.rs │ │ ├── _ignored_file.rs │ │ ├── included_dir │ │ └── mod.rs │ │ ├── included_file.rs │ │ └── mod.rs ├── forky_net │ ├── Cargo.toml │ └── src │ │ ├── axum_utils │ │ ├── axum_ext.rs │ │ └── mod.rs │ │ ├── layers │ │ ├── cors.rs │ │ ├── mod.rs │ │ └── no_cache.rs │ │ ├── lib.rs │ │ ├── reqwest_utils │ │ ├── mod.rs │ │ └── reqwest_ext.rs │ │ └── state │ │ ├── api_environment.rs │ │ ├── mod.rs │ │ └── uptime.rs ├── forky_play │ ├── Cargo.toml │ ├── assets │ │ ├── branding │ │ │ ├── icon.png │ │ │ └── icon.svg │ │ ├── fonts │ │ │ ├── FiraMono-LICENSE │ │ │ ├── FiraMono-Medium.ttf │ │ │ └── FiraSans-Bold.ttf │ │ └── shaders │ │ │ ├── custom_material.wgsl │ │ │ ├── noise.wgsl │ │ │ ├── sdf2.wgsl │ │ │ ├── sdf3.wgsl │ │ │ ├── simple.wgsl │ │ │ ├── unlit.wgsl │ │ │ ├── unlit_texture.wgsl │ │ │ ├── utility.wgsl │ │ │ └── uv.wgsl │ ├── docs │ │ ├── Splines.md │ │ └── Tools.md │ ├── examples │ │ ├── bevy_graph.rs │ │ ├── gamai_graph.rs │ │ ├── maze.rs │ │ ├── maze_terminal.rs │ │ ├── mithril.rs │ │ ├── node_set_graph.rs │ │ ├── rotate_cube.rs │ │ ├── shader.rs │ │ ├── shader_unlit.rs │ │ ├── shader_uv.rs │ │ ├── spline_catmull_rom.rs │ │ ├── spline_editor.rs │ │ └── spline_mesh.rs │ ├── src │ │ ├── camera │ │ │ ├── camera_view_toggle.rs │ │ │ ├── fly_camera_bundle.rs │ │ │ ├── fps_camera_bundle.rs │ │ │ ├── mod.rs │ │ │ ├── orbit_camera_bundle.rs │ │ │ ├── orbit_camera_controller.rs │ │ │ ├── orbit_keyboard_controller.rs │ │ │ └── plugin.rs │ │ ├── common │ │ │ ├── id_hashmap.rs │ │ │ └── mod.rs │ │ ├── debug │ │ │ ├── gizmos.rs │ │ │ ├── grid.rs │ │ │ └── mod.rs │ │ ├── extensions │ │ │ ├── material.rs │ │ │ └── mod.rs │ │ ├── geometry__ │ │ │ ├── bezier │ │ │ │ ├── cubic.rs │ │ │ │ ├── linear.rs │ │ │ │ ├── mod.rs │ │ │ │ └── quadratic.rs │ │ │ ├── bezier2 │ │ │ │ ├── cubic.rs │ │ │ │ ├── linear.rs │ │ │ │ ├── mod.rs │ │ │ │ └── quadratic.rs │ │ │ ├── bezier3 │ │ │ │ ├── cubic.rs │ │ │ │ ├── linear.rs │ │ │ │ ├── mod.rs │ │ │ │ └── quadratic.rs │ │ │ └── mod.rs │ │ ├── input │ │ │ ├── keyboard_controller.rs │ │ │ ├── mod.rs │ │ │ ├── mouse_controller.rs │ │ │ ├── plugin.rs │ │ │ └── transform_controller.rs │ │ ├── lib.rs │ │ ├── materials │ │ │ ├── forky_material_plugin.rs │ │ │ ├── forky_shader.rs │ │ │ ├── inline_shaders.rs │ │ │ ├── mod.rs │ │ │ ├── unlit_material.rs │ │ │ ├── unlit_texture_material.rs │ │ │ └── uv_material.rs │ │ ├── mesh_utils │ │ │ ├── mesh_factory.rs │ │ │ └── mod.rs │ │ ├── spline │ │ │ ├── _solvers │ │ │ │ ├── catmull_rom.rs │ │ │ │ └── mod.rs │ │ │ ├── _spline │ │ │ │ ├── cubic_spline.rs │ │ │ │ ├── linear_spline.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── quadratic_spline.rs │ │ │ │ ├── spline.rs │ │ │ │ └── spline_type.rs │ │ │ ├── graph │ │ │ │ ├── mod.rs │ │ │ │ ├── on_node_moved.rs │ │ │ │ ├── spline_edge.rs │ │ │ │ ├── spline_graph.rs │ │ │ │ ├── spline_graph_lookup.rs │ │ │ │ ├── spline_graph_plugin.rs │ │ │ │ ├── spline_node.rs │ │ │ │ └── spline_node_positional.rs │ │ │ ├── mesh │ │ │ │ ├── create_spline_mesh.rs │ │ │ │ ├── edge_loop.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── normals.rs │ │ │ │ ├── triangles.rs │ │ │ │ ├── uvs.rs │ │ │ │ └── vertices.rs │ │ │ ├── mod.rs │ │ │ ├── spline_plugin.rs │ │ │ └── utils │ │ │ │ ├── debug_utils.rs │ │ │ │ └── mod.rs │ │ └── utility │ │ │ ├── keycode.rs │ │ │ ├── mod.rs │ │ │ └── systems.rs │ └── test │ │ ├── extensions │ │ ├── app.rs │ │ ├── mod.rs │ │ └── quat.rs │ │ ├── geometry │ │ ├── bezier.rs │ │ ├── bezier_render.rs │ │ └── mod.rs │ │ ├── maze │ │ ├── ball.rs │ │ ├── depth_first_backtrace.rs │ │ ├── maze_walls.rs │ │ ├── mod.rs │ │ ├── plugin.rs │ │ └── rect_maze.rs │ │ ├── misc │ │ ├── boid.rs │ │ ├── ecs.rs │ │ ├── graphics.rs │ │ ├── kaleid.rs │ │ ├── mod.rs │ │ ├── physics.rs │ │ └── utility.rs │ │ ├── mod.rs │ │ ├── physics │ │ ├── euler_physics.rs │ │ ├── mod.rs │ │ ├── revolute_joint.rs │ │ └── slerp_joint.rs │ │ ├── spline │ │ ├── catmull_rom.rs │ │ ├── ecs_spline_graph.rs │ │ ├── graph.rs │ │ ├── mod.rs │ │ ├── spline.rs │ │ ├── spline_graph.rs │ │ ├── spline_mesh.rs │ │ ├── spline_mesh_render.rs │ │ ├── spline_physics.rs │ │ └── spline_physics_render.rs │ │ └── sweet.rs └── forky_web │ ├── Cargo.toml │ └── src │ ├── dom_utils │ ├── animation_frame.rs │ ├── context_menu.rs │ ├── document_interaction_listener.rs │ ├── file.rs │ ├── forky_style_g.rs │ ├── future_timeout.rs │ ├── history.rs │ ├── html_event_listener.rs │ ├── html_event_waiter.rs │ ├── interval.rs │ ├── lifecycle.rs │ ├── location.rs │ ├── loop_utils.rs │ ├── mod.rs │ ├── poll.rs │ ├── resize_listener.rs │ ├── search_params.rs │ └── utils.rs │ ├── extensions │ ├── array.rs │ ├── closure.rs │ ├── document.rs │ ├── element.rs │ ├── iframe.rs │ ├── mod.rs │ ├── response.rs │ └── result.rs │ ├── lib.rs │ ├── logging │ ├── log_buffer.rs │ ├── log_filter.rs │ ├── mod.rs │ ├── replace_func.rs │ └── set_panic_hook.rs │ └── net │ ├── fetch.rs │ └── mod.rs ├── docs ├── .gitignore ├── book.toml ├── src │ ├── SUMMARY.md │ ├── custom │ │ ├── index.css │ │ └── index.js │ ├── draft │ │ ├── bevy_editor.md │ │ ├── bevy_webxr_plan.md │ │ ├── default_graphs │ │ │ ├── render_graph.dot.svg │ │ │ └── schedule_Main.dot.svg │ │ ├── esp │ │ │ ├── esp32-c3.md │ │ │ ├── general.md │ │ │ ├── leds.md │ │ │ └── wasm.md │ │ ├── notes.md │ │ └── play │ │ │ └── notes.md │ ├── forky_cli │ │ ├── index.md │ │ ├── mod.md │ │ └── watch.md │ ├── index.md │ └── other │ │ └── contributing.md └── theme │ ├── book.js │ ├── css │ ├── chrome.css │ ├── general.css │ ├── print.css │ └── variables.css │ ├── favicon.png │ ├── favicon.svg │ ├── fonts │ ├── OPEN-SANS-LICENSE.txt │ ├── SOURCE-CODE-PRO-LICENSE.txt │ ├── fonts.css │ ├── open-sans-v17-all-charsets-300.woff2 │ ├── open-sans-v17-all-charsets-300italic.woff2 │ ├── open-sans-v17-all-charsets-600.woff2 │ ├── open-sans-v17-all-charsets-600italic.woff2 │ ├── open-sans-v17-all-charsets-700.woff2 │ ├── open-sans-v17-all-charsets-700italic.woff2 │ ├── open-sans-v17-all-charsets-800.woff2 │ ├── open-sans-v17-all-charsets-800italic.woff2 │ ├── open-sans-v17-all-charsets-italic.woff2 │ ├── open-sans-v17-all-charsets-regular.woff2 │ └── source-code-pro-v11-all-charsets-500.woff2 │ ├── head.hbs │ ├── highlight.css │ ├── highlight.js │ └── index.hbs ├── examples └── build.rs ├── html ├── https.config.js └── index.html ├── justfile ├── rustfmt.toml └── src └── lib.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.wasm32-unknown-unknown] 2 | runner = 'sweet test-wasm' 3 | 4 | [env] 5 | SWEET_ROOT = { value = "", relative = true } 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [mrchantey] 2 | -------------------------------------------------------------------------------- /.github/workflows/book.yml: -------------------------------------------------------------------------------- 1 | # Github Setup: 2 | # 1. settings > pages > branch > main/docs 3 | # 2. settings > actions > general > workflow permissions > read and write permissions 4 | name: 🌍 Deploy Book 5 | on: 6 | push: 7 | branches: main 8 | paths: ['docs/**','.github/workflows/book.yml'] 9 | jobs: 10 | deploy: 11 | name: Build and Deploy 12 | runs-on: ubuntu-20.04 13 | concurrency: 14 | group: ${{ github.workflow }}-${{ github.ref }} 15 | steps: 16 | - name: 📂 Checkout 17 | uses: actions/checkout@v4 18 | - name: 📂 Cache 19 | uses: actions/cache@v3 20 | with: 21 | path: | 22 | ~/.cargo/bin/ 23 | ~/.cargo/registry/index/ 24 | ~/.cargo/registry/cache/ 25 | ~/.cargo/git/db/ 26 | target/ 27 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 28 | - name: 🔨 Install mdbook 29 | uses: peaceiris/actions-mdbook@v1 30 | with: 31 | mdbook-version: '0.4.34' 32 | - name: 🔨 Install mdbook-mermaid 33 | uses: baptiste0928/cargo-install@v2 34 | with: 35 | crate: mdbook-mermaid 36 | version: '0.12.6' 37 | - name: 🔨 Build Book 38 | run: mdbook build 39 | working-directory: ./docs 40 | - name: 🌍 Deploy 41 | uses: peaceiris/actions-gh-pages@v3 42 | if: ${{ github.ref == 'refs/heads/main' }} 43 | with: 44 | github_token: ${{ secrets.GITHUB_TOKEN }} 45 | publish_branch: pages 46 | publish_dir: ./docs/book 47 | destination_dir: docs -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # https://pratikpc.medium.com/publishing-crates-using-github-actions-165ee67780e1 2 | name: 🌍 Publish Crates 3 | on: 4 | push: 5 | tags: 'v*.*.never' 6 | workflow_dispatch: 7 | jobs: 8 | publish: 9 | name: Publish 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout sources 13 | uses: actions/checkout@v4 14 | 15 | - name: Install stable toolchain 16 | uses: actions-rs/toolchain@v1 17 | with: 18 | profile: minimal 19 | toolchain: stable 20 | override: true 21 | # - run: cargo publish --token ${CRATES_TOKEN} 22 | # env: 23 | # CRATES_TOKEN: ${{ secrets.CRATES_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # rust 2 | rustc-ice-* 3 | target/ 4 | crates/*/target/ 5 | **/*.rs.bk 6 | html/* 7 | !html/index.html 8 | !html/https.config.js 9 | 10 | # esp idf 11 | .embuild -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // "rust-analyzer.cargo.target": "wasm32-unknown-unknown", 3 | "files.autoSave": "afterDelay", 4 | "files.autoSaveDelay": 1000, 5 | "files.exclude": { 6 | "**/.git": true, 7 | "**/.svn": true, 8 | "**/.hg": true, 9 | "**/CVS": true, 10 | "**/.DS_Store": true, 11 | "**/Thumbs.db": true, 12 | // ".vscode": true, 13 | //optional 14 | "LICENSE": true, 15 | "**/.embuild/": true, 16 | // "**/.cargo/": true, 17 | // "**/Cargo.lock": true, 18 | // "**/mod.rs": true, 19 | // "out/": true, 20 | // "**/target/": true, 21 | "**/sdkconfig.defaults": true, 22 | "**/build.rs": true, 23 | "docs/book/**": true, 24 | "html/assets/**": true 25 | }, 26 | "rust-analyzer.cargo.features": "all", 27 | // "rust-analyzer.cargo.features": [ 28 | // "web_sys_unstable_apis" 29 | // ], 30 | "search.exclude": { 31 | "Cargo.lock": true, 32 | "**/assets/*": true, 33 | "**.svg": true 34 | }, 35 | "rust-analyzer.showUnlinkedFileNotification": false 36 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Peter Hayman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Forky 2 |
3 | 4 |

5 | Rust utilities 6 |

7 | 8 |

9 | Crates.io version 10 | Download 11 | docs.rs docs 12 |

13 | 14 |

15 | Book 16 | | 17 | API Docs 18 | | 19 | Contributing 20 |

21 | 22 | 23 | 24 | made with ❤️‍🔥 by mrchantey 25 |
26 | 27 | ## Contents 28 | - [Forky CLI](./crates/forky_cli/README.md) -------------------------------------------------------------------------------- /crates/forky_bevy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "forky_bevy" 3 | version.workspace = true 4 | edition.workspace = true 5 | authors.workspace = true 6 | documentation.workspace = true 7 | license.workspace = true 8 | readme.workspace = true 9 | description.workspace = true 10 | repository.workspace = true 11 | 12 | [dependencies] 13 | forky_core.workspace = true 14 | bevy.workspace = true 15 | rand.workspace = true 16 | # bevy = { workspace = true, optional = true } 17 | 18 | anyhow.workspace = true 19 | extend.workspace = true 20 | 21 | [target.'cfg(target_arch = "wasm32")'.dependencies] 22 | forky_web.workspace = true 23 | js-sys.workspace = true 24 | # wasm-bindgen = { workspace = true, optional = true } 25 | # wasm-bindgen-futures = { workspace = true, optional = true } 26 | # web-sys = { workspace = true, optional = true } 27 | 28 | 29 | [dev-dependencies] 30 | sweet.workspace = true -------------------------------------------------------------------------------- /crates/forky_bevy/src/extensions/app.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use bevy::prelude::*; 3 | use extend::ext; 4 | use forky_core::utils::RcCell; 5 | 6 | #[ext] 7 | pub impl App { 8 | fn __(&mut self) -> &mut Self { self } 9 | fn with_app_res(self) -> RcCell { AppRes::init(self) } 10 | 11 | #[cfg(target_arch = "wasm32")] 12 | #[must_use] 13 | fn run_on_animation_frame(mut self) -> forky_web::AnimationFrame { 14 | forky_web::AnimationFrame::new(move || { 15 | self.update(); 16 | }) 17 | } 18 | } 19 | 20 | 21 | #[cfg(test)] 22 | mod test { 23 | use crate::prelude::*; 24 | use sweet::prelude::*; 25 | #[test] 26 | pub fn works() { 27 | let app = AppRes::new(); 28 | let app = app.borrow_mut(); 29 | expect(app.world().contains_non_send::()).to_be_true(); 30 | } 31 | } -------------------------------------------------------------------------------- /crates/forky_bevy/src/extensions/app_res.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use extend::ext; 3 | use forky_core::prelude::*; 4 | 5 | #[derive(Deref, DerefMut)] 6 | pub struct AppRes(pub RcCell); 7 | 8 | impl AppRes { 9 | pub fn new() -> RcCell { Self::init(App::new()) } 10 | 11 | 12 | pub fn build(func: impl FnOnce(&mut App)) -> RcCell { 13 | let mut app = App::new(); 14 | func(&mut app); 15 | Self::init(app) 16 | } 17 | 18 | pub fn init(app: App) -> RcCell { 19 | let app = rccell(app); 20 | let app2 = app.clone(); 21 | app.borrow_mut().insert_non_send_resource(AppRes(app2)); 22 | app 23 | } 24 | } 25 | 26 | #[ext] 27 | pub impl RcCell { 28 | #[cfg(target_arch = "wasm32")] 29 | fn run_on_animation_frame(self) -> forky_web::AnimationFrame { 30 | forky_web::AnimationFrame::new(move || { 31 | self.borrow_mut().update(); 32 | }) 33 | } 34 | 35 | #[cfg(target_arch = "wasm32")] 36 | fn run_forever(self) -> impl std::future::Future { 37 | async { 38 | let _frame = self.run_on_animation_frame(); 39 | forky_web::loop_forever().await; 40 | } 41 | } 42 | 43 | #[cfg(target_arch = "wasm32")] 44 | fn run_while_mounted(self) { 45 | todo!("broken in 12.1?"); 46 | // let mut app = self.borrow_mut(); 47 | // app.finish(); 48 | // app.cleanup(); 49 | // drop(app); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /crates/forky_bevy/src/extensions/global_transform.rs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | fn inverse_transform_point(&self,global_pos:Vec3) -> Vec3 { 4 | let inverse_transform_matrix = self.compute_matrix().inverse(); 5 | inverse_transform_matrix.transform_point(global_pos) 6 | } 7 | 8 | */ 9 | -------------------------------------------------------------------------------- /crates/forky_bevy/src/extensions/map.rs: -------------------------------------------------------------------------------- 1 | use bevy::utils::HashMap; 2 | use extend::ext; 3 | use std::hash::Hash; 4 | 5 | #[ext] 6 | pub impl HashMap 7 | where 8 | T1: Hash + PartialEq + Eq + Clone, 9 | T2: Default, 10 | { 11 | fn get_or_default(&mut self, key: T1) -> &T2 { 12 | if self.contains_key(&key) { 13 | return self.get(&key).unwrap(); 14 | } 15 | self.insert(key.clone(), Default::default()); 16 | self.get(&key).unwrap() 17 | } 18 | fn get_or_default_mut(&mut self, key: T1) -> &mut T2 { 19 | if self.contains_key(&key) { 20 | return self.get_mut(&key).unwrap(); 21 | } 22 | self.insert(key.clone(), Default::default()); 23 | self.get_mut(&key).unwrap() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /crates/forky_bevy/src/extensions/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod app; 2 | #[allow(unused_imports)] 3 | pub use self::app::*; 4 | pub mod app_res; 5 | #[allow(unused_imports)] 6 | pub use self::app_res::*; 7 | pub mod global_transform; 8 | #[allow(unused_imports)] 9 | pub use self::global_transform::*; 10 | pub mod map; 11 | #[allow(unused_imports)] 12 | pub use self::map::*; 13 | pub mod pose; 14 | #[allow(unused_imports)] 15 | pub use self::pose::*; 16 | pub mod quat; 17 | #[allow(unused_imports)] 18 | pub use self::quat::*; 19 | pub mod transform_x; 20 | #[allow(unused_imports)] 21 | pub use self::transform_x::*; 22 | pub mod vec3; 23 | #[allow(unused_imports)] 24 | pub use self::vec3::*; 25 | -------------------------------------------------------------------------------- /crates/forky_bevy/src/extensions/pose.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | 4 | #[derive(Debug)] 5 | pub struct Pose { 6 | pub position: Vec3, 7 | pub rotation: Quat, 8 | } 9 | 10 | impl Default for Pose { 11 | fn default() -> Self { 12 | Pose { 13 | position: Vec3::default(), 14 | rotation: Quat::default(), 15 | } 16 | } 17 | } 18 | 19 | 20 | impl Pose { 21 | pub fn from_transform(tran: &Transform) -> Pose { 22 | Pose { 23 | position: tran.translation, 24 | rotation: tran.rotation, 25 | } 26 | } 27 | pub fn set_from_transform(&mut self, tran: &Transform) { 28 | self.position = tran.translation; 29 | self.rotation = tran.rotation; 30 | } 31 | 32 | pub fn lerp(a: &Pose, b: &Pose, t: f32) -> Pose { 33 | Pose { 34 | position: Vec3::lerp(a.position, b.position, t), 35 | rotation: Quat::slerp(a.rotation, b.rotation, t), 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /crates/forky_bevy/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(test, feature(test, custom_test_frameworks))] 2 | #![cfg_attr(test, test_runner(sweet::test_runner))] 3 | 4 | pub mod extensions; 5 | pub mod systems; 6 | 7 | 8 | pub mod prelude { 9 | pub use crate::extensions::*; 10 | pub use crate::systems::*; 11 | } 12 | -------------------------------------------------------------------------------- /crates/forky_bevy/src/systems/exit_system.rs: -------------------------------------------------------------------------------- 1 | use bevy::app::AppExit; 2 | use bevy::core::FrameCount; 3 | use bevy::prelude::*; 4 | 5 | pub fn exit_system(mut exit: EventWriter) { 6 | exit.send(AppExit::Success); 7 | } 8 | pub fn exit_in_frames(count: u32) -> impl Fn(Res, EventWriter) { 9 | move |frames, mut exit| { 10 | if frames.0 >= count - 1 { 11 | exit.send(AppExit::Success); 12 | } 13 | } 14 | } 15 | 16 | pub fn close_on_esc(mut exit: EventWriter, input: Res>) { 17 | if input.just_pressed(KeyCode::Escape) { 18 | exit.send(AppExit::Success); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /crates/forky_bevy/src/systems/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod exit_system; 2 | #[allow(unused_imports)] 3 | pub use self::exit_system::*; 4 | -------------------------------------------------------------------------------- /crates/forky_cli/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "forky_cli" 3 | version.workspace = true 4 | edition.workspace = true 5 | authors.workspace = true 6 | documentation.workspace = true 7 | license.workspace = true 8 | readme = "README.md" 9 | description.workspace = true 10 | repository.workspace = true 11 | 12 | [[bin]] 13 | name = "forky" 14 | path = "src/main.rs" 15 | 16 | # [dependencies] 17 | [target.'cfg(not(target_arch = "wasm32"))'.dependencies] # specify os for rust analyzer 18 | ## forky 19 | forky_core.workspace = true 20 | forky_fs.workspace = true 21 | forky_net = { workspace = true, features = ["reqwest"] } 22 | 23 | anyhow.workspace = true 24 | extend.workspace = true 25 | 26 | ## async 27 | futures.workspace = true 28 | rayon.workspace = true 29 | tokio.workspace = true 30 | 31 | ## fs 32 | glob.workspace = true 33 | ## cli 34 | clap.workspace = true 35 | colorize.workspace = true 36 | ## style 37 | cssparser.workspace = true 38 | 39 | ## key 40 | enigo = "0.3" 41 | reqwest.workspace = true 42 | 43 | ## serve 44 | http.workspace = true 45 | axum.workspace = true 46 | axum-extra.workspace = true 47 | axum-server.workspace = true 48 | tower.workspace = true 49 | tower-http.workspace = true 50 | tower-livereload.workspace = true 51 | 52 | [dev-dependencies] 53 | sweet.workspace = true 54 | -------------------------------------------------------------------------------- /crates/forky_cli/README.md: -------------------------------------------------------------------------------- 1 | # Forky CLI 2 | 3 |
4 | 5 |

6 | CLI for various forky utilities. 7 |

8 | 9 |

10 | Crates.io version 11 | Download 12 | docs.rs docs 13 |

14 | 15 |

16 | Book 17 | | 18 | API Docs 19 | | 20 | Contributing 21 |

22 | 23 | made with ❤️‍🔥 by mrchantey 24 |
-------------------------------------------------------------------------------- /crates/forky_cli/examples/cli.rs: -------------------------------------------------------------------------------- 1 | use ::forky_cli::prelude::*; 2 | 3 | fn main() -> anyhow::Result<()> { ForkyCli::run() } 4 | -------------------------------------------------------------------------------- /crates/forky_cli/examples/swap_mouse.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | fn main() -> std::io::Result<()> { 4 | let output = Command::new("reg") 5 | .args(&[ 6 | "add", 7 | "HKCU\\Control Panel\\Mouse", 8 | "/v", 9 | "SwapMouseButtons", 10 | "/t", 11 | "REG_SZ", 12 | "/d", 13 | "1", 14 | "/f", 15 | ]) 16 | .output()?; 17 | 18 | if !output.status.success() { 19 | eprintln!( 20 | "Failed to change mouse button setting: {}", 21 | String::from_utf8_lossy(&output.stderr) 22 | ); 23 | } 24 | 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /crates/forky_cli/src/common/forky_cli.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use anyhow::Result; 3 | use clap::Parser; 4 | use clap::Subcommand; 5 | 6 | /// Welcome to the Forky Cli! 7 | #[derive(Parser)] 8 | #[command(version, about, long_about = None)] 9 | pub struct ForkyCli { 10 | #[command(subcommand)] 11 | command: Commands, 12 | } 13 | #[derive(Subcommand)] 14 | enum Commands { 15 | AutoKey(AutoKeyCommand), 16 | Fed(ForEachDirectory), 17 | Mod(AutoModCommand), 18 | Serve(Serve), 19 | Watch(WatchCommand), 20 | } 21 | 22 | impl ForkyCli { 23 | pub fn run() -> Result<()> { 24 | match Self::parse().command { 25 | Commands::AutoKey(cmd) => cmd.run(), 26 | Commands::Fed(cmd) => cmd.run(), 27 | Commands::Mod(cmd) => cmd.run(), 28 | Commands::Serve(cmd) => cmd.run(), 29 | Commands::Watch(cmd) => cmd.run(), 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /crates/forky_cli/src/common/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod auto_mod; 2 | #[allow(unused_imports)] 3 | pub use self::auto_mod::*; 4 | pub mod for_each_directory; 5 | #[allow(unused_imports)] 6 | pub use self::for_each_directory::*; 7 | pub mod forky_cli; 8 | #[allow(unused_imports)] 9 | pub use self::forky_cli::*; 10 | pub mod watch; 11 | #[allow(unused_imports)] 12 | pub use self::watch::*; 13 | -------------------------------------------------------------------------------- /crates/forky_cli/src/key/auto_key_command.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use anyhow::Result; 3 | use clap::Parser; 4 | use enigo::*; 5 | 6 | /// automate keypresses 7 | #[derive(Parser)] 8 | pub struct AutoKeyCommand; 9 | 10 | impl AutoKeyCommand { 11 | pub fn run(self) -> Result<()> { 12 | InputSequence::default() 13 | // exit dock 14 | .input(Key::Escape) 15 | .ulaunch(1, "r beetmash-biz") 16 | .ulaunch(2, "r beetmash-api") 17 | .ulaunch(3, "r beetmash-site") 18 | .ulaunch(4, "r beetmash") 19 | .ulaunch(5, "r beet") 20 | // .command("code /home/pete/me/beetmash-biz") 21 | // .command("cd ~ && code .") 22 | .run()?; 23 | Ok(()) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /crates/forky_cli/src/key/input_sequence.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use anyhow::Result; 3 | use enigo::{Enigo, Key, Settings}; 4 | use std::time::Duration; 5 | 6 | #[derive(Debug)] 7 | pub struct InputSequence { 8 | commands: Vec, 9 | delay: Duration, 10 | } 11 | 12 | impl Default for InputSequence { 13 | fn default() -> Self { 14 | Self { 15 | delay: Duration::from_millis(500), 16 | commands: Vec::new(), 17 | } 18 | } 19 | } 20 | 21 | impl InputSequence { 22 | pub fn new() -> Self { 23 | Self::default() 24 | } 25 | 26 | pub fn input(mut self, command: impl Into) -> Self { 27 | self.commands.push(command.into()); 28 | self 29 | } 30 | pub fn command(mut self, command: impl Into) -> Self { 31 | self.commands.push(Input::Command(command.into())); 32 | self 33 | } 34 | 35 | pub fn ulaunch(self, workspace: usize, search: &str) -> Self { 36 | self.input(vec![ 37 | Key::Meta, 38 | Key::Unicode(workspace.to_string().chars().next().unwrap()), 39 | ]) 40 | .input(vec![Key::Alt, Key::Space]) 41 | .input(search) 42 | .input(Key::UpArrow) // ensure its the last result, exact match 43 | .input(Key::Return) 44 | .input(Duration::from_secs(1)) 45 | } 46 | 47 | pub fn run(&mut self) -> Result<()> { 48 | self.run_with_enigo(&mut Enigo::new(&Settings::default())?) 49 | } 50 | pub fn run_with_enigo(&mut self, enigo: &mut Enigo) -> Result<()> { 51 | for command in self.commands.iter() { 52 | command.run(enigo)?; 53 | std::thread::sleep(self.delay); 54 | } 55 | Ok(()) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /crates/forky_cli/src/key/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod auto_key_command; 2 | #[allow(unused_imports)] 3 | pub use self::auto_key_command::*; 4 | pub mod input_command; 5 | #[allow(unused_imports)] 6 | pub use self::input_command::*; 7 | pub mod input_sequence; 8 | #[allow(unused_imports)] 9 | pub use self::input_sequence::*; 10 | -------------------------------------------------------------------------------- /crates/forky_cli/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(test, feature(test, custom_test_frameworks))] 2 | #![cfg_attr(test, test_runner(sweet::test_runner))] 3 | // #![feature(never_type, never_type_fallback)] 4 | #![feature(let_chains)] 5 | pub mod common; 6 | pub mod key; 7 | pub mod server; 8 | pub mod style; 9 | pub mod utils; 10 | 11 | pub mod prelude { 12 | pub use crate::common::*; 13 | pub use crate::key::*; 14 | pub use crate::server::*; 15 | pub use crate::style::*; 16 | pub use crate::utils::*; 17 | } 18 | -------------------------------------------------------------------------------- /crates/forky_cli/src/main.rs: -------------------------------------------------------------------------------- 1 | #![cfg(not(target_arch = "wasm32"))] 2 | use ::forky_cli::prelude::*; 3 | 4 | fn main() -> anyhow::Result<()> { ForkyCli::run() } 5 | -------------------------------------------------------------------------------- /crates/forky_cli/src/server/_self_signed_certs/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDkzCCAnugAwIBAgIUXVYkRCrM/ge03DVymDtXCuybp7gwDQYJKoZIhvcNAQEL 3 | BQAwWTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM 4 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4X 5 | DTIxMDczMTE0MjIxMloXDTIyMDczMTE0MjIxMlowWTELMAkGA1UEBhMCVVMxEzAR 6 | BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 7 | IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 8 | MIIBCgKCAQEA02V5ZjmqLB/VQwTarrz/35qsa83L+DbAoa0001+jVmmC+G9Nufi0 9 | daroFWj/Uicv2fZWETU8JoZKUrX4BK9og5cg5rln/CtBRWCUYIwRgY9R/CdBGPn4 10 | kp+XkSJaCw74ZIyLy/Zfux6h8ES1m9YRnBza+s7U+ImRBRf4MRPtXQ3/mqJxAZYq 11 | dOnKnvssRyD2qutgVTAxwMUvJWIivRhRYDj7WOpS4CEEeQxP1iH1/T5P7FdtTGdT 12 | bVBABCA8JhL96uFGPpOYHcM/7R5EIA3yZ5FNg931QzoDITjtXGtQ6y9/l/IYkWm6 13 | J67RWcN0IoTsZhz0WNU4gAeslVtJLofn8QIDAQABo1MwUTAdBgNVHQ4EFgQUzFnK 14 | NfS4LAYuKeWwHbzooER0yZ0wHwYDVR0jBBgwFoAUzFnKNfS4LAYuKeWwHbzooER0 15 | yZ0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAk4O+e9jia59W 16 | ZwetN4GU7OWcYhmOgSizRSs6u7mTfp62LDMt96WKU3THksOnZ44HnqWQxsSfdFVU 17 | XJD12tjvVU8Z4FWzQajcHeemUYiDze8EAh6TnxnUcOrU8IcwiKGxCWRY/908jnWg 18 | +MMscfMCMYTRdeTPqD8fGzAlUCtmyzH6KLE3s4Oo/r5+NR+Uvrwpdvb7xe0MwwO9 19 | Q/zR4N8ep/HwHVEObcaBofE1ssZLksX7ZgCP9wMgXRWpNAtC5EWxMbxYjBfWFH24 20 | fDJlBMiGJWg8HHcxK7wQhFh+fuyNzE+xEWPsI9VL1zDftd9x8/QsOagyEOnY8Vxr 21 | AopvZ09uEQ== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /crates/forky_cli/src/server/_self_signed_certs/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDTZXlmOaosH9VD 3 | BNquvP/fmqxrzcv4NsChrTTTX6NWaYL4b025+LR1qugVaP9SJy/Z9lYRNTwmhkpS 4 | tfgEr2iDlyDmuWf8K0FFYJRgjBGBj1H8J0EY+fiSn5eRIloLDvhkjIvL9l+7HqHw 5 | RLWb1hGcHNr6ztT4iZEFF/gxE+1dDf+aonEBlip06cqe+yxHIPaq62BVMDHAxS8l 6 | YiK9GFFgOPtY6lLgIQR5DE/WIfX9Pk/sV21MZ1NtUEAEIDwmEv3q4UY+k5gdwz/t 7 | HkQgDfJnkU2D3fVDOgMhOO1ca1DrL3+X8hiRabonrtFZw3QihOxmHPRY1TiAB6yV 8 | W0kuh+fxAgMBAAECggEADltu8k1qTFLhJgsXWxTFAAe+PBgfCT2WuaRM2So+qqjB 9 | 12Of0MieYPt5hbK63HaC3nfHgqWt7yPhulpXfOH45C8IcgMXl93MMg0MJr58leMI 10 | +2ojFrIrerHSFm5R1TxwDEwrVm/mMowzDWFtQCc6zPJ8wNn5RuP48HKfTZ3/2fjw 11 | zEjSwPO2wFMfo1EJNTjlI303lFbdFBs67NaX6puh30M7Tn+gznHKyO5a7F57wkIt 12 | fkgnEy/sgMedQlwX7bRpUoD6f0fZzV8Qz4cHFywtYErczZJh3VGitJoO/VCIDdty 13 | RPXOAqVDd7EpP1UUehZlKVWZ0OZMEfRgKbRCel5abQKBgQDwgwrIQ5+BiZv6a0VT 14 | ETeXB+hRbvBinRykNo/RvLc3j1enRh9/zO/ShadZIXgOAiM1Jnr5Gp8KkNGca6K1 15 | myhtad7xYPODYzNXXp6T1OPgZxHZLIYzVUj6ypXeV64Te5ZiDaJ1D49czsq+PqsQ 16 | XRcgBJSNpFtDFiXWpjXWfx8PxwKBgQDhAnLY5Sl2eeQo+ud0MvjwftB/mN2qCzJY 17 | 5AlQpRI4ThWxJgGPuHTR29zVa5iWNYuA5LWrC1y/wx+t5HKUwq+5kxvs+npYpDJD 18 | ZX/w0Glc6s0Jc/mFySkbw9B2LePedL7lRF5OiAyC6D106Sc9V2jlL4IflmOzt4CD 19 | ZTNbLtC6hwKBgHfIzBXxl/9sCcMuqdg1Ovp9dbcZCaATn7ApfHd5BccmHQGyav27 20 | k7XF2xMJGEHhzqcqAxUNrSgV+E9vTBomrHvRvrd5Ec7eGTPqbBA0d0nMC5eeFTh7 21 | wV0miH20LX6Gjt9G6yJiHYSbeV5G1+vOcTYBEft5X/qJjU7aePXbWh0BAoGBAJlV 22 | 5tgCCuhvFloK6fHYzqZtdT6O+PfpW20SMXrgkvMF22h2YvgDFrDwqKRUB47NfHzg 23 | 3yBpxNH1ccA5/w97QO8w3gX3h6qicpJVOAPusu6cIBACFZfjRv1hyszOZwvw+Soa 24 | Fj5kHkqTY1YpkREPYS9V2dIW1Wjic1SXgZDw7VM/AoGAP/cZ3ZHTSCDTFlItqy5C 25 | rIy2AiY0WJsx+K0qcvtosPOOwtnGjWHb1gdaVdfX/IRkSsX4PAOdnsyidNC5/l/m 26 | y8oa+5WEeGFclWFhr4dnTA766o8HrM2UjIgWWYBF2VKdptGnHxFeJWFUmeQC/xeW 27 | w37pCS7ykL+7gp7V0WShYsw= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /crates/forky_cli/src/server/_self_signed_certs/mod.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrchantey/forky/78068992ea64c3eb0955f019ef4cd71ef006f514/crates/forky_cli/src/server/_self_signed_certs/mod.rs -------------------------------------------------------------------------------- /crates/forky_cli/src/server/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod address; 2 | #[allow(unused_imports)] 3 | pub use self::address::*; 4 | pub mod proxy; 5 | #[allow(unused_imports)] 6 | pub use self::proxy::*; 7 | pub mod serve; 8 | #[allow(unused_imports)] 9 | pub use self::serve::*; 10 | pub mod tls; 11 | #[allow(unused_imports)] 12 | pub use self::tls::*; 13 | -------------------------------------------------------------------------------- /crates/forky_cli/src/style/cli_all.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use anyhow::Result; 3 | use clap::ArgMatches; 4 | use forky_core::prelude::*; 5 | use forky_fs::prelude::*; 6 | 7 | pub struct StyleAllCli { 8 | pub lightning: Option, 9 | } 10 | 11 | impl StyleAllCli { 12 | pub fn watch_with_mutex(&self, mutex: ArcMut<()>) -> Result<()> { 13 | Self::watcher().with_mutex(mutex).watch(|_| self.run()) 14 | } 15 | 16 | pub fn watch(&self) -> Result<()> { Self::watcher().watch(|_| self.run()) } 17 | 18 | //TODO only update changed files 19 | fn watcher() -> FsWatcher { 20 | FsWatcher::default() 21 | .with_watch("**/*.css") 22 | .with_ignore("**/index.css") 23 | .with_ignore("**/html/**") 24 | .with_ignore("**/target/**") 25 | } 26 | 27 | pub fn run(&self) -> Result<()> { 28 | create_type_files()?; 29 | create_index_files()?; 30 | 31 | if let Some(lightning) = &self.lightning { 32 | lightning.run()?; 33 | } 34 | 35 | Ok(()) 36 | } 37 | } 38 | 39 | impl From<&ArgMatches> for StyleAllCli { 40 | fn from(value: &ArgMatches) -> Self { 41 | let lightning = value.get_one::("lightning").cloned(); 42 | let package = value.get_one::("package").cloned(); 43 | 44 | let lightning = match lightning { 45 | Some(dst) => { 46 | let src = if let Some(package) = package { 47 | format!("crates/{}/src/lib.css", package) 48 | } else { 49 | "src/lib.css".to_string() 50 | }; 51 | Some(Lightning { src, dst }) 52 | } 53 | None => None, 54 | }; 55 | 56 | Self { lightning } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /crates/forky_cli/src/style/command_all.rs: -------------------------------------------------------------------------------- 1 | use super::StyleAllCli; 2 | use anyhow::Result; 3 | use clap::Arg; 4 | use clap::ArgAction; 5 | use clap::ArgMatches; 6 | use clap::Command; 7 | use forky_fs::prelude::*; 8 | 9 | pub struct StyleCommandAll; 10 | 11 | impl Subcommand for StyleCommandAll { 12 | fn name(&self) -> &'static str { "all" } 13 | fn about(&self) -> &'static str { "Apply to all style directories." } 14 | 15 | fn append_command(&self, command: Command) -> Command { 16 | command 17 | .arg( 18 | Arg::new("lightning") 19 | .help("specify directory for lightning to run") 20 | .required(false) 21 | .short('l') 22 | .long("lightning") 23 | .action(ArgAction::Set), 24 | ) 25 | .arg( 26 | Arg::new("package") 27 | .help("package to find lib.css file in") 28 | .required(false) 29 | .short('p') 30 | .long("package") 31 | .action(ArgAction::Set), 32 | ) 33 | } 34 | 35 | fn run(&self, args: &ArgMatches) -> Result<()> { 36 | let cli: StyleAllCli = args.into(); 37 | cli.run() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /crates/forky_cli/src/style/command_file.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use anyhow::Result; 3 | use clap::Arg; 4 | use clap::ArgMatches; 5 | use forky_fs::prelude::*; 6 | use std::path::Path; 7 | 8 | pub struct StyleCommandFile; 9 | 10 | impl Subcommand for StyleCommandFile { 11 | fn name(&self) -> &'static str { "file" } 12 | fn about(&self) -> &'static str { "Apply to specified style file." } 13 | 14 | fn append_command(&self, command: clap::Command) -> clap::Command { 15 | command 16 | .arg(Arg::new("in").required(true)) 17 | .arg(Arg::new("out").required(false)) 18 | } 19 | fn run(&self, args: &ArgMatches) -> Result<()> { 20 | terminal::print_forky(); 21 | let path_in = args.get_one::("in").unwrap(); 22 | let path_in = Path::new(path_in).to_path_buf(); 23 | if !path_in.exists() { 24 | anyhow::bail!("path not found: {:?}", path_in) 25 | } 26 | let content = create_type_text(&path_in); 27 | let path_out = if let Some(path_out) = args.get_one::("out") { 28 | Path::new(path_out).to_path_buf() 29 | } else { 30 | super::type_files::get_path_out(&path_in) 31 | }; 32 | super::type_files::write_to_disk(&path_out, &content)?; 33 | Ok(()) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /crates/forky_cli/src/style/lightning.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use forky_core::prelude::*; 3 | use forky_fs::prelude::CommandExt; 4 | // use forky_fs::process::spawn_command_blocking; 5 | use std::fs::create_dir_all; 6 | use std::path::Path; 7 | 8 | pub struct Lightning { 9 | pub src: String, 10 | pub dst: String, 11 | } 12 | impl Lightning { 13 | #[rustfmt::skip] 14 | pub fn run(&self) -> Result<()>{ 15 | create_dir_all(Path::new(&self.dst).parent().ok()?)?; 16 | 17 | println!("\nstyle: running lightningcss\n"); 18 | let cmd = vec![ 19 | "npx", "lightningcss", &self.src, 20 | "--bundle", 21 | "--minify", 22 | "--nesting", 23 | "--sourcemap", 24 | "-o", &self.dst 25 | ]; 26 | // let cmd = vec![ 27 | // "lightningcss" 28 | // ]; 29 | // spawn_command_blocking(&cmd) 30 | CommandExt::spawn_command_with_shell_blocking(&cmd) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /crates/forky_cli/src/style/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod cli_all; 2 | #[allow(unused_imports)] 3 | pub use self::cli_all::*; 4 | pub mod command_all; 5 | #[allow(unused_imports)] 6 | pub use self::command_all::*; 7 | pub mod command_file; 8 | #[allow(unused_imports)] 9 | pub use self::command_file::*; 10 | pub mod index_files; 11 | #[allow(unused_imports)] 12 | pub use self::index_files::*; 13 | pub mod lightning; 14 | #[allow(unused_imports)] 15 | pub use self::lightning::*; 16 | pub mod style_command; 17 | #[allow(unused_imports)] 18 | pub use self::style_command::*; 19 | pub mod type_files; 20 | #[allow(unused_imports)] 21 | pub use self::type_files::*; 22 | -------------------------------------------------------------------------------- /crates/forky_cli/src/style/style_command.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use forky_fs::prelude::*; 3 | 4 | pub struct StyleCommand; 5 | 6 | impl Subcommand for StyleCommand { 7 | fn name(&self) -> &'static str { "style" } 8 | fn about(&self) -> &'static str { "Generate types for styles" } 9 | 10 | fn subcommands(&self) -> Vec> { 11 | vec![Box::new(StyleCommandAll), Box::new(StyleCommandFile)] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /crates/forky_cli/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod path_buf; 2 | #[allow(unused_imports)] 3 | pub use self::path_buf::*; 4 | -------------------------------------------------------------------------------- /crates/forky_cli/src/utils/path_buf.rs: -------------------------------------------------------------------------------- 1 | use forky_core::prelude::*; 2 | use std::path::Path; 3 | use std::path::PathBuf; 4 | 5 | pub struct CliPathExt; 6 | 7 | impl CliPathExt { 8 | pub fn push_with( 9 | parent: impl AsRef, 10 | path: impl AsRef, 11 | ) -> PathBuf { 12 | let mut child = parent.as_ref().to_path_buf(); 13 | child.push(path); 14 | child 15 | } 16 | pub fn filename_starts_with_uppercase(path: impl AsRef) -> bool { 17 | path.as_ref().file_name().str().first().is_ascii_uppercase() 18 | } 19 | 20 | pub fn anscestors_includes( 21 | path: impl AsRef, 22 | arr: impl IntoIterator>, 23 | ) -> bool { 24 | arr.into_iter().any(|f| { 25 | path.as_ref() 26 | .ancestors() 27 | .any(|p| p.file_stem().unwrap_or_default() == f.as_ref()) 28 | }) 29 | } 30 | 31 | pub fn filename_included( 32 | path: impl AsRef, 33 | arr: impl IntoIterator>, 34 | ) -> bool { 35 | arr.into_iter().any(|f| { 36 | path.as_ref().file_stem().unwrap_or_default() == f.as_ref() 37 | }) 38 | } 39 | pub fn filestem_starts_with_underscore(path: impl AsRef) -> bool { 40 | path.as_ref().file_stem().str().first() == '_' 41 | } 42 | pub fn filestem_ends_with_underscore(path: impl AsRef) -> bool { 43 | path.as_ref().file_stem().str().last() == '_' 44 | } 45 | pub fn filestem_ends_with_double_underscore( 46 | path: impl AsRef, 47 | ) -> bool { 48 | path.as_ref().file_stem().str().ends_with("__") 49 | } 50 | pub fn filestem_contains_double_underscore(path: impl AsRef) -> bool { 51 | path.as_ref().file_stem().str().contains("__") 52 | } 53 | 54 | pub fn pop_first_two_path_components(path: &str) -> PathBuf { 55 | let mut components = Path::new(path).components(); 56 | components.next(); 57 | components.next(); 58 | components.as_path().to_path_buf() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /crates/forky_core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "forky_core" 3 | version.workspace = true 4 | edition.workspace = true 5 | authors.workspace = true 6 | documentation.workspace = true 7 | license.workspace = true 8 | readme.workspace = true 9 | description.workspace = true 10 | repository.workspace = true 11 | 12 | 13 | [dependencies] 14 | anyhow.workspace = true 15 | extend.workspace = true 16 | rand.workspace = true 17 | 18 | [dev-dependencies] 19 | sweet.workspace = true 20 | -------------------------------------------------------------------------------- /crates/forky_core/src/extensions/duration.rs: -------------------------------------------------------------------------------- 1 | use extend::ext; 2 | use std::time::Duration; 3 | 4 | #[ext] 5 | pub impl Duration { 6 | fn from_hms(hour: u64, minute: u64, second: u64) -> Duration { 7 | Duration::from_secs(hour * 3600 + minute * 60 + second) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /crates/forky_core/src/extensions/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod duration; 2 | #[allow(unused_imports)] 3 | pub use self::duration::*; 4 | pub mod option; 5 | #[allow(unused_imports)] 6 | pub use self::option::*; 7 | pub mod path_buf_ext; 8 | #[allow(unused_imports)] 9 | pub use self::path_buf_ext::*; 10 | pub mod path_ext; 11 | #[allow(unused_imports)] 12 | pub use self::path_ext::*; 13 | pub mod result_x; 14 | #[allow(unused_imports)] 15 | pub use self::result_x::*; 16 | pub mod str_x; 17 | #[allow(unused_imports)] 18 | pub use self::str_x::*; 19 | pub mod string; 20 | #[allow(unused_imports)] 21 | pub use self::string::*; 22 | pub mod vec; 23 | #[allow(unused_imports)] 24 | pub use self::vec::*; 25 | -------------------------------------------------------------------------------- /crates/forky_core/src/extensions/option.rs: -------------------------------------------------------------------------------- 1 | use anyhow::*; 2 | use extend::ext; 3 | 4 | #[ext] 5 | pub impl Option { 6 | fn ok(self) -> Result { option_to_result(self) } 7 | } 8 | 9 | fn option_to_result(option: Option) -> Result { 10 | match option { 11 | Some(value) => Ok(value), 12 | None => Err(anyhow!("Expected Some")), 13 | } 14 | } -------------------------------------------------------------------------------- /crates/forky_core/src/extensions/path_buf_ext.rs: -------------------------------------------------------------------------------- 1 | use extend::ext; 2 | use std::path::PathBuf; 3 | 4 | #[ext] 5 | pub impl PathBuf { 6 | fn is_dir_or_extension(&self, ext: &str) -> bool { 7 | match self.extension() { 8 | Some(value) => value.to_str().unwrap() == ext, 9 | None => self.is_dir(), 10 | } 11 | } 12 | 13 | 14 | /// List of all directories, including self if it is a directory. 15 | fn dir_parts(&self) -> Vec { 16 | let mut acc = Vec::new(); 17 | let mut current = self.clone(); 18 | if self.is_dir() { 19 | acc.push(self.clone()); 20 | } 21 | while let Some(parent) = current.parent() { 22 | acc.push(parent.to_path_buf()); 23 | current = parent.to_path_buf(); 24 | } 25 | acc 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /crates/forky_core/src/extensions/path_ext.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use std::ffi::OsStr; 3 | use std::path::Path; 4 | use std::path::PathBuf; 5 | 6 | pub struct PathExt; 7 | 8 | impl PathExt { 9 | pub fn relative(path: &impl AsRef) -> Result<&Path> { 10 | let cwd = std::env::current_dir()?; 11 | let p = path.as_ref().strip_prefix(cwd)?; 12 | Ok(p) 13 | } 14 | pub fn absolute(path: impl AsRef) -> Result { 15 | let cwd = std::env::current_dir()?; 16 | let p = Path::join(&cwd, path); 17 | Ok(p) 18 | } 19 | pub fn to_forward_slash(path: impl AsRef) -> PathBuf { 20 | Path::new(&path.as_ref().to_string_lossy().replace("\\", "/")) 21 | .to_path_buf() 22 | } 23 | pub fn to_forward_slash_str(path: impl AsRef) -> String { 24 | path.as_ref() 25 | .to_str() 26 | .unwrap_or_default() 27 | .replace("\\", "/") 28 | } 29 | 30 | pub fn file_stem(path: &impl AsRef) -> Result<&OsStr> { 31 | path.as_ref().file_stem().ok_or_else(|| { 32 | anyhow::anyhow!( 33 | "File has no stem: {}", 34 | path.as_ref().to_string_lossy() 35 | ) 36 | }) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /crates/forky_core/src/extensions/result_x.rs: -------------------------------------------------------------------------------- 1 | use extend::ext; 2 | 3 | #[ext] 4 | pub impl Result { 5 | fn ok_or(self, func: impl FnOnce(E)) -> Option { 6 | match self { 7 | Ok(value) => Some(value), 8 | Err(err) => { 9 | func(err); 10 | None 11 | } 12 | } 13 | } 14 | } 15 | // #[ext] 16 | // pub impl Result { 17 | // Consume the error, log it and return None, otherwise return the value. 18 | // fn log_err(self) -> Option { 19 | // match self { 20 | // Ok(value) => Some(value), 21 | // Err(err) => { 22 | // log::error!("{err}"); 23 | // None 24 | // } 25 | // } 26 | // } 27 | // } 28 | 29 | 30 | // #[ext(name =ResultExtEDebug)] 31 | // pub impl Result { 32 | // /// Map a `Result` to an [`anyhow::Result`]. 33 | // fn anyhow(self) -> anyhow::Result { 34 | // match self { 35 | // Ok(v) => Ok(v), 36 | // Err(e) => Err(anyhow::anyhow!("{:?}", e)), 37 | // } 38 | // } 39 | // } 40 | -------------------------------------------------------------------------------- /crates/forky_core/src/extensions/str_x.rs: -------------------------------------------------------------------------------- 1 | use extend::ext; 2 | use std::ffi::OsStr; 3 | 4 | #[ext] 5 | pub impl &str { 6 | /// get the first char or default 7 | fn first(&self) -> char { self.chars().next().unwrap_or_default() } 8 | /// get the last char or default 9 | fn last(&self) -> char { self.chars().last().unwrap_or_default() } 10 | } 11 | 12 | #[ext] 13 | pub impl Option<&str> { 14 | fn or_default(&self) -> &str { 15 | match &self { 16 | Some(c) => c, 17 | None => "", 18 | } 19 | } 20 | } 21 | // pub impl Option<&&str> { 22 | // fn or_default(&self) -> &str { 23 | // match &self { 24 | // Some(c) => c, 25 | // None => "", 26 | // } 27 | // } 28 | // } 29 | 30 | #[ext] 31 | pub impl Option<&OsStr> { 32 | fn str(&self) -> &str { 33 | self.unwrap_or_default().to_str().unwrap_or_default() 34 | } 35 | } 36 | 37 | 38 | #[cfg(test)] 39 | mod test { 40 | use crate::prelude::*; 41 | use sweet::prelude::*; 42 | 43 | #[test] 44 | fn works() { 45 | expect("".first()).to_be('\0'); 46 | expect("".last()).to_be('\0'); 47 | expect("12".first()).to_be('1'); 48 | expect("12".last()).to_be('2'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /crates/forky_core/src/extensions/string.rs: -------------------------------------------------------------------------------- 1 | use extend::ext; 2 | 3 | #[ext] 4 | pub impl String { 5 | fn push_string(&mut self, str: &String) -> &Self { 6 | self.push_str(str.as_str()); 7 | self 8 | } 9 | fn push_str_line(&mut self, str: &str) -> &Self { 10 | self.push_str(str); 11 | self.push('\n'); 12 | self 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /crates/forky_core/src/extensions/vec.rs: -------------------------------------------------------------------------------- 1 | use extend::ext; 2 | use std::slice::SliceIndex; 3 | 4 | #[ext(name = VecXOrd)] 5 | pub impl Vec { 6 | fn sorted(mut self) -> Self { 7 | self.sort(); 8 | self 9 | } 10 | } 11 | 12 | #[ext(name = VecXDefault)] 13 | pub impl Vec { 14 | fn from_len(len: usize) -> Self { vec![T::default(); len] } 15 | } 16 | #[ext(name = VecXInto)] 17 | pub impl, U> Vec { 18 | fn into_vec(self) -> Vec { self.into_iter().map(|x| x.into()).collect() } 19 | } 20 | 21 | 22 | #[ext(name = VecX)] 23 | pub impl Vec { 24 | fn _first(&self) -> &T { self.first().unwrap() } 25 | fn _pop(&mut self) -> T { self.pop().unwrap() } 26 | fn _get(&self, index: T2) -> &>::Output 27 | where 28 | T2: SliceIndex<[T]>, 29 | { 30 | self.get(index).unwrap() 31 | } 32 | fn _get_mut(&mut self, index: T2) -> &>::Output 33 | where 34 | T2: SliceIndex<[T]>, 35 | { 36 | self.get_mut(index).unwrap() 37 | } 38 | fn remove_first_element(&mut self, element: T) -> bool 39 | where 40 | T: PartialEq, 41 | { 42 | let index = self.iter().position(|x| *x == element); 43 | if let Some(index) = index { 44 | self.remove(index); 45 | true 46 | } else { 47 | false 48 | } 49 | } 50 | } 51 | 52 | 53 | 54 | #[cfg(test)] 55 | mod test { 56 | use crate::prelude::*; 57 | use sweet::prelude::*; 58 | 59 | #[test] 60 | fn works() { 61 | let v = vec![0, 2, 1].sorted(); 62 | expect(v.len()).to_be(3); 63 | expect(v[0]).to_be(0); 64 | expect(v[1]).to_be(1); 65 | expect(v[2]).to_be(2); 66 | } 67 | 68 | #[test] 69 | fn first() { 70 | let v = vec![0, 2, 1]; 71 | let v = v._first(); 72 | expect(*v).to_be(0); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /crates/forky_core/src/forky_event/forky_event.rs: -------------------------------------------------------------------------------- 1 | #[derive(Default)] 2 | pub struct ForkyEvent { 3 | pub listeners: Vec>, 4 | } 5 | 6 | impl ForkyEvent { 7 | pub fn new() -> Self { 8 | Self { 9 | listeners: Vec::new(), 10 | } 11 | } 12 | 13 | pub fn trigger(&mut self, val: &T) { 14 | for listener in self.listeners.iter_mut() { 15 | listener(val); 16 | } 17 | } 18 | pub fn add_listener(&mut self, listener: impl 'static + FnMut(&T)) { 19 | self.listeners.push(Box::new(listener)); 20 | } 21 | 22 | pub fn clear(&mut self) { self.listeners.clear(); } 23 | } 24 | 25 | 26 | #[cfg(test)] 27 | mod test { 28 | use crate::prelude::*; 29 | use sweet::prelude::*; 30 | 31 | #[test] 32 | fn works() { 33 | let mut e = ForkyEvent::default(); 34 | let func = mock_bucket::(); 35 | let func2 = func.clone(); 36 | e.add_listener(move |val| func2(*val)); 37 | e.trigger(&3); 38 | 39 | expect(&func).to_have_returned_with(3); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /crates/forky_core/src/forky_event/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod forky_event; 2 | #[allow(unused_imports)] 3 | pub use self::forky_event::*; 4 | -------------------------------------------------------------------------------- /crates/forky_core/src/graph/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod node; 2 | #[allow(unused_imports)] 3 | pub use self::node::*; 4 | -------------------------------------------------------------------------------- /crates/forky_core/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(test, feature(test, custom_test_frameworks))] 2 | #![cfg_attr(test, test_runner(sweet::test_runner))] 3 | pub mod extensions; 4 | pub mod forky_event; 5 | pub mod graph; 6 | pub mod math; 7 | pub mod math_f64; 8 | pub mod utils; 9 | 10 | 11 | pub mod prelude { 12 | pub use crate::extensions::*; 13 | pub use crate::forky_event::*; 14 | pub use crate::graph::*; 15 | pub use crate::math; 16 | pub use crate::math_f64; 17 | pub use crate::utils::*; 18 | } 19 | -------------------------------------------------------------------------------- /crates/forky_core/src/math/constants.rs: -------------------------------------------------------------------------------- 1 | pub const TAU: f32 = std::f32::consts::TAU; 2 | pub const QUARTER_TAU: f32 = TAU * 0.25; 3 | pub const HALF_TAU: f32 = TAU * 0.5; 4 | pub const THREE_QUARTER_TAU: f32 = TAU * 0.75; 5 | 6 | pub const PI: f32 = HALF_TAU; 7 | 8 | pub const GRAVITY: f32 = -9.81; 9 | 10 | 11 | pub const DEG2RAD: f32 = PI / 180.; 12 | pub const RAD2DEG: f32 = 180. / PI; 13 | pub const RAD2HOURS: f32 = 12. / PI; 14 | pub const HOURS2RAD: f32 = PI / 12.; 15 | pub const DEG2HOURS: f32 = 1. / 15.; 16 | pub const HOURS2DEG: f32 = 15.; 17 | -------------------------------------------------------------------------------- /crates/forky_core/src/math/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod constants; 2 | #[allow(unused_imports)] 3 | pub use self::constants::*; 4 | -------------------------------------------------------------------------------- /crates/forky_core/src/math_f64/constants.rs: -------------------------------------------------------------------------------- 1 | pub const TAU: f64 = std::f64::consts::TAU; 2 | pub const QUARTER_TAU: f64 = TAU * 0.25; 3 | pub const HALF_TAU: f64 = TAU * 0.5; 4 | pub const THREE_QUARTER_TAU: f64 = TAU * 0.75; 5 | 6 | pub const PI: f64 = std::f64::consts::PI; 7 | 8 | pub const DEG2RAD: f64 = PI / 180.; 9 | pub const RAD2DEG: f64 = 180. / PI; 10 | pub const RAD2HOURS: f64 = 12. / PI; 11 | pub const HOURS2RAD: f64 = PI / 12.; 12 | pub const DEG2HOURS: f64 = 1. / 15.; 13 | pub const HOURS2DEG: f64 = 15.; 14 | -------------------------------------------------------------------------------- /crates/forky_core/src/math_f64/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod constants; 2 | #[allow(unused_imports)] 3 | pub use self::constants::*; 4 | pub mod funcs; 5 | #[allow(unused_imports)] 6 | pub use self::funcs::*; 7 | -------------------------------------------------------------------------------- /crates/forky_core/src/style/mod.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrchantey/forky/78068992ea64c3eb0955f019ef4cd71ef006f514/crates/forky_core/src/style/mod.rs -------------------------------------------------------------------------------- /crates/forky_core/src/utils/async_utils.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::rc::Rc; 3 | use std::sync::Arc; 4 | use std::sync::Mutex; 5 | // use std::time::Duration; 6 | 7 | 8 | 9 | pub type ArcMut = Arc>; 10 | pub fn arcmut(val: T) -> ArcMut { Arc::new(Mutex::new(val)) } 11 | 12 | pub type RcCell = Rc>; 13 | pub fn rccell(val: T) -> RcCell { Rc::new(RefCell::new(val)) } 14 | 15 | 16 | 17 | // trait ArcMutex { 18 | // fn arcmut(self) -> ArcMut { arcmut(self) } 19 | // } 20 | 21 | // impl ArcMutex for T { 22 | // // fn arcmut(self) -> ArcMut { arcmut(self) } 23 | // } 24 | -------------------------------------------------------------------------------- /crates/forky_core/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod async_utils; 2 | #[allow(unused_imports)] 3 | pub use self::async_utils::*; 4 | pub mod random; 5 | #[allow(unused_imports)] 6 | pub use self::random::*; 7 | -------------------------------------------------------------------------------- /crates/forky_core/src/utils/random.rs: -------------------------------------------------------------------------------- 1 | use rand::Rng; 2 | 3 | /// Returns a random value between 0.0 and 1.0 4 | pub fn random_value() -> f32 { rand::thread_rng().gen_range(0.0..1.0) } 5 | pub fn random_signed() -> f32 { rand::thread_rng().gen_range(-1.0..1.0) } 6 | pub fn random_percent_i32() -> i32 { rand::thread_rng().gen_range(0..100) } 7 | -------------------------------------------------------------------------------- /crates/forky_esp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "forky_esp" 3 | version.workspace = true 4 | edition.workspace = true 5 | authors.workspace = true 6 | documentation.workspace = true 7 | license.workspace = true 8 | readme.workspace = true 9 | description.workspace = true 10 | repository.workspace = true 11 | 12 | [[bin]] 13 | name = "forky_esp" 14 | path = "src/entry/main.rs" 15 | 16 | [[bin]] 17 | name = "hello_world" 18 | path = "src/entry/hello_world.rs" 19 | 20 | [[bin]] 21 | name = "hello_led" 22 | path = "src/entry/hello_led.rs" 23 | [[bin]] 24 | name = "hello_led_strip" 25 | path = "src/entry/hello_led_strip.rs" 26 | # [[bin]] 27 | # name = "hello_wasm" 28 | # path = "src/entry/hello_wasm.rs" 29 | [[bin]] 30 | name = "device" 31 | path = "src/entry/device.rs" 32 | 33 | [dependencies] 34 | # esp32c3-hal = "0.2.0" 35 | # esp-hal-common = { version = "0.2.0", features = ["esp32c3"] } 36 | extend.workspace = true 37 | # esp32c3-hal = { version = "0.2.0", path="../../../../../Users/petey/work-ref/esp-hal/esp32c3-hal"} 38 | esp32c3-hal = { version = "0.2.0" } 39 | riscv-rt = { version = "0.9.0", optional = true } 40 | esp-backtrace = { version = "0.2.0", features = [ 41 | "esp32c3", 42 | "panic-handler", 43 | "exception-handler", 44 | "print-uart", 45 | ] } 46 | # problems with installing esp-backtrace on windows 47 | esp-hal-common = { version = "0.2.0", features = ["esp32c3"] } 48 | # esp-hal-common = { version = "0.2.0", features = ["esp32c3"], path="../../../../../Users/petey/work-ref/esp-hal/esp-hal-common"} 49 | smart-leds = "0.3.0" 50 | fugit = "0.3.6" 51 | 52 | [dev-dependencies] 53 | sweet.workspace = true 54 | 55 | [features] 56 | default = ["rt", "smartled"] 57 | rt = ["riscv-rt"] 58 | smartled = ["esp-hal-common/smartled"] 59 | -------------------------------------------------------------------------------- /crates/forky_esp/src/__extensions/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod rgb; 2 | -------------------------------------------------------------------------------- /crates/forky_esp/src/__extensions/rgb.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use extend::ext; 3 | use smart_leds::{ 4 | brightness, gamma, 5 | hsv::{hsv2rgb, Hsv}, 6 | SmartLedsWrite, RGB, RGB8, 7 | }; 8 | use std::{fmt::Display, slice::SliceIndex}; 9 | 10 | // #[ext] 11 | // pub impl RGBW8 { 12 | // fn to_rgb(&self) -> RGB8 { 13 | // RGB8{ 14 | // self.r, 15 | // self.g, 16 | // self.b 17 | // } 18 | // } 19 | // } 20 | -------------------------------------------------------------------------------- /crates/forky_esp/src/_core/_esp_device.rs: -------------------------------------------------------------------------------- 1 | use esp32c3_hal::{ 2 | clock::ClockControl, 3 | pac, 4 | prelude::*, 5 | pulse_control::ClockSource, 6 | timer::TimerGroup, 7 | utils::{smartLedAdapter, SmartLedsAdapter}, 8 | PulseControl, Rtc, IO, 9 | }; 10 | use esp_hal_common::{ 11 | pac::{Peripherals, UART0}, 12 | system::SystemParts, 13 | }; 14 | 15 | use crate::{Logger, Timer}; 16 | 17 | 18 | pub struct ESPDevice { 19 | pub pulse: PulseControl, 20 | pub io: IO, 21 | pub timer: Timer, 22 | pub logger: Logger, 23 | // pub peripherals: Peripherals, 24 | // pub system: SystemParts, 25 | } 26 | 27 | 28 | impl ESPDevice { 29 | pub fn new() -> ESPDevice { 30 | let peripherals = pac::Peripherals::take().unwrap(); 31 | let mut system = peripherals.SYSTEM.split(); 32 | 33 | let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); 34 | 35 | let timer = Timer::new(&clocks); 36 | let logger = Logger::new(peripherals.UART0); 37 | 38 | let mut rtc = Rtc::new(peripherals.RTC_CNTL); 39 | let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); 40 | let mut wdt0 = timer_group0.wdt; 41 | 42 | let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); 43 | 44 | //put in led controller? 45 | let pulse = PulseControl::new( 46 | peripherals.RMT, 47 | &mut system.peripheral_clock_control, 48 | ClockSource::APB, 49 | 0, 50 | 0, 51 | 0, 52 | ) 53 | .unwrap(); 54 | 55 | // Disable watchdogs 56 | rtc.swd.disable(); 57 | rtc.rwdt.disable(); 58 | wdt0.disable(); 59 | ESPDevice { 60 | pulse, 61 | timer, 62 | logger, 63 | io, 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /crates/forky_esp/src/_core/_led_controller_rgb.rs: -------------------------------------------------------------------------------- 1 | use crate::ESPDevice; 2 | // use esp32c3_hal::utils::*; 3 | use esp_hal_common::{ 4 | pulse_control::{ConfiguredChannel, OutputChannel}, 5 | utils::smart_leds_adapter::*, 6 | OutputPin, 7 | }; 8 | use smart_leds::{hsv, *}; 9 | 10 | 11 | #[macro_export] 12 | macro_rules! led_controller_rgb { 13 | ($channel: expr, $pin: expr,$num_leds: literal) => { 14 | LEDController::<_, _, { $num_leds * 24 + 1 }, { $num_leds }>::new( 15 | $channel, $pin, 16 | ) 17 | }; 18 | } 19 | 20 | pub struct LEDController< 21 | CHANNEL, 22 | PIN, 23 | const BUFFER_SIZE: usize, 24 | const NUM_LEDS: usize, 25 | > { 26 | // led: T, 27 | data: [RGB8; NUM_LEDS], 28 | led: SmartLedsAdapter, 29 | } 30 | 31 | 32 | impl 33 | LEDController 34 | where 35 | CC: ConfiguredChannel, 36 | PIN: OutputPin, 37 | { 38 | pub fn new( 39 | mut channel: OC, 40 | pin: PIN, 41 | ) -> LEDController 42 | where 43 | OC: OutputChannel, 44 | { 45 | let mut led = 46 | SmartLedsAdapter::::new(channel, pin); 47 | LEDController { 48 | led, 49 | data: [RGB8 { 50 | r: 255, 51 | g: 255, 52 | b: 255, 53 | }; NUM_LEDS], 54 | } 55 | } 56 | 57 | pub fn set_hue_all(&mut self, hue: u8) { 58 | let color = hsv::Hsv { 59 | hue, 60 | sat: 255, 61 | val: 255, 62 | }; 63 | for i in 0..NUM_LEDS { 64 | self.data[i] = hsv::hsv2rgb(color); 65 | } 66 | } 67 | 68 | pub fn show(&mut self) { 69 | self.led 70 | .write(self.data.iter().cloned()) 71 | // .write(brightness(gamma(self.data.iter().cloned()), 10)) 72 | .unwrap(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /crates/forky_esp/src/_core/_logger.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::Write; 2 | use esp_hal_common::{pac::UART0, prelude::*, Serial}; 3 | 4 | 5 | pub struct Logger { 6 | pub serial: Serial, 7 | } 8 | 9 | 10 | impl Logger { 11 | pub fn new(uart: UART0) -> Logger { 12 | let mut serial = Serial::new(uart); 13 | Logger { serial } 14 | } 15 | pub fn write(&mut self, val: &str) { 16 | writeln!(self.serial, "{}", val).unwrap(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /crates/forky_esp/src/_core/_timer.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::Write; 2 | use esp32c3_hal::Delay; 3 | use esp_hal_common::{clock::Clocks, prelude::*}; 4 | 5 | 6 | pub struct Timer { 7 | pub delay: Delay, 8 | } 9 | 10 | 11 | impl Timer { 12 | pub fn new(clocks: &Clocks) -> Timer { 13 | let delay = Delay::new(&clocks); 14 | Timer { delay } 15 | } 16 | 17 | pub fn delay(&mut self, val: u16) { self.delay.delay_ms(val); } 18 | } 19 | -------------------------------------------------------------------------------- /crates/forky_esp/src/_core/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod _esp_device; 2 | pub mod _led_controller_rgb; 3 | pub mod _led_controller_rgbw; 4 | pub mod _logger; 5 | pub mod _smart_leds_adapter_rgbw; 6 | pub mod _timer; 7 | -------------------------------------------------------------------------------- /crates/forky_esp/src/entry/device.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use forky_esp::*; 5 | use riscv_rt::entry; 6 | 7 | #[entry] 8 | fn main() -> ! { 9 | let mut device = ESPDevice::new(); 10 | 11 | loop { 12 | device.write("hello"); 13 | device.write("world"); 14 | device.delay(1000); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /crates/forky_esp/src/entry/hello_led.rs: -------------------------------------------------------------------------------- 1 | //https://github.com/esp-rs/esp-hal/blob/main/esp32c3-hal/examples/hello_rgb.rs 2 | #![no_std] 3 | #![no_main] 4 | use forky_esp::*; 5 | 6 | #[entry] 7 | fn main() -> ! { 8 | let mut device = ESPDevice::new(); 9 | 10 | let mut controller = 11 | led_controller_rgb!(device.pulse.channel0, device.io.pins.gpio7, 1); 12 | 13 | // controller 14 | loop { 15 | for hue in 0..=255 { 16 | controller.set_hue_all(hue); 17 | controller.show(); 18 | device.timer.delay(10); 19 | } 20 | // device.timer.delay(2000); 21 | // device.logger.write("howdy!"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /crates/forky_esp/src/entry/hello_led_strip.rs: -------------------------------------------------------------------------------- 1 | //https://github.com/esp-rs/esp-hal/blob/main/esp32c3-hal/examples/hello_rgb.rs 2 | #![no_std] 3 | #![no_main] 4 | use forky_esp::*; 5 | 6 | #[entry] 7 | fn main() -> ! { 8 | let mut device = ESPDevice::new(); 9 | 10 | let mut controller = 11 | led_controller_rgbw!(device.pulse.channel0, device.io.pins.gpio7, 5); 12 | // led_controller_rgb!(device.pulse.channel0, device.io.pins.gpio7, 4); 13 | 14 | controller.set_white(127); 15 | controller.set_all(0, 0, 4, 4); 16 | controller.show(); 17 | loop { 18 | for h in 0..=255 { 19 | // controller.set_hue(h); 20 | // controller.show(); 21 | device.timer.delay(100); 22 | } 23 | // device.timer.delay(2000); 24 | // device.logger.write("howdy!"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /crates/forky_esp/src/entry/hello_world.rs: -------------------------------------------------------------------------------- 1 | //https://github.com/esp-rs/esp-hal/blob/main/esp32c3-hal/examples/hello_world.rs 2 | #![no_std] 3 | #![no_main] 4 | use forky_esp::*; 5 | 6 | #[entry] 7 | fn main() -> ! { 8 | let mut device = ESPDevice::new(); 9 | 10 | loop { 11 | device.logger.write("hello world"); 12 | device.timer.delay(1000); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /crates/forky_esp/src/entry/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod device; 2 | #[allow(unused_imports)] 3 | pub use self::device::*; 4 | pub mod hello_led; 5 | #[allow(unused_imports)] 6 | pub use self::hello_led::*; 7 | pub mod hello_led_strip; 8 | #[allow(unused_imports)] 9 | pub use self::hello_led_strip::*; 10 | pub mod hello_world; 11 | #[allow(unused_imports)] 12 | pub use self::hello_world::*; 13 | -------------------------------------------------------------------------------- /crates/forky_esp/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | // #![feature(generic_const_exprs)] 4 | // #[allow(unused_imports, unused_variables)] 5 | //general 6 | pub use esp32c3_hal::prelude::*; 7 | pub use esp_backtrace as _; 8 | pub use riscv_rt::entry; 9 | //crate 10 | mod _core; 11 | pub use _core::*; 12 | // mod _utility; 13 | // pub use _utility::*; 14 | -------------------------------------------------------------------------------- /crates/forky_esp/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | pub use esp32c3_hal::prelude::*; 5 | use esp_backtrace as _; 6 | // use nb::block; 7 | use riscv_rt::entry; 8 | 9 | #[entry] 10 | fn main() -> ! { loop {} } 11 | -------------------------------------------------------------------------------- /crates/forky_fs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "forky_fs" 3 | version.workspace = true 4 | edition.workspace = true 5 | authors.workspace = true 6 | documentation.workspace = true 7 | license.workspace = true 8 | readme.workspace = true 9 | description.workspace = true 10 | repository.workspace = true 11 | 12 | 13 | [dependencies] 14 | forky_core.workspace = true 15 | ## utils 16 | glob.workspace = true 17 | anyhow.workspace = true 18 | thiserror.workspace = true 19 | extend.workspace = true 20 | sha2.workspace = true 21 | hex.workspace = true 22 | 23 | ## terminal 24 | crossterm.workspace = true 25 | gag.workspace = true 26 | 27 | ## cli 28 | clap.workspace = true 29 | 30 | ## fs 31 | notify.workspace = true 32 | notify-debouncer-full.workspace = true 33 | ## async 34 | tokio.workspace = true 35 | futures.workspace = true 36 | 37 | 38 | [dev-dependencies] 39 | sweet.workspace = true -------------------------------------------------------------------------------- /crates/forky_fs/src/cli/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod fs_watcher; 2 | #[allow(unused_imports)] 3 | pub use self::fs_watcher::*; 4 | pub mod subcommand; 5 | #[allow(unused_imports)] 6 | pub use self::subcommand::*; 7 | -------------------------------------------------------------------------------- /crates/forky_fs/src/fs/fs_async_utils.rs: -------------------------------------------------------------------------------- 1 | use std::ops::AsyncFn; 2 | use tokio::time::sleep; 3 | use tokio::time::Duration; 4 | 5 | #[deprecated = "i think this is deceptively tricky, use a library instead"] 6 | pub async fn retry_async( 7 | func: impl AsyncFn() -> Result, 8 | timeout: Duration, 9 | ) -> Result { 10 | let start = std::time::Instant::now(); 11 | loop { 12 | match func().await { 13 | Ok(val) => return Ok(val), 14 | Err(err) => { 15 | if start.elapsed() > timeout { 16 | return Err(err); 17 | } 18 | } 19 | } 20 | sleep(Duration::from_millis(10)).await; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/forky_fs/src/fs/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod fs_async_utils; 2 | #[allow(unused_imports)] 3 | pub use self::fs_async_utils::*; 4 | pub mod fs_error; 5 | #[allow(unused_imports)] 6 | pub use self::fs_error::*; 7 | pub mod fs_ext; 8 | #[allow(unused_imports)] 9 | pub use self::fs_ext::*; 10 | pub mod read_dir; 11 | #[allow(unused_imports)] 12 | pub use self::read_dir::*; 13 | pub mod read_file; 14 | #[allow(unused_imports)] 15 | pub use self::read_file::*; 16 | -------------------------------------------------------------------------------- /crates/forky_fs/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(test, feature(test, custom_test_frameworks))] 2 | #![cfg_attr(test, test_runner(sweet::test_runner))] 3 | #![feature(type_alias_impl_trait)] 4 | #![feature(async_fn_traits)] 5 | pub mod cli; 6 | pub mod fs; 7 | pub mod utility; 8 | 9 | pub mod prelude { 10 | pub use crate::cli::*; 11 | pub use crate::fs::*; 12 | pub use crate::utility::*; 13 | } 14 | -------------------------------------------------------------------------------- /crates/forky_fs/src/utility/cli_args/misc.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | /// remove first one cos thats binary name 4 | pub fn get_cli_args() -> Vec { 5 | let mut args: Vec = std::env::args().collect(); 6 | args.remove(0); 7 | args 8 | } 9 | 10 | 11 | #[cfg(test)] 12 | mod test { 13 | use super::*; 14 | use sweet::prelude::*; 15 | 16 | #[test] 17 | fn works() { expect(get_cli_args().len()).to_be_greater_or_equal_to(0); } 18 | } 19 | -------------------------------------------------------------------------------- /crates/forky_fs/src/utility/cli_args/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod misc; 2 | #[allow(unused_imports)] 3 | pub use self::misc::*; 4 | -------------------------------------------------------------------------------- /crates/forky_fs/src/utility/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod cli_args; 2 | pub mod command; 3 | #[allow(unused_imports)] 4 | pub use self::command::*; 5 | pub mod process; 6 | pub mod terminal; 7 | -------------------------------------------------------------------------------- /crates/forky_fs/src/utility/process/child_x.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use extend::ext; 3 | use std::process::Child; 4 | use std::thread; 5 | use std::time::Duration; 6 | 7 | #[derive(Debug)] 8 | pub enum ChildProcessStatus { 9 | Killed, 10 | ExitSuccess(i32), 11 | ExitFail(i32), 12 | } 13 | 14 | #[ext] 15 | pub impl Child { 16 | /// Returns either when child completes or kill returns true 17 | fn wait_killable( 18 | mut self, 19 | should_kill: impl Fn() -> bool, 20 | ) -> Result { 21 | loop { 22 | if should_kill() { 23 | self.kill()?; 24 | return Ok(ChildProcessStatus::Killed); 25 | } 26 | match self.try_wait() { 27 | Ok(Some(status)) => match status.success() { 28 | true => { 29 | // println!("output: {:?}", self.wait_with_output()); 30 | return Ok(ChildProcessStatus::ExitSuccess(0)); 31 | } 32 | false => { 33 | return Ok(ChildProcessStatus::ExitFail( 34 | status.code().unwrap_or(-1), 35 | )) 36 | } 37 | }, 38 | Ok(None) => { 39 | //still running, is sleep required? 40 | thread::sleep(Duration::from_millis(1)); 41 | continue; 42 | } 43 | Err(err) => { 44 | anyhow::bail!( 45 | "Error waiting for the child process: {}", 46 | err 47 | ) 48 | } 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /crates/forky_fs/src/utility/process/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod child_x; 2 | #[allow(unused_imports)] 3 | pub use self::child_x::*; 4 | -------------------------------------------------------------------------------- /crates/forky_fs/src/utility/terminal/misc.rs: -------------------------------------------------------------------------------- 1 | use crossterm::*; 2 | use std::io::stdout; 3 | use std::io::Write; 4 | use anyhow::Result; 5 | 6 | pub fn clear() { clear_terminal().unwrap(); } 7 | 8 | pub fn print_forky() { 9 | println!("\n🦀 running forky! 🦀\n"); 10 | } 11 | 12 | pub fn show_cursor() { 13 | let mut stdout = stdout(); 14 | stdout.execute(cursor::Show).unwrap(); 15 | } 16 | 17 | 18 | pub fn reset_cursor() { 19 | let mut stdout = stdout(); 20 | stdout.execute(cursor::MoveTo(0, 0)).unwrap(); 21 | } 22 | 23 | fn clear_terminal() -> Result<()> { 24 | let mut stdout = stdout(); 25 | stdout 26 | .queue(terminal::Clear(terminal::ClearType::All))? 27 | // .queue(cursor::Hide)? 28 | .queue(cursor::MoveTo(0, 0))?; 29 | stdout.flush()?; 30 | Ok(()) 31 | } 32 | -------------------------------------------------------------------------------- /crates/forky_fs/src/utility/terminal/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod misc; 2 | #[allow(unused_imports)] 3 | pub use self::misc::*; 4 | pub mod redirect_io; 5 | #[allow(unused_imports)] 6 | pub use self::redirect_io::*; 7 | -------------------------------------------------------------------------------- /crates/forky_fs/src/utility/terminal/redirect_io.rs: -------------------------------------------------------------------------------- 1 | use gag::BufferRedirect; 2 | use std::io::Read; 3 | 4 | 5 | pub fn start_redirect_io() -> BufferRedirect { 6 | let buf = BufferRedirect::stdout().unwrap(); 7 | buf 8 | } 9 | 10 | pub fn end_redirect_io(buf: &mut BufferRedirect) -> String { 11 | let mut output = String::new(); 12 | buf.read_to_string(&mut output).unwrap(); 13 | output 14 | } 15 | -------------------------------------------------------------------------------- /crates/forky_fs/test_dir/_ignored_dir/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod _test_use; 2 | #[allow(unused_imports)] 3 | pub use self::_test_use::*; 4 | pub mod test_mod; 5 | -------------------------------------------------------------------------------- /crates/forky_fs/test_dir/_ignored_file.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /crates/forky_fs/test_dir/included_dir/mod.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrchantey/forky/78068992ea64c3eb0955f019ef4cd71ef006f514/crates/forky_fs/test_dir/included_dir/mod.rs -------------------------------------------------------------------------------- /crates/forky_fs/test_dir/included_file.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /crates/forky_fs/test_dir/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod included_dir; 2 | pub mod included_file; 3 | #[allow(unused_imports)] 4 | pub use self::included_file::*; 5 | -------------------------------------------------------------------------------- /crates/forky_net/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "forky_net" 3 | version.workspace = true 4 | edition.workspace = true 5 | authors.workspace = true 6 | documentation.workspace = true 7 | license.workspace = true 8 | readme.workspace = true 9 | description.workspace = true 10 | repository.workspace = true 11 | 12 | 13 | [features] 14 | reqwest = ["dep:reqwest", "dep:http-body-util", "dep:once_cell"] 15 | axum = ["dep:axum", "dep:tower"] 16 | 17 | [dependencies] 18 | anyhow.workspace = true 19 | extend.workspace = true 20 | forky_core.workspace = true 21 | 22 | http.workspace = true 23 | http-body.workspace = true 24 | bytes.workspace = true 25 | 26 | reqwest = { workspace = true, optional = true } 27 | http-body-util = { workspace = true, optional = true } 28 | once_cell = { workspace = true, optional = true } 29 | 30 | axum = { workspace = true, optional = true } 31 | tower = { workspace = true, optional = true } 32 | 33 | [dev-dependencies] 34 | tokio.workspace = true 35 | sweet.workspace = true 36 | -------------------------------------------------------------------------------- /crates/forky_net/src/axum_utils/axum_ext.rs: -------------------------------------------------------------------------------- 1 | use bytes::Bytes; 2 | use http_body_util::BodyExt; 3 | 4 | 5 | 6 | 7 | 8 | pub struct AxumExt; 9 | 10 | 11 | 12 | impl AxumExt { 13 | pub async fn collect_response( 14 | res: axum::response::Response, 15 | ) -> Result, axum::Error> { 16 | let (parts, body) = res.into_parts(); 17 | 18 | let body = body.collect().await.map(|b| b.to_bytes())?; 19 | 20 | let res = http::Response::from_parts(parts, body); 21 | Ok(res) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /crates/forky_net/src/axum_utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod axum_ext; 2 | #[allow(unused_imports)] 3 | pub use self::axum_ext::*; 4 | -------------------------------------------------------------------------------- /crates/forky_net/src/layers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod cors; 2 | #[allow(unused_imports)] 3 | pub use self::cors::*; 4 | pub mod no_cache; 5 | #[allow(unused_imports)] 6 | pub use self::no_cache::*; 7 | -------------------------------------------------------------------------------- /crates/forky_net/src/layers/no_cache.rs: -------------------------------------------------------------------------------- 1 | use axum::extract::Request; 2 | use axum::http::header; 3 | use axum::http::HeaderValue; 4 | use axum::middleware::Next; 5 | use axum::response::IntoResponse; 6 | use axum::response::Response; 7 | 8 | /// Middleware to add no-cache headers to a response 9 | pub async fn no_cache(request: Request, next: Next) -> Response { 10 | let response = next.run(request).await; 11 | append_no_cache_headers(response) 12 | } 13 | 14 | /// Append no-cache headers to a response 15 | pub fn append_no_cache_headers(val: impl IntoResponse) -> Response { 16 | let mut response = val.into_response(); 17 | let headers = response.headers_mut(); 18 | headers.insert( 19 | header::CACHE_CONTROL, 20 | HeaderValue::from_static("no-cache, no-store, must-revalidate"), 21 | ); 22 | headers.insert(header::PRAGMA, HeaderValue::from_static("no-cache")); 23 | headers.insert(header::EXPIRES, HeaderValue::from_static("0")); 24 | // do something with `response`... 25 | 26 | response 27 | } 28 | 29 | -------------------------------------------------------------------------------- /crates/forky_net/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(test, feature(test, custom_test_frameworks))] 2 | #![cfg_attr(test, test_runner(sweet::test_runner))] 3 | #![allow(async_fn_in_trait)] 4 | 5 | 6 | 7 | #[cfg(feature = "axum")] 8 | pub mod axum_utils; 9 | #[cfg(feature = "axum")] 10 | pub mod layers; 11 | #[cfg(feature = "reqwest")] 12 | pub mod reqwest_utils; 13 | pub mod state; 14 | 15 | pub mod prelude { 16 | #[cfg(feature = "axum")] 17 | pub use crate::axum_utils::*; 18 | #[cfg(feature = "axum")] 19 | pub use crate::layers::*; 20 | #[cfg(feature = "reqwest")] 21 | pub use crate::reqwest_utils::*; 22 | pub use crate::state::*; 23 | } 24 | -------------------------------------------------------------------------------- /crates/forky_net/src/reqwest_utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod reqwest_ext; 2 | #[allow(unused_imports)] 3 | pub use self::reqwest_ext::*; 4 | -------------------------------------------------------------------------------- /crates/forky_net/src/state/api_environment.rs: -------------------------------------------------------------------------------- 1 | /// Specify the environment of the api 2 | /// 3 | /// The default value will be resolved by [`ApiEnvironment::get`] 4 | /// 1. if `API_ENV` is set to local,staging,prod, use that value 5 | /// 2. Otherwise use `debug_assertions` to determine if it should be local or prod 6 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 7 | pub enum ApiEnvironment { 8 | /// Should not use Mongo or AWS at all 9 | Local, 10 | /// Use remote services but staging buckets and dbs 11 | Staging, 12 | /// Use production remote services 13 | Prod, 14 | } 15 | 16 | impl Default for ApiEnvironment { 17 | fn default() -> Self { Self::get() } 18 | } 19 | 20 | impl Into<&'static str> for ApiEnvironment { 21 | fn into(self) -> &'static str { 22 | match self { 23 | Self::Local => "local", 24 | Self::Staging => "staging", 25 | Self::Prod => "prod", 26 | } 27 | } 28 | } 29 | 30 | impl std::fmt::Display for ApiEnvironment { 31 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 32 | write!(f, "{}", Into::<&'static str>::into(*self)) 33 | } 34 | } 35 | 36 | 37 | impl ApiEnvironment { 38 | pub fn get() -> Self { 39 | if let Some(env) = std::env::var("API_ENV").ok() { 40 | match env.as_str() { 41 | "local" => Self::Local, 42 | "staging" => Self::Staging, 43 | "prod" => Self::Prod, 44 | _ => Self::from_debug_assertions(), 45 | } 46 | } else { 47 | Self::from_debug_assertions() 48 | } 49 | } 50 | fn from_debug_assertions() -> Self { 51 | if cfg!(debug_assertions) { 52 | Self::Local 53 | } else { 54 | Self::Prod 55 | } 56 | } 57 | pub fn is_local(&self) -> bool { *self == Self::Local } 58 | } 59 | -------------------------------------------------------------------------------- /crates/forky_net/src/state/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod api_environment; 2 | #[allow(unused_imports)] 3 | pub use self::api_environment::*; 4 | pub mod uptime; 5 | #[allow(unused_imports)] 6 | pub use self::uptime::*; 7 | -------------------------------------------------------------------------------- /crates/forky_net/src/state/uptime.rs: -------------------------------------------------------------------------------- 1 | use std::sync::atomic::AtomicUsize; 2 | use std::sync::atomic::Ordering; 3 | 4 | 5 | static NUM_UPTIME_REQUESTS: AtomicUsize = AtomicUsize::new(0); 6 | /// 7 | /// Handy uptime struct for use in axum state 8 | /// Like all substates ensure that `FromRef` is implemented: 9 | /// ```rust ignore 10 | /// impl FromRef for Uptime { 11 | /// fn from_ref(app_state: &AppState) -> Uptime { app_state.uptime.clone() } 12 | /// } 13 | /// ``` 14 | /// 15 | #[derive(Debug, Clone)] 16 | pub struct Uptime { 17 | pub start: std::time::Instant, 18 | } 19 | impl Default for Uptime { 20 | fn default() -> Self { Self::new() } 21 | } 22 | 23 | 24 | 25 | impl Uptime { 26 | pub fn new() -> Self { 27 | Self { 28 | start: std::time::Instant::now(), 29 | } 30 | } 31 | pub fn incr_requests(&self) -> usize { 32 | NUM_UPTIME_REQUESTS.fetch_add(1, Ordering::SeqCst) + 1 33 | } 34 | 35 | pub fn stats(&self) -> String { 36 | let uptime = self.start.elapsed().as_secs(); 37 | let requests = self.incr_requests(); 38 | format!("Uptime: {} seconds, Requests: {}", uptime, requests) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /crates/forky_play/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "forky_play" 3 | version.workspace = true 4 | edition.workspace = true 5 | authors.workspace = true 6 | documentation.workspace = true 7 | license.workspace = true 8 | readme.workspace = true 9 | description.workspace = true 10 | repository.workspace = true 11 | 12 | [features] 13 | shader_debug = [] 14 | shader_debug_internal = [] 15 | 16 | [dependencies] 17 | ### Internal ### 18 | forky_core.workspace = true 19 | forky_bevy.workspace = true 20 | 21 | ### Game ### 22 | bevy = { workspace = true, default-features = true } 23 | # bevy-inspector-egui.workspace = true 24 | # bevy_rapier3d.workspace = true 25 | # bevy_mod_debugdump.workspace = true 26 | # wgpu.workspace = true 27 | 28 | ### Utility ### 29 | extend.workspace = true 30 | anyhow.workspace = true 31 | petgraph = { version = "0.7", features = ["serde-1"] } 32 | 33 | [target.'cfg(target_arch = "wasm32")'.dependencies] 34 | forky_web.workspace = true 35 | 36 | [dev-dependencies] 37 | sweet.workspace = true 38 | # forky_fs = {workspace = true } 39 | 40 | # rustflags = ["-C", "link-arg=-fuse-ld=lld"] 41 | 42 | 43 | ### Optimization https://bevyengine.org/learn/book/getting-started/setup/ 44 | 45 | # [profile.dev] 46 | # opt-level = 1 47 | 48 | # [profile.dev.package."*"] 49 | # opt-level = 3 50 | 51 | # [target.x86_64-pc-windows-msvc] 52 | # linker = "rust-lld.exe" 53 | # rustflags = ["-Zshare-generics=n"] 54 | -------------------------------------------------------------------------------- /crates/forky_play/assets/branding/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrchantey/forky/78068992ea64c3eb0955f019ef4cd71ef006f514/crates/forky_play/assets/branding/icon.png -------------------------------------------------------------------------------- /crates/forky_play/assets/fonts/FiraMono-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrchantey/forky/78068992ea64c3eb0955f019ef4cd71ef006f514/crates/forky_play/assets/fonts/FiraMono-Medium.ttf -------------------------------------------------------------------------------- /crates/forky_play/assets/fonts/FiraSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrchantey/forky/78068992ea64c3eb0955f019ef4cd71ef006f514/crates/forky_play/assets/fonts/FiraSans-Bold.ttf -------------------------------------------------------------------------------- /crates/forky_play/assets/shaders/custom_material.wgsl: -------------------------------------------------------------------------------- 1 | struct CustomMaterial { 2 | color: vec4, 3 | }; 4 | 5 | @group(1) @binding(0) 6 | var material: CustomMaterial; 7 | @group(1) @binding(1) 8 | var base_color_texture: texture_2d; 9 | @group(1) @binding(2) 10 | var base_color_sampler: sampler; 11 | 12 | @fragment 13 | fn fragment( 14 | #import bevy_pbr::mesh_vertex_output 15 | ) -> @location(0) vec4 { 16 | return vec4(0.,0.,1.,1.); 17 | // return material.color * textureSample(base_color_texture, base_color_sampler, uv); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /crates/forky_play/assets/shaders/simple.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_core_pipeline::fullscreen_vertex_shader 2 | 3 | @group(0) @binding(0) 4 | var color: vec4; 5 | @group(0) @binding(1) 6 | var my_texture: texture_2d; 7 | @group(0) @binding(2) 8 | var my_sampler: sampler; 9 | 10 | @fragment 11 | fn fragment(@location(0) uv: vec2) -> @location(0) vec4 { 12 | // return color; 13 | return color * textureSample(my_texture, my_sampler, uv); 14 | // textureSample(texture, sampler, uv) 15 | // return vec4(uv.xy,0.,1.); 16 | // return vec4(color.r,color.g ,color.b,1.); 17 | } -------------------------------------------------------------------------------- /crates/forky_play/assets/shaders/unlit.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_pbr::forward_io::VertexOutput 2 | 3 | @group(1) @binding(0) 4 | var color: vec4; 5 | 6 | @fragment 7 | fn fragment(in: VertexOutput) -> @location(0) vec4 { 8 | return color; 9 | } 10 | -------------------------------------------------------------------------------- /crates/forky_play/assets/shaders/unlit_texture.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_pbr::forward_io::VertexOutput 2 | 3 | @group(1) @binding(0) 4 | var color: vec4; 5 | @group(1) @binding(1) 6 | var tiling: vec4; 7 | @group(1) @binding(2) 8 | var base_color_texture: texture_2d; 9 | @group(1) @binding(3) 10 | var base_color_sampler: sampler; 11 | 12 | @fragment 13 | fn fragment(in: VertexOutput) -> @location(0) vec4 { 14 | let tiled_uv = (in.uv * tiling.xy) % 1.; 15 | return color * textureSample(base_color_texture, base_color_sampler, tiled_uv); 16 | } 17 | -------------------------------------------------------------------------------- /crates/forky_play/assets/shaders/utility.wgsl: -------------------------------------------------------------------------------- 1 | #define_import_path forky::utility 2 | 3 | const PI: f32 = 3.14159265358979323846264338327950288; 4 | const TAU: f32 = 6.28318530717958647692528676655900577; 5 | 6 | // shader art: https://youtu.be/f4s1h2YETNY 7 | 8 | // Palette 9 | // how it works https://iquilezles.org/articles/palettes/ 10 | // color tool http://dev.thi.ng/gradients/ 11 | fn palette( 12 | dc_offset:vec3, 13 | amp:vec3, 14 | freq:vec3, 15 | phase:vec3, 16 | t:f32)->vec3{ 17 | return dc_offset + cos(TAU * (t + phase * freq)) * amp; 18 | } 19 | 20 | // falloff should be low value, ie 0.01 21 | fn bloom(value:f32,falloff:f32,contrast:f32)->f32{ 22 | return pow(falloff / value, contrast); 23 | } -------------------------------------------------------------------------------- /crates/forky_play/assets/shaders/uv.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_pbr::forward_io::VertexOutput 2 | 3 | @fragment 4 | fn fragment(in: VertexOutput) -> @location(0) vec4 { 5 | return vec4(in.uv.x,in.uv.y,1.,1.); 6 | } -------------------------------------------------------------------------------- /crates/forky_play/docs/Splines.md: -------------------------------------------------------------------------------- 1 | # Splines 2 | - Spline Types: 3 | - Bezier 4 | - Catmull 5 | 6 | 7 | - Freya Holmer 8 | - The Continuity of Splines: https://youtu.be/jvPPXbo87ds 9 | - The Beauty of Bezier Curves: https://youtu.be/aVwxzDHniEw 10 | ## Resources 11 | 12 | - [GDC - Spline Based Procedural Geometry](https://www.youtube.com/watch?v=o9RK6O2kOKo) 13 | - Optimize beziers - Bernstein Polynomial equations -------------------------------------------------------------------------------- /crates/forky_play/docs/Tools.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | 3 | 4 | ## Selection Flow 5 | ```rs 6 | 7 | 8 | if select_button 9 | if moused_over 10 | if primary_selected != moused_over 11 | remove(primary_selected,_primary_select) 12 | add(moused_over,primary_select) 13 | 14 | if !multi_select_button //select,moused_over,multi_select 15 | deselect_all 16 | add(moused_over,selected) 17 | else if !multi_select_button 18 | deselect_all() 19 | 20 | if select_button && !moused_over 21 | deselect all 22 | 23 | ``` 24 | 25 | ## Resources 26 | -------------------------------------------------------------------------------- /crates/forky_play/examples/bevy_graph.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use forky_play::*; 3 | 4 | fn main() { 5 | App::new() 6 | .add_plugins(plugins::ForkyDebugPlugin::default()) 7 | .add_plugins(plugins::RotateCubePlugin) 8 | // .add_plugins(graph::BlitGraphPlugin) 9 | // .add_plugins(graph::ClearGraphPlugin) 10 | .add_systems(Update, utility::create_exit_after_system(4.)) 11 | .run(); 12 | } 13 | -------------------------------------------------------------------------------- /crates/forky_play/examples/gamai_graph.rs: -------------------------------------------------------------------------------- 1 | // use bevy::log::LogPlugin; 2 | // use bevy::prelude::*; 3 | // use bevy::winit::WinitPlugin; 4 | // use bevy_mod_debugdump::schedule_graph::Settings; 5 | // use gamai::*; 6 | // use std::fs::File; 7 | // use std::io::Write; 8 | 9 | 10 | // #[action] 11 | // fn root() {} 12 | // #[action] 13 | // fn child1() {} 14 | // #[action] 15 | // fn child2() {} 16 | // #[action] 17 | // fn child3() {} 18 | 19 | // pub fn main() -> Result<()> { 20 | // let tree1 = || { 21 | // tree! {} 22 | // // tree! { 23 | // // 24 | // // 25 | // // 26 | // // 27 | // // 28 | // // 29 | // // 30 | // // } 31 | // }; 32 | 33 | // let mut app = App::new(); 34 | 35 | // app.add_plugins(TreePlugin::new(tree1)); 36 | // // app.add_plugins(tree2.plugin()); 37 | // app.add_plugins( 38 | // DefaultPlugins 39 | // .build() 40 | // .disable::() 41 | // .disable::(), 42 | // ); 43 | // let graph = 44 | // bevy_mod_debugdump::schedule_graph_dot(&mut app, Update, &Settings { 45 | // // include_system: Some(Box::new(|_| false)), 46 | // ..default() 47 | // }); 48 | // let path = "target/graph"; 49 | // std::fs::create_dir_all(path)?; 50 | // let mut file = File::create("target/graph/render_graph.dot").unwrap(); 51 | // file.write_all(graph.as_bytes()).unwrap(); 52 | // Ok(()) 53 | // } 54 | -------------------------------------------------------------------------------- /crates/forky_play/examples/maze.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use forky_play::maze::MazePlugin; 3 | use forky_play::*; 4 | 5 | fn main() { 6 | App::new() 7 | .add_plugins(plugins::ForkyFullPlugin::default()) 8 | .add_plugins(MazePlugin) 9 | // .add_systems(Update,utility::create_exit_after_system(3.)) 10 | .run(); 11 | } 12 | -------------------------------------------------------------------------------- /crates/forky_play/examples/maze_terminal.rs: -------------------------------------------------------------------------------- 1 | // use forky_fs::*; 2 | use forky_play::maze::rect_maze::RectMaze; 3 | use forky_play::maze::*; 4 | 5 | 6 | fn main() -> ! { 7 | let mut count = 0; 8 | loop { 9 | count = count + 1; 10 | let width = 140; 11 | let height = 34; 12 | let mut maze = RectMaze::new(width, height); 13 | 14 | // terminal::clear(); 15 | maze.depth_first_backtrack(|_g| { 16 | // time::sleep_ms(16); 17 | // terminal::reset_cursor(); 18 | // let grid = maze::_rect::draw_maze(g, width, height); 19 | // let str = maze::_rect::format(&grid, width, height); 20 | // log!(str); 21 | // println!("making maze number {}", count); 22 | }); 23 | 24 | // let str = maze.format(); 25 | // file::write(format!("./output/maze_{}.txt", count), str.as_str()) 26 | // .unwrap(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/forky_play/examples/mithril.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use forky_play::mithril; 3 | 4 | #[rustfmt::skip] 5 | fn main() { 6 | App::new() 7 | .add_plugins(mithril::MithrilPlugin) 8 | .run(); 9 | } 10 | -------------------------------------------------------------------------------- /crates/forky_play/examples/node_set_graph.rs: -------------------------------------------------------------------------------- 1 | use bevy::log::LogPlugin; 2 | use bevy::prelude::*; 3 | use bevy::winit::WinitPlugin; 4 | use bevy_mod_debugdump::schedule_graph::Settings; 5 | use std::fs::File; 6 | use std::io::Write; 7 | #[derive(Debug, Default, SystemSet, Clone, Eq, PartialEq, Hash)] 8 | pub struct Set1; 9 | #[derive(Debug, Default, SystemSet, Clone, Eq, PartialEq, Hash)] 10 | pub struct Set2(pub usize); 11 | 12 | 13 | pub fn main() -> anyhow::Result<()> { 14 | let mut app = App::new(); 15 | 16 | app.configure_sets(Update, Set1.before(Set2(1))); 17 | app.configure_sets(Update, Set1.before(Set2(7))); 18 | // app.add_plugins(tree2.plugin()); 19 | app.add_plugins( 20 | DefaultPlugins 21 | .build() 22 | .disable::() 23 | .disable::(), 24 | ); 25 | let render_graph = 26 | bevy_mod_debugdump::schedule_graph_dot(&mut app, Update, &Settings { 27 | // include_system: Some(Box::new(|_| false)), 28 | ..default() 29 | }); 30 | let path = "target/graph"; 31 | std::fs::create_dir_all(path)?; 32 | let mut file = File::create("target/graph/render_graph.dot").unwrap(); 33 | file.write_all(render_graph.as_bytes()).unwrap(); 34 | Ok(()) 35 | } 36 | -------------------------------------------------------------------------------- /crates/forky_play/examples/rotate_cube.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use forky_play::*; 3 | fn main() { 4 | App::new() 5 | .add_plugins(plugins::ForkyDebugPlugin::default()) 6 | // .add_plugins(plugins::RotateCubePlugin) 7 | .run(); 8 | } 9 | -------------------------------------------------------------------------------- /crates/forky_play/examples/shader.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use forky_play::materials::UnlitTextureMaterial; 3 | use forky_play::*; 4 | 5 | fn main() { 6 | App::new() 7 | .add_plugins(plugins::ForkyDebugPlugin::default()) 8 | .add_plugins(MaterialPlugin::::default()) 9 | .add_systems(Startup, setup) 10 | .run(); 11 | } 12 | 13 | fn setup( 14 | mut commands: Commands, 15 | mut meshes: ResMut>, 16 | mut materials: ResMut>, 17 | asset_server: Res, 18 | ) { 19 | commands.spawn(MaterialMeshBundle { 20 | mesh: meshes.add(Mesh::from(Cuboid::default())), 21 | transform: Transform::from_xyz(0.0, 0.5, 0.0), 22 | material: materials.add(UnlitTextureMaterial { 23 | color: Color::GREEN, 24 | color_texture: Some(asset_server.load("branding/icon.png")), 25 | alpha_mode: AlphaMode::Blend, 26 | ..default() 27 | }), 28 | ..default() 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /crates/forky_play/examples/shader_unlit.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use forky_play::materials::UnlitMaterial; 3 | use forky_play::*; 4 | 5 | fn main() { 6 | App::new() 7 | .add_plugins(plugins::ForkyDebugPlugin::default()) 8 | .add_systems(Startup, setup) 9 | .run(); 10 | } 11 | 12 | fn setup( 13 | mut commands: Commands, 14 | mut meshes: ResMut>, 15 | mut materials: ResMut>, 16 | ) { 17 | commands.spawn(MaterialMeshBundle { 18 | mesh: meshes.add(Mesh::from(Cuboid::default())), 19 | transform: Transform::from_xyz(0.0, 0.5, 0.0), 20 | material: materials.add(UnlitMaterial { 21 | color: Color::GREEN, 22 | // color_texture: Some(asset_server.load("branding/icon.png")), 23 | alpha_mode: AlphaMode::Blend, 24 | }), 25 | ..default() 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /crates/forky_play/examples/shader_uv.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use forky_play::materials::UvMaterial; 3 | use forky_play::*; 4 | 5 | fn main() { 6 | App::new() 7 | .add_plugins(plugins::ForkyDebugPlugin::default()) 8 | .add_systems(Startup, setup) 9 | .run(); 10 | } 11 | 12 | fn setup( 13 | mut commands: Commands, 14 | mut meshes: ResMut>, 15 | mut materials: ResMut>, 16 | ) { 17 | commands.spawn(MaterialMeshBundle { 18 | mesh: meshes.add(Mesh::from(Cuboid::default())), 19 | transform: Transform::from_xyz(0.0, 0.5, 0.0), 20 | material: materials.add(UvMaterial { 21 | color: Color::GREEN, 22 | // color_texture: Some(asset_server.load("branding/icon.png")), 23 | alpha_mode: AlphaMode::Blend, 24 | }), 25 | ..default() 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /crates/forky_play/examples/spline_catmull_rom.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use forky_play::*; 3 | 4 | fn main() { 5 | let mut app = App::new(); 6 | app.__() 7 | .add_systems(Update, utility::create_exit_after_system(10.)) 8 | .add_plugins(plugins::ForkyFullPlugin::default()) 9 | .add_plugins(spline::SplinePlugin) 10 | .add_systems(Startup, setup) 11 | .run(); 12 | } 13 | 14 | 15 | 16 | fn setup( 17 | mut commands: Commands, 18 | mut graph_lookup: ResMut, 19 | mut materials: ResMut>, 20 | ) { 21 | let material = materials.add(materials::UvMaterial::default()); 22 | let graph = graph_lookup.create_graph(material); 23 | 24 | let node1 = graph.create_node(&mut commands, Vec3::new(-1., 1., 0.)); 25 | let node2 = graph.create_node(&mut commands, Vec3::new(-1., -1., 0.)); 26 | let node3 = graph.create_node(&mut commands, Vec3::new(1., -1., 0.)); 27 | let node4 = graph.create_node(&mut commands, Vec3::new(1., 1., 0.)); 28 | 29 | graph.create_edge(&mut commands, node1.node, node2.node); 30 | graph.create_edge(&mut commands, node2.node, node3.node); 31 | graph.create_edge(&mut commands, node3.node, node4.node); 32 | graph.create_edge(&mut commands, node4.node, node1.node); 33 | } 34 | -------------------------------------------------------------------------------- /crates/forky_play/examples/spline_editor.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use forky_play::*; 3 | 4 | fn main() { 5 | let mut app = App::new(); 6 | app.__() 7 | .add_plugins(plugins::ForkyFullPlugin::default()) 8 | .add_plugins(spline::SplinePlugin) 9 | .add_systems(Startup, setup) 10 | .run(); 11 | } 12 | fn setup( 13 | mut graph_lookup: ResMut, 14 | mut materials: ResMut>, 15 | ) { 16 | let material = materials.add(materials::UvMaterial::default()); 17 | graph_lookup.create_graph(material); 18 | } 19 | -------------------------------------------------------------------------------- /crates/forky_play/examples/spline_mesh.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use forky_play::spline::*; 3 | use forky_play::*; 4 | 5 | fn main() { 6 | let mut app = App::new(); 7 | app.__() 8 | // .add_systems(Update,utility::create_exit_after_system(10.)) 9 | .add_plugins(plugins::ForkyFullPlugin::default()) 10 | .add_plugins(spline::SplinePlugin) 11 | .add_systems(Startup, setup) 12 | .run(); 13 | } 14 | 15 | 16 | 17 | fn setup( 18 | mut commands: Commands, 19 | mut graph_lookup: ResMut, 20 | mut materials: ResMut>, 21 | ) { 22 | let material = materials.add(materials::UvMaterial::default()); 23 | let graph = graph_lookup.create_graph(material); 24 | 25 | let spline = Spline::Cubic(CubicSpline::new( 26 | Vec3::new(-1.0, 0., 1.), 27 | Vec3::new(-1., 0., 0.), 28 | Vec3::new(1., 0., 0.), 29 | Vec3::new(1., 0., 1.), 30 | )); 31 | 32 | graph.create_edge_from_spline(&mut commands, spline); 33 | } 34 | -------------------------------------------------------------------------------- /crates/forky_play/src/camera/fly_camera_bundle.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::*; 3 | use bevy::prelude::*; 4 | 5 | #[derive(Bundle)] 6 | pub struct FlyCameraBundle { 7 | name: Name, 8 | transform: Transform, 9 | camera: Camera3d, 10 | view_type: CameraViewType, 11 | transform_controller: input::TransformController, 12 | } 13 | 14 | impl Default for FlyCameraBundle { 15 | fn default() -> Self { 16 | Self::forward() 17 | } 18 | } 19 | 20 | impl FlyCameraBundle { 21 | pub fn new(name: &'static str, transform: Transform, view_type: CameraViewType) -> Self { 22 | Self { 23 | name: name.into(), 24 | camera: default(), 25 | transform, 26 | view_type, 27 | transform_controller: input::TransformController::default() 28 | .with_local_axis() 29 | .with_rotation_disabled() 30 | .clone(), 31 | } 32 | } 33 | 34 | pub fn right() -> Self { 35 | Self::new( 36 | "Right Camera", 37 | Transform::from_translation(Vec3::new(10., 0., 0.)).with_rotation(Quat::from_right()), 38 | CameraViewType::Right, 39 | ) 40 | } 41 | pub fn forward() -> Self { 42 | Self::new( 43 | "Forward Camera", 44 | Transform::from_translation(Vec3::new(0., 0., 10.)).with_rotation(Quat::from_forward()), 45 | CameraViewType::Front, 46 | ) 47 | } 48 | 49 | pub fn up() -> Self { 50 | Self::new( 51 | "Up Camera", 52 | Transform::from_translation(Vec3::new(0., 10., 0.)).with_rotation(Quat::from_up()), 53 | CameraViewType::Top, 54 | ) 55 | } 56 | 57 | pub fn with_position(mut self, position: Vec3) -> Self { 58 | self.transform.translation = position; 59 | self 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /crates/forky_play/src/camera/fps_camera_bundle.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | #[derive(Bundle)] 4 | pub struct FpsCameraBundle {} 5 | 6 | // impl Default for FpsCameraBundle { 7 | // fn default() -> Self { Self::new(Vec3::new(2., 3., 5.)) } 8 | // } 9 | // impl FpsCameraBundle { 10 | // pub fn new(_position: Vec3) -> Self { Self {} } 11 | // } 12 | -------------------------------------------------------------------------------- /crates/forky_play/src/camera/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod camera_view_toggle; 2 | #[allow(unused_imports)] 3 | pub use self::camera_view_toggle::*; 4 | pub mod fly_camera_bundle; 5 | #[allow(unused_imports)] 6 | pub use self::fly_camera_bundle::*; 7 | pub mod fps_camera_bundle; 8 | #[allow(unused_imports)] 9 | pub use self::fps_camera_bundle::*; 10 | pub mod orbit_camera_bundle; 11 | #[allow(unused_imports)] 12 | pub use self::orbit_camera_bundle::*; 13 | pub mod orbit_camera_controller; 14 | #[allow(unused_imports)] 15 | pub use self::orbit_camera_controller::*; 16 | pub mod orbit_keyboard_controller; 17 | #[allow(unused_imports)] 18 | pub use self::orbit_keyboard_controller::*; 19 | pub mod plugin; 20 | #[allow(unused_imports)] 21 | pub use self::plugin::*; 22 | -------------------------------------------------------------------------------- /crates/forky_play/src/camera/orbit_camera_bundle.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::*; 3 | use bevy::prelude::*; 4 | 5 | #[derive(Bundle)] 6 | pub struct OrbitCameraBundle { 7 | name: Name, 8 | camera: Camera3d, 9 | transform: Transform, 10 | parent: CameraParent, 11 | view_type: CameraViewType, 12 | controller: OrbitController, 13 | transform_controller: input::TransformController, 14 | } 15 | 16 | impl Default for OrbitCameraBundle { 17 | fn default() -> Self { 18 | Self::new(Vec3::new(2., 3., 5.)) 19 | } 20 | } 21 | impl OrbitCameraBundle { 22 | pub fn new(position: Vec3) -> Self { 23 | let radius = position.length(); 24 | Self { 25 | name: "Orbit Camera".into(), 26 | camera: default(), 27 | transform: Transform::from_translation(position).looking_at(Vec3::ZERO, Vec3::Y), 28 | parent: CameraParent, 29 | view_type: CameraViewType::Orbit, 30 | controller: OrbitController { 31 | radius, 32 | ..default() 33 | }, 34 | transform_controller: input::TransformController::default(), 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/forky_play/src/camera/orbit_keyboard_controller.rs: -------------------------------------------------------------------------------- 1 | //https://bevy-cheatbook.github.io/input/keyboard.html 2 | use super::*; 3 | use crate::*; 4 | use bevy::prelude::*; 5 | use forky_core::math::*; 6 | 7 | pub fn orbit_keyboard_controller( 8 | time: Res