Refactoring

This commit is contained in:
Ivan Anikin
2026-05-20 15:33:00 +07:00
parent 8732ce99e3
commit 86baa476f4
41 changed files with 287 additions and 1513 deletions
@@ -64,10 +64,6 @@ namespace
TargetPreset.bLoop = SourcePreset.bLoop;
TargetPreset.LoopDelay = SourcePreset.LoopDelay;
TargetPreset.BlendSpeedOverride = SourcePreset.BlendSpeedOverride;
TargetPreset.AnimationMontage = SourcePreset.AnimationMontage;
TargetPreset.AnimationPlayRate = SourcePreset.AnimationPlayRate;
TargetPreset.AnimationStartSection = SourcePreset.AnimationStartSection;
TargetPreset.bRestartAnimationOnReplay = SourcePreset.bRestartAnimationOnReplay;
}
}
@@ -4,10 +4,7 @@
#include "Animation/AnimData/IAnimationDataController.h"
#include "AnimPreviewInstance.h"
#include "Animation/AnimMontage.h"
#include "Animation/AnimSequence.h"
#include "Animation/AnimSequenceBase.h"
#include "Animation/AnimationAsset.h"
#include "Animation/DebugSkelMeshComponent.h"
#include "Animation/Skeleton.h"
#include "Components/SkeletalMeshComponent.h"
@@ -115,15 +112,7 @@ float FMorphPresetEditorController::GetTimelineLength() const
{
if (const UMorphPresetDataAsset* PresetAsset = Preset.Get())
{
float TimelineLength = PresetAsset->GetTimelineLength();
if (PresetAsset->AnimationMontage)
{
const float PlayRate = FMath::Max(PresetAsset->AnimationPlayRate, 0.01f);
const UAnimSequenceBase* PreviewSequence = PresetAsset->AnimationMontage->GetFirstAnimReference();
const float AnimationLength = PreviewSequence ? PreviewSequence->GetPlayLength() : PresetAsset->AnimationMontage->GetPlayLength();
TimelineLength = FMath::Max(TimelineLength, AnimationLength / PlayRate);
}
return FMath::Max(TimelineLength, 0.1f);
return FMath::Max(PresetAsset->GetTimelineLength(), 0.1f);
}
return 1.0f;
@@ -145,7 +134,7 @@ void FMorphPresetEditorController::SetCurrentTime(float InTime)
if (PreviewMeshComponent->PreviewInstance)
{
PreviewMeshComponent->PreviewInstance->SetPlaying(false);
PreviewMeshComponent->PreviewInstance->SetPosition(GetPreviewAnimationPosition(), false);
PreviewMeshComponent->PreviewInstance->SetPosition(CurrentTime, false);
RefreshPreviewAnimationPose();
}
}
@@ -225,20 +214,21 @@ void FMorphPresetEditorController::NotifyPresetEdited(bool bBroadcastPresetChang
PresetAsset->MarkPackageDirty();
}
UAnimationAsset* DesiredPreviewAsset = ResolvePreviewAnimationAsset();
UAnimationAsset* CurrentPreviewAsset = nullptr;
if (TSharedPtr<IPersonaPreviewScene> PreviewScene = GetPreviewScene())
if (ActivePreviewMesh.Get() != GetPreviewMesh())
{
CurrentPreviewAsset = PreviewScene->GetPreviewAnimationAsset();
RebuildPreviewScene();
if (bBroadcastPresetChanged)
{
PresetChanged.Broadcast();
}
return;
}
if (DesiredPreviewAsset != CurrentPreviewAsset ||
(DesiredPreviewAsset && PreviewAnimation.IsValid()) ||
(!DesiredPreviewAsset && !PreviewAnimation.IsValid()))
if (!PreviewAnimation.IsValid())
{
RebuildPreviewAnimation();
}
else if (PreviewAnimation.IsValid())
else
{
SetAnimSequencePlayLength(*PreviewAnimation, GetTimelineLength(), false);
}
@@ -436,6 +426,7 @@ void FMorphPresetEditorController::RebuildPreviewScene()
PreviewAnimation.Reset();
USkeletalMesh* PreviewMesh = GetPreviewMesh();
ActivePreviewMesh = PreviewMesh;
if (PreviewMesh == nullptr)
{
PreviewSceneChanged.Broadcast();
@@ -464,56 +455,29 @@ void FMorphPresetEditorController::RebuildPreviewAnimation()
PreviewAnimation.Reset();
PreviewStatusText = FText::GetEmpty();
UAnimationAsset* PreviewAsset = ResolvePreviewAnimationAsset();
if (PreviewAsset && !IsPreviewAnimationCompatible(PreviewAsset))
PreviewAnimation = TStrongObjectPtr<UAnimSequence>(AnimSequence);
SetAnimSequencePlayLength(*AnimSequence, GetTimelineLength(), false);
if (USkeletalMesh* PreviewMesh = GetPreviewMesh())
{
const USkeletalMesh* PreviewMesh = GetPreviewMesh();
const FString PreviewMeshSkeletonName = PreviewMesh && PreviewMesh->GetSkeleton()
? PreviewMesh->GetSkeleton()->GetPathName()
: TEXT("None");
const FString AnimationSkeletonName = PreviewAsset->GetSkeleton()
? PreviewAsset->GetSkeleton()->GetPathName()
: TEXT("None");
PreviewStatusText = FText::FromString(FString::Printf(
TEXT("Animation preview is disabled: montage sequence '%s' uses skeleton '%s', but Preview Mesh uses '%s'. Retarget the animation to the Preview Mesh skeleton."),
*GetNameSafe(PreviewAsset),
*AnimationSkeletonName,
*PreviewMeshSkeletonName));
UE_LOG(LogMorphPresetEditorPreview, Warning, TEXT("%s"), *PreviewStatusText.ToString());
PreviewAsset = nullptr;
}
if (!PreviewAsset)
{
PreviewAnimation = TStrongObjectPtr<UAnimSequence>(AnimSequence);
PreviewAsset = AnimSequence;
SetAnimSequencePlayLength(*AnimSequence, GetTimelineLength(), false);
if (USkeletalMesh* PreviewMesh = GetPreviewMesh())
if (USkeleton* Skeleton = PreviewMesh->GetSkeleton())
{
if (USkeleton* Skeleton = PreviewMesh->GetSkeleton())
{
AnimSequence->SetSkeleton(Skeleton);
}
AnimSequence->SetSkeleton(Skeleton);
}
}
PreviewScene->SetPreviewAnimationAsset(PreviewAsset, true);
PreviewScene->SetPreviewAnimationAsset(AnimSequence, true);
if (UDebugSkelMeshComponent* PreviewMeshComponent = PreviewScene->GetPreviewMeshComponent())
{
PreviewMeshComponent->SetAnimationMode(EAnimationMode::AnimationSingleNode);
if (PreviewMeshComponent->PreviewInstance)
{
const UMorphPresetDataAsset* PresetAsset = Preset.Get();
const float PlayRate = PresetAsset ? FMath::Max(PresetAsset->AnimationPlayRate, 0.01f) : 1.0f;
PreviewMeshComponent->PreviewInstance->SetAnimationAsset(PreviewAsset, false, PlayRate);
PreviewMeshComponent->PreviewInstance->SetAnimationAsset(AnimSequence, false, 1.0f);
PreviewMeshComponent->PreviewInstance->EnableControllers(true);
PreviewMeshComponent->PreviewInstance->SetSkeletalControlAlpha(1.0f);
PreviewMeshComponent->PreviewInstance->SetPlaying(false);
PreviewMeshComponent->PreviewInstance->SetLooping(false);
PreviewMeshComponent->PreviewInstance->SetPosition(GetPreviewAnimationPosition(), false);
PreviewMeshComponent->PreviewInstance->SetPosition(CurrentTime, false);
RefreshPreviewAnimationPose();
}
}
@@ -539,52 +503,6 @@ void FMorphPresetEditorController::RefreshPreviewAnimationPose()
PreviewScene->InvalidateViews();
}
UAnimationAsset* FMorphPresetEditorController::ResolvePreviewAnimationAsset() const
{
const UMorphPresetDataAsset* PresetAsset = Preset.Get();
if (PresetAsset && PresetAsset->AnimationMontage)
{
if (UAnimSequenceBase* FirstAnimReference = PresetAsset->AnimationMontage->GetFirstAnimReference())
{
return FirstAnimReference;
}
}
return nullptr;
}
float FMorphPresetEditorController::GetPreviewAnimationPosition() const
{
const UMorphPresetDataAsset* PresetAsset = Preset.Get();
UAnimationAsset* PreviewAsset = ResolvePreviewAnimationAsset();
if (!PresetAsset || !PreviewAsset)
{
return CurrentTime;
}
const float PlayRate = FMath::Max(PresetAsset->AnimationPlayRate, 0.01f);
float PreviewPosition = CurrentTime * PlayRate;
if (const UAnimSequenceBase* PreviewSequence = Cast<UAnimSequenceBase>(PreviewAsset))
{
return FMath::Clamp(PreviewPosition, 0.0f, PreviewSequence->GetPlayLength());
}
return PreviewPosition;
}
bool FMorphPresetEditorController::IsPreviewAnimationCompatible(UAnimationAsset* PreviewAsset) const
{
if (!PreviewAsset)
{
return true;
}
const USkeletalMesh* PreviewMesh = GetPreviewMesh();
const USkeleton* PreviewSkeleton = PreviewMesh ? PreviewMesh->GetSkeleton() : nullptr;
const USkeleton* AnimationSkeleton = PreviewAsset->GetSkeleton();
return PreviewSkeleton && AnimationSkeleton && PreviewSkeleton->IsCompatibleForEditor(AnimationSkeleton);
}
void FMorphPresetEditorController::ApplyPresetToPreview()
{
const UMorphPresetDataAsset* PresetAsset = Preset.Get();
@@ -13,7 +13,9 @@
#include "PropertyCustomizationHelpers.h"
#include "SEditorViewport.h"
#include "Sound/SoundBase.h"
#include "ToolMenus.h"
#include "Toolkits/AssetEditorToolkit.h"
#include "ViewportToolbar/UnrealEdViewportToolbar.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Input/SEditableTextBox.h"
#include "Widgets/Input/SSlider.h"
@@ -118,11 +120,13 @@ namespace
public:
SLATE_BEGIN_ARGS(SMorphPresetPreviewViewport) {}
SLATE_ARGUMENT(TSharedPtr<FMorphPresetEditorController>, Controller)
SLATE_ARGUMENT(TWeakPtr<FAssetEditorToolkit>, AssetEditorToolkit)
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
Controller = InArgs._Controller;
AssetEditorToolkit = InArgs._AssetEditorToolkit;
SEditorViewport::Construct(SEditorViewport::FArguments());
}
@@ -146,11 +150,45 @@ namespace
virtual TSharedPtr<SWidget> BuildViewportToolbar() override
{
return SNullWidget::NullWidget;
const FName ViewportToolbarName = TEXT("MorphPresetEditor.ViewportToolbar");
if (!UToolMenus::Get()->IsMenuRegistered(ViewportToolbarName))
{
UToolMenu* const ViewportToolbarMenu = UToolMenus::Get()->RegisterMenu(
ViewportToolbarName,
NAME_None,
EMultiBoxType::SlimHorizontalToolBar);
ViewportToolbarMenu->StyleName = TEXT("ViewportToolbar");
FToolMenuSection& LeftSection = ViewportToolbarMenu->AddSection(TEXT("Left"));
LeftSection.AddEntry(UE::UnrealEd::CreateTransformsSubmenu());
LeftSection.AddEntry(UE::UnrealEd::CreateSnappingSubmenu());
FToolMenuSection& RightSection = ViewportToolbarMenu->AddSection(TEXT("Right"));
RightSection.Alignment = EToolMenuSectionAlign::Last;
RightSection.AddEntry(UE::UnrealEd::CreateCameraSubmenu(UE::UnrealEd::FViewportCameraMenuOptions().ShowAll()));
RightSection.AddEntry(UE::UnrealEd::CreateViewModesSubmenu());
RightSection.AddEntry(UE::UnrealEd::CreatePerformanceAndScalabilitySubmenu());
}
FToolMenuContext ViewportToolbarContext;
if (TSharedPtr<IPersonaPreviewScene> PreviewScene = Controller.IsValid() ? Controller->GetPreviewScene() : nullptr)
{
ViewportToolbarContext.AppendCommandList(PreviewScene->GetCommandList());
}
ViewportToolbarContext.AppendCommandList(GetCommandList());
UUnrealEdViewportToolbarContext* const ContextObject =
UE::UnrealEd::CreateViewportToolbarDefaultContext(SharedThis(this));
ContextObject->AssetEditorToolkit = AssetEditorToolkit;
ViewportToolbarContext.AddObject(ContextObject);
return UToolMenus::Get()->GenerateWidget(ViewportToolbarName, ViewportToolbarContext);
}
private:
TSharedPtr<FMorphPresetEditorController> Controller;
TWeakPtr<FAssetEditorToolkit> AssetEditorToolkit;
};
}
@@ -330,6 +368,7 @@ void SMorphPresetViewportPanel::RebuildContent()
[
SNew(SMorphPresetPreviewViewport)
.Controller(Controller)
.AssetEditorToolkit(AssetEditorToolkit)
]);
}
@@ -8,7 +8,6 @@ class FUICommandList;
class AActor;
class IPersonaPreviewScene;
class IPersonaToolkit;
class UAnimationAsset;
class UAnimSequence;
class ULipSyncComponent;
class ULipSyncMappingDataAsset;
@@ -68,9 +67,6 @@ private:
void RebuildPreviewAnimation();
void ApplyPresetToPreview();
void RefreshPreviewAnimationPose();
UAnimationAsset* ResolvePreviewAnimationAsset() const;
float GetPreviewAnimationPosition() const;
bool IsPreviewAnimationCompatible(UAnimationAsset* PreviewAsset) const;
void RebuildLipSyncPreviewComponents();
void DestroyLipSyncPreviewComponents();
void TickLipSyncPreviewComponents(float DeltaTime);
@@ -82,6 +78,7 @@ private:
TSharedPtr<FUICommandList> CommandList;
TStrongObjectPtr<UAnimSequence> PreviewAnimation;
TStrongObjectPtr<ULipSyncMappingDataAsset> DefaultLipSyncPreviewMapping;
TWeakObjectPtr<USkeletalMesh> ActivePreviewMesh;
TWeakObjectPtr<ULipSyncMappingDataAsset> LipSyncPreviewMapping;
TWeakObjectPtr<USoundBase> LipSyncPreviewSound;
TWeakObjectPtr<AActor> LipSyncPreviewActor;