diff --git a/.gitignore b/.gitignore index 43ad57c..5b5d9cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,17 @@ +# Core directory files +/Source/ThirdParty/Live2DCubismCore/**/*.a +/Source/ThirdParty/Live2DCubismCore/**/*.bundle +/Source/ThirdParty/Live2DCubismCore/**/*.dll +/Source/ThirdParty/Live2DCubismCore/**/*.dylib +/Source/ThirdParty/Live2DCubismCore/**/*.lib +/Source/ThirdParty/Live2DCubismCore/**/*.so + +# Other files +/build/ +.vs/ +.vscode/ +.idea/ +*.iml +.DS_Store Binaries Intermediate diff --git a/CHANGELOG.md b/CHANGELOG.md index 951dc29..6fa348f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,27 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [5-r.1-alpha.2] - 2024-09-26 + +### Added + +* Add support for Unreal Engine 5.1 and 5.4. + +### Changed + +* Align component addition order with execution order. + +### Fixed + +* Fix the calculation of CubismMotionComponent. +* Fix incorrect pose transition behavior. + + ## [5-r.1-alpha.1] - 2024-09-05 ### Added * New released! + + +[5-r.1-alpha.2]: https://github.com/Live2D/CubismUnrealEngineComponents/compare/5-r.1-alpha.1...5-r.1-alpha.2 diff --git a/Content/Materials/CustomUnlitAdditive.uasset b/Content/Materials/CustomUnlitAdditive.uasset index 4c27aff..ad14909 100644 Binary files a/Content/Materials/CustomUnlitAdditive.uasset and b/Content/Materials/CustomUnlitAdditive.uasset differ diff --git a/Content/Materials/CustomUnlitAdditiveMasked.uasset b/Content/Materials/CustomUnlitAdditiveMasked.uasset index e8cdd78..a576285 100644 Binary files a/Content/Materials/CustomUnlitAdditiveMasked.uasset and b/Content/Materials/CustomUnlitAdditiveMasked.uasset differ diff --git a/Content/Materials/CustomUnlitAdditiveMaskedInverted.uasset b/Content/Materials/CustomUnlitAdditiveMaskedInverted.uasset index 653226a..9154b5f 100644 Binary files a/Content/Materials/CustomUnlitAdditiveMaskedInverted.uasset and b/Content/Materials/CustomUnlitAdditiveMaskedInverted.uasset differ diff --git a/Content/Materials/CustomUnlitMultiplicative.uasset b/Content/Materials/CustomUnlitMultiplicative.uasset index 24a1eac..3b6d431 100644 Binary files a/Content/Materials/CustomUnlitMultiplicative.uasset and b/Content/Materials/CustomUnlitMultiplicative.uasset differ diff --git a/Content/Materials/CustomUnlitMultiplicativeMasked.uasset b/Content/Materials/CustomUnlitMultiplicativeMasked.uasset index 6566706..c29d647 100644 Binary files a/Content/Materials/CustomUnlitMultiplicativeMasked.uasset and b/Content/Materials/CustomUnlitMultiplicativeMasked.uasset differ diff --git a/Content/Materials/CustomUnlitMultiplicativeMaskedInverted.uasset b/Content/Materials/CustomUnlitMultiplicativeMaskedInverted.uasset index d467d60..a3e1f15 100644 Binary files a/Content/Materials/CustomUnlitMultiplicativeMaskedInverted.uasset and b/Content/Materials/CustomUnlitMultiplicativeMaskedInverted.uasset differ diff --git a/Content/Materials/CustomUnlitNormal.uasset b/Content/Materials/CustomUnlitNormal.uasset index e93e553..6137737 100644 Binary files a/Content/Materials/CustomUnlitNormal.uasset and b/Content/Materials/CustomUnlitNormal.uasset differ diff --git a/Content/Materials/CustomUnlitNormalMasked.uasset b/Content/Materials/CustomUnlitNormalMasked.uasset index 359797b..6c54f70 100644 Binary files a/Content/Materials/CustomUnlitNormalMasked.uasset and b/Content/Materials/CustomUnlitNormalMasked.uasset differ diff --git a/Content/Materials/CustomUnlitNormalMaskedInverted.uasset b/Content/Materials/CustomUnlitNormalMaskedInverted.uasset index dab0fd8..133496c 100644 Binary files a/Content/Materials/CustomUnlitNormalMaskedInverted.uasset and b/Content/Materials/CustomUnlitNormalMaskedInverted.uasset differ diff --git a/Content/Samples/LookAt/LookAtTest.umap b/Content/Samples/LookAt/LookAtTest.umap index 332a565..c1f0240 100644 Binary files a/Content/Samples/LookAt/LookAtTest.umap and b/Content/Samples/LookAt/LookAtTest.umap differ diff --git a/Content/Samples/Models/Mao/Mao.uasset b/Content/Samples/Models/Mao/Mao.uasset index adc7dd7..3d60e5e 100644 Binary files a/Content/Samples/Models/Mao/Mao.uasset and b/Content/Samples/Models/Mao/Mao.uasset differ diff --git a/Content/Samples/Models/Mao/Mao/texture_00.uasset b/Content/Samples/Models/Mao/Mao/texture_00.uasset index 1c7a5eb..cefb9d2 100644 Binary files a/Content/Samples/Models/Mao/Mao/texture_00.uasset and b/Content/Samples/Models/Mao/Mao/texture_00.uasset differ diff --git a/Content/Samples/Models/Mao/Mao_cdi3.uasset b/Content/Samples/Models/Mao/Mao_cdi3.uasset index 9b83d7b..87d19fa 100644 Binary files a/Content/Samples/Models/Mao/Mao_cdi3.uasset and b/Content/Samples/Models/Mao/Mao_cdi3.uasset differ diff --git a/Content/Samples/Models/Mao/Mao_model3.uasset b/Content/Samples/Models/Mao/Mao_model3.uasset index a324cfc..b1565a4 100644 Binary files a/Content/Samples/Models/Mao/Mao_model3.uasset and b/Content/Samples/Models/Mao/Mao_model3.uasset differ diff --git a/Content/Samples/Models/Mao/Mao_physics3.uasset b/Content/Samples/Models/Mao/Mao_physics3.uasset index e53a83f..f9658e4 100644 Binary files a/Content/Samples/Models/Mao/Mao_physics3.uasset and b/Content/Samples/Models/Mao/Mao_physics3.uasset differ diff --git a/Content/Samples/Models/Mao/Mao_pose3.uasset b/Content/Samples/Models/Mao/Mao_pose3.uasset index ac7c17b..8578a23 100644 Binary files a/Content/Samples/Models/Mao/Mao_pose3.uasset and b/Content/Samples/Models/Mao/Mao_pose3.uasset differ diff --git a/Content/Samples/Models/Mao/expressions/exp_01_exp3.uasset b/Content/Samples/Models/Mao/expressions/exp_01_exp3.uasset index bee14d8..a10c808 100644 Binary files a/Content/Samples/Models/Mao/expressions/exp_01_exp3.uasset and b/Content/Samples/Models/Mao/expressions/exp_01_exp3.uasset differ diff --git a/Content/Samples/Models/Mao/expressions/exp_02_exp3.uasset b/Content/Samples/Models/Mao/expressions/exp_02_exp3.uasset index 8cddd86..3dc4a8f 100644 Binary files a/Content/Samples/Models/Mao/expressions/exp_02_exp3.uasset and b/Content/Samples/Models/Mao/expressions/exp_02_exp3.uasset differ diff --git a/Content/Samples/Models/Mao/expressions/exp_03_exp3.uasset b/Content/Samples/Models/Mao/expressions/exp_03_exp3.uasset index da4c2dc..4921a2e 100644 Binary files a/Content/Samples/Models/Mao/expressions/exp_03_exp3.uasset and b/Content/Samples/Models/Mao/expressions/exp_03_exp3.uasset differ diff --git a/Content/Samples/Models/Mao/expressions/exp_04_exp3.uasset b/Content/Samples/Models/Mao/expressions/exp_04_exp3.uasset index f3f7906..dcc971e 100644 Binary files a/Content/Samples/Models/Mao/expressions/exp_04_exp3.uasset and b/Content/Samples/Models/Mao/expressions/exp_04_exp3.uasset differ diff --git a/Content/Samples/Models/Mao/expressions/exp_05_exp3.uasset b/Content/Samples/Models/Mao/expressions/exp_05_exp3.uasset index 22360a5..a03f11f 100644 Binary files a/Content/Samples/Models/Mao/expressions/exp_05_exp3.uasset and b/Content/Samples/Models/Mao/expressions/exp_05_exp3.uasset differ diff --git a/Content/Samples/Models/Mao/expressions/exp_06_exp3.uasset b/Content/Samples/Models/Mao/expressions/exp_06_exp3.uasset index 3e759c9..7faf52b 100644 Binary files a/Content/Samples/Models/Mao/expressions/exp_06_exp3.uasset and b/Content/Samples/Models/Mao/expressions/exp_06_exp3.uasset differ diff --git a/Content/Samples/Models/Mao/expressions/exp_07_exp3.uasset b/Content/Samples/Models/Mao/expressions/exp_07_exp3.uasset index 053c92a..0f9e3b1 100644 Binary files a/Content/Samples/Models/Mao/expressions/exp_07_exp3.uasset and b/Content/Samples/Models/Mao/expressions/exp_07_exp3.uasset differ diff --git a/Content/Samples/Models/Mao/expressions/exp_08_exp3.uasset b/Content/Samples/Models/Mao/expressions/exp_08_exp3.uasset index 5f2991f..fa9f7bb 100644 Binary files a/Content/Samples/Models/Mao/expressions/exp_08_exp3.uasset and b/Content/Samples/Models/Mao/expressions/exp_08_exp3.uasset differ diff --git a/Content/Samples/Models/Mao/motions/mtn_01_motion3.uasset b/Content/Samples/Models/Mao/motions/mtn_01_motion3.uasset index 1849de2..b2ca0c9 100644 Binary files a/Content/Samples/Models/Mao/motions/mtn_01_motion3.uasset and b/Content/Samples/Models/Mao/motions/mtn_01_motion3.uasset differ diff --git a/Content/Samples/Models/Mao/motions/mtn_02_motion3.uasset b/Content/Samples/Models/Mao/motions/mtn_02_motion3.uasset index 7820933..aaaa68d 100644 Binary files a/Content/Samples/Models/Mao/motions/mtn_02_motion3.uasset and b/Content/Samples/Models/Mao/motions/mtn_02_motion3.uasset differ diff --git a/Content/Samples/Models/Mao/motions/mtn_03_motion3.uasset b/Content/Samples/Models/Mao/motions/mtn_03_motion3.uasset index de8ac83..bac31af 100644 Binary files a/Content/Samples/Models/Mao/motions/mtn_03_motion3.uasset and b/Content/Samples/Models/Mao/motions/mtn_03_motion3.uasset differ diff --git a/Content/Samples/Models/Mao/motions/mtn_04_motion3.uasset b/Content/Samples/Models/Mao/motions/mtn_04_motion3.uasset index 8c3a1a4..6c3fa7c 100644 Binary files a/Content/Samples/Models/Mao/motions/mtn_04_motion3.uasset and b/Content/Samples/Models/Mao/motions/mtn_04_motion3.uasset differ diff --git a/Content/Samples/Models/Mao/motions/sample_01_motion3.uasset b/Content/Samples/Models/Mao/motions/sample_01_motion3.uasset index 274d9b1..f28cf61 100644 Binary files a/Content/Samples/Models/Mao/motions/sample_01_motion3.uasset and b/Content/Samples/Models/Mao/motions/sample_01_motion3.uasset differ diff --git a/Content/Samples/Models/Mao/motions/special_01_motion3.uasset b/Content/Samples/Models/Mao/motions/special_01_motion3.uasset index 345971f..a27af48 100644 Binary files a/Content/Samples/Models/Mao/motions/special_01_motion3.uasset and b/Content/Samples/Models/Mao/motions/special_01_motion3.uasset differ diff --git a/Content/Samples/Models/Mao/motions/special_02_motion3.uasset b/Content/Samples/Models/Mao/motions/special_02_motion3.uasset index 5b42b4f..754ad76 100644 Binary files a/Content/Samples/Models/Mao/motions/special_02_motion3.uasset and b/Content/Samples/Models/Mao/motions/special_02_motion3.uasset differ diff --git a/Content/Samples/Models/Mao/motions/special_03_motion3.uasset b/Content/Samples/Models/Mao/motions/special_03_motion3.uasset index 1f65e4d..1a7474d 100644 Binary files a/Content/Samples/Models/Mao/motions/special_03_motion3.uasset and b/Content/Samples/Models/Mao/motions/special_03_motion3.uasset differ diff --git a/Content/Samples/Raycast/RaycastTest.umap b/Content/Samples/Raycast/RaycastTest.umap index 82cb2b5..f473c74 100644 Binary files a/Content/Samples/Raycast/RaycastTest.umap and b/Content/Samples/Raycast/RaycastTest.umap differ diff --git a/Live2DCubismSDK.uplugin b/Live2DCubismSDK.uplugin index 326491b..05371e6 100644 --- a/Live2DCubismSDK.uplugin +++ b/Live2DCubismSDK.uplugin @@ -1,34 +1,34 @@ -{ - "FileVersion": 3, - "Version": 1, - "VersionName": "5-r.1-alpha.1", - "FriendlyName": "Live2DCubismSDK", - "Description": "Live2D Cubism SDK for Unreal Engine Components", - "Category": "Other", - "CreatedBy": "Live2D Inc,", - "CreatedByURL": "https://www.live2d.com/", - "DocsURL": "https://docs.live2d.com/cubism-sdk-manual/top/", - "MarketplaceURL": "", - "SupportURL": "", - "CanContainContent": true, - "IsBetaVersion": true, - "IsExperimentalVersion": true, - "Installed": false, - "Modules": [ - { - "Name": "Live2DCubismFramework", - "Type": "Runtime", - "LoadingPhase": "PostConfigInit" - }, - { - "Name": "Live2DCubismFrameworkEditor", - "Type": "Editor", - "LoadingPhase": "Default" - }, - { - "Name": "Live2DCubismFrameworkImporter", - "Type": "Editor", - "LoadingPhase": "Default" - } - ] +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "5-r.1-alpha.2", + "FriendlyName": "Live2DCubismSDK", + "Description": "Live2D Cubism SDK for Unreal Engine Components", + "Category": "Other", + "CreatedBy": "Live2D Inc,", + "CreatedByURL": "https://www.live2d.com/", + "DocsURL": "https://docs.live2d.com/cubism-sdk-manual/top/", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": true, + "IsExperimentalVersion": true, + "Installed": false, + "Modules": [ + { + "Name": "Live2DCubismFramework", + "Type": "Runtime", + "LoadingPhase": "PostConfigInit" + }, + { + "Name": "Live2DCubismFrameworkEditor", + "Type": "Editor", + "LoadingPhase": "Default" + }, + { + "Name": "Live2DCubismFrameworkImporter", + "Type": "Editor", + "LoadingPhase": "Default" + } + ] } \ No newline at end of file diff --git a/README.ja.md b/README.ja.md index 65d69c9..a950676 100644 --- a/README.ja.md +++ b/README.ja.md @@ -63,11 +63,14 @@ Cubismファイルをuassetファイルに変換する機能は `./Source/Live2D | Unreal Engine | バージョン | | --- | --- | -| Unreal Editor | 5.3.2 | +| Unreal Editor 5.4 | 5.4.4 | +| Unreal Editor 5.3 | 5.3.2 | +| Unreal Editor 5.2 | 5.2.1 | +| Unreal Editor 5.1 | 5.1.1 | | ライブラリ / ツール | バージョン | | --- | --- | -| Visual Studio 2022 | 17.9.3 | +| Visual Studio 2022 | 17.11.4 | | Windows SDK | 10.0.22621.0 | ## テスト済みの環境 diff --git a/README.md b/README.md index da42a05..ca6367a 100644 --- a/README.md +++ b/README.md @@ -63,11 +63,14 @@ Resources like shaders and other assets are located in `./Content/Materials`. | Unreal Engine | Version | | --- | --- | -| Unreal Editor | 5.3.2 | +| Unreal Editor 5.4 | 5.4.4 | +| Unreal Editor 5.3 | 5.3.2 | +| Unreal Editor 5.2 | 5.2.1 | +| Unreal Editor 5.1 | 5.1.1 | | Library / Tool | Version | | --- | --- | -| Visual Studio 2022 | 17.9.3 | +| Visual Studio 2022 | 17.11.4 | | Windows SDK | 10.0.22621.0 | ## Tested environment diff --git a/Source/Live2DCubismFramework/Private/Effects/LookAt/CubismLookAtComponent.cpp b/Source/Live2DCubismFramework/Private/Effects/LookAt/CubismLookAtComponent.cpp index d8dfe24..c175d1b 100644 --- a/Source/Live2DCubismFramework/Private/Effects/LookAt/CubismLookAtComponent.cpp +++ b/Source/Live2DCubismFramework/Private/Effects/LookAt/CubismLookAtComponent.cpp @@ -12,20 +12,8 @@ #include "Model/CubismModelActor.h" #include "Model/CubismModelComponent.h" #include "Model/CubismParameterComponent.h" -#include "Kismet/GameplayStatics.h" - -const float FrameRate = 30.0f; -const float Epsilon = 0.01f; UCubismLookAtComponent::UCubismLookAtComponent() - : FaceTargetX(0.0f) - , FaceTargetY(0.0f) - , FaceX(0.0f) - , FaceY(0.0f) - , FaceVX(0.0f) - , FaceVY(0.0f) - , LastTimeSeconds(0.0f) - , UserTimeSeconds(0.0f) { PrimaryComponentTick.bCanEverTick = true; PrimaryComponentTick.TickGroup = TG_DuringPhysics; @@ -93,50 +81,50 @@ void UCubismLookAtComponent::TickComponent(float DeltaTime, ELevelTick TickType, switch (Parameter.Axis) { - case ECubismLookAtAxis::X: - { - Parameter.Value = Parameter.Factor * LastPosition.X; - break; - } - case ECubismLookAtAxis::Y: - { - Parameter.Value = Parameter.Factor * LastPosition.Y; - break; - } - case ECubismLookAtAxis::Z: - { - Parameter.Value = Parameter.Factor * LastPosition.Z; - break; - } - default: - { - ensure(false); - break; - } + case ECubismLookAtAxis::X: + { + Parameter.Value = Parameter.Factor * LastPosition.X; + break; + } + case ECubismLookAtAxis::Y: + { + Parameter.Value = Parameter.Factor * LastPosition.Y; + break; + } + case ECubismLookAtAxis::Z: + { + Parameter.Value = Parameter.Factor * LastPosition.Z; + break; + } + default: + { + ensure(false); + break; + } } - switch(Parameter.BlendMode) + switch (Parameter.BlendMode) + { + case ECubismParameterBlendMode::Overwrite: + { + Destination->SetParameterValue(Parameter.Value); + break; + } + case ECubismParameterBlendMode::Additive: + { + Destination->AddParameterValue(Parameter.Value); + break; + } + case ECubismParameterBlendMode::Multiplicative: + { + Destination->MultiplyParameterValue(Parameter.Value); + break; + } + default: { - case ECubismParameterBlendMode::Overwrite: - { - Destination->SetParameterValue(Parameter.Value); - break; - } - case ECubismParameterBlendMode::Additive: - { - Destination->AddParameterValue(Parameter.Value); - break; - } - case ECubismParameterBlendMode::Multiplicative: - { - Destination->MultiplyParameterValue(Parameter.Value); - break; - } - default: - { - ensure(false); - break; - } + ensure(false); + break; + } } } } @@ -146,90 +134,27 @@ FVector UCubismLookAtComponent::SmoothDamp(const FVector CurrentValue, const flo { // global(world) coordinates to local(object) coordinates const FTransform Transform = Model->GetRelativeTransform(); + FVector TargetValue = Transform.InverseTransformPosition(Target ? Target->GetActorLocation() : Transform.GetLocation()); - APlayerController* PlayerController = GetWorld()->GetFirstPlayerController(); - if (!PlayerController) - { - return CurrentValue; - } - - FVector2D ScreenPosition; - PlayerController->ProjectWorldLocationToScreen((Target->GetActorLocation() - Transform.GetLocation()), ScreenPosition, false); + const float Scale = 100.0f / Model->GetPixelsPerUnit(); + TargetValue = FVector(-TargetValue.Y, TargetValue.Z, TargetValue.X) * Scale; - FVector2D Resolution = GEngine->GameViewport->Viewport->GetSizeXY(); + const float Omega = 2.0f / Smoothing; + const float x = Omega * DeltaTime; + const float Invexp = 1.0f / (1.0f + x + 0.48f * x * x + 0.235f * x * x * x); - FaceTargetX = (float)(ScreenPosition.X / Resolution.X) * 2.0f - 1.0f; - FaceTargetY = (float)(ScreenPosition.Y / Resolution.Y) * 2.0f - 1.0f; + const FVector Damp = CurrentValue - TargetValue; - UserTimeSeconds += DeltaTime; + const FVector Tmp = (CurrentVelocity + Omega * Damp) * DeltaTime; + CurrentVelocity = (CurrentVelocity - Omega * Tmp) * Invexp; - const float FaceParamMaxV = 40.0f / 10.0f; - const float MaxV = FaceParamMaxV * 1.0f / FrameRate; + FVector NewDamp = (Damp + Tmp) * Invexp; - - if (LastTimeSeconds == 0.0f) + if (FVector::DotProduct(Damp, NewDamp) < 0.0f) { - LastTimeSeconds = UserTimeSeconds; - return CurrentValue; + NewDamp = FVector::ZeroVector; + CurrentVelocity = FVector::ZeroVector; } - - const float DeltaTimeWeight = (UserTimeSeconds - LastTimeSeconds) * FrameRate; - LastTimeSeconds = UserTimeSeconds; - - const float TimeToMaxSpeed = 0.15f; - const float FrameToMaxSpeed = TimeToMaxSpeed * FrameRate; // sec * frame/sec - const float MaxA = DeltaTimeWeight * MaxV / FrameToMaxSpeed; - - - const float DX = FaceTargetX - FaceX; - const float DY = FaceTargetY - FaceY; - - - if (FMath::Abs(DX) <= Epsilon && FMath::Abs(DY) <= Epsilon) - { - return CurrentValue; - } - - const float D = FMath::Sqrt((DX * DX) + (DY * DY)); - - - const float VX = MaxV * DX / D; - const float VY = MaxV * DY / D; - - - float AX = VX - FaceVX; - float AY = VY - FaceVY; - - const float A = FMath::Sqrt((AX * AX) + (AY * AY)); - - - if (A < -MaxA || A > MaxA) - { - AX *= MaxA / A; - AY *= MaxA / A; - } - - FaceVX += AX; - FaceVY += AY; - - { - - const float MaxVelocity = 0.5f * (FMath::Sqrt((MaxA * MaxA) + 16.0f * MaxA * D - 8.0f * MaxA * D) - MaxA); - const float CurVelocity = FMath::Sqrt((FaceVX * FaceVX) + (FaceVY * FaceVY)); - - if (CurVelocity > MaxVelocity) - { - FaceVX *= MaxVelocity / CurVelocity; - FaceVY *= MaxVelocity / CurVelocity; - } - } - - FaceX += FaceVX; - FaceY += FaceVY; - - FVector Ret = FVector(-FaceX, -FaceY, 0); - - - return Ret; + return NewDamp + TargetValue; } diff --git a/Source/Live2DCubismFramework/Private/Model/CubismParameterComponent.cpp b/Source/Live2DCubismFramework/Private/Model/CubismParameterComponent.cpp index a6f394d..da582e2 100644 --- a/Source/Live2DCubismFramework/Private/Model/CubismParameterComponent.cpp +++ b/Source/Live2DCubismFramework/Private/Model/CubismParameterComponent.cpp @@ -52,8 +52,8 @@ void UCubismParameterComponent::Setup(UCubismModelComponent* InModel) Value = 0.0f; } - check(!TMathUtil::IsNaN(MaximumValue)); - check(!TMathUtil::IsNaN(MinimumValue)); + check(!FGenericPlatformMath::IsNaN(MaximumValue)); + check(!FGenericPlatformMath::IsNaN(MinimumValue)); check(MaximumValue > MinimumValue); } @@ -64,7 +64,7 @@ float UCubismParameterComponent::GetParameterValue() const void UCubismParameterComponent::SetParameterValue(float TargetValue, const float Weight) { - if (!TMathUtil::IsNaN(MinimumValue) && !TMathUtil::IsNaN(MaximumValue)) + if (!FGenericPlatformMath::IsNaN(MinimumValue) && !FGenericPlatformMath::IsNaN(MaximumValue)) { TargetValue = FMath::Clamp(TargetValue, MinimumValue, MaximumValue); } @@ -80,7 +80,7 @@ void UCubismParameterComponent::AddParameterValue(float TargetValue, const float { float CurrentValue = Model->GetParameterValue(Index) + TargetValue * Weight; - if (!TMathUtil::IsNaN(MinimumValue) && !TMathUtil::IsNaN(MaximumValue)) + if (!FGenericPlatformMath::IsNaN(MinimumValue) && !FGenericPlatformMath::IsNaN(MaximumValue)) { CurrentValue = FMath::Clamp(CurrentValue, MinimumValue, MaximumValue); } @@ -94,7 +94,7 @@ void UCubismParameterComponent::MultiplyParameterValue(float TargetValue, const { float CurrentValue = Model->GetParameterValue(Index) * (1.0f + (TargetValue - 1.0f) * Weight); - if (!TMathUtil::IsNaN(MinimumValue) && !TMathUtil::IsNaN(MaximumValue)) + if (!FGenericPlatformMath::IsNaN(MinimumValue) && !FGenericPlatformMath::IsNaN(MaximumValue)) { CurrentValue = FMath::Clamp(CurrentValue, MinimumValue, MaximumValue); } @@ -126,6 +126,11 @@ void UCubismParameterComponent::PostEditChangeProperty(FPropertyChangedEvent& Pr const float CurrentValue = (MaximumValue - MinimumValue) * Value + MinimumValue; Model->SetParameterValue(Index, CurrentValue); + + if(Model->ParameterStore) + { + Model->ParameterStore->SaveParameterValue(Index); + } } } #endif diff --git a/Source/Live2DCubismFramework/Private/Model/CubismParameterStoreComponent.cpp b/Source/Live2DCubismFramework/Private/Model/CubismParameterStoreComponent.cpp index a1261a3..692b3cc 100644 --- a/Source/Live2DCubismFramework/Private/Model/CubismParameterStoreComponent.cpp +++ b/Source/Live2DCubismFramework/Private/Model/CubismParameterStoreComponent.cpp @@ -37,6 +37,16 @@ void UCubismParameterStoreComponent::Setup(UCubismModelComponent* InModel) Model->ParameterStore = this; } +void UCubismParameterStoreComponent::SaveParameterValue(const int32 ParameterIndex) +{ + ParameterValues.Add(ParameterIndex, Model->GetParameter(ParameterIndex)->GetParameterValue()); +} + +void UCubismParameterStoreComponent::SavePartOpacity(const int32 PartIndex) +{ + PartOpacities.Add(PartIndex, Model->GetPart(PartIndex)->Opacity); +} + void UCubismParameterStoreComponent::SaveParameters() { for (const TObjectPtr& Parameter : Model->Parameters) diff --git a/Source/Live2DCubismFramework/Private/Model/CubismPartComponent.cpp b/Source/Live2DCubismFramework/Private/Model/CubismPartComponent.cpp index 6c65351..1125530 100644 --- a/Source/Live2DCubismFramework/Private/Model/CubismPartComponent.cpp +++ b/Source/Live2DCubismFramework/Private/Model/CubismPartComponent.cpp @@ -42,7 +42,7 @@ void UCubismPartComponent::Setup(UCubismModelComponent* InModel) Opacity = 1.0f; } - check(!TMathUtil::IsNaN(Opacity)); + check(!FGenericPlatformMath::IsNaN(Opacity)); } void UCubismPartComponent::SetPartOpacity(float TargetOpacity) @@ -72,6 +72,11 @@ void UCubismPartComponent::PostEditChangeProperty(FPropertyChangedEvent& Propert if (PropertyName == GET_MEMBER_NAME_CHECKED(UCubismPartComponent, Opacity)) { Model->SetPartOpacity(Index, Opacity); + + if(Model->ParameterStore) + { + Model->ParameterStore->SavePartOpacity(Index); + } } } #endif diff --git a/Source/Live2DCubismFramework/Private/Motion/CubismMotion.cpp b/Source/Live2DCubismFramework/Private/Motion/CubismMotion.cpp index 436cf32..c10d972 100644 --- a/Source/Live2DCubismFramework/Private/Motion/CubismMotion.cpp +++ b/Source/Live2DCubismFramework/Private/Motion/CubismMotion.cpp @@ -9,6 +9,11 @@ #include "Motion/CubismMotion.h" FCubismMotion::FCubismMotion(const UCubismMotion3Json* Json, const float InOffsetTime) + : Weight(1.0f) + , FadeOutSeconds(0.0f) + , EndTimeSeconds(-1.0f) + , bIsTriggeredFadeOut(false) + , bFinished(false) { Duration = Json->Duration; bLoop = Json->bLoop; @@ -30,64 +35,84 @@ void FCubismMotion::Init(const float Time) EndTime = Duration; } -float FCubismMotion::CalcWeight(const FString Id, const float ElapsedTime) const +float FCubismMotion::UpdateFadeWeight(const TSharedPtr& CubismMotion, float UserTimeSeconds) { - float FadeInWeight = 1.0f; - float FadeOutWeight = 1.0f; + float FadeWeight = Weight; - if (FadeInTime > 0.0f) - { - FadeInWeight = EasingSin((ElapsedTime - OffsetTime) / FadeInTime); - } + const float FadeIn = CubismMotion->FadeInTime == 0.0f + ? 1.0f + : EasingSin((UserTimeSeconds - CubismMotion->StartTime) / CubismMotion->FadeInTime); - if (State != ECubismMotionState::PlayInLoop && FadeOutTime > 0.0f) - { - FadeOutWeight = EasingSin((EndTime - ElapsedTime) / FadeOutTime); - } + const float FadeOut = (CubismMotion->FadeOutTime == 0.0f || CubismMotion->GetEndTime() < 0.0f) + ? 1.0f + : EasingSin((CubismMotion->GetEndTime() - UserTimeSeconds) / CubismMotion->FadeOutTime); - for (const FCubismMotionCurve& Curve : Curves) - { - if (Curve.Id != Id) - { - continue; - } - - if (Curve.FadeInTime == 0.0f) - { - FadeInWeight = 1.0f; - } - else if (Curve.FadeInTime > 0.0f) - { - FadeInWeight = EasingSin((ElapsedTime - OffsetTime) / Curve.FadeInTime); - } - - if (Curve.FadeOutTime == 0.0f || State == ECubismMotionState::PlayInLoop) - { - FadeOutWeight = 1.0f; - } - else if (Curve.FadeOutTime > 0.0f) - { - FadeOutWeight = EasingSin((EndTime - ElapsedTime) / Curve.FadeOutTime); - } - - break; - } - - const float FadeWeight = FadeInWeight * FadeOutWeight; + FadeWeight = FadeWeight * FadeIn * FadeOut; check(0.0f <= FadeWeight && FadeWeight <= 1.0f); return FadeWeight; } +void FCubismMotion::SetWeight(float MotionWeight) +{ + this->Weight = MotionWeight; +} + +float FCubismMotion::GetWeight() const +{ + return Weight; +} +void FCubismMotion::SetFadeout(float NewFadeOutSeconds) +{ + this->FadeOutSeconds = NewFadeOutSeconds; + bIsTriggeredFadeOut = true; +} + void FCubismMotion::FadeOut(const float Time) { State = ECubismMotionState::Play; - const float NewEndTime = FadeOutTime + Time - StartTime; + const float NewEndTime = FadeOutTime + Time; if (NewEndTime < EndTime) { EndTime = NewEndTime; } } + +void FCubismMotion::StartFadeout(float NewFadeOutSeconds, float UserTimeSeconds) +{ + const float NewEndTimeSeconds = UserTimeSeconds + NewFadeOutSeconds; + bIsTriggeredFadeOut = true; + + if (EndTimeSeconds < 0.0f || NewEndTimeSeconds < EndTimeSeconds) + { + EndTimeSeconds = NewEndTimeSeconds; + } +} + +bool FCubismMotion::IsTriggeredFadeOut() +{ + return bIsTriggeredFadeOut; +} + +float FCubismMotion::GetFadeOutSeconds() +{ + return FadeOutSeconds; +} + +float FCubismMotion::GetEndTime() +{ + return EndTimeSeconds; +} + +void FCubismMotion::IsFinished(bool F) +{ + bFinished = F; +} + +bool FCubismMotion::IsFinished() const +{ + return bFinished; +} diff --git a/Source/Live2DCubismFramework/Private/Motion/CubismMotionComponent.cpp b/Source/Live2DCubismFramework/Private/Motion/CubismMotionComponent.cpp index 9389c6d..605f900 100644 --- a/Source/Live2DCubismFramework/Private/Motion/CubismMotionComponent.cpp +++ b/Source/Live2DCubismFramework/Private/Motion/CubismMotionComponent.cpp @@ -86,7 +86,7 @@ void UCubismMotionComponent::PlayMotion(const int32 InIndex, const float OffsetT for (const TSharedPtr& Motion : MotionQueue) { - Motion->FadeOut(Time); + Motion->SetFadeout(Motion->FadeOutTime); } TSharedPtr NextMotion = MakeShared(Json, OffsetTime); @@ -124,18 +124,11 @@ void UCubismMotionComponent::PostEditChangeProperty(struct FPropertyChangedEvent { Super::PostEditChangeProperty(PropertyChangedEvent); - const FName PropertyName = PropertyChangedEvent.Property? PropertyChangedEvent.Property->GetFName() : NAME_None; + const FName PropertyName = PropertyChangedEvent.Property ? PropertyChangedEvent.Property->GetFName() : NAME_None; if (PropertyName == GET_MEMBER_NAME_CHECKED(UCubismMotionComponent, Index)) { - if (Jsons.IsValidIndex(Index)) - { - PlayMotion(Index, 0.0f, ECubismMotionPriority::Force); - } - else - { - StopAllMotions(); - } + PlayMotion(Index, 0.0f, ECubismMotionPriority::Force); } } #endif @@ -167,27 +160,33 @@ void UCubismMotionComponent::TickComponent(float DeltaTime, ELevelTick TickType, Time += Speed * DeltaTime; - for (const TSharedPtr& Motion : MotionQueue) + for (int32 i = 0; i < MotionQueue.Num();) { + TSharedPtr& Motion = MotionQueue[i]; + if (Motion->State == ECubismMotionState::None) { // Initialize the motion. Motion->Init(Time); } - UpdateMotion(Motion); - } - - Model->ParameterStore->SaveParameters(); + float FadeWeight = Motion->UpdateFadeWeight(Motion, Time); - for (int32 i = MotionQueue.Num()-1; i >= 0; i--) - { - const TSharedPtr& Motion = MotionQueue[i]; + UpdateMotion(Time, FadeWeight, Motion); - if (Motion->State == ECubismMotionState::End) + if (Motion->IsFinished()) { MotionQueue.RemoveAt(i); } + else + { + if (Motion->IsTriggeredFadeOut()) + { + Motion->StartFadeout(Motion->GetFadeOutSeconds(), Time); + } + + i++; + } } if (IsFinished()) @@ -199,68 +198,155 @@ void UCubismMotionComponent::TickComponent(float DeltaTime, ELevelTick TickType, } // End of UActorComponent interface -void UCubismMotionComponent::UpdateMotion(const TSharedPtr& Motion) +void UCubismMotionComponent::UpdateMotion(float UserTimeSeconds, float FadeWeight, const TSharedPtr& CubismMotion) { - float ElapsedTime = Time - Motion->StartTime; + float TimeOffsetSeconds = UserTimeSeconds - CubismMotion->StartTime; + + if (TimeOffsetSeconds < 0.0f) + { + TimeOffsetSeconds = 0.0f; + } + + const float TmpFadeIn = (CubismMotion->FadeInTime <= 0.0f) + ? 1.0f + : FCubismMotion::EasingSin((UserTimeSeconds - CubismMotion->EndTime) / CubismMotion->FadeInTime); + + const float TmpFadeOut = (CubismMotion->FadeOutTime <= 0.0f || CubismMotion->EndTime < 0.0f) + ? 1.0f + : FCubismMotion::EasingSin((CubismMotion->EndTime - UserTimeSeconds) / CubismMotion->FadeOutTime); + + // 'Repeat' time as necessary. + float MotionTime = TimeOffsetSeconds; + + if (CubismMotion->State == ECubismMotionState::PlayInLoop) + { + while (MotionTime > CubismMotion->Duration) + { + MotionTime -= CubismMotion->Duration; + } + } + + TArray Curves = CubismMotion->Curves; - if (Motion->State == ECubismMotionState::PlayInLoop) + // Evaluate model curves. + for (const FCubismMotionCurve& Curve : Curves) { - while (ElapsedTime > Motion->Duration) + if (Curve.Target != ECubismMotionCurveTarget::Model) + { + continue; + } + + // Evaluate curve and call handler. + float Value = CubismMotion->GetValue(Curve.Id, MotionTime); + + if (Curve.Id == "PartOpacity") { - ElapsedTime -= Motion->Duration; + Model->Opacity = Value; } } - for (const FCubismMotionCurve& Curve : Motion->Curves) - { - const float Value = Motion->GetValue(Curve.Id, ElapsedTime); - - switch (Curve.Target) - { - case ECubismMotionCurveTarget::Model: - { - Model->Opacity = Value; - - break; - } - case ECubismMotionCurveTarget::Parameter: - { - if (UCubismParameterComponent* DstParameter = Model->GetParameter(Curve.Id)) - { - const float FadeWeight = Motion->CalcWeight(Curve.Id, ElapsedTime); - - DstParameter->SetParameterValue(Value, FadeWeight); - } - - break; - } - case ECubismMotionCurveTarget::PartOpacity: - { - UCubismParameterComponent* DstParameter = Model->GetParameter(Curve.Id); - - check(DstParameter); - - DstParameter->SetParameterValue(Value); - - break; - } - default: - { - ensure(false); - break; - } - } - } - - if (Time - Motion->StartTime > Motion->Duration) + for (const FCubismMotionCurve& Curve : Curves) + { + if (Curve.Target != ECubismMotionCurveTarget::Parameter) + { + continue; + } + + // Find parameter. + UCubismParameterComponent* Parameter = Model->GetParameter(Curve.Id); + + // Skip curve evaluation if no value in sink. + if (!Parameter) + { + continue; + } + + const float SourceValue = Parameter->GetParameterValue(); + + // Evaluate curve and apply value. + float Value = CubismMotion->GetValue(Curve.Id, MotionTime); + + + float NewValue; + // Fade per parameter. + if (Curve.FadeInTime < 0.0f && Curve.FadeOutTime < 0.0f) + { + //Apply motion fade. + NewValue = SourceValue + (Value - SourceValue) * FadeWeight; + } + else + { + // If fade-in or fade-out is set for a parameter, apply it. + float FadeInWeight; + float FadeOutWeight; + + if (Curve.FadeInTime < 0.0f) + { + FadeInWeight = TmpFadeIn; + } + else + { + FadeInWeight = Curve.FadeInTime == 0.0f + ? 1.0f + : FCubismMotion::EasingSin((UserTimeSeconds - CubismMotion->StartTime) / Curve.FadeInTime); + } + + if (Curve.FadeOutTime < 0.0f) + { + FadeOutWeight = TmpFadeOut; + } + else + { + FadeOutWeight = (Curve.FadeOutTime == 0.0f || CubismMotion->EndTime < 0.0f) + ? 1.0f + : FCubismMotion::EasingSin((UserTimeSeconds - CubismMotion->EndTime) / Curve.FadeOutTime); + } + + const float ParamWeight = CubismMotion->GetWeight() * FadeInWeight * FadeOutWeight; + + // Apply fade per parameter. + NewValue = SourceValue + (Value - SourceValue) * ParamWeight; + } + + Parameter->SetParameterValue(NewValue); + } + + for (const FCubismMotionCurve& Curve : Curves) + { + if (Curve.Target != ECubismMotionCurveTarget::PartOpacity) + { + continue; + } + + // Find parameter. + UCubismParameterComponent* Parameter = Model->GetParameter(Curve.Id); + + // Skip curve evaluation if no value in sink. + if (!Parameter) + { + continue; + } + + // Evaluate curve and apply value. + float Value = CubismMotion->GetValue(Curve.Id, MotionTime); + + Parameter->SetParameterValue(Value); + } + + if ((CubismMotion->GetEndTime() > 0.0f) && (CubismMotion->GetEndTime() < UserTimeSeconds)) + { + CubismMotion->IsFinished(true); + } + + if (Time - CubismMotion->StartTime > CubismMotion->Duration) { - if (Motion->State == ECubismMotionState::PlayInLoop) + if (CubismMotion->State == ECubismMotionState::PlayInLoop) { - Motion->StartTime = Time; + CubismMotion->StartTime = UserTimeSeconds; } else { - Motion->State = ECubismMotionState::End; + CubismMotion->IsFinished(true); } } } diff --git a/Source/Live2DCubismFramework/Private/Pose/CubismPoseComponent.cpp b/Source/Live2DCubismFramework/Private/Pose/CubismPoseComponent.cpp index dfaa953..b7cd747 100644 --- a/Source/Live2DCubismFramework/Private/Pose/CubismPoseComponent.cpp +++ b/Source/Live2DCubismFramework/Private/Pose/CubismPoseComponent.cpp @@ -202,6 +202,8 @@ void UCubismPoseComponent::DoFade(float DeltaTime) Part->SetPartOpacity(Opacity); } + + Model->ParameterStore->SavePartOpacity(Part->Index); } } } @@ -223,6 +225,7 @@ void UCubismPoseComponent::CopyPartOpacities() for (const TObjectPtr& LinkPart : PartParam.LinkParts) { LinkPart->SetPartOpacity(Opacity); + Model->ParameterStore->SavePartOpacity(LinkPart->Index); } } } diff --git a/Source/Live2DCubismFramework/Private/Rendering/CubismDrawableSceneProxy.h b/Source/Live2DCubismFramework/Private/Rendering/CubismDrawableSceneProxy.h index 7acb25a..817b931 100644 --- a/Source/Live2DCubismFramework/Private/Rendering/CubismDrawableSceneProxy.h +++ b/Source/Live2DCubismFramework/Private/Rendering/CubismDrawableSceneProxy.h @@ -10,9 +10,10 @@ #include "PrimitiveSceneProxy.h" #include "DynamicMeshBuilder.h" -#include "MaterialDomain.h" #include "Materials/Material.h" +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 2 #include "Materials/MaterialRenderProxy.h" +#endif /** * Dynamic mesh data for a drawable. diff --git a/Source/Live2DCubismFramework/Private/Rendering/CubismShaders.cpp b/Source/Live2DCubismFramework/Private/Rendering/CubismShaders.cpp index 4da3c3e..7f86749 100644 --- a/Source/Live2DCubismFramework/Private/Rendering/CubismShaders.cpp +++ b/Source/Live2DCubismFramework/Private/Rendering/CubismShaders.cpp @@ -10,7 +10,9 @@ #include "ShaderParameterUtils.h" #include "ShaderParameterStruct.h" +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 2 #include "DataDrivenShaderPlatformInfo.h" +#endif #include "BatchedElements.h" #include "RenderResource.h" #include "GlobalShader.h" diff --git a/Source/Live2DCubismFramework/Public/Effects/LookAt/CubismLookAtComponent.h b/Source/Live2DCubismFramework/Public/Effects/LookAt/CubismLookAtComponent.h index 18d5462..6d37d32 100644 --- a/Source/Live2DCubismFramework/Public/Effects/LookAt/CubismLookAtComponent.h +++ b/Source/Live2DCubismFramework/Public/Effects/LookAt/CubismLookAtComponent.h @@ -16,7 +16,7 @@ struct FCubismLookAtParameter; /** * A component to apply the look-at effect to the specified parameters of the Cubism model. */ -UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) class LIVE2DCUBISMFRAMEWORK_API UCubismLookAtComponent : public UActorComponent { GENERATED_BODY() @@ -37,7 +37,7 @@ class LIVE2DCUBISMFRAMEWORK_API UCubismLookAtComponent : public UActorComponent /** * The smoothing value of the look-at effect. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Live2D Cubism", meta=(ClampMin = "0.0001", ClampMax = "1.0", SliderMin = "0.0001", SliderMax = "1.0")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Live2D Cubism", meta = (ClampMin = "0.0001", ClampMax = "1.0", SliderMin = "0.0001", SliderMax = "1.0")) float Smoothing = 0.15f; public: @@ -76,15 +76,6 @@ class LIVE2DCUBISMFRAMEWORK_API UCubismLookAtComponent : public UActorComponent */ FVector SmoothDamp(const FVector CurrentValue, const float DeltaTime); - float FaceTargetX; - float FaceTargetY; - float FaceX; - float FaceY; - float FaceVX; - float FaceVY; - float LastTimeSeconds; - float UserTimeSeconds; - public: // UObject interface virtual void PostLoad() override; diff --git a/Source/Live2DCubismFramework/Public/Model/CubismParameterStoreComponent.h b/Source/Live2DCubismFramework/Public/Model/CubismParameterStoreComponent.h index dee9a5f..2883e65 100644 --- a/Source/Live2DCubismFramework/Public/Model/CubismParameterStoreComponent.h +++ b/Source/Live2DCubismFramework/Public/Model/CubismParameterStoreComponent.h @@ -29,6 +29,20 @@ class LIVE2DCUBISMFRAMEWORK_API UCubismParameterStoreComponent : public UActorCo UFUNCTION(BlueprintCallable, Category = "Live2D Cubism") void Setup(UCubismModelComponent* InModel); + /** + * @brief The function to save the value of a parameter at the specified index. + * @param ParameterIndex The index of the parameter. + */ + UFUNCTION(BlueprintCallable, Category = "Live2D Cubism") + void SaveParameterValue(const int32 ParameterIndex); + + /** + * @brief The function to save the opacity of a part at the specified index. + * @param PartIndex The index of the part. + */ + UFUNCTION(BlueprintCallable, Category = "Live2D Cubism") + void SavePartOpacity(const int32 PartIndex); + /** * @brief The function to save the parameters. */ diff --git a/Source/Live2DCubismFramework/Public/Motion/CubismMotion.h b/Source/Live2DCubismFramework/Public/Motion/CubismMotion.h index 1b02d55..b36dda8 100644 --- a/Source/Live2DCubismFramework/Public/Motion/CubismMotion.h +++ b/Source/Live2DCubismFramework/Public/Motion/CubismMotion.h @@ -102,7 +102,7 @@ class FCubismMotion * @param Time The current time. * @return The weight of the fade in and the fade in/out. */ - float CalcWeight(const FString Id, const float ElapsedTime) const; + float UpdateFadeWeight(const TSharedPtr& CubismMotion, float UserTimeSeconds); /** * The function to fade out the motion. @@ -110,6 +110,61 @@ class FCubismMotion */ void FadeOut(const float Time); + /** + * The function to set weight value. + * @param The weight value of the motion. + */ + void SetWeight(float weight); + + /** + * The function to get weight value. + * @return The weight value of the motion. + */ + float GetWeight() const; + + /** + * Set the time when fade out ends. + * @param The time at which the fade ends. + */ + void SetFadeout(float NewFadeOutSeconds); + + /** + * Initiate fade out. + * @param The time at which the fade ends. + * @param Time The current time. + */ + void StartFadeout(float NewFadeOutSeconds, float UserTimeSeconds); + + /** + * Whether fade out has started. + * @return True if the fade out flag is set. + */ + bool IsTriggeredFadeOut(); + + /** + * Get fade out time. + * @return The fade out time. + */ + float GetFadeOutSeconds(); + + /** + * End time of motion playback. + * @return Time at which motion playback ends. + */ + float GetEndTime(); + + /** + * Whether the motion has finished playing or not. + * @param True if the motion has finished playing. + */ + void IsFinished(bool F); + + /** + * Whether the motion has finished playing or not. + * @return True if the motion has finished playing. + */ + bool IsFinished() const; + private: friend class UCubismMotionComponent; @@ -137,4 +192,14 @@ class FCubismMotion { return CurveTable->FindRichCurve(*Id, Id)->Eval(Time, 0.0f); } + + float Weight; + + float FadeOutSeconds; + + float EndTimeSeconds; + + bool bIsTriggeredFadeOut; + + bool bFinished; }; diff --git a/Source/Live2DCubismFramework/Public/Motion/CubismMotionComponent.h b/Source/Live2DCubismFramework/Public/Motion/CubismMotionComponent.h index 772275d..f1eb948 100644 --- a/Source/Live2DCubismFramework/Public/Motion/CubismMotionComponent.h +++ b/Source/Live2DCubismFramework/Public/Motion/CubismMotionComponent.h @@ -41,7 +41,7 @@ class LIVE2DCUBISMFRAMEWORK_API UCubismMotionComponent : public UActorComponent /** * The index of the motion to play. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Live2D Cubism", meta = (ClampMin = "-1", SliderMin = "-1")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Live2D Cubism") int32 Index = -1; /** @@ -141,7 +141,7 @@ class LIVE2DCUBISMFRAMEWORK_API UCubismMotionComponent : public UActorComponent * @brief The function to update the motion. * @param Motion The motion to update. */ - void UpdateMotion(const TSharedPtr& Motion); + void UpdateMotion(float UserTimeSeconds, float FadeWeight, const TSharedPtr& CubismMotion); public: // UObject interface diff --git a/Source/Live2DCubismFramework/Public/Physics/CubismPhysics3Json.h b/Source/Live2DCubismFramework/Public/Physics/CubismPhysics3Json.h index 6dc1904..d5590bb 100644 --- a/Source/Live2DCubismFramework/Public/Physics/CubismPhysics3Json.h +++ b/Source/Live2DCubismFramework/Public/Physics/CubismPhysics3Json.h @@ -55,7 +55,7 @@ enum class ECubismPhysicsSource : uint8 * An enumeration to specify the target of physics parameter. */ UENUM(BlueprintType) -enum class ECubismPhysicsTargetType +enum class ECubismPhysicsTargetType : uint8 { Parameter, }; diff --git a/Source/Live2DCubismFrameworkEditor/Private/CubismModelActorFactory.cpp b/Source/Live2DCubismFrameworkEditor/Private/CubismModelActorFactory.cpp index 1871516..de58aab 100644 --- a/Source/Live2DCubismFrameworkEditor/Private/CubismModelActorFactory.cpp +++ b/Source/Live2DCubismFrameworkEditor/Private/CubismModelActorFactory.cpp @@ -46,11 +46,6 @@ void UCubismModelActorFactory::PostSpawnActor(UObject* Asset, AActor* NewActor) NewActor->SetActorLocation(GEditor->ClickLocation); } -void UCubismModelActorFactory::PostCreateBlueprint(UObject* Asset, AActor* CDO) -{ - -} - void UCubismModelActorFactory::CreateModel(const TObjectPtr& ModelActor, const TObjectPtr& Model3Json) { UCubismModelComponent* Model = NewObject(ModelActor, TEXT("CubismModel"), RF_Transactional); @@ -70,13 +65,6 @@ void UCubismModelActorFactory::CreateModel(const TObjectPtr& Model ModelActor->AddInstanceComponent(Model); } - { - UCubismRendererComponent* Renderer = NewObject(Model, TEXT("CubismRenderer"), RF_Transactional); - - Renderer->RegisterComponent(); - ModelActor->AddInstanceComponent(Renderer); - } - // setup cubism parameter store { UCubismParameterStoreComponent* ParameterStore = NewObject(Model, TEXT("CubismParameterStore"), RF_Transactional); @@ -84,16 +72,20 @@ void UCubismModelActorFactory::CreateModel(const TObjectPtr& Model ParameterStore->RegisterComponent(); } - // load physics3.json - const TObjectPtr& Physics3Json = LoadPhysics3Json(Model3Json); - if (Physics3Json != nullptr) + // load motion3.json + const TArray& Motion3JsonGroups = LoadMotion3Jsons(Model3Json); + if (Motion3JsonGroups.Num() != 0) { - UCubismPhysicsComponent* Physics = NewObject(Model, TEXT("CubismPhysics")); + UCubismMotionComponent* Motion = NewObject(Model, TEXT("CubismMotion"), RF_Transactional); - Physics->Json = Physics3Json; + Motion->Jsons.Empty(); + for (const FMotion3JsonGroup& Group : Motion3JsonGroups) + { + Motion->Jsons.Append(Group.Motion3Jsons); + } - Physics->RegisterComponent(); - ModelActor->AddInstanceComponent(Physics); + Motion->RegisterComponent(); + ModelActor->AddInstanceComponent(Motion); } // load pose3.json @@ -121,34 +113,6 @@ void UCubismModelActorFactory::CreateModel(const TObjectPtr& Model ModelActor->AddInstanceComponent(Expression); } - // load motion3.json - const TArray& Motion3JsonGroups = LoadMotion3Jsons(Model3Json); - if (Motion3JsonGroups.Num() != 0) - { - UCubismMotionComponent* Motion = NewObject(Model, TEXT("CubismMotion"), RF_Transactional); - - Motion->Jsons.Empty(); - for (const FMotion3JsonGroup& Group : Motion3JsonGroups) - { - Motion->Jsons.Append(Group.Motion3Jsons); - } - - Motion->RegisterComponent(); - ModelActor->AddInstanceComponent(Motion); - } - - // load userdata3.json - const TObjectPtr& UserData3Json = LoadUserData3Json(Model3Json); - if (UserData3Json != nullptr) - { - UCubismUserDataComponent* UserData = NewObject(Model, TEXT("CubismUserData"), RF_Transactional); - - UserData->Json = UserData3Json; - - UserData->RegisterComponent(); - ModelActor->AddInstanceComponent(UserData); - } - // setup eye blink if exists if (Model3Json->EyeBlinks.Num() > 0) { @@ -182,6 +146,37 @@ void UCubismModelActorFactory::CreateModel(const TObjectPtr& Model Raycast->RegisterComponent(); ModelActor->AddInstanceComponent(Raycast); } + + // load physics3.json + const TObjectPtr& Physics3Json = LoadPhysics3Json(Model3Json); + if (Physics3Json != nullptr) + { + UCubismPhysicsComponent* Physics = NewObject(Model, TEXT("CubismPhysics")); + + Physics->Json = Physics3Json; + + Physics->RegisterComponent(); + ModelActor->AddInstanceComponent(Physics); + } + + { + UCubismRendererComponent* Renderer = NewObject(Model, TEXT("CubismRenderer"), RF_Transactional); + + Renderer->RegisterComponent(); + ModelActor->AddInstanceComponent(Renderer); + } + + // load userdata3.json + const TObjectPtr& UserData3Json = LoadUserData3Json(Model3Json); + if (UserData3Json != nullptr) + { + UCubismUserDataComponent* UserData = NewObject(Model, TEXT("CubismUserData"), RF_Transactional); + + UserData->Json = UserData3Json; + + UserData->RegisterComponent(); + ModelActor->AddInstanceComponent(UserData); + } } const FString GetAssetPath(const FString& SourcePath) diff --git a/Source/Live2DCubismFrameworkEditor/Public/CubismModelActorFactory.h b/Source/Live2DCubismFrameworkEditor/Public/CubismModelActorFactory.h index 4806879..81c9ef5 100644 --- a/Source/Live2DCubismFrameworkEditor/Public/CubismModelActorFactory.h +++ b/Source/Live2DCubismFrameworkEditor/Public/CubismModelActorFactory.h @@ -47,7 +47,6 @@ class UCubismModelActorFactory : public UActorFactory public: //~ Begin UActorFactory Interface virtual void PostSpawnActor(UObject* Asset, AActor* NewActor) override; - virtual void PostCreateBlueprint(UObject* Asset, AActor* CDO) override; virtual bool CanCreateActorFrom(const FAssetData& AssetData, FText& OutErrorMsg) override; //~ End UActorFactory Interface };