267 lines
7.1 KiB
Lua
267 lines
7.1 KiB
Lua
--[[
|
|
// BatchThumbnailLoader.lua
|
|
|
|
// Creates a batch thumbnail loader object that handles the loading
|
|
// of mutiple thumb nails.
|
|
|
|
// Thumbnails may not yet be generated, so this will retry and
|
|
// assign the final thumbnail
|
|
]]
|
|
|
|
local CoreGui = game:GetService("CoreGui")
|
|
local ContentProvider = game:GetService('ContentProvider')
|
|
local Modules = CoreGui.RobloxGui.Modules
|
|
|
|
local Http = require(Modules.Shell.Http)
|
|
local LoadingWidget = require(Modules.Shell.LoadingWidget)
|
|
local Utility = require(Modules.Shell.Utility)
|
|
|
|
local RETRIES = 6
|
|
local FADE_IN_TIME = 0.25
|
|
local TEMPLATE_DECAL = Instance.new("Decal")
|
|
local BATCH_LIMIT = 30
|
|
local function preloadThumbnailAsync(assetId)
|
|
TEMPLATE_DECAL.Texture = assetId
|
|
ContentProvider:PreloadAsync({ TEMPLATE_DECAL })
|
|
end
|
|
|
|
local BatchThumbnailLoader = {}
|
|
--[[ Sizes ]]--
|
|
BatchThumbnailLoader.Sizes =
|
|
{
|
|
Small = Vector2.new(100, 100);
|
|
Medium = Vector2.new(250, 250);
|
|
Large = Vector2.new(576, 324);
|
|
}
|
|
|
|
function BatchThumbnailLoader:Init()
|
|
self._active = true
|
|
self.isLoading = false
|
|
self.isRequesting = false
|
|
self.imageObjects = {}
|
|
self.loadingProps = {}
|
|
self.newRequests = nil
|
|
self.requests = nil
|
|
self.uriMap = {}
|
|
self.loaders = {}
|
|
self.activeTry = 0
|
|
end
|
|
|
|
local function createThumbnailKey(token, size)
|
|
return tostring(token)..tostring(size)
|
|
end
|
|
|
|
function BatchThumbnailLoader:CreateThumbnail(imageObject, token, size, showSpinner, fadeImage, spinnerProperties)
|
|
spinnerProperties = spinnerProperties or {}
|
|
if showSpinner == nil then
|
|
showSpinner = true
|
|
end
|
|
if fadeImage == nil then
|
|
fadeImage = true
|
|
end
|
|
local requestLoad = false
|
|
local thumbnailKey = createThumbnailKey(token, size)
|
|
if not self._active then
|
|
BatchThumbnailLoader:Init()
|
|
end
|
|
if self.isLoading == false then
|
|
requestLoad = true
|
|
if self.newRequests == nil then
|
|
self.newRequests = {}
|
|
end
|
|
end
|
|
if self.newRequests[size] == nil then
|
|
self.newRequests[size] = {}
|
|
end
|
|
table.insert(self.newRequests[size], token)
|
|
|
|
if self.imageObjects[thumbnailKey] == nil then
|
|
self.imageObjects[thumbnailKey] = {}
|
|
end
|
|
self.imageObjects[thumbnailKey][imageObject] = imageObject
|
|
|
|
--Create the loading spinner.
|
|
self.loadingProps[imageObject] = {}
|
|
self.loadingProps[imageObject].showSpinner = showSpinner
|
|
self.loadingProps[imageObject].fadeImage = fadeImage
|
|
self.loadingProps[imageObject].spinnerProperties = spinnerProperties
|
|
|
|
if self.uriMap[thumbnailKey] ~= nil then
|
|
spawn(function()
|
|
preloadThumbnailAsync(self.uriMap[thumbnailKey])
|
|
BatchThumbnailLoader:_loadImage(imageObject, self.uriMap[thumbnailKey])
|
|
end)
|
|
return
|
|
else
|
|
BatchThumbnailLoader:_loadImage(imageObject, nil)
|
|
end
|
|
|
|
if requestLoad then
|
|
spawn(function()
|
|
BatchThumbnailLoader:BatchLoadThumbnailsAsync()
|
|
end)
|
|
end
|
|
end
|
|
|
|
function BatchThumbnailLoader:_loadImage(imageObject, imageUri)
|
|
local loaded = imageUri ~= nil
|
|
if imageObject == nil then
|
|
return
|
|
end
|
|
imageObject.Image = ""
|
|
if self.loadingProps[imageObject].fadeImage then
|
|
local tween = Utility.PropertyTweener(imageObject, "ImageTransparency", 1, 1, 0,
|
|
Utility.EaseInOutQuad, true, nil)
|
|
end
|
|
if not loaded then
|
|
if self.loadingProps[imageObject].showSpinner then
|
|
self.loadingProps[imageObject].spinnerProperties['Parent'] = self.loadingProps[imageObject].spinnerProperties['Parent']
|
|
or imageObject
|
|
self.loaders[imageObject] = LoadingWidget(self.loadingProps[imageObject].spinnerProperties, nil, true)
|
|
end
|
|
else
|
|
if self.loaders[imageObject] then
|
|
self.loaders[imageObject]:Cleanup()
|
|
self.loaders[imageObject] = nil
|
|
end
|
|
imageObject.Image = imageUri
|
|
if self.loadingProps[imageObject].fadeImage then
|
|
local tween = Utility.PropertyTweener(imageObject, "ImageTransparency", 1, 0, FADE_IN_TIME,
|
|
Utility.EaseInOutQuad, true, nil)
|
|
end
|
|
end
|
|
end
|
|
|
|
function BatchThumbnailLoader:_loadThumbnails(tokens, size)
|
|
local batchTokens;
|
|
local reloadBatchList = {}
|
|
local batchCount = 0
|
|
while #tokens > 0 do
|
|
batchCount = batchCount + 1
|
|
batchTokens = {}
|
|
if #tokens <= BATCH_LIMIT then
|
|
batchTokens = tokens
|
|
tokens = {}
|
|
else
|
|
for _=1, BATCH_LIMIT do
|
|
local newToken = table.remove(tokens)
|
|
table.insert(batchTokens, newToken)
|
|
end
|
|
end
|
|
local result = Http.GetAssetThumbnailBatchAsync(batchTokens, size.x, size.y)
|
|
if result then
|
|
for i,v in ipairs(result) do
|
|
local token = batchTokens[i]
|
|
local isFinal = v["final"]
|
|
if isFinal then
|
|
local uri = v["url"]
|
|
local thumbnailKey = createThumbnailKey(token, size)
|
|
self.uriMap[thumbnailKey] = uri
|
|
for _,imageObj in pairs(self.imageObjects[thumbnailKey]) do
|
|
spawn(function()
|
|
preloadThumbnailAsync(self.uriMap[thumbnailKey])
|
|
BatchThumbnailLoader:_loadImage(imageObj, self.uriMap[thumbnailKey])
|
|
end)
|
|
end
|
|
else
|
|
table.insert(reloadBatchList, token)
|
|
end
|
|
end
|
|
else
|
|
for _,token in ipairs(batchTokens) do
|
|
table.insert(reloadBatchList, token)
|
|
end
|
|
end
|
|
end
|
|
return reloadBatchList
|
|
end
|
|
|
|
function BatchThumbnailLoader:_batchLoadThumbnails(batchList)
|
|
if batchList == nil then
|
|
return nil
|
|
end
|
|
local requireReload = false
|
|
local newBatchList = {};
|
|
for size, tokens in pairs(batchList) do
|
|
local reloadBatchList = BatchThumbnailLoader:_loadThumbnails(tokens, size)
|
|
if #reloadBatchList ~= 0 then
|
|
if newBatchList[size] == nil then
|
|
newBatchList[size] = {}
|
|
end
|
|
requireReload = true
|
|
newBatchList[size] = reloadBatchList
|
|
end
|
|
end
|
|
if not requireReload then
|
|
return nil
|
|
end
|
|
return newBatchList
|
|
end
|
|
|
|
-- marge new array into old array
|
|
local function mergeArray(newArray, oldArray)
|
|
local mergedArray = {}
|
|
if oldArray ~= nil then
|
|
for size, tokens in pairs(oldArray) do
|
|
mergedArray[size] = {}
|
|
for _,token in ipairs(tokens) do
|
|
table.insert(mergedArray[size], token)
|
|
end
|
|
end
|
|
end
|
|
if newArray ~= nil then
|
|
for size, tokens in pairs(newArray) do
|
|
if mergedArray[size] == nil then
|
|
mergedArray[size] = {}
|
|
end
|
|
for _,token in ipairs(tokens) do
|
|
table.insert(mergedArray[size], token)
|
|
end
|
|
end
|
|
end
|
|
return mergedArray
|
|
end
|
|
|
|
function BatchThumbnailLoader:_tryBatchLoadThumbnails(startTime)
|
|
local activeTry = startTime
|
|
local tryCount = 1
|
|
--retries until the max number of attempts. Or if this is still the most recent batch.
|
|
while tryCount <= RETRIES and activeTry == self.activeTry do
|
|
self.isRequesting = true
|
|
self.requests = BatchThumbnailLoader:_batchLoadThumbnails(self.requests)
|
|
self.isRequesting = false
|
|
if self.requests == nil then
|
|
break
|
|
end
|
|
tryCount = tryCount + 1
|
|
wait(tryCount ^ 2)
|
|
end
|
|
end
|
|
|
|
function BatchThumbnailLoader:BatchLoadThumbnailsAsync()
|
|
repeat
|
|
wait(0.1)
|
|
until self.isRequesting == false and self.isLoading == false
|
|
self.isLoading = true
|
|
if self.newRequests == nil then
|
|
-- No new requests.
|
|
self.isLoading = false
|
|
return
|
|
end
|
|
--Merge the new list of tokens to load.
|
|
self.requests = mergeArray(self.newRequests, self.requests)
|
|
self.newRequests = nil
|
|
self.isLoading = false
|
|
if self.requests ~= nil then
|
|
self.activeTry = tick()
|
|
BatchThumbnailLoader:_tryBatchLoadThumbnails(self.activeTry)
|
|
end
|
|
end
|
|
|
|
function BatchThumbnailLoader:SetTransparency(value, imageObject)
|
|
if self.loaders[imageObject] ~= nil then
|
|
self.loaders[imageObject]:SetTransparency(value)
|
|
end
|
|
end
|
|
|
|
return BatchThumbnailLoader |