--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] local urltex = {} urltex.TextureSize = 1024 urltex.ActivePanel = urltex.ActivePanel or NULL urltex.Queue = urltex.Queue or {} urltex.Cache = urltex.Cache or {} concommand.Add("pac_urltex_clear_cache", function() urltex.Cache = {} urltex.Queue = {} end) if urltex.ActivePanel:IsValid() then urltex.ActivePanel:Remove() end local enable = CreateClientConVar("pac_enable_urltex", "1", true) local EMPTY_FUNC = function() end local function findFlag(url, flagID) local startPos, endPos = url:find(flagID) if not startPos then return url, false end if url:sub(endPos + 1, endPos + 1) == ' ' or url:sub(startPos - 1, startPos - 1) == ' ' then url = url:gsub(' ?' .. flagID .. ' ?', '') return url, true end return url, false end function urltex.GetMaterialFromURL(url, callback, skip_cache, shader, size, size_hack, additionalData) if size_hack == nil then size_hack = true end additionalData = additionalData or {} shader = shader or "VertexLitGeneric" if not enable:GetBool() then return end local noclampS, noclamp, noclampT url, noclampS = findFlag(url, 'noclamps') url, noclampT = findFlag(url, 'noclampt') url, noclamp = findFlag(url, 'noclamp') local urlAddress = url local urlIndex = url if noclamp then urlIndex = urlIndex .. ' noclamp' elseif noclampS then urlIndex = urlIndex .. ' noclampS' elseif noclampT then urlIndex = urlIndex .. ' noclampT' end noclamp = noclamp or noclampS and noclampT local renderTargetNeeded = noclampS or noclamp or noclampT if isfunction(callback) and not skip_cache and urltex.Cache[urlIndex] then local tex = urltex.Cache[urlIndex] local mat = CreateMaterial("pac3_urltex_" .. pac.Hash(), shader, additionalData) mat:SetTexture("$basetexture", tex) callback(mat, tex) return end callback = callback or EMPTY_FUNC if urltex.Queue[urlIndex] then table.insert(urltex.Queue[urlIndex].callbacks, callback) else urltex.Queue[urlIndex] = { url = urlAddress, urlIndex = urlIndex, callbacks = {callback}, tries = 0, size = size, size_hack = size_hack, shader = shader, noclampS = noclampS, noclampT = noclampT, noclamp = noclamp, rt = renderTargetNeeded, additionalData = additionalData } end end function urltex.Think() if not pac.IsEnabled() then return end if table.Count(urltex.Queue) > 0 then for url, data in pairs(urltex.Queue) do -- when the panel is gone start a new one if not urltex.ActivePanel:IsValid() then urltex.StartDownload(data.url, data) end end urltex.Busy = true else urltex.Busy = false end end timer.Create("urltex_queue", 0.1, 0, urltex.Think) function urltex.StartDownload(url, data) if urltex.ActivePanel:IsValid() then urltex.ActivePanel:Remove() end url = pac.FixUrl(url) local size = tonumber(data.size or urltex.TextureSize) local id = "urltex_download_" .. url local pnl local frames_passed = 0 local function createDownloadPanel() pnl = vgui.Create("DHTML") -- Tested in PPM/2, this code works perfectly pnl:SetVisible(false) pnl:SetSize(size, size) pnl:SetHTML([[ ]]) pnl:Refresh() function pnl:ConsoleMessage(msg) if msg == 'REAL_FRAME_PASSED' then frames_passed = frames_passed + 1 end end urltex.ActivePanel = pnl end local go = false local time = 0 local timeoutNum = 0 local think local function onTimeout() timeoutNum = timeoutNum + 1 if IsValid(pnl) then pnl:Remove() end if timeoutNum < 5 then pac.dprint("material download %q timed out.. trying again for the %ith time", url, timeoutNum) -- try again go = false time = 0 createDownloadPanel() else pac.dprint("material download %q timed out for good", url, timeoutNum) pac.RemoveHook("Think", id) timer.Remove(id) urltex.Queue[data.urlIndex] = nil end end function think() -- panel is no longer valid if not pnl:IsValid() then onTimeout() return end -- give it some time.. IsLoading is sometimes lying, especially on chromium branch if not go and not pnl:IsLoading() then time = pac.RealTime + 1 go = true end if go and time < pac.RealTime and frames_passed > 20 then pnl:UpdateHTMLTexture() local html_mat = pnl:GetHTMLMaterial() if html_mat then local crc = pac.Hash() local vertex_mat = CreateMaterial("pac3_urltex_" .. crc, data.shader, data.additionalData) local tex = html_mat:GetTexture("$basetexture") tex:Download() vertex_mat:SetTexture("$basetexture", tex) -- tex:Download() urltex.Cache[data.urlIndex] = tex pac.RemoveHook("Think", id) timer.Remove(id) urltex.Queue[data.urlIndex] = nil local rt if data.rt then local textureFlags = 0 textureFlags = textureFlags + 4 -- clamp S textureFlags = textureFlags + 8 -- clamp T textureFlags = textureFlags + 16 -- anisotropic textureFlags = textureFlags + 256 -- no mipmaps -- textureFlags = textureFlags + 2048 -- Texture is procedural textureFlags = textureFlags + 32768 -- Texture is a render target -- textureFlags = textureFlags + 67108864 -- Usable as a vertex texture if data.noclamp then textureFlags = textureFlags - 4 textureFlags = textureFlags - 8 elseif data.noclampS then textureFlags = textureFlags - 4 elseif data.noclampT then textureFlags = textureFlags - 8 end local vertex_mat2 = CreateMaterial("pac3_urltex_" .. crc .. '_hack', 'UnlitGeneric', data.additionalData) vertex_mat2:SetTexture("$basetexture", tex) rt = GetRenderTargetEx("pac3_urltex_" .. crc, size, size, RT_SIZE_NO_CHANGE, MATERIAL_RT_DEPTH_NONE, textureFlags, CREATERENDERTARGETFLAGS_UNFILTERABLE_OK, IMAGE_FORMAT_RGB888) render.PushRenderTarget(rt) render.Clear(0, 0, 0, 255, false, false) cam.Start2D() surface.SetMaterial(vertex_mat2) surface.SetDrawColor(255, 255, 255) surface.DrawTexturedRect(0, 0, size, size) cam.End2D() render.PopRenderTarget() vertex_mat:SetTexture('$basetexture', rt) urltex.Cache[data.urlIndex] = rt end timer.Simple(0, function() pnl:Remove() end) if data.callbacks then for i, callback in pairs(data.callbacks) do callback(vertex_mat, rt or tex) end end end end end pac.AddHook("Think", id, think) -- 5 sec max timeout, 5 maximal timeouts timer.Create(id, 5, 5, onTimeout) createDownloadPanel() end return urltex