diff --git a/src/addons/lua_engine.cpp b/src/addons/lua_engine.cpp index 5e5b2f1f..55543d4e 100644 --- a/src/addons/lua_engine.cpp +++ b/src/addons/lua_engine.cpp @@ -1397,6 +1397,10 @@ void LuaEngine::registerCoreAPI() { "function mt:GetHorizontalScrollRange() return 0 end\n" "function mt:GetVerticalScroll() return 0 end\n" "function mt:GetHorizontalScroll() return 0 end\n" + // Zero when unset, which is what the real client answers and what + // FrameXML concatenates into a name without checking. + "function mt:SetID(id) self.__id = id end\n" + "function mt:GetID() return self.__id or 0 end\n" "function mt:SetScrollChild(child) self.__scrollChild = child end\n" "function mt:GetScrollChild() return self.__scrollChild end\n" "function mt:SetFontString(fs) self.__fontString = fs end\n" diff --git a/src/ui/framexml_emitter.cpp b/src/ui/framexml_emitter.cpp index efa062a5..19417fdf 100644 --- a/src/ui/framexml_emitter.cpp +++ b/src/ui/framexml_emitter.cpp @@ -408,6 +408,14 @@ struct Emitter { if (const std::string* strata = node.attr("frameStrata")) { line(var + ":SetFrameStrata(" + quote(*strata) + ")"); } + // How a frame in a numbered set knows which one it is, and FrameXML + // builds names out of it: PartyMemberFrame_RefreshPetDebuffs reaches + // for _G["PartyMemberFrame" .. self:GetID() .. "PetFrame"]. Ignoring + // the attribute left every one of the 848 declared across 57 files + // answering zero. + if (const std::string* id = node.attr("id"); id && !id->empty()) { + line(var + ":SetID(" + *id + ")"); + } if (node.attr("enableMouse")) { line(var + ":EnableMouse(" + (node.attrBool("enableMouse") ? "true" : "false") + ")"); } diff --git a/tests/test_framexml.cpp b/tests/test_framexml.cpp index 87c273d0..4ef9999d 100644 --- a/tests/test_framexml.cpp +++ b/tests/test_framexml.cpp @@ -229,6 +229,15 @@ TEST_CASE("A template installs OnLoad but does not run it", "[framexml][emit]") REQUIRE(has(r.lua, "SetScript(\"OnLoad\"")); } +TEST_CASE("A frame's id becomes SetID", "[framexml][emit]") { + // How a frame in a numbered set knows which one it is. FrameXML builds + // names out of it — PartyMemberFrame_RefreshPetDebuffs reaches for + // _G["PartyMemberFrame" .. self:GetID() .. "PetFrame"] — and 848 of these + // are declared across 57 files. + XmlNode root = parseOrFail(""); + REQUIRE(has(emitFrameXml(root).lua, ":SetID(3)")); +} + TEST_CASE("parentKey binds a region to a field on its owner", "[framexml][emit]") { // How FrameXML's handlers reach their own pieces: QuestHonorFrameTemplate's // OnLoad opens with self.icon:SetTexture(...), and the icon is bound only