Move cutscene mode to renderer

This patch splits "cutscene mode" (disabling silhouttes, territory
borders and other visual overlays) from the cinema manager component
and moves it to the renderer, since it doesn't influence the simulation
anyway. The mode can now be independently controlled by the GUI. This
is done so it can also be used for other narrative elements like speech
or dialogue in the future. Cutscene mode is still always enabled while
cinema paths are playing, though.
By design, this also fixes the issue that range overlays weren't hidden
during cutscene mode.
This commit is contained in:
Vantha 2026-02-23 23:52:43 +01:00 committed by Vantha
parent c7247936bf
commit 1d3cdec48d
9 changed files with 37 additions and 38 deletions

View file

@ -697,25 +697,23 @@ function toggleGUI()
updateCinemaPath();
}
var g_HasHiddenSilhouettes = false;
// TODO: The whole cinema UI should be handled by its own class.
var g_CutsceneModeEnabled = false;
function updateCinemaPath()
{
const isPlayingCinemaPath = GetSimState().cinemaPlaying && !g_Disconnected;
Engine.GetGUIObjectByName("session").hidden = !g_ShowGUI || isPlayingCinemaPath;
Engine.GetGUIObjectByName("cinemaOverlay").hidden = !isPlayingCinemaPath;
// TODO: This isn't great and should use a different system.
if (isPlayingCinemaPath && Engine.ConfigDB_GetValue("user", "silhouettes") == "true")
if (isPlayingCinemaPath && !g_CutsceneModeEnabled)
{
Engine.ConfigDB_CreateValue("user", "silhouettes", "false");
g_HasHiddenSilhouettes = true;
Engine.Renderer_SetCutsceneModeEnabled(true);
g_CutsceneModeEnabled = true;
}
else if (!isPlayingCinemaPath && g_HasHiddenSilhouettes)
else if (!isPlayingCinemaPath && g_CutsceneModeEnabled)
{
// TODO: Keyboard shortcuts can still try to toggle silhouettes
// which would behave incorrectly on reset.
Engine.ConfigDB_Reload("user");
g_HasHiddenSilhouettes = false;
Engine.Renderer_SetCutsceneModeEnabled(false);
g_CutsceneModeEnabled = false;
}
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -138,6 +138,7 @@ CRenderingOptions::CRenderingOptions() : m_ConfigHooks(new ConfigHooks())
m_DisplayFrustum = false;
m_DisplayShadowsFrustum = false;
m_RenderActors = true;
m_CutsceneMode = false;
}
CRenderingOptions::~CRenderingOptions()

View file

