File size: 9,808 Bytes
b6a38d7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
DefineClass.XSetpieceDlg = {
__parents = { "XDialog" },
ZOrder = 99,
HandleMouse = true,
skippable = true,
openedAt = false,
skipDelay = 250,
setpiece = false,
setpiece_seed = 0,
testMode = false,
triggerUnits = false,
extra_params = false,
setpieceInstance = false,
fadeDlg = false,
lifecycle_thread = false,
skipping_setpiece = false,
}
function XSetpieceDlg:Init(parent, context)
self.setpiece = context and context.setpiece or "MoveTest"
self.testMode = context and context.testMode
self.triggerUnits = context and context.triggerUnits
self.extra_params = context and context.extra_params or empty_table
assert(Setpieces[self.setpiece].TakePlayerControl) -- setpieces that don't take control from the player should be run directly via StartSetpiece in a game time thread
--this is only semi sync when called from entersector rtt..
NetUpdateHash("SetpieceStateStart")
ChangeGameState("setpiece_playing", true)
end
function XSetpieceDlg:Open(...)
XDialog.Open(self, ...)
self.openedAt = GameTime()
if rawget(self, "idSkipHint") then
if GetUIStyleGamepad(nil, self) then
self.idSkipHint:SetText(T(576896503712, "<ButtonB> Skip"))
else
self.idSkipHint:SetText(T(696052205292, "<style SkipHint>Escape: Skip</style>")) -- no icon for Esc button
end
end
self.lifecycle_thread = CreateGameTimeThread(XSetpieceDlg.Lifecycle, self)
end
DefineClass.XMovieBlackBars = {
__parents = {"XDialog"},
top = false,
bottom = false
}
function XMovieBlackBars:Open()
XDialog.Open(self)
self:CreateBlackBarControls()
end
function XMovieBlackBars:CreateBlackBarControls()
local top = XTemplateSpawn("XWindow", self)
top:SetDock("top")
top:SetBackground(RGBA(0, 0, 0, 255))
top:Open()
top.scale = point(1000, 1000)
top.SetOutsideScale = empty_func
self.top = top
local bottom = XTemplateSpawn("XWindow", self)
bottom:SetDock("bottom")
bottom:SetBackground(RGBA(0, 0, 0, 255))
bottom:Open()
bottom.scale = point(1000, 1000)
bottom.SetOutsideScale = empty_func
self.bottom = bottom
local left = XTemplateSpawn("XWindow", self)
left:SetDock("left")
left:SetBackground(RGBA(0, 0, 0, 255))
left:Open()
left.scale = point(1000, 1000)
left.SetOutsideScale = empty_func
self.left = left
local right = XTemplateSpawn("XWindow", self)
right:SetDock("right")
right:SetBackground(RGBA(0, 0, 0, 255))
right:Open()
right.scale = point(1000, 1000)
right.SetOutsideScale = empty_func
self.right = right
end
function XMovieBlackBars:SetBarsOnSides()
self.left:SetDock("left")
self.right:SetDock("right")
self.top:SetDock(false)
self.bottom:SetDock(false)
self.top:SetVisible(false)
self.bottom:SetVisible(false)
self.left:SetVisible(true)
self.right:SetVisible(true)
end
function XMovieBlackBars:SetBarsTopBottom()
self.left:SetDock(false)
self.right:SetDock(false)
self.top:SetDock("top")
self.bottom:SetDock("bottom")
self.left:SetVisible(false)
self.right:SetVisible(false)
self.top:SetVisible(true)
self.bottom:SetVisible(true)
end
function XMovieBlackBars:SetLayoutSpace(x, y, width, height)
local targetRatio = MulDivRound(16, 100, 9) -- 16:9
local aspectWidth = width
local aspectHeight = MulDivRound(width, 100, targetRatio)
if aspectHeight > height then
-- wider than 16:9 - strips on the sides
aspectWidth = MulDivRound(height, targetRatio, 100)
local blackBarWidth = (width - aspectWidth) / 2
local blackBarWidth = Max(blackBarWidth, 100)
self.left:SetMinWidth(blackBarWidth)
self.right:SetMinWidth(blackBarWidth)
self.left:SetMinHeight(height)
self.right:SetMinHeight(height)
self:SetBarsOnSides()
else
-- narrower than 16:9 - strips on top/bottom
aspectWidth = MulDivRound(height, targetRatio, 100)
aspectHeight = MulDivRound(aspectWidth, 100, targetRatio)
local blackBarHeight = (height - aspectHeight) / 2
blackBarHeight = Max(blackBarHeight, 100)
self.top:SetMinWidth(width)
self.bottom:SetMinWidth(width)
self.top:SetMinHeight(blackBarHeight)
self.bottom:SetMinHeight(blackBarHeight)
self:SetBarsTopBottom()
end
return XWindow.SetLayoutSpace(self, x, y, width, height)
end
function OnMsg.Autorun()
NetSyncEvents.SetPieceDoneWaitingLS = SetPieceDoneWaitingLS
end
function SetPieceDoneWaitingLS()
Msg("SetPieceDoneWaitingLS")
end
function CloseLoadGameLoadingScreen()
-- zulu specific code moved to zulu
end
function XSetpieceDlg:Lifecycle()
CloseLoadGameLoadingScreen()
local setpiece = Setpieces[self.setpiece]
Msg("SetpieceStarting", setpiece)
OnSetpieceStarted(setpiece)
local camera = { GetCamera() }
-- Hide UI, black bars, lock camera
XTemplateSpawn("XCameraLockLayer", self):Open()
XHideDialogs:new({Id = "idHideDialogs", LeaveDialogIds = self:HasMember("LeaveDialogsOpen") and self.LeaveDialogsOpen or false}, self):Open()
local blackbars = XTemplateSpawn("XMovieBlackBars", self)
blackbars:SetId("BlackBars")
blackbars:Open()
if not netInGame or table.count(netGamePlayers) <= 1 then
WaitLoadingScreenClose()
else
if NetIsHost() then
local dlg = GetLoadingScreenDialog()
if dlg then
WaitLoadingScreenClose()
end
NetSyncEvent("SetPieceDoneWaitingLS")
end
WaitMsg("SetPieceDoneWaitingLS", 60000)
end
NetUpdateHash("XSetpieceDlg:Lifecycle_Starting")
-- Interface spawned by the setpiece should be in this child, which is
-- below the letterboxing window.
local uiChildren = XTemplateSpawn("XWindow", self)
uiChildren:SetId("idSetpieceUI")
uiChildren:Open()
uiChildren:SetZOrder(0)
self.setpieceInstance = StartSetpiece(self.setpiece, self.testMode, self.setpiece_seed, self.triggerUnits, unpack_params(self.extra_params))
Msg("SetpieceStarted", setpiece)
self:WaitSetpieceCompletion()
Msg("SetpieceEnding", setpiece)
local skipHint = rawget(self, "idSkipHint")
if skipHint then skipHint:Close() end
if setpiece.RestoreCamera then
SetCamera(unpack_params(camera))
else
SetupInitialCamera()
end
NetUpdateHash("SetpieceStateDone")
ChangeGameState("setpiece_playing", false)
sprocall(EndSetpiece, self.setpiece)
Msg("SetpieceEnded", setpiece) -- this releases control when executing sequential effects, any sleeps in gametimes after this are prone to never exiting due to game getting paused
-- some deinitialization (e.g. restoring Ambient Life unit positions) is done at SetpieceEnded
-- wait several frames to make sure nothing from that is seen on screen
WaitNextFrame(7)
self:Close() -- must be before EndSetpiece and the Msg, so IsSetpiecePlaying returns false during their execution
end
function XSetpieceDlg:GetFadeWin()
if not self.fadeDlg then
local fadeWin = XWindow:new({
Visible = false,
Background = RGBA(0, 0, 0, 255),
AddInterpolation = function(self, int, idx)
if not int then return end
int.flags = (int.flags or 0) | const.intfGameTime
return XWindow.AddInterpolation(self, int, idx)
end,
}, self)
fadeWin:Open()
self.fadeDlg = fadeWin
end
return self.fadeDlg
end
function XSetpieceDlg:FadeOut(fadeOutTime)
if self.skipping_setpiece then return end -- don't mess up the fade out screen created by the skipping logic
local fade_win = self:GetFadeWin()
local fade_time = fadeOutTime
if fade_time > 0 then
if fade_win:GetVisible() then return end -- game is already faded out, nothing to do
fade_win.FadeInTime = fade_time
fade_win:SetVisible(true)
Sleep(fade_time)
else
fade_win:SetVisible(true, "instant")
end
end
function XSetpieceDlg:FadeIn(fadeInDelay, fadeInTime)
if self.skipping_setpiece then return end -- don't mess up the fade out screen created by the skipping logic
local fade_win = self:GetFadeWin()
fade_win.FadeOutTime = fadeInTime
fade_win:SetVisible(true, "instant")
Sleep(fadeInDelay or self.fadeOutDelay)
fade_win:SetVisible(false)
Sleep(fade_win.FadeOutTime)
end
function XSetpieceDlg:WaitSetpieceCompletion()
while not self.setpieceInstance do
WaitMsg("SetpieceStarted", 300)
end
self.setpieceInstance:WaitCompletion()
end
function SkipSetpiece(setpieceInstance)
setpieceInstance:Skip()
end
function XSetpieceDlg:OnShortcut(shortcut, source, ...)
if GameTime() - self.openedAt < self.skipDelay then return "break" end
if RealTime() - terminal.activate_time < self.skipDelay then return "break" end
if rawget(self, "skip_input_done") then return end
if rawget(self, "idSkipHint") and not self.idSkipHint:GetVisible() then
self.idSkipHint:SetVisible(true)
return "break"
end
if shortcut ~= "Escape" and shortcut ~= "ButtonB" and shortcut ~= "MouseL" then return end
if self.skippable and self.setpieceInstance and (not IsRecording() or shortcut == "Escape") then
local skipHint = rawget(self, "idSkipHint")
if skipHint then
skipHint:SetVisible(false)
end
rawset(self, "skip_input_done", true)
SkipSetpiece(self.setpieceInstance)
return "break"
end
end
function SkipAnySetpieces()
local dlg = GetDialog("XSetpieceDlg")
if dlg then
if dlg.setpieceInstance then
dlg.setpieceInstance:Skip()
dlg:WaitSetpieceCompletion()
while GameState.setpiece_playing do
WaitMsg("SetpieceEnded", 100)
end
end
end
end
function IsSetpiecePlaying()
return GameState.setpiece_playing
end
function IsSetpieceTestMode()
local dlg = GetDialog("XSetpieceDlg")
return dlg and dlg.testMode
end
function WaitPlayingSetpiece()
local dlg = GetDialog("XSetpieceDlg")
if dlg then
dlg:Wait()
end
end
function OnMsg.SetpieceStarted()
ObjModified("setpiece_observe")
end
function OnMsg.SetpieceDialogClosed()
ObjModified("setpiece_observe")
end
function MovieRecordSetpiece(id, duration, quality, shutter)
quality = quality or 64
shutter = shutter or 0
OpenDialog("XSetpieceDlg", false, {setpiece = id })
RecordMovie(id .. ".tga", 0, 60, duration, quality, shutter, function() return not IsSetpiecePlaying() end)
end |