bevy_animation_graph_editor 0.10.0

Animation graph editor for the Bevy game engine
Documentation
use std::{
    any::{Any, TypeId},
    marker::PhantomData,
};

use bevy::asset::{Asset, AssetServer, Assets, Handle};
use bevy_inspector_egui::reflect_inspector::InspectorUi;
use egui_dock::egui;

use super::{EguiInspectorExtension, MakeBuffer};
use crate::ui::utils::asset_sort_key;

pub struct AssetPickerInspector<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for AssetPickerInspector<T> {
    fn default() -> Self {
        Self {
            _marker: PhantomData,
        }
    }
}

impl<T: Asset> EguiInspectorExtension for AssetPickerInspector<T> {
    type Base = Handle<T>;
    type Buffer = ();

    fn mutable(
        value: &mut Self::Base,
        _: &mut Self::Buffer,
        ui: &mut egui::Ui,
        _options: &dyn Any,
        id: egui::Id,
        env: InspectorUi<'_, '_>,
    ) -> bool {
        let value_id = value.id();

        let Some(world) = env.context.world.as_mut() else {
            return false;
        };
        let (mut world_t_assets, world) = world.split_off_resource(TypeId::of::<Assets<T>>());
        let Ok(t_assets) = world_t_assets.get_resource_mut::<Assets<T>>() else {
            return false;
        };
        let Some((asset_server, _)) = world.split_off_resource_typed::<AssetServer>() else {
            return false;
        };

        let mut selected = value_id;

        egui::ComboBox::from_id_salt(id)
            .selected_text(if t_assets.contains(selected) {
                asset_server
                    .get_path(selected)
                    .map(|p| p.path().to_string_lossy().into())
                    .unwrap_or("Unsaved Asset".to_string())
            } else {
                "None".to_string()
            })
            .show_ui(ui, |ui| {
                let mut assets_ids: Vec<_> = t_assets.ids().collect();
                assets_ids.sort_by_key(|id| asset_sort_key(*id, &asset_server));
                for asset_id in assets_ids {
                    ui.selectable_value(
                        &mut selected,
                        asset_id,
                        asset_server
                            .get_path(asset_id)
                            .unwrap_or_default()
                            .path()
                            .to_str()
                            .unwrap_or_default(),
                    );
                }
            });
        if selected != value_id {
            *value = asset_server.get_id_handle(selected).unwrap();
            true
        } else {
            false
        }
    }

    fn readonly(
        _value: &Self::Base,
        buffer: &Self::Buffer,
        ui: &mut egui::Ui,
        _options: &dyn Any,
        id: egui::Id,
        mut env: InspectorUi<'_, '_>,
    ) {
        env.ui_for_reflect_readonly_with_options(buffer, ui, id, &());
    }
}

impl<T: Asset> AssetPickerInspector<T> {}

impl<T: Asset> MakeBuffer<()> for Handle<T> {
    fn make_buffer(&self) {}
}