Untitled

 avatar
unknown
c_cpp
a year ago
10 kB
15
Indexable
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "WindowSystem/WindowSystemDemoActor.generated.h"

class UWindowManagerComponent;
class UWindowWidget;

/**
 * Debug-friendly demo actor:
 * - Retries until PlayerController/Desktop exist
 * - Logs every step + shows on-screen messages
 * - Spawns UMG & 3D Viewport windows (with WindowIds for persistence)
 */
UCLASS()
class VIEWPORTWINDOWS_API AWindowSystemDemoActor : public AActor
{
    GENERATED_BODY()

public:
    AWindowSystemDemoActor();

protected:
    virtual void BeginPlay() override;

    /** Creates the demo windows (self-retries until Desktop is valid) */
    void SpawnDemoWindows();

    /** Debug helpers */
    void LogMsg(const FString& Msg, FColor Color = FColor::Cyan) const;
    void DumpState(const TCHAR* Phase) const;

    /** Retry timer */
    FTimerHandle SpawnRetryHandle;
    int32 SpawnRetryCount = 0;

    /** Track spawned windows so we don't duplicate them */
    UPROPERTY()
    UWindowWidget* SpawnedUMG = nullptr;

    UPROPERTY()
    UWindowWidget* SpawnedViewport = nullptr;

public: // Components
    /** Window manager component that builds the Desktop and spawns windows */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Viewport Windows")
    UWindowManagerComponent* WindowManager;

public: // Configurable demo settings
    /** Spawn demo windows on BeginPlay */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    bool bOpenOnBeginPlay = true;

    /** Class for the UMG content window (leave None to use SimpleLabelWidget) */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    TSubclassOf<UUserWidget> DemoContentClass;

    /** Optional tag to pick a LookAt actor for the 3D viewport window */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    FName LookAtTag = TEXT("DemoCamTarget");

    /** ---- UMG Window params ---- */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    FText UMGWindowTitle = FText::FromString(TEXT("UMG Window"));

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    FVector2D UMGWindowPosition = FVector2D(80.f, 80.f);

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    FVector2D UMGWindowSize = FVector2D(420.f, 280.f);

    /** Stable ID for persistence (pin to save/lock) */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    FName UMGWindowId = TEXT("UMG_Main");

    /** ---- 3D Viewport Window params ---- */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    FText ViewportWindowTitle = FText::FromString(TEXT("3D Viewport"));

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    FVector2D ViewportWindowPosition = FVector2D(540.f, 120.f);

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    FVector2D ViewportWindowSize = FVector2D(600.f, 380.f);

    /** Stable ID for persistence (pin to save/lock) */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Viewport Windows|Demo")
    FName ViewportWindowId = TEXT("Viewport_Main");
};


#include "WindowSystem/WindowSystemDemoActor.h"

#include "WindowSystem/WindowManagerComponent.h"
#include "WindowSystem/WindowWidget.h"
#include "WindowSystem/SimpleLabelWidget.h"

#include "Components/CanvasPanelSlot.h"
#include "Kismet/GameplayStatics.h"
#include "GameFramework/PlayerController.h"
#include "Engine/Engine.h"
#include "TimerManager.h"

DEFINE_LOG_CATEGORY_STATIC(LogViewportWindowsDemo, Log, All);

AWindowSystemDemoActor::AWindowSystemDemoActor()
{
    PrimaryActorTick.bCanEverTick = false;
    WindowManager = CreateDefaultSubobject<UWindowManagerComponent>(TEXT("WindowManager"));
}

void AWindowSystemDemoActor::LogMsg(const FString& Msg, FColor Color) const
{
    UE_LOG(LogViewportWindowsDemo, Log, TEXT("%s"), *Msg);
    if (GEngine)
    {
        GEngine->AddOnScreenDebugMessage(-1, 4.0f, Color, Msg);
    }
}

void AWindowSystemDemoActor::DumpState(const TCHAR* Phase) const
{
    UWorld* World = GetWorld();
    APlayerController* PC = World ? UGameplayStatics::GetPlayerController(World, 0) : nullptr;
    const bool bPCReady = (PC && PC->IsLocalController());
    const void* DesktopPtr = WindowManager ? WindowManager->GetDesktop() : nullptr;

    FString Msg = FString::Printf(
        TEXT("[VPW Demo] %s\n  World=%s  PC=%s  Local=%s  WindowManager=%s  Desktop=%s\n  DemoContentClass=%s  UMGId=%s  VPId=%s"),
        Phase,
        *GetNameSafe(World),
        *GetNameSafe(PC),
        bPCReady ? TEXT("Yes") : TEXT("No"),
        *GetNameSafe(WindowManager),
        DesktopPtr ? TEXT("Valid") : TEXT("NULL"),
        *GetNameSafe(DemoContentClass),
        *UMGWindowId.ToString(),
        *ViewportWindowId.ToString()
    );
    LogMsg(Msg, FColor::Silver);
}

void AWindowSystemDemoActor::BeginPlay()
{
    Super::BeginPlay();

    DumpState(TEXT("BeginPlay"));

    if (!bOpenOnBeginPlay)
    {
        LogMsg(TEXT("[VPW Demo] bOpenOnBeginPlay = false (skipping window spawn)"), FColor::Yellow);
        return;
    }

    if (!WindowManager)
    {
        LogMsg(TEXT("[VPW Demo] WindowManager component is NULL!"), FColor::Red);
        return;
    }

    // Kick desktop initialization (it will succeed once PC is valid)
    WindowManager->InitializeDesktop();
    LogMsg(TEXT("[VPW Demo] Called WindowManager->InitializeDesktop()"), FColor::Cyan);

    // Try to spawn now; will self-retry until Desktop is valid.
    SpawnRetryCount = 0;
    SpawnDemoWindows();
}

