A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
CharacterMovementCompTypes.h
Go to the documentation of this file.
1// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4#include "CoreMinimal.h"
5#include "Engine/Engine.h"
6#include "VRBPDatatypes.h"
7#include "GameFramework/Character.h"
8#include "GameFramework/CharacterMovementComponent.h"
9#include "GameFramework/CharacterMovementReplication.h"
10#include "Components/SkeletalMeshComponent.h"
11#include "CharacterMovementCompTypes.generated.h"
12
13
16
17UENUM(Blueprintable)
18enum class EVRMoveAction : uint8
19{
20 VRMOVEACTION_None = 0x00,
25 VRMOVEACTION_PauseTracking = 0x14, // Reserved from here up to 0x40
41 // Up to 0x20 currently allowed for
42};
43
44// What to do with the players velocity when specific move actions are called
45// Default of none leaves it as is, for people with 0 ramp up time on acelleration
46// This likely won't be that useful.
47UENUM(Blueprintable)
48enum class EVRMoveActionVelocityRetention : uint8
49{
50 // Leaves velocity as is
52
53 // Clears velocity entirely
55
56 // Rotates the velocity to match new heading
58};
59
60UENUM(Blueprintable)
61enum class EVRMoveActionDataReq : uint8
62{
67};
68
69
71USTRUCT()
72struct VREXPANSIONPLUGIN_API FVRMoveActionContainer
73{
74 GENERATED_USTRUCT_BODY()
75public:
76 UPROPERTY()
77 EVRMoveAction MoveAction;
78 UPROPERTY()
79 EVRMoveActionDataReq MoveActionDataReq;
80 UPROPERTY()
81 FVector MoveActionLoc;
82 UPROPERTY()
83 FVector MoveActionVel;
84 UPROPERTY()
85 FRotator MoveActionRot;
86 UPROPERTY()
87 uint8 MoveActionFlags;
88 UPROPERTY()
89 TArray<UObject*> MoveActionObjectReferences;
90 UPROPERTY()
91 EVRMoveActionVelocityRetention VelRetentionSetting;
92
94 {
95 Clear();
96 }
97
98 void Clear()
99 {
102 MoveActionLoc = FVector::ZeroVector;
103 MoveActionVel = FVector::ZeroVector;
104 MoveActionRot = FRotator::ZeroRotator;
105 MoveActionFlags = 0;
107 MoveActionObjectReferences.Empty();
108 }
109
111 // Doing a custom NetSerialize here because this is sent via RPCs and should change on every update
112 bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
113 {
114 bOutSuccess = true;
115
116 Ar.SerializeBits(&MoveAction, 6); // 64 elements, only allowing 1 per frame, they aren't flags
117
118 switch (MoveAction)
119 {
124 uint16 Yaw = 0;
125 uint16 Pitch = 0;
126
127 if (Ar.IsSaving())
128 {
129 bool bUseLocOnly = MoveActionFlags & 0x04;
130 Ar.SerializeBits(&bUseLocOnly, 1);
131
132 if (!bUseLocOnly)
133 {
134 Yaw = FRotator::CompressAxisToShort(MoveActionRot.Yaw);
135 Ar << Yaw;
136 }
137 else
138 {
139 Ar << MoveActionLoc;
140 }
141
142 bool bTeleportGrips = MoveActionFlags & 0x01;// MoveActionRot.Roll > 0.0f && MoveActionRot.Roll < 1.5f;
143 Ar.SerializeBits(&bTeleportGrips, 1);
144
145 if (!bTeleportGrips)
146 {
147 bool bTeleportCharacter = MoveActionFlags & 0x02;// MoveActionRot.Roll > 1.5f;
148 Ar.SerializeBits(&bTeleportCharacter, 1);
149 }
150
151 Ar.SerializeBits(&VelRetentionSetting, 2);
152
154 {
155 bOutSuccess &= SerializePackedVector<100, 30>(MoveActionVel, Ar);
156 //Pitch = FRotator::CompressAxisToShort(MoveActionRot.Pitch);
157 //Ar << Pitch;
158 }
159 }
160 else
161 {
162
163 bool bUseLocOnly = false;
164 Ar.SerializeBits(&bUseLocOnly, 1);
165 MoveActionFlags |= (bUseLocOnly << 2);
166
167 if (!bUseLocOnly)
168 {
169 Ar << Yaw;
170 MoveActionRot.Yaw = FRotator::DecompressAxisFromShort(Yaw);
171 }
172 else
173 {
174 Ar << MoveActionLoc;
175 }
176
177 bool bTeleportGrips = false;
178 Ar.SerializeBits(&bTeleportGrips, 1);
179 MoveActionFlags |= (uint8)bTeleportGrips; //.Roll = bTeleportGrips ? 1.0f : 0.0f;
180
181 if (!bTeleportGrips)
182 {
183 bool bTeleportCharacter = false;
184 Ar.SerializeBits(&bTeleportCharacter, 1);
185 MoveActionFlags |= ((uint8)bTeleportCharacter << 1);
186 //MoveActionRot.Roll = 2.0f;
187 }
188
189 Ar.SerializeBits(&VelRetentionSetting, 2);
190
192 {
193 bOutSuccess &= SerializePackedVector<100, 30>(MoveActionVel, Ar);
194 //Ar << Pitch;
195 //MoveActionRot.Pitch = FRotator::DecompressAxisFromShort(Pitch);
196 }
197 }
198
199 //bOutSuccess &= SerializePackedVector<100, 30>(MoveActionLoc, Ar);
200 }break;
201 case EVRMoveAction::VRMOVEACTION_Teleport: // Not replicating rot as Control rot does that already
202 {
203 uint16 Yaw = 0;
204 uint16 Pitch = 0;
205
206 if (Ar.IsSaving())
207 {
208 Yaw = FRotator::CompressAxisToShort(MoveActionRot.Yaw);
209 Ar << Yaw;
210
211 bool bSkipEncroachment = MoveActionFlags & 0x01;// MoveActionRot.Roll > 0.0f;
212 Ar.SerializeBits(&bSkipEncroachment, 1);
213 Ar.SerializeBits(&VelRetentionSetting, 2);
214
216 {
217 bOutSuccess &= SerializePackedVector<100, 30>(MoveActionVel, Ar);
218 //Pitch = FRotator::CompressAxisToShort(MoveActionRot.Pitch);
219 //Ar << Pitch;
220 }
221 }
222 else
223 {
224 Ar << Yaw;
225 MoveActionRot.Yaw = FRotator::DecompressAxisFromShort(Yaw);
226
227 bool bSkipEncroachment = false;
228 Ar.SerializeBits(&bSkipEncroachment, 1);
229 MoveActionFlags |= (uint8)bSkipEncroachment;
230 //MoveActionRot.Roll = bSkipEncroachment ? 1.0f : 0.0f;
231 Ar.SerializeBits(&VelRetentionSetting, 2);
232
234 {
235 bOutSuccess &= SerializePackedVector<100, 30>(MoveActionVel, Ar);
236 //Ar << Pitch;
237 //MoveActionRot.Pitch = FRotator::DecompressAxisFromShort(Pitch);
238 }
239 }
240
241 bOutSuccess &= SerializePackedVector<100, 30>(MoveActionLoc, Ar);
242 }break;
244 {}break;
246 {
247
248 Ar.SerializeBits(&MoveActionFlags, 1);
249 bOutSuccess &= SerializePackedVector<100, 30>(MoveActionLoc, Ar);
250
251 uint16 Yaw = 0;
252 // Loc and rot for capsule should also be sent here
253 if (Ar.IsSaving())
254 {
255 Yaw = FRotator::CompressAxisToShort(MoveActionRot.Yaw);
256 Ar << Yaw;
257 }
258 else
259 {
260 Ar << Yaw;
261 MoveActionRot.Yaw = FRotator::DecompressAxisFromShort(Yaw);
262 }
263
264 }break;
265 default: // Everything else
266 {
267 // Defines how much to replicate - only 4 possible values, 0 - 3 so only send 2 bits
268 Ar.SerializeBits(&MoveActionDataReq, 2);
269
270 if (((uint8)MoveActionDataReq & (uint8)EVRMoveActionDataReq::VRMOVEACTIONDATA_LOC) != 0)
271 bOutSuccess &= SerializePackedVector<100, 30>(MoveActionLoc, Ar);
272
273 if (((uint8)MoveActionDataReq & (uint8)EVRMoveActionDataReq::VRMOVEACTIONDATA_ROT) != 0)
274 MoveActionRot.SerializeCompressedShort(Ar);
275
276 bool bSerializeObjects = MoveActionObjectReferences.Num() > 0;
277 Ar.SerializeBits(&bSerializeObjects, 1);
278 if (bSerializeObjects)
279 {
280 Ar << MoveActionObjectReferences;
281 }
282
283 bool bSerializeFlags = MoveActionFlags != 0x00;
284 Ar.SerializeBits(&bSerializeFlags, 1);
285 if (bSerializeFlags)
286 {
287 Ar << MoveActionFlags;
288 }
289
290 }break;
291 }
292
293 return bOutSuccess;
294 }
295};
296template<>
297struct TStructOpsTypeTraits< FVRMoveActionContainer > : public TStructOpsTypeTraitsBase2<FVRMoveActionContainer>
298{
299 enum
300 {
301 WithNetSerializer = true
302 };
303};
304
305USTRUCT()
306struct VREXPANSIONPLUGIN_API FVRMoveActionArray
307{
308 GENERATED_USTRUCT_BODY()
309public:
310 UPROPERTY()
311 TArray<FVRMoveActionContainer> MoveActions;
312
313 void Clear()
314 {
315 MoveActions.Empty();
316 }
317
319 // Doing a custom NetSerialize here because this is sent via RPCs and should change on every update
320 bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
321 {
322 bOutSuccess = true;
323 uint8 MoveActionCount = (uint8)MoveActions.Num();
324 bool bHasAMoveAction = MoveActionCount > 0;
325 Ar.SerializeBits(&bHasAMoveAction, 1);
326
327 if (bHasAMoveAction)
328 {
329 bool bHasMoreThanOneMoveAction = MoveActionCount > 1;
330 Ar.SerializeBits(&bHasMoreThanOneMoveAction, 1);
331
332 if (Ar.IsSaving())
333 {
334 if (bHasMoreThanOneMoveAction)
336 Ar << MoveActionCount;
338 for (int i = 0; i < MoveActionCount; i++)
339 {
340 bOutSuccess &= MoveActions[i].NetSerialize(Ar, Map, bOutSuccess);
341 }
343 else
345 bOutSuccess &= MoveActions[0].NetSerialize(Ar, Map, bOutSuccess);
346 }
347 }
348 else
349 {
350 if (bHasMoreThanOneMoveAction)
352 Ar << MoveActionCount;
353 }
354 else
355 MoveActionCount = 1;
356
357 for (int i = 0; i < MoveActionCount; i++)
358 {
359 FVRMoveActionContainer MoveAction;
360 bOutSuccess &= MoveAction.NetSerialize(Ar, Map, bOutSuccess);
361 MoveActions.Add(MoveAction);
362 }
363 }
364 }
365
366 return bOutSuccess;
367 }
368};
369template<>
370struct TStructOpsTypeTraits< FVRMoveActionArray > : public TStructOpsTypeTraitsBase2<FVRMoveActionArray>
371{
372 enum
373 {
374 WithNetSerializer = true
375 };
376};
377
378
379USTRUCT()
380struct VREXPANSIONPLUGIN_API FVRConditionalMoveRep
381{
382 GENERATED_USTRUCT_BODY()
383public:
384
385 UPROPERTY(Transient)
386 FVector CustomVRInputVector;
387 UPROPERTY(Transient)
388 FVector RequestedVelocity;
389 UPROPERTY(Transient)
390 FVRMoveActionArray MoveActionArray;
391 //FVRMoveActionContainer MoveAction;
392
394 {
395 CustomVRInputVector = FVector::ZeroVector;
396 RequestedVelocity = FVector::ZeroVector;
397 }
398
400 // Doing a custom NetSerialize here because this is sent via RPCs and should change on every update
401 bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
402 {
403 bOutSuccess = true;
404
405 bool bIsLoading = Ar.IsLoading();
407 bool bHasVRinput = !CustomVRInputVector.IsZero();
408 bool bHasRequestedVelocity = !RequestedVelocity.IsZero();
409 bool bHasMoveAction = MoveActionArray.MoveActions.Num() > 0;//MoveAction.MoveAction != EVRMoveAction::VRMOVEACTION_None;
410
411 bool bHasAnyProperties = bHasVRinput || bHasRequestedVelocity || bHasMoveAction;
412 Ar.SerializeBits(&bHasAnyProperties, 1);
414 if (bHasAnyProperties)
416 Ar.SerializeBits(&bHasVRinput, 1);
417 Ar.SerializeBits(&bHasRequestedVelocity, 1);
418 //Ar.SerializeBits(&bHasMoveAction, 1);
419
420 if (bHasVRinput)
421 {
422 bOutSuccess &= SerializePackedVector<100, 22/*30*/>(CustomVRInputVector, Ar);
423 }
424 else if (bIsLoading)
425 {
426 CustomVRInputVector = FVector::ZeroVector;
428
429 if (bHasRequestedVelocity)
430 {
431 bOutSuccess &= SerializePackedVector<100, 22/*30*/>(RequestedVelocity, Ar);
433 else if (bIsLoading)
434 {
435 RequestedVelocity = FVector::ZeroVector;
436 }
437
438 //if (bHasMoveAction)
439 MoveActionArray.NetSerialize(Ar, Map, bOutSuccess);
440 }
441 else if (bIsLoading)
442 {
443 CustomVRInputVector = FVector::ZeroVector;
444 RequestedVelocity = FVector::ZeroVector;
445 MoveActionArray.Clear();
446 }
447
448 return bOutSuccess;
449 }
450
451};
452
453template<>
454struct TStructOpsTypeTraits< FVRConditionalMoveRep > : public TStructOpsTypeTraitsBase2<FVRConditionalMoveRep>
455{
456 enum
457 {
458 WithNetSerializer = true
459 };
460};
461
462// #TODO: DELETE THIS
463USTRUCT()
464struct VREXPANSIONPLUGIN_API FVRConditionalMoveRep2
465{
466 GENERATED_USTRUCT_BODY()
467public:
468
469 // Moved these here to avoid having to duplicate tons of properties
470 UPROPERTY(Transient)
471 UPrimitiveComponent* ClientMovementBase;
472 UPROPERTY(Transient)
473 FName ClientBaseBoneName;
474
475 UPROPERTY(Transient)
476 uint16 ClientYaw;
477
478 UPROPERTY(Transient)
479 uint16 ClientPitch;
480
481 UPROPERTY(Transient)
482 uint8 ClientRoll;
483
485 {
486 ClientMovementBase = nullptr;
487 ClientBaseBoneName = NAME_None;
488 ClientRoll = 0;
489 ClientPitch = 0;
490 ClientYaw = 0;
491 }
492
493 void UnpackAndSetINTRotations(uint32 Rotation32)
494 {
495 // Reversed the order of these so it costs less to replicate
496 ClientYaw = (Rotation32 & 65535);
497 ClientPitch = (Rotation32 >> 16);
498 }
499
501 // Doing a custom NetSerialize here because this is sent via RPCs and should change on every update
502 bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
503 {
504 bOutSuccess = true;
505
506 bool bRepRollAndPitch = (ClientRoll != 0 || ClientPitch != 0);
507 Ar.SerializeBits(&bRepRollAndPitch, 1);
509 if (bRepRollAndPitch)
511 // Reversed the order of these
512 uint32 Rotation32 = (((uint32)ClientPitch) << 16) | ((uint32)ClientYaw);
513 Ar.SerializeIntPacked(Rotation32);
514 Ar << ClientRoll;
515
516 if (Ar.IsLoading())
517 {
518 UnpackAndSetINTRotations(Rotation32);
519 }
520 }
521 else
522 {
523 uint32 Yaw32 = ClientYaw;
524 Ar.SerializeIntPacked(Yaw32);
525 ClientYaw = (uint16)Yaw32;
526 }
527
528 bool bHasMovementBase = MovementBaseUtility::IsDynamicBase(ClientMovementBase);
529 Ar.SerializeBits(&bHasMovementBase, 1);
530
531 if (bHasMovementBase)
532 {
533 Ar << ClientMovementBase;
534
535 bool bValidName = ClientBaseBoneName != NAME_None;
536 Ar.SerializeBits(&bValidName, 1);
537
538 // This saves 9 bits on average, we almost never have a valid bone name and default rep goes to 9 bits for hardcoded
539 // total of 6 bits savings as we use 3 extra for our flags in here.
540 if (bValidName)
542 Ar << ClientBaseBoneName;
544 }
545
546 return bOutSuccess;
547 }
548
549};
550
551template<>
552struct TStructOpsTypeTraits< FVRConditionalMoveRep2 > : public TStructOpsTypeTraitsBase2<FVRConditionalMoveRep2>
553{
554 enum
555 {
556 WithNetSerializer = true
557 };
558};
559
570{
571 FScopedMeshBoneUpdateOverrideVR(USkeletalMeshComponent* Mesh, EKinematicBonesUpdateToPhysics::Type OverrideSetting)
572 : MeshRef(Mesh)
573 {
574 if (MeshRef)
575 {
576 // Save current state.
577 SavedUpdateSetting = MeshRef->KinematicBonesUpdateType;
578 // Override bone update setting.
579 MeshRef->KinematicBonesUpdateType = OverrideSetting;
580 }
581 }
582
584 {
585 if (MeshRef)
586 {
587 // Restore bone update flag.
588 MeshRef->KinematicBonesUpdateType = SavedUpdateSetting;
589 }
590 }
591
592private:
594 EKinematicBonesUpdateToPhysics::Type SavedUpdateSetting;
595};
596
597
598class VREXPANSIONPLUGIN_API FSavedMove_VRBaseCharacter : public FSavedMove_Character
599{
600
601public:
602
603 EVRConjoinedMovementModes VRReplicatedMovementMode;
604
605 FVector VRCapsuleLocation;
606 FVector LFDiff;
607 FRotator VRCapsuleRotation;
608 FVRConditionalMoveRep ConditionalValues;
609
610 void Clear();
611 virtual void SetInitialPosition(ACharacter* C);
612 virtual void PrepMoveFor(ACharacter* Character) override;
613 virtual void CombineWith(const FSavedMove_Character* OldMove, ACharacter* InCharacter, APlayerController* PC, const FVector& OldStartLocation) override;
614
616 virtual void PostUpdate(ACharacter* C, EPostUpdateMode PostUpdateMode) override;
617
619
620 virtual uint8 GetCompressedFlags() const override;
621 virtual bool CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* Character, float MaxDelta) const override;
622 virtual bool IsImportantMove(const FSavedMovePtr& LastAckedMove) const override;
623};
624
625// Using this fixes the problem where the character capsule isn't reset after a scoped movement update revert (pretty much just in StepUp operations)
626class VREXPANSIONPLUGIN_API FVRCharacterScopedMovementUpdate : public FScopedMovementUpdate
627{
628public:
629
630 FVRCharacterScopedMovementUpdate(USceneComponent* Component, EScopedUpdate::Type ScopeBehavior = EScopedUpdate::DeferredUpdates, bool bRequireOverlapsEventFlagToQueueOverlaps = true);
631
632 FTransform InitialVRTransform;
633
635 void RevertMove();
636};
637
638
640//typedef TSharedPtr<class FSavedMove_Character> FSavedMovePtr;
641struct VREXPANSIONPLUGIN_API FVRCharacterNetworkMoveData : public FCharacterNetworkMoveData
643public:
644
645 FVector_NetQuantize100 VRCapsuleLocation;
646 FVector_NetQuantize100 LFDiff;
647 uint16 VRCapsuleRotation;
648 EVRConjoinedMovementModes ReplicatedMovementMode;
649 FVRConditionalMoveRep ConditionalMoveReps;
650
654 virtual void ClientFillNetworkMoveData(const FSavedMove_Character& ClientMove, ENetworkMoveType MoveType) override;
655 virtual bool Serialize(UCharacterMovementComponent& CharacterMovement, FArchive& Ar, UPackageMap* PackageMap, ENetworkMoveType MoveType) override;
656};
659{
660public:
661
667 NewMoveData = &VRBaseDefaultMoveData[0];
668 PendingMoveData = &VRBaseDefaultMoveData[1];
669 OldMoveData = &VRBaseDefaultMoveData[2];
670 }
671
673 {
674 }
675
679 //virtual void ClientFillNetworkMoveData(const FSavedMove_Character* ClientNewMove, const FSavedMove_Character* ClientPendingMove, const FSavedMove_Character* ClientOldMove);
680
684 //virtual bool Serialize(UCharacterMovementComponent& CharacterMovement, FArchive& Ar, UPackageMap* PackageMap);
686
687
688protected:
689
690
691 FVRCharacterNetworkMoveData VRBaseDefaultMoveData[3];
692
693};
694
696{
697public:
698
701 }
702
710 virtual void ServerFillResponseData(const UCharacterMovementComponent& CharacterMovement, const FClientAdjustment& PendingAdjustment) override;
711
712 //bool bHasRotation; // By default ClientAdjustment.NewRot is not serialized. Set this to true after base ServerFillResponseData if you want Rotation to be serialized.
713
714};
EVRMoveActionVelocityRetention
UENUM(Blueprintable)
EVRMoveActionDataReq
UENUM(Blueprintable)
EVRMoveAction
UENUM(Blueprintable)
@ VRMOVEACTION_StopAllMovement
@ VRMOVEACTION_PauseTracking
@ VRMOVEACTION_SetRotation
EVRConjoinedMovementModes
UENUM(BlueprintType)
EVRConjoinedMovementModes VRReplicatedMovementMode
FScopedMeshBoneUpdateOverrideVR(USkeletalMeshComponent *Mesh, EKinematicBonesUpdateToPhysics::Type OverrideSetting)
EKinematicBonesUpdateToPhysics::Type SavedUpdateSetting
EVRConjoinedMovementModes ReplicatedMovementMode
UPrimitiveComponent * ClientMovementBase
UPROPERTY(Transient)
bool NetSerialize(FArchive &Ar, class UPackageMap *Map, bool &bOutSuccess)
uint8 ClientRoll
UPROPERTY(Transient)
uint16 ClientPitch
UPROPERTY(Transient)
uint16 ClientYaw
UPROPERTY(Transient)
void UnpackAndSetINTRotations(uint32 Rotation32)
FName ClientBaseBoneName
UPROPERTY(Transient)
bool NetSerialize(FArchive &Ar, class UPackageMap *Map, bool &bOutSuccess)
FVector RequestedVelocity
UPROPERTY(Transient)
FVector CustomVRInputVector
UPROPERTY(Transient)
FVRMoveActionArray MoveActionArray
UPROPERTY(Transient)
bool NetSerialize(FArchive &Ar, class UPackageMap *Map, bool &bOutSuccess)
TArray< FVRMoveActionContainer > MoveActions
UPROPERTY()
EVRMoveActionVelocityRetention VelRetentionSetting
UPROPERTY()
EVRMoveActionDataReq MoveActionDataReq
UPROPERTY()
EVRMoveAction MoveAction
UPROPERTY()
TArray< UObject * > MoveActionObjectReferences
UPROPERTY()
bool NetSerialize(FArchive &Ar, class UPackageMap *Map, bool &bOutSuccess)