增加多屏显示,视频播放

This commit is contained in:
liuyunhui
2025-09-19 14:40:23 +08:00
parent fded7b9a51
commit 9076a5ea41
112 changed files with 24986 additions and 21 deletions
@@ -0,0 +1,59 @@
/************************************************************************/
/* Author: YWT20 */
/* Expected release year : 2024 */
/************************************************************************/
using UnrealBuildTool;
public class MultiWindow : ModuleRules
{
public MultiWindow(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"UMG",
"InputCore",
"ApplicationCore",
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}
@@ -0,0 +1,25 @@
/************************************************************************/
/* Author: YWT20 */
/* Expected release year : 2024 */
/************************************************************************/
#include "MultiWindow.h"
#define LOCTEXT_NAMESPACE "FMultiWindowModule"
void FMultiWindowModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FMultiWindowModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FMultiWindowModule, MultiWindow)
@@ -0,0 +1,242 @@
/************************************************************************/
/* Author: YWT20 */
/* Expected release year : 2024 */
/************************************************************************/
#include "MultiWindowActor.h"
#include "Components/Widget.h"
#include "Widgets/SWindow.h"
#include "Widgets/Layout/SConstraintCanvas.h"
#include "Engine.h"
#include <SMWindow.h>
AMultiWindowActor::AMultiWindowActor()
{
PrimaryActorTick.bCanEverTick = true;
}
void AMultiWindowActor::BeginPlay()
{
Super::BeginPlay();
viewPort = GEngine->GameViewport->Viewport;
}
void AMultiWindowActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
SetWindowClose();
}
void AMultiWindowActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
UpdateContentDPI();
if (WindowPos != GetWindowPositoin())
{
WindowPos = GetWindowPositoin();
OnWindowMoved.Broadcast(WindowPos);
}
if (ForceFocusToGameViewport && !viewPort->HasFocus())
{
if (!timerHandle.IsValid())
{
GetWorldTimerManager().SetTimer(timerHandle, this, &AMultiWindowActor::CheckFocus, focusTime, false);
}
}
}
void AMultiWindowActor::InitWindow(TSharedPtr<SWindow> InWindow, UUserWidget* InContentWidget)
{
if (IsPendingKillPending()) return;
window = InWindow;
contentWidget = InContentWidget;
window->GetOnWindowClosedEvent().AddUObject(this, &AMultiWindowActor::EventOnWindowClose);
WindowPos = GetWindowPositoin();
window->GetOnWindowActivatedEvent().AddLambda([&]() {
OnWindowActivated.Broadcast();
});
window->GetOnWindowDeactivatedEvent().AddLambda([&]() {
OnWindowDeactivated.Broadcast();
});
}
void AMultiWindowActor::UpdateContentDPI()
{
if (bIsAutoContentDPIScale && WindowOriginSize != GetWindowSize())
{
FVector2D TempWindowDPI = GetWindowSize() / WindowOriginSize;
if (TempWindowDPI != WindowDPI)
{
WindowDPI = TempWindowDPI;
contentWidget->SetRenderScale(WindowDPI);
}
}
}
void AMultiWindowActor::CheckFocus()
{
if (!viewPort->HasFocus())
{
FSlateApplication::Get().SetAllUserFocusToGameViewport();
}
GetWorldTimerManager().ClearTimer(timerHandle);
}
void AMultiWindowActor::SetWindowShow(bool bIsShow)
{
if (window.IsValid())
{
if (bIsShow)
{
window->ShowWindow();
}
else
{
window->HideWindow();
}
}
}
void AMultiWindowActor::SetWindowContentWidget(UUserWidget* ContentWidget)
{
if (ContentWidget && window.IsValid())
{
window->SetContent(ContentWidget->TakeWidget());
contentWidget = ContentWidget;
}
}
UUserWidget* AMultiWindowActor::GetWindowContentWidget()
{
return contentWidget;
}
void AMultiWindowActor::SetWindowSize(FVector2D WindowSize)
{
if (window)
{
window->Resize(WindowSize);
WindowOriginSize = WindowSize;
}
}
void AMultiWindowActor::SetWindowPosition(FVector2D WindowPosition)
{
if (window)
{
window->MoveWindowTo(WindowPosition);
}
}
FVector2D AMultiWindowActor::GetWindowSize()
{
if (window)
{
FVector2D tempSize = window->GetSizeInScreen();
FMargin tempBorderSize = window->GetWindowBorderSize(false);
tempSize.X -= tempBorderSize.GetDesiredSize().X;
tempSize.Y -= tempBorderSize.GetDesiredSize().Y + window->GetTitleBarSize().Get();
return tempSize;
}
return FVector2D();
}
FVector2D AMultiWindowActor::GetWindowPositoin()
{
if (window)
{
FVector2D tempSize = window->GetPositionInScreen();
return tempSize;
}
return FVector2D();
}
//FVector2D AMultiWindowActor::GetWindowDPI()
//{
// return WindowDPI;
//}
void AMultiWindowActor::SetWindowTitle(const FString& WindowTitle)
{
if (window)
{
window->SetTitle(FText::FromString(WindowTitle));
}
}
void AMultiWindowActor::SetWindowMaximize()
{
if (window)
{
window->Maximize();
}
}
void AMultiWindowActor::SetWindowRestore()
{
if (window)
{
window->Restore();
}
}
void AMultiWindowActor::SetWindowMinimize()
{
if (window)
{
window->Minimize();
}
}
void AMultiWindowActor::SetWindowClose()
{
if (window)
{
if (OnWindowClose.IsBound())
{
OnWindowClose.Broadcast();
}
OnWindowClose.Clear();
window->GetOnWindowClosedEvent().RemoveAll(this);
window->GetOnWindowActivatedEvent().RemoveAll(this);
window->GetOnWindowDeactivatedEvent().RemoveAll(this);
//window->DestroyWindowImmediately();
window->RequestDestroyWindow();
window.Reset();
Destroy();
}
}
FText AMultiWindowActor::GetWindowTitle()
{
if (window)
{
return window->GetTitle();
}
return FText();
}
void AMultiWindowActor::SetDPIScaleFactor(const float Factor)
{
if (window)
{
window->SetDPIScaleFactor(Factor);
}
}
float AMultiWindowActor::GetDPIScaleFactor() const
{
if (window)
{
return window->GetDPIScaleFactor();
}
return 0.0f;
}
@@ -0,0 +1,171 @@
/************************************************************************/
/* Author: YWT20 */
/* Expected release year : 2024 */
/************************************************************************/
#include "MultiWindowBPLibrary.h"
#include "Engine.h"
#include "Blueprint/UserWidget.h"
#include "SMWindow.h"
#include "Components/Widget.h"
#include "Widgets/SWidget.h"
#include "Widgets/Layout/SConstraintCanvas.h"
#include "Framework/Application/SlateApplication.h"
#include "Engine/GameViewportClient.h"
#include "GenericPlatform/GenericApplication.h"
#include "GameFramework/GameUserSettings.h"
#include "MultiWindow.h"
UMultiWindowBPLibrary::UMultiWindowBPLibrary(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
bool UMultiWindowBPLibrary::CreateMultiWindow(
UObject* WorldContextObject,
UUserWidget* ContentWidget,
AMultiWindowActor*& MultiWindowActor,
FVector2D WindowPositon,
FVector2D WindowSize,
bool bIsAutoCenter,
bool bIsCreateTitle,
FString WindowTitle,
float WindowBorderMarginLeft,
float WindowBorderMarginTop,
float WindowBorderMarginRight,
float WindowBorderMarginBottom,
EWindowSizingRule WindowSizingRule,
bool bIsAutoContentDPIScale,
bool IsTopmostWindow,
bool ForceFocusToGameViewport
)
{
TSharedPtr<SMWindow> window = SNew(SMWindow)
.Title(FText::FromString(WindowTitle))
.ScreenPosition(WindowPositon)
.ClientSize(WindowSize)
.FocusWhenFirstShown(true)
.HasCloseButton(true)
.IsTopmostWindow(IsTopmostWindow)
.SupportsMaximize(true)
.LayoutBorder(FMargin(WindowBorderMarginLeft, WindowBorderMarginTop, WindowBorderMarginRight, WindowBorderMarginBottom))
.SupportsMinimize(true)
.CreateTitleBar(bIsCreateTitle)
.AutoCenter(bIsAutoCenter ? (EAutoCenter::PrimaryWorkArea) : (EAutoCenter::None))
.SizingRule((ESizingRule)WindowSizingRule);
if (!window.IsValid()) { return false; }
window->SetViewportSizeDrivenByWindow(true);
FSlateApplication& slateApp = FSlateApplication::Get();
TArray<TSharedRef <SWindow>> OutWindows;
slateApp.GetAllVisibleWindowsOrdered(OutWindows);
if (TSharedPtr <SWindow> MainMenu = OutWindows[0])
{
slateApp.AddWindowAsNativeChild(window.ToSharedRef(), MainMenu.ToSharedRef());
}
else
{
slateApp.AddWindow(window.ToSharedRef(), true);
}
if (ContentWidget)
{
window->SetContent(ContentWidget->TakeWidget());
}
window->SetWindowMode(EWindowMode::Windowed);
if (UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject)) {
MultiWindowActor = World->SpawnActor<AMultiWindowActor>(FVector::ZeroVector, FRotator::ZeroRotator);
MultiWindowActor->InitWindow(window, ContentWidget);
MultiWindowActor->WindowOriginSize = WindowSize;
MultiWindowActor->bIsAutoContentDPIScale = bIsAutoContentDPIScale;
MultiWindowActor->ForceFocusToGameViewport = ForceFocusToGameViewport;
window->MultiWindowActor = MultiWindowActor;
}
return true;
}
bool UMultiWindowBPLibrary::CreateRelativeMultiWindow(UObject* WorldContextObject, UUserWidget* ContentWidget, AMultiWindowActor*& MultiWindowActor, int32 MonitorIndex, FVector2D WindowPositon, FVector2D WindowSize, bool bIsAutoCenter, bool bIsCreateTitle, FString WindowTitle, float WindowBorderMarginLeft, float WindowBorderMarginTop, float WindowBorderMarginRight, float WindowBorderMarginBottom, EWindowSizingRule WindowSizingRule, bool bIsAutoContentDPIScale, bool IsTopmostWindow, bool ForceFocusToGameViewport)
{
CreateMultiWindow(WorldContextObject, ContentWidget, MultiWindowActor, WindowPositon, WindowSize, bIsAutoCenter, bIsCreateTitle, WindowTitle, WindowBorderMarginLeft, WindowBorderMarginTop, WindowBorderMarginRight, WindowBorderMarginBottom, WindowSizingRule, bIsAutoContentDPIScale, IsTopmostWindow);
if (MonitorIndex < 0) return false;
FDisplayMetrics displayMetrics;
displayMetrics.RebuildDisplayMetrics(displayMetrics);
if (!displayMetrics.MonitorInfo.IsValidIndex(MonitorIndex)) return false;
FMonitorInfo monitorInfo = displayMetrics.MonitorInfo[MonitorIndex];
if (!GEngine) return false;
if (bIsAutoCenter)
{
WindowPositon = FVector2D(monitorInfo.WorkArea.Left, monitorInfo.WorkArea.Top);
WindowPositon += FVector2D(monitorInfo.NativeWidth * 0.5f, monitorInfo.NativeHeight * 0.5f);
WindowPositon -= WindowSize / 2;
}
else
{
WindowPositon += FVector2D(monitorInfo.WorkArea.Left, monitorInfo.WorkArea.Top);
}
MultiWindowActor->ForceFocusToGameViewport = ForceFocusToGameViewport;
MultiWindowActor->SetWindowPosition(WindowPositon);
return true;
}
bool UMultiWindowBPLibrary::CreateMultiWindowByMonitor(UObject* WorldContextObject, UUserWidget* ContentWidget, AMultiWindowActor*& MultiWindowActor, int32 MonitorIndex, bool bIsCreateTitle, FString WindowTitle, bool ForceFocusToGameViewport)
{
CreateMultiWindow(WorldContextObject, ContentWidget, MultiWindowActor, FVector2D(), FVector2D(800.0f, 640.0f), false, bIsCreateTitle, WindowTitle, 0, 0, 0, 0, EWindowSizingRule::FixedSize, false, true);
if (MonitorIndex < 0) return false;
FDisplayMetrics displayMetrics;
displayMetrics.RebuildDisplayMetrics(displayMetrics);
if (!displayMetrics.MonitorInfo.IsValidIndex(MonitorIndex)) return false;
FMonitorInfo monitorInfo = displayMetrics.MonitorInfo[MonitorIndex];
if (!GEngine) return false;
MultiWindowActor->SetWindowPosition(FVector2D(monitorInfo.WorkArea.Left, monitorInfo.WorkArea.Top));
MultiWindowActor->ForceFocusToGameViewport = ForceFocusToGameViewport;
MultiWindowActor->SetWindowMaximize();
return true;
}
int32 UMultiWindowBPLibrary::GetMonitorCount()
{
FDisplayMetrics displayMetrics;
displayMetrics.RebuildDisplayMetrics(displayMetrics);
return displayMetrics.MonitorInfo.Num();
}
int32 UMultiWindowBPLibrary::GetPrimaryMonitorIndex()
{
FDisplayMetrics displayMetrics;
displayMetrics.RebuildDisplayMetrics(displayMetrics);
for (int32 i = 0; i < displayMetrics.MonitorInfo.Num(); i++)
{
if (displayMetrics.MonitorInfo[i].bIsPrimary) return i;
}
return -1;
}
void UMultiWindowBPLibrary::MW_PrintToLog()
{
FDisplayMetrics displayMetrics;
displayMetrics.RebuildDisplayMetrics(displayMetrics);
displayMetrics.PrintToLog();
}
@@ -0,0 +1,44 @@
/************************************************************************/
/* Author: YWT20 */
/* Expected release year : 2024 */
/************************************************************************/
#include "SMWindow.h"
#include "MultiWindowActor.h"
FReply SMWindow::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& InCharacterEvent)
{
if (MultiWindowActor)
{
return MultiWindowActor->contentWidget->OnKeyChar(MyGeometry, InCharacterEvent).NativeReply;
}
return FReply::Unhandled();
}
FReply SMWindow::OnPreviewKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent)
{
if (MultiWindowActor)
{
return MultiWindowActor->contentWidget->OnPreviewKeyDown(MyGeometry, InKeyEvent).NativeReply;
}
return FReply::Unhandled();
}
FReply SMWindow::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent)
{
if (MultiWindowActor)
{
return MultiWindowActor->contentWidget->OnKeyDown(MyGeometry, InKeyEvent).NativeReply;
}
return FReply::Unhandled();
}
FReply SMWindow::OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent)
{
if (MultiWindowActor)
{
return MultiWindowActor->contentWidget->OnKeyUp(MyGeometry, InKeyEvent).NativeReply;
}
return FReply::Unhandled();
}
@@ -0,0 +1,17 @@
/************************************************************************/
/* Author: YWT20 */
/* Expected release year : 2024 */
/************************************************************************/
#pragma once
#include "Modules/ModuleManager.h"
class FMultiWindowModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
@@ -0,0 +1,147 @@
/************************************************************************/
/* Author: YWT20 */
/* Expected release year : 2024 */
/************************************************************************/
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "GameFramework/Actor.h"
#include "Framework/Application/SlateApplication.h"
#include "TimerManager.h"
#include "MultiWindowActor.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWindowEvent);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWindowMovedEvent, FVector2D, pos);
UCLASS()
class MULTIWINDOW_API AMultiWindowActor : public AActor
{
GENERATED_BODY()
public:
AMultiWindowActor();
protected:
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
public:
virtual void Tick(float DeltaTime) override;
TSharedPtr<SWindow> window = nullptr;
UUserWidget* contentWidget;
FViewport* viewPort;
FTimerHandle timerHandle;
public:
FVector2D WindowOriginSize;
FVector2D WindowPos;
FVector2D WindowDPI;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MultiWindow")
float focusTime = 0.25f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MultiWindow")
bool ForceFocusToGameViewport;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MultiWindow")
bool bIsAutoContentDPIScale;
// Invoked when the window is about to be closed.
UPROPERTY(BlueprintAssignable, Category = "MultiWindow|Event")
FOnWindowEvent OnWindowClose;
// Invoked when the window has been activated.
UPROPERTY(BlueprintAssignable, Category = "MultiWindow|Event")
FOnWindowEvent OnWindowActivated;
// Invoked when the window has been deactivated.
UPROPERTY(BlueprintAssignable, Category = "MultiWindow|Event")
FOnWindowEvent OnWindowDeactivated;
UPROPERTY(BlueprintAssignable, Category = "MultiWindow|Event")
FOnWindowMovedEvent OnWindowMoved;
public:
void EventOnWindowClose(const TSharedRef<SWindow>& InSWindow)
{
if (IsPendingKillPending()) return;
if (OnWindowClose.IsBound())
{
OnWindowClose.Broadcast();
}
};
public:
// Initialize multi-window data
void InitWindow(TSharedPtr<SWindow> InWindow, UUserWidget* InContentWidget);
void UpdateContentDPI();
void CheckFocus();
// Set the window visible
UFUNCTION(BlueprintCallable, Category = "MultiWindow")
void SetWindowShow(bool bIsShow);
// Set the widget content for this window
UFUNCTION(BlueprintCallable, Category = "MultiWindow")
void SetWindowContentWidget(UUserWidget* ContentWidget);
// Set the widget content for this window
UFUNCTION(BlueprintPure, Category = "MultiWindow")
UUserWidget* GetWindowContentWidget();
// Resize the window to be dpi scaled NewClientSize immediately
UFUNCTION(BlueprintCallable, Category = "MultiWindow")
void SetWindowSize(FVector2D WindowSize);
UFUNCTION(BlueprintPure, Category = "MultiWindow")
FVector2D GetWindowSize();
UFUNCTION(BlueprintCallable, Category = "MultiWindow")
void SetWindowPosition(FVector2D WindowPosition);
UFUNCTION(BlueprintPure, Category = "MultiWindow")
FVector2D GetWindowPositoin();
//UFUNCTION(BlueprintPure, Category = "MultiWindow")
// FVector2D GetWindowDPI();
// Sets the current window title
UFUNCTION(BlueprintCallable, Category = "MultiWindow")
void SetWindowTitle(const FString& WindowTitle);
// Maximize window size
UFUNCTION(BlueprintCallable, Category = "MultiWindow")
void SetWindowMaximize();
// Restore window size
UFUNCTION(BlueprintCallable, Category = "MultiWindow")
void SetWindowRestore();
// Minimize window size
UFUNCTION(BlueprintCallable, Category = "MultiWindow")
void SetWindowMinimize();
// Close the window
UFUNCTION(BlueprintCallable, Category = "MultiWindow")
void SetWindowClose();
// Grabs the current window title
UFUNCTION(BlueprintPure, Category = "MultiWindow | V2")
FText GetWindowTitle();
// Overrides the DPI scale factor of the native window
UFUNCTION(BlueprintCallable, Category = "MultiWindow | V2")
void SetDPIScaleFactor(const float Factor);
// Returns the DPI scale factor of the native window
UFUNCTION(BlueprintPure, Category = "MultiWindow | V2")
float GetDPIScaleFactor() const;
};
@@ -0,0 +1,96 @@
/************************************************************************/
/* Author: YWT20 */
/* Expected release year : 2024 */
/************************************************************************/
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MultiWindowActor.h"
#include "MultiWindowBPLibrary.generated.h"
UENUM(BlueprintType)
enum class EWindowSizingRule : uint8
{
/* The windows size fixed and cannot be resized **/
FixedSize,
/** The window size is computed from its content and cannot be resized by users */
Autosized,
/** The window can be resized by users */
UserSized,
};
UCLASS()
class UMultiWindowBPLibrary : public UBlueprintFunctionLibrary
{
GENERATED_UCLASS_BODY()
public:
// Create new window
UFUNCTION(BlueprintCallable, Category = "MultiWindow | V1", meta = (WorldContext = "WorldContextObject", AdvancedDisplay = "5"))
static bool CreateMultiWindow(
UObject* WorldContextObject,
UUserWidget* ContentWidget,
AMultiWindowActor*& MultiWindowActor,
FVector2D WindowPositon = FVector2D(0, 0),
FVector2D WindowSize = FVector2D(500, 500),
bool bIsAutoCenter = false,
bool bIsCreateTitle = true,
FString WindowTitle = FString(TEXT("MultiWindow")),
float WindowBorderMarginLeft = 5.0f,
float WindowBorderMarginTop = 5.0f,
float WindowBorderMarginRight = 5.0f,
float WindowBorderMarginBottom = 5.0f,
EWindowSizingRule WindowSizingRule = EWindowSizingRule::UserSized,
bool bIsAutoContentDPIScale = false,
bool IsTopmostWindow = false,
bool ForceFocusToGameViewport = false
);
// Create new relative window
UFUNCTION(BlueprintCallable, Category = "MultiWindow | V2", meta = (WorldContext = "WorldContextObject", AdvancedDisplay = "5"))
static bool CreateRelativeMultiWindow(
UObject* WorldContextObject,
UUserWidget* ContentWidget,
AMultiWindowActor*& MultiWindowActor,
int32 MonitorIndex,
FVector2D WindowPositon = FVector2D(0, 0),
FVector2D WindowSize = FVector2D(500, 500),
bool bIsAutoCenter = false,
bool bIsCreateTitle = true,
FString WindowTitle = FString(TEXT("MultiWindow")),
float WindowBorderMarginLeft = 5.0f,
float WindowBorderMarginTop = 5.0f,
float WindowBorderMarginRight = 5.0f,
float WindowBorderMarginBottom = 5.0f,
EWindowSizingRule WindowSizingRule = EWindowSizingRule::UserSized,
bool bIsAutoContentDPIScale = false,
bool IsTopmostWindow = false,
bool ForceFocusToGameViewport = false
);
// Create new window by Monitor
UFUNCTION(BlueprintCallable, Category = "MultiWindow | V2", meta = (WorldContext = "WorldContextObject"))
static bool CreateMultiWindowByMonitor(
UObject* WorldContextObject,
UUserWidget* ContentWidget,
AMultiWindowActor*& MultiWindowActor,
int32 MonitorIndex,
bool bIsCreateTitle = false,
FString WindowTitle = FString(TEXT("MultiWindow")),
bool ForceFocusToGameViewport = false
);
// Get monitor count
UFUNCTION(BlueprintPure, Category = "MultiWindow | V2")
static int32 GetMonitorCount();
// Get primary monitor index
UFUNCTION(BlueprintPure, Category = "MultiWindow | V2")
static int32 GetPrimaryMonitorIndex();
// Logs out display metrics
UFUNCTION(BlueprintCallable, Category = "MultiWindow | V2")
static void MW_PrintToLog();
};
@@ -0,0 +1,27 @@
/************************************************************************/
/* Author: YWT20 */
/* Expected release year : 2024 */
/************************************************************************/
#pragma once
#include "Framework/Application/SlateApplication.h"
#include "Widgets/SWindow.h"
/**
*
*/
class MULTIWINDOW_API SMWindow : public SWindow
{
public:
class AMultiWindowActor* MultiWindowActor;
public:
virtual FReply OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& InCharacterEvent) override;
virtual FReply OnPreviewKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override;
virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override;
virtual FReply OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override;
};