From 19feaf57d31d204249e70b1babdfe78fcead8389 Mon Sep 17 00:00:00 2001 From: VDm Date: Mon, 11 Aug 2025 00:56:29 +0400 Subject: [PATCH] feat(ui): implement CSimpleFrame_GetAttribute script method --- src/ui/CSimpleFrame.cpp | 27 +++++++-------- src/ui/CSimpleFrame.hpp | 3 +- src/ui/CSimpleFrameScript.cpp | 62 ++++++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/ui/CSimpleFrame.cpp b/src/ui/CSimpleFrame.cpp index 1441a58..71dcc3f 100644 --- a/src/ui/CSimpleFrame.cpp +++ b/src/ui/CSimpleFrame.cpp @@ -706,22 +706,14 @@ void CSimpleFrame::LoadXML_Attributes(XMLNode* node, CStatus* status) { while (child) { auto childName = child->m_name.GetString(); if (SStrCmpI(childName, "Attribute", STORM_MAX_STR)) { - const char* frameName = this->GetName(); - if (!frameName) { - frameName = ""; - } - status->Add(STATUS_WARNING, "Frame %s: Unknown attributes element %s", frameName, childName); + status->Add(STATUS_WARNING, "Frame %s: Unknown attributes element %s", this->GetDisplayName(), childName); child = child->m_next; continue; } auto name = child->GetAttributeByName("name"); if (!name) { - const char* frameName = this->GetName(); - if (!frameName) { - frameName = ""; - } - status->Add(STATUS_WARNING, "Frame %s: unnamed attribute element", frameName); + status->Add(STATUS_WARNING, "Frame %s: unnamed attribute element", this->GetDisplayName()); child = child->m_next; continue; } @@ -733,11 +725,7 @@ void CSimpleFrame::LoadXML_Attributes(XMLNode* node, CStatus* status) { auto value = child->GetAttributeByName("value"); if (!value || !SStrCmpI(value, "nil", STORM_MAX_STR)) { - const char* frameName = this->GetName(); - if (!frameName) { - frameName = ""; - } - status->Add(STATUS_WARNING, "Frame %s: attribute element named %s missing value", frameName, name); + status->Add(STATUS_WARNING, "Frame %s: attribute element named %s missing value", this->GetDisplayName(), name); child = child->m_next; continue; } @@ -1651,3 +1639,12 @@ void CSimpleFrame::UnregisterRegion(CSimpleRegion* region) { this->m_regions.UnlinkNode(region); } + +bool CSimpleFrame::GetAttribute(const char* name, int32_t& luaRef) { + auto attribute = this->m_attributes.Ptr(name); + if (!attribute || attribute->luaRef == -1) { + return false; + } + luaRef = attribute->luaRef; + return true; +} diff --git a/src/ui/CSimpleFrame.hpp b/src/ui/CSimpleFrame.hpp index a477e37..e25d1e5 100644 --- a/src/ui/CSimpleFrame.hpp +++ b/src/ui/CSimpleFrame.hpp @@ -19,7 +19,7 @@ struct lua_State; class FRAMEATTR : public TSHashObject { public: - int32_t luaRef; + int32_t luaRef = -1; }; class CSimpleFrame : public CScriptRegion { @@ -165,6 +165,7 @@ class CSimpleFrame : public CScriptRegion { void Show(); int32_t TestHitRect(const C2Vector& pt); void UnregisterForEvents(int32_t a2); + bool GetAttribute(const char* name, int32_t& luaRef); }; #endif diff --git a/src/ui/CSimpleFrameScript.cpp b/src/ui/CSimpleFrameScript.cpp index 739e317..e50e569 100644 --- a/src/ui/CSimpleFrameScript.cpp +++ b/src/ui/CSimpleFrameScript.cpp @@ -231,7 +231,67 @@ int32_t CSimpleFrame_CanChangeAttributes(lua_State* L) { } int32_t CSimpleFrame_GetAttribute(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleFrame::GetObjectType(); + auto frame = static_cast(FrameScript_GetObjectThis(L, type)); + + if (lua_gettop(L) == 4 && lua_isstring(L, 3)) { + size_t prefixLength; + size_t nameLength; + size_t suffixLength; + auto prefix = lua_tolstring(L, 2, &prefixLength); + auto name = lua_tolstring(L, 3, &nameLength); + auto suffix = lua_tolstring(L, 4, &suffixLength); + + int32_t luaRef = -1; + char fullName[256]; + + size_t offset = 0; + offset += SStrNCopy(&fullName[offset], prefix, prefixLength, sizeof(fullName) - offset); + offset += SStrNCopy(&fullName[offset], name, nameLength, sizeof(fullName) - offset); + offset += SStrNCopy(&fullName[offset], suffix, suffixLength, sizeof(fullName) - offset); + + if (frame->GetAttribute(fullName, luaRef)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + return 1; + } + + offset = 0; + offset += SStrNCopy(&fullName[offset], prefix, prefixLength, sizeof(fullName) - offset - 1); + offset += SStrNCopy(&fullName[offset], name, nameLength, sizeof(fullName) - offset - 1); + fullName[offset++] = '*'; + fullName[offset++] = '\0'; + + if (frame->GetAttribute(fullName, luaRef)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + return 1; + } + + offset = 0; + fullName[offset++] = '*'; + offset += SStrNCopy(&fullName[offset], name, nameLength, sizeof(fullName) - offset - 1); + fullName[offset++] = '*'; + fullName[offset++] = '\0'; + + if (frame->GetAttribute(fullName, luaRef) || frame->GetAttribute(name, luaRef)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + return 1; + } + + lua_pushnil(L); + } else { + if (!lua_isstring(L, 2)) { + return luaL_error(L, "Usage: %s:GetAttribute(\"name\")", frame->GetDisplayName()); + } + + auto name = lua_tolstring(L, 2, nullptr); + int32_t luaRef = -1; + if (frame->GetAttribute(name, luaRef)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + } else { + lua_pushnil(L); + } + } + return 1; } int32_t CSimpleFrame_SetAttribute(lua_State* L) {