Add Games File
This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "AnimNode_VrmConstraint.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmAssetListObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
|
||||
FAnimNode_VrmConstraint::FAnimNode_VrmConstraint() {
|
||||
}
|
||||
|
||||
void FAnimNode_VrmConstraint::UpdateCache(FComponentSpacePoseContext& Output) {
|
||||
}
|
||||
|
||||
void FAnimNode_VrmConstraint::Initialize_AnyThread(const FAnimationInitializeContext& Context) {
|
||||
bCallInitialized = true;
|
||||
Super::Initialize_AnyThread(Context);
|
||||
|
||||
VrmMetaObject_Internal = const_cast<UVrmMetaObject*>(VrmMetaObject);
|
||||
if (VrmMetaObject_Internal == nullptr && EnableAutoSearchMetaData) {
|
||||
VrmAssetListObject_Internal = VRMUtil::GetAssetListObject(VRMGetSkinnedAsset(Context.AnimInstanceProxy->GetSkelMeshComponent()));
|
||||
if (VrmAssetListObject_Internal) {
|
||||
VrmMetaObject_Internal = VrmAssetListObject_Internal->VrmMetaObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
void FAnimNode_VrmConstraint::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) {
|
||||
Super::CacheBones_AnyThread(Context);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmConstraint::UpdateInternal(const FAnimationUpdateContext& Context){
|
||||
Super::UpdateInternal(Context);
|
||||
}
|
||||
|
||||
|
||||
void FAnimNode_VrmConstraint::GatherDebugData(FNodeDebugData& DebugData)
|
||||
{
|
||||
FString DebugLine = DebugData.GetNodeName(this);
|
||||
|
||||
DebugLine += "(";
|
||||
AddDebugNodeData(DebugLine);
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneToModify.BoneName.ToString());
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneNameToModify.ToString());
|
||||
DebugData.AddDebugItem(DebugLine);
|
||||
|
||||
ComponentPose.GatherDebugData(DebugData);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmConstraint::EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) {
|
||||
if (bCallByAnimInstance) {
|
||||
ActualAlpha = 1.f;
|
||||
} else {
|
||||
Super::EvaluateComponentPose_AnyThread(Output);
|
||||
}
|
||||
}
|
||||
|
||||
void FAnimNode_VrmConstraint::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
|
||||
{
|
||||
check(OutBoneTransforms.Num() == 0);
|
||||
|
||||
UpdateCache(Output);
|
||||
|
||||
if (VrmMetaObject_Internal == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& a : VrmMetaObject_Internal->VRMConstraintMeta) {
|
||||
|
||||
|
||||
int32 dstBoneIndex = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().FindBoneIndex(*(a.Key));
|
||||
if (Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().GetRefBonePose().IsValidIndex(dstBoneIndex) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FCompactPoseBoneIndex dstPoseBoneIndex(dstBoneIndex);
|
||||
auto dstRefTrans = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().GetRefBonePose()[dstBoneIndex];
|
||||
auto dstRefRot = dstRefTrans.GetRotation();
|
||||
|
||||
auto dstParentBoneIndex = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().GetParentIndex(dstBoneIndex);
|
||||
FCompactPoseBoneIndex dstParentPoseBoneIndex(dstParentBoneIndex);
|
||||
auto dstParentTrans = Output.Pose.GetComponentSpaceTransform(dstParentPoseBoneIndex);
|
||||
|
||||
int32 srcBoneIndex = -1;
|
||||
|
||||
switch (a.Value.type) {
|
||||
case EVRMConstraintType::None:
|
||||
break;
|
||||
case EVRMConstraintType::Roll:
|
||||
{
|
||||
auto& tmp = a.Value.constraintRoll;
|
||||
srcBoneIndex = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().FindBoneIndex(*(tmp.sourceName));
|
||||
}
|
||||
break;
|
||||
case EVRMConstraintType::Aim :
|
||||
{
|
||||
auto& tmp = a.Value.constraintAim;
|
||||
srcBoneIndex = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().FindBoneIndex(*(tmp.sourceName));
|
||||
}
|
||||
break;
|
||||
case EVRMConstraintType::Rotation :
|
||||
{
|
||||
auto& tmp = a.Value.constraintRotation;
|
||||
srcBoneIndex = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().FindBoneIndex(*(tmp.sourceName));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (srcBoneIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
FCompactPoseBoneIndex srcPoseBoneIndex(srcBoneIndex);
|
||||
auto srcRefTrans = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().GetRefBonePose()[srcBoneIndex];
|
||||
auto srcRefRot = srcRefTrans.GetRotation();
|
||||
|
||||
auto srcParentBoneIndex = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().GetParentIndex(srcBoneIndex);
|
||||
FCompactPoseBoneIndex srcParentPoseBoneIndex(srcParentBoneIndex);
|
||||
auto srcParentTrans = Output.Pose.GetComponentSpaceTransform(srcParentPoseBoneIndex);
|
||||
|
||||
|
||||
if (a.Value.type == EVRMConstraintType::Rotation) {
|
||||
auto& rot = a.Value.constraintRotation;
|
||||
|
||||
auto srcCurrentTrans = Output.Pose.GetLocalSpaceTransform(srcPoseBoneIndex);
|
||||
auto srcCurrentRot = srcCurrentTrans.GetRotation();
|
||||
|
||||
auto dstCurrentTrans = Output.Pose.GetComponentSpaceTransform(dstPoseBoneIndex);
|
||||
auto dstCurrentRot = dstCurrentTrans.GetRotation();
|
||||
|
||||
{
|
||||
auto r = (srcRefRot.Inverse() * srcCurrentRot);
|
||||
FVector axis;
|
||||
decltype(FVector::X) angle;
|
||||
r.ToAxisAndAngle(axis, angle);
|
||||
r = FQuat(axis, angle * rot.weight);
|
||||
r = dstParentTrans.GetRotation() * dstRefRot * r;
|
||||
|
||||
dstCurrentTrans.SetRotation(r);
|
||||
Output.Pose.SetComponentSpaceTransform(dstPoseBoneIndex, dstCurrentTrans);
|
||||
}
|
||||
}
|
||||
if (a.Value.type == EVRMConstraintType::Roll) {
|
||||
auto& roll = a.Value.constraintRoll;
|
||||
|
||||
auto srcCurrentTrans = Output.Pose.GetLocalSpaceTransform(srcPoseBoneIndex);
|
||||
auto srcCurrentRot = srcCurrentTrans.GetRotation();
|
||||
|
||||
auto dstCurrentTrans = Output.Pose.GetComponentSpaceTransform(dstPoseBoneIndex);
|
||||
auto dstCurrentRot = dstCurrentTrans.GetRotation();
|
||||
|
||||
{
|
||||
//auto r = (srcRefRot.Inverse() * srcCurrentRot);
|
||||
auto r = srcCurrentRot;
|
||||
//auto r = (srcCurrentRot);
|
||||
FVector axis;
|
||||
decltype(FVector::X) angle;
|
||||
r.ToAxisAndAngle(axis, angle);
|
||||
angle = FMath::UnwindRadians(angle);
|
||||
FVector v;
|
||||
if (roll.rollAxis.Find("X") >= 0) {
|
||||
v.Set(1, 0, 0);
|
||||
}
|
||||
if (roll.rollAxis.Find("Y") >= 0) {
|
||||
v.Set(0, 1, 0);
|
||||
}
|
||||
if (roll.rollAxis.Find("Z") >= 0) {
|
||||
v.Set(0, 0, 1);
|
||||
}
|
||||
if (roll.rollAxis.Find("negative") >= 0) {
|
||||
v *= -1.f;
|
||||
}
|
||||
//v = srcCurrentTrans.TransformVector(v);
|
||||
//v *= -1.f;
|
||||
|
||||
auto d = FVector::DotProduct(axis, v);
|
||||
r = FQuat(v, angle * roll.weight * d);
|
||||
|
||||
r = dstParentTrans.GetRotation() * r;
|
||||
dstCurrentTrans.SetRotation(r);
|
||||
Output.Pose.SetComponentSpaceTransform(dstPoseBoneIndex, dstCurrentTrans);
|
||||
}
|
||||
}
|
||||
if (a.Value.type == EVRMConstraintType::Aim) {
|
||||
auto& aim = a.Value.constraintAim;
|
||||
|
||||
//auto srcCurrentTrans = Output.Pose.GetComponentSpaceTransform(srcPoseBoneIndex);
|
||||
//auto srcCurrentRot = srcCurrentTrans.GetRotation();
|
||||
|
||||
//auto dstCurrentTrans = Output.Pose.GetComponentSpaceTransform(dstPoseBoneIndex);
|
||||
auto dstCurrentTrans = dstRefTrans * dstParentTrans;
|
||||
//auto dstCurrentRot = dstCurrentTrans.GetRotation();
|
||||
|
||||
{
|
||||
|
||||
FVector v;
|
||||
if (aim.aimAxis.Find("X") >= 0) {
|
||||
v.Set(1, 0, 0);
|
||||
}
|
||||
if (aim.aimAxis.Find("Y") >= 0) {
|
||||
v.Set(0, 1, 0);
|
||||
}
|
||||
if (aim.aimAxis.Find("Z") >= 0) {
|
||||
v.Set(0, 0, 1);
|
||||
}
|
||||
if (aim.aimAxis.Find("negative") >= 0) {
|
||||
v *= -1.f;
|
||||
}
|
||||
|
||||
auto fromVec = dstCurrentTrans.TransformVector(v);
|
||||
auto toVec = srcParentTrans.TransformVector(v);
|
||||
//auto toVec = (srcCurrentTrans.GetLocation() - srcRefTrans.GetLocation()).Normalize();
|
||||
auto fromToQuat = FQuat::FindBetweenNormals(fromVec, toVec);
|
||||
|
||||
auto r = fromToQuat;
|
||||
|
||||
FVector axis;
|
||||
decltype(FVector::X) angle;
|
||||
r.ToAxisAndAngle(axis, angle);
|
||||
r = FQuat(axis, angle * aim.weight);
|
||||
|
||||
r = dstCurrentTrans.GetRotation().Inverse() * r * dstCurrentTrans.GetRotation();
|
||||
|
||||
r = dstParentTrans.GetRotation() * dstRefRot * r;
|
||||
dstCurrentTrans.SetRotation(r);
|
||||
Output.Pose.SetComponentSpaceTransform(dstPoseBoneIndex, dstCurrentTrans);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FAnimNode_VrmConstraint::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAnimNode_VrmConstraint::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
||||
{
|
||||
//BoneToModify.Initialize(RequiredBones);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmConstraint::ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground) const
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
|
||||
auto MetaObjectLocal = VrmMetaObject_Internal;
|
||||
|
||||
if (MetaObjectLocal == nullptr && EnableAutoSearchMetaData) {
|
||||
auto* p = VRMUtil::GetAssetListObject(VRMGetSkinnedAsset(PreviewSkelMeshComp));
|
||||
if (p) {
|
||||
MetaObjectLocal = p->VrmMetaObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (MetaObjectLocal == nullptr || PreviewSkelMeshComp == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (PreviewSkelMeshComp->GetWorld() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESceneDepthPriorityGroup Priority = SDPG_World;
|
||||
if (bPreviewForeground) Priority = SDPG_Foreground;
|
||||
|
||||
|
||||
const TArray<FLinearColor> color = {
|
||||
FLinearColor(1.f, 0, 0),
|
||||
FLinearColor(1.f, 0.5, 0),
|
||||
FLinearColor(1.f, 0, 0.5),
|
||||
};
|
||||
|
||||
for (const auto& c : MetaObjectLocal->VRMConstraintMeta) {
|
||||
int colType = 0;
|
||||
FString sourceName;
|
||||
switch (c.Value.type) {
|
||||
case EVRMConstraintType::Rotation:
|
||||
sourceName = c.Value.constraintRotation.sourceName;
|
||||
colType = 0;
|
||||
break;
|
||||
case EVRMConstraintType::Aim:
|
||||
sourceName = c.Value.constraintAim.sourceName;
|
||||
colType = 1;
|
||||
break;
|
||||
case EVRMConstraintType::Roll:
|
||||
sourceName = c.Value.constraintRoll.sourceName;
|
||||
colType = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
FString targetName = c.Key;
|
||||
|
||||
const FTransform t1 = PreviewSkelMeshComp->GetSocketTransform(*sourceName);
|
||||
const FTransform t2 = PreviewSkelMeshComp->GetSocketTransform(*targetName);
|
||||
|
||||
DrawWireSphere(PDI, t1, color[colType], 1, 32, Priority);
|
||||
|
||||
PDI->DrawLine(
|
||||
t1.GetLocation(),
|
||||
t2.GetLocation(),
|
||||
color[colType] / 2.f,
|
||||
Priority);
|
||||
}
|
||||
|
||||
|
||||
// PDI->DrawLine(
|
||||
// t.GetLocation(),
|
||||
// t2.GetLocation(),
|
||||
// color[springNo % color.Num()] / 2.f,
|
||||
// Priority);
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
|
||||
#include "AnimNode_VrmCopyHandBone.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "BonePose.h"
|
||||
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
namespace {
|
||||
|
||||
const TArray<FString> HandBoneTableLeap = {
|
||||
// "L_Wrist",
|
||||
//"L_Palm",
|
||||
"L_thumb_meta",
|
||||
"L_thumb_a",
|
||||
"L_thumb_b",
|
||||
// "L_thumb_end",
|
||||
// "L_index_meta",
|
||||
"L_index_a",
|
||||
"L_index_b",
|
||||
"L_index_c",
|
||||
// "L_index_end",
|
||||
// "L_middle_meta",
|
||||
"L_middle_a",
|
||||
"L_middle_b",
|
||||
"L_middle_c",
|
||||
// "L_middle_end",
|
||||
// "L_ring_meta",
|
||||
"L_ring_a",
|
||||
"L_ring_b",
|
||||
"L_ring_c",
|
||||
// "L_ring_end",
|
||||
// "L_pinky_meta",
|
||||
"L_pinky_a",
|
||||
"L_pinky_b",
|
||||
"L_pinky_c",
|
||||
// "L_pinky_end",
|
||||
|
||||
// "R_Wrist",
|
||||
//"R_Palm",
|
||||
"R_thumb_meta",
|
||||
"R_thumb_a",
|
||||
"R_thumb_b",
|
||||
// "R_thumb_end",
|
||||
// "R_index_meta",
|
||||
"R_index_a",
|
||||
"R_index_b",
|
||||
"R_index_c",
|
||||
// "R_index_end",
|
||||
// "R_middle_meta",
|
||||
"R_middle_a",
|
||||
"R_middle_b",
|
||||
"R_middle_c",
|
||||
// "R_middle_end",
|
||||
// "R_ring_meta",
|
||||
"R_ring_a",
|
||||
"R_ring_b",
|
||||
"R_ring_c",
|
||||
// "R_ring_end",
|
||||
// "R_pinky_meta",
|
||||
"R_pinky_a",
|
||||
"R_pinky_b",
|
||||
"R_pinky_c",
|
||||
// "R_pinky_end",
|
||||
};
|
||||
|
||||
const TArray<FString> HandBoneTableVRoid = {
|
||||
//"J_Bip_L_Hand",
|
||||
"J_Bip_L_Thumb1",
|
||||
"J_Bip_L_Thumb2",
|
||||
"J_Bip_L_Thumb3",
|
||||
"J_Bip_L_Index1",
|
||||
"J_Bip_L_Index2",
|
||||
"J_Bip_L_Index3",
|
||||
"J_Bip_L_Middle1",
|
||||
"J_Bip_L_Middle2",
|
||||
"J_Bip_L_Middle3",
|
||||
"J_Bip_L_Ring1",
|
||||
"J_Bip_L_Ring2",
|
||||
"J_Bip_L_Ring3",
|
||||
"J_Bip_L_Little1",
|
||||
"J_Bip_L_Little2",
|
||||
"J_Bip_L_Little3",
|
||||
|
||||
|
||||
//"J_Bip_R_Hand",
|
||||
"J_Bip_R_Thumb1",
|
||||
"J_Bip_R_Thumb2",
|
||||
"J_Bip_R_Thumb3",
|
||||
"J_Bip_R_Index1",
|
||||
"J_Bip_R_Index2",
|
||||
"J_Bip_R_Index3",
|
||||
"J_Bip_R_Middle1",
|
||||
"J_Bip_R_Middle2",
|
||||
"J_Bip_R_Middle3",
|
||||
"J_Bip_R_Ring1",
|
||||
"J_Bip_R_Ring2",
|
||||
"J_Bip_R_Ring3",
|
||||
"J_Bip_R_Little1",
|
||||
"J_Bip_R_Little2",
|
||||
"J_Bip_R_Little3",
|
||||
};
|
||||
|
||||
const TArray<FString> HandBoneTableVRM = {
|
||||
//"leftHand",
|
||||
"leftThumbProximal",
|
||||
"leftThumbIntermediate",
|
||||
"leftThumbDistal",
|
||||
"leftIndexProximal",
|
||||
"leftIndexIntermediate",
|
||||
"leftIndexDistal",
|
||||
"leftMiddleProximal",
|
||||
"leftMiddleIntermediate",
|
||||
"leftMiddleDistal",
|
||||
"leftRingProximal",
|
||||
"leftRingIntermediate",
|
||||
"leftRingDistal",
|
||||
"leftLittleProximal",
|
||||
"leftLittleIntermediate",
|
||||
"leftLittleDistal",
|
||||
|
||||
//"rightHand"
|
||||
"rightThumbProximal",
|
||||
"rightThumbIntermediate",
|
||||
"rightThumbDistal",
|
||||
"rightIndexProximal",
|
||||
"rightIndexIntermediate",
|
||||
"rightIndexDistal",
|
||||
"rightMiddleProximal",
|
||||
"rightMiddleIntermediate",
|
||||
"rightMiddleDistal",
|
||||
"rightRingProximal",
|
||||
"rightRingIntermediate",
|
||||
"rightRingDistal",
|
||||
"rightLittleProximal",
|
||||
"rightLittleIntermediate",
|
||||
"rightLittleDistal",
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
FAnimNode_VrmCopyHandBone::FAnimNode_VrmCopyHandBone()
|
||||
{
|
||||
}
|
||||
|
||||
void FAnimNode_VrmCopyHandBone::GatherDebugData(FNodeDebugData& DebugData)
|
||||
{
|
||||
FString DebugLine = DebugData.GetNodeName(this);
|
||||
|
||||
DebugLine += "(";
|
||||
AddDebugNodeData(DebugLine);
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneToModify.BoneName.ToString());
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneNameToModify.ToString());
|
||||
DebugData.AddDebugItem(DebugLine);
|
||||
|
||||
ComponentPose.GatherDebugData(DebugData);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmCopyHandBone::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
|
||||
{
|
||||
check(OutBoneTransforms.Num() == 0);
|
||||
|
||||
const auto dstRefSkeleton = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton();
|
||||
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
|
||||
//dstRefSkeleton.GetParentIndex
|
||||
|
||||
TArray<FBoneTransform> tmpOutTransform;
|
||||
tmpOutTransform.SetNum(HandBoneTableVRoid.Num());
|
||||
|
||||
TArray<int> boneIndexTable;
|
||||
boneIndexTable.SetNum(HandBoneTableVRoid.Num());
|
||||
|
||||
auto BoneSpace = EBoneControlSpace::BCS_ParentBoneSpace;
|
||||
|
||||
TArray<USkeletalMeshComponent*> MeshTable = {
|
||||
SkeletalMeshComponentLeft,
|
||||
SkeletalMeshComponentRight,
|
||||
};
|
||||
|
||||
for (int i = 0; i < HandBoneTableVRM.Num(); ++i) {
|
||||
|
||||
FString BoneNameModel = HandBoneTableVRoid[i];
|
||||
FString BoneNameLeap = HandBoneTableLeap[i];
|
||||
|
||||
if (VrmMetaObject) {
|
||||
FString *s = VrmMetaObject->humanoidBoneTable.Find(HandBoneTableVRM[i]);
|
||||
if (s) {
|
||||
BoneNameModel = *s;
|
||||
}
|
||||
}
|
||||
|
||||
boneIndexTable[i] = -1;
|
||||
int skelNo = -1;
|
||||
for (auto SkeletalMeshComponent : MeshTable) {
|
||||
skelNo++;
|
||||
|
||||
if (SkeletalMeshComponent == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto &dstRefSkeletonTransform = dstRefSkeleton.GetRefBonePose();
|
||||
const auto &srcRefSkeletonTransform = VRMGetRefSkeleton( VRMGetSkinnedAsset(SkeletalMeshComponent) ).GetRefBonePose();
|
||||
|
||||
const auto srcIndex = SkeletalMeshComponent->GetBoneIndex(*BoneNameLeap);
|
||||
const auto dstIndex = dstRefSkeleton.FindBoneIndex(*BoneNameModel);
|
||||
|
||||
if (srcIndex < 0 || dstIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& srcCurrentTrans = SkeletalMeshComponent->GetSocketTransform(*BoneNameLeap, RTS_ParentBoneSpace);
|
||||
|
||||
const auto& srcRefTrans = srcRefSkeletonTransform[srcIndex];
|
||||
const auto& dstRefTrans = dstRefSkeletonTransform[dstIndex];
|
||||
|
||||
FCompactPoseBoneIndex CompactPoseBoneToModify(dstIndex);
|
||||
|
||||
//auto a = srcCurrentTrans;
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(CompactPoseBoneToModify);
|
||||
FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, BoneSpace);
|
||||
|
||||
FQuat baseDiff = FQuat::FindBetween(srcRefTrans.GetLocation(), dstRefTrans.GetLocation());
|
||||
//FQuat q9 = FQuat(FVector(1, 0, 0), 3.14f / 2.f);
|
||||
FQuat q9;
|
||||
|
||||
auto v = srcRefTrans.GetLocation().GetSafeNormal();
|
||||
if (skelNo == 0) {
|
||||
if (BoneNameLeap.Find(TEXT("thumb")) >= 0) {
|
||||
if (BoneNameLeap.Find(TEXT("meta")) < 0) {
|
||||
q9 = FQuat(FVector(1, 0, 0), 3.14f / 2.f) * FQuat(v, -3.14f / 2.f) * srcRefTrans.GetRotation().Inverse();
|
||||
} else {
|
||||
auto vv = srcRefTrans.GetLocation();
|
||||
vv.Y = srcRefTrans.GetLocation().Z;
|
||||
vv.Z = srcRefTrans.GetLocation().Y;
|
||||
|
||||
FQuat baseDiff2 = FQuat::FindBetween(vv, FVector(1,0,0));
|
||||
q9 = FQuat(v, -3.14f / 2.f) * baseDiff2.Inverse() * srcRefTrans.GetRotation().Inverse();
|
||||
}
|
||||
}else {
|
||||
q9 = FQuat(v, 3.14f / 2.f) * srcRefTrans.GetRotation().Inverse();
|
||||
}
|
||||
} else {
|
||||
if (BoneNameLeap.Find(TEXT("thumb")) >= 0) {
|
||||
if (BoneNameLeap.Find(TEXT("meta")) < 0) {
|
||||
//q9 = srcRefTrans.GetRotation().Inverse();
|
||||
q9 = FQuat(FVector(1, 0, 0), 3.14f / 2.f) * FQuat(v, -3.14f / 2.f) * srcRefTrans.GetRotation().Inverse();
|
||||
} else {
|
||||
//q9 = FQuat(-v, 3.14f) * srcRefTrans.GetRotation().Inverse();
|
||||
|
||||
auto vv = srcRefTrans.GetLocation();
|
||||
vv.X = srcRefTrans.GetLocation().X;
|
||||
vv.Y = srcRefTrans.GetLocation().Z;
|
||||
vv.Z = srcRefTrans.GetLocation().Y;
|
||||
|
||||
FQuat baseDiff2 = FQuat::FindBetween(vv, FVector(-1,0,0));
|
||||
auto tt = srcRefTrans;
|
||||
tt.SetLocation(vv);
|
||||
//q9 = FQuat(FVector(1, 0, 0), 3.14f / 2.f) * FQuat(v, 3.14f / 2.f) * baseDiff2.Inverse() * srcRefTrans.GetRotation().Inverse();
|
||||
//q9 = FQuat(FVector(0, 0, -1), -3.14f / 2.f) * FQuat(FVector(1, 0, 0), -3.14f / 2.f) * FQuat(FVector(0, 1, 0), -3.14f / 2.f) * FQuat(v, 3.14f / 2.f) * baseDiff2.Inverse() * srcRefTrans.GetRotation().Inverse();
|
||||
q9 = FQuat(FVector(0, 0, -1), -3.14f / 2.f) * FQuat(FVector(1, 0, 0), -3.14f / 2.f) * FQuat(FVector(0, 1, 0), -3.14f / 2.f) * FQuat(v, 3.14f / 2.f) * baseDiff2.Inverse() * srcRefTrans.GetRotation().Inverse();
|
||||
//q9.X *= -1.f;
|
||||
//q9.Y *= -1.f;
|
||||
//q9.Z *= -1.f;
|
||||
|
||||
|
||||
/*
|
||||
auto vv = srcRefTrans.GetLocation();
|
||||
vv.X = -srcRefTrans.GetLocation().X;
|
||||
vv.Y = srcRefTrans.GetLocation().Z;
|
||||
vv.Z = srcRefTrans.GetLocation().Y;
|
||||
|
||||
FQuat baseDiff2 = FQuat::FindBetween(vv, FVector(1,0,0));
|
||||
//q9 = FQuat(FVector(1, 0, 0), 3.14f / 2.f) * FQuat(v, 3.14f / 2.f) * baseDiff2.Inverse() * srcRefTrans.GetRotation().Inverse();
|
||||
q9 = FQuat(FVector(1, 0, 0), -3.14f / 2.f) * FQuat(FVector(0, 1, 0), -3.14f / 2.f) * FQuat(v, 3.14f / 2.f) * baseDiff2.Inverse() * srcRefTrans.GetRotation().Inverse();
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
q9 = FQuat(-v, 3.14f / 2.f) * FQuat(FVector(0, 1, 0), 3.14f) * FQuat(FVector(0, 0, 1), 3.14f) * srcRefTrans.GetRotation().Inverse();
|
||||
}
|
||||
}
|
||||
|
||||
FQuat q = baseDiff * q9;
|
||||
//FQuat q = FQuat::FindBetween(srcRefTrans.GetLocation(), dstRefTrans.GetLocation());
|
||||
|
||||
//NewBoneTM.SetRotation(q*FQuat(FVector(1, 0, 0), 3.14f / 2.f) * srcCurrentTrans.GetRotation() * FQuat(FVector(-1, 0, 0), 3.14f / 2.f));
|
||||
//NewBoneTM.SetRotation(FQuat(FVector(1, 0, 0), 3.14f / 2.f) * srcCurrentTrans.GetRotation() * FQuat(FVector(-1, 0, 0), 3.14f / 2.f));
|
||||
|
||||
NewBoneTM.SetRotation(q * srcCurrentTrans.GetRotation() * q.Inverse());
|
||||
|
||||
//NewBoneTM.SetRotation(q9 * baseDiff*srcCurrentTrans.GetRotation() * baseDiff.Inverse() * q9.Inverse());
|
||||
//NewBoneTM.SetRotation(q9 * baseDiff*srcCurrentTrans.GetRotation() * q9.Inverse());
|
||||
|
||||
|
||||
//NewBoneTM.SetLocation(dstRefTrans.GetLocation());
|
||||
|
||||
//NewBoneTM.SetLocation(NewBoneTM.GetLocation() );
|
||||
//NewBoneTM.SetLocation(NewBoneTM.GetRotation() * dstRefTrans.GetLocation() );
|
||||
//NewBoneTM.SetLocation(dstRefTrans.GetLocation());
|
||||
//a.SetLocation(dstRefTrans.GetLocation());
|
||||
|
||||
//FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, a, CompactPoseBoneToModify, EBoneControlSpace::BCS_ParentBoneSpace);
|
||||
|
||||
//OutBoneTransforms.Insert
|
||||
tmpOutTransform[i] = FBoneTransform(CompactPoseBoneToModify, NewBoneTM);
|
||||
boneIndexTable[i] = dstIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
tmpOutTransform.Sort(FCompareBoneTransformIndex());
|
||||
//tmpOutTransform.Sort([](const FBoneTransform& x, const FBoneTransform& y) { return x.BoneIndex.GetInt() < y.BoneIndex.GetInt(); });
|
||||
|
||||
boneIndexTable.Sort();
|
||||
for (int i=0; i<tmpOutTransform.Num(); ++i){
|
||||
if (boneIndexTable[i] < 0) {
|
||||
continue;
|
||||
}
|
||||
auto &a = tmpOutTransform[i];
|
||||
|
||||
int parentBoneIndex = dstRefSkeleton.GetParentIndex(boneIndexTable[i]);
|
||||
|
||||
int parentInHandTable = boneIndexTable.Find(parentBoneIndex);
|
||||
if (parentInHandTable >= 0) {
|
||||
a.Transform *= tmpOutTransform[parentInHandTable].Transform;
|
||||
}else {
|
||||
FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, a.Transform, a.BoneIndex, BoneSpace);
|
||||
}
|
||||
OutBoneTransforms.Add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FAnimNode_VrmCopyHandBone::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
// if both bones are valid
|
||||
//return (BoneToModify.IsValidToEvaluate(RequiredBones));
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAnimNode_VrmCopyHandBone::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
||||
{
|
||||
//BoneToModify.Initialize(RequiredBones);
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "AnimNode_VrmModifyBoneDynamic.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
FAnimNode_VrmModifyBoneDynamic::FAnimNode_VrmModifyBoneDynamic()
|
||||
: Translation(FVector::ZeroVector)
|
||||
, Rotation(FRotator::ZeroRotator)
|
||||
, Scale(FVector(1.0f))
|
||||
, TranslationMode(BMM_Ignore)
|
||||
, RotationMode(BMM_Ignore)
|
||||
, ScaleMode(BMM_Ignore)
|
||||
, TranslationSpace(BCS_ComponentSpace)
|
||||
, RotationSpace(BCS_ComponentSpace)
|
||||
, ScaleSpace(BCS_ComponentSpace)
|
||||
{
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneDynamic::GatherDebugData(FNodeDebugData& DebugData)
|
||||
{
|
||||
FString DebugLine = DebugData.GetNodeName(this);
|
||||
|
||||
DebugLine += "(";
|
||||
AddDebugNodeData(DebugLine);
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneToModify.BoneName.ToString());
|
||||
DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneNameToModify.ToString());
|
||||
DebugData.AddDebugItem(DebugLine);
|
||||
|
||||
ComponentPose.GatherDebugData(DebugData);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneDynamic::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
|
||||
{
|
||||
check(OutBoneTransforms.Num() == 0);
|
||||
|
||||
// the way we apply transform is same as FMatrix or FTransform
|
||||
// we apply scale first, and rotation, and translation
|
||||
// if you'd like to translate first, you'll need two nodes that first node does translate and second nodes to rotate.
|
||||
const FBoneContainer& BoneContainer = Output.Pose.GetPose().GetBoneContainer();
|
||||
|
||||
//FCompactPoseBoneIndex CompactPoseBoneToModify = BoneToModify.GetCompactPoseIndex(BoneContainer);
|
||||
int32 boneIndex = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().FindBoneIndex(BoneNameToModify);
|
||||
if (boneIndex < 0) {
|
||||
return;
|
||||
}
|
||||
FCompactPoseBoneIndex CompactPoseBoneToModify(boneIndex);
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(CompactPoseBoneToModify);
|
||||
FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
|
||||
if (ScaleMode != BMM_Ignore)
|
||||
{
|
||||
// Convert to Bone Space.
|
||||
FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, ScaleSpace);
|
||||
|
||||
if (ScaleMode == BMM_Additive)
|
||||
{
|
||||
NewBoneTM.SetScale3D(NewBoneTM.GetScale3D() * Scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
NewBoneTM.SetScale3D(Scale);
|
||||
}
|
||||
|
||||
// Convert back to Component Space.
|
||||
FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, ScaleSpace);
|
||||
}
|
||||
|
||||
if (RotationMode != BMM_Ignore)
|
||||
{
|
||||
// Convert to Bone Space.
|
||||
FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, RotationSpace);
|
||||
|
||||
const FQuat BoneQuat(Rotation);
|
||||
if (RotationMode == BMM_Additive)
|
||||
{
|
||||
NewBoneTM.SetRotation(BoneQuat * NewBoneTM.GetRotation());
|
||||
}
|
||||
else
|
||||
{
|
||||
NewBoneTM.SetRotation(BoneQuat);
|
||||
}
|
||||
|
||||
// Convert back to Component Space.
|
||||
FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, RotationSpace);
|
||||
}
|
||||
|
||||
if (TranslationMode != BMM_Ignore)
|
||||
{
|
||||
// Convert to Bone Space.
|
||||
FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, TranslationSpace);
|
||||
|
||||
if (TranslationMode == BMM_Additive)
|
||||
{
|
||||
NewBoneTM.AddToTranslation(Translation);
|
||||
}
|
||||
else
|
||||
{
|
||||
NewBoneTM.SetTranslation(Translation);
|
||||
}
|
||||
|
||||
// Convert back to Component Space.
|
||||
FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, TranslationSpace);
|
||||
}
|
||||
|
||||
if (boneIndex >= 0) {
|
||||
//FCompactPoseBoneIndex b(boneIndex);
|
||||
OutBoneTransforms.Add(FBoneTransform(CompactPoseBoneToModify, NewBoneTM));
|
||||
//OutBoneTransforms.Add(FBoneTransform(BoneToModify.GetCompactPoseIndex(BoneContainer), NewBoneTM));
|
||||
}
|
||||
}
|
||||
|
||||
bool FAnimNode_VrmModifyBoneDynamic::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
// if both bones are valid
|
||||
//return (BoneToModify.IsValidToEvaluate(RequiredBones));
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneDynamic::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
||||
{
|
||||
//BoneToModify.Initialize(RequiredBones);
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "AnimNode_VrmModifyBoneList.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
|
||||
#include <algorithm>
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
|
||||
FAnimNode_VrmModifyBoneList::FAnimNode_VrmModifyBoneList()
|
||||
{
|
||||
}
|
||||
|
||||
//void FAnimNode_VrmModifyBoneList::Update_AnyThread(const FAnimationUpdateContext& Context) {
|
||||
// Super::Update_AnyThread(Context);
|
||||
// //Context.GetDeltaTime();
|
||||
//}
|
||||
|
||||
void FAnimNode_VrmModifyBoneList::Initialize_AnyThread(const FAnimationInitializeContext& Context) {
|
||||
Super::Initialize_AnyThread(Context);
|
||||
}
|
||||
void FAnimNode_VrmModifyBoneList::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) {
|
||||
Super::CacheBones_AnyThread(Context);
|
||||
}
|
||||
|
||||
|
||||
void FAnimNode_VrmModifyBoneList::UpdateInternal(const FAnimationUpdateContext& Context){
|
||||
Super::UpdateInternal(Context);
|
||||
}
|
||||
|
||||
|
||||
void FAnimNode_VrmModifyBoneList::GatherDebugData(FNodeDebugData& DebugData)
|
||||
{
|
||||
FString DebugLine = DebugData.GetNodeName(this);
|
||||
|
||||
DebugLine += "(";
|
||||
AddDebugNodeData(DebugLine);
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneToModify.BoneName.ToString());
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneNameToModify.ToString());
|
||||
DebugData.AddDebugItem(DebugLine);
|
||||
|
||||
ComponentPose.GatherDebugData(DebugData);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneList::EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) {
|
||||
Super::EvaluateComponentPose_AnyThread(Output);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneList::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
|
||||
{
|
||||
check(OutBoneTransforms.Num() == 0);
|
||||
|
||||
const auto Skeleton = Output.AnimInstanceProxy->GetSkeleton();
|
||||
const auto RefSkeleton = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton();
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
const auto& RefSkeletonTransform = Output.Pose.GetPose().GetBoneContainer().GetRefPoseArray();
|
||||
|
||||
TArray<int> boneIndexTable;
|
||||
TArray<FBoneTransform> tmpOutTransform;
|
||||
|
||||
//dstRefSkeleton.GetParentIndex
|
||||
|
||||
{
|
||||
for (const auto &t : BoneTrans) {
|
||||
|
||||
int index = RefSkeleton.FindBoneIndex(*t.Key);
|
||||
if (index < 0) continue;
|
||||
|
||||
FBoneTransform f(FCompactPoseBoneIndex(index), t.Value);
|
||||
|
||||
FVector v = RefSkeletonTransform[index].GetLocation();
|
||||
//f.Transform.SetTranslation(v);
|
||||
|
||||
//f.Transform.SetTranslation(RefSkeletonTransform[index].GetLocation());
|
||||
tmpOutTransform.Add(f);
|
||||
boneIndexTable.Add(index);
|
||||
}
|
||||
|
||||
// bone hierarchy
|
||||
// start with 1
|
||||
for (int i = 0; i < tmpOutTransform.Num(); ++i) {
|
||||
auto& a = tmpOutTransform[i];
|
||||
int parentBoneIndex = RefSkeleton.GetParentIndex(boneIndexTable[i]);
|
||||
if (parentBoneIndex < 0) continue;
|
||||
|
||||
int parentInTable = boneIndexTable.Find(parentBoneIndex);
|
||||
|
||||
for (int j = 0; j < 100; ++j) {
|
||||
if (parentInTable >= 0) {
|
||||
// find in table
|
||||
break;
|
||||
}
|
||||
if (parentBoneIndex < 0) {
|
||||
// root bone
|
||||
break;
|
||||
}
|
||||
|
||||
// add outtransform with ref bone
|
||||
//FBoneTransform f(FCompactPoseBoneIndex(parentBoneIndex), RefSkeletonTransform[parentBoneIndex]);
|
||||
|
||||
// add outtransform with input bone
|
||||
FCompactPoseBoneIndex CompactPoseBoneToModify(parentBoneIndex);
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(CompactPoseBoneToModify);
|
||||
FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, EBoneControlSpace::BCS_ParentBoneSpace);
|
||||
|
||||
FBoneTransform f(CompactPoseBoneToModify, NewBoneTM);
|
||||
|
||||
|
||||
tmpOutTransform.Add(f);
|
||||
boneIndexTable.Add(parentBoneIndex);
|
||||
|
||||
parentBoneIndex = RefSkeleton.GetParentIndex(parentBoneIndex);
|
||||
parentInTable = boneIndexTable.Find(parentBoneIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// sort
|
||||
tmpOutTransform.Sort(FCompareBoneTransformIndex());
|
||||
boneIndexTable.Sort();
|
||||
}
|
||||
|
||||
for (int i = 0; i < tmpOutTransform.Num(); ++i) {
|
||||
auto& a = tmpOutTransform[i];
|
||||
|
||||
int parentBoneIndex = RefSkeleton.GetParentIndex(boneIndexTable[i]);
|
||||
|
||||
int parentInHandTable = boneIndexTable.Find(parentBoneIndex);
|
||||
if (parentInHandTable < 0) {
|
||||
// root
|
||||
auto BoneSpace = EBoneControlSpace::BCS_ParentBoneSpace;
|
||||
FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, a.Transform, a.BoneIndex, BoneSpace);
|
||||
}else{
|
||||
bool bUseInputTrans = false;
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
#else
|
||||
FString t = RefSkeleton.GetBoneName(boneIndexTable[i]).ToString();
|
||||
|
||||
auto ret = UseInputTransBoneList.FilterByPredicate([&t](FString a) {
|
||||
return t.Compare(a, ESearchCase::IgnoreCase) == 0;
|
||||
}
|
||||
);
|
||||
if (ret.Num() > 0) {
|
||||
bUseInputTrans = true;
|
||||
}
|
||||
#endif
|
||||
if (bUseInputTrans) {
|
||||
FCompactPoseBoneIndex CompactPoseBoneToModify(boneIndexTable[i]);
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(CompactPoseBoneToModify);
|
||||
FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, EBoneControlSpace::BCS_ParentBoneSpace);
|
||||
a.Transform = NewBoneTM * tmpOutTransform[parentInHandTable].Transform;
|
||||
} else {
|
||||
a.Transform *= tmpOutTransform[parentInHandTable].Transform;
|
||||
}
|
||||
}
|
||||
OutBoneTransforms.Add(a);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool FAnimNode_VrmModifyBoneList::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
// if both bones are valid
|
||||
//return (BoneToModify.IsValidToEvaluate(RequiredBones));
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneList::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
||||
{
|
||||
//BoneToModify.Initialize(RequiredBones);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneList::ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground) const
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
|
||||
if (PreviewSkelMeshComp->GetWorld() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESceneDepthPriorityGroup Priority = SDPG_World;
|
||||
if (bPreviewForeground) Priority = SDPG_Foreground;
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "AnimNode_VrmModifyBoneListRetarget.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
|
||||
FAnimNode_VrmModifyBoneListRetarget::FAnimNode_VrmModifyBoneListRetarget()
|
||||
{
|
||||
}
|
||||
|
||||
//void FAnimNode_VrmModifyBoneListRetarget::Update_AnyThread(const FAnimationUpdateContext& Context) {
|
||||
// Super::Update_AnyThread(Context);
|
||||
// //Context.GetDeltaTime();
|
||||
//}
|
||||
|
||||
void FAnimNode_VrmModifyBoneListRetarget::Initialize_AnyThread(const FAnimationInitializeContext& Context) {
|
||||
Super::Initialize_AnyThread(Context);
|
||||
}
|
||||
void FAnimNode_VrmModifyBoneListRetarget::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) {
|
||||
Super::CacheBones_AnyThread(Context);
|
||||
}
|
||||
|
||||
|
||||
void FAnimNode_VrmModifyBoneListRetarget::UpdateInternal(const FAnimationUpdateContext& Context){
|
||||
Super::UpdateInternal(Context);
|
||||
}
|
||||
|
||||
|
||||
void FAnimNode_VrmModifyBoneListRetarget::GatherDebugData(FNodeDebugData& DebugData)
|
||||
{
|
||||
FString DebugLine = DebugData.GetNodeName(this);
|
||||
|
||||
DebugLine += "(";
|
||||
AddDebugNodeData(DebugLine);
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneToModify.BoneName.ToString());
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneNameToModify.ToString());
|
||||
DebugData.AddDebugItem(DebugLine);
|
||||
|
||||
ComponentPose.GatherDebugData(DebugData);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneListRetarget::EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) {
|
||||
Super::EvaluateComponentPose_AnyThread(Output);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneListRetarget::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
|
||||
{
|
||||
check(OutBoneTransforms.Num() == 0);
|
||||
|
||||
const auto Skeleton = Output.AnimInstanceProxy->GetSkeleton();
|
||||
const auto RefSkeleton = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton();
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
const auto& RefSkeletonTransform = Output.Pose.GetPose().GetBoneContainer().GetRefPoseArray();
|
||||
|
||||
TArray<int> boneIndexTable;
|
||||
TArray<FBoneTransform> tmpOutTransform;
|
||||
|
||||
//dstRefSkeleton.GetParentIndex
|
||||
|
||||
{
|
||||
|
||||
if (VrmMetaObject == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool bFirstBone = true;
|
||||
|
||||
for (const auto &t : VrmMetaObject->humanoidBoneTable) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
auto *tmpVal = BoneTrans.Find(t.Key.ToLower());
|
||||
if (tmpVal == nullptr) continue;
|
||||
|
||||
auto modelBone = *tmpVal;
|
||||
#else
|
||||
auto filterList= BoneTrans.FilterByPredicate([&t](TPair<FString, FTransform> a) {
|
||||
return a.Key.Compare(t.Key, ESearchCase::IgnoreCase) == 0;
|
||||
}
|
||||
);
|
||||
if (filterList.Num() != 1) continue;
|
||||
auto modelBone = filterList.begin()->Value;
|
||||
#endif
|
||||
|
||||
|
||||
int index = RefSkeleton.FindBoneIndex(*t.Value);
|
||||
if (index < 0) continue;
|
||||
|
||||
FBoneTransform f(FCompactPoseBoneIndex(index), modelBone);
|
||||
//f.Transform.SetRotation(FQuat::Identity);
|
||||
|
||||
if (bFirstBone) {
|
||||
bFirstBone = false;
|
||||
|
||||
if (bUseRemoteCenterPos) {
|
||||
auto v = f.Transform.GetLocation() * ModelRelativeScale;
|
||||
f.Transform.SetTranslation(v);
|
||||
} else {
|
||||
auto v = RefSkeletonTransform[index].GetLocation();
|
||||
f.Transform.SetTranslation(v);
|
||||
}
|
||||
} else {
|
||||
FVector v = RefSkeletonTransform[index].GetLocation();
|
||||
f.Transform.SetTranslation(v);
|
||||
}
|
||||
|
||||
//f.Transform.SetTranslation(RefSkeletonTransform[index].GetLocation());
|
||||
tmpOutTransform.Add(f);
|
||||
boneIndexTable.Add(index);
|
||||
}
|
||||
|
||||
// bone hierarchy
|
||||
// start with 1
|
||||
for (int i = 1; i < tmpOutTransform.Num(); ++i) {
|
||||
auto& a = tmpOutTransform[i];
|
||||
int parentBoneIndex = RefSkeleton.GetParentIndex(boneIndexTable[i]);
|
||||
int parentInTable = boneIndexTable.Find(parentBoneIndex);
|
||||
|
||||
for (int j = 0; j < 100; ++j) {
|
||||
if (parentInTable >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// add outtransform with ref bone
|
||||
FBoneTransform f(FCompactPoseBoneIndex(parentBoneIndex), RefSkeletonTransform[parentBoneIndex]);
|
||||
tmpOutTransform.Add(f);
|
||||
boneIndexTable.Add(parentBoneIndex);
|
||||
|
||||
parentBoneIndex = RefSkeleton.GetParentIndex(parentBoneIndex);
|
||||
parentInTable = boneIndexTable.Find(parentBoneIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// sort
|
||||
tmpOutTransform.Sort(FCompareBoneTransformIndex());
|
||||
boneIndexTable.Sort();
|
||||
}
|
||||
|
||||
for (int i = 0; i < tmpOutTransform.Num(); ++i) {
|
||||
auto& a = tmpOutTransform[i];
|
||||
|
||||
int parentBoneIndex = RefSkeleton.GetParentIndex(boneIndexTable[i]);
|
||||
|
||||
int parentInHandTable = boneIndexTable.Find(parentBoneIndex);
|
||||
if (parentInHandTable >= 0) {
|
||||
a.Transform *= tmpOutTransform[parentInHandTable].Transform;
|
||||
} else {
|
||||
// root
|
||||
auto BoneSpace = EBoneControlSpace::BCS_ParentBoneSpace;
|
||||
FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, a.Transform, a.BoneIndex, BoneSpace);
|
||||
}
|
||||
OutBoneTransforms.Add(a);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool FAnimNode_VrmModifyBoneListRetarget::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
// if both bones are valid
|
||||
//return (BoneToModify.IsValidToEvaluate(RequiredBones));
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneListRetarget::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
||||
{
|
||||
//BoneToModify.Initialize(RequiredBones);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyBoneListRetarget::ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground) const
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
|
||||
if (VrmMetaObject == nullptr || PreviewSkelMeshComp == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (PreviewSkelMeshComp->GetWorld() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESceneDepthPriorityGroup Priority = SDPG_World;
|
||||
if (bPreviewForeground) Priority = SDPG_Foreground;
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "AnimNode_VrmModifyHumanoidBone.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
|
||||
#include "VrmAssetListObject.h"
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
FAnimNode_VrmModifyHumanoidBone::FAnimNode_VrmModifyHumanoidBone()
|
||||
:
|
||||
//TranslationMode(BMM_Ignore)
|
||||
//, RotationMode(BMM_Ignore)
|
||||
//, TranslationSpace(BCS_ComponentSpace)
|
||||
RotationSpace(BCS_WorldSpace)
|
||||
{
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyHumanoidBone::GatherDebugData(FNodeDebugData& DebugData)
|
||||
{
|
||||
FString DebugLine = DebugData.GetNodeName(this);
|
||||
|
||||
DebugLine += "(";
|
||||
AddDebugNodeData(DebugLine);
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneToModify.BoneName.ToString());
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneNameToModify.ToString());
|
||||
DebugData.AddDebugItem(DebugLine);
|
||||
|
||||
ComponentPose.GatherDebugData(DebugData);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyHumanoidBone::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
|
||||
{
|
||||
check(OutBoneTransforms.Num() == 0);
|
||||
|
||||
// the way we apply transform is same as FMatrix or FTransform
|
||||
// we apply scale first, and rotation, and translation
|
||||
// if you'd like to translate first, you'll need two nodes that first node does translate and second nodes to rotate.
|
||||
const FBoneContainer& BoneContainer = Output.Pose.GetPose().GetBoneContainer();
|
||||
|
||||
if (VrmAssetList == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &Transform_hum = HumanoidBoneTransform.Transform;
|
||||
const auto &Transform_ext = ExtBoneTransform.Transform;
|
||||
|
||||
const auto &a = VRMUtil::vrm_humanoid_bone_list;
|
||||
const auto &table = VrmAssetList->VrmMetaObject->humanoidBoneTable;
|
||||
|
||||
int boneTableNo_hum = 0;
|
||||
int boneTableNo_ext = 0;
|
||||
|
||||
while (boneTableNo_hum <= a.Num()) {
|
||||
int currentBone = -1;
|
||||
|
||||
FTransform trans;
|
||||
int boneIndex[2] = {-1, -1};
|
||||
|
||||
if (boneTableNo_hum < Transform_hum.Num() && boneTableNo_hum<a.Num()) {
|
||||
auto boneName = table.Find(a[boneTableNo_hum]);
|
||||
if (boneName) {
|
||||
boneIndex[0] = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().FindBoneIndex(**boneName);
|
||||
}
|
||||
}
|
||||
if (boneTableNo_ext < Transform_ext.Num()) {
|
||||
boneIndex[1] = boneTableNo_ext;
|
||||
}
|
||||
|
||||
if (boneIndex[0] < 0 && boneIndex[1] < 0) {
|
||||
// no bone
|
||||
++boneTableNo_hum;
|
||||
continue;
|
||||
//break;
|
||||
}
|
||||
|
||||
if (boneIndex[0] == boneIndex[1]) {
|
||||
currentBone = boneIndex[0];
|
||||
trans = Transform_hum[boneTableNo_hum];
|
||||
++boneTableNo_hum;
|
||||
++boneTableNo_ext;
|
||||
|
||||
} else {
|
||||
if (boneIndex[0] < 0) {
|
||||
// find ext
|
||||
currentBone = boneIndex[1];
|
||||
trans = Transform_ext[boneTableNo_ext];
|
||||
++boneTableNo_ext;
|
||||
} else if (boneIndex[1] < 0) {
|
||||
// find hum
|
||||
currentBone = boneIndex[0];
|
||||
trans = Transform_hum[boneTableNo_hum];
|
||||
++boneTableNo_hum;
|
||||
} else {
|
||||
if (boneIndex[0] < boneIndex[1]) {
|
||||
// find hum
|
||||
currentBone = boneIndex[0];
|
||||
trans = Transform_hum[boneTableNo_hum];
|
||||
++boneTableNo_hum;
|
||||
} else {
|
||||
// find ext
|
||||
currentBone = boneIndex[1];
|
||||
trans = Transform_ext[boneTableNo_ext];
|
||||
++boneTableNo_ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const FCompactPoseBoneIndex CompactPoseBoneToModify(currentBone);
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(CompactPoseBoneToModify);
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
const FTransform orgTM = NewBoneTM;
|
||||
|
||||
// Convert to Bone Space.
|
||||
FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, RotationSpace);
|
||||
|
||||
//const FQuat BoneQuat(Rotation);
|
||||
const FQuat BoneQuat = trans.GetRotation();
|
||||
//if (RotationMode == BMM_Additive)
|
||||
//{
|
||||
//NewBoneTM.SetRotation(BoneQuat * NewBoneTM.GetRotation());
|
||||
//} else
|
||||
//{
|
||||
NewBoneTM.SetRotation(BoneQuat);
|
||||
//}
|
||||
|
||||
// Convert back to Component Space.
|
||||
FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, RotationSpace);
|
||||
|
||||
{
|
||||
TArray<FBoneTransform> bt;
|
||||
|
||||
bt.Add(FBoneTransform(CompactPoseBoneToModify, NewBoneTM));
|
||||
|
||||
const float BlendWeight = FMath::Clamp<float>(ActualAlpha, 0.f, 1.f);
|
||||
Output.Pose.LocalBlendCSBoneTransforms(bt, BlendWeight);
|
||||
}
|
||||
//OutBoneTransforms.Add(FBoneTransform(CompactPoseBoneToModify, NewBoneTM));
|
||||
|
||||
}
|
||||
|
||||
if (0) {
|
||||
for (int boneNo = 0; boneNo < Transform_hum.Num(); ++boneNo) {
|
||||
if (boneNo >= a.Num()) {
|
||||
continue;
|
||||
}
|
||||
auto boneName = table.Find(a[boneNo]);
|
||||
|
||||
if (boneName == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int32 boneIndex = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton().FindBoneIndex(**boneName);
|
||||
|
||||
if (boneIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
auto rot = Transform_hum[boneNo].GetRotation();
|
||||
|
||||
|
||||
|
||||
const FCompactPoseBoneIndex CompactPoseBoneToModify(boneIndex);
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(CompactPoseBoneToModify);
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
const FTransform orgTM = NewBoneTM;
|
||||
|
||||
// Convert to Bone Space.
|
||||
FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, RotationSpace);
|
||||
|
||||
//const FQuat BoneQuat(Rotation);
|
||||
const FQuat BoneQuat = rot;
|
||||
//if (RotationMode == BMM_Additive)
|
||||
//{
|
||||
//NewBoneTM.SetRotation(BoneQuat * NewBoneTM.GetRotation());
|
||||
//} else
|
||||
//{
|
||||
NewBoneTM.SetRotation(BoneQuat);
|
||||
//}
|
||||
|
||||
// Convert back to Component Space.
|
||||
FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, RotationSpace);
|
||||
|
||||
{
|
||||
TArray<FBoneTransform> bt;
|
||||
|
||||
bt.Add(FBoneTransform(CompactPoseBoneToModify, NewBoneTM));
|
||||
|
||||
const float BlendWeight = FMath::Clamp<float>(ActualAlpha, 0.f, 1.f);
|
||||
Output.Pose.LocalBlendCSBoneTransforms(bt, BlendWeight);
|
||||
}
|
||||
//OutBoneTransforms.Add(FBoneTransform(CompactPoseBoneToModify, NewBoneTM));
|
||||
}
|
||||
}
|
||||
|
||||
//OutBoneTransforms.Sort(FCompareBoneTransformIndex());
|
||||
}
|
||||
|
||||
bool FAnimNode_VrmModifyHumanoidBone::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
// if both bones are valid
|
||||
//return (BoneToModify.IsValidToEvaluate(RequiredBones));
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAnimNode_VrmModifyHumanoidBone::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
||||
{
|
||||
//BoneToModify.Initialize(RequiredBones);
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "AnimNode_VrmPoseBlendNode.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmAssetListObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
|
||||
FAnimNode_VrmPoseBlendNode::FAnimNode_VrmPoseBlendNode() {
|
||||
}
|
||||
|
||||
void FAnimNode_VrmPoseBlendNode::Initialize_AnyThread(const FAnimationInitializeContext& Context) {
|
||||
bCallInitialized = true;
|
||||
|
||||
if (EnableAutoSearchMetaData) {
|
||||
auto v = VRMUtil::GetAssetListObject(VRMGetSkinnedAsset(Context.AnimInstanceProxy->GetSkelMeshComponent()));
|
||||
if (v) {
|
||||
PoseAsset = v->PoseFace;
|
||||
//SetPoseAsset(v->PoseFace);
|
||||
}
|
||||
}
|
||||
|
||||
Super::Initialize_AnyThread(Context);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmPoseBlendNode::Evaluate_AnyThread(FPoseContext& Output) {
|
||||
Super::Evaluate_AnyThread(Output);
|
||||
|
||||
if (bRemovePoseCurve) {
|
||||
auto* sk = VRMGetSkinnedAsset(Output.AnimInstanceProxy->GetSkelMeshComponent());
|
||||
|
||||
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
#elif UE_VERSION_OLDER_THAN(5,3,0)
|
||||
auto& MorphList = sk->GetMorphTargets();
|
||||
TArray<SmartName::UID_Type> removeList;
|
||||
|
||||
auto* k = sk->GetSkeleton();
|
||||
|
||||
auto CurveList = k->GetDefaultCurveUIDList();
|
||||
|
||||
//k->AddSmartNameAndModify(USkeleton::AnimCurveMappingName, *p.expressionName, sm);
|
||||
|
||||
auto* CurveMappingPtr = k->GetSmartNameContainer(USkeleton::AnimCurveMappingName);
|
||||
|
||||
//
|
||||
TArray<FName> nameList;
|
||||
CurveMappingPtr->FillUIDToNameArray(nameList);
|
||||
|
||||
TArray<SmartName::UID_Type> uidList;
|
||||
CurveMappingPtr->FillUidArray(uidList);
|
||||
|
||||
for (int i = 0; i < nameList.Num(); ++i) {
|
||||
auto* ind = MorphList.FindByPredicate([&nameList, &i](const TObjectPtr<UMorphTarget > morph) {
|
||||
if (morph->GetName().Compare(nameList[i].ToString())) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
if (ind == nullptr) {
|
||||
removeList.Add(uidList[i]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
auto& MorphList = sk->GetMorphTargets();
|
||||
TArray<FName> removeList;
|
||||
|
||||
Output.Curve.ForEachElement([&removeList, &MorphList](const UE::Anim::FCurveElement& InCurveElement)
|
||||
{
|
||||
FString CurveElementName = InCurveElement.Name.ToString();
|
||||
auto* ind = MorphList.FindByPredicate([&CurveElementName](const TObjectPtr<UMorphTarget > morph) {
|
||||
if (CurveElementName.Compare(morph->GetName(), ESearchCase::IgnoreCase) == 0) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (ind == nullptr) {
|
||||
removeList.Add(InCurveElement.Name);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
|
||||
#elif UE_VERSION_OLDER_THAN(5,1,0)
|
||||
for (auto a : removeList) {
|
||||
Output.Curve.Set(a, 0);
|
||||
}
|
||||
#else
|
||||
for (auto a : removeList) {
|
||||
Output.Curve.InvalidateCurveWeight(a);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
|
||||
#include "AnimNode_VrmQuestHandBone.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "BonePose.h"
|
||||
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
typedef enum ovrpBoneId_ {
|
||||
ovrpBoneId_Invalid = -1,
|
||||
ovrpBoneId_Hand_Start = 0,
|
||||
ovrpBoneId_Hand_WristRoot = ovrpBoneId_Hand_Start + 0, // root frame of the hand, where the wrist is located
|
||||
ovrpBoneId_Hand_ForearmStub = ovrpBoneId_Hand_Start + 1, // frame for user's forearm
|
||||
ovrpBoneId_Hand_Thumb0 = ovrpBoneId_Hand_Start + 2, // thumb trapezium bone
|
||||
ovrpBoneId_Hand_Thumb1 = ovrpBoneId_Hand_Start + 3, // thumb metacarpal bone
|
||||
ovrpBoneId_Hand_Thumb2 = ovrpBoneId_Hand_Start + 4, // thumb proximal phalange bone
|
||||
ovrpBoneId_Hand_Thumb3 = ovrpBoneId_Hand_Start + 5, // thumb distal phalange bone
|
||||
ovrpBoneId_Hand_Index1 = ovrpBoneId_Hand_Start + 6, // index proximal phalange bone
|
||||
ovrpBoneId_Hand_Index2 = ovrpBoneId_Hand_Start + 7, // index intermediate phalange bone
|
||||
ovrpBoneId_Hand_Index3 = ovrpBoneId_Hand_Start + 8, // index distal phalange bone
|
||||
ovrpBoneId_Hand_Middle1 = ovrpBoneId_Hand_Start + 9, // middle proximal phalange bone
|
||||
ovrpBoneId_Hand_Middle2 = ovrpBoneId_Hand_Start + 10, // middle intermediate phalange bone
|
||||
ovrpBoneId_Hand_Middle3 = ovrpBoneId_Hand_Start + 11, // middle distal phalange bone
|
||||
ovrpBoneId_Hand_Ring1 = ovrpBoneId_Hand_Start + 12, // ring proximal phalange bone
|
||||
ovrpBoneId_Hand_Ring2 = ovrpBoneId_Hand_Start + 13, // ring intermediate phalange bone
|
||||
ovrpBoneId_Hand_Ring3 = ovrpBoneId_Hand_Start + 14, // ring distal phalange bone
|
||||
ovrpBoneId_Hand_Pinky0 = ovrpBoneId_Hand_Start + 15, // pinky metacarpal bone
|
||||
ovrpBoneId_Hand_Pinky1 = ovrpBoneId_Hand_Start + 16, // pinky proximal phalange bone
|
||||
ovrpBoneId_Hand_Pinky2 = ovrpBoneId_Hand_Start + 17, // pinky intermediate phalange bone
|
||||
ovrpBoneId_Hand_Pinky3 = ovrpBoneId_Hand_Start + 18, // pinky distal phalange bone
|
||||
ovrpBoneId_Hand_MaxSkinnable = ovrpBoneId_Hand_Start + 19,
|
||||
// Bone tips are position only. They are not used for skinning but useful for hit-testing.
|
||||
// NOTE: ovrBoneId_Hand_ThumbTip == ovrBoneId_Hand_MaxSkinnable since the extended tips need to be contiguous
|
||||
ovrpBoneId_Hand_ThumbTip = ovrpBoneId_Hand_Start + ovrpBoneId_Hand_MaxSkinnable + 0, // tip of the thumb
|
||||
ovrpBoneId_Hand_IndexTip = ovrpBoneId_Hand_Start + ovrpBoneId_Hand_MaxSkinnable + 1, // tip of the index finger
|
||||
ovrpBoneId_Hand_MiddleTip = ovrpBoneId_Hand_Start + ovrpBoneId_Hand_MaxSkinnable + 2, // tip of the middle finger
|
||||
ovrpBoneId_Hand_RingTip = ovrpBoneId_Hand_Start + ovrpBoneId_Hand_MaxSkinnable + 3, // tip of the ring finger
|
||||
ovrpBoneId_Hand_PinkyTip = ovrpBoneId_Hand_Start + ovrpBoneId_Hand_MaxSkinnable + 4, // tip of the pinky
|
||||
ovrpBoneId_Hand_End = ovrpBoneId_Hand_Start + ovrpBoneId_Hand_MaxSkinnable + 5,
|
||||
|
||||
// add other skeleton bone definitions here...
|
||||
|
||||
ovrpBoneId_Max = ovrpBoneId_Hand_End,
|
||||
ovrpBoneId_EnumSize = 0x7fff
|
||||
} ovrpBoneId;
|
||||
|
||||
*/
|
||||
|
||||
const TArray<VRMUtil::VRMBoneTable> handtable_l_ue4_vrm = {
|
||||
{"Hand_L","leftHand"}, // +0
|
||||
{"lowerarm_l","----"}, //{"lowerarm_l","leftLowerArm"},
|
||||
{"thumb_03_l","----"},
|
||||
{"thumb_01_l","leftThumbProximal"},
|
||||
{"thumb_02_l","leftThumbIntermediate"},
|
||||
{"thumb_03_l","leftThumbDistal"},
|
||||
{"index_01_l","leftIndexProximal"}, // +6
|
||||
{"index_02_l","leftIndexIntermediate"},
|
||||
{"index_03_l","leftIndexDistal"},
|
||||
{"middle_01_l","leftMiddleProximal"},
|
||||
{"middle_02_l","leftMiddleIntermediate"},
|
||||
{"middle_03_l","leftMiddleDistal"},
|
||||
{"ring_01_l","leftRingProximal"},
|
||||
{"ring_02_l","leftRingIntermediate"},
|
||||
{"ring_03_l","leftRingDistal"},
|
||||
{"pinky_03_l","----"},
|
||||
{"pinky_01_l","leftLittleProximal"},
|
||||
{"pinky_02_l","leftLittleIntermediate"},
|
||||
{"pinky_03_l","leftLittleDistal"},
|
||||
};
|
||||
|
||||
|
||||
const TArray<VRMUtil::VRMBoneTable> handtable_r_ue4_vrm = {
|
||||
{"Hand_R", "rightHand"}, // +0
|
||||
{"lowerarm_r","----"}, //{"lowerarm_r","rightLowerArm"},
|
||||
{"lowerarm_r","----"},
|
||||
{ "thumb_01_r","rightThumbProximal" },
|
||||
{ "thumb_02_r","rightThumbIntermediate" },
|
||||
{ "thumb_03_r","rightThumbDistal" },
|
||||
{ "index_01_r","rightIndexProximal" }, // +6
|
||||
{ "index_02_r","rightIndexIntermediate" },
|
||||
{ "index_03_r","rightIndexDistal" },
|
||||
{ "middle_01_r","rightMiddleProximal" },
|
||||
{ "middle_02_r","rightMiddleIntermediate" },
|
||||
{ "middle_03_r","rightMiddleDistal" },
|
||||
{ "ring_01_r","rightRingProximal" },
|
||||
{ "ring_02_r","rightRingIntermediate" },
|
||||
{ "ring_03_r","rightRingDistal" },
|
||||
{ "pinky_01_r","----" },
|
||||
{ "pinky_01_r","rightLittleProximal" },
|
||||
{ "pinky_02_r","rightLittleIntermediate" },
|
||||
{ "pinky_03_r","rightLittleDistal" },
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
{"lowerarm_twist_01_l",""},
|
||||
{"upperarm_twist_01_l",""},
|
||||
{"clavicle_r","rightShoulder"},
|
||||
{"UpperArm_R","rightUpperArm"},
|
||||
{"lowerarm_r","rightLowerArm"},
|
||||
{"Hand_R","rightHand"},
|
||||
{"index_01_r","rightIndexProximal"},
|
||||
{"index_02_r","rightIndexIntermediate"},
|
||||
{"index_03_r","rightIndexDistal"},
|
||||
{"middle_01_r","rightMiddleProximal"},
|
||||
{"middle_02_r","rightMiddleIntermediate"},
|
||||
{"middle_03_r","rightMiddleDistal"},
|
||||
{"pinky_01_r","rightLittleProximal"},
|
||||
{"pinky_02_r","rightLittleIntermediate"},
|
||||
{"pinky_03_r","rightLittleDistal"},
|
||||
{"ring_01_r","rightRingProximal"},
|
||||
{"ring_02_r","rightRingIntermediate"},
|
||||
{"ring_03_r","rightRingDistal"},
|
||||
{"thumb_01_r","rightThumbProximal"},
|
||||
{"thumb_02_r","rightThumbIntermediate"},
|
||||
{"thumb_03_r","rightThumbDistal"},
|
||||
{"lowerarm_twist_01_r",""},
|
||||
{"upperarm_twist_01_r",""},
|
||||
{"neck_01","neck"},
|
||||
{"head","head"},
|
||||
{"Thigh_L","leftUpperLeg"},
|
||||
{"calf_l","leftLowerLeg"},
|
||||
{"calf_twist_01_l",""},
|
||||
{"Foot_L","leftFoot"},
|
||||
{"ball_l","leftToes"},
|
||||
{"thigh_twist_01_l",""},
|
||||
{"Thigh_R","rightUpperLeg"},
|
||||
{"calf_r","rightLowerLeg"},
|
||||
{"calf_twist_01_r",""},
|
||||
{"Foot_R","rightFoot"},
|
||||
{"ball_r","rightToes"},
|
||||
{"thigh_twist_01_r",""},
|
||||
{"ik_foot_root",""},
|
||||
{"ik_foot_l",""},
|
||||
{"ik_foot_r",""},
|
||||
{"ik_hand_root",""},
|
||||
*/
|
||||
}
|
||||
|
||||
FAnimNode_VrmQuestHandBone::FAnimNode_VrmQuestHandBone()
|
||||
{
|
||||
}
|
||||
|
||||
void FAnimNode_VrmQuestHandBone::GatherDebugData(FNodeDebugData& DebugData)
|
||||
{
|
||||
FString DebugLine = DebugData.GetNodeName(this);
|
||||
|
||||
DebugLine += "(";
|
||||
AddDebugNodeData(DebugLine);
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneToModify.BoneName.ToString());
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneNameToModify.ToString());
|
||||
DebugData.AddDebugItem(DebugLine);
|
||||
|
||||
ComponentPose.GatherDebugData(DebugData);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmQuestHandBone::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
|
||||
{
|
||||
|
||||
if (VrmMetaObject == nullptr){
|
||||
return;
|
||||
}
|
||||
if (HandTransform.HandLeft.Num() < 10 || HandReferenceTransform.HandLeft.Num() < 10) {
|
||||
return;
|
||||
}
|
||||
if (HandTransform.HandRight.Num() < 10 || HandReferenceTransform.HandRight.Num() < 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
check(OutBoneTransforms.Num() == 0);
|
||||
// the way we apply transform is same as FMatrix or FTransform
|
||||
// we apply scale first, and rotation, and translation
|
||||
// if you'd like to translate first, you'll need two nodes that first node does translate and second nodes to rotate.
|
||||
const FBoneContainer& BoneContainer = Output.Pose.GetPose().GetBoneContainer();
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
|
||||
const TArray<VRMUtil::VRMBoneTable>* handTable[2] = {
|
||||
&handtable_l_ue4_vrm,
|
||||
&handtable_r_ue4_vrm,
|
||||
};
|
||||
|
||||
const TArray<FTransform>* handTrans[2] = {
|
||||
&HandTransform.HandLeft,
|
||||
&HandTransform.HandRight,
|
||||
};
|
||||
|
||||
const TArray<FTransform>* handRefTrans[2] = {
|
||||
&HandReferenceTransform.HandLeft,
|
||||
&HandReferenceTransform.HandRight,
|
||||
};
|
||||
|
||||
|
||||
for (int side = 0; side < 2; ++side) {
|
||||
for (int boneNo = 0; boneNo < handTable[side]->Num(); ++boneNo) {
|
||||
|
||||
FString* boneName = VrmMetaObject->humanoidBoneTable.Find((*handTable[side])[boneNo].BoneVRM);
|
||||
if (boneName == nullptr) {
|
||||
continue;
|
||||
}
|
||||
int32_t boneIndex = BoneContainer.GetPoseBoneIndexForBoneName(**boneName);
|
||||
if (boneIndex == INDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FCompactPoseBoneIndex CompactPoseBoneToModify(boneIndex);// = BoneContainer.GetCompactPoseIndexFromSkeletonIndex(boneIndex);
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(CompactPoseBoneToModify);
|
||||
FTransform orgBoneTM = NewBoneTM;
|
||||
|
||||
// Convert to Bone Space.
|
||||
FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, EBoneControlSpace::BCS_WorldSpace);
|
||||
FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, orgBoneTM, CompactPoseBoneToModify, EBoneControlSpace::BCS_ParentBoneSpace);
|
||||
|
||||
// HandLeft[i].GetRotation();
|
||||
//NewBoneTM = HandTransform.HandLeft[i];// .SetRotation(BoneQuat);
|
||||
|
||||
FQuat q;
|
||||
{
|
||||
FQuat q_baseOffset;
|
||||
if (side == 0) {
|
||||
q_baseOffset = FRotator(0, 90, 180).Quaternion();
|
||||
} else {
|
||||
q_baseOffset = FRotator(0, 90, 0).Quaternion();
|
||||
}
|
||||
|
||||
// correct base
|
||||
{
|
||||
q = (*handTrans[side])[boneNo].GetRotation() * q_baseOffset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (3<=boneNo && boneNo<=5){
|
||||
//thumb
|
||||
FQuat q_baseOffset;
|
||||
if (side == 0) {
|
||||
q_baseOffset = FRotator(0, 115, 0).Quaternion();
|
||||
} else {
|
||||
q_baseOffset = FRotator(-65, 0, 90).Quaternion();
|
||||
}
|
||||
|
||||
//thumb
|
||||
auto q2 = (*handRefTrans[side])[boneNo].GetRotation() *q_baseOffset;
|
||||
q = q * q2.Inverse();
|
||||
}
|
||||
|
||||
|
||||
//for ref test
|
||||
//q = HandReferenceTransform.HandLeft[i].GetRotation() * q;
|
||||
|
||||
if (boneNo > 0) {
|
||||
{
|
||||
//auto r = fromParentTM.GetRotation();
|
||||
//q = r.Inverse() * q * r; // wrong
|
||||
//q = r * q * r.Inverse();
|
||||
}
|
||||
|
||||
//q = orgBoneTM.GetRotation() * q;
|
||||
|
||||
//auto ref = (*handRefTrans[side])[boneNo].GetRotation().Inverse();
|
||||
//auto ref = HandReferenceTransform.HandLeft[boneNo].GetRotation().Inverse();
|
||||
//q = ref * q;
|
||||
}
|
||||
|
||||
//NewBoneTM.SetLocation(HandTransform.HandLeft[i].GetLocation()*100.f);
|
||||
NewBoneTM.SetRotation(q);// .SetRotation(BoneQuat);
|
||||
//NewBoneTM.SetRotation(HandTransform.HandLeft[i].GetRotation());// .SetRotation(BoneQuat);
|
||||
|
||||
// Convert back to Component Space.
|
||||
//FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, EBoneControlSpace::BCS_ParentBoneSpace);
|
||||
FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CompactPoseBoneToModify, EBoneControlSpace::BCS_WorldSpace);
|
||||
|
||||
OutBoneTransforms.Add(FBoneTransform(CompactPoseBoneToModify, NewBoneTM));
|
||||
}
|
||||
}
|
||||
|
||||
OutBoneTransforms.Sort(FCompareBoneTransformIndex());
|
||||
}
|
||||
|
||||
bool FAnimNode_VrmQuestHandBone::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
// if both bones are valid
|
||||
//return (BoneToModify.IsValidToEvaluate(RequiredBones));
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAnimNode_VrmQuestHandBone::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
||||
{
|
||||
//BoneToModify.Initialize(RequiredBones);
|
||||
}
|
||||
@@ -0,0 +1,383 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "AnimNode_VrmRetargetFromMannequin.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstance.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
FAnimNode_VrmRetargetFromMannequin::FAnimNode_VrmRetargetFromMannequin() {
|
||||
}
|
||||
|
||||
void FAnimNode_VrmRetargetFromMannequin::PreUpdate(const UAnimInstance* InAnimInstance)
|
||||
{
|
||||
//DECLARE_SCOPE_HIERARCHICAL_COUNTER_ANIMNODE(PreUpdate)
|
||||
|
||||
Super::PreUpdate(InAnimInstance);
|
||||
|
||||
//FAnimNode_RetargetPoseFromMesh::EnsureInitialized
|
||||
// if user hasn't explicitly connected a source mesh, optionally use the parent mesh component (if there is one)
|
||||
if (!srcMannequinMesh.IsValid() && bUseAttachedParent)
|
||||
{
|
||||
USkeletalMeshComponent* TargetMesh = InAnimInstance->GetSkelMeshComponent();
|
||||
|
||||
// Walk up the attachment chain until we find a skeletal mesh component
|
||||
USkeletalMeshComponent* ParentMeshComponent = nullptr;
|
||||
for (USceneComponent* AttachParentComp = TargetMesh->GetAttachParent(); AttachParentComp != nullptr; AttachParentComp = AttachParentComp->GetAttachParent())
|
||||
{
|
||||
ParentMeshComponent = Cast<USkeletalMeshComponent>(AttachParentComp);
|
||||
if (ParentMeshComponent)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ParentMeshComponent == nullptr) {
|
||||
AActor *targetActor = nullptr;
|
||||
AActor *myActor = TargetMesh->GetOwner();
|
||||
for (USceneComponent* AttachParentComp = TargetMesh->GetAttachParent(); AttachParentComp != nullptr; AttachParentComp = AttachParentComp->GetAttachParent()) {
|
||||
targetActor = AttachParentComp->GetOwner();
|
||||
if (targetActor != myActor) {
|
||||
break;
|
||||
}
|
||||
targetActor = nullptr;
|
||||
}
|
||||
if (targetActor) {
|
||||
TArray<USkeletalMeshComponent*> c;
|
||||
targetActor->GetComponents<USkeletalMeshComponent>(c);
|
||||
if (c.IsValidIndex(0)) {
|
||||
ParentMeshComponent = c[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ParentMeshComponent)
|
||||
{
|
||||
srcMannequinMesh = ParentMeshComponent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FAnimNode_VrmRetargetFromMannequin::UpdateCache(FComponentSpacePoseContext& Output) {
|
||||
|
||||
if (srcMannequinMesh == nullptr){
|
||||
srcSkeletalMesh = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (srcSkeletalMesh == VRMGetSkeletalMeshAsset(srcMannequinMesh)) {
|
||||
return;
|
||||
}
|
||||
|
||||
srcSkeletalMesh = VRMGetSkeletalMeshAsset(srcMannequinMesh);
|
||||
|
||||
if (srcSkeletalMesh == nullptr) return;
|
||||
if (dstSkeletalMesh == nullptr) return;
|
||||
|
||||
auto& srcRefSkeleton = VRMGetRefSkeleton(srcSkeletalMesh);
|
||||
auto& dstRefSkeleton = VRMGetRefSkeleton(dstSkeletalMesh);
|
||||
|
||||
// ref pose
|
||||
const auto& srcRefSkeletonTransform = srcRefSkeleton.GetRefBonePose();
|
||||
const auto& dstRefSkeletonTransform = dstRefSkeleton.GetRefBonePose();
|
||||
|
||||
// ref component
|
||||
srcRefSkeletonCompTransform = srcRefSkeletonTransform;
|
||||
dstRefSkeletonCompTransform = dstRefSkeletonTransform;
|
||||
for (int i = 1; i < srcRefSkeletonCompTransform.Num(); ++i) {
|
||||
int parent = srcRefSkeleton.GetParentIndex(i);
|
||||
srcRefSkeletonCompTransform[i] *= srcRefSkeletonCompTransform[parent];
|
||||
}
|
||||
for (int i = 1; i < dstRefSkeletonCompTransform.Num(); ++i) {
|
||||
int parent = dstRefSkeleton.GetParentIndex(i);
|
||||
dstRefSkeletonCompTransform[i] *= dstRefSkeletonCompTransform[parent];
|
||||
}
|
||||
|
||||
// current A-pose compTransform
|
||||
dstCurrentSkeletonCompTransform = dstRefSkeletonTransform;
|
||||
for (int i = 0; i < dstRefSkeletonCompTransform.Num(); ++i) {
|
||||
FCompactPoseBoneIndex ii(i);
|
||||
|
||||
auto t = Output.Pose.GetLocalSpaceTransform(ii);
|
||||
if (i == 0) {
|
||||
dstCurrentSkeletonCompTransform[i] = t;
|
||||
} else {
|
||||
int parent = dstRefSkeleton.GetParentIndex(i);
|
||||
dstCurrentSkeletonCompTransform[i] = t * dstCurrentSkeletonCompTransform[parent];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FAnimNode_VrmRetargetFromMannequin::Initialize_AnyThread(const FAnimationInitializeContext& Context) {
|
||||
Super::Initialize_AnyThread(Context);
|
||||
|
||||
dstSkeletalMesh = nullptr;
|
||||
srcSkeletalMesh = nullptr;
|
||||
|
||||
if (Context.AnimInstanceProxy == nullptr) return;
|
||||
if (Context.AnimInstanceProxy->GetSkelMeshComponent() == nullptr) return;
|
||||
|
||||
dstSkeletalMesh = VRMGetSkinnedAsset(Context.AnimInstanceProxy->GetSkelMeshComponent());
|
||||
srcSkeletalMesh = nullptr;
|
||||
}
|
||||
void FAnimNode_VrmRetargetFromMannequin::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) {
|
||||
Super::CacheBones_AnyThread(Context);
|
||||
|
||||
}
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,20,0)
|
||||
#else
|
||||
void FAnimNode_VrmRetargetFromMannequin::ResetDynamics(ETeleportType InTeleportType) {
|
||||
Super::ResetDynamics(InTeleportType);
|
||||
}
|
||||
#endif
|
||||
|
||||
void FAnimNode_VrmRetargetFromMannequin::UpdateInternal(const FAnimationUpdateContext& Context){
|
||||
Super::UpdateInternal(Context);
|
||||
}
|
||||
|
||||
|
||||
void FAnimNode_VrmRetargetFromMannequin::GatherDebugData(FNodeDebugData& DebugData)
|
||||
{
|
||||
FString DebugLine = DebugData.GetNodeName(this);
|
||||
|
||||
DebugLine += "(";
|
||||
AddDebugNodeData(DebugLine);
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneToModify.BoneName.ToString());
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneNameToModify.ToString());
|
||||
DebugData.AddDebugItem(DebugLine);
|
||||
|
||||
ComponentPose.GatherDebugData(DebugData);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmRetargetFromMannequin::EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) {
|
||||
Super::EvaluateComponentPose_AnyThread(Output);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmRetargetFromMannequin::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
|
||||
{
|
||||
check(OutBoneTransforms.Num() == 0);
|
||||
|
||||
UpdateCache(Output);
|
||||
|
||||
if (srcSkeletalMesh == nullptr) return;
|
||||
if (dstSkeletalMesh == nullptr) return;
|
||||
|
||||
const UVrmMetaObject* dstMeta = VrmMetaObject;
|
||||
if (dstMeta == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto srcSkeletalMeshComp = Cast<USkeletalMeshComponent>(srcMannequinMesh);
|
||||
auto srcAsSkinnedMeshComp = srcMannequinMesh;
|
||||
if (srcAsSkinnedMeshComp == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &srcRefSkeleton = VRMGetRefSkeleton(VRMGetSkeletalMeshAsset(srcAsSkinnedMeshComp) );
|
||||
auto &dstRefSkeleton = VRMGetRefSkeleton(VRMGetSkeletalMeshAsset(Output.AnimInstanceProxy->GetSkelMeshComponent()) );
|
||||
|
||||
// ref pose
|
||||
const auto& dstRefSkeletonTransform = dstRefSkeleton.GetRefBonePose();
|
||||
const auto& srcRefSkeletonTransform = srcRefSkeleton.GetRefBonePose();
|
||||
|
||||
const TArray<FString>* SrcBoneList = &VRMUtil::vrm_humanoid_bone_list;
|
||||
|
||||
// is ue5 mannequin remap
|
||||
enum class RemapType {
|
||||
E_None,
|
||||
E_UpperChest,
|
||||
E_Chest,
|
||||
};
|
||||
RemapType remapType = RemapType::E_None;
|
||||
|
||||
{
|
||||
bool bUE5Mannequin = false;
|
||||
for (int i = 1; i <= 5; ++i) {
|
||||
int index = srcAsSkinnedMeshComp->GetBoneIndex(*(FString(TEXT("spine_0"))+FString::FromInt(i)));
|
||||
if (index == INDEX_NONE) {
|
||||
break;
|
||||
}
|
||||
if (i == 5) {
|
||||
bUE5Mannequin = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bUE5Mannequin) {
|
||||
TArray<FString>table = { TEXT("spine"), TEXT("chest"), TEXT("upperChest") };
|
||||
bool b[3] = {false, false, false};
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
auto* a = dstMeta->humanoidBoneTable.Find(*table[i]);
|
||||
if (a && (*a) != "") {
|
||||
b[i] = true;
|
||||
}
|
||||
}
|
||||
if (b[0] && b[1] && b[2]) {
|
||||
remapType = RemapType::E_UpperChest;
|
||||
}
|
||||
if (b[0] && b[1] && b[2]==false) {
|
||||
remapType = RemapType::E_Chest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int BoneCount = 0;
|
||||
for (const auto& humanoidName : VRMUtil::vrm_humanoid_bone_list) {
|
||||
FName srcName, dstName;
|
||||
srcName = dstName = NAME_None;
|
||||
|
||||
++BoneCount;
|
||||
{
|
||||
for (auto& bonemap : VRMUtil::table_ue4_vrm) {
|
||||
if (bonemap.BoneVRM == humanoidName) {
|
||||
srcName = *bonemap.BoneUE4;
|
||||
|
||||
// replace src bone name by srcMeta object
|
||||
if (MannequinVrmMetaObject) {
|
||||
auto *p = MannequinVrmMetaObject->humanoidBoneTable.Find(bonemap.BoneVRM);
|
||||
if (p) {
|
||||
srcName = **p;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (srcName == NAME_None) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (remapType) {
|
||||
case RemapType::E_UpperChest:
|
||||
if (humanoidName == TEXT("upperChest")) {
|
||||
srcName = TEXT("spine_05");
|
||||
}
|
||||
if (humanoidName == TEXT("chest")) {
|
||||
srcName = TEXT("spine_03");
|
||||
//3,4
|
||||
}
|
||||
if (humanoidName == TEXT("spine")) {
|
||||
srcName = TEXT("spine_01");
|
||||
//1,2
|
||||
}
|
||||
break;
|
||||
case RemapType::E_Chest:
|
||||
if (humanoidName == TEXT("chest")) {
|
||||
srcName = TEXT("spine_05");
|
||||
}
|
||||
if (humanoidName == TEXT("spine")) {
|
||||
srcName = TEXT("spine_01");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
auto a = dstMeta->humanoidBoneTable.Find(humanoidName);
|
||||
if (a) {
|
||||
dstName = **a;
|
||||
}
|
||||
}
|
||||
if (dstName == NAME_None) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto dstIndex = Output.AnimInstanceProxy->GetSkelMeshComponent()->GetBoneIndex(dstName);
|
||||
if (dstIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
auto srcIndex = srcAsSkinnedMeshComp->GetBoneIndex(srcName);
|
||||
if (srcIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FCompactPoseBoneIndex srcPoseBoneIndex(srcIndex);
|
||||
FCompactPoseBoneIndex dstPoseBoneIndex(dstIndex);
|
||||
|
||||
|
||||
const auto srcCurrentTrans = srcAsSkinnedMeshComp->GetSocketTransform(srcName, RTS_Component);
|
||||
|
||||
auto modelBone = srcCurrentTrans;
|
||||
{
|
||||
|
||||
{
|
||||
if (bIgnoreCenterLocation) {
|
||||
modelBone.SetLocation(CenterLocationOffset);
|
||||
} else {
|
||||
auto dd = Output.Pose.GetComponentSpaceTransform(dstPoseBoneIndex);
|
||||
modelBone.SetLocation(dd.GetLocation());
|
||||
|
||||
if (BoneCount == 1) {
|
||||
// RootBone transform
|
||||
float s = dd.GetLocation().Z / FMath::Max(1.0f, srcRefSkeletonCompTransform[srcIndex].GetLocation().Z);
|
||||
#if UE_VERSION_OLDER_THAN(4,24,0)
|
||||
FVector ComponentScale = Output.AnimInstanceProxy->GetSkelMeshComponent()->RelativeScale3D;
|
||||
#else
|
||||
FVector ComponentScale = Output.AnimInstanceProxy->GetSkelMeshComponent()->GetRelativeScale3D();
|
||||
#endif
|
||||
if (ComponentScale.X == 0.f) {
|
||||
ComponentScale.X = 0.001f;
|
||||
}
|
||||
if (ComponentScale.Y == 0.f) {
|
||||
ComponentScale.Y = 0.001f;
|
||||
}
|
||||
if (ComponentScale.Z == 0.f) {
|
||||
ComponentScale.Z = 0.001f;
|
||||
}
|
||||
|
||||
modelBone.SetLocation(
|
||||
FMath::Lerp(
|
||||
srcCurrentTrans.GetLocation(), // original location
|
||||
srcCurrentTrans.GetLocation() * s, // scled by height
|
||||
CenterLocationScaleByHeightScale)
|
||||
/ ComponentScale // inv model scale
|
||||
+ CenterLocationOffset
|
||||
);
|
||||
} // RootBone transform
|
||||
}
|
||||
}
|
||||
|
||||
modelBone.SetRotation(
|
||||
srcCurrentTrans.GetRotation()
|
||||
* srcRefSkeletonCompTransform[srcIndex].GetRotation().Inverse()
|
||||
* dstCurrentSkeletonCompTransform[dstIndex].GetRotation()
|
||||
);
|
||||
|
||||
Output.Pose.SetComponentSpaceTransform(dstPoseBoneIndex, modelBone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FAnimNode_VrmRetargetFromMannequin::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
// if both bones are valid
|
||||
//return (BoneToModify.IsValidToEvaluate(RequiredBones));
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAnimNode_VrmRetargetFromMannequin::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
||||
{
|
||||
//BoneToModify.Initialize(RequiredBones);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmRetargetFromMannequin::ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground) const
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
|
||||
if (VrmMetaObject == nullptr || PreviewSkelMeshComp == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (PreviewSkelMeshComp->GetWorld() == nullptr) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,464 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
/*
|
||||
|
||||
// VRMSpringBone.cs
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 DWANGO Co., Ltd. for UniVRM
|
||||
Copyright (c) 2018 ousttrue for UniGLTF, UniHumanoid
|
||||
Copyright (c) 2018 Masataka SUMI for MToon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "AnimNode_VrmSpringBone.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "SceneInterface.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmAssetListObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#include "VrmSpringBone.h"
|
||||
|
||||
#include <algorithm>
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
FAnimNode_VrmSpringBone::FAnimNode_VrmSpringBone()
|
||||
{
|
||||
NoWindBoneNameList = TArray<FName>{
|
||||
TEXT("J_Sec_L_Bust1"),
|
||||
TEXT("J_Sec_L_Bust2"),
|
||||
TEXT("J_Sec_R_Bust1"),
|
||||
TEXT("J_Sec_R_Bust2"),
|
||||
};
|
||||
}
|
||||
|
||||
//void FAnimNode_VrmSpringBone::Update_AnyThread(const FAnimationUpdateContext& Context) {
|
||||
// Super::Update_AnyThread(Context);
|
||||
// //Context.GetDeltaTime();
|
||||
//}
|
||||
|
||||
bool FAnimNode_VrmSpringBone::IsSpringInit() const {
|
||||
if (SpringManager.Get()) {
|
||||
return SpringManager->bInit;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void FAnimNode_VrmSpringBone::Initialize_AnyThread(const FAnimationInitializeContext& Context) {
|
||||
|
||||
Super::Initialize_AnyThread(Context);
|
||||
|
||||
if (Context.AnimInstanceProxy == nullptr) return;
|
||||
|
||||
VrmMetaObject_Internal = const_cast<UVrmMetaObject*>(VrmMetaObject);
|
||||
if (VrmMetaObject_Internal == nullptr && EnableAutoSearchMetaData) {
|
||||
VrmAssetListObject_Internal = VRMUtil::GetAssetListObject(VRMGetSkinnedAsset(Context.AnimInstanceProxy->GetSkelMeshComponent()));
|
||||
if (VrmAssetListObject_Internal) {
|
||||
VrmMetaObject_Internal = VrmAssetListObject_Internal->VrmMetaObject;
|
||||
}
|
||||
}
|
||||
|
||||
if (SpringManager.Get()) {
|
||||
SpringManager.Get()->reset();
|
||||
} else {
|
||||
if (VrmMetaObject_Internal) {
|
||||
if (VrmMetaObject_Internal->GetVRMVersion() >= 1) {
|
||||
SpringManager = MakeShareable(new VRM1Spring::VRM1SpringManager());
|
||||
}
|
||||
}
|
||||
if (SpringManager.IsValid() == false) {
|
||||
SpringManager = MakeShareable(new VRMSpringBone::VRMSpringManager());
|
||||
}
|
||||
if (SpringManager.Get()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
void FAnimNode_VrmSpringBone::Initialize_AnyThread_local(const FAnimationInitializeContext& Context) {
|
||||
{
|
||||
//Super::Initialize_AnyThread(Context); crash
|
||||
|
||||
//FAnimNode_SkeletalControlBase::Initialize_AnyThread
|
||||
FAnimNode_Base::Initialize_AnyThread(Context);
|
||||
//ComponentPose.Initialize(Context);
|
||||
AlphaBoolBlend.Reinitialize();
|
||||
AlphaScaleBiasClamp.Reinitialize();
|
||||
}
|
||||
if (SpringManager.Get()) {
|
||||
SpringManager.Get()->reset();
|
||||
}
|
||||
else {
|
||||
if (VrmMetaObject_Internal) {
|
||||
if (VrmMetaObject_Internal->GetVRMVersion() >= 1) {
|
||||
SpringManager = MakeShareable(new VRM1Spring::VRM1SpringManager());
|
||||
}
|
||||
}
|
||||
if (SpringManager.IsValid() == false) {
|
||||
SpringManager = MakeShareable(new VRMSpringBone::VRMSpringManager());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FAnimNode_VrmSpringBone::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) {
|
||||
Super::CacheBones_AnyThread(Context);
|
||||
}
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,20,0)
|
||||
#else
|
||||
void FAnimNode_VrmSpringBone::ResetDynamics(ETeleportType InTeleportType) {
|
||||
Super::ResetDynamics(InTeleportType);
|
||||
if (SpringManager.Get()){
|
||||
bool bReset = true;
|
||||
if (InTeleportType == ETeleportType::TeleportPhysics) {
|
||||
if (bIgnorePhysicsResetOnTeleport) {
|
||||
bReset = false;
|
||||
}
|
||||
}
|
||||
if (bReset) {
|
||||
SpringManager.Get()->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void FAnimNode_VrmSpringBone::UpdateInternal(const FAnimationUpdateContext& Context){
|
||||
Super::UpdateInternal(Context);
|
||||
|
||||
CurrentDeltaTime = Context.GetDeltaTime();
|
||||
}
|
||||
|
||||
|
||||
void FAnimNode_VrmSpringBone::GatherDebugData(FNodeDebugData& DebugData)
|
||||
{
|
||||
FString DebugLine = DebugData.GetNodeName(this);
|
||||
|
||||
DebugLine += "(";
|
||||
AddDebugNodeData(DebugLine);
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneToModify.BoneName.ToString());
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneNameToModify.ToString());
|
||||
DebugData.AddDebugItem(DebugLine);
|
||||
|
||||
ComponentPose.GatherDebugData(DebugData);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmSpringBone::EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) {
|
||||
if (bCallByAnimInstance) {
|
||||
ActualAlpha = 1.f;
|
||||
/*
|
||||
EvaluateComponentSpaceInternal(Output);
|
||||
|
||||
BoneTransformsSpring.Reset(BoneTransformsSpring.Num());
|
||||
EvaluateSkeletalControl_AnyThread(Output, BoneTransformsSpring);
|
||||
|
||||
if (BoneTransformsSpring.Num() > 0)
|
||||
{
|
||||
ActualAlpha = 1.f;
|
||||
const float BlendWeight = FMath::Clamp<float>(ActualAlpha, 0.f, 1.f);
|
||||
Output.Pose.LocalBlendCSBoneTransforms(BoneTransformsSpring, BlendWeight);
|
||||
}
|
||||
*/
|
||||
}
|
||||
else {
|
||||
Super::EvaluateComponentPose_AnyThread(Output);
|
||||
}
|
||||
}
|
||||
|
||||
void FAnimNode_VrmSpringBone::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
|
||||
{
|
||||
check(OutBoneTransforms.Num() == 0);
|
||||
|
||||
const auto RefSkeleton = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton();
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
|
||||
//dstRefSkeleton.GetParentIndex
|
||||
|
||||
//auto BoneSpace = EBoneControlSpace::BCS_ParentBoneSpace;
|
||||
auto BoneSpace = EBoneControlSpace::BCS_WorldSpace;
|
||||
{
|
||||
|
||||
if (VrmMetaObject_Internal == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (VRMGetSkeleton(VrmMetaObject_Internal->SkeletalMesh) != Output.AnimInstanceProxy->GetSkeleton()) {
|
||||
//skip for renamed bone
|
||||
//return;
|
||||
}
|
||||
if (Output.Pose.GetPose().GetNumBones() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &RefSkeletonTransform = Output.Pose.GetPose().GetBoneContainer().GetRefPoseArray();
|
||||
|
||||
{
|
||||
if (SpringManager.Get() == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (SpringManager->bInit == false) {
|
||||
SpringManager->init(VrmMetaObject_Internal.Get(), Output);
|
||||
return;
|
||||
}
|
||||
|
||||
SpringManager->update(this, CurrentDeltaTime, Output, OutBoneTransforms);
|
||||
|
||||
SpringManager->applyToComponent(Output, OutBoneTransforms);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FAnimNode_VrmSpringBone::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
// if both bones are valid
|
||||
//return (BoneToModify.IsValidToEvaluate(RequiredBones));
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAnimNode_VrmSpringBone::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
||||
{
|
||||
//BoneToModify.Initialize(RequiredBones);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmSpringBone::ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground) const
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
|
||||
auto MetaObjectLocal = VrmMetaObject_Internal;
|
||||
|
||||
if (MetaObjectLocal == nullptr && EnableAutoSearchMetaData) {
|
||||
auto *p = VRMUtil::GetAssetListObject(VRMGetSkinnedAsset(PreviewSkelMeshComp));
|
||||
if (p) {
|
||||
MetaObjectLocal = p->VrmMetaObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (MetaObjectLocal == nullptr || PreviewSkelMeshComp == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (PreviewSkelMeshComp->GetWorld() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESceneDepthPriorityGroup Priority = SDPG_World;
|
||||
if (bPreviewForeground) Priority = SDPG_Foreground;
|
||||
|
||||
if (MetaObjectLocal->VRM1SpringBoneMeta.Springs.Num() > 0) {
|
||||
// vrm1
|
||||
|
||||
// col
|
||||
for (const auto& c : MetaObjectLocal->VRM1SpringBoneMeta.Colliders) {
|
||||
const FTransform t = PreviewSkelMeshComp->GetSocketTransform(*c.boneName);
|
||||
|
||||
float r = (c.radius) * 100.f;
|
||||
auto offs = c.offset;
|
||||
offs.Set(offs.X, -offs.Z, offs.Y);
|
||||
offs *= 100;
|
||||
offs = t.TransformVector(offs);
|
||||
|
||||
if (c.shapeType == TEXT("sphere")) {
|
||||
|
||||
FTransform tt = t;
|
||||
tt.AddToTranslation(offs);
|
||||
|
||||
DrawWireSphere(PDI, tt, FLinearColor(1,1,0), r, 32, Priority);
|
||||
}
|
||||
else {
|
||||
|
||||
auto tail = c.tail;
|
||||
tail.Set(tail.X, -tail.Z, tail.Y);
|
||||
tail *= 100;
|
||||
tail = t.TransformVector(tail);
|
||||
|
||||
FTransform t1 = t;
|
||||
t1.AddToTranslation(offs);
|
||||
|
||||
FTransform t2 = t;
|
||||
t2.AddToTranslation(tail);
|
||||
|
||||
if (0) {
|
||||
// sphere and line
|
||||
DrawWireSphere(PDI, t1, FLinearColor(1, 1, 1), r, 32, Priority);
|
||||
DrawWireSphere(PDI, t2, FLinearColor::Green, r, 32, Priority);
|
||||
PDI->DrawLine(
|
||||
t1.GetLocation(),
|
||||
t2.GetLocation(),
|
||||
FLinearColor::Green,
|
||||
Priority);
|
||||
}
|
||||
else {
|
||||
// capsule
|
||||
FVector center = (t1.GetLocation() + t2.GetLocation()) / 2.f;
|
||||
FVector Up = (t1.GetLocation() - t2.GetLocation()).GetSafeNormal();
|
||||
FVector Forward, Right;
|
||||
|
||||
Up.FindBestAxisVectors(Forward, Right);
|
||||
const FVector X = (Forward);
|
||||
const FVector Y = (Right);
|
||||
const FVector Z = (Up);
|
||||
float halfheight = (t1.GetLocation() - center).Size() + r;
|
||||
DrawWireCapsule(PDI, center, X, Y, Z, FLinearColor::Green, r, halfheight, 32, Priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// spring col
|
||||
|
||||
for (int springNo = 0; springNo < MetaObjectLocal->VRM1SpringBoneMeta.Springs.Num(); ++springNo) {
|
||||
const auto& s = MetaObjectLocal->VRM1SpringBoneMeta.Springs[springNo];
|
||||
|
||||
|
||||
const TArray<FLinearColor> color = {
|
||||
FLinearColor(1.f, 0, 0),
|
||||
FLinearColor(1.f, 0.5, 0),
|
||||
FLinearColor(1.f, 0, 0.5),
|
||||
};
|
||||
|
||||
for (int jointNo = 0; jointNo < s.joints.Num()-1; ++jointNo) {
|
||||
auto& j1 = s.joints[jointNo];
|
||||
auto& j2 = s.joints[jointNo + 1];
|
||||
|
||||
const FTransform t = PreviewSkelMeshComp->GetSocketTransform(*j2.boneName);
|
||||
|
||||
float r = j1.hitRadius * 100.f;
|
||||
|
||||
DrawWireSphere(PDI, t.GetLocation(), color[springNo%color.Num()], r, 32, Priority);
|
||||
|
||||
const FTransform t2 = PreviewSkelMeshComp->GetSocketTransform(*j1.boneName);
|
||||
|
||||
PDI->DrawLine(
|
||||
t.GetLocation(),
|
||||
t2.GetLocation(),
|
||||
color[springNo % color.Num()] / 2.f,
|
||||
Priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vrm0
|
||||
for (const auto &colMeta : MetaObjectLocal->VRMColliderMeta) {
|
||||
const FTransform t = PreviewSkelMeshComp->GetSocketTransform(*colMeta.boneName);
|
||||
|
||||
for (const auto &col : colMeta.collider) {
|
||||
float r = (col.radius) * 100.f;
|
||||
auto offs = col.offset;
|
||||
//offs.Set(offs.X, -offs.Z, offs.Y); // 本来はこれが正しいが、VRM0の座標が間違っている
|
||||
offs.Set(-offs.X, offs.Z, offs.Y); // VRM0の仕様としては これ
|
||||
offs *= 100;
|
||||
FVector v = t.TransformPosition(offs);
|
||||
|
||||
FTransform tt = t;
|
||||
tt.AddToTranslation(offs);
|
||||
|
||||
DrawWireSphere(PDI, tt, FLinearColor::Green, r, 32, Priority);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct SData{
|
||||
int32 bone = 0;
|
||||
float radius = 0.f;
|
||||
|
||||
bool operator==(const SData& a) const {
|
||||
return (bone == a.bone && radius == a.radius);
|
||||
}
|
||||
};
|
||||
|
||||
TArray<SData> dataList;
|
||||
TArray<int32> boneList;
|
||||
|
||||
for (const auto &spr : MetaObjectLocal->VRMSpringMeta) {
|
||||
for (const auto &boneName : spr.boneNames) {
|
||||
int32_t boneIndex = PreviewSkelMeshComp->GetBoneIndex(*boneName);
|
||||
boneList.AddUnique(boneIndex);
|
||||
|
||||
{
|
||||
SData s;
|
||||
s.bone = boneIndex;
|
||||
s.radius = spr.hitRadius;
|
||||
|
||||
dataList.AddUnique(s);
|
||||
}
|
||||
|
||||
for (int i = 0; i < boneList.Num(); ++i) {
|
||||
TArray<int32> c;
|
||||
VRMUtil::GetDirectChildBones(VRMGetRefSkeleton( VRMGetSkinnedAsset(PreviewSkelMeshComp) ), boneList[i], c);
|
||||
if (c.Num()) {
|
||||
for (const auto &cc : c) {
|
||||
boneList.AddUnique(cc);
|
||||
|
||||
SData s;
|
||||
s.bone = cc;
|
||||
s.radius = spr.hitRadius;
|
||||
dataList.AddUnique(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto &RefBonePose = VRMGetRefSkeleton(VRMGetSkinnedAsset(PreviewSkelMeshComp)).GetRefBonePose();
|
||||
|
||||
for (int i = 0; i < dataList.Num(); ++i) {
|
||||
FTransform t;
|
||||
|
||||
{
|
||||
TArray<int32> c;
|
||||
VRMUtil::GetDirectChildBones(VRMGetRefSkeleton(VRMGetSkinnedAsset(PreviewSkelMeshComp)), dataList[i].bone, c);
|
||||
if (c.IsValidIndex(0)) {
|
||||
const auto& name = PreviewSkelMeshComp->GetBoneName(c[0]);
|
||||
t = PreviewSkelMeshComp->GetSocketTransform(name);
|
||||
}
|
||||
else {
|
||||
const auto& name = PreviewSkelMeshComp->GetBoneName(dataList[i].bone);
|
||||
t = PreviewSkelMeshComp->GetSocketTransform(name);
|
||||
//t.SetLocation(t.GetLocation() * 1.7);
|
||||
t.SetLocation(t.GetLocation() + RefBonePose[dataList[i].bone].GetLocation() * 0.7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
float r = dataList[i].radius * 100.f;
|
||||
FVector v = t.GetLocation();
|
||||
|
||||
DrawWireSphere(PDI, t, FLinearColor::Red, r, 32, Priority);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (PreviewSkelMeshComp && PreviewSkelMeshComp->GetWorld())
|
||||
{
|
||||
FVector const CSEffectorLocation = FVector(0, 0, 0);//CachedEffectorCSTransform.GetLocation();
|
||||
|
||||
FVector const Precision = FVector(1);//CachedEffectorCSTransform.GetLocation();
|
||||
|
||||
FTransform CachedEffectorCSTransform;
|
||||
|
||||
// Show end effector position.
|
||||
//DrawDebugBox(PreviewSkelMeshComp->GetWorld(), CSEffectorLocation, FVector(Precision), FColor::Green, true, 0.1f);
|
||||
//DrawDebugCoordinateSystem(PreviewSkelMeshComp->GetWorld(), CSEffectorLocation, CachedEffectorCSTransform.GetRotation().Rotator(), 5.f, true, 0.1f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
|
||||
#include "RigUnit_VrmDynamicHierarchy.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "Rigs/RigHierarchyController.h"
|
||||
#include "Units/RigUnitContext.h"
|
||||
#include "ControlRig.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
|
||||
#include "VrmUtil.h"
|
||||
#include "VrmAssetListObject.h"
|
||||
#include "VrmMetaObject.h"
|
||||
|
||||
//#include "Units/Execution/RigUnit_PrepareForExecution.h"
|
||||
|
||||
//#include UE_INLINE_GENERATED_CPP_BY_NAME(RigUnit_DynamicHierarchy)
|
||||
|
||||
FRigUnit_VRMInitControllerTransform_Execute() {
|
||||
|
||||
const USkeletalMeshComponent* skc = ExecuteContext.UnitContext.DataSourceRegistry->RequestSource<USkeletalMeshComponent>(UControlRig::OwnerComponent);
|
||||
if (skc == nullptr) return;
|
||||
|
||||
auto* sk = VRMGetSkeletalMeshAsset(skc);
|
||||
if (sk == nullptr) return;
|
||||
|
||||
auto* k = sk->GetSkeleton();
|
||||
if (k == nullptr) return;
|
||||
|
||||
|
||||
URigHierarchyController* Controller = ExecuteContext.Hierarchy->GetController(true);
|
||||
if (Controller == nullptr) return;
|
||||
|
||||
UVrmAssetListObject* assetList = VRMUtil::GetAssetListObject(sk);
|
||||
|
||||
if (assetList == nullptr) return;
|
||||
//Controller->
|
||||
|
||||
TArray<FRigControlElement*> controlList = ExecuteContext.Hierarchy->GetControls();
|
||||
TArray<FRigNullElement*> nullList = ExecuteContext.Hierarchy->GetNulls();
|
||||
//contollerList[0]->GetNameString();
|
||||
|
||||
//ExecuteContext.Hierarchy->SetInitialGlobalTransform
|
||||
//Controller
|
||||
|
||||
|
||||
TMap<FRigElementKey, FTransform> elemInitTransformList;
|
||||
for (auto& table : VRMUtil::table_ue4_vrm) {
|
||||
|
||||
auto* elem = nullList.FindByPredicate(
|
||||
[&table](FRigNullElement* e) {
|
||||
#if UE_VERSION_OLDER_THAN(5,4,0)
|
||||
if (e->GetNameString().Compare(table.BoneUE4 + "_s") == 0) {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (e->GetName().Compare(table.BoneUE4 + "_s") == 0) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
});
|
||||
|
||||
if (elem == nullptr) continue;
|
||||
|
||||
FRigElementKey bone;
|
||||
{
|
||||
const auto& assetBoneTable = assetList->VrmMetaObject->humanoidBoneTable;
|
||||
|
||||
auto* str = assetBoneTable.Find(table.BoneVRM);
|
||||
if (str == nullptr) continue;
|
||||
|
||||
bone.Type = ERigElementType::Bone;
|
||||
bone.Name = *(*str);
|
||||
}
|
||||
|
||||
|
||||
FRigElementKey a;
|
||||
a.Name = *(table.BoneUE4 + "_s");
|
||||
a.Type = ERigElementType::Null;
|
||||
|
||||
|
||||
auto index = k->GetReferenceSkeleton().FindBoneIndex(bone.Name);
|
||||
auto refPose = k->GetReferenceSkeleton().GetRefBonePose();
|
||||
|
||||
elemInitTransformList.Add(a, refPose[index]);
|
||||
}
|
||||
|
||||
for (auto& c : controlList) {
|
||||
//ExecuteContext.Hierarchy->SetInitialLocalTransform(c->GetKey(), FTransform::Identity);
|
||||
//ExecuteContext.Hierarchy->SetLocalTransform(c->GetKey(), FTransform::Identity);
|
||||
}
|
||||
for (auto& c : nullList) {
|
||||
auto *f = elemInitTransformList.Find(c->GetKey());
|
||||
if (f) {
|
||||
ExecuteContext.Hierarchy->SetInitialGlobalTransform(c->GetKey(), *f);
|
||||
ExecuteContext.Hierarchy->SetLocalTransform(c->GetKey(), *f);
|
||||
} else {
|
||||
ExecuteContext.Hierarchy->SetInitialLocalTransform(c->GetKey(), FTransform::Identity);
|
||||
ExecuteContext.Hierarchy->SetLocalTransform(c->GetKey(), FTransform::Identity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
FRigUnit_VRMGenerateBoneToControlTable_Execute()
|
||||
{
|
||||
Items_MannequinBone.Empty();
|
||||
//Items_MannequinControl.Empty();
|
||||
Items_VRMBone.Empty();
|
||||
|
||||
const USkeletalMeshComponent* skc = ExecuteContext.UnitContext.DataSourceRegistry->RequestSource<USkeletalMeshComponent>(UControlRig::OwnerComponent);
|
||||
if (skc == nullptr) return;
|
||||
|
||||
auto* sk = VRMGetSkeletalMeshAsset(skc);
|
||||
if (sk == nullptr) return;
|
||||
|
||||
auto* k = sk->GetSkeleton();
|
||||
if (k == nullptr) return;
|
||||
|
||||
|
||||
URigHierarchyController* Controller = ExecuteContext.Hierarchy->GetController(true);
|
||||
if (Controller == nullptr) return;
|
||||
|
||||
UVrmAssetListObject *assetList = VRMUtil::GetAssetListObject(sk);
|
||||
|
||||
if (assetList == nullptr) return;
|
||||
//Controller->
|
||||
|
||||
TArray<FRigControlElement*> controllerList = ExecuteContext.Hierarchy->GetControls();
|
||||
//contollerList[0]->GetNameString();
|
||||
|
||||
//ExecuteContext.Hierarchy->SetInitialGlobalTransform
|
||||
//Controller
|
||||
|
||||
|
||||
for (auto& table : VRMUtil::table_ue4_vrm) {
|
||||
|
||||
auto* elem = controllerList.FindByPredicate(
|
||||
[&table](FRigControlElement* e) {
|
||||
#if UE_VERSION_OLDER_THAN(5,4,0)
|
||||
if (e->GetNameString().Compare(table.BoneUE4 + "_c") == 0) {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (e->GetName().Compare(table.BoneUE4 + "_c") == 0) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
});
|
||||
|
||||
if (elem == nullptr) continue;
|
||||
|
||||
FRigElementKey bone;
|
||||
{
|
||||
const auto& assetBoneTable = assetList->VrmMetaObject->humanoidBoneTable;
|
||||
|
||||
auto* str = assetBoneTable.Find(table.BoneVRM);
|
||||
if (str == nullptr) continue;
|
||||
|
||||
bone.Type = ERigElementType::Bone;
|
||||
bone.Name = *(*str);
|
||||
|
||||
Items_VRMBone.Add(*(*str));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
FRigElementKey a;
|
||||
a.Name = *(table.BoneUE4);
|
||||
a.Type = ERigElementType::Control;
|
||||
Items_MannequinBone.Add(*(table.BoneUE4));
|
||||
}
|
||||
{
|
||||
FRigElementKey a;
|
||||
a.Name = *(table.BoneUE4 + "_c");
|
||||
a.Type = ERigElementType::Control;
|
||||
//Items_MannequinControl.Add(a);
|
||||
}
|
||||
//Items_VRMBone.Add(bone);
|
||||
}
|
||||
}
|
||||
|
||||
FRigUnit_VRMGetCurveNameFromMesh_Execute() {
|
||||
FString ErrorMessage;
|
||||
|
||||
Items_Curve.Reset();
|
||||
Items_Morph.Reset();
|
||||
|
||||
const USkeletalMeshComponent* skc = ExecuteContext.UnitContext.DataSourceRegistry->RequestSource<USkeletalMeshComponent>(UControlRig::OwnerComponent);
|
||||
if (skc == nullptr) return;
|
||||
|
||||
{
|
||||
auto* sk = skc->GetSkinnedAsset();
|
||||
auto* k = sk->GetSkeleton();
|
||||
auto morph = sk->GetMorphTargets();
|
||||
|
||||
const FRigControlValue Value = FRigControlValue::Make<float>(0);
|
||||
const FTransform ShapeTransform;
|
||||
const FTransform OffsetTransform;
|
||||
|
||||
for (auto& a : morph) {
|
||||
Items_Morph.Add(a.GetFName());
|
||||
}
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,3,0)
|
||||
const FSmartNameMapping* CurveMapping = k->GetSmartNameContainer(USkeleton::AnimCurveMappingName);
|
||||
if (CurveMapping) {
|
||||
TArray<FName> CurveNames;
|
||||
CurveMapping->FillNameArray(CurveNames);
|
||||
for (const FName& CurveName : CurveNames) {
|
||||
auto* meta = CurveMapping->GetCurveMetaData(CurveName);
|
||||
if (meta->Type.bMorphtarget == true) {
|
||||
continue;
|
||||
}
|
||||
Items_Curve.Add(CurveName);
|
||||
}
|
||||
}
|
||||
#else
|
||||
k->ForEachCurveMetaData([&](const FName& InCurveName, const FCurveMetaData& InMetaData)
|
||||
{
|
||||
if (InMetaData.Type.bMorphtarget == true) {
|
||||
return;
|
||||
}
|
||||
Items_Curve.Add(InCurveName);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FRigUnit_VRMAddCurveFromMesh_Execute()
|
||||
{
|
||||
FString ErrorMessage;
|
||||
|
||||
Items_Curve.Reset();
|
||||
Items_Morph.Reset();
|
||||
|
||||
const USkeletalMeshComponent* skc = ExecuteContext.UnitContext.DataSourceRegistry->RequestSource<USkeletalMeshComponent>(UControlRig::OwnerComponent);
|
||||
if (skc == nullptr) return;
|
||||
|
||||
URigHierarchyController* Controller = ExecuteContext.Hierarchy->GetController(true);
|
||||
if (Controller == nullptr) return;
|
||||
|
||||
FRigControlSettings ControlSettings;
|
||||
|
||||
ControlSettings.ControlType = ERigControlType::Float;
|
||||
ControlSettings.PrimaryAxis = ERigControlAxis::X;
|
||||
|
||||
ControlSettings.MinimumValue = FRigControlValue::Make<float>(0);
|
||||
ControlSettings.MaximumValue = FRigControlValue::Make<float>(1);
|
||||
|
||||
ControlSettings.SetupLimitArrayForType(true, true, true);
|
||||
ControlSettings.SetVisible(false);
|
||||
|
||||
FRigHierarchyControllerInstructionBracket InstructionBracket(Controller, ExecuteContext.GetInstructionIndex());
|
||||
|
||||
{
|
||||
auto *sk = skc->GetSkinnedAsset();
|
||||
auto* k = sk->GetSkeleton();
|
||||
auto morph = sk->GetMorphTargets();
|
||||
|
||||
const FRigControlValue Value = FRigControlValue::Make<float>(0);
|
||||
const FTransform ShapeTransform;
|
||||
const FTransform OffsetTransform;
|
||||
|
||||
if (bIncludeMorphs) {
|
||||
auto root = Controller->AddNull(TEXT("VRM4U_Root_Morph"), FRigElementKey(), OffsetTransform);
|
||||
for (auto& a : morph) {
|
||||
FName n = *(Prefix + a.GetFName().ToString() + Suffix);
|
||||
Items_Morph.Add(Controller->AddControl(n, root, ControlSettings, Value, OffsetTransform, ShapeTransform, false, false));
|
||||
}
|
||||
}
|
||||
|
||||
if (bIncludeCurves) {
|
||||
auto root = Controller->AddNull(TEXT("VRM4U_Root_Curve"), FRigElementKey(), OffsetTransform);
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,3,0)
|
||||
const FSmartNameMapping* CurveMapping = k->GetSmartNameContainer(USkeleton::AnimCurveMappingName);
|
||||
if (CurveMapping) {
|
||||
TArray<FName> CurveNames;
|
||||
CurveMapping->FillNameArray(CurveNames);
|
||||
for (const FName& CurveName : CurveNames) {
|
||||
auto* meta = CurveMapping->GetCurveMetaData(CurveName);
|
||||
if (meta->Type.bMorphtarget == true) {
|
||||
continue;
|
||||
}
|
||||
FName n = *(Prefix + CurveName.ToString() + Suffix);
|
||||
Items_Curve.Add(Controller->AddControl(n, root, ControlSettings, Value, OffsetTransform, ShapeTransform, false, false));
|
||||
}
|
||||
}
|
||||
#else
|
||||
k->ForEachCurveMetaData([&](const FName& InCurveName, const FCurveMetaData& InMetaData)
|
||||
{
|
||||
if (InMetaData.Type.bMorphtarget == true) {
|
||||
return;
|
||||
}
|
||||
FName n = *(Prefix + InCurveName.ToString() + Suffix);
|
||||
Items_Curve.Add(Controller->AddControl(n, root, ControlSettings, Value, OffsetTransform, ShapeTransform, false, false));
|
||||
});
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "VRM4U.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "VrmRuntimeSettings.h"
|
||||
#include "Developer/Settings/Public/ISettingsModule.h"
|
||||
|
||||
//#include "ISettingsModule.h"
|
||||
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FVRM4UModule"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogVRM4U);
|
||||
|
||||
|
||||
void FVRM4UModule::StartupModule()
|
||||
{
|
||||
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
|
||||
{
|
||||
|
||||
}
|
||||
if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
|
||||
{
|
||||
SettingsModule->RegisterSettings("Project", "Plugins", "VRM4U",
|
||||
LOCTEXT("RuntimeSettingsName", "VRM4U"),
|
||||
LOCTEXT("RuntimeSettingsDescription", "Configure the VRM4U plugin"),
|
||||
GetMutableDefault<UVrmRuntimeSettings>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FVRM4UModule::ShutdownModule()
|
||||
{
|
||||
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
|
||||
// we call this function before unloading the module.
|
||||
|
||||
if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
|
||||
{
|
||||
SettingsModule->UnregisterSettings("Project", "Plugins", "VRM4U");
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FVRM4UModule, VRM4U)
|
||||
@@ -0,0 +1,80 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "VRM4U_AnimSubsystem.h"
|
||||
|
||||
|
||||
void UVRM4U_AnimSubsystem::Clear() {
|
||||
FScopeLock Lock(&cs);
|
||||
baseData.Empty();
|
||||
}
|
||||
|
||||
void UVRM4U_AnimSubsystem::GetBoneByIndex(int index, TMap<FString, FTransform>& trans) {
|
||||
FScopeLock Lock(&cs);
|
||||
if (baseData.IsValidIndex(index)) {
|
||||
trans = baseData[index].BoneTransform;
|
||||
}
|
||||
}
|
||||
|
||||
void UVRM4U_AnimSubsystem::GetBoneByPort(int port, TMap<FString, FTransform>& trans) {
|
||||
FScopeLock Lock(&cs);
|
||||
for (auto& a : baseData) {
|
||||
if (a.port == port) {
|
||||
trans = a.BoneTransform;
|
||||
return;
|
||||
}
|
||||
}
|
||||
FVrmTransformData a;
|
||||
a.port = port;
|
||||
baseData.Add(a);
|
||||
trans = baseData.Last(0).BoneTransform;
|
||||
}
|
||||
|
||||
void UVRM4U_AnimSubsystem::GetRawdataByIndex(int index, TMap<FString, FTransform>& trans) {
|
||||
FScopeLock Lock(&cs);
|
||||
if (baseData.IsValidIndex(index)) {
|
||||
trans = baseData[index].RawData;
|
||||
}
|
||||
}
|
||||
|
||||
void UVRM4U_AnimSubsystem::GetRawdataByPort(int port, TMap<FString, FTransform>& trans) {
|
||||
FScopeLock Lock(&cs);
|
||||
for (auto& a : baseData) {
|
||||
if (a.port == port) {
|
||||
trans = a.RawData;
|
||||
return;
|
||||
}
|
||||
}
|
||||
FVrmTransformData a;
|
||||
a.port = port;
|
||||
baseData.Add(a);
|
||||
trans = baseData.Last(0).RawData;
|
||||
}
|
||||
|
||||
void UVRM4U_AnimSubsystem::SetBoneTransform(int port, const TMap<FString, FTransform>& trans) {
|
||||
FScopeLock Lock(&cs);
|
||||
for (auto& a : baseData) {
|
||||
if (a.port == port) {
|
||||
a.BoneTransform = trans;
|
||||
return;
|
||||
}
|
||||
}
|
||||
FVrmTransformData a;
|
||||
a.port = port;
|
||||
a.BoneTransform = trans;
|
||||
baseData.Add(a);
|
||||
}
|
||||
|
||||
void UVRM4U_AnimSubsystem::SetRawData(int port, const TMap<FString, FTransform>& trans) {
|
||||
FScopeLock Lock(&cs);
|
||||
for (auto& a : baseData) {
|
||||
if (a.port == port) {
|
||||
a.RawData = trans;
|
||||
return;
|
||||
}
|
||||
}
|
||||
FVrmTransformData a;
|
||||
a.port = port;
|
||||
a.RawData = trans;
|
||||
baseData.Add(a);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "Vrm1LicenseObject.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,411 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
|
||||
#include "VrmAnimInstance.h"
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmUtil.h"
|
||||
#include "Animation/AnimNodeBase.h"
|
||||
#include "BoneControllers/AnimNode_Fabrik.h"
|
||||
#include "BoneControllers/AnimNode_TwoBoneIK.h"
|
||||
#include "BoneControllers/AnimNode_SplineIK.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
|
||||
void FVrmAnimInstanceProxy::Initialize(UAnimInstance* InAnimInstance) {
|
||||
}
|
||||
bool FVrmAnimInstanceProxy::Evaluate(FPoseContext& Output) {
|
||||
Output.ResetToRefPose();
|
||||
|
||||
UVrmAnimInstance *animInstance = Cast<UVrmAnimInstance>(GetAnimInstanceObject());
|
||||
if (animInstance == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
enum BoneTarget{
|
||||
E_Hand_L,
|
||||
E_UpperArm_L,
|
||||
E_Hand_R,
|
||||
E_UpperArm_R,
|
||||
E_Head,
|
||||
E_Spine,
|
||||
|
||||
E_MAX,
|
||||
};
|
||||
|
||||
// boneName
|
||||
FString targetBoneTable[] = {
|
||||
TEXT("leftHand"),
|
||||
TEXT("leftUpperArm"),
|
||||
TEXT("rightHand"),
|
||||
TEXT("rightUpperArm"),
|
||||
TEXT("head"),
|
||||
TEXT("spine"),
|
||||
};
|
||||
{
|
||||
const UVrmMetaObject *meta = animInstance->MetaObject;
|
||||
if (meta) {
|
||||
for (auto &humanoidName : targetBoneTable) {
|
||||
for (auto &modelName : meta->humanoidBoneTable) {
|
||||
if (humanoidName.Compare(modelName.Key, ESearchCase::IgnoreCase) != 0) {
|
||||
continue;
|
||||
}
|
||||
// bone rename
|
||||
humanoidName = modelName.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tracking point
|
||||
FTransform targetTracking[] = {
|
||||
animInstance->TransHandLeft,
|
||||
animInstance->TransHandRight,
|
||||
animInstance->TransHead,
|
||||
};
|
||||
{
|
||||
const USceneComponent *targetComponent[] = {
|
||||
animInstance->ComponentHandLeft,
|
||||
animInstance->ComponentHandRight,
|
||||
animInstance->ComponentHead,
|
||||
};
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (targetComponent[i] == nullptr) continue;
|
||||
targetTracking[i] = targetComponent[i]->GetComponentTransform();
|
||||
}
|
||||
}
|
||||
|
||||
// mainBone Transform
|
||||
//FTeransform boneTransform[E_MAX] = {
|
||||
|
||||
//};
|
||||
|
||||
|
||||
|
||||
USkeletalMeshComponent *srcMesh = animInstance->BaseSkeletalMeshComponent;
|
||||
if (srcMesh == nullptr) {
|
||||
// return false;
|
||||
}
|
||||
|
||||
const auto &RefSkeletonTransform = GetSkelMeshComponent()->SkeletalMesh->RefSkeleton.GetRefBonePose();
|
||||
|
||||
auto &pose = Output.Pose;
|
||||
|
||||
FComponentSpacePoseContext ComponentSpacePoseContext(Output.AnimInstanceProxy);
|
||||
ComponentSpacePoseContext.Pose.InitPose(Output.Pose);
|
||||
|
||||
for (int i = 2; i >=0 ; --i) {
|
||||
|
||||
if (targetTracking[i].GetLocation().Size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FAnimNode_Fabrik f;
|
||||
{
|
||||
|
||||
f.EffectorTransformSpace = EBoneControlSpace::BCS_WorldSpace;
|
||||
f.EffectorTransform = targetTracking[i];
|
||||
|
||||
//f.EffectorTarget;
|
||||
|
||||
f.EffectorRotationSource = EBoneRotationSource::BRS_CopyFromTarget;
|
||||
|
||||
f.TipBone.BoneName = *(targetBoneTable[i * 2]);
|
||||
f.TipBone.Initialize(this->GetSkeleton());
|
||||
|
||||
f.RootBone.BoneName = *(targetBoneTable[i * 2 + 1]);
|
||||
f.RootBone.Initialize(this->GetSkeleton());
|
||||
|
||||
f.Precision = 1.f;
|
||||
f.MaxIterations = 10;
|
||||
f.bEnableDebugDraw = false;
|
||||
}
|
||||
FAnimNode_TwoBoneIK t;
|
||||
{
|
||||
t.IKBone.BoneName = *(targetBoneTable[i * 2]);
|
||||
|
||||
t.bAllowStretching = true;
|
||||
t.StartStretchRatio = 1.f;
|
||||
t.MaxStretchScale = 1.1f;
|
||||
//t.bTakeRotationFromEffectorSpace = false;
|
||||
t.bMaintainEffectorRelRot = false;
|
||||
t.bAllowTwist = true;
|
||||
|
||||
t.EffectorLocationSpace = EBoneControlSpace::BCS_WorldSpace;
|
||||
|
||||
t.EffectorLocation = targetTracking[i].GetLocation();
|
||||
|
||||
//f.EffectorTarget;
|
||||
|
||||
t.JointTargetLocationSpace = EBoneControlSpace::BCS_WorldSpace;
|
||||
|
||||
const USceneComponent *tmp[] = {
|
||||
animInstance->ComponentHandJointTargetLeft,
|
||||
animInstance->ComponentHandJointTargetRight,
|
||||
nullptr,
|
||||
};
|
||||
if (tmp[i]) {
|
||||
t.JointTargetLocation = tmp[i]->GetComponentLocation();
|
||||
}
|
||||
//f.JointTarget;
|
||||
}
|
||||
FAnimNode_SplineIK s;
|
||||
{
|
||||
s.StartBone.BoneName = *targetBoneTable[E_Spine];
|
||||
s.StartBone.Initialize(this->GetSkeleton());
|
||||
s.EndBone.BoneName = *targetBoneTable[E_Head];
|
||||
s.EndBone.Initialize(this->GetSkeleton());
|
||||
|
||||
s.BoneAxis = ESplineBoneAxis::Y;
|
||||
|
||||
s.bAutoCalculateSpline = false;
|
||||
|
||||
s.PointCount = 2;
|
||||
|
||||
s.ControlPoints.SetNum(2);
|
||||
s.ControlPoints[0].SetIdentity();
|
||||
s.ControlPoints[1] = targetTracking[2];
|
||||
s.ControlPoints[1].SetToRelativeTransform(GetComponentTransform());
|
||||
|
||||
//ComponentSpacePoseContext.
|
||||
|
||||
s.Roll = 0.f;
|
||||
|
||||
s.TwistStart = 0.f;
|
||||
|
||||
s.TwistEnd = 0.f;
|
||||
|
||||
//s.TwistBlend;
|
||||
|
||||
s.Stretch = 0.01f;
|
||||
|
||||
s.Offset = 0.f;
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
//ApplyBoneControllers(GetCurveBoneControllers(), ComponentSpacePoseContext);
|
||||
//ApplyBoneControllers(BoneControllers, ComponentSpacePoseContext);
|
||||
if (USkeleton* LocalSkeleton = ComponentSpacePoseContext.AnimInstanceProxy->GetSkeleton())
|
||||
{
|
||||
//for (auto& SingleBoneController : InBoneControllers)
|
||||
if (i != 2) {
|
||||
auto &SingleBoneController = t;
|
||||
|
||||
TArray<FBoneTransform> BoneTransforms;
|
||||
FAnimationCacheBonesContext Proxy(this);
|
||||
SingleBoneController.CacheBones_AnyThread(Proxy);
|
||||
if (SingleBoneController.IsValidToEvaluate(LocalSkeleton, ComponentSpacePoseContext.Pose.GetPose().GetBoneContainer()))
|
||||
{
|
||||
SingleBoneController.EvaluateSkeletalControl_AnyThread(ComponentSpacePoseContext, BoneTransforms);
|
||||
if (BoneTransforms.Num() > 0)
|
||||
{
|
||||
ComponentSpacePoseContext.Pose.LocalBlendCSBoneTransforms(BoneTransforms, 1.0f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto &SingleBoneController = s;
|
||||
|
||||
TArray<FBoneTransform> BoneTransforms;
|
||||
FAnimationCacheBonesContext Proxy(this);
|
||||
SingleBoneController.CacheBones_AnyThread(Proxy);
|
||||
if (SingleBoneController.IsValidToEvaluate(LocalSkeleton, ComponentSpacePoseContext.Pose.GetPose().GetBoneContainer()))
|
||||
{
|
||||
SingleBoneController.EvaluateSkeletalControl_AnyThread(ComponentSpacePoseContext, BoneTransforms);
|
||||
if (BoneTransforms.Num() > 0)
|
||||
{
|
||||
ComponentSpacePoseContext.Pose.LocalBlendCSBoneTransforms(BoneTransforms, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
#if UE_VERSION_OLDER_THAN(4,21,0)
|
||||
ComponentSpacePoseContext.Pose.ConvertToLocalPoses(Output.Pose);
|
||||
#endif
|
||||
|
||||
for (int i=0; i<3; ++i){
|
||||
auto b = GetSkelMeshComponent()->GetBoneIndex(*targetBoneTable[i*2]);
|
||||
if (b == INDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
FCompactPose::BoneIndexType bi(b);
|
||||
auto t = Output.Pose[bi];
|
||||
auto tmp = targetTracking[i];
|
||||
//tmp.SetToRelativeTransform(GetComponentTransform());
|
||||
//t.SetRotation( GetComponentTransform().GetRotation().Inverse() * (tmp.GetRotation()) );
|
||||
|
||||
|
||||
//const FTransform& BoneTM = ComponentSpacePoseContext.Pose.GetComponentSpaceTransform(bi);
|
||||
t.SetRotation( t.GetRotation() * (tmp.GetRotation()) );
|
||||
Output.Pose[bi] = t;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
for (auto &boneName : meta->humanoidBoneTable) {
|
||||
|
||||
if (boneName.Key == TEXT("leftEye") || boneName.Key == TEXT("rightEye")) {
|
||||
continue;
|
||||
}
|
||||
//auto i = srcMesh->GetBoneIndex();
|
||||
if (srcMesh->GetBoneIndex(*(boneName.Key)) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto t = srcMesh->GetSocketTransform(*(boneName.Key), RTS_ParentBoneSpace);
|
||||
|
||||
auto i = GetSkelMeshComponent()->GetBoneIndex(*(boneName.Value));
|
||||
if (i < 0) {
|
||||
continue;
|
||||
}
|
||||
auto refLocation = RefSkeletonTransform[i].GetLocation();
|
||||
|
||||
FVector newLoc = t.GetLocation();
|
||||
if (newLoc.Normalize()) {
|
||||
newLoc *= refLocation.Size();
|
||||
t.SetLocation(newLoc);
|
||||
}
|
||||
|
||||
FCompactPose::BoneIndexType bi(i);
|
||||
pose[bi] = t;
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,24,0)
|
||||
void FVrmAnimInstanceProxy::UpdateAnimationNode(float DeltaSeconds) {
|
||||
}
|
||||
#else
|
||||
void FVrmAnimInstanceProxy::UpdateAnimationNode(const FAnimationUpdateContext& InContext){
|
||||
}
|
||||
#endif
|
||||
|
||||
/////
|
||||
|
||||
UVrmAnimInstance::UVrmAnimInstance(const FObjectInitializer& ObjectInitializer)
|
||||
:Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
FAnimInstanceProxy* UVrmAnimInstance::CreateAnimInstanceProxy() {
|
||||
|
||||
return new FVrmAnimInstanceProxy(this);
|
||||
}
|
||||
|
||||
|
||||
void UVrmAnimInstance::NativeInitializeAnimation() {
|
||||
}
|
||||
void UVrmAnimInstance::NativeUpdateAnimation(float DeltaSeconds) {
|
||||
|
||||
{
|
||||
if (BaseSkeletalMeshComponent == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto a = BaseSkeletalMeshComponent->GetAnimInstance();
|
||||
if (a == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (VRMGetSkinnedAsset(BaseSkeletalMeshComponent) == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
a->CurrentSkeleton = VRMGetSkeleton( VRMGetSkinnedAsset(BaseSkeletalMeshComponent) );
|
||||
}
|
||||
}
|
||||
void UVrmAnimInstance::NativePostEvaluateAnimation() {
|
||||
if (BaseSkeletalMeshComponent) {
|
||||
if (BaseSkeletalMeshComponent->AnimScriptInstance) {
|
||||
IAnimClassInterface* AnimClassInterface = IAnimClassInterface::GetFromClass(this->GetClass());
|
||||
//const USkeleton* AnimSkeleton = (AnimClassInterface) ? AnimClassInterface->GetTargetSkeleton() : nullptr;
|
||||
if (AnimClassInterface) {
|
||||
//AnimClassInterface->
|
||||
}
|
||||
//BaseSkeletalMeshComponent->AnimScriptInstance->target
|
||||
//BaseSkeletalMeshComponent->AnimScriptInstance->CurrentSkeleton =
|
||||
//BaseSkeletalMeshComponent->SkeletalMesh->Skeleton;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
void UVrmAnimInstance::NativeUninitializeAnimation() {
|
||||
}
|
||||
void UVrmAnimInstance::NativeBeginPlay() {
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static TArray<FString> shapeBlend = {
|
||||
"Neutral","A","I","U","E","O","Blink","Joy","Angry","Sorrow","Fun","LookUp","LookDown","LookLeft","LookRight","Blink_L","Blink_R",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void UVrmAnimInstance::SetMorphTargetVRM(EVRMBlendShapeGroup type, float Value) {
|
||||
|
||||
if (MetaObject == nullptr){
|
||||
return;
|
||||
}
|
||||
|
||||
USkeletalMeshComponent *skc = GetOwningComponent();
|
||||
//auto &morphMap = skc->GetMorphTargetCurves();
|
||||
for (auto &a : MetaObject->BlendShapeGroup) {
|
||||
if (a.name != shapeBlend[(int)type]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto &b : a.BlendShape) {
|
||||
//b.meshName
|
||||
|
||||
SetMorphTarget(*(b.morphTargetName), Value);
|
||||
|
||||
/*
|
||||
for (auto &m : skc->SkeletalMesh->MorphTargets) {
|
||||
auto s = m->GetName();
|
||||
//if (s.Find(b.meshName) < 0) {
|
||||
// continue;
|
||||
//}
|
||||
auto s1 = FString::Printf(TEXT("%02d_"), b.meshID);
|
||||
if (s.Find(s1) < 0) {
|
||||
continue;
|
||||
}
|
||||
auto s2 = FString::Printf(TEXT("_%02d"), b.shapeIndex);
|
||||
if (s.Find(s2) < 0) {
|
||||
continue;
|
||||
}
|
||||
SetMorphTarget(*s, Value);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void UVrmAnimInstance::SetVrmData(USkeletalMeshComponent *baseSkeletalMesh, UVrmMetaObject *meta) {
|
||||
IAnimClassInterface* AnimClassInterface = IAnimClassInterface::GetFromClass(this->GetClass());
|
||||
//const USkeleton* AnimSkeleton = (AnimClassInterface) ? AnimClassInterface->GetTargetSkeleton() : nullptr;
|
||||
|
||||
USkeletalMeshComponent *skc = GetOwningComponent();
|
||||
|
||||
skc->SetSkeletalMesh(meta->SkeletalMesh);
|
||||
BaseSkeletalMeshComponent = baseSkeletalMesh;
|
||||
MetaObject = meta;
|
||||
|
||||
//if (AnimClassInterface) {
|
||||
// AnimClassInterface->
|
||||
//}
|
||||
//BaseSkeletalMeshComponent->AnimScriptInstance->target
|
||||
//BaseSkeletalMeshComponent->AnimScriptInstance->CurrentSkeleton =
|
||||
//BaseSkeletalMeshComponent->SkeletalMesh->Skeleton;
|
||||
}
|
||||
@@ -0,0 +1,576 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "VrmAnimInstanceCopy.h"
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmAssetListObject.h"
|
||||
#include "VrmUtil.h"
|
||||
#include "VrmBPFunctionLibrary.h"
|
||||
#include "Animation/AnimNodeBase.h"
|
||||
//#include "BoneControllers/AnimNode_Fabrik.h"
|
||||
//#include "BoneControllers/AnimNode_TwoBoneIK.h"
|
||||
//#include "BoneControllers/AnimNode_SplineIK.h"
|
||||
#include "AnimNode_VrmSpringBone.h"
|
||||
#include "AnimNode_VrmConstraint.h"
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,4,0)
|
||||
#include "Animation/Rig.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace {
|
||||
// for UE4.19-4.22
|
||||
template<class BaseType, class PoseType>
|
||||
static void ConvertToLocalPoses(const BaseType &basePose, PoseType& OutPose)
|
||||
{
|
||||
checkSlow(basePose.GetPose().IsValid());
|
||||
OutPose = basePose.GetPose();
|
||||
|
||||
// now we need to convert back to local bases
|
||||
// only convert back that has been converted to mesh base
|
||||
// if it was local base, and if it hasn't been modified
|
||||
// that is still okay even if parent is changed,
|
||||
// that doesn't mean this local has to change
|
||||
// go from child to parent since I need parent inverse to go back to local
|
||||
// root is same, so no need to do Index == 0
|
||||
const FCSPose<FCompactPose>::BoneIndexType RootBoneIndex(0);
|
||||
if (basePose.GetComponentSpaceFlags()[RootBoneIndex])
|
||||
{
|
||||
OutPose[RootBoneIndex] = basePose.GetPose()[RootBoneIndex];
|
||||
}
|
||||
|
||||
const int32 NumBones = basePose.GetPose().GetNumBones();
|
||||
for (int32 Index = NumBones - 1; Index > 0; Index--)
|
||||
{
|
||||
const FCSPose<FCompactPose>::BoneIndexType BoneIndex(Index);
|
||||
if (basePose.GetComponentSpaceFlags()[BoneIndex])
|
||||
{
|
||||
const FCSPose<FCompactPose>::BoneIndexType ParentIndex = basePose.GetPose().GetParentBoneIndex(BoneIndex);
|
||||
OutPose[BoneIndex].SetToRelativeTransform(OutPose[ParentIndex]);
|
||||
OutPose[BoneIndex].NormalizeRotation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FVrmAnimInstanceCopyProxy::FVrmAnimInstanceCopyProxy()
|
||||
{
|
||||
if (Node_SpringBone.Get() == nullptr) {
|
||||
Node_SpringBone = MakeShareable(new FAnimNode_VrmSpringBone());
|
||||
}
|
||||
if (Node_Constraint.Get() == nullptr) {
|
||||
Node_Constraint = MakeShareable(new FAnimNode_VrmConstraint());
|
||||
}
|
||||
}
|
||||
|
||||
FVrmAnimInstanceCopyProxy::FVrmAnimInstanceCopyProxy(UAnimInstance* InAnimInstance)
|
||||
: FAnimInstanceProxy(InAnimInstance)
|
||||
{
|
||||
if (Node_SpringBone.Get() == nullptr) {
|
||||
Node_SpringBone = MakeShareable(new FAnimNode_VrmSpringBone());
|
||||
}
|
||||
if (Node_Constraint.Get() == nullptr) {
|
||||
Node_Constraint = MakeShareable(new FAnimNode_VrmConstraint());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FVrmAnimInstanceCopyProxy::Initialize(UAnimInstance* InAnimInstance) {
|
||||
}
|
||||
bool FVrmAnimInstanceCopyProxy::Evaluate(FPoseContext& Output) {
|
||||
|
||||
if (bCopyStop) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bAnimStop && bUseAnimStop) {
|
||||
Output.Pose.CopyBonesFrom(CachedPose);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//Output.ResetToRefPose();
|
||||
|
||||
UVrmAnimInstanceCopy *animInstance = Cast<UVrmAnimInstanceCopy>(GetAnimInstanceObject());
|
||||
if (animInstance == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (animInstance->DstVrmAssetList == nullptr) {
|
||||
//if (animInstance->SrcVrmAssetList == nullptr || animInstance->DstVrmAssetList == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const UVrmMetaObject *srcMeta = animInstance->SrcVrmMetaOverride;
|
||||
if (srcMeta == nullptr){
|
||||
if (animInstance->SrcVrmAssetList) {
|
||||
srcMeta = animInstance->SrcVrmAssetList->VrmMetaObject;
|
||||
}
|
||||
}
|
||||
|
||||
const UVrmMetaObject *dstMeta = animInstance->DstVrmAssetList->VrmMetaObject;
|
||||
if (dstMeta) {
|
||||
if (animInstance->DstVrmMetaForCustomSpring) {
|
||||
dstMeta = animInstance->DstVrmMetaForCustomSpring;
|
||||
}
|
||||
}
|
||||
|
||||
if (dstMeta == nullptr) {
|
||||
//if (srcMeta == nullptr || dstMeta == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
auto srcSkeletalMeshComp = animInstance->SrcSkeletalMeshComponent;
|
||||
auto srcAsSkinnedMeshComp = animInstance->SrcAsSkinnedMeshComponent;
|
||||
|
||||
if (srcAsSkinnedMeshComp == nullptr) {
|
||||
if (srcSkeletalMeshComp == nullptr || srcSkeletalMeshComp->GetAnimInstance() == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (VRMGetSkinnedAsset(srcAsSkinnedMeshComp) == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ref pose
|
||||
const auto &dstRefSkeletonTransform = VRMGetRefSkeleton( VRMGetSkinnedAsset(GetSkelMeshComponent()) ).GetRefBonePose();
|
||||
const auto &srcRefSkeletonTransform = VRMGetRefSkeleton( VRMGetSkinnedAsset(srcAsSkinnedMeshComp) ).GetRefBonePose();
|
||||
|
||||
auto &pose = Output.Pose;
|
||||
|
||||
// morph copy
|
||||
if (srcSkeletalMeshComp && srcSkeletalMeshComp->GetAnimInstance()){
|
||||
EAnimCurveType types[] = {
|
||||
EAnimCurveType::AttributeCurve,
|
||||
EAnimCurveType::MaterialCurve,
|
||||
EAnimCurveType::MorphTargetCurve,
|
||||
};
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const TMap<FName, float>& t = srcSkeletalMeshComp->GetAnimInstance()->GetAnimationCurveList(types[i]);
|
||||
for (auto& a : t) {
|
||||
GetSkelMeshComponent()->SetMorphTarget(a.Key, a.Value, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float HeightScale = 1.f;
|
||||
bool bUniqueRootBone = true;
|
||||
int BoneCount = 0;
|
||||
for (const auto &t : VRMUtil::vrm_humanoid_bone_list) {
|
||||
FName srcName, dstName;
|
||||
srcName = dstName = NAME_None;
|
||||
|
||||
++BoneCount;
|
||||
{
|
||||
if (srcMeta) {
|
||||
auto a = srcMeta->humanoidBoneTable.Find(t);
|
||||
if (a) {
|
||||
srcName = **a;
|
||||
}
|
||||
} else {
|
||||
for (auto &bonemap : VRMUtil::table_ue4_vrm) {
|
||||
if (bonemap.BoneVRM == t) {
|
||||
srcName = *bonemap.BoneUE4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//auto srcName = srcSkeletalMeshComp->SkeletalMesh->Skeleton->GetRigBoneMapping(t);
|
||||
if (srcName == NAME_None) {
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
auto a = dstMeta->humanoidBoneTable.Find(t);
|
||||
if (a) {
|
||||
dstName = **a;
|
||||
}
|
||||
}
|
||||
//auto dstName = GetSkelMeshComponent()->SkeletalMesh->Skeleton->GetRigBoneMapping(t);
|
||||
if (dstName == NAME_None) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto dstIndex = GetSkelMeshComponent()->GetBoneIndex(dstName);
|
||||
if (dstIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
auto srcIndex = srcAsSkinnedMeshComp->GetBoneIndex(srcName);
|
||||
if (srcIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const auto srcCurrentTrans = srcAsSkinnedMeshComp->GetSocketTransform(srcName, RTS_ParentBoneSpace);
|
||||
const auto srcRefTrans = srcRefSkeletonTransform[srcIndex];
|
||||
const auto dstRefTrans = dstRefSkeletonTransform[dstIndex];
|
||||
|
||||
FTransform dstTrans = dstRefTrans;
|
||||
|
||||
{
|
||||
FQuat diff = srcCurrentTrans.GetRotation()*srcRefTrans.GetRotation().Inverse();
|
||||
dstTrans.SetRotation(dstTrans.GetRotation()*diff);
|
||||
}
|
||||
//dstTrans.SetLocation(dstRefTrans.GetLocation());// +srcCurrentTrans.GetLocation() - srcRefTrans.GetLocation());
|
||||
|
||||
//FVector newLoc = dstTrans.GetLocation();
|
||||
if (BoneCount == 1) {
|
||||
if (bIgnoreCenterLocation) {
|
||||
dstTrans.SetTranslation(CenterLocationOffset);
|
||||
} else {
|
||||
int32_t p = dstIndex;
|
||||
float HipHeight = 0;
|
||||
while (p != INDEX_NONE) {
|
||||
|
||||
HipHeight += dstRefSkeletonTransform[p].GetLocation().Z;
|
||||
p = VRMGetRefSkeleton( VRMGetSkinnedAsset(GetSkelMeshComponent()) ).GetParentIndex(p);
|
||||
}
|
||||
//FVector diff = srcCurrentTrans.GetLocation() - srcRefTrans.GetLocation();
|
||||
//FVector scale = dstRefTrans.GetLocation() / srcRefTrans.GetLocation();
|
||||
FVector diff = srcCurrentTrans.GetLocation() - srcRefTrans.GetLocation();
|
||||
HeightScale = HipHeight / srcRefTrans.GetLocation().Z;
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,24,0)
|
||||
FVector ComponentScale = Output.AnimInstanceProxy->GetSkelMeshComponent()->RelativeScale3D;
|
||||
#else
|
||||
FVector ComponentScale = Output.AnimInstanceProxy->GetSkelMeshComponent()->GetRelativeScale3D();
|
||||
#endif
|
||||
if (ComponentScale.X == 0.f) {
|
||||
ComponentScale.X = 0.001f;
|
||||
}
|
||||
if (ComponentScale.Y == 0.f) {
|
||||
ComponentScale.Y = 0.001f;
|
||||
}
|
||||
if (ComponentScale.Z == 0.f) {
|
||||
ComponentScale.Z = 0.001f;
|
||||
}
|
||||
|
||||
dstTrans.SetTranslation(
|
||||
(dstRefTrans.GetLocation() + FMath::Lerp(diff, diff * HeightScale, CenterLocationScaleByHeightScale)) / ComponentScale
|
||||
+ CenterLocationOffset
|
||||
);
|
||||
if (dstIndex == 0) {
|
||||
bUniqueRootBone = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FCompactPose::BoneIndexType bi(dstIndex);
|
||||
pose[bi] = dstTrans;
|
||||
}
|
||||
|
||||
// root bone
|
||||
if (bUniqueRootBone){
|
||||
FCompactPose::BoneIndexType bi(0);
|
||||
const auto srcTrans = srcAsSkinnedMeshComp->GetSocketTransform(srcAsSkinnedMeshComp->GetBoneName(0), RTS_ParentBoneSpace);
|
||||
|
||||
auto t = srcTrans;
|
||||
if (bIgnoreCenterLocation) {
|
||||
t.SetTranslation(CenterLocationOffset);
|
||||
}else{
|
||||
#if UE_VERSION_OLDER_THAN(4,24,0)
|
||||
FVector ComponentScale = Output.AnimInstanceProxy->GetSkelMeshComponent()->RelativeScale3D;
|
||||
#else
|
||||
FVector ComponentScale = Output.AnimInstanceProxy->GetSkelMeshComponent()->GetRelativeScale3D();
|
||||
#endif
|
||||
if (ComponentScale.X == 0.f) {
|
||||
ComponentScale.X = 0.001f;
|
||||
}
|
||||
if (ComponentScale.Y == 0.f) {
|
||||
ComponentScale.Y = 0.001f;
|
||||
}
|
||||
if (ComponentScale.Z == 0.f) {
|
||||
ComponentScale.Z = 0.001f;
|
||||
}
|
||||
|
||||
t.SetTranslation(
|
||||
(FMath::Lerp(t.GetTranslation(), t.GetTranslation() * HeightScale, CenterLocationScaleByHeightScale)) / ComponentScale
|
||||
+ CenterLocationOffset
|
||||
);
|
||||
}
|
||||
pose[bi] = t;
|
||||
}
|
||||
|
||||
// constraint
|
||||
if (bIgnoreVRMConstraint == false) {
|
||||
// if (0){
|
||||
bool bCalc = true;
|
||||
{
|
||||
bool bPlay, bSIE, bEditor;
|
||||
bPlay = bSIE = bEditor = true;
|
||||
UVrmBPFunctionLibrary::VRMGetPlayMode(bPlay, bSIE, bEditor);
|
||||
if (bPlay == false) {
|
||||
bCalc = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bCalc) {
|
||||
if (Node_Constraint.Get() == nullptr) {
|
||||
Node_Constraint = MakeShareable(new FAnimNode_VrmConstraint());
|
||||
}
|
||||
|
||||
if (Node_Constraint.Get()) {
|
||||
#if UE_VERSION_OLDER_THAN(4,22,0)
|
||||
#else
|
||||
if (animInstance->PendingDynamicResetTeleportType != ETeleportType::None)
|
||||
{
|
||||
Node_Constraint->ResetDynamics(animInstance->PendingDynamicResetTeleportType);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto& constraint = *Node_Constraint.Get();
|
||||
|
||||
constraint.VrmMetaObject_Internal = const_cast<UVrmMetaObject*>(dstMeta);
|
||||
constraint.bCallByAnimInstance = true;
|
||||
|
||||
FAnimationInitializeContext InitContext(this);
|
||||
|
||||
if (constraint. bCallInitialized == false) {
|
||||
constraint.Initialize_AnyThread(InitContext);
|
||||
constraint.ComponentPose.SetLinkNode(&constraint);
|
||||
}
|
||||
|
||||
if (0) {
|
||||
++CalcCount;
|
||||
FComponentSpacePoseContext InputCSPose(this);
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
InputCSPose.Pose.InitPose(Output.Pose);
|
||||
constraint.EvaluateComponentSpace_AnyThread(InputCSPose);
|
||||
ConvertToLocalPoses(InputCSPose.Pose, Output.Pose);
|
||||
}
|
||||
}
|
||||
else {
|
||||
FComponentSpacePoseContext InputCSPose(this);
|
||||
InputCSPose.Pose.InitPose(Output.Pose);
|
||||
constraint.EvaluateComponentSpace_AnyThread(InputCSPose);
|
||||
ConvertToLocalPoses(InputCSPose.Pose, Output.Pose);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Node_Constraint = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (bIgnoreVRMSwingBone == false) {
|
||||
//if (0){
|
||||
bool bCalc = true;
|
||||
{
|
||||
bool bPlay, bSIE, bEditor;
|
||||
bPlay = bSIE = bEditor = true;
|
||||
UVrmBPFunctionLibrary::VRMGetPlayMode(bPlay, bSIE, bEditor);
|
||||
if (bPlay == false) {
|
||||
bCalc = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bCalc) {
|
||||
if (Node_SpringBone.Get() == nullptr) {
|
||||
Node_SpringBone = MakeShareable(new FAnimNode_VrmSpringBone());
|
||||
}
|
||||
|
||||
if (Node_SpringBone.Get()) {
|
||||
#if UE_VERSION_OLDER_THAN(4,22,0)
|
||||
#else
|
||||
if(animInstance->PendingDynamicResetTeleportType != ETeleportType::None)
|
||||
{
|
||||
Node_SpringBone->ResetDynamics(animInstance->PendingDynamicResetTeleportType);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto& springBone = *Node_SpringBone.Get();
|
||||
|
||||
springBone.VrmMetaObject_Internal = const_cast<UVrmMetaObject*>(dstMeta);
|
||||
springBone.bCallByAnimInstance = true;
|
||||
springBone.CurrentDeltaTime = CurrentDeltaTime;
|
||||
|
||||
FAnimationInitializeContext InitContext(this);
|
||||
|
||||
if (springBone.IsSpringInit() == false) {
|
||||
springBone.Initialize_AnyThread_local(InitContext);
|
||||
springBone.ComponentPose.SetLinkNode(&springBone);
|
||||
CalcCount = 0;
|
||||
springBone.CurrentDeltaTime = 1.f / 20.f;
|
||||
}
|
||||
if (CalcCount < 3) {
|
||||
FVector bak = springBone.gravityAdd;
|
||||
++CalcCount;
|
||||
FComponentSpacePoseContext InputCSPose(this);
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
InputCSPose.Pose.InitPose(Output.Pose);
|
||||
springBone.EvaluateComponentSpace_AnyThread(InputCSPose);
|
||||
ConvertToLocalPoses(InputCSPose.Pose, Output.Pose);
|
||||
}
|
||||
springBone.gravityAdd = bak;
|
||||
|
||||
} else {
|
||||
FComponentSpacePoseContext InputCSPose(this);
|
||||
InputCSPose.Pose.InitPose(Output.Pose);
|
||||
springBone.EvaluateComponentSpace_AnyThread(InputCSPose);
|
||||
ConvertToLocalPoses(InputCSPose.Pose, Output.Pose);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Node_SpringBone = nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (bUseAnimStop) {
|
||||
CachedPose.CopyBonesFrom(Output.Pose);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#if UE_VERSION_OLDER_THAN(4,24,0)
|
||||
void FVrmAnimInstanceCopyProxy::UpdateAnimationNode(float DeltaSeconds) {
|
||||
CurrentDeltaTime = DeltaSeconds;
|
||||
}
|
||||
#else
|
||||
void FVrmAnimInstanceCopyProxy::UpdateAnimationNode(const FAnimationUpdateContext& InContext) {
|
||||
CurrentDeltaTime = InContext.GetDeltaTime();
|
||||
}
|
||||
#endif
|
||||
|
||||
/////
|
||||
|
||||
UVrmAnimInstanceCopy::UVrmAnimInstanceCopy(const FObjectInitializer& ObjectInitializer)
|
||||
:Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
FAnimInstanceProxy* UVrmAnimInstanceCopy::CreateAnimInstanceProxy() {
|
||||
myProxy = new FVrmAnimInstanceCopyProxy(this);
|
||||
myProxy->bIgnoreVRMSwingBone = bIgnoreVRMSwingBone;
|
||||
myProxy->bIgnoreWindDirectionalSource = bIgnoreWindDirectionalSource;
|
||||
return myProxy;
|
||||
}
|
||||
|
||||
|
||||
void UVrmAnimInstanceCopy::NativeInitializeAnimation() {
|
||||
for (int i = 0; i < FMath::Min(InitialMorphValue.Num(), InitialMorphName.Num()); ++i) {
|
||||
SetMorphTarget(InitialMorphName[i], InitialMorphValue[i]);
|
||||
}
|
||||
}
|
||||
void UVrmAnimInstanceCopy::NativeUpdateAnimation(float DeltaSeconds) {
|
||||
}
|
||||
void UVrmAnimInstanceCopy::NativePostEvaluateAnimation() {
|
||||
myProxy->bUseAnimStop = bUseAnimStop;
|
||||
myProxy->bAnimStop = bAnimStop;
|
||||
myProxy->bIgnoreCenterLocation = bIgnoreCenterLocation;
|
||||
myProxy->CenterLocationScaleByHeightScale = CenterLocationScaleByHeightScale;
|
||||
myProxy->CenterLocationOffset= CenterLocationOffset;
|
||||
myProxy->bCopyStop = bCopyStop;
|
||||
}
|
||||
void UVrmAnimInstanceCopy::NativeUninitializeAnimation() {
|
||||
if (GetOwningComponent()) {
|
||||
GetOwningComponent()->ClearMorphTargets();
|
||||
}
|
||||
|
||||
if (!SrcSkeletalMeshComponent && bUseAttachedParent)
|
||||
{
|
||||
USkeletalMeshComponent* TargetMesh = GetOwningComponent();
|
||||
|
||||
// Walk up the attachment chain until we find a skeletal mesh component
|
||||
USkeletalMeshComponent* ParentMeshComponent = nullptr;
|
||||
for (USceneComponent* AttachParentComp = TargetMesh->GetAttachParent(); AttachParentComp != nullptr; AttachParentComp = AttachParentComp->GetAttachParent())
|
||||
{
|
||||
ParentMeshComponent = Cast<USkeletalMeshComponent>(AttachParentComp);
|
||||
if (ParentMeshComponent)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ParentMeshComponent == nullptr) {
|
||||
AActor *targetActor = nullptr;
|
||||
AActor *myActor = TargetMesh->GetOwner();
|
||||
for (USceneComponent* AttachParentComp = TargetMesh->GetAttachParent(); AttachParentComp != nullptr; AttachParentComp = AttachParentComp->GetAttachParent()) {
|
||||
targetActor = AttachParentComp->GetOwner();
|
||||
if (targetActor != myActor) {
|
||||
break;
|
||||
}
|
||||
targetActor = nullptr;
|
||||
}
|
||||
if (targetActor) {
|
||||
TArray<USkeletalMeshComponent*> c;
|
||||
targetActor->GetComponents<USkeletalMeshComponent>(c);
|
||||
if (c.IsValidIndex(0)) {
|
||||
ParentMeshComponent = c[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ParentMeshComponent)
|
||||
{
|
||||
SrcSkeletalMeshComponent = ParentMeshComponent;
|
||||
}
|
||||
}
|
||||
if (SrcAsSkinnedMeshComponent == nullptr) {
|
||||
SrcAsSkinnedMeshComponent = SrcSkeletalMeshComponent;
|
||||
}
|
||||
}
|
||||
void UVrmAnimInstanceCopy::NativeBeginPlay() {
|
||||
if (GetOwningComponent()) {
|
||||
GetOwningComponent()->ClearMorphTargets();
|
||||
}
|
||||
}
|
||||
|
||||
void UVrmAnimInstanceCopy::SetSkeletalMeshCopyData(UVrmAssetListObject *dstAssetList,
|
||||
USkeletalMeshComponent *srcSkeletalMesh, USkinnedMeshComponent* srcSkinnedMesh, UVrmAssetListObject *srcAssetList, UVrmMetaObject* srcVrmMeta) {
|
||||
|
||||
SrcSkeletalMeshComponent = srcSkeletalMesh;
|
||||
SrcAsSkinnedMeshComponent = srcSkinnedMesh;
|
||||
SrcVrmAssetList = srcAssetList;
|
||||
DstVrmAssetList = dstAssetList;
|
||||
SrcVrmMetaOverride = srcVrmMeta;
|
||||
|
||||
if (SrcAsSkinnedMeshComponent == nullptr) {
|
||||
SrcAsSkinnedMeshComponent = SrcSkeletalMeshComponent;
|
||||
}
|
||||
}
|
||||
|
||||
void UVrmAnimInstanceCopy::SetSkeletalMeshCopyDataForCustomSpring(UVrmMetaObject *dstMetaForCustomSpring) {
|
||||
DstVrmMetaForCustomSpring = dstMetaForCustomSpring;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UVrmAnimInstanceCopy::SetVrmSpringBoneParam(float gravityScale, FVector gravityAdd, float stiffnessScale, float stiffnessAdd, float randomWindRange) {
|
||||
if (myProxy == nullptr) return;
|
||||
auto a = myProxy->Node_SpringBone.Get();
|
||||
if (a == nullptr) return;
|
||||
|
||||
a->gravityScale = gravityScale;
|
||||
a->gravityAdd = gravityAdd;
|
||||
a->stiffnessScale = stiffnessScale;
|
||||
a->stiffnessAdd = stiffnessAdd;
|
||||
a->randomWindRange = randomWindRange;
|
||||
}
|
||||
|
||||
void UVrmAnimInstanceCopy::SetVrmSpringBoneBool(bool bIgnoreVrmSpringBone, bool bIgnorePhysicsCollision, bool bIgnoreVRMCollision, bool bIgnoreWind) {
|
||||
if (myProxy == nullptr) return;
|
||||
auto a = myProxy->Node_SpringBone.Get();
|
||||
if (a == nullptr) return;
|
||||
|
||||
this->bIgnoreVRMSwingBone = bIgnoreVrmSpringBone;
|
||||
myProxy->bIgnoreVRMSwingBone = bIgnoreVrmSpringBone;
|
||||
a->bIgnorePhysicsCollision = bIgnorePhysicsCollision;
|
||||
a->bIgnoreVRMCollision = bIgnoreVRMCollision;
|
||||
a->bIgnoreWindDirectionalSource = bIgnoreWind;
|
||||
}
|
||||
|
||||
void UVrmAnimInstanceCopy::SetVrmSpringBoneIgnoreWingBone(const TArray<FName> &boneNameList) {
|
||||
if (myProxy == nullptr) return;
|
||||
auto a = myProxy->Node_SpringBone.Get();
|
||||
if (a == nullptr) return;
|
||||
|
||||
a->NoWindBoneNameList = boneNameList;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,442 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "VrmAnimInstanceRetargetFromMannequin.h"
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,2,0)
|
||||
#else
|
||||
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmAssetListObject.h"
|
||||
#include "VrmUtil.h"
|
||||
#include "VrmBPFunctionLibrary.h"
|
||||
#include "Animation/AnimNodeBase.h"
|
||||
|
||||
//#include "BoneControllers/AnimNode_Fabrik.h"
|
||||
//#include "BoneControllers/AnimNode_TwoBoneIK.h"
|
||||
//#include "BoneControllers/AnimNode_SplineIK.h"
|
||||
#include "AnimNode_VrmSpringBone.h"
|
||||
#include "AnimNode_VrmConstraint.h"
|
||||
#include "AnimNodes/AnimNode_RetargetPoseFromMesh.h"
|
||||
|
||||
#include "VrmRigHeader.h"
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,4,0)
|
||||
#include "Animation/Rig.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace {
|
||||
template<class BaseType, class PoseType>
|
||||
static void ConvertToLocalPoses2(const BaseType &basePose, PoseType& OutPose)
|
||||
{
|
||||
checkSlow(basePose.GetPose().IsValid());
|
||||
OutPose = basePose.GetPose();
|
||||
|
||||
// now we need to convert back to local bases
|
||||
// only convert back that has been converted to mesh base
|
||||
// if it was local base, and if it hasn't been modified
|
||||
// that is still okay even if parent is changed,
|
||||
// that doesn't mean this local has to change
|
||||
// go from child to parent since I need parent inverse to go back to local
|
||||
// root is same, so no need to do Index == 0
|
||||
const FCSPose<FCompactPose>::BoneIndexType RootBoneIndex(0);
|
||||
if (basePose.GetComponentSpaceFlags()[RootBoneIndex])
|
||||
{
|
||||
OutPose[RootBoneIndex] = basePose.GetPose()[RootBoneIndex];
|
||||
}
|
||||
|
||||
const int32 NumBones = basePose.GetPose().GetNumBones();
|
||||
for (int32 Index = NumBones - 1; Index > 0; Index--)
|
||||
{
|
||||
const FCSPose<FCompactPose>::BoneIndexType BoneIndex(Index);
|
||||
if (basePose.GetComponentSpaceFlags()[BoneIndex])
|
||||
{
|
||||
const FCSPose<FCompactPose>::BoneIndexType ParentIndex = basePose.GetPose().GetParentBoneIndex(BoneIndex);
|
||||
OutPose[BoneIndex].SetToRelativeTransform(OutPose[ParentIndex]);
|
||||
OutPose[BoneIndex].NormalizeRotation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FVrmAnimInstanceRetargetFromMannequinProxy::FVrmAnimInstanceRetargetFromMannequinProxy()
|
||||
{
|
||||
}
|
||||
|
||||
FVrmAnimInstanceRetargetFromMannequinProxy::FVrmAnimInstanceRetargetFromMannequinProxy(UAnimInstance* InAnimInstance)
|
||||
: FAnimInstanceProxy(InAnimInstance)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FVrmAnimInstanceRetargetFromMannequinProxy::Initialize(UAnimInstance* InAnimInstance) {
|
||||
Super::Initialize(InAnimInstance);
|
||||
}
|
||||
|
||||
void FVrmAnimInstanceRetargetFromMannequinProxy::CustomInitialize() {
|
||||
|
||||
if (Node_SpringBone.Get() == nullptr) {
|
||||
Node_SpringBone = MakeShareable(new FAnimNode_VrmSpringBone());
|
||||
}
|
||||
if (Node_Constraint.Get() == nullptr) {
|
||||
Node_Constraint = MakeShareable(new FAnimNode_VrmConstraint());
|
||||
}
|
||||
|
||||
if (Node_Retarget.Get() == nullptr) {
|
||||
Node_Retarget = MakeShareable(new FAnimNode_RetargetPoseFromMesh());
|
||||
FAnimationInitializeContext InitContext(this);
|
||||
Node_Retarget->Initialize_AnyThread(InitContext);
|
||||
}
|
||||
}
|
||||
|
||||
bool FVrmAnimInstanceRetargetFromMannequinProxy::Evaluate(FPoseContext& Output) {
|
||||
|
||||
//Output.Pose.CopyBonesFrom(CachedPose);
|
||||
|
||||
UVrmAnimInstanceRetargetFromMannequin* animInstance = Cast<UVrmAnimInstanceRetargetFromMannequin>(GetAnimInstanceObject());
|
||||
if (animInstance == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (animInstance->DstVrmAssetList == nullptr) {
|
||||
if (IsInGameThread())
|
||||
{
|
||||
//FMessageLog("AnimBlueprintLog").Warning(
|
||||
// FText::Format(LOCTEXT("AnimInstance_SlotNode", "SLOTNODE: '{0}' in animation instance class {1} already exists. Remove duplicates from the animation graph for this class."),
|
||||
// FText::FromString(SlotNodeName.ToString()), FText::FromString(ClassNameString)));
|
||||
//FMessageLog("AnimBlueprintLog").Warning(FText::Format("UVrmAnimInstanceRetargetFromMannequin")));
|
||||
}
|
||||
else
|
||||
{
|
||||
//UE_LOG(LogAnimation, Warning, TEXT("SLOTNODE: '%s' in animation instance class %s already exists. Remove duplicates from the animation graph for this class."), *SlotNodeName.ToString(), *ClassNameString);
|
||||
}
|
||||
UE_LOG(LogAnimation, Warning, TEXT("UVrmAnimInstanceRetargetFromMannequin:: no DestVrmAssetList"));
|
||||
return false;
|
||||
}
|
||||
|
||||
const UVrmMetaObject *dstMeta = animInstance->DstVrmAssetList->VrmMetaObject;
|
||||
if (dstMeta) {
|
||||
if (animInstance->DstVrmMetaForCustomSpring) {
|
||||
dstMeta = animInstance->DstVrmMetaForCustomSpring;
|
||||
}
|
||||
}
|
||||
|
||||
if (dstMeta == nullptr) {
|
||||
UE_LOG(LogAnimation, Warning, TEXT("UVrmAnimInstanceRetargetFromMannequin:: no DstMeta"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// morph copy
|
||||
if (animInstance->SrcSkeletalMeshComponent){
|
||||
if (animInstance->SrcSkeletalMeshComponent->GetAnimInstance()) {
|
||||
EAnimCurveType types[] = {
|
||||
EAnimCurveType::AttributeCurve,
|
||||
EAnimCurveType::MaterialCurve,
|
||||
EAnimCurveType::MorphTargetCurve,
|
||||
};
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const TMap<FName, float>& t = animInstance->SrcSkeletalMeshComponent->GetAnimInstance()->GetAnimationCurveList(types[i]);
|
||||
for (auto& a : t) {
|
||||
GetSkelMeshComponent()->SetMorphTarget(a.Key, a.Value, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,2,0)
|
||||
#else
|
||||
|
||||
//retarget
|
||||
if (bUseRetargeter && Retargeter && Node_Retarget.Get()) {
|
||||
|
||||
if (Node_Retarget.Get()) {
|
||||
auto node = Node_Retarget.Get();
|
||||
|
||||
FAnimationCacheBonesContext c(this);
|
||||
node->CacheBones_AnyThread(c);
|
||||
|
||||
node->Evaluate_AnyThread(Output);
|
||||
}
|
||||
} else {
|
||||
Node_Retarget = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// constraint
|
||||
if (bIgnoreVRMConstraint == false) {
|
||||
bool bCalc = true;
|
||||
{
|
||||
bool bPlay, bSIE, bEditor;
|
||||
bPlay = bSIE = bEditor = true;
|
||||
UVrmBPFunctionLibrary::VRMGetPlayMode(bPlay, bSIE, bEditor);
|
||||
if (bPlay == false) {
|
||||
bCalc = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bCalc) {
|
||||
if (Node_Constraint.Get() == nullptr) {
|
||||
Node_Constraint = MakeShareable(new FAnimNode_VrmConstraint());
|
||||
}
|
||||
|
||||
if (Node_Constraint.Get()) {
|
||||
if (animInstance->PendingDynamicResetTeleportType != ETeleportType::None)
|
||||
{
|
||||
Node_Constraint->ResetDynamics(animInstance->PendingDynamicResetTeleportType);
|
||||
}
|
||||
|
||||
auto& constraint = *Node_Constraint.Get();
|
||||
|
||||
constraint.VrmMetaObject_Internal = const_cast<UVrmMetaObject*>(dstMeta);
|
||||
constraint.bCallByAnimInstance = true;
|
||||
|
||||
FAnimationInitializeContext InitContext(this);
|
||||
|
||||
if (constraint. bCallInitialized == false) {
|
||||
constraint.Initialize_AnyThread(InitContext);
|
||||
constraint.ComponentPose.SetLinkNode(&constraint);
|
||||
}
|
||||
|
||||
{
|
||||
FComponentSpacePoseContext InputCSPose(this);
|
||||
InputCSPose.Pose.InitPose(Output.Pose);
|
||||
constraint.EvaluateComponentSpace_AnyThread(InputCSPose);
|
||||
ConvertToLocalPoses2(InputCSPose.Pose, Output.Pose);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Node_Constraint = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (bIgnoreVRMSwingBone == false) {
|
||||
//if (0){
|
||||
bool bCalc = true;
|
||||
{
|
||||
bool bPlay, bSIE, bEditor;
|
||||
bPlay = bSIE = bEditor = true;
|
||||
UVrmBPFunctionLibrary::VRMGetPlayMode(bPlay, bSIE, bEditor);
|
||||
if (bPlay == false) {
|
||||
bCalc = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bCalc) {
|
||||
if (Node_SpringBone.Get() == nullptr) {
|
||||
Node_SpringBone = MakeShareable(new FAnimNode_VrmSpringBone());
|
||||
}
|
||||
|
||||
if (Node_SpringBone.Get()) {
|
||||
if(animInstance->PendingDynamicResetTeleportType != ETeleportType::None)
|
||||
{
|
||||
Node_SpringBone->ResetDynamics(animInstance->PendingDynamicResetTeleportType);
|
||||
}
|
||||
|
||||
auto& springBone = *Node_SpringBone.Get();
|
||||
|
||||
springBone.VrmMetaObject_Internal = const_cast<UVrmMetaObject*>(dstMeta);
|
||||
springBone.bCallByAnimInstance = true;
|
||||
springBone.CurrentDeltaTime = CurrentDeltaTime;
|
||||
|
||||
FAnimationInitializeContext InitContext(this);
|
||||
|
||||
if (springBone.IsSpringInit() == false) {
|
||||
springBone.Initialize_AnyThread_local(InitContext);
|
||||
springBone.ComponentPose.SetLinkNode(&springBone);
|
||||
CalcCount = 0;
|
||||
springBone.CurrentDeltaTime = 1.f / 20.f;
|
||||
}
|
||||
if (CalcCount < 3) {
|
||||
FVector bak = springBone.gravityAdd;
|
||||
++CalcCount;
|
||||
FComponentSpacePoseContext InputCSPose(this);
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
InputCSPose.Pose.InitPose(Output.Pose);
|
||||
springBone.EvaluateComponentSpace_AnyThread(InputCSPose);
|
||||
ConvertToLocalPoses2(InputCSPose.Pose, Output.Pose);
|
||||
}
|
||||
springBone.gravityAdd = bak;
|
||||
|
||||
} else {
|
||||
FComponentSpacePoseContext InputCSPose(this);
|
||||
InputCSPose.Pose.InitPose(Output.Pose);
|
||||
springBone.EvaluateComponentSpace_AnyThread(InputCSPose);
|
||||
ConvertToLocalPoses2(InputCSPose.Pose, Output.Pose);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Node_SpringBone = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
void FVrmAnimInstanceRetargetFromMannequinProxy::UpdateAnimationNode(const FAnimationUpdateContext& InContext) {
|
||||
CurrentDeltaTime = InContext.GetDeltaTime();
|
||||
CustomInitialize();
|
||||
|
||||
}
|
||||
|
||||
void FVrmAnimInstanceRetargetFromMannequinProxy::PreUpdate(UAnimInstance* InAnimInstance, float DeltaSeconds) {
|
||||
Super::PreUpdate(InAnimInstance, DeltaSeconds);
|
||||
|
||||
|
||||
if (Node_Retarget.Get()) {
|
||||
auto node = Node_Retarget.Get();
|
||||
|
||||
node->IKRetargeterAsset = Retargeter.Get();
|
||||
//node->SourceMeshComponent = InAnimInstance->SrcSkeletalMeshComponent; // null ok
|
||||
|
||||
FAnimationInitializeContext InitContext(this);
|
||||
|
||||
if (node->GetRetargetProcessor() == nullptr) {
|
||||
node->Initialize_AnyThread(InitContext);
|
||||
}
|
||||
|
||||
node->PreUpdate(InAnimInstance);
|
||||
}
|
||||
}
|
||||
|
||||
/////
|
||||
|
||||
UVrmAnimInstanceRetargetFromMannequin::UVrmAnimInstanceRetargetFromMannequin(const FObjectInitializer& ObjectInitializer)
|
||||
:Super(ObjectInitializer)
|
||||
{
|
||||
bUsingCopyPoseFromMesh = true;
|
||||
bUseMultiThreadedAnimationUpdate = false;
|
||||
}
|
||||
|
||||
FAnimInstanceProxy* UVrmAnimInstanceRetargetFromMannequin::CreateAnimInstanceProxy() {
|
||||
myProxy = new FVrmAnimInstanceRetargetFromMannequinProxy(this);
|
||||
myProxy->bIgnoreVRMSwingBone = bIgnoreVRMSwingBone;
|
||||
myProxy->bIgnoreWindDirectionalSource = bIgnoreWindDirectionalSource;
|
||||
return myProxy;
|
||||
}
|
||||
|
||||
|
||||
void UVrmAnimInstanceRetargetFromMannequin::NativeInitializeAnimation() {
|
||||
for (int i = 0; i < FMath::Min(InitialMorphValue.Num(), InitialMorphName.Num()); ++i) {
|
||||
SetMorphTarget(InitialMorphName[i], InitialMorphValue[i]);
|
||||
}
|
||||
}
|
||||
void UVrmAnimInstanceRetargetFromMannequin::NativeUpdateAnimation(float DeltaSeconds) {
|
||||
}
|
||||
void UVrmAnimInstanceRetargetFromMannequin::NativePostEvaluateAnimation() {
|
||||
}
|
||||
|
||||
void UVrmAnimInstanceRetargetFromMannequin::NativeUninitializeAnimation() {
|
||||
if (GetOwningComponent()) {
|
||||
GetOwningComponent()->ClearMorphTargets();
|
||||
}
|
||||
|
||||
if (!SrcSkeletalMeshComponent && bUseAttachedParent)
|
||||
{
|
||||
USkeletalMeshComponent* TargetMesh = GetOwningComponent();
|
||||
|
||||
// Walk up the attachment chain until we find a skeletal mesh component
|
||||
USkeletalMeshComponent* ParentMeshComponent = nullptr;
|
||||
for (USceneComponent* AttachParentComp = TargetMesh->GetAttachParent(); AttachParentComp != nullptr; AttachParentComp = AttachParentComp->GetAttachParent())
|
||||
{
|
||||
ParentMeshComponent = Cast<USkeletalMeshComponent>(AttachParentComp);
|
||||
if (ParentMeshComponent)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ParentMeshComponent == nullptr) {
|
||||
AActor *targetActor = nullptr;
|
||||
AActor *myActor = TargetMesh->GetOwner();
|
||||
for (USceneComponent* AttachParentComp = TargetMesh->GetAttachParent(); AttachParentComp != nullptr; AttachParentComp = AttachParentComp->GetAttachParent()) {
|
||||
targetActor = AttachParentComp->GetOwner();
|
||||
if (targetActor != myActor) {
|
||||
break;
|
||||
}
|
||||
targetActor = nullptr;
|
||||
}
|
||||
if (targetActor) {
|
||||
TArray<USkeletalMeshComponent*> c;
|
||||
targetActor->GetComponents<USkeletalMeshComponent>(c);
|
||||
if (c.IsValidIndex(0)) {
|
||||
ParentMeshComponent = c[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ParentMeshComponent)
|
||||
{
|
||||
SrcSkeletalMeshComponent = ParentMeshComponent;
|
||||
}
|
||||
}
|
||||
if (SrcAsSkinnedMeshComponent == nullptr) {
|
||||
SrcAsSkinnedMeshComponent = SrcSkeletalMeshComponent;
|
||||
}
|
||||
}
|
||||
void UVrmAnimInstanceRetargetFromMannequin::NativeBeginPlay() {
|
||||
if (GetOwningComponent()) {
|
||||
GetOwningComponent()->ClearMorphTargets();
|
||||
}
|
||||
}
|
||||
|
||||
void UVrmAnimInstanceRetargetFromMannequin::PreUpdateAnimation(float DeltaSeconds) {
|
||||
Super::PreUpdateAnimation(DeltaSeconds);
|
||||
}
|
||||
|
||||
void UVrmAnimInstanceRetargetFromMannequin::SetRetargetData(bool bUseRetargeter, UIKRetargeter* IKRetargeter) {
|
||||
myProxy->Retargeter = IKRetargeter;
|
||||
myProxy->bUseRetargeter = bUseRetargeter;
|
||||
}
|
||||
|
||||
|
||||
void UVrmAnimInstanceRetargetFromMannequin::SetVrmAssetList(UVrmAssetListObject *dstAssetList) {
|
||||
DstVrmAssetList = dstAssetList;
|
||||
}
|
||||
|
||||
void UVrmAnimInstanceRetargetFromMannequin::SetSkeletalMeshCopyDataForCustomSpring(UVrmMetaObject *dstMetaForCustomSpring) {
|
||||
DstVrmMetaForCustomSpring = dstMetaForCustomSpring;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UVrmAnimInstanceRetargetFromMannequin::SetVrmSpringBoneParam(float gravityScale, FVector gravityAdd, float stiffnessScale, float stiffnessAdd, float randomWindRange) {
|
||||
if (myProxy == nullptr) return;
|
||||
auto a = myProxy->Node_SpringBone.Get();
|
||||
if (a == nullptr) return;
|
||||
|
||||
a->gravityScale = gravityScale;
|
||||
a->gravityAdd = gravityAdd;
|
||||
a->stiffnessScale = stiffnessScale;
|
||||
a->stiffnessAdd = stiffnessAdd;
|
||||
a->randomWindRange = randomWindRange;
|
||||
}
|
||||
|
||||
void UVrmAnimInstanceRetargetFromMannequin::SetVrmSpringBoneBool(bool bIgnoreVrmSpringBone, bool bIgnorePhysicsCollision, bool bIgnoreVRMCollision, bool bIgnoreWind) {
|
||||
if (myProxy == nullptr) return;
|
||||
auto a = myProxy->Node_SpringBone.Get();
|
||||
if (a == nullptr) return;
|
||||
|
||||
this->bIgnoreVRMSwingBone = bIgnoreVrmSpringBone;
|
||||
myProxy->bIgnoreVRMSwingBone = bIgnoreVrmSpringBone;
|
||||
a->bIgnorePhysicsCollision = bIgnorePhysicsCollision;
|
||||
a->bIgnoreVRMCollision = bIgnoreVRMCollision;
|
||||
a->bIgnoreWindDirectionalSource = bIgnoreWind;
|
||||
}
|
||||
|
||||
void UVrmAnimInstanceRetargetFromMannequin::SetVrmSpringBoneIgnoreWingBone(const TArray<FName> &boneNameList) {
|
||||
if (myProxy == nullptr) return;
|
||||
auto a = myProxy->Node_SpringBone.Get();
|
||||
if (a == nullptr) return;
|
||||
|
||||
a->NoWindBoneNameList = boneNameList;
|
||||
}
|
||||
|
||||
|
||||
#endif // 5.3
|
||||
@@ -0,0 +1,26 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "VrmAnimInstanceTemplate.h"
|
||||
#include "Animation/AnimNodeBase.h"
|
||||
|
||||
FVrmAnimInstanceTemplateProxy::FVrmAnimInstanceTemplateProxy()
|
||||
{
|
||||
}
|
||||
|
||||
FVrmAnimInstanceTemplateProxy::FVrmAnimInstanceTemplateProxy(UAnimInstance* InAnimInstance)
|
||||
: FAnimInstanceProxy(InAnimInstance)
|
||||
{
|
||||
}
|
||||
|
||||
/////
|
||||
|
||||
UVrmAnimInstanceTemplate::UVrmAnimInstanceTemplate(const FObjectInitializer& ObjectInitializer)
|
||||
:Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
FAnimInstanceProxy* UVrmAnimInstanceTemplate::CreateAnimInstanceProxy() {
|
||||
myProxy = new FVrmAnimInstanceTemplateProxy(this);
|
||||
return myProxy;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "VrmAssetListObject.h"
|
||||
#include "EditorFramework/AssetImportData.h"
|
||||
#include "UObject/AssetRegistryTagsContext.h"
|
||||
//#include "LoaderBPFunctionLibrary.h"
|
||||
|
||||
|
||||
|
||||
UVrmAssetListObject::UVrmAssetListObject(const FObjectInitializer& ObjectInitializer)
|
||||
:Super(ObjectInitializer)
|
||||
{
|
||||
Package = GetTransientPackage();
|
||||
|
||||
//Result = new FReturnedData();
|
||||
}
|
||||
|
||||
|
||||
void UVrmAssetListObject::CopyMember(UVrmAssetListObject *dst) const {
|
||||
dst->bAssetSave = bAssetSave;
|
||||
dst->bSkipMorphTarget = bSkipMorphTarget;
|
||||
|
||||
dst->MtoonLitSet = MtoonLitSet;
|
||||
dst->MtoonUnlitSet = MtoonUnlitSet;
|
||||
dst->SSSSet = SSSSet;
|
||||
dst->SSSProfileSet = SSSProfileSet;
|
||||
dst->UnlitSet = UnlitSet;
|
||||
dst->GLTFSet = GLTFSet;
|
||||
dst->UEFNUnlitSet = UEFNUnlitSet;
|
||||
dst->UEFNLitSet = UEFNLitSet;
|
||||
dst->UEFNSSSProfileSet = UEFNSSSProfileSet;
|
||||
dst->CustomSet = CustomSet;
|
||||
|
||||
|
||||
dst->BaseMToonLitOpaqueMaterial = BaseMToonLitOpaqueMaterial;
|
||||
dst->BaseMToonLitTranslucentMaterial = BaseMToonLitTranslucentMaterial;
|
||||
dst->OptMToonLitOpaqueMaterial = OptMToonLitOpaqueMaterial;
|
||||
dst->OptMToonLitOpaqueTwoSidedMaterial = OptMToonLitOpaqueTwoSidedMaterial;
|
||||
dst->OptMToonLitTranslucentMaterial = OptMToonLitTranslucentMaterial;
|
||||
dst->OptMToonLitTranslucentTwoSidedMaterial = OptMToonLitTranslucentTwoSidedMaterial;
|
||||
|
||||
dst->BaseMToonUnlitOpaqueMaterial = BaseMToonUnlitOpaqueMaterial;
|
||||
dst->BaseMToonUnlitTranslucentMaterial = BaseMToonUnlitTranslucentMaterial;
|
||||
dst->OptMToonUnlitOpaqueMaterial = OptMToonUnlitOpaqueMaterial;
|
||||
dst->OptMToonUnlitOpaqueTwoSidedMaterial = OptMToonUnlitOpaqueTwoSidedMaterial;
|
||||
dst->OptMToonUnlitTranslucentMaterial = OptMToonUnlitTranslucentMaterial;
|
||||
dst->OptMToonUnlitTranslucentTwoSidedMaterial = OptMToonUnlitTranslucentTwoSidedMaterial;
|
||||
|
||||
dst->OptMToonOutlineMaterial = OptMToonOutlineMaterial;
|
||||
|
||||
dst->BaseUnlitOpaqueMaterial = BaseUnlitOpaqueMaterial;
|
||||
dst->BaseUnlitTranslucentMaterial = BaseUnlitTranslucentMaterial;
|
||||
dst->BasePBROpaqueMaterial = BasePBROpaqueMaterial;
|
||||
|
||||
|
||||
dst->BaseSkeletalMesh = BaseSkeletalMesh;
|
||||
dst->VrmMetaObject = VrmMetaObject;
|
||||
dst->VrmLicenseObject = VrmLicenseObject;
|
||||
dst->Vrm1LicenseObject = Vrm1LicenseObject;
|
||||
dst->SkeletalMesh = SkeletalMesh;
|
||||
dst->Textures = Textures;
|
||||
dst->Materials = Materials;
|
||||
dst->HumanoidRig = HumanoidRig;
|
||||
dst->Package = Package;
|
||||
dst->FileFullPathName = FileFullPathName;
|
||||
dst->OrigFileName = OrigFileName;
|
||||
dst->BaseFileName = BaseFileName;
|
||||
dst->HumanoidSkeletalMesh = HumanoidSkeletalMesh;
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
#if UE_VERSION_OLDER_THAN(5,4,0)
|
||||
void UVrmAssetListObject::GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const
|
||||
{
|
||||
if (AssetImportData)
|
||||
{
|
||||
OutTags.Add(FAssetRegistryTag(SourceFileTagName(), AssetImportData->GetSourceData().ToJson(), FAssetRegistryTag::TT_Hidden));
|
||||
|
||||
OutTags.Add(FAssetRegistryTag("VRM4U", SourceFileTagName().ToString(), FAssetRegistryTag::TT_Hidden));
|
||||
}
|
||||
Super::GetAssetRegistryTags(OutTags);
|
||||
}
|
||||
#else
|
||||
void UVrmAssetListObject::GetAssetRegistryTags(FAssetRegistryTagsContext Context) const
|
||||
{
|
||||
if (AssetImportData)
|
||||
{
|
||||
Context.AddTag(FAssetRegistryTag(SourceFileTagName(), AssetImportData->GetSourceData().ToJson(), FAssetRegistryTag::TT_Hidden));
|
||||
|
||||
Context.AddTag(FAssetRegistryTag("VRM4U", SourceFileTagName().ToString(), FAssetRegistryTag::TT_Hidden));
|
||||
}
|
||||
Super::GetAssetRegistryTags(Context);
|
||||
}
|
||||
#endif
|
||||
|
||||
void UVrmAssetListObject::WaitUntilAsyncPropertyReleased() const {
|
||||
if (IsValid(SkeletalMesh) == false) {
|
||||
return;
|
||||
}
|
||||
//SkeletalMesh->WaitUntilAsyncPropertyReleased(AsyncProperties);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "VrmAssetUserData.h"
|
||||
|
||||
#include "VrmAssetListObject.h"
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmCameraCheckComponent.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
#include "Editor.h"
|
||||
#include "EditorViewportClient.h"
|
||||
#include "LevelEditorViewport.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
UVrmCameraCheckComponent::UVrmCameraCheckComponent(const FObjectInitializer& ObjectInitializer)
|
||||
:Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
void UVrmCameraCheckComponent::OnRegister() {
|
||||
Super::OnRegister();
|
||||
SetCameraCheck(true);
|
||||
}
|
||||
void UVrmCameraCheckComponent::OnUnregister() {
|
||||
SetCameraCheck(false);
|
||||
Super::OnUnregister();
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
void UVrmCameraCheckComponent::OnCameraTransformChanged(const FVector&, const FRotator&, ELevelViewportType, int32) {
|
||||
OnCameraMove.Broadcast();
|
||||
}
|
||||
#endif
|
||||
|
||||
void UVrmCameraCheckComponent::SetCameraCheck(bool bCheckOn) {
|
||||
#if WITH_EDITOR
|
||||
if (bCheckOn) {
|
||||
if (handle.IsValid()) {
|
||||
FEditorDelegates::OnEditorCameraMoved.Remove(handle);
|
||||
}
|
||||
handle = FEditorDelegates::OnEditorCameraMoved.AddUObject(this, &UVrmCameraCheckComponent::OnCameraTransformChanged);
|
||||
} else {
|
||||
if (handle.IsValid()) {
|
||||
FEditorDelegates::OnEditorCameraMoved.Remove(handle);
|
||||
handle.Reset();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmCineCameraActor.h"
|
||||
#include "VrmCineCameraComponent.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
AVrmCineCameraActor::AVrmCineCameraActor(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer
|
||||
.SetDefaultSubobjectClass<UVrmCineCameraComponent>(TEXT("CameraComponent"))
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
UVrmCineCameraComponent* AVrmCineCameraActor::GetVrmCineCameraComponent() const {
|
||||
return Cast<UVrmCineCameraComponent>(GetCineCameraComponent());
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmCineCameraComponent.h"
|
||||
#include "VrmDrawFrustumComponent.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
void UVrmCineCameraComponent::GetCameraView(float DeltaTime, FMinimalViewInfo& DesiredView) {
|
||||
Super::GetCameraView(DeltaTime, DesiredView);
|
||||
DesiredView.OffCenterProjectionOffset = OffCenterProjectionOffset;
|
||||
}
|
||||
|
||||
void UVrmCineCameraComponent::OnRegister()
|
||||
{
|
||||
#if WITH_EDITORONLY_DATA
|
||||
AActor* MyOwner = GetOwner();
|
||||
if ((MyOwner != nullptr) && !IsRunningCommandlet())
|
||||
{
|
||||
if (DrawFrustum == nullptr)
|
||||
{
|
||||
DrawFrustum = NewObject<UVrmDrawFrustumComponent>(MyOwner, NAME_None, RF_Transactional | RF_TextExportTransient);
|
||||
DrawFrustum->SetupAttachment(this);
|
||||
DrawFrustum->CreationMethod = CreationMethod;
|
||||
DrawFrustum->RegisterComponentWithWorld(GetWorld());
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,21,0)
|
||||
#else
|
||||
DrawFrustum->SetIsVisualizationComponent(true);
|
||||
#endif
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
#else
|
||||
DrawFrustum->bFrustumEnabled = bDrawFrustumAllowed;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
RefreshVisualRepresentation();
|
||||
#endif // WITH_EDITORONLY_DATA
|
||||
|
||||
Super::OnRegister();
|
||||
}
|
||||
|
||||
#if WITH_EDITORONLY_DATA
|
||||
void UVrmCineCameraComponent::RefreshVisualRepresentation()
|
||||
{
|
||||
if (DrawFrustum != nullptr)
|
||||
{
|
||||
UVrmDrawFrustumComponent* v = Cast< UVrmDrawFrustumComponent>(DrawFrustum);
|
||||
v->OffCenterProjectionOffset = OffCenterProjectionOffset;
|
||||
}
|
||||
Super::RefreshVisualRepresentation();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmCustomStruct.h"
|
||||
|
||||
#include "VRM4U.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
//#include "ISettingsModule.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
/*=============================================================================
|
||||
DrawFrsutumComponent.cpp: UDrawFrsutumComponent implementation.
|
||||
=============================================================================*/
|
||||
|
||||
#include "VrmDrawFrustumComponent.h"
|
||||
#include "PrimitiveViewRelevance.h"
|
||||
#include "PrimitiveSceneProxy.h"
|
||||
#include "Engine/CollisionProfile.h"
|
||||
#include "SceneManagement.h"
|
||||
#include "SceneView.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
|
||||
/** Represents a draw frustum to the scene manager. */
|
||||
class FVrmDrawFrustumSceneProxy final : public FPrimitiveSceneProxy
|
||||
{
|
||||
public:
|
||||
SIZE_T GetTypeHash() const override
|
||||
{
|
||||
static size_t UniquePointer;
|
||||
return reinterpret_cast<size_t>(&UniquePointer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization constructor.
|
||||
* @param InComponent - game component to draw in the scene
|
||||
*/
|
||||
FVrmDrawFrustumSceneProxy(const UVrmDrawFrustumComponent* InComponent)
|
||||
: FPrimitiveSceneProxy(InComponent)
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
#else
|
||||
, bFrustumEnabled(InComponent->bFrustumEnabled)
|
||||
#endif
|
||||
, FrustumColor(InComponent->FrustumColor)
|
||||
, FrustumAngle(InComponent->FrustumAngle)
|
||||
, FrustumAspectRatio(InComponent->FrustumAspectRatio)
|
||||
, FrustumStartDist(InComponent->FrustumStartDist)
|
||||
, FrustumEndDist(InComponent->FrustumEndDist)
|
||||
, OffCenterProjectionOffset(InComponent->OffCenterProjectionOffset)
|
||||
{
|
||||
bWillEverBeLit = false;
|
||||
}
|
||||
|
||||
// FPrimitiveSceneProxy interface.
|
||||
|
||||
virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
|
||||
{
|
||||
QUICK_SCOPE_CYCLE_COUNTER( STAT_DrawFrustumSceneProxy_DrawDynamicElements );
|
||||
|
||||
FVector Direction(1,0,0);
|
||||
FVector LeftVector(0,1,0);
|
||||
FVector UpVector(0,0,1);
|
||||
|
||||
FVector Verts[8];
|
||||
|
||||
// FOVAngle controls the horizontal angle.
|
||||
const float HozHalfAngleInRadians = FMath::DegreesToRadians(FrustumAngle * 0.5f);
|
||||
|
||||
float HozLength = 0.0f;
|
||||
float VertLength = 0.0f;
|
||||
|
||||
if (FrustumAngle > 0.0f)
|
||||
{
|
||||
HozLength = FrustumStartDist * FMath::Tan(HozHalfAngleInRadians);
|
||||
VertLength = HozLength / FrustumAspectRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float OrthoWidth = (FrustumAngle == 0.0f) ? 1000.0f : -FrustumAngle;
|
||||
HozLength = OrthoWidth * 0.5f;
|
||||
VertLength = HozLength / FrustumAspectRatio;
|
||||
}
|
||||
|
||||
FVector Offset(0, OffCenterProjectionOffset.X, OffCenterProjectionOffset.Y);
|
||||
|
||||
// near plane verts
|
||||
Verts[0] = (Direction * FrustumStartDist) + (UpVector * VertLength) + (LeftVector * HozLength) + (Offset * VertLength);
|
||||
Verts[1] = (Direction * FrustumStartDist) + (UpVector * VertLength) - (LeftVector * HozLength) + (Offset * VertLength);
|
||||
Verts[2] = (Direction * FrustumStartDist) - (UpVector * VertLength) - (LeftVector * HozLength) + (Offset * VertLength);
|
||||
Verts[3] = (Direction * FrustumStartDist) - (UpVector * VertLength) + (LeftVector * HozLength) + (Offset * VertLength);
|
||||
|
||||
if (FrustumAngle > 0.0f)
|
||||
{
|
||||
HozLength = FrustumEndDist * FMath::Tan(HozHalfAngleInRadians);
|
||||
VertLength = HozLength / FrustumAspectRatio;
|
||||
}
|
||||
|
||||
// far plane verts
|
||||
Verts[4] = (Direction * FrustumEndDist) + (UpVector * VertLength) + (LeftVector * HozLength) + (Offset * VertLength);
|
||||
Verts[5] = (Direction * FrustumEndDist) + (UpVector * VertLength) - (LeftVector * HozLength) + (Offset * VertLength);
|
||||
Verts[6] = (Direction * FrustumEndDist) - (UpVector * VertLength) - (LeftVector * HozLength) + (Offset * VertLength);
|
||||
Verts[7] = (Direction * FrustumEndDist) - (UpVector * VertLength) + (LeftVector * HozLength) + (Offset * VertLength);
|
||||
|
||||
for (int32 X = 0; X < 8; ++X)
|
||||
{
|
||||
Verts[X] = GetLocalToWorld().TransformPosition(Verts[X]);
|
||||
}
|
||||
|
||||
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
|
||||
{
|
||||
if (VisibilityMap & (1 << ViewIndex))
|
||||
{
|
||||
FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
|
||||
const FSceneView* View = Views[ViewIndex];
|
||||
|
||||
const uint8 DepthPriorityGroup = GetDepthPriorityGroup(View);
|
||||
PDI->DrawLine( Verts[0], Verts[1], FrustumColor, DepthPriorityGroup );
|
||||
PDI->DrawLine( Verts[1], Verts[2], FrustumColor, DepthPriorityGroup );
|
||||
PDI->DrawLine( Verts[2], Verts[3], FrustumColor, DepthPriorityGroup );
|
||||
PDI->DrawLine( Verts[3], Verts[0], FrustumColor, DepthPriorityGroup );
|
||||
|
||||
PDI->DrawLine( Verts[4], Verts[5], FrustumColor, DepthPriorityGroup );
|
||||
PDI->DrawLine( Verts[5], Verts[6], FrustumColor, DepthPriorityGroup );
|
||||
PDI->DrawLine( Verts[6], Verts[7], FrustumColor, DepthPriorityGroup );
|
||||
PDI->DrawLine( Verts[7], Verts[4], FrustumColor, DepthPriorityGroup );
|
||||
|
||||
PDI->DrawLine( Verts[0], Verts[4], FrustumColor, DepthPriorityGroup );
|
||||
PDI->DrawLine( Verts[1], Verts[5], FrustumColor, DepthPriorityGroup );
|
||||
PDI->DrawLine( Verts[2], Verts[6], FrustumColor, DepthPriorityGroup );
|
||||
PDI->DrawLine( Verts[3], Verts[7], FrustumColor, DepthPriorityGroup );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override
|
||||
{
|
||||
FPrimitiveViewRelevance Result;
|
||||
Result.bDrawRelevance = IsShown(View) && View->Family->EngineShowFlags.CameraFrustums && bFrustumEnabled;
|
||||
Result.bDynamicRelevance = true;
|
||||
Result.bShadowRelevance = IsShadowCast(View);
|
||||
Result.bEditorPrimitiveRelevance = UseEditorCompositing(View);
|
||||
return Result;
|
||||
}
|
||||
|
||||
virtual uint32 GetMemoryFootprint( void ) const override { return( sizeof( *this ) + GetAllocatedSize() ); }
|
||||
uint32 GetAllocatedSize( void ) const { return( FPrimitiveSceneProxy::GetAllocatedSize() ); }
|
||||
|
||||
#if RHI_RAYTRACING
|
||||
virtual ERayTracingPrimitiveFlags GetCachedRayTracingInstance(FRayTracingInstance& OutRayTracingInstance) override
|
||||
{
|
||||
return ERayTracingPrimitiveFlags::UnsupportedProxyType;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool bFrustumEnabled;
|
||||
FColor FrustumColor;
|
||||
float FrustumAngle;
|
||||
float FrustumAspectRatio;
|
||||
float FrustumStartDist;
|
||||
float FrustumEndDist;
|
||||
|
||||
FVector2D OffCenterProjectionOffset;
|
||||
};
|
||||
|
||||
UVrmDrawFrustumComponent::UVrmDrawFrustumComponent(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
FPrimitiveSceneProxy* UVrmDrawFrustumComponent::CreateSceneProxy()
|
||||
{
|
||||
return new FVrmDrawFrustumSceneProxy(this);
|
||||
}
|
||||
|
||||
|
||||
FBoxSphereBounds UVrmDrawFrustumComponent::CalcBounds(const FTransform& LocalToWorld) const
|
||||
{
|
||||
return FBoxSphereBounds( LocalToWorld.TransformPosition(FVector::ZeroVector), FVector(FrustumEndDist), FrustumEndDist );
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
|
||||
// ApplicationLifecycleComponent.cpp: Component to handle receiving notifications from the OS about application state (activated, suspended, termination, etc)
|
||||
|
||||
#include "VrmDropFiles.h"
|
||||
#include "Misc/CoreDelegates.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#include "Windows/AllowWindowsPlatformTypes.h"
|
||||
#include "commdlg.h"
|
||||
#include "Windows/HideWindowsPlatformTypes.h"
|
||||
#endif
|
||||
|
||||
UVrmDropFilesComponent::FStaticOnDropFiles UVrmDropFilesComponent::StaticOnDropFilesDelegate;
|
||||
UVrmDropFilesComponent *UVrmDropFilesComponent::s_LatestActiveComponent = nullptr;
|
||||
|
||||
|
||||
UVrmDropFilesComponent::UVrmDropFilesComponent(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
void UVrmDropFilesComponent::OnRegister()
|
||||
{
|
||||
Super::OnRegister();
|
||||
|
||||
/*
|
||||
FCoreDelegates::ApplicationWillDeactivateDelegate.AddUObject(this, &UApplicationLifecycleComponent::ApplicationWillDeactivateDelegate_Handler);
|
||||
FCoreDelegates::ApplicationHasReactivatedDelegate.AddUObject(this, &UApplicationLifecycleComponent::ApplicationHasReactivatedDelegate_Handler);
|
||||
FCoreDelegates::ApplicationWillEnterBackgroundDelegate.AddUObject(this, &UApplicationLifecycleComponent::ApplicationWillEnterBackgroundDelegate_Handler);
|
||||
FCoreDelegates::ApplicationHasEnteredForegroundDelegate.AddUObject(this, &UApplicationLifecycleComponent::ApplicationHasEnteredForegroundDelegate_Handler);
|
||||
FCoreDelegates::ApplicationWillTerminateDelegate.AddUObject(this, &UApplicationLifecycleComponent::ApplicationWillTerminateDelegate_Handler);
|
||||
FCoreDelegates::ApplicationShouldUnloadResourcesDelegate.AddUObject(this, &UApplicationLifecycleComponent::ApplicationShouldUnloadResourcesDelegate_Handler);
|
||||
FCoreDelegates::ApplicationReceivedStartupArgumentsDelegate.AddUObject(this, &UApplicationLifecycleComponent::ApplicationReceivedStartupArgumentsDelegate_Handler);
|
||||
|
||||
FCoreDelegates::OnTemperatureChange.AddUObject(this, &UApplicationLifecycleComponent::OnTemperatureChangeDelegate_Handler);
|
||||
FCoreDelegates::OnLowPowerMode.AddUObject(this, &UApplicationLifecycleComponent::OnLowPowerModeDelegate_Handler);
|
||||
*/
|
||||
StaticOnDropFilesDelegate.AddUObject(this, &UVrmDropFilesComponent::OnDropFilesDelegate_Handler);
|
||||
|
||||
s_LatestActiveComponent = this;
|
||||
}
|
||||
|
||||
void UVrmDropFilesComponent::OnUnregister()
|
||||
{
|
||||
Super::OnUnregister();
|
||||
|
||||
/*
|
||||
FCoreDelegates::ApplicationWillDeactivateDelegate.RemoveAll(this);
|
||||
FCoreDelegates::ApplicationHasReactivatedDelegate.RemoveAll(this);
|
||||
FCoreDelegates::ApplicationWillEnterBackgroundDelegate.RemoveAll(this);
|
||||
FCoreDelegates::ApplicationHasEnteredForegroundDelegate.RemoveAll(this);
|
||||
FCoreDelegates::ApplicationWillTerminateDelegate.RemoveAll(this);
|
||||
FCoreDelegates::ApplicationShouldUnloadResourcesDelegate.RemoveAll(this);
|
||||
FCoreDelegates::ApplicationReceivedStartupArgumentsDelegate.RemoveAll(this);
|
||||
FCoreDelegates::OnTemperatureChange.RemoveAll(this);
|
||||
FCoreDelegates::OnLowPowerMode.RemoveAll(this);
|
||||
*/
|
||||
|
||||
StaticOnDropFilesDelegate.RemoveAll(this);
|
||||
|
||||
if (s_LatestActiveComponent == this) {
|
||||
s_LatestActiveComponent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool UVrmDropFilesComponent::VRMGetOpenFileName(FString &FileName) {
|
||||
FileName = "";
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
OPENFILENAME ofn = {};
|
||||
TCHAR filename[MAX_PATH] = {};
|
||||
|
||||
filename[0] = '\0';
|
||||
memset(&ofn, 0, sizeof(OPENFILENAME));
|
||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||
//ofn.hwndOwner = hWnd;
|
||||
ofn.lpstrFilter =
|
||||
TEXT("VRM file(*.vrm)\0*.vrm\0")
|
||||
TEXT("all file(*.*)\0*.*\0\0");
|
||||
ofn.lpstrFile = filename;
|
||||
ofn.nMaxFile = sizeof(filename);
|
||||
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
//ofn.lpstrDefExt = TEXT("*");
|
||||
ofn.lpstrTitle = TEXT("Model");
|
||||
|
||||
if (GetOpenFileName(&ofn)) {
|
||||
FileName = filename;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
return false;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmEditorEventComponent.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
#include "Editor.h"
|
||||
#include "EditorViewportClient.h"
|
||||
#include "LevelEditorViewport.h"
|
||||
#include "Engine/Selection.h"
|
||||
|
||||
//#include "MovieSceneTrackEditor.h"
|
||||
#if UE_VERSION_OLDER_THAN(4,26,0)
|
||||
#elif UE_VERSION_OLDER_THAN(4,27,0)
|
||||
#include "ILevelSequenceEditorToolkit.h"
|
||||
#include "LevelSequenceEditor/Private/LevelSequenceEditorBlueprintLibrary.h"
|
||||
#elif UE_VERSION_OLDER_THAN(5,0,0)
|
||||
#include "ILevelSequenceEditorToolkit.h"
|
||||
#include "LevelSequenceEditor/Public/LevelSequenceEditorBlueprintLibrary.h"
|
||||
#elif UE_VERSION_OLDER_THAN(5,3,0)
|
||||
#include "ILevelSequenceEditorToolkit.h"
|
||||
#include "LevelSequenceEditor/Public/LevelSequenceEditorBlueprintLibrary.h"
|
||||
#else
|
||||
#include "ILevelSequenceEditorToolkit.h"
|
||||
#include "LevelSequenceEditorBlueprintLibrary.h"
|
||||
#endif
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,5,0)
|
||||
#else
|
||||
#include "MovieSceneSequencePlayer.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "LevelSequence.h"
|
||||
#include "ISequencer.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
UVrmEditorEventComponent::UVrmEditorEventComponent(const FObjectInitializer& ObjectInitializer)
|
||||
:Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
void UVrmEditorEventComponent::OnRegister() {
|
||||
Super::OnRegister();
|
||||
}
|
||||
void UVrmEditorEventComponent::OnUnregister() {
|
||||
Super::OnUnregister();
|
||||
}
|
||||
|
||||
void UVrmEditorEventComponent::OnSelectionChangeFunc(UObject *obj) {
|
||||
#if WITH_EDITOR
|
||||
if (GEditor == nullptr) return;
|
||||
bool bFound = false;
|
||||
USelection* Selection = Cast<USelection>(obj);
|
||||
if (Selection == GEditor->GetSelectedComponents() || Selection == GEditor->GetSelectedActors()){
|
||||
for (int32 Idx = 0; Idx < Selection->Num(); Idx++)
|
||||
{
|
||||
const auto *a = Selection->GetSelectedObject(Idx);
|
||||
if (a == this->GetOwner()) {
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bFound && Selection->Num() == 1) {
|
||||
OnSelectionChange.Broadcast(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void UVrmEditorEventComponent::OnSelectionObjectFunc(UObject *obj) {
|
||||
#if WITH_EDITOR
|
||||
if (GEditor == nullptr) return;
|
||||
bool bFound = false;
|
||||
USelection* Selection = Cast<USelection>(obj);
|
||||
if (Selection == GEditor->GetSelectedComponents() || Selection == GEditor->GetSelectedActors()) {
|
||||
|
||||
for (int32 Idx = 0; Idx < Selection->Num(); Idx++)
|
||||
{
|
||||
if (Selection->GetSelectedObject(Idx) == this->GetOwner()) {
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bFound) {
|
||||
OnSelectionObject.Broadcast(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void UVrmEditorEventComponent::SetSelectCheck(bool bCheckOn) {
|
||||
#if WITH_EDITOR
|
||||
USelection::SelectionChangedEvent.AddUObject(this, &UVrmEditorEventComponent::OnSelectionChangeFunc);
|
||||
USelection::SelectObjectEvent.AddUObject(this, &UVrmEditorEventComponent::OnSelectionObjectFunc);
|
||||
//SelectObjectEvent
|
||||
if (bCheckOn) {
|
||||
//GEditor->OnEndCameraMovement.Assign(OnCameraMove)
|
||||
//if (GEditor->GetActiveViewport()) {
|
||||
// FEditorViewportClient* ViewportClient = StaticCast<FEditorViewportClient*>(GEditor->GetActiveViewport()->GetClient());
|
||||
// if (ViewportClient) {
|
||||
// ViewportClient->SetActorLock(this->GetOwner());
|
||||
// }
|
||||
//}
|
||||
//GCurrentLevelEditingViewportClient->SetActorLock(this->GetOwner());
|
||||
//GEditor->OnEndCameraMovement().AddUObject(this, &UVrmCameraCheckComponent::OnCameraTransformChanged);
|
||||
//GEditor->OnBeginCameraMovement().AddUObject(this, &UVrmCameraCheckComponent::OnCameraTransformChanged);
|
||||
//handle = FEditorDelegates::OnEditorCameraMoved.AddUObject(this, &UVrmCameraCheckComponent::OnCameraTransformChanged);
|
||||
} else {
|
||||
//if (handle.IsValid()) {
|
||||
//FEditorDelegates::OnEditorCameraMoved.Remove(handle);
|
||||
// }
|
||||
//GEditor->OnEndCameraMovement().Remove
|
||||
}
|
||||
//FOnEndTransformCamera& () { return OnEndCameraTransformEvent; }
|
||||
#endif
|
||||
}
|
||||
|
||||
void UVrmEditorEventComponent::OnGlobalTimeChangeFunc() {
|
||||
#if WITH_EDITOR
|
||||
#if UE_VERSION_OLDER_THAN(4,26,0)
|
||||
#elif UE_VERSION_OLDER_THAN(5,5,0)
|
||||
|
||||
int32 t = ULevelSequenceEditorBlueprintLibrary::GetCurrentTime();
|
||||
OnGlobalTimeChange.Broadcast((float)t);
|
||||
#else
|
||||
//int32 t = ULevelSequenceEditorBlueprintLibrary::GetCurrentTime();
|
||||
auto mm = ULevelSequenceEditorBlueprintLibrary::GetGlobalPosition();
|
||||
int32 t = mm.Timecode.Frames;
|
||||
OnGlobalTimeChange.Broadcast((float)t);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void UVrmEditorEventComponent::SetGlobalTimeCheck(bool bCheckOn) {
|
||||
#if WITH_EDITOR
|
||||
#if UE_VERSION_OLDER_THAN(4,26,0)
|
||||
#else
|
||||
{
|
||||
if (GEditor == nullptr) return;
|
||||
auto *LevelSeq = ULevelSequenceEditorBlueprintLibrary::GetCurrentLevelSequence();
|
||||
if (LevelSeq == nullptr) return;
|
||||
|
||||
IAssetEditorInstance* AssetEditor = GEditor->GetEditorSubsystem<UAssetEditorSubsystem>()->FindEditorForAsset(LevelSeq, false);
|
||||
if (AssetEditor == nullptr) return;
|
||||
|
||||
ILevelSequenceEditorToolkit* LevelSequenceEditor = static_cast<ILevelSequenceEditorToolkit*>(AssetEditor);
|
||||
|
||||
if (LevelSequenceEditor == nullptr){
|
||||
return;
|
||||
}
|
||||
TWeakPtr<ISequencer> seq = LevelSequenceEditor->GetSequencer();
|
||||
|
||||
|
||||
|
||||
if (seq.IsValid()) {
|
||||
seq.Pin()->OnGlobalTimeChanged().AddUObject(this, &UVrmEditorEventComponent::OnGlobalTimeChangeFunc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ALevelSequenceActor* LevelSequenceActor = nullptr;
|
||||
for (ALevelSequenceActor* ExistingLevelSequenceActor : TActorRange<ALevelSequenceActor>(MeshActor->GetWorld()))
|
||||
{
|
||||
LevelSequenceActor = ExistingLevelSequenceActor;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
//auto *seq = ULevelSequenceEditorBlueprintLibrary::GetCurrentLevelSequence();
|
||||
//if (seq = nullptr) {
|
||||
//USelection::SelectionChangedEvent.AddUObject(this, &UVrmEditorEventComponent::OnSelectionChangeFunc);
|
||||
//USelection::SelectObjectEvent.AddUObject(this, &UVrmEditorEventComponent::OnSelectionObjectFunc);
|
||||
//}
|
||||
//seq->OnGlobalTimeChanged().AddRaw(this, &UVrmEditorEventComponent::OnGlobalTimeChangeFunc);
|
||||
//USelection::SelectionChangedEvent.AddUObject(this, &UVrmEditorEventComponent::OnSelectionChangeFunc);
|
||||
//USelection::SelectObjectEvent.AddUObject(this, &UVrmEditorEventComponent::OnSelectionObjectFunc);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UVrmEditorEventComponent::OnPIEEventFunc(EVRM4U_PIEEvent e) {
|
||||
#if WITH_EDITOR
|
||||
#if UE_VERSION_OLDER_THAN(4,26,0)
|
||||
#else
|
||||
OnPIEEvent.Broadcast(e);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void UVrmEditorEventComponent::OnBeginPIE(const bool bIsSimulating) {
|
||||
OnPIEEventFunc(EVRM4U_PIEEvent::BeginPIE);
|
||||
}
|
||||
void UVrmEditorEventComponent::OnEndPIE(const bool bIsSimulating) {
|
||||
OnPIEEventFunc(EVRM4U_PIEEvent::EndPIE);
|
||||
}
|
||||
|
||||
|
||||
void UVrmEditorEventComponent::SetPIEEventCheck(bool bCheckOn) {
|
||||
#if WITH_EDITOR
|
||||
#if UE_VERSION_OLDER_THAN(4,26,0)
|
||||
#else
|
||||
{
|
||||
FEditorDelegates::BeginPIE.AddUObject(this, &UVrmEditorEventComponent::OnBeginPIE);
|
||||
FEditorDelegates::EndPIE.AddUObject(this, &UVrmEditorEventComponent::OnEndPIE);
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmHMDTrackingComponent.h"
|
||||
|
||||
#if WITH_VRM4U_HMD_TRACKER
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "../Private/OculusHMDModule.h"
|
||||
#include "../Private/OculusHMD.h"
|
||||
#include "../Private/OculusHMD_Settings.h"
|
||||
|
||||
namespace VRM4ULocal {
|
||||
FORCEINLINE FQuat ToFQuat(const ovrpQuatf& InQuat)
|
||||
{
|
||||
return FQuat(-InQuat.z, InQuat.x, InQuat.y, -InQuat.w);
|
||||
}
|
||||
|
||||
/** Converts FQuat to ovrpQuatf */
|
||||
FORCEINLINE ovrpQuatf ToOvrpQuatf(const FQuat& InQuat)
|
||||
{
|
||||
return ovrpQuatf{ InQuat.Y, InQuat.Z, -InQuat.X, -InQuat.W };
|
||||
}
|
||||
|
||||
/** Converts vector from Oculus to Unreal */
|
||||
FORCEINLINE FVector ToFVector(const ovrpVector3f& InVec)
|
||||
{
|
||||
return FVector(-InVec.z, InVec.x, InVec.y);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
UVrmHMDTrackingComponent::UVrmHMDTrackingComponent(const FObjectInitializer& ObjectInitializer)
|
||||
:Super(ObjectInitializer)
|
||||
{
|
||||
//PrimaryComponentTick.TickGroup;
|
||||
PrimaryComponentTick.bStartWithTickEnabled = true;
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
bAutoActivate = true;
|
||||
}
|
||||
|
||||
void UVrmHMDTrackingComponent::OnRegister() {
|
||||
Super::OnRegister();
|
||||
}
|
||||
void UVrmHMDTrackingComponent::OnUnregister() {
|
||||
Super::OnUnregister();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UVrmHMDTrackingComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) {
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
#if WITH_VRM4U_HMD_TRACKER
|
||||
bEnableLeft = false;
|
||||
bEnableRight = false;
|
||||
bEnableHead = false;
|
||||
|
||||
float WoldToMetersScale = 100.f;
|
||||
{
|
||||
OculusHMD::FOculusHMD* OculusHMD = (OculusHMD::FOculusHMD*)(GEngine->XRSystem.Get());
|
||||
if (!OculusHMD)
|
||||
return;
|
||||
|
||||
OculusHMD::FSettings* s = OculusHMD->GetSettings();
|
||||
|
||||
ovrpPoseStatef PoseState;
|
||||
OculusHMD::FPose Pose;
|
||||
|
||||
WoldToMetersScale = OculusHMD->GetWorldToMetersScale();
|
||||
|
||||
if (OVRP_FAILURE(FOculusHMDModule::GetPluginWrapper().GetNodePoseState3(ovrpStep_Render, OVRP_CURRENT_FRAMEINDEX, ovrpNode_Head, &PoseState)) ||
|
||||
!OculusHMD->ConvertPose_Internal(PoseState.Pose, Pose, s, WoldToMetersScale))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HeadPos = Pose.Position;
|
||||
HeadRot = Pose.Orientation.Rotator();
|
||||
bEnableHead = true;
|
||||
}
|
||||
{
|
||||
ovrpHand eHandState[] = {
|
||||
ovrpHand_Left,
|
||||
ovrpHand_Right,
|
||||
};
|
||||
|
||||
ovrpSkeletonType eSkeletonType[] = {
|
||||
ovrpSkeletonType_HandLeft,
|
||||
ovrpSkeletonType_HandRight,
|
||||
};
|
||||
|
||||
TArray<FTransform>* handTrans[] = {
|
||||
&leftHand,
|
||||
&rightHand,
|
||||
};
|
||||
|
||||
TArray<FTransform>* handReferenceTrans[] = {
|
||||
&leftHandReference,
|
||||
&rightHandReference,
|
||||
};
|
||||
|
||||
TArray<float>* pinch[] = {
|
||||
&leftPinch,
|
||||
&rightPinch,
|
||||
};
|
||||
|
||||
{
|
||||
ovrpControllerState4 OvrpControllerState;
|
||||
if (OVRP_SUCCESS(FOculusHMDModule::GetPluginWrapper().GetControllerState4((ovrpController)(ovrpController_LHand | ovrpController_RHand | ovrpController_Hands), &OvrpControllerState))) {
|
||||
OvrpControllerState.ConnectedControllerTypes++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int handCount = 0; handCount < 2; ++handCount) {
|
||||
|
||||
ovrpHandState handState;
|
||||
if (OVRP_SUCCESS(FOculusHMDModule::GetPluginWrapper().GetHandState(ovrpStep_Render, eHandState[handCount], &handState)) == false) {
|
||||
continue;
|
||||
}
|
||||
if (handCount == 0) {
|
||||
bEnableLeft = true;
|
||||
} else {
|
||||
bEnableRight = true;
|
||||
}
|
||||
|
||||
rootScale = handState.HandScale;
|
||||
|
||||
|
||||
(*(pinch[handCount])).SetNum(ovrpHandFinger_Max);
|
||||
for (int i = 0; i < leftPinch.Num(); ++i) {
|
||||
(*(pinch[handCount]))[i] = handState.PinchStrength[i];
|
||||
}
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
ovrpSkeleton skeleton;
|
||||
if (FOculusHMDModule::GetPluginWrapper().GetSkeleton(eSkeletonType[handCount], &skeleton) == 0) {
|
||||
#elif UE_VERSION_OLDER_THAN(5,0,0)
|
||||
ovrpSkeleton2 skeleton;
|
||||
if (FOculusHMDModule::GetPluginWrapper().GetSkeleton2(eSkeletonType[handCount], &skeleton) == 0) {
|
||||
#else
|
||||
ovrpSkeleton skeleton;
|
||||
if (FOculusHMDModule::GetPluginWrapper().GetSkeleton(eSkeletonType[handCount], &skeleton) == 0) {
|
||||
#endif
|
||||
handTrans[handCount]->SetNum(skeleton.NumBones);
|
||||
handReferenceTrans[handCount]->SetNum(skeleton.NumBones);
|
||||
for (uint32_t i = 0; i < skeleton.NumBones; ++i) {
|
||||
|
||||
int boneID = skeleton.Bones[i].BoneId;
|
||||
|
||||
//auto aa = VRM4ULocal::ToFQuat(handState.BoneRotations[boneID]);
|
||||
auto curRot = VRM4ULocal::ToFQuat(handState.BoneRotations[boneID]);
|
||||
auto skeletonRot = VRM4ULocal::ToFQuat(skeleton.Bones[i].Pose.Orientation);
|
||||
auto skeletonPos = VRM4ULocal::ToFVector(skeleton.Bones[i].Pose.Position) * WoldToMetersScale;
|
||||
|
||||
auto t = FTransform(curRot, skeletonPos);
|
||||
auto t_ref = FTransform(skeletonRot, skeletonPos);
|
||||
|
||||
int parentBone = skeleton.Bones[i].ParentBoneIndex;
|
||||
if (parentBone >= 0) {
|
||||
t = t * (*(handTrans[handCount]))[parentBone];
|
||||
t_ref = t_ref * (*(handReferenceTrans[handCount]))[parentBone];
|
||||
} else {
|
||||
{
|
||||
auto q1 = VRM4ULocal::ToFQuat(handState.RootPose.Orientation);
|
||||
auto p1 = VRM4ULocal::ToFVector(handState.RootPose.Position) * WoldToMetersScale;
|
||||
|
||||
t = t * FTransform(q1, p1);
|
||||
}
|
||||
|
||||
{
|
||||
auto q2 = VRM4ULocal::ToFQuat(skeleton.Bones[i].Pose.Orientation);
|
||||
auto p2 = VRM4ULocal::ToFVector(skeleton.Bones[i].Pose.Position) * WoldToMetersScale;
|
||||
|
||||
t_ref = t_ref * FTransform(q2, p2);
|
||||
}
|
||||
}
|
||||
|
||||
(*(handTrans[handCount]))[i] = t;
|
||||
(*(handReferenceTrans[handCount]))[i] = t_ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bEnableTracking = true;
|
||||
|
||||
//ovrpBool handTrackingEnabled = false;
|
||||
//auto res = FOculusHMDModule::GetPluginWrapper().GetHandTrackingEnabled(&handTrackingEnabled);
|
||||
|
||||
//str2 = FString::Printf(TEXT("%d"), handTrackingEnabled);
|
||||
//str2 = handTrackingEnabled;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "VrmHMDTrackingComponent.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(meta=(BlueprintSpawnableComponent))
|
||||
class VRM4U_API UVrmHMDTrackingComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
|
||||
float rootScale;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
|
||||
TArray<FTransform> rightHand;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
|
||||
TArray<FTransform> leftHand;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
|
||||
TArray<FTransform> rightHandReference;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
|
||||
TArray<FTransform> leftHandReference;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
|
||||
TArray<float> rightPinch;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
|
||||
TArray<float> leftPinch;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
|
||||
FVector HeadPos;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
|
||||
FRotator HeadRot;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Character)
|
||||
FString dummyForLog;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = Character)
|
||||
bool bEnableLeft;
|
||||
UPROPERTY(BlueprintReadOnly, Category = Character)
|
||||
bool bEnableRight;
|
||||
UPROPERTY(BlueprintReadOnly, Category = Character)
|
||||
bool bEnableHead;
|
||||
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U", meta = (DynamicOutputParam = "OutVrmAsset"))
|
||||
bool IsEnable() const {
|
||||
return bEnableTracking;
|
||||
};
|
||||
|
||||
public:
|
||||
void OnRegister() override;
|
||||
void OnUnregister() override;
|
||||
|
||||
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
private:
|
||||
bool bEnableTracking = false;;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmImportMaterialSet.h"
|
||||
|
||||
|
||||
//UVrmImportMaterialSet::UVrmImportMaterialSet() {
|
||||
//}
|
||||
@@ -0,0 +1,6 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "VrmLicenseObject.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "VrmMetaObject.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "VrmModelActor.h"
|
||||
|
||||
|
||||
// Sets default values
|
||||
AVrmModelActor::AVrmModelActor(const FObjectInitializer& ObjectInitializer)
|
||||
:Super(ObjectInitializer)
|
||||
{
|
||||
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
// Called when the game starts or when spawned
|
||||
void AVrmModelActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
}
|
||||
|
||||
// Called every frame
|
||||
void AVrmModelActor::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmNetworkBPFunctionLibrary.h"
|
||||
#include "VRM4U.h"
|
||||
|
||||
#include "Engine/Engine.h"
|
||||
#include "Logging/MessageLog.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#include "Windows/AllowWindowsPlatformTypes.h"
|
||||
#include <windows.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <winsock.h>
|
||||
|
||||
#include "Windows/HideWindowsPlatformTypes.h"
|
||||
#endif
|
||||
|
||||
void UVrmNetworkBPFunctionLibrary::VRMGetIPAddressTable(TArray<FString> &AddressTable) {
|
||||
|
||||
AddressTable.Empty();
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
DWORD dwSize = 0;
|
||||
|
||||
TArray<uint8> IPAddrTableBuffer;
|
||||
IPAddrTableBuffer.SetNum(sizeof(MIB_IPADDRTABLE));
|
||||
|
||||
if (GetIpAddrTable(nullptr, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
|
||||
IPAddrTableBuffer.SetNum(dwSize);
|
||||
}
|
||||
|
||||
auto dwRetVal = GetIpAddrTable(reinterpret_cast<MIB_IPADDRTABLE*>(IPAddrTableBuffer.GetData()), &dwSize, 0);
|
||||
if ( dwRetVal != NO_ERROR ) {
|
||||
UE_LOG(LogVRM4U, Warning, TEXT("GetIpAddrTable call failed with %d\n"), dwRetVal);
|
||||
}
|
||||
|
||||
{
|
||||
MIB_IPADDRTABLE* pIPAddrTable = reinterpret_cast<MIB_IPADDRTABLE*>(IPAddrTableBuffer.GetData());
|
||||
for (DWORD i = 0; i < pIPAddrTable->dwNumEntries; ++i) {
|
||||
AddressTable.Add(inet_ntoa(*(struct in_addr*)&pIPAddrTable->table[i].dwAddr));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmPoseableMeshComponent.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "VrmAnimInstance.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
|
||||
|
||||
|
||||
UVrmPoseableMeshComponent::UVrmPoseableMeshComponent(const FObjectInitializer& ObjectInitializer)
|
||||
:Super(ObjectInitializer)
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
|
||||
// for morph curve copy
|
||||
bTickInEditor = true;
|
||||
}
|
||||
|
||||
void UVrmPoseableMeshComponent::OnRegister() {
|
||||
Super::OnRegister();
|
||||
|
||||
if (bUseDefaultMaterial) {
|
||||
this->OverrideMaterials.Empty();
|
||||
}
|
||||
Init();
|
||||
UpdateLeader();
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
void UVrmPoseableMeshComponent::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) {
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
UpdateLeader();
|
||||
}
|
||||
void UVrmPoseableMeshComponent::PostEditChangeChainProperty(struct FPropertyChangedChainEvent& PropertyChangedEvent) {
|
||||
Super::PostEditChangeChainProperty(PropertyChangedEvent);
|
||||
}
|
||||
#endif
|
||||
|
||||
void UVrmPoseableMeshComponent::OnAttachmentChanged() {
|
||||
Super::OnAttachmentChanged();
|
||||
}
|
||||
|
||||
void UVrmPoseableMeshComponent::InitializeComponent() {
|
||||
Super::InitializeComponent();
|
||||
}
|
||||
|
||||
void UVrmPoseableMeshComponent::UpdateLeader() {
|
||||
|
||||
if (bUseParentAsLeader) {
|
||||
USkinnedMeshComponent* skin = Cast<USkinnedMeshComponent>(this->GetAttachParent());
|
||||
USkeletalMeshComponent* skel = Cast<USkeletalMeshComponent>(skin);
|
||||
#if UE_VERSION_OLDER_THAN(5,1,0)
|
||||
SetMasterPoseComponent(skin);
|
||||
#else
|
||||
SetLeaderPoseComponent(skin);
|
||||
#endif
|
||||
VRMCopyPoseAndMorphFromSkeletalComponent(skel);
|
||||
}
|
||||
}
|
||||
|
||||
void UVrmPoseableMeshComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) {
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,20,0)
|
||||
#else
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,1,0)
|
||||
USkinnedMeshComponent* MPCPtr = MasterPoseComponent.Get();
|
||||
#else
|
||||
USkinnedMeshComponent* MPCPtr = LeaderPoseComponent.Get();
|
||||
#endif
|
||||
|
||||
if (MPCPtr) {
|
||||
MorphTargetWeights = MPCPtr->MorphTargetWeights;
|
||||
ActiveMorphTargets = MPCPtr->ActiveMorphTargets;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void UVrmPoseableMeshComponent::VRMCopyPoseAndMorphFromSkeletalComponent(USkeletalMeshComponent* InComponentToCopy) {
|
||||
if (InComponentToCopy && VRMGetSkinnedAsset(InComponentToCopy)) {
|
||||
Super::CopyPoseFromSkeletalComponent(InComponentToCopy);
|
||||
|
||||
MorphTargetWeights = InComponentToCopy->MorphTargetWeights;
|
||||
ActiveMorphTargets = InComponentToCopy->ActiveMorphTargets;
|
||||
}
|
||||
}
|
||||
|
||||
void UVrmPoseableMeshComponent::RefreshBoneTransforms(FActorComponentTickFunction* TickFunction)
|
||||
{
|
||||
Super::RefreshBoneTransforms(TickFunction);
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,1,0)
|
||||
USkinnedMeshComponent* MPCPtr = MasterPoseComponent.Get();
|
||||
#else
|
||||
USkinnedMeshComponent* MPCPtr = LeaderPoseComponent.Get();
|
||||
#endif
|
||||
if (MPCPtr) {
|
||||
MorphTargetWeights = MPCPtr->MorphTargetWeights;
|
||||
ActiveMorphTargets = MPCPtr->ActiveMorphTargets;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmRuntimeSettings.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
#include "Editor/EditorEngine.h"
|
||||
#include "Misc/MessageDialog.h"
|
||||
#include "UnrealEdMisc.h"
|
||||
#include "Misc/ConfigCacheIni.h"
|
||||
#include "HAL/PlatformFileManager.h"
|
||||
#endif
|
||||
|
||||
#define LOCTEXT_NAMESPACE "VRM4U"
|
||||
|
||||
|
||||
UVrmRuntimeSettings::UVrmRuntimeSettings(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
bDropVRMFileEnable = false;
|
||||
AssetListObject.SetPath(TEXT("/VRM4U/VrmAssetListObjectBP.VrmAssetListObjectBP"));
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
void UVrmRuntimeSettings::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) {
|
||||
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
|
||||
if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(UVrmRuntimeSettings, bAllowAllAssimpFormat)
|
||||
&& bAllowAllAssimpFormat)
|
||||
{
|
||||
FString FullPath = FPaths::ConvertRelativePathToFull(GetDefaultConfigFilename());
|
||||
FPlatformFileManager::Get().GetPlatformFile().SetReadOnly(*FullPath, false);
|
||||
|
||||
auto DialogText(LOCTEXT("VRM4UImportWarning", "Please check the license of the model before using it.\n\nAssImp対応フォーマットのインポートを有効化しました。\nモデルのライセンスに従ってご利用ください。"));
|
||||
FMessageDialog::Open(EAppMsgType::Ok, DialogText);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,915 @@
|
||||
#include "VrmSpringBone.h"
|
||||
|
||||
#include "VrmAssetListObject.h"
|
||||
#include "Engine/World.h"
|
||||
|
||||
VrmSpringBone::VrmSpringBone()
|
||||
{
|
||||
}
|
||||
|
||||
VrmSpringBone::~VrmSpringBone()
|
||||
{
|
||||
}
|
||||
|
||||
namespace VRMSpringBone {
|
||||
|
||||
void VRMSpring::Update(const FAnimNode_VrmSpringBone* animNode, float DeltaTime, FTransform ComponentToLocal,
|
||||
const TArray<VRMSpringColliderGroup>& colliderGroup,
|
||||
FComponentSpacePoseContext& Output) {
|
||||
|
||||
if (skeletalMesh == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RefSkeleton = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton();
|
||||
const auto& RefSkeletonTransform = Output.Pose.GetPose().GetBoneContainer().GetRefPoseArray();
|
||||
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
// モデルローカル座標
|
||||
ComponentToLocal = ComponentTransform.Inverse();
|
||||
|
||||
//
|
||||
// x10 adjust?
|
||||
FVector ue4grav(-gravityDir.X, gravityDir.Z, gravityDir.Y);
|
||||
|
||||
const int MAX_LOOP = FMath::Max(1, animNode->loopc);
|
||||
for (int i = 0; i < MAX_LOOP; ++i) {
|
||||
//const float stiffnessForce = stiffness * DeltaTime * 10.f * animNode->stiffnessScale + animNode->stiffinessAdd;
|
||||
//FVector external = ComponentToLocal.TransformVector(ue4grav) * (gravityPower * DeltaTime) * animNode->gravityScale + ComponentToLocal.TransformVector(animNode->gravityAdd) * DeltaTime;
|
||||
//external *= 100.f; // to unreal scale
|
||||
|
||||
float CurrentDeltaTime = DeltaTime / (float)MAX_LOOP;
|
||||
|
||||
const float stiffnessForce = stiffness * CurrentDeltaTime * 10.f * animNode->stiffnessScale + animNode->stiffnessAdd;
|
||||
FVector external = ComponentToLocal.TransformVector(ue4grav) * (gravityPower * CurrentDeltaTime) * animNode->gravityScale + ComponentToLocal.TransformVector(animNode->gravityAdd) * CurrentDeltaTime;
|
||||
|
||||
//wind
|
||||
if (animNode->bIgnoreWindDirectionalSource == false) {
|
||||
const USkeletalMeshComponent* SkelComp = Output.AnimInstanceProxy->GetSkelMeshComponent();
|
||||
//InAnimInstance->GetSkelMeshComponent();
|
||||
|
||||
const UWorld* World = nullptr;
|
||||
if (SkelComp) {
|
||||
World = SkelComp->GetWorld();
|
||||
}
|
||||
FSceneInterface* Scene = nullptr;
|
||||
if (World) {
|
||||
Scene = World->Scene;
|
||||
}
|
||||
|
||||
if (Scene)
|
||||
{
|
||||
|
||||
// Unused by our simulation but needed for the call to GetWindParameters below
|
||||
float WindMinGust;
|
||||
float WindMaxGust;
|
||||
FVector WindDirection;
|
||||
float WindSpeed;
|
||||
|
||||
|
||||
// Setup wind data
|
||||
//Body->bWindEnabled = true;
|
||||
//Scene->GetWindParameters_GameThread(SkelComp->GetComponentTransform().TransformPosition(Body->Pose.Position), Body->WindData.WindDirection, Body->WindData.WindSpeed, WindMinGust, WindMaxGust);
|
||||
Scene->GetWindParameters_GameThread(SkelComp->GetComponentTransform().GetLocation(), WindDirection, WindSpeed, WindMinGust, WindMaxGust);
|
||||
|
||||
WindDirection = SkelComp->GetComponentTransform().Inverse().TransformVector(WindDirection);
|
||||
|
||||
// from AnimPhysicsSolver
|
||||
const float WindUnitScale = 0.5f * 250.0f * FMath::FRandRange(1.f - animNode->randomWindRange, 1.f + animNode->randomWindRange) * animNode->windScale;
|
||||
//
|
||||
|
||||
// Wind velocity in body space
|
||||
FVector WindVelocity = WindDirection * WindSpeed * WindUnitScale;// *BodyWindScale;
|
||||
WindVelocity *= CurrentDeltaTime;
|
||||
|
||||
//Body->WindData.WindDirection = SkelComp->GetComponentTransform().Inverse().TransformVector(Body->WindData.WindDirection);
|
||||
//Body->WindData.WindAdaption = FMath::FRandRange(0.0f, 2.0f);
|
||||
//Body->WindData.BodyWindScale = WindScale;
|
||||
|
||||
//if (CVarEnableWind.GetValueOnAnyThread() == 1 && bEnableWind)
|
||||
|
||||
external += WindVelocity / 100.f;
|
||||
}
|
||||
}// wind end
|
||||
|
||||
|
||||
external *= 100.f; // to unreal scale
|
||||
|
||||
FVector external_noAdd = ComponentToLocal.TransformVector(ue4grav) * (gravityPower * CurrentDeltaTime) * animNode->gravityScale;
|
||||
external_noAdd *= 100.f; // to unreal scale
|
||||
|
||||
|
||||
const auto WorldContext = Output.AnimInstanceProxy->GetSkelMeshComponent();
|
||||
|
||||
for (int springCount = 0; springCount < SpringDataChain.Num(); ++springCount) {
|
||||
|
||||
auto& ChainRoot = SpringDataChain[springCount];
|
||||
FTransform currentTransform = FTransform::Identity;
|
||||
|
||||
bool bSkipGravAdd = false;
|
||||
|
||||
for (int chainCount = 0; chainCount < ChainRoot.Num(); ++chainCount) {
|
||||
|
||||
auto& sData = ChainRoot[chainCount];
|
||||
|
||||
FVector currentTail = ComponentToLocal.TransformPosition(sData.m_currentTail);
|
||||
FVector prevTail = ComponentToLocal.TransformPosition(sData.m_prevTail);
|
||||
|
||||
int myBoneIndex = RefSkeleton.FindBoneIndex(sData.boneName);
|
||||
if (myBoneIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (animNode->NoWindBoneNameList.Contains(sData.boneName)) {
|
||||
bSkipGravAdd = true;
|
||||
}
|
||||
|
||||
|
||||
int myParentBoneIndex = RefSkeleton.GetParentIndex(myBoneIndex);
|
||||
|
||||
//currentTransform = FTransform::Identity;
|
||||
FQuat ParentRotation = FQuat::Identity;
|
||||
if (chainCount == 0) {
|
||||
FCompactPoseBoneIndex uu = Output.Pose.GetPose().GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(myBoneIndex);
|
||||
//FCompactPoseBoneIndex uu(myBoneIndex);
|
||||
|
||||
if (Output.Pose.GetPose().IsValidIndex(uu) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(uu);
|
||||
ParentRotation = NewBoneTM.GetRotation();
|
||||
|
||||
currentTransform = NewBoneTM;
|
||||
}
|
||||
else {
|
||||
auto c = RefSkeletonTransform[sData.boneIndex];
|
||||
auto t = c * currentTransform;
|
||||
|
||||
ParentRotation = t.GetRotation();
|
||||
currentTransform = t;
|
||||
}
|
||||
FQuat m_localRotation = FQuat::Identity;
|
||||
|
||||
|
||||
// verlet積分で次の位置を計算
|
||||
FVector nextTail = currentTail
|
||||
+ (currentTail - prevTail) * (1.0f - dragForce) // 前フレームの移動を継続する(減衰もあるよ)
|
||||
+ ParentRotation * m_localRotation * sData.m_boneAxis * stiffnessForce // 親の回転による子ボーンの移動目標
|
||||
;
|
||||
if (bSkipGravAdd) {
|
||||
nextTail += external_noAdd; // 外力による移動量
|
||||
}
|
||||
else {
|
||||
nextTail += external; // 外力による移動量
|
||||
}
|
||||
|
||||
|
||||
// 長さをboneLengthに強制
|
||||
//nextTail = sData.m_transform.GetLocation() + (nextTail - sData.m_transform.GetLocation()).GetSafeNormal() * sData.m_length;
|
||||
nextTail = currentTransform.GetLocation() + (nextTail - currentTransform.GetLocation()).GetSafeNormal() * sData.m_length;
|
||||
|
||||
// Collisionで移動
|
||||
|
||||
// vrm <-> physics collision
|
||||
if (animNode->bIgnorePhysicsCollision == false) {
|
||||
const int ColCount = animNode->collisionCheckLoopCount;
|
||||
for (int colc = 0; colc < ColCount; ++colc) {
|
||||
FVector Start = ComponentToLocal.InverseTransformPosition(nextTail);
|
||||
FVector End = Start + FVector(0.001f);
|
||||
//* WorldContextObject
|
||||
float Radius = hitRadius * 100.f;
|
||||
ETraceTypeQuery TraceChannel = ETraceTypeQuery::TraceTypeQuery1;
|
||||
bool bTraceComplex = false;
|
||||
|
||||
TArray<AActor*> ActorsToIgnore;
|
||||
EDrawDebugTrace::Type DrawDebugType = EDrawDebugTrace::None;
|
||||
TArray<FHitResult> OutHits;
|
||||
bool bIgnoreSelf = true;
|
||||
FLinearColor TraceColor(EForceInit::ForceInit);
|
||||
FLinearColor TraceHitColor(EForceInit::ForceInit);
|
||||
float DrawTime = 0.f;
|
||||
|
||||
bool b = UKismetSystemLibrary::SphereTraceMulti(WorldContext, Start, End, hitRadius * 100.f,
|
||||
TraceChannel, false, ActorsToIgnore,
|
||||
DrawDebugType,
|
||||
OutHits, bIgnoreSelf, TraceColor, TraceHitColor, DrawTime);
|
||||
if (b == false) {
|
||||
break;
|
||||
}
|
||||
for (auto hit : OutHits) {
|
||||
{
|
||||
//WorldContext->GetOwner
|
||||
//hit.BoneName
|
||||
|
||||
}
|
||||
float r = hit.PenetrationDepth; // hitRadius * 100.f + hit.Distance;
|
||||
auto normal = hit.Normal;
|
||||
auto posFromCollider = nextTail + normal * r; // (float)ColCount;
|
||||
// 長さをboneLengthに強制
|
||||
nextTail = currentTransform.GetLocation() + (posFromCollider - currentTransform.GetLocation()).GetSafeNormal() * sData.m_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vrm <-> vrm collision
|
||||
if (animNode->bIgnoreVRMCollision == false) {
|
||||
for (auto ind : ColliderGroupIndexArray) {
|
||||
if (ind >= colliderGroup.Num()) {
|
||||
continue;
|
||||
}
|
||||
const auto& cg = colliderGroup[ind];
|
||||
|
||||
int ii = RefSkeleton.FindBoneIndex(cg.node_name);
|
||||
if (ii < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FCompactPoseBoneIndex uu = Output.Pose.GetPose().GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(ii);
|
||||
//FCompactPoseBoneIndex uu(ii);
|
||||
if (uu == INDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
FTransform collisionBoneTrans = Output.Pose.GetComponentSpaceTransform(uu);
|
||||
|
||||
for (auto c : cg.colliders) {
|
||||
|
||||
|
||||
float r = (hitRadius + c.radius) * 100.f;
|
||||
//FVector v = collisionBoneTrans.TransformPosition(c.offset*100);
|
||||
auto offs = c.offset;
|
||||
//offs.Set(offs.X, -offs.Z, offs.Y); // 本来はこれが正しいが、VRM0の座標が間違っている
|
||||
offs.Set(-offs.X, offs.Z, offs.Y); // VRM0の仕様としては これ
|
||||
offs *= 100;
|
||||
FVector v = collisionBoneTrans.TransformPosition(offs);
|
||||
|
||||
if ((v - nextTail).SizeSquared() > r * r) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ヒット。Colliderの半径方向に押し出す
|
||||
auto normal = (nextTail - v).GetSafeNormal();
|
||||
auto posFromCollider = v + normal * (r);
|
||||
// 長さをboneLengthに強制
|
||||
nextTail = currentTransform.GetLocation() + (posFromCollider - currentTransform.GetLocation()).GetSafeNormal() * sData.m_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sData.m_prevTail = ComponentToLocal.InverseTransformPosition(currentTail);
|
||||
sData.m_currentTail = ComponentToLocal.InverseTransformPosition(nextTail);
|
||||
|
||||
FQuat rotation = ParentRotation * m_localRotation;
|
||||
|
||||
sData.m_resultQuat = FQuat::FindBetween((rotation * sData.m_boneAxis).GetSafeNormal(),
|
||||
(nextTail - currentTransform.GetLocation()).GetSafeNormal()) * rotation;
|
||||
|
||||
currentTransform.SetRotation(sData.m_resultQuat);
|
||||
}
|
||||
}// chain loop
|
||||
}// delta time loop
|
||||
}
|
||||
|
||||
|
||||
void VRMSpringManager::reset() {
|
||||
spring.Empty();
|
||||
bInit = false;
|
||||
}
|
||||
|
||||
void VRMSpringManager::init(const UVrmMetaObject* meta, FComponentSpacePoseContext& Output) {
|
||||
if (meta == nullptr) return;
|
||||
if (bInit) return;
|
||||
|
||||
if (meta->GetVRMVersion() == 1) return;
|
||||
if (meta->VrmAssetListObject == nullptr) return;
|
||||
|
||||
skeletalMesh = VRMGetSkinnedAsset(Output.AnimInstanceProxy->GetSkelMeshComponent());
|
||||
//skeletalMesh = meta->SkeletalMesh;
|
||||
const FReferenceSkeleton& RefSkeleton = VRMGetRefSkeleton(skeletalMesh);
|
||||
const auto& RefSkeletonTransform = Output.Pose.GetPose().GetBoneContainer().GetRefPoseArray();
|
||||
|
||||
spring.SetNum(meta->VRMSpringMeta.Num());
|
||||
|
||||
for (int i = 0; i < spring.Num(); ++i) {
|
||||
auto& s = spring[i];
|
||||
const auto& metaS = meta->VRMSpringMeta[i];
|
||||
|
||||
s.skeletalMesh = skeletalMesh;// meta->SkeletalMesh;
|
||||
|
||||
s.stiffness = metaS.stiffness;
|
||||
s.gravityPower = metaS.gravityPower;
|
||||
s.gravityDir = meta->VrmAssetListObject->model_root_transform.TransformVector(metaS.gravityDir);
|
||||
s.dragForce = metaS.dragForce;
|
||||
s.hitRadius = metaS.hitRadius;
|
||||
|
||||
s.RootSpringData.SetNum(metaS.bones.Num());
|
||||
for (int scount = 0; scount < s.RootSpringData.Num(); ++scount) {
|
||||
s.RootSpringData[scount].boneName = *metaS.boneNames[scount];
|
||||
s.RootSpringData[scount].boneIndex = RefSkeleton.FindBoneIndex(*metaS.boneNames[scount]);
|
||||
}
|
||||
// TODO add child
|
||||
|
||||
s.SpringDataChain.SetNum(metaS.bones.Num());
|
||||
for (int scount = 0; scount < s.RootSpringData.Num(); ++scount) {
|
||||
auto& chain = s.SpringDataChain[scount];
|
||||
|
||||
//root
|
||||
{
|
||||
auto index = VRMGetRefSkeleton(skeletalMesh).FindBoneIndex(*metaS.boneNames[scount]);
|
||||
if (index == INDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& sData = chain.AddDefaulted_GetRef();
|
||||
sData.boneName = *metaS.boneNames[scount];
|
||||
sData.boneIndex = index;
|
||||
|
||||
TArray<int32> Children;
|
||||
VRMUtil::GetDirectChildBones(VRMGetRefSkeleton(skeletalMesh), sData.boneIndex, Children);
|
||||
if (Children.Num() > 0) {
|
||||
sData.m_boneAxis = RefSkeletonTransform[Children[0]].GetLocation();
|
||||
}
|
||||
else {
|
||||
sData.m_boneAxis = RefSkeletonTransform[sData.boneIndex].GetLocation() * 0.7f;
|
||||
}
|
||||
}
|
||||
|
||||
// child
|
||||
if (1) {
|
||||
for (int chainCount = 0; chainCount < 100; ++chainCount) {
|
||||
bool bLast = false;
|
||||
TArray<int32> Children;
|
||||
|
||||
VRMUtil::GetDirectChildBones(VRMGetRefSkeleton(skeletalMesh), chain[chainCount].boneIndex, Children);
|
||||
if (Children.Num() <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto& sData = chain.AddDefaulted_GetRef();
|
||||
|
||||
sData.boneIndex = Children[0];
|
||||
sData.boneName = *RefSkeleton.GetBoneName(sData.boneIndex).ToString();
|
||||
|
||||
VRMUtil::GetDirectChildBones(VRMGetRefSkeleton(skeletalMesh), sData.boneIndex, Children);
|
||||
if (Children.Num() > 0) {
|
||||
sData.m_boneAxis = RefSkeletonTransform[Children[0]].GetLocation();
|
||||
}
|
||||
else {
|
||||
sData.m_boneAxis = RefSkeletonTransform[sData.boneIndex].GetLocation() * 0.7f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
s.ColliderGroupIndexArray.SetNum(metaS.ColliderIndexArray.Num());
|
||||
for (int c = 0; c < s.ColliderGroupIndexArray.Num(); ++c) {
|
||||
s.ColliderGroupIndexArray[c] = metaS.ColliderIndexArray[c];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// init default transform
|
||||
{
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
for (auto& s : spring) {
|
||||
for (auto& root : s.SpringDataChain) {
|
||||
FTransform currentTransform = FTransform::Identity;
|
||||
|
||||
for (int ChildCount = 0; ChildCount < root.Num(); ++ChildCount) {
|
||||
//for (auto& sData : root) {
|
||||
auto& sData = root[ChildCount];
|
||||
sData.m_length = sData.m_boneAxis.Size();
|
||||
int myBoneIndex = RefSkeleton.FindBoneIndex(sData.boneName);
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
if (sData.boneIndex >= Output.Pose.GetPose().GetBoneContainer().GetSkeletonToPoseBoneIndexArray().Num()) {
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
if (Output.Pose.GetPose().GetBoneContainer().GetMeshPoseIndexFromSkeletonPoseIndex(FSkeletonPoseBoneIndex(sData.boneIndex)) == FMeshPoseBoneIndex(INDEX_NONE)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
FQuat ParentRotation = FQuat::Identity;
|
||||
if (ChildCount == 0) {
|
||||
FCompactPoseBoneIndex uu = Output.Pose.GetPose().GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(myBoneIndex);
|
||||
|
||||
if (Output.Pose.GetPose().IsValidIndex(uu) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(uu);
|
||||
ParentRotation = NewBoneTM.GetRotation();
|
||||
|
||||
currentTransform = NewBoneTM;
|
||||
}
|
||||
else {
|
||||
auto c = RefSkeletonTransform[sData.boneIndex];
|
||||
auto t = c * currentTransform;
|
||||
|
||||
ParentRotation = t.GetRotation();
|
||||
currentTransform = t;
|
||||
}
|
||||
}
|
||||
FVector v = currentTransform.GetLocation() + sData.m_boneAxis;
|
||||
sData.m_currentTail = sData.m_prevTail = ComponentTransform.TransformPosition(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collider
|
||||
colliderGroup.SetNum(meta->VRMColliderMeta.Num());
|
||||
for (int i = 0; i < colliderGroup.Num(); ++i) {
|
||||
auto& cg = colliderGroup[i];
|
||||
const auto& cmeta = meta->VRMColliderMeta[i];
|
||||
|
||||
cg.node = cmeta.bone;
|
||||
cg.node_name = *cmeta.boneName;
|
||||
|
||||
cg.colliders.SetNum(cmeta.collider.Num());
|
||||
for (int c = 0; c < cg.colliders.Num(); ++c) {
|
||||
cg.colliders[c].offset = cmeta.collider[c].offset;
|
||||
cg.colliders[c].radius = cmeta.collider[c].radius;
|
||||
}
|
||||
|
||||
TArray<VRMSpringCollider> colliders;
|
||||
}
|
||||
|
||||
|
||||
bInit = true;
|
||||
}
|
||||
void VRMSpringManager::update(const FAnimNode_VrmSpringBone* animNode, float DeltaTime, FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) {
|
||||
for (int i = 0; i < spring.Num(); ++i) {
|
||||
FTransform c;
|
||||
//c = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
c = Output.AnimInstanceProxy->GetActorTransform();
|
||||
|
||||
spring[i].Update(animNode, DeltaTime, c, colliderGroup, Output);
|
||||
}
|
||||
}
|
||||
void VRMSpringManager::applyToComponent(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) {
|
||||
|
||||
const auto RefSkeleton = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton();
|
||||
const auto& RefSkeletonTransform = Output.Pose.GetPose().GetBoneContainer().GetRefPoseArray();
|
||||
|
||||
|
||||
VRMSpringManager* SpringManager = this;
|
||||
|
||||
for (auto& springRoot : SpringManager->spring) {
|
||||
for (auto& sChain : springRoot.SpringDataChain) {
|
||||
int BoneChain = 0;
|
||||
|
||||
FTransform CurrentTransForm = FTransform::Identity;
|
||||
for (auto& sData : sChain) {
|
||||
|
||||
|
||||
//FCompactPoseBoneIndex uu = Output.Pose.GetPose().GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(sData.boneIndex);
|
||||
FCompactPoseBoneIndex uu(sData.boneIndex);
|
||||
|
||||
if (Output.Pose.GetPose().IsValidIndex(uu) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FTransform NewBoneTM;
|
||||
|
||||
if (BoneChain == 0) {
|
||||
NewBoneTM = Output.Pose.GetComponentSpaceTransform(uu);
|
||||
NewBoneTM.SetRotation(sData.m_resultQuat);
|
||||
|
||||
CurrentTransForm = NewBoneTM;
|
||||
}
|
||||
else {
|
||||
|
||||
NewBoneTM = CurrentTransForm;
|
||||
|
||||
auto c = RefSkeletonTransform[sData.boneIndex];
|
||||
NewBoneTM = c * NewBoneTM;
|
||||
NewBoneTM.SetRotation(sData.m_resultQuat);
|
||||
|
||||
|
||||
//const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
//NewBoneTM.SetLocation(ComponentTransform.TransformPosition(sData.m_currentTail));
|
||||
|
||||
CurrentTransForm = NewBoneTM;
|
||||
}
|
||||
|
||||
FBoneTransform a(uu, NewBoneTM);
|
||||
|
||||
bool bFirst = true;
|
||||
for (auto& t : OutBoneTransforms) {
|
||||
if (t.BoneIndex == a.BoneIndex) {
|
||||
bFirst = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFirst) {
|
||||
OutBoneTransforms.Add(a);
|
||||
}
|
||||
BoneChain++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
OutBoneTransforms.Sort(FCompareBoneTransformIndex());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
namespace VRM1Spring {
|
||||
|
||||
void VRM1SpringManager::reset() {
|
||||
for (auto &j : JointStateMap) {
|
||||
j.Value.currentTail = j.Value.prevTail = j.Value.initialTail;
|
||||
}
|
||||
}
|
||||
|
||||
void VRM1SpringManager::init(const UVrmMetaObject* meta, FComponentSpacePoseContext& Output) {
|
||||
|
||||
if (meta == nullptr) return;
|
||||
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
FTransform ComponentToLocal = ComponentTransform.Inverse();
|
||||
|
||||
vrmMetaObject = meta;
|
||||
skeletalMesh = VRMGetSkinnedAsset(Output.AnimInstanceProxy->GetSkelMeshComponent());
|
||||
const FReferenceSkeleton& RefSkeleton = VRMGetRefSkeleton(skeletalMesh);
|
||||
//const auto& RefSkeletonTransform = Output.Pose.GetPose().GetBoneContainer().GetRefPoseArray();
|
||||
const auto& RefSkeletonTransform = RefSkeleton.GetRefBonePose();
|
||||
|
||||
|
||||
for (auto& s : vrmMetaObject->VRM1SpringBoneMeta.Springs) {
|
||||
for (int jointNo = 0; jointNo < s.joints.Num(); jointNo++) {
|
||||
|
||||
auto &j1 = s.joints[jointNo];
|
||||
|
||||
if (j1.boneNo == INDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int parentBoneIndex = RefSkeleton.GetParentIndex(j1.boneNo);
|
||||
if (parentBoneIndex < 0) continue;
|
||||
FCompactPoseBoneIndex uu = Output.Pose.GetPose().GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(parentBoneIndex);
|
||||
if (Output.Pose.GetPose().IsValidIndex(uu) == false) {
|
||||
continue;
|
||||
}
|
||||
FTransform parentTransform = Output.Pose.GetComponentSpaceTransform(uu);
|
||||
|
||||
auto& state = JointStateMap.FindOrAdd(j1.boneNo);
|
||||
|
||||
if (RefSkeletonTransform.IsValidIndex(j1.boneNo) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
state.initialLocalMatrix = RefSkeletonTransform[j1.boneNo];
|
||||
state.initialLocalRotation = RefSkeletonTransform[j1.boneNo].GetRotation();
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
state.boneLength = RefSkeletonTransform[parentBoneIndex].GetLocation().Size();
|
||||
#else
|
||||
state.boneLength = RefSkeletonTransform[j1.boneNo].GetLocation().Length();
|
||||
#endif
|
||||
state.boneAxis = RefSkeletonTransform[j1.boneNo].TransformPosition(FVector::ZeroVector).GetSafeNormal();
|
||||
|
||||
{
|
||||
FCompactPoseBoneIndex u = Output.Pose.GetPose().GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(j1.boneNo);
|
||||
auto t = Output.Pose.GetComponentSpaceTransform(u);
|
||||
|
||||
state.prevTail =
|
||||
state.currentTail =
|
||||
state.initialTail = ComponentToLocal.InverseTransformPosition(t.GetLocation());
|
||||
|
||||
state.resultQuat = t.GetRotation();
|
||||
}
|
||||
}
|
||||
}
|
||||
bInit = true;
|
||||
}
|
||||
|
||||
void VRM1SpringManager::update(const FAnimNode_VrmSpringBone* animNode, float DeltaTime, FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) {
|
||||
|
||||
if (skeletalMesh == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (FMath::IsNearlyZero(DeltaTime)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RefSkeleton = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton();
|
||||
//const auto& RefSkeletonTransform = Output.Pose.GetPose().GetBoneContainer().GetRefPoseArray();
|
||||
const auto& RefSkeletonTransform = RefSkeleton.GetRefBonePose();
|
||||
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
// モデルローカル座標
|
||||
// FTransform c;
|
||||
//c = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
//c = Output.AnimInstanceProxy->GetActorTransform();
|
||||
|
||||
const FTransform ComponentToLocal = ComponentTransform.Inverse();
|
||||
|
||||
// 計算した揺れ骨、または揺れ骨の親
|
||||
TMap<int, FTransform> calcTransform;
|
||||
|
||||
// 揺れ骨一覧
|
||||
TArray<int> springBoneNoList;
|
||||
{
|
||||
for (auto& s : vrmMetaObject->VRM1SpringBoneMeta.Springs) {
|
||||
for (auto& j : s.joints) {
|
||||
springBoneNoList.AddUnique(j.boneNo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& s : vrmMetaObject->VRM1SpringBoneMeta.Springs) {
|
||||
|
||||
for (int jointNo = 0; jointNo < s.joints.Num(); ++jointNo) {
|
||||
FTransform parentTransform = FTransform::Identity;
|
||||
FTransform currentTransform = FTransform::Identity;
|
||||
|
||||
auto& j1 = s.joints[jointNo];
|
||||
|
||||
auto* state = JointStateMap.Find(j1.boneNo);
|
||||
if (state == nullptr) {
|
||||
init(vrmMetaObject, Output);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RefSkeletonTransform.IsValidIndex(j1.boneNo) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int parentBoneIndex = RefSkeleton.GetParentIndex(j1.boneNo);
|
||||
if (parentBoneIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (springBoneNoList.Find(parentBoneIndex) < 0) {
|
||||
// 親が揺れ骨ではない。通常骨から参照
|
||||
|
||||
// 親
|
||||
{
|
||||
FCompactPoseBoneIndex uu = Output.Pose.GetPose().GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(parentBoneIndex);
|
||||
if (Output.Pose.GetPose().IsValidIndex(uu) == false) {
|
||||
continue;
|
||||
}
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(uu);
|
||||
parentTransform = NewBoneTM;
|
||||
}
|
||||
|
||||
{
|
||||
// 自分
|
||||
FCompactPoseBoneIndex uu = Output.Pose.GetPose().GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(j1.boneNo);
|
||||
if (Output.Pose.GetPose().IsValidIndex(uu) == false) {
|
||||
continue;
|
||||
}
|
||||
FTransform NewBoneTM = Output.Pose.GetComponentSpaceTransform(uu);
|
||||
currentTransform = NewBoneTM;
|
||||
}
|
||||
} else {
|
||||
// 親が揺れ骨。揺れ骨計算結果から参照
|
||||
|
||||
// 親
|
||||
//parentTransform = currentTransform;
|
||||
auto* p = calcTransform.Find(parentBoneIndex);
|
||||
if (p) {
|
||||
parentTransform = *p;
|
||||
}
|
||||
|
||||
auto c = RefSkeletonTransform[j1.boneNo];
|
||||
auto t = c * parentTransform;
|
||||
|
||||
// 自分
|
||||
currentTransform = t;
|
||||
}
|
||||
|
||||
FQuat m_localRotation = state->initialLocalMatrix.GetRotation();
|
||||
|
||||
const FVector currentTail = ComponentToLocal.TransformPosition(state->currentTail);
|
||||
const FVector prevTail = ComponentToLocal.TransformPosition(state->prevTail);
|
||||
|
||||
const FVector inertia = (currentTail - prevTail) * (1.0f - j1.dragForce);
|
||||
const FVector stiffness = currentTransform.GetRotation() * state->boneAxis * 1.f * DeltaTime
|
||||
* 100.f * j1.stiffness * animNode->stiffnessScale + animNode->stiffnessAdd;
|
||||
|
||||
FVector ue4grav(-j1.gravityDir.X, j1.gravityDir.Z, j1.gravityDir.Y);
|
||||
ue4grav = vrmMetaObject->VrmAssetListObject->model_root_transform.Inverse().TransformVector(ue4grav);
|
||||
FVector external = ComponentToLocal.TransformVector(ue4grav) * (j1.gravityPower * DeltaTime) * animNode->gravityScale
|
||||
+ ComponentToLocal.TransformVector(animNode->gravityAdd) * DeltaTime;
|
||||
|
||||
|
||||
FVector nextTailTarget = currentTail + inertia + stiffness + external;
|
||||
//FVector nextTailTarget = currentTail + stiffness * 10;
|
||||
|
||||
// 長さをboneLengthに強制
|
||||
FVector nextTailDirection = (nextTailTarget - currentTransform.GetLocation()).GetSafeNormal();
|
||||
FVector nextTailPosition = currentTransform.GetLocation() + nextTailDirection * state->boneLength;
|
||||
|
||||
|
||||
// vrm <-> vrm collision
|
||||
if (animNode->bIgnoreVRMCollision == false) {
|
||||
|
||||
// このSpringが参照するコライダのインデックス
|
||||
TArray<int> checkcolliderIndexArray;
|
||||
for (auto colg : s.colliderGroups) {
|
||||
checkcolliderIndexArray.Append(vrmMetaObject->VRM1SpringBoneMeta.ColliderGroups[colg].colliders);
|
||||
}
|
||||
|
||||
// 全てのコライダ
|
||||
auto& AllColliderArray = vrmMetaObject->VRM1SpringBoneMeta.Colliders;
|
||||
|
||||
for (auto colNo : checkcolliderIndexArray){
|
||||
if (colNo >= AllColliderArray.Num()) {
|
||||
continue;
|
||||
}
|
||||
const auto& collider = AllColliderArray[colNo];
|
||||
|
||||
FTransform collisionBoneTrans;
|
||||
{
|
||||
int boneNo = RefSkeleton.FindBoneIndex(*collider.boneName);
|
||||
if (boneNo < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FCompactPoseBoneIndex uu = Output.Pose.GetPose().GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(boneNo);
|
||||
//FCompactPoseBoneIndex uu(ii);
|
||||
if (uu == INDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
collisionBoneTrans = Output.Pose.GetComponentSpaceTransform(uu);
|
||||
}
|
||||
|
||||
auto offs = collider.offset;
|
||||
offs.Set(offs.X, -offs.Z, offs.Y);
|
||||
offs *= 100;
|
||||
//offs = collisionBoneTrans.TransformVector(offs);
|
||||
|
||||
auto tail = collider.tail;
|
||||
tail.Set(tail.X, -tail.Z, tail.Y);
|
||||
tail *= 100;
|
||||
//tail = collisionBoneTrans.TransformVector(tail);
|
||||
|
||||
float r = (j1.hitRadius + collider.radius) * 100.f;
|
||||
|
||||
if (collider.shapeType == TEXT("sphere")) {
|
||||
FVector v = collisionBoneTrans.TransformPosition(offs);
|
||||
|
||||
if ((v - nextTailPosition).SizeSquared() > r * r) {
|
||||
continue;
|
||||
}
|
||||
// ヒット。Colliderの半径方向に押し出す
|
||||
auto normal = (nextTailPosition - v).GetSafeNormal();
|
||||
auto posFromCollider = v + normal * r;
|
||||
// 長さをboneLengthに強制
|
||||
nextTailPosition = currentTransform.GetLocation() + (posFromCollider - currentTransform.GetLocation()).GetSafeNormal() * state->boneLength;
|
||||
nextTailDirection = (posFromCollider - currentTransform.GetLocation()).GetSafeNormal();
|
||||
}
|
||||
else {
|
||||
|
||||
FTransform t1 = collisionBoneTrans;
|
||||
auto v1 = t1.TransformPosition(offs);
|
||||
|
||||
FTransform t2 = collisionBoneTrans;
|
||||
auto v2 = t2.TransformPosition(tail);
|
||||
|
||||
FVector nearestPoint = FMath::ClosestPointOnSegment(nextTailPosition, v1, v2);
|
||||
|
||||
float dif = (nearestPoint - nextTailPosition).SizeSquared();
|
||||
if (dif > r * r) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto normal = (nextTailPosition - nearestPoint).GetSafeNormal();
|
||||
|
||||
auto posFromCollider = nearestPoint + normal * r;
|
||||
// 長さをboneLengthに強制
|
||||
nextTailPosition = currentTransform.GetLocation() + (posFromCollider - currentTransform.GetLocation()).GetSafeNormal() * state->boneLength;
|
||||
nextTailDirection = (posFromCollider - currentTransform.GetLocation()).GetSafeNormal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
state->prevTail = ComponentToLocal.InverseTransformPosition(currentTail);
|
||||
state->currentTail = ComponentToLocal.InverseTransformPosition(nextTailPosition);
|
||||
|
||||
{
|
||||
FVector from = currentTransform.TransformVector(state->boneAxis).GetSafeNormal();
|
||||
FVector to = nextTailDirection;
|
||||
|
||||
state->resultQuat = FQuat::FindBetween(from, to) * parentTransform.GetRotation() * state->initialLocalMatrix.GetRotation();
|
||||
}
|
||||
|
||||
// initial rot
|
||||
{
|
||||
//state->resultQuat = currentTransform.GetRotation();
|
||||
}
|
||||
{
|
||||
//state->resultQuat = (state->initialLocalMatrix * parentTransform).GetRotation();
|
||||
}
|
||||
{
|
||||
//state->resultQuat = parentTransform.GetRotation() * state->initialLocalRotation;
|
||||
}
|
||||
|
||||
currentTransform.SetRotation(state->resultQuat);
|
||||
|
||||
// 揺れ骨計算結果を保持。これの子の揺れ骨のため。
|
||||
calcTransform.Add(j1.boneNo, currentTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VRM1SpringManager::applyToComponent(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) {
|
||||
|
||||
const auto RefSkeleton = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton();
|
||||
const auto& RefSkeletonTransform = Output.Pose.GetPose().GetBoneContainer().GetRefPoseArray();
|
||||
|
||||
// 計算した揺れ骨、または揺れ骨の親
|
||||
TMap<int, FTransform> calcTransform;
|
||||
|
||||
// 揺れ骨一覧
|
||||
TArray<int> springBoneNoList;
|
||||
{
|
||||
for (auto& s : vrmMetaObject->VRM1SpringBoneMeta.Springs) {
|
||||
for (auto& j : s.joints) {
|
||||
springBoneNoList.AddUnique(j.boneNo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& s : vrmMetaObject->VRM1SpringBoneMeta.Springs) {
|
||||
|
||||
FTransform CurrentTransForm;
|
||||
|
||||
for (int jointNo = 0; jointNo < s.joints.Num(); ++jointNo) {
|
||||
auto& j = s.joints[jointNo];
|
||||
|
||||
auto* state = JointStateMap.Find(j.boneNo);
|
||||
if (state == nullptr) continue;
|
||||
|
||||
FCompactPoseBoneIndex uu = Output.Pose.GetPose().GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(j.boneNo);
|
||||
//FCompactPoseBoneIndex uu(j.boneNo);
|
||||
|
||||
if (Output.Pose.GetPose().IsValidIndex(uu) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FTransform NewBoneTM;
|
||||
|
||||
int parentBoneIndex = RefSkeleton.GetParentIndex(j.boneNo);
|
||||
if (springBoneNoList.Find(parentBoneIndex) < 0) {
|
||||
// 親は揺れ骨でない。
|
||||
|
||||
// 現在値
|
||||
NewBoneTM = Output.Pose.GetComponentSpaceTransform(uu);
|
||||
|
||||
// 差分
|
||||
NewBoneTM.SetRotation(state->resultQuat);
|
||||
|
||||
CurrentTransForm = NewBoneTM;
|
||||
}
|
||||
else {
|
||||
// 親は揺れ骨。計算結果から参照する
|
||||
|
||||
auto* p = calcTransform.Find(parentBoneIndex);
|
||||
if (p) {
|
||||
NewBoneTM = *p;
|
||||
}
|
||||
|
||||
auto c = RefSkeletonTransform[j.boneNo];
|
||||
NewBoneTM = c * NewBoneTM;
|
||||
NewBoneTM.SetRotation(state->resultQuat);
|
||||
|
||||
CurrentTransForm = NewBoneTM;
|
||||
}
|
||||
|
||||
FBoneTransform a(uu, NewBoneTM);
|
||||
|
||||
bool bFirst = true;
|
||||
for (auto& t : OutBoneTransforms) {
|
||||
if (t.BoneIndex == a.BoneIndex) {
|
||||
bFirst = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFirst) {
|
||||
OutBoneTransforms.Add(a);
|
||||
}
|
||||
|
||||
|
||||
calcTransform.Add(j.boneNo, CurrentTransForm);
|
||||
// update rotation
|
||||
//FVector to = (state->currentTail * (node.parent.worldMatrix * state->initialLocalMatrix).inverse).normalized;
|
||||
//node.rotation = initialLocalRotation * Quaternion.fromToQuaternion(boneAxis, to);
|
||||
}
|
||||
}
|
||||
OutBoneTransforms.Sort(FCompareBoneTransformIndex());
|
||||
|
||||
}
|
||||
} //spring1
|
||||
@@ -0,0 +1,173 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
/*
|
||||
|
||||
// VRMSpringBone.cs
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 DWANGO Co., Ltd. for UniVRM
|
||||
Copyright (c) 2018 ousttrue for UniGLTF, UniHumanoid
|
||||
Copyright (c) 2018 Masataka SUMI for MToon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AnimNode_VrmSpringBone.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "SceneInterface.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
|
||||
class VRM4U_API VrmSpringBone{
|
||||
public:
|
||||
VrmSpringBone();
|
||||
~VrmSpringBone();
|
||||
};
|
||||
|
||||
namespace VRMSpringBone {
|
||||
class VRMSpringManagerBase {
|
||||
public:
|
||||
VRMSpringManagerBase() {}
|
||||
virtual ~VRMSpringManagerBase() {}
|
||||
bool bInit = false;
|
||||
USkeletalMesh* skeletalMesh = nullptr;
|
||||
const UVrmMetaObject* vrmMetaObject = nullptr;
|
||||
|
||||
virtual void init(const UVrmMetaObject* meta, FComponentSpacePoseContext& Output) {}
|
||||
virtual void update(const FAnimNode_VrmSpringBone* animNode, float DeltaTime, FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) {}
|
||||
virtual void reset() {}
|
||||
virtual void applyToComponent(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) {}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
namespace VRMSpringBone {
|
||||
|
||||
class VRMSpringCollider {
|
||||
public:
|
||||
FVector offset = FVector::ZeroVector;
|
||||
float radius = 0.f;
|
||||
};
|
||||
class VRMSpringColliderGroup {
|
||||
public:
|
||||
int node = 0;
|
||||
FName node_name;
|
||||
|
||||
TArray<VRMSpringCollider> colliders;
|
||||
};
|
||||
|
||||
class VRMSpringData {
|
||||
public:
|
||||
int boneIndex = -1;
|
||||
FName boneName;
|
||||
FVector m_currentTail = FVector::ZeroVector;
|
||||
FVector m_prevTail = FVector::ZeroVector;
|
||||
//FTransform m_transform = FTransform::Identity;
|
||||
FVector m_boneAxis = FVector::ForwardVector;
|
||||
float m_length = 1.f;
|
||||
|
||||
FQuat m_resultQuat = FQuat::Identity;
|
||||
};
|
||||
|
||||
class VRMSpring {
|
||||
public:
|
||||
float stiffness = 0.f;
|
||||
float gravityPower = 0.f;
|
||||
FVector gravityDir = { 0,0,0 };
|
||||
float dragForce = 0.f;
|
||||
float hitRadius = 0.f;
|
||||
|
||||
//int boneNum = 0;
|
||||
//int *bones;
|
||||
//FString bones_name;
|
||||
|
||||
//int colliderGourpNum = 0;
|
||||
//int* colliderGroups = nullptr;
|
||||
TArray<int> ColliderGroupIndexArray;
|
||||
|
||||
|
||||
TArray< TArray<VRMSpringData> > SpringDataChain;
|
||||
TArray<VRMSpringData> RootSpringData;
|
||||
|
||||
USkeletalMesh* skeletalMesh = nullptr;
|
||||
~VRMSpring() {
|
||||
skeletalMesh = nullptr;
|
||||
}
|
||||
|
||||
void Update(const FAnimNode_VrmSpringBone* animNode, float DeltaTime, FTransform center,
|
||||
const TArray<VRMSpringColliderGroup>& colliderGroup,
|
||||
FComponentSpacePoseContext& Output);
|
||||
};
|
||||
|
||||
class VRMSpringManager : public VRMSpringManagerBase {
|
||||
public:
|
||||
|
||||
virtual void init(const UVrmMetaObject* meta, FComponentSpacePoseContext& Output) override;
|
||||
virtual void update(const FAnimNode_VrmSpringBone* animNode, float DeltaTime, FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual void reset() override;
|
||||
|
||||
virtual void applyToComponent(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
|
||||
TArray<VRMSpring> spring;
|
||||
TArray<VRMSpringColliderGroup> colliderGroup;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace VRM1Spring {
|
||||
|
||||
class SpringBoneJointState {
|
||||
public:
|
||||
FVector prevTail;
|
||||
FVector currentTail;
|
||||
|
||||
FVector initialTail;
|
||||
FVector boneAxis;
|
||||
float boneLength = 0.f;
|
||||
FTransform initialLocalMatrix;
|
||||
FQuat initialLocalRotation;
|
||||
|
||||
FQuat resultQuat;
|
||||
};
|
||||
|
||||
|
||||
class VRM1SpringManager : public VRMSpringBone::VRMSpringManagerBase {
|
||||
public:
|
||||
|
||||
TMap< int, SpringBoneJointState > JointStateMap;
|
||||
|
||||
virtual void init(const UVrmMetaObject* meta, FComponentSpacePoseContext& Output) override;
|
||||
virtual void update(const FAnimNode_VrmSpringBone* animNode, float DeltaTime, FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual void reset() override;
|
||||
virtual void applyToComponent(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,145 @@
|
||||
// VRM4U Copyright (c) 2021-2022 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#include "VRM4U.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "UObject/UObjectHash.h"
|
||||
#include "UObject/UObjectIterator.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,3,0)
|
||||
#else
|
||||
#include "InterchangeHelper.h"
|
||||
#endif
|
||||
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
//same as URigHierarchy
|
||||
|
||||
void LocalSanitizeName(FString& InOutName)
|
||||
{
|
||||
// Sanitize the name
|
||||
for (int32 i = 0; i < InOutName.Len(); ++i)
|
||||
{
|
||||
TCHAR& C = InOutName[i];
|
||||
|
||||
const bool bGoodChar = FChar::IsAlpha(C) || // Any letter
|
||||
//(C == '_') || (C == '-') || (C == '.') || // _ - . anytime
|
||||
(FChar::IsDigit(C));// || // 0-9 anytime
|
||||
//((i > 0) && (C == ' ')); // Space after the first character to support virtual bones
|
||||
|
||||
/*
|
||||
const bool bGoodChar =
|
||||
((C >= 'A') && (C <= 'Z')) || ((C >= 'a') && (C <= 'z')) || // A-Z (upper and lowercase) anytime
|
||||
(C == '_') || // _ anytime
|
||||
((i > 0) && (C >= '0') && (C <= '9')); // 0-9 after the first character
|
||||
*/
|
||||
|
||||
if (!bGoodChar)
|
||||
{
|
||||
C = '_';
|
||||
}
|
||||
}
|
||||
|
||||
//if (InOutName.Len() > GetMaxNameLength())
|
||||
//{
|
||||
// InOutName.LeftChopInline(InOutName.Len() - GetMaxNameLength());
|
||||
//}
|
||||
}
|
||||
|
||||
FString LocalGetSanitizedName(const FString& InName)
|
||||
{
|
||||
FString Name = InName;
|
||||
LocalSanitizeName(Name);
|
||||
|
||||
return Name;
|
||||
}
|
||||
|
||||
FString LocalGetSafeNewName(const FString& InName, TFunction<bool(const FString&)> IsNameAvailableFunction)
|
||||
{
|
||||
check(IsNameAvailableFunction);
|
||||
|
||||
FString SanitizedName = InName;
|
||||
LocalSanitizeName(SanitizedName);
|
||||
FString Name = SanitizedName;
|
||||
|
||||
int32 Suffix = 1;
|
||||
while (!IsNameAvailableFunction(Name))
|
||||
{
|
||||
FString BaseString = SanitizedName;
|
||||
//if (BaseString.Len() > GetMaxNameLength() - 4)
|
||||
//{
|
||||
// BaseString.LeftChopInline(BaseString.Len() - (GetMaxNameLength() - 4));
|
||||
//}
|
||||
Name = *FString::Printf(TEXT("%s_%d"), *BaseString, ++Suffix);
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
|
||||
bool LocalIsNameAvailable(const FString& InName)// , ERigElementType InElementType, FString* OutErrorMessage)
|
||||
{
|
||||
FString UnsanitizedName = InName;
|
||||
|
||||
FString SanitizedName = UnsanitizedName;
|
||||
LocalSanitizeName(SanitizedName);
|
||||
|
||||
if (SanitizedName != UnsanitizedName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FString LocalGetSafeNewName(const FString& InPotentialNewName)
|
||||
{
|
||||
return LocalGetSafeNewName(InPotentialNewName, [](const FString& InName) -> bool {
|
||||
return LocalIsNameAvailable(InName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool VRMUtil::IsNoSafeName(const FString& str) {
|
||||
for (int i = 0; i < str.Len(); ++i) {
|
||||
if ((str[i] != '_') && (FString::Chr(str[i]).IsNumeric()==false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
FString VRMUtil::GetSafeNewName(const FString& str) {
|
||||
return LocalGetSafeNewName(str);
|
||||
}
|
||||
|
||||
FString VRMUtil::MakeName(const FString& str, bool IsJoint) {
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,22,0)
|
||||
return GetSafeNewName(str);
|
||||
#elif UE_VERSION_OLDER_THAN(5,3,0)
|
||||
const TCHAR* InvalidChar = IsJoint ? INVALID_OBJECTNAME_CHARACTERS TEXT("+ ") : INVALID_OBJECTNAME_CHARACTERS;
|
||||
FString TmpName = str;
|
||||
while (*InvalidChar)
|
||||
{
|
||||
TmpName.ReplaceCharInline(*InvalidChar, TCHAR('_'), ESearchCase::CaseSensitive);
|
||||
++InvalidChar;
|
||||
}
|
||||
return TmpName;
|
||||
#elif UE_VERSION_OLDER_THAN(5,7,0)
|
||||
return UE::Interchange::MakeName(str, IsJoint);
|
||||
#else
|
||||
return UE::Interchange::MakeSanitizedName(str, IsJoint);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FName VRMUtil::GetSanitizedName(const FString& str) {
|
||||
return *LocalGetSanitizedName(str);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "AnimNode_VrmConstraint.generated.h"
|
||||
|
||||
class UVrmMetaObject;
|
||||
class UVrmAssetListObject;
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4U_API FAnimNode_VrmConstraint : public FAnimNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
bool EnableAutoSearchMetaData = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta=(PinHiddenByDefault))
|
||||
const UVrmMetaObject *VrmMetaObject = nullptr;
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
TAssetPtr<UVrmMetaObject> VrmMetaObject_Internal = nullptr;
|
||||
TAssetPtr<UVrmAssetListObject> VrmAssetListObject_Internal = nullptr;
|
||||
#else
|
||||
TSoftObjectPtr<UVrmMetaObject> VrmMetaObject_Internal = nullptr;
|
||||
TSoftObjectPtr<UVrmAssetListObject> VrmAssetListObject_Internal = nullptr;
|
||||
#endif
|
||||
|
||||
|
||||
bool bCallInitialized = false;
|
||||
|
||||
bool bCallByAnimInstance = false;
|
||||
|
||||
FAnimNode_VrmConstraint();
|
||||
|
||||
void UpdateCache(FComponentSpacePoseContext& Output);
|
||||
|
||||
// FAnimNode_Base interface
|
||||
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
||||
// End of FAnimNode_Base interface
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) override;
|
||||
virtual void CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) override;
|
||||
// virtual void Update_AnyThread(const FAnimationUpdateContext& Context) override;
|
||||
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual void EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) override;
|
||||
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
||||
|
||||
virtual void UpdateInternal(const FAnimationUpdateContext& Context)override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
|
||||
virtual void ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground = false) const;
|
||||
|
||||
private:
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
|
||||
#include "AnimNode_VrmCopyHandBone.generated.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
class UVrmMetaObject;
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4U_API FAnimNode_VrmCopyHandBone : public FAnimNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Skeleton, meta=(PinShownByDefault))
|
||||
USkeletalMeshComponent *SkeletalMeshComponentLeft = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Skeleton, meta=(PinShownByDefault))
|
||||
USkeletalMeshComponent *SkeletalMeshComponentRight = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta=(PinShownByDefault))
|
||||
UVrmMetaObject *VrmMetaObject = nullptr;
|
||||
|
||||
FAnimNode_VrmCopyHandBone();
|
||||
|
||||
// FAnimNode_Base interface
|
||||
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
||||
// End of FAnimNode_Base interface
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
|
||||
private:
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
|
||||
#include "AnimNode_VrmModifyBoneDynamic.generated.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4U_API FAnimNode_VrmModifyBoneDynamic : public FAnimNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
/** Name of bone to control. This is the main bone chain to modify from. **/
|
||||
//UPROPERTY(EditAnywhere, Category=SkeletalControl)
|
||||
//FBoneReference BoneToModify;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=SkeletalControl, meta=(PinShownByDefault))
|
||||
FName BoneNameToModify;
|
||||
|
||||
/** New translation of bone to apply. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Translation, meta=(PinShownByDefault))
|
||||
FVector Translation;
|
||||
|
||||
/** New rotation of bone to apply. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Rotation, meta=(PinShownByDefault))
|
||||
FRotator Rotation;
|
||||
|
||||
/** New Scale of bone to apply. This is only worldspace. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Scale, meta=(PinShownByDefault))
|
||||
FVector Scale;
|
||||
|
||||
/** Whether and how to modify the translation of this bone. */
|
||||
UPROPERTY(EditAnywhere, Category=Translation)
|
||||
TEnumAsByte<EBoneModificationMode> TranslationMode;
|
||||
|
||||
/** Whether and how to modify the translation of this bone. */
|
||||
UPROPERTY(EditAnywhere, Category=Rotation)
|
||||
TEnumAsByte<EBoneModificationMode> RotationMode;
|
||||
|
||||
/** Whether and how to modify the translation of this bone. */
|
||||
UPROPERTY(EditAnywhere, Category=Scale)
|
||||
TEnumAsByte<EBoneModificationMode> ScaleMode;
|
||||
|
||||
/** Reference frame to apply Translation in. */
|
||||
UPROPERTY(EditAnywhere, Category=Translation)
|
||||
TEnumAsByte<enum EBoneControlSpace> TranslationSpace;
|
||||
|
||||
/** Reference frame to apply Rotation in. */
|
||||
UPROPERTY(EditAnywhere, Category=Rotation)
|
||||
TEnumAsByte<enum EBoneControlSpace> RotationSpace;
|
||||
|
||||
/** Reference frame to apply Scale in. */
|
||||
UPROPERTY(EditAnywhere, Category=Scale)
|
||||
TEnumAsByte<enum EBoneControlSpace> ScaleSpace;
|
||||
|
||||
FAnimNode_VrmModifyBoneDynamic();
|
||||
|
||||
// FAnimNode_Base interface
|
||||
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
||||
// End of FAnimNode_Base interface
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
|
||||
private:
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "AnimNode_VrmModifyBoneList.generated.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
class UVrmMetaObject;
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4U_API FAnimNode_VrmModifyBoneList : public FAnimNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
TMap<FString, FTransform> BoneTrans;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
TArray<FString> UseInputTransBoneList;
|
||||
|
||||
FAnimNode_VrmModifyBoneList();
|
||||
|
||||
// FAnimNode_Base interface
|
||||
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
||||
// End of FAnimNode_Base interface
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) override;
|
||||
virtual void CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) override;
|
||||
// virtual void Update_AnyThread(const FAnimationUpdateContext& Context) override;
|
||||
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual void EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) override;
|
||||
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
||||
|
||||
virtual void UpdateInternal(const FAnimationUpdateContext& Context)override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
|
||||
virtual void ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground = false) const;
|
||||
|
||||
private:
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "AnimNode_VrmModifyBoneListRetarget.generated.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
class UVrmMetaObject;
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4U_API FAnimNode_VrmModifyBoneListRetarget : public FAnimNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta=(PinHiddenByDefault))
|
||||
const UVrmMetaObject *VrmMetaObject = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
TMap<FString, FTransform> BoneTrans;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
bool bUseRemoteCenterPos = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
float ModelRelativeScale = 1.f;
|
||||
|
||||
FAnimNode_VrmModifyBoneListRetarget();
|
||||
|
||||
// FAnimNode_Base interface
|
||||
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
||||
// End of FAnimNode_Base interface
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) override;
|
||||
virtual void CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) override;
|
||||
// virtual void Update_AnyThread(const FAnimationUpdateContext& Context) override;
|
||||
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual void EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) override;
|
||||
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
||||
|
||||
virtual void UpdateInternal(const FAnimationUpdateContext& Context)override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
|
||||
virtual void ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground = false) const;
|
||||
|
||||
private:
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
};
|
||||
@@ -0,0 +1,88 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
|
||||
#include "AnimNode_VrmModifyHumanoidBone.generated.h"
|
||||
|
||||
class UVrmAssetListObject;
|
||||
class USkeletalMeshComponent;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FVRMBoneTransform
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
TArray<FTransform> Transform;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
TArray<bool> bEnableRotation;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
TArray<bool> bEnableTranslation;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
TArray<FName> VRMHumanoidBoneName;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4U_API FAnimNode_VrmModifyHumanoidBone : public FAnimNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
/** Name of bone to control. This is the main bone chain to modify from. **/
|
||||
//UPROPERTY(EditAnywhere, Category=SkeletalControl)
|
||||
//FBoneReference BoneToModify;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
UVrmAssetListObject *VrmAssetList = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = SkeletalControl, meta = (PinShownByDefault))
|
||||
FVRMBoneTransform HumanoidBoneTransform;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = SkeletalControl, meta = (PinShownByDefault))
|
||||
FVRMBoneTransform ExtBoneTransform;
|
||||
|
||||
/** Whether and how to modify the translation of this bone. */
|
||||
//UPROPERTY(EditAnywhere, Category=Translation)
|
||||
//TEnumAsByte<EBoneModificationMode> TranslationMode;
|
||||
|
||||
/** Whether and how to modify the translation of this bone. */
|
||||
//UPROPERTY(EditAnywhere, Category=Rotation)
|
||||
//TEnumAsByte<EBoneModificationMode> RotationMode;
|
||||
|
||||
|
||||
/** Reference frame to apply Translation in. */
|
||||
//UPROPERTY(EditAnywhere, Category=Translation)
|
||||
//TEnumAsByte<enum EBoneControlSpace> TranslationSpace;
|
||||
|
||||
/** Reference frame to apply Rotation in. */
|
||||
//UPROPERTY(EditAnywhere, Category=Rotation)
|
||||
TEnumAsByte<enum EBoneControlSpace> RotationSpace;
|
||||
|
||||
FAnimNode_VrmModifyHumanoidBone();
|
||||
|
||||
// FAnimNode_Base interface
|
||||
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
||||
// End of FAnimNode_Base interface
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
|
||||
private:
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "AnimNodes/AnimNode_PoseBlendNode.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "AnimNode_VrmPoseBlendNode.generated.h"
|
||||
|
||||
class UVrmMetaObject;
|
||||
class UVrmAssetListObject;
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4U_API FAnimNode_VrmPoseBlendNode : public FAnimNode_PoseBlendNode
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
bool EnableAutoSearchMetaData = true;
|
||||
|
||||
//UPROPERTY(EditAnywhere, EditFixedSize, BlueprintReadWrite, Category = Links)
|
||||
//FPoseLink SourcePose;
|
||||
|
||||
//UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta=(PinHiddenByDefault))
|
||||
//const UVrmMetaObject *VrmMetaObject = nullptr;
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
TAssetPtr<UVrmMetaObject> VrmMetaObject_Internal = nullptr;
|
||||
TAssetPtr<UVrmAssetListObject> VrmAssetListObject_Internal = nullptr;
|
||||
//TAssetPtr<FPoseLink> SourcePose_Internal = nullptr;
|
||||
#else
|
||||
TSoftObjectPtr<UVrmMetaObject> VrmMetaObject_Internal = nullptr;
|
||||
TSoftObjectPtr<UVrmAssetListObject> VrmAssetListObject_Internal = nullptr;
|
||||
//TSoftObjectPtr<FPoseLink> SourcePose_Internal = nullptr;
|
||||
#endif
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
bool bRemovePoseCurve = false;
|
||||
|
||||
|
||||
bool bCallInitialized = false;
|
||||
|
||||
bool bCallByAnimInstance = false;
|
||||
|
||||
FAnimNode_VrmPoseBlendNode();
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) override;
|
||||
|
||||
virtual void Evaluate_AnyThread(FPoseContext& Output) override;
|
||||
|
||||
|
||||
private:
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
|
||||
#include "AnimNode_VrmQuestHandBone.generated.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
class UVrmMetaObject;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FVRMQuestHandBone
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
TArray<FTransform> HandLeft;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
TArray<FTransform> HandRight;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4U_API FAnimNode_VrmQuestHandBone : public FAnimNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
UVrmMetaObject* VrmMetaObject = nullptr;
|
||||
|
||||
//UPROPERTY(EditAnywhere, Category = Rotation, meta = (PinHiddenByDefault))
|
||||
//TEnumAsByte<enum EBoneControlSpace> TransformSpace;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
FVRMQuestHandBone HandTransform;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
FVRMQuestHandBone HandReferenceTransform;
|
||||
|
||||
|
||||
FAnimNode_VrmQuestHandBone();
|
||||
|
||||
// FAnimNode_Base interface
|
||||
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
||||
// End of FAnimNode_Base interface
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
|
||||
private:
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "AnimNode_VrmRetargetFromMannequin.generated.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
class UVrmMetaObject;
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4U_API FAnimNode_VrmRetargetFromMannequin : public FAnimNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
/* If SourceMeshComponent is not valid, and if this is true, it will look for attached parent as a source */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category= Skeleton, meta = (NeverAsPin))
|
||||
bool bUseAttachedParent = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
TWeakObjectPtr<USkeletalMeshComponent> srcMannequinMesh= nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta=(PinHiddenByDefault))
|
||||
UVrmMetaObject *VrmMetaObject = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
bool bIgnoreCenterLocation = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
FVector CenterLocationScaleByHeightScale = { 1.0f, 1.0f, 1.0f }; // FVector(1.0f, 1.0f, 1.0f);
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
FVector CenterLocationOffset = { 0.0f, 0.0f, 0.0f }; // FVector(1.0f, 1.0f, 1.0f);
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
UVrmMetaObject *MannequinVrmMetaObject = nullptr;
|
||||
|
||||
FAnimNode_VrmRetargetFromMannequin();
|
||||
|
||||
UPROPERTY()
|
||||
USkeletalMesh *srcSkeletalMesh = nullptr;
|
||||
UPROPERTY()
|
||||
USkeletalMesh *dstSkeletalMesh = nullptr;
|
||||
|
||||
TArray<FTransform> srcRefSkeletonCompTransform;
|
||||
TArray<FTransform> dstRefSkeletonCompTransform;
|
||||
TArray<FTransform> dstCurrentSkeletonCompTransform;
|
||||
|
||||
void UpdateCache(FComponentSpacePoseContext& Output);
|
||||
|
||||
// FAnimNode_Base interface
|
||||
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
||||
// End of FAnimNode_Base interface
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) override;
|
||||
virtual void CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) override;
|
||||
// virtual void Update_AnyThread(const FAnimationUpdateContext& Context) override;
|
||||
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual void EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) override;
|
||||
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
||||
|
||||
virtual bool NeedsDynamicReset() const override { return true; }
|
||||
#if UE_VERSION_OLDER_THAN(4,20,0)
|
||||
#else
|
||||
virtual void ResetDynamics(ETeleportType InTeleportType) override;
|
||||
#endif
|
||||
|
||||
virtual bool HasPreUpdate() const override { return true; }
|
||||
virtual void PreUpdate(const UAnimInstance* InAnimInstance) override;
|
||||
virtual void UpdateInternal(const FAnimationUpdateContext& Context)override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
|
||||
virtual void ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground = false) const;
|
||||
|
||||
private:
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "AnimNode_VrmSpringBone.generated.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
class UVrmMetaObject;
|
||||
class UVrmAssetListObject;
|
||||
|
||||
namespace VRMSpringBone {
|
||||
class VRMSpringManagerBase;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4U_API FAnimNode_VrmSpringBone : public FAnimNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
bool EnableAutoSearchMetaData = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta=(PinHiddenByDefault))
|
||||
const UVrmMetaObject *VrmMetaObject = nullptr;
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
TAssetPtr<UVrmMetaObject> VrmMetaObject_Internal = nullptr;
|
||||
TAssetPtr<UVrmAssetListObject> VrmAssetListObject_Internal = nullptr;
|
||||
#else
|
||||
TSoftObjectPtr<UVrmMetaObject> VrmMetaObject_Internal = nullptr;
|
||||
TSoftObjectPtr<UVrmAssetListObject> VrmAssetListObject_Internal = nullptr;
|
||||
#endif
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
float gravityScale = 1.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
FVector gravityAdd = FVector::ZeroVector;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
float stiffnessScale = 1.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
float stiffnessAdd = 0.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
float randomWindRange = 0.2f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
float windScale = 1.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
int loopc = 1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
int collisionCheckLoopCount = 2;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
bool bIgnorePhysicsResetOnTeleport = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta=(PinHiddenByDefault))
|
||||
bool bIgnorePhysicsCollision = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta=(PinHiddenByDefault))
|
||||
bool bIgnoreVRMCollision = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
bool bIgnoreWindDirectionalSource = false;
|
||||
|
||||
//
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
TArray<FName> NoWindBoneNameList;
|
||||
|
||||
TSharedPtr<VRMSpringBone::VRMSpringManagerBase> SpringManager;
|
||||
|
||||
float CurrentDeltaTime = 0.f;
|
||||
|
||||
bool bCallByAnimInstance = false;
|
||||
TArray<FBoneTransform> BoneTransformsSpring;
|
||||
bool IsSpringInit() const;
|
||||
|
||||
FAnimNode_VrmSpringBone();
|
||||
|
||||
// FAnimNode_Base interface
|
||||
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
||||
// End of FAnimNode_Base interface
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) override;
|
||||
virtual void Initialize_AnyThread_local(const FAnimationInitializeContext& Context);
|
||||
virtual void CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) override;
|
||||
// virtual void Update_AnyThread(const FAnimationUpdateContext& Context) override;
|
||||
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual void EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) override;
|
||||
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
||||
|
||||
virtual bool NeedsDynamicReset() const override { return true; }
|
||||
#if UE_VERSION_OLDER_THAN(4,20,0)
|
||||
#else
|
||||
virtual void ResetDynamics(ETeleportType InTeleportType) override;
|
||||
#endif
|
||||
|
||||
virtual void UpdateInternal(const FAnimationUpdateContext& Context)override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
|
||||
virtual void ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground = false) const;
|
||||
|
||||
private:
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "Units/RigUnit.h"
|
||||
#include "ControlRigDefines.h"
|
||||
|
||||
#include "RigUnit_VrmDynamicHierarchy.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
* get curve list
|
||||
*/
|
||||
USTRUCT(meta = (DisplayName = "VRM4U GetCurveNameFromMesh", Keywords = "VRM4U", Varying))
|
||||
struct FRigUnit_VRMGetCurveNameFromMesh : public FRigUnitMutable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FRigUnit_VRMGetCurveNameFromMesh()
|
||||
{
|
||||
}
|
||||
|
||||
RIGVM_METHOD()
|
||||
virtual void Execute() override;
|
||||
|
||||
UPROPERTY(meta = (Output))
|
||||
TArray<FName> Items_Morph;
|
||||
|
||||
UPROPERTY(meta = (Output))
|
||||
TArray<FName> Items_Curve;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* add morph and curve
|
||||
*/
|
||||
USTRUCT(meta=(DisplayName="VRM4U AddCurveFromMesh", Keywords="AddCurve,Spawn", Varying))
|
||||
struct FRigUnit_VRMAddCurveFromMesh : public FRigUnitMutable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FRigUnit_VRMAddCurveFromMesh()
|
||||
{
|
||||
}
|
||||
|
||||
RIGVM_METHOD()
|
||||
virtual void Execute() override;
|
||||
|
||||
UPROPERTY(meta = (Input))
|
||||
FString Prefix = TEXT("");
|
||||
|
||||
UPROPERTY(meta = (Input))
|
||||
FString Suffix = TEXT("_c");
|
||||
|
||||
UPROPERTY(meta = (Input))
|
||||
bool bIncludeMorphs = true;
|
||||
|
||||
UPROPERTY(meta = (Input))
|
||||
bool bIncludeCurves = true;
|
||||
|
||||
UPROPERTY(meta = (Output))
|
||||
TArray<FRigElementKey> Items_Morph;
|
||||
|
||||
UPROPERTY(meta = (Output))
|
||||
TArray<FRigElementKey> Items_Curve;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* generate contorl to bone table
|
||||
*/
|
||||
USTRUCT(meta = (DisplayName = "VRM4U GenerateTable", Keywords = "Table", Varying))
|
||||
struct FRigUnit_VRMGenerateBoneToControlTable: public FRigUnitMutable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FRigUnit_VRMGenerateBoneToControlTable()
|
||||
{
|
||||
}
|
||||
|
||||
RIGVM_METHOD()
|
||||
virtual void Execute() override;
|
||||
|
||||
UPROPERTY(meta = (Output))
|
||||
TArray<FName> Items_MannequinBone;
|
||||
|
||||
UPROPERTY(meta = (Output))
|
||||
TArray<FName> Items_VRMBone;
|
||||
};
|
||||
|
||||
/**
|
||||
* init controller transform
|
||||
*/
|
||||
USTRUCT(meta = (DisplayName = "VRM4U InitController Transform", Keywords = "Table", Varying))
|
||||
struct FRigUnit_VRMInitControllerTransform: public FRigUnitMutable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FRigUnit_VRMInitControllerTransform()
|
||||
{
|
||||
}
|
||||
|
||||
RIGVM_METHOD()
|
||||
virtual void Execute() override;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
//#include "Engine.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogVRM4U, Verbose, All);
|
||||
|
||||
#define SPRITER_IMPORT_ERROR(FormatString, ...) \
|
||||
if (!bSilent) { UE_LOG(LogVRM4U, Warning, FormatString, __VA_ARGS__); }
|
||||
#define SPRITER_IMPORT_WARNING(FormatString, ...) \
|
||||
if (!bSilent) { UE_LOG(LogVRM4U, Warning, FormatString, __VA_ARGS__); }
|
||||
|
||||
|
||||
|
||||
class FVRM4UModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/EngineSubsystem.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
#include "VRM4U_AnimSubsystem.generated.h"
|
||||
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,22,0)
|
||||
|
||||
//Couldn't find parent type for 'VRM4U_AnimSubsystem' named 'UEngineSubsystem'
|
||||
#error "please remove VRM4U_AnimSubsystem.h/cpp for <=UE4.21"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
USTRUCT()
|
||||
struct FVrmTransformData {
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
int port = 0;
|
||||
|
||||
// UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = VRM4U)
|
||||
UPROPERTY()
|
||||
TMap<FString, FTransform> BoneTransform;
|
||||
|
||||
// UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = VRM4U)
|
||||
UPROPERTY()
|
||||
TMap<FString, FTransform> RawData;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class VRM4U_API UVRM4U_AnimSubsystem : public UEngineSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FCriticalSection cs;
|
||||
|
||||
public:
|
||||
|
||||
// TMap<FString, FTransform>;
|
||||
|
||||
TArray<FVrmTransformData> baseData;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
void Clear();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
void GetBoneByIndex(int index, TMap<FString, FTransform>&trans);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
void GetBoneByPort(int port, TMap<FString, FTransform>& trans);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
void GetRawdataByIndex(int index, TMap<FString, FTransform>& trans);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
void GetRawdataByPort(int port, TMap<FString, FTransform>& trans);
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
void SetBoneTransform(int port, const TMap<FString, FTransform>& trans);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
void SetRawData(int port, const TMap<FString, FTransform>& trans);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
|
||||
//#if WITH_EDITOR
|
||||
//#include "UnrealEd.h"
|
||||
//#include "AssetTypeActions_Base.h"
|
||||
//#endif
|
||||
|
||||
#include "Vrm1LicenseObject.generated.h"
|
||||
|
||||
class UTexture2D;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
USTRUCT(BlueprintType, meta = (AutoExpandCategories = "License"))
|
||||
struct FLicenseStringDataPair {
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License")
|
||||
FString key;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License")
|
||||
FString value;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, meta = (AutoExpandCategories = "License"))
|
||||
struct FLicenseStringDataArray {
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License")
|
||||
FString key;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License")
|
||||
TArray<FString> value;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType, meta = (AutoExpandCategories = "License"))
|
||||
struct FLicenseBoolDataPair {
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License")
|
||||
FString key;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License")
|
||||
bool value = false;
|
||||
};
|
||||
|
||||
UCLASS(Blueprintable, BlueprintType, meta = (AutoExpandCategories = "License"))
|
||||
class VRM4U_API UVrm1LicenseObject : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Information)
|
||||
UTexture2D* thumbnail = nullptr;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License")
|
||||
TArray<FLicenseStringDataPair> LicenseString;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License")
|
||||
TArray<FLicenseStringDataArray> LicenseStringArray;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License")
|
||||
TArray<FLicenseBoolDataPair> LicenseBool;
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Animation/AnimInstance.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "VrmAnimInstance.generated.h"
|
||||
|
||||
class UVrmMetaObject;
|
||||
class USkeleton;
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EVRMBlendShapeGroup : uint8
|
||||
{
|
||||
BSG_Neutoral UMETA(DisplayName="00_Neutoral"),
|
||||
BSG_A UMETA(DisplayName="01_A"),
|
||||
BSG_I UMETA(DisplayName="02_I"),
|
||||
BSG_U UMETA(DisplayName="03_U"),
|
||||
BSG_E UMETA(DisplayName="04_E"),
|
||||
BSG_O UMETA(DisplayName="05_O"),
|
||||
BSG_Blink UMETA(DisplayName="06_Blink"),
|
||||
BSG_Joy UMETA(DisplayName="07_Joy"),
|
||||
BSG_Angry UMETA(DisplayName="08_Angry"),
|
||||
BSG_Sorrow UMETA(DisplayName="09_Sorrow"),
|
||||
BSG_Fun UMETA(DisplayName="10_Fun"),
|
||||
BSG_LookUp UMETA(DisplayName="11_LookUp"),
|
||||
BSG_LookDown UMETA(DisplayName="12_LookDown"),
|
||||
BSG_LookLeft UMETA(DisplayName="13_LookLeft"),
|
||||
BSG_LookRight UMETA(DisplayName="14_LookRight"),
|
||||
BSG_Blink_L UMETA(DisplayName="15_Blink_L"),
|
||||
BSG_Blink_R UMETA(DisplayName="16_Blink_R"),
|
||||
Num UMETA(Hidden)
|
||||
};
|
||||
|
||||
|
||||
USTRUCT()
|
||||
struct VRM4U_API FVrmAnimInstanceProxy : public FAnimInstanceProxy {
|
||||
|
||||
public:
|
||||
GENERATED_BODY()
|
||||
|
||||
FVrmAnimInstanceProxy()
|
||||
{
|
||||
}
|
||||
|
||||
FVrmAnimInstanceProxy(UAnimInstance* InAnimInstance)
|
||||
: FAnimInstanceProxy(InAnimInstance)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Initialize(UAnimInstance* InAnimInstance) override;
|
||||
virtual bool Evaluate(FPoseContext& Output) override;
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,24,0)
|
||||
virtual void UpdateAnimationNode(float DeltaSeconds) override;
|
||||
#else
|
||||
virtual void UpdateAnimationNode(const FAnimationUpdateContext& InContext);
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class VRM4U_API UVrmAnimInstance : public UAnimInstance
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
UVrmMetaObject *MetaObject;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
USkeleton *BaseSkeleton;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
USkeletalMeshComponent *BaseSkeletalMeshComponent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tracking)
|
||||
FTransform TransHandLeft;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tracking)
|
||||
FTransform TransHandRight;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tracking)
|
||||
FTransform TransHead;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tracking)
|
||||
USceneComponent *ComponentHandLeft;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tracking)
|
||||
USceneComponent *ComponentHandRight;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tracking)
|
||||
USceneComponent *ComponentHead;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tracking)
|
||||
USceneComponent *ComponentHandJointTargetLeft;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tracking)
|
||||
USceneComponent *ComponentHandJointTargetRight;
|
||||
|
||||
protected:
|
||||
virtual FAnimInstanceProxy* CreateAnimInstanceProxy() override;
|
||||
public:
|
||||
virtual void NativeInitializeAnimation()override;
|
||||
// Native update override point. It is usually a good idea to simply gather data in this step and
|
||||
// for the bulk of the work to be done in NativeUpdateAnimation.
|
||||
virtual void NativeUpdateAnimation(float DeltaSeconds)override;
|
||||
// Native Post Evaluate override point
|
||||
virtual void NativePostEvaluateAnimation()override;
|
||||
// Native Uninitialize override point
|
||||
virtual void NativeUninitializeAnimation()override;
|
||||
|
||||
// Executed when begin play is called on the owning component
|
||||
virtual void NativeBeginPlay()override;
|
||||
|
||||
//virtual USkeleton* GetTargetSkeleton() const override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Animation")
|
||||
void SetMorphTargetVRM(EVRMBlendShapeGroup type, float Value);
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Animation")
|
||||
void SetVrmData(USkeletalMeshComponent *baseSkeletalMesh, UVrmMetaObject *meta);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,142 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Animation/AnimInstance.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Animation/AnimNodeBase.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "VrmAnimInstanceCopy.generated.h"
|
||||
|
||||
class UVrmAssetListObject;
|
||||
struct FAnimNode_VrmSpringBone;
|
||||
struct FAnimNode_VrmConstraint;
|
||||
|
||||
USTRUCT()
|
||||
struct VRM4U_API FVrmAnimInstanceCopyProxy : public FAnimInstanceProxy {
|
||||
|
||||
public:
|
||||
GENERATED_BODY()
|
||||
|
||||
float CurrentDeltaTime = 0.f;
|
||||
bool bIgnoreVRMSwingBone = false;
|
||||
bool bIgnoreVRMConstraint = false;
|
||||
bool bIgnoreWindDirectionalSource = false;
|
||||
int CalcCount = 0;
|
||||
TSharedPtr<FAnimNode_VrmSpringBone> Node_SpringBone;
|
||||
TSharedPtr<FAnimNode_VrmConstraint> Node_Constraint;
|
||||
|
||||
bool bUseAnimStop = false;
|
||||
bool bAnimStop = false;
|
||||
bool bIgnoreCenterLocation = false;
|
||||
FVector CenterLocationScaleByHeightScale = { 1.f, 1.f, 1.f };
|
||||
FVector CenterLocationOffset = {0.f, 0.f, 0.f};
|
||||
bool bCopyStop = false;
|
||||
FCompactHeapPose CachedPose;
|
||||
|
||||
FVrmAnimInstanceCopyProxy();
|
||||
|
||||
FVrmAnimInstanceCopyProxy(UAnimInstance* InAnimInstance);
|
||||
|
||||
virtual void Initialize(UAnimInstance* InAnimInstance) override;
|
||||
virtual bool Evaluate(FPoseContext& Output) override;
|
||||
#if UE_VERSION_OLDER_THAN(4,24,0)
|
||||
virtual void UpdateAnimationNode(float DeltaSeconds) override;
|
||||
#else
|
||||
virtual void UpdateAnimationNode(const FAnimationUpdateContext& InContext);
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class VRM4U_API UVrmAnimInstanceCopy : public UAnimInstance
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category= Rendering, meta = (NeverAsPin))
|
||||
bool bUseAttachedParent = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
USkeletalMeshComponent *SrcSkeletalMeshComponent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
USkinnedMeshComponent* SrcAsSkinnedMeshComponent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
UVrmAssetListObject *SrcVrmAssetList;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
UVrmMetaObject* SrcVrmMetaOverride;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
UVrmAssetListObject *DstVrmAssetList;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
UVrmMetaObject *DstVrmMetaForCustomSpring;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FName> InitialMorphName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<float> InitialMorphValue;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
bool bUseAnimStop = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
bool bAnimStop = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
bool bCopyStop = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
bool bIgnoreCenterLocation = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVector CenterLocationScaleByHeightScale = {1.f, 1.f, 1.f};
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVector CenterLocationOffset = { 0.f, 0.f, 0.f };
|
||||
|
||||
protected:
|
||||
virtual FAnimInstanceProxy* CreateAnimInstanceProxy() override;
|
||||
|
||||
FVrmAnimInstanceCopyProxy *myProxy = nullptr;
|
||||
bool bIgnoreVRMSwingBone = false;
|
||||
bool bIgnoreWindDirectionalSource = false;
|
||||
public:
|
||||
virtual void NativeInitializeAnimation()override;
|
||||
// Native update override point. It is usually a good idea to simply gather data in this step and
|
||||
// for the bulk of the work to be done in NativeUpdateAnimation.
|
||||
virtual void NativeUpdateAnimation(float DeltaSeconds)override;
|
||||
// Native Post Evaluate override point
|
||||
virtual void NativePostEvaluateAnimation()override;
|
||||
// Native Uninitialize override point
|
||||
virtual void NativeUninitializeAnimation()override;
|
||||
|
||||
// Executed when begin play is called on the owning component
|
||||
virtual void NativeBeginPlay()override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetSkeletalMeshCopyData(UVrmAssetListObject *dstAssetList, USkeletalMeshComponent *srcSkeletalMesh, USkinnedMeshComponent* srcSkinnedMesh, UVrmAssetListObject *srcAssetList, UVrmMetaObject* srcVrmMetaOption);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetSkeletalMeshCopyDataForCustomSpring(UVrmMetaObject *dstMetaForCustomSpring);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetVrmSpringBoneParam(float gravityScale = 1.f, FVector gravityAdd = FVector::ZeroVector, float stiffnessScale = 1.f, float stiffnessAdd = 0.f, float randomWindRange = 0.2f);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetVrmSpringBoneBool(bool bIgnoreVrmSpringBone = false, bool bIgnorePhysicsCollision = false, bool bIgnoreVRMCollision = false, bool bIgnoreWind = false);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetVrmSpringBoneIgnoreWingBone(const TArray<FName> &boneNameList);
|
||||
|
||||
FVrmAnimInstanceCopyProxy *GetProxy() { return myProxy; }
|
||||
};
|
||||
@@ -0,0 +1,151 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Animation/AnimInstance.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Animation/AnimNodeBase.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,2,0)
|
||||
static_assert(0, "Available for UE5.2+. delete h/cpp files");
|
||||
#endif
|
||||
|
||||
#include "Retargeter/IKRetargeter.h"
|
||||
#include "VrmAnimInstanceRetargetFromMannequin.generated.h"
|
||||
|
||||
class UVrmAssetListObject;
|
||||
struct FAnimNode_VrmSpringBone;
|
||||
struct FAnimNode_VrmConstraint;
|
||||
struct FAnimNode_RetargetPoseFromMesh;
|
||||
|
||||
USTRUCT()
|
||||
struct VRM4U_API FVrmAnimInstanceRetargetFromMannequinProxy : public FAnimInstanceProxy {
|
||||
|
||||
public:
|
||||
GENERATED_BODY()
|
||||
|
||||
float CurrentDeltaTime = 0.f;
|
||||
bool bUseRetargeter = false;
|
||||
bool bIgnoreVRMSwingBone = false;
|
||||
bool bIgnoreVRMConstraint = false;
|
||||
bool bIgnoreWindDirectionalSource = false;
|
||||
int CalcCount = 0;
|
||||
TSharedPtr<FAnimNode_VrmSpringBone> Node_SpringBone;
|
||||
TSharedPtr<FAnimNode_VrmConstraint> Node_Constraint;
|
||||
#if UE_VERSION_OLDER_THAN(5,2,0)
|
||||
#else
|
||||
//TWeakObjectPtr<USkeletalMeshComponent> RetargetSourceMeshComponent = nullptr;
|
||||
TSoftObjectPtr<UIKRetargeter> Retargeter;
|
||||
TSharedPtr<FAnimNode_RetargetPoseFromMesh> Node_Retarget;
|
||||
|
||||
void CustomInitialize();
|
||||
#endif
|
||||
|
||||
FCompactHeapPose CachedPose;
|
||||
|
||||
FVrmAnimInstanceRetargetFromMannequinProxy();
|
||||
|
||||
FVrmAnimInstanceRetargetFromMannequinProxy(UAnimInstance* InAnimInstance);
|
||||
|
||||
virtual void Initialize(UAnimInstance* InAnimInstance) override;
|
||||
virtual bool Evaluate(FPoseContext& Output) override;
|
||||
|
||||
virtual void UpdateAnimationNode(const FAnimationUpdateContext& InContext);
|
||||
|
||||
virtual void PreUpdate(UAnimInstance* InAnimInstance, float DeltaSeconds);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class VRM4U_API UVrmAnimInstanceRetargetFromMannequin : public UAnimInstance
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category= Rendering, meta = (NeverAsPin))
|
||||
bool bUseAttachedParent = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
USkeletalMeshComponent *SrcSkeletalMeshComponent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
USkinnedMeshComponent* SrcAsSkinnedMeshComponent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
UVrmAssetListObject *DstVrmAssetList;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
UVrmMetaObject *DstVrmMetaForCustomSpring;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FName> InitialMorphName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<float> InitialMorphValue;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
bool bUseAnimStop = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
bool bAnimStop = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
bool bCopyStop = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
bool bIgnoreCenterLocation = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVector CenterLocationScaleByHeightScale = {1.f, 1.f, 1.f};
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVector CenterLocationOffset = { 0.f, 0.f, 0.f };
|
||||
|
||||
protected:
|
||||
virtual FAnimInstanceProxy* CreateAnimInstanceProxy() override;
|
||||
|
||||
virtual bool CanRunParallelWork() const { return false; }
|
||||
|
||||
FVrmAnimInstanceRetargetFromMannequinProxy *myProxy = nullptr;
|
||||
bool bIgnoreVRMSwingBone = false;
|
||||
bool bIgnoreWindDirectionalSource = false;
|
||||
public:
|
||||
virtual void NativeInitializeAnimation()override;
|
||||
// Native update override point. It is usually a good idea to simply gather data in this step and
|
||||
// for the bulk of the work to be done in NativeUpdateAnimation.
|
||||
virtual void NativeUpdateAnimation(float DeltaSeconds)override;
|
||||
// Native Post Evaluate override point
|
||||
virtual void NativePostEvaluateAnimation()override;
|
||||
// Native Uninitialize override point
|
||||
virtual void NativeUninitializeAnimation()override;
|
||||
|
||||
// Executed when begin play is called on the owning component
|
||||
virtual void NativeBeginPlay()override;
|
||||
virtual void PreUpdateAnimation(float DeltaSeconds) override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetRetargetData(bool bUseRetargeter, UIKRetargeter *IKRetargeter);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetVrmAssetList(UVrmAssetListObject *dstAssetList);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetSkeletalMeshCopyDataForCustomSpring(UVrmMetaObject *dstMetaForCustomSpring);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetVrmSpringBoneParam(float gravityScale = 1.f, FVector gravityAdd = FVector::ZeroVector, float stiffnessScale = 1.f, float stiffnessAdd = 0.f, float randomWindRange = 0.2f);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetVrmSpringBoneBool(bool bIgnoreVrmSpringBone = false, bool bIgnorePhysicsCollision = false, bool bIgnoreVRMCollision = false, bool bIgnoreWind = false);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetVrmSpringBoneIgnoreWingBone(const TArray<FName> &boneNameList);
|
||||
|
||||
FVrmAnimInstanceRetargetFromMannequinProxy*GetProxy() { return myProxy; }
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Animation/AnimInstance.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Animation/AnimNodeBase.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "VrmAnimInstanceTemplate.generated.h"
|
||||
|
||||
class UIKRetargeter;
|
||||
class UVrmMetaObject;
|
||||
|
||||
USTRUCT()
|
||||
struct VRM4U_API FVrmAnimInstanceTemplateProxy : public FAnimInstanceProxy {
|
||||
|
||||
public:
|
||||
GENERATED_BODY()
|
||||
|
||||
FVrmAnimInstanceTemplateProxy();
|
||||
FVrmAnimInstanceTemplateProxy(UAnimInstance* InAnimInstance);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class VRM4U_API UVrmAnimInstanceTemplate : public UAnimInstance
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = VRM4U)
|
||||
UIKRetargeter *VrmRetargeter = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = VRM4U)
|
||||
UVrmMetaObject* VrmMetaObject = nullptr;
|
||||
|
||||
protected:
|
||||
virtual FAnimInstanceProxy* CreateAnimInstanceProxy() override;
|
||||
|
||||
FVrmAnimInstanceTemplateProxy *myProxy = nullptr;
|
||||
public:
|
||||
FVrmAnimInstanceTemplateProxy *GetProxy() { return myProxy; }
|
||||
};
|
||||
@@ -0,0 +1,286 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "Animation/Skeleton.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
#include "VrmImportMaterialSet.h"
|
||||
#include "VrmUtil.h"
|
||||
#include "VrmAssetListObject.generated.h"
|
||||
|
||||
class UMaterialInterface;
|
||||
class UTexture2D;
|
||||
class USkeletalMesh;
|
||||
class USkeleton;
|
||||
class UVrmMetaObject;
|
||||
class UVrmLicenseObject;
|
||||
class UVrm1LicenseObject;
|
||||
struct FReturnedData;
|
||||
class UNodeMappingContainer;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class VRM4U_API UVrmAssetListObject : public UObject
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
void CopyMember(UVrmAssetListObject *dst) const;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InOption")
|
||||
bool bAssetSave = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InOption")
|
||||
bool bSkipMorphTarget=false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UVrmImportMaterialSet* MtoonLitSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UVrmImportMaterialSet* MtoonUnlitSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UVrmImportMaterialSet* SSSSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UVrmImportMaterialSet* SSSProfileSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UVrmImportMaterialSet* UnlitSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UVrmImportMaterialSet* GLTFSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UVrmImportMaterialSet* UEFNUnlitSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UVrmImportMaterialSet* UEFNLitSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UVrmImportMaterialSet* UEFNSSSProfileSet;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UVrmImportMaterialSet* CustomSet;
|
||||
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_Lit")
|
||||
UMaterialInterface* BaseMToonLitOpaqueMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_Lit")
|
||||
UMaterialInterface* BaseMToonLitTranslucentMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_Lit")
|
||||
UMaterialInterface* OptMToonLitOpaqueMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_Lit")
|
||||
UMaterialInterface* OptMToonLitOpaqueTwoSidedMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_Lit")
|
||||
UMaterialInterface* OptMToonLitTranslucentMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_Lit")
|
||||
UMaterialInterface* OptMToonLitTranslucentTwoSidedMaterial;
|
||||
|
||||
// unlit
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_unlit")
|
||||
UMaterialInterface* BaseMToonUnlitOpaqueMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_unlit")
|
||||
UMaterialInterface* BaseMToonUnlitTranslucentMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_Unlit")
|
||||
UMaterialInterface* OptMToonUnlitOpaqueMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_Unlit")
|
||||
UMaterialInterface* OptMToonUnlitOpaqueTwoSidedMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_Unlit")
|
||||
UMaterialInterface* OptMToonUnlitTranslucentMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon_Unlit")
|
||||
UMaterialInterface* OptMToonUnlitTranslucentTwoSidedMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial_MToon")
|
||||
UMaterialInterface* OptMToonOutlineMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UMaterialInterface* BaseUnlitOpaqueMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UMaterialInterface* BaseUnlitTranslucentMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "InMaterial")
|
||||
UMaterialInterface* BasePBROpaqueMaterial;
|
||||
|
||||
//
|
||||
|
||||
//UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
//USkeleton* BaseSkeleton;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
USkeletalMesh* BaseSkeletalMesh;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
UVrmMetaObject* VrmMetaObject;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
UVrmMetaObject* VrmHumanoidMetaObject;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
UVrmMetaObject* VrmMannequinMetaObject;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
UVrmLicenseObject* VrmLicenseObject;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
UVrm1LicenseObject* Vrm1LicenseObject;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
USkeletalMesh* SkeletalMesh;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
TArray<UTexture2D*> Textures;
|
||||
|
||||
#if WITH_EDITORONLY_DATA
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
UTexture2D* SmallThumbnailTexture;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
UObject* SSSProfile;
|
||||
#endif
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
EVRMImportMaterialType ImportMode;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
TArray<UMaterialInterface*> Materials;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
TArray<UMaterialInterface*> OutlineMaterials;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
UNodeMappingContainer *HumanoidRig;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
UPoseAsset *PoseBody;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
UPoseAsset *PoseFace;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
TArray<bool> MaterialFlag_Translucent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
TArray<bool> MaterialFlag_TwoSided;
|
||||
|
||||
// no uproperty
|
||||
TArray<bool> MaterialFlag_Opaque;
|
||||
TMap<FString, FTransform> Pose_bind;
|
||||
TMap<FString, FTransform> Pose_tpose;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
FTransform model_root_transform;
|
||||
|
||||
//TArray<FTransform> poseGlobal_bindpose; // bone
|
||||
//TArray<FTransform> poseGlobal_tpose; // node
|
||||
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
EVRMImportTextureCompressType Texture_CompressType = EVRMImportTextureCompressType::VRMITC_Auto;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Out")
|
||||
TArray<EVRMImportTextureCompressType> Texture_CompressTypeList;
|
||||
|
||||
UPROPERTY()
|
||||
UPackage *Package;
|
||||
|
||||
UPROPERTY()
|
||||
UVrmAssetListObject* ReimportBase;
|
||||
|
||||
UPROPERTY()
|
||||
FString FileFullPathName;
|
||||
|
||||
UPROPERTY()
|
||||
FString OrigFileName;
|
||||
|
||||
UPROPERTY()
|
||||
FString BaseFileName;
|
||||
|
||||
UPROPERTY()
|
||||
USkeletalMesh* UE4SkeletalMesh;
|
||||
|
||||
UPROPERTY()
|
||||
USkeletalMesh* HumanoidSkeletalMesh;
|
||||
|
||||
TMap<int, int> MaterialMergeTable;
|
||||
|
||||
TMap<FString, FString> MaterialNameOrigToAsset;
|
||||
TMap<FString, int> MaterialNameAssetToMatNo;
|
||||
|
||||
TArray<bool> MaterialHasAlphaCutoff;
|
||||
|
||||
TArray<bool> MaterialHasMToon;
|
||||
|
||||
TSharedPtr<FReturnedData> MeshReturnedData;
|
||||
//FReturnedData *Result;
|
||||
|
||||
#if WITH_EDITORONLY_DATA
|
||||
|
||||
//#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
// typedef LocalImportData UAssetImportData;
|
||||
//#else
|
||||
// typedef LocalImportData TObjectPtr<class UAssetImportData>
|
||||
//#endif
|
||||
|
||||
// VRM4U_PRECOMPILE_500
|
||||
UPROPERTY(VisibleAnywhere, Instanced, Category = ImportSettings)
|
||||
class UAssetImportData *AssetImportData = nullptr;
|
||||
//TObjectPtr<class UAssetImportData> AssetImportData;
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
//class UAssetImportData* AssetImportData = nullptr;
|
||||
#else
|
||||
//TObjectPtr<class UAssetImportData> AssetImportData;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if WITH_EDITOR
|
||||
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,4,0)
|
||||
virtual void GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const override;
|
||||
#else
|
||||
virtual void GetAssetRegistryTags(FAssetRegistryTagsContext Context) const override;
|
||||
#endif
|
||||
// Import data for this
|
||||
void WaitUntilAsyncPropertyReleased() const;
|
||||
|
||||
|
||||
class UAssetImportData* GetAssetImportData() const
|
||||
{
|
||||
//WaitUntilAsyncPropertyReleased(ESkeletalMeshAsyncProperties::AssetImportData);
|
||||
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
return AssetImportData;
|
||||
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
||||
}
|
||||
|
||||
void SetAssetImportData(class UAssetImportData* InAssetImportData)
|
||||
{
|
||||
//WaitUntilAsyncPropertyReleased(ESkeletalMeshAsyncProperties::AssetImportData);
|
||||
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
AssetImportData = InAssetImportData;
|
||||
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/AssetUserData.h"
|
||||
#include "VrmAssetUserData.generated.h"
|
||||
|
||||
class UVrmAssetListObject;
|
||||
|
||||
UCLASS(BlueprintType)
|
||||
class VRM4U_API UVrmAssetUserData : public UAssetUserData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
TObjectPtr<UVrmAssetListObject> VrmAssetListObject = nullptr;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,271 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "Engine/EngineTypes.h"
|
||||
#include "Engine/TextureRenderTarget2D.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
#include "Engine/Scene.h"
|
||||
#include "LiveLinkTypes.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,26,0)
|
||||
#else
|
||||
#include "AssetRegistry/AssetData.h"
|
||||
#endif
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,20,0)
|
||||
struct FCameraTrackingFocusSettings {
|
||||
int dummy;
|
||||
};
|
||||
#elif UE_VERSION_OLDER_THAN(5,3,0)
|
||||
#include "CinematicCamera/Public/CineCameraComponent.h"
|
||||
#else
|
||||
#include "CineCameraComponent.h"
|
||||
#endif
|
||||
|
||||
#include "VrmBPFunctionLibrary.generated.h"
|
||||
|
||||
class UTextureRenderTarget2D;
|
||||
class UMaterialInstanceConstant;
|
||||
class UAnimationAsset;
|
||||
class USkeleton;
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,20,0)
|
||||
struct FCameraFilmbackSettings {
|
||||
public:
|
||||
int dummy = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EVRMWidgetMode : uint8
|
||||
{
|
||||
WM_Translate,
|
||||
WM_Rotate,
|
||||
WM_Scale,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class VRM4U_API UVrmBPFunctionLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable,Category="VRM4U")
|
||||
static void VRMTransMatrix(const FTransform &transform, TArray<FLinearColor> &matrix, TArray<FLinearColor> &matrix_inv);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static void VRMGetMorphTargetList(const USkeletalMesh *target, TArray<FString> &morphTargetList);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static bool VRMGetRefBoneTransform(const USkeleton *target, const FName boneName, FTransform &boneTransform);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static void VRMGetHumanoidBoneNameList(TArray<FString> &BoneNameListString, TArray<FName> &BoneNameListName);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static void VRMGetEpicSkeletonBoneNameList(TArray<FString>& BoneNameListString, TArray<FName>& BoneNameListName);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMGetEpicSkeletonToHumanoid(TMap<FString, FString>& table);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static bool VRMGetHumanoidParentBone(const FName boneName, FName &parentBoneName);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMInitAnim(USkeletalMeshComponent *target);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMUpdateRefPose(USkeletalMeshComponent* target, bool bForceAlignGlobal, bool bForceUE4Humanoid);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static void VRMGetMaterialPropertyOverrides(const UMaterialInterface *Material, TEnumAsByte<EBlendMode> &BlendMode, TEnumAsByte<EMaterialShadingModel> &ShadingModel, bool &IsTwoSided, bool &IsMasked);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static void VRMGetMobileMode(bool &IsMobile, bool &IsAndroid, bool &IsIOS);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject", UnsafeDuringActorConstruction = "true"))
|
||||
static void VRMDrawMaterialToRenderTarget(UObject* WorldContextObject, UTextureRenderTarget2D* TextureRenderTarget, UMaterialInterface* Material);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMUpdateTextureProperty(UTexture* Texture);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMChangeMaterialParent(UMaterialInstanceConstant *dst, UMaterialInterface* NewParent, USkeletalMesh *UseSkeletalMesh);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMChangeMaterialTexture(UMaterialInstanceConstant *dst, FName texName, UTexture *texture);
|
||||
|
||||
// mat begin
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMChangeMaterialSkipEditChange(UMaterialInstanceConstant *material, USkeletalMesh *UseSkeletalMesh, bool bSkip);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMChangeMaterialShadingModel(UMaterialInstanceConstant *material, EMaterialShadingModel ShadingModel, bool bOverride, bool bForce);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMChangeMaterialBlendMode(UMaterialInstanceConstant *material, EBlendMode BlendMode, bool bOverride, bool bForce);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMChangeMaterialScalarParameter(UMaterialInstanceConstant *material, FName paramName, float param, bool bEnable);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMChangeMaterialVectorParameter(UMaterialInstanceConstant *material, FName paramName, FLinearColor param, bool bEnable);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMChangeMaterialStaticSwitch(UMaterialInstanceConstant *material, FName paramName, bool bEnable);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (DevelopmentOnly))
|
||||
static void VRMGetMaterialStaticSwitch(UMaterialInstance* material, FName paramName, bool &bHasParam, bool &bEnable);
|
||||
|
||||
// mat end
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static UObject* VRMDuplicateAsset(UObject *src, FString name, UObject *thisOwner);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMSetMaterial(USkeletalMesh *target, int no, UMaterialInterface *material);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMSetImportedBounds(USkeletalMesh *target, FVector min, FVector max);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static bool VRMGetAssetsByPackageName(FName PackageName, TArray<FAssetData>& OutAssetData, bool bIncludeOnlyOnDiskAssets = false);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMSetIsDirty(UObject *obj);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static UTextureRenderTarget2D* VRMCreateRenderTarget2D(UObject* WorldContextObject, int32 Width = 256, int32 Height = 256, ETextureRenderTargetFormat Format = RTF_RGBA16f, FLinearColor ClearColor = FLinearColor::Black);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static bool VRMRenderingThreadEnable(bool bEnable);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static int VRMGetMeshSectionNum(const USkeletalMesh* mesh);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static bool VRMRemoveMeshSection(USkeletalMesh* mesh, int LODIndex, int SectionIndex);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static bool VRMGetShadowEnable(const USkeletalMesh *mesh, int MaterialIndex);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMSetLightingChannelPrim(UPrimitiveComponent *prim, bool channel0, bool channel1, bool channel2);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMSetLightingChannelLight(ULightComponent *light, bool channel0, bool channel1, bool channel2);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMSetCastRaytracedShadow(ULightComponent *light, bool bEnable);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMSetShadowSlopeBias(ULightComponent *light, float bias=0.5f);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMSetSpecularScale(ULightComponent* light, float scale=1.0f);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMSetPostProcessSettingAO(FPostProcessSettings& OutSettings, const FPostProcessSettings& InSettings, bool bOverride, float AOIntensity, float Radius, bool bRayTracing = true);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U", meta = (DynamicOutputParam = "filmback"))
|
||||
static bool VRMGetCameraFilmback(UCineCameraComponent *CineCamera, FCameraFilmbackSettings &filmback);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static bool VRMSetCameraFilmback(UCineCameraComponent *CineCamera, const FCameraFilmbackSettings &filmback);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static bool VRMSetPostProcessSettingFromCineCamera(FPostProcessSettings &OutSettings, const FPostProcessSettings &InSettings, const UCineCameraComponent *CineCamera);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMSetPostProcessToneCurveAmount(FPostProcessSettings& OutSettings, const FPostProcessSettings& InSettings, bool bOverride, float Amount);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U", meta = (DynamicOutputParam = "Settings"))
|
||||
static void VRMMakeCameraTrackingFocusSettings(AActor *ActorToTrack, FVector RelativeOffset, bool bDrawDebugTrackingFocusPoint, FCameraTrackingFocusSettings &Settings);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (DynamicOutputParam = "Settings"))
|
||||
static void VRMSetActorLabel(AActor *Actor, const FString& NewActorLabel);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U", meta = (WorldContext = "WorldContextObject", DynamicOutputParam = "transform"))
|
||||
static void VRMGetCameraTransform(const UObject* WorldContextObject, int32 PlayerIndex, bool bGameOnly, FTransform &transform, float &fovDegree);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMGetPlayMode(bool &bPlay, bool &bSIE, bool &bIsEditor);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U", meta = (WorldContext = "WorldContextObject", DynamicOutputParam = "skeleton"))
|
||||
static bool VRMGetAnimationAssetData(const UAnimationAsset *animAsset, USkeleton *&skeleton);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMExecuteConsoleCommand(UObject* WorldContextObject, const FString &cmd);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static bool VRMSetTransparentWindow(bool bEnable, FLinearColor crKey);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static bool VRMAddTickPrerequisite(UActorComponent *dst, UActorComponent *src, bool bRemove);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMAllowTranslucentSelection(bool bEnable);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject"))
|
||||
static void VRMSetWidgetMode(const EVRMWidgetMode mode);
|
||||
|
||||
//UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (DynamicOutputParam = "PropertyNames|PropertyValues|FrameNo"))
|
||||
//static bool VRMLiveLinkEvaluate(const FName Subject, TArray<FName> &PropertyNames, TArray<float> &PropertyValues, int &FrameNo);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (DevelopmentOnly))
|
||||
static bool VRMBakeAnim(const USkeletalMeshComponent* skc, const FString& FilePath, const FString& AssetFileName);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject", DeterminesOutputType = "UObjectClass", DynamicOutputParam = "OutActors"))
|
||||
static void VRMGetAllActorsHasSceneComponent(const UObject* WorldContextObject, TSubclassOf<UObject> UObjectClass, TArray<AActor*>& OutActors);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static void VRMGetUEVersion(int& major, int& minor, int& patch) {
|
||||
major = ENGINE_MAJOR_VERSION;
|
||||
minor = ENGINE_MINOR_VERSION;
|
||||
patch = ENGINE_PATCH_VERSION;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (WorldContext = "WorldContextObject", DynamicOutputParam = "RigNodeName"))
|
||||
static void VRMGetRigNodeNameFromBoneName(const USkeleton *skeleton, const FName &boneName, FName &RigNodeName);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMSetPerBoneMotionBlur(USkinnedMeshComponent* SkinnedMesh, bool bUsePerBoneMotionBlur);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMGetIKRigDefinition(UObject *retargeter, UObject *& src, UObject *& target);
|
||||
//static void GetIKRigDefinition(UIKRetargeter, UIKRigDefinition * &src, UIKRigDefinition * &target)
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static void VRMGetPreviewMesh(UObject* target, USkeletalMesh*& mesh);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U", meta = (DynamicOutputParam = "skeletalmesh"))
|
||||
static void VRMGetSkeletalMeshFromSkinnedMeshComponent(const USkinnedMeshComponent* target, USkeletalMesh*& skeletalmesh);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U", meta = (DynamicOutputParam = "AssetName"))
|
||||
static void VRMGetTopLevelAssetName(const FAssetData& target, FName& AssetName);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static UVrmAssetListObject* VRMGetVrmAssetListObjectFromAsset(const UObject *Asset);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static bool VRMIsMovieRendering();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static bool VRMIsTemporaryObject(const UObject *obj);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static bool VRMIsEditorPreviewObject(const UObject* obj);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
static void VRMGetViewportSize(FIntPoint &ViewportSize, FIntPoint &BufferSize);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/PoseableMeshComponent.h"
|
||||
#include "Misc/CoreDelegates.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
#include "Editor/UnrealEdTypes.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "VrmCameraCheckComponent.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(meta=(BlueprintSpawnableComponent))
|
||||
class VRM4U_API UVrmCameraCheckComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FVrmCameraCheckDelegate);
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FVrmCameraCheckDelegate OnCameraMove;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U", meta = (DynamicOutputParam = "OutVrmAsset"))
|
||||
void SetCameraCheck(bool bCheckOn);
|
||||
|
||||
public:
|
||||
void OnRegister() override;
|
||||
void OnUnregister() override;
|
||||
|
||||
private:
|
||||
#if WITH_EDITOR
|
||||
void OnCameraTransformChanged(const FVector&, const FRotator&, ELevelViewportType, int32);
|
||||
#endif
|
||||
|
||||
FDelegateHandle handle;
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CineCameraActor.h"
|
||||
|
||||
#include "VrmCineCameraActor.generated.h"
|
||||
|
||||
|
||||
UCLASS(ClassGroup = Common, hideCategories = (Input, Rendering, AutoPlayerActivation), showcategories = ("Input|MouseInput", "Input|TouchInput"), Blueprintable)
|
||||
class VRM4U_API AVrmCineCameraActor : public ACineCameraActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Ctor
|
||||
AVrmCineCameraActor(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Camera")
|
||||
UVrmCineCameraComponent* GetVrmCineCameraComponent() const;
|
||||
|
||||
public:
|
||||
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CineCameraComponent.h"
|
||||
|
||||
#include "VrmCineCameraComponent.generated.h"
|
||||
|
||||
|
||||
UCLASS(Blueprintable, ClassGroup = Camera, meta=(BlueprintSpawnableComponent))
|
||||
class VRM4U_API UVrmCineCameraComponent : public UCineCameraComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
virtual void OnRegister() override;
|
||||
#if WITH_EDITORONLY_DATA
|
||||
// Refreshes the visual components to match the component state
|
||||
virtual void RefreshVisualRepresentation() override;
|
||||
#endif
|
||||
|
||||
|
||||
virtual void GetCameraView(float DeltaTime, FMinimalViewInfo& DesiredView) override;
|
||||
|
||||
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "Vrm Camera Settings")
|
||||
FVector2D OffCenterProjectionOffset;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
|
||||
#include "VrmCustomStruct.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FVRMRetargetSrcAnimSequence
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
class UAnimSequenceBase *AnimSequence = nullptr;
|
||||
};
|
||||
|
||||
|
||||
namespace {
|
||||
//bool operator<(const FBoneTransform &a, const FBoneTransform &b) {
|
||||
// return a.BoneIndex < b.BoneIndex;
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "Components/PrimitiveComponent.h"
|
||||
#include "Components/DrawFrustumComponent.h"
|
||||
#include "VrmDrawFrustumComponent.generated.h"
|
||||
|
||||
class FPrimitiveSceneProxy;
|
||||
|
||||
/**
|
||||
* Utility component for drawing a view frustum. Origin is at the component location, frustum points down position X axis.
|
||||
*/
|
||||
|
||||
UCLASS(collapsecategories, hidecategories=Object, editinlinenew, MinimalAPI)
|
||||
class UVrmDrawFrustumComponent : public UDrawFrustumComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
virtual FPrimitiveSceneProxy* CreateSceneProxy() override;
|
||||
virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override;
|
||||
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = DrawFrustumComponent)
|
||||
FVector2D OffCenterProjectionOffset;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
// ApplicationLifecycleComponent.: See FCoreDelegates for details
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "Misc/CoreDelegates.h"
|
||||
#include "VrmDropFiles.generated.h"
|
||||
|
||||
// A parallel enum to the temperature change severity enum in CoreDelegates
|
||||
// Note if you change this, then you must change the one in CoreDelegates
|
||||
/*
|
||||
UENUM(BlueprintType)
|
||||
enum class ETemperatureSeverityType : uint8
|
||||
{
|
||||
Unknown,
|
||||
Good,
|
||||
Bad,
|
||||
Serious,
|
||||
Critical,
|
||||
|
||||
NumSeverities,
|
||||
};
|
||||
*/
|
||||
//static_assert((int)ETemperatureSeverityType::NumSeverities == (int)FCoreDelegates::ETemperatureSeverity::NumSeverities, "TemperatureSeverity enums are out of sync");
|
||||
|
||||
/** Component to handle receiving notifications from the OS about application state (activated, suspended, termination, etc). */
|
||||
UCLASS(ClassGroup=Utility, HideCategories=(Activation, "Components|Activation", Collision), meta=(BlueprintSpawnableComponent))
|
||||
class VRM4U_API UVrmDropFilesComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
//DECLARE_DYNAMIC_MULTICAST_DELEGATE(FApplicationLifetimeDelegate);
|
||||
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTemperatureChangeDelegate , ETemperatureSeverityType, Severity);
|
||||
//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLowPowerModeDelegate, bool, bInLowPowerMode);
|
||||
|
||||
DECLARE_MULTICAST_DELEGATE_OneParam(FStaticOnDropFiles, FString);
|
||||
static FStaticOnDropFiles StaticOnDropFilesDelegate;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnDropFiles, FString, FileName);
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnDropFiles OnDropFiles;
|
||||
|
||||
static UVrmDropFilesComponent *s_LatestActiveComponent;
|
||||
|
||||
public:
|
||||
void OnRegister() override;
|
||||
void OnUnregister() override;
|
||||
|
||||
static const UVrmDropFilesComponent* getLatestActiveComponent() {
|
||||
return s_LatestActiveComponent;
|
||||
};
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
bool VRMGetOpenFileName(FString &Filename);
|
||||
|
||||
private:
|
||||
/** Native handlers that get registered with the actual FCoreDelegates, and then proceed to broadcast to the delegates above */
|
||||
/*
|
||||
void ApplicationWillDeactivateDelegate_Handler() { ApplicationWillDeactivateDelegate.Broadcast(); }
|
||||
void ApplicationHasReactivatedDelegate_Handler() { ApplicationHasReactivatedDelegate.Broadcast(); }
|
||||
void ApplicationWillEnterBackgroundDelegate_Handler() { ApplicationWillEnterBackgroundDelegate.Broadcast(); }
|
||||
void ApplicationHasEnteredForegroundDelegate_Handler() { ApplicationHasEnteredForegroundDelegate.Broadcast(); }
|
||||
void ApplicationWillTerminateDelegate_Handler() { ApplicationWillTerminateDelegate.Broadcast(); }
|
||||
void ApplicationShouldUnloadResourcesDelegate_Handler() { ApplicationShouldUnloadResourcesDelegate.Broadcast(); }
|
||||
void ApplicationReceivedStartupArgumentsDelegate_Handler(const TArray<FString>& StartupArguments) { ApplicationReceivedStartupArgumentsDelegate.Broadcast(StartupArguments); }
|
||||
void OnTemperatureChangeDelegate_Handler(FCoreDelegates::ETemperatureSeverity Severity) { OnTemperatureChangeDelegate.Broadcast((ETemperatureSeverityType)Severity); }
|
||||
void OnLowPowerModeDelegate_Handler(bool bInLowerPowerMode) { OnLowPowerModeDelegate.Broadcast(bInLowerPowerMode); }
|
||||
*/
|
||||
void OnDropFilesDelegate_Handler(FString FileName) { OnDropFiles.Broadcast(FileName); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/PoseableMeshComponent.h"
|
||||
#include "Misc/CoreDelegates.h"
|
||||
|
||||
#include "VrmEditorEventComponent.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EVRM4U_PIEEvent : uint8
|
||||
{
|
||||
PreBeginPIE,
|
||||
BeginPIE,
|
||||
PrePIEEnded,
|
||||
PostPIEStarted,
|
||||
EndPIE,
|
||||
PausePIE,
|
||||
ResumePIE,
|
||||
SingleStepPIE,
|
||||
OnPreSwitchBeginPIEAndSIE,
|
||||
OnSwitchBeginPIEAndSIE,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(meta=(BlueprintSpawnableComponent))
|
||||
class VRM4U_API UVrmEditorEventComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FVrmSelectionChangedEventDelegate, bool, dummy);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FVrmSelectionObjectEventDelegate, bool, dummy);
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FVrmSelectionChangedEventDelegate OnSelectionChange;
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FVrmSelectionObjectEventDelegate OnSelectionObject;
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetSelectCheck(bool bCheckOn);
|
||||
|
||||
//
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FVrmPIEEventDelegate, EVRM4U_PIEEvent, dummy);
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FVrmPIEEventDelegate OnPIEEvent;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetPIEEventCheck(bool bCheckOn);
|
||||
|
||||
//
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FVrmGlobalTimeChangeEventDelegate, float, CurrentTime);
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FVrmGlobalTimeChangeEventDelegate OnGlobalTimeChange;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetGlobalTimeCheck(bool bCheckOn);
|
||||
|
||||
public:
|
||||
void OnRegister() override;
|
||||
void OnUnregister() override;
|
||||
|
||||
private:
|
||||
|
||||
void OnSelectionObjectFunc(UObject *obj);
|
||||
void OnSelectionChangeFunc(UObject *obj);
|
||||
|
||||
void OnGlobalTimeChangeFunc();
|
||||
|
||||
/*
|
||||
PreBeginPIE,
|
||||
BeginPIE,
|
||||
PrePIEEnded,
|
||||
PostPIEStarted,
|
||||
EndPIE,
|
||||
PausePIE,
|
||||
ResumePIE,
|
||||
SingleStepPIE,
|
||||
OnPreSwitchBeginPIEAndSIE,
|
||||
OnSwitchBeginPIEAndSIE,
|
||||
*/
|
||||
void OnBeginPIE(const bool bIsSimulating);
|
||||
void OnEndPIE(const bool bIsSimulating);
|
||||
void OnPIEEventFunc(EVRM4U_PIEEvent e);
|
||||
|
||||
FDelegateHandle handle;
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/DataAsset.h"
|
||||
#include "VrmImportMaterialSet.generated.h"
|
||||
|
||||
class UMaterialInterface;
|
||||
|
||||
UCLASS(BlueprintType)
|
||||
class VRM4U_API UVrmImportMaterialSet : public UDataAsset{
|
||||
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Material")
|
||||
UMaterialInterface* Opaque;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Material")
|
||||
UMaterialInterface* OpaqueTwoSided;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Material")
|
||||
UMaterialInterface* Translucent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Material")
|
||||
UMaterialInterface* TranslucentTwoSided;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
|
||||
//#if WITH_EDITOR
|
||||
//#include "UnrealEd.h"
|
||||
//#include "AssetTypeActions_Base.h"
|
||||
//#endif
|
||||
|
||||
#include "VrmLicenseObject.generated.h"
|
||||
|
||||
class UTexture2D;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class VRM4U_API UVrmLicenseObject : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Information)
|
||||
FString title;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Information)
|
||||
FString version;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Information)
|
||||
FString author;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Information)
|
||||
FString contactInformation;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Information)
|
||||
FString reference;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Information)
|
||||
UTexture2D *thumbnail;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License_Personation/CharacterizationPermission")
|
||||
FString allowedUserName;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License_Personation/CharacterizationPermission")
|
||||
FString violentUsageName;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License_Personation/CharacterizationPermission")
|
||||
FString sexualUsageName;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License_Personation/CharacterizationPermission")
|
||||
FString commercialUsageName;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License_Personation/CharacterizationPermission")
|
||||
FString otherPermissionUrl;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License_Redistribution/ModificationsLicense")
|
||||
FString licenseName;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "License_Redistribution/ModificationsLicense")
|
||||
FString otherLicenseUrl;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
#if WITH_EDITOR
|
||||
class FAssetTypeActions_VrmLicenseObject : public FAssetTypeActions_Base
|
||||
{
|
||||
public:
|
||||
virtual FText GetName() const override
|
||||
{ return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_MyAsset", "MyAsset"); }
|
||||
virtual FColor GetTypeColor() const override { return FColor::White; }
|
||||
virtual uint32 GetCategories() override { return EAssetTypeCategories::Misc; }
|
||||
virtual UClass* GetSupportedClass() const override {
|
||||
return UVrmLicenseObject::StaticClass();
|
||||
};
|
||||
virtual bool IsImportedAsset() const override { return false; }
|
||||
};
|
||||
#endif
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "VrmMetaObject.generated.h"
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMSpringMeta{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float stiffness = 0.2f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float gravityPower = 0.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVector gravityDir = { 0,-1,0 };
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float dragForce = 0.4f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float hitRadius = 0.f;
|
||||
|
||||
//UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
//int boneNum = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<int> bones;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FString> boneNames;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<int> ColliderIndexArray;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<int> ColliderGroupArrayVRM10; // for datacheck
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMSpringColliderData {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVector offset = FVector::ZeroVector;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float radius = 0.f;
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMColliderGroupMeta {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString groupName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<int> colliderGroup;
|
||||
};
|
||||
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMColliderMeta {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int bone = -1;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString boneName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVRMSpringColliderData> collider;
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRM1SpringJointMeta {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int boneNo = -1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString boneName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float hitRadius = 0.1f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float stiffness = 0.5f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float gravityPower = 1.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVector gravityDir = { 0,-1,0 };
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float dragForce = 0.5f;
|
||||
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRM1SpringMeta {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVRM1SpringJointMeta> joints;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<int> colliderGroups;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int center = 0;
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRM1SpringCollider {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int boneNo = -1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString boneName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FName shapeType;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVector offset = FVector::ZeroVector;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float radius = 0.f;
|
||||
|
||||
// for capsule. offset-tail cylinder
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVector tail = FVector::ZeroVector;
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRM1SpringColliderGroups {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString name;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<int> colliders;
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRM1SpringBoneMeta {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVRM1SpringMeta> Springs;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVRM1SpringCollider> Colliders;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVRM1SpringColliderGroups> ColliderGroups;
|
||||
};
|
||||
|
||||
|
||||
//////
|
||||
|
||||
|
||||
|
||||
// BlendShape
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVrmBlendShape{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString morphTargetName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString nodeName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString meshName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int meshID=0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int shapeIndex=0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int weight=100;
|
||||
};
|
||||
|
||||
// BlendShape Material
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVrmBlendShapeMaterialList {
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString materialName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString propertyName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FLinearColor color = FLinearColor::Black;
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVrmBlendShapeGroup {
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString name;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVrmBlendShape> BlendShape;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVrmBlendShapeMaterialList> MaterialList;
|
||||
|
||||
// vrm10
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
bool isBinary = false;
|
||||
|
||||
// none, block, blend
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString overrideBlink;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString overrideLookAt;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString overrideMouth;
|
||||
|
||||
};
|
||||
|
||||
//struct VRM4U_API FBVrmlendShapeGroup {
|
||||
// TArray<FVrmBlendShape>
|
||||
//};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EVRMConstraintType : uint8 {
|
||||
None, Roll, Aim, Rotation,
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMConstraintRoll {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString sourceName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int source = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString rollAxis;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float weight = 1.f;
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMConstraintAim {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString sourceName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int source = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString aimAxis;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float weight = 1.f;
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMConstraintRotation {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString sourceName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int source = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
float weight = 1.f;
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMAnimationLookAt {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int lookAtNode = -1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString lookAtNodeName;
|
||||
};
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMAnimationExpressionPreset {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString expressionName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int expressionNode = -1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FString expressionNodeName;
|
||||
};
|
||||
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMAnimationMeta {
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVRMAnimationLookAt lookAt;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVRMAnimationExpressionPreset> expressionPreset;
|
||||
|
||||
};
|
||||
|
||||
|
||||
USTRUCT(Blueprintable, BlueprintType)
|
||||
struct VRM4U_API FVRMConstraint {
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
EVRMConstraintType type = EVRMConstraintType::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVRMConstraintRoll constraintRoll;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVRMConstraintAim constraintAim;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVRMConstraintRotation constraintRotation;
|
||||
};
|
||||
|
||||
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class VRM4U_API UVrmMetaObject : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
int Version = 0;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "VRM4U")
|
||||
int GetVRMVersion() const {
|
||||
return Version;
|
||||
}
|
||||
|
||||
// humanoid name -> model name
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TMap<FString, FString> humanoidBoneTable;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVrmBlendShapeGroup> BlendShapeGroup;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVRMSpringMeta> VRMSpringMeta;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVRM1SpringBoneMeta VRM1SpringBoneMeta;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVRMColliderMeta> VRMColliderMeta;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<FVRMColliderGroupMeta> VRMColliderGroupMeta;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TMap<FString, FVRMConstraint> VRMConstraintMeta;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
FVRMAnimationMeta VRMAnimationMeta;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
class USkeletalMesh *SkeletalMesh;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
class UVrmAssetListObject *VrmAssetListObject;
|
||||
|
||||
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "VrmModelActor.generated.h"
|
||||
|
||||
class USkeletalMesh;
|
||||
|
||||
UCLASS()
|
||||
class VRM4U_API AVrmModelActor : public AActor
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
UMaterialInterface* BaseOpaqueMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
UMaterialInterface* BaseTransparentMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<UTexture2D*> Textures;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
TArray<UMaterialInterface*> Materials;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Rendering)
|
||||
USkeletalMesh* SkeletalMesh;
|
||||
|
||||
protected:
|
||||
// Called when the game starts or when spawned
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
public:
|
||||
// Called every frame
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
//virtual void OnConstruction(const FTransform& Transform)override;
|
||||
|
||||
|
||||
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "Engine/EngineTypes.h"
|
||||
|
||||
|
||||
#include "VrmNetworkBPFunctionLibrary.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class VRM4U_API UVrmNetworkBPFunctionLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static void VRMGetIPAddressTable(TArray<FString> &AddressTable);
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/PoseableMeshComponent.h"
|
||||
#include "VrmPoseableMeshComponent.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable, meta=(BlueprintSpawnableComponent))
|
||||
class VRM4U_API UVrmPoseableMeshComponent : public UPoseableMeshComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
bool bUseParentAsLeader = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
bool bUseDefaultMaterial = false;
|
||||
|
||||
void OnRegister() override;
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "VRM4U")
|
||||
void Init();
|
||||
|
||||
virtual void RefreshBoneTransforms(FActorComponentTickFunction* TickFunction = NULL) override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Components|PoseableMesh")
|
||||
void VRMCopyPoseAndMorphFromSkeletalComponent(USkeletalMeshComponent* InComponentToCopy);
|
||||
|
||||
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;
|
||||
|
||||
virtual void UpdateLeader();
|
||||
|
||||
virtual void InitializeComponent() override;
|
||||
virtual void OnAttachmentChanged() override;
|
||||
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
virtual void PostEditChangeChainProperty(struct FPropertyChangedChainEvent& PropertyChangedEvent) override;
|
||||
#endif
|
||||
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
|
||||
#elif UE_VERSION_OLDER_THAN(5,2,0)
|
||||
|
||||
#include "UObject/UnrealTypePrivate.h"
|
||||
#include "IKRigDefinition.h"
|
||||
#include "IKRigSolver.h"
|
||||
#include "Retargeter/IKRetargeter.h"
|
||||
#if WITH_EDITOR
|
||||
#include "RigEditor/IKRigController.h"
|
||||
#include "RetargetEditor/IKRetargeterController.h"
|
||||
#include "Solvers/IKRig_PBIKSolver.h"
|
||||
#endif
|
||||
|
||||
#elif UE_VERSION_OLDER_THAN(5,3,0)
|
||||
|
||||
#include "UObject/UnrealTypePrivate.h"
|
||||
#include "IKRigDefinition.h"
|
||||
#include "IKRigSolver.h"
|
||||
#include "Retargeter/IKRetargeter.h"
|
||||
#if WITH_EDITOR
|
||||
#include "RigEditor/IKRigController.h"
|
||||
#include "RetargetEditor/IKRetargeterController.h"
|
||||
#include "Solvers/IKRig_FBIKSolver.h"
|
||||
#endif
|
||||
|
||||
#elif UE_VERSION_OLDER_THAN(5,6,0)
|
||||
|
||||
#include "UObject/UnrealTypePrivate.h"
|
||||
#include "Rig/IKRigDefinition.h"
|
||||
#include "Rig/Solvers/IKRigSolver.h"
|
||||
#include "Retargeter/IKRetargeter.h"
|
||||
#if WITH_EDITOR
|
||||
#include "RigEditor/IKRigController.h"
|
||||
#include "RetargetEditor/IKRetargeterController.h"
|
||||
#include "Rig/Solvers/IKRig_FBIKSolver.h"
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include "UObject/UnrealTypePrivate.h"
|
||||
#include "Rig/IKRigDefinition.h"
|
||||
#include "Rig/Solvers/IKRigFullBodyIK.h"
|
||||
#include "Retargeter/IKRetargeter.h"
|
||||
#if WITH_EDITOR
|
||||
#include "RigEditor/IKRigController.h"
|
||||
#include "RetargetEditor/IKRetargeterController.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
//#include "VrmAssetListObject.h"
|
||||
#include "VrmRuntimeSettings.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(config=Engine, defaultconfig)
|
||||
class VRM4U_API UVrmRuntimeSettings : public UObject
|
||||
{
|
||||
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
// Enables experimental *incomplete and unsupported* texture atlas groups that sprites can be assigned to
|
||||
//UPROPERTY(EditAnywhere, config, Category=Settings)
|
||||
//bool bEnableSpriteAtlasGroups;
|
||||
|
||||
/** For runtime load sample map */
|
||||
UPROPERTY(config, EditAnywhere, Category = Settings, meta = (
|
||||
ConfigRestartRequired=true
|
||||
))
|
||||
uint32 bDropVRMFileEnable:1;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = Settings, meta = (
|
||||
ConfigRestartRequired = true
|
||||
))
|
||||
bool bAllowAllAssimpFormat = false;
|
||||
|
||||
//UPROPERTY(config, EditAnywhere, Category = Settings, meta = (AllowedClasses = "VrmAssetListObject", ExactClass = false))
|
||||
|
||||
/** Default material set for runtimeload */
|
||||
UPROPERTY(config, EditAnywhere, Category = Settings, meta = (
|
||||
AllowedClasses = "/Script/CoreUObject.Object",
|
||||
ExactClass = false
|
||||
))
|
||||
FSoftObjectPath AssetListObject;
|
||||
|
||||
/** priority<100 for VRM4U. Default plugins priority=100 */
|
||||
UPROPERTY(config, EditAnywhere, Category = Settings, meta = (
|
||||
ConfigRestartRequired = true
|
||||
))
|
||||
int32 ImportPriority = 90;
|
||||
|
||||
UPROPERTY(config, EditAnywhere, Category = Settings, meta = (
|
||||
ConfigRestartRequired = true
|
||||
))
|
||||
TArray<FString> extList;
|
||||
|
||||
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent);
|
||||
#endif
|
||||
|
||||
};
|
||||
@@ -0,0 +1,589 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "Engine/Texture.h"
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,1,0)
|
||||
#else
|
||||
#include "Engine/SkinnedAssetCommon.h"
|
||||
#include "Engine/SkinnedAsset.h"
|
||||
#endif
|
||||
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "VrmUtil.generated.h"
|
||||
|
||||
class USkeleton;
|
||||
struct FReferenceSkeleton;
|
||||
class UMorphTarget;
|
||||
class UPhysicsAsset;
|
||||
struct FSkeletalMaterial;
|
||||
|
||||
// skeleton begin
|
||||
|
||||
template<typename T>
|
||||
USkeleton* VRMGetSkeleton(T* t){
|
||||
if (t == nullptr) return nullptr;
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->Skeleton;
|
||||
#else
|
||||
return t->GetSkeleton();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
#else
|
||||
template<typename T>
|
||||
USkeleton* VRMGetSkeleton(TObjectPtr<T> t) {
|
||||
return t->GetSkeleton();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
const USkeleton* VRMGetSkeleton(const T* t) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->Skeleton;
|
||||
#else
|
||||
return t->GetSkeleton();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void VRMSetSkeleton(T* t, USkeleton *sk) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
t->Skeleton = sk;
|
||||
#else
|
||||
t->SetSkeleton(sk);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
#else
|
||||
template<typename T>
|
||||
void VRMSetSkeleton(TObjectPtr<T> t, USkeleton* sk) {
|
||||
t->SetSkeleton(sk);
|
||||
}
|
||||
#endif
|
||||
|
||||
//skeleton end
|
||||
|
||||
// refskeleton begin
|
||||
|
||||
template<typename T>
|
||||
FReferenceSkeleton& VRMGetRefSkeleton(T* t) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->RefSkeleton;
|
||||
#else
|
||||
return t->GetRefSkeleton();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
#else
|
||||
template<typename T>
|
||||
FReferenceSkeleton& VRMGetRefSkeleton(TObjectPtr<T> t) {
|
||||
return t->GetRefSkeleton();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
const FReferenceSkeleton& VRMGetRefSkeleton(const T* t) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->RefSkeleton;
|
||||
#else
|
||||
return t->GetRefSkeleton();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void VRMSetRefSkeleton(T* t, const FReferenceSkeleton& refsk) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
t->RefSkeleton = refsk;
|
||||
#else
|
||||
t->SetRefSkeleton(refsk);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
#else
|
||||
template<typename T>
|
||||
void VRMSetRefSkeleton(TObjectPtr<T> t, const FReferenceSkeleton& refsk) {
|
||||
t->SetRefSkeleton(refsk);
|
||||
}
|
||||
#endif
|
||||
|
||||
//refskeleton end
|
||||
|
||||
// morph targets
|
||||
#if UE_VERSION_OLDER_THAN(5,4,0)
|
||||
template<typename T>
|
||||
TArray<UMorphTarget*>& VRMGetMorphTargets(T* t) {
|
||||
#else
|
||||
template<typename T>
|
||||
TArray<TObjectPtr<UMorphTarget>>& VRMGetMorphTargets(T * t) {
|
||||
#endif
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->MorphTargets;
|
||||
#else
|
||||
return t->GetMorphTargets();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
const TArray<UMorphTarget*>& VRMGetMorphTargets(const T* t) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->MorphTargets;
|
||||
#else
|
||||
return t->GetMorphTargets();
|
||||
#endif
|
||||
}
|
||||
|
||||
// materials
|
||||
|
||||
template<typename T>
|
||||
TArray<FSkeletalMaterial>& VRMGetMaterials(T* t) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->Materials;
|
||||
#else
|
||||
return t->GetMaterials();
|
||||
#endif
|
||||
}
|
||||
|
||||
// physics
|
||||
|
||||
template<typename T>
|
||||
void VRMSetPhysicsAsset(T* t, UPhysicsAsset *pa) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
t->PhysicsAsset = pa;
|
||||
#else
|
||||
t->SetPhysicsAsset(pa);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
UPhysicsAsset* VRMGetPhysicsAsset(T* t) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->PhysicsAsset;
|
||||
#else
|
||||
return t->GetPhysicsAsset();
|
||||
#endif
|
||||
}
|
||||
|
||||
// nodemappingdata
|
||||
#if UE_VERSION_OLDER_THAN(5,4,0)
|
||||
template<typename T>
|
||||
TArray<class UNodeMappingContainer*>& VRMGetNodeMappingData(T* t) {
|
||||
#else
|
||||
template<typename T>
|
||||
TArray<TObjectPtr<class UNodeMappingContainer>>& VRMGetNodeMappingData(T * t) {
|
||||
#endif
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->NodeMappingData;
|
||||
#else
|
||||
return t->GetNodeMappingData();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const TArray<class UNodeMappingContainer*>& VRMGetNodeMappingData(const T* t) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->NodeMappingData;
|
||||
#else
|
||||
return t->GetNodeMappingData();
|
||||
#endif
|
||||
}
|
||||
|
||||
// retargetbase
|
||||
|
||||
|
||||
template<typename T>
|
||||
void VRMSetRetargetBasePose(T* t, TArray<FTransform>& pose) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
t->RetargetBasePose = pose;
|
||||
#elif UE_VERSION_OLDER_THAN(5,3,0)
|
||||
t->SetRetargetBasePose(pose);
|
||||
#else
|
||||
// no old retarget pose.
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
TArray<FTransform>& VRMGetRetargetBasePose(T* t) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->RetargetBasePose;
|
||||
#else
|
||||
return t->GetRetargetBasePose();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const TArray<FTransform>& VRMGetRetargetBasePose(const T* t) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
return t->RetargetBasePose;
|
||||
#else
|
||||
return t->GetRetargetBasePose();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// key
|
||||
template<typename T>
|
||||
void VRMSetUseLegacyMeshDerivedDataKey(T* t, bool b) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
t->UseLegacyMeshDerivedDataKey = b;
|
||||
#elif UE_VERSION_OLDER_THAN(5,4,0)
|
||||
t->SetUseLegacyMeshDerivedDataKey(b);
|
||||
#else
|
||||
// ue5.4 no action
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
#else
|
||||
VRM4U_API void VRMAddRetargetChain(class UIKRigController* con, FName name, FName begin, FName end);
|
||||
#endif
|
||||
|
||||
|
||||
//template<typename T>
|
||||
FORCEINLINE USkeletalMesh *VRMGetSkeletalMeshAsset(USkeletalMeshComponent* t) {
|
||||
#if UE_VERSION_OLDER_THAN(5,1,0)
|
||||
return t->SkeletalMesh;
|
||||
#else
|
||||
return (t->GetSkeletalMeshAsset());
|
||||
#endif
|
||||
}
|
||||
FORCEINLINE const USkeletalMesh* VRMGetSkeletalMeshAsset(const USkeletalMeshComponent* t) {
|
||||
#if UE_VERSION_OLDER_THAN(5,1,0)
|
||||
return t->SkeletalMesh;
|
||||
#else
|
||||
return (t->GetSkeletalMeshAsset());
|
||||
#endif
|
||||
}
|
||||
FORCEINLINE USkeletalMesh *VRMGetSkeletalMeshAsset(TWeakObjectPtr<USkeletalMeshComponent> t) {
|
||||
#if UE_VERSION_OLDER_THAN(5,1,0)
|
||||
return t->SkeletalMesh;
|
||||
#else
|
||||
return (t->GetSkeletalMeshAsset());
|
||||
#endif
|
||||
}
|
||||
FORCEINLINE const USkeletalMesh* VRMGetSkeletalMeshAsset(TWeakObjectPtr<const USkeletalMeshComponent> t) {
|
||||
#if UE_VERSION_OLDER_THAN(5,1,0)
|
||||
return t->SkeletalMesh;
|
||||
#else
|
||||
return (t->GetSkeletalMeshAsset());
|
||||
#endif
|
||||
}
|
||||
|
||||
//template<>
|
||||
FORCEINLINE USkeletalMesh *VRMGetSkinnedAsset(USkinnedMeshComponent* t) {
|
||||
#if UE_VERSION_OLDER_THAN(5,1,0)
|
||||
return t->SkeletalMesh;
|
||||
#else
|
||||
return Cast<USkeletalMesh>(t->GetSkinnedAsset());
|
||||
#endif
|
||||
}
|
||||
//template<>
|
||||
FORCEINLINE USkeletalMesh *VRMGetSkinnedAsset(const USkinnedMeshComponent* t) {
|
||||
#if UE_VERSION_OLDER_THAN(5,1,0)
|
||||
return t->SkeletalMesh;
|
||||
#else
|
||||
return Cast<USkeletalMesh>(t->GetSkinnedAsset());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EVRMImportMaterialType : uint8
|
||||
{
|
||||
VRMIMT_Auto UMETA(DisplayName = "Auto(MToon Unlit)"),
|
||||
VRMIMT_MToon UMETA(DisplayName = "MToon Lit"),
|
||||
VRMIMT_MToonUnlit UMETA(DisplayName = "MToon Unlit"),
|
||||
VRMIMT_SSS UMETA(DisplayName = "Subsurface"),
|
||||
VRMIMT_SSSProfile UMETA(DisplayName = "Subsurface Profile"),
|
||||
VRMIMT_Unlit UMETA(DisplayName = "Unlit"),
|
||||
VRMIMT_glTF UMETA(DisplayName = "PBR(glTF2)"),
|
||||
VRMIMT_UEFNLit UMETA(DisplayName = "UEFN(Lit)"),
|
||||
VRMIMT_UEFNUnlit UMETA(DisplayName = "UEFN(Unlit)"),
|
||||
VRMIMT_UEFNSSSProfile UMETA(DisplayName = "UEFN(SSSProfile)"),
|
||||
VRMIMT_Custom UMETA(DisplayName = "Custom"),
|
||||
|
||||
VRMIMT_MAX,
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EVRMImportTextureCompressType : uint8
|
||||
{
|
||||
VRMITC_Auto UMETA(DisplayName = "Auto(DXT1)"),
|
||||
VRMITC_DXT1 UMETA(DisplayName = "DXT1"),
|
||||
VRMITC_BC7 UMETA(DisplayName = "BC7"),
|
||||
VRMITC_NoCompression UMETA(DisplayName = "NoCompression"),
|
||||
|
||||
VRMITC_MAX,
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct VRM4U_API FImportOptionData {
|
||||
public:
|
||||
GENERATED_BODY()
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,26,0)
|
||||
static const bool VRM4U_UseBC7 = false;
|
||||
#else
|
||||
static const bool VRM4U_UseBC7 = true;
|
||||
#endif
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,2,0)
|
||||
static const bool VRM4U_UseUE5Mat = false;
|
||||
#else
|
||||
static const bool VRM4U_UseUE5Mat = true;
|
||||
#endif
|
||||
|
||||
|
||||
void init();
|
||||
|
||||
bool bUEFN = false;
|
||||
|
||||
bool bAPoseRetarget = true;
|
||||
|
||||
bool bMobileBone = false;
|
||||
|
||||
int BoneWeightInfluenceNum = 8;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
EVRMImportMaterialType MaterialType = EVRMImportMaterialType::VRMIMT_Auto;
|
||||
|
||||
bool bForceOverride = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
float ModelScale = 1.0f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
float AnimationTranslateScale = 1.0f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
float PlayRateScale = 1.0f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bRemoveRootBoneRotation = true;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bRemoveRootBonePosition = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bVrm10RemoveLocalRotation = true;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bVrm10UseBindToRestPose = true;
|
||||
|
||||
bool bVrm10Bindpose = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bForceOriginalBoneName = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bGenerateHumanoidRenamedMesh = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bGenerateIKBone = false;
|
||||
|
||||
bool bGenerateRigIK = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bSkipPhysics = true;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bSkipRetargeter = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bSkipMorphTarget = false;
|
||||
|
||||
bool bEnableMorphTargetNormal = false;
|
||||
|
||||
bool bForceOriginalMorphTargetName = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bRemoveBlendShapeGroupPrefix = false;
|
||||
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bForceOpaque= false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bForceTwoSided = false;
|
||||
|
||||
bool bSingleUAssetFile = false;
|
||||
|
||||
bool bDefaultGridTextureMode = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bBC7Mode = VRM4U_UseBC7;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bMipmapGenerateMode = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bUseUE5Material = VRM4U_UseUE5Mat;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bGenerateOutlineMaterial = true;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bMergeMaterial = true;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bMergePrimitive = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bOptimizeVertex = true;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bRemoveDegenerateTriangles = false;
|
||||
|
||||
bool bSimpleRoot = true;
|
||||
|
||||
bool bActiveBone = true;
|
||||
|
||||
bool bSkipNoMeshBone = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bIgnoreVRMValidation = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bDebugOneBone = false;
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bDebugNoMesh = false;
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "VRM4U")
|
||||
bool bDebugNoMaterial = false;
|
||||
|
||||
UPROPERTY()
|
||||
class USkeleton* Skeleton = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class VRM4U_API VRMUtil {
|
||||
//GENERATED_UCLASS_BODY()
|
||||
public:
|
||||
struct VRMBoneTable {
|
||||
FString BoneUE4;
|
||||
FString BoneVRM;
|
||||
};
|
||||
static const TArray<VRMBoneTable> table_ue4_vrm;
|
||||
static const TArray<VRMBoneTable> table_ue4_pmx;
|
||||
static bool GetReplacedPMXBone(FString &replaced, const FString &base);
|
||||
|
||||
static const TArray<FString> vrm_humanoid_bone_list;
|
||||
static const TArray<FName> vrm_humanoid_bone_list_name;
|
||||
|
||||
static const TArray<FString> vrm_humanoid_parent_list;
|
||||
|
||||
static const TArray<FString> ue4_humanoid_bone_list;
|
||||
static const TArray<FName> ue4_humanoid_bone_list_name;
|
||||
|
||||
struct FImportImage
|
||||
{
|
||||
#if UE_VERSION_OLDER_THAN(4,23,0)
|
||||
TArray<uint8> RawData;
|
||||
#else
|
||||
TArray64<uint8> RawData;
|
||||
#endif
|
||||
ETextureSourceFormat Format = TSF_Invalid;
|
||||
TextureCompressionSettings CompressionSettings = TC_Default;
|
||||
int32 NumMips;
|
||||
int32 SizeX = 0;
|
||||
int32 SizeY = 0;
|
||||
bool SRGB = true;
|
||||
|
||||
static int32 GetBytesPerPixel(ETextureSourceFormat Format)
|
||||
{
|
||||
int32 BytesPerPixel = 0;
|
||||
switch (Format)
|
||||
{
|
||||
case TSF_G8: BytesPerPixel = 1; break;
|
||||
#if UE_VERSION_OLDER_THAN(4,24,0)
|
||||
#else
|
||||
case TSF_G16: BytesPerPixel = 2; break;
|
||||
#endif
|
||||
case TSF_BGRA8: BytesPerPixel = 4; break;
|
||||
case TSF_BGRE8: BytesPerPixel = 4; break;
|
||||
case TSF_RGBA16: BytesPerPixel = 8; break;
|
||||
case TSF_RGBA16F: BytesPerPixel = 8; break;
|
||||
default: BytesPerPixel = 0; break;
|
||||
}
|
||||
return BytesPerPixel;
|
||||
}
|
||||
|
||||
|
||||
void Init2DWithParams(int32 InSizeX, int32 InSizeY, ETextureSourceFormat InFormat, bool InSRGB);
|
||||
void Init2DWithOneMip(int32 InSizeX, int32 InSizeY, ETextureSourceFormat InFormat, const void* InData = nullptr) {
|
||||
SizeX = InSizeX;
|
||||
SizeY = InSizeY;
|
||||
NumMips = 1;
|
||||
Format = InFormat;
|
||||
RawData.AddUninitialized((int64)SizeX * SizeY * GetBytesPerPixel(Format));
|
||||
if (InData)
|
||||
{
|
||||
FMemory::Memcpy(RawData.GetData(), InData, RawData.Num());
|
||||
}
|
||||
}
|
||||
void Init2DWithMips(int32 InSizeX, int32 InSizeY, int32 InNumMips, ETextureSourceFormat InFormat, const void* InData = nullptr);
|
||||
|
||||
int64 GetMipSize(int32 InMipIndex) const;
|
||||
void* GetMipData(int32 InMipIndex);
|
||||
};
|
||||
|
||||
|
||||
static bool IsNoSafeName(const FString& str);
|
||||
static FString GetSafeNewName(const FString& str);
|
||||
static FString MakeName(const FString& str, bool IsJoint = false);
|
||||
static FName GetSanitizedName(const FString& str);
|
||||
|
||||
static int32 GetDirectChildBones(FReferenceSkeleton& refs, int32 ParentBoneIndex, TArray<int32>& Children);
|
||||
|
||||
static class UVrmAssetListObject* GetAssetListObjectAny(const UObject* obj);
|
||||
static class UVrmAssetListObject* GetAssetListObject(const USkeletalMesh *);
|
||||
|
||||
static void CloseEditorWindowByFolderPath(const UObject* obj);
|
||||
|
||||
static int GetChildBone(const USkeleton* skeleton, const int32 ParentBoneIndex, bool recursive, TArray<int32>& Children);
|
||||
static int GetChildBone(const USkeleton* skeleton, const int32 ParentBoneIndex, TArray<int32>& Children) {
|
||||
return GetChildBone(skeleton, ParentBoneIndex, true, Children);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class VRM4U_API VRMRetargetData {
|
||||
public:
|
||||
|
||||
struct RetargetParts {
|
||||
FString BoneUE4;
|
||||
FString BoneVRM;
|
||||
FString BoneModel;
|
||||
|
||||
FRotator rot;
|
||||
bool operator==(const RetargetParts& a) const{
|
||||
return BoneUE4.Compare(a.BoneUE4, ESearchCase::IgnoreCase) == 0;
|
||||
}
|
||||
};
|
||||
class UVrmAssetListObject* vrmAssetList = nullptr;
|
||||
TArray<RetargetParts> retargetTable;
|
||||
|
||||
void Setup(class UVrmAssetListObject* vrmAssetList, bool bVRM, bool bBVH, bool bPMX);
|
||||
void UpdateBoneName();
|
||||
void Remove(FString BoneUE4);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.IO;
|
||||
|
||||
public class VRM4U : ModuleRules
|
||||
{
|
||||
private string ModulePath
|
||||
{
|
||||
get { return ModuleDirectory; }
|
||||
}
|
||||
|
||||
private string ThirdPartyPath
|
||||
{
|
||||
get { return Path.GetFullPath(Path.Combine(ModulePath, "../../ThirdParty/")); }
|
||||
}
|
||||
|
||||
public VRM4U(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
//"VRM4U/Public",
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
//"VRM4U/Private",
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"RHI",
|
||||
"RenderCore",
|
||||
"AnimGraphRuntime",
|
||||
"LiveLinkInterface",
|
||||
"CinematicCamera",
|
||||
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"Engine",
|
||||
"AssetRegistry",
|
||||
"InputCore",
|
||||
"ControlRig",
|
||||
"AnimationCore",
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
if (Target.bBuildEditor)
|
||||
{
|
||||
PrivateDependencyModuleNames.Add("UnrealEd");
|
||||
PrivateDependencyModuleNames.Add("LevelEditor");
|
||||
|
||||
PrivateDependencyModuleNames.Add("LevelSequence");
|
||||
PrivateDependencyModuleNames.Add("LevelSequenceEditor");
|
||||
PrivateDependencyModuleNames.Add("Sequencer");
|
||||
|
||||
BuildVersion Version2;
|
||||
if (BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version2))
|
||||
{
|
||||
if (Version2.MajorVersion == 5)
|
||||
{
|
||||
PrivateDependencyModuleNames.Add("MovieRenderPipelineEditor");
|
||||
PrivateDependencyModuleNames.Add("ControlRigDeveloper");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
BuildVersion Version2;
|
||||
if (BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version2))
|
||||
{
|
||||
if (Version2.MajorVersion == 5)
|
||||
{
|
||||
PrivateDependencyModuleNames.Add("MovieRenderPipelineCore");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
}
|
||||
);
|
||||
|
||||
BuildVersion Version;
|
||||
if (BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version))
|
||||
{
|
||||
//if (Version.MajorVersion == X && Version.MinorVersion == Y)
|
||||
if (Version.MajorVersion == 5)
|
||||
{
|
||||
PrivateDependencyModuleNames.Add("RigVM");
|
||||
PrivateDependencyModuleNames.Add("IKRig");
|
||||
if (Target.bBuildEditor)
|
||||
{
|
||||
PrivateDependencyModuleNames.Add("IKRigEditor");
|
||||
}
|
||||
|
||||
PrivateDependencyModuleNames.Add("InterchangeCore");
|
||||
}
|
||||
}
|
||||
|
||||
//(Target.Version.MinorVersion >= 25)
|
||||
// warning: crash without OculusVR Plugin
|
||||
bool bUseQuestTracking = false;
|
||||
|
||||
if (bUseQuestTracking)
|
||||
{
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
PrivateDependencyModuleNames.AddRange(new string[] {
|
||||
"OculusHMD",
|
||||
"OVRPlugin",
|
||||
});
|
||||
PublicDelayLoadDLLs.Add("OVRPlugin.dll");
|
||||
RuntimeDependencies.Add("$(EngineDir)/Binaries/ThirdParty/Oculus/OVRPlugin/OVRPlugin/" + Target.Platform.ToString() + "/OVRPlugin.dll");
|
||||
|
||||
PublicDefinitions.Add("WITH_VRM4U_HMD_TRACKER=1");
|
||||
}
|
||||
else
|
||||
{
|
||||
PublicDefinitions.Add("WITH_VRM4U_HMD_TRACKER=0");
|
||||
}
|
||||
}
|
||||
else {
|
||||
PublicDefinitions.Add("WITH_VRM4U_HMD_TRACKER=0");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "AnimNode_VrmVMC.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
|
||||
#include "VRM4U_VMCSubsystem.h"
|
||||
#include "VrmAssetListObject.h"
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
/////////////////////////////////////////////////////
|
||||
// FAnimNode_ModifyBone
|
||||
|
||||
|
||||
FAnimNode_VrmVMC::FAnimNode_VrmVMC()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FAnimNode_VrmVMC::~FAnimNode_VrmVMC()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//void FAnimNode_VrmVMC::Update_AnyThread(const FAnimationUpdateContext& Context) {
|
||||
// Super::Update_AnyThread(Context);
|
||||
// //Context.GetDeltaTime();
|
||||
//}
|
||||
|
||||
void FAnimNode_VrmVMC::Initialize_AnyThread(const FAnimationInitializeContext& Context) {
|
||||
Super::Initialize_AnyThread(Context);
|
||||
|
||||
VrmMetaObject_Internal = const_cast<UVrmMetaObject*>(VrmMetaObject);
|
||||
if (VrmMetaObject_Internal == nullptr && EnableAutoSearchMetaData) {
|
||||
VrmAssetListObject_Internal = VRMUtil::GetAssetListObject(VRMGetSkinnedAsset(Context.AnimInstanceProxy->GetSkelMeshComponent()));
|
||||
if (VrmAssetListObject_Internal) {
|
||||
VrmMetaObject_Internal = VrmAssetListObject_Internal->VrmMetaObject;
|
||||
}
|
||||
}
|
||||
|
||||
UVRM4U_VMCSubsystem* subsystem = GEngine->GetEngineSubsystem<UVRM4U_VMCSubsystem>();
|
||||
if (subsystem == nullptr) return;
|
||||
{
|
||||
auto *s = subsystem->FindOrAddServer(ServerAddress, Port);
|
||||
if (s) {
|
||||
s->bForceUpdate = bForceUpdate;
|
||||
}
|
||||
}
|
||||
bCreateServer = true;
|
||||
|
||||
// init global reftransform
|
||||
{
|
||||
const auto Skeleton = Context.AnimInstanceProxy->GetSkeleton();
|
||||
const auto RefSkeleton = Skeleton->GetReferenceSkeleton();
|
||||
const auto& RefSkeletonTransform = RefSkeleton.GetRefBonePose();
|
||||
|
||||
RefSkeletonTransform_global = RefSkeletonTransform;
|
||||
{
|
||||
auto& g = RefSkeletonTransform_global;
|
||||
for (int i = 0; i < RefSkeletonTransform.Num(); ++i) {
|
||||
int parent = RefSkeleton.GetParentIndex(i);
|
||||
if (parent < 0) continue;
|
||||
g[i] = g[i] * g[parent];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
void FAnimNode_VrmVMC::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) {
|
||||
Super::CacheBones_AnyThread(Context);
|
||||
}
|
||||
|
||||
|
||||
void FAnimNode_VrmVMC::UpdateInternal(const FAnimationUpdateContext& Context){
|
||||
Super::UpdateInternal(Context);
|
||||
}
|
||||
|
||||
|
||||
void FAnimNode_VrmVMC::GatherDebugData(FNodeDebugData& DebugData)
|
||||
{
|
||||
FString DebugLine = DebugData.GetNodeName(this);
|
||||
|
||||
DebugLine += "(";
|
||||
AddDebugNodeData(DebugLine);
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneToModify.BoneName.ToString());
|
||||
//DebugLine += FString::Printf(TEXT(" Target: %s)"), *BoneNameToModify.ToString());
|
||||
DebugData.AddDebugItem(DebugLine);
|
||||
|
||||
ComponentPose.GatherDebugData(DebugData);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmVMC::EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) {
|
||||
Super::EvaluateComponentPose_AnyThread(Output);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmVMC::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
|
||||
{
|
||||
check(OutBoneTransforms.Num() == 0);
|
||||
|
||||
if (VrmMetaObject_Internal == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
UVRM4U_VMCSubsystem* subsystem = GEngine->GetEngineSubsystem<UVRM4U_VMCSubsystem>();
|
||||
if (subsystem == nullptr) return;
|
||||
|
||||
const auto Skeleton = Output.AnimInstanceProxy->GetSkeleton();
|
||||
const auto RefSkeleton = Output.AnimInstanceProxy->GetSkeleton()->GetReferenceSkeleton();
|
||||
const FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();
|
||||
const auto& RefSkeletonTransform = RefSkeleton.GetRefBonePose();
|
||||
|
||||
if (RefSkeletonTransform_global.Num() != RefSkeletonTransform.Num()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<int> boneIndexTable;
|
||||
TArray<FBoneTransform> tmpOutTransform;
|
||||
|
||||
FVMCData VMCData;
|
||||
if (subsystem->CopyVMCData(VMCData, ServerAddress, Port) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (VMCData.BoneData.Num() == 0 && VMCData.CurveData.Num() == 0) {
|
||||
return;
|
||||
}
|
||||
if (bApplyPerfectSync) {
|
||||
for (auto& c : VMCData.CurveData) {
|
||||
if (c.Key.Contains(TEXT("BlendShape.")) == false) continue;
|
||||
|
||||
c.Key.RightChopInline(11); // [blendahape.]
|
||||
}
|
||||
}
|
||||
|
||||
TMap<FString, FTransform>& BoneTrans = VMCData.BoneData;
|
||||
|
||||
const auto &MorphList = Output.AnimInstanceProxy->GetSkelMeshComponent()->GetSkinnedAsset()->GetMorphTargets();
|
||||
for (auto& c : VMCData.CurveData) {
|
||||
#if UE_VERSION_OLDER_THAN(5,3,0)
|
||||
{
|
||||
SmartName::UID_Type NewUID;
|
||||
FName NewName = *c.Key;
|
||||
|
||||
NewUID = Skeleton->GetUIDByName(USkeleton::AnimCurveMappingName, NewName);
|
||||
|
||||
Output.Curve.Set(NewUID, c.Value);
|
||||
}
|
||||
#else
|
||||
auto m = MorphList.FindByPredicate([&c](const TObjectPtr<UMorphTarget> &m) {
|
||||
FString s = c.Key;
|
||||
|
||||
if (m->GetName().Compare(s, ESearchCase::IgnoreCase)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (m) {
|
||||
Output.Curve.Set(*m->GetName(), c.Value);
|
||||
} else {
|
||||
Output.Curve.Set(*c.Key, c.Value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
bool bFirstBone = true;
|
||||
|
||||
for (const auto &t : VrmMetaObject_Internal->humanoidBoneTable) {
|
||||
#if UE_VERSION_OLDER_THAN(4,27,0)
|
||||
auto *tmpVal = BoneTrans.Find(t.Key.ToLower());
|
||||
if (tmpVal == nullptr) continue;
|
||||
|
||||
auto modelBone = *tmpVal;
|
||||
#else
|
||||
auto filterList= BoneTrans.FilterByPredicate([&t](TPair<FString, FTransform> a) {
|
||||
return a.Key.Compare(t.Key, ESearchCase::IgnoreCase) == 0;
|
||||
}
|
||||
);
|
||||
if (filterList.Num() != 1) continue;
|
||||
auto modelBone = filterList.begin()->Value;
|
||||
#endif
|
||||
|
||||
|
||||
int index = RefSkeleton.FindBoneIndex(*t.Value);
|
||||
if (index < 0) continue;
|
||||
|
||||
FBoneTransform f(FCompactPoseBoneIndex(index), modelBone);
|
||||
//f.Transform.SetRotation(FQuat::Identity);
|
||||
|
||||
if (bFirstBone) {
|
||||
bFirstBone = false;
|
||||
|
||||
if (bUseRemoteCenterPos) {
|
||||
auto v = f.Transform.GetLocation() * ModelRelativeScale;
|
||||
f.Transform.SetTranslation(v);
|
||||
} else {
|
||||
auto v = RefSkeletonTransform[index].GetLocation();
|
||||
f.Transform.SetTranslation(v);
|
||||
}
|
||||
|
||||
|
||||
// root bone
|
||||
FTransform RootTrans;
|
||||
for (auto& a : BoneTrans) {
|
||||
if (a.Key.Compare(TEXT("root"), ESearchCase::IgnoreCase)) {
|
||||
continue;
|
||||
}
|
||||
RootTrans = a.Value;
|
||||
break;
|
||||
}
|
||||
if (index == 0) {
|
||||
// hip == root
|
||||
f.Transform.SetTranslation(f.Transform.GetLocation() + RootTrans.GetLocation());
|
||||
} else {
|
||||
// orig root
|
||||
FBoneTransform bt(FCompactPoseBoneIndex(0), RootTrans);
|
||||
tmpOutTransform.Add(bt);
|
||||
boneIndexTable.Add(0);
|
||||
}
|
||||
|
||||
} else {
|
||||
FVector v = RefSkeletonTransform[index].GetLocation();
|
||||
f.Transform.SetTranslation(v);
|
||||
}
|
||||
|
||||
if (bIgnoreLocalRotation){
|
||||
auto r_refg = RefSkeletonTransform_global[index].GetRotation();
|
||||
auto r_ref = RefSkeletonTransform[index].GetRotation();
|
||||
auto r_vmc = f.Transform.GetRotation();
|
||||
|
||||
auto r_dif = r_refg.Inverse() * r_vmc * r_refg;
|
||||
|
||||
f.Transform.SetRotation(r_ref * r_dif);
|
||||
}
|
||||
//f.Transform.SetTranslation(RefSkeletonTransform[index].GetLocation());
|
||||
tmpOutTransform.Add(f);
|
||||
boneIndexTable.Add(index);
|
||||
}
|
||||
|
||||
// bone hierarchy
|
||||
for (int i = 1; i < tmpOutTransform.Num(); ++i) {
|
||||
int parentBoneIndex = RefSkeleton.GetParentIndex(boneIndexTable[i]);
|
||||
int parentInTable = boneIndexTable.Find(parentBoneIndex);
|
||||
|
||||
for (int j = 0; j < 1000; ++j) {
|
||||
if (parentInTable >= 0) {
|
||||
break;
|
||||
}
|
||||
if (parentBoneIndex < 0) break;
|
||||
|
||||
// add outtransform with ref bone
|
||||
FBoneTransform f(FCompactPoseBoneIndex(parentBoneIndex), RefSkeletonTransform[parentBoneIndex]);
|
||||
tmpOutTransform.Add(f);
|
||||
boneIndexTable.Add(parentBoneIndex);
|
||||
|
||||
parentBoneIndex = RefSkeleton.GetParentIndex(parentBoneIndex);
|
||||
parentInTable = boneIndexTable.Find(parentBoneIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// sort
|
||||
tmpOutTransform.Sort(FCompareBoneTransformIndex());
|
||||
boneIndexTable.Sort();
|
||||
}
|
||||
|
||||
for (int i = 0; i < tmpOutTransform.Num(); ++i) {
|
||||
auto& a = tmpOutTransform[i];
|
||||
|
||||
int parentBoneIndex = RefSkeleton.GetParentIndex(boneIndexTable[i]);
|
||||
|
||||
int parentInHandTable = boneIndexTable.Find(parentBoneIndex);
|
||||
if (parentInHandTable >= 0) {
|
||||
a.Transform *= tmpOutTransform[parentInHandTable].Transform;
|
||||
} else {
|
||||
// root
|
||||
auto BoneSpace = EBoneControlSpace::BCS_ParentBoneSpace;
|
||||
FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, a.Transform, a.BoneIndex, BoneSpace);
|
||||
}
|
||||
OutBoneTransforms.Add(a);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool FAnimNode_VrmVMC::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
||||
{
|
||||
// if both bones are valid
|
||||
//return (BoneToModify.IsValidToEvaluate(RequiredBones));
|
||||
return true;
|
||||
}
|
||||
|
||||
void FAnimNode_VrmVMC::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
||||
{
|
||||
//BoneToModify.Initialize(RequiredBones);
|
||||
}
|
||||
|
||||
void FAnimNode_VrmVMC::ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground) const
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
|
||||
if (VrmMetaObject_Internal == nullptr || PreviewSkelMeshComp == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (PreviewSkelMeshComp->GetWorld() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESceneDepthPriorityGroup Priority = SDPG_World;
|
||||
if (bPreviewForeground) Priority = SDPG_Foreground;
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VRM4UCapture.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "VRM4UCaptureLog.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "Internationalization/Internationalization.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "VRM4UMisc"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogVRM4UCapture);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FSpriterImporterModule
|
||||
|
||||
class FVRM4UCaptureModule : public FDefaultModuleImpl
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ShutdownModule() override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPLEMENT_MODULE(FVRM4UCaptureModule, VRM4UCapture);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,8 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
//#include "VRMImporterModule.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
//#include "VRMImporterModule.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogVRM4UCapture, Verbose, All);
|
||||
|
||||
//#define SPRITER_IMPORT_ERROR(FormatString, ...) \
|
||||
// if (!bSilent) { UE_LOG(LogVRM4UMIsc, Warning, FormatString, __VA_ARGS__); }
|
||||
//#define SPRITER_IMPORT_WARNING(FormatString, ...) \
|
||||
// if (!bSilent) { UE_LOG(LogVRM4UMIsc, Warning, FormatString, __VA_ARGS__); }
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "VRM4U_VMCSubsystem.h"
|
||||
#include "VrmVMCObject.h"
|
||||
|
||||
#include "Engine/Engine.h"
|
||||
#include "UObject/StrongObjectPtr.h"
|
||||
#include "Misc/ScopeLock.h"
|
||||
#include "OSCManager.h"
|
||||
#include "OSCServer.h"
|
||||
|
||||
bool UVRM4U_VMCSubsystem::CopyVMCData(FVMCData &data, FString ServerAddress, int port) {
|
||||
for (int i = 0; i < VMCObjectList.Num(); ++i) {
|
||||
auto a = VMCObjectList[i].Get();
|
||||
if (a == nullptr) continue;
|
||||
|
||||
if (a->ServerName == ServerAddress && a->port == port) {
|
||||
a->CopyVMCData(data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UVRM4U_VMCSubsystem::GetVMCData(TMap<FString, FTransform>& BoneData, TMap<FString, float>& CurveData, FString ServerAddress, int port) {
|
||||
FVMCData d;
|
||||
if (CopyVMCData(d, ServerAddress, port) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BoneData = d.BoneData;
|
||||
CurveData = d.CurveData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
UVrmVMCObject* UVRM4U_VMCSubsystem::FindOrAddServer(const FString ServerAddress, int port) {
|
||||
|
||||
bool bFound = false;
|
||||
for (int i = 0; i < VMCObjectList.Num(); ++i) {
|
||||
auto a = VMCObjectList[i].Get();
|
||||
if (a == nullptr) continue;
|
||||
|
||||
if (a->ServerName == ServerAddress && a->port == port) {
|
||||
bFound = true;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
if (bFound == false) {
|
||||
int ind = VMCObjectList.AddDefaulted();
|
||||
VMCObjectList[ind].Reset(NewObject<UVrmVMCObject>());
|
||||
VMCObjectList[ind]->CreateServer(ServerAddress, port);
|
||||
return VMCObjectList[ind].Get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UVRM4U_VMCSubsystem::DestroyVMCServer(const FString ServerAddress, int port) {
|
||||
for (int i = 0; i < VMCObjectList.Num(); ++i) {
|
||||
auto a = VMCObjectList[i].Get();
|
||||
if (a == nullptr) continue;
|
||||
|
||||
if (a->ServerName == ServerAddress && a->port == port) {
|
||||
a->DestroyServer();
|
||||
VMCObjectList[i].Reset(nullptr);
|
||||
VMCObjectList.RemoveAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void UVRM4U_VMCSubsystem::DestroyVMCServerAll() {
|
||||
while (VMCObjectList.Num()) {
|
||||
auto a = VMCObjectList[0].Get();
|
||||
if (a) {
|
||||
a->DestroyServer();
|
||||
}
|
||||
VMCObjectList[0].Reset(nullptr);
|
||||
VMCObjectList.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool UVRM4U_VMCSubsystem::CreateVMCServer(const FString ServerAddress, int port) {
|
||||
return (FindOrAddServer(ServerAddress, port) != nullptr);
|
||||
}
|
||||
|
||||
void UVRM4U_VMCSubsystem::ClearData(const FString ServerAddress, int port) {
|
||||
for (int i = 0; i < VMCObjectList.Num(); ++i) {
|
||||
auto a = VMCObjectList[i].Get();
|
||||
if (a == nullptr) continue;
|
||||
|
||||
if (a->ServerName == ServerAddress && a->port == port) {
|
||||
VMCObjectList[i]->ClearVMCData();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UVRM4U_VMCSubsystem::Initialize(FSubsystemCollectionBase& Collection) {
|
||||
Super::Initialize(Collection);
|
||||
|
||||
#if WITH_EDITOR
|
||||
FEditorDelegates::BeginStandaloneLocalPlay.AddLambda([&](const uint32 processID) {
|
||||
this->DestroyVMCServerAll();
|
||||
});
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VrmCaptureManager.h"
|
||||
#include "VrmMocopiReceiver.h"
|
||||
#include "VRM4UCaptureLog.h"
|
||||
|
||||
UVrmMocopiReceiver* UVrmCaptureManager::CreateVrmMocopiReceiver(FString InReceiveIPAddress, int32 InPort, bool bInMulticastLoopback, bool bInStartListening, FString ServerName, UObject* Outer)
|
||||
{
|
||||
{
|
||||
FString InAddress = InReceiveIPAddress;
|
||||
if (!InAddress.IsEmpty() && InAddress != TEXT("0"))
|
||||
{
|
||||
}
|
||||
|
||||
bool bCanBind = false;
|
||||
bool bAppendPort = false;
|
||||
if (ISocketSubsystem* SocketSys = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM))
|
||||
{
|
||||
const TSharedPtr<FInternetAddr> Addr = SocketSys->GetLocalHostAddr(*GLog, bCanBind);
|
||||
if (Addr.IsValid())
|
||||
{
|
||||
InAddress = Addr->ToString(bAppendPort);
|
||||
}
|
||||
}
|
||||
UE_LOG(LogVRM4UCapture, Display, TEXT("MocopiReceiver ReceiveAddress not specified. Using LocalHost IP: '%s'"), *InAddress);
|
||||
}
|
||||
|
||||
if (ServerName.IsEmpty())
|
||||
{
|
||||
ServerName = FString::Printf(TEXT("MocopiReceiver_%s"), *FGuid::NewGuid().ToString(EGuidFormats::Digits));
|
||||
}
|
||||
|
||||
UVrmMocopiReceiver* NewMocopiServer = nullptr;
|
||||
if (Outer)
|
||||
{
|
||||
NewMocopiServer = NewObject<UVrmMocopiReceiver>(Outer, *ServerName, RF_StrongRefOnFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogVRM4UCapture, Warning, TEXT("Outer object not set. MocopiReceiver may be garbage collected if not referenced."));
|
||||
NewMocopiServer = NewObject<UVrmMocopiReceiver>(GetTransientPackage(), *ServerName);
|
||||
}
|
||||
|
||||
if (NewMocopiServer)
|
||||
{
|
||||
//NewMocopiServer->SetMulticastLoopback(bInMulticastLoopback);
|
||||
if (NewMocopiServer->SetAddress(InReceiveIPAddress, InPort))
|
||||
{
|
||||
if (bInStartListening)
|
||||
{
|
||||
NewMocopiServer->Listen();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogVRM4UCapture, Warning, TEXT("Failed to parse ReceiveAddress '%s' for MocopiReceiver."), *InReceiveIPAddress);
|
||||
}
|
||||
|
||||
return NewMocopiServer;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,563 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
|
||||
#include "VrmMocopiReceiver.h"
|
||||
|
||||
#include "VRM4UCaptureLog.h"
|
||||
|
||||
#include "CoreGlobals.h"
|
||||
#include "Stats/Stats.h"
|
||||
#include "Tickable.h"
|
||||
#include "Common/UdpSocketReceiver.h"
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
FMocopiReceiverProxy::FMocopiReceiverProxy(UVrmMocopiReceiver * InReceiver):
|
||||
Receiver(InReceiver){
|
||||
FIPv4Address::Parse("0.0.0.0", ReceiveIPAddress);
|
||||
}
|
||||
|
||||
FMocopiReceiverProxy::~FMocopiReceiverProxy() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
void FMocopiReceiverProxy::Stop() {
|
||||
if (SocketReceiver) {
|
||||
delete SocketReceiver;
|
||||
SocketReceiver = nullptr;
|
||||
}
|
||||
if (Socket) {
|
||||
Socket->Close();
|
||||
ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(Socket);
|
||||
Socket = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void FMocopiReceiverProxy::Listen() {
|
||||
FString InServerName = "udp_serv";
|
||||
//int32 Port = 12351;
|
||||
bool bMulticastLoopback = true;
|
||||
|
||||
FUdpSocketBuilder Builder(*InServerName);
|
||||
Builder.BoundToPort(Port);
|
||||
if (ReceiveIPAddress.IsMulticastAddress())
|
||||
{
|
||||
Builder.JoinedToGroup(ReceiveIPAddress);
|
||||
if (bMulticastLoopback)
|
||||
{
|
||||
Builder.WithMulticastLoopback();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bMulticastLoopback)
|
||||
{
|
||||
//UE_LOG(LogOSC, Warning, TEXT("OSCServer '%s' ReceiveIPAddress provided is not a multicast address. Not respecting MulticastLoopback boolean."),
|
||||
// *InServerName);
|
||||
}
|
||||
Builder.BoundToAddress(ReceiveIPAddress);
|
||||
}
|
||||
|
||||
Socket = Builder.Build();
|
||||
if (Socket)
|
||||
{
|
||||
SocketReceiver = new FUdpSocketReceiver(Socket, FTimespan::FromMilliseconds(100), *(InServerName + TEXT("_ListenerThread")));
|
||||
SocketReceiver->OnDataReceived().BindRaw(this, &FMocopiReceiverProxy::OnPacketReceived);
|
||||
SocketReceiver->Start();
|
||||
|
||||
//UE_LOG(LogOSC, Display, TEXT("OSCServer '%s' Listening: %s:%d."), *InServerName, *ReceiveIPAddress.ToString(), Port);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is expected when the server isn't available, so it's not a Warning
|
||||
//UE_LOG(LogOSC, Display, TEXT("OSCServer '%s' failed to bind to socket on %s:%d. Check that the server is available on the specified address."), *InServerName, *ReceiveIPAddress.ToString(), Port);
|
||||
}
|
||||
}
|
||||
|
||||
bool FMocopiReceiverProxy::SetAddress(const FString& InReceiveIPAddress, int32 InPort) {
|
||||
if (!FIPv4Address::Parse(InReceiveIPAddress, ReceiveIPAddress))
|
||||
{
|
||||
//UE_LOG(LogOSC, Error, TEXT("Invalid ReceiveIPAddress '%s'. OSCServer ReceiveIP Address not updated."), *InReceiveIPAddress);
|
||||
return false;
|
||||
}
|
||||
|
||||
Port = InPort;
|
||||
return true;
|
||||
}
|
||||
void FMocopiReceiverProxy::Tick(float InDeltaTime) {
|
||||
|
||||
}
|
||||
|
||||
TStatId FMocopiReceiverProxy::GetStatId() const
|
||||
{
|
||||
RETURN_QUICK_DECLARE_CYCLE_STAT(FMocopiReceiverProxy, STATGROUP_Tickables);
|
||||
}
|
||||
|
||||
void FMocopiReceiverProxy::OnPacketReceived(const FArrayReaderPtr& InData, const FIPv4Endpoint& InEndpoint) {
|
||||
|
||||
RecvDataSet.Append(InData->GetData(), InData->Num());
|
||||
|
||||
// data size limit
|
||||
if (RecvDataSet.Num() >= 1024 * 64) {
|
||||
decltype(RecvDataSet) a;
|
||||
a.Append(RecvDataSet.GetData() + 1024*48, RecvDataSet.Num() - 1024*48);
|
||||
RecvDataSet = a;
|
||||
}
|
||||
|
||||
|
||||
//UE_LOG(LogVRM4UCapture, Verbose, TEXT("recv '%d' "), InData->Num());
|
||||
|
||||
struct LocalStructRawData {
|
||||
TArray<float> f;
|
||||
FQuat rot;
|
||||
FVector pos;
|
||||
|
||||
LocalStructRawData() {
|
||||
f.SetNum(7);
|
||||
}
|
||||
};
|
||||
|
||||
struct LocalStructTransData {
|
||||
//TArray<LocalStructRawData> data;
|
||||
|
||||
TArray<FTransform> transformLocal;
|
||||
TArray <FTransform> transformWorld;
|
||||
TArray <FTransform> transformVrmLocal;
|
||||
TArray <FTransform> transformBvhLocal;
|
||||
|
||||
|
||||
LocalStructTransData() {
|
||||
transformWorld.SetNum(MocopiData::BoneNum);
|
||||
transformLocal.SetNum(MocopiData::BoneNum);
|
||||
transformVrmLocal.SetNum(MocopiData::BoneNum);
|
||||
transformBvhLocal.SetNum(MocopiData::BoneNum);
|
||||
//data.SetNum(MocopiData::BoneNum);
|
||||
}
|
||||
};
|
||||
|
||||
LocalStructTransData d;
|
||||
|
||||
const char FIELD_HEAD[] = {
|
||||
'h', 'e', 'a', 'd',
|
||||
};
|
||||
|
||||
const char FIELD_SKDF[] = {
|
||||
's', 'k', 'd', 'f',
|
||||
};
|
||||
|
||||
const char FIELD_BTRS[] = {
|
||||
'b', 't', 'r', 's',
|
||||
};
|
||||
|
||||
|
||||
const char FIELD_TRAN[] = {
|
||||
't', 'r', 'a', 'n',
|
||||
};
|
||||
|
||||
const char FIELD_BNID[] = {
|
||||
'b', 'n', 'i', 'd',
|
||||
};
|
||||
|
||||
const char FIELD_FRAM[] = {
|
||||
'f', 'r', 'a', 'm',
|
||||
};
|
||||
|
||||
const char FIELD_FNUM[] = {
|
||||
'f', 'n', 'u', 'm',
|
||||
};
|
||||
|
||||
const char FIELD_TIME[] = {
|
||||
't', 'i', 'm', 'e',
|
||||
};
|
||||
|
||||
const int BoneChain[] = {
|
||||
0, // 0
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
7, // 11
|
||||
11, 12, 13,
|
||||
7, // 15
|
||||
15, 16, 17,
|
||||
0, //19
|
||||
19, 20, 21,
|
||||
0, //23
|
||||
23, 24, 25,
|
||||
};
|
||||
|
||||
auto GetValue = [&](uint8*& pData, uint32_t &length, int cur, const char field[4]) {
|
||||
|
||||
if (cur < 4) {
|
||||
return false;
|
||||
}
|
||||
{
|
||||
int t = 0;
|
||||
for (t = 0; t < 4; ++t) {
|
||||
if (field[t] != RecvDataSet.GetData()[cur + t]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (t == 4) {
|
||||
pData = (RecvDataSet.GetData() + cur + 4);
|
||||
length = *reinterpret_cast<uint32*>((RecvDataSet.GetData() + cur - 4));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
pData = nullptr;
|
||||
length = 0;
|
||||
return false;
|
||||
};
|
||||
|
||||
/*
|
||||
for (int i = RecvDataSet.Num() - 4; i >= 8; --i) {
|
||||
if (isalpha(RecvDataSet.GetData()[i]) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 length = 0;
|
||||
uint8* p = nullptr;
|
||||
if (GetValue(p, length, i, FIELD_FRAM)){
|
||||
|
||||
// p == value
|
||||
// p-4 == field
|
||||
// p-8 == packetsize
|
||||
//
|
||||
// i == field
|
||||
// i-4 == packetsize
|
||||
|
||||
uint16* packetSize = reinterpret_cast<uint16*>(p - 8);
|
||||
|
||||
//UE_LOG(LogVRM4UCapture, Verbose, TEXT("packetSize '%d'"), (*packetSize));
|
||||
|
||||
if ((*packetSize) + 8 <= RecvDataSet.Num()) {
|
||||
//UE_LOG(LogVRM4UCapture, Verbose, TEXT("shrink '%d' -> %d "), RecvDataSet.Num(), (*packetSize) + 8);
|
||||
|
||||
decltype(RecvDataSet) a;
|
||||
a.Append(RecvDataSet.GetData() + i - 4, (*packetSize) + 8);
|
||||
RecvDataSet = a;
|
||||
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
bool bUpdateData = false;
|
||||
for (int packetNo = 0; packetNo < 10; ++packetNo) {
|
||||
|
||||
int32 frame = -1;
|
||||
int32 time = -1;
|
||||
{
|
||||
bool bFindFieldSkdf = false;
|
||||
bool bFindFieldBtrs = false;
|
||||
bool bFindFieldFram = false;
|
||||
|
||||
float* TransformData = nullptr;
|
||||
uint16* boneid = nullptr;
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < RecvDataSet.Num() - 4; ++i) {
|
||||
if (isalpha(RecvDataSet.GetData()[i]) == false) {
|
||||
continue;
|
||||
}
|
||||
uint32 length = 0;
|
||||
uint8* p = nullptr;
|
||||
|
||||
if (GetValue(p, length, i, FIELD_SKDF)) {
|
||||
//UE_LOG(LogVRM4UCapture, Verbose, TEXT("skdf %d"), bFindFieldFram);
|
||||
bFindFieldSkdf = true;
|
||||
|
||||
// remove read data
|
||||
FMemory::Memmove(RecvDataSet.GetData(), RecvDataSet.GetData() + (i+4), RecvDataSet.Num() - (i+4));
|
||||
RecvDataSet.SetNum(RecvDataSet.Num() - (i+4));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (bFindFieldFram == false) {
|
||||
if (GetValue(p, length, i, FIELD_FRAM)) {
|
||||
bFindFieldFram = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
int t = 0;
|
||||
for (t = 0; t < 4; ++t) {
|
||||
if (isalpha((RecvDataSet.GetData()[i + t])) == false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (t == 4) {
|
||||
UE_LOG(LogVRM4UCapture, Verbose, TEXT("recv '%c%c%c%c' "),
|
||||
*((char*)(RecvDataSet.GetData()) + i),
|
||||
*((char*)(RecvDataSet.GetData()) + i+1),
|
||||
*((char*)(RecvDataSet.GetData()) + i+2),
|
||||
*((char*)(RecvDataSet.GetData()) + i+3)
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (GetValue(p, length, i, FIELD_FNUM)) {
|
||||
frame = *reinterpret_cast<int32*>(p);
|
||||
}
|
||||
|
||||
if (GetValue(p, length, i, FIELD_TIME)) {
|
||||
time = *reinterpret_cast<int32*>(p);
|
||||
}
|
||||
|
||||
if (frame < 0) continue;
|
||||
|
||||
if (bFindFieldBtrs == false) {
|
||||
if (GetValue(p, length, i, FIELD_BTRS)) {
|
||||
bFindFieldBtrs = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (GetValue(p, length, i, FIELD_BNID)) {
|
||||
boneid = reinterpret_cast<uint16*>(p);
|
||||
}
|
||||
|
||||
if (GetValue(p, length, i, FIELD_TRAN)) {
|
||||
TransformData = reinterpret_cast<float*>(p);
|
||||
}
|
||||
|
||||
if (boneid && TransformData) {
|
||||
// mocopi
|
||||
{
|
||||
LocalStructRawData st;
|
||||
|
||||
st.rot = FQuat(-TransformData[0], -TransformData[1], TransformData[2], TransformData[3]);
|
||||
if (*boneid == 0) {
|
||||
st.rot = FRotator(0, 0, -90).Quaternion() * st.rot;
|
||||
}
|
||||
|
||||
st.pos.Set(TransformData[4], TransformData[5], -TransformData[6]);
|
||||
st.pos *= 100.f;
|
||||
|
||||
d.transformLocal[*boneid] = FTransform(st.rot, st.pos);
|
||||
}
|
||||
|
||||
// vrm
|
||||
{
|
||||
LocalStructRawData st;
|
||||
|
||||
d.transformVrmLocal[*boneid] = FTransform(st.rot, st.pos);
|
||||
st.rot = FQuat(-TransformData[0], -TransformData[1], TransformData[2], TransformData[3]);
|
||||
st.rot = FRotator(0, 0, -90).Quaternion() * st.rot * FRotator(0, 0, -90).Quaternion().Inverse();
|
||||
|
||||
st.pos.Set(TransformData[4], TransformData[6], TransformData[5]);
|
||||
st.pos *= 100.f;
|
||||
|
||||
d.transformVrmLocal[*boneid] = FTransform(st.rot, st.pos);
|
||||
}
|
||||
|
||||
if (*boneid == MocopiData::BoneNum-1) {
|
||||
|
||||
// remove read data
|
||||
FMemory::Memmove(RecvDataSet.GetData(), RecvDataSet.GetData() + i, RecvDataSet.Num() - i);
|
||||
RecvDataSet.SetNum(RecvDataSet.Num() - i);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
boneid = nullptr;
|
||||
TransformData = nullptr;
|
||||
}
|
||||
}// data loop
|
||||
if (bFindFieldSkdf) {
|
||||
continue;
|
||||
}
|
||||
if (bFindFieldFram == false) {
|
||||
break;
|
||||
}
|
||||
} // packet loop
|
||||
|
||||
|
||||
// no packet
|
||||
if (d.transformLocal.Num() != MocopiData::BoneNum) break;
|
||||
|
||||
d.transformWorld = d.transformLocal;
|
||||
|
||||
{
|
||||
auto v = d.transformWorld[0].GetLocation();
|
||||
d.transformWorld[0].SetLocation(FVector(v.X, v.Z, v.Y));
|
||||
}
|
||||
|
||||
for (int i = 1; i < MocopiData::BoneNum; ++i) {
|
||||
int parent = BoneChain[i];
|
||||
|
||||
auto r1 = d.transformWorld[parent].GetRotation();
|
||||
auto p1 = d.transformWorld[parent].GetLocation();
|
||||
|
||||
FTransform::Multiply(&d.transformWorld[i], &d.transformLocal[i], &d.transformWorld[parent]);
|
||||
}
|
||||
|
||||
FStructMocopiData md;
|
||||
if (frame>=0 && time>=0) {
|
||||
md.FrameNo = frame;
|
||||
md.Time = time;
|
||||
}
|
||||
md.MocopiTransformWorld = d.transformWorld;
|
||||
md.MocopiTransformLocal = d.transformLocal;
|
||||
md.VrmTransformLocal = d.transformVrmLocal;
|
||||
|
||||
{
|
||||
TMap<FString, int> BoneIdList = {
|
||||
{"hips", 0},
|
||||
{"leftUpperLeg", 19},
|
||||
{"rightUpperLeg", 23},
|
||||
{"leftLowerLeg", 20},
|
||||
{"rightLowerLeg", 24},
|
||||
{"leftFoot", 21},
|
||||
{"rightFoot", 25},
|
||||
{"spine", 3}, //
|
||||
{"chest", 6}, //
|
||||
{"upperChest", 7}, //
|
||||
{"neck", 8}, //
|
||||
{"head", 9},
|
||||
{"leftShoulder", 11},
|
||||
{"rightShoulder", 15},
|
||||
{"leftUpperArm", 12},
|
||||
{"rightUpperArm", 16},
|
||||
{"leftLowerArm", 13},
|
||||
{"rightLowerArm", 17},
|
||||
{"leftHand", 14},
|
||||
{"rightHand", 18},
|
||||
{"leftToes", 22},
|
||||
{"rightToes", 26},
|
||||
};
|
||||
|
||||
for (auto& b : BoneIdList) {
|
||||
md.VrmTransformBoneList.Add(b.Key, d.transformVrmLocal[b.Value]);
|
||||
}
|
||||
}
|
||||
|
||||
if (Receiver) {
|
||||
Receiver->OnPacketReceived(md);
|
||||
bUpdateData = true;
|
||||
}
|
||||
}// packet loop
|
||||
|
||||
if (bUpdateData && Receiver) {
|
||||
Receiver->PacketBroadcast();
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_LITTLE_ENDIAN
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
|
||||
|
||||
UVrmMocopiReceiver::UVrmMocopiReceiver(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer), ReceiverProxy(MakeUnique<FMocopiReceiverProxy>(this))
|
||||
{
|
||||
MocopiReceiveBuffer.Reserve(BufferNum);
|
||||
}
|
||||
|
||||
void UVrmMocopiReceiver::BeginDestroy() {
|
||||
Stop();
|
||||
Super::BeginDestroy();
|
||||
}
|
||||
|
||||
bool UVrmMocopiReceiver::SetAddress(const FString& InReceiveIPAddress, int32 InPort) {
|
||||
return ReceiverProxy->SetAddress(InReceiveIPAddress, InPort);
|
||||
}
|
||||
|
||||
|
||||
void UVrmMocopiReceiver::Stop() {
|
||||
if (ReceiverProxy) {
|
||||
ReceiverProxy->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UVrmMocopiReceiver::Listen() {
|
||||
ReceiverProxy->Listen();
|
||||
}
|
||||
|
||||
|
||||
void UVrmMocopiReceiver::SetBufferNum(int32 Num) {
|
||||
FScopeLock ScopeLock(&BufferCS);
|
||||
Num = FMath::Max(Num, 1);
|
||||
BufferNum = Num;
|
||||
MocopiReceiveBuffer.Reserve(BufferNum);
|
||||
}
|
||||
|
||||
|
||||
void UVrmMocopiReceiver::GetNextFrameData(FStructMocopiData &data, bool &bEnable, bool &bUpdate){
|
||||
bEnable = false;
|
||||
bUpdate = false;
|
||||
|
||||
FScopeLock ScopeLock(&BufferCS);
|
||||
|
||||
if (MocopiReceiveBuffer.Num() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bEnable == false) {
|
||||
for (int i = MocopiReceiveBuffer.Num() - 2; i >= 0; --i) {
|
||||
if (MocopiReceiveBuffer[i].FrameNo == currentFrameNo) {
|
||||
data = MocopiReceiveBuffer[i + 1];
|
||||
bEnable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bEnable == false) {
|
||||
data = MocopiReceiveBuffer.Last();
|
||||
}
|
||||
}
|
||||
|
||||
if (data.FrameNo != currentFrameNo) {
|
||||
bUpdate = true;
|
||||
}
|
||||
currentFrameNo = data.FrameNo;
|
||||
currentTime = data.Time;
|
||||
bEnable = true;
|
||||
}
|
||||
|
||||
void UVrmMocopiReceiver::GetLatestFrameData(FStructMocopiData &data, bool &bEnable, bool &bUpdate){
|
||||
bEnable = false;
|
||||
bUpdate = false;
|
||||
|
||||
FScopeLock ScopeLock(&BufferCS);
|
||||
|
||||
if (MocopiReceiveBuffer.Num() <= 0) {
|
||||
return;
|
||||
}
|
||||
data = MocopiReceiveBuffer.Last();
|
||||
|
||||
if (data.FrameNo != currentFrameNo) {
|
||||
bUpdate = true;
|
||||
}
|
||||
currentFrameNo = data.FrameNo;
|
||||
currentTime = data.Time;
|
||||
bEnable = true;
|
||||
|
||||
}
|
||||
|
||||
void UVrmMocopiReceiver::PacketBroadcast() {
|
||||
FScopeLock ScopeLock(&BufferCS);
|
||||
OnReceived.Broadcast(MocopiReceiveBuffer.Last());
|
||||
}
|
||||
|
||||
void UVrmMocopiReceiver::OnPacketReceived(FStructMocopiData data) {
|
||||
FScopeLock ScopeLock(&BufferCS);
|
||||
|
||||
while (MocopiReceiveBuffer.Num() >= BufferNum - 1) {
|
||||
if (MocopiReceiveBuffer.Num() == 0) {
|
||||
break;
|
||||
}
|
||||
#if UE_VERSION_OLDER_THAN(4,26,0)
|
||||
MocopiReceiveBuffer.RemoveAt(0);
|
||||
#else
|
||||
MocopiReceiveBuffer.PopFront();
|
||||
#endif
|
||||
}
|
||||
MocopiReceiveBuffer.Add(data);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "VrmVMCObject.h"
|
||||
#include "VRM4U_VMCSubsystem.h"
|
||||
|
||||
#include "Engine/Engine.h"
|
||||
#include "UObject/StrongObjectPtr.h"
|
||||
#include "Misc/ScopeLock.h"
|
||||
#include "OSCManager.h"
|
||||
#include "OSCServer.h"
|
||||
|
||||
void UVrmVMCObject::DestroyServer() {
|
||||
ServerName = "";
|
||||
port = 0;
|
||||
|
||||
if (OSCServer.Get()) {
|
||||
OSCServer->Stop();
|
||||
}
|
||||
OSCServer.Reset(nullptr);
|
||||
}
|
||||
void UVrmVMCObject::CreateServer(FString inName, uint16 inPort) {
|
||||
ServerName = inName;
|
||||
port = inPort;
|
||||
#if UE_VERSION_OLDER_THAN(4,25,0)
|
||||
#else
|
||||
OSCServer.Reset(UOSCManager::CreateOSCServer(ServerName, port, true, true, FString(), this));
|
||||
|
||||
OSCServer->OnOscMessageReceivedNative.RemoveAll(nullptr);
|
||||
OSCServer->OnOscMessageReceivedNative.AddUObject(this, &UVrmVMCObject::OSCReceivedMessageEvent);
|
||||
|
||||
#if WITH_EDITOR
|
||||
OSCServer->SetTickInEditor(true);
|
||||
#endif // WITH_EDITOR
|
||||
#endif
|
||||
}
|
||||
|
||||
void UVrmVMCObject::OSCReceivedMessageEvent(const FOSCMessage& Message, const FString& IPAddress, uint16 Port) {
|
||||
|
||||
FOSCAddress a = UOSCManager::GetOSCMessageAddress(Message);
|
||||
FString addressPath = UOSCManager::GetOSCAddressFullPath(a);
|
||||
|
||||
TArray<FString> str;
|
||||
UOSCManager::GetAllStrings(Message, str);
|
||||
|
||||
TArray<float> curve;
|
||||
UOSCManager::GetAllFloats(Message, curve);
|
||||
|
||||
FTransform t;
|
||||
float f = 0;
|
||||
if (curve.Num() == 1) {
|
||||
f = curve[0];
|
||||
}
|
||||
if (curve.Num() >= 7) {
|
||||
t.SetLocation(FVector(-curve[0], curve[2], curve[1]) * 100.f);
|
||||
t.SetRotation(FQuat(-curve[3], curve[5], curve[4], curve[6]));
|
||||
}
|
||||
if (curve.Num() >= 10) {
|
||||
t.SetScale3D(FVector(curve[7], curve[9], curve[8]));
|
||||
}
|
||||
|
||||
if (addressPath == TEXT("/VMC/Ext/Root/Pos")) {
|
||||
VMCData.BoneData.FindOrAdd(str[0]) = t;
|
||||
bDataUpdated = true;
|
||||
}
|
||||
if (addressPath == TEXT("/VMC/Ext/Bone/Pos")) {
|
||||
VMCData.BoneData.FindOrAdd(str[0]) = t;
|
||||
bDataUpdated = true;
|
||||
}
|
||||
if (addressPath == TEXT("/VMC/Ext/Blend/Val")) {
|
||||
VMCData.CurveData.FindOrAdd(str[0]) = f;
|
||||
bDataUpdated = true;
|
||||
}
|
||||
|
||||
if (bDataUpdated == true){
|
||||
bool b = bForceUpdate;
|
||||
if (addressPath == TEXT("/VMC/Ext/OK")) {
|
||||
b = true;
|
||||
}
|
||||
if (addressPath == TEXT("/VMC/Ext/T")) {
|
||||
b = true;
|
||||
}
|
||||
if (addressPath == TEXT("/VMC/Ext/Blend/Apply")) {
|
||||
b = true;
|
||||
}
|
||||
|
||||
if (b) {
|
||||
FScopeLock lock(&cs);
|
||||
VMCData_Cache = VMCData;
|
||||
bDataUpdated = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
bool UVrmVMCObject::CopyVMCData(FVMCData& dst) {
|
||||
FScopeLock lock(&cs);
|
||||
dst = VMCData_Cache;
|
||||
return true;
|
||||
}
|
||||
|
||||
void UVrmVMCObject::ClearVMCData() {
|
||||
FScopeLock lock(&cs);
|
||||
VMCData.ClearData();
|
||||
VMCData_Cache.ClearData();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "BoneContainer.h"
|
||||
#include "BonePose.h"
|
||||
#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
|
||||
#include "AnimNode_VrmVMC.generated.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
class UVrmMetaObject;
|
||||
class UVrmAssetListObject;
|
||||
|
||||
/**
|
||||
* Simple controller that replaces or adds to the translation/rotation of a single bone.
|
||||
*/
|
||||
USTRUCT(BlueprintInternalUseOnly)
|
||||
struct VRM4UCAPTURE_API FAnimNode_VrmVMC : public FAnimNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
bool EnableAutoSearchMetaData = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta=(PinHiddenByDefault))
|
||||
const UVrmMetaObject *VrmMetaObject = nullptr;
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
TAssetPtr<UVrmMetaObject> VrmMetaObject_Internal = nullptr;
|
||||
TAssetPtr<UVrmAssetListObject> VrmAssetListObject_Internal = nullptr;
|
||||
#else
|
||||
TSoftObjectPtr<UVrmMetaObject> VrmMetaObject_Internal = nullptr;
|
||||
TSoftObjectPtr<UVrmAssetListObject> VrmAssetListObject_Internal = nullptr;
|
||||
#endif
|
||||
|
||||
//UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
//TMap<FString, FTransform> BoneTrans;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
bool bUseRemoteCenterPos = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
float ModelRelativeScale = 1.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
bool bIgnoreLocalRotation = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
FString ServerAddress = "0.0.0.0";
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
int Port = 39539;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinShownByDefault))
|
||||
bool bApplyPerfectSync = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Skeleton, meta = (PinHiddenByDefault))
|
||||
bool bForceUpdate = false;
|
||||
|
||||
bool bCreateServer = false;
|
||||
|
||||
TArray<FTransform> RefSkeletonTransform_global;
|
||||
|
||||
FAnimNode_VrmVMC();
|
||||
virtual ~FAnimNode_VrmVMC();
|
||||
|
||||
// FAnimNode_Base interface
|
||||
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
||||
// End of FAnimNode_Base interface
|
||||
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) override;
|
||||
virtual void CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) override;
|
||||
// virtual void Update_AnyThread(const FAnimationUpdateContext& Context) override;
|
||||
virtual void EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms) override;
|
||||
virtual void EvaluateComponentPose_AnyThread(FComponentSpacePoseContext& Output) override;
|
||||
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
|
||||
|
||||
virtual void UpdateInternal(const FAnimationUpdateContext& Context)override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
|
||||
virtual void ConditionalDebugDraw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* PreviewSkelMeshComp, bool bPreviewForeground = false) const;
|
||||
|
||||
private:
|
||||
// FAnimNode_SkeletalControlBase interface
|
||||
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
||||
// End of FAnimNode_SkeletalControlBase interface
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/EngineSubsystem.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
#include "UObject/StrongObjectPtr.h"
|
||||
|
||||
#include "OSCServer.h"
|
||||
#include "VrmVMCObject.h"
|
||||
|
||||
#include "VRM4U_VMCSubsystem.generated.h"
|
||||
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,22,0)
|
||||
|
||||
//Couldn't find parent type for 'VRM4U_AnimSubsystem' named 'UEngineSubsystem'
|
||||
#error "please remove VRM4U_AnimSubsystem.h/cpp for <=UE4.21"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
UCLASS()
|
||||
class VRM4UCAPTURE_API UVRM4U_VMCSubsystem : public UEngineSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
bool CreateVMCServer(const FString ServerAddress, int port);
|
||||
|
||||
void ClearData(const FString ServerAddress, int port);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
void DestroyVMCServer(const FString ServerAddress, int port);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
void DestroyVMCServerAll();
|
||||
|
||||
UVrmVMCObject* FindOrAddServer(const FString ServerAddress, int port);
|
||||
|
||||
TArray< TStrongObjectPtr<UVrmVMCObject> > VMCObjectList;
|
||||
|
||||
bool CopyVMCData(FVMCData& DstData, FString ServerAddress, int port);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = VRM4U)
|
||||
bool GetVMCData(TMap<FString, FTransform> &BoneData, TMap<FString, float> &CurveData, FString ServerAddress, int port);
|
||||
|
||||
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
|
||||
private:
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
#include "Engine/LatentActionManager.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "VrmCaptureManager.generated.h"
|
||||
|
||||
class UVrmMocopiReceiver;
|
||||
|
||||
UCLASS()
|
||||
class VRM4UCAPTURE_API UVrmCaptureManager : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
static UVrmMocopiReceiver* CreateVrmMocopiReceiver(FString ReceiveIPAddress, int32 Port, bool bMulticastLoopback, bool bStartListening, FString ServerName, UObject* Outer = nullptr);
|
||||
|
||||
|
||||
};
|
||||
@@ -0,0 +1,157 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Misc/CoreDelegates.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "Interfaces/IPv4/IPv4Address.h"
|
||||
#include "Interfaces/IPv4/IPv4Endpoint.h"
|
||||
#include "Common/UdpSocketReceiver.h"
|
||||
#include "Sockets.h"
|
||||
#include "Common/UdpSocketBuilder.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
#include "Tickable.h"
|
||||
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,26,0)
|
||||
#else
|
||||
#include "Containers/RingBuffer.h"
|
||||
#endif
|
||||
|
||||
#include "VrmMocopiReceiver.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
enum MocopiData{
|
||||
BoneNum = 27,
|
||||
};
|
||||
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FStructMocopiData{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
int FrameNo = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
int Time = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, EditFixedSize, Category = "VRM4U")
|
||||
TArray<FTransform> MocopiTransformWorld;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, EditFixedSize, Category = "VRM4U")
|
||||
TArray<FTransform> MocopiTransformLocal;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, EditFixedSize, Category = "VRM4U")
|
||||
TArray<FTransform> VrmTransformLocal;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRM4U")
|
||||
TMap<FString, FTransform> VrmTransformBoneList;
|
||||
|
||||
FStructMocopiData() {
|
||||
MocopiTransformWorld.SetNum(MocopiData::BoneNum);
|
||||
MocopiTransformLocal.SetNum(MocopiData::BoneNum);
|
||||
VrmTransformLocal.SetNum(MocopiData::BoneNum);
|
||||
}
|
||||
};
|
||||
|
||||
class VRM4UCAPTURE_API FMocopiReceiverProxy : public FTickableGameObject
|
||||
{
|
||||
UVrmMocopiReceiver* Receiver;
|
||||
FSocket* Socket = nullptr;
|
||||
FUdpSocketReceiver* SocketReceiver = nullptr;
|
||||
|
||||
FIPv4Address ReceiveIPAddress;
|
||||
int32 Port = 8888;
|
||||
|
||||
TArray<uint8> RecvDataSet;
|
||||
|
||||
public:
|
||||
FMocopiReceiverProxy(UVrmMocopiReceiver *InReceiver);
|
||||
//FMocopiReceiverProxy(UVrmMocopiReceiver& InServer);
|
||||
virtual ~FMocopiReceiverProxy();
|
||||
|
||||
#if WITH_EDITOR
|
||||
virtual bool IsTickableInEditor() const override {
|
||||
return true;
|
||||
}
|
||||
#endif // WITH_EDITOR
|
||||
|
||||
void Listen();
|
||||
|
||||
void Stop();
|
||||
|
||||
bool SetAddress(const FString& ReceiveIPAddress, int32 Port);
|
||||
|
||||
virtual void Tick(float InDeltaTime) override;
|
||||
virtual TStatId GetStatId() const override;
|
||||
|
||||
void OnPacketReceived(const FArrayReaderPtr& InData, const FIPv4Endpoint& InEndpoint);
|
||||
};
|
||||
|
||||
|
||||
UCLASS(BlueprintType)
|
||||
class VRM4UCAPTURE_API UVrmMocopiReceiver : public UObject
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
int BufferNum = 10;
|
||||
int currentFrameNo = 0;
|
||||
int currentTime = 0;
|
||||
|
||||
mutable FCriticalSection BufferCS;
|
||||
|
||||
TUniquePtr<FMocopiReceiverProxy> ReceiverProxy;
|
||||
|
||||
#if UE_VERSION_OLDER_THAN(4,26,0)
|
||||
TArray<FStructMocopiData> MocopiReceiveBuffer;
|
||||
#else
|
||||
TRingBuffer<FStructMocopiData> MocopiReceiveBuffer;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void Listen();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void Stop();
|
||||
|
||||
void OnPacketReceived(const FArrayReaderPtr& InData, const FIPv4Endpoint& InEndpoint);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
bool SetAddress(const FString& ReceiveIPAddress, int32 Port);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void SetBufferNum(int32 Num = 10);
|
||||
|
||||
void OnPacketReceived(FStructMocopiData data);
|
||||
|
||||
void PacketBroadcast();
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FVrmMocopiReceiverDelegate, FStructMocopiData, data);
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "VRM4U")
|
||||
FVrmMocopiReceiverDelegate OnReceived;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void GetNextFrameData(FStructMocopiData &data, bool &bEnable, bool &bUpdate);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void GetLatestFrameData(FStructMocopiData &data, bool &bEnable, bool &bUpdate);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "VRM4U")
|
||||
void GetCurrentTime(int& FrameNo, int& Time) {
|
||||
FrameNo = currentFrameNo;
|
||||
Time = currentTime;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void BeginDestroy() override;
|
||||
|
||||
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
#include "UObject/StrongObjectPtr.h"
|
||||
#include "OSCServer.h" // for game build link error
|
||||
|
||||
#include "VrmVMCObject.generated.h"
|
||||
|
||||
struct FOSCMessage;
|
||||
|
||||
struct FVMCData {
|
||||
FString ServerAddress = "";
|
||||
int Port = 0;
|
||||
|
||||
TMap<FString, FTransform> BoneData;
|
||||
TMap<FString, float> CurveData;
|
||||
|
||||
void ClearData() {
|
||||
BoneData.Empty();
|
||||
CurveData.Empty();
|
||||
}
|
||||
|
||||
bool operator==(const FVMCData& Other) const {
|
||||
if (Port != Other.Port) return false;
|
||||
if (ServerAddress != Other.ServerAddress) return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
UCLASS()
|
||||
class VRM4UCAPTURE_API UVrmVMCObject : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FCriticalSection cs;
|
||||
|
||||
TStrongObjectPtr<UOSCServer> OSCServer;
|
||||
|
||||
FVMCData VMCData;
|
||||
FVMCData VMCData_Cache;
|
||||
|
||||
bool bDataUpdated = false;
|
||||
public:
|
||||
|
||||
|
||||
FString ServerName;
|
||||
uint16 port;
|
||||
|
||||
bool bForceUpdate = false;
|
||||
|
||||
void CreateServer(FString name, uint16 port);
|
||||
void DestroyServer();
|
||||
void OSCReceivedMessageEvent(const FOSCMessage& Message, const FString& IPAddress, uint16 Port);
|
||||
|
||||
bool CopyVMCData(FVMCData& dst);
|
||||
void ClearVMCData();
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class VRM4UCapture : ModuleRules
|
||||
{
|
||||
public VRM4UCapture(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Networking",
|
||||
"Sockets",
|
||||
"OSC",
|
||||
"AnimGraphRuntime",
|
||||
|
||||
"VRM4U",
|
||||
});
|
||||
|
||||
if (Target.bBuildEditor)
|
||||
{
|
||||
PrivateDependencyModuleNames.Add("UnrealEd");
|
||||
}
|
||||
|
||||
|
||||
PrivateIncludePathModuleNames.AddRange(
|
||||
new string[] {
|
||||
});
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[] {
|
||||
});
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// Relative to Engine\Plugins\Runtime\Oculus\OculusVR\Source
|
||||
//"../Runtime/Renderer/Private",
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "AnimGraphNode_VrmVMC.h"
|
||||
#include "Misc/EngineVersionComparison.h"
|
||||
#include "UnrealWidget.h"
|
||||
#include "AnimNodeEditModes.h"
|
||||
#include "AnimationRuntime.h"
|
||||
#include "Animation/AnimInstance.h"
|
||||
#include "Kismet2/CompilerResultsLog.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "VrmMetaObject.h"
|
||||
#include "VrmUtil.h"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// UAnimGraphNode_ModifyBone
|
||||
|
||||
#define LOCTEXT_NAMESPACE "A3Nodesaaaa"
|
||||
////////////////////
|
||||
|
||||
|
||||
UAnimGraphNode_VrmVMC::UAnimGraphNode_VrmVMC(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
#if UE_VERSION_OLDER_THAN(5,0,0)
|
||||
CurWidgetMode = (int32)FWidget::WM_Rotate;
|
||||
#else
|
||||
CurWidgetMode = UE::Widget::EWidgetMode::WM_Rotate;
|
||||
#endif
|
||||
}
|
||||
|
||||
void UAnimGraphNode_VrmVMC::ValidateAnimNodePostCompile(FCompilerResultsLog& MessageLog, UAnimBlueprintGeneratedClass* CompiledClass, int32 CompiledNodeIndex) {
|
||||
|
||||
if (Node.VrmMetaObject == nullptr) {
|
||||
//MessageLog.Warning(*LOCTEXT("VrmNoMetaObject", "@@ - You must set VrmMetaObject").ToString(), this);
|
||||
} else {
|
||||
if (Node.VrmMetaObject->SkeletalMesh) {
|
||||
if (VRMGetSkeleton(Node.VrmMetaObject->SkeletalMesh) != CompiledClass->GetTargetSkeleton()) {
|
||||
MessageLog.Warning(*LOCTEXT("VrmDifferentSkeleton", "@@ - You must set VrmMetaObject has same skeleton").ToString(), this);
|
||||
}
|
||||
}
|
||||
if (CompiledClass->GetTargetSkeleton()->GetReferenceSkeleton().GetRawBoneNum() <= 0) {
|
||||
MessageLog.Warning(*LOCTEXT("VrmNoBone", "@@ - Skeleton bad data").ToString(), this);
|
||||
}
|
||||
}
|
||||
|
||||
Super::ValidateAnimNodePostCompile(MessageLog, CompiledClass, CompiledNodeIndex);
|
||||
}
|
||||
|
||||
void UAnimGraphNode_VrmVMC::ValidateAnimNodeDuringCompilation(USkeleton* ForSkeleton, FCompilerResultsLog& MessageLog)
|
||||
{
|
||||
// Temporary fix where skeleton is not fully loaded during AnimBP compilation and thus virtual bone name check is invalid UE-39499 (NEED FIX)
|
||||
if (ForSkeleton && !ForSkeleton->HasAnyFlags(RF_NeedPostLoad))
|
||||
{
|
||||
if (Node.VrmMetaObject == nullptr) {
|
||||
//MessageLog.Warning(*LOCTEXT("VrmNoMetaObject", "@@ - You must set VrmMetaObject").ToString(), this);
|
||||
} else {
|
||||
if (Node.VrmMetaObject->SkeletalMesh){
|
||||
if (VRMGetSkeleton(Node.VrmMetaObject->SkeletalMesh) != ForSkeleton) {
|
||||
// MessageLog.Warning(*LOCTEXT("VrmDifferentSkeleton", "@@ - You must set VrmMetaObject has same skeleton").ToString(), this);
|
||||
}
|
||||
}
|
||||
if (ForSkeleton->GetReferenceSkeleton().GetRawBoneNum() <= 0) {
|
||||
// MessageLog.Warning(*LOCTEXT("VrmNoBone", "@@ - Skeleton bad data").ToString(), this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//if (ForSkeleton->GetReferenceSkeleton().FindBoneIndex(Node.BoneToModify.BoneName) == INDEX_NONE)
|
||||
if (ForSkeleton->GetReferenceSkeleton().FindBoneIndex(Node.BoneNameToModify) == INDEX_NONE)
|
||||
{
|
||||
//if (Node.BoneToModify.BoneName == NAME_None)
|
||||
if (Node.BoneNameToModify == NAME_None)
|
||||
{
|
||||
MessageLog.Warning(*LOCTEXT("NoBoneSelectedToModify", "@@ - You must pick a bone to modify").ToString(), this);
|
||||
}
|
||||
else
|
||||
{
|
||||
FFormatNamedArguments Args;
|
||||
//Args.Add(TEXT("BoneName"), FText::FromName(Node.BoneToModify.BoneName));
|
||||
Args.Add(TEXT("BoneName"), FText::FromName(Node.BoneNameToModify));
|
||||
|
||||
FText Msg = FText::Format(LOCTEXT("NoBoneFoundToModify", "@@ - Bone {BoneName} not found in Skeleton"), Args);
|
||||
|
||||
MessageLog.Warning(*Msg.ToString(), this);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//if ((Node.TranslationMode == BMM_Ignore) && (Node.RotationMode == BMM_Ignore) && (Node.ScaleMode == BMM_Ignore))
|
||||
{
|
||||
// MessageLog.Warning(*LOCTEXT("NothingToModify", "@@ - No components to modify selected. Either Rotation, Translation, or Scale should be set to something other than Ignore").ToString(), this);
|
||||
}
|
||||
|
||||
Super::ValidateAnimNodeDuringCompilation(ForSkeleton, MessageLog);
|
||||
}
|
||||
|
||||
FText UAnimGraphNode_VrmVMC::GetControllerDescription() const
|
||||
{
|
||||
return LOCTEXT("VrmVMC", "VrmVMC");
|
||||
}
|
||||
|
||||
FText UAnimGraphNode_VrmVMC::GetTooltipText() const
|
||||
{
|
||||
return LOCTEXT("AnimGraphNode_VrmVMC_Tooltip", "VrmVMC");
|
||||
}
|
||||
|
||||
FText UAnimGraphNode_VrmVMC::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
||||
{
|
||||
return GetControllerDescription();
|
||||
//if ((TitleType == ENodeTitleType::ListView || TitleType == ENodeTitleType::MenuTitle) && (Node.SpringBone.BoneName == NAME_None))
|
||||
//{
|
||||
// return GetControllerDescription();
|
||||
//}
|
||||
|
||||
/*
|
||||
FFormatNamedArguments Args;
|
||||
Args.Add(TEXT("ControllerDescription"), GetControllerDescription());
|
||||
Args.Add(TEXT("Server"), FText::FromString(Node.ServerAddress));
|
||||
Args.Add(TEXT("Port"), FText::FromString(FString::FromInt(Node.Port)));
|
||||
|
||||
if (TitleType == ENodeTitleType::ListView || TitleType == ENodeTitleType::MenuTitle)
|
||||
{
|
||||
CachedNodeTitles.SetCachedTitle(TitleType, FText::Format(LOCTEXT("AnimGraphNode_VrmVMC_ListTitle", "{ControllerDescription} - {Server}:{Port}"), Args), this);
|
||||
}
|
||||
else
|
||||
{
|
||||
CachedNodeTitles.SetCachedTitle(TitleType, FText::Format(LOCTEXT("AnimGraphNode_VrmVMC_ListTitle", "{ControllerDescription}\n{Server}:{Port}"), Args), this);
|
||||
}
|
||||
|
||||
return CachedNodeTitles[TitleType];
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
//void UAnimGraphNode_VrmVMC::CopyNodeDataToPreviewNode(FAnimNode_Base* InPreviewNode)
|
||||
//{
|
||||
//}
|
||||
|
||||
FEditorModeID UAnimGraphNode_VrmVMC::GetEditorMode() const
|
||||
{
|
||||
return Super::GetEditorMode();
|
||||
}
|
||||
|
||||
void UAnimGraphNode_VrmVMC::Draw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent * PreviewSkelMeshComp) const
|
||||
{
|
||||
if (PreviewSkelMeshComp)
|
||||
{
|
||||
if (FAnimNode_VrmVMC* ActiveNode = GetActiveInstanceNode<FAnimNode_VrmVMC>(PreviewSkelMeshComp->GetAnimInstance()))
|
||||
{
|
||||
if (bPreviewLive) {
|
||||
//ActiveNode->ConditionalDebugDraw(PDI, PreviewSkelMeshComp, bPreviewForeground);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,65 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
//#include "BoneControllers/AnimNode_ModifyBone.h"
|
||||
#include "AnimNode_VrmVMC.h"
|
||||
#include "EdGraph/EdGraphNodeUtils.h"
|
||||
#include "AnimGraphNode_SkeletalControlBase.h"
|
||||
|
||||
#include "UnrealWidget.h"
|
||||
#include "AnimNodeEditMode.h"
|
||||
|
||||
#include "AnimGraphNode_VrmVMC.generated.h"
|
||||
|
||||
class FCompilerResultsLog;
|
||||
class FPrimitiveDrawInterface;
|
||||
class USkeletalMeshComponent;
|
||||
|
||||
UCLASS(meta=(Keywords = "VRM4U"))
|
||||
class UAnimGraphNode_VrmVMC : public UAnimGraphNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = Settings)
|
||||
FAnimNode_VrmVMC Node;
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, Category = Preview)
|
||||
bool bPreviewLive = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = Preview)
|
||||
bool bPreviewForeground = false;
|
||||
|
||||
// UEdGraphNode interface
|
||||
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
|
||||
virtual FText GetTooltipText() const override;
|
||||
// End of UEdGraphNode interface
|
||||
|
||||
protected:
|
||||
// UAnimGraphNode_Base interface
|
||||
virtual void ValidateAnimNodeDuringCompilation(USkeleton* ForSkeleton, FCompilerResultsLog& MessageLog) override;
|
||||
virtual void ValidateAnimNodePostCompile(FCompilerResultsLog& MessageLog, UAnimBlueprintGeneratedClass* CompiledClass, int32 CompiledNodeIndex) override;
|
||||
// virtual FEditorModeID GetEditorMode() const override;
|
||||
//virtual void CopyNodeDataToPreviewNode(FAnimNode_Base* InPreviewNode) override;
|
||||
//virtual void CopyPinDefaultsToNodeData(UEdGraphPin* InPin) override;
|
||||
|
||||
virtual FEditorModeID GetEditorMode() const override;
|
||||
virtual void Draw(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent * PreviewSkelMeshComp) const override;
|
||||
// End of UAnimGraphNode_Base interface
|
||||
|
||||
// UAnimGraphNode_SkeletalControlBase interface
|
||||
virtual FText GetControllerDescription() const override;
|
||||
virtual const FAnimNode_SkeletalControlBase* GetNode() const override { return &Node; }
|
||||
// End of UAnimGraphNode_SkeletalControlBase interface
|
||||
|
||||
private:
|
||||
/** Constructing FText strings can be costly, so we cache the node's title */
|
||||
FNodeTitleTextTable CachedNodeTitles;
|
||||
|
||||
// storing current widget mode
|
||||
int32 CurWidgetMode;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#include "VRM4UCaptureEditor.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "VRM4UCaptureEditorLog.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "Internationalization/Internationalization.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "VRM4UMisc"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogVRM4UCaptureEditor);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FSpriterImporterModule
|
||||
|
||||
class FVRM4UCaptureEditorModule : public FDefaultModuleImpl
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ShutdownModule() override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPLEMENT_MODULE(FVRM4UCaptureEditorModule, VRM4UCaptureEditor);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,8 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
//#include "VRMImporterModule.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
//#include "VRMImporterModule.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogVRM4UCaptureEditor, Verbose, All);
|
||||
|
||||
//#define SPRITER_IMPORT_ERROR(FormatString, ...) \
|
||||
// if (!bSilent) { UE_LOG(LogVRM4UMIsc, Warning, FormatString, __VA_ARGS__); }
|
||||
//#define SPRITER_IMPORT_WARNING(FormatString, ...) \
|
||||
// if (!bSilent) { UE_LOG(LogVRM4UMIsc, Warning, FormatString, __VA_ARGS__); }
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class VRM4UCaptureEditor : ModuleRules
|
||||
{
|
||||
public VRM4UCaptureEditor(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
|
||||
"AnimGraphRuntime",
|
||||
"AnimGraph",
|
||||
"BlueprintGraph",
|
||||
|
||||
"UnrealEd",
|
||||
"AnimationEditMode",
|
||||
"Persona",
|
||||
|
||||
"VRM4U",
|
||||
"VRM4UCapture",
|
||||
});
|
||||
|
||||
PrivateIncludePathModuleNames.AddRange(
|
||||
new string[] {
|
||||
});
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[] {
|
||||
});
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
//"../Runtime/Renderer/Private",
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
#include "VRM4UEditor.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "VRM4UEditorLog.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "Internationalization/Internationalization.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "VRM4UEditor"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogVRM4UEditor);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FSpriterImporterModule
|
||||
|
||||
class FVRM4UEditorModule : public FDefaultModuleImpl
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ShutdownModule() override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPLEMENT_MODULE(FVRM4UEditorModule, VRM4UEditor);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user