Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions AnimationEditor/how to/01-create-applet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# 01 — Create a new Animation applet (editor)

This guide shows how to add a new Animation applet (editor) following the same structure as
`AnimationKeyframeEditorViewModel` and `MountAnimationCreatorViewModel`.

Where to put code
- Place your editor-specific files under `Editors/AnimationEditor/<YourAppletName>/` (this is consistent with the existing editors).
- Example existing editors:
- `Editors/AnimationEditor/AnimationKeyframeEditor/AnimationKeyframeEditorViewModel.cs`
- `Editors/AnimationEditor/MountAnimationCreator/MountAnimationCreatorViewModel.cs`

High level steps
1. Create a ViewModel class (recommended: derive from `EditorHostBase`).
2. (Optional) Create a custom view `UserControl` if you want a custom UI; otherwise the shared `EditorHostView` is used.
3. Add a `Create(...)` method and wire your SceneObjects and services exactly like the existing editors.
4. Add any helper classes (ViewModels, sub-ViewModels) under your folder.

Minimal ViewModel skeleton (copy & adapt)

```csharp
// file: Editors/AnimationEditor/MyApplet/MyAppletViewModel.cs
using System;
using Editors.Shared.Core.Common.BaseControl;
using Editors.Shared.Core.Common;
using Editors.Shared.Core.Common.AnimationPlayer;
using Shared.Core.ToolCreation;
using Microsoft.Extensions.DependencyInjection; // (for DI registration example later)

namespace Editors.AnimationVisualEditors.MyApplet
{
public partial class MyAppletViewModel : EditorHostBase
{
public override Type EditorViewModelType => typeof(AnimationEditor.Common.BaseControl.EditorHostView);

// Dependencies you typically need — match constructor to what DI can provide.
public MyAppletViewModel(
IEditorHostParameters editorHostParameters,
SceneObjectViewModelBuilder sceneObjectViewModelBuilder,
AnimationPlayerViewModel animationPlayerViewModel,
SceneObjectEditor sceneObjectEditor,
IPackFileService pfs,
ISkeletonAnimationLookUpHelper skeletonAnimationLookUpHelper,
SelectionManager selectionManager,
IFileSaveService fileSaveService,
IUiCommandFactory uiCommandFactory) : base(editorHostParameters)
{
DisplayName = "My Applet";

// Use the provided builders/services to create default scene objects the same way
// other editors do to ensure things like MountLinkController are initialized.
var riderItem = sceneObjectViewModelBuilder.CreateAsset("IDK", true, "Rider", Microsoft.Xna.Framework.Color.Black, null);
var mountItem = sceneObjectViewModelBuilder.CreateAsset("IDK", true, "Mount", Microsoft.Xna.Framework.Color.Black, null);
mountItem.Data.IsSelectable = true;

var newAnimAsset = sceneObjectEditor.CreateAsset("IDK", "New Anim", Microsoft.Xna.Framework.Color.Red);
animationPlayerViewModel.RegisterAsset(newAnimAsset);

Create(riderItem.Data, mountItem.Data, newAnimAsset);
SceneObjects.Add(riderItem);
SceneObjects.Add(mountItem);
}

internal void Create(SceneObject rider, SceneObject mount, SceneObject newAnimation)
{
// store refs, hook events, create sub-viewmodels etc.
}
}
}
```

Notes about using `EditorHostBase`
- The shared `EditorHostView` is used by many editors and is a good default unless you need custom UI.
- Put logic that wires SceneObjects and registers with the `AnimationPlayerViewModel` into the constructor, or into a helper `Create(...)` method similar to existing editors.

Common pitfalls
- If you leave essential components (like the MountLink controller in the Mount editor) uncreated until some manual initialization, code that expects them on startup can get NullReferenceExceptions. The pattern in the repo is to create at least default Rider/Mount/NewAnim scene objects in the constructor so the editor is ready.
- Be mindful of the non-nullable reference warnings. You can:
- initialize fields eagerly,
- mark them nullable if they legitimately start null, or
- ensure constructors always initialize them.

Testing
- Build the solution. If there are DI or registration errors the build/run will tell you which types are missing.
- Next step is to register the applet in DI and the editor database (see `02-register-and-debug.md`).

References
- Example ViewModels to copy from:
- `Editors/AnimationEditor/AnimationKeyframeEditor/AnimationKeyframeEditorViewModel.cs`
- `Editors/AnimationEditor/MountAnimationCreator/MountAnimationCreatorViewModel.cs`

