Component used in the editor's character preview panels. It manages a CharacterFootPlacement helper to adjust a SkinnedModelRenderer based on CharacterAppearanceData (maturity and animation state) and applies updated pose when needed. The system schedules Prepare and Apply calls on the UpdateBones stage for all instances.
namespace CharacterEditor;
/// <summary>Uses the world character's proportion pass for scene-panel previews.</summary>
public sealed class CharacterPreviewGrowth : Component
{
readonly CharacterFootPlacement pose = new();
SkinnedModelRenderer body;
CharacterAppearanceData appearance;
Model lastModel;
string lastSequence;
float lastMaturity = -1;
Transform lastTransform;
bool needsPose, wasAnimated;
public void Configure(SkinnedModelRenderer target, CharacterAppearanceData data)
{
if (body != target) { pose.Dispose(); needsPose = true; }
body = target;
appearance = data;
_ = Scene.GetSystem<CharacterPreviewGrowthSystem>();
}
internal void Prepare()
{
if (!body.IsValid() || appearance is null) return;
bool animated = body.UseAnimGraph && body.PlaybackRate != 0;
needsPose |= animated || wasAnimated != animated || lastModel != body.Model || lastSequence != body.Sequence.Name || lastMaturity != appearance.BodyMaturity || lastTransform != body.WorldTransform;
wasAnimated = animated;
if (needsPose) pose.Prepare(body);
}
internal void Apply()
{
if (!needsPose || !body.IsValid() || appearance is null) return;
pose.Update(body, appearance, groundFeet: false, allowEditor: true);
lastModel = body.Model;
lastSequence = body.Sequence.Name;
lastMaturity = appearance.BodyMaturity;
lastTransform = body.WorldTransform;
needsPose = false;
}
protected override void OnEnabled() => needsPose = true;
protected override void OnDisabled() { pose.Dispose(); needsPose = true; }
protected override void OnDestroy() => pose.Dispose();
}
public sealed class CharacterPreviewGrowthSystem : GameObjectSystem<CharacterPreviewGrowthSystem>
{
public CharacterPreviewGrowthSystem(Scene scene) : base(scene)
{
Listen(Stage.UpdateBones, -100, Prepare, "Prepare preview proportions");
Listen(Stage.UpdateBones, 100, Apply, "Apply preview proportions");
}
void Prepare() { foreach (var preview in Scene.GetAllComponents<CharacterPreviewGrowth>()) preview.Prepare(); }
void Apply() { foreach (var preview in Scene.GetAllComponents<CharacterPreviewGrowth>()) preview.Apply(); }
}