From 0d4350185723b89b723f0214d3992ca1ef620086 Mon Sep 17 00:00:00 2001 From: grilledham Date: Wed, 6 Feb 2019 21:20:08 +0000 Subject: [PATCH 1/7] added _G.dump and dump commands --- features/gui/debug/command.lua | 127 +++++++++++++++++++++++++++++++++ features/gui/debug/model.lua | 1 + 2 files changed, 128 insertions(+) diff --git a/features/gui/debug/command.lua b/features/gui/debug/command.lua index 24a39949..1d4a74d1 100644 --- a/features/gui/debug/command.lua +++ b/features/gui/debug/command.lua @@ -1,6 +1,12 @@ local DebugView = require 'features.gui.debug.main_view' +local Model = require 'features.gui.debug.model' local Command = require 'utils.command' +local loadstring = loadstring +local pcall = pcall +local dump = Model.dump +local log = log + Command.add( 'debug', { @@ -11,3 +17,124 @@ Command.add( DebugView.open_dubug(player) end ) + +Command.add( + 'dump', + { + arguments = {'str'}, + capture_excess_arguments = true, + allowed_by_server = true, + debug_only = true, + description = 'dumps value to player.print' + }, + function(args, player) + local p + if player then + p = player.print + else + p = print + end + + local func, err = loadstring('return ' .. args.str) + + if not func then + p(err) + return + end + + local suc, value = pcall(func) + + if not suc then + if value then + local i = value:find('\n') + if i then + p(value:sub(1, i)) + return + end + + i = value:find('%s') + if i then + p(value:sub(i + 1)) + end + end + + return + end + + p(dump(value)) + end +) + +Command.add( + 'dump-log', + { + arguments = {'str'}, + capture_excess_arguments = true, + allowed_by_server = true, + debug_only = true, + description = 'dumps value to log' + }, + function(args, player) + local p + if player then + p = player.print + else + p = print + end + + local func, err = loadstring('return ' .. args.str) + + if not func then + p(err) + return + end + + local suc, value = pcall(func) + + if not suc then + p(value) + return + end + + log(dump(value)) + end +) + +Command.add( + 'dump-file', + { + arguments = {'str'}, + capture_excess_arguments = true, + allowed_by_server = true, + debug_only = true, + description = 'dumps value to dump.lua' + }, + function(args, player) + local p + local player_index + if player then + p = player.print + player_index = player.index + else + p = print + player_index = 0 + end + + local func, err = loadstring('return ' .. args.str) + + if not func then + p(err) + return + end + + local suc, value = pcall(func) + + if not suc then + p(value) + return + end + + value = dump(value) + game.write_file('dump.lua', value, false, player_index) + end +) diff --git a/features/gui/debug/model.lua b/features/gui/debug/model.lua index fb636718..90be49de 100644 --- a/features/gui/debug/model.lua +++ b/features/gui/debug/model.lua @@ -87,6 +87,7 @@ function Public.dump(data) return inspect(data, inspect_options) end local dump = Public.dump +_G.dump = dump function Public.dump_ignore_builder(ignore) local function process(item) From 818639580558ef8138c7b115d77b4e05f2516073 Mon Sep 17 00:00:00 2001 From: grilledham Date: Wed, 6 Feb 2019 21:20:27 +0000 Subject: [PATCH 2/7] changed structure of gui.data --- utils/gui.lua | 55 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/utils/gui.lua b/utils/gui.lua index 2a42fc77..96893c77 100644 --- a/utils/gui.lua +++ b/utils/gui.lua @@ -3,6 +3,9 @@ local Event = require 'utils.event' local Game = require 'utils.game' local Global = require 'utils.global' +local tostring = tostring +local next = next + local Gui = {} local data = {} @@ -24,17 +27,46 @@ end -- Associates data with the LuaGuiElement. If data is nil then removes the data function Gui.set_data(element, value) - data[element.player_index * 0x100000000 + element.index] = value + local player_index = element.player_index + local values = data[player_index] + + if value == nil then + if not values then + return + end + + values[element.index] = nil + + if next(values) == nil then + data[player_index] = nil + end + else + if not values then + values = {} + data[player_index] = values + end + + values[element.index] = value + end end +local set_data = Gui.set_data -- Gets the Associated data with this LuaGuiElement if any. function Gui.get_data(element) - return data[element.player_index * 0x100000000 + element.index] + local player_index = element.player_index + + local values = data[player_index] + if not values then + return nil + end + + return values[element.index] end +local remove_data_recursively -- Removes data associated with LuaGuiElement and its children recursively. function Gui.remove_data_recursively(element) - Gui.set_data(element, nil) + set_data(element, nil) local children = element.children @@ -42,13 +74,15 @@ function Gui.remove_data_recursively(element) return end - for _, child in ipairs(children) do + for _, child in next, children do if child.valid then - Gui.remove_data_recursively(child) + remove_data_recursively(child) end end end +remove_data_recursively = Gui.remove_data_recursively +local remove_children_data function Gui.remove_children_data(element) local children = element.children @@ -56,21 +90,22 @@ function Gui.remove_children_data(element) return end - for _, child in ipairs(children) do + for _, child in next, children do if child.valid then - Gui.set_data(child, nil) - Gui.remove_children_data(child) + set_data(child, nil) + remove_children_data(child) end end end +remove_children_data = Gui.remove_children_data function Gui.destroy(element) - Gui.remove_data_recursively(element) + remove_data_recursively(element) element.destroy() end function Gui.clear(element) - Gui.remove_children_data(element) + remove_children_data(element) element.clear() end From 9a1cdfd512b4d169d356f2cc78750055ef996a93 Mon Sep 17 00:00:00 2001 From: grilledham Date: Sat, 9 Feb 2019 17:57:55 +0000 Subject: [PATCH 3/7] gui_data --- features/gui/debug/gui_data_view.lua | 87 ++++++++++++++++++++++++++++ features/gui/debug/main_view.lua | 3 +- utils/gui.lua | 2 + 3 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 features/gui/debug/gui_data_view.lua diff --git a/features/gui/debug/gui_data_view.lua b/features/gui/debug/gui_data_view.lua new file mode 100644 index 00000000..3668057d --- /dev/null +++ b/features/gui/debug/gui_data_view.lua @@ -0,0 +1,87 @@ +local Gui = require 'utils.gui' +local Global = require 'utils.global' +local Token = require 'utils.token' +local Color = require 'resources.color_presets' +local Model = require 'features.gui.debug.model' +local Game = require 'utils.game' + +local dump = Model.dump +local dump_text = Model.dump_text +local concat = table.concat + +local Public = {} + +local header_name = Gui.uid_name() +local left_panel_name = Gui.uid_name() +local right_panel_name = Gui.uid_name() + +Public.name = 'Gui Data' + +function Public.show(container) + local main_flow = container.add {type = 'flow', direction = 'horizontal'} + + local left_panel = main_flow.add {type = 'scroll-pane', name = left_panel_name} + local left_panel_style = left_panel.style + left_panel_style.width = 300 + + for player_index, values in pairs(Gui.data) do + local player = Game.get_player_by_index(player_index) + local player_name + if not player then + player_name = 'invalid player' + else + player_name = player.name + end + + local header = + left_panel.add({type = 'flow'}).add { + type = 'label', + name = header_name, + caption = concat({player_index, ' - ', player_name}) + } + Gui.set_data(header, values) + end + + local right_flow = main_flow.add {type = 'flow', direction = 'vertical'} + + local right_panel = right_flow.add {type = 'text-box', name = right_panel_name} + right_panel.word_wrap = true + right_panel.read_only = true + right_panel.selectable = true + + local right_panel_style = right_panel.style + right_panel_style.vertically_stretchable = true + right_panel_style.horizontally_stretchable = true + + local data = { + right_panel = right_panel, + selected_header = nil + } + + Gui.set_data(left_panel, data) +end + +Gui.on_click( + header_name, + function(event) + local element = event.element + local values = Gui.get_data(element) + + local left_panel = element.parent.parent + local data = Gui.get_data(left_panel) + local right_panel = data.right_panel + local selected_header = data.selected_header + + if selected_header then + selected_header.style.font_color = Color.white + end + + element.style.font_color = Color.orange + data.selected_header = element + + local content = dump(values) or 'nil' + right_panel.text = content + end +) + +return Public diff --git a/features/gui/debug/main_view.lua b/features/gui/debug/main_view.lua index cd2eb63f..12a289f6 100644 --- a/features/gui/debug/main_view.lua +++ b/features/gui/debug/main_view.lua @@ -7,7 +7,8 @@ local pages = { require 'features.gui.debug.redmew_global_view', require 'features.gui.debug.global_view', require 'features.gui.debug.package_view', - require 'features.gui.debug._g_view' + require 'features.gui.debug._g_view', + require 'features.gui.debug.gui_data_view' } local main_frame_name = Gui.uid_name() diff --git a/utils/gui.lua b/utils/gui.lua index 96893c77..25aeaad0 100644 --- a/utils/gui.lua +++ b/utils/gui.lua @@ -314,6 +314,8 @@ if _DEBUG then return token end + + Gui.data = data end return Gui From e9b31c7038eec1dd98ad5987ff7185f840f6bece Mon Sep 17 00:00:00 2001 From: grilledham Date: Sun, 26 May 2019 20:32:44 +0100 Subject: [PATCH 4/7] updates --- control.lua | 4 +- features/gui/debug/gui_data_view.lua | 267 +++++++++++++++++++++++---- features/gui/debug/main_view.lua | 4 +- utils/global.lua | 8 + utils/gui.lua | 54 +++++- 5 files changed, 293 insertions(+), 44 deletions(-) diff --git a/control.lua b/control.lua index 55ee256f..211d2f5a 100644 --- a/control.lua +++ b/control.lua @@ -141,10 +141,12 @@ end if _DEBUG then require 'features.scenario_data_manipulation' end --- Needs to be at bottom so tokens are registered last. + if _DUMP_ENV then require 'utils.dump_env' end + +-- Needs to be at bottom so tokens are registered last. if _DEBUG then require 'features.gui.debug.command' end diff --git a/features/gui/debug/gui_data_view.lua b/features/gui/debug/gui_data_view.lua index 3668057d..1df7721d 100644 --- a/features/gui/debug/gui_data_view.lua +++ b/features/gui/debug/gui_data_view.lua @@ -3,7 +3,6 @@ local Global = require 'utils.global' local Token = require 'utils.token' local Color = require 'resources.color_presets' local Model = require 'features.gui.debug.model' -local Game = require 'utils.game' local dump = Model.dump local dump_text = Model.dump_text @@ -11,21 +10,21 @@ local concat = table.concat local Public = {} -local header_name = Gui.uid_name() -local left_panel_name = Gui.uid_name() -local right_panel_name = Gui.uid_name() +local player_header_name = Gui.uid_name() +local element_header_name = Gui.uid_name() +local player_panel_name = Gui.uid_name() +local element_panel_name = Gui.uid_name() +local input_text_box_name = Gui.uid_name() +local refresh_name = Gui.uid_name() +local data_panel_name = Gui.uid_name() Public.name = 'Gui Data' -function Public.show(container) - local main_flow = container.add {type = 'flow', direction = 'horizontal'} - - local left_panel = main_flow.add {type = 'scroll-pane', name = left_panel_name} - local left_panel_style = left_panel.style - left_panel_style.width = 300 +local function draw_player_headers(player_panel, selected_index) + local selected_header = nil for player_index, values in pairs(Gui.data) do - local player = Game.get_player_by_index(player_index) + local player = game.get_player(player_index) local player_name if not player then player_name = 'invalid player' @@ -34,53 +33,251 @@ function Public.show(container) end local header = - left_panel.add({type = 'flow'}).add { + player_panel.add({type = 'flow'}).add { type = 'label', - name = header_name, + name = player_header_name, caption = concat({player_index, ' - ', player_name}) } - Gui.set_data(header, values) + Gui.set_data(header, {values = values, player_index = player_index}) + + if player_index == selected_index then + selected_header = header + end end + return selected_header +end + +function Public.show(container) + local main_flow = container.add {type = 'flow', direction = 'horizontal'} + + local player_panel = main_flow.add {type = 'scroll-pane', name = player_panel_name} + local player_panel_style = player_panel.style + player_panel_style.width = 200 + + draw_player_headers(player_panel) + local right_flow = main_flow.add {type = 'flow', direction = 'vertical'} - local right_panel = right_flow.add {type = 'text-box', name = right_panel_name} - right_panel.word_wrap = true - right_panel.read_only = true - right_panel.selectable = true + local element_panel = right_flow.add {type = 'scroll-pane', name = element_panel_name} + local element_panel_style = element_panel.style + element_panel_style.horizontally_stretchable = true + element_panel_style.height = 200 - local right_panel_style = right_panel.style - right_panel_style.vertically_stretchable = true - right_panel_style.horizontally_stretchable = true + local right_middle_flow = right_flow.add {type = 'flow', direction = 'horizontal'} + + local input_text_box = right_middle_flow.add {type = 'text-box', name = input_text_box_name} + local input_text_box_style = input_text_box.style + input_text_box_style.horizontally_stretchable = true + input_text_box_style.height = 32 + input_text_box_style.maximal_width = 1000 + + local refresh_button = + right_middle_flow.add { + type = 'sprite-button', + name = refresh_name, + sprite = 'utility/reset', + tooltip = 'refresh' + } + local refresh_button_style = refresh_button.style + refresh_button_style.width = 32 + refresh_button_style.height = 32 + + local data_panel = right_flow.add {type = 'text-box', name = data_panel_name} + data_panel.read_only = true + data_panel.selectable = true + + local data_panel_style = data_panel.style + data_panel_style.vertically_stretchable = true + data_panel_style.horizontally_stretchable = true + data_panel_style.maximal_width = 1000 + data_panel_style.maximal_height = 1000 local data = { - right_panel = right_panel, - selected_header = nil + player_panel = player_panel, + element_panel = element_panel, + input_text_box = input_text_box, + data_panel = data_panel, + selected_player_header = nil, + selected_element_header = nil, + selected_player_index = nil, + selected_element_index = nil } - Gui.set_data(left_panel, data) + Gui.set_data(player_panel, data) + Gui.set_data(element_panel, data) + Gui.set_data(input_text_box, data) + Gui.set_data(refresh_button, data) +end + +local function draw_element_headers(element_panel, values, selected_index) + local selected_header = nil + local element_map = Gui.element_map + local name_map = Gui.names + + for ei, stored_data in pairs(values) do + local ele = element_map[ei] + local ele_name = '' + if ele and ele.valid then + ele_name = ele.name + end + + local gui_name = name_map[ele_name] + if gui_name then + ele_name = gui_name + end + + local middle_header = + element_panel.add({type = 'flow'}).add { + type = 'label', + name = element_header_name, + caption = concat({ei, ' - ', ele_name}) + } + + Gui.set_data(middle_header, {stored_data = stored_data, element_index = ei}) + + if ei == selected_index then + selected_header = middle_header + end + end + + return selected_header end Gui.on_click( - header_name, + player_header_name, function(event) local element = event.element - local values = Gui.get_data(element) + local header_data = Gui.get_data(element) + local values = header_data.values + local player_index = header_data.player_index - local left_panel = element.parent.parent - local data = Gui.get_data(left_panel) - local right_panel = data.right_panel - local selected_header = data.selected_header + local player_panel = element.parent.parent + local data = Gui.get_data(player_panel) + local element_panel = data.element_panel + local selected_player_header = data.selected_player_header + local input_text_box = data.input_text_box - if selected_header then - selected_header.style.font_color = Color.white + if selected_player_header then + selected_player_header.style.font_color = Color.white end element.style.font_color = Color.orange - data.selected_header = element + data.selected_player_header = element + data.selected_player_index = player_index + data.selected_element_index = nil - local content = dump(values) or 'nil' - right_panel.text = content + input_text_box.text = '' + + if not values then + return + end + + local copy = {} + for k, v in pairs(values) do + copy[k] = v + end + + draw_element_headers(element_panel, copy) + end +) + +Gui.on_click( + element_header_name, + function(event) + local element = event.element + local header_data = Gui.get_data(element) + local stored_data = header_data.stored_data + local element_index = header_data.element_index + + local player_panel = element.parent.parent + local data = Gui.get_data(player_panel) + local data_panel = data.data_panel + local selected_element_header = data.selected_element_header + local input_text_box = data.input_text_box + + if selected_element_header then + selected_element_header.style.font_color = Color.white + end + + element.style.font_color = Color.orange + data.selected_element_header = element + data.selected_element_index = element_index + + local selected_player_index = data.selected_player_index + + if selected_player_index then + input_text_box.text = + concat {'global.tokens[', Gui.token, '].data[', selected_player_index, '][', element_index, ']'} + else + input_text_box.text = 'missing player' + end + + local content = dump(stored_data) or 'nil' + data_panel.text = content + end +) + +local function update_dump(text_input, data, player) + local suc, ouput = dump_text(text_input.text, player) + if not suc then + text_input.style.font_color = Color.red + else + text_input.style.font_color = Color.black + data.data_panel.text = ouput + end +end + +Gui.on_text_changed( + input_text_box_name, + function(event) + local element = event.element + local data = Gui.get_data(element) + + update_dump(element, data, event.player) + end +) + +Gui.on_click( + refresh_name, + function(event) + local element = event.element + local data = Gui.get_data(element) + + local input_text_box = data.input_text_box + local player_panel = data.player_panel + local element_panel = data.element_panel + local selected_player_index = data.selected_player_index + local selected_element_index = data.selected_element_index + + Gui.clear(player_panel) + local selected_player_header = draw_player_headers(player_panel, selected_player_index) + data.selected_player_header = selected_player_header + if selected_player_header then + selected_player_header.style.font_color = Color.orange + end + + Gui.clear(element_panel) + if selected_player_header then + local player_header_data = Gui.get_data(selected_player_header) + local values = player_header_data.values + + local copy = {} + for k, v in pairs(values) do + copy[k] = v + end + + local selected_element_header = draw_element_headers(element_panel, copy, selected_element_index) + data.selected_element_header = selected_element_header + if selected_element_header then + selected_element_header.style.font_color = Color.orange + end + + update_dump(input_text_box, data, event.player) + else + data.input_text_box.text = '' + data.data_panel.text = '' + end end ) diff --git a/features/gui/debug/main_view.lua b/features/gui/debug/main_view.lua index 291625f6..cf9d8f0c 100644 --- a/features/gui/debug/main_view.lua +++ b/features/gui/debug/main_view.lua @@ -8,7 +8,7 @@ local pages = { require 'features.gui.debug.global_view', require 'features.gui.debug.package_view', require 'features.gui.debug._g_view', - require 'features.gui.debug.gui_data_view' + require 'features.gui.debug.gui_data_view', require 'features.gui.debug.event_view' } @@ -31,7 +31,7 @@ function Public.open_dubug(player) return end - frame = center.add {type = 'frame', name = main_frame_name, caption = 'Debuggertron 3001', direction = 'vertical'} + frame = center.add {type = 'frame', name = main_frame_name, caption = 'Debuggertron 3002', direction = 'vertical'} local frame_style = frame.style frame_style.height = 600 frame_style.width = 900 diff --git a/utils/global.lua b/utils/global.lua index 4d23bd43..ef0537cc 100644 --- a/utils/global.lua +++ b/utils/global.lua @@ -14,6 +14,8 @@ function Global.register(tbl, callback) callback(Token.get_global(token)) end ) + + return token end function Global.register_init(tbl, init_handler, callback) @@ -34,6 +36,8 @@ function Global.register_init(tbl, init_handler, callback) callback(Token.get_global(token)) end ) + + return token end if _DEBUG then @@ -53,6 +57,8 @@ if _DEBUG then callback(Token.get_global(token)) end ) + + return token end function Global.register_init(tbl, init_handler, callback) @@ -73,6 +79,8 @@ if _DEBUG then callback(Token.get_global(token)) end ) + + return token end end diff --git a/utils/gui.lua b/utils/gui.lua index a121cc2f..5e32f851 100644 --- a/utils/gui.lua +++ b/utils/gui.lua @@ -8,13 +8,25 @@ local next = next local Gui = {} local data = {} +local element_map = {} -Global.register( - data, - function(tbl) - data = tbl - end -) +if _DEBUG then + Gui.token = + Global.register( + {data = data, element_map = element_map}, + function(tbl) + data = tbl.data + element_map = tbl.element_map + end + ) +else + Global.register( + data, + function(tbl) + data = tbl + end + ) +end local top_elements = {} local on_visible_handlers = {} @@ -310,7 +322,37 @@ if _DEBUG then return token end + function Gui.set_data(element, value) + local player_index = element.player_index + local values = data[player_index] + + if value == nil then + if not values then + return + end + + local index = element.index + values[index] = nil + element_map[index] = nil + + if next(values) == nil then + data[player_index] = nil + end + else + if not values then + values = {} + data[player_index] = values + end + + local index = element.index + values[index] = value + element_map[index] = element + end + end + set_data = Gui.set_data + Gui.data = data + Gui.element_map = element_map end return Gui From f77a50b33bca75e915c6628060f53bd5c990bf3e Mon Sep 17 00:00:00 2001 From: grilledham Date: Sun, 26 May 2019 20:44:59 +0100 Subject: [PATCH 5/7] clear text unless both player and element is selected. --- features/gui/debug/gui_data_view.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/features/gui/debug/gui_data_view.lua b/features/gui/debug/gui_data_view.lua index 1df7721d..1dbcb2f7 100644 --- a/features/gui/debug/gui_data_view.lua +++ b/features/gui/debug/gui_data_view.lua @@ -271,13 +271,14 @@ Gui.on_click( data.selected_element_header = selected_element_header if selected_element_header then selected_element_header.style.font_color = Color.orange - end + update_dump(input_text_box, data, event.player) - update_dump(input_text_box, data, event.player) - else - data.input_text_box.text = '' - data.data_panel.text = '' + return + end end + + data.input_text_box.text = '' + data.data_panel.text = '' end ) From 1af3d3b237b6f7d5fc5023beec0a07df0deb1c81 Mon Sep 17 00:00:00 2001 From: grilledham Date: Sun, 26 May 2019 21:03:42 +0100 Subject: [PATCH 6/7] fixed desyn issue --- features/gui/debug/gui_data_view.lua | 4 ++-- utils/gui.lua | 32 ++++++++++++---------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/features/gui/debug/gui_data_view.lua b/features/gui/debug/gui_data_view.lua index 1dbcb2f7..c01c16f9 100644 --- a/features/gui/debug/gui_data_view.lua +++ b/features/gui/debug/gui_data_view.lua @@ -23,7 +23,7 @@ Public.name = 'Gui Data' local function draw_player_headers(player_panel, selected_index) local selected_header = nil - for player_index, values in pairs(Gui.data) do + for player_index, values in pairs(Gui.data()) do local player = game.get_player(player_index) local player_name if not player then @@ -112,7 +112,7 @@ end local function draw_element_headers(element_panel, values, selected_index) local selected_header = nil - local element_map = Gui.element_map + local element_map = Gui.element_map() local name_map = Gui.names for ei, stored_data in pairs(values) do diff --git a/utils/gui.lua b/utils/gui.lua index 5e32f851..ca130ba4 100644 --- a/utils/gui.lua +++ b/utils/gui.lua @@ -10,23 +10,14 @@ local Gui = {} local data = {} local element_map = {} -if _DEBUG then - Gui.token = - Global.register( - {data = data, element_map = element_map}, - function(tbl) - data = tbl.data - element_map = tbl.element_map - end - ) -else +Gui.token = Global.register( - data, - function(tbl) - data = tbl - end - ) -end + {data = data, element_map = element_map}, + function(tbl) + data = tbl.data + element_map = tbl.element_map + end +) local top_elements = {} local on_visible_handlers = {} @@ -351,8 +342,13 @@ if _DEBUG then end set_data = Gui.set_data - Gui.data = data - Gui.element_map = element_map + function Gui.data() + return data + end + + function Gui.element_map() + return element_map + end end return Gui From 6387b73788194dc657bc7d7757655d31149cfc45 Mon Sep 17 00:00:00 2001 From: grilledham Date: Sun, 26 May 2019 21:13:57 +0100 Subject: [PATCH 7/7] removed unused variables --- features/gui/debug/gui_data_view.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/features/gui/debug/gui_data_view.lua b/features/gui/debug/gui_data_view.lua index c01c16f9..6e728fdd 100644 --- a/features/gui/debug/gui_data_view.lua +++ b/features/gui/debug/gui_data_view.lua @@ -1,6 +1,4 @@ local Gui = require 'utils.gui' -local Global = require 'utils.global' -local Token = require 'utils.token' local Color = require 'resources.color_presets' local Model = require 'features.gui.debug.model'