From c01b5b902ada81c632399d372c36447e6dcb55d6 Mon Sep 17 00:00:00 2001 From: pingu7867 Date: Thu, 17 Apr 2025 23:34:52 -0400 Subject: [PATCH 1/5] autoload prompt: replace "cancel" with "don't show this again" and change the default --- lua/pac3/editor/client/saved_parts.lua | 2 +- lua/pac3/editor/client/wear.lua | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lua/pac3/editor/client/saved_parts.lua b/lua/pac3/editor/client/saved_parts.lua index 4ef455512..98e070214 100644 --- a/lua/pac3/editor/client/saved_parts.lua +++ b/lua/pac3/editor/client/saved_parts.lua @@ -96,7 +96,7 @@ end local last_backup local maxBackups = CreateConVar("pac_backup_limit", "100", {FCVAR_ARCHIVE}, "Maximal amount of backups") -local autoload_prompt = CreateConVar("pac_prompt_for_autoload", "1", {FCVAR_ARCHIVE}, "Whether to ask before loading autoload. The prompt can let you choose to not load, pick autoload or the newest backup") +local autoload_prompt = CreateConVar("pac_prompt_for_autoload", "0", {FCVAR_ARCHIVE}, "Whether to ask before loading autoload. The prompt can let you choose to not load, pick autoload or the newest backup") local auto_spawn_prop = CreateConVar("pac_autoload_preferred_prop", "2", {FCVAR_ARCHIVE}, "When loading a pac with an owner name suggesting a prop, notify you and then wait before auto-applying the outfit next time you spawn a prop.\n" .. "0 : do not check\n1 : check if only 1 such group is present\n2 : check if multiple such groups are present and queue one group at a time") diff --git a/lua/pac3/editor/client/wear.lua b/lua/pac3/editor/client/wear.lua index 8a03a5d73..260c77e97 100644 --- a/lua/pac3/editor/client/wear.lua +++ b/lua/pac3/editor/client/wear.lua @@ -305,7 +305,7 @@ do local backup_files, directories = file.Find( "pac3/__backup/*.txt", "DATA", "datedesc") local latest_outfit = cookie.GetString( "pac_last_loaded_outfit", "" ) if not backup_files then - local pnl = Derma_Query("Do you want to load your autoload outfit?", "PAC3 autoload (pac_prompt_for_autoload)", + local pnl = Derma_Query("Do you want to load your autoload outfit?\nclick outside the window to cancel", "PAC3 autoload (pac_prompt_for_autoload)", "load pac3/autoload.txt : " .. string.NiceSize(file.Size("pac3/autoload.txt", "DATA")), function() pac.Message("Wearing autoload...") pace.LoadParts("autoload") @@ -321,13 +321,13 @@ do end end, - "cancel", function() pac.Message("Not loading autoload or backups...") end + "don't show this again", function() GetConVar("pac_prompt_for_autoload"):SetBool(false) end ) pnl.Think = function() if not pnl:HasFocus() or (input.IsMouseDown(MOUSE_LEFT) and not (pnl:IsHovered() or pnl:IsChildHovered())) then pnl:Remove() end end else if backup_files[1] then local latest_autosave = "pac3/__backup/" .. backup_files[1] - local pnl = Derma_Query("Do you want to load an outfit?", "PAC3 autoload (pac_prompt_for_autoload)", + local pnl = Derma_Query("Do you want to load an outfit?\nclick outside the window to cancel", "PAC3 autoload (pac_prompt_for_autoload)", "load pac3/autoload.txt : " .. string.NiceSize(file.Size("pac3/autoload.txt", "DATA")), function() pac.Message("Wearing autoload...") pace.LoadParts("autoload") @@ -348,18 +348,18 @@ do end end, - "cancel", function() pac.Message("Not loading autoload or backups...") end + "don't show this again", function() GetConVar("pac_prompt_for_autoload"):SetBool(false) end ) pnl.Think = function() if not pnl:HasFocus() or (input.IsMouseDown(MOUSE_LEFT) and not (pnl:IsHovered() or pnl:IsChildHovered())) then pnl:Remove() end end else - local pnl = Derma_Query("Do you want to load your autoload outfit?", "PAC3 autoload (pac_prompt_for_autoload)", + local pnl = Derma_Query("Do you want to load your autoload outfit?\nclick outside the window to cancel", "PAC3 autoload (pac_prompt_for_autoload)", "load pac3/autoload.txt : " .. string.NiceSize(file.Size("pac3/autoload.txt", "DATA")), function() pac.Message("Wearing autoload...") pace.LoadParts("autoload") pace.WearParts() end, - "cancel", function() pac.Message("Not loading autoload or backups...") end + "don't show this again", function() GetConVar("pac_prompt_for_autoload"):SetBool(false) end ) pnl.Think = function() if not pnl:HasFocus() or (input.IsMouseDown(MOUSE_LEFT) and not (pnl:IsHovered() or pnl:IsChildHovered())) then pnl:Remove() end end end From e7dddc6f37961e375191fbd6e1cd035b54ef1b00 Mon Sep 17 00:00:00 2001 From: pingu7867 Date: Fri, 18 Apr 2025 16:48:50 -0400 Subject: [PATCH 2/5] Fixed clip planes lagging behind when parented to a bone on a model part (#1391) (#1404) Resolves last reported problem on issue #1341 Co-authored-by: Twist --- lua/pac3/core/client/parts/bone.lua | 15 +++++++++------ lua/pac3/core/client/parts/clip.lua | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lua/pac3/core/client/parts/bone.lua b/lua/pac3/core/client/parts/bone.lua index e3414b447..29526e574 100644 --- a/lua/pac3/core/client/parts/bone.lua +++ b/lua/pac3/core/client/parts/bone.lua @@ -290,12 +290,12 @@ function PART:GetBonePosition() if not self.bone_index then return ent:GetPos(), ent:GetAngles() end local m = ent:GetBoneMatrix(self.bone_index) - if not m then return ent:GetPos(), ent:GetAngles() end - local pos = m:GetTranslation() - local ang = m:GetAngles() - - return pos, ang + if m then + return m:GetTranslation(), m:GetAngles() + else + return ent:GetPos(), ent:GetAngles() + end end function PART:GetBoneMatrix() @@ -306,12 +306,15 @@ BUILDER:Register() pac.AddHook("OnEntityCreated", "hide_mesh_no_crash", function(ent) local ply = ent:GetRagdollOwner() + if ply:IsPlayer() and ply.pac_inf_scale then for i = 0, ply:GetBoneCount() - 1 do local scale = ply:GetManipulateBoneScale(i) + if scale == inf_scale then - scale = Vector(0,0,0) + scale = vector_origin end + ply:ManipulateBoneScale(i, scale) end end diff --git a/lua/pac3/core/client/parts/clip.lua b/lua/pac3/core/client/parts/clip.lua index 7b40e4f0a..7dda463a2 100644 --- a/lua/pac3/core/client/parts/clip.lua +++ b/lua/pac3/core/client/parts/clip.lua @@ -40,6 +40,16 @@ do function PART:PreOnDraw() bclip = render_EnableClipping(true) + -- this fixes clip planes lagging behind when parented to a bone on a model part + local owner = self:GetParentOwner() + if owner:IsValid() and not owner.pac_clip_bonessetup and owner.PACPart then + -- in case there are multiple clips on one model part, only the first one needs to call SetupBones + self.pac_clip_owner = owner + owner.pac_clip_bonessetup = true + + pac.SetupBones(owner) + end + local pos, ang = LocalToWorld(self.Position + self.PositionOffset, self:CalcAngles(self.Angles + self.AngleOffset), self:GetBonePosition()) local normal = ang:Forward() @@ -49,6 +59,11 @@ do local render_PopCustomClipPlane = render.PopCustomClipPlane function PART:PostOnDraw() + if self.pac_clip_owner then + self.pac_clip_owner.pac_clip_bonessetup = nil + self.pac_clip_owner = nil + end + render_PopCustomClipPlane() render_EnableClipping(bclip) From 9a2febc3f1b2c61f4bc2f68e560d804bd8b3815f Mon Sep 17 00:00:00 2001 From: pingu7867 Date: Tue, 7 Oct 2025 17:38:54 -0400 Subject: [PATCH 3/5] wear fix when in whitelist mode, don't consider yourself as blacklisted master duplicate of Commit 00f614c I'm pushing this directly duplicated because I have other changes on develop not ready for master and this is a medium-priority fix --- lua/pac3/editor/client/wear.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/pac3/editor/client/wear.lua b/lua/pac3/editor/client/wear.lua index dbb38d37f..690fbd3f7 100644 --- a/lua/pac3/editor/client/wear.lua +++ b/lua/pac3/editor/client/wear.lua @@ -138,7 +138,7 @@ do -- from server pac.dprint("received outfit %q from %s with %i number of children to set on %s", part_data.self.Name or "", tostring(owner), table.Count(part_data.children), part_data.self.OwnerName or "") if pace.CallHook("WearPartFromServer", owner, part_data, data) == false then return end - if pace.ShouldIgnorePlayer(owner) then pace.RemovePartFromServer(owner, "__ALL__", data) return end + if pace.ShouldIgnorePlayer(owner) and owner ~= LocalPlayer() then pace.RemovePartFromServer(owner, "__ALL__", data) return end local dupepart = pac.GetPartFromUniqueID(data.player_uid, part_data.self.UniqueID) From 34204198e93cb86a78af4fd6c4d40ca96f221ed5 Mon Sep 17 00:00:00 2001 From: TiberiumFusion <6332277+TiberiumFusion@users.noreply.github.com> Date: Tue, 14 Oct 2025 20:36:29 -0400 Subject: [PATCH 4/5] Handle Google drive images so that they display properly This covers the 2 interactive ways that the user can make pac load a web resource in the context of a material. The third (non-interactive way) in pac's spaghetti code lies elsewhere. --- lua/pac3/core/client/util.lua | 2 +- lua/pac3/core/shared/http.lua | 15 +++++++++++---- lua/pac3/libraries/urltex.lua | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lua/pac3/core/client/util.lua b/lua/pac3/core/client/util.lua index b032a2df3..6b3951a3c 100644 --- a/lua/pac3/core/client/util.lua +++ b/lua/pac3/core/client/util.lua @@ -440,7 +440,7 @@ function pac.Handleurltex(part, url, callback, shader, additionalData) if not url:match("https?://.+/%S*") then return false end pac.urltex.GetMaterialFromURL( - pac.FixUrl(url), + pac.FixUrl(url, "image"), function(mat, tex) if not part:IsValid() then return end diff --git a/lua/pac3/core/shared/http.lua b/lua/pac3/core/shared/http.lua index 35d5ddd55..2114d5738 100644 --- a/lua/pac3/core/shared/http.lua +++ b/lua/pac3/core/shared/http.lua @@ -61,7 +61,7 @@ local function http(method, url, headers, cb, failcb) }) end -function pac.FixUrl(url) +function pac.FixUrl(url, expectedContentType) url = url:Trim() url = url:gsub("[\"'<>\n\\]+", "") @@ -74,14 +74,21 @@ function pac.FixUrl(url) return url end - if url:find("drive.google.com", 1, true) and not url:find("export=download", 1, true) then + if url:find("drive.google.com", 1, true) then local id = url:match("https://drive.google.com/file/d/(.-)/") or url:match("https://drive.google.com/file/d/(.-)$") or - url:match("https://drive.google.com/open%?id=(.-)$") + url:match("https://drive.google.com/open%?id=(.-)$") or + url:match("https://drive.google.com/uc%?export=download&id=(.-)$") or + url:match("https://drive.google.com/uc%?id=(.-)&export=download$") if id then - return "https://drive.google.com/uc?export=download&id=" .. id + if expectedContentType == "image" then + local thumbnailSize = math.Clamp( pac.urltex.TextureSize, 32, 4096 ) + return "https://drive.google.com/thumbnail?id=" .. id .. "&sz=s" .. string.format("%.0f", thumbnailSize) + elseif not url:find("export=download", 1, true) then + return "https://drive.google.com/uc?export=download&id=" .. id + end end return url end diff --git a/lua/pac3/libraries/urltex.lua b/lua/pac3/libraries/urltex.lua index 93c8cf1cf..07b847ee8 100644 --- a/lua/pac3/libraries/urltex.lua +++ b/lua/pac3/libraries/urltex.lua @@ -113,7 +113,7 @@ function urltex.StartDownload(url, data) urltex.ActivePanel:Remove() end - url = pac.FixUrl(url) + url = pac.FixUrl(url, "image") local size = tonumber(data.size or urltex.TextureSize) local id = "urltex_download_" .. url local pnl From ad24088b51ae7dc4b014b727315f19e062d02293 Mon Sep 17 00:00:00 2001 From: TiberiumFusion <6332277+TiberiumFusion@users.noreply.github.com> Date: Wed, 15 Oct 2025 01:21:40 -0400 Subject: [PATCH 5/5] Handle multiple mime types in server responses This enables pac to properly download and display remote content when the server providing it uses mime type strings such as "image/png,application/binary". This in turn fixes the loading of pngs and jpgs from some servers (notably Google drive). --- lua/pac3/libraries/resource.lua | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lua/pac3/libraries/resource.lua b/lua/pac3/libraries/resource.lua index 138705529..269f11b8b 100644 --- a/lua/pac3/libraries/resource.lua +++ b/lua/pac3/libraries/resource.lua @@ -139,6 +139,7 @@ local function download(from, to, callback, on_fail, on_header, check_etag, etag local allowed = { [".txt"] = true, + [".jpeg"] = true, [".jpg"] = true, [".png"] = true, [".vtf"] = true, @@ -150,7 +151,20 @@ local function download(from, to, callback, on_fail, on_header, check_etag, etag function(body, len, header) do if need_extension then - local ext = header["Content-Type"] and (header["Content-Type"]:match(".-/(.-);") or header["Content-Type"]:match(".-/(.+)")) or "dat" + local ext = "dat" + if header["Content-Type"] then + for _, mime in ipairs( string.Split(header["Content-Type"], ',') ) do -- some common services, including google, serve multi-item mime strings like "image/png,application/binary" + subtype = mime:match(".-/(.-);") or mime:match(".-/(.+)") + if subtype then + subtype = subtype:lower() + if allowed['.' .. subtype] then + ext = subtype + break -- take the first subtype (if any) found in our whitelist + end + end + end + end + if ext == "jpeg" then ext = "jpg" end if body:StartWith("VTF") then