Example #1
0
void UUserWidget::RemoveFromParent()
{
	if ( FullScreenWidget.IsValid() )
	{
		TSharedPtr<SWidget> WidgetHost = FullScreenWidget.Pin();

		// If this is a game world add the widget to the current worlds viewport.
		UWorld* World = GetWorld();
		if ( World && World->IsGameWorld() )
		{
			if ( UGameViewportClient* ViewportClient = World->GetGameViewport() )
			{
				TSharedRef<SWidget> WidgetHostRef = WidgetHost.ToSharedRef();

				ViewportClient->RemoveViewportWidgetContent(WidgetHostRef);

				if ( ULocalPlayer* LocalPlayer = GetOwningLocalPlayer() )
				{
					ViewportClient->RemoveViewportWidgetForPlayer(LocalPlayer, WidgetHostRef);
				}

				FWorldDelegates::LevelRemovedFromWorld.RemoveAll(this);
			}
		}
	}
	else
	{
		Super::RemoveFromParent();
	}
}
void AGameplayDebuggingReplicator::TickActor(float DeltaTime, enum ELevelTick TickType, FActorTickFunction& ThisTickFunction)
{
	Super::TickActor(DeltaTime, TickType, ThisTickFunction);

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	UWorld* World = GetWorld();
	if (!IsGlobalInWorld() || !World || GetNetMode() == ENetMode::NM_Client || !IGameplayDebugger::IsAvailable())
	{
		// global level replicator don't have any local player and it's prepared to work only on servers
		return;
	}

	UGameInstance* GameInstance = World->GetGameInstance();
	if (!GameInstance || !World->IsGameWorld())
	{
		return;
	}

	PlayerControllersUpdateDelay -= DeltaTime;
	if (PlayerControllersUpdateDelay <= 0)
	{
		for (FConstPlayerControllerIterator Iterator = World->GetPlayerControllerIterator(); Iterator; Iterator++)
		{
			APlayerController* PC = *Iterator;
			if (PC)
			{
				IGameplayDebugger& Debugger = IGameplayDebugger::Get();
				Debugger.CreateGameplayDebuggerForPlayerController(PC);
			}
		}
		PlayerControllersUpdateDelay = 5;
	}
#endif
}
void ACullDistanceVolume::Destroyed()
{
	Super::Destroyed();

	UWorld* World = GetWorld();
	if (GIsEditor && World && World->IsGameWorld())
	{
		World->bDoDelayedUpdateCullDistanceVolumes = true;
	}
}
void UWidgetLayoutLibrary::RemoveAllWidgets(UObject* WorldContextObject)
{
	UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject);
	if ( World && World->IsGameWorld() )
	{
		if ( UGameViewportClient* ViewportClient = World->GetGameViewport() )
		{
			ViewportClient->RemoveAllViewportWidgets();
		}
	}
}
Example #5
0
void UUserWidget::AddToScreen(ULocalPlayer* Player, int32 ZOrder)
{
	if ( !FullScreenWidget.IsValid() )
	{
		// First create and initialize the variable so that users calling this function twice don't
		// attempt to add the widget to the viewport again.
		TSharedRef<SConstraintCanvas> FullScreenCanvas = SNew(SConstraintCanvas);
		FullScreenWidget = FullScreenCanvas;

		TSharedRef<SWidget> UserSlateWidget = TakeWidget();

		FullScreenCanvas->AddSlot()
			.Offset(BIND_UOBJECT_ATTRIBUTE(FMargin, GetFullScreenOffset))
			.Anchors(BIND_UOBJECT_ATTRIBUTE(FAnchors, GetViewportAnchors))
			.Alignment(BIND_UOBJECT_ATTRIBUTE(FVector2D, GetFullScreenAlignment))
			[
				UserSlateWidget
			];

		// If this is a game world add the widget to the current worlds viewport.
		UWorld* World = GetWorld();
		if ( World && World->IsGameWorld() )
		{
			if ( UGameViewportClient* ViewportClient = World->GetGameViewport() )
			{
				if ( Player )
				{
					ViewportClient->AddViewportWidgetForPlayer(Player, FullScreenCanvas, ZOrder);
				}
				else
				{
					// We add 10 to the zorder when adding to the viewport to avoid 
					// displaying below any built-in controls, like the virtual joysticks on mobile builds.
					ViewportClient->AddViewportWidgetContent(FullScreenCanvas, ZOrder + 10);
				}

				// Just in case we already hooked this delegate, remove the handler.
				FWorldDelegates::LevelRemovedFromWorld.RemoveAll(this);

				// Widgets added to the viewport are automatically removed if the persistent level is unloaded.
				FWorldDelegates::LevelRemovedFromWorld.AddUObject(this, &UUserWidget::OnLevelRemovedFromWorld);
			}
		}
	}
	else
	{
		FMessageLog("PIE").Warning(FText::Format(LOCTEXT("WidgetAlreadyOnScreen", "The widget '{0}' was already added to the screen."),
			FText::FromString(GetClass()->GetName())));
	}
}
FVector2D UWidgetLayoutLibrary::GetViewportSize(UObject* WorldContextObject)
{
	UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject);
	if ( World && World->IsGameWorld() )
	{
		if ( UGameViewportClient* ViewportClient = World->GetGameViewport() )
		{
			FVector2D ViewportSize;
			ViewportClient->GetViewportSize(ViewportSize);
			return ViewportSize;
		}
	}

	return FVector2D(1, 1);
}
float UWidgetLayoutLibrary::GetViewportScale(UObject* WorldContextObject)
{
	UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject);
	if ( World && World->IsGameWorld() )
	{
		if ( UGameViewportClient* ViewportClient = World->GetGameViewport() )
		{
			FVector2D ViewportSize;
			ViewportClient->GetViewportSize(ViewportSize);
			return GetDefault<UUserInterfaceSettings>()->GetDPIScaleBasedOnSize(FIntPoint(ViewportSize.X, ViewportSize.Y));
		}
	}

	return 1;
}
void UTKMathFunctionLibrary::ConvertAnchorToAnchor(UObject* WorldContextObject, FAnchors CurrentAnchor, FMargin Offsets, FAnchors TargetAnchor, FMargin& ConvertedOffsets)
{
	if (CurrentAnchor.Minimum == TargetAnchor.Minimum && CurrentAnchor.Maximum == TargetAnchor.Maximum)
	{
		ConvertedOffsets = Offsets;
		return;
	}

	FVector2D View = FVector2D(1, 1);
	UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject);
	if (World && World->IsGameWorld())
	{
		if (UGameViewportClient* ViewportClient = World->GetGameViewport())
		{
			ViewportClient->GetViewportSize(View);
		}
	}

	FMargin ZeroAnchorOffsets = Offsets;
	//Convert to 0,0 anchor first.
	if (CurrentAnchor.Minimum != FVector2D(0, 0) || CurrentAnchor.Maximum != FVector2D(0, 0))
	{
		ZeroAnchorOffsets.Left = View.X * CurrentAnchor.Minimum.X + Offsets.Left;
		ZeroAnchorOffsets.Top = View.Y * CurrentAnchor.Minimum.Y + Offsets.Top;

		if (CurrentAnchor.Minimum.X != CurrentAnchor.Maximum.X)
		{
			ZeroAnchorOffsets.Right = View.X * CurrentAnchor.Maximum.X - (Offsets.Right + Offsets.Left);
		}
		if (CurrentAnchor.Minimum.Y != CurrentAnchor.Maximum.Y)
		{
			ZeroAnchorOffsets.Bottom = View.Y * CurrentAnchor.Maximum.Y - (Offsets.Bottom + Offsets.Top);
		}

		if (TargetAnchor.Minimum == FVector2D(0, 0) && TargetAnchor.Maximum == FVector2D(0, 0))
		{
			ConvertedOffsets = ZeroAnchorOffsets;
			return;
		}
	}

	//Convert 0,0 anchor offsets to target anchor offsets.
	ConvertedOffsets.Left = (-View.X) * TargetAnchor.Minimum.X + ZeroAnchorOffsets.Left;
	ConvertedOffsets.Top = (-View.Y) * TargetAnchor.Minimum.Y + ZeroAnchorOffsets.Top;

	ConvertedOffsets.Right = TargetAnchor.Minimum.X != TargetAnchor.Maximum.X ? View.X * TargetAnchor.Maximum.X - (ZeroAnchorOffsets.Left + ZeroAnchorOffsets.Right) : ZeroAnchorOffsets.Right;
	ConvertedOffsets.Bottom = TargetAnchor.Minimum.Y != TargetAnchor.Maximum.Y ? View.Y * TargetAnchor.Maximum.Y - (ZeroAnchorOffsets.Top + ZeroAnchorOffsets.Bottom) : ZeroAnchorOffsets.Bottom;
}
void FGameplayDebugger::OnLevelActorAdded(AActor* InActor)
{
	// This function doesn't help much, because it's only called in EDITOR!
	// We need a function that is called in the game!  So instead of creating it automatically, I'm leaving it
	// to be created explicitly by any player controller that needs to create it.
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	APlayerController* PC = Cast<APlayerController>(InActor);
	if (PC && PC->GetNetMode() < ENetMode::NM_Client)
	{
		UWorld* PCWorld = PC->GetWorld();
		if (PCWorld && PCWorld->IsGameWorld())
		{
			CreateGameplayDebuggerForPlayerController(PC);
		}
	}
#endif
}
Example #10
0
bool ULevelStreaming::IsStreamingStatePending() const
{
	UWorld* PersistentWorld = GetWorld();
	if (PersistentWorld)
	{
		if (IsLevelLoaded() == ShouldBeLoaded() && IsLevelVisible() == ShouldBeVisible())
		{
			FName DesiredPackageName = PersistentWorld->IsGameWorld() ? GetLODPackageName() : GetWorldAssetPackageFName();
			if (!LoadedLevel || LoadedLevel->GetOutermost()->GetFName() == DesiredPackageName)
			{
				return false;
			}
		}
		
		return true;
	}
	
	return false;
}
bool UWorldComposition::UpdateEditorStreamingState(const FVector& InLocation)
{
	UWorld* OwningWorld = GetWorld();
	bool bStateChanged = false;
	
	// Handle only editor worlds
	if (!OwningWorld->IsGameWorld() && 
		!OwningWorld->IsVisibilityRequestPending())
	{
		// Get the list of visible and hidden levels from current view point
		TArray<FDistanceVisibleLevel> DistanceVisibleLevels;
		TArray<FDistanceVisibleLevel> DistanceHiddenLevels;
		GetDistanceVisibleLevels(InLocation, DistanceVisibleLevels, DistanceHiddenLevels);

		// Hidden levels
		for (const auto& Level : DistanceHiddenLevels)
		{
			ULevelStreaming* EditorStreamingLevel = OwningWorld->GetLevelStreamingForPackageName(TilesStreaming[Level.TileIdx]->GetWorldAssetPackageFName());
			if (EditorStreamingLevel && 
				EditorStreamingLevel->IsLevelLoaded() &&
				EditorStreamingLevel->bShouldBeVisibleInEditor != false)
			{
				EditorStreamingLevel->bShouldBeVisibleInEditor = false;
				bStateChanged = true;
			}
		}

		// Visible levels
		for (const auto& Level : DistanceVisibleLevels)
		{
			ULevelStreaming* EditorStreamingLevel = OwningWorld->GetLevelStreamingForPackageName(TilesStreaming[Level.TileIdx]->GetWorldAssetPackageFName());
			if (EditorStreamingLevel &&
				EditorStreamingLevel->IsLevelLoaded() &&
				EditorStreamingLevel->bShouldBeVisibleInEditor != true)
			{
				EditorStreamingLevel->bShouldBeVisibleInEditor = true;
				bStateChanged = true;
			}
		}
	}

	return bStateChanged;
}
Example #12
0
void UUserWidget::AddToViewport(int32 ZOrder)
{
	if ( !FullScreenWidget.IsValid() )
	{
		TSharedPtr<SWidget> OutUserSlateWidget;
		TSharedRef<SWidget> RootWidget = MakeViewportWidget(OutUserSlateWidget);

		FullScreenWidget = RootWidget;

		// If this is a game world add the widget to the current worlds viewport.
		UWorld* World = GetWorld();
		if ( World && World->IsGameWorld() )
		{
			if ( UGameViewportClient* ViewportClient = World->GetGameViewport() )
			{
				ViewportClient->AddViewportWidgetContent(RootWidget, 10 + ZOrder);
			}
		}
	}
}
void USocketIOClientComponent::Connect(const FString& InAddressAndPort, USIOJsonObject* Query /*= nullptr*/, USIOJsonObject* Headers /*= nullptr*/)
{
	//Check if we're limiting this component
	if(bLimitConnectionToGameWorld)
	{ 
		UWorld* World = GEngine->GetWorldFromContextObject(this, EGetWorldErrorMode::LogAndReturnNull);
		if (World)
		{
			bool bIsGameWorld = (World->IsGameWorld() || World->IsPreviewWorld());
			if(!bIsGameWorld)
			{
				UE_LOG(SocketIOLog, Log, TEXT("USocketIOClientComponent::Connect attempt in non-game world blocked by bLimitConnectionToGameWorld."));
				return;
			}
		}
		else
		{
			UE_LOG(SocketIOLog, Warning, TEXT("USocketIOClientComponent::Connect attempt while in invalid world."));
			return;
		}
	}
	TSharedPtr<FJsonObject> QueryFJson;
	TSharedPtr<FJsonObject> HeadersFJson;

	if (Query != nullptr)
	{
		QueryFJson = Query->GetRootObject();
	}

	if (Headers != nullptr)
	{
		HeadersFJson = Headers->GetRootObject();
	}

	//Ensure we sync our native max/reconnection attempts before connecting
	NativeClient->MaxReconnectionAttempts = MaxReconnectionAttempts;
	NativeClient->ReconnectionDelay = ReconnectionDelayInMs;
	NativeClient->VerboseLog = bVerboseConnectionLog;
	
	ConnectNative(InAddressAndPort, QueryFJson, HeadersFJson);
}
Example #14
0
void UUserWidget::RemoveFromParent()
{
	if ( FullScreenWidget.IsValid() )
	{
		TSharedPtr<SWidget> WidgetHost = FullScreenWidget.Pin();

		// If this is a game world add the widget to the current worlds viewport.
		UWorld* World = GetWorld();
		if ( World && World->IsGameWorld() )
		{
			if ( UGameViewportClient* ViewportClient = World->GetGameViewport() )
			{
				ViewportClient->RemoveViewportWidgetContent(WidgetHost.ToSharedRef());
			}
		}
	}
	else
	{
		Super::RemoveFromParent();
	}
}
void USlateBlueprintLibrary::AbsoluteToViewport(UObject* WorldContextObject, const FGeometry& Geometry, FVector2D AbsoluteCoordinate, FVector2D& ScreenPosition, FVector2D& ViewportPosition)
{
	UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject);
	if ( World && World->IsGameWorld() )
	{
		if ( UGameViewportClient* ViewportClient = World->GetGameViewport() )
		{
			if ( FViewport* Viewport = ViewportClient->Viewport )
			{
				FVector2D ViewportSize;
				ViewportClient->GetViewportSize(ViewportSize);

				FVector2D PixelLocation = Viewport->VirtualDesktopPixelToViewport(FIntPoint((int32)AbsoluteCoordinate.X, (int32)AbsoluteCoordinate.Y)) * ViewportSize;

				float CurrentViewportScale = GetDefault<UUserInterfaceSettings>()->GetDPIScaleBasedOnSize(FIntPoint(ViewportSize.X, ViewportSize.Y));

				// If the user has configured a resolution quality we need to multiply
				// the pixels by the resolution quality to arrive at the true position in
				// the viewport, as the rendered image will be stretched to fill whatever
				// size the viewport is at.
				Scalability::FQualityLevels ScalabilityQuality = Scalability::GetQualityLevels();
				const float QualityScale = ( ScalabilityQuality.ResolutionQuality / 100.0f );

				// Remove the resolution quality scale.
				ScreenPosition = PixelLocation * QualityScale;

				// Remove DPI Scaling.
				ViewportPosition = PixelLocation / CurrentViewportScale;

				return;
			}
		}
	}

	ScreenPosition = FVector2D(0, 0);
	ViewportPosition = FVector2D(0, 0);
}
Example #16
0
void AGameState::PostInitializeComponents()
{
	Super::PostInitializeComponents();

	FTimerManager& TimerManager = GetWorldTimerManager();
	TimerManager.SetTimer(TimerHandle_DefaultTimer, this, &AGameState::DefaultTimer, 1.0f / GetWorldSettings()->GetEffectiveTimeDilation(), true);

	UWorld* World = GetWorld();
	World->GameState = this;

	if (World->IsGameWorld() && Role == ROLE_Authority)
	{
		UpdateServerTimeSeconds();
		if (ServerWorldTimeSecondsUpdateFrequency > 0.f)
		{
			TimerManager.SetTimer(TimerHandle_UpdateServerTimeSeconds, this, &AGameState::UpdateServerTimeSeconds, ServerWorldTimeSecondsUpdateFrequency, true);
		}
	}

	for (TActorIterator<APlayerState> It(World); It; ++It)
	{
		AddPlayerState(*It);
	}
}
void AGameplayDebuggerReplicator::TickActor(float DeltaTime, enum ELevelTick TickType, FActorTickFunction& ThisTickFunction)
{
	Super::TickActor(DeltaTime, TickType, ThisTickFunction);

#if ENABLED_GAMEPLAY_DEBUGGER
	UWorld* World = GetWorld();
	const ENetMode NetMode = GetNetMode();
	if (!World)
	{
		// return without world
		return;
	}

	UGameInstance* GameInstance = World->GetGameInstance();
	if (!GameInstance || !World->IsGameWorld())
	{
		return;
	}

	if (NetMode != NM_DedicatedServer)
	{
		if (bActivationKeyPressed)
		{
			ActivationKeyTime += DeltaTime;
			if (ActivationKeyTime >= GameplayDebuggerHelpers::ActivationKeyTimePch)
			{
				GEngine->bEnableOnScreenDebugMessages = false;
				if (AHUD* const GameHUD = LocalPlayerOwner ? LocalPlayerOwner->GetHUD() : nullptr)
				{
					GameHUD->bShowHUD = false;
				}
				BindKeyboardInput(InputComponent);

				ServerActivateGameplayDebugger(true);
				ClientActivateGameplayDebugger(true);
				bActivationKeyPressed = false;
			}
		}

		if (bEnabledTargetSelection)
		{
			if (GetLocalPlayerOwner())
			{
				SelectTargetToDebug();
			}
		}

		bool bMarkComponentsAsRenderStateDirty = false;
		for (UGameplayDebuggerBaseObject* Obj : ReplicatedObjects)
		{
			if (Obj && Obj->IsRenderStateDirty())
			{
				if (!bMarkComponentsAsRenderStateDirty)
				{
					MarkComponentsRenderStateDirty();
				}
				bMarkComponentsAsRenderStateDirty = true;
				Obj->CleanRenderStateDirtyFlag();
			}
		}
	}

	if (NetMode < NM_Client && LocalPlayerOwner)
	{
		TMap<FString, TArray<UGameplayDebuggerBaseObject*> > CategoryToClasses;
		for (UGameplayDebuggerBaseObject* Obj : ReplicatedObjects)
		{
			if (Obj)
			{
				FString Category = Obj->GetCategoryName();
				if (IsCategoryEnabled(Category))
				{
					CategoryToClasses.FindOrAdd(Category).Add(Obj);
				}
			}
		}

		for (auto It(CategoryToClasses.CreateIterator()); It; ++It)
		{
			TArray<UGameplayDebuggerBaseObject*>& CurrentObjects = It.Value();
			for (UGameplayDebuggerBaseObject* Obj : CurrentObjects)
			{
				Obj->CollectDataToReplicateOnServer(LocalPlayerOwner, LastSelectedActorToDebug);
			}
		}
	}

#endif
}
Example #18
0
FReply FSceneViewport::OnMouseButtonDown( const FGeometry& InGeometry, const FPointerEvent& InMouseEvent )
{
	// Start a new reply state
	// Prevent throttling when interacting with the viewport so we can move around in it
	CurrentReplyState = FReply::Handled().PreventThrottling();

	KeyStateMap.Add(InMouseEvent.GetEffectingButton(), true);
	UpdateModifierKeys( InMouseEvent );
	UpdateCachedMousePos( InGeometry, InMouseEvent );
	UpdateCachedGeometry(InGeometry);

	// Switch to the viewport clients world before processing input
	FScopedConditionalWorldSwitcher WorldSwitcher( ViewportClient );
	if( ViewportClient && GetSizeXY() != FIntPoint::ZeroValue )
	{
		// If we're obtaining focus, we have to copy the modifier key states prior to processing this mouse button event, as this is the only point at which the mouse down
		// event is processed when focus initially changes and the modifier keys need to be in-place to detect any unique drag-like events.
		if ( !HasFocus() )
		{
			FModifierKeysState KeysState = FSlateApplication::Get().GetModifierKeys();
			ApplyModifierKeys( KeysState );
		}

		// Process the mouse event
		if( !ViewportClient->InputKey( this, 0, InMouseEvent.GetEffectingButton(), IE_Pressed ) )
		{
			CurrentReplyState = FReply::Unhandled(); 
		}

		if (ViewportClient->CaptureMouseOnClick() != EMouseCaptureMode::NoCapture && !ViewportClient->IgnoreInput())
		{
			TSharedRef<SViewport> ViewportWidgetRef = ViewportWidget.Pin().ToSharedRef();

			// Mouse down should focus viewport for keyboard input
			CurrentReplyState.SetKeyboardFocus(ViewportWidgetRef, EKeyboardFocusCause::Mouse);
			
			UWorld* World = ViewportClient->GetWorld();
			if (World && World->IsGameWorld() && World->GetFirstPlayerController())
			{
				CurrentReplyState.CaptureMouse(ViewportWidgetRef);
				CurrentReplyState.LockMouseToWidget(ViewportWidgetRef);

				bool bShouldShowMouseCursor = World->GetFirstPlayerController()->ShouldShowMouseCursor();
				if (ViewportClient->HideCursorDuringCapture() && bShouldShowMouseCursor)
				{
					bCursorHiddenDueToCapture = true;
				}
				if (bCursorHiddenDueToCapture || !bShouldShowMouseCursor)
				{
					CurrentReplyState.UseHighPrecisionMouseMovement(ViewportWidgetRef);
				}
			}
			else
			{
				CurrentReplyState.UseHighPrecisionMouseMovement(ViewportWidgetRef);
			}
		}
	}
	
	// Re-set prevent throttling here as it can get reset when inside of InputKey()
	CurrentReplyState.PreventThrottling();

	return CurrentReplyState;
}
Example #19
0
FReply FSceneViewport::OnMouseButtonDown( const FGeometry& InGeometry, const FPointerEvent& InMouseEvent )
{
	// Start a new reply state
	// Prevent throttling when interacting with the viewport so we can move around in it
	CurrentReplyState = FReply::Handled().PreventThrottling();

	KeyStateMap.Add(InMouseEvent.GetEffectingButton(), true);
	UpdateModifierKeys( InMouseEvent );
	UpdateCachedMousePos( InGeometry, InMouseEvent );
	UpdateCachedGeometry(InGeometry);

	// Switch to the viewport clients world before processing input
	FScopedConditionalWorldSwitcher WorldSwitcher( ViewportClient );
	if( ViewportClient && GetSizeXY() != FIntPoint::ZeroValue )
	{
		// If we're obtaining focus, we have to copy the modifier key states prior to processing this mouse button event, as this is the only point at which the mouse down
		// event is processed when focus initially changes and the modifier keys need to be in-place to detect any unique drag-like events.
		if ( !HasFocus() )
		{
			FModifierKeysState KeysState = FSlateApplication::Get().GetModifierKeys();
			ApplyModifierKeys( KeysState );
		}

		const bool bAnyMenuWasVisible = FSlateApplication::Get().AnyMenusVisible();

		// Process the mouse event
		if (!ViewportClient->InputKey(this, InMouseEvent.GetUserIndex(), InMouseEvent.GetEffectingButton(), IE_Pressed))
		{
			CurrentReplyState = FReply::Unhandled(); 
		}

		// a new menu was opened if there was previously not a menu visible but now there is
		const bool bNewMenuWasOpened = !bAnyMenuWasVisible && FSlateApplication::Get().AnyMenusVisible();

		if (!ViewportClient->IgnoreInput() &&
			!bNewMenuWasOpened && // We should not focus the viewport if a menu was opened as it would close the menu
			( ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CapturePermanently ||
			  ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CaptureDuringMouseDown ||
			  ( ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CaptureDuringRightMouseDown && InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) ) )
		{
			TSharedRef<SViewport> ViewportWidgetRef = ViewportWidget.Pin().ToSharedRef();

			// Mouse down should focus viewport for user input
			CurrentReplyState.SetUserFocus(ViewportWidgetRef, EFocusCause::SetDirectly, true);
			
			UWorld* World = ViewportClient->GetWorld();
			if (World && World->IsGameWorld() && World->GetFirstPlayerController())
			{
				CurrentReplyState.CaptureMouse(ViewportWidgetRef);
				CurrentReplyState.LockMouseToWidget(ViewportWidgetRef);

				bool bShouldShowMouseCursor = World->GetFirstPlayerController()->ShouldShowMouseCursor();
				if (ViewportClient->HideCursorDuringCapture() && bShouldShowMouseCursor)
				{
					bCursorHiddenDueToCapture = true;
					MousePosBeforeHiddenDueToCapture = FIntPoint( InMouseEvent.GetScreenSpacePosition().X, InMouseEvent.GetScreenSpacePosition().Y );
				}
				if (bCursorHiddenDueToCapture || !bShouldShowMouseCursor)
				{
					CurrentReplyState.UseHighPrecisionMouseMovement(ViewportWidgetRef);
				}
			}
			else
			{
				CurrentReplyState.UseHighPrecisionMouseMovement(ViewportWidgetRef);
			}
		}
	}
	
	// Re-set prevent throttling here as it can get reset when inside of InputKey()
	CurrentReplyState.PreventThrottling();

	return CurrentReplyState;
}
void FFoliageInstanceBaseCache::CompactInstanceBaseCache(AInstancedFoliageActor* IFA)
{
	UWorld* World = IFA->GetWorld();
	if (!World || World->IsGameWorld())
	{
		return;
	}

	FFoliageInstanceBaseCache& Cache = IFA->InstanceBaseCache;
	
	TSet<FFoliageInstanceBaseId> BasesInUse;
	for (auto& Pair : IFA->FoliageMeshes)
	{
		for (const auto& Pair : Pair.Value->ComponentHash)
		{
			if (Pair.Key != FFoliageInstanceBaseCache::InvalidBaseId)
			{
				BasesInUse.Add(Pair.Key);
			}
		}
	}
	
	// Look for any removed maps
	TSet<FFoliageInstanceBasePtr> InvalidBasePtrs;
	for (auto& Pair : Cache.InstanceBaseLevelMap)
	{
		const auto& WorldAsset = Pair.Key;
		
		bool bExists = (WorldAsset == World);
		// Check sub-levels
		if (!bExists)
		{
			const FName PackageName = FName(*FPackageName::ObjectPathToPackageName(WorldAsset.ToStringReference().ToString()));
			if (World->WorldComposition)
			{
				bExists = World->WorldComposition->DoesTileExists(PackageName);
			}
			else
			{
				bExists = (World->GetLevelStreamingForPackageName(PackageName) != nullptr);
			}
		}

		if (!bExists)
		{
			InvalidBasePtrs.Append(Pair.Value);
			Cache.InstanceBaseLevelMap.Remove(Pair.Key);
		}
		else
		{
			// Remove dead links
			for (int32 i = Pair.Value.Num()-1; i >= 0; --i)
			{
				// Base needs to be removed if it's not in use by existing instances or component was removed
				if (Pair.Value[i].IsNull() || !BasesInUse.Contains(Cache.GetInstanceBaseId(Pair.Value[i])))
				{
					InvalidBasePtrs.Add(Pair.Value[i]);
					Pair.Value.RemoveAt(i);
				}
			}

			if (Pair.Value.Num() == 0)
			{
				Cache.InstanceBaseLevelMap.Remove(Pair.Key);
			}
		}
	}
	
	TSet<FFoliageInstanceBaseId> InvalidBaseIds;
	Cache.InstanceBaseInvMap.Empty();
	// Look for any removed base components
	for (const auto& Pair : Cache.InstanceBaseMap)
	{
		const FFoliageInstanceBaseInfo& BaseInfo = Pair.Value;
		if (InvalidBasePtrs.Contains(BaseInfo.BasePtr))
		{
			InvalidBaseIds.Add(Pair.Key);
			Cache.InstanceBaseMap.Remove(Pair.Key);
		}
		else
		{
			// Regenerate inverse map
			check(!Cache.InstanceBaseInvMap.Contains(BaseInfo.BasePtr));
			Cache.InstanceBaseInvMap.Add(BaseInfo.BasePtr, Pair.Key);
		}
	}

	if (InvalidBaseIds.Num())
	{
		for (auto& Pair : IFA->FoliageMeshes)
		{
			auto& MeshInfo = Pair.Value;
			MeshInfo->ComponentHash.Empty();
			int32 InstanceIdx = 0;
			
			for (FFoliageInstance& Instance : MeshInfo->Instances)
			{
				if (InvalidBaseIds.Contains(Instance.BaseId))
				{
					Instance.BaseId = FFoliageInstanceBaseCache::InvalidBaseId;
				}

				MeshInfo->ComponentHash.FindOrAdd(Instance.BaseId).Add(InstanceIdx);
				InstanceIdx++;
			}
		}

		Cache.InstanceBaseMap.Compact();
		Cache.InstanceBaseLevelMap.Compact();
	}
}
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 (Owner->ActiveParticles == 0 || (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();

	const FTransform& OwnerTM = Owner->Component->GetAsyncComponentToWorld();
	const FVector ParentScale = OwnerTM.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));

	const TArray<FVector>& PlayerLocations = Owner->Component->GetPlayerLocations();
	TArray<float> PlayerLODDistanceFactor = Owner->Component->GetPlayerLODDistanceFactor();	//Make a copy because we need to square it later
	const int32 PlayerCount = PlayerLocations.Num();

	if (World->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)
			{
				// 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(OwnerTM);
						}
						else
						{
							// A frame behind, but shouldn't be an issue...
							BoundingBox = Owner->Component->GetAsyncBounds().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		= OwnerTM.TransformPosition(Location);
			OldLocation		= OwnerTM.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;
			Extent = MeshType->bCollisionsConsiderPartilceSize ? Extent * Size : Extent;
		}
		
		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 ((World->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 = bIgnoreTriggerVolumes && 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		= OwnerTM.TransformVector(Particle.Velocity);
						FVector	BaseVelocity	= OwnerTM.TransformVector(Particle.BaseVelocity);
						BaseVelocity			= BaseVelocity.MirrorByVector(Hit.Normal) * CollisionPayload.UsedDampingFactor;

						Particle.BaseVelocity		= OwnerTM.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		= OwnerTM.InverseTransformPosition(NewLocation);

						if (bApplyPhysics)
						{
							check(IsInGameThread());
							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)
						{
							check(IsInGameThread());
							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 = OwnerTM.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 = OwnerTM.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;
}