void AFP_FirstPersonCharacter::OnFire() { // Play a sound if there is one if (FireSound != NULL) { UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation()); } // try and play a firing animation if specified if(FireAnimation != NULL) { // Get the animation object for the arms mesh UAnimInstance* AnimInstance = Mesh1P->GetAnimInstance(); if(AnimInstance != NULL) { AnimInstance->Montage_Play(FireAnimation, 1.f); } } // Now send a trace from the end of our gun to see if we should hit anything APlayerController* PlayerController = Cast<APlayerController>(GetController()); // Calculate the direction of fire and the start location for trace FVector CamLoc; FRotator CamRot; PlayerController->GetPlayerViewPoint(CamLoc, CamRot); const FVector ShootDir = CamRot.Vector(); FVector StartTrace = FVector::ZeroVector; if (PlayerController) { FRotator UnusedRot; PlayerController->GetPlayerViewPoint(StartTrace, UnusedRot); // Adjust trace so there is nothing blocking the ray between the camera and the pawn, and calculate distance from adjusted start StartTrace = StartTrace + ShootDir * ((GetActorLocation() - StartTrace) | ShootDir); } // Calculate endpoint of trace const FVector EndTrace = StartTrace + ShootDir * WeaponRange; // Check for impact const FHitResult Impact = WeaponTrace(StartTrace, EndTrace); // Deal with impact AActor* DamagedActor = Impact.GetActor(); UPrimitiveComponent* DamagedComponent = Impact.GetComponent(); // If we hit an actor, with a component that is simulating physics, apply an impulse if ((DamagedActor != NULL) && (DamagedActor != this) && (DamagedComponent != NULL) && DamagedComponent->IsSimulatingPhysics()) { DamagedComponent->AddImpulseAtLocation(ShootDir*WeaponDamage, Impact.Location); } }
void UCheatManager::TestCollisionDistance() { APlayerController* PC = GetOuterAPlayerController(); if(PC) { // Get view location to act as start point FVector ViewLoc; FRotator ViewRot; PC->GetPlayerViewPoint(ViewLoc, ViewRot); FlushPersistentDebugLines( GetOuterAPlayerController()->GetWorld() );//change the GetWorld // calculate from viewloc for (FObjectIterator Iter(AVolume::StaticClass()); Iter; ++Iter) { AVolume * Volume = Cast<AVolume>(*Iter); if (Volume->GetClass()->GetDefaultObject() != Volume) { FVector ClosestPoint(0,0,0); float Distance = Volume->GetBrushComponent()->GetDistanceToCollision(ViewLoc, ClosestPoint); float NormalizedDistance = FMath::Clamp<float>(Distance, 0.f, 1000.f)/1000.f; FColor DrawColor(255*NormalizedDistance, 255*(1-NormalizedDistance), 0); DrawDebugLine(GetWorld(), ViewLoc, ClosestPoint, DrawColor, true); UE_LOG(LogCheatManager, Log, TEXT("Distance to (%s) is %0.2f"), *Volume->GetName(), Distance); } } } }
void AGameplayAbilityTargetActor_Trace::AimWithPlayerController(const AActor* InSourceActor, FCollisionQueryParams Params, const FVector& TraceStart, FVector& OutTraceEnd, bool bIgnorePitch) const { if (!OwningAbility) // Server and launching client only { return; } APlayerController* PC = OwningAbility->GetCurrentActorInfo()->PlayerController.Get(); check(PC); FVector ViewStart; FRotator ViewRot; PC->GetPlayerViewPoint(ViewStart, ViewRot); const FVector ViewDir = ViewRot.Vector(); FVector ViewEnd = ViewStart + (ViewDir * MaxRange); ClipCameraRayToAbilityRange(ViewStart, ViewDir, TraceStart, MaxRange, ViewEnd); FHitResult HitResult; LineTraceWithFilter(HitResult, InSourceActor->GetWorld(), Filter, ViewStart, ViewEnd, TraceProfile.Name, Params); const bool bUseTraceResult = HitResult.bBlockingHit && (FVector::DistSquared(TraceStart, HitResult.Location) <= (MaxRange * MaxRange)); const FVector AdjustedEnd = (bUseTraceResult) ? HitResult.Location : ViewEnd; FVector AdjustedAimDir = (AdjustedEnd - TraceStart).GetSafeNormal(); if (AdjustedAimDir.IsZero()) { AdjustedAimDir = ViewDir; } if (!bTraceAffectsAimPitch && bUseTraceResult) { FVector OriginalAimDir = (ViewEnd - TraceStart).GetSafeNormal(); if (!OriginalAimDir.IsZero()) { // Convert to angles and use original pitch const FRotator OriginalAimRot = OriginalAimDir.Rotation(); FRotator AdjustedAimRot = AdjustedAimDir.Rotation(); AdjustedAimRot.Pitch = OriginalAimRot.Pitch; AdjustedAimDir = AdjustedAimRot.Vector(); } } OutTraceEnd = TraceStart + (AdjustedAimDir * MaxRange); }
bool ARadiantWebViewActor::TraceScreenPoint(APawn* InPawn, FVector2D& OutUV) { FVector Location; FRotator Rotation; APlayerController *PC = Cast<APlayerController>(InPawn->GetController()); if (PC) { PC->GetPlayerViewPoint(Location, Rotation); } else { InPawn->GetActorEyesViewPoint(Location, Rotation); } const FVector VectorToTarget = Location - GetActorLocation(); const float DistanceToTrace = VectorToTarget.Size() + TraceOversize; const FVector EndTrace = Location + Rotation.Vector()*DistanceToTrace; // Is this actor "pointing" at our surface mesh? static FName TraceTag = FName(TEXT("RadiantGUITrace")); FCollisionQueryParams TraceParams(TraceTag, true, InPawn); // TraceParams.bTraceAsyncScene = true; TraceParams.bReturnFaceIndex = true; FHitResult HitResult; UWorld* const World = GetWorld(); if (World->LineTraceSingleByChannel(HitResult, Location, EndTrace, TraceChannel, TraceParams)) { if (HitResult.Actor.IsValid() && (HitResult.Actor.Get() == this)) { FVector ActorRelativeLocation = ActorToWorld().InverseTransformPosition(HitResult.Location); return GetUVForPoint(HitResult.FaceIndex, ActorRelativeLocation, OutUV); } } return false; }
void UCheatManager::TickCollisionDebug() { // If we are debugging capsule tracing if(bDebugCapsuleSweep) { APlayerController* PC = GetOuterAPlayerController(); if(PC) { // Get view location to act as start point FVector ViewLoc; FRotator ViewRot; PC->GetPlayerViewPoint(ViewLoc, ViewRot); FVector ViewDir = ViewRot.Vector(); FVector End = ViewLoc + (DebugTraceDistance * ViewDir); // Fill in params and do trace static const FName TickCollisionDebugName(TEXT("TickCollisionDebug")); FCollisionQueryParams CapsuleParams(TickCollisionDebugName, false, PC->GetPawn()); CapsuleParams.bTraceComplex = bDebugCapsuleTraceComplex; if (bDebugCapsuleSweep) { // If we get a hit, draw the capsule FHitResult Result; bool bHit = GetWorld()->SweepSingle(Result, ViewLoc, End, FQuat::Identity, DebugTraceChannel, FCollisionShape::MakeCapsule(DebugCapsuleRadius, DebugCapsuleHalfHeight), CapsuleParams); if(bHit) { AddCapsuleSweepDebugInfo(ViewLoc, End, Result.ImpactPoint, Result.Normal, Result.ImpactNormal, Result.Location, DebugCapsuleHalfHeight, DebugCapsuleRadius, false, (Result.bStartPenetrating && Result.bBlockingHit)? true: false); UE_LOG(LogCollision, Log, TEXT("Collision component (%s) : Actor (%s)"), *GetNameSafe(Result.Component.Get()), *GetNameSafe(Result.GetActor())); } } } } // draw for (int32 TraceIdx=0; TraceIdx < DebugTraceInfoList.Num(); ++TraceIdx) { FDebugTraceInfo & TraceInfo = DebugTraceInfoList[TraceIdx]; DrawDebugDirectionalArrow(GetWorld(), TraceInfo.LineTraceStart, TraceInfo.LineTraceEnd, 10.f, FColor::White, SDPG_World); // if it's current trace index, use highlight color if (CurrentTraceIndex == TraceIdx) { if (TraceInfo.bInsideOfObject) { DrawDebugCapsule(GetWorld(), TraceInfo.HitLocation, TraceInfo.CapsuleHalfHeight, TraceInfo.CapsuleRadius, FQuat::Identity, FColor(255,100,64)); } else { DrawDebugCapsule(GetWorld(), TraceInfo.HitLocation, TraceInfo.CapsuleHalfHeight, TraceInfo.CapsuleRadius, FQuat::Identity, FColor(255,200,128)); } } else { if (TraceInfo.bInsideOfObject) { DrawDebugCapsule(GetWorld(), TraceInfo.HitLocation, TraceInfo.CapsuleHalfHeight, TraceInfo.CapsuleRadius, FQuat::Identity, FColor(64,100,255)); } else { DrawDebugCapsule(GetWorld(), TraceInfo.HitLocation, TraceInfo.CapsuleHalfHeight, TraceInfo.CapsuleRadius, FQuat::Identity, FColor(128,200,255)); } } DrawDebugDirectionalArrow(GetWorld(), TraceInfo.HitNormalStart, TraceInfo.HitNormalEnd, 5, FColor(255,64,64), SDPG_World); DrawDebugDirectionalArrow(GetWorld(), TraceInfo.HitNormalStart, TraceInfo.HitImpactNormalEnd, 5, FColor(64,64,255), SDPG_World); } FLinearColor CurrentColor(255.f/255.f,96.f/255.f,96/255.f); FLinearColor DeltaColor = (FLinearColor(1.0f, 1.0f, 1.0f, 1.0f) - CurrentColor)*0.1f; int32 TotalCount=0; if ( DebugTracePawnInfoList.Num() > 0 ) { // the latest will draw very red-ish to whiter color as it gets older. for (int32 TraceIdx=CurrentTracePawnIndex; TotalCount<10; TraceIdx=SAFE_TRACEINDEX_DECREASE(TraceIdx), CurrentColor+=DeltaColor, ++TotalCount) { FDebugTraceInfo & TraceInfo = DebugTracePawnInfoList[TraceIdx]; DrawDebugDirectionalArrow(GetWorld(), TraceInfo.LineTraceStart, TraceInfo.LineTraceEnd, 10.f, FColor(200,200,100), SDPG_World); if (TraceInfo.bInsideOfObject) { DrawDebugCapsule(GetWorld(), TraceInfo.HitLocation, TraceInfo.CapsuleHalfHeight, TraceInfo.CapsuleRadius, FQuat::Identity, FColor(64, 64, 255)); } else { DrawDebugCapsule(GetWorld(), TraceInfo.HitLocation, TraceInfo.CapsuleHalfHeight, TraceInfo.CapsuleRadius, FQuat::Identity, CurrentColor.Quantize()); } DrawDebugDirectionalArrow(GetWorld(), TraceInfo.HitNormalStart, TraceInfo.HitNormalEnd, 5.f, FColor(255,64,64), SDPG_World); } } }
/** * Issues level streaming load/unload requests based on whether * players are inside/outside level streaming volumes. */ void UWorld::ProcessLevelStreamingVolumes(FVector* OverrideViewLocation) { // if we are delaying using streaming volumes, return now if( StreamingVolumeUpdateDelay > 0 ) { StreamingVolumeUpdateDelay--; return; } // Option to skip indefinitely. else if( StreamingVolumeUpdateDelay == INDEX_NONE ) { return; } SCOPE_CYCLE_COUNTER( STAT_VolumeStreamingTickTime ); // Begin by assembling a list of kismet streaming objects that have non-EditorPreVisOnly volumes associated with them. // @todo DB: Cache this, e.g. level startup. TArray<ULevelStreaming*> LevelStreamingObjectsWithVolumes; TMap<ULevelStreaming*,bool> LevelStreamingObjectsWithVolumesOtherThanBlockingLoad; for( int32 LevelIndex = 0 ; LevelIndex < StreamingLevels.Num() ; ++LevelIndex ) { ULevelStreaming* LevelStreamingObject = StreamingLevels[LevelIndex]; if( LevelStreamingObject ) { for ( int32 i = 0 ; i < LevelStreamingObject->EditorStreamingVolumes.Num() ; ++i ) { ALevelStreamingVolume* StreamingVolume = LevelStreamingObject->EditorStreamingVolumes[i]; if( StreamingVolume && !StreamingVolume->bEditorPreVisOnly && !StreamingVolume->bDisabled ) { LevelStreamingObjectsWithVolumes.Add( LevelStreamingObject ); if( StreamingVolume->StreamingUsage != SVB_BlockingOnLoad ) { LevelStreamingObjectsWithVolumesOtherThanBlockingLoad.Add( LevelStreamingObject, true ); } break; } } } } // The set of levels with volumes whose volumes current contain player viewpoints. TMap<ULevelStreaming*,FVisibleLevelStreamingSettings> VisibleLevelStreamingObjects; // Iterate over all players and build a list of level streaming objects with // volumes that contain player viewpoints. bool bStreamingVolumesAreRelevant = false; for( FConstPlayerControllerIterator Iterator = GetPlayerControllerIterator(); Iterator; ++Iterator ) { APlayerController* PlayerActor = *Iterator; if (PlayerActor->bIsUsingStreamingVolumes) { bStreamingVolumesAreRelevant = true; FVector ViewLocation(0,0,0); // let the caller override the location to check for volumes if (OverrideViewLocation) { ViewLocation = *OverrideViewLocation; } else { FRotator ViewRotation(0,0,0); PlayerActor->GetPlayerViewPoint( ViewLocation, ViewRotation ); } TMap<AVolume*,bool> VolumeMap; // Iterate over streaming levels with volumes and compute whether the // player's ViewLocation is in any of their volumes. for( int32 LevelIndex = 0 ; LevelIndex < LevelStreamingObjectsWithVolumes.Num() ; ++LevelIndex ) { ULevelStreaming* LevelStreamingObject = LevelStreamingObjectsWithVolumes[ LevelIndex ]; // StreamingSettings is an OR of all level streaming settings of volumes containing player viewpoints. FVisibleLevelStreamingSettings StreamingSettings; // See if level streaming settings were computed for other players. FVisibleLevelStreamingSettings* ExistingStreamingSettings = VisibleLevelStreamingObjects.Find( LevelStreamingObject ); if ( ExistingStreamingSettings ) { // Stop looking for viewpoint-containing volumes once all streaming settings have been enabled for the level. if ( ExistingStreamingSettings->AllSettingsEnabled() ) { continue; } // Initialize the level's streaming settings with settings that were computed for other players. StreamingSettings = *ExistingStreamingSettings; } // For each streaming volume associated with this level . . . for ( int32 i = 0 ; i < LevelStreamingObject->EditorStreamingVolumes.Num() ; ++i ) { ALevelStreamingVolume* StreamingVolume = LevelStreamingObject->EditorStreamingVolumes[i]; if ( StreamingVolume && !StreamingVolume->bEditorPreVisOnly && !StreamingVolume->bDisabled ) { bool bViewpointInVolume; bool* bResult = VolumeMap.Find(StreamingVolume); if ( bResult ) { // This volume has already been considered for another level. bViewpointInVolume = *bResult; } else { // Compute whether the viewpoint is inside the volume and cache the result. bViewpointInVolume = StreamingVolume->EncompassesPoint( ViewLocation ); VolumeMap.Add( StreamingVolume, bViewpointInVolume ); INC_DWORD_STAT( STAT_VolumeStreamingChecks ); } if ( bViewpointInVolume ) { // Copy off the streaming settings for this volume. StreamingSettings |= FVisibleLevelStreamingSettings( (EStreamingVolumeUsage) StreamingVolume->StreamingUsage ); // Update the streaming settings for the level. // This also marks the level as "should be loaded". VisibleLevelStreamingObjects.Add( LevelStreamingObject, StreamingSettings ); // Stop looking for viewpoint-containing volumes once all streaming settings have been enabled. if ( StreamingSettings.AllSettingsEnabled() ) { break; } } } } } // for each streaming level } // bIsUsingStreamingVolumes } // for each PlayerController // do nothing if no players are using streaming volumes if (bStreamingVolumesAreRelevant) { // Iterate over all streaming levels and set the level's loading status based // on whether it was found to be visible by a level streaming volume. for( int32 LevelIndex = 0 ; LevelIndex < LevelStreamingObjectsWithVolumes.Num() ; ++LevelIndex ) { ULevelStreaming* LevelStreamingObject = LevelStreamingObjectsWithVolumes[LevelIndex]; // Figure out whether level should be loaded and keep track of original state for notifications on change. FVisibleLevelStreamingSettings* NewStreamingSettings= VisibleLevelStreamingObjects.Find( LevelStreamingObject ); bool bShouldAffectLoading = LevelStreamingObjectsWithVolumesOtherThanBlockingLoad.Find( LevelStreamingObject ) != NULL; bool bShouldBeLoaded = (NewStreamingSettings != NULL); bool bOriginalShouldBeLoaded = LevelStreamingObject->bShouldBeLoaded; bool bOriginalShouldBeVisible = LevelStreamingObject->bShouldBeVisible; bool bOriginalShouldBlockOnLoad = LevelStreamingObject->bShouldBlockOnLoad; int32 bOriginalLODIndex = LevelStreamingObject->LevelLODIndex; if( bShouldBeLoaded || bShouldAffectLoading ) { if( bShouldBeLoaded ) { // Loading. LevelStreamingObject->bShouldBeLoaded = true; LevelStreamingObject->bShouldBeVisible = NewStreamingSettings->ShouldBeVisible( bOriginalShouldBeVisible ); LevelStreamingObject->bShouldBlockOnLoad = NewStreamingSettings->ShouldBlockOnLoad(); } // Prevent unload request flood. The additional check ensures that unload requests can still be issued in the first UnloadCooldownTime seconds of play. else if( TimeSeconds - LevelStreamingObject->LastVolumeUnloadRequestTime > LevelStreamingObject->MinTimeBetweenVolumeUnloadRequests || LevelStreamingObject->LastVolumeUnloadRequestTime < 0.1f ) { //UE_LOG(LogLevel, Warning, TEXT("Unloading") ); if( GetPlayerControllerIterator() ) { LevelStreamingObject->LastVolumeUnloadRequestTime = TimeSeconds; LevelStreamingObject->bShouldBeLoaded = false; LevelStreamingObject->bShouldBeVisible = false; } } // Notify players of the change. if( bOriginalShouldBeLoaded != LevelStreamingObject->bShouldBeLoaded || bOriginalShouldBeVisible != LevelStreamingObject->bShouldBeVisible || bOriginalShouldBlockOnLoad != LevelStreamingObject->bShouldBlockOnLoad || bOriginalLODIndex != LevelStreamingObject->LevelLODIndex) { for( FConstPlayerControllerIterator Iterator = GetPlayerControllerIterator(); Iterator; ++Iterator ) { APlayerController* PlayerController = *Iterator; PlayerController->LevelStreamingStatusChanged( LevelStreamingObject, LevelStreamingObject->bShouldBeLoaded, LevelStreamingObject->bShouldBeVisible, LevelStreamingObject->bShouldBlockOnLoad, LevelStreamingObject->LevelLODIndex); } } } } } }
void UParticleModuleCollision::Update(FParticleEmitterInstance* Owner, int32 Offset, float DeltaTime) { SCOPE_CYCLE_COUNTER(STAT_ParticleCollisionTime); check(Owner); check(Owner->Component); UWorld* World = Owner->Component->GetWorld(); if (bDropDetail && World && World->bDropDetail) { return; } //Gets the owning actor of the component. Can be NULL if the component is spawned with the World as an Outer, e.g. in UGameplayStatics::SpawnEmitterAtLocation(). AActor* Actor = Owner->Component->GetOwner(); UParticleLODLevel* LODLevel = Owner->SpriteTemplate->GetCurrentLODLevel(Owner); check(LODLevel); const int32 MeshRotationOffset = Owner->GetMeshRotationOffset(); const bool bMeshRotationActive = Owner->IsMeshRotationActive(); FVector ParentScale = FVector(1.0f, 1.0f, 1.0f); if (Owner->Component) { ParentScale = Owner->Component->ComponentToWorld.GetScale3D(); } FParticleEventInstancePayload* EventPayload = NULL; if (LODLevel->EventGenerator) { EventPayload = (FParticleEventInstancePayload*)(Owner->GetModuleInstanceData(LODLevel->EventGenerator)); if (EventPayload && (EventPayload->bCollisionEventsPresent == false) && (EventPayload->bDeathEventsPresent == false)) { EventPayload = NULL; } } FParticleCollisionInstancePayload* CollisionInstPayload = (FParticleCollisionInstancePayload*)(Owner->GetModuleInstanceData(this)); TArray<FVector> PlayerLocations; TArray<float> PlayerLODDistanceFactor; int32 PlayerCount = 0; if (Owner->GetWorld()->IsGameWorld()) { bool bIgnoreAllCollision = false; // LOD collision based on visibility // This is at the 'emitter instance' level as it will be true or false for the whole instance... if (bCollideOnlyIfVisible && ((World->TimeSeconds - Owner->Component->LastRenderTime) > 0.1f)) { // no collision if not recently rendered bIgnoreAllCollision = true; } else { // If the MaxCollisionDistance is greater than WORLD_MAX, they obviously want the check disabled... if (MaxCollisionDistance < WORLD_MAX) { // Store off the player locations and LOD distance factors for( FConstPlayerControllerIterator Iterator = World->GetPlayerControllerIterator(); Iterator; ++Iterator ) { APlayerController* PlayerController = *Iterator; if (PlayerController->IsLocalPlayerController()) { FVector POVLoc; FRotator POVRotation; PlayerController->GetPlayerViewPoint(POVLoc, POVRotation); PlayerLocations.Add(POVLoc); PlayerLODDistanceFactor.Add(PlayerController->LocalPlayerCachedLODDistanceFactor); } } PlayerCount = PlayerLocations.Num(); // If we have at least a few particles, do a simple check vs. the bounds if (Owner->ActiveParticles > 7) { if (CollisionInstPayload->CurrentLODBoundsCheckCount == 0) { FBox BoundingBox; BoundingBox.Init(); if (Owner->Component->Template && Owner->Component->Template->bUseFixedRelativeBoundingBox) { BoundingBox = Owner->Component->Template->FixedRelativeBoundingBox.TransformBy(Owner->Component->ComponentToWorld); } else { // A frame behind, but shouldn't be an issue... BoundingBox = Owner->Component->Bounds.GetBox(); } // see if any player is within the extended bounds... bIgnoreAllCollision = true; // Check for the system itself beyond beyond the bounds // LOD collision by distance bool bCloseEnough = false; for (int32 PlyrIdx = 0; PlyrIdx < PlayerCount; PlyrIdx++) { // Invert the LOD distance factor here because we are using it to *expand* the // bounds rather than shorten the distance checked as it is usually used for. float InvDistanceFactor = 1.0f / PlayerLODDistanceFactor[PlyrIdx]; FBox CheckBounds = BoundingBox; float BoxExpansionValue = MaxCollisionDistance * InvDistanceFactor; BoxExpansionValue += BoxExpansionValue * 0.075f; // Expand it by the max collision distance (and a little bit extra) CheckBounds = CheckBounds.ExpandBy(BoxExpansionValue); if (CheckBounds.IsInside(PlayerLocations[PlyrIdx])) { // If one is close enough, that's all it takes! bCloseEnough = true; break; } } if (bCloseEnough == true) { bIgnoreAllCollision = false; } } CollisionInstPayload->CurrentLODBoundsCheckCount++; // Every 30 frames recheck the overall bounds... if (CollisionInstPayload->CurrentLODBoundsCheckCount > 30) { CollisionInstPayload->CurrentLODBoundsCheckCount = 0; } } } } if (bIgnoreAllCollision == true) { // Turn off collision on *all* existing particles... // We don't want it to turn back on and have particles // already embedded start performing collision checks. BEGIN_UPDATE_LOOP; { Particle.Flags |= STATE_Particle_IgnoreCollisions; } END_UPDATE_LOOP; return; } // Square the LODDistanceFactor values now, so we don't have to do it // per particle in the update loop below... for (int32 SquareIdx = 0; SquareIdx < PlayerLocations.Num(); SquareIdx++) { PlayerLODDistanceFactor[SquareIdx] *= PlayerLODDistanceFactor[SquareIdx]; } } float SquaredMaxCollisionDistance = FMath::Square(MaxCollisionDistance); BEGIN_UPDATE_LOOP; { if ((Particle.Flags & STATE_Particle_CollisionIgnoreCheck) != 0) { CONTINUE_UPDATE_LOOP; } PARTICLE_ELEMENT(FParticleCollisionPayload, CollisionPayload); if ((Particle.Flags & STATE_Particle_DelayCollisions) != 0) { if (CollisionPayload.Delay > Particle.RelativeTime) { CONTINUE_UPDATE_LOOP; } Particle.Flags &= ~STATE_Particle_DelayCollisions; } FVector Location; FVector OldLocation; // Location won't be calculated till after tick so we need to calculate an intermediate one here. Location = Particle.Location + Particle.Velocity * DeltaTime; if (LODLevel->RequiredModule->bUseLocalSpace) { // Transform the location and old location into world space Location = Owner->Component->ComponentToWorld.TransformPosition(Location); OldLocation = Owner->Component->ComponentToWorld.TransformPosition(Particle.OldLocation); } else { OldLocation = Particle.OldLocation; } FVector Direction = (Location - OldLocation).GetSafeNormal(); // Determine the size FVector Size = Particle.Size * ParentScale; FVector Extent(0.0f); // Setup extent for mesh particles. UParticleModuleTypeDataMesh* MeshType = Cast<UParticleModuleTypeDataMesh>(LODLevel->TypeDataModule); if (MeshType && MeshType->Mesh) { Extent = MeshType->Mesh->GetBounds().BoxExtent; } FHitResult Hit; Hit.Normal.X = 0.0f; Hit.Normal.Y = 0.0f; Hit.Normal.Z = 0.0f; check( Owner->Component ); FVector End = Location + Direction * Size / DirScalar; if ((Owner->GetWorld()->IsGameWorld() == true) && (MaxCollisionDistance < WORLD_MAX)) { // LOD collision by distance bool bCloseEnough = false; for (int32 CheckIdx = 0; CheckIdx < PlayerCount; CheckIdx++) { float CheckValue = (PlayerLocations[CheckIdx] - End).SizeSquared() * PlayerLODDistanceFactor[CheckIdx]; if (CheckValue < SquaredMaxCollisionDistance) { bCloseEnough = true; break; } } if (bCloseEnough == false) { Particle.Flags |= STATE_Particle_IgnoreCollisions; CONTINUE_UPDATE_LOOP; } } AActor* IgnoreActor = bIgnoreSourceActor ? Actor : NULL; if (PerformCollisionCheck(Owner, &Particle, Hit, IgnoreActor, End, OldLocation, Extent)) { bool bDecrementMaxCount = true; bool bIgnoreCollision = false; if (Hit.GetActor()) { bDecrementMaxCount = !bPawnsDoNotDecrementCount || !Cast<APawn>(Hit.GetActor()); bIgnoreCollision = Hit.GetActor()->IsA(ATriggerBase::StaticClass()); //@todo.SAS. Allow for PSys to say what it wants to collide w/? } if (bIgnoreCollision == false) { if (bDecrementMaxCount && (bOnlyVerticalNormalsDecrementCount == true)) { if ((Hit.Normal.IsNearlyZero() == false) && (FMath::Abs(Hit.Normal.Z) + VerticalFudgeFactor) < 1.0f) { //UE_LOG(LogParticles, Log, TEXT("Particle from %s had a non-vertical hit!"), *(Owner->Component->Template->GetPathName())); bDecrementMaxCount = false; } } if (bDecrementMaxCount) { CollisionPayload.UsedCollisions--; } if (CollisionPayload.UsedCollisions > 0) { if (LODLevel->RequiredModule->bUseLocalSpace) { // Transform the particle velocity to world space FVector OldVelocity = Owner->Component->ComponentToWorld.TransformVector(Particle.Velocity); FVector BaseVelocity = Owner->Component->ComponentToWorld.TransformVector(Particle.BaseVelocity); BaseVelocity = BaseVelocity.MirrorByVector(Hit.Normal) * CollisionPayload.UsedDampingFactor; Particle.BaseVelocity = Owner->Component->ComponentToWorld.InverseTransformVector(BaseVelocity); Particle.BaseRotationRate = Particle.BaseRotationRate * CollisionPayload.UsedDampingFactorRotation.X; if (bMeshRotationActive && MeshRotationOffset > 0) { FMeshRotationPayloadData* PayloadData = (FMeshRotationPayloadData*)((uint8*)&Particle + MeshRotationOffset); PayloadData->RotationRateBase *= CollisionPayload.UsedDampingFactorRotation; } // Reset the current velocity and manually adjust location to bounce off based on normal and time of collision. FVector NewVelocity = Direction.MirrorByVector(Hit.Normal) * (Location - OldLocation).Size() * CollisionPayload.UsedDampingFactor; Particle.Velocity = FVector::ZeroVector; // New location FVector NewLocation = Location + NewVelocity * (1.f - Hit.Time); Particle.Location = Owner->Component->ComponentToWorld.InverseTransformPosition(NewLocation); if (bApplyPhysics) { UPrimitiveComponent* PrimitiveComponent = Hit.Component.Get(); if(PrimitiveComponent && PrimitiveComponent->IsAnySimulatingPhysics()) { FVector vImpulse; vImpulse = -(NewVelocity - OldVelocity) * ParticleMass.GetValue(Particle.RelativeTime, Owner->Component); PrimitiveComponent->AddImpulseAtLocation(vImpulse, Hit.Location, Hit.BoneName); } } } else { FVector vOldVelocity = Particle.Velocity; // Reflect base velocity and apply damping factor. Particle.BaseVelocity = Particle.BaseVelocity.MirrorByVector(Hit.Normal) * CollisionPayload.UsedDampingFactor; Particle.BaseRotationRate = Particle.BaseRotationRate * CollisionPayload.UsedDampingFactorRotation.X; if (bMeshRotationActive && MeshRotationOffset > 0) { FMeshRotationPayloadData* PayloadData = (FMeshRotationPayloadData*)((uint8*)&Particle + MeshRotationOffset); PayloadData->RotationRateBase *= CollisionPayload.UsedDampingFactorRotation; } // Reset the current velocity and manually adjust location to bounce off based on normal and time of collision. FVector vNewVelocity = Direction.MirrorByVector(Hit.Normal) * (Location - OldLocation).Size() * CollisionPayload.UsedDampingFactor; Particle.Velocity = FVector::ZeroVector; Particle.Location += vNewVelocity * (1.f - Hit.Time); if (bApplyPhysics) { UPrimitiveComponent* PrimitiveComponent = Hit.Component.Get(); if(PrimitiveComponent && PrimitiveComponent->IsAnySimulatingPhysics()) { FVector vImpulse; vImpulse = -(vNewVelocity - vOldVelocity) * ParticleMass.GetValue(Particle.RelativeTime, Owner->Component); PrimitiveComponent->AddImpulseAtLocation(vImpulse, Hit.Location, Hit.BoneName); } } } if (EventPayload && (EventPayload->bCollisionEventsPresent == true)) { LODLevel->EventGenerator->HandleParticleCollision(Owner, EventPayload, &CollisionPayload, &Hit, &Particle, Direction); } } else { if (LODLevel->RequiredModule->bUseLocalSpace == true) { Size = Owner->Component->ComponentToWorld.TransformVector(Size); } Particle.Location = Hit.Location + (Size / 2.0f); if (LODLevel->RequiredModule->bUseLocalSpace == true) { // We need to transform the location back relative to the PSys. // NOTE: LocalSpace makes sense only for stationary emitters that use collision. Particle.Location = Owner->Component->ComponentToWorld.InverseTransformPosition(Particle.Location); } switch (CollisionCompletionOption) { case EPCC_Kill: { if (EventPayload && (EventPayload->bDeathEventsPresent == true)) { LODLevel->EventGenerator->HandleParticleKilled(Owner, EventPayload, &Particle); } KILL_CURRENT_PARTICLE; } break; case EPCC_Freeze: { Particle.Flags |= STATE_Particle_Freeze; } break; case EPCC_HaltCollisions: { Particle.Flags |= STATE_Particle_IgnoreCollisions; } break; case EPCC_FreezeTranslation: { Particle.Flags |= STATE_Particle_FreezeTranslation; } break; case EPCC_FreezeRotation: { Particle.Flags |= STATE_Particle_FreezeRotation; } break; case EPCC_FreezeMovement: { Particle.Flags |= STATE_Particle_FreezeRotation; Particle.Flags |= STATE_Particle_FreezeTranslation; } break; } if (EventPayload && (EventPayload->bCollisionEventsPresent == true)) { LODLevel->EventGenerator->HandleParticleCollision(Owner, EventPayload, &CollisionPayload, &Hit, &Particle, Direction); } } Particle.Flags |= STATE_Particle_CollisionHasOccurred; } } } END_UPDATE_LOOP; }
/** * Exec handler, parsing the passed in command * * @param InWorld World Context * @param Cmd Command to parse * @param Ar output device used for logging */ bool FDebugToolExec::Exec( UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar ) { // these commands are only allowed in standalone games #if UE_BUILD_SHIPPING || UE_BUILD_TEST if (GEngine->GetNetMode(InWorld) != NM_Standalone || (GEngine->GetWorldContextFromWorldChecked(InWorld).PendingNetGame != NULL)) { return 0; } // Edits the class defaults. else #endif if( FParse::Command(&Cmd,TEXT("EDITDEFAULT")) ) { // not allowed in the editor as this command can have far reaching effects such as impacting serialization if (!GIsEditor) { UClass* Class = NULL; if( ParseObject<UClass>( Cmd, TEXT("CLASS="), Class, ANY_PACKAGE ) == false ) { TCHAR ClassName[256]; if ( FParse::Token(Cmd,ClassName,ARRAY_COUNT(ClassName), 1) ) { Class = FindObject<UClass>( ANY_PACKAGE, ClassName); } } if (Class) { EditObject(Class->GetDefaultObject(), true); } else { Ar.Logf( TEXT("Missing class") ); } } return 1; } else if (FParse::Command(&Cmd,TEXT("EDITOBJECT"))) { UClass* searchClass = NULL; UObject* foundObj = NULL; // Search by class. if (ParseObject<UClass>(Cmd, TEXT("CLASS="), searchClass, ANY_PACKAGE)) { // pick the first valid object for (FObjectIterator It(searchClass); It && foundObj == NULL; ++It) { if (!It->IsPendingKill() && !It->IsTemplate()) { foundObj = *It; } } } // Search by name. else { FName searchName; FString SearchPathName; if ( FParse::Value(Cmd, TEXT("NAME="), searchName) ) { // Look for actor by name. for( TObjectIterator<UObject> It; It && foundObj == NULL; ++It ) { if (It->GetFName() == searchName) { foundObj = *It; } } } else if ( FParse::Token(Cmd,SearchPathName, true) ) { foundObj = FindObject<UObject>(ANY_PACKAGE,*SearchPathName); } } // Bring up an property editing window for the found object. if (foundObj != NULL) { // not allowed in the editor unless it is a PIE object as this command can have far reaching effects such as impacting serialization if (!GIsEditor || ((!foundObj->IsTemplate() && (foundObj->GetOutermost()->PackageFlags & PKG_PlayInEditor)))) { EditObject(foundObj, true); } } else { Ar.Logf(TEXT("Target not found")); } return 1; } else if (FParse::Command(&Cmd,TEXT("EDITARCHETYPE"))) { UObject* foundObj = NULL; // require fully qualified path name FString SearchPathName; if (FParse::Token(Cmd, SearchPathName, true)) { foundObj = FindObject<UObject>(ANY_PACKAGE,*SearchPathName); } // Bring up an property editing window for the found object. if (foundObj != NULL) { // not allowed in the editor unless it is a PIE object as this command can have far reaching effects such as impacting serialization if (!GIsEditor || ((!foundObj->IsTemplate() && (foundObj->GetOutermost()->PackageFlags & PKG_PlayInEditor)))) { EditObject(foundObj, false); } } else { Ar.Logf(TEXT("Target not found")); } return 1; } // Edits an objects properties or copies them to the clipboard. else if( FParse::Command(&Cmd,TEXT("EDITACTOR")) ) { UClass* Class = NULL; AActor* Found = NULL; if (FParse::Command(&Cmd, TEXT("TRACE"))) { APlayerController* PlayerController = InWorld->GetFirstPlayerController(); if (PlayerController != NULL) { // Do a trace in the player's facing direction and edit anything that's hit. FVector PlayerLocation; FRotator PlayerRotation; PlayerController->GetPlayerViewPoint(PlayerLocation, PlayerRotation); FHitResult Hit(1.0f); PlayerController->GetWorld()->LineTraceSingle(Hit, PlayerLocation, PlayerLocation + PlayerRotation.Vector() * 10000.f, ECC_Pawn, FCollisionQueryParams(NAME_None, true, PlayerController->GetPawn())); Found = Hit.GetActor(); } } // Search by class. else if( ParseObject<UClass>( Cmd, TEXT("CLASS="), Class, ANY_PACKAGE ) && Class->IsChildOf(AActor::StaticClass()) ) { UGameEngine* GameEngine = Cast<UGameEngine>(GEngine); // Look for the closest actor of this class to the player. FVector PlayerLocation(0.0f); APlayerController* PlayerController = InWorld->GetFirstPlayerController(); if (PlayerController != NULL) { FRotator DummyRotation; PlayerController->GetPlayerViewPoint(PlayerLocation, DummyRotation); } float MinDist = FLT_MAX; for( TActorIterator<AActor> It(InWorld, Class); It; ++It ) { if ( !It->IsPendingKill() ) { float const Dist = (PlayerController && It->GetRootComponent()) ? FVector::Dist(It->GetActorLocation(), PlayerLocation) : 0.f; if (Dist < MinDist) { MinDist = Dist; Found = *It; } } } } // Search by name. else { FName ActorName; if( FParse::Value( Cmd, TEXT("NAME="), ActorName ) ) { // Look for actor by name. for( FActorIterator It(InWorld); It; ++It ) { if( It->GetFName() == ActorName ) { Found = *It; break; } } } } // Bring up an property editing window for the found object. if( Found ) { // not allowed in the editor unless it is a PIE object as this command can have far reaching effects such as impacting serialization if (!GIsEditor || ((!Found->IsTemplate() && (Found->GetOutermost()->PackageFlags & PKG_PlayInEditor)))) { EditObject(Found, true); } } else { Ar.Logf( TEXT("Target not found") ); } return 1; } else { return 0; } }
void USceneCubemapCapturer::StartCapture(UWorld* World, uint32 InCaptureBoxSideRes, EPixelFormat InFormat) { CaptureBoxSideRes = InCaptureBoxSideRes; CaptureFormat = InFormat; FVector Location = OverriddenLocation; FQuat Orientation= OverriddenOrientation; APlayerController* CapturePlayerController = UGameplayStatics::GetPlayerController(GWorld, 0); if (CapturePlayerController) { FRotator Rotation; CapturePlayerController->GetPlayerViewPoint(Location, Rotation); Rotation.Pitch = Rotation.Roll = 0; Orientation = FQuat(Rotation); Location += CaptureOffset; } if (!OverriddenOrientation.IsIdentity()) { Orientation = OverriddenOrientation; } if (!OverriddenLocation.IsZero()) { Location = OverriddenLocation; } const FVector ZAxis(0, 0, 1); const FVector YAxis(0, 1, 0); const FQuat FaceOrientations[]= { {ZAxis, PI/2}, { ZAxis, -PI/2}, // right, left {YAxis, -PI/2}, { YAxis, PI/2}, // top, bottom {ZAxis, 0}, { ZAxis, -PI} }; // front, back for (int i = 0; i < 6; ++i) { USceneCaptureComponent2D* CaptureComponent = NewObject<USceneCaptureComponent2D>(); CaptureComponent->SetVisibility(true); CaptureComponent->SetHiddenInGame(false); CaptureComponent->CaptureStereoPass = EStereoscopicPass::eSSP_FULL;//LEFT_EYE; //?? CaptureComponent->FOVAngle = 90.f; CaptureComponent->bCaptureEveryFrame = true; CaptureComponent->CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR; const FName TargetName = MakeUniqueObjectName(this, UTextureRenderTarget2D::StaticClass(), TEXT("SceneCaptureTextureTarget")); CaptureComponent->TextureTarget = NewObject<UTextureRenderTarget2D>(this, TargetName); CaptureComponent->TextureTarget->InitCustomFormat(CaptureBoxSideRes, CaptureBoxSideRes, CaptureFormat, false); CaptureComponents.Add(CaptureComponent); CaptureComponent->RegisterComponentWithWorld(GWorld); CaptureComponent->SetWorldLocationAndRotation(Location, Orientation * FaceOrientations[i]); CaptureComponent->UpdateContent(); } Stage = SettingPos; FActorSpawnParameters SpawnInfo; SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; SpawnInfo.bNoFail = true; SpawnInfo.ObjectFlags = RF_Transient; AStaticMeshActor* InGameActor; InGameActor = World->SpawnActor<AStaticMeshActor>(SpawnInfo); OutputDir = FPaths::GameSavedDir() + TEXT("/Cubemaps"); IFileManager::Get().MakeDirectory(*OutputDir); }