--
128 changes: 128 additions & 0 deletions AnimationEditor/how to/02-register-and-debug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# 02 — Register your applet in DI and add a dev-config for quick debug

After you add your ViewModel (see `01-create-applet.md`), register it so the editor host can create and show it.

1) Add the ViewModel to the animation editors DI container

Edit the container at:

```
TheAssetEditor/Editors/AnimationEditor/DependencyInjectionContainer.cs
```

Inside `Register(IServiceCollection serviceCollection)` add a scoped registration for your view model:

```csharp
serviceCollection.AddScoped<MyAppletViewModel>();
```

This mirrors how the repo registers existing editors:

```csharp
serviceCollection.AddScoped<MountAnimationCreatorViewModel>();
serviceCollection.AddScoped<AnimationKeyframeEditorViewModel>();
```

2) Register the editor in the editor database (so it appears in the toolbar/menu)

In the same `DependencyInjectionContainer`, implement `RegisterTools(IEditorDatabase database)` and add an EditorInfo entry. Example:

```csharp
EditorInfoBuilder
.Create<MyAppletViewModel, AnimationEditor.Common.BaseControl.EditorHostView>(EditorEnums.MyApplet_Editor)
.AddToToolbar("My Applet", true)
.Build(database);
```

Notes:
- `EditorHostView` is the default shared host view. Use a custom UserControl type here if you created a custom UI view for your applet.
- `EditorEnums.MyApplet_Editor` must exist in the `EditorEnums` enum (see next step).

3) Add an enum value for your editor

Open:

```
Shared/SharedCore/Shared.Core/ToolCreation/EditorEnums.cs
```

Add an entry (for example):

```csharp
public enum EditorEnums
{
...
MyApplet_Editor,
None,
}
```

Make sure the enum value is unique and update any usages if necessary.

4) (Optional) Add a dev-config so your app opens pre-configured for development

To open your editor automatically (with sample inputs), add a dev-config like the repo's `MountTool` example. Create a class under `Editors/AnimationEditor/MyApplet/DevConfig/MyAppletDevConfig.cs` implementing `IDeveloperConfiguration`.

Sample DevConfig (copy & adapt from `MountTool`):

```csharp
using Shared.Core.DevConfig;
using Shared.Core.ToolCreation;
using Shared.Core.PackFiles; // for packfile lookups

namespace Editors.AnimationVisualEditors.MyApplet.DevConfig
{
internal class MyAppletDevConfig : IDeveloperConfiguration
{
private readonly IEditorManager _editorManager;
private readonly IPackFileService _packFileService;

public MyAppletDevConfig(IEditorManager editorManager, IPackFileService packFileService)
{
_editorManager = editorManager;
_packFileService = packFileService;
}

public void OverrideSettings(ApplicationSettings currentSettings)
{
// if you need to change game settings for development/testing
}

public void OpenFileOnLoad()
{
// create a debug AnimationToolInput (like MountTool does)
var input = new AnimationToolInput()
{
Mesh = _packFileService.FindFile("variantmeshes\\...\\some.variantmeshdefinition"),
Animation = _packFileService.FindFile("animations\\...\\some.anim")
};

_editorManager.Create(EditorEnums.MyApplet_Editor, x => (x as MyAppletViewModel)?.SetDebugInputParameters(input));
}
}
}
```

This is useful for quickly launching your editor preloaded with assets.

5) Build and run

- Build the solution and run the host application.
- The editor toolbar should show your applet (if you used `.AddToToolbar(...)`).
- Use the toolbar button or the editor manager to create your editor.

Troubleshooting
- If constructor dependencies are missing, ensure the required services are registered in other DI containers that the top-level bootstrapping includes (the project has many specialized DI containers; the Animation DI container depends on other shared containers).
- If your editor throws NREs at startup related to missing controllers, follow the pattern in `MountAnimationCreatorViewModel` and create default Rider/Mount/NewAnim objects in the constructor so dependent controllers are created immediately.

Extra: register a custom view
- If you create a custom `UserControl` for your applet (e.g. `MyAppletView`), register it (AddTransient) in the DI container and change the EditorInfo registration to:

```csharp
EditorInfoBuilder
.Create<MyAppletViewModel, MyAppletView>(EditorEnums.MyApplet_Editor)
.AddToToolbar("My Applet", true)
.Build(database);
```

That's it — you should now be able to add and iterate on an applet using the same patterns as the repo's keyframe and mount editors.
Loading