void AWindowSystemDemoActor::SpawnDemoWindows()
{
    UWorld* World = GetWorld();
    if (!World)
    {
        LogMsg(TEXT("[VPW Demo] World is NULL in SpawnDemoWindows"), FColor::Red);
        return;
    }

    // Ensure Desktop exists first
    if (!WindowManager || !WindowManager->GetDesktop())
    {
        if (++SpawnRetryCount <= 40) // ~2 seconds total @ 0.05s
        {
            LogMsg(FString::Printf(TEXT("[VPW Demo] Desktop not ready (try %d) — retrying..."), SpawnRetryCount), FColor::Yellow);
            World->GetTimerManager().SetTimer(SpawnRetryHandle, this, &AWindowSystemDemoActor::SpawnDemoWindows, 0.05f, false);
        }
        else
        {
            LogMsg(TEXT("[VPW Demo] Desktop never became ready — aborting demo spawn."), FColor::Red);
            DumpState(TEXT("DesktopFailed"));
        }
        return;
    }

    DumpState(TEXT("DesktopReady"));

    // -------- UMG Window --------
    if (!SpawnedUMG)
    {
        TSubclassOf<UUserWidget> ContentClass = DemoContentClass;
        if (!ContentClass)
        {
            LogMsg(TEXT("[VPW Demo] DemoContentClass is None — using USimpleLabelWidget fallback."), FColor::Yellow);
            ContentClass = USimpleLabelWidget::StaticClass();
        }

        LogMsg(FString::Printf(TEXT("[VPW Demo] Spawning UMG Window: Pos=(%.1f,%.1f) Size=(%.1f,%.1f) Title='%s' Id='%s'"),
            UMGWindowPosition.X, UMGWindowPosition.Y, UMGWindowSize.X, UMGWindowSize.Y,
            *UMGWindowTitle.ToString(), *UMGWindowId.ToString()), FColor::Green);

        SpawnedUMG = WindowManager->CreateUMGWindow(
            ContentClass,
            UMGWindowPosition,
            UMGWindowSize,
            UMGWindowTitle,
            UMGWindowId
        );

        if (SpawnedUMG)
        {
            if (UCanvasPanelSlot* C = SpawnedUMG->GetCanvasSlot())
            {
                LogMsg(FString::Printf(TEXT("[VPW Demo] UMG Window CREATED. Canvas Pos=(%.1f,%.1f) Size=(%.1f,%.1f) Z=%d"),
                    C->GetPosition().X, C->GetPosition().Y, C->GetSize().X, C->GetSize().Y, C->GetZOrder()), FColor::Green);
            }
            else
            {
                LogMsg(TEXT("[VPW Demo] UMG Window CREATED but CanvasSlot is NULL."), FColor::Yellow);
            }
        }
        else
        {
            LogMsg(TEXT("[VPW Demo] FAILED to create UMG Window."), FColor::Red);
        }
    }

    // -------- 3D Viewport Window --------
    if (!SpawnedViewport)
    {
        AActor* LookAt = nullptr;
        if (!LookAtTag.IsNone())
        {
            TArray<AActor*> Found;
            UGameplayStatics::GetAllActorsWithTag(World, LookAtTag, Found);
            if (Found.Num() > 0)
            {
                LookAt = Found[0];
                LogMsg(FString::Printf(TEXT("[VPW Demo] LookAt actor found by tag '%s': %s"),
                    *LookAtTag.ToString(), *GetNameSafe(LookAt)), FColor::Cyan);
            }
            else
            {
                LogMsg(FString::Printf(TEXT("[VPW Demo] No actor found with tag '%s' (this is OK)."), *LookAtTag.ToString()), FColor::Yellow);
            }
        }

        LogMsg(FString::Printf(TEXT("[VPW Demo] Spawning Viewport Window: Pos=(%.1f,%.1f) Size=(%.1f,%.1f) Title='%s' Id='%s'"),
            ViewportWindowPosition.X, ViewportWindowPosition.Y, ViewportWindowSize.X, ViewportWindowSize.Y,
            *ViewportWindowTitle.ToString(), *ViewportWindowId.ToString()), FColor::Green);

        SpawnedViewport = WindowManager->Create3DViewportWindow(
            LookAt,
            ViewportWindowPosition,
            ViewportWindowSize,
            ViewportWindowTitle,
            ViewportWindowId
        );

        if (SpawnedViewport)
        {
            if (UCanvasPanelSlot* C = SpawnedViewport->GetCanvasSlot())
            {
                LogMsg(FString::Printf(TEXT("[VPW Demo] Viewport Window CREATED. Canvas Pos=(%.1f,%.1f) Size=(%.1f,%.1f) Z=%d"),
                    C->GetPosition().X, C->GetPosition().Y, C->GetSize().X, C->GetSize().Y, C->GetZOrder()), FColor::Green);
            }
            else
            {
                LogMsg(TEXT("[VPW Demo] Viewport Window CREATED but CanvasSlot is NULL."), FColor::Yellow);
            }
        }
        else
        {
            LogMsg(TEXT("[VPW Demo] FAILED to create Viewport Window."), FColor::Red);
        }
    }

    // Final state
    if (SpawnedUMG || SpawnedViewport)
    {
        DumpState(TEXT("SpawnComplete"));
    }
}

Editor is loading...
Leave a Comment