mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Revamp the cinema GUI code
This patch introduces a new class for managing the cinema overlay (two black bars) and cutscene mode. This makes it more extensible for the future, e.g. allowing to display text on the bars. Since <include> elements can only be placed inside an <object>, this patch needs to restructure session.xml a bit and also adds some explanation comments while at it.
This commit is contained in:
parent
d882ab74a1
commit
64de934dd3
7 changed files with 198 additions and 127 deletions
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* This class manages the cinematic overlay, which is responsible for showing black bars at the top and bottom while
|
||||
* cinema paths are playing. Cinema paths are predefined camera animations, which block player input of any kind while
|
||||
* playing; cutscenes, essentially. Whether one is playing is communicated through the simulation state.
|
||||
*/
|
||||
class CinemaOverlay
|
||||
{
|
||||
constructor()
|
||||
{
|
||||
this.overlay = Engine.GetGUIObjectByName("cinemaOverlay");
|
||||
this.barTop = Engine.GetGUIObjectByName("cinemaOverlayBarTop");
|
||||
this.barBottom = Engine.GetGUIObjectByName("cinemaOverlayBarBottom");
|
||||
|
||||
// Objects to hide while showing the overlay.
|
||||
this.primarySessionOverlays = Engine.GetGUIObjectByName("primaryOverlays");
|
||||
this.bandbox = Engine.GetGUIObjectByName("bandbox");
|
||||
this.hotkeys = Engine.GetGUIObjectByName("hotkeys");
|
||||
|
||||
this.overlay.onSimulationUpdate = this.onSimulationUpdate.bind(this);
|
||||
this.overlay.onWindowResized = () =>
|
||||
{
|
||||
this.recalculateBarSizes();
|
||||
};
|
||||
this.overlay.hidden = true;
|
||||
this.isCutsceneModeEnabled = Engine.Renderer_GetCutsceneModeEnabled();
|
||||
|
||||
this.recalculateBarSizes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable cutscene mode and remember it in order to save unnecessary calls to the engine.
|
||||
* This, however, assumes that the mode isn't modified anywhere else.
|
||||
*/
|
||||
setCutsceneModeEnabled(enabled)
|
||||
{
|
||||
if (this.isCutsceneModeEnabled == enabled)
|
||||
return;
|
||||
|
||||
Engine.Renderer_SetCutsceneModeEnabled(!!enabled);
|
||||
this.isCutsceneModeEnabled = enabled;
|
||||
}
|
||||
|
||||
isInCutsceneMode()
|
||||
{
|
||||
return this.isCutsceneModeEnabled;
|
||||
}
|
||||
|
||||
onSimulationUpdate()
|
||||
{
|
||||
const cinemaPathPlaying = GetSimState().cinemaPathPlaying;
|
||||
if (this.overlay.hidden && cinemaPathPlaying)
|
||||
this.show();
|
||||
else if (!this.overlay.hidden && !cinemaPathPlaying)
|
||||
this.hide();
|
||||
}
|
||||
|
||||
show()
|
||||
{
|
||||
if (!this.overlay.hidden)
|
||||
return;
|
||||
|
||||
this.primarySessionOverlays.hidden = true;
|
||||
this.bandbox.hidden = true;
|
||||
this.hotkeys.hidden = true;
|
||||
this.overlay.hidden = false;
|
||||
|
||||
this.setCutsceneModeEnabled(true);
|
||||
}
|
||||
|
||||
hide()
|
||||
{
|
||||
if (this.overlay.hidden)
|
||||
return;
|
||||
|
||||
this.primarySessionOverlays.hidden = !g_ShowGUI;
|
||||
this.hotkeys.hidden = false;
|
||||
this.overlay.hidden = true;
|
||||
|
||||
this.setCutsceneModeEnabled(false);
|
||||
}
|
||||
|
||||
recalculateBarSizes()
|
||||
{
|
||||
const minHeight = 115;
|
||||
const width = this.overlay.getComputedSize().right;
|
||||
const height = this.overlay.getComputedSize().bottom;
|
||||
// The aspect ratio of 2.39:1 is typical in films and has a cinematic feel to it.
|
||||
const barHeight = Math.max(minHeight, (height - width / 2.39) / 2);
|
||||
this.barTop.size.bottom = barHeight;
|
||||
this.barBottom.size.top = -barHeight;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<object name="cinemaOverlay">
|
||||
<object name="cinemaOverlayBarTop" type="image" sprite="color:black" size="0 0 100% 100"/>
|
||||
<object name="cinemaOverlayBarBottom" type="image" sprite="color:black" size="0 100%-100 100% 100%"/>
|
||||
</object>
|
||||
|
|
@ -527,7 +527,7 @@ function getPreferredEntities(ents)
|
|||
|
||||
function handleInputBeforeGui(ev, hoveredObject)
|
||||
{
|
||||
if (GetSimState().cinemaPlaying)
|
||||
if (g_CinemaOverlay.isInCutsceneMode())
|
||||
return false;
|
||||
|
||||
// Capture cursor position so we can use it for displaying cursors,
|
||||
|
|
@ -843,7 +843,7 @@ function handleInputBeforeGui(ev, hoveredObject)
|
|||
}
|
||||
function handleInputAfterGui(ev)
|
||||
{
|
||||
if (GetSimState().cinemaPlaying)
|
||||
if (g_CinemaOverlay.isInCutsceneMode())
|
||||
return false;
|
||||
if (ev.hotkey === undefined)
|
||||
ev.hotkey = null;
|
||||
|
|
|
|||
|
|
@ -444,7 +444,6 @@ function handleNetStatusMessage(message)
|
|||
if (message.status == "disconnected")
|
||||
{
|
||||
g_Disconnected = true;
|
||||
updateCinemaPath();
|
||||
closeOpenDialogs();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ var g_Ambient;
|
|||
var g_AutoFormation;
|
||||
var g_Chat;
|
||||
var g_Cheats;
|
||||
var g_CinemaOverlay;
|
||||
var g_DeveloperOverlay;
|
||||
var g_DiplomacyColors;
|
||||
var g_DiplomacyDialog;
|
||||
|
|
@ -296,6 +297,7 @@ function init(initData, hotloadData)
|
|||
g_Ambient = new Ambient();
|
||||
g_AutoFormation = new AutoFormation();
|
||||
g_Chat = new Chat(g_PlayerViewControl, g_Cheats);
|
||||
g_CinemaOverlay = new CinemaOverlay();
|
||||
g_DeveloperOverlay = new DeveloperOverlay(g_PlayerViewControl, g_Selection);
|
||||
g_DiplomacyDialog = new DiplomacyDialog(g_PlayerViewControl, g_DiplomacyColors);
|
||||
g_GameSpeedControl = new GameSpeedControl(g_PlayerViewControl);
|
||||
|
|
@ -631,6 +633,10 @@ function onTick()
|
|||
handleNetMessages();
|
||||
|
||||
updateCursorAndTooltip();
|
||||
updateTimers();
|
||||
|
||||
if (g_CinemaOverlay.isInCutsceneMode())
|
||||
return;
|
||||
|
||||
if (g_Selection.dirty)
|
||||
{
|
||||
|
|
@ -650,12 +656,7 @@ function onTick()
|
|||
else if (g_ShowAllStatusBars && now % g_StatusBarUpdate <= tickLength)
|
||||
recalculateStatusBarDisplay();
|
||||
|
||||
updateTimers();
|
||||
Engine.GuiInterfaceCall("ClearRenamedEntities");
|
||||
|
||||
const isPlayingCinemaPath = GetSimState().cinemaPlaying && !g_Disconnected;
|
||||
if (isPlayingCinemaPath)
|
||||
updateCinemaOverlay();
|
||||
}
|
||||
|
||||
function onSimulationUpdate()
|
||||
|
|
@ -686,7 +687,6 @@ function onSimulationUpdate()
|
|||
handler();
|
||||
|
||||
// TODO: Move to handlers
|
||||
updateCinemaPath();
|
||||
handleNotifications();
|
||||
updateGUIObjects();
|
||||
}
|
||||
|
|
@ -694,40 +694,8 @@ function onSimulationUpdate()
|
|||
function toggleGUI()
|
||||
{
|
||||
g_ShowGUI = !g_ShowGUI;
|
||||
updateCinemaPath();
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (isPlayingCinemaPath && !g_CutsceneModeEnabled)
|
||||
{
|
||||
Engine.Renderer_SetCutsceneModeEnabled(true);
|
||||
g_CutsceneModeEnabled = true;
|
||||
}
|
||||
else if (!isPlayingCinemaPath && g_CutsceneModeEnabled)
|
||||
{
|
||||
Engine.Renderer_SetCutsceneModeEnabled(false);
|
||||
g_CutsceneModeEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
function updateCinemaOverlay()
|
||||
{
|
||||
const cinemaOverlay = Engine.GetGUIObjectByName("cinemaOverlay");
|
||||
const width = cinemaOverlay.getComputedSize().right;
|
||||
const height = cinemaOverlay.getComputedSize().bottom;
|
||||
let barHeight = (height - width / 2.39) / 2;
|
||||
if (barHeight < 0)
|
||||
barHeight = 0;
|
||||
|
||||
Engine.GetGUIObjectByName("cinemaBarTop").size.bottom = barHeight;
|
||||
Engine.GetGUIObjectByName("cinemaBarBottom").size.top = -barHeight;
|
||||
Engine.GetGUIObjectByName("primaryOverlays").hidden = !g_ShowGUI;
|
||||
Engine.GetGUIObjectByName("supplementaryOverlays").hidden = !g_ShowGUI;
|
||||
}
|
||||
|
||||
// TODO: Use event subscription onSimulationUpdate, onEntitySelectionChange, onPlayerViewChange, ... instead
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
<script directory="gui/session/"/>
|
||||
<script directory="gui/session/campaigns/"/>
|
||||
<script directory="gui/session/chat/"/>
|
||||
<script directory="gui/session/cinema/"/>
|
||||
<script directory="gui/session/developer_overlay/"/>
|
||||
<script directory="gui/session/diplomacy/"/>
|
||||
<script directory="gui/session/diplomacy/playercontrols/"/>
|
||||
|
|
@ -34,93 +35,99 @@
|
|||
onSimulationUpdate();
|
||||
</action>
|
||||
|
||||
<!-- Hotkeys won't work properly unless outside menu -->
|
||||
<include directory="gui/session/hotkeys/"/>
|
||||
|
||||
<include file="gui/session/NetworkStatusOverlay.xml"/>
|
||||
<include file="gui/session/NetworkDelayOverlay.xml"/>
|
||||
<include file="gui/session/PauseOverlay.xml"/>
|
||||
<include file="gui/session/TimeNotificationOverlay.xml"/>
|
||||
|
||||
<!-- Chat messages -->
|
||||
<object name="chatPanel" size="3 131 100% 100%-240" z="0" absolute="true">
|
||||
<object name="chatLines">
|
||||
<repeat count="20">
|
||||
<object name="chatLine[n]" type="button" style="chatPanelOverlay" tooltip_style="sessionToolTipBottomBold" ghost="true" hidden="true"/>
|
||||
</repeat>
|
||||
<object name="primaryOverlays">
|
||||
<!-- Chat messages -->
|
||||
<object name="chatPanel" size="3 131 100% 100%-240" z="0" absolute="true">
|
||||
<object name="chatLines">
|
||||
<repeat count="20">
|
||||
<object name="chatLine[n]" type="button" style="chatPanelOverlay" tooltip_style="sessionToolTipBottomBold" ghost="true" hidden="true"/>
|
||||
</repeat>
|
||||
</object>
|
||||
</object>
|
||||
|
||||
<include directory="gui/session/chat/"/>
|
||||
<include directory="gui/session/developer_overlay/"/>
|
||||
<include directory="gui/session/dialogs/"/>
|
||||
<include directory="gui/session/diplomacy/"/>
|
||||
<include directory="gui/session/match_settings/"/>
|
||||
<include file="gui/session/GameSpeedControl.xml"/>
|
||||
<include file="gui/session/PanelEntities.xml"/>
|
||||
<include file="gui/session/ResearchProgress.xml"/>
|
||||
<include file="gui/session/TimeNotificationOverlay.xml"/>
|
||||
<include file="gui/session/TopPanel.xml"/>
|
||||
<include file="gui/session/trade/TradeDialog.xml"/>
|
||||
<include file="gui/session/tutorial_panel.xml"/>
|
||||
<include file="gui/session/Menu.xml"/>
|
||||
|
||||
<!-- Contains miscellanious objects s.a.: the technology research -->
|
||||
<!-- progress, group selection icons, and the hero selection icon -->
|
||||
<include directory="gui/session/session_objects/"/>
|
||||
|
||||
<!-- Information tooltip -->
|
||||
<!-- Follows the mouse around if 'independent' is set to 'true'. -->
|
||||
<object name="informationTooltip" type="tooltip" independent="true" style="informationTooltip"/>
|
||||
|
||||
<!-- Structure placement info tooltip -->
|
||||
<object name="placementTooltip" type="tooltip" independent="true" style="informationTooltip"/>
|
||||
|
||||
<!-- START of BOTTOM PANEL -->
|
||||
<!-- Limit to the minimal supported width of 1024 pixels. -->
|
||||
<object size="50%-512 0 50%+512 100%">
|
||||
|
||||
<object size="50%-512 100%-204 50%-312 100%">
|
||||
<include file="gui/session/minimap/MiniMap.xml"/>
|
||||
</object>
|
||||
|
||||
<!-- Supplemental Details Panel (left). -->
|
||||
<object name="supplementalSelectionDetails"
|
||||
size="50%-316 100%-166 50%-110 100%"
|
||||
sprite="supplementalDetailsPanel"
|
||||
type="image"
|
||||
z="20"
|
||||
>
|
||||
<include directory="gui/session/selection_panels_left/"/>
|
||||
</object>
|
||||
|
||||
<!-- Selection Details Panel (middle). -->
|
||||
<object name="selectionDetails"
|
||||
size="50%-114 100%-204 50%+114 100%"
|
||||
sprite="selectionDetailsPanel"
|
||||
type="image"
|
||||
>
|
||||
<include directory="gui/session/selection_panels_middle/"/>
|
||||
</object>
|
||||
|
||||
<!-- Commands Panel (right). -->
|
||||
<object name="unitCommands"
|
||||
size="50%+110 100%-166 50%+512 100%"
|
||||
sprite="unitCommandsPanel"
|
||||
type="image"
|
||||
z="20"
|
||||
>
|
||||
<include directory="gui/session/selection_panels_right/"/>
|
||||
</object>
|
||||
</object><!-- END OF BOTTOM PANEL -->
|
||||
</object><!-- END OF PRIMARY OVERLAYS -->
|
||||
|
||||
<!-- Hotkeys of button objects can only be triggered while the object is neither set hidden nor disabled. -->
|
||||
<!-- That is why they are placed outside of menus and overlays. -->
|
||||
<!-- And this object can therefore be used to turn on and off all these hotkeys here at once. -->
|
||||
<object name="hotkeys">
|
||||
<include directory="gui/session/hotkeys/"/>
|
||||
</object>
|
||||
|
||||
<include directory="gui/session/chat/"/>
|
||||
<include directory="gui/session/developer_overlay/"/>
|
||||
<include directory="gui/session/dialogs/"/>
|
||||
<include directory="gui/session/diplomacy/"/>
|
||||
<include directory="gui/session/match_settings/"/>
|
||||
<include file="gui/session/GameSpeedControl.xml"/>
|
||||
<include file="gui/session/PanelEntities.xml"/>
|
||||
<include file="gui/session/ResearchProgress.xml"/>
|
||||
<include file="gui/session/TopPanel.xml"/>
|
||||
<include file="gui/session/trade/TradeDialog.xml"/>
|
||||
<include file="gui/session/tutorial_panel.xml"/>
|
||||
<include file="gui/session/Menu.xml"/>
|
||||
<!-- Selection bandbox. -->
|
||||
<!-- Placed outside the primary overlays, so it can be shown even when all overlays are hidden (e.g. with the hotkey)-->
|
||||
<object name="bandbox" type="image" sprite="bandbox" ghost="true" hidden="true" z="200"/>
|
||||
|
||||
<!-- Contains miscellanious objects s.a.: the technology research -->
|
||||
<!-- progress, group selection icons, and the hero selection icon -->
|
||||
<include directory="gui/session/session_objects/"/>
|
||||
<!-- Overlaps with the primary overlays, they're never shown both at once. -->
|
||||
<include file="gui/session/cinema/CinemaOverlay.xml"/>
|
||||
|
||||
<!-- Information tooltip -->
|
||||
<!-- Follows the mouse around if 'independent' is set to 'true'. -->
|
||||
<object name="informationTooltip" type="tooltip" independent="true" style="informationTooltip"/>
|
||||
|
||||
<!-- Structure placement info tooltip -->
|
||||
<object name="placementTooltip" type="tooltip" independent="true" style="informationTooltip"/>
|
||||
|
||||
<!-- START of BOTTOM PANEL -->
|
||||
<!-- Limit to the minimal supported width of 1024 pixels. -->
|
||||
<object size="50%-512 0 50%+512 100%">
|
||||
|
||||
<object size="50%-512 100%-204 50%-312 100%">
|
||||
<include file="gui/session/minimap/MiniMap.xml"/>
|
||||
</object>
|
||||
|
||||
<!-- Supplemental Details Panel (left). -->
|
||||
<object name="supplementalSelectionDetails"
|
||||
size="50%-316 100%-166 50%-110 100%"
|
||||
sprite="supplementalDetailsPanel"
|
||||
type="image"
|
||||
z="20"
|
||||
>
|
||||
<include directory="gui/session/selection_panels_left/"/>
|
||||
</object>
|
||||
|
||||
<!-- Selection Details Panel (middle). -->
|
||||
<object name="selectionDetails"
|
||||
size="50%-114 100%-204 50%+114 100%"
|
||||
sprite="selectionDetailsPanel"
|
||||
type="image"
|
||||
>
|
||||
<include directory="gui/session/selection_panels_middle/"/>
|
||||
</object>
|
||||
|
||||
<!-- Commands Panel (right). -->
|
||||
<object name="unitCommands"
|
||||
size="50%+110 100%-166 50%+512 100%"
|
||||
sprite="unitCommandsPanel"
|
||||
type="image"
|
||||
z="20"
|
||||
>
|
||||
<include directory="gui/session/selection_panels_right/"/>
|
||||
</object>
|
||||
</object><!-- END OF BOTTOM PANEL -->
|
||||
<!-- Objects that make sense to sometimes still show while the primary overlays are hidden. -->
|
||||
<object name="supplimentaryOverlays">
|
||||
<include file="gui/session/NetworkStatusOverlay.xml"/>
|
||||
<include file="gui/session/NetworkDelayOverlay.xml"/>
|
||||
<include file="gui/session/PauseOverlay.xml"/>
|
||||
</object>
|
||||
</object> <!-- END OF SESSION OBJECT -->
|
||||
|
||||
<!-- Selection bandbox -->
|
||||
<object name="bandbox" type="image" sprite="bandbox" ghost="true" hidden="true" z="200"/>
|
||||
|
||||
<!-- Cinema overlay -->
|
||||
<object name="cinemaOverlay" hidden="true" ghost="true">
|
||||
<object name="cinemaBarTop" type="image" sprite="color:0 0 0 255" size="0 0 100% 100" ghost="true"/>
|
||||
<object name="cinemaBarBottom" type="image" sprite="color:0 0 0 255" size="0 100%-100 100% 100%" ghost="true"/>
|
||||
</object>
|
||||
|
||||
</objects>
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ GuiInterface.prototype.GetSimulationState = function()
|
|||
|
||||
const cmpCinemaManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_CinemaManager);
|
||||
if (cmpCinemaManager)
|
||||
ret.cinemaPlaying = cmpCinemaManager.IsPlayingQueue();
|
||||
ret.cinemaPathPlaying = cmpCinemaManager.IsPlayingQueue();
|
||||
|
||||
const cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
|
||||
ret.victoryConditions = cmpEndGameManager.GetVictoryConditions();
|
||||
|
|
|
|||
Loading…
Reference in a new issue