Compare commits

..

6 Commits

Author SHA1 Message Date
fallenoak
3bf95af10c
feat(ui): implement CSimpleTexture_SetDrawLayer
Some checks are pending
Push / ${{ matrix.build.system_name }} / ${{ matrix.build.build_type }} / ${{ matrix.build.compiler_name }} (map[build_type:Release cc:cl compiler_name:MSVC cxx:cl os:windows-latest system_name:Windows test_path:WhoaTest]) (push) Waiting to run
Push / ${{ matrix.build.system_name }} / ${{ matrix.build.build_type }} / ${{ matrix.build.compiler_name }} (map[build_type:Release cc:clang compiler_name:Clang cxx:clang++ os:macos-latest system_name:macOS test_path:WhoaTest]) (push) Waiting to run
Push / ${{ matrix.build.system_name }} / ${{ matrix.build.build_type }} / ${{ matrix.build.compiler_name }} (map[build_type:Release cc:gcc compiler_name:GCC cxx:g++ os:ubuntu-latest system_name:Linux test_path:WhoaTest]) (push) Waiting to run
2026-02-03 16:24:09 -06:00
fallenoak
0681e432e2
feat(ui): handle 3 argument form in CSimpleFrame_GetAttribute 2026-02-03 14:57:22 -06:00
fallenoak
66fd4a6564
feat(ui): implement CSimpleFrame_SetAttribute 2026-02-03 10:13:08 -06:00
fallenoak
c201da76cd
feat(ui): partially implement CSimpleFrame_GetAttribute 2026-02-03 09:40:46 -06:00
fallenoak
3d8073cf75
feat(ui): implement CSimpleFrame::LoadXML_Attributes 2026-02-03 09:00:27 -06:00
fallenoak
bdce266205
feat(ui): add CSimpleFrame::SetAttribute 2026-02-03 08:36:04 -06:00
4 changed files with 312 additions and 4 deletions

View File

@ -95,6 +95,10 @@ void CSimpleFrame::AddFrameRegion(CSimpleRegion* region, uint32_t drawlayer) {
this->NotifyDrawLayerChanged(drawlayer);
}
int32_t CSimpleFrame::AttributeChangesAllowed() {
return true;
}
void CSimpleFrame::DisableDrawLayer(uint32_t drawlayer) {
this->m_drawenabled[drawlayer] = 0;
this->NotifyDrawLayerChanged(drawlayer);
@ -376,6 +380,29 @@ void CSimpleFrame::RegisterForEvents(int32_t a2) {
}
}
void CSimpleFrame::RunOnAttributeChangedScript(const char* name, int32_t luaRef) {
if (!this->m_onAttributeChange.luaRef) {
return;
}
auto L = FrameScript_GetContext();
// TODO taint management
// Attribute name
auto nameLower = static_cast<char*>(alloca(SStrLen(name) + 1));
SStrCopy(nameLower, name);
SStrLower(nameLower);
lua_pushstring(L, nameLower);
// Attribute ref
lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef);
this->RunScript(this->m_onAttributeChange, 2, nullptr);
// TODO taint management
}
void CSimpleFrame::RunOnCharScript(const char* chr) {
if (this->m_onChar.luaRef) {
auto L = FrameScript_GetContext();
@ -749,7 +776,69 @@ int32_t CSimpleFrame::HideThis() {
}
void CSimpleFrame::LoadXML_Attributes(const XMLNode* node, CStatus* status) {
// TODO
auto L = FrameScript_GetContext();
auto child = node->GetChild();
while (child) {
// Unexpected child node
if (SStrCmpI(child->GetName(), "Attribute")) {
status->Add(STATUS_WARNING, "Frame %s: Unknown attributes element %s", this->GetDisplayName(), child->GetName());
child = child->GetSibling();
continue;
}
auto attrName = child->GetAttributeByName("name");
// No attribute name
if (!attrName) {
status->Add(STATUS_WARNING, "Frame %s: unnamed attribute element", this->GetDisplayName());
child = child->GetSibling();
continue;
}
auto attrType = child->GetAttributeByName("type");
if (!attrType) {
attrType = "string";
}
auto attrValue = child->GetAttributeByName("value");
// Missing attribute value for non-nil type
if (SStrCmpI(attrType, "nil") && !attrValue) {
status->Add(STATUS_WARNING, "Frame %s: attribute element named %s missing value", this->GetDisplayName(), attrName);
child = child->GetSibling();
continue;
}
// Push attribute value to stack
if (!SStrCmpI(attrType, "nil")) {
lua_pushnil(L);
} else if (!SStrCmpI(attrType, "boolean")) {
lua_pushboolean(L, StringToBOOL(attrValue));
} else if (!SStrCmpI(attrType, "number")) {
lua_pushnumber(L, SStrToFloat(attrValue));
} else {
lua_pushstring(L, attrValue);
}
auto attr = this->m_attributes.Ptr(attrName);
if (attr) {
luaL_unref(L, LUA_REGISTRYINDEX, attr->luaRef);
} else {
attr = this->m_attributes.New(attrName, 0, 0x0);
}
// TODO taint management
attr->luaRef = luaL_ref(L, LUA_REGISTRYINDEX);
// TODO taint management
child = child->GetSibling();
}
}
void CSimpleFrame::LoadXML_Backdrop(const XMLNode* node, CStatus* status) {
@ -1329,6 +1418,18 @@ void CSimpleFrame::RemoveFrameRegion(CSimpleRegion* region, uint32_t drawlayer)
this->NotifyDrawLayerChanged(drawlayer);
}
void CSimpleFrame::SetAttribute(const char* name, int32_t luaRef) {
auto attr = this->m_attributes.Ptr(name);
if (!attr) {
attr = this->m_attributes.New(name, 0, 0x0);
}
attr->luaRef = luaRef;
this->RunOnAttributeChangedScript(name, luaRef);
}
void CSimpleFrame::SetBackdrop(CBackdropGenerator* backdrop) {
if (this->m_backdrop) {
delete this->m_backdrop;

View File

@ -128,6 +128,7 @@ class CSimpleFrame : public CScriptRegion {
// Member functions
CSimpleFrame(CSimpleFrame* parent);
void AddFrameRegion(CSimpleRegion* region, uint32_t drawlayer);
int32_t AttributeChangesAllowed();
void DisableDrawLayer(uint32_t drawlayer);
void DisableEvent(CSimpleEventType eventType);
void EnableDrawLayer(uint32_t drawlayer);
@ -146,6 +147,7 @@ class CSimpleFrame : public CScriptRegion {
void RegisterForEvents(int32_t a2);
void RegisterRegion(CSimpleRegion* region);
void RemoveFrameRegion(CSimpleRegion* region, uint32_t drawlayer);
void RunOnAttributeChangedScript(const char* name, int32_t luaRef);
void RunOnCharScript(const char* chr);
void RunOnEnableScript();
void RunOnEnterScript(int32_t a2);
@ -159,6 +161,7 @@ class CSimpleFrame : public CScriptRegion {
void RunOnShowScript();
void RunOnSizeChangedScript(float width, float height);
void RunOnUpdateScript(float elapsedSec);
void SetAttribute(const char* name, int32_t luaRef);
void SetBackdrop(CBackdropGenerator* backdrop);
void SetBeingScrolled(int32_t a2, int32_t a3);
void SetFrameAlpha(uint8_t alpha);

View File

@ -180,11 +180,197 @@ 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<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
// 3 argument form
if (lua_gettop(L) == 4 && lua_isstring(L, 3)) {
size_t prefixLen, nameLen, suffixLen;
auto prefix = lua_tolstring(L, 2, &prefixLen);
auto name = lua_tolstring(L, 3, &nameLen);
auto suffix = lua_tolstring(L, 4, &suffixLen);
char buffer[256];
char* write;
size_t remaining;
size_t copyLen;
int32_t luaRef;
// Attempt 1: prefix + name + suffix
write = buffer;
remaining = 255;
if (prefixLen > 0) {
copyLen = (prefixLen < remaining) ? prefixLen : remaining;
memcpy(write, prefix, copyLen);
write += copyLen;
remaining -= copyLen;
}
if (nameLen > 0) {
copyLen = (nameLen < remaining) ? nameLen : remaining;
memcpy(write, name, copyLen);
write += copyLen;
remaining -= copyLen;
}
if (suffixLen > 0) {
copyLen = (suffixLen < remaining) ? suffixLen : remaining;
memcpy(write, suffix, copyLen);
write += copyLen;
}
*write = '\0';
if (frame->GetAttribute(buffer, luaRef)) {
lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef);
return 1;
}
// Attempt 2: "*" + name + suffix
write = buffer;
*write++ = '*';
remaining = 254;
if (nameLen > 0) {
copyLen = (nameLen < remaining) ? nameLen : remaining;
memcpy(write, name, copyLen);
write += copyLen;
remaining -= copyLen;
}
if (suffixLen > 0) {
copyLen = (suffixLen < remaining) ? suffixLen : remaining;
memcpy(write, suffix, copyLen);
write += copyLen;
}
*write = '\0';
if (frame->GetAttribute(buffer, luaRef)) {
lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef);
return 1;
}
// Attempt 3: prefix + name + "*"
write = buffer;
remaining = 254;
if (prefixLen > 0) {
copyLen = (prefixLen < remaining) ? prefixLen : remaining;
memcpy(write, prefix, copyLen);
write += copyLen;
remaining -= copyLen;
}
if (nameLen > 0) {
copyLen = (nameLen < remaining) ? nameLen : remaining;
memcpy(write, name, copyLen);
write += copyLen;
}
*write++ = '*';
*write = '\0';
if (frame->GetAttribute(buffer, luaRef)) {
lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef);
return 1;
}
// Attempt 4: "*" + name + "*"
write = buffer;
*write++ = '*';
remaining = 253;
if (nameLen > 0) {
copyLen = (nameLen < remaining) ? nameLen : remaining;
memcpy(write, name, copyLen);
write += copyLen;
}
*write++ = '*';
*write = '\0';
if (frame->GetAttribute(buffer, luaRef)) {
lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef);
return 1;
}
// Attempt 5: name
if (frame->GetAttribute(name, luaRef)) {
lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef);
return 1;
}
// Not found
lua_pushnil(L);
return 1;
}
// 1 argument form
if (lua_isstring(L, 2)) {
auto attrName = lua_tostring(L, 2);
int32_t luaRef;
if (frame->GetAttribute(attrName, luaRef)) {
lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef);
return 1;
}
// Not found
lua_pushnil(L);
return 1;
}
// Invalid call
luaL_error(L, "Usage: %s:GetAttribute(\"name\")", frame->GetDisplayName());
return 0;
}
int32_t CSimpleFrame_SetAttribute(lua_State* L) {
WHOA_UNIMPLEMENTED(0);
auto type = CSimpleFrame::GetObjectType();
auto frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
if (!frame->ProtectedFunctionsAllowed() && !frame->AttributeChangesAllowed()) {
// TODO disallowed logic
return 0;
}
lua_settop(L, 3);
if (!lua_isstring(L, 2) || lua_type(L, 3) == LUA_TNONE) {
luaL_error(L, "Usage: %s:SetAttribute(\"name\", value)", frame->GetDisplayName());
return 0;
}
auto attrName = lua_tostring(L, 2);
int32_t luaRef;
if (frame->GetAttribute(attrName, luaRef)) {
luaL_unref(L, LUA_REGISTRYINDEX, luaRef);
}
// TODO taint management
luaRef = luaL_ref(L, LUA_REGISTRYINDEX);
// TODO taint management
frame->SetAttribute(attrName, luaRef);
return 0;
}
int32_t CSimpleFrame_GetEffectiveScale(lua_State* L) {

View File

@ -19,7 +19,25 @@ int32_t CSimpleTexture_GetDrawLayer(lua_State* L) {
}
int32_t CSimpleTexture_SetDrawLayer(lua_State* L) {
WHOA_UNIMPLEMENTED(0);
auto type = CSimpleTexture::GetObjectType();
auto texture = static_cast<CSimpleTexture*>(FrameScript_GetObjectThis(L, type));
if (!lua_isstring(L, 2)) {
luaL_error(L, "Usage: %s:SetDrawLayer(\"layer\")", texture->GetDisplayName());
return 0;
}
auto drawlayerStr = lua_tostring(L, 2);
int32_t drawlayer = texture->m_drawlayer;
if (!StringToDrawLayer(drawlayerStr, drawlayer)) {
luaL_error(L, "Usage: %s:SetDrawLayer(\"layer\")", texture->GetDisplayName());
return 0;
}
texture->SetFrame(texture->m_parent, drawlayer, texture->m_shown);
return 0;
}
int32_t CSimpleTexture_GetBlendMode(lua_State* L) {