bevy_animation_graph_editor 0.9.0

Animation graph editor for the Bevy game engine
Documentation
mod egui_nodes;
mod graph_show;
mod icons;
mod scanner;
mod tree;
mod ui;

use std::path::PathBuf;

use bevy::{camera::visibility::RenderLayers, prelude::*};
use bevy_animation_graph::AnimationGraphPlugin;
use bevy_egui::{EguiPlugin, EguiPrimaryContextPass};
use bevy_inspector_egui::{DefaultInspectorConfigPlugin, bevy_egui};
use clap::Parser;
use graph_show::GraphIndicesMap;
use scanner::ScannerPlugin;
use ui::{
    UiState,
    actions::{PendingActions, clip_preview::ClipPreviewScenes, saving::DirtyAssets},
    egui_inspector_impls::BetterInspectorPlugin,
};

use crate::ui::node_editors::register_node_editables;

#[derive(Parser, Resource)]
struct Cli {
    #[arg(short, long)]
    asset_source: PathBuf,
}

/// Will start up an animation graph asset editor. This plugin will add all other required
/// plugins: if you use it, do not add [`DefaultPlugins`], [`EguiPlugin`] or others manually (see
/// plugin source code for full up-to-date list).
///
/// This plugin also takes care of command-line parsing.
///
/// You only need to add plugins necessary to register your custom animation node types, if you
/// have any.
pub struct AnimationGraphEditorPlugin;

impl Plugin for AnimationGraphEditorPlugin {
    fn build(&self, app: &mut App) {
        let cli = Cli::parse();

        app //
            .add_plugins(
                DefaultPlugins
                    .set(AssetPlugin {
                        file_path: std::fs::canonicalize(&cli.asset_source)
                            .unwrap()
                            .to_string_lossy()
                            .into(),
                        watch_for_changes_override: Some(true),
                        ..Default::default()
                    })
                    .set(WindowPlugin {
                        primary_window: Some(Window {
                            title: format!(
                                "Bevy Animation Graph Editor {}",
                                env!("CARGO_PKG_VERSION")
                            ),
                            ..Default::default()
                        }),
                        ..Default::default()
                    }),
            )
            .add_plugins(EguiPlugin::default())
            .add_plugins(AnimationGraphPlugin::from_physics_schedule(FixedPostUpdate))
            .add_plugins(DefaultInspectorConfigPlugin)
            .add_plugins(BetterInspectorPlugin)
            // .add_plugins(bevy_inspector_egui::quick::WorldInspectorPlugin::new())
            .add_plugins(ScannerPlugin);

        #[cfg(feature = "physics_avian")]
        app.add_plugins(avian3d::prelude::PhysicsPlugins::new(FixedPostUpdate));

        UiState::init(app.world_mut());

        app.insert_resource(PendingActions::default())
            .insert_resource(DirtyAssets::default())
            .insert_resource(GraphIndicesMap::default())
            .insert_resource(ClipPreviewScenes::default())
            .insert_resource(cli);

        register_node_editables(app);

        app.add_systems(Startup, setup);

        app.add_systems(
            EguiPrimaryContextPass,
            (
                ui::setup_ui,
                ui::show_ui_system,
                ui::actions::process_actions_system,
                ui::override_scene_animations,
                ui::render_pose_gizmos,
                ui::propagate_layers,
            )
                .chain(),
        );
    }
}

#[derive(Component)]
struct UiCamera;
pub fn setup(mut commands: Commands) {
    commands.spawn((
        Camera2d,
        UiCamera,
        bevy_egui::PrimaryEguiContext,
        RenderLayers::none(),
    ));
}