SyntaxGameServer/RCCService2018/content/internal/AppShell/Modules/Shell/BatchThumbnailLoader.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