├── .gitignore ├── rustfmt.toml ├── assets ├── bevy_icon.png └── example.curve.ron ├── .vscode └── settings.json ├── src ├── editor │ ├── mod.rs │ ├── editor_bevy.rs │ └── editor_egui.rs ├── asset.rs ├── knot_search.rs ├── inspector.rs └── lib.rs ├── LICENSE-MIT ├── examples ├── inspector_egui.rs ├── egui_only.rs ├── dev.rs ├── console.rs └── animation.rs ├── .github └── workflows │ └── ci.yml ├── benches ├── knot_search.rs └── lookup_curve.rs ├── Cargo.toml ├── README.md ├── CHANGELOG.md └── LICENSE-APACHE /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | .ignore 4 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | use_field_init_shorthand = true 2 | newline_style = "Unix" -------------------------------------------------------------------------------- /assets/bevy_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/villor/bevy_lookup_curve/HEAD/assets/bevy_icon.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 4, 3 | "editor.insertSpaces": true, 4 | "files.eol": "\n", 5 | "files.encoding": "utf8", 6 | "rust-analyzer.cargo.features": "all" 7 | } -------------------------------------------------------------------------------- /src/editor/mod.rs: -------------------------------------------------------------------------------- 1 | //! Contains editor implementations for `LookupCurve`s. 2 | mod editor_egui; 3 | pub use editor_egui::*; 4 | 5 | #[cfg(feature = "editor_bevy")] 6 | mod editor_bevy; 7 | #[cfg(feature = "editor_bevy")] 8 | pub use editor_bevy::*; 9 | -------------------------------------------------------------------------------- /assets/example.curve.ron: -------------------------------------------------------------------------------- 1 | ( 2 | knots: [ 3 | ( 4 | position: (0.0, 0.0), 5 | interpolation: Cubic, 6 | left_tangent: ( 7 | slope: 0.0, 8 | mode: Aligned, 9 | ), 10 | right_tangent: ( 11 | slope: 0.0, 12 | mode: Aligned, 13 | ), 14 | ), 15 | ( 16 | position: (0.3830273, 0.5604923), 17 | interpolation: Cubic, 18 | left_tangent: ( 19 | slope: 0.0, 20 | mode: Aligned, 21 | ), 22 | right_tangent: ( 23 | slope: 0.0, 24 | mode: Aligned, 25 | ), 26 | ), 27 | ( 28 | position: (1.0, 1.0), 29 | interpolation: Cubic, 30 | left_tangent: ( 31 | slope: 0.0, 32 | mode: Aligned, 33 | ), 34 | right_tangent: ( 35 | slope: 0.0, 36 | mode: Aligned, 37 | ), 38 | ), 39 | ] 40 | ) -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/inspector_egui.rs: -------------------------------------------------------------------------------- 1 | //! This example demonstrates the usage of the `inspector-egui` feature. 2 | use bevy::prelude::*; 3 | use bevy_inspector_egui::quick::{AssetInspectorPlugin, ResourceInspectorPlugin}; 4 | 5 | use bevy_lookup_curve::prelude::*; 6 | 7 | fn main() { 8 | App::new() 9 | .add_plugins(DefaultPlugins) 10 | .add_plugins(LookupCurvePlugin) 11 | .add_plugins(AssetInspectorPlugin::::default()) 12 | .register_type::() 13 | .add_plugins(ResourceInspectorPlugin::::default()) 14 | .add_systems(Startup, setup) 15 | .run(); 16 | } 17 | 18 | #[derive(Resource, Default, Reflect)] 19 | struct LookupCurveDevState { 20 | curve_handle: Handle, 21 | curve_noasset: LookupCurve, 22 | } 23 | 24 | fn setup(mut commands: Commands, assets: Res) { 25 | let handle = assets.load("example.curve.ron"); 26 | 27 | commands.insert_resource(LookupCurveDevState { 28 | curve_handle: handle, 29 | curve_noasset: LookupCurve::default(), 30 | }); 31 | } 32 | -------------------------------------------------------------------------------- /src/asset.rs: -------------------------------------------------------------------------------- 1 | //! Contains the asset loader plugin for `LookupCurve` assets. 2 | use bevy_app::{App, Plugin}; 3 | use bevy_asset::{AssetApp, AssetLoader, LoadContext, io::Reader}; 4 | 5 | use crate::{LookupCurve, LookupCurveLoadError}; 6 | 7 | pub(crate) struct AssetPlugin; 8 | 9 | impl Plugin for AssetPlugin { 10 | fn build(&self, app: &mut App) { 11 | app.init_asset::(); 12 | app.register_asset_loader(LookupCurveAssetLoader); 13 | } 14 | } 15 | 16 | #[derive(Default)] 17 | pub struct LookupCurveAssetLoader; 18 | 19 | impl AssetLoader for LookupCurveAssetLoader { 20 | type Asset = LookupCurve; 21 | type Settings = (); 22 | type Error = LookupCurveLoadError; 23 | 24 | async fn load( 25 | &self, 26 | reader: &mut dyn Reader, 27 | _settings: &(), 28 | _load_context: &mut LoadContext<'_>, 29 | ) -> Result { 30 | let mut bytes = Vec::new(); 31 | reader.read_to_end(&mut bytes).await?; 32 | let lookup_curve = ron::de::from_bytes::(&bytes)?; 33 | Ok(lookup_curve) 34 | } 35 | 36 | fn extensions(&self) -> &[&str] { 37 | &["curve.ron"] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/egui_only.rs: -------------------------------------------------------------------------------- 1 | //! Demonstrates using bevy_lookup_curve with just egui, no bevy app. 2 | //! 3 | //! This example has no dependencies on bevy except `bevy_math`. 4 | use eframe::egui; 5 | 6 | use bevy_lookup_curve::prelude::*; 7 | 8 | fn main() -> eframe::Result { 9 | let options = eframe::NativeOptions { 10 | viewport: egui::ViewportBuilder::default().with_inner_size([800.0, 400.0]), 11 | ..Default::default() 12 | }; 13 | 14 | let path = "./assets/example.curve.ron"; 15 | let lookup_curve = LookupCurve::load_from_file(path).expect("Failed to load curve"); 16 | 17 | eframe::run_native( 18 | "Lookup Curve (egui only example)", 19 | options, 20 | Box::new(|_| { 21 | Ok(Box::new(MyApp { 22 | lookup_curve, 23 | editor: LookupCurveEguiEditor::with_save_path(path.to_string()), 24 | })) 25 | }), 26 | ) 27 | } 28 | 29 | struct MyApp { 30 | lookup_curve: LookupCurve, 31 | editor: LookupCurveEguiEditor, 32 | } 33 | 34 | impl eframe::App for MyApp { 35 | fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { 36 | egui::CentralPanel::default() 37 | .show(ctx, |ui| self.editor.ui(ui, &mut self.lookup_curve, None)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/dev.rs: -------------------------------------------------------------------------------- 1 | //! Includes most of the functionality of the crate, for development and testing purposes. 2 | use bevy::prelude::*; 3 | use bevy_egui::EguiPlugin; 4 | use bevy_inspector_egui::quick::{AssetInspectorPlugin, ResourceInspectorPlugin}; 5 | 6 | use bevy_lookup_curve::prelude::*; 7 | 8 | fn main() { 9 | App::new() 10 | .add_plugins(DefaultPlugins) 11 | .add_plugins(EguiPlugin::default()) 12 | .add_plugins(LookupCurvePlugin) 13 | .add_plugins(AssetInspectorPlugin::::default()) 14 | .register_type::() 15 | .add_plugins(ResourceInspectorPlugin::::default()) 16 | .add_systems(Startup, setup) 17 | .add_systems(Update, move_sample) 18 | .run(); 19 | } 20 | 21 | #[derive(Resource, Default, Reflect)] 22 | struct LookupCurveDevState { 23 | curve_handle: Handle, 24 | curve_noasset: LookupCurve, 25 | sample_dir: f32, 26 | sample: f32, 27 | move_sample: bool, 28 | } 29 | 30 | fn setup(mut commands: Commands, assets: Res) { 31 | commands.spawn(Camera2d); 32 | 33 | let handle = assets.load("example.curve.ron"); 34 | 35 | commands.spawn(LookupCurveEditor { 36 | sample: Some(0.0), 37 | ..LookupCurveEditor::with_save_path( 38 | handle.clone(), 39 | "./assets/example.curve.ron".to_string(), 40 | ) 41 | }); 42 | 43 | commands.insert_resource(LookupCurveDevState { 44 | curve_handle: handle, 45 | curve_noasset: LookupCurve::default(), 46 | sample_dir: 1.0, 47 | sample: 0.0, 48 | move_sample: true, 49 | }); 50 | } 51 | 52 | fn move_sample( 53 | mut dev_state: ResMut, 54 | mut editor: Query<&mut LookupCurveEditor>, 55 | time: Res