From 3fb86ab12e180c475cfe6cf6c52d272fe2f83504 Mon Sep 17 00:00:00 2001 From: VDm Date: Sun, 22 Jun 2025 13:56:06 +0400 Subject: [PATCH] feat(ui): implement CSimpleCheckbox methods to support textures --- src/ui/CSimpleCheckbox.cpp | 94 +++++++++++++++++++++++++ src/ui/CSimpleCheckbox.hpp | 5 ++ src/ui/CSimpleCheckboxScript.cpp | 113 +++++++++++++++++++++++++++++-- 3 files changed, 205 insertions(+), 7 deletions(-) diff --git a/src/ui/CSimpleCheckbox.cpp b/src/ui/CSimpleCheckbox.cpp index cbf79a1..3f0bbab 100644 --- a/src/ui/CSimpleCheckbox.cpp +++ b/src/ui/CSimpleCheckbox.cpp @@ -1,10 +1,15 @@ #include "ui/CSimpleCheckbox.hpp" #include "ui/CSimpleCheckboxScript.hpp" #include "ui/CSimpleTexture.hpp" +#include "ui/LoadXML.hpp" +#include "util/StringTo.hpp" +#include + int32_t CSimpleCheckbox::s_metatable; int32_t CSimpleCheckbox::s_objectType; + void CSimpleCheckbox::CreateScriptMetaTable() { lua_State* L = FrameScript_GetContext(); int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleCheckbox::RegisterScriptMethods); @@ -32,6 +37,27 @@ int32_t CSimpleCheckbox::GetScriptMetaTable() { return CSimpleCheckbox::s_metatable; } +void CSimpleCheckbox::LoadXML(XMLNode* node, CStatus* status) { + CSimpleButton::LoadXML(node, status); + + const char* checked = node->GetAttributeByName("checked"); + + if (checked && *checked) { + this->SetChecked(StringToBOOL(checked), 0); + } + + for (XMLNode* child = node->m_child; child; child = child->m_next) { + if (!SStrCmpI(child->GetName(), "CheckedTexture", STORM_MAX_STR)) { + CSimpleTexture* texture = LoadXML_Texture(child, this, status); + this->SetCheckedTexture(texture); + + } else if (!SStrCmpI(child->GetName(), "DisabledCheckedTexture", STORM_MAX_STR)) { + CSimpleTexture* texture = LoadXML_Texture(child, this, status); + this->SetDisabledCheckedTexture(texture); + } + } +} + void CSimpleCheckbox::Enable(int32_t enabled) { this->CSimpleButton::Enable(enabled); this->SetChecked(this->m_checked, 1); @@ -66,6 +92,74 @@ int32_t CSimpleCheckbox::GetChecked() { return this->m_checked; } +void CSimpleCheckbox::SetCheckedTexture(const char* texFile) { + if (this->m_checkedTexture) { + this->m_checkedTexture->SetTexture(texFile, false, false, GxTex_Linear, ImageMode_UI); + return; + } + + // TODO: CDataAllocator__GetData(CSimpleTexture::s_allocator, 0, ".?AVCSimpleTexture@@", -2); + auto texture = NEW(CSimpleTexture, nullptr, DRAWLAYER_ARTWORK, 0); + if (texture->SetTexture(texFile, false, false, GxTex_Linear, ImageMode_UI)) { + texture->SetAllPoints(this, 1); + texture->SetBlendMode(GxBlend_Add); + this->SetCheckedTexture(texture); + } else if (texture) { + // TODO: FrameScript_Object::LookupScriptMethod(texture, 1); + } +} + +void CSimpleCheckbox::SetCheckedTexture(CSimpleTexture* texture) { + if (texture == this->m_checkedTexture) { + return; + } + + if (this->m_checkedTexture) { + // TODO: FrameScript_Object::LookupScriptMethod(this->m_checkedTexture, 1); + } + + if (texture) { + texture->SetFrame(this, 3, 0); + } + + this->m_checkedTexture = texture; + this->SetChecked(this->m_checked, 1); +} + +void CSimpleCheckbox::SetDisabledCheckedTexture(const char* texFile) { + if (this->m_disabledTexture) { + this->m_disabledTexture->SetTexture(texFile, false, false, GxTex_Linear, ImageMode_UI); + return; + } + + // TODO: CDataAllocator__GetData(CSimpleTexture::s_allocator, 0, ".?AVCSimpleTexture@@", -2); + auto texture = NEW(CSimpleTexture, nullptr, DRAWLAYER_ARTWORK, 0); + if (texture->SetTexture(texFile, false, false, GxTex_Linear, ImageMode_UI)) { + texture->SetAllPoints(this, 1); + texture->SetBlendMode(GxBlend_Add); + this->SetDisabledCheckedTexture(texture); + } else if (texture) { + // TODO: FrameScript_Object::LookupScriptMethod(texture, 1); + } +} + +void CSimpleCheckbox::SetDisabledCheckedTexture(CSimpleTexture* texture) { + if (texture == this->m_disabledTexture) { + return; + } + + if (this->m_disabledTexture) { + // TODO: FrameScript_Object::LookupScriptMethod(this->m_disabledTexture, 1); + } + + if (texture) { + texture->SetFrame(this, 3, 0); + } + + this->m_disabledTexture = texture; + this->SetChecked(this->m_checked, 1); +} + void CSimpleCheckbox::OnClick(const char* btn, int32_t a3) { this->SetChecked(this->m_checked == 0, 0); this->CSimpleButton::OnClick(btn, a3); diff --git a/src/ui/CSimpleCheckbox.hpp b/src/ui/CSimpleCheckbox.hpp index 4a86152..7c2adbb 100644 --- a/src/ui/CSimpleCheckbox.hpp +++ b/src/ui/CSimpleCheckbox.hpp @@ -22,9 +22,14 @@ class CSimpleCheckbox : public CSimpleButton { // Virtual member functions virtual bool IsA(int32_t type); virtual int32_t GetScriptMetaTable(); + virtual void LoadXML(XMLNode* node, CStatus* status); virtual void Enable(int32_t enabled); virtual void SetChecked(int32_t state, int32_t force); virtual int32_t GetChecked(); + virtual void SetCheckedTexture(const char* texFile); + virtual void SetCheckedTexture(CSimpleTexture* texture); + virtual void SetDisabledCheckedTexture(const char* texFile); + virtual void SetDisabledCheckedTexture(CSimpleTexture* texture); virtual void OnClick(const char* btn, int32_t a3); // Member functions diff --git a/src/ui/CSimpleCheckboxScript.cpp b/src/ui/CSimpleCheckboxScript.cpp index 5f8717a..dd16a90 100644 --- a/src/ui/CSimpleCheckboxScript.cpp +++ b/src/ui/CSimpleCheckboxScript.cpp @@ -1,5 +1,6 @@ #include "ui/CSimpleCheckboxScript.hpp" #include "ui/CSimpleCheckbox.hpp" +#include "ui/CSimpleTexture.hpp" #include "util/Lua.hpp" #include "util/StringTo.hpp" #include "util/Unimplemented.hpp" @@ -9,7 +10,7 @@ int32_t CSimpleCheckbox_SetChecked(lua_State* L) { auto type = CSimpleCheckbox::GetObjectType(); auto checkbox = static_cast(FrameScript_GetObjectThis(L, type)); - int32_t state = StringToBOOL(L, 2, 0); + int32_t state = StringToBOOL(L, 2, 1); checkbox->SetChecked(state, 0); return 0; } @@ -18,25 +19,123 @@ int32_t CSimpleCheckbox_GetChecked(lua_State* L) { auto type = CSimpleCheckbox::GetObjectType(); auto checkbox = static_cast(FrameScript_GetObjectThis(L, type)); - lua_Number state = checkbox->GetChecked() ? 1.0 : 0.0; - lua_pushnumber(L, state); + if (checkbox->GetChecked()) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + return 1; } int32_t CSimpleCheckbox_GetCheckedTexture(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleCheckbox::GetObjectType(); + auto checkbox = static_cast(FrameScript_GetObjectThis(L, type)); + auto texture = checkbox->m_checkedTexture; + + if (texture) { + if (!texture->lua_registered) { + texture->RegisterScriptObject(nullptr); + } + lua_rawgeti(L, LUA_REGISTRYINDEX, texture->lua_objectRef); + } else { + lua_pushnil(L); + } + + return 1; } int32_t CSimpleCheckbox_SetCheckedTexture(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleCheckbox::GetObjectType(); + auto checkbox = static_cast(FrameScript_GetObjectThis(L, type)); + auto name = checkbox->GetDisplayName(); + + if (lua_type(L, 2) == LUA_TTABLE) { + lua_rawgeti(L, 2, 0); + auto texture = static_cast(lua_touserdata(L, -1)); + lua_settop(L, -2); + + if (!texture) { + luaL_error(L, "%s:SetCheckedTexture(): Couldn't find 'this' in texture", name); + } else { + auto textureType = CSimpleTexture::GetObjectType(); + if (!texture->IsA(textureType)) { + luaL_error(L, "%s:SetCheckedTexture(): Wrong object type, expected texture", name); + texture = nullptr; + } + } + + checkbox->SetCheckedTexture(texture); + return 0; + } + + if (lua_isstring(L, 2)) { + auto texFile = lua_tostring(L, 2); + checkbox->SetCheckedTexture(texFile); + return 0; + } + + if (lua_type(L, 2) != LUA_TNIL) { + luaL_error(L, "Usage: %s:SetCheckedTexture(texture or \"texture\" or nil)", name); + } + + checkbox->SetCheckedTexture(static_cast(nullptr)); + return 0; } int32_t CSimpleCheckbox_GetDisabledCheckedTexture(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleCheckbox::GetObjectType(); + auto checkbox = static_cast(FrameScript_GetObjectThis(L, type)); + auto texture = checkbox->m_disabledTexture; + + if (texture) { + if (!texture->lua_registered) { + texture->RegisterScriptObject(nullptr); + } + lua_rawgeti(L, LUA_REGISTRYINDEX, texture->lua_objectRef); + } else { + lua_pushnil(L); + } + + return 1; } int32_t CSimpleCheckbox_SetDisabledCheckedTexture(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleCheckbox::GetObjectType(); + auto checkbox = static_cast(FrameScript_GetObjectThis(L, type)); + auto name = checkbox->GetDisplayName(); + + if (lua_type(L, 2) == LUA_TTABLE) { + lua_rawgeti(L, 2, 0); + auto texture = static_cast(lua_touserdata(L, -1)); + lua_settop(L, -2); + + if (!texture) { + luaL_error(L, "%s:SetDisabledCheckedTexture(): Couldn't find 'this' in texture", name); + } else { + auto textureType = CSimpleTexture::GetObjectType(); + if (!texture->IsA(textureType)) { + luaL_error(L, "%s:SetDisabledCheckedTexture(): Wrong object type, expected texture", name); + texture = nullptr; + } + } + + checkbox->SetDisabledCheckedTexture(texture); + return 0; + } + + if (lua_isstring(L, 2)) { + auto texFile = lua_tostring(L, 2); + checkbox->SetDisabledCheckedTexture(texFile); + return 0; + } + + if (lua_type(L, 2) != LUA_TNIL) { + luaL_error(L, "Usage: %s:SetDisabledCheckedTexture(texture or \"texture\" or nil)", name); + } + + checkbox->SetDisabledCheckedTexture(static_cast(nullptr)); + return 0; } FrameScript_Method SimpleCheckboxMethods[NUM_SIMPLE_CHECKBOX_SCRIPT_METHODS] = {