@ -120,6 +120,12 @@ OPTION_CUSTOM_SETTER(NAME, TYPE); OPTION_GETTER(NAME, TYPE); OPTION_DEF(NAME, TY
OPTION(DisplayFrustum, bool);
OPTION(DisplayShadowsFrustum, bool);
// Cutscene Mode: while active, (most) visual overlays aren't rendered in order to give the scene a more "pure"
// and real feel, like a movie.
// The idea is for it to be inactive during normal gameplay, but enabled while playing cinema paths and
// potentially during other scripted story events/cutscenes as well, like speech/dialogue.
OPTION(CutsceneMode, bool);
OPTION(RenderActors, bool);
#undef OPTION_DEFAULT_SETTER

View file

@ -874,7 +874,8 @@ void CSceneRenderer::RenderSubmissions(
ITerrainOverlay::RenderOverlaysBeforeWater(deviceCommandContext);
// render other debug-related overlays before water (so they can be seen when underwater)
m->overlayRenderer.RenderOverlaysBeforeWater(deviceCommandContext);
if (!g_RenderingOptions.GetCutsceneMode())
m->overlayRenderer.RenderOverlaysBeforeWater(deviceCommandContext);
RenderModels(deviceCommandContext, context, cullGroup);
@ -908,8 +909,9 @@ void CSceneRenderer::RenderSubmissions(
// render debug-related terrain overlays
ITerrainOverlay::RenderOverlaysAfterWater(deviceCommandContext, cullGroup);
// render some other overlays after water (so they can be displayed on top of water)
m->overlayRenderer.RenderOverlaysAfterWater(deviceCommandContext);
if (!g_RenderingOptions.GetCutsceneMode())
// render some other overlays after water (so they can be displayed on top of water)
m->overlayRenderer.RenderOverlaysAfterWater(deviceCommandContext);
// particles are transparent so render after water
if (g_RenderingOptions.GetParticles())
@ -1087,7 +1089,7 @@ void CSceneRenderer::PrepareScene(
m->particleManager.RenderSubmit(*this, frustum);
if (g_RenderingOptions.GetSilhouettes())
if (!g_RenderingOptions.GetCutsceneMode() && g_RenderingOptions.GetSilhouettes())
{
m->silhouetteRenderer.ComputeSubmissions(m_ViewCamera);
@ -1159,16 +1161,17 @@ void CSceneRenderer::RenderScene(
void CSceneRenderer::RenderSceneOverlays(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
if (g_RenderingOptions.GetSilhouettes())
if (!g_RenderingOptions.GetCutsceneMode())
{
RenderSilhouettes(deviceCommandContext, m->globalContext);
if (g_RenderingOptions.GetSilhouettes())
RenderSilhouettes(deviceCommandContext, m->globalContext);
m->silhouetteRenderer.RenderDebugOverlays(deviceCommandContext);
// Render overlays that should appear on top of all other objects.
m->overlayRenderer.RenderForegroundOverlays(deviceCommandContext, m_ViewCamera);
}
m->silhouetteRenderer.RenderDebugOverlays(deviceCommandContext);
// Render overlays that should appear on top of all other objects.
m->overlayRenderer.RenderForegroundOverlays(deviceCommandContext, m_ViewCamera);
m_CurrentScene = nullptr;
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -41,6 +41,7 @@ void Set##NAME##Enabled(bool enabled) \
g_RenderingOptions.Set##NAME(enabled); \
}
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(CutsceneMode);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(DisplayFrustum);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(DisplayShadowsFrustum);
@ -76,6 +77,7 @@ void RegisterScriptFunctions(const ScriptRequest& rq)
ScriptFunction::Register<&TextureExists>(rq, "TextureExists");
ScriptFunction::Register<&GetRenderDebugMode>(rq, "Renderer_GetRenderDebugMode");
ScriptFunction::Register<&SetRenderDebugMode>(rq, "Renderer_SetRenderDebugMode");
REGISTER_BOOLEAN_SCRIPT_SETTING(CutsceneMode);
REGISTER_BOOLEAN_SCRIPT_SETTING(DisplayFrustum);
REGISTER_BOOLEAN_SCRIPT_SETTING(DisplayShadowsFrustum);
}

View file

@ -248,7 +248,6 @@ public:
return;
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext().GetSystemEntity());
CmpPtr<ICmpTerritoryManager> cmpTerritoryManager(GetSimContext().GetSystemEntity());
if (cmpRangeManager)
{
if (enabled)
@ -256,10 +255,6 @@ public:
// TODO: improve m_MapRevealed state and without fade in
cmpRangeManager->SetLosRevealWholeMapForAll(enabled);
}
if (cmpTerritoryManager)
cmpTerritoryManager->SetVisibility(!enabled);
ICmpSelectable::SetOverrideVisibility(!enabled);
ICmpOverlayRenderer::SetOverrideVisibility(!enabled);
m_Enabled = enabled;
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -201,7 +201,7 @@ public:
void RenderSubmit(SceneCollector &collector)
{
if (!m_Enabled || !ICmpOverlayRenderer::m_OverrideVisible)
if (!m_Enabled)
return;
for (size_t i = 0; i < m_Sprites.size(); ++i)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -632,10 +632,6 @@ void CCmpSelectable::UpdateDynamicOverlay(float frameOffset)
void CCmpSelectable::RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling)
{
// don't render selection overlay if it's not gonna be visible
if (!ICmpSelectable::m_OverrideVisible)
return;
if (m_Visible && m_Color.a > 0)
{
if (!m_Cached)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -25,5 +25,3 @@ BEGIN_INTERFACE_WRAPPER(OverlayRenderer)
DEFINE_INTERFACE_METHOD("Reset", ICmpOverlayRenderer, Reset)
DEFINE_INTERFACE_METHOD("AddSprite", ICmpOverlayRenderer, AddSprite)
END_INTERFACE_WRAPPER(OverlayRenderer)
bool ICmpOverlayRenderer::m_OverrideVisible = true;