Clients/Client2018/content/internal/AppShell/Modules/Shell/ThumbnailLoader.lua

277 lines
7.3 KiB
Lua

--[[
// ThumbnailLoader.lua
// Creates a thumbnail loader object that handles the loading
// of thumb nails.
// Thumbnails may not yet be generated, so this will retry generation and
// assign the final thumbnail
]]
local CoreGui = game:GetService("CoreGui")
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
local Modules = GuiRoot:FindFirstChild("Modules")
local ShellModules = Modules:FindFirstChild("Shell")
local ContentProvider = game:GetService('ContentProvider')
local PlayersService = game:GetService("Players")
local Http = require(ShellModules:FindFirstChild('Http'))
local LoadingWidget = require(ShellModules:FindFirstChild('LoadingWidget'))
local Utility = require(ShellModules:FindFirstChild('Utility'))
local ThumbnailLoader = {}
local AssetGameBaseUrl = Http.AssetGameBaseUrl
local RETRIES = 6
local FORMAT = "png"
local FADE_IN_TIME = 0.25
local TEMPLATE_DECAL = Instance.new("Decal")
local function preloadThumbnailAsync(assetId)
TEMPLATE_DECAL.Texture = assetId
ContentProvider:PreloadAsync({ TEMPLATE_DECAL })
end
--[[ Sizes ]]--
ThumbnailLoader.Sizes = {
Small = Vector2.new(100, 100);
Medium = Vector2.new(250, 250);
Large = Vector2.new(576, 324);
}
ThumbnailLoader.AvatarSizes = {
Size48x48 = Vector2.new(48, 48);
Size150x150 = Vector2.new(150, 150);
Size352x352 = Vector2.new(352, 352);
Size420x420 = Vector2.new(420, 420);
}
ThumbnailLoader.SubstitutionTypeResult = {
None = 0;
Unapproved = 1;
PendingReview = 2;
Broken = 3;
Unavailable = 4;
Unknown = 5;
}
ThumbnailLoader.AssetType = {
Icon = { IsFinal = Http.GetAssetThumbnailFinalAsync;
SetImageUrl = 'Thumbs/Asset.ashx?width=%d&height=%d&assetId=%d&ignorePlaceMediaItems=true'; };
SquareIcon = { IsFinal = Http.GetAssetThumbnailFinalAsync;
SetImageUrl = 'Thumbs/GameIcon.ashx?width=%d&height=%d&assetId=%d&ignorePlaceMediaItems=true'; };
Avatar = { IsFinal = Http.GetAssetAvatarFinalAsync;
SetImageUrl = 'Thumbs/Avatar.ashx?width=%d&height=%d&userId=%d&ignorePlaceMediaItems=true'; };
Outfit = { IsFinal = Http.GetOutfitThumbnailFinalAsync;
SetImageUrl = 'Thumbs/Avatar.ashx?width=%d&height=%d&userId=%d&ignorePlaceMediaItems=true'; };
}
--[[
imageObject - a roblox gui image object (ImageLabel, ImageButton)
assetId - the id of the asset you want an image for
size - a ThumbnailLoader.Sizes
assetType - a ThumbnailLoader.AssetType
]]
function ThumbnailLoader:Create(imageObject, assetId, size, assetType, cachebust)
local this = {}
local isLoading = false
local cancelled = false
local isFinalSuccess = false
local uri = AssetGameBaseUrl..string.format(assetType.SetImageUrl, size.x, size.y, assetId or -1)
if cachebust then
uri = uri .. '&cb=' .. tostring(tick())
end
local getIsFinalFunc = assetType.IsFinal
local function tryGetFinalAsync()
local result = getIsFinalFunc(assetId, size.x, size.y, FORMAT)
if result then
local isFinal = result["Final"] or result["thumbnailFinal"]
local substitutionType = result["substitutionType"] or result["SubstitutionType"]
if isFinal == true and
(substitutionType == nil or substitutionType == ThumbnailLoader.SubstitutionTypeResult.None) then
isFinalSuccess = true
preloadThumbnailAsync(uri)
return true
end
end
return false
end
local function loadThumbInternalAsync()
local tryCount = 0
isLoading = true
isFinalSuccess = false
while tryCount <= RETRIES and isLoading and not cancelled do
if tryGetFinalAsync() then
break
end
tryCount = tryCount + 1
wait(tryCount ^ 2)
end
isLoading = false
end
local loader = nil
function this:LoadAsync(showSpinner, fadeImage, spinnerProperties)
spinnerProperties = spinnerProperties or {}
if not assetId then return end
if showSpinner == nil then
showSpinner = true
end
if fadeImage == nil then
fadeImage = true
end
-- reset image
imageObject.Image = ""
if fadeImage then
local tween = Utility.PropertyTweener(imageObject, "ImageTransparency", 1, 1, 0,
Utility.EaseInOutQuad, true, nil)
end
--try first time before starting loading widget
if not tryGetFinalAsync() then
if showSpinner then
spinnerProperties['Parent'] = spinnerProperties['Parent'] or imageObject
loader = LoadingWidget(
spinnerProperties,
{ loadThumbInternalAsync } )
loader:AwaitFinished()
loader:Cleanup()
else
loadThumbInternalAsync()
end
end
if not cancelled then
imageObject.Image = isFinalSuccess and uri or ""
if fadeImage then
local tween = Utility.PropertyTweener(imageObject, "ImageTransparency", 1, 0, FADE_IN_TIME,
Utility.EaseInOutQuad, true, nil)
end
end
return isFinalSuccess
end
function this:Cancel()
isLoading = false
cancelled = true
end
function this:SetTransparency(value)
if loader then
loader:SetTransparency(value)
end
end
return this
end
--[[
imageObject - a roblox gui image object (ImageLabel, ImageButton)
userId - userId of the player you want the avatar thumbnail for
thumbnailType - Enum.ThumbnailType (HeadShot = 0, AvatarBust = 1, AvatarThumbnail = 2)
thumbnailSize - Enum.ThumbnailSize (Size48x48 = 0, Size180x180 = 1, Size420x420 = 2)
]]
function ThumbnailLoader:LoadAvatarThumbnailAsync(imageObject, userId, thumbnailType, thumbnailSize, cachebust)
local this = {}
local isLoading = false
local cancelled = false
local isFinalSuccess = false
local uri = nil
local isFinal = false
local function tryGetFinalAsync()
local success, msg = pcall(function()
uri, isFinal = PlayersService:GetUserThumbnailAsync(userId, thumbnailType, thumbnailSize)
end)
if success and uri and isFinal then
isFinalSuccess = true
if cachebust then
uri = uri .. '&cb=' .. tostring(tick())
end
preloadThumbnailAsync(uri)
return true
end
return false
end
local function loadThumbInternalAsync()
local tryCount = 0
isLoading = true
isFinalSuccess = false
while tryCount <= RETRIES and isLoading and not cancelled do
if tryGetFinalAsync() then
break
end
tryCount = tryCount + 1
wait(tryCount ^ 2)
end
isLoading = false
end
local loader = nil
function this:LoadAsync(showSpinner, fadeImage, spinnerProperties)
spinnerProperties = spinnerProperties or {}
if not userId then return end
if showSpinner == nil then
showSpinner = true
end
if fadeImage == nil then
fadeImage = true
end
-- reset image
imageObject.Image = ""
if fadeImage then
local tween = Utility.PropertyTweener(imageObject, "ImageTransparency", 1, 1, 0,
Utility.EaseInOutQuad, true, nil)
end
--try first time before starting loading widget
if not tryGetFinalAsync() then
if showSpinner then
spinnerProperties['Parent'] = spinnerProperties['Parent'] or imageObject
loader = LoadingWidget(
spinnerProperties,
{ loadThumbInternalAsync } )
loader:AwaitFinished()
loader:Cleanup()
else
loadThumbInternalAsync()
end
end
if not cancelled then
imageObject.Image = isFinalSuccess and uri or ""
if fadeImage then
local tween = Utility.PropertyTweener(imageObject, "ImageTransparency", 1, 0, FADE_IN_TIME,
Utility.EaseInOutQuad, true, nil)
end
end
return isFinalSuccess
end
function this:Cancel()
isLoading = false
cancelled = true
end
function this:SetTransparency(value)
if loader then
loader:SetTransparency(value)
end
end
return this
end
return ThumbnailLoader