- New C++ AGigLineNPCPerson: reusable NPC/pedestrian prefab built on the MPFB human. ACharacter capsule half-height 83 cm (total 1.66 m, head top ~1.66 m so a 1.60 m camera doesn't clip), the character skeletal mesh on the built-in mesh as the visible body (feet on Z 0), AutoPossessAI for 0.5.0 pedestrians. Staged at Z 0 in the review scene; captured as review-npc-prefab.png. - AGigLineShotActor now names screenshots by stable camera name (no list-index prefix): inserting or reordering cameras no longer renumbers files or orphans the old ones. Re-rendered all review/demo shots with stable names. - ue_build_review_map.py: chmod the target .umap before save_map (git marks maps 444 on checkout, silently making save_map return False and dropping stages). - Screenshots/README.md, ROADMAP, TODO updated for the prefab + stable names. - DemoMap.umap rebuilt by the render pipeline (north buildings + demo cameras).
83 lines
2.1 KiB
C++
83 lines
2.1 KiB
C++
#include "GigLineShotActor.h"
|
|
|
|
#include "Camera/CameraActor.h"
|
|
#include "Engine/World.h"
|
|
#include "GameFramework/PlayerController.h"
|
|
#include "UnrealClient.h"
|
|
|
|
AGigLineShotActor::AGigLineShotActor()
|
|
{
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
PrimaryActorTick.bStartWithTickEnabled = true;
|
|
}
|
|
|
|
void AGigLineShotActor::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
NextShot();
|
|
}
|
|
|
|
void AGigLineShotActor::Tick(float DeltaSeconds)
|
|
{
|
|
Super::Tick(DeltaSeconds);
|
|
|
|
if (bWaitingForSettle)
|
|
{
|
|
SettleCountdown -= DeltaSeconds;
|
|
if (SettleCountdown <= 0.f)
|
|
{
|
|
bWaitingForSettle = false;
|
|
// Use the stable custom name only (no list-index prefix): inserting or
|
|
// reordering cameras must not renumber files and orphan the old ones.
|
|
const FString Name = CurrentShot < ShotNames.Num()
|
|
? ShotNames[CurrentShot]
|
|
: FString::FromInt(CurrentShot);
|
|
const FString FileName = FString::Printf(TEXT("review-%s"), *Name);
|
|
// Resolution is the game window's; the runner passes -ResX/-ResY.
|
|
FScreenshotRequest::RequestScreenshot(FileName, false, false);
|
|
bWaitingForScreenshot = true;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (bWaitingForScreenshot && !FScreenshotRequest::IsScreenshotRequested())
|
|
{
|
|
bWaitingForScreenshot = false;
|
|
UE_LOG(LogTemp, Log, TEXT("GigLineShotActor: captured %s"), *FScreenshotRequest::GetFilename());
|
|
++CurrentShot;
|
|
NextShot();
|
|
}
|
|
}
|
|
|
|
void AGigLineShotActor::NextShot()
|
|
{
|
|
if (!PlayerController)
|
|
{
|
|
PlayerController = GetWorld()->GetFirstPlayerController();
|
|
}
|
|
|
|
if (CurrentShot >= ShotLocations.Num() || !PlayerController)
|
|
{
|
|
UE_LOG(LogTemp, Log, TEXT("GigLineShotActor: done (%d shots)"), CurrentShot);
|
|
if (bQuitWhenDone)
|
|
{
|
|
PlayerController->ConsoleCommand(TEXT("quit"));
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (CurrentCamera)
|
|
{
|
|
CurrentCamera->Destroy();
|
|
}
|
|
|
|
FActorSpawnParameters Params;
|
|
Params.ObjectFlags |= RF_Transient;
|
|
CurrentCamera = GetWorld()->SpawnActor<ACameraActor>(
|
|
ACameraActor::StaticClass(), ShotLocations[CurrentShot], ShotRotations[CurrentShot], Params);
|
|
PlayerController->SetViewTarget(CurrentCamera);
|
|
|
|
SettleCountdown = SettleSeconds;
|
|
bWaitingForSettle = true;
|
|
}
|