rusteal 0.8.0

Rust bindings for Unreal Engine 5.8.2
use bindings::manual::world_ext::new_object;
use bindings::rusteal_editor::RustealEditorSubsystem;
use bindings::tool_menus::{ToolMenuEntryScript, ToolMenuEntryScriptExt};
use rusteal_runtime::runtime::{FName, RustealResult, UObjectRef};
use rusteal_runtime::{uclass, uclass_impl};

use crate::menu::{{ plugin }}MenuEntry;

#[uclass(parent = RustealEditorSubsystem)]
pub struct {{ plugin }}EditorSubsystem {
    #[uproperty(BlueprintReadOnly, category = "{{ plugin }}")]
    menu_entry: UObjectRef<ToolMenuEntryScript>,
}

#[uclass_impl]
impl {{ plugin }}EditorSubsystem {
    #[ufunction(Override)]
    fn receive_initialize(&mut self) {
        log::info!("[{{ plugin }}] Hello from the editor");

        if let Err(e) = self.add_menu_entry() {
            log::warn!("[{{ plugin }}] no menu entry: {e:?}");
        }
    }

    #[ufunction(Override)]
    fn receive_deinitialize(&mut self) {
        if let Ok(entry) = self.menu_entry().checked() {
            entry.unregister_menu_entry();
        }
    }

    fn add_menu_entry(&mut self) -> RustealResult<()> {
        let entry =
            new_object::<{{ plugin }}MenuEntry>(&self.as_ref())?.upcast_to::<ToolMenuEntryScript>();
        let script = entry.checked()?;

        script.init_entry(
            FName::new("{{ plugin }}").handle(),
            FName::new("LevelEditor.MainMenu.Tools").handle(),
            FName::new("{{ plugin }}").handle(),
            FName::new("{{ plugin }}CountAssets").handle(),
            Some("Count assets"),
            Some("Count the project's assets by type, off the game thread"),
        );

        script.register_menu_entry();
        self.set_menu_entry(entry);

        Ok(())
    }
}