274 lines
7.4 KiB
Lua
274 lines
7.4 KiB
Lua
-- Written by Kip Turner, Copyright Roblox 2015
|
|
|
|
local CoreGui = game:GetService("CoreGui")
|
|
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
|
|
local Modules = GuiRoot:FindFirstChild("Modules")
|
|
local ShellModules = Modules:FindFirstChild("Shell")
|
|
local Utility = require(ShellModules:FindFirstChild('Utility'))
|
|
|
|
local Analytics = require(ShellModules:FindFirstChild('Analytics'))
|
|
local SoundManager = require(ShellModules:FindFirstChild('SoundManager'))
|
|
local GlobalSettings = require(ShellModules:FindFirstChild('GlobalSettings'))
|
|
|
|
local XboxRoduxScreenFocus = settings():GetFFlag("XboxRoduxScreenFocus")
|
|
|
|
local ScreenManager = {}
|
|
|
|
local ScreenStack = {}
|
|
local ScreenToHideMap = {}
|
|
|
|
local ScreenGuis = {[1] = GuiRoot}
|
|
|
|
local function ContainsScreenInternal(screen)
|
|
local foundScreenIndex = nil
|
|
for i, otherScreen in pairs(ScreenStack) do
|
|
if otherScreen == screen then
|
|
foundScreenIndex = i
|
|
end
|
|
end
|
|
|
|
return foundScreenIndex
|
|
end
|
|
|
|
local function GetScreenPriorityInternal(screen)
|
|
local priority = GlobalSettings.DefaultPriority
|
|
if screen.GetPriority ~= nil then
|
|
priority = screen:GetPriority()
|
|
end
|
|
return priority
|
|
end
|
|
|
|
local function SetRBXEventStream_Screen(screen, status)
|
|
if screen and type(screen.GetAnalyticsInfo) == "function" then
|
|
local screenAnalyticsInfo = screen:GetAnalyticsInfo()
|
|
if type(screenAnalyticsInfo) == "table" and screenAnalyticsInfo[Analytics.WidgetNames('WidgetId')] then
|
|
screenAnalyticsInfo.Status = status
|
|
Analytics.SetRBXEventStream("Widget", screenAnalyticsInfo)
|
|
end
|
|
end
|
|
end
|
|
|
|
function ScreenManager:GetInsertIndexForScreen(screen)
|
|
local screenPriority = GetScreenPriorityInternal(screen)
|
|
local currentScreen = self:GetTopScreen()
|
|
while currentScreen and GetScreenPriorityInternal(currentScreen) > screenPriority do
|
|
currentScreen = self:GetScreenBelow(currentScreen)
|
|
end
|
|
if currentScreen then
|
|
local currentScreenIndex = ContainsScreenInternal(currentScreen)
|
|
if currentScreenIndex then
|
|
return currentScreenIndex + 1
|
|
end
|
|
end
|
|
return 1
|
|
end
|
|
|
|
function ScreenManager:GetGuiRoot()
|
|
return GuiRoot
|
|
end
|
|
|
|
function ScreenManager:GetScreenGuiByPriority(priority)
|
|
priority = math.max(1, priority)
|
|
if not ScreenGuis[priority] then
|
|
for i = 1, priority do
|
|
if not ScreenGuis[i] then
|
|
ScreenGuis[i] = Utility.Create'ScreenGui'
|
|
{
|
|
Name = 'AppShell' .. tostring(i);
|
|
Parent = CoreGui;
|
|
}
|
|
end
|
|
end
|
|
end
|
|
|
|
return ScreenGuis[priority]
|
|
end
|
|
|
|
-- TODO: handle race conditions for opening multiple screens
|
|
local openScreenEntryCount = 0
|
|
local openScreenExitCount = 0
|
|
function ScreenManager:OpenScreen(screen, hideCurrent)
|
|
if openScreenEntryCount ~= openScreenExitCount then
|
|
Utility.DebugLog("ScreenManager: OpenScreen Re-entry detected" , openScreenEntryCount, openScreenExitCount)
|
|
end
|
|
openScreenEntryCount = openScreenEntryCount + 1
|
|
|
|
if hideCurrent == nil then
|
|
hideCurrent = true
|
|
end
|
|
|
|
local currentScreen = self:GetTopScreen()
|
|
local insertIndex = self:GetInsertIndexForScreen(screen)
|
|
local isNewTop = insertIndex > #ScreenStack
|
|
|
|
if not isNewTop then
|
|
hideCurrent = false
|
|
end
|
|
|
|
if currentScreen ~= screen then
|
|
local foundScreenIndex = ContainsScreenInternal(screen)
|
|
|
|
if foundScreenIndex then
|
|
table.remove(ScreenStack, foundScreenIndex)
|
|
end
|
|
|
|
if currentScreen then
|
|
currentScreen:RemoveFocus()
|
|
if hideCurrent then
|
|
currentScreen:Hide()
|
|
end
|
|
ScreenToHideMap[currentScreen] = hideCurrent
|
|
end
|
|
|
|
table.insert(ScreenStack, insertIndex, screen)
|
|
|
|
if isNewTop then
|
|
if ScreenToHideMap[screen] ~= false then
|
|
screen:Show()
|
|
SetRBXEventStream_Screen(screen, "Show")
|
|
end
|
|
|
|
if screen == self:GetTopScreen() then
|
|
screen:Focus()
|
|
SetRBXEventStream_Screen(screen, "Focus")
|
|
end
|
|
else
|
|
ScreenToHideMap[screen] = true
|
|
end
|
|
end
|
|
|
|
openScreenExitCount = openScreenExitCount + 1
|
|
end
|
|
|
|
local closeCurrentEntryCount = 0
|
|
local closeCurrentExitCount = 0
|
|
function ScreenManager:CloseCurrent()
|
|
if closeCurrentEntryCount ~= closeCurrentExitCount then
|
|
Utility.DebugLog("ScreenManager: CloseScreen Re-entry detected" , closeCurrentEntryCount, closeCurrentExitCount)
|
|
end
|
|
closeCurrentEntryCount = closeCurrentEntryCount + 1
|
|
|
|
local currentScreen = ScreenStack[#ScreenStack]
|
|
local belowScreen = currentScreen and self:GetScreenBelow(currentScreen)
|
|
if currentScreen then
|
|
currentScreen:Hide()
|
|
currentScreen:RemoveFocus()
|
|
if currentScreen.ScreenRemoved then
|
|
currentScreen:ScreenRemoved()
|
|
end
|
|
SetRBXEventStream_Screen(currentScreen, "Close")
|
|
table.remove(ScreenStack, #ScreenStack)
|
|
ScreenToHideMap[currentScreen] = nil
|
|
end
|
|
|
|
|
|
-- if belowScreen and belowScreen ~= self:GetTopScreen() then return end
|
|
local newTop = belowScreen
|
|
if newTop and newTop == self:GetTopScreen() then
|
|
local showNewTop = (ScreenToHideMap[newTop] == true)
|
|
-- spawn(function()
|
|
if showNewTop then
|
|
newTop:Show()
|
|
SetRBXEventStream_Screen(newTop, "Show")
|
|
end
|
|
if newTop == self:GetTopScreen() then
|
|
newTop:Focus()
|
|
SetRBXEventStream_Screen(newTop, "Focus")
|
|
end
|
|
-- end)
|
|
end
|
|
closeCurrentExitCount = closeCurrentExitCount + 1
|
|
end
|
|
|
|
function ScreenManager:ContainsScreen(screen)
|
|
local index = ContainsScreenInternal(screen)
|
|
if index then
|
|
return ScreenStack[index]
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function ScreenManager:GetScreenBelow(screen)
|
|
local thisScreenIndex = ContainsScreenInternal(screen)
|
|
if thisScreenIndex then
|
|
return ScreenStack[thisScreenIndex - 1]
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function ScreenManager:GetTopScreen()
|
|
return ScreenStack[#ScreenStack]
|
|
end
|
|
|
|
|
|
----- TWEENS -----
|
|
|
|
local function FadeInElement(element, tweeners)
|
|
if element == nil then return end
|
|
if element:IsA('ImageLabel') or element:IsA('ImageButton') then
|
|
table.insert(tweeners, Utility.PropertyTweener(element, 'ImageTransparency', 1, element.ImageTransparency, 0.5, Utility.EaseOutQuad))
|
|
end
|
|
if element:IsA('GuiObject') then
|
|
table.insert(tweeners, Utility.PropertyTweener(element, 'BackgroundTransparency', 1, element.BackgroundTransparency, 0.5, Utility.EaseOutQuad))
|
|
end
|
|
if element:IsA('TextLabel') or element:IsA('TextBox') or element:IsA('TextButton') then
|
|
table.insert(tweeners, Utility.PropertyTweener(element, 'TextTransparency', 1, element.TextTransparency, 0.5, Utility.EaseOutQuad))
|
|
end
|
|
for _, child in pairs(element:GetChildren()) do
|
|
FadeInElement(child, tweeners)
|
|
end
|
|
end
|
|
|
|
function ScreenManager:FadeInSitu(guiObject)
|
|
local tweeners = {}
|
|
if guiObject then
|
|
FadeInElement(guiObject, tweeners)
|
|
end
|
|
return tweeners
|
|
end
|
|
|
|
function ScreenManager:DefaultFadeIn(guiObject)
|
|
local tweeners = {}
|
|
|
|
if guiObject then
|
|
table.insert(tweeners, Utility.PropertyTweener(guiObject, 'Position', guiObject.Position + UDim2.new(0.15, 0, 0, 0), guiObject.Position, 0.5,
|
|
function(t,b,c,d)
|
|
if t >= d then return b + c end
|
|
t = t / d;
|
|
local tComputed = t*(t-2)
|
|
return -UDim2.new(c.X.Scale * tComputed, c.X.Offset * tComputed, c.Y.Scale * tComputed, c.Y.Offset * tComputed) + b
|
|
end))
|
|
|
|
FadeInElement(guiObject, tweeners)
|
|
end
|
|
|
|
return tweeners
|
|
end
|
|
|
|
function ScreenManager:DefaultCancelFade(tweens)
|
|
if tweens then
|
|
for _, tween in pairs(tweens) do
|
|
tween:Finish()
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
function ScreenManager:PlayDefaultOpenSound()
|
|
SoundManager:Play('ScreenChange')
|
|
end
|
|
|
|
-- replace current ScreenManager with new APIs
|
|
if XboxRoduxScreenFocus then
|
|
local screenManager2 = require(ShellModules.ScreenManager2)
|
|
|
|
ScreenManager.OpenScreen = screenManager2.OpenScreen
|
|
ScreenManager.CloseCurrent = screenManager2.CloseCurrent
|
|
ScreenManager.GetTopScreen = screenManager2.GetTopScreen
|
|
ScreenManager.ContainsScreen = screenManager2.ContainsScreen
|
|
end
|
|
|
|
|
|
return ScreenManager
|