A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
HandSocketVisualizer.cpp
Go to the documentation of this file.
1// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
2
4#include "SceneManagement.h"
5//#include "UObject/Field.h"
6#include "VRBPDatatypes.h"
7#include "ScopedTransaction.h"
8#include "Modules/ModuleManager.h"
9#include "EditorViewportClient.h"
10#include "Misc/PackageName.h"
11//#include "Persona.h"
12
14#define LOCTEXT_NAMESPACE "HandSocketVisualizer"
15
16bool FHandSocketVisualizer::VisProxyHandleClick(FEditorViewportClient* InViewportClient, HComponentVisProxy* VisProxy, const FViewportClick& Click)
17{
18 bool bEditing = false;
19 if (VisProxy && VisProxy->Component.IsValid())
20 {
21 bEditing = true;
22 if (VisProxy->IsA(HHandSocketVisProxy::StaticGetType()))
23 {
24
25 if( const UHandSocketComponent * HandComp = UpdateSelectedHandComponent(VisProxy))
26 {
27 HHandSocketVisProxy* Proxy = (HHandSocketVisProxy*)VisProxy;
28 if (Proxy)
29 {
32 TargetViewport = InViewportClient->Viewport;
33 }
34 }
35 }
36 }
37
38 return bEditing;
39}
40
41
42bool FHandSocketVisualizer::GetCustomInputCoordinateSystem(const FEditorViewportClient* ViewportClient, FMatrix& OutMatrix) const
43{
44 if (TargetViewport == nullptr || TargetViewport != ViewportClient->Viewport)
45 {
46 return false;
47 }
48
49 if (HandPropertyPath.IsValid() && CurrentlySelectedBone != NAME_None/* && CurrentlySelectedBone != "HandSocket"*/)
50 {
51 if (CurrentlySelectedBone == "HandSocket")
52 {
53 UHandSocketComponent* CurrentlyEditingComponent = GetCurrentlyEditingComponent();
54 if (CurrentlyEditingComponent)
55 {
56 if (CurrentlyEditingComponent->bMirrorVisualizationMesh)
57 {
58 FTransform NewTrans = CurrentlyEditingComponent->GetRelativeTransform();
59 NewTrans.Mirror(CurrentlyEditingComponent->GetAsEAxis(CurrentlyEditingComponent->MirrorAxis), CurrentlyEditingComponent->GetAsEAxis(CurrentlyEditingComponent->FlipAxis));
60
61 if (USceneComponent* ParentComp = CurrentlyEditingComponent->GetAttachParent())
62 {
63 NewTrans = NewTrans * ParentComp->GetComponentTransform();
64 }
65
66 OutMatrix = FRotationMatrix::Make(NewTrans.GetRotation());
67 }
68 }
69
70 return false;
71 }
72 else if (CurrentlySelectedBone == "Visualizer")
73 {
74 if (UHandSocketComponent* CurrentlyEditingComponent = GetCurrentlyEditingComponent())
75 {
76
77 FTransform newTrans = FTransform::Identity;
78 if (CurrentlyEditingComponent->bDecoupleMeshPlacement)
79 {
80 if (USceneComponent* ParentComp = CurrentlyEditingComponent->GetAttachParent())
81 {
82 newTrans = CurrentlyEditingComponent->HandRelativePlacement * ParentComp->GetComponentTransform();
83 }
84 }
85 else
86 {
87 newTrans = CurrentlyEditingComponent->GetHandRelativePlacement() * CurrentlyEditingComponent->GetComponentTransform();
88 }
89
90 OutMatrix = FRotationMatrix::Make(newTrans.GetRotation());
91 }
92 }
93 else
94 {
95 if (UHandSocketComponent* CurrentlyEditingComponent = GetCurrentlyEditingComponent())
96 {
97 FTransform newTrans = CurrentlyEditingComponent->HandVisualizerComponent->GetBoneTransform(CurrentlySelectedBoneIdx);
98 OutMatrix = FRotationMatrix::Make(newTrans.GetRotation());
99 }
100 }
101
102 return true;
103 }
104
105 return false;
106}
107
109{
110 return (HandPropertyPath.IsValid() && HandPropertyPath.GetParentOwningActor() && FActorEditorUtils::IsAPreviewOrInactiveActor(HandPropertyPath.GetParentOwningActor()));
111}
112
113void FHandSocketVisualizer::DrawVisualizationHUD(const UActorComponent* Component, const FViewport* Viewport, const FSceneView* View, FCanvas* Canvas)
114{
115 if (TargetViewport == nullptr || TargetViewport != Viewport)
116 {
117 return;
118 }
119
120 if (const UHandSocketComponent* HandComp = Cast<const UHandSocketComponent>(Component))
121 {
122 if (CurrentlySelectedBone != NAME_None)
123 {
124 if (UHandSocketComponent* CurrentlyEditingComponent = GetCurrentlyEditingComponent())
125 {
126 if (!CurrentlyEditingComponent->HandVisualizerComponent)
127 {
128 return;
129 }
130
131 int32 XL;
132 int32 YL;
133 const FIntRect CanvasRect = Canvas->GetViewRect();
134
135 FPlane location = View->Project(CurrentlyEditingComponent->HandVisualizerComponent->GetBoneTransform(CurrentlySelectedBoneIdx).GetLocation());
136 StringSize(GEngine->GetLargeFont(), XL, YL, *CurrentlySelectedBone.ToString());
137 //const float DrawPositionX = location.X - XL;
138 //const float DrawPositionY = location.Y - YL;
139 const float DrawPositionX = FMath::FloorToFloat(CanvasRect.Min.X + (CanvasRect.Width() - XL) * 0.5f);
140 const float DrawPositionY = CanvasRect.Min.Y + 50.0f;
141 Canvas->DrawShadowedString(DrawPositionX, DrawPositionY, *CurrentlySelectedBone.ToString(), GEngine->GetLargeFont(), FLinearColor::Yellow);
142 }
143 }
144 }
145}
146
147void FHandSocketVisualizer::DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI)
148{
149 //UWorld* World = Component->GetWorld();
150 //return World && (World->WorldType == EWorldType::EditorPreview || World->WorldType == EWorldType::Inactive);
151
152 //cast the component into the expected component type
153 if (const UHandSocketComponent* HandComponent = Cast<UHandSocketComponent>(Component))
154 {
155 if (!HandComponent->HandVisualizerComponent)
156 return;
157
158 //This is an editor only uproperty of our targeting component, that way we can change the colors if we can't see them against the background
159 const FLinearColor SelectedColor = FLinearColor::Yellow;//TargetingComponent->EditorSelectedColor;
160 const FLinearColor UnselectedColor = FLinearColor::White;//TargetingComponent->EditorUnselectedColor;
161 const FVector Location = HandComponent->HandVisualizerComponent->GetComponentLocation();
162 float BoneScale = 1.0f - ((View->ViewLocation - Location).SizeSquared() / FMath::Square(100.0f));
163 BoneScale = FMath::Clamp(BoneScale, 0.2f, 1.0f);
164 HHandSocketVisProxy* newHitProxy = new HHandSocketVisProxy(Component);
165 newHitProxy->TargetBoneName = "Visualizer";
166 PDI->SetHitProxy(newHitProxy);
167 PDI->DrawPoint(Location, CurrentlySelectedBone == newHitProxy->TargetBoneName ? SelectedColor : FLinearColor::Red, 20.f * BoneScale, SDPG_Foreground);
168 PDI->SetHitProxy(NULL);
169 newHitProxy = nullptr;
170
171 newHitProxy = new HHandSocketVisProxy(Component);
172 newHitProxy->TargetBoneName = "HandSocket";
173 BoneScale = 1.0f - ((View->ViewLocation - HandComponent->GetComponentLocation()).SizeSquared() / FMath::Square(100.0f));
174 BoneScale = FMath::Clamp(BoneScale, 0.2f, 1.0f);
175 PDI->SetHitProxy(newHitProxy);
176 PDI->DrawPoint(HandComponent->GetComponentLocation(), FLinearColor::Green, 20.f * BoneScale, SDPG_Foreground);
177 PDI->SetHitProxy(NULL);
178 newHitProxy = nullptr;
179
180 if (HandComponent->bUseCustomPoseDeltas)
181 {
182 TArray<FTransform> BoneTransforms = HandComponent->HandVisualizerComponent->GetBoneSpaceTransforms();
183 FTransform ParentTrans = HandComponent->HandVisualizerComponent->GetComponentTransform();
184 // We skip root bone, moving the visualizer itself handles that
185 for (int i = 1; i < HandComponent->HandVisualizerComponent->GetNumBones(); i++)
186 {
187 FName BoneName = HandComponent->HandVisualizerComponent->GetBoneName(i);
188 FTransform BoneTransform = HandComponent->HandVisualizerComponent->GetBoneTransform(i);
189 FVector BoneLoc = BoneTransform.GetLocation();
190 BoneScale = 1.0f - ((View->ViewLocation - BoneLoc).SizeSquared() / FMath::Square(100.0f));
191 BoneScale = FMath::Clamp(BoneScale, 0.1f, 0.9f);
192 newHitProxy = new HHandSocketVisProxy(Component);
193 newHitProxy->TargetBoneName = BoneName;
194 newHitProxy->BoneIdx = i;
195 PDI->SetHitProxy(newHitProxy);
196 PDI->DrawPoint(BoneLoc, CurrentlySelectedBone == newHitProxy->TargetBoneName ? SelectedColor : UnselectedColor, 20.f * BoneScale, SDPG_Foreground);
197 PDI->SetHitProxy(NULL);
198 newHitProxy = nullptr;
199 }
200 }
201
202 if (HandComponent->bShowRangeVisualization)
203 {
204 float RangeVisualization = HandComponent->OverrideDistance;
205
206 if (RangeVisualization <= 0.0f)
207 {
208 if (USceneComponent* Parent = Cast<USceneComponent>(HandComponent->GetAttachParent()))
209 {
210 FStructProperty* ObjectProperty = CastField<FStructProperty>(Parent->GetClass()->FindPropertyByName("VRGripInterfaceSettings"));
211
212 AActor* ParentsActor = nullptr;
213 if (!ObjectProperty)
214 {
215 ParentsActor = Parent->GetOwner();
216 if (ParentsActor)
217 {
218 ObjectProperty = CastField<FStructProperty>(Parent->GetOwner()->GetClass()->FindPropertyByName("VRGripInterfaceSettings"));
219 }
220 }
221
222 if (ObjectProperty)
223 {
224 UObject* Target = ParentsActor;
225
226 if (Target == nullptr)
227 {
228 Target = Parent;
229 }
230
231 if (const FBPInterfaceProperties* Curve = ObjectProperty->ContainerPtrToValuePtr<FBPInterfaceProperties>(Target))
232 {
233 if (HandComponent->SlotPrefix == "VRGripS")
234 {
235 RangeVisualization = Curve->SecondarySlotRange;
236 }
237 else
238 {
239 RangeVisualization = Curve->PrimarySlotRange;
240 }
241 }
242 }
243 }
244 }
245
246 // Scale into our parents space as that is actually what the range is based on
247 FBox BoxToDraw = FBox::BuildAABB(FVector::ZeroVector, FVector(RangeVisualization) * HandComponent->GetAttachParent()->GetComponentScale());
248 BoxToDraw.Min += HandComponent->GetComponentLocation();
249 BoxToDraw.Max += HandComponent->GetComponentLocation();
250
251 DrawWireBox(PDI, BoxToDraw, FColor::Green, 0.0f);
252 }
253 }
254}
255
256bool FHandSocketVisualizer::GetWidgetLocation(const FEditorViewportClient* ViewportClient, FVector& OutLocation) const
257{
258 if (TargetViewport == nullptr || TargetViewport != ViewportClient->Viewport)
259 {
260 return false;
261 }
262
263 if (HandPropertyPath.IsValid() && CurrentlySelectedBone != NAME_None && CurrentlySelectedBone != "HandSocket")
264 {
265 if (CurrentlySelectedBone == "HandSocket")
266 {
267 return false;
268 }
269 else if (CurrentlySelectedBone == "Visualizer")
270 {
271 if (UHandSocketComponent* CurrentlyEditingComponent = GetCurrentlyEditingComponent())
272 {
273 FTransform newTrans = FTransform::Identity;
274 if (CurrentlyEditingComponent->bDecoupleMeshPlacement)
275 {
276 if (USceneComponent* ParentComp = CurrentlyEditingComponent->GetAttachParent())
277 {
278 newTrans = CurrentlyEditingComponent->HandRelativePlacement * ParentComp->GetComponentTransform();
279 }
280 }
281 else
282 {
283 newTrans = CurrentlyEditingComponent->GetHandRelativePlacement() * CurrentlyEditingComponent->GetComponentTransform();
284 }
285
286 OutLocation = newTrans.GetLocation();
287 }
288 }
289 else
290 {
291 if (UHandSocketComponent* CurrentlyEditingComponent = GetCurrentlyEditingComponent())
292 {
293 OutLocation = CurrentlyEditingComponent->HandVisualizerComponent->GetBoneTransform(CurrentlySelectedBoneIdx).GetLocation();
294 }
295 }
296
297 return true;
298 }
299
300 return false;
301}
302
303bool FHandSocketVisualizer::HandleInputDelta(FEditorViewportClient* ViewportClient, FViewport* Viewport, FVector& DeltaTranslate, FRotator& DeltaRotate, FVector& DeltaScale)
304{
305
306 if (TargetViewport == nullptr || TargetViewport != Viewport)
307 {
308 return false;
309 }
310
311 bool bHandled = false;
312
313 if (HandPropertyPath.IsValid())
314 {
315 if (CurrentlySelectedBone == "HandSocket" || CurrentlySelectedBone == NAME_None)
316 {
317 bHandled = false;
318 }
319 else if (CurrentlySelectedBone == "Visualizer")
320 {
321 const FScopedTransaction Transaction(LOCTEXT("ChangingComp", "ChangingComp"));
322
323 UHandSocketComponent* CurrentlyEditingComponent = GetCurrentlyEditingComponent();
324 if (!CurrentlyEditingComponent)
325 {
326 return false;
327 }
328
329 CurrentlyEditingComponent->Modify();
330 if (AActor* Owner = CurrentlyEditingComponent->GetOwner())
331 {
332 Owner->Modify();
333 }
334 bool bLevelEdit = ViewportClient->IsLevelEditorClient();
335
336 FTransform CurrentTrans = FTransform::Identity;
337
338 if (CurrentlyEditingComponent->bDecoupleMeshPlacement)
339 {
340 if (USceneComponent* ParentComp = CurrentlyEditingComponent->GetAttachParent())
341 {
342 CurrentTrans = CurrentlyEditingComponent->HandRelativePlacement * ParentComp->GetComponentTransform();
343 }
344 }
345 else
346 {
347 CurrentTrans = CurrentlyEditingComponent->GetHandRelativePlacement() * CurrentlyEditingComponent->GetComponentTransform();
348 }
349
350 if (!DeltaTranslate.IsNearlyZero())
351 {
352 CurrentTrans.AddToTranslation(DeltaTranslate);
353 }
354
355 if (!DeltaRotate.IsNearlyZero())
356 {
357 CurrentTrans.SetRotation(DeltaRotate.Quaternion() * CurrentTrans.GetRotation());
358 }
359
360 if (!DeltaScale.IsNearlyZero())
361 {
362 CurrentTrans.MultiplyScale3D(DeltaScale);
363 }
364
365 if (CurrentlyEditingComponent->bDecoupleMeshPlacement)
366 {
367 if (USceneComponent* ParentComp = CurrentlyEditingComponent->GetAttachParent())
368 {
369 CurrentlyEditingComponent->HandRelativePlacement = CurrentTrans.GetRelativeTransform(ParentComp->GetComponentTransform());
370 }
371 }
372 else
373 {
374 CurrentlyEditingComponent->HandRelativePlacement = CurrentTrans.GetRelativeTransform(CurrentlyEditingComponent->GetComponentTransform());
375 }
376
377 NotifyPropertyModified(CurrentlyEditingComponent, FindFProperty<FProperty>(UHandSocketComponent::StaticClass(), GET_MEMBER_NAME_CHECKED(UHandSocketComponent, HandRelativePlacement)));
378 //GEditor->RedrawLevelEditingViewports(true);
379 bHandled = true;
380
381 }
382 else
383 {
384 UHandSocketComponent* CurrentlyEditingComponent = GetCurrentlyEditingComponent();
385 if (!CurrentlyEditingComponent || !CurrentlyEditingComponent->HandVisualizerComponent)
386 {
387 return false;
388 }
389
390 const FScopedTransaction Transaction(LOCTEXT("ChangingComp", "ChangingComp"));
391
392 CurrentlyEditingComponent->Modify();
393 if (AActor* Owner = CurrentlyEditingComponent->GetOwner())
394 {
395 Owner->Modify();
396 }
397 bool bLevelEdit = ViewportClient->IsLevelEditorClient();
398
399 FTransform BoneTrans = CurrentlyEditingComponent->HandVisualizerComponent->GetBoneTransform(CurrentlySelectedBoneIdx);
400 FTransform NewTrans = BoneTrans;
401 NewTrans.SetRotation(DeltaRotate.Quaternion() * NewTrans.GetRotation());
402
403 FQuat DeltaRotateMod = NewTrans.GetRelativeTransform(BoneTrans).GetRotation();
404 bool bFoundBone = false;
405 for (FBPVRHandPoseBonePair& BonePair : CurrentlyEditingComponent->CustomPoseDeltas)
406 {
407 if (BonePair.BoneName == CurrentlySelectedBone)
408 {
409 bFoundBone = true;
410 BonePair.DeltaPose *= DeltaRotateMod;
411 break;
412 }
413 }
414
415 if (!bFoundBone)
416 {
417 FBPVRHandPoseBonePair newBonePair;
418 newBonePair.BoneName = CurrentlySelectedBone;
419 newBonePair.DeltaPose *= DeltaRotateMod;
420 CurrentlyEditingComponent->CustomPoseDeltas.Add(newBonePair);
421 bFoundBone = true;
422 }
423
424 if (bFoundBone)
425 {
426 NotifyPropertyModified(CurrentlyEditingComponent, FindFProperty<FProperty>(UHandSocketComponent::StaticClass(), GET_MEMBER_NAME_CHECKED(UHandSocketComponent, CustomPoseDeltas)));
427 }
428
429 //GEditor->RedrawLevelEditingViewports(true);
430 bHandled = true;
431 }
432 }
433
434 return bHandled;
435}
436
438{
439 HandPropertyPath = FComponentPropertyPath();
440 CurrentlySelectedBone = NAME_None;
441 CurrentlySelectedBoneIdx = INDEX_NONE;
442 TargetViewport = nullptr;
443}
444
445#undef LOCTEXT_NAMESPACE
IMPLEMENT_HIT_PROXY(HHandSocketVisProxy, HComponentVisProxy)
bool GetWidgetLocation(const FEditorViewportClient *ViewportClient, FVector &OutLocation) const override
bool HandleInputDelta(FEditorViewportClient *ViewportClient, FViewport *Viewport, FVector &DeltaTranslate, FRotator &DeltaRotate, FVector &DeltaScale) override
virtual void DrawVisualizationHUD(const UActorComponent *Component, const FViewport *Viewport, const FSceneView *View, FCanvas *Canvas) override
FComponentPropertyPath HandPropertyPath
UPROPERTY()
FViewport * TargetViewport
UPROPERTY()
virtual void DrawVisualization(const UActorComponent *Component, const FSceneView *View, FPrimitiveDrawInterface *PDI) override
bool GetCustomInputCoordinateSystem(const FEditorViewportClient *ViewportClient, FMatrix &OutMatrix) const override
virtual void EndEditing() override
const UHandSocketComponent * UpdateSelectedHandComponent(HComponentVisProxy *VisProxy)
UHandSocketComponent * GetCurrentlyEditingComponent() const
virtual bool VisProxyHandleClick(FEditorViewportClient *InViewportClient, HComponentVisProxy *VisProxy, const FViewportClick &Click) override
bool IsVisualizingArchetype() const override
UCLASS(Blueprintable, ClassGroup = (VRExpansionPlugin), hideCategories = ("Component Tick",...
TArray< FBPVRHandPoseBonePair > CustomPoseDeltas
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Animation")
TEnumAsByte< EVRAxis::Type > FlipAxis
UPROPERTY(VisibleDefaultsOnly, Category = "Hand Socket Data|Mirroring|Advanced")
TEnumAsByte< EAxis::Type > GetAsEAxis(TEnumAsByte< EVRAxis::Type > InAxis)
bool bDecoupleMeshPlacement
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Hand Socket Data")
TEnumAsByte< EVRAxis::Type > MirrorAxis
UPROPERTY(EditDefaultsOnly, Category = "Hand Socket Data|Mirroring|Advanced")
FTransform HandRelativePlacement
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data")
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
FName BoneName
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Settings")
FQuat DeltaPose
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Settings")