349 lines
9.2 KiB
Lua
349 lines
9.2 KiB
Lua
local CoreGui = game:GetService("CoreGui")
|
|
local GuiService = game:GetService('GuiService')
|
|
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
|
|
local Modules = GuiRoot:FindFirstChild("Modules")
|
|
local ShellModules = Modules:FindFirstChild("Shell")
|
|
|
|
local GlobalSettings = require(ShellModules:FindFirstChild('GlobalSettings'))
|
|
local Strings = require(ShellModules:FindFirstChild('LocalizedStrings'))
|
|
local Utility = require(ShellModules:FindFirstChild('Utility'))
|
|
local LoadingWidget = require(ShellModules:FindFirstChild('LoadingWidget'))
|
|
|
|
local CarouselView = require(ShellModules:FindFirstChild('CarouselView'))
|
|
local CarouselController = require(ShellModules:FindFirstChild('CarouselController'))
|
|
|
|
|
|
local function GameCarouselItem(size, sortName, getGameCollection, onNewGameSelected, hasResultsChanged)
|
|
local this = {}
|
|
|
|
local myCarouselController = nil
|
|
local controllerMutex = false
|
|
local myCarouselView = CarouselView()
|
|
local TEXT_OFFSET = 112
|
|
local CAROUSEL_OFFSET = 110
|
|
local hasResults = true
|
|
local lockInPUP = false
|
|
--Initially is unlocked
|
|
local locked = false
|
|
local currentLoader = nil
|
|
local inFocus = false
|
|
|
|
local noSelectionObject = Utility.Create'ImageLabel'
|
|
{
|
|
Name = 'NoSelectionObject';
|
|
BackgroundTransparency = 1;
|
|
}
|
|
|
|
local container = Utility.Create'ImageButton'
|
|
{
|
|
Name = sortName.." ImageButton";
|
|
Size = size;
|
|
Position = UDim2.new(0, 0, 0, 0);
|
|
BorderSizePixel = 0;
|
|
BackgroundTransparency = 1;
|
|
ClipsDescendants = false;
|
|
AutoButtonColor = false;
|
|
SelectionImageObject = noSelectionObject;
|
|
Selectable = false;
|
|
}
|
|
|
|
local selectionHolder = Utility.Create'ImageLabel'
|
|
{
|
|
Name = sortName.." SelectionHolder";
|
|
BackgroundTransparency = 1;
|
|
Size = UDim2.new(0, 400, 1, 0);
|
|
Position = UDim2.new(0, 50, 0, 50);
|
|
SelectionImageObject = noSelectionObject;
|
|
Selectable = true;
|
|
Parent = container;
|
|
}
|
|
|
|
selectionHolder.NextSelectionLeft = selectionHolder
|
|
selectionHolder.NextSelectionRight = selectionHolder
|
|
|
|
local nameLabel = Utility.Create'TextLabel'
|
|
{
|
|
Name = "NameLabel";
|
|
Text = Strings:LocalizedString("LoadingWord");
|
|
Size = UDim2.new(0, 0, 0, 0);
|
|
Position = UDim2.new(0, TEXT_OFFSET, 0, 22);
|
|
TextXAlignment = Enum.TextXAlignment.Left;
|
|
TextColor3 = GlobalSettings.WhiteTextColor;
|
|
Font = GlobalSettings.RegularFont;
|
|
FontSize = Enum.FontSize.Size36; -- GlobalSettings.TitleSize;
|
|
BackgroundTransparency = 1;
|
|
Selectable = false;
|
|
Parent = container;
|
|
}
|
|
|
|
local function loadGameCollection(carouselController, carouselView, container)
|
|
local loaderImgTransparency = 0
|
|
if currentLoader then
|
|
loaderImgTransparency = Utility.Clamp(0, 1, currentLoader:GetTransparency())
|
|
currentLoader:Cleanup()
|
|
end
|
|
nameLabel.Text = Strings:LocalizedString("LoadingWord");
|
|
selectionHolder.Selectable = true
|
|
|
|
spawn(function()
|
|
local loader = LoadingWidget(
|
|
{ Parent = container; Position = UDim2.new(0.5, CAROUSEL_OFFSET, 0.5, 50); ImageTransparency = loaderImgTransparency },
|
|
{
|
|
function()
|
|
--The InitializeAsync will also remove old items if exist
|
|
carouselController:InitializeAsync(getGameCollection())
|
|
--The Connect will also remove old connections if exist
|
|
carouselController:Connect()
|
|
carouselController.NewItemSelected:connect(onNewGameSelected)
|
|
|
|
--Make sure this thread is the latest one, if so,
|
|
--make the callback and update selection
|
|
if this and myCarouselController == carouselController and myCarouselView == carouselView then
|
|
hasResults = carouselController:HasResults()
|
|
hasResultsChanged(this)
|
|
if hasResults then
|
|
selectionHolder.Selectable = false
|
|
nameLabel.Text = sortName
|
|
if this:IsSelected() then
|
|
this:RemoveFocus()
|
|
this:Focus()
|
|
end
|
|
else
|
|
selectionHolder.Selectable = true
|
|
nameLabel.Text = ""
|
|
end
|
|
else
|
|
if carouselView then
|
|
carouselView:SetParent(nil)
|
|
end
|
|
end
|
|
end
|
|
}
|
|
)
|
|
|
|
if currentLoader then
|
|
currentLoader:SetParent(nil)
|
|
end
|
|
|
|
currentLoader = loader
|
|
loader:AwaitFinished()
|
|
loader:Cleanup()
|
|
end)
|
|
end
|
|
|
|
function this:Init(Transparency)
|
|
Transparency = Transparency and Transparency or 0
|
|
myCarouselView:SetTransparency(Transparency)
|
|
myCarouselView:SetSize(UDim2.new(0, 1700, 0, 232))
|
|
myCarouselView:SetPosition(UDim2.new(0, CAROUSEL_OFFSET, 0, 50))
|
|
myCarouselView:SetPadding(20)
|
|
myCarouselView:SetItemSizePercentOfContainer(0.84)
|
|
myCarouselView:SetSelectionImageObject(
|
|
Utility.Create'ImageLabel'
|
|
{
|
|
BackgroundTransparency = 1;
|
|
}
|
|
)
|
|
myCarouselView:SetParent(container)
|
|
|
|
if myCarouselController then
|
|
myCarouselController:Disconnect()
|
|
end
|
|
|
|
if myCarouselController then
|
|
local prevFrontPageIndex, prevEndPageIndex, prevAbsoluteDataIndex = myCarouselController:GetIndexData()
|
|
myCarouselController = CarouselController(myCarouselView, true, prevFrontPageIndex, prevEndPageIndex, prevAbsoluteDataIndex)
|
|
else
|
|
myCarouselController = CarouselController(myCarouselView, true)
|
|
end
|
|
myCarouselController:SetLoadBuffer(15)
|
|
loadGameCollection(myCarouselController, myCarouselView, container)
|
|
end
|
|
|
|
function this:Refresh()
|
|
if myCarouselView then
|
|
if this:IsSelected() then
|
|
selectionHolder.Selectable = true
|
|
Utility.SetSelectedCoreObject(selectionHolder)
|
|
--Clear game data
|
|
onNewGameSelected(nil)
|
|
end
|
|
--Reset the old CarouselView
|
|
myCarouselView:RemoveFocus()
|
|
myCarouselView:RemoveAllItems()
|
|
myCarouselView:SetParent(nil)
|
|
|
|
--Init with previous Transparency
|
|
local prevTransparency = myCarouselView:GetTransparency()
|
|
myCarouselView = CarouselView()
|
|
this:Init(prevTransparency)
|
|
end
|
|
end
|
|
|
|
function this:HasResults()
|
|
return hasResults
|
|
end
|
|
|
|
function this:GetContainer()
|
|
return container
|
|
end
|
|
|
|
function this:ContainsItem(item)
|
|
return myCarouselView:ContainsItem(item)
|
|
end
|
|
|
|
function this:GetCarouselView()
|
|
return myCarouselView
|
|
end
|
|
|
|
function this:GetSortName()
|
|
return sortName
|
|
end
|
|
|
|
function this:GetNameText()
|
|
return nameLabel.Text
|
|
end
|
|
|
|
function this:SetNameText(name)
|
|
nameLabel.Text = name
|
|
end
|
|
|
|
-- Important subtle detail: the center of this needs to be in about the same
|
|
-- x-coordinate as the first item in each carousel so that selection doesn't
|
|
-- move laterally when you arrow up and down.
|
|
local LockOverlay = Utility.Create'ImageLabel'
|
|
{
|
|
Name = "LockOverlay";
|
|
Size = UDim2.new(0, 400, 1, 0);
|
|
Position = UDim2.new(0, 50, 0, 50);
|
|
BackgroundTransparency = 1;
|
|
Selectable = true;
|
|
SelectionImageObject = Utility.Create'ImageLabel'
|
|
{
|
|
BackgroundTransparency = 1;
|
|
};
|
|
ZIndex = 3;
|
|
}
|
|
|
|
LockOverlay.NextSelectionRight = LockOverlay
|
|
LockOverlay.NextSelectionLeft = LockOverlay
|
|
|
|
function this:Lock()
|
|
locked = true
|
|
LockOverlay.Parent = container
|
|
if this:IsSelected() then
|
|
this:RemoveFocus()
|
|
this:Focus()
|
|
end
|
|
myCarouselView:SetSelectable(false)
|
|
myCarouselView:SetClipsDescendants(true)
|
|
end
|
|
|
|
function this:Unlock()
|
|
locked = false
|
|
myCarouselView:SetSelectable(true)
|
|
myCarouselView:SetClipsDescendants(false)
|
|
if this:IsSelected() then
|
|
this:RemoveFocus()
|
|
this:Focus()
|
|
end
|
|
LockOverlay.Parent = nil
|
|
end
|
|
|
|
function this:IsLocked()
|
|
return locked
|
|
end
|
|
|
|
function this:SetLockInPUP(State)
|
|
lockInPUP = State
|
|
end
|
|
|
|
function this:GetLockInPUP()
|
|
return lockInPUP
|
|
end
|
|
|
|
function this:Focus()
|
|
if inFocus then return end
|
|
inFocus = true
|
|
if this then
|
|
if locked then
|
|
if myCarouselController then
|
|
onNewGameSelected(myCarouselController:GetFrontGameData(), true)
|
|
end
|
|
Utility.SetSelectedCoreObject(LockOverlay)
|
|
else
|
|
myCarouselView:Focus()
|
|
if not selectionHolder.Selectable and myCarouselView:GetAvailableItem() then
|
|
Utility.SetSelectedCoreObject(myCarouselView:GetAvailableItem())
|
|
else
|
|
Utility.SetSelectedCoreObject(selectionHolder)
|
|
--Clear game data
|
|
onNewGameSelected(nil)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function this:RemoveFocus()
|
|
if not inFocus then return end
|
|
myCarouselView:RemoveFocus()
|
|
inFocus = false
|
|
end
|
|
|
|
|
|
local fadeDuration = 0.2
|
|
local targetTextTransparency = 0
|
|
local textTransparencyTweens = {}
|
|
|
|
local function setTextTransparency(value, duration, refresh)
|
|
if not refresh and value == targetTextTransparency then return end
|
|
|
|
if duration then
|
|
targetTextTransparency = Utility.Clamp(0, 1, targetTextTransparency)
|
|
if not refresh and value == targetTextTransparency then return end
|
|
else
|
|
duration = fadeDuration
|
|
end
|
|
|
|
Utility.CancelTweens(textTransparencyTweens)
|
|
|
|
table.insert(textTransparencyTweens,
|
|
Utility.PropertyTweener(
|
|
nameLabel,
|
|
'TextTransparency',
|
|
targetTextTransparency,
|
|
value,
|
|
duration,
|
|
Utility.EaseOutQuad,
|
|
true))
|
|
|
|
targetTextTransparency = value
|
|
end
|
|
|
|
function this:SetTransparency(imageTransparency, textTransparency, duration, refresh)
|
|
setTextTransparency(textTransparency, duration, refresh)
|
|
myCarouselView:SetTransparency(imageTransparency, duration, refresh)
|
|
if currentLoader then
|
|
currentLoader:SetTransparency(Utility.Clamp(0, 1, imageTransparency))
|
|
end
|
|
end
|
|
|
|
function this:Destroy()
|
|
container:Destroy()
|
|
this = nil
|
|
end
|
|
|
|
function this:IsSelected()
|
|
if GuiService.SelectedCoreObject then
|
|
return GuiService.SelectedCoreObject == selectionHolder or myCarouselView:ContainsItem(GuiService.SelectedCoreObject) or
|
|
GuiService.SelectedCoreObject == LockOverlay
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
return this
|
|
end
|
|
|
|
return GameCarouselItem
|