Clients/Client2018/content/internal/AppShell/Modules/Shell/BaseCarouselScreen.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