From d751c9ef8acece2e14e6fe81839d79b74eae710f Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Mon, 13 Feb 2023 16:51:16 -0500 Subject: [PATCH 01/12] Add LuaJson::PushToLua --- src/lua/LuaJson.cpp | 14 +++++++------- src/lua/LuaJson.h | 7 +++++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/lua/LuaJson.cpp b/src/lua/LuaJson.cpp index bfd984a96f0..349c07faea2 100644 --- a/src/lua/LuaJson.cpp +++ b/src/lua/LuaJson.cpp @@ -13,7 +13,7 @@ */ // Do a simple JSON->Lua translation. -static void _push_json_to_lua(lua_State *l, Json &obj) +void LuaJson::PushToLua(lua_State *l, const Json &obj) { lua_checkstack(l, 20); @@ -40,15 +40,15 @@ static void _push_json_to_lua(lua_State *l, Json &obj) size_t size = obj.size(); for (size_t idx = 0; idx < size; idx++) { lua_pushinteger(l, idx + 1); - _push_json_to_lua(l, obj[idx]); + PushToLua(l, obj[idx]); lua_settable(l, -3); } } break; case Json::value_t::object: { lua_newtable(l); - for (Json::iterator it = obj.begin(); it != obj.end(); it++) { - lua_pushstring(l, it.key().c_str()); - _push_json_to_lua(l, it.value()); + for (const auto &pair : obj.items()) { + lua_pushstring(l, pair.key().c_str()); + PushToLua(l, pair.value()); lua_settable(l, -3); } } break; @@ -79,7 +79,7 @@ static int l_load_json(lua_State *l) if (data.is_null()) return luaL_error(l, "Error loading JSON file %s.", filename.c_str()); - _push_json_to_lua(l, data); + LuaJson::PushToLua(l, data); return 1; } @@ -106,7 +106,7 @@ static int l_load_save_file(lua_State *l) return luaL_error(l, "Error loading JSON file %s.", filename.c_str()); } - _push_json_to_lua(l, data); + LuaJson::PushToLua(l, data); return 1; } diff --git a/src/lua/LuaJson.h b/src/lua/LuaJson.h index 53c20b6abf9..6f6f87a7be1 100644 --- a/src/lua/LuaJson.h +++ b/src/lua/LuaJson.h @@ -4,8 +4,15 @@ #ifndef PI_LUA_JSON_H #define PI_LUA_JSON_H +#include "JsonFwd.h" +#include "Lua.h" + namespace LuaJson { + void Register(); + + void PushToLua(lua_State *l, const Json &data); + } #endif From 329f93ccb2b093fc8fffada4fbe8d041fe92811a Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Mon, 16 Sep 2024 22:13:53 -0400 Subject: [PATCH 02/12] PiGui: add treePush, boolean state functions - Add missing treePush(id) to complement treePop() - Add basic functions to access ImGui's state storage. Limited to booleans for now with automatic ID scoping. - Fix ui.invisibleButton() requiring an explicit flag parameter even if empty --- data/pigui/libs/forwarded.lua | 1 + src/lua/LuaPiGui.cpp | 38 ++++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/data/pigui/libs/forwarded.lua b/data/pigui/libs/forwarded.lua index fd77c5d122e..9030ee18a7e 100644 --- a/data/pigui/libs/forwarded.lua +++ b/data/pigui/libs/forwarded.lua @@ -106,6 +106,7 @@ ui.isMouseDoubleClicked = pigui.IsMouseDoubleClicked ui.isMouseHoveringRect = pigui.IsMouseHoveringRect ui.collapsingHeader = pigui.CollapsingHeader ui.treeNode = pigui.TreeNode +ui.treePush = pigui.TreePush ui.treePop = pigui.TreePop ui.beginPopupModal = pigui.BeginPopupModal ui.endPopup = pigui.EndPopup diff --git a/src/lua/LuaPiGui.cpp b/src/lua/LuaPiGui.cpp index ca9dd5eee6b..104e1a86ac3 100644 --- a/src/lua/LuaPiGui.cpp +++ b/src/lua/LuaPiGui.cpp @@ -1346,7 +1346,7 @@ static int l_pigui_invisible_button(lua_State *l) PROFILE_SCOPED() std::string id = LuaPull(l, 1); ImVec2 size = LuaPull(l, 2); - ImGuiButtonFlags flags = LuaPull(l, 3); + ImGuiButtonFlags flags = LuaPull(l, 3, ImGuiButtonFlags_None); bool ret = ImGui::InvisibleButton(id.c_str(), size, flags); LuaPush(l, ret); return 1; @@ -3269,6 +3269,13 @@ static int l_pigui_treenode(lua_State *l) return 1; } +static int l_pigui_treepush(lua_State *l) +{ + PROFILE_SCOPED() + ImGui::TreePush(LuaPull(l, 1)); + return 0; +} + /* * Function: treePop * @@ -3403,6 +3410,30 @@ static int l_pigui_table_set_bg_color(lua_State *l) return 0; } +// ============================================================================ + +static int l_pigui_get_bool_state(lua_State *l) +{ + const char *id = LuaPull(l, 1); + bool default_val = LuaPull(l, 2, false); + + bool state = ImGui::GetStateStorage()->GetBool(ImGui::GetCurrentWindow()->GetID(id), default_val); + + LuaPush(l, state); + return 1; +} + +static int l_pigui_set_bool_state(lua_State *l) +{ + const char *id = LuaPull(l, 1); + bool val = LuaPull(l, 2); + + ImGui::GetStateStorage()->SetBool(ImGui::GetCurrentWindow()->GetID(id), val); + return 0; +} + +// ============================================================================ + static Color4ub to_Color4ub(ImVec4 c) { return Color4ub(uint8_t(c.x * 255), uint8_t(c.y * 255), uint8_t(c.z * 255), uint8_t(c.w * 255)); @@ -3599,6 +3630,7 @@ void LuaObject::RegisterClass() { "ListBox", l_pigui_listbox }, { "CollapsingHeader", l_pigui_collapsing_header }, { "TreeNode", l_pigui_treenode }, + { "TreePush", l_pigui_treepush }, { "TreePop", l_pigui_treepop }, { "CaptureMouseFromApp", l_pigui_capture_mouse_from_app }, { "PlotHistogram", l_pigui_plot_histogram }, @@ -3644,6 +3676,10 @@ void LuaObject::RegisterClass() { "TableSetBgColor", l_pigui_table_set_bg_color }, // TODO: finish exposing Tables API + // Simple ImGui state access + { "GetBoolState", l_pigui_get_bool_state }, + { "SetBoolState", l_pigui_set_bool_state }, + { "WantTextInput", l_pigui_want_text_input }, { "ClearMouse", l_pigui_clear_mouse }, { 0, 0 } From d4fdf9760e92546b01cfc13a5c209cec256e93bd Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Sat, 20 Jan 2024 19:38:46 -0500 Subject: [PATCH 03/12] Add ui.Format.Volume --- data/lang/core/en.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/lang/core/en.json b/data/lang/core/en.json index 3bfc590864d..d7933cfe8c6 100644 --- a/data/lang/core/en.json +++ b/data/lang/core/en.json @@ -1843,6 +1843,10 @@ "description": "Duration unit: one 7-day week", "message": "w" }, + "UNIT_CUBIC_METERS": { + "description": "Volume unit: cubic meter", + "message": "m³" + }, "UNKNOWN": { "description": "", "message": "" From 1a78679508ae98c4f5a19ff653163ea5fad2353a Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Fri, 27 Sep 2024 17:30:54 -0400 Subject: [PATCH 04/12] ui: add comboBox wrapper over BeginCombo()/EndCombo() --- data/pigui/libs/wrappers.lua | 29 +++++++++++++++++++ src/lua/LuaPiGui.cpp | 54 ++++++++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/data/pigui/libs/wrappers.lua b/data/pigui/libs/wrappers.lua index 1e5dd01cc38..bf4acc2c80a 100644 --- a/data/pigui/libs/wrappers.lua +++ b/data/pigui/libs/wrappers.lua @@ -971,3 +971,32 @@ function ui.incrementDrag(...) return pigui.IncrementDrag(table.unpack(args)) end) end + +-- Function: comboBox +-- +-- Wrapper for BeginCombo() + EndCombo(). The given function is called while +-- the combo box is open. +-- +-- Parameters: +-- +-- label - string, label to display next to the combo box +-- preview - string, label of currently selected item +-- flags - optional ComboFlags, table controlling display of the combo box +-- fun - function, renders the contents of the combo box while open +-- +---@param label string +---@param preview string +---@param flags any +---@param fun fun() +---@overload fun(label: string, preview: string, fun: fun()) +function ui.comboBox(label, preview, flags, fun) + if not fun then + fun = flags + flags = nil + end + + if pigui.BeginCombo(label, preview) then + fun() + pigui.EndCombo() + end +end diff --git a/src/lua/LuaPiGui.cpp b/src/lua/LuaPiGui.cpp index 104e1a86ac3..8e48233ba4d 100644 --- a/src/lua/LuaPiGui.cpp +++ b/src/lua/LuaPiGui.cpp @@ -526,6 +526,14 @@ void pi_lua_generic_pull(lua_State *l, int index, ImGuiTableColumnFlags_ &thefla theflags = parse_imgui_flags(l, index, imguiTableColumnFlagsTable); } +int l_pigui_check_table_column_flags(lua_State *l) +{ + luaL_checktype(l, 1, LUA_TTABLE); + ImGuiTableColumnFlags_ fl = imguiTableColumnFlagsTable.LookupTable(l, 1); + LuaPush(l, fl); + return 1; +} + static LuaFlags imguiColorEditFlagsTable = { { "None", ImGuiColorEditFlags_None }, { "NoAlpha", ImGuiColorEditFlags_NoAlpha }, @@ -559,11 +567,27 @@ void pi_lua_generic_pull(lua_State *l, int index, ImGuiColorEditFlags_ &theflags theflags = parse_imgui_flags(l, index, imguiColorEditFlagsTable); } -int l_pigui_check_table_column_flags(lua_State *l) +static LuaFlags imguiComboFlagsTable = { + { "None", ImGuiComboFlags_None }, + { "PopupAlignLeft", ImGuiComboFlags_PopupAlignLeft }, + { "HeightSmall", ImGuiComboFlags_HeightSmall }, + { "HeightRegular", ImGuiComboFlags_HeightRegular }, + { "HeightLarge", ImGuiComboFlags_HeightLarge }, + { "HeightLargest", ImGuiComboFlags_HeightLargest }, + { "NoArrowButton", ImGuiComboFlags_NoArrowButton }, + { "NoPreview", ImGuiComboFlags_NoPreview }, +}; + +void pi_lua_generic_pull(lua_State *l, int index, ImGuiComboFlags_ &theflags) +{ + theflags = parse_imgui_flags(l, index, imguiComboFlagsTable); +} + +int l_pigui_check_combo_flags(lua_State *l) { luaL_checktype(l, 1, LUA_TTABLE); - ImGuiTableColumnFlags_ fl = imguiTableColumnFlagsTable.LookupTable(l, 1); - LuaPush(l, fl); + ImGuiComboFlags_ fl = imguiComboFlagsTable.LookupTable(l, 1); + LuaPush(l, fl); return 1; } @@ -2636,6 +2660,27 @@ static int l_pigui_combo(lua_State *l) return 2; } +static int l_pigui_begin_combo(lua_State *l) +{ + PROFILE_SCOPED() + + std::string lbl = LuaPull(l, 1); + std::string preview = LuaPull(l, 2); + ImGuiComboFlags flags = LuaPull(l, 3, ImGuiComboFlags_None); + + bool open = ImGui::BeginCombo(lbl.c_str(), preview.c_str(), flags); + LuaPush(l, open); + return 1; +} + +static int l_pigui_end_combo(lua_State *l) +{ + PROFILE_SCOPED() + + ImGui::EndCombo(); + return 0; +} + static int l_pigui_listbox(lua_State *l) { PROFILE_SCOPED() @@ -3627,6 +3672,8 @@ void LuaObject::RegisterClass() { "GetItemRect", l_pigui_get_item_rect }, { "InputText", l_pigui_input_text }, { "Combo", l_pigui_combo }, + { "BeginCombo", l_pigui_begin_combo }, + { "EndCombo", l_pigui_end_combo }, { "ListBox", l_pigui_listbox }, { "CollapsingHeader", l_pigui_collapsing_header }, { "TreeNode", l_pigui_treenode }, @@ -3715,4 +3762,5 @@ void LuaObject::RegisterClass() imguiTableColumnFlagsTable.Register(l, "ImGuiTableColumnFlags"); imguiTableBgFlagsTable.Register(l, "ImGuiTableBgTargetFlags"); imguiColorEditFlagsTable.Register(l, "ImGuiTableColumnFlags"); + imguiComboFlagsTable.Register(l, "ImGuiComboFlags"); } From fbb86b53dbf5f77bd96fb33b0de90d7ba100c3c0 Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Mon, 16 Sep 2024 21:43:23 -0400 Subject: [PATCH 05/12] ui: normalize fonts used for setItemTooltip --- data/pigui/libs/forwarded.lua | 4 ++-- data/pigui/libs/icons.lua | 6 +++--- data/pigui/libs/text.lua | 22 +++++++++++++++++++--- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/data/pigui/libs/forwarded.lua b/data/pigui/libs/forwarded.lua index 9030ee18a7e..676ee08c67f 100644 --- a/data/pigui/libs/forwarded.lua +++ b/data/pigui/libs/forwarded.lua @@ -50,8 +50,8 @@ ui.setScrollHereY = pigui.SetScrollHereY ui.selectable = pigui.Selectable ui.progressBar = pigui.ProgressBar ui.plotHistogram = pigui.PlotHistogram -ui.setTooltip = pigui.SetTooltip -ui.setItemTooltip = pigui.SetItemTooltip +-- ui.setTooltip = pigui.SetTooltip +-- ui.setItemTooltip = pigui.SetItemTooltip ui.addCircle = pigui.AddCircle ui.addCircleFilled = pigui.AddCircleFilled ui.addRect = pigui.AddRect ---@type fun(a: Vector2, b: Vector2, col: Color, rounding: number, edges: integer, thickness: number) diff --git a/data/pigui/libs/icons.lua b/data/pigui/libs/icons.lua index b5a28d84686..c26d2468005 100644 --- a/data/pigui/libs/icons.lua +++ b/data/pigui/libs/icons.lua @@ -100,7 +100,7 @@ function ui.addIcon(position, icon, color, size, anchor_horizontal, anchor_verti end if tooltip and (ui.isMouseHoveringWindow() or not ui.isAnyWindowHovered()) and tooltip ~= "" then if pigui.IsMouseHoveringRect(pos, pos + size, true) then - ui.maybeSetTooltip(tooltip) + ui.setTooltip(tooltip) end end return size @@ -155,7 +155,7 @@ function ui.addWideIcon(position, icon, color, size, anchor_horizontal, anchor_v end if tooltip and (ui.isMouseHoveringWindow() or not ui.isAnyWindowHovered()) and tooltip ~= "" then if pigui.IsMouseHoveringRect(pos, pos + size, true) then - ui.maybeSetTooltip(tooltip) + ui.setTooltip(tooltip) end end @@ -185,7 +185,7 @@ function ui.addIconSimple(pos, icon, size, color, tooltip) if tooltip and (ui.isMouseHoveringWindow() or not ui.isAnyWindowHovered()) then if pigui.IsMouseHoveringRect(pos, pos + size, true) then - ui.maybeSetTooltip(tooltip) + ui.setTooltip(tooltip) end end end diff --git a/data/pigui/libs/text.lua b/data/pigui/libs/text.lua index 10eed36a92e..cc1bc7eb0fa 100644 --- a/data/pigui/libs/text.lua +++ b/data/pigui/libs/text.lua @@ -429,7 +429,7 @@ ui.addStyledText = function(position, anchor_horizontal, anchor_vertical, text, if tooltip and (ui.isMouseHoveringWindow() or not ui.isAnyWindowHovered()) and tooltip ~= "" then if pigui.IsMouseHoveringRect(position, position + size, true) then - ui.maybeSetTooltip(tooltip) + ui.setTooltip(tooltip) end end @@ -446,7 +446,7 @@ end -- tooltip - string, tooltip text to display to the user -- font - optional font table, used to display the given tooltip -- -function ui.maybeSetTooltip(tooltip, font) +function ui.setTooltip(tooltip, font) if not Input.GetMouseCaptured() then ui.withFont(font or ui.fonts.pionillium.details, function() pigui.SetTooltip(tooltip) @@ -454,4 +454,20 @@ function ui.maybeSetTooltip(tooltip, font) end end -ui.setTooltip = ui.maybeSetTooltip +-- +-- Function: setItemTooltip +-- +-- Displays a tooltip in the UI if the last submitted "item" is hovered with a short delay. +-- The function does not display a tooltip if the mouse is currently captured by the game. +-- +-- Parameters: +-- tooltip - string, tooltip text to display to the user +-- font - optional font table, used to display the given tooltip +-- +function ui.setItemTooltip(tooltip, font) + if not Input.GetMouseCaptured() then + ui.withFont(font or ui.fonts.pionillium.details, function() + pigui.SetItemTooltip(tooltip) + end) + end +end From 870738cce80378d8571562bf36363874475a0bd9 Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Wed, 18 Sep 2024 01:14:37 -0400 Subject: [PATCH 06/12] ui: button() takes optional padding argument --- data/pigui/libs/buttons.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/data/pigui/libs/buttons.lua b/data/pigui/libs/buttons.lua index 08b167ca07c..bf335ba7fcf 100644 --- a/data/pigui/libs/buttons.lua +++ b/data/pigui/libs/buttons.lua @@ -60,7 +60,7 @@ end -- -- Function: ui.button -- --- > clicked = ui.button(label, button_size, variant, tooltip) +-- > clicked = ui.button(label, button_size, variant, tooltip, padding) -- -- Example: -- @@ -74,19 +74,20 @@ end -- variant - [optional] Table, color variants used for this button; -- contains Color fields 'normal', 'hovered', and 'active' -- tooltip - [optional] string, mouseover text +-- padding - [optional] Vector2, size of padding on each side of button -- -- Returns: -- -- clicked - true if button was clicked -- -function ui.button(label, button_size, variant, tooltip) +function ui.button(label, button_size, variant, tooltip, padding) if variant then pigui.PushStyleColor("Button", variant.normal) pigui.PushStyleColor("ButtonHovered", variant.hovered) pigui.PushStyleColor("ButtonActive", variant.active) end - pigui.PushStyleVar("FramePadding", ui.theme.styles.ButtonPadding) + pigui.PushStyleVar("FramePadding", padding or ui.theme.styles.ButtonPadding) local res = pigui.Button(label, button_size or Vector2(0, 0)) pigui.PopStyleVar(1) From d691c2fbe4a1fbb1792451e958d3394fcaa8a6ba Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Fri, 27 Sep 2024 17:34:22 -0400 Subject: [PATCH 07/12] ui: buttons use setItemTooltip() - Small delay before displaying button tooltip, better matches the rest of the UI - Consistent font choice with rest of UI --- data/pigui/libs/buttons.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/data/pigui/libs/buttons.lua b/data/pigui/libs/buttons.lua index bf335ba7fcf..8b4992485c0 100644 --- a/data/pigui/libs/buttons.lua +++ b/data/pigui/libs/buttons.lua @@ -95,7 +95,10 @@ function ui.button(label, button_size, variant, tooltip, padding) pigui.PopStyleColor(3) end - if pigui.IsItemHovered() and tooltip then pigui.SetTooltip(tooltip) end + if tooltip then + ui.setItemTooltip(tooltip) + end + return res end @@ -186,8 +189,8 @@ function ui.iconButton(id, icon, tooltip, variant, size, padding, flags) pigui:PopFont() end - if tooltip and pigui.IsItemHovered() then - ui.setTooltip(tooltip) + if tooltip then + ui.setItemTooltip(tooltip) end return ret From 13c73a36b945d3c48ecc3f4151884a84964d6fda Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Wed, 18 Sep 2024 15:52:04 -0400 Subject: [PATCH 08/12] debug-ui: pass self to tab, only reload active tab - Ensure the tab function receives a reference to the self argument - Reload only the actively selected tab when pressing Ctrl+R --- data/pigui/views/debug.lua | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/data/pigui/views/debug.lua b/data/pigui/views/debug.lua index 311792abd18..ec978af8290 100644 --- a/data/pigui/views/debug.lua +++ b/data/pigui/views/debug.lua @@ -14,11 +14,17 @@ local function drawTab(tab, i, delta) local label = tab.label or "" local icon_str = "{}##{}" % { ui.get_icon_glyph(icon), i } + local active = false + ui.tabItem(icon_str, label, function() + active = true + ui.child(label, Vector2(0, 0), childWindowFlags, function() - tab.draw(delta) + tab.draw(tab, delta) end) end) + + return active end ---@class Debug.DebugTab @@ -51,14 +57,17 @@ end function debugView.drawTabs(delta) for i, tab in ipairs(debugView.tabs) do if not tab.show or tab.show() then - drawTab(tab, i, delta) + if drawTab(tab, i, delta) then + + if ui.ctrlHeld() and ui.isKeyReleased(string.byte 'r') then + print("Hot reloading module " .. tab.module) + package.reimport(tab.module) + end - if ui.ctrlHeld() and ui.isKeyReleased(string.byte 'r') then - print("Hot reloading module " .. tab.module) - package.reimport(tab.module) end end end + end ui.registerHandler('debug-tabs', debugView.drawTabs) From e233340f05c4ee131ba833003a8a90db08d96e0a Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Thu, 19 Sep 2024 21:18:51 -0400 Subject: [PATCH 09/12] Add utils.mixin() - Allows taking an existing table value and making a copy with some values overridden - Primary usecase is "inline modification" of a plain table (i.e. not a prototype or class instance) - Make table.merge() and table.append() more efficient by only checking validity of the predicate once --- data/libs/autoload.lua | 24 ++++++++++++++++++------ data/libs/utils.lua | 5 +++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/data/libs/autoload.lua b/data/libs/autoload.lua index 17374981a63..c0c1aea18f9 100644 --- a/data/libs/autoload.lua +++ b/data/libs/autoload.lua @@ -85,9 +85,15 @@ end ---@param predicate nil|fun(k: K, v: V): any, any ---@return table table.merge = function(a, b, predicate) - for k, v in pairs(b) do - if predicate then k, v = predicate(k, v) end - a[k] = v + if predicate then + for k, v in pairs(b) do + k, v = predicate(k, v) + a[k] = v + end + else + for k, v in pairs(b) do + a[k] = v + end end return a end @@ -102,9 +108,15 @@ end ---@param predicate nil|fun(v: T): any ---@return table table.append = function(a, b, predicate) - for _, v in ipairs(b) do - if predicate then v = predicate(v) end - table.insert(a, v) + if predicate then + for _, v in ipairs(b) do + v = predicate(v) + table.insert(a, v) + end + else + for _, v in ipairs(b) do + table.insert(a, v) + end end return a end diff --git a/data/libs/utils.lua b/data/libs/utils.lua index f9691222745..197f999cd1c 100644 --- a/data/libs/utils.lua +++ b/data/libs/utils.lua @@ -494,6 +494,11 @@ utils.proto = function(classname) return newProto end +-- Return a copy of a with the values from b added to it +function utils.mixin(a, b) + return table.append(table.copy(a), b) +end + -- -- Function: print_r -- From e1c9f0bd78dcefea433cc21e40ab7d2081c91c79 Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Tue, 24 Sep 2024 22:56:20 -0400 Subject: [PATCH 10/12] utils: add best_score(), least_score(), object:IsA() - Add helpers to iterate a table and return the value with the greatest or least score according to the passed scoring function along with the "winning" score - Add constant-time class inheritance lookup via cached inheritance map - Fix erroneous use of table.append() instead of table.merge() --- data/libs/utils.lua | 65 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/data/libs/utils.lua b/data/libs/utils.lua index 197f999cd1c..2d9ea9d341d 100644 --- a/data/libs/utils.lua +++ b/data/libs/utils.lua @@ -230,6 +230,58 @@ utils.find_if = function(t, predicate) return nil end +-- +-- Function: best_score +-- +-- Returns the value in the passed table with the highest score according to the passed scoring function +-- +-- Iteration order is undefined (uses pairs() internally). +-- +---@generic K, V +---@param t table +---@param score_fun fun(k: K, v: V): number? +---@return V?, number +utils.best_score = function(t, score_fun) + local score = 0.0 + local best_val = nil + + for k, v in pairs(t) do + local new_score = score_fun(k, v) + if new_score and new_score > score then + score = new_score + best_val = v + end + end + + return best_val, score +end + +-- +-- Function: least_score +-- +-- Returns the value in the passed table with the lowest score according to the passed scoring function +-- +-- Iteration order is undefined (uses pairs() internally). +-- +---@generic K, V +---@param t table +---@param score_fun fun(k: K, v: V): number? +---@return V?, number +utils.least_score = function(t, score_fun) + local score = math.huge + local best_val = nil + + for k, v in pairs(t) do + local new_score = score_fun(k, v) + if new_score and new_score < score then + score = new_score + best_val = v + end + end + + return best_val, score +end + -- -- Function: stable_sort -- @@ -326,7 +378,7 @@ end -- local object = {} -object.meta = { __index = object, class="object" } +object.meta = { __index = object, class="object", inherits = { ["object"] = true } } -- -- Function: New @@ -390,7 +442,10 @@ end utils.inherits = function (baseClass, name) local new_class = {} local base_class = baseClass or object - new_class.meta = { __index = new_class, class=name } + new_class.meta = { __index = new_class, class=name, inherits = { [name] = true } } + + -- Allow quick lookup by parent class + table.merge(new_class.meta.inherits, base_class.meta.inherits) -- generic constructor function new_class.New(...) @@ -406,6 +461,10 @@ utils.inherits = function (baseClass, name) return new_class end + function new_class:IsA(typename) + return new_class.meta.inherits[typename] + end + function new_class.Unserialize(data) local tmp = base_class.Unserialize(data) setmetatable(tmp, new_class.meta) @@ -496,7 +555,7 @@ end -- Return a copy of a with the values from b added to it function utils.mixin(a, b) - return table.append(table.copy(a), b) + return table.merge(table.copy(a), b) end -- From 619a7504871ff5608249515a228ef5808a1cb7ff Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Tue, 24 Sep 2024 22:58:57 -0400 Subject: [PATCH 11/12] Improve Lua type information - Add type information to Event.Register - Add additional method prototypes to Ship.meta.lua --- data/libs/Event.lua | 2 ++ data/meta/CoreObject/Ship.meta.lua | 15 +++++++++++++++ data/meta/Engine.lua | 5 +++++ data/meta/Model.lua | 23 +++++++++++++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 data/meta/Model.lua diff --git a/data/libs/Event.lua b/data/libs/Event.lua index 2288b43c0ce..ff744b8ee3c 100644 --- a/data/libs/Event.lua +++ b/data/libs/Event.lua @@ -131,6 +131,8 @@ Event.New = function() -- -- stable -- + ---@param name string + ---@param cb function self.Register = function (name, cb) super.Register(self, name, package.modulename(2), cb) end diff --git a/data/meta/CoreObject/Ship.meta.lua b/data/meta/CoreObject/Ship.meta.lua index 044e6208209..dc37389aade 100644 --- a/data/meta/CoreObject/Ship.meta.lua +++ b/data/meta/CoreObject/Ship.meta.lua @@ -115,3 +115,18 @@ function Ship:GetShieldsPercent() end -- Sets the thruster fuel tank of the ship to the given percentage of its maximum. ---@param percent number function Ship:SetFuelPercent(percent) end + +-- Update ship properties after changing ship equipment or cargo +function Ship:UpdateEquipStats() end + +-- Is this ship currently docked with anything? +---@return boolean +function Ship:IsDocked() end + +-- Is this ship currently landed on a planet? +---@return boolean +function Ship:IsLanded() end + +-- Get the starport this ship is docked with, if any +---@return SpaceStation? +function Ship:GetDockedWith() end diff --git a/data/meta/Engine.lua b/data/meta/Engine.lua index 0051d44fe38..458a2572dfc 100644 --- a/data/meta/Engine.lua +++ b/data/meta/Engine.lua @@ -20,4 +20,9 @@ local Engine = {} -- TODO: add information about Engine methods +-- Get a model file by name +---@param name string +---@return SceneGraph.Model model +function Engine.GetModel(name) end + return Engine diff --git a/data/meta/Model.lua b/data/meta/Model.lua new file mode 100644 index 00000000000..1207ef8d54f --- /dev/null +++ b/data/meta/Model.lua @@ -0,0 +1,23 @@ +-- Copyright © 2008-2024 Pioneer Developers. See AUTHORS.txt for details +-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt + +-- This file implements type information about C++ classes for Lua static analysis + +---@meta + +---@class SceneGraph.Model +--- +---@field name string +---@field pattern integer Current pattern applied to the model +---@field numPatterns integer Number of patterns supported by the model + +---@class SceneGraph.Model +local Model = {} + +-- Set the pattern currently applied to the model +---@param idx integer +function Model:SetPattern(idx) end + +-- Set debug flags used when rendering this model +---@param flags ModelDebugFlags[] +function Model:SetDebugFlags(flags) end From 73671cfa8cc37c8d03b3ebaacd4e1db5eee417ea Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Tue, 24 Sep 2024 23:37:45 -0400 Subject: [PATCH 12/12] MissionUtils: add Hours, Weeks time units --- data/modules/MissionUtils.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/data/modules/MissionUtils.lua b/data/modules/MissionUtils.lua index 540ad8de7b8..71df4fc8b07 100644 --- a/data/modules/MissionUtils.lua +++ b/data/modules/MissionUtils.lua @@ -8,11 +8,15 @@ local utils = require "utils" local AU = 149598000000 local AU_sqrt = math.sqrt(AU) -local Days = 24*60*60 +local Hours = 60*60 +local Days = 24*Hours +local Weeks = 7*Days local MissionUtils = { AU = AU, - Days = Days + Days = Days, + Hours = Hours, + Weeks = Weeks, } ---@class MissionUtils.Calculator