Download CommonLua/GedXWindowInspector.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 10.4 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/GedXWindowInspector.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/GedXWindowInspector.lua
-
curl -L -o GedXWindowInspector.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/GedXWindowInspector.lua
10.4 kB
| function OpenXWindowInspector(context) | |
| PauseLuaThreads("XWindowInspector") | |
| CreateRealTimeThread(function() | |
| local target = terminal.desktop:GetMouseTarget(terminal.GetMousePos()) or terminal.desktop | |
| local gedTarget = GetParentOfKind(target, "GedApp") | |
| if gedTarget then | |
| context.dark_mode = gedTarget.dark_mode | |
| end | |
| local ged = OpenGedApp("XWindowInspector", terminal.desktop, context) | |
| if ged then | |
| GedXWindowInspectorSelectWindow(ged, target) | |
| else | |
| ResumeLuaThreads("XWindowInspector") | |
| end | |
| end) | |
| end | |
| function OnMsg.LuaThreadsPaused() | |
| ObjModified(terminal.desktop) -- updates the status text, which is bound with context "root" (which happens to be the desktop) | |
| end | |
| function GedThreadsPausedStatus() | |
| return AreLuaThreadsPaused() and "<style GedError>Lua threads are PAUSED to freeze the UI!" or "Threads currently running..." | |
| end | |
| function GedTogglePauseLuaThreads(ged) | |
| local was_paused = next(PauseLuaThreadsReasons) | |
| if was_paused then | |
| ResumeLuaThreads("XWindowInspector") | |
| local pause_reason = next(PauseLuaThreadsReasons) | |
| if pause_reason then | |
| ged:ShowMessage("Warning", string.format("Lua threads are still paused due to reason %s", pause_reason)) | |
| end | |
| else | |
| PauseLuaThreads("XWindowInspector") | |
| end | |
| end | |
| if FirstLoad then | |
| GedXWindowInspectors = {} | |
| GedXWindowInspectorSelection = setmetatable({}, weak_keys_meta) | |
| GedXWindowInspectorTerminalTarget = false | |
| end | |
| function OnMsg.ClassesGenerate() | |
| assert(not (XWindow.TreeView or XWindow.PlacementText or XWindow.OnEditorSelect)) | |
| XWindow.TreeView = T(408752573312, "<NodeColor><class> <color 128 128 128><Id><PlacementText>") | |
| XWindow.NodeColor = function(self) | |
| return self.IdNode and #self > 0 and "<color 75 105 198>" or "" | |
| end | |
| XWindow.PlacementText = function(self) | |
| local ret = { (self:GetProperty("Id") ~= "") and "" or nil } | |
| local dbg_template = rawget(self, "__dbg_template_template") or rawget(self, "__dbg_template") | |
| if dbg_template then | |
| ret[#ret+1] = "T: " .. dbg_template | |
| end | |
| local dock = self:GetProperty("Dock") | |
| if dock then | |
| ret[#ret+1] = "Dock: " .. dock | |
| end | |
| local dbg_template_comment = rawget(self, "__dbg_template_comment") | |
| if dbg_template_comment then | |
| ret[#ret+1] = "<color 0 128 0>" .. dbg_template_comment | |
| end | |
| return Untranslated(table.concat(ret, " ")) | |
| end | |
| XWindow.OnEditorSelect = function(self, selected, ged) | |
| if selected then | |
| GedXWindowInspectorSelection[ged] = self | |
| end | |
| end | |
| end | |
| local function GedUpdateActionToggled(actionid, value) | |
| for k, socket in pairs(GedConnections) do | |
| if socket.app_template == "XWindowInspector" or socket.app_template == "GedParticleEditor" then | |
| socket:Send("rfnApp", "SetActionToggled", actionid, value) | |
| end | |
| end | |
| end | |
| local function GedUpdateInspectorActions(socket) | |
| socket:Send("rfnApp", "SetActionToggled", "FocusLogging", terminal.desktop.focus_logging_enabled) | |
| socket:Send("rfnApp", "SetActionToggled", "RolloverLogging", terminal.desktop.rollover_logging_enabled) | |
| socket:Send("rfnApp", "SetActionToggled", "ContextLogging", XContextUpdateLogging) | |
| socket:Send("rfnApp", "SetActionToggled", "RolloverMode", GedXWindowInspectorTerminalTarget and GedXWindowInspectorTerminalTarget.enabled) | |
| end | |
| function OnMsg.GedOpened(ged_id) | |
| local ged = GedConnections[ged_id] | |
| if ged and ged.app_template == "XWindowInspector" then | |
| table.insert(GedXWindowInspectors, ged) | |
| end | |
| if ged and (ged.app_template == "XWindowInspector" or ged.app_template == "GedParticleEditor") then | |
| GedUpdateInspectorActions(ged) | |
| end | |
| end | |
| function GedRpcBindToGlobal(ged, path, global_name) | |
| local obj = ged:ResolveObj(path) | |
| rawset(_G, global_name, obj) | |
| end | |
| function OnMsg.GedClosing(ged_id) | |
| table.remove_entry(GedXWindowInspectors, "ged_id", ged_id) | |
| if not next(GedXWindowInspectors) then | |
| ResumeLuaThreads("XWindowInspector") | |
| end | |
| end | |
| function OnMsg.XWindowModified(win, child, leaving) | |
| if #GedXWindowInspectors == 0 then return end | |
| if leaving then | |
| -- validate selected windows | |
| for ged, selection in pairs(GedXWindowInspectorSelection) do | |
| if child == selection then | |
| GedXWindowInspectorSelection[ged] = win | |
| end | |
| end | |
| -- close inspectors with deleted root objects | |
| for _, inspector in ipairs(GedXWindowInspectors) do | |
| if child == inspector:ResolveObj("root") then | |
| inspector:Close() | |
| end | |
| end | |
| end | |
| repeat | |
| for _, inspector in ipairs(GedXWindowInspectors) do | |
| if win == inspector:ResolveObj("root") then | |
| -- go through a thread, so multiple changes to a XWindow only result in a single call | |
| if not win:IsThreadRunning("XWindowInspectorObjModified") then | |
| local ged, modified = inspector, win | |
| win:CreateThread("XWindowInspectorObjModified", function() | |
| ObjModified(modified) | |
| GedXWindowInspectorSelectWindow(ged, GedXWindowInspectorSelection[ged]) | |
| end) | |
| end | |
| end | |
| end | |
| win = win.parent | |
| until not win | |
| end | |
| local function GetItemPath(root, control) | |
| local path = {} | |
| if not root or not control or not control:IsWithin(root) then | |
| return path | |
| end | |
| local target = control | |
| while target.parent and target ~= root do | |
| local idx = table.find(target.parent, target) | |
| table.insert(path, 1, idx) | |
| target = target.parent | |
| end | |
| return path | |
| end | |
| function GedXWindowInspectorSelectWindow(socket, win) | |
| local root = socket:ResolveObj("root") | |
| if socket.selected_object ~= win then | |
| socket:SetSelection("root", GetItemPath(root, win)) | |
| socket.selected_object = win | |
| end | |
| end | |
| function GedGetXWindowPath(obj) | |
| local data = {} | |
| repeat | |
| table.insert(data, 1, { | |
| text = _InternalTranslate(XWindow.TreeView, obj, false), | |
| path = GetItemPath(terminal.desktop, obj), | |
| }) | |
| obj = obj.parent | |
| until not obj | |
| return data | |
| end | |
| DefineClass.RolloverModeTerminalTarget = { | |
| __parents = { "TerminalTarget" }, | |
| enabled = false, | |
| callback = false, | |
| terminal_target_priority = 20000000, | |
| } | |
| function RolloverModeTerminalTarget:MouseEvent(event, pt, button, time) | |
| if not self.enabled then | |
| return "continue" | |
| end | |
| local target = terminal.desktop:GetMouseTarget(pt) or terminal.desktop | |
| if event == "OnMouseButtonDown" then | |
| self.enabled = false | |
| if button == "R" then | |
| self.callback(target, "cancel") | |
| else | |
| self.callback(target, "done") | |
| end | |
| GedUpdateActionToggled("RolloverMode", false) | |
| else | |
| self.callback(target, "update") | |
| end | |
| return "break" | |
| end | |
| function RolloverModeTerminalTarget:EnableRolloverMode(enabled, callback) | |
| if self.callback and self.enabled then | |
| self.callback(false, "cancel") | |
| end | |
| self.enabled = enabled | |
| self.callback = callback | |
| GedUpdateActionToggled("RolloverMode", self.enabled) | |
| end | |
| local flashing_window = false | |
| function XRolloverMode(enabled, callback) | |
| if not GedXWindowInspectorTerminalTarget then | |
| GedXWindowInspectorTerminalTarget = RolloverModeTerminalTarget:new() | |
| terminal.AddTarget(GedXWindowInspectorTerminalTarget) | |
| end | |
| GedXWindowInspectorTerminalTarget:EnableRolloverMode(enabled, callback) | |
| end | |
| function GedRpcRolloverMode(socket, enabled) | |
| local old_sel = socket:ResolveObj("SelectedWindow") | |
| XRolloverMode(enabled, function(window, status) | |
| if window then | |
| if status == "cancel" then | |
| GedXWindowInspectorSelectWindow(socket, old_sel) | |
| else | |
| GedXWindowInspectorSelectWindow(socket, window) | |
| end | |
| end | |
| end) | |
| end | |
| function GedRpcColorPickerRollover(ged, name, prop_id) | |
| local obj = ged:ResolveObj(name) | |
| if not obj then return end | |
| local thread_status = "updating" | |
| CreateRealTimeThread(function() | |
| flashing_window = { | |
| BorderWidth = 2, | |
| BorderColor = RGB(200, 0, 0), | |
| Box = terminal.desktop.box, | |
| Thread = false, | |
| } | |
| UIL.Invalidate() | |
| SetPostProcPredicate("debug_color_pick", true) | |
| local old_value = obj:GetProperty(prop_id) | |
| while thread_status == "updating" do | |
| local pixel = ReturnPixel() | |
| if pixel and pixel ~= obj:GetProperty(prop_id) then | |
| obj:SetProperty(prop_id, pixel) | |
| ObjModified(obj) | |
| end | |
| Sleep(10) | |
| end | |
| if thread_status == "cancel" then | |
| obj:SetProperty(prop_id, old_value) | |
| ObjModified(obj) | |
| end | |
| SetPostProcPredicate("debug_color_pick", false) | |
| flashing_window = false | |
| UIL.Invalidate() | |
| end) | |
| XRolloverMode(true, function(window, status) | |
| if status == "done" then | |
| thread_status = "done" | |
| elseif status == "cancel" then | |
| thread_status = "cancel" | |
| else | |
| local pos = terminal.GetMousePos() | |
| RequestPixel(pos:x(), pos:y()) | |
| end | |
| end) | |
| terminal.BringToTop() | |
| end | |
| function GedRpcInspectFocusedWindow(socket) | |
| local desktop = terminal.desktop | |
| local target = desktop:GetKeyboardFocus() or desktop:NextFocusCandidate() | |
| socket:Send("rfnApp", "SetSelection", "root", target and GetItemPath(socket:ResolveObj("root"), target)) | |
| end | |
| function GedRpcToggleFocusLogging(socket, enabled) | |
| terminal.desktop.focus_logging_enabled = enabled | |
| GedUpdateActionToggled("FocusLogging", enabled) | |
| end | |
| function GedRpcToggleRolloverLogging(socket, enabled) | |
| terminal.desktop.rollover_logging_enabled = enabled | |
| GedUpdateActionToggled("RolloverLogging", enabled) | |
| end | |
| function GedRpcToggleContextLogging(socket, enabled) | |
| XContextUpdateLogging = enabled | |
| GedUpdateActionToggled("ContextLogging", enabled) | |
| end | |
| function XFlashWindow(obj) | |
| if not obj then return end | |
| if flashing_window then | |
| DeleteThread(flashing_window.Thread) | |
| end | |
| flashing_window = { | |
| BorderWidth = 1, | |
| BorderColor = RGB(0, 0, 0), | |
| Box = box(0, 0, 0, 0), | |
| Thread = false, | |
| } | |
| flashing_window.Thread = CreateRealTimeThread(function() | |
| for i = 1, 5 do | |
| local target = obj.interaction_box or obj.box | |
| if obj.window_state == "destroying" or not target then | |
| break | |
| end | |
| flashing_window.Box = target | |
| flashing_window.BorderColor = RGB(255, 255, 255) | |
| UIL.Invalidate() | |
| Sleep(50) | |
| flashing_window.BorderColor = RGB(0, 0, 0) | |
| UIL.Invalidate() | |
| Sleep(50) | |
| end | |
| flashing_window = false | |
| UIL.Invalidate() | |
| end) | |
| end | |
| function GedRpcFlashWindow(socket, obj_name) | |
| local obj = socket:ResolveObj(obj_name) | |
| XFlashWindow(obj) | |
| end | |
| function GedRpcXWindowInspector(socket, obj_name) | |
| local obj = socket:ResolveObj(obj_name) | |
| CreateRealTimeThread(function() | |
| OpenGedApp("XWindowInspector", obj) | |
| end) | |
| end | |
| function GedXWindowInspectorFlashWindow() | |
| if flashing_window then | |
| local border_width = flashing_window.BorderWidth | |
| UIL.DrawBorderRect(flashing_window.Box, border_width, border_width, flashing_window.BorderColor, RGBA(0, 0, 0, 0)) | |
| end | |
| end | |
| function OnMsg.Start() | |
| if Platform.desktop then | |
| UIL.Register("GedXWindowInspectorFlashWindow", XDesktop.terminal_target_priority + 1) | |
| end | |
| end | |