A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
GrippableActor.cpp
Go to the documentation of this file.
1// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2
4#include "TimerManager.h"
5#include "Net/UnrealNetwork.h"
6#include "PhysicsReplication.h"
7#if WITH_PUSH_MODEL
8#include "Net/Core/PushModel/PushModel.h"
9#endif
10
11
12 //=============================================================================
13AGrippableActor::AGrippableActor(const FObjectInitializer& ObjectInitializer)
14 : Super()
15{
29
31
32 // Default replication on for multiplayer
33 //this->bNetLoadOnClient = false;
34 SetReplicatingMovement(true);
35 bReplicates = true;
36
40
41 // Setting a minimum of every 3rd frame (VR 90fps) for replication consideration
42 // Otherwise we will get some massive slow downs if the replication is allowed to hit the 2 per second minimum default
43 MinNetUpdateFrequency = 30.0f;
44}
45
46void AGrippableActor::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const
47{
48 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
49
50 DOREPLIFETIME_CONDITION(AGrippableActor, GripLogicScripts, COND_Custom);
55 DOREPLIFETIME_CONDITION(AGrippableActor, VRGripInterfaceSettings, COND_Custom);
56 DOREPLIFETIME_CONDITION(AGrippableActor, GameplayTags, COND_Custom);
57
58 DISABLE_REPLICATED_PRIVATE_PROPERTY(AActor, AttachmentReplication);
59
60 FDoRepLifetimeParams AttachmentReplicationParams{ COND_Custom, REPNOTIFY_Always, /*bIsPushBased=*/true };
61 DOREPLIFETIME_WITH_PARAMS_FAST(AGrippableActor, AttachmentWeldReplication, AttachmentReplicationParams);
62}
63
64void AGrippableActor::PreReplication(IRepChangedPropertyTracker & ChangedPropertyTracker)
65{
66
67 // Don't replicate if set to not do it
69 DOREPLIFETIME_ACTIVE_OVERRIDE(AGrippableActor, GameplayTags, bRepGripSettingsAndGameplayTags);
70 DOREPLIFETIME_ACTIVE_OVERRIDE(AGrippableActor, GripLogicScripts, bReplicateGripScripts);
71
72 //Super::PreReplication(ChangedPropertyTracker);
73
74#if WITH_PUSH_MODEL
75 const AActor* const OldAttachParent = AttachmentWeldReplication.AttachParent;
76 const UActorComponent* const OldAttachComponent = AttachmentWeldReplication.AttachComponent;
77#endif
78
79 // Attachment replication gets filled in by GatherCurrentMovement(), but in the case of a detached root we need to trigger remote detachment.
80 AttachmentWeldReplication.AttachParent = nullptr;
81 AttachmentWeldReplication.AttachComponent = nullptr;
82
84
85 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(AActor, ReplicatedMovement, IsReplicatingMovement());
86
87 // Don't need to replicate AttachmentReplication if the root component replicates, because it already handles it.
88 DOREPLIFETIME_ACTIVE_OVERRIDE(AGrippableActor, AttachmentWeldReplication, RootComponent && !RootComponent->GetIsReplicated());
89
90 // Don't need to replicate AttachmentReplication if the root component replicates, because it already handles it.
91 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(AActor, AttachmentReplication, RootComponent && !RootComponent->GetIsReplicated());
92
93
94#if WITH_PUSH_MODEL
95 if (UNLIKELY(OldAttachParent != AttachmentWeldReplication.AttachParent || OldAttachComponent != AttachmentWeldReplication.AttachComponent))
96 {
97 //MARK_PROPERTY_DIRTY_FROM_NAME(AGrippableActor, AttachmentWeldReplication, this);
98 }
99#endif
100
101 UBlueprintGeneratedClass* BPClass = Cast<UBlueprintGeneratedClass>(GetClass());
102 if (BPClass != nullptr)
103 {
104 BPClass->InstancePreReplication(this, ChangedPropertyTracker);
105 }
106}
107
109{
110 if (IsReplicatingMovement() || (RootComponent && RootComponent->GetAttachParent()))
111 {
112 bool bWasAttachmentModified = false;
113 bool bWasRepMovementModified = false;
114
115 AActor* OldAttachParent = AttachmentWeldReplication.AttachParent;
116 USceneComponent* OldAttachComponent = AttachmentWeldReplication.AttachComponent;
117
118 AttachmentWeldReplication.AttachParent = nullptr;
119 AttachmentWeldReplication.AttachComponent = nullptr;
120
121 FRepMovement& RepMovement = GetReplicatedMovement_Mutable();
122
123 UPrimitiveComponent* RootPrimComp = Cast<UPrimitiveComponent>(GetRootComponent());
124 if (RootPrimComp && RootPrimComp->IsSimulatingPhysics())
125 {
126 FRigidBodyState RBState;
127 RootPrimComp->GetRigidBodyState(RBState);
128
129 RepMovement.FillFrom(RBState, this);
130 // Don't replicate movement if we're welded to another parent actor.
131 // Their replication will affect our position indirectly since we are attached.
132 RepMovement.bRepPhysics = !RootPrimComp->IsWelded();
133
134 if (!RepMovement.bRepPhysics)
135 {
136 if (RootComponent->GetAttachParent() != nullptr)
137 {
138 // Networking for attachments assumes the RootComponent of the AttachParent actor.
139 // If that's not the case, we can't update this, as the client wouldn't be able to resolve the Component and would detach as a result.
140 AttachmentWeldReplication.AttachParent = RootComponent->GetAttachParent()->GetAttachmentRootActor();
141 if (AttachmentWeldReplication.AttachParent != nullptr)
142 {
143 AttachmentWeldReplication.LocationOffset = RootComponent->GetRelativeLocation();
144 AttachmentWeldReplication.RotationOffset = RootComponent->GetRelativeRotation();
145 AttachmentWeldReplication.RelativeScale3D = RootComponent->GetRelativeScale3D();
146 AttachmentWeldReplication.AttachComponent = RootComponent->GetAttachParent();
147 AttachmentWeldReplication.AttachSocket = RootComponent->GetAttachSocketName();
148 AttachmentWeldReplication.bIsWelded = RootPrimComp ? RootPrimComp->IsWelded() : false;
149
150 // Technically, the values might have stayed the same, but we'll just assume they've changed.
151 bWasAttachmentModified = true;
152 }
153 }
154 }
155
156 // Technically, the values might have stayed the same, but we'll just assume they've changed.
157 bWasRepMovementModified = true;
158 }
159 else if (RootComponent != nullptr)
160 {
161 // If we are attached, don't replicate absolute position, use AttachmentReplication instead.
162 if (RootComponent->GetAttachParent() != nullptr)
163 {
164 // Networking for attachments assumes the RootComponent of the AttachParent actor.
165 // If that's not the case, we can't update this, as the client wouldn't be able to resolve the Component and would detach as a result.
166 AttachmentWeldReplication.AttachParent = RootComponent->GetAttachParent()->GetAttachmentRootActor();
167 if (AttachmentWeldReplication.AttachParent != nullptr)
168 {
169 AttachmentWeldReplication.LocationOffset = RootComponent->GetRelativeLocation();
170 AttachmentWeldReplication.RotationOffset = RootComponent->GetRelativeRotation();
171 AttachmentWeldReplication.RelativeScale3D = RootComponent->GetRelativeScale3D();
172 AttachmentWeldReplication.AttachComponent = RootComponent->GetAttachParent();
173 AttachmentWeldReplication.AttachSocket = RootComponent->GetAttachSocketName();
174 AttachmentWeldReplication.bIsWelded = RootPrimComp ? RootPrimComp->IsWelded() : false;
175
176 // Technically, the values might have stayed the same, but we'll just assume they've changed.
177 bWasAttachmentModified = true;
178 }
179 }
180 else
181 {
182 RepMovement.Location = FRepMovement::RebaseOntoZeroOrigin(RootComponent->GetComponentLocation(), this);
183 RepMovement.Rotation = RootComponent->GetComponentRotation();
184 RepMovement.LinearVelocity = GetVelocity();
185 RepMovement.AngularVelocity = FVector::ZeroVector;
186
187 // Technically, the values might have stayed the same, but we'll just assume they've changed.
188 bWasRepMovementModified = true;
189 }
190
191 bWasRepMovementModified = (bWasRepMovementModified || RepMovement.bRepPhysics);
192 RepMovement.bRepPhysics = false;
193 }
194
195#if WITH_PUSH_MODEL
196 if (bWasRepMovementModified)
197 {
198 // MARK_PROPERTY_DIRTY_FROM_NAME(AActor, ReplicatedMovement, this);
199 }
200
201 if (bWasAttachmentModified ||
202 OldAttachParent != AttachmentWeldReplication.AttachParent ||
203 OldAttachComponent != AttachmentWeldReplication.AttachComponent)
204 {
205 //MARK_PROPERTY_DIRTY_FROM_NAME(AGrippableActor, AttachmentWeldReplication, this);
206 }
207#endif
208 }
209}
210
212{
214 {
215 return;
216 }
217
218 if (AttachmentWeldReplication.AttachParent)
219 {
220 if (RootComponent)
221 {
222 USceneComponent* AttachParentComponent = (AttachmentWeldReplication.AttachComponent ? AttachmentWeldReplication.AttachComponent : AttachmentWeldReplication.AttachParent->GetRootComponent());
223
224 if (AttachParentComponent)
225 {
226 RootComponent->SetRelativeLocation_Direct(AttachmentWeldReplication.LocationOffset);
227 RootComponent->SetRelativeRotation_Direct(AttachmentWeldReplication.RotationOffset);
228 RootComponent->SetRelativeScale3D_Direct(AttachmentWeldReplication.RelativeScale3D);
229
230 // If we're already attached to the correct Parent and Socket, then the update must be position only.
231 // AttachToComponent would early out in this case.
232 // Note, we ignore the special case for simulated bodies in AttachToComponent as AttachmentReplication shouldn't get updated
233 // if the body is simulated (see AActor::GatherMovement).
234 const bool bAlreadyAttached = (AttachParentComponent == RootComponent->GetAttachParent() && AttachmentWeldReplication.AttachSocket == RootComponent->GetAttachSocketName() && AttachParentComponent->GetAttachChildren().Contains(RootComponent));
235 if (bAlreadyAttached)
236 {
237 // Note, this doesn't match AttachToComponent, but we're assuming it's safe to skip physics (see comment above).
238 RootComponent->UpdateComponentToWorld(EUpdateTransformFlags::SkipPhysicsUpdate, ETeleportType::None);
239 }
240 else
241 {
242 FAttachmentTransformRules attachRules = FAttachmentTransformRules::KeepRelativeTransform;
243 attachRules.bWeldSimulatedBodies = AttachmentWeldReplication.bIsWelded;
244 RootComponent->AttachToComponent(AttachParentComponent, attachRules, AttachmentWeldReplication.AttachSocket);
245 }
246 }
247 }
248 }
249 else
250 {
251 DetachFromActor(FDetachmentTransformRules::KeepWorldTransform);
252
253 // Handle the case where an object was both detached and moved on the server in the same frame.
254 // Calling this extraneously does not hurt but will properly fire events if the movement state changed while attached.
255 // This is needed because client side movement is ignored when attached
256 if (IsReplicatingMovement())
257 {
259 }
260 }
261}
262
263bool AGrippableActor::ReplicateSubobjects(UActorChannel* Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags)
264{
265 bool WroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags);
266
268 {
269 for (UVRGripScriptBase* Script : GripLogicScripts)
270 {
271 if (Script && !Script->IsPendingKill())
272 {
273 WroteSomething |= Channel->ReplicateSubobject(Script, *Bunch, *RepFlags);
274 }
275 }
276 }
277
278 return WroteSomething;
279}
280
281//=============================================================================
285
287{
288 // Call the base class
289 Super::BeginPlay();
290
291 // Call all grip scripts begin play events so they can perform any needed logic
292 for (UVRGripScriptBase* Script : GripLogicScripts)
293 {
294 if (Script)
295 {
296 Script->BeginPlay(this);
297 }
298 }
299}
300
301
302void AGrippableActor::SetDenyGripping(bool bDenyGripping)
303{
305}
306
307void AGrippableActor::SetGripPriority(int NewGripPriority)
308{
310}
311
312void AGrippableActor::TickGrip_Implementation(UGripMotionControllerComponent * GrippingController, const FBPActorGripInformation & GripInformation, float DeltaTime) {}
314void AGrippableActor::OnGripRelease_Implementation(UGripMotionControllerComponent* ReleasingController, const FBPActorGripInformation& GripInformation, bool bWasSocketed) { }
316void AGrippableActor::OnChildGripRelease_Implementation(UGripMotionControllerComponent * ReleasingController, const FBPActorGripInformation & GripInformation, bool bWasSocketed) {}
317void AGrippableActor::OnSecondaryGrip_Implementation(UGripMotionControllerComponent* GripOwningController, USceneComponent* SecondaryGripComponent, const FBPActorGripInformation& GripInformation) { OnSecondaryGripAdded.Broadcast(GripOwningController, GripInformation); }
318void AGrippableActor::OnSecondaryGripRelease_Implementation(UGripMotionControllerComponent* GripOwningController, USceneComponent* ReleasingSecondaryGripComponent, const FBPActorGripInformation& GripInformation) { OnSecondaryGripRemoved.Broadcast(GripOwningController, GripInformation); }
323void AGrippableActor::OnInput_Implementation(FKey Key, EInputEvent KeyEvent) {}
324bool AGrippableActor::RequestsSocketing_Implementation(USceneComponent *& ParentToSocketTo, FName & OptionalSocketName, FTransform_NetQuantize & RelativeTransform) { return false; }
325
330
331
336
341
346
351
356
361
362void AGrippableActor::GetGripStiffnessAndDamping_Implementation(float &GripStiffnessOut, float &GripDampingOut)
363{
366}
367
372
377
378void AGrippableActor::ClosestGripSlotInRange_Implementation(FVector WorldLocation, bool bSecondarySlot, bool & bHadSlotInRange, FTransform & SlotWorldTransform, FName & SlotName, UGripMotionControllerComponent * CallingController, FName OverridePrefix)
379{
380 if (OverridePrefix.IsNone())
381 bSecondarySlot ? OverridePrefix = "VRGripS" : OverridePrefix = "VRGripP";
382
383 UVRExpansionFunctionLibrary::GetGripSlotInRangeByTypeName(OverridePrefix, this, WorldLocation, bSecondarySlot ? VRGripInterfaceSettings.SecondarySlotRange : VRGripInterfaceSettings.PrimarySlotRange, bHadSlotInRange, SlotWorldTransform, SlotName, CallingController);
384}
385
390
391void AGrippableActor::IsHeld_Implementation(TArray<FBPGripPair> & HoldingControllers, bool & bIsHeld)
392{
393 HoldingControllers = VRGripInterfaceSettings.HoldingControllers;
395}
396
398{
400 {
401 // The subsystem automatically removes entries with the same function signature so its safe to just always add here
402 GetWorld()->GetSubsystem<UBucketUpdateSubsystem>()->AddObjectToBucket(ClientAuthReplicationData.UpdateRate, this, FName(TEXT("PollReplicationEvent")));
404
405 if (UWorld * World = GetWorld())
406 ClientAuthReplicationData.TimeAtInitialThrow = World->GetTimeSeconds();
407
408 return true;
409 }
410
411 return false;
412}
413
415{
417 {
418 GetWorld()->GetSubsystem<UBucketUpdateSubsystem>()->RemoveObjectFromBucketByFunctionName(this, FName(TEXT("PollReplicationEvent")));
420 return true;
421 }
422
423 return false;
424}
425
427{
428 if (bGripped)
429 {
430 OnGripped.Broadcast(Controller, GripInformation);
431 }
432 else
433 {
434 OnDropped.Broadcast(Controller, GripInformation, bWasSocketed);
435 }
436}
437
438void AGrippableActor::SetHeld_Implementation(UGripMotionControllerComponent * HoldingController, uint8 GripID, bool bIsHeld)
439{
440 if (bIsHeld)
441 {
442 VRGripInterfaceSettings.HoldingControllers.AddUnique(FBPGripPair(HoldingController, GripID));
444
447 }
448 else
449 {
450 VRGripInterfaceSettings.HoldingControllers.Remove(FBPGripPair(HoldingController, GripID));
452
454 {
455 bool bWasLocallyOwned = HoldingController ? HoldingController->IsLocallyControlled() : false;
456 if (bWasLocallyOwned && ShouldWeSkipAttachmentReplication(false))
457 {
458 if (UPrimitiveComponent* PrimComp = Cast<UPrimitiveComponent>(GetRootComponent()))
459 {
460 if (PrimComp->IsSimulatingPhysics())
461 {
463 }
464 }
465 }
466 }
467 }
468}
469
470bool AGrippableActor::GetGripScripts_Implementation(TArray<UVRGripScriptBase*> & ArrayReference)
471{
472 ArrayReference = GripLogicScripts;
473 return GripLogicScripts.Num() > 0;
474}
475
476/*FBPInteractionSettings AGrippableActor::GetInteractionSettings_Implementation()
477{
478 return VRGripInterfaceSettings.InteractionSettings;
479}*/
480
482{
484 return false; // Tell the bucket subsystem to remove us from consideration
485
486 UWorld* OurWorld = GetWorld();
487 if (!OurWorld)
488 return false; // Tell the bucket subsystem to remove us from consideration
489
490 bool bRemoveBlocking = false;
491
492 if ((OurWorld->GetTimeSeconds() - ClientAuthReplicationData.TimeAtInitialThrow) > 10.0f)
493 {
494 // Lets time out sending, its been 10 seconds since we threw the object and its likely that it is conflicting with some server
495 // Authed movement that is forcing it to keep momentum.
496 //return false; // Tell the bucket subsystem to remove us from consideration
497 bRemoveBlocking = true;
498 }
499
500 // Store current transform for resting check
501 FTransform CurTransform = this->GetActorTransform();
502
503 if (!bRemoveBlocking)
504 {
505 if (!CurTransform.GetRotation().Equals(ClientAuthReplicationData.LastActorTransform.GetRotation()) || !CurTransform.GetLocation().Equals(ClientAuthReplicationData.LastActorTransform.GetLocation()))
506 {
508
509 if (UPrimitiveComponent * PrimComp = Cast<UPrimitiveComponent>(RootComponent))
510 {
511 // Need to clamp to a max time since start, to handle cases with conflicting collisions
512 if (PrimComp->IsSimulatingPhysics() && ShouldWeSkipAttachmentReplication(false))
513 {
514 FRepMovementVR ClientAuthMovementRep;
515 if (ClientAuthMovementRep.GatherActorsMovement(this))
516 {
517 Server_GetClientAuthReplication(ClientAuthMovementRep);
518
519 if (PrimComp->RigidBodyIsAwake())
520 {
521 return true;
522 }
523 }
524 }
525 }
526 else
527 {
528 bRemoveBlocking = true;
529 //return false; // Tell the bucket subsystem to remove us from consideration
530 }
531 }
532 //else
533 // {
534 // Difference is too small, lets end sending location
535 //ClientAuthReplicationData.LastActorTransform = FTransform::Identity;
536 // }
537 }
538
539 bool TimedBlockingRelease = false;
540
541 AActor* TopOwner = GetOwner();
542 if (TopOwner != nullptr)
543 {
544 AActor* tempOwner = TopOwner->GetOwner();
545
546 // I have an owner so search that for the top owner
547 while (tempOwner)
548 {
549 TopOwner = tempOwner;
550 tempOwner = TopOwner->GetOwner();
551 }
552
553 if (APlayerController * PlayerController = Cast<APlayerController>(TopOwner))
554 {
555 if (APlayerState * PlayerState = PlayerController->PlayerState)
556 {
558 {
559 OurWorld->GetTimerManager().ClearTimer(ClientAuthReplicationData.ResetReplicationHandle);
560 }
561
562 // Lets clamp the ping to a min / max value just in case
563 float clampedPing = FMath::Clamp(PlayerState->ExactPing * 0.001f, 0.0f, 1000.0f);
564 OurWorld->GetTimerManager().SetTimer(ClientAuthReplicationData.ResetReplicationHandle, this, &AGrippableActor::CeaseReplicationBlocking, clampedPing, false);
565 TimedBlockingRelease = true;
566 }
567 }
568 }
569
570 if (!TimedBlockingRelease)
571 {
573 }
574
575 // Tell server to kill us
577 return false; // Tell the bucket subsystem to remove us from consideration
578}
579
581{
584
585 ClientAuthReplicationData.LastActorTransform = FTransform::Identity;
586
588 {
589 if (UWorld * OurWorld = GetWorld())
590 {
591 OurWorld->GetTimerManager().ClearTimer(ClientAuthReplicationData.ResetReplicationHandle);
592 }
593 }
594}
595
596void AGrippableActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
597{
598
600
601 // Call all grip scripts begin play events so they can perform any needed logic
602 for (UVRGripScriptBase* Script : GripLogicScripts)
603 {
604 if (Script)
605 {
606 Script->EndPlay(EndPlayReason);
607 }
608 }
609
610 Super::EndPlay(EndPlayReason);
611}
612
613bool AGrippableActor::Server_EndClientAuthReplication_Validate()
614{
615 return true;
616}
617
618void AGrippableActor::Server_EndClientAuthReplication_Implementation()
619{
620 if (UWorld* World = GetWorld())
621 {
622 if (FPhysScene* PhysScene = World->GetPhysicsScene())
623 {
624 if (FPhysicsReplication* PhysicsReplication = PhysScene->GetPhysicsReplication())
625 {
626 if (UPrimitiveComponent* RootPrim = Cast<UPrimitiveComponent>(GetRootComponent()))
627 {
628 PhysicsReplication->RemoveReplicatedTarget(RootPrim);
629 }
630 }
631 }
632 }
633}
634
635bool AGrippableActor::Server_GetClientAuthReplication_Validate(const FRepMovementVR & newMovement)
636{
637 return true;
638}
639
640void AGrippableActor::Server_GetClientAuthReplication_Implementation(const FRepMovementVR & newMovement)
641{
643 {
644 if (!newMovement.Location.ContainsNaN() && !newMovement.Rotation.ContainsNaN())
645 {
646 FRepMovement& MovementRep = GetReplicatedMovement_Mutable();
647 newMovement.CopyTo(MovementRep);
649 }
650 }
651}
652
654{
656 //if (bAllowIgnoringAttachOnOwner && (ClientAuthReplicationData.bIsCurrentlyClientAuth || ShouldWeSkipAttachmentReplication()))
657 {
658 return;
659 }
660
661 if (RootComponent)
662 {
663 const FRepAttachment ReplicationAttachment = GetAttachmentReplication();
664 if (!ReplicationAttachment.AttachParent)
665 {
666 const FRepMovement& RepMove = GetReplicatedMovement();
667
668 // This "fix" corrects the simulation state not replicating over correctly
669 // If you turn off movement replication, simulate an object, turn movement replication back on and un-simulate, it never knows the difference
670 // This change ensures that it is checking against the current state
671 if (RootComponent->IsSimulatingPhysics() != RepMove.bRepPhysics)//SavedbRepPhysics != ReplicatedMovement.bRepPhysics)
672 {
673 // Turn on/off physics sim to match server.
674 SyncReplicatedPhysicsSimulation();
675
676 // It doesn't really hurt to run it here, the super can call it again but it will fail out as they already match
677 }
678 }
679 }
680
681 Super::OnRep_ReplicateMovement();
682}
683
685{
687 //if (ClientAuthReplicationData.bIsCurrentlyClientAuth && ShouldWeSkipAttachmentReplication(false))
688 {
689 return;
690 }
691
692 Super::OnRep_ReplicatedMovement();
693}
694
696{
698 //if ((ClientAuthReplicationData.bIsCurrentlyClientAuth || VRGripInterfaceSettings.bIsHeld) && bAllowIgnoringAttachOnOwner && ShouldWeSkipAttachmentReplication(false))
699 {
700 return;
701 }
702
703 Super::PostNetReceivePhysicState();
704}
705// This isn't called very many places but it does come up
707{
708 Super::MarkComponentsAsPendingKill();
709
710 for (int32 i = 0; i < GripLogicScripts.Num(); ++i)
711 {
712 if (UObject *SubObject = GripLogicScripts[i])
713 {
714 SubObject->MarkPendingKill();
715 }
716 }
717
718 GripLogicScripts.Empty();
719}
720
722// Clean up our objects so that they aren't sitting around for GC
724{
725 Super::PreDestroyFromReplication();
726
727 // Destroy any sub-objects we created
728 for (int32 i = 0; i < GripLogicScripts.Num(); ++i)
729 {
730 if (UObject *SubObject = GripLogicScripts[i])
731 {
732 OnSubobjectDestroyFromReplication(SubObject); //-V595
733 SubObject->PreDestroyFromReplication();
734 SubObject->MarkPendingKill();
735 }
736 }
737
738 for (UActorComponent * ActorComp : GetComponents())
739 {
740 // Pending kill components should have already had this called as they were network spawned and are being killed
741 if (ActorComp && !ActorComp->IsPendingKill() && ActorComp->GetClass()->ImplementsInterface(UVRGripInterface::StaticClass()))
742 ActorComp->PreDestroyFromReplication();
743 }
744
745 GripLogicScripts.Empty();
746}
747
748// On Destroy clean up our objects
750{
751 Super::BeginDestroy();
752
753 for (int32 i = 0; i < GripLogicScripts.Num(); i++)
754 {
755 if (UObject *SubObject = GripLogicScripts[i])
756 {
757 SubObject->MarkPendingKill();
758 }
759 }
760
761 GripLogicScripts.Empty();
762}
763
765{
766 Super::GetSubobjectsWithStableNamesForNetworking(ObjList);
767
769 {
770 for (int32 i = 0; i < GripLogicScripts.Num(); ++i)
771 {
772 if (UObject* SubObject = GripLogicScripts[i])
773 {
774 ObjList.Add(SubObject);
775 }
776 }
777 }
778}
EGripMovementReplicationSettings
UENUM(Blueprintable)
ESecondaryGripType
UENUM(Blueprintable)
EGripCollisionType
UENUM(Blueprintable)
EGripLateUpdateSettings
UENUM(Blueprintable)
EGripInterfaceTeleportBehavior
UENUM(Blueprintable)
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = (VRExpansionPlugin))
virtual void MarkComponentsAsPendingKill() override
bool bRepGripSettingsAndGameplayTags
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "VRGripInterface")
FGameplayTagContainer GameplayTags
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "GameplayTags")
virtual float GripBreakDistance_Implementation() override
TArray< class UVRGripScriptBase * > GripLogicScripts
UPROPERTY(EditAnywhere, Replicated, BlueprintReadOnly, Instanced, Category = "VRGripInterface")
virtual bool GetGripScripts_Implementation(TArray< UVRGripScriptBase * > &ArrayReference) override
FVRClientAuthReplicationData ClientAuthReplicationData
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "Replication")
void CeaseReplicationBlocking()
UFUNCTION(Category = "Networking")
virtual EGripLateUpdateSettings GripLateUpdateSetting_Implementation() override
virtual void GatherCurrentMovement() override
virtual bool SimulateOnDrop_Implementation() override
virtual void OnSecondaryGripRelease_Implementation(UGripMotionControllerComponent *GripOwningController, USceneComponent *ReleasingSecondaryGripComponent, const FBPActorGripInformation &GripInformation) override
virtual void OnChildGripRelease_Implementation(UGripMotionControllerComponent *ReleasingController, const FBPActorGripInformation &GripInformation, bool bWasSocketed=false) override
virtual void PreReplication(IRepChangedPropertyTracker &ChangedPropertyTracker) override
bool ShouldWeSkipAttachmentReplication(bool bConsiderHeld=true) const
virtual bool RequestsSocketing_Implementation(USceneComponent *&ParentToSocketTo, FName &OptionalSocketName, FTransform_NetQuantize &RelativeTransform) override
virtual void BeginPlay() override
void Server_GetClientAuthReplication(const FRepMovementVR &newMovement)
UFUNCTION(UnReliable, Server, WithValidation, Category = "Networking")
virtual void SetHeld_Implementation(UGripMotionControllerComponent *HoldingController, uint8 GripID, bool bIsHeld) override
virtual void PostNetReceivePhysicState() override
virtual bool AllowsMultipleGrips_Implementation() override
virtual void OnSecondaryUsed_Implementation() override
bool bReplicateGripScripts
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "VRGripInterface")
virtual void GetGripStiffnessAndDamping_Implementation(float &GripStiffnessOut, float &GripDampingOut) override
virtual EGripInterfaceTeleportBehavior TeleportBehavior_Implementation() override
void Server_EndClientAuthReplication()
UFUNCTION(Reliable, Server, WithValidation, Category = "Networking")
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
virtual void OnGrip_Implementation(UGripMotionControllerComponent *GrippingController, const FBPActorGripInformation &GripInformation) override
virtual void Native_NotifyThrowGripDelegates(UGripMotionControllerComponent *Controller, bool bGripped, const FBPActorGripInformation &GripInformation, bool bWasSocketed=false) override
bool ReplicateSubobjects(UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) override
virtual void OnInput_Implementation(FKey Key, EInputEvent KeyEvent) override
FVROnGripSignature OnSecondaryGripAdded
UPROPERTY(BlueprintAssignable, Category = "Grip Events")
virtual void OnRep_ReplicateMovement() override
virtual FBPAdvGripSettings AdvancedGripSettings_Implementation() override
bool PollReplicationEvent()
UFUNCTION()
FBPInterfaceProperties VRGripInterfaceSettings
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "VRGripInterface")
AGrippableActor(const FObjectInitializer &ObjectInitializer)
virtual void BeginDestroy() override
virtual void OnEndUsed_Implementation() override
virtual ESecondaryGripType SecondaryGripType_Implementation() override
virtual void OnRep_ReplicatedMovement() override
virtual void OnRep_AttachmentReplication() override
bool bAllowIgnoringAttachOnOwner
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "Replication")
bool RemoveFromClientReplicationBucket()
UFUNCTION(BlueprintCallable, Category = "Networking")
virtual void OnChildGrip_Implementation(UGripMotionControllerComponent *GrippingController, const FBPActorGripInformation &GripInformation) override
FVROnGripSignature OnSecondaryGripRemoved
UPROPERTY(BlueprintAssignable, Category = "Grip Events")
bool AddToClientReplicationBucket()
UFUNCTION(BlueprintCallable, Category = "Networking")
virtual void PreDestroyFromReplication() override
virtual void IsHeld_Implementation(TArray< FBPGripPair > &HoldingControllers, bool &bIsHeld) override
void SetDenyGripping(bool bDenyGripping)
UFUNCTION(BlueprintCallable, Category = "VRGripInterface")
virtual void ClosestGripSlotInRange_Implementation(FVector WorldLocation, bool bSecondarySlot, bool &bHadSlotInRange, FTransform &SlotWorldTransform, FName &SlotName, UGripMotionControllerComponent *CallingController=nullptr, FName OverridePrefix=NAME_None) override
FVROnDropSignature OnDropped
UPROPERTY(BlueprintAssignable, Category = "Grip Events")
virtual bool DenyGripping_Implementation(UGripMotionControllerComponent *GripInitiator=nullptr) override
virtual void OnGripRelease_Implementation(UGripMotionControllerComponent *ReleasingController, const FBPActorGripInformation &GripInformation, bool bWasSocketed=false) override
FVROnGripSignature OnGripped
UPROPERTY(BlueprintAssignable, Category = "Grip Events")
virtual void OnSecondaryGrip_Implementation(UGripMotionControllerComponent *GripOwningController, USceneComponent *SecondaryGripComponent, const FBPActorGripInformation &GripInformation) override
virtual void OnUsed_Implementation() override
FRepAttachmentWithWeld AttachmentWeldReplication
UPROPERTY(Replicated, ReplicatedUsing = OnRep_AttachmentReplication)
virtual void OnEndSecondaryUsed_Implementation() override
virtual void GetSubobjectsWithStableNamesForNetworking(TArray< UObject * > &ObjList) override
void SetGripPriority(int NewGripPriority)
UFUNCTION(BlueprintCallable, Category = "VRGripInterface")
virtual void TickGrip_Implementation(UGripMotionControllerComponent *GrippingController, const FBPActorGripInformation &GripInformation, float DeltaTime) override
virtual EGripMovementReplicationSettings GripMovementReplicationType_Implementation() override
virtual EGripCollisionType GetPrimaryGripType_Implementation(bool bIsSlot) override
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = MotionController)
static void GetGripSlotInRangeByTypeName(FName SlotType, AActor *Actor, FVector WorldLocation, float MaxRange, bool &bHadSlotInRange, FTransform &SlotWorldTransform, FName &SlotName, UGripMotionControllerComponent *QueryController=nullptr)
UFUNCTION(BlueprintPure, Category = "VRGrip", meta = (bIgnoreSelf = "true", DisplayName = "GetGripSlo...
UCLASS(NotBlueprintable, BlueprintType, EditInlineNew, DefaultToInstanced, Abstract,...
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
uint8 GripPriority
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AdvancedGripSettings")
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
ESecondaryGripType SecondaryGripType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
bool bDenyGripping
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
EGripCollisionType FreeDefaultGripType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
float ConstraintBreakDistance
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
bool bAllowMultipleGrips
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
float SecondarySlotRange
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
EGripLateUpdateSettings LateUpdateSetting
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
EGripCollisionType SlotDefaultGripType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
EGripInterfaceTeleportBehavior OnTeleportBehavior
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
float ConstraintStiffness
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
float PrimarySlotRange
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
bool bIsHeld
UPROPERTY(BlueprintReadWrite, NotReplicated, Category = "VRGripInterface")
TArray< FBPGripPair > HoldingControllers
UPROPERTY(BlueprintReadWrite, NotReplicated, Category = "VRGripInterface")
float ConstraintDamping
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
FBPAdvGripSettings AdvancedGripSettings
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface|AdvancedGripSettings")
EGripMovementReplicationSettings MovementReplicationType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
bool bSimulateOnDrop
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
void CopyTo(FRepMovement &other) const
bool GatherActorsMovement(AActor *OwningActor)
USTRUCT(BlueprintType, Category = "VRExpansionLibrary|TransformNetQuantize", meta = (HasNativeMake = ...
int32 UpdateRate
UPROPERTY(EditAnywhere, NotReplicated, BlueprintReadOnly, Category = "VRReplication",...
bool bUseClientAuthThrowing
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRReplication")