本文整理汇总了C++中FTransform::GetRelativeTransform方法的典型用法代码示例。如果您正苦于以下问题:C++ FTransform::GetRelativeTransform方法的具体用法?C++ FTransform::GetRelativeTransform怎么用?C++ FTransform::GetRelativeTransform使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类FTransform
的用法示例。
在下文中一共展示了FTransform::GetRelativeTransform方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: GetSocketTransform
FTransform USpringArmComponent::GetSocketTransform(FName InSocketName, ERelativeTransformSpace TransformSpace) const
{
FTransform RelativeTransform(RelativeSocketRotation, RelativeSocketLocation);
switch(TransformSpace)
{
case RTS_World:
{
return RelativeTransform * ComponentToWorld;
break;
}
case RTS_Actor:
{
if( const AActor* Actor = GetOwner() )
{
FTransform SocketTransform = RelativeTransform * ComponentToWorld;
return SocketTransform.GetRelativeTransform(Actor->GetTransform());
}
break;
}
case RTS_Component:
{
return RelativeTransform;
}
}
return RelativeTransform;
}
示例2: SetKeyImplementation
void UAnimPreviewInstance::SetKeyImplementation(const FCompactPose& PreControllerInLocalSpace, const FCompactPose& PostControllerInLocalSpace)
{
#if WITH_EDITOR
// evaluate the curve data first
UAnimSequence* CurrentSequence = Cast<UAnimSequence>(CurrentAsset);
UDebugSkelMeshComponent* Component = Cast<UDebugSkelMeshComponent> (GetSkelMeshComponent());
if(CurrentSequence && CurrentSkeleton && Component && Component->SkeletalMesh)
{
FScopedTransaction ScopedTransaction(LOCTEXT("SetKey", "Set Key"));
CurrentSequence->Modify(true);
Modify();
TArray<FName> BonesToModify;
// need to get component transform first. Depending on when this gets called, the transform is not up-to-date.
// first look at the bonecontrollers, and convert each bone controller to transform curve key
// and add new curvebonecontrollers with additive data type
// clear bone controller data
for(auto& SingleBoneController : BoneControllers)
{
// find bone name, and just get transform of the bone in local space
// and get the additive data
// find if this already exists, then just add curve data only
FName BoneName = SingleBoneController.BoneToModify.BoneName;
// now convert data
const FMeshPoseBoneIndex MeshBoneIndex(Component->GetBoneIndex(BoneName));
const FCompactPoseBoneIndex BoneIndex = RequiredBones.MakeCompactPoseIndex(MeshBoneIndex);
FTransform LocalTransform = PostControllerInLocalSpace[BoneIndex];
// now we have LocalTransform and get additive data
FTransform AdditiveTransform = LocalTransform.GetRelativeTransform(PreControllerInLocalSpace[BoneIndex]);
AddKeyToSequence(CurrentSequence, CurrentTime, BoneName, AdditiveTransform);
BonesToModify.Add(BoneName);
}
// see if the bone is selected right now and if that is added - if bone is selected, we should add identity key to it.
if ( Component->BonesOfInterest.Num() > 0 )
{
// if they're selected, we should add to the modifyBone list even if they're not modified, so that they can key that point.
// first make sure those are added
// if not added, make sure to set the key for them
for (const auto& BoneIndex : Component->BonesOfInterest)
{
FName BoneName = Component->GetBoneName(BoneIndex);
// if it's not on BonesToModify, add identity here.
if (!BonesToModify.Contains(BoneName))
{
AddKeyToSequence(CurrentSequence, CurrentTime, BoneName, FTransform::Identity);
}
}
}
ResetModifiedBone(false);
OnSetKeyCompleteDelegate.ExecuteIfBound();
}
#endif
}
示例3: AddInstanceWithMaterial
int32 UPaperGroupedSpriteComponent::AddInstanceWithMaterial(const FTransform& Transform, UPaperSprite* Sprite, UMaterialInterface* MaterialOverride, bool bWorldSpace, FLinearColor Color)
{
const int32 NewInstanceIndex = PerInstanceSpriteData.Num();
const FTransform LocalTransform(bWorldSpace ? Transform.GetRelativeTransform(ComponentToWorld) : Transform);
FSpriteInstanceData& NewInstanceData = *new (PerInstanceSpriteData)FSpriteInstanceData();
SetupNewInstanceData(NewInstanceData, NewInstanceIndex, LocalTransform, Sprite, MaterialOverride, Color.ToFColor(/*bSRGB=*/ false));
MarkRenderStateDirty();
UNavigationSystem::UpdateNavOctree(this);
return NewInstanceIndex;
}
示例4: UpdateInstanceTransform
bool UPaperGroupedSpriteComponent::UpdateInstanceTransform(int32 InstanceIndex, const FTransform& NewInstanceTransform, bool bWorldSpace, bool bMarkRenderStateDirty)
{
if (!PerInstanceSpriteData.IsValidIndex(InstanceIndex))
{
return false;
}
// Request navigation update
UNavigationSystem::UpdateNavOctree(this);
FSpriteInstanceData& InstanceData = PerInstanceSpriteData[InstanceIndex];
// Render data uses local transform of the instance
FTransform LocalTransform = bWorldSpace ? NewInstanceTransform.GetRelativeTransform(ComponentToWorld) : NewInstanceTransform;
InstanceData.Transform = LocalTransform.ToMatrixWithScale();
if (bPhysicsStateCreated)
{
// Physics uses world transform of the instance
const FTransform WorldTransform = bWorldSpace ? NewInstanceTransform : (LocalTransform * ComponentToWorld);
if (FBodyInstance* InstanceBodyInstance = InstanceBodies[InstanceIndex])
{
// Update transform.
InstanceBodyInstance->SetBodyTransform(WorldTransform, ETeleportType::None);
InstanceBodyInstance->UpdateBodyScale(WorldTransform.GetScale3D());
}
}
// Request navigation update
UNavigationSystem::UpdateNavOctree(this);
if (bMarkRenderStateDirty)
{
MarkRenderStateDirty();
}
return true;
}
示例5: AddedTransform
//.........这里部分代码省略.........
// save global trasnform
FbxAMatrix GlobalMatrix = Link->EvaluateGlobalTransform(CurTime);
// we'd like to verify this before going to Transform.
// currently transform has tons of NaN check, so it will crash there
FMatrix GlobalUEMatrix = Converter.ConvertMatrix(GlobalMatrix);
if (GlobalUEMatrix.ContainsNaN())
{
bSuccess = false;
AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error, FText::Format(LOCTEXT("Error_InvalidTransform",
"Track {0} contains invalid transform. Could not import the track."), FText::FromName(BoneName))), FFbxErrors::Animation_TransformError);
break;
}
FTransform GlobalTransform = Converter.ConvertTransform(GlobalMatrix);
if (GlobalTransform.ContainsNaN())
{
bSuccess = false;
AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error, FText::Format(LOCTEXT("Error_InvalidUnrealTransform",
"Track {0} did not yeild valid transform. Please report this to animation team."), FText::FromName(BoneName))), FFbxErrors::Animation_TransformError);
break;
}
// debug data, including import transformation
FTransform AddedTransform(AddedMatrix);
NewDebugData.SourceGlobalTransform.Add(GlobalTransform * AddedTransform);
FTransform LocalTransform;
if( !bPreserveLocalTransform && LinkParent)
{
// I can't rely on LocalMatrix. I need to recalculate quaternion/scale based on global transform if Parent exists
FbxAMatrix ParentGlobalMatrix = Link->GetParent()->EvaluateGlobalTransform(CurTime);
FTransform ParentGlobalTransform = Converter.ConvertTransform(ParentGlobalMatrix);
LocalTransform = GlobalTransform.GetRelativeTransform(ParentGlobalTransform);
NewDebugData.SourceParentGlobalTransform.Add(ParentGlobalTransform);
}
else
{
FbxAMatrix& LocalMatrix = Link->EvaluateLocalTransform(CurTime);
FbxVector4 NewLocalT = LocalMatrix.GetT();
FbxVector4 NewLocalS = LocalMatrix.GetS();
FbxQuaternion NewLocalQ = LocalMatrix.GetQ();
LocalTransform.SetTranslation(Converter.ConvertPos(NewLocalT));
LocalTransform.SetScale3D(Converter.ConvertScale(NewLocalS));
LocalTransform.SetRotation(Converter.ConvertRotToQuat(NewLocalQ));
NewDebugData.SourceParentGlobalTransform.Add(FTransform::Identity);
}
if(TemplateData && BoneTreeIndex == 0)
{
// If we found template data earlier, apply the import transform matrix to
// the root track.
LocalTransform.SetFromMatrix(LocalTransform.ToMatrixWithScale() * AddedMatrix);
}
if (LocalTransform.ContainsNaN())
{
bSuccess = false;
AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error, FText::Format(LOCTEXT("Error_InvalidUnrealLocalTransform",
"Track {0} did not yeild valid local transform. Please report this to animation team."), FText::FromName(BoneName))), FFbxErrors::Animation_TransformError);
break;
}
RawTrack.ScaleKeys.Add(LocalTransform.GetScale3D());
示例6: GripComponent
bool UGripMotionControllerComponent::GripComponent(
UPrimitiveComponent* ComponentToGrip,
const FTransform &WorldOffset,
bool bWorldOffsetIsRelative,
FName OptionalSnapToSocketName,
TEnumAsByte<EGripCollisionType> GripCollisionType,
bool bAllowSetMobility,
float GripStiffness,
float GripDamping,
bool bTurnOffLateUpdateWhenColliding
)
{
if (!bIsServer || !ComponentToGrip)
{
UE_LOG(LogTemp, Warning, TEXT("VRGripMotionController grab function was passed an invalid or already gripped component"));
return false;
}
// Has to be movable to work
if (ComponentToGrip->Mobility != EComponentMobility::Movable)
{
if (bAllowSetMobility)
ComponentToGrip->SetMobility(EComponentMobility::Movable);
else
{
UE_LOG(LogTemp, Warning, TEXT("VRGripMotionController tried to grip a component set to static mobility and bAllowSetMobility is false"));
return false; // It is not movable, can't grip it
}
}
ComponentToGrip->IgnoreActorWhenMoving(this->GetOwner(), true);
// So that events caused by sweep and the like will trigger correctly
ComponentToGrip->AddTickPrerequisiteComponent(this);
FBPActorGripInformation newActorGrip;
newActorGrip.GripCollisionType = GripCollisionType;
newActorGrip.Component = ComponentToGrip;
if(ComponentToGrip->GetOwner())
newActorGrip.bOriginalReplicatesMovement = ComponentToGrip->GetOwner()->bReplicateMovement;
newActorGrip.Stiffness = GripStiffness;
newActorGrip.Damping = GripDamping;
newActorGrip.bTurnOffLateUpdateWhenColliding = bTurnOffLateUpdateWhenColliding;
if (OptionalSnapToSocketName.IsValid() && ComponentToGrip->DoesSocketExist(OptionalSnapToSocketName))
{
// I inverse it so that laying out the sockets makes sense
FTransform sockTrans = ComponentToGrip->GetSocketTransform(OptionalSnapToSocketName, ERelativeTransformSpace::RTS_Component);
newActorGrip.RelativeTransform = sockTrans.Inverse();
newActorGrip.RelativeTransform.SetScale3D(ComponentToGrip->GetComponentScale());
}
else if (bWorldOffsetIsRelative)
newActorGrip.RelativeTransform = WorldOffset;
else
newActorGrip.RelativeTransform = WorldOffset.GetRelativeTransform(this->GetComponentTransform());
NotifyGrip(newActorGrip);
GrippedActors.Add(newActorGrip);
return true;
}
示例7: PerformBlendPhysicsBones
//.........这里部分代码省略.........
BodyInstance = Bodies[BodyIndex];
//if simulated body copy back and blend with animation
if(BodyInstance->IsInstanceSimulatingPhysics())
{
FTransform PhysTM = BodyInstance->GetUnrealWorldTransform_AssumesLocked();
// Store this world-space transform in cache.
WorldBoneTMs[BoneIndex].TM = PhysTM;
WorldBoneTMs[BoneIndex].bUpToDate = true;
float UsePhysWeight = (bBlendPhysics)? 1.f : BodyInstance->PhysicsBlendWeight;
// Find this bones parent matrix.
FTransform ParentWorldTM;
// if we wan't 'full weight' we just find
if(UsePhysWeight > 0.f)
{
if(BoneIndex == 0)
{
ParentWorldTM = LocalToWorldTM;
}
else
{
// If not root, get parent TM from cache (making sure its up-to-date).
int32 ParentIndex = SkeletalMesh->RefSkeleton.GetParentIndex(BoneIndex);
UpdateWorldBoneTM(WorldBoneTMs, ParentIndex, this, LocalToWorldTM, TotalScale3D);
ParentWorldTM = WorldBoneTMs[ParentIndex].TM;
}
// Then calc rel TM and convert to atom.
FTransform RelTM = PhysTM.GetRelativeTransform(ParentWorldTM);
RelTM.RemoveScaling();
FQuat RelRot(RelTM.GetRotation());
FVector RelPos = RecipScale3D * RelTM.GetLocation();
FTransform PhysAtom = FTransform(RelRot, RelPos, InLocalAtoms[BoneIndex].GetScale3D());
// Now blend in this atom. See if we are forcing this bone to always be blended in
InLocalAtoms[BoneIndex].Blend( InLocalAtoms[BoneIndex], PhysAtom, UsePhysWeight );
if(BoneIndex == 0)
{
//We must update RecipScale3D based on the atom scale of the root
TotalScale3D *= InLocalAtoms[0].GetScale3D();
RecipScale3D = TotalScale3D.Reciprocal();
}
if (UsePhysWeight < 1.f)
{
bUpdatePhysics = true;
}
}
}
}
// Update SpaceBases entry for this bone now
if( BoneIndex == 0 )
{
EditableSpaceBases[0] = InLocalAtoms[0];
}
else
{
const int32 ParentIndex = SkeletalMesh->RefSkeleton.GetParentIndex(BoneIndex);
EditableSpaceBases[BoneIndex] = InLocalAtoms[BoneIndex] * EditableSpaceBases[ParentIndex];
示例8: RasterizeSegmentPoints
void RasterizeSegmentPoints(ULandscapeInfo* LandscapeInfo, TArray<FLandscapeSplineInterpPoint> Points, const FTransform& SplineToWorld, bool bRaiseTerrain, bool bLowerTerrain, ULandscapeLayerInfoObject* LayerInfo)
{
ALandscapeProxy* LandscapeProxy = LandscapeInfo->GetLandscapeProxy();
const FTransform SplineToLandscape = SplineToWorld.GetRelativeTransform(LandscapeProxy->LandscapeActorToWorld());
FLandscapeEditDataInterface LandscapeEdit(LandscapeInfo);
TSet<ULandscapeComponent*> ModifiedComponents;
// I'd dearly love to use FIntRect in this code, but Landscape works with "Inclusive Max" and FIntRect is "Exclusive Max"
int32 LandscapeMinX, LandscapeMinY, LandscapeMaxX, LandscapeMaxY;
if (!LandscapeInfo->GetLandscapeExtent(LandscapeMinX, LandscapeMinY, LandscapeMaxX, LandscapeMaxY))
{
return;
}
FBox SegmentBounds = FBox(0);
for (const FLandscapeSplineInterpPoint& Point : Points)
{
SegmentBounds += Point.FalloffLeft;
SegmentBounds += Point.FalloffRight;
}
SegmentBounds = SegmentBounds.TransformBy(SplineToLandscape.ToMatrixWithScale());
int32 MinX = FMath::CeilToInt(SegmentBounds.Min.X);
int32 MinY = FMath::CeilToInt(SegmentBounds.Min.Y);
int32 MaxX = FMath::FloorToInt(SegmentBounds.Max.X);
int32 MaxY = FMath::FloorToInt(SegmentBounds.Max.Y);
MinX = FMath::Max(MinX, LandscapeMinX);
MinY = FMath::Max(MinY, LandscapeMinY);
MaxX = FMath::Min(MaxX, LandscapeMaxX);
MaxY = FMath::Min(MaxY, LandscapeMaxY);
if (MinX > MaxX || MinY > MaxY)
{
// The segment's bounds don't intersect the landscape, so skip it entirely
return;
}
for (int32 j = 0; j < Points.Num(); j++)
{
Points[j].Center = SplineToLandscape.TransformPosition(Points[j].Center);
Points[j].Left = SplineToLandscape.TransformPosition(Points[j].Left);
Points[j].Right = SplineToLandscape.TransformPosition(Points[j].Right);
Points[j].FalloffLeft = SplineToLandscape.TransformPosition(Points[j].FalloffLeft);
Points[j].FalloffRight = SplineToLandscape.TransformPosition(Points[j].FalloffRight);
// local-heights to texture value heights
Points[j].Left.Z = Points[j].Left.Z * LANDSCAPE_INV_ZSCALE + LandscapeDataAccess::MidValue;
Points[j].Right.Z = Points[j].Right.Z * LANDSCAPE_INV_ZSCALE + LandscapeDataAccess::MidValue;
Points[j].FalloffLeft.Z = Points[j].FalloffLeft.Z * LANDSCAPE_INV_ZSCALE + LandscapeDataAccess::MidValue;
Points[j].FalloffRight.Z = Points[j].FalloffRight.Z * LANDSCAPE_INV_ZSCALE + LandscapeDataAccess::MidValue;
}
// Heights raster
if (bRaiseTerrain || bLowerTerrain)
{
RasterizeSegmentHeight(MinX, MinY, MaxX, MaxY, LandscapeEdit, Points, bRaiseTerrain, bLowerTerrain, ModifiedComponents);
if (MinX > MaxX || MinY > MaxY)
{
// The segment's bounds don't intersect any data, so we skip it entirely
// it wouldn't intersect any weightmap data either so we don't even bother trying
}
}
// Blend layer raster
if (LayerInfo != NULL)
{
RasterizeSegmentAlpha(MinX, MinY, MaxX, MaxY, LandscapeEdit, Points, LayerInfo, ModifiedComponents);
}
LandscapeEdit.Flush();
for (ULandscapeComponent* Component : ModifiedComponents)
{
// Recreate collision for modified components and update the navmesh
ULandscapeHeightfieldCollisionComponent* CollisionComponent = Component->CollisionComponent.Get();
if (CollisionComponent)
{
CollisionComponent->RecreateCollision();
UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(Component);
if (NavSys)
{
NavSys->UpdateNavOctree(CollisionComponent);
}
}
}
}
示例9: ProcessAnimationTracks
//.........这里部分代码省略.........
}
}
}
// if requested, retarget the FBoneAtoms towards the target end effectors
if (bRetarget)
{
if (NumScaleKeys > 0 && ParentBoneIndex != INDEX_NONE)
{
// update our bone table from the current bone through the last end effector we need to test
UpdateWorldBoneTransformRange(
AnimSeq,
BoneData,
RefPose,
PositionTracks,
RotationTracks,
ScaleTracks,
BoneIndex,
HighestTargetBoneIndex,
false,
NewWorldBones);
FScaleTrack& ScaleTrack = ScaleTracks[TrackIndex];
// adjust all translation keys to align better with the destination
for ( int32 KeyIndex = 0; KeyIndex < NumScaleKeys; ++KeyIndex )
{
FVector& Key= ScaleTrack.ScaleKeys[KeyIndex];
const int32 FrameIndex= FMath::Clamp(KeyIndex, 0, LastFrame);
const FTransform& NewWorldParent = NewWorldBones[(ParentBoneIndex*NumFrames) + FrameIndex];
const FTransform& RawWorldChild = RawWorldBones[(BoneIndex*NumFrames) + FrameIndex];
const FTransform& RelTM = (RawWorldChild.GetRelativeTransform(NewWorldParent));
const FTransform Delta = FTransform(RelTM);
Key = Delta.GetScale3D();
}
}
if (NumRotKeys > 0 && ParentBoneIndex != INDEX_NONE)
{
if (HighestTargetBoneIndex == BoneIndex)
{
for ( int32 KeyIndex = 0; KeyIndex < NumRotKeys; ++KeyIndex )
{
FQuat& Key = RotTrack.RotKeys[KeyIndex];
check(ParentBoneIndex != INDEX_NONE);
const int32 FrameIndex = FMath::Clamp(KeyIndex, 0, LastFrame);
FTransform NewWorldParent = NewWorldBones[(ParentBoneIndex*NumFrames) + FrameIndex];
FTransform RawWorldChild = RawWorldBones[(BoneIndex*NumFrames) + FrameIndex];
const FTransform& RelTM = (RawWorldChild.GetRelativeTransform(NewWorldParent));
FQuat Rot = FTransform(RelTM).GetRotation();
const FQuat& AlignedKey = EnforceShortestArc(Key, Rot);
Key = AlignedKey;
}
}
else
{
// update our bone table from the current bone through the last end effector we need to test
UpdateWorldBoneTransformRange(
AnimSeq,
BoneData,
RefPose,
示例10: FilterLinearKeysTemplate
//.........这里部分代码省略.........
// get the parameters of the member being tested
float TestTime = Times[TestKey];
T TestValue = Keys[TestKey];
// compute the proposed, interpolated value for the key
const float Alpha = (TestTime - LowTime) * InvRange;
const T LerpValue = Interpolate(LowValue, HighValue, Alpha);
// compute the error between our interpolated value and the desired value
float LerpError = CalcDelta(TestValue, LerpValue);
// if the local-space lerp error is within our tolerances, we will also check the
// effect this interpolated key will have on our target end effectors
float TargetError = -1.0f;
if (LerpError <= MaxDelta)
{
// get the raw world transform for this bone (the original world-space position)
const int32 FrameIndex = TestKey;
const FTransform& RawBase = RawWorldBones[(BoneIndex*NumFrames) + FrameIndex];
// generate the proposed local bone atom and transform (local space)
FTransform ProposedTM = UpdateBoneAtom(BoneIndex, BoneAtoms[FrameIndex], LerpValue);
// convert the proposed local transform to world space using this bone's parent transform
const FTransform& CurrentParent = ParentBoneIndex != INDEX_NONE ? NewWorldBones[(ParentBoneIndex*NumFrames) + FrameIndex] : FTransform::Identity;
FTransform ProposedBase = ProposedTM * CurrentParent;
// for each target end effector, compute the error we would introduce with our proposed key
for (int32 TargetIndex=0; TargetIndex<TargetBoneIndices.Num(); ++TargetIndex)
{
// find the offset transform from the raw base to the end effector
const int32 TargetBoneIndex = TargetBoneIndices[TargetIndex];
FTransform RawTarget = RawWorldBones[(TargetBoneIndex*NumFrames) + FrameIndex];
const FTransform& RelTM = RawTarget.GetRelativeTransform(RawBase);
// forecast where the new end effector would be using our proposed key
FTransform ProposedTarget = RelTM * ProposedBase;
// If this is an EndEffector with a Socket attached to it, add an extra bone, to measure error introduced by effector rotation compression.
if( BoneData[TargetIndex].bHasSocket || BoneData[TargetIndex].bKeyEndEffector )
{
ProposedTarget = DummyBone * ProposedTarget;
RawTarget = DummyBone * RawTarget;
}
// determine the extend of error at the target end effector
float ThisError = (ProposedTarget.GetTranslation() - RawTarget.GetTranslation()).Size();
TargetError = FMath::Max(TargetError, ThisError);
// exit early when we encounter a large delta
float const TargetDeltaThreshold = BoneData[TargetIndex].bHasSocket ? EffectorDiffSocket : DeltaThreshold;
if( TargetError > TargetDeltaThreshold )
{
break;
}
}
}
// If the parent has a key at this time, we'll scale our error values as requested.
// This increases the odds that we will choose keys on the same frames as our parent bone,
// making the skeleton more uniform in key distribution.
if (ParentTimes)
{
if (ParentTimes->Find(TestTime) != INDEX_NONE)
{
// our parent has a key at this time,
示例11: InputDelta
bool FEdMode::InputDelta(FEditorViewportClient* InViewportClient, FViewport* InViewport, FVector& InDrag, FRotator& InRot, FVector& InScale)
{
if(UsesPropertyWidgets())
{
AActor* SelectedActor = GetFirstSelectedActorInstance();
if(SelectedActor != NULL && InViewportClient->GetCurrentWidgetAxis() != EAxisList::None)
{
GEditor->NoteActorMovement();
if (EditedPropertyName != TEXT(""))
{
FTransform LocalTM = FTransform::Identity;
if(bEditedPropertyIsTransform)
{
LocalTM = GetPropertyValueByName<FTransform>(SelectedActor, EditedPropertyName, EditedPropertyIndex);
}
else
{
FVector LocalPos = GetPropertyValueByName<FVector>(SelectedActor, EditedPropertyName, EditedPropertyIndex);
LocalTM = FTransform(LocalPos);
}
// Get actor transform (actor to world)
FTransform ActorTM = SelectedActor->ActorToWorld();
// Calculate world transform
FTransform WorldTM = LocalTM * ActorTM;
// Calc delta specified by drag
//FTransform DeltaTM(InRot.Quaternion(), InDrag);
// Apply delta in world space
WorldTM.SetTranslation(WorldTM.GetTranslation() + InDrag);
WorldTM.SetRotation(InRot.Quaternion() * WorldTM.GetRotation());
// Convert new world transform back into local space
LocalTM = WorldTM.GetRelativeTransform(ActorTM);
// Apply delta scale
LocalTM.SetScale3D(LocalTM.GetScale3D() + InScale);
SelectedActor->PreEditChange(NULL);
if(bEditedPropertyIsTransform)
{
SetPropertyValueByName<FTransform>(SelectedActor, EditedPropertyName, EditedPropertyIndex, LocalTM);
}
else
{
SetPropertyValueByName<FVector>(SelectedActor, EditedPropertyName, EditedPropertyIndex, LocalTM.GetLocation());
}
SelectedActor->PostEditChange();
return true;
}
}
}
if( GetCurrentTool() )
{
return GetCurrentTool()->InputDelta(InViewportClient,InViewport,InDrag,InRot,InScale);
}
return 0;
}