455 lines
15 KiB
Lua
455 lines
15 KiB
Lua
--[[
|
|
// BaseCarouselScreen.lua
|
|
|
|
// Creates a base screen for a carousel view
|
|
// To be used for game genre and search screens
|
|
|
|
// Creates a Play and Favorite Button, details view (votes, description), and
|
|
// a carousel view
|
|
]]
|
|
local CoreGui = game:GetService("CoreGui")
|
|
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
|
|
local Modules = GuiRoot:FindFirstChild("Modules")
|
|
local ShellModules = Modules:FindFirstChild("Shell")
|
|
local PlatformService = nil
|
|
pcall(function() PlatformService = game:GetService('PlatformService') end)
|
|
|
|
local AssetManager = require(ShellModules:FindFirstChild('AssetManager'))
|
|
local Errors = require(ShellModules:FindFirstChild('Errors'))
|
|
local ErrorOverlayModule = require(ShellModules:FindFirstChild('ErrorOverlay'))
|
|
local GameData = require(ShellModules:FindFirstChild('GameData'))
|
|
local GameJoinModule = require(ShellModules:FindFirstChild('GameJoin'))
|
|
local GlobalSettings = require(ShellModules:FindFirstChild('GlobalSettings'))
|
|
local LoadingWidget = require(ShellModules:FindFirstChild('LoadingWidget'))
|
|
local ScreenManager = require(ShellModules:FindFirstChild('ScreenManager'))
|
|
local SoundManager = require(ShellModules:FindFirstChild('SoundManager'))
|
|
local Strings = require(ShellModules:FindFirstChild('LocalizedStrings'))
|
|
local Utility = require(ShellModules:FindFirstChild('Utility'))
|
|
|
|
local BaseScreen = require(ShellModules:FindFirstChild('BaseScreen'))
|
|
local CarouselView = require(ShellModules:FindFirstChild('CarouselView'))
|
|
local CarouselController = require(ShellModules:FindFirstChild('CarouselController'))
|
|
local VoteFrame = require(ShellModules:FindFirstChild('VoteFrame'))
|
|
local Analytics = require(ShellModules:FindFirstChild('Analytics'))
|
|
|
|
local function CreateBaseCarouselScreen()
|
|
local this = BaseScreen()
|
|
|
|
local newGameSelectedCn = nil
|
|
local dataModelViewChangedCn = nil
|
|
|
|
local canJoinGame = true
|
|
local returnedFromGame = true
|
|
|
|
-- we need to move ZIndex up because of drop shadows
|
|
local BASE_ZINDEX = 2
|
|
|
|
local playButtonColor = GlobalSettings.GreenButtonColor
|
|
local playButtonSelectedColor = GlobalSettings.GreenSelectedButtonColor
|
|
local favoriteButtonColor = GlobalSettings.GreyButtonColor
|
|
local favoriteSelectedButtonColor = GlobalSettings.GreySelectedButtonColor
|
|
local buttonTextColor = GlobalSettings.WhiteTextColor
|
|
local buttonSelectedTextColor = GlobalSettings.TextSelectedColor
|
|
|
|
local viewContainer = Utility.Create'Frame'
|
|
{
|
|
Name = "ViewContainer";
|
|
Size = UDim2.new(1, 0, 1, 0);
|
|
BackgroundTransparency = 1;
|
|
Parent = this.Container;
|
|
}
|
|
this.ViewContainer = viewContainer
|
|
|
|
local myCarouselView = CarouselView()
|
|
myCarouselView:SetSize(UDim2.new(0, 1724, 0, 450))
|
|
myCarouselView:SetPosition(UDim2.new(0, 0, 0, 240))
|
|
myCarouselView:SetPadding(18)
|
|
myCarouselView:SetItemSizePercentOfContainer(2/3)
|
|
myCarouselView:SetParent(viewContainer)
|
|
|
|
local myCarouselController = CarouselController(myCarouselView)
|
|
|
|
local playButton = Utility.Create'ImageButton'
|
|
{
|
|
Name = "PlayButton";
|
|
Size = UDim2.new(0, 228, 0, 72);
|
|
Position = UDim2.new(0, 0, 1, -77);
|
|
BackgroundTransparency = 1;
|
|
ImageColor3 = playButtonColor;
|
|
Image = GlobalSettings.RoundCornerButtonImage;
|
|
ScaleType = Enum.ScaleType.Slice;
|
|
SliceCenter = Rect.new(Vector2.new(4, 4), Vector2.new(28, 28));
|
|
ZIndex = BASE_ZINDEX;
|
|
Parent = viewContainer;
|
|
|
|
SoundManager:CreateSound('MoveSelection');
|
|
AssetManager.CreateShadow(1);
|
|
}
|
|
local playText = Utility.Create'TextLabel'
|
|
{
|
|
Name = "PlayText";
|
|
Size = UDim2.new(1, 0, 1, 0);
|
|
BackgroundTransparency = 1;
|
|
Text = Strings:LocalizedString("PlayWord");
|
|
Font = GlobalSettings.RegularFont;
|
|
FontSize = GlobalSettings.ButtonSize;
|
|
TextColor3 = buttonTextColor;
|
|
ZIndex = BASE_ZINDEX;
|
|
Parent = playButton;
|
|
}
|
|
Utility.ResizeButtonWithText(playButton, playText, GlobalSettings.TextHorizontalPadding)
|
|
|
|
local favoriteButton = Utility.Create'ImageButton'
|
|
{
|
|
Name = "FavoriteButton";
|
|
Position = UDim2.new(0, playButton.Size.X.Offset + 10, 1, -77);
|
|
Size = UDim2.new(0, 228, 0, 72);
|
|
BackgroundTransparency = 1;
|
|
ImageColor3 = favoriteButtonColor;
|
|
Image = GlobalSettings.RoundCornerButtonImage;
|
|
ScaleType = Enum.ScaleType.Slice;
|
|
SliceCenter = Rect.new(Vector2.new(4, 4), Vector2.new(28, 28));
|
|
ZIndex = BASE_ZINDEX;
|
|
Parent = viewContainer;
|
|
|
|
SoundManager:CreateSound('MoveSelection');
|
|
AssetManager.CreateShadow(1);
|
|
}
|
|
local favoriteText = Utility.Create'TextLabel'
|
|
{
|
|
Name = "FavoriteText";
|
|
Size = UDim2.new(1, 0, 1, 0);
|
|
BackgroundTransparency = 1;
|
|
Text = Strings:LocalizedString("FavoriteWord");
|
|
Font = GlobalSettings.RegularFont;
|
|
FontSize = GlobalSettings.ButtonSize;
|
|
TextColor3 = buttonTextColor;
|
|
ZIndex = 2;
|
|
Parent = favoriteButton;
|
|
}
|
|
|
|
local favoriteStarImage = Utility.Create'ImageLabel'
|
|
{
|
|
Name = "FavoriteStarImage";
|
|
Size = UDim2.new(0, 32, 0, 31);
|
|
Position = UDim2.new(0, 16, 0.5, -31/2);
|
|
BackgroundTransparency = 1;
|
|
Image = 'rbxasset://textures/ui/Shell/Icons/FavoriteStar@1080.png';
|
|
Visible = false;
|
|
ZIndex = BASE_ZINDEX;
|
|
Parent = favoriteButton;
|
|
}
|
|
|
|
--Make it big enough to hold the star and text
|
|
Utility.ResizeButtonWithDynamicText(favoriteButton, favoriteText, {Strings:LocalizedString("FavoritedWord")},
|
|
GlobalSettings.TextHorizontalPadding + (favoriteStarImage.Position.X.Offset + favoriteStarImage.Size.X.Offset + 12) / 2)
|
|
|
|
-- begin game details content
|
|
local gameDetailsContainer = Utility.Create'Frame'
|
|
{
|
|
Name = "GameDetailsContainer";
|
|
Size = UDim2.new(0, 0, 0, 0);
|
|
Position = UDim2.new(0, 18, 0, 732);
|
|
BackgroundTransparency = 1;
|
|
Parent = viewContainer;
|
|
}
|
|
local gameTitle = Utility.Create'TextLabel'
|
|
{
|
|
Name = "GameTitleLabel";
|
|
Size = UDim2.new(0, 0, 0, 0);
|
|
Position = UDim2.new(0, 0, 0, 0);
|
|
BackgroundTransparency = 1;
|
|
Text = "";
|
|
TextColor3 = GlobalSettings.WhiteTextColor;
|
|
TextXAlignment = Enum.TextXAlignment.Left;
|
|
Font = GlobalSettings.LightFont;
|
|
FontSize = GlobalSettings.HeaderSize;
|
|
Parent = gameDetailsContainer;
|
|
}
|
|
local voteFrame = VoteFrame(gameDetailsContainer, UDim2.new(0, 38, 0, 46))
|
|
local voteFrameContainer = voteFrame:GetContainer()
|
|
|
|
local thumbsUpImage = Utility.Create'ImageLabel'
|
|
{
|
|
Name = "ThumbsUpImage";
|
|
Size = UDim2.new(0, 28, 0, 28);
|
|
Position = UDim2.new(0, 0, 0, voteFrameContainer.Position.Y.Offset + voteFrameContainer.Size.Y.Offset - 28);
|
|
BackgroundTransparency = 1;
|
|
Image = 'rbxasset://textures/ui/Shell/Icons/ThumbsUpIcon@1080.png';
|
|
Parent = gameDetailsContainer;
|
|
}
|
|
local thumbsDownImage = Utility.Create'ImageLabel'
|
|
{
|
|
Name = "ThumbsDownImage";
|
|
Size = UDim2.new(0, 28, 0, 28);
|
|
Position = UDim2.new(0, voteFrameContainer.Position.X.Offset + voteFrameContainer.Size.X.Offset + 10, 0, voteFrameContainer.Position.Y.Offset);
|
|
BackgroundTransparency = 1;
|
|
Image = 'rbxasset://textures/ui/Shell/Icons/ThumbsDownIcon@1080.png';
|
|
Parent = gameDetailsContainer;
|
|
}
|
|
local separatorDot = Utility.Create'ImageLabel'
|
|
{
|
|
Name = "SeparatorDot";
|
|
Size = UDim2.new(0, 10, 0, 10);
|
|
Position = UDim2.new(0, thumbsDownImage.Position.X.Offset + thumbsDownImage.Size.X.Offset + 32, 0, voteFrameContainer.Position.Y.Offset + (voteFrameContainer.Size.Y.Offset/2) - (10/2));
|
|
BackgroundTransparency = 1;
|
|
Image = 'rbxasset://textures/ui/Shell/Icons/SeparatorDot@1080.png';
|
|
Parent = gameDetailsContainer;
|
|
}
|
|
local creatorIcon = Utility.Create'ImageLabel'
|
|
{
|
|
Name = "CreatorIcon";
|
|
Size = UDim2.new(0, 24, 0, 24);
|
|
Position = UDim2.new(0, separatorDot.Position.X.Offset + separatorDot.Size.X.Offset + 32, 0, separatorDot.Position.Y.Offset + separatorDot.Size.Y.Offset/2 - 12);
|
|
BackgroundTransparency = 1;
|
|
Image = 'rbxasset://textures/ui/Shell/Icons/RobloxIcon24.png';
|
|
Parent = gameDetailsContainer;
|
|
}
|
|
local creatorName = Utility.Create'TextLabel'
|
|
{
|
|
Name = "CreatorName";
|
|
Size = UDim2.new(0, 0, 0, 0);
|
|
Position = UDim2.new(0, creatorIcon.Position.X.Offset + creatorIcon.Size.X.Offset + 8, 0, separatorDot.Position.Y.Offset + separatorDot.Size.Y.Offset/2 - 2);
|
|
BackgroundTransparency = 1;
|
|
Font = GlobalSettings.RegularFont;
|
|
FontSize = GlobalSettings.DescriptionSize;
|
|
TextColor3 = GlobalSettings.LightGreyTextColor;
|
|
TextXAlignment = Enum.TextXAlignment.Left;
|
|
Text = "";
|
|
Parent = gameDetailsContainer;
|
|
}
|
|
local descriptionText = Utility.Create'TextLabel'
|
|
{
|
|
Name = "DescriptionText";
|
|
Size = UDim2.new(0, 850, 0, 64);
|
|
Position = UDim2.new(0, gameTitle.Position.X.Offset, 0, voteFrameContainer.Position.Y.Offset + voteFrameContainer.Size.Y.Offset + 20);
|
|
BackgroundTransparency = 1;
|
|
Text = "";
|
|
TextColor3 = GlobalSettings.LightGreyTextColor;
|
|
TextXAlignment = Enum.TextXAlignment.Left;
|
|
TextYAlignment = Enum.TextYAlignment.Top;
|
|
Font = GlobalSettings.LightFont;
|
|
TextWrapped = true;
|
|
FontSize = GlobalSettings.DescriptionSize;
|
|
Parent = gameDetailsContainer;
|
|
}
|
|
|
|
local noResultsText = Utility.Create'TextLabel'
|
|
{
|
|
Name = "noResultsText";
|
|
Size = UDim2.new(0, 0, 0, 0);
|
|
Position = UDim2.new(0.5, 0, 0.5, 0);
|
|
BackgroundTransparency = 1;
|
|
Text = Strings:LocalizedString("NoGamesPhrase");
|
|
TextColor3 = GlobalSettings.LightGreyTextColor;
|
|
Font = GlobalSettings.RegularFont;
|
|
FontSize = GlobalSettings.MediumFontSize;
|
|
Visible = false;
|
|
Parent = this.Container;
|
|
}
|
|
|
|
-- Selection overrides
|
|
playButton.NextSelectionLeft = playButton
|
|
favoriteButton.NextSelectionRight = favoriteButton
|
|
|
|
playButton.SelectionGained:connect(function()
|
|
playButton.ImageColor3 = playButtonSelectedColor
|
|
playText.TextColor3 = buttonSelectedTextColor
|
|
end)
|
|
playButton.SelectionLost:connect(function()
|
|
playButton.ImageColor3 = playButtonColor
|
|
playText.TextColor3 = buttonTextColor
|
|
end)
|
|
favoriteButton.SelectionGained:connect(function()
|
|
favoriteButton.ImageColor3 = favoriteSelectedButtonColor
|
|
favoriteText.TextColor3 = buttonSelectedTextColor
|
|
end)
|
|
favoriteButton.SelectionLost:connect(function()
|
|
favoriteButton.ImageColor3 = favoriteButtonColor
|
|
favoriteText.TextColor3 = buttonTextColor
|
|
end)
|
|
|
|
local function setIsFavorited(isFavorited)
|
|
if isFavorited == true then
|
|
favoriteStarImage.Visible = true
|
|
favoriteText.Position = UDim2.new(0, favoriteStarImage.Position.X.Offset + favoriteStarImage.Size.X.Offset + 12, 0, 0)
|
|
favoriteText.Text = Strings:LocalizedString("FavoritedWord")
|
|
favoriteText.TextXAlignment = Enum.TextXAlignment.Left
|
|
else
|
|
favoriteStarImage.Visible = false
|
|
favoriteText.Position = UDim2.new(0, 0, 0, 0)
|
|
favoriteText.Text = Strings:LocalizedString("FavoriteWord")
|
|
favoriteText.TextXAlignment = Enum.TextXAlignment.Center
|
|
end
|
|
end
|
|
local function setVoteView(voteData)
|
|
local upVotes = voteData and voteData.UpVotes or 0
|
|
local downVotes = voteData and voteData.DownVotes or 0
|
|
if upVotes == 0 and downVotes == 0 then
|
|
voteFrame:SetPercentFilled(nil)
|
|
else
|
|
voteFrame:SetPercentFilled(upVotes / (upVotes + downVotes))
|
|
end
|
|
end
|
|
|
|
local GameSelectedConns = {}
|
|
local onNewGameSelected = nil
|
|
|
|
local function ClearGameSelectedView()
|
|
--Disconnect Events
|
|
Utility.DisconnectEvents(GameSelectedConns)
|
|
GameSelectedConns = {}
|
|
gameTitle.Text = ""
|
|
creatorName.Text = ""
|
|
descriptionText.Text = ""
|
|
setVoteView()
|
|
setIsFavorited()
|
|
end
|
|
|
|
onNewGameSelected = function(placeId)
|
|
Utility.DisconnectEvents(GameSelectedConns)
|
|
GameSelectedConns = {}
|
|
|
|
local data = GameData:GetGameData(placeId)
|
|
if data then
|
|
--Use signals to make sure that these fetched data corresponds to the game we focus on
|
|
table.insert(GameSelectedConns, data.OnGetVoteDataEnd:
|
|
connect(function(voteData) setVoteView(voteData)
|
|
end))
|
|
|
|
table.insert(GameSelectedConns, data.OnGetGameDetailsEnd:
|
|
connect(function(gameData)
|
|
descriptionText.Text = gameData.Description or ""
|
|
setIsFavorited(gameData.IsFavorited)
|
|
end))
|
|
gameTitle.Text = data.Name
|
|
creatorName.Text = data.CreatorName
|
|
descriptionText.Text = data.Description or ""
|
|
setVoteView(data.VoteData)
|
|
setIsFavorited(data.IsFavorited)
|
|
spawn(function()
|
|
if not data.VoteData then
|
|
data:GetVoteDataAsync()
|
|
end
|
|
|
|
if not data.Description or data.IsFavorited == nil then
|
|
data:GetGameDetailsAsync()
|
|
end
|
|
end)
|
|
else
|
|
ClearGameSelectedView()
|
|
end
|
|
end
|
|
|
|
playButton.MouseButton1Click:connect(function()
|
|
SoundManager:Play('ButtonPress')
|
|
local placeId = myCarouselController:GetCurrentFocusGameData()
|
|
local data = GameData:GetGameData(placeId)
|
|
if data then
|
|
if canJoinGame and returnedFromGame then
|
|
canJoinGame = false
|
|
--Should never happen, as all game in carousel inits with CreatorUserId
|
|
if not data.CreatorUserId then
|
|
data:GetGameDetailsAsync()
|
|
end
|
|
GameJoinModule:StartGame(GameJoinModule.JoinType.Normal, data.PlaceId, data.CreatorUserId)
|
|
canJoinGame = true
|
|
end
|
|
end
|
|
end)
|
|
|
|
favoriteButton.MouseButton1Click:connect(function()
|
|
SoundManager:Play('ButtonPress')
|
|
local placeId = myCarouselController:GetCurrentFocusGameData()
|
|
local data = GameData:GetGameData(placeId)
|
|
if data then
|
|
local success, reason = data:PostFavoriteAsync()
|
|
if success then
|
|
setIsFavorited(data.IsFavorited)
|
|
elseif reason then
|
|
local err = Errors.Favorite[reason]
|
|
ScreenManager:OpenScreen(ErrorOverlayModule(err), false)
|
|
end
|
|
end
|
|
end)
|
|
|
|
function this:LoadGameCollection(gameCollection)
|
|
viewContainer.Visible = false
|
|
noResultsText.Visible = false
|
|
myCarouselView:SetParent(nil)
|
|
|
|
spawn(function()
|
|
local loader = LoadingWidget(
|
|
{ Parent = this.Container },
|
|
{
|
|
function()
|
|
myCarouselController:InitializeAsync(gameCollection)
|
|
end
|
|
}
|
|
)
|
|
|
|
loader:AwaitFinished()
|
|
loader:Cleanup()
|
|
loader = nil
|
|
|
|
myCarouselView:SetParent(viewContainer)
|
|
if this:IsFocused() then
|
|
if myCarouselController:HasResults() then
|
|
viewContainer.Visible = true
|
|
Utility.SetSelectedCoreObject(myCarouselView:GetFocusItem())
|
|
else
|
|
noResultsText.Visible = true
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- Override Base Functions
|
|
function this:GetDefaultSelectionObject()
|
|
return myCarouselView:GetFocusItem()
|
|
end
|
|
|
|
function this:GetAnalyticsInfo()
|
|
return
|
|
{
|
|
[Analytics.WidgetNames('WidgetId')] = Analytics.WidgetNames('BaseCarouselScreenId');
|
|
Title = this:GetTitle();
|
|
}
|
|
end
|
|
|
|
local baseFocus = this.Focus
|
|
function this:Focus()
|
|
baseFocus(self)
|
|
myCarouselView:Focus()
|
|
|
|
if PlatformService then
|
|
dataModelViewChangedCn = PlatformService.ViewChanged:connect(function(viewType)
|
|
-- return from game debounce
|
|
if viewType == 0 then
|
|
returnedFromGame = false
|
|
wait(1)
|
|
returnedFromGame = true
|
|
end
|
|
end)
|
|
end
|
|
|
|
newGameSelectedCn = myCarouselController.NewItemSelected:connect(onNewGameSelected)
|
|
onNewGameSelected(myCarouselController:GetCurrentFocusGameData())
|
|
myCarouselController:Connect()
|
|
end
|
|
|
|
local baseRemoveFocus = this.RemoveFocus
|
|
function this:RemoveFocus()
|
|
baseRemoveFocus(self)
|
|
dataModelViewChangedCn = Utility.DisconnectEvent(dataModelViewChangedCn)
|
|
newGameSelectedCn = Utility.DisconnectEvent(newGameSelectedCn)
|
|
myCarouselController:Disconnect()
|
|
Utility.DisconnectEvents(GameSelectedConns)
|
|
GameSelectedConns = {}
|
|
end
|
|
|
|
return this
|
|
end
|
|
|
|
return CreateBaseCarouselScreen
|