void ACharacter::OnRep_ReplicatedBasedMovement() { if (Role != ROLE_SimulatedProxy) { return; } // Skip base updates while playing root motion, it is handled inside of OnRep_RootMotion if (IsPlayingNetworkedRootMotionMontage()) { return; } TGuardValue<bool> bInBaseReplicationGuard(bInBaseReplication, true); const bool bBaseChanged = (BasedMovement.MovementBase != ReplicatedBasedMovement.MovementBase || BasedMovement.BoneName != ReplicatedBasedMovement.BoneName); if (bBaseChanged) { // Even though we will copy the replicated based movement info, we need to use SetBase() to set up tick dependencies and trigger notifications. SetBase(ReplicatedBasedMovement.MovementBase, ReplicatedBasedMovement.BoneName); } // Make sure to use the values of relative location/rotation etc from the server. BasedMovement = ReplicatedBasedMovement; if (ReplicatedBasedMovement.HasRelativeLocation()) { // Update transform relative to movement base const FVector OldLocation = GetActorLocation(); const FQuat OldRotation = GetActorQuat(); MovementBaseUtility::GetMovementBaseTransform(ReplicatedBasedMovement.MovementBase, ReplicatedBasedMovement.BoneName, CharacterMovement->OldBaseLocation, CharacterMovement->OldBaseQuat); const FVector NewLocation = CharacterMovement->OldBaseLocation + ReplicatedBasedMovement.Location; if (ReplicatedBasedMovement.HasRelativeRotation()) { // Relative location, relative rotation FRotator NewRotation = (FRotationMatrix(ReplicatedBasedMovement.Rotation) * FQuatRotationMatrix(CharacterMovement->OldBaseQuat)).Rotator(); // TODO: need a better way to not assume we only use Yaw. NewRotation.Pitch = 0.f; NewRotation.Roll = 0.f; SetActorLocationAndRotation(NewLocation, NewRotation); } else { // Relative location, absolute rotation SetActorLocationAndRotation(NewLocation, ReplicatedBasedMovement.Rotation); } // When position or base changes, movement mode will need to be updated. This assumes rotation changes don't affect that. CharacterMovement->bJustTeleported |= (bBaseChanged || GetActorLocation() != OldLocation); INetworkPredictionInterface* PredictionInterface = Cast<INetworkPredictionInterface>(GetMovementComponent()); if (PredictionInterface) { PredictionInterface->SmoothCorrection(OldLocation, OldRotation); } } }
FMatrix FEditorModeTools::GetCustomDrawingCoordinateSystem() { FMatrix Matrix = FMatrix::Identity; switch (GetCoordSystem()) { case COORD_Local: { // Let the current mode have a shot at setting the local coordinate system. // If it doesn't want to, create it by looking at the currently selected actors list. bool CustomCoordinateSystemProvided = false; for (const auto& Mode : Modes) { if (Mode->GetCustomDrawingCoordinateSystem(Matrix, nullptr)) { CustomCoordinateSystemProvided = true; break; } } if (!CustomCoordinateSystemProvided) { const int32 Num = GetSelectedActors()->CountSelections<AActor>(); // Coordinate system needs to come from the last actor selected if (Num > 0) { Matrix = FQuatRotationMatrix(GetSelectedActors()->GetBottom<AActor>()->GetActorQuat()); } } if (!Matrix.Equals(FMatrix::Identity)) { Matrix.RemoveScaling(); } } break; case COORD_World: break; default: break; } return Matrix; }
bool FEdModeGeometry::GetCustomDrawingCoordinateSystem( FMatrix& InMatrix, void* InData ) { if( GetSelectionState() == GSS_None ) { return 0; } if( InData ) { FGeomBase* GeomBase = static_cast<FGeomBase*>(InData); FGeomObjectPtr GeomObject = GeomBase->GetParentObject(); check(GeomObject.IsValid()); ABrush* Brush = GeomObject->GetActualBrush(); InMatrix = FRotationMatrix(GeomBase->GetNormal().Rotation()) * FQuatRotationMatrix(Brush->GetActorQuat()); } else { // If we don't have a specific geometry object to get the normal from // use the one that was last selected. for( int32 o = 0 ; o < GeomObjects.Num() ; ++o ) { FGeomObjectPtr go = GeomObjects[o]; go->CompileSelectionOrder(); if( go->SelectionOrder.Num() ) { FGeomBase* GeomBase = go->SelectionOrder[go->SelectionOrder.Num() - 1]; check(GeomBase != nullptr); FGeomObjectPtr GeomObject = GeomBase->GetParentObject(); check(GeomObject.IsValid()); ABrush* Brush = GeomObject->GetActualBrush(); InMatrix = FRotationMatrix( go->SelectionOrder[ go->SelectionOrder.Num()-1 ]->GetWidgetRotation() ) * FQuatRotationMatrix(Brush->GetActorQuat()); return 1; } } } return 0; }
void UParticleModuleVelocityCone::Render3DPreview(FParticleEmitterInstance* Owner, const FSceneView* View,FPrimitiveDrawInterface* PDI) { #if WITH_EDITOR float ConeMaxAngle = 0.0f; float ConeMinAngle = 0.0f; Angle.GetOutRange(ConeMinAngle, ConeMaxAngle); float ConeMaxVelocity = 0.0f; float ConeMinVelocity = 0.0f; Velocity.GetOutRange(ConeMinVelocity, ConeMaxVelocity); float MaxLifetime = 0.0f; TArray<UParticleModule*>& Modules = Owner->SpriteTemplate->GetCurrentLODLevel(Owner)->Modules; for (int32 ModuleIndex = 0; ModuleIndex < Modules.Num(); ModuleIndex++) { UParticleModuleLifetimeBase* LifetimeMod = Cast<UParticleModuleLifetimeBase>(Modules[ModuleIndex]); if (LifetimeMod != NULL) { MaxLifetime = LifetimeMod->GetMaxLifetime(); break; } } const int32 ConeSides = 16; const float ConeRadius = ConeMaxVelocity * MaxLifetime; // Calculate direction transform const FVector DefaultDirection(0.0f, 0.0f, 1.0f); const FVector ForwardDirection = (Direction != FVector::ZeroVector)? Direction.GetSafeNormal(): DefaultDirection; FVector UpDirection(0.0f, 0.0f, 1.0f); FVector RightDirection(1.0f, 0.0f, 0.0f); if ((ForwardDirection != UpDirection) && (-ForwardDirection != UpDirection)) { RightDirection = UpDirection ^ ForwardDirection; UpDirection = ForwardDirection ^ RightDirection; } else { UpDirection = ForwardDirection ^ RightDirection; RightDirection = UpDirection ^ ForwardDirection; } FMatrix DirectionRotation; DirectionRotation.SetIdentity(); DirectionRotation.SetAxis(0, RightDirection.GetSafeNormal()); DirectionRotation.SetAxis(1, UpDirection.GetSafeNormal()); DirectionRotation.SetAxis(2, ForwardDirection); // Calculate the owning actor's scale and rotation UParticleLODLevel* LODLevel = Owner->SpriteTemplate->GetCurrentLODLevel(Owner); check(LODLevel); FVector OwnerScale(1.0f); FMatrix OwnerRotation(FMatrix::Identity); FVector LocalToWorldOrigin(0.0f); FMatrix LocalToWorld(FMatrix::Identity); if (Owner->Component) { AActor* Actor = Owner->Component->GetOwner(); if (Actor) { if (bApplyOwnerScale == true) { OwnerScale = Owner->Component->ComponentToWorld.GetScale3D(); } OwnerRotation = FQuatRotationMatrix(Actor->GetActorQuat()); } LocalToWorldOrigin = Owner->Component->ComponentToWorld.GetLocation(); LocalToWorld = Owner->Component->ComponentToWorld.ToMatrixWithScale().RemoveTranslation(); LocalToWorld.RemoveScaling(); } FMatrix Transform; Transform.SetIdentity(); // DrawWireCone() draws a cone down the X axis, but this cone's default direction is down Z const FRotationMatrix XToZRotation(FRotator((int32)(HALF_PI * 10430), 0, 0)); Transform *= XToZRotation; // Apply scale Transform.SetAxis(0, Transform.GetScaledAxis( EAxis::X ) * OwnerScale.X); Transform.SetAxis(1, Transform.GetScaledAxis( EAxis::Y ) * OwnerScale.Y); Transform.SetAxis(2, Transform.GetScaledAxis( EAxis::Z ) * OwnerScale.Z); // Apply direction transform Transform *= DirectionRotation; // Transform according to world and local space flags if (!LODLevel->RequiredModule->bUseLocalSpace && !bInWorldSpace) { Transform *= LocalToWorld; } else if (LODLevel->RequiredModule->bUseLocalSpace && bInWorldSpace) { Transform *= OwnerRotation; Transform *= LocalToWorld.InverseFast(); } else if (!bInWorldSpace) { Transform *= OwnerRotation; } // Apply translation Transform.SetOrigin(LocalToWorldOrigin); TArray<FVector> OuterVerts; TArray<FVector> InnerVerts; // Draw inner and outer cones DrawWireCone(PDI, InnerVerts, Transform, ConeRadius, ConeMinAngle, ConeSides, ModuleEditorColor, SDPG_World); DrawWireCone(PDI, OuterVerts, Transform, ConeRadius, ConeMaxAngle, ConeSides, ModuleEditorColor, SDPG_World); // Draw radial spokes for (int32 i = 0; i < ConeSides; ++i) { PDI->DrawLine( OuterVerts[i], InnerVerts[i], ModuleEditorColor, SDPG_World ); } #endif }