增加多屏显示,视频播放
This commit is contained in:
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 1,
|
||||
"VersionName": "1.0",
|
||||
"FriendlyName": "MultiWindow",
|
||||
"Description": "",
|
||||
"Category": "Other",
|
||||
"CreatedBy": "YWT20",
|
||||
"CreatedByURL": "https://www.unrealengine.com/marketplace/en-US/profile/YWT20",
|
||||
"DocsURL": "",
|
||||
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/1056b6c5d31c49809416547f44545453",
|
||||
"SupportURL": "https://www.youtube.com/channel/UCWYg44Cjom34vYb1Zedt__A?view_as=subscriber",
|
||||
"EngineVersion": "5.3.0",
|
||||
"CanContainContent": true,
|
||||
"Installed": true,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "MultiWindow",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "PreLoadingScreen",
|
||||
"PlatformAllowList": [
|
||||
"Win64",
|
||||
"Mac",
|
||||
"Linux"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -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)
|
||||
+242
@@ -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;
|
||||
}
|
||||
+171
@@ -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;
|
||||
};
|
||||
+96
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user