Added multi-PIE support to adaptive canvas size:

- Adaptive size is controlled by the ImGui Widget, which passes it from the view-port to the context proxy.
- Context only copies display size that is set from the outside.
- Removed feature dependency from the manager.
This commit is contained in:
Sebastian 2020-04-16 15:35:19 +01:00
parent 62a739ac9f
commit 003eed34d7
5 changed files with 59 additions and 26 deletions

View File

@ -59,9 +59,9 @@ FImGuiContextProxy::FImGuiContextProxy(const FString& InName, int32 InContextInd
// Set session data storage. // Set session data storage.
IO.IniFilename = IniFilename.c_str(); IO.IniFilename = IniFilename.c_str();
// Use pre-defined canvas size. // Start with the default canvas size.
IO.DisplaySize = { DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT }; ResetDisplaySize();
DisplaySize = ImGuiInterops::ToVector2D(IO.DisplaySize); IO.DisplaySize = { DisplaySize.X, DisplaySize.Y };
// Initialize key mapping, so context can correctly interpret input state. // Initialize key mapping, so context can correctly interpret input state.
ImGuiInterops::SetUnrealKeyMap(IO); ImGuiInterops::SetUnrealKeyMap(IO);
@ -84,6 +84,11 @@ FImGuiContextProxy::~FImGuiContextProxy()
} }
} }
void FImGuiContextProxy::ResetDisplaySize()
{
DisplaySize = { DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT };
}
void FImGuiContextProxy::DrawEarlyDebug() void FImGuiContextProxy::DrawEarlyDebug()
{ {
if (bIsFrameStarted && !bIsDrawEarlyDebugCalled) if (bIsFrameStarted && !bIsDrawEarlyDebugCalled)
@ -147,11 +152,6 @@ void FImGuiContextProxy::Tick(float DeltaSeconds)
} }
} }
void FImGuiContextProxy::SetAdaptiveCanvasSize(bool bAdaptive)
{
bAdaptiveCanvasSize = bAdaptive;
}
void FImGuiContextProxy::BeginFrame(float DeltaTime) void FImGuiContextProxy::BeginFrame(float DeltaTime)
{ {
if (!bIsFrameStarted) if (!bIsFrameStarted)
@ -162,16 +162,7 @@ void FImGuiContextProxy::BeginFrame(float DeltaTime)
ImGuiInterops::CopyInput(IO, InputState); ImGuiInterops::CopyInput(IO, InputState);
InputState.ClearUpdateState(); InputState.ClearUpdateState();
if (bAdaptiveCanvasSize) { IO.DisplaySize = { DisplaySize.X, DisplaySize.Y };
if (GEngine && GEngine->GameViewport)
{
GEngine->GameViewport->GetViewportSize(DisplaySize);
IO.DisplaySize = ImVec2(DisplaySize.X, DisplaySize.Y);
}
} else {
IO.DisplaySize = { DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT };
DisplaySize = ImGuiInterops::ToVector2D(IO.DisplaySize);
}
ImGui::NewFrame(); ImGui::NewFrame();

View File

@ -44,9 +44,15 @@ public:
// Set this context as current ImGui context. // Set this context as current ImGui context.
void SetAsCurrent() { ImGui::SetCurrentContext(Context); } void SetAsCurrent() { ImGui::SetCurrentContext(Context); }
// Context display size (read once per frame during context update). // Get the desired context display size.
const FVector2D& GetDisplaySize() const { return DisplaySize; } const FVector2D& GetDisplaySize() const { return DisplaySize; }
// Set the desired context display size.
void SetDisplaySize(const FVector2D& Size) { DisplaySize = Size; }
// Reset the desired context display size to default size.
void ResetDisplaySize();
// Whether this context has an active item (read once per frame during context update). // Whether this context has an active item (read once per frame during context update).
bool HasActiveItem() const { return bHasActiveItem; } bool HasActiveItem() const { return bHasActiveItem; }
@ -68,9 +74,6 @@ public:
// Tick to advance context to the next frame. Only one call per frame will be processed. // Tick to advance context to the next frame. Only one call per frame will be processed.
void Tick(float DeltaSeconds); void Tick(float DeltaSeconds);
// Set the adaptive canvas size configuration.
void SetAdaptiveCanvasSize(bool);
private: private:
void BeginFrame(float DeltaTime = 1.f / 60.f); void BeginFrame(float DeltaTime = 1.f / 60.f);
@ -109,6 +112,4 @@ private:
FSimpleMulticastDelegate* SharedDrawEvent = nullptr; FSimpleMulticastDelegate* SharedDrawEvent = nullptr;
std::string IniFilename; std::string IniFilename;
bool bAdaptiveCanvasSize = false;
}; };

View File

@ -175,7 +175,6 @@ void FImGuiModuleManager::AddWidgetToViewport(UGameViewportClient* GameViewport)
// Make sure that we have a context for this viewport's world and get its index. // Make sure that we have a context for this viewport's world and get its index.
int32 ContextIndex; int32 ContextIndex;
auto& ContextProxy = ContextManager.GetWorldContextProxy(*GameViewport->GetWorld(), ContextIndex); auto& ContextProxy = ContextManager.GetWorldContextProxy(*GameViewport->GetWorld(), ContextIndex);
ContextProxy.SetAdaptiveCanvasSize(Settings.AdaptiveCanvasSize());
// Make sure that textures are loaded before the first Slate widget is created. // Make sure that textures are loaded before the first Slate widget is created.
LoadTextures(); LoadTextures();

View File

@ -84,6 +84,7 @@ void SImGuiWidget::Construct(const FArguments& InArgs)
const auto& Settings = ModuleManager->GetSettings(); const auto& Settings = ModuleManager->GetSettings();
SetHideMouseCursor(Settings.UseSoftwareCursor()); SetHideMouseCursor(Settings.UseSoftwareCursor());
CreateInputHandler(Settings.GetImGuiInputHandlerClass()); CreateInputHandler(Settings.GetImGuiInputHandlerClass());
SetAdaptiveCanvasSize(Settings.AdaptiveCanvasSize());
// Initialize state. // Initialize state.
UpdateVisibility(); UpdateVisibility();
@ -125,6 +126,7 @@ void SImGuiWidget::Tick(const FGeometry& AllottedGeometry, const double InCurren
UpdateInputState(); UpdateInputState();
UpdateTransparentMouseInput(AllottedGeometry); UpdateTransparentMouseInput(AllottedGeometry);
HandleWindowFocusLost(); HandleWindowFocusLost();
UpdateCanvasSize();
} }
FReply SImGuiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) FReply SImGuiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent)
@ -496,9 +498,44 @@ void SImGuiWidget::HandleWindowFocusLost()
} }
} }
void SImGuiWidget::SetAdaptiveCanvasSize(bool bEnabled)
{
if (bAdaptiveCanvasSize != bEnabled)
{
bAdaptiveCanvasSize = bEnabled;
bUpdateCanvasSize = true;
UpdateCanvasSize();
}
}
void SImGuiWidget::UpdateCanvasSize()
{
if (bUpdateCanvasSize)
{
if (auto* ContextProxy = ModuleManager->GetContextManager().GetContextProxy(ContextIndex))
{
if (bAdaptiveCanvasSize)
{
if (GameViewport.IsValid())
{
FVector2D DisplaySize;
GameViewport->GetViewportSize(DisplaySize);
ContextProxy->SetDisplaySize(DisplaySize);
}
}
else
{
ContextProxy->ResetDisplaySize();
// No need for more updates, if we successfully processed fixed-canvas mode.
bUpdateCanvasSize = false;
}
}
}
}
void SImGuiWidget::UpdateCanvasControlMode(const FInputEvent& InputEvent) void SImGuiWidget::UpdateCanvasControlMode(const FInputEvent& InputEvent)
{ {
CanvasControlWidget->SetActive(InputEvent.IsLeftAltDown() && InputEvent.IsLeftShiftDown()); CanvasControlWidget->SetActive(!bAdaptiveCanvasSize && InputEvent.IsLeftAltDown() && InputEvent.IsLeftShiftDown());
} }
void SImGuiWidget::OnPostImGuiUpdate() void SImGuiWidget::OnPostImGuiUpdate()

View File

@ -103,6 +103,9 @@ private:
void UpdateTransparentMouseInput(const FGeometry& AllottedGeometry); void UpdateTransparentMouseInput(const FGeometry& AllottedGeometry);
void HandleWindowFocusLost(); void HandleWindowFocusLost();
void SetAdaptiveCanvasSize(bool bEnabled);
void UpdateCanvasSize();
void UpdateCanvasControlMode(const FInputEvent& InputEvent); void UpdateCanvasControlMode(const FInputEvent& InputEvent);
void OnPostImGuiUpdate(); void OnPostImGuiUpdate();
@ -135,6 +138,8 @@ private:
bool bForegroundWindow = false; bool bForegroundWindow = false;
bool bHideMouseCursor = true; bool bHideMouseCursor = true;
bool bTransparentMouseInput = false; bool bTransparentMouseInput = false;
bool bAdaptiveCanvasSize = false;
bool bUpdateCanvasSize = false;
TSharedPtr<SImGuiCanvasControl> CanvasControlWidget; TSharedPtr<SImGuiCanvasControl> CanvasControlWidget;
TWeakPtr<SWidget> PreviousUserFocusedWidget; TWeakPtr<SWidget> PreviousUserFocusedWidget;