mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
594 lines
14 KiB
Lua
594 lines
14 KiB
Lua
|
|
--[[
|
||
|
|
| 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 L = pace.LanguageString
|
||
|
|
|
||
|
|
local PANEL = {}
|
||
|
|
|
||
|
|
PANEL.ClassName = "tree"
|
||
|
|
PANEL.Base = "pac_dtree"
|
||
|
|
|
||
|
|
function PANEL:Init()
|
||
|
|
pace.pac_dtree.Init(self)
|
||
|
|
|
||
|
|
self:SetLineHeight(18)
|
||
|
|
self:SetIndentSize(10)
|
||
|
|
|
||
|
|
self.parts = {}
|
||
|
|
|
||
|
|
self:Populate()
|
||
|
|
|
||
|
|
pace.tree = self
|
||
|
|
end
|
||
|
|
|
||
|
|
do
|
||
|
|
local function get_added_nodes(self)
|
||
|
|
local added_nodes = {}
|
||
|
|
for i,v in ipairs(self.added_nodes) do
|
||
|
|
if v.part and v:IsVisible() and v:IsExpanded() then
|
||
|
|
table.insert(added_nodes, v)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
table.sort(added_nodes, function(a, b) return select(2, a:LocalToScreen()) < select(2, b:LocalToScreen()) end)
|
||
|
|
return added_nodes
|
||
|
|
end
|
||
|
|
|
||
|
|
local function scroll_to_node(self, node)
|
||
|
|
timer.Simple(0.1, function()
|
||
|
|
if not self:IsValid() then return end
|
||
|
|
if not node:IsValid() then return end
|
||
|
|
|
||
|
|
local _, y = self:LocalToScreen()
|
||
|
|
local h = self:GetTall()
|
||
|
|
|
||
|
|
local _, node_y = node:LocalToScreen()
|
||
|
|
|
||
|
|
if node_y > y + h or node_y < y then
|
||
|
|
self:ScrollToChild(node)
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
local info_image = {
|
||
|
|
pace.MiscIcons.info,
|
||
|
|
pace.MiscIcons.warning,
|
||
|
|
pace.MiscIcons.error,
|
||
|
|
}
|
||
|
|
|
||
|
|
function PANEL:Think(...)
|
||
|
|
if not pace.current_part:IsValid() then return end
|
||
|
|
|
||
|
|
if
|
||
|
|
pace.current_part.pace_tree_node and
|
||
|
|
pace.current_part.pace_tree_node:IsValid() and not
|
||
|
|
(
|
||
|
|
pace.BusyWithProperties:IsValid() or
|
||
|
|
pace.ActiveSpecialPanel:IsValid() or
|
||
|
|
pace.editing_viewmodel or
|
||
|
|
pace.editing_hands or
|
||
|
|
pace.properties.search:HasFocus()
|
||
|
|
) and
|
||
|
|
not gui.IsConsoleVisible()
|
||
|
|
then
|
||
|
|
if input.IsKeyDown(KEY_LEFT) then
|
||
|
|
pace.Call("VariableChanged", pace.current_part, "EditorExpand", false)
|
||
|
|
elseif input.IsKeyDown(KEY_RIGHT) then
|
||
|
|
pace.Call("VariableChanged", pace.current_part, "EditorExpand", true)
|
||
|
|
end
|
||
|
|
|
||
|
|
if input.IsKeyDown(KEY_UP) or input.IsKeyDown(KEY_PAGEUP) then
|
||
|
|
local added_nodes = get_added_nodes(self)
|
||
|
|
local offset = input.IsKeyDown(KEY_PAGEUP) and 10 or 1
|
||
|
|
if not self.scrolled_up or self.scrolled_up < os.clock() then
|
||
|
|
for i,v in ipairs(added_nodes) do
|
||
|
|
if v == pace.current_part.pace_tree_node then
|
||
|
|
local node = added_nodes[i - offset] or added_nodes[1]
|
||
|
|
if node then
|
||
|
|
node:DoClick()
|
||
|
|
scroll_to_node(self, node)
|
||
|
|
break
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self.scrolled_up = self.scrolled_up or os.clock() + 0.4
|
||
|
|
end
|
||
|
|
else
|
||
|
|
self.scrolled_up = nil
|
||
|
|
end
|
||
|
|
|
||
|
|
if input.IsKeyDown(KEY_DOWN) or input.IsKeyDown(KEY_PAGEDOWN) then
|
||
|
|
local added_nodes = get_added_nodes(self)
|
||
|
|
local offset = input.IsKeyDown(KEY_PAGEDOWN) and 10 or 1
|
||
|
|
if not self.scrolled_down or self.scrolled_down < os.clock() then
|
||
|
|
for i,v in ipairs(added_nodes) do
|
||
|
|
if v == pace.current_part.pace_tree_node then
|
||
|
|
local node = added_nodes[i + offset] or added_nodes[#added_nodes]
|
||
|
|
if node then
|
||
|
|
node:DoClick()
|
||
|
|
--scroll_to_node(self, node)
|
||
|
|
break
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self.scrolled_down = self.scrolled_down or os.clock() + 0.4
|
||
|
|
end
|
||
|
|
else
|
||
|
|
self.scrolled_down = nil
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
for _, part in pairs(pac.GetLocalParts()) do
|
||
|
|
local node = part.pace_tree_node
|
||
|
|
if not node or not node:IsValid() then continue end
|
||
|
|
|
||
|
|
if node.add_button then
|
||
|
|
node.add_button:SetVisible(false)
|
||
|
|
end
|
||
|
|
|
||
|
|
if part.Info then
|
||
|
|
local info = part.Info
|
||
|
|
node.info:SetTooltip(info.message)
|
||
|
|
node.info:SetImage(info_image[info.type])
|
||
|
|
node.info:SetVisible(true)
|
||
|
|
else
|
||
|
|
node.info:SetVisible(false)
|
||
|
|
end
|
||
|
|
|
||
|
|
if part.ClassName == "event" then
|
||
|
|
if part.is_active then
|
||
|
|
node.Icon:SetImage("icon16/clock_red.png")
|
||
|
|
else
|
||
|
|
node.Icon:SetImage(part.Icon)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if part.ClassName == "custom_animation" then
|
||
|
|
local anim = part:GetLuaAnimation()
|
||
|
|
if anim then
|
||
|
|
node:SetText(part:GetName() .. " [" .. string.format("%.2f", anim.Frame + anim.FrameDelta) .. "]")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if (part.ClassName == "proxy" or part.ClassName == "event") and part.Name == "" then
|
||
|
|
node:SetText(pace.pac_show_uniqueid:GetBool() and string.format("%s (%s)", part:GetName(), part:GetPrintUniqueID()) or part:GetName())
|
||
|
|
end
|
||
|
|
|
||
|
|
if part:IsHiddenCached() then
|
||
|
|
if not node.Icon.event_icon then
|
||
|
|
local pnl = vgui.Create("DImage", node.Icon)
|
||
|
|
pnl:SetImage("icon16/clock_red.png")
|
||
|
|
pnl:SetSize(8, 8)
|
||
|
|
pnl:SetPos(8, 8)
|
||
|
|
pnl:SetVisible(false)
|
||
|
|
node.Icon.event_icon = pnl
|
||
|
|
end
|
||
|
|
|
||
|
|
node.Icon.event_icon:SetVisible(true)
|
||
|
|
else
|
||
|
|
if node.Icon.event_icon then
|
||
|
|
node.Icon.event_icon:SetVisible(false)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local pnl = vgui.GetHoveredPanel() or NULL
|
||
|
|
|
||
|
|
if pnl:IsValid() then
|
||
|
|
local pnl = pnl:GetParent()
|
||
|
|
|
||
|
|
if IsValid(pnl) and IsValid(pnl.part) then
|
||
|
|
pace.Call("HoverPart", pnl.part)
|
||
|
|
if pnl.add_button then
|
||
|
|
pnl.add_button:SetVisible(true)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function PANEL:OnMouseReleased(mc)
|
||
|
|
if mc == MOUSE_RIGHT then
|
||
|
|
pace.Call("PartMenu")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function PANEL:SetModel(path)
|
||
|
|
if not file.Exists(path, "GAME") then
|
||
|
|
path = player_manager.TranslatePlayerModel(path)
|
||
|
|
if not file.Exists(path, "GAME") then
|
||
|
|
print(path, "is invalid")
|
||
|
|
return
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local pnl = vgui.Create("SpawnIcon", self)
|
||
|
|
pnl:SetModel(path or "")
|
||
|
|
pnl:SetSize(16, 16)
|
||
|
|
|
||
|
|
self.Icon:Remove()
|
||
|
|
self.Icon = pnl
|
||
|
|
|
||
|
|
self.ModelPath = path
|
||
|
|
end
|
||
|
|
|
||
|
|
function PANEL:GetModel()
|
||
|
|
return self.ModelPath
|
||
|
|
end
|
||
|
|
|
||
|
|
local function install_drag(node)
|
||
|
|
node:SetDraggableName("pac3")
|
||
|
|
|
||
|
|
local old = node.OnDrop
|
||
|
|
function node:OnDrop(child, ...)
|
||
|
|
-- we're hovering on the label, not the actual node
|
||
|
|
-- so get the parent node instead
|
||
|
|
if not child.part then
|
||
|
|
child = child:GetParent()
|
||
|
|
end
|
||
|
|
|
||
|
|
if child.part and child.part:IsValid() then
|
||
|
|
if self.part and self.part:IsValid() and self.part:GetParent() ~= child.part then
|
||
|
|
pace.RecordUndoHistory()
|
||
|
|
self.part:SetParent(child.part)
|
||
|
|
pace.RecordUndoHistory()
|
||
|
|
end
|
||
|
|
elseif self.part and self.part:IsValid() then
|
||
|
|
if self.part.ClassName ~= "group" then
|
||
|
|
pace.RecordUndoHistory()
|
||
|
|
local group = pac.CreatePart("group", self.part:GetPlayerOwner())
|
||
|
|
group:SetEditorExpand(true)
|
||
|
|
self.part:SetParent(group)
|
||
|
|
pace.RecordUndoHistory()
|
||
|
|
pace.TrySelectPart()
|
||
|
|
|
||
|
|
else
|
||
|
|
pace.RecordUndoHistory()
|
||
|
|
self.part:SetParent()
|
||
|
|
pace.RecordUndoHistory()
|
||
|
|
pace.RefreshTree(true)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return old(self, child, ...)
|
||
|
|
end
|
||
|
|
|
||
|
|
function node:DroppedOn(child)
|
||
|
|
|
||
|
|
if not child.part then
|
||
|
|
child = child:GetParent()
|
||
|
|
end
|
||
|
|
|
||
|
|
self:InsertNode(child)
|
||
|
|
self:SetExpanded(true)
|
||
|
|
|
||
|
|
if child.part and child.part:IsValid() then
|
||
|
|
if self.part and self.part:IsValid() and child.part:GetParent() ~= self.part then
|
||
|
|
pace.RecordUndoHistory()
|
||
|
|
child.part:SetParent(self.part)
|
||
|
|
pace.RecordUndoHistory()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function install_expand(node)
|
||
|
|
local old = node.SetExpanded
|
||
|
|
node.SetExpanded = function(self, b, ...)
|
||
|
|
if self.part and self.part:IsValid() then
|
||
|
|
self.part:SetEditorExpand(b)
|
||
|
|
return old(self, b, ...)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local old = node.Expander.OnMousePressed
|
||
|
|
node.Expander.OnMousePressed = function(pnl, code, ...)
|
||
|
|
old(pnl, code, ...)
|
||
|
|
|
||
|
|
if code == MOUSE_RIGHT then
|
||
|
|
local menu = DermaMenu()
|
||
|
|
menu:SetPos(input.GetCursorPos())
|
||
|
|
menu:MakePopup()
|
||
|
|
|
||
|
|
menu:AddOption(L"collapse all", function()
|
||
|
|
node.part:CallRecursive('SetEditorExpand', false)
|
||
|
|
pace.RefreshTree(true)
|
||
|
|
end):SetImage('icon16/arrow_in.png')
|
||
|
|
|
||
|
|
menu:AddOption(L"expand all", function()
|
||
|
|
node.part:CallRecursive('SetEditorExpand', true)
|
||
|
|
pace.RefreshTree(true)
|
||
|
|
end):SetImage('icon16/arrow_down.png')
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local fix_folder_funcs = function(tbl)
|
||
|
|
tbl.MakeFolder = function() end
|
||
|
|
tbl.FilePopulateCallback = function() end
|
||
|
|
tbl.FilePopulate = function() end
|
||
|
|
tbl.PopulateChildren = function() end
|
||
|
|
tbl.ChildExpanded = function() end
|
||
|
|
tbl.PopulateChildrenAndSelf = function() end
|
||
|
|
return tbl
|
||
|
|
end
|
||
|
|
|
||
|
|
local function node_layout(self, ...)
|
||
|
|
pace.pac_dtree_node.PerformLayout(self, ...)
|
||
|
|
if self.Label then
|
||
|
|
self.Label:SetFont(pace.CurrentFont)
|
||
|
|
--self.Label:SetTextColor(derma.Color("text_dark", self, color_black))
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.add_button then
|
||
|
|
local x = self.Label:GetPos() + self.Label:GetTextInset() + 4
|
||
|
|
surface.SetFont(pace.CurrentFont)
|
||
|
|
local w = surface.GetTextSize(self.Label:GetText())
|
||
|
|
self.add_button:SetPos(x + w, (self.Label:GetTall() - self.add_button:GetTall()) / 2)
|
||
|
|
end
|
||
|
|
|
||
|
|
if self.info then
|
||
|
|
local is_adding = self.add_button:IsVisible()
|
||
|
|
local x = self.Label:GetPos() + self.Label:GetTextInset() + (is_adding and self.add_button:GetWide() + 4 or 4)
|
||
|
|
surface.SetFont(pace.CurrentFont)
|
||
|
|
local w = surface.GetTextSize(self.Label:GetText())
|
||
|
|
self.info:SetPos(x + w, (self.Label:GetTall() - self.info:GetTall()) / 2)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function add_parts_menu(node)
|
||
|
|
pace.Call("AddPartMenu", node.part)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- a hack, because creating a new node button will mess up the layout
|
||
|
|
function PANEL:AddNode(...)
|
||
|
|
|
||
|
|
if self.RootNode then
|
||
|
|
install_drag(self.RootNode)
|
||
|
|
end
|
||
|
|
|
||
|
|
local node = fix_folder_funcs((self.RootNode and pace.pac_dtree.AddNode or pace.pac_dtree_node.AddNode)(self, ...))
|
||
|
|
install_expand(node)
|
||
|
|
install_drag(node)
|
||
|
|
|
||
|
|
local add_button = node:Add("DImageButton")
|
||
|
|
add_button:SetImage(pace.MiscIcons.new)
|
||
|
|
add_button:SetSize(16, 16)
|
||
|
|
add_button:SetVisible(false)
|
||
|
|
add_button.DoClick = function() add_parts_menu(node) pace.Call("PartSelected", node.part) end
|
||
|
|
add_button.DoRightClick = function() node:DoRightClick() end
|
||
|
|
node.add_button = add_button
|
||
|
|
node.SetModel = self.SetModel
|
||
|
|
node.GetModel = self.GetModel
|
||
|
|
node.AddNode = PANEL.AddNode
|
||
|
|
node.PerformLayout = node_layout
|
||
|
|
|
||
|
|
local info = node:Add("DImageButton")
|
||
|
|
info:SetImage(pace.MiscIcons.info)
|
||
|
|
info:SetSize(16, 16)
|
||
|
|
info:SetVisible(false)
|
||
|
|
info.DoClick = function() pace.MessagePrompt(info:GetTooltip()) end
|
||
|
|
node.info = info
|
||
|
|
|
||
|
|
return node
|
||
|
|
end
|
||
|
|
|
||
|
|
local enable_model_icons = CreateClientConVar("pac_editor_model_icons", "1")
|
||
|
|
|
||
|
|
function PANEL:PopulateParts(node, parts, children)
|
||
|
|
fix_folder_funcs(node)
|
||
|
|
|
||
|
|
local temp = {}
|
||
|
|
for k,v in pairs(parts) do
|
||
|
|
table.insert(temp, v)
|
||
|
|
end
|
||
|
|
parts = temp
|
||
|
|
|
||
|
|
local tbl = {}
|
||
|
|
|
||
|
|
table.sort(parts, function(a,b)
|
||
|
|
return a and b and a:GetName() < b:GetName()
|
||
|
|
end)
|
||
|
|
|
||
|
|
for key, val in pairs(parts) do
|
||
|
|
if not val:HasChildren() then
|
||
|
|
table.insert(tbl, val)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
for key, val in pairs(parts) do
|
||
|
|
if val:HasChildren() then
|
||
|
|
table.insert(tbl, val)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
for key, part in pairs(tbl) do
|
||
|
|
key = part.Id
|
||
|
|
|
||
|
|
if not part:GetShowInEditor() then goto CONTINUE end
|
||
|
|
|
||
|
|
if not part:HasParent() or children then
|
||
|
|
local part_node
|
||
|
|
|
||
|
|
if IsValid(part.pace_tree_node) then
|
||
|
|
part_node = part.pace_tree_node
|
||
|
|
elseif IsValid(self.parts[key]) then
|
||
|
|
part_node = self.parts[key]
|
||
|
|
else
|
||
|
|
part_node = node:AddNode(pace.pac_show_uniqueid:GetBool() and string.format("%s (%s)", part:GetName(), part:GetPrintUniqueID()) or part:GetName())
|
||
|
|
end
|
||
|
|
|
||
|
|
fix_folder_funcs(part_node)
|
||
|
|
|
||
|
|
if part.Description then part_node:SetTooltip(L(part.Description)) end
|
||
|
|
|
||
|
|
part.pace_tree_node = part_node
|
||
|
|
part_node.part = part
|
||
|
|
|
||
|
|
self.parts[key] = part_node
|
||
|
|
|
||
|
|
part_node.DoClick = function()
|
||
|
|
if not part:IsValid() then return end
|
||
|
|
pace.Call("PartSelected", part)
|
||
|
|
|
||
|
|
--part_node.add_button:SetVisible(true)
|
||
|
|
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
part_node.DoRightClick = function()
|
||
|
|
if not part:IsValid() then return end
|
||
|
|
|
||
|
|
pace.Call("PartMenu", part)
|
||
|
|
pace.Call("PartSelected", part)
|
||
|
|
part_node:InternalDoClick()
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
if
|
||
|
|
enable_model_icons:GetBool() and
|
||
|
|
part.is_model_part and
|
||
|
|
part.GetModel and
|
||
|
|
part:GetOwner():IsValid()
|
||
|
|
then
|
||
|
|
part_node:SetModel(part:GetOwner():GetModel(), part.Icon)
|
||
|
|
elseif isstring(part.Icon) then
|
||
|
|
part_node.Icon:SetImage(part.Icon)
|
||
|
|
end
|
||
|
|
|
||
|
|
self:PopulateParts(part_node, part:GetChildren(), true)
|
||
|
|
|
||
|
|
if part.newly_created then
|
||
|
|
part_node:SetSelected(true)
|
||
|
|
|
||
|
|
local function expand(part)
|
||
|
|
if part:HasParent() and part.Parent.pace_tree_node then
|
||
|
|
part.Parent.pace_tree_node:SetExpanded(true)
|
||
|
|
expand(part.Parent)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
expand(part)
|
||
|
|
|
||
|
|
part_node:SetSelected(true)
|
||
|
|
part.newly_created = nil
|
||
|
|
else
|
||
|
|
part_node:SetSelected(false)
|
||
|
|
part_node:SetExpanded(part:GetEditorExpand())
|
||
|
|
end
|
||
|
|
end
|
||
|
|
::CONTINUE::
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function PANEL:SelectPart(part)
|
||
|
|
for key, node in pairs(self.parts) do
|
||
|
|
if not node.part or not node.part:IsValid() then
|
||
|
|
node:Remove()
|
||
|
|
self.parts[key] = nil
|
||
|
|
else
|
||
|
|
if node.part == part then
|
||
|
|
node:SetSelected(true)
|
||
|
|
else
|
||
|
|
node:SetSelected(false)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self:InvalidateLayout()
|
||
|
|
end
|
||
|
|
|
||
|
|
function PANEL:Populate(reset)
|
||
|
|
|
||
|
|
self:SetLineHeight(18)
|
||
|
|
self:SetIndentSize(2)
|
||
|
|
|
||
|
|
for key, node in pairs(self.parts) do
|
||
|
|
if reset or (not node.part or not node.part:IsValid()) then
|
||
|
|
node:Remove()
|
||
|
|
self.parts[key] = nil
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
--[[self.m_pSelectedItem = nil
|
||
|
|
|
||
|
|
for key, node in pairs(self:GetItems()) do
|
||
|
|
node:Remove()
|
||
|
|
end]]
|
||
|
|
|
||
|
|
self:PopulateParts(self, pac.GetLocalParts())
|
||
|
|
|
||
|
|
self:InvalidateLayout()
|
||
|
|
end
|
||
|
|
|
||
|
|
pace.RegisterPanel(PANEL)
|
||
|
|
|
||
|
|
local function remove_node(part)
|
||
|
|
if not part:GetShowInEditor() then return end
|
||
|
|
|
||
|
|
if (part.pace_tree_node or NULL):IsValid() then
|
||
|
|
part.pace_tree_node:SetForceShowExpander()
|
||
|
|
part.pace_tree_node:GetRoot().m_pSelectedItem = nil
|
||
|
|
part.pace_tree_node:Remove()
|
||
|
|
pace.RefreshTree()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
pac.AddHook("pac_OnPartRemove", "pace_remove_tree_nodes", remove_node)
|
||
|
|
|
||
|
|
|
||
|
|
local last_refresh = 0
|
||
|
|
local function refresh(part)
|
||
|
|
if last_refresh > SysTime() then return end
|
||
|
|
if not part:GetShowInEditor() then return end
|
||
|
|
|
||
|
|
|
||
|
|
last_refresh = SysTime() + 0.1
|
||
|
|
timer.Simple(0, function()
|
||
|
|
if not part:IsValid() then return end
|
||
|
|
if not part:GetShowInEditor() then return end
|
||
|
|
|
||
|
|
pace.RefreshTree(true)
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
pac.AddHook("pac_OnWoreOutfit", "pace_refresh_tree_nodes", refresh)
|
||
|
|
pac.AddHook("pac_OnPartParent", "pace_refresh_tree_nodes", refresh)
|
||
|
|
pac.AddHook("pac_OnPartCreated", "pace_refresh_tree_nodes", refresh)
|
||
|
|
|
||
|
|
pac.AddHook("pace_OnVariableChanged", "pace_create_tree_nodes", function(part, key, val)
|
||
|
|
if key == "EditorExpand" then
|
||
|
|
local node = part.pace_tree_node
|
||
|
|
if IsValid(node) then
|
||
|
|
node:SetExpanded(val)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
function pace.RefreshTree(reset)
|
||
|
|
if pace.tree:IsValid() then
|
||
|
|
timer.Create("pace_refresh_tree", 0.01, 1, function()
|
||
|
|
if pace.tree:IsValid() then
|
||
|
|
pace.tree:Populate(reset)
|
||
|
|
pace.tree.RootNode:SetExpanded(true, true) -- why do I have to do this?
|
||
|
|
|
||
|
|
pace.TrySelectPart()
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if Entity(1):IsPlayer() and not PAC_RESTART and not VLL2_FILEDEF then
|
||
|
|
pace.OpenEditor()
|
||
|
|
pace.RefreshTree(true)
|
||
|
|
end
|