if (type (Require) ~= 'function') then loadstring(exports['nc_libraries']:extend('Extend'), 'Require')() end Require('Table') Require('Math') Require('Thread') Require('Hash') Require('Interface/Textures') local AsyncElements = {} AsyncElements.Threads = { Textures = {}, Icons = {}, Requests = {}, Downloads = {}, Fonts = {} } AsyncElements.Count = { Textures = 0, Icons = 0, Requests = 0, Downloads = 0, Fonts = 0 } AsyncElements.DownloadCompleteEvent = false; AsyncElements.TextureFallback = dxCreateTexture(1, 1, 'dxt5') function AsyncElements:Constructor() if not self.Initialized then self.Initialized = true end return self end function AsyncElements.onDownloadComplete(File, Success, RequestedResource) if Success then local args = AsyncElements.Threads.Downloads[File]; if type(args) == 'table' then AsyncElements:Texture(unpack(args)) end end AsyncElements.Threads.Downloads[md5(File)] = nil; AsyncElements.Count.Downloads = AsyncElements.Count.Downloads - 1; if next(AsyncElements.Threads.Downloads) == nil then DOWNLOAD_COMPLETE_EVENT = false; removeEventHandler('onClientFileDownloadComplete', resourceRoot, AsyncElements.onDownloadComplete, true, 'high+99') end end function AsyncElements:GetTextureFallback() return self.TextureFallback end local fileContentCache = {} function AsyncElements:IconAuto(PathOrRaw, Callback, Time) local Raw = PathOrRaw if not PathOrRaw:find("= 5 then return self.TextureFallback, 0, 0 end if (type(Callback) == 'string' and Callback:lower() == 'clamp') then Callback = function(svg) dxSetTextureEdge(svg, 'clamp') end end local function CreateAIcon(Time, Index, Callback, isSync) if isSync then WaitTick(Time) end local SVG = Textures:RequestIcon(Width, Height, isResponsive, Raw) if type(Callback) == 'function' then pcall(Callback, SVG) end self.Threads.Icons[Index] = nil self.Count.Icons = self.Count.Icons - 1 end if (Time or _G.TIME_ASYNC_CREATION or 95) <= 0 then CreateAIcon(0, Index, Callback, false); else self.Threads.Icons[Index] = CreateThread(CreateAIcon, (Time or _G.TIME_ASYNC_CREATION or 20) * (Size + 1), Index, Callback, true) self.Count.Icons = (self.Count.Icons or 0) + 1 end return self.TextureFallback, 0, 0 end function AsyncElements:Icon(Width, Height, isResponsive, Raw, Callback, Time) local Icon = Textures:GetIcon(Width, Height, isResponsive, Raw); if isElement(Icon) then return Icon; end local Index = md5(Width..Height..tostring(isResponsive)..Raw); if self.Threads.Icons[Index] then return self.TextureFallback end local Size = self.Count.Icons or 1 if Size >= 5 then return self.TextureFallback end if (type(Callback) == 'string' and Callback:lower() == 'clamp') then Callback = function(svg) dxSetTextureEdge(svg, 'clamp') end end local function CreateAIcon(Time, Index, Callback, isSync) if isSync then WaitTick(Time) end local SVG = Textures:RequestIcon(Width, Height, isResponsive, Raw) if type(Callback) == 'function' then pcall(Callback, SVG) end self.Threads.Icons[Index] = nil self.Count.Icons = self.Count.Icons - 1 end if (Time or _G.TIME_ASYNC_CREATION or 95) <= 0 then CreateAIcon(0, Index, Callback, false); else self.Threads.Icons[Index] = CreateThread(CreateAIcon, (Time or _G.TIME_ASYNC_CREATION or 20) * Size, Index, Callback, true) self.Count.Icons = self.Count.Icons + 1 end return self.TextureFallback end function AsyncElements:Request(Url, Time, Args, Save, Callback) local Path = Url if not Args then Args = {true, 'argb', true, 'clamp'} end local Name = 'CACHE/' .. md5(Url):lower() .. '.png' if not AsyncElements.Threads.Requests[Name] then local Texture = AsyncElements.Textures:GetTexture(Path) if isElement(Texture) then return Texture end local Size = AsyncElements.Count.Requests or 1 if Size >= 5 then return self.TextureFallback end if not AsyncElements.Threads.Requests[Name] then AsyncElements.Threads.Requests[Name] = true IMAGES:AlterDelay(150, 20000) IMAGES:getExternImage(Url, function(Response, _, Url, Save, Name, Args) AsyncElements.Threads.Requests[Name] = nil; if (not Response or type(Url) ~= 'string') then return end local file if Save then if not fileExists(Name) then file = fileCreate(Name) if isElement(file) then fileWrite(file, Response) fileClose(file) end end end Textures:RequestTexture(Name, Args) end, {Url, Save, Name, Args}) end return self.TextureFallback end return self.TextureFallback end function AsyncElements:Download(_Type, ...) if _Type:lower() == 'texture' then local args = {...} if not args[4] then args[4] = {false, 'argb', true, 'clamp'} end local Path = args[2] local IMAGE_CREATED = self.Textures:GetTexture(Path) or false if isElement(IMAGE_CREATED) then return IMAGE_CREATED end if type(self.Threads.Downloads[Path]) == 'table' then return self.TextureFallback end local Size = self.Count.Downloads or 1 if Size >= 5 then return self.TextureFallback end AsyncElements.Threads.Downloads[Path] = args; AsyncElements.Count.Downloads = AsyncElements.Count.Downloads + 1; if not AsyncElements.DownloadCompleteEvent then addEventHandler('onClientFileDownloadComplete', resourceRoot, AsyncElements.onDownloadComplete, true, 'high+999') AsyncElements.DownloadCompleteEvent = true end downloadFile(Path) return self.TextureFallback; elseif _Type:lower() == 'icon' then local args = {...} local Width, Height, Raw = args[2], args[3], args[4] local ICON = AsyncElements.Textures:GetIcon(Width, Height, Raw); local Index = md5(Width..Height..Raw); if isElement(ICON) then return ICON; end if type(AsyncElements.Threads.Downloads[Index]) == 'table' then return self.TextureFallback; end local Size = AsyncElements.Count.Downloads or 1 if Size >= 5 then return self.TextureFallback end AsyncElements.Threads.Downloads[Index] = args; AsyncElements.Count.Downloads = AsyncElements.Count.Downloads + 1; if not AsyncElements.DownloadCompleteEvent then AsyncElements.DownloadCompleteEvent = true; addEventHandler('onClientFileDownloadComplete', resourceRoot, AsyncElements.onDownloadComplete, true, 'high+99') end downloadFile(Raw) return self.TextureFallback; end end function AsyncElements:SizedTexture(Path, Width, Height, Time, Args, Callback) if not Args then Args = {'argb', true, 'clamp'} end local IMAGE_CREATED = Textures:GetSizedTexture(Path, Width, Height) if isElement(IMAGE_CREATED) then return IMAGE_CREATED, true end local Index = Path .. ':' .. Width .. 'x' .. Height if self.Threads.Textures[Index] then return self.TextureFallback, false end local Size = self.Count.Textures or 1 if Size >= 5 then return self.TextureFallback, false end local function CreateATexture(Time, Path, Width, Height, Args, Callback, isSync) if isSync then WaitTick(Time) end local Texture = Textures:RequestSizedTexture(Path, Width, Height, true, unpack(Args)) if type(Callback) == 'function' then pcall(Callback, Texture) end if self.Threads.Textures[Index] then self.Threads.Textures[Index] = nil self.Count.Textures = self.Count.Textures - 1 end end if (Time or _G.TIME_ASYNC_CREATION or 95) <= 0 then CreateATexture(0, Path, Width, Height, Args, Callback, false) else self.Threads.Textures[Index] = CreateThread( CreateATexture, (Time or _G.TIME_ASYNC_CREATION or 95) * Size, Path, Width, Height, Args, Callback, true ) self.Count.Textures = self.Count.Textures + 1 end return self.TextureFallback, false end function AsyncElements:Texture(Path, Time, Args, Callback) if not Args then Args = {true, 'argb', true, 'clamp'} end local IMAGE_CREATED = Textures:GetTexture(Path) if isElement(IMAGE_CREATED) then return IMAGE_CREATED; end if self.Threads.Textures[Path] then return self.TextureFallback; end local Size = self.Count.Textures or 1 if Size >= 5 then return self.TextureFallback; end local function CreateATexture(Time, Path, Args, Callback, isSync) if isSync then WaitTick(Time) end local Texture = Textures:RequestTexture(Path, unpack(Args)) if type(Callback) == 'function' then pcall(Callback, Texture) end if self.Threads.Textures[Path] then self.Threads.Textures[Path] = nil self.Count.Textures = self.Count.Textures - 1 end end if (Time or _G.TIME_ASYNC_CREATION or 95) <= 0 then CreateATexture(0, Path, Args, Callback, false) else self.Threads.Textures[Path] = CreateThread(CreateATexture, (Time or _G.TIME_ASYNC_CREATION or 95) * Size, Path, Args, Callback, true) self.Count.Textures = self.Count.Textures + 1 end return self.TextureFallback; end function AsyncElements:Font(FontName, FontSize, Recursive, Time, Callback, ...) if not (FontName and FontSize) then return false end local FontElement = Fonts and Fonts.Elements and Fonts.Elements[FontName] and Fonts.Elements[FontName][FontSize] and Fonts.Elements[FontName][FontSize][type(Recursive) == 'boolean' and Recursive or false] if isElement(FontElement) then return FontElement; end if self.Threads.Fonts[FontName..FontSize..tostring(Recursive)] then return false; end local Size = self.Count.Fonts or 1 if Size >= 5 then return false; end local function CreateAFont(Time, FontName, FontSize, Recursive, Callback, isSync, ...) if isSync then WaitTick(Size == 1 and 1 or Time) end local FontElement = Fonts:Get(FontName, FontSize, Recursive, ...) if type(Callback) == 'function' then pcall(Callback, FontElement) end if self.Threads.Fonts[FontName..FontSize..tostring(Recursive)] then self.Threads.Fonts[FontName..FontSize..tostring(Recursive)] = nil self.Count.Fonts = self.Count.Fonts - 1 end return FontElement; end if (Time or _G.TIME_ASYNC_CREATION or 95) <= 0 then return CreateAFont(0, FontName, FontSize, Recursive, Callback, false, ...) else self.Threads.Fonts[FontName..FontSize..tostring(Recursive)] = CreateThread(CreateAFont, (Time or _G.TIME_ASYNC_CREATION or 95) * Size, FontName, FontSize, Recursive, Callback, true, ...) self.Count.Fonts = self.Count.Fonts + 1 end return false; end function AsyncElements:ARGBTexture(Path, Time, Args, Callback) if not Args then Args = {true, 'argb', true, 'clamp'} end local IMAGE_CREATED = Textures:GetTexture(Path) if isElement(IMAGE_CREATED) then return IMAGE_CREATED; end if self.Threads.Textures[Path] then return self.TextureFallback; end local Size = self.Count.Textures or 1 if Size >= 5 then return self.TextureFallback; end local function CreateATexture(Time, Path, Args, Callback, isSync) if isSync then WaitTick(Time) end local Texture = Textures:RequestARGBTexture(Path, unpack(Args)) if type(Callback) == 'function' then pcall(Callback, Texture) end if self.Threads.Textures[Path] then self.Threads.Textures[Path] = nil self.Count.Textures = self.Count.Textures - 1 end end if (Time or _G.TIME_ASYNC_CREATION or 95) <= 0 then CreateATexture(0, Path, Args, Callback, false) else self.Threads.Textures[Path] = CreateThread(CreateATexture, (Time or _G.TIME_ASYNC_CREATION or 95) * Size, Path, Args, Callback, true) self.Count.Textures = self.Count.Textures + 1 end return self.TextureFallback; end _G.AsyncElements = AsyncElements return AsyncElements