707 lines
23 KiB
Lua
707 lines
23 KiB
Lua
-- Written by Kip Turner and Bo Zhang, Copyright Roblox 2017
|
|
|
|
local CoreGui = game:GetService("CoreGui")
|
|
local GuiService = game:GetService('GuiService')
|
|
local RunService = game:GetService('RunService')
|
|
|
|
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
|
|
local Modules = GuiRoot:FindFirstChild("Modules")
|
|
local ShellModules = Modules:FindFirstChild("Shell")
|
|
|
|
local PackageData = require(ShellModules:FindFirstChild('PackageData'))
|
|
local ScrollingGridModule = require(ShellModules:FindFirstChild('ScrollingGrid'))
|
|
local AvatarTile = require(ShellModules:FindFirstChild('AvatarTile'))
|
|
local Utility = require(ShellModules:FindFirstChild('Utility'))
|
|
local ScreenManager = require(ShellModules:FindFirstChild('ScreenManager'))
|
|
local GlobalSettings = require(ShellModules:FindFirstChild('GlobalSettings'))
|
|
local LoadingWidget = require(ShellModules:FindFirstChild('LoadingWidget'))
|
|
local ThumbnailLoader = require(ShellModules:FindFirstChild('ThumbnailLoader'))
|
|
|
|
local Analytics = require(ShellModules:FindFirstChild('Analytics'))
|
|
local Strings = require(ShellModules:FindFirstChild('LocalizedStrings'))
|
|
local SoundManager = require(ShellModules:FindFirstChild('SoundManager'))
|
|
|
|
local HintActionView = require(ShellModules:FindFirstChild('HintActionView'))
|
|
local XboxAppState = require(ShellModules:FindFirstChild('AppState'))
|
|
|
|
local GLOW_BASE_RPM = 2
|
|
local GLOW_TOP_RPM = -0.5
|
|
local GLOW_TRANSPARENCY = 0.2
|
|
local CATALOG_BELOW_POSITION = 320
|
|
|
|
|
|
local function CreateAvatarPane(parent)
|
|
local this = {}
|
|
|
|
local inFocus = false
|
|
local isShown = false
|
|
|
|
local AvatarObjects = {}
|
|
|
|
local OnGuiServiceChangedConn = nil
|
|
|
|
local lastParent = parent
|
|
|
|
|
|
local MainContainer = Utility.Create'Frame'
|
|
{
|
|
Name = 'AvatarPane';
|
|
Size = UDim2.new(1, 0, 1, 0);
|
|
BackgroundTransparency = 1;
|
|
Visible = false;
|
|
}
|
|
|
|
|
|
|
|
local MyAvatarContainer = Utility.Create'Frame'
|
|
{
|
|
Name = 'MyAvatarContainer';
|
|
Size = UDim2.new(0.38,0,1,0);
|
|
Position = UDim2.new(0,0,0,0);
|
|
BackgroundTransparency = 1;
|
|
ClipsDescendants = true;
|
|
Parent = MainContainer;
|
|
}
|
|
local MyNameLabel = Utility.Create'TextLabel'
|
|
{
|
|
Name = 'MyNameLabel';
|
|
Text = '';
|
|
Size = UDim2.new(1,0,0,25);
|
|
Position = UDim2.new(0,12,0,0);
|
|
TextXAlignment = 'Left';
|
|
TextColor3 = GlobalSettings.WhiteTextColor;
|
|
Font = GlobalSettings.RegularFont;
|
|
FontSize = GlobalSettings.SubHeaderSize;
|
|
BackgroundTransparency = 1;
|
|
Parent = MyAvatarContainer;
|
|
};
|
|
local ProfileImageContainer = Utility.Create'Frame'
|
|
{
|
|
Name = 'ProfileImageContainer';
|
|
Size = UDim2.new(0.68,0,0.9,-MyNameLabel.Size.Y.Offset);
|
|
Position = UDim2.new(0.16, 0, 0.05, MyNameLabel.Size.Y.Offset);
|
|
BackgroundTransparency = 1;
|
|
Parent = MyAvatarContainer;
|
|
}
|
|
local ProfileImage = Utility.Create'ImageLabel'
|
|
{
|
|
Name = 'ProfileImage';
|
|
Size = UDim2.new(0,780,0,780);
|
|
Position = UDim2.new(0.5, 0, 0.5, 0);
|
|
BackgroundTransparency = 1;
|
|
ZIndex = 3;
|
|
Parent = ProfileImageContainer;
|
|
};
|
|
local CrossfadeProfileImage = Utility.Create'ImageLabel'
|
|
{
|
|
Name = 'CrossfadeProfileImage';
|
|
Size = UDim2.new(1,0,1,0);
|
|
Position = UDim2.new(0, 0, 0, 0);
|
|
BackgroundTransparency = 1;
|
|
ImageTransparency = 1;
|
|
ZIndex = 3;
|
|
Parent = ProfileImage;
|
|
};
|
|
local CharacterGlowBase = Utility.Create'ImageLabel'
|
|
{
|
|
Name = 'CharacterGlowBase';
|
|
Size = UDim2.new(0,1015,0,1002);
|
|
BackgroundTransparency = 1;
|
|
Image = 'rbxasset://textures/ui/Shell/Images/CharacterGlow/CharacterGlowBase.png';
|
|
ImageTransparency = GLOW_TRANSPARENCY;
|
|
Parent = CrossfadeProfileImage;
|
|
AnchorPoint = Vector2.new(0.5, 0.5);
|
|
Position = UDim2.new(0.5, 0, 0.5, 0);
|
|
};
|
|
local CharacterGlowTop = Utility.Create'ImageLabel'
|
|
{
|
|
Name = 'CharacterGlowTop';
|
|
Size = UDim2.new(0,1026,0,1009);
|
|
BackgroundTransparency = 1;
|
|
Image = 'rbxasset://textures/ui/Shell/Images/CharacterGlow/CharacterGlowTop.png';
|
|
ImageTransparency = GLOW_TRANSPARENCY;
|
|
ZIndex = 2;
|
|
Parent = CrossfadeProfileImage;
|
|
AnchorPoint = Vector2.new(0.5, 0.5);
|
|
Position = UDim2.new(0.5, 0, 0.5, 0);
|
|
};
|
|
local function onSizeChanged()
|
|
ProfileImage.Size = Utility.CalculateFill(ProfileImage, ThumbnailLoader.AvatarSizes.Size352x352)
|
|
ProfileImage.AnchorPoint = Vector2.new(0.5, 0.5)
|
|
ProfileImage.Position = UDim2.new(0.5, 0, 0.5, 0)
|
|
end
|
|
|
|
-- Hint Action View
|
|
local hintActionView = HintActionView(nil, "AvatarPaneSelectAction")
|
|
hintActionView:SetImage('rbxasset://textures/ui/Shell/ButtonIcons/XButton.png')
|
|
hintActionView:SetText(Strings:LocalizedString('EquipWord'))
|
|
hintActionView:SetTransparency(1)
|
|
hintActionView:SetParent(lastParent.Parent) -- this assumes parent is HubContainer from AppHub.lua
|
|
|
|
local function UpdateEquipButton(IsOwned, IsWearing)
|
|
hintActionView:SetVisibleWithTween( (IsOwned and not IsWearing) and 0 or 1)
|
|
end
|
|
|
|
local SelectableAvatarsContainer = Utility.Create'Frame'
|
|
{
|
|
Name = 'SelectableAvatarsContainer';
|
|
Size = UDim2.new(0.6,0,1,0);
|
|
Position = UDim2.new(0.4,0,0,0);
|
|
BackgroundTransparency = 1;
|
|
Parent = MainContainer;
|
|
}
|
|
|
|
local NoCatalogStatusMessage = Utility.Create'TextLabel'
|
|
{
|
|
Name = 'NoCatalogStatusMessage';
|
|
Text = Strings:LocalizedString('DefaultErrorPhrase');
|
|
Size = UDim2.new(0.9,0,1,-125);
|
|
Position = UDim2.new(0.05, 0, 0, 0);
|
|
TextColor3 = GlobalSettings.GreyTextColor;
|
|
TextWrapped = true;
|
|
TextTransparency = GlobalSettings.FriendStatusTextTransparency;
|
|
Font = GlobalSettings.BoldFont;
|
|
FontSize = GlobalSettings.DescriptionSize;
|
|
BackgroundTransparency = 1;
|
|
Visible = false;
|
|
Parent = SelectableAvatarsContainer;
|
|
};
|
|
|
|
local MyCollectionTitle = Utility.Create'TextLabel'
|
|
{
|
|
Name = 'MyCollectionTitle';
|
|
Text = Strings:LocalizedString('AvatarOutfitsTitle');
|
|
Size = UDim2.new(1,0,0,40);
|
|
TextXAlignment = 'Left';
|
|
TextColor3 = GlobalSettings.WhiteTextColor;
|
|
Font = GlobalSettings.RegularFont;
|
|
FontSize = GlobalSettings.SubHeaderSize;
|
|
BackgroundTransparency = 1;
|
|
Visible = false;
|
|
Parent = SelectableAvatarsContainer;
|
|
};
|
|
|
|
local MyCollectionScroller = ScrollingGridModule()
|
|
MyCollectionScroller:SetSize(UDim2.new(1,0,1,-MyCollectionTitle.Size.Y.Offset - 40))
|
|
MyCollectionScroller:SetScrollDirection(MyCollectionScroller.Enum.ScrollDirection.Horizontal)
|
|
MyCollectionScroller:SetCellSize(Vector2.new(220, 220))
|
|
MyCollectionScroller:SetSpacing(Vector2.new(25,25))
|
|
MyCollectionScroller:SetPosition(UDim2.new(0,0,0,MyCollectionTitle.Size.Y.Offset))
|
|
MyCollectionScroller:SetRowColumnConstraint(1)
|
|
-- MyCollectionScroller:SetParent(SelectableAvatarsContainer)
|
|
|
|
local CatalogTitle = Utility.Create'TextLabel'
|
|
{
|
|
Name = 'CatalogTitle';
|
|
Text = Strings:LocalizedString('AvatarCatalogTitle');
|
|
Size = UDim2.new(1,0,0,40);
|
|
Position = UDim2.new(0,0,0,0);
|
|
TextXAlignment = 'Left';
|
|
TextColor3 = GlobalSettings.WhiteTextColor;
|
|
Font = GlobalSettings.RegularFont;
|
|
FontSize = GlobalSettings.SubHeaderSize;
|
|
BackgroundTransparency = 1;
|
|
Parent = SelectableAvatarsContainer;
|
|
};
|
|
|
|
local AvatarScroller = ScrollingGridModule()
|
|
AvatarScroller:SetSize(UDim2.new(1,0,1,-CatalogTitle.Size.Y.Offset - 40))
|
|
AvatarScroller:SetScrollDirection(AvatarScroller.Enum.ScrollDirection.Horizontal)
|
|
AvatarScroller:SetCellSize(Vector2.new(220, 220))
|
|
AvatarScroller:SetPosition(UDim2.new(0,0,0,40))
|
|
AvatarScroller:SetSpacing(Vector2.new(25,25))
|
|
AvatarScroller:SetRowColumnConstraint(2)
|
|
AvatarScroller:SetParent(SelectableAvatarsContainer)
|
|
|
|
local function SortMyCollectionScroller()
|
|
MyCollectionScroller:SortItems(
|
|
function(a, b)
|
|
local aObject = a and AvatarObjects[a] and AvatarObjects[a]:GetPackageInfo()
|
|
local bObject = b and AvatarObjects[b] and AvatarObjects[b]:GetPackageInfo()
|
|
local aIsEquipped = aObject and aObject:IsWearing()
|
|
local bIsEquipped = bObject and bObject:IsWearing()
|
|
local aName = aObject and aObject:GetName()
|
|
local bName = bObject and bObject:GetName()
|
|
|
|
if aIsEquipped then return true elseif bIsEquipped then return false end
|
|
if aName and bName then
|
|
return aName < bName
|
|
end
|
|
return aObject ~= nil
|
|
end)
|
|
end
|
|
|
|
--if all avatars owned, MyCollection should be 2 rows and catalog should be hidden
|
|
local function CheckAllAvatarsOwned()
|
|
if #AvatarScroller.GridItems == 0 then
|
|
MyCollectionScroller:SetRowColumnConstraint(2)
|
|
CatalogTitle.Visible = false
|
|
AvatarScroller.Visible = false
|
|
AvatarScroller:SetParent(nil)
|
|
else
|
|
MyCollectionScroller:SetRowColumnConstraint(1)
|
|
CatalogTitle.Visible = true
|
|
AvatarScroller.Visible = true
|
|
AvatarScroller:SetParent(SelectableAvatarsContainer)
|
|
end
|
|
end
|
|
|
|
local function OnAddToMyCollectionScroller()
|
|
CatalogTitle.Position = UDim2.new(0,0,0, CATALOG_BELOW_POSITION)
|
|
AvatarScroller:SetPosition(UDim2.new(0,0,0,CATALOG_BELOW_POSITION + 40))
|
|
AvatarScroller:SetRowColumnConstraint(1)
|
|
MyCollectionTitle.Visible = true
|
|
MyCollectionScroller:SetParent(SelectableAvatarsContainer)
|
|
CheckAllAvatarsOwned()
|
|
SortMyCollectionScroller()
|
|
end
|
|
|
|
local LoaderSpinner = nil
|
|
local GlobalFadeCount = 1
|
|
local function CrossfadeAvatarImage(frontImage, fadeImage, imageSource, duration)
|
|
if not imageSource then return end
|
|
duration = duration or 0.75
|
|
|
|
GlobalFadeCount = GlobalFadeCount + 1
|
|
local thisFadeCount = GlobalFadeCount
|
|
local fadeoutDuration = duration
|
|
|
|
spawn(function()
|
|
local dummyImage = nil
|
|
if LoaderSpinner then
|
|
LoaderSpinner:Cleanup()
|
|
end
|
|
|
|
--If imageSource if a function, then it's maybe a async call to get new image and we show the loaderspinner.
|
|
--Otherwise, if the imageSource is a valid new image, we just do the Crossfade (without the spinner)
|
|
if type(imageSource) == 'function' then
|
|
local newLoaderSpinner = LoadingWidget({Parent = frontImage, ZIndex = 3}, {
|
|
function() dummyImage = imageSource() end
|
|
})
|
|
LoaderSpinner = newLoaderSpinner
|
|
newLoaderSpinner:AwaitFinished()
|
|
newLoaderSpinner:Cleanup()
|
|
elseif type(imageSource) == 'table' and imageSource.Image then
|
|
dummyImage = imageSource
|
|
end
|
|
|
|
if thisFadeCount == GlobalFadeCount then
|
|
--Avoid updating with same image
|
|
if dummyImage and frontImage and dummyImage.Image ~= frontImage.Image then
|
|
local noPreviousImage = (frontImage.Image == "" and fadeImage.Image == "")
|
|
if noPreviousImage then
|
|
fadeoutDuration = 0
|
|
else
|
|
fadeImage.Image = frontImage.Image
|
|
end
|
|
|
|
|
|
Utility.PropertyTweener(fadeImage, 'ImageTransparency', noPreviousImage and 0 or frontImage.ImageTransparency, 1, fadeoutDuration, Utility.EaseInOutQuad, true)
|
|
Utility.PropertyTweener(CharacterGlowBase, 'ImageTransparency', CharacterGlowBase.ImageTransparency, 1, fadeoutDuration, Utility.EaseInOutQuad, true)
|
|
Utility.PropertyTweener(CharacterGlowTop, 'ImageTransparency', CharacterGlowTop.ImageTransparency, 1, fadeoutDuration, Utility.EaseInOutQuad, true)
|
|
frontImage.ImageTransparency = 1
|
|
|
|
frontImage.Image = dummyImage.Image
|
|
|
|
Utility.PropertyTweener(frontImage, 'ImageTransparency', frontImage.ImageTransparency, 0, duration, Utility.EaseInOutQuad, true)
|
|
Utility.PropertyTweener(CharacterGlowBase, 'ImageTransparency', CharacterGlowBase.ImageTransparency, GLOW_TRANSPARENCY, duration, Utility.EaseInOutQuad, true)
|
|
Utility.PropertyTweener(CharacterGlowTop, 'ImageTransparency', CharacterGlowTop.ImageTransparency, GLOW_TRANSPARENCY, duration, Utility.EaseInOutQuad, true)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
local function UpdateProfileImage(imageSource)
|
|
MyNameLabel.Text = XboxAppState.store:getState().XboxUser.gamertag
|
|
CrossfadeAvatarImage(ProfileImage, CrossfadeProfileImage, imageSource)
|
|
end
|
|
|
|
local function onOwnershipChanged(tile, nowOwns)
|
|
-- Move purchased packages into my MyCollection
|
|
if nowOwns then
|
|
local guiObject = tile and tile:GetGuiObject()
|
|
if guiObject and AvatarScroller:ContainsItem(guiObject) then
|
|
AvatarScroller:RemoveItem(guiObject)
|
|
MyCollectionScroller:AddItem(guiObject)
|
|
OnAddToMyCollectionScroller()
|
|
if inFocus then
|
|
GuiService.SelectedCoreObject = guiObject
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local ownershipChangedCns = {}
|
|
|
|
local function listenToOwnershipChanged(tile)
|
|
local packageInfo = tile and tile:GetPackageInfo()
|
|
if packageInfo and not packageInfo:IsOwned() and (packageInfo.OwnershipChanged ~= nil) then
|
|
if not ownershipChangedCns[tile] then
|
|
ownershipChangedCns[tile] = packageInfo.OwnershipChanged:connect(function(nowOwns)
|
|
onOwnershipChanged(tile, nowOwns)
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function removeListenToOwnershipChanged(tile)
|
|
if ownershipChangedCns[tile] then
|
|
ownershipChangedCns[tile]:disconnect()
|
|
ownershipChangedCns[tile] = nil
|
|
end
|
|
end
|
|
|
|
local function onEquipChanged()
|
|
local selectedObject = GuiService.SelectedCoreObject
|
|
|
|
if AvatarObjects[selectedObject] then
|
|
local packageInfo = AvatarObjects[selectedObject]:GetPackageInfo()
|
|
if packageInfo then
|
|
UpdateEquipButton(packageInfo:IsOwned(), packageInfo:IsWearing())
|
|
end
|
|
else
|
|
-- user can select avatar tab button
|
|
UpdateEquipButton(false, false)
|
|
end
|
|
SortMyCollectionScroller()
|
|
end
|
|
|
|
local lastSelectedObject = GuiService.SelectedCoreObject
|
|
local function OnSelectedCoreObjectChanged()
|
|
local selectedObject = GuiService.SelectedCoreObject
|
|
|
|
if AvatarObjects[lastSelectedObject] then
|
|
AvatarObjects[lastSelectedObject]:RemoveFocus()
|
|
end
|
|
if AvatarObjects[selectedObject] then
|
|
AvatarObjects[selectedObject]:Focus()
|
|
lastSelectedObject = selectedObject
|
|
end
|
|
onEquipChanged()
|
|
end
|
|
|
|
|
|
function this:GetDefaultSelectableObject()
|
|
if MyCollectionScroller:GetFirstVisibleItem() then
|
|
return MyCollectionScroller:GetFirstVisibleItem()
|
|
end
|
|
if AvatarScroller:GetFirstVisibleItem() then
|
|
return AvatarScroller:GetFirstVisibleItem()
|
|
end
|
|
|
|
--In case GetFirstVisibleItem breaks
|
|
if MyCollectionScroller.GridItems[1] then
|
|
return MyCollectionScroller.GridItems[1]
|
|
end
|
|
if AvatarScroller.GridItems[1] then
|
|
return AvatarScroller.GridItems[1]
|
|
end
|
|
end
|
|
|
|
local packagesData = nil
|
|
local packagesDataConns = {}
|
|
local AvatarWebDataInitializeLoader = nil
|
|
local function removeListenToPackagesDataUpdate()
|
|
for _, conn in pairs(packagesDataConns) do
|
|
conn:disconnect()
|
|
end
|
|
packagesDataConns = {}
|
|
end
|
|
|
|
local function listenToPackagesDataUpdate()
|
|
if packagesData and packagesDataConns then
|
|
table.insert(packagesDataConns, packagesData.OnDifferentWearing:connect(function(assetId) onEquipChanged() end))
|
|
table.insert(packagesDataConns, packagesData.OnDifferentOwned:connect(function(assetId, owned) onEquipChanged() end))
|
|
table.insert(packagesDataConns, packagesData.OnProfileImageUpdateEnd:connect(function(newProfileImage)
|
|
UpdateProfileImage(newProfileImage)
|
|
end))
|
|
table.insert(packagesDataConns, packagesData.OnProfileImageUpdateBegin:connect(function()
|
|
UpdateProfileImage(function()
|
|
return packagesData.OnProfileImageUpdateEnd.wait()
|
|
end)
|
|
end))
|
|
end
|
|
end
|
|
|
|
local function LoadAvatarWebData()
|
|
local function clearCatalogPackages()
|
|
AvatarScroller:RemoveAllItems()
|
|
MyCollectionScroller:RemoveAllItems()
|
|
for k,_ in pairs(AvatarObjects) do
|
|
AvatarObjects[k] = nil
|
|
end
|
|
AvatarObjects = {}
|
|
end
|
|
|
|
local function loadCatalogPackages(packages)
|
|
clearCatalogPackages()
|
|
if packages then
|
|
for _, packageInfo in pairs(packages) do
|
|
local avatarItemContainer = AvatarTile(packageInfo)
|
|
|
|
AvatarObjects[avatarItemContainer:GetGuiObject()] = avatarItemContainer
|
|
|
|
if packageInfo:IsOwned() then
|
|
MyCollectionScroller:AddItem(avatarItemContainer:GetGuiObject())
|
|
OnAddToMyCollectionScroller()
|
|
else
|
|
AvatarScroller:AddItem(avatarItemContainer:GetGuiObject())
|
|
listenToOwnershipChanged(avatarItemContainer)
|
|
end
|
|
|
|
if isShown then
|
|
avatarItemContainer:Show()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--Wait until initialize is done
|
|
if AvatarWebDataInitializeLoader then return end
|
|
|
|
if PackageData:HasCachedData() then --Sync process to get and update packagesData, no spinner
|
|
local prevVersion = packagesData and packagesData.Version or nil
|
|
packagesData = PackageData:GetCachedData()
|
|
--If init or packagesData got updated
|
|
if not prevVersion or prevVersion ~= packagesData.Version then
|
|
SelectableAvatarsContainer.Visible = false
|
|
UpdateProfileImage(packagesData.ProfileImage.Data)
|
|
loadCatalogPackages(packagesData.Packages.Data)
|
|
SelectableAvatarsContainer.Visible = true
|
|
removeListenToPackagesDataUpdate()
|
|
listenToPackagesDataUpdate()
|
|
end
|
|
else --Async process to get and update packagesData, show spinner
|
|
SelectableAvatarsContainer.Visible = false
|
|
local containerSize = SelectableAvatarsContainer.Size
|
|
AvatarWebDataInitializeLoader = LoadingWidget(
|
|
{Parent = MainContainer, Position = SelectableAvatarsContainer.Position + UDim2.new(containerSize.X.Scale / 2, containerSize.X.Offset / 2, containerSize.Y.Scale / 2, containerSize.Y.Offset / 2)},
|
|
{function()
|
|
packagesData = PackageData:GetCachedData()
|
|
if packagesData and packagesData.Packages then
|
|
loadCatalogPackages(packagesData.Packages.Data)
|
|
end
|
|
end}
|
|
)
|
|
spawn(function()
|
|
NoCatalogStatusMessage.Visible = false
|
|
|
|
UpdateProfileImage(function()
|
|
if AvatarWebDataInitializeLoader then
|
|
AvatarWebDataInitializeLoader:AwaitFinished()
|
|
end
|
|
if packagesData and packagesData.ProfileImage then
|
|
return packagesData.ProfileImage.Data
|
|
end
|
|
end)
|
|
|
|
AvatarWebDataInitializeLoader:AwaitFinished()
|
|
AvatarWebDataInitializeLoader:Cleanup()
|
|
AvatarWebDataInitializeLoader = nil
|
|
SelectableAvatarsContainer.Visible = true
|
|
removeListenToPackagesDataUpdate()
|
|
|
|
if not packagesData then
|
|
NoCatalogStatusMessage.Visible = true
|
|
end
|
|
|
|
--Hook connections if the pane is still visible after loading
|
|
if isShown then
|
|
listenToPackagesDataUpdate()
|
|
end
|
|
|
|
if inFocus and isShown and GuiService.SelectedCoreObject == nil then
|
|
GuiService.SelectedCoreObject = this:GetDefaultSelectableObject()
|
|
end
|
|
|
|
if this.TransitionTweens == nil or #this.TransitionTweens == 0 then
|
|
this.TransitionTweens = ScreenManager:FadeInSitu(SelectableAvatarsContainer)
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
LoadAvatarWebData()
|
|
|
|
--[[ Public API ]]--
|
|
function this:GetName()
|
|
return Strings:LocalizedString('AvatarWord')
|
|
end
|
|
|
|
function this:GetAnalyticsInfo()
|
|
return {[Analytics.WidgetNames('WidgetId')] = Analytics.WidgetNames('AvatarPaneId')}
|
|
end
|
|
|
|
function this:IsFocused()
|
|
return inFocus
|
|
end
|
|
|
|
local debounceSelect = false
|
|
function this:OnSelectAction()
|
|
if debounceSelect then return end
|
|
debounceSelect = true
|
|
|
|
local selectedObject = GuiService.SelectedCoreObject
|
|
if selectedObject and AvatarObjects[selectedObject] then
|
|
if AvatarObjects[selectedObject]:Select() then
|
|
SoundManager:Play('ButtonPress')
|
|
end
|
|
end
|
|
|
|
debounceSelect = false
|
|
end
|
|
|
|
function this:OpenEquippedPackage()
|
|
if isShown and inFocus then
|
|
for _, avatarItemContainer in pairs(AvatarObjects) do
|
|
local packageInfo = avatarItemContainer:GetPackageInfo()
|
|
if packageInfo then
|
|
if packageInfo:IsWearing() then
|
|
avatarItemContainer:OnClick()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
--[[ End Public API ]]--
|
|
|
|
local profileImageChangeCn = nil
|
|
function this:Show()
|
|
isShown = true
|
|
|
|
Utility.DisconnectEvent(profileImageChangeCn)
|
|
profileImageChangeCn = ProfileImageContainer:GetPropertyChangedSignal('AbsoluteSize'):connect(function()
|
|
onSizeChanged()
|
|
end)
|
|
onSizeChanged()
|
|
|
|
local lastUpdate = tick()
|
|
RunService:BindToRenderStep("UpdateAvatarGlow", Enum.RenderPriority.Camera.Value,
|
|
function()
|
|
local now = tick()
|
|
local delta = now - lastUpdate
|
|
|
|
CharacterGlowBase.Rotation = CharacterGlowBase.Rotation + delta * GLOW_BASE_RPM * 6 -- 6 = 360 / 60
|
|
CharacterGlowTop.Rotation = CharacterGlowTop.Rotation + delta * GLOW_TOP_RPM * 6
|
|
|
|
lastUpdate = now
|
|
end)
|
|
|
|
if packagesData then
|
|
listenToPackagesDataUpdate()
|
|
UpdateProfileImage(packagesData.ProfileImage.Data)
|
|
end
|
|
LoadAvatarWebData()
|
|
|
|
for _, avatarItemContainer in pairs(AvatarObjects) do
|
|
avatarItemContainer:Show()
|
|
listenToOwnershipChanged(avatarItemContainer)
|
|
local packageInfo = avatarItemContainer and avatarItemContainer:GetPackageInfo()
|
|
if packageInfo then
|
|
onOwnershipChanged(avatarItemContainer, packageInfo:IsOwned())
|
|
end
|
|
end
|
|
|
|
local seenXButtonPressed = false
|
|
local seenXSelectedObject = nil
|
|
local function onSelectAvatar(actionName, inputState, inputObject)
|
|
if inputState == Enum.UserInputState.Begin then
|
|
seenXButtonPressed = true
|
|
seenXSelectedObject = GuiService.SelectedCoreObject
|
|
elseif inputState == Enum.UserInputState.End and seenXButtonPressed then
|
|
if seenXSelectedObject and seenXSelectedObject == GuiService.SelectedCoreObject then
|
|
self:OnSelectAction()
|
|
end
|
|
seenXButtonPressed = false
|
|
seenXSelectedObject = nil
|
|
end
|
|
end
|
|
|
|
hintActionView:BindAction(onSelectAvatar, Enum.KeyCode.ButtonX)
|
|
|
|
self.TransitionTweens = ScreenManager:DefaultFadeIn(MainContainer)
|
|
|
|
SortMyCollectionScroller()
|
|
|
|
MainContainer.Parent = lastParent
|
|
MainContainer.Visible = true
|
|
ScreenManager:PlayDefaultOpenSound()
|
|
end
|
|
|
|
|
|
function this:Hide()
|
|
isShown = false
|
|
MainContainer.Visible = false
|
|
removeListenToPackagesDataUpdate()
|
|
|
|
profileImageChangeCn = Utility.DisconnectEvent(profileImageChangeCn)
|
|
|
|
RunService:UnbindFromRenderStep("UpdateAvatarGlow")
|
|
hintActionView:UnbindAction()
|
|
hintActionView:SetTransparency(1)
|
|
|
|
for _, avatarItemContainer in pairs(AvatarObjects) do
|
|
avatarItemContainer:Hide()
|
|
removeListenToOwnershipChanged(avatarItemContainer)
|
|
end
|
|
|
|
ScreenManager:DefaultCancelFade(self.TransitionTweens)
|
|
self.TransitionTweens = nil
|
|
-- Clean out saved selected object so when we tab back
|
|
-- we will start with the default selection
|
|
lastSelectedObject = nil
|
|
self.SavedSelectObject = nil
|
|
end
|
|
|
|
function this:Focus()
|
|
inFocus = true
|
|
|
|
Utility.DisconnectEvent(OnGuiServiceChangedConn)
|
|
OnGuiServiceChangedConn = GuiService:GetPropertyChangedSignal('SelectedCoreObject'):connect(function()
|
|
OnSelectedCoreObjectChanged()
|
|
end)
|
|
|
|
if self.SavedSelectObject and self.SavedSelectObject:IsDescendantOf(MainContainer) then
|
|
GuiService.SelectedCoreObject = self.SavedSelectObject
|
|
else
|
|
local defaultSelection = self:GetDefaultSelectableObject()
|
|
if defaultSelection then
|
|
GuiService.SelectedCoreObject = defaultSelection
|
|
end
|
|
end
|
|
end
|
|
|
|
function this:RemoveFocus()
|
|
inFocus = false
|
|
--Remove Focus on AvatarObjects
|
|
if AvatarObjects and AvatarObjects[lastSelectedObject] then
|
|
AvatarObjects[lastSelectedObject]:RemoveFocus()
|
|
end
|
|
OnGuiServiceChangedConn = Utility.DisconnectEvent(OnGuiServiceChangedConn)
|
|
|
|
local selectedObject = GuiService.SelectedCoreObject
|
|
if isShown then
|
|
if selectedObject and selectedObject:IsDescendantOf(MainContainer) then
|
|
self.SavedSelectObject = GuiService.SelectedCoreObject
|
|
GuiService.SelectedCoreObject = nil
|
|
else
|
|
self.SavedSelectObject = lastSelectedObject
|
|
end
|
|
end
|
|
OnSelectedCoreObjectChanged()
|
|
end
|
|
|
|
function this:SetPosition(newPosition)
|
|
MainContainer.Position = newPosition
|
|
end
|
|
|
|
function this:SetParent(newParent)
|
|
lastParent = newParent
|
|
MainContainer.Parent = newParent
|
|
end
|
|
|
|
return this
|
|
end
|
|
|
|
return CreateAvatarPane
|