Back to Home

ESO Lua File v100030

libraries/zo_scene/zo_scenemanager_leader.lua

[◄ back to folders ]
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
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
ZO_SceneManager_Leader = ZO_SceneManager_Base:Subclass()
--static
ZO_SceneManager_Leader.bypassHideSceneConfirmationReason = 0
function ZO_SceneManager_Leader.AddBypassHideSceneConfirmationReason(name)
    ZO_SceneManager_Leader.bypassHideSceneConfirmationReason = ZO_SceneManager_Leader.bypassHideSceneConfirmationReason + 1
    local reasonName = "ZO_BHSCR_"..name
    internalassert(_G[reasonName] == nil)
    _G[reasonName] = ZO_SceneManager_Leader.bypassHideSceneConfirmationReason
end
ZO_SceneManager_Leader.AddBypassHideSceneConfirmationReason("ALREADY_SEEN")
--class
function ZO_SceneManager_Leader:New(...)
    return ZO_SceneManager_Base.New(self, ...)
end
function ZO_SceneManager_Leader:Initialize(...)
    ZO_SceneManager_Base.Initialize(self, ...)
    self.sceneStack = {}
    self.previousSceneStack = {}
    self.remoteSceneSequenceNumber = 0
    EVENT_MANAGER:RegisterForEvent("SceneManager", EVENT_REMOTE_SCENE_REQUEST, function(eventId, ...) self:OnRemoteSceneRequest(...) end)
end
-- sequence number
function ZO_SceneManager_Leader:GetNextSequenceNumber()
    self.remoteSceneSequenceNumber = self.remoteSceneSequenceNumber + 1
    return self.remoteSceneSequenceNumber
end
function ZO_SceneManager_Leader:OnRemoteSceneRequest(messageOrigin, requestType, sceneName)
    if messageOrigin ~= ZO_REMOTE_SCENE_CHANGE_ORIGIN then
        if requestType == REMOTE_SCENE_REQUEST_TYPE_SHOW_BASE_SCENE then
            self:ShowBaseScene(sceneName)
            return
        end
        local scene = self:GetScene(sceneName)
        if scene then
            if requestType == REMOTE_SCENE_REQUEST_TYPE_SWAP then
                self:SwapCurrentScene(sceneName)
            else
                if self:IsShowing(sceneName) then
                    if requestType == REMOTE_SCENE_REQUEST_TYPE_HIDE then
                        self:Hide(sceneName)
                    end
                else
                    if requestType == REMOTE_SCENE_REQUEST_TYPE_PUSH then
                        self:Push(sceneName)
                    elseif requestType == REMOTE_SCENE_REQUEST_TYPE_SHOW then
                        self:Show(sceneName)
                    end
                end
            end
        end
    end
end
-- scene stack
function ZO_SceneManager_Leader:IsSceneOnStack(sceneName)
    if self.currentScene and self.nextScene and self.nextScenePushed and self.currentScene:GetName() == sceneName then
        return true
    end
    for i, currentSceneName in ipairs(self.sceneStack) do
        if currentSceneName == sceneName then
            return true
        end
    end
    return false
end
function ZO_SceneManager_Leader:IsSceneOnTopOfStack(sceneName)
    if self.currentScene and self.nextScene and self.nextScenePushed then
        return self.nextScene:GetName() == sceneName
    end
    return self.sceneStack[#self.sceneStack] == sceneName
end
function ZO_SceneManager_Leader:WasSceneOnStack(sceneName)
    for i, currentSceneName in ipairs(self.previousSceneStack) do
        if currentSceneName == sceneName then
            return true
        end
    end
    return false
end
function ZO_SceneManager_Leader:WasSceneOnTopOfStack(sceneName)
    if self.currentScene and self.nextScene and not self.nextSceneClearsSceneStack then
        return self.currentScene:GetName() == sceneName
    end
    return self.previousSceneStack[#self.previousSceneStack] == sceneName
end
function ZO_SceneManager_Leader:PushOnSceneStack(sceneName)
    if sceneName ~= self.baseScene:GetName() then
        self:CopySceneStackIntoPrevious()
        table.insert(self.sceneStack, sceneName)
    end
end
function ZO_SceneManager_Leader:PopScenesFromStack(numScenes)
    for i = #self.sceneStack, #self.sceneStack - numScenes + 1, -1 do
        self.sceneStack[i] = nil
    end
end
function ZO_SceneManager_Leader:ClearSceneStack()
end
function ZO_SceneManager_Leader:CopySceneStackIntoPrevious()
    ZO_ClearNumericallyIndexedTable(self.previousSceneStack)
    for i, scene in ipairs(self.sceneStack) do
        self.previousSceneStack[i] = scene
    end
end
function ZO_SceneManager_Leader:CreateStackFromScratch(...)
    self:ShowBaseScene()
    self.dontAddCurrentSceneBackToStack = true
    local numScenes = select("#", ...)
    if numScenes > 0 then
        for i = 1, numScenes - 1 do
            self:PushOnSceneStack(select(i, ...))
        end
        self:Push(select(numScenes, ...))
    end
end
-- next scene overrides
function ZO_SceneManager_Leader:SetNextScene(nextScene, push, nextSceneClearsSceneStack, numScenesNextScenePops)
    ZO_SceneManager_Base.SetNextScene(self, nextScene, push, nextSceneClearsSceneStack, numScenesNextScenePops)
    self.nextScenePushed = push
    self.nextSceneClearsSceneStack = nextSceneClearsSceneStack
    self.numScenesNextScenePops = numScenesNextScenePops
end
-- scene logic
function ZO_SceneManager_Leader:PopScenes(numberOfScenes)
    if self.currentScene and self.currentScene:GetState() ~= SCENE_HIDING then
        local topSceneName
        if #self.sceneStack >= numberOfScenes then
            topSceneName = self.sceneStack[#self.sceneStack - numberOfScenes + 1]
        else
            topSceneName = self.baseScene:GetName()
        end
        local KEEP_SCENE_STACK = false
        self:Show(topSceneName, nil, KEEP_SCENE_STACK, numberOfScenes)
    end
end
function ZO_SceneManager_Leader:PopScenesAndShow(numberOfScenes, sceneToShow)
    if self.currentScene and self.currentScene:GetState() ~= SCENE_HIDING then
        if #self.sceneStack >= numberOfScenes then
            local KEEP_SCENE_STACK = false
            self:Show(sceneToShow, nil, KEEP_SCENE_STACK, numberOfScenes - 1)
        end
    end
end
--[[
Replace the current scene with a new scene while preserving the stack
Current Stack --> New Stack
| Current Scene | | New Scene |
| Scene 2 | | Scene 2 |
| Scene 1 | | Scene 1 |
If there isn't actually anything on the stack, Show is used to replace the scene
--]]
function ZO_SceneManager_Leader:SwapCurrentScene(newCurrentScene)
    if #self.sceneStack >= 1 then
        local NUMBER_OF_SCENES_TO_POP = 1
        self:PopScenesAndShow(NUMBER_OF_SCENES_TO_POP, newCurrentScene)
    else
        self:Show(newCurrentScene)
    end
end
function ZO_SceneManager_Leader:Push(sceneName)
    local IS_PUSH = true
    self:Show(sceneName, IS_PUSH)
end
function ZO_SceneManager_Leader:ShowWithFollowup(sceneName, resultCallback)
    if self:WillCurrentSceneConfirmHide() then
        self.currentScene:RegisterCallback("HideSceneConfirmationResult", resultCallback)
        self:Show(sceneName)
    else
        self:Show(sceneName)
        local ALLOWED_TO_HIDE_CURRENT_SCENE = true
        resultCallback(ALLOWED_TO_HIDE_CURRENT_SCENE)
    end
end
-- Note that push, nextSceneClearsSceneStack, numScenesNextScenePops, and bypassHideSceneConfirmationReason are meant to be INTERNAL parameters. They should NOT
-- be used when calling Show from outside of this file. These same params should be passed to ConfirmHideScene.
function ZO_SceneManager_Leader:Show(sceneName, push, nextSceneClearsSceneStack, numScenesNextScenePops, bypassHideSceneConfirmationReason)
    local currentScene = self.currentScene
    local nextScene = self.scenes[sceneName]
    if nextScene == nil then
        internalassert(false, string.format("Missing scene: %q", sceneName))
        return
    end
    if nextSceneClearsSceneStack == nil then
        nextSceneClearsSceneStack = true
    end
    if numScenesNextScenePops == nil then
        numScenesNextScenePops = 0
    end
    --if a scene exists
    if currentScene then
        if nextScene ~= currentScene then
            --If we need confirmation to hide this scene go request it unless we've already done that and this is the response
            if self:WillCurrentSceneConfirmHide(bypassHideSceneConfirmationReason) then
                return currentScene:ConfirmHideScene(sceneName, push, nextSceneClearsSceneStack, numScenesNextScenePops, bypassHideSceneConfirmationReason)
            end
            if self.nextScene then
                if nextScene ~= self.nextScene then
                    local oldNextScene = self.nextScene
                    self:SetNextScene(nextScene, push, nextSceneClearsSceneStack, numScenesNextScenePops)
                    currentScene:RefreshFragments()
                    local CURRENT_SCENE_IGNORED = ""
                    local NO_SEQUENCE_NUMBER = 0
                    local FRAGMENT_COMPLETE_STATE_IGNORED = false
                    local nextSceneName = self.nextScene and self.nextScene:GetName() or ZO_REMOTE_SCENE_NO_SCENE_IDENTIFIER                        
                    SendLeaderToFollowerSync(ZO_REMOTE_SCENE_CHANGE_ORIGIN, REMOTE_SCENE_SYNC_TYPE_CHANGE_NEXT_SCENE, CURRENT_SCENE_IGNORED, nextSceneName, NO_SEQUENCE_NUMBER, FRAGMENT_COMPLETE_STATE_IGNORED)
                    
                    self:OnNextSceneRemovedFromQueue(oldNextScene, nextScene)
                end
            else
                self:SetNextScene(nextScene, push, nextSceneClearsSceneStack, numScenesNextScenePops)
                self:HideScene(currentScene)
            end
        else
            if currentScene:GetState() == SCENE_HIDING then
                local oldNextScene = self.nextScene
                self:ClearNextScene()
                self:ShowScene(currentScene)
                if oldNextScene then
                    self:OnNextSceneRemovedFromQueue(oldNextScene, self.nextScene)
                end
            end
        end
    else
        --otherwise, start showing this scene
        self.previousScene = self.currentScene
        self:SetCurrentScene(nextScene)
        self:ShowScene(self.currentScene)
    end
end
function ZO_SceneManager_Leader:Hide(sceneName)
    if self.currentScene and self.currentScene:GetName() == sceneName and self.currentScene:GetState() ~= SCENE_HIDING then
        self:PopScenes(1)
    end
end
function ZO_SceneManager_Leader:WillCurrentSceneConfirmHide(bypassHideSceneConfirmationReason)
    local currentScene = self.currentScene
    return currentScene and currentScene:HasHideSceneConfirmation() and bypassHideSceneConfirmationReason ~= ZO_BHSCR_ALREADY_SEEN and currentScene:IsShowing()
end
function ZO_SceneManager_Leader:ShowScene(scene)
    ZO_SceneManager_Base.ShowScene(self, scene, self:GetNextSequenceNumber())
end
function ZO_SceneManager_Leader:HideScene(scene)
    ZO_SceneManager_Base.HideScene(self, scene, self:GetNextSequenceNumber())
end
function ZO_SceneManager_Leader:SyncFollower()
    local currentScene = self:GetCurrentScene()
    local syncType = currentScene:IsShowing() and REMOTE_SCENE_SYNC_TYPE_SHOW_SCENE or REMOTE_SCENE_SYNC_TYPE_HIDE_SCENE
    local currentSceneName = currentScene:GetName()
    local sequenceNumber = 0
    local currentSceneTransitionComplete = true
    if currentScene:IsRemoteScene() then
        sequenceNumber = currentScene:GetSequenceNumber()
        if currentScene:GetState() == SCENE_SHOWING or currentScene:GetState() == SCENE_HIDING then
            currentSceneTransitionComplete = currentScene:AreFragmentsDoneTransitioning()
        end
    end
    local nextSceneName = self.nextScene and self.nextScene:GetName() or ZO_REMOTE_SCENE_NO_SCENE_IDENTIFIER
    SendLeaderToFollowerSync(ZO_REMOTE_SCENE_CHANGE_ORIGIN, syncType, currentSceneName, nextSceneName, sequenceNumber, currentSceneTransitionComplete)
end
function ZO_SceneManager_Leader:OnSceneStateChange(scene, oldState, newState)
    if scene == self:GetCurrentScene() then
        if newState == SCENE_HIDING or newState == SCENE_SHOWING then
            self:SyncFollower()
        end
    end
    ZO_SceneManager_Base.OnSceneStateChange(self, scene, oldState, newState)
end
-- override of ZO_SceneManager_Base:OnSceneStateHidden
function ZO_SceneManager_Leader:OnSceneStateHidden(scene)
    local lastSceneGroup = scene:GetSceneGroup()
    local nextSceneGroup
    local currentNextScene = self.nextScene
    if currentNextScene then
        nextSceneGroup = currentNextScene:GetSceneGroup()
    end
    if lastSceneGroup ~= nextSceneGroup then
        if lastSceneGroup ~= nil then
            lastSceneGroup:SetState(SCENE_GROUP_HIDDEN)
        end
        if nextSceneGroup ~= nil then
            nextSceneGroup:SetState(SCENE_GROUP_SHOWING)
            -- Check to see if self.nextScene has changed as a result of nextSceneGroup:SetState(SCENE_GROUP_SHOWING)
            if currentNextScene ~= self.nextScene then
                -- If self.nextScene has changed and currentNextScene's scene group is no longer showing, we set its state to SCENE_GROUP_HIDDEN
                local newNextSceneGroup = self.nextScene and self.nextScene:GetSceneGroup()
                if nextSceneGroup ~= newNextSceneGroup then
                    nextSceneGroup:SetState(SCENE_GROUP_HIDDEN)
                end
                -- Update currentNextScene to the new scene
                currentNextScene = self.nextScene
            end
        end
    end
    if currentNextScene then
        local push = self.nextScenePushed
        if push then
            if not self.dontAddCurrentSceneBackToStack then
                self:PushOnSceneStack(scene:GetName())
            end
        elseif self.nextSceneClearsSceneStack then
            self:ClearSceneStack()
        elseif self.numScenesNextScenePops > 0 then
            self:PopScenesFromStack(self.numScenesNextScenePops)
        end
        if self.dontAddCurrentSceneBackToStack then
            self.dontAddCurrentSceneBackToStack = false
        else
            self.previousScene = self:GetCurrentScene()
        end
        self:SetCurrentScene(currentNextScene)
        self:ClearNextScene()
        self:ShowScene(self:GetCurrentScene(), push)
    end
end
function ZO_SceneManager_Leader:SendFragmentCompleteMessage()
    self:SyncFollower()
end
function ZO_SceneManager_Leader:RequestShowLeaderBaseScene()
    self:ShowBaseScene()
end