You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Option for the grab/poke raycast distance #jira UE-129539 #jira UE-130564 #rb cedric.caillaud #preflight 615c2e46f556160001b5d5d5 #ROBOMERGE-AUTHOR: danny.chapman #ROBOMERGE-SOURCE: CL 17719687 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v879-17706426) [CL 17719705 by danny chapman in ue5-release-engine-test branch]
642 lines
24 KiB
C++
642 lines
24 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "PhysicsAssetEditorSkeletalMeshComponent.h"
|
|
#include "Materials/MaterialInterface.h"
|
|
#include "Materials/MaterialInstanceDynamic.h"
|
|
#include "Components/SkeletalMeshComponent.h"
|
|
#include "Materials/Material.h"
|
|
#include "Preferences/PhysicsAssetEditorOptions.h"
|
|
#include "SceneManagement.h"
|
|
#include "PhysicsAssetEditorSharedData.h"
|
|
#include "PhysicsAssetEditorHitProxies.h"
|
|
#include "PhysicsAssetEditorSkeletalMeshComponent.h"
|
|
#include "PhysicsAssetEditorAnimInstance.h"
|
|
#include "PhysicsEngine/PhysicsConstraintTemplate.h"
|
|
#include "PhysicsEngine/PhysicsAsset.h"
|
|
#include "Chaos/Core.h"
|
|
#include "SkeletalMeshTypes.h"
|
|
#include "AnimPreviewInstance.h"
|
|
#include "UObject/Package.h"
|
|
#include "EditorStyleSet.h"
|
|
|
|
namespace
|
|
{
|
|
// How large to make the constraint arrows.
|
|
// The factor of 60 was found experimentally, to look reasonable in comparison with the rest of the constraint visuals.
|
|
constexpr float ConstraintArrowScale = 60.0f;
|
|
|
|
bool bDebugViewportClicks = false;
|
|
FAutoConsoleVariableRef CVarChaosImmPhysStepTime(TEXT("p.PhAT.DebugViewportClicks"), bDebugViewportClicks, TEXT("Set to 1 to show mouse click results in PhAT"));
|
|
|
|
}
|
|
|
|
UPhysicsAssetEditorSkeletalMeshComponent::UPhysicsAssetEditorSkeletalMeshComponent(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
, BoneUnselectedColor(170, 155, 225)
|
|
, NoCollisionColor(200, 200, 200)
|
|
, FixedColor(125, 125, 0)
|
|
, ConstraintBone1Color(255, 166, 0)
|
|
, ConstraintBone2Color(0, 150, 150)
|
|
, HierarchyDrawColor(220, 255, 220)
|
|
, AnimSkelDrawColor(255, 64, 64)
|
|
, COMRenderSize(5.0f)
|
|
, InfluenceLineLength(2.0f)
|
|
, InfluenceLineColor(0, 255, 0)
|
|
{
|
|
if (!HasAnyFlags(RF_DefaultSubObject | RF_ArchetypeObject | RF_ClassDefaultObject))
|
|
{
|
|
// Body materials
|
|
UMaterialInterface* BaseElemSelectedMaterial = LoadObject<UMaterialInterface>(NULL, TEXT("/Engine/EditorMaterials/PhAT_ElemSelectedMaterial.PhAT_ElemSelectedMaterial"), NULL, LOAD_None, NULL);
|
|
ElemSelectedMaterial = UMaterialInstanceDynamic::Create(BaseElemSelectedMaterial, GetTransientPackage());
|
|
check(ElemSelectedMaterial);
|
|
|
|
BoneMaterialHit = UMaterial::GetDefaultMaterial(MD_Surface);
|
|
check(BoneMaterialHit);
|
|
|
|
UMaterialInterface* BaseBoneUnselectedMaterial = LoadObject<UMaterialInterface>(NULL, TEXT("/Engine/EditorMaterials/PhAT_UnselectedMaterial.PhAT_UnselectedMaterial"), NULL, LOAD_None, NULL);
|
|
BoneUnselectedMaterial = UMaterialInstanceDynamic::Create(BaseBoneUnselectedMaterial, GetTransientPackage());
|
|
check(BoneUnselectedMaterial);
|
|
|
|
UMaterialInterface* BaseBoneNoCollisionMaterial = LoadObject<UMaterialInterface>(NULL, TEXT("/Engine/EditorMaterials/PhAT_NoCollisionMaterial.PhAT_NoCollisionMaterial"), NULL, LOAD_None, NULL);
|
|
BoneNoCollisionMaterial = UMaterialInstanceDynamic::Create(BaseBoneNoCollisionMaterial, GetTransientPackage());
|
|
check(BoneNoCollisionMaterial);
|
|
|
|
// this is because in phat editor, you'd like to see fixed bones to be fixed without animation force update
|
|
KinematicBonesUpdateType = EKinematicBonesUpdateToPhysics::SkipSimulatingBones;
|
|
bUpdateJointsFromAnimation = false;
|
|
SetForcedLOD(1);
|
|
|
|
static FName CollisionProfileName(TEXT("PhysicsActor"));
|
|
SetCollisionProfileName(CollisionProfileName);
|
|
}
|
|
|
|
bSelectable = false;
|
|
}
|
|
|
|
void UPhysicsAssetEditorSkeletalMeshComponent::RenderAssetTools(const FSceneView* View, class FPrimitiveDrawInterface* PDI)
|
|
{
|
|
check(SharedData);
|
|
|
|
UPhysicsAsset* const PhysicsAsset = GetPhysicsAsset();
|
|
|
|
if (!PhysicsAsset)
|
|
{
|
|
// Nothing to draw without an asset, this can happen if the preview scene has no skeletal mesh
|
|
return;
|
|
}
|
|
|
|
EPhysicsAssetEditorCollisionViewMode CollisionViewMode = SharedData->GetCurrentCollisionViewMode(SharedData->bRunningSimulation);
|
|
|
|
if (bDebugViewportClicks)
|
|
{
|
|
PDI->DrawLine(SharedData->LastClickOrigin, SharedData->LastClickOrigin + SharedData->LastClickDirection * 5000.0f, FLinearColor(1, 1, 0, 1), SDPG_Foreground);
|
|
PDI->DrawPoint(SharedData->LastClickOrigin, FLinearColor(1, 1, 0), 5, SDPG_Foreground);
|
|
PDI->DrawLine(SharedData->LastClickHitPos, SharedData->LastClickHitPos + SharedData->LastClickHitNormal * 10.0f, FLinearColor(1, 0, 0, 1), SDPG_Foreground);
|
|
PDI->DrawPoint(SharedData->LastClickHitPos, FLinearColor(1, 0, 0), 5, SDPG_Foreground);
|
|
}
|
|
|
|
// set opacity of our materials
|
|
static FName OpacityName(TEXT("Opacity"));
|
|
ElemSelectedMaterial->SetScalarParameterValue(OpacityName, SharedData->EditorOptions->CollisionOpacity);
|
|
BoneUnselectedMaterial->SetScalarParameterValue(OpacityName, SharedData->EditorOptions->bSolidRenderingForSelectedOnly ? 0.0f : SharedData->EditorOptions->CollisionOpacity);
|
|
BoneNoCollisionMaterial->SetScalarParameterValue(OpacityName, SharedData->EditorOptions->bSolidRenderingForSelectedOnly ? 0.0f : SharedData->EditorOptions->CollisionOpacity);
|
|
|
|
static FName SelectionColorName(TEXT("SelectionColor"));
|
|
const FSlateColor SelectionColor = FEditorStyle::GetSlateColor(SelectionColorName);
|
|
const FLinearColor LinearSelectionColor(SelectionColor.IsColorSpecified() ? SelectionColor.GetSpecifiedColor() : FLinearColor::White);
|
|
|
|
ElemSelectedMaterial->SetVectorParameterValue(SelectionColorName, LinearSelectionColor);
|
|
|
|
// Contains info needed for drawing, in a form that can be sorted by distance.
|
|
struct DrawElement
|
|
{
|
|
DrawElement(
|
|
FTransform InTM,
|
|
HHitProxy* InHitProxy,
|
|
float InScale,
|
|
const FSceneView* InView,
|
|
FKShapeElem* InShapeElem,
|
|
const FName& InBoneName
|
|
)
|
|
: TM(InTM), HitProxy(InHitProxy), Scale(InScale), ShapeElem(InShapeElem)
|
|
#ifdef UE_BUILD_DEBUG
|
|
, BoneName(InBoneName)
|
|
#endif
|
|
{
|
|
// The TM position is at the center of the objects, so can be used directly for sorting.
|
|
// Sorting by distance (rather than along the view direction) reduces flickering when
|
|
// the camera is rotated without moving it.
|
|
FVector ViewDir = InView->GetViewDirection();
|
|
//Distance = TM.GetTranslation() | ViewDir; // Would sort along the view direction
|
|
SortingMetric = (TM.GetTranslation() - InView->ViewLocation).SquaredLength(); // Sorts by Distance
|
|
}
|
|
|
|
UMaterialInterface* Material = 0;
|
|
FColor Color = FColor(ForceInitToZero);
|
|
FTransform TM;
|
|
HHitProxy* HitProxy = nullptr;
|
|
float Scale;
|
|
FKShapeElem* ShapeElem = nullptr;
|
|
float SortingMetric;
|
|
#ifdef UE_BUILD_DEBUG
|
|
FName BoneName;
|
|
#endif
|
|
};
|
|
TArray<DrawElement> DrawElements;
|
|
|
|
// Draw bodies
|
|
for (int32 i = 0; i <PhysicsAsset->SkeletalBodySetups.Num(); ++i)
|
|
{
|
|
if (!ensure(PhysicsAsset->SkeletalBodySetups[i]))
|
|
{
|
|
continue;
|
|
}
|
|
if ((PhysicsAsset->SkeletalBodySetups[i]->PhysicsType == EPhysicsType::PhysType_Kinematic &&
|
|
SharedData->EditorOptions->bHideKinematicBodies) ||
|
|
(PhysicsAsset->SkeletalBodySetups[i]->PhysicsType == EPhysicsType::PhysType_Simulated &&
|
|
SharedData->EditorOptions->bHideSimulatedBodies)
|
|
)
|
|
{
|
|
continue;
|
|
}
|
|
if (SharedData->HiddenBodies.Contains(i))
|
|
{
|
|
continue;
|
|
}
|
|
int32 BoneIndex = GetBoneIndex(PhysicsAsset->SkeletalBodySetups[i]->BoneName);
|
|
|
|
// If we found a bone for it, draw the collision.
|
|
// The logic is as follows; always render in the ViewMode requested when not in hit mode - but if we are in hit mode and the right editing mode, render as solid
|
|
if (BoneIndex != INDEX_NONE)
|
|
{
|
|
FTransform BoneTM = GetBoneTransform(BoneIndex);
|
|
float Scale = BoneTM.GetScale3D().GetAbsMax();
|
|
BoneTM.RemoveScaling();
|
|
|
|
FKAggregateGeom* AggGeom = &PhysicsAsset->SkeletalBodySetups[i]->AggGeom;
|
|
|
|
for (int32 j = 0; j <AggGeom->SphereElems.Num(); ++j)
|
|
{
|
|
DrawElement DE(
|
|
GetPrimitiveTransform(BoneTM, i, EAggCollisionShape::Sphere, j, Scale),
|
|
new HPhysicsAssetEditorEdBoneProxy(i, EAggCollisionShape::Sphere, j),
|
|
Scale, View, &AggGeom->SphereElems[j], GetBoneName(BoneIndex)
|
|
);
|
|
|
|
//solids are drawn if it's the ViewMode and we're not doing a hit, or if it's hitAndBodyMode
|
|
if (CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::Solid || CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::SolidWireframe)
|
|
{
|
|
DE.Material = GetPrimitiveMaterial(i, EAggCollisionShape::Sphere, j);
|
|
}
|
|
if (CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::SolidWireframe || CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::Wireframe)
|
|
{
|
|
DE.Color = GetPrimitiveColor(i, EAggCollisionShape::Sphere, j);
|
|
}
|
|
if (DE.Material || DE.Color.A)
|
|
{
|
|
DrawElements.Add(DE);
|
|
}
|
|
}
|
|
|
|
for (int32 j = 0; j <AggGeom->BoxElems.Num(); ++j)
|
|
{
|
|
DrawElement DE(
|
|
GetPrimitiveTransform(BoneTM, i, EAggCollisionShape::Box, j, Scale),
|
|
new HPhysicsAssetEditorEdBoneProxy(i, EAggCollisionShape::Box, j),
|
|
Scale, View, &AggGeom->BoxElems[j], GetBoneName(BoneIndex)
|
|
);
|
|
|
|
if (CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::Solid || CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::SolidWireframe)
|
|
{
|
|
DE.Material = GetPrimitiveMaterial(i, EAggCollisionShape::Box, j);
|
|
}
|
|
if (CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::SolidWireframe || CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::Wireframe)
|
|
{
|
|
DE.Color = GetPrimitiveColor(i, EAggCollisionShape::Box, j);
|
|
}
|
|
if (DE.Material || DE.Color.A)
|
|
{
|
|
DrawElements.Add(DE);
|
|
}
|
|
}
|
|
|
|
for (int32 j = 0; j <AggGeom->SphylElems.Num(); ++j)
|
|
{
|
|
DrawElement DE(
|
|
GetPrimitiveTransform(BoneTM, i, EAggCollisionShape::Sphyl, j, Scale),
|
|
new HPhysicsAssetEditorEdBoneProxy(i, EAggCollisionShape::Sphyl, j),
|
|
Scale, View, &AggGeom->SphylElems[j], GetBoneName(BoneIndex)
|
|
);
|
|
|
|
if (CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::Solid || CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::SolidWireframe)
|
|
{
|
|
DE.Material = GetPrimitiveMaterial(i, EAggCollisionShape::Sphyl, j);
|
|
}
|
|
if (CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::SolidWireframe || CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::Wireframe)
|
|
{
|
|
DE.Color = GetPrimitiveColor(i, EAggCollisionShape::Sphyl, j);
|
|
}
|
|
if (DE.Material || DE.Color.A)
|
|
{
|
|
DrawElements.Add(DE);
|
|
}
|
|
}
|
|
|
|
for (int32 j = 0; j <AggGeom->ConvexElems.Num(); ++j)
|
|
{
|
|
DrawElement DE(
|
|
GetPrimitiveTransform(BoneTM, i, EAggCollisionShape::Convex, j, Scale),
|
|
new HPhysicsAssetEditorEdBoneProxy(i, EAggCollisionShape::Convex, j),
|
|
Scale, View, &AggGeom->ConvexElems[j], GetBoneName(BoneIndex)
|
|
);
|
|
|
|
if (CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::Solid || CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::SolidWireframe)
|
|
{
|
|
DE.Material = GetPrimitiveMaterial(i, EAggCollisionShape::Convex, j);
|
|
}
|
|
if (CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::SolidWireframe || CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::Wireframe)
|
|
{
|
|
DE.Color = GetPrimitiveColor(i, EAggCollisionShape::Convex, j);
|
|
}
|
|
if (DE.Material || DE.Color.A)
|
|
{
|
|
DrawElements.Add(DE);
|
|
}
|
|
}
|
|
|
|
for (int32 j = 0; j <AggGeom->TaperedCapsuleElems.Num(); ++j)
|
|
{
|
|
DrawElement DE(
|
|
GetPrimitiveTransform(BoneTM, i, EAggCollisionShape::TaperedCapsule, j, Scale),
|
|
new HPhysicsAssetEditorEdBoneProxy(i, EAggCollisionShape::TaperedCapsule, j),
|
|
Scale, View, &AggGeom->TaperedCapsuleElems[j], GetBoneName(BoneIndex)
|
|
);
|
|
|
|
if (CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::Solid || CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::SolidWireframe)
|
|
{
|
|
DE.Material = GetPrimitiveMaterial(i, EAggCollisionShape::TaperedCapsule, j);
|
|
}
|
|
if (CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::SolidWireframe || CollisionViewMode == EPhysicsAssetEditorCollisionViewMode::Wireframe)
|
|
{
|
|
DE.Color = GetPrimitiveColor(i, EAggCollisionShape::TaperedCapsule, j);
|
|
}
|
|
if (DE.Material || DE.Color.A)
|
|
{
|
|
DrawElements.Add(DE);
|
|
}
|
|
}
|
|
|
|
if (SharedData->bShowCOM && Bodies.IsValidIndex(i))
|
|
{
|
|
Bodies[i]->DrawCOMPosition(PDI, COMRenderSize, SharedData->COMRenderColor);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sort elements
|
|
DrawElements.Sort([this](const DrawElement& DE1, const DrawElement& DE2) {
|
|
return DE1.SortingMetric > DE2.SortingMetric;
|
|
});
|
|
|
|
|
|
// Render sorted elements.
|
|
for (const DrawElement& DE : DrawElements)
|
|
{
|
|
PDI->SetHitProxy(DE.HitProxy);
|
|
if (DE.Material)
|
|
{
|
|
DE.ShapeElem->DrawElemSolid(PDI, DE.TM, DE.Scale, DE.Material->GetRenderProxy());
|
|
}
|
|
if (DE.Color.A)
|
|
{
|
|
DE.ShapeElem->DrawElemWire(PDI, DE.TM, DE.Scale, DE.Color);
|
|
}
|
|
PDI->SetHitProxy(NULL);
|
|
}
|
|
|
|
// Draw Constraints
|
|
EPhysicsAssetEditorConstraintViewMode ConstraintViewMode = SharedData->GetCurrentConstraintViewMode(SharedData->bRunningSimulation);
|
|
if (ConstraintViewMode != EPhysicsAssetEditorConstraintViewMode::None)
|
|
{
|
|
for (int32 i = 0; i <PhysicsAsset->ConstraintSetup.Num(); ++i)
|
|
{
|
|
if((!SharedData->EditorOptions->bRenderOnlySelectedConstraints || (SharedData->EditorOptions->bRenderOnlySelectedConstraints && SharedData->IsConstraintSelected(i))) &&
|
|
!SharedData->HiddenConstraints.Contains(i))
|
|
{
|
|
int32 BoneIndex1 = GetBoneIndex(PhysicsAsset->ConstraintSetup[i]->DefaultInstance.ConstraintBone1);
|
|
int32 BoneIndex2 = GetBoneIndex(PhysicsAsset->ConstraintSetup[i]->DefaultInstance.ConstraintBone2);
|
|
// if bone doesn't exist, do not draw it. It crashes in random points when we try to manipulate.
|
|
if (BoneIndex1 != INDEX_NONE && BoneIndex2 != INDEX_NONE)
|
|
{
|
|
PDI->SetHitProxy(new HPhysicsAssetEditorEdConstraintProxy(i));
|
|
|
|
DrawConstraint(i, View, PDI, SharedData->EditorOptions->bShowConstraintsAsPoints);
|
|
|
|
PDI->SetHitProxy(NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UPhysicsAssetEditorSkeletalMeshComponent::DebugDraw(const FSceneView* View, FPrimitiveDrawInterface* PDI)
|
|
{
|
|
RenderAssetTools(View, PDI);
|
|
}
|
|
|
|
FPrimitiveSceneProxy* UPhysicsAssetEditorSkeletalMeshComponent::CreateSceneProxy()
|
|
{
|
|
FPrimitiveSceneProxy* Proxy = NULL;
|
|
EPhysicsAssetEditorMeshViewMode MeshViewMode = SharedData->GetCurrentMeshViewMode(SharedData->bRunningSimulation);
|
|
if (MeshViewMode != EPhysicsAssetEditorMeshViewMode::None)
|
|
{
|
|
Proxy = UDebugSkelMeshComponent::CreateSceneProxy();
|
|
}
|
|
|
|
return Proxy;
|
|
}
|
|
|
|
bool ConstraintInSelected(int32 Index, const TArray<FPhysicsAssetEditorSharedData::FSelection> & Constraints)
|
|
{
|
|
for (int32 i = 0; i<Constraints.Num(); ++i)
|
|
{
|
|
|
|
if (Constraints[i].Index == Index)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void UPhysicsAssetEditorSkeletalMeshComponent::DrawConstraint(int32 ConstraintIndex, const FSceneView* View, FPrimitiveDrawInterface* PDI, bool bDrawAsPoint)
|
|
{
|
|
EPhysicsAssetEditorConstraintViewMode ConstraintViewMode = SharedData->GetCurrentConstraintViewMode(SharedData->bRunningSimulation);
|
|
bool bDrawLimits = false;
|
|
bool bConstraintSelected = ConstraintInSelected(ConstraintIndex, SharedData->SelectedConstraints);
|
|
if (ConstraintViewMode == EPhysicsAssetEditorConstraintViewMode::AllLimits || bConstraintSelected)
|
|
{
|
|
bDrawLimits = true;
|
|
}
|
|
|
|
bool bDrawSelected = false;
|
|
if (!SharedData->bRunningSimulation && bConstraintSelected)
|
|
{
|
|
bDrawSelected = true;
|
|
}
|
|
|
|
UPhysicsConstraintTemplate* ConstraintSetup = SharedData->PhysicsAsset->ConstraintSetup[ConstraintIndex];
|
|
|
|
FTransform Con1Frame = SharedData->GetConstraintMatrix(ConstraintIndex, EConstraintFrame::Frame1, 1.f);
|
|
FTransform Con2Frame = SharedData->GetConstraintMatrix(ConstraintIndex, EConstraintFrame::Frame2, 1.f);
|
|
|
|
const float DrawScale = ConstraintArrowScale * SharedData->EditorOptions->ConstraintDrawSize;
|
|
|
|
ConstraintSetup->DefaultInstance.DrawConstraint(PDI, SharedData->EditorOptions->ConstraintDrawSize, DrawScale, bDrawLimits, bDrawSelected, Con1Frame, Con2Frame, bDrawAsPoint);
|
|
}
|
|
|
|
FTransform UPhysicsAssetEditorSkeletalMeshComponent::GetPrimitiveTransform(FTransform& BoneTM, int32 BodyIndex, EAggCollisionShape::Type PrimType, int32 PrimIndex, float Scale)
|
|
{
|
|
UBodySetup* SharedBodySetup = SharedData->PhysicsAsset->SkeletalBodySetups[BodyIndex];
|
|
FVector Scale3D(Scale);
|
|
|
|
FTransform ManTM = FTransform::Identity;
|
|
|
|
if (SharedData->bManipulating && !SharedData->bRunningSimulation)
|
|
{
|
|
FPhysicsAssetEditorSharedData::FSelection Body(BodyIndex, PrimType, PrimIndex);
|
|
for (int32 i = 0; i<SharedData->SelectedBodies.Num(); ++i)
|
|
{
|
|
if (Body == SharedData->SelectedBodies[i])
|
|
{
|
|
ManTM = SharedData->SelectedBodies[i].ManipulateTM;
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (PrimType == EAggCollisionShape::Sphere)
|
|
{
|
|
FTransform PrimTM = ManTM * SharedBodySetup->AggGeom.SphereElems[PrimIndex].GetTransform();
|
|
PrimTM.ScaleTranslation(Scale3D);
|
|
return PrimTM * BoneTM;
|
|
}
|
|
else if (PrimType == EAggCollisionShape::Box)
|
|
{
|
|
FTransform PrimTM = ManTM * SharedBodySetup->AggGeom.BoxElems[PrimIndex].GetTransform();
|
|
PrimTM.ScaleTranslation(Scale3D);
|
|
return PrimTM * BoneTM;
|
|
}
|
|
else if (PrimType == EAggCollisionShape::Sphyl)
|
|
{
|
|
FTransform PrimTM = ManTM * SharedBodySetup->AggGeom.SphylElems[PrimIndex].GetTransform();
|
|
PrimTM.ScaleTranslation(Scale3D);
|
|
return PrimTM * BoneTM;
|
|
}
|
|
else if (PrimType == EAggCollisionShape::Convex)
|
|
{
|
|
FTransform PrimTM = ManTM * SharedBodySetup->AggGeom.ConvexElems[PrimIndex].GetTransform();
|
|
PrimTM.ScaleTranslation(Scale3D);
|
|
return PrimTM * BoneTM;
|
|
}
|
|
else if (PrimType == EAggCollisionShape::TaperedCapsule)
|
|
{
|
|
FTransform PrimTM = ManTM * SharedBodySetup->AggGeom.TaperedCapsuleElems[PrimIndex].GetTransform();
|
|
PrimTM.ScaleTranslation(Scale3D);
|
|
return PrimTM * BoneTM;
|
|
}
|
|
|
|
// Should never reach here
|
|
check(0);
|
|
return FTransform::Identity;
|
|
}
|
|
|
|
FColor UPhysicsAssetEditorSkeletalMeshComponent::GetPrimitiveColor(int32 BodyIndex, EAggCollisionShape::Type PrimitiveType, int32 PrimitiveIndex)
|
|
{
|
|
UBodySetup* SharedBodySetup = SharedData->PhysicsAsset->SkeletalBodySetups[BodyIndex];
|
|
|
|
if (!SharedData->bRunningSimulation && SharedData->GetSelectedConstraint())
|
|
{
|
|
UPhysicsConstraintTemplate* cs = SharedData->PhysicsAsset->ConstraintSetup[SharedData->GetSelectedConstraint()->Index];
|
|
|
|
if (cs->DefaultInstance.ConstraintBone1 == SharedBodySetup->BoneName)
|
|
{
|
|
return ConstraintBone1Color;
|
|
}
|
|
else if (cs->DefaultInstance.ConstraintBone2 == SharedBodySetup->BoneName)
|
|
{
|
|
return ConstraintBone2Color;
|
|
}
|
|
}
|
|
|
|
FPhysicsAssetEditorSharedData::FSelection Body(BodyIndex, PrimitiveType, PrimitiveIndex);
|
|
|
|
static FName SelectionColorName(TEXT("SelectionColor"));
|
|
const FSlateColor SelectionColor = FEditorStyle::GetSlateColor(SelectionColorName);
|
|
const FLinearColor SelectionColorLinear(SelectionColor.IsColorSpecified() ? SelectionColor.GetSpecifiedColor() : FLinearColor::White);
|
|
const FColor ElemSelectedColor = SelectionColorLinear.ToFColor(true);
|
|
const FColor ElemSelectedBodyColor = (SelectionColorLinear* 0.5f).ToFColor(true);
|
|
|
|
bool bInBody = false;
|
|
for (int32 i = 0; i<SharedData->SelectedBodies.Num(); ++i)
|
|
{
|
|
if (BodyIndex == SharedData->SelectedBodies[i].Index)
|
|
{
|
|
bInBody = true;
|
|
}
|
|
|
|
if (Body == SharedData->SelectedBodies[i] && !SharedData->bRunningSimulation)
|
|
{
|
|
return ElemSelectedColor;
|
|
}
|
|
}
|
|
|
|
if (bInBody && !SharedData->bRunningSimulation) //this primitive is in a body that's currently selected, but this primitive itself isn't selected
|
|
{
|
|
return ElemSelectedBodyColor;
|
|
}
|
|
if(PrimitiveType == EAggCollisionShape::TaperedCapsule)
|
|
{
|
|
return NoCollisionColor;
|
|
}
|
|
|
|
if (SharedData->bRunningSimulation)
|
|
{
|
|
const bool bIsSimulatedAtAll = SharedBodySetup->PhysicsType == PhysType_Simulated || (SharedBodySetup->PhysicsType == PhysType_Default && SharedData->EditorOptions->PhysicsBlend > 0.f);
|
|
if (!bIsSimulatedAtAll)
|
|
{
|
|
return FixedColor;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!SharedData->bRunningSimulation && SharedData->SelectedBodies.Num())
|
|
{
|
|
// If there is no collision with this body, use 'no collision material'.
|
|
if (SharedData->NoCollisionBodies.Find(BodyIndex) != INDEX_NONE)
|
|
{
|
|
return NoCollisionColor;
|
|
}
|
|
}
|
|
}
|
|
|
|
return BoneUnselectedColor;
|
|
}
|
|
|
|
UMaterialInterface* UPhysicsAssetEditorSkeletalMeshComponent::GetPrimitiveMaterial(int32 BodyIndex, EAggCollisionShape::Type PrimitiveType, int32 PrimitiveIndex)
|
|
{
|
|
if (SharedData->bRunningSimulation)
|
|
{
|
|
return PrimitiveType == EAggCollisionShape::TaperedCapsule ? BoneNoCollisionMaterial : BoneUnselectedMaterial;
|
|
}
|
|
|
|
FPhysicsAssetEditorSharedData::FSelection Body(BodyIndex, PrimitiveType, PrimitiveIndex);
|
|
|
|
for (int32 i = 0; i < SharedData->SelectedBodies.Num(); ++i)
|
|
{
|
|
if (Body == SharedData->SelectedBodies[i] && !SharedData->bRunningSimulation)
|
|
{
|
|
return ElemSelectedMaterial;
|
|
}
|
|
}
|
|
|
|
if (PrimitiveType == EAggCollisionShape::TaperedCapsule)
|
|
{
|
|
return BoneNoCollisionMaterial;
|
|
}
|
|
|
|
// If there is no collision with this body, use 'no collision material'.
|
|
if (SharedData->SelectedBodies.Num() && SharedData->NoCollisionBodies.Find(BodyIndex) != INDEX_NONE && !SharedData->bRunningSimulation)
|
|
{
|
|
return BoneNoCollisionMaterial;
|
|
}
|
|
else
|
|
{
|
|
return BoneUnselectedMaterial;
|
|
}
|
|
}
|
|
|
|
void UPhysicsAssetEditorSkeletalMeshComponent::RefreshBoneTransforms(FActorComponentTickFunction* TickFunction)
|
|
{
|
|
Super::RefreshBoneTransforms(TickFunction);
|
|
|
|
// Horrible kludge, but we need to flip the buffer back here as we need to wait on the physics tick group.
|
|
// However UDebugSkelMeshComponent passes NULL to force non-threaded work, which assumes a flip is needed straight away
|
|
if (ShouldBlendPhysicsBones())
|
|
{
|
|
bNeedToFlipSpaceBaseBuffers = true;
|
|
FinalizeBoneTransform();
|
|
bNeedToFlipSpaceBaseBuffers = true;
|
|
}
|
|
}
|
|
|
|
void UPhysicsAssetEditorSkeletalMeshComponent::AddImpulseAtLocation(FVector Impulse, FVector Location, FName BoneName)
|
|
{
|
|
#if !WITH_CHAOS
|
|
Super::AddImpulseAtLocation(Impulse, Location, BoneName);
|
|
#else
|
|
if (PreviewInstance != nullptr)
|
|
{
|
|
PreviewInstance->AddImpulseAtLocation(Impulse, Location, BoneName);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bool UPhysicsAssetEditorSkeletalMeshComponent::ShouldCreatePhysicsState() const
|
|
{
|
|
// @todo(chaos): the main physics scene is not running (and never runs) in the physics editor,
|
|
// and currently this means it will accumulate body create/destroy commands every time
|
|
// we hit "Simulate". Fix this! However, we still need physics state for mouse ray hit detection
|
|
// on the bodies so we can't just avoid creating physics state...
|
|
return Super::ShouldCreatePhysicsState();
|
|
}
|
|
|
|
|
|
void UPhysicsAssetEditorSkeletalMeshComponent::Grab(FName InBoneName, const FVector& Location, const FRotator& Rotation, bool bRotationConstrained)
|
|
{
|
|
UPhysicsAssetEditorAnimInstance* PhatPreviewInstance = Cast<UPhysicsAssetEditorAnimInstance>(PreviewInstance);
|
|
if (PhatPreviewInstance != nullptr)
|
|
{
|
|
PhatPreviewInstance->Grab(InBoneName, Location, Rotation, bRotationConstrained);
|
|
}
|
|
}
|
|
|
|
void UPhysicsAssetEditorSkeletalMeshComponent::Ungrab()
|
|
{
|
|
UPhysicsAssetEditorAnimInstance* PhatPreviewInstance = Cast<UPhysicsAssetEditorAnimInstance>(PreviewInstance);
|
|
if (PhatPreviewInstance != nullptr)
|
|
{
|
|
PhatPreviewInstance->Ungrab();
|
|
}
|
|
}
|
|
|
|
void UPhysicsAssetEditorSkeletalMeshComponent::UpdateHandleTransform(const FTransform& NewTransform)
|
|
{
|
|
UPhysicsAssetEditorAnimInstance* PhatPreviewInstance = Cast<UPhysicsAssetEditorAnimInstance>(PreviewInstance);
|
|
if (PhatPreviewInstance != nullptr)
|
|
{
|
|
PhatPreviewInstance->UpdateHandleTransform(NewTransform);
|
|
}
|
|
}
|
|
|
|
void UPhysicsAssetEditorSkeletalMeshComponent::UpdateDriveSettings(bool bLinearSoft, float LinearStiffness, float LinearDamping)
|
|
{
|
|
UPhysicsAssetEditorAnimInstance* PhatPreviewInstance = Cast<UPhysicsAssetEditorAnimInstance>(PreviewInstance);
|
|
if (PhatPreviewInstance != nullptr)
|
|
{
|
|
PhatPreviewInstance->UpdateDriveSettings(bLinearSoft, LinearStiffness, LinearDamping);
|
|
}
|
|
}
|
|
|
|
void UPhysicsAssetEditorSkeletalMeshComponent::CreateSimulationFloor(FBodyInstance* FloorBodyInstance, const FTransform& Transform)
|
|
{
|
|
UPhysicsAssetEditorAnimInstance* PhatPreviewInstance = Cast<UPhysicsAssetEditorAnimInstance>(PreviewInstance);
|
|
if (PhatPreviewInstance != nullptr)
|
|
{
|
|
PhatPreviewInstance->CreateSimulationFloor(FloorBodyInstance, Transform);
|
|
}
|
|
}
|