SprayMesh Extended: Rework preview panels to use a cache

Preview panels (such as the ones in the /spraymesh menu) will now attempt to cache DHTML panels, so they don't have to be redownloaded every time the user opens the panel.
This commit is contained in:
Chev 2025-01-06 15:12:04 -08:00
parent a82e4387db
commit 2e3cfce969
Signed by: chev2
GPG key ID: 0B212D6AED495EC9
3 changed files with 93 additions and 53 deletions

View file

@ -68,8 +68,8 @@ local PREVIEW_HTML_BASE = [=[
}
img, video {
width: %spx;
height: %spx;
width: 100vw;
height: 100vh;
object-fit: contain;
}
</style>
@ -84,7 +84,7 @@ local PREVIEW_HTML_IMAGE = [=[<img src="%s">]=]
local PREVIEW_HTML_VIDEO = [=[<video src="%s" muted autoplay loop>]=]
-- Gets preview HTML (HTML code only--no derma panel), to preview sprays using DHTML
function spraymesh_derma_utils.GetPreviewHTML(previewSize, sprayURL)
function spraymesh_derma_utils.GetPreviewHTML(sprayURL)
local elementFormatted = ""
if spraymesh.IsVideoExtension(sprayURL) then
@ -100,8 +100,31 @@ function spraymesh_derma_utils.GetPreviewHTML(previewSize, sprayURL)
return Format(
PREVIEW_HTML_BASE,
previewSize,
previewSize,
elementFormatted
)
end
local PANEL_CACHE = {}
-- Gets preview HTML (panel only), to preview sprays using DHTML
function spraymesh_derma_utils.GetPreviewPanel(sprayURL)
local urlHash = util.SHA256(sprayURL)
if IsValid(PANEL_CACHE[urlHash]) then
return PANEL_CACHE[urlHash]
else
local htmlPanel = vgui.Create("DHTML")
htmlPanel:SetVisible(true)
htmlPanel:SetAlpha(0)
htmlPanel:SetAllowLua(false)
htmlPanel:SetMouseInputEnabled(false)
htmlPanel:SetKeyboardInputEnabled(false)
local htmlCode = spraymesh_derma_utils.GetPreviewHTML(sprayURL)
htmlPanel:SetHTML(htmlCode)
PANEL_CACHE[urlHash] = htmlPanel
return htmlPanel
end
end

View file

@ -367,22 +367,53 @@ function PANEL:AddSpray(url, name)
self.Sprays[url] = nil
end
-- A transparency grid background, to indicate which sprays are transparent
local newSprayTransparentBase = self.IconLayout:Add("DPanel")
newSprayTransparentBase:SetTooltip("Right-click for options")
newSprayTransparentBase:SetMouseInputEnabled(true)
newSprayTransparentBase:SetCursor("hand")
newSprayTransparentBase:SetSize(self.SprayPreviewSize, self.SprayPreviewSize)
local newSpray = self.IconLayout:Add("DPanel")
newSpray:SetSize(self.SprayPreviewSize, self.SprayPreviewSize)
newSpray:SetMouseInputEnabled(true)
newSpray:SetCursor("hand")
newSpray:SetTooltip("Right-click for options")
newSprayTransparentBase.URL = string.gsub(url, "https?://", "")
newSprayTransparentBase.Name = name
newSpray.URL = string.gsub(url, "https?://", "")
newSpray.Name = name
newSprayTransparentBase.Paint = function(panel, width, height)
local sprayPanel = spraymesh_derma_utils.GetPreviewPanel(url)
newSpray.Material = sprayPanel:GetHTMLMaterial()
newSpray.Paint = function(panel, width, height)
-- Draw transparency grid, so the user has a better idea of which parts
-- of the image are transparent
surface.SetDrawColor(255, 255, 255, 255)
surface.SetMaterial(MAT_FAKE_TRANSPARENT)
surface.DrawTexturedRect(0, 0, width, height)
-- If the material isn't valid, continuously try to re-fetch the HTML IMaterial
if not panel.Material then
if IsValid(sprayPanel) then
panel.Material = sprayPanel:GetHTMLMaterial()
end
return
end
surface.SetMaterial(panel.Material)
surface.DrawTexturedRect(0, 0, width, height)
end
newSprayTransparentBase.OnMousePressed = function(panel, keyCode)
newSpray.PaintOver = function(panel, width, height)
if panel.URL == self.URL_CVar:GetString() then
--surface.SetDrawColor(255, 255, 255, 30)
--surface.DrawRect(0, 0, width, height)
local blink = Lerp((math.sin(RealTime() * 5) + 1) / 2, 200, 255)
surface.SetDrawColor(255, blink, 0, 255)
surface.DrawOutlinedRect(0, 0, width, height, 6)
end
draw.WordBox(8, width / 2, height - 8, panel.Name, "DSprayConfiguration.SprayText", SPRAY_NAME_BG_COLOR, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM)
end
newSpray.OnMousePressed = function(panel, keyCode)
if keyCode == MOUSE_LEFT then
surface.PlaySound("ui/buttonclick.wav")
@ -440,33 +471,6 @@ function PANEL:AddSpray(url, name)
end
end
local newSpray = newSprayTransparentBase:Add("DHTML")
newSpray:SetAllowLua(false)
newSpray:Dock(FILL)
newSpray:SetMouseInputEnabled(false)
local sprayHTML = spraymesh_derma_utils.GetPreviewHTML(self.SprayPreviewSize, url)
newSpray:SetHTML(sprayHTML)
newSpray.URL = string.gsub(url, "https?://", "")
newSpray.Name = name
newSpray.PaintOver = function(panel, width, height)
if panel.URL == self.URL_CVar:GetString() then
--surface.SetDrawColor(255, 255, 255, 30)
--surface.DrawRect(0, 0, width, height)
local blink = Lerp((math.sin(RealTime() * 5) + 1) / 2, 170, 255)
surface.SetDrawColor(0, 127, blink, 255)
surface.DrawOutlinedRect(0, 0, width, height, 6)
end
draw.WordBox(8, width / 2, height - 8, panel.Name, "DSprayConfiguration.SprayText", SPRAY_NAME_BG_COLOR, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM)
end
newSprayTransparentBase.Panel = newSpray
self.Sprays[url] = newSpray
-- Sort sprays

View file

@ -67,10 +67,11 @@ function DISPLAY:Init()
self.NameDisplay:DockMargin(0, 0, 0, 4)
self.NameDisplay:Dock(BOTTOM)
self.ImageDisplay = vgui.Create("DHTML", self)
self.ImageDisplay:SetAllowLua(false)
self.ImageDisplay:Dock(FILL)
-- Placeholder image
self.ImageDisplay = vgui.Create("DPanel", self)
self.ImageDisplay:SetMouseInputEnabled(false)
self.ImageDisplay:Dock(FILL)
self.ImageDisplay.Paint = nil
self:SetSize(self.SprayPreviewSize + 8, self.SprayPreviewSize + 32 + 8)
end
@ -104,14 +105,8 @@ function DISPLAY:OnMousePressed(keyCode)
end
function DISPLAY:Paint(w, h)
local padding = 4
surface.SetDrawColor(0, 0, 0, 200)
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(255, 255, 255, 255)
surface.SetMaterial(MAT_FAKE_TRANSPARENT)
surface.DrawTexturedRect(padding, padding, w - (padding * 2), h - 32 - (padding * 2))
end
function DISPLAY:SetURL(url)
@ -121,8 +116,26 @@ function DISPLAY:SetURL(url)
self.URL = url
local sprayHTML = spraymesh_derma_utils.GetPreviewHTML(self.SprayPreviewSize, url)
self.ImageDisplay:SetHTML(sprayHTML)
local sprayPanel = spraymesh_derma_utils.GetPreviewPanel(url)
self.ImageDisplay.Material = sprayPanel:GetHTMLMaterial()
self.ImageDisplay.Paint = function(panel, width, height)
surface.SetDrawColor(255, 255, 255, 255)
surface.SetMaterial(MAT_FAKE_TRANSPARENT)
surface.DrawTexturedRect(0, 0, width, height)
-- If the material isn't valid, continuously try to re-fetch the HTML IMaterial
if not panel.Material then
if IsValid(sprayPanel) then
panel.Material = sprayPanel:GetHTMLMaterial()
end
return
end
surface.SetMaterial(panel.Material)
surface.DrawTexturedRect(0, 0, width, height)
end
end
-- Builds the caption (e.g. Player - 12345678)