local Gui = require 'utils.gui' local Color = require 'utils.color_presets' local Model = require 'utils.debug.model' local dump = Model.dump local dump_text = Model.dump_text local concat = table.concat local Public = {} 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' 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(player_index) local player_name if not player then player_name = 'invalid player' else player_name = player.name end local header = player_panel.add({ type = 'flow' }).add { type = 'label', name = player_header_name, caption = concat({ player_index, ' - ', player_name }) } 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 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_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 = { 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(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 rec(children, copy) for key, child in next, children do if child.name then copy[key] = child elseif type(child) == 'table' then rec(child, copy) end end end local function deepCopy(children) local copy = {} rec(children, copy) return copy end local function draw_element_headers(element_panel, values, selected_index) local copy = deepCopy(values) local selected_header = nil local name_map = Gui.names for ei, stored_data in pairs(copy) do local ele_name = '' if stored_data and stored_data.name then ele_name = stored_data.name end local gui_name = name_map[ele_name] if gui_name then ele_name = gui_name end if ele_name:match('%d* %- utils/debug/') then goto continue 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 ::continue:: end return selected_header end Gui.on_click( player_header_name, function (event) local element = event.element local header_data = Gui.get_data(element) if not header_data then return end Gui.clear(element) local values = header_data.values local player_index = header_data.player_index local player_panel = element.parent.parent local data = Gui.get_data(player_panel) if not data then return end local element_panel = data.element_panel local selected_player_header = data.selected_player_header local input_text_box = data.input_text_box if selected_player_header then selected_player_header.style.font_color = Color.white end element.style.font_color = Color.orange data.selected_player_header = element data.selected_player_index = player_index data.selected_element_index = nil input_text_box.text = '' if not values then return end draw_element_headers(element_panel, values) end ) Gui.on_click( element_header_name, function (event) local element = event.element local header_data = Gui.get_data(element) if not header_data then return end 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) if not data then return end 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 { 'storage.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) local suc, ouput = dump_text(text_input.text) 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) end ) Gui.on_click( refresh_name, function (event) local element = event.element local data = Gui.get_data(element) if not data then return end 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) if not player_header_data then return end local values = player_header_data.values local selected_element_header = draw_element_headers(element_panel, values, selected_element_index) data.selected_element_header = selected_element_header if selected_element_header then selected_element_header.style.font_color = Color.orange update_dump(input_text_box, data, event.player) return end end data.input_text_box.text = '' data.data_panel.text = '' end ) return Public