diff --git a/config/GM8E01_00/splits.txt b/config/GM8E01_00/splits.txt index 0ad8c574..f2d7ed6e 100644 --- a/config/GM8E01_00/splits.txt +++ b/config/GM8E01_00/splits.txt @@ -2450,11 +2450,11 @@ GuiSys/CGuiWidget.cpp: .text start:0x802CA5DC end:0x802CAF74 .rodata start:0x803D68F8 end:0x803D6948 .data start:0x803ECA10 end:0x803ECA50 + .sdata2 start:0x805AE130 end:0x805AE138 GuiSys/CGuiWidgetIdDB.cpp: .text start:0x802CAF74 end:0x802CB1B0 .rodata start:0x803D6948 end:0x803D69B0 - .sdata2 start:0x805AE130 end:0x805AE138 GuiSys/CGuiWidgetDrawParms.cpp: .text start:0x802CB1B0 end:0x802CB1D0 diff --git a/config/GM8E01_00/symbols.txt b/config/GM8E01_00/symbols.txt index 2b1e9a4e..e70c4ba8 100644 --- a/config/GM8E01_00/symbols.txt +++ b/config/GM8E01_00/symbols.txt @@ -12014,7 +12014,7 @@ Touch__10CGuiWidgetCFv = .text:0x802C0CC8; // type:function size:0x4 scope:globa GetIsFinishedLoadingWidgetSpecific__10CGuiWidgetCFv = .text:0x802C0CCC; // type:function size:0x8 scope:global UpdateMeterWorkers__9CAuiMeterFv = .text:0x802C0CD4; // type:function size:0x22C scope:global OnVisible__9CAuiMeterFv = .text:0x802C0F00; // type:function size:0x48 scope:global -SetRemainder__9CAuiMeteri = .text:0x802C0F48; // type:function size:0x4C scope:global +SetRemainder__9CAuiMeterFi = .text:0x802C0F48; // type:function size:0x4C scope:global SetCapacity__9CAuiMeterFi = .text:0x802C0F94; // type:function size:0x70 scope:global SetMaxCapacity__9CAuiMeterFi = .text:0x802C1004; // type:function size:0x88 scope:global GetWorkerWidget__9CAuiMeterFi = .text:0x802C108C; // type:function size:0x10 scope:global @@ -12276,7 +12276,7 @@ Create__10CGuiWidgetFP9CGuiFrameR12CInputStreamb = .text:0x802CAE58; // type:fun __ct__Q210CGuiWidget15CGuiWidgetParmsFP9CGuiFramebssbbbRC6CColorQ210CGuiWidget18EGuiModelDrawFlagsbb = .text:0x802CAF30; // type:function size:0x44 scope:global FindWidgetID__14CGuiWidgetIdDBCFRCQ24rstl66basic_string,Q24rstl17rmemory_allocator> = .text:0x802CAF74; // type:function size:0x88 scope:global AddWidget__14CGuiWidgetIdDBFRCQ24rstl66basic_string,Q24rstl17rmemory_allocator> = .text:0x802CAFFC; // type:function size:0xA8 scope:global -fn_802CB0A4 = .text:0x802CB0A4; // type:function size:0x28 +Reserve__14CGuiWidgetIdDBFi = .text:0x802CB0A4; // type:function size:0x28 __ct__14CGuiWidgetIdDBFv = .text:0x802CB0CC; // type:function size:0xE4 scope:global __sinit_CGuiWidgetDrawParms_cpp = .text:0x802CB1B0; // type:function size:0x20 scope:local GetWidgetTypeID__16CAuiEnergyBarT01CFv = .text:0x802CB1D0; // type:function size:0xC scope:global @@ -18642,7 +18642,7 @@ lbl_803EC6F8 = .data:0x803EC6F8; // type:object size:0x40 lbl_803EC738 = .data:0x803EC738; // type:object size:0x40 lbl_803EC778 = .data:0x803EC778; // type:object size:0x40 lbl_803EC7B8 = .data:0x803EC7B8; // type:object size:0x10 -lbl_803EC7C8 = .data:0x803EC7C8; // type:object size:0x40 +__vt__9CGuiGroup = .data:0x803EC7C8; // type:object size:0x40 lbl_803EC808 = .data:0x803EC808; // type:object size:0x40 __vt__9CGuiLight = .data:0x803EC848; // type:object size:0x40 scope:global lbl_803EC888 = .data:0x803EC888; // type:object size:0x40 @@ -26262,7 +26262,7 @@ lbl_805AE124 = .sdata2:0x805AE124; // type:object size:0x4 data:float lbl_805AE128 = .sdata2:0x805AE128; // type:object size:0x4 data:float lbl_805AE12C = .sdata2:0x805AE12C; // type:object size:0x4 data:float lbl_805AE130 = .sdata2:0x805AE130; // type:object size:0x2 data:2byte -lbl_805AE132 = .sdata2:0x805AE132; // type:object size:0x6 data:2byte +gkInvalidWidgetId__10CGuiWidget = .sdata2:0x805AE132; // type:object size:0x6 data:2byte @4 = .sdata2:0x805AE138; // type:object size:0x4 scope:local data:float @5 = .sdata2:0x805AE13C; // type:object size:0x4 scope:local data:float lbl_805AE140 = .sdata2:0x805AE140; // type:object size:0x4 data:float diff --git a/config/GM8E01_01/symbols.txt b/config/GM8E01_01/symbols.txt index 6755edf9..905893fa 100644 --- a/config/GM8E01_01/symbols.txt +++ b/config/GM8E01_01/symbols.txt @@ -12029,7 +12029,7 @@ Touch__10CGuiWidgetCFv = .text:0x802C0D74; // type:function size:0x4 scope:globa GetIsFinishedLoadingWidgetSpecific__10CGuiWidgetCFv = .text:0x802C0D78; // type:function size:0x8 scope:global UpdateMeterWorkers__9CAuiMeterFv = .text:0x802C0D80; // type:function size:0x22C scope:global OnVisible__9CAuiMeterFv = .text:0x802C0FAC; // type:function size:0x48 scope:global -SetRemainder__9CAuiMeteri = .text:0x802C0FF4; // type:function size:0x4C scope:global +SetRemainder__9CAuiMeterFi = .text:0x802C0FF4; // type:function size:0x4C scope:global SetCapacity__9CAuiMeterFi = .text:0x802C1040; // type:function size:0x70 scope:global SetMaxCapacity__9CAuiMeterFi = .text:0x802C10B0; // type:function size:0x88 scope:global GetWorkerWidget__9CAuiMeterFi = .text:0x802C1138; // type:function size:0x10 scope:global @@ -12291,7 +12291,7 @@ Create__10CGuiWidgetFP9CGuiFrameR12CInputStreamb = .text:0x802CAF04; // type:fun __ct__Q210CGuiWidget15CGuiWidgetParmsFP9CGuiFramebssbbbRC6CColorQ210CGuiWidget18EGuiModelDrawFlagsbb = .text:0x802CAFDC; // type:function size:0x44 scope:global FindWidgetID__14CGuiWidgetIdDBCFRCQ24rstl66basic_string,Q24rstl17rmemory_allocator> = .text:0x802CB020; // type:function size:0x88 scope:global AddWidget__14CGuiWidgetIdDBFRCQ24rstl66basic_string,Q24rstl17rmemory_allocator> = .text:0x802CB0A8; // type:function size:0xA8 scope:global -fn_802CB0A4 = .text:0x802CB150; // type:function size:0x28 scope:global +Reserve__14CGuiWidgetIdDBFi = .text:0x802CB150; // type:function size:0x28 scope:global __ct__14CGuiWidgetIdDBFv = .text:0x802CB178; // type:function size:0xE4 scope:global __sinit_CGuiWidgetDrawParms_cpp = .text:0x802CB25C; // type:function size:0x20 scope:local GetWidgetTypeID__16CAuiEnergyBarT01CFv = .text:0x802CB27C; // type:function size:0xC scope:global @@ -18693,7 +18693,7 @@ lbl_803EC6F8 = .data:0x803EC8D8; // type:object size:0x40 scope:global lbl_803EC738 = .data:0x803EC918; // type:object size:0x40 scope:global lbl_803EC778 = .data:0x803EC958; // type:object size:0x40 scope:global lbl_803EC7B8 = .data:0x803EC998; // type:object size:0x10 scope:global -lbl_803EC7C8 = .data:0x803EC9A8; // type:object size:0x40 scope:global +__vt__9CGuiGroup = .data:0x803EC9A8; // type:object size:0x40 scope:global lbl_803EC808 = .data:0x803EC9E8; // type:object size:0x40 scope:global __vt__9CGuiLight = .data:0x803ECA28; // type:object size:0x40 scope:global lbl_803EC888 = .data:0x803ECA68; // type:object size:0x40 scope:global @@ -26307,7 +26307,7 @@ lbl_805AE124 = .sdata2:0x805AE304; // type:object size:0x4 scope:global data:flo lbl_805AE128 = .sdata2:0x805AE308; // type:object size:0x4 scope:global data:float lbl_805AE12C = .sdata2:0x805AE30C; // type:object size:0x4 scope:global data:float lbl_805AE130 = .sdata2:0x805AE310; // type:object size:0x2 scope:global data:2byte -lbl_805AE132 = .sdata2:0x805AE312; // type:object size:0x6 scope:global data:2byte +gkInvalidWidgetId__10CGuiWidget = .sdata2:0x805AE312; // type:object size:0x6 scope:global data:2byte @4 = .sdata2:0x805AE318; // type:object size:0x4 scope:local data:float @5 = .sdata2:0x805AE31C; // type:object size:0x4 scope:local data:float lbl_805AE140 = .sdata2:0x805AE320; // type:object size:0x4 scope:global data:float diff --git a/configure.py b/configure.py index 2ce65d20..e493bd54 100755 --- a/configure.py +++ b/configure.py @@ -714,7 +714,7 @@ config.libs = [ Object(NonMatching, "GuiSys/CGuiTextPane.cpp"), Object(NonMatching, "GuiSys/CGuiTextSupport.cpp"), Object(NonMatching, "GuiSys/CGuiWidget.cpp"), - Object(NonMatching, "GuiSys/CGuiWidgetIdDB.cpp"), + Object(Matching, "GuiSys/CGuiWidgetIdDB.cpp"), Object(Matching, "GuiSys/CGuiWidgetDrawParms.cpp"), Object(NonMatching, "GuiSys/CAuiEnergyBarT01.cpp"), Object(NonMatching, "GuiSys/CAuiImagePane.cpp"), diff --git a/include/GuiSys/CAuiMeter.hpp b/include/GuiSys/CAuiMeter.hpp new file mode 100644 index 00000000..bacf8bbc --- /dev/null +++ b/include/GuiSys/CAuiMeter.hpp @@ -0,0 +1,27 @@ +#ifndef _CAUIMETER +#define _CAUIMETER + +#include +#include + +class CAuiMeter : public CGuiGroup { +public: + CAuiMeter(const CGuiWidgetParms& parms, bool b, int w1, int w2); + bool AddWorkerWidget(CGuiWidget* widget) override; + CGuiWidget* GetWorkerWidget(int idx); + void SetMaxCapacity(int cap); + void SetCapacity(int cap); + void SetRemainder(int rem); + void OnVisible() override; + void UpdateMeterWorkers(); + FourCC GetWidgetTypeID() const override { return 'METR'; } + +private: + bool xc4_noRoundUp; + int xc8_maxCapacity; + int xcc_capacity; + int xd0_value; + rstl::vector< CGuiGroup* > xd4_workers; +}; + +#endif // _CAUIMETER diff --git a/include/GuiSys/CGuiCompoundWidget.hpp b/include/GuiSys/CGuiCompoundWidget.hpp index 337baf74..baf0bc70 100644 --- a/include/GuiSys/CGuiCompoundWidget.hpp +++ b/include/GuiSys/CGuiCompoundWidget.hpp @@ -5,6 +5,7 @@ class CGuiCompoundWidget : public CGuiWidget { public: + ~CGuiCompoundWidget(); FourCC GetWidgetTypeID() const override { return -1; } void OnVisible() override; diff --git a/include/GuiSys/CGuiGroup.hpp b/include/GuiSys/CGuiGroup.hpp index f139874b..f724b82b 100644 --- a/include/GuiSys/CGuiGroup.hpp +++ b/include/GuiSys/CGuiGroup.hpp @@ -5,6 +5,7 @@ class CGuiGroup : public CGuiCompoundWidget { public: + CGuiGroup(const CGuiWidgetParms& parms, int, bool); FourCC GetWidgetTypeID() const override { return 'GRUP'; } void SelectWorkerWidget(int workerId, bool setActive, bool setVisible); @@ -12,7 +13,6 @@ public: const CGuiWidget* GetSelectedWidget() const; bool AddWorkerWidget(CGuiWidget* worker) override; void OnActivate() override; - private: uint xb8_workerCount; int xbc_selectedWorker; diff --git a/include/GuiSys/CGuiWidget.hpp b/include/GuiSys/CGuiWidget.hpp index e887c8ca..1208f4ec 100644 --- a/include/GuiSys/CGuiWidget.hpp +++ b/include/GuiSys/CGuiWidget.hpp @@ -56,6 +56,7 @@ public: virtual bool GetIsFinishedLoadingWidgetSpecific() const; virtual void OnVisible(); virtual void OnActivate(); + short GetWorkerId() const { return xb4_workerId; } void SetIsVisible(bool visible); void SetColor(const CColor& color); @@ -67,7 +68,9 @@ public: CGuiFrame* GetFrame() { return xb0_frame; } + static const short InvalidWidgetId() { return gkInvalidWidgetId; } private: + static const short gkInvalidWidgetId; short x70_selfId; short x72_parentId; CTransform4f x74_transform; diff --git a/include/GuiSys/CGuiWidgetIdDB.hpp b/include/GuiSys/CGuiWidgetIdDB.hpp new file mode 100644 index 00000000..c54a00c5 --- /dev/null +++ b/include/GuiSys/CGuiWidgetIdDB.hpp @@ -0,0 +1,18 @@ +#ifndef _CGUIWIDGETIDDB +#define _CGUIWIDGETIDDB + +#include "rstl/string.hpp" +#include "rstl/vector.hpp" + +class CGuiWidgetIdDB { +public: + CGuiWidgetIdDB(); + void Reserve(int); + int AddWidget(const rstl::string& name); + short FindWidgetID(const rstl::string& name) const; +private: + rstl::vector< rstl::string > x0_db; + short x14_lastPoolId; +}; + +#endif // _CGUIWIDGETIDDB diff --git a/src/GuiSys/CAuiMeter.cpp b/src/GuiSys/CAuiMeter.cpp new file mode 100644 index 00000000..dc55e8db --- /dev/null +++ b/src/GuiSys/CAuiMeter.cpp @@ -0,0 +1,97 @@ +#include "GuiSys/CGuiGroup.hpp" +#include "GuiSys/CGuiWidget.hpp" +#include "Kyoto/Math/CMath.hpp" +#include "rstl/math.hpp" +#include + +CAuiMeter::CAuiMeter(const CGuiWidgetParms& parms, bool noRoundUp, int maxCapacity, int workerCount) +: CGuiGroup(parms, 0, false) +, xc4_noRoundUp(noRoundUp) +, xc8_maxCapacity(maxCapacity) +, xcc_capacity(xc8_maxCapacity) +, xd0_value(0) { + xd4_workers.reserve(workerCount); +} + +bool CAuiMeter::AddWorkerWidget(CGuiWidget* worker) { + CGuiGroup::AddWorkerWidget(worker); + short id = worker->GetWorkerId(); + if (id >= xd4_workers.size()) { + for (int i = xd4_workers.size(); i <= id; ++i) { + xd4_workers.push_back(nullptr); + } + } + xd4_workers[id] = static_cast< CGuiGroup* >(worker); + return true; +} + +CGuiWidget* CAuiMeter::GetWorkerWidget(int idx) { return xd4_workers[idx]; } + +// TODO: Why is the only needed for the first one? +static inline const int& hack_min(const int& a, const int& b) { return a < b ? b : a; } + +void CAuiMeter::SetMaxCapacity(const int cap) { + xc8_maxCapacity = hack_min(0, cap); + xcc_capacity = rstl::min_val(xcc_capacity, xc8_maxCapacity); + xd0_value = rstl::min_val(xd0_value, xcc_capacity); + UpdateMeterWorkers(); +} + +void CAuiMeter::SetCapacity(int cap) { + xcc_capacity = CMath::Clamp(0, cap, xc8_maxCapacity); + xd0_value = rstl::min_val(xd0_value, xcc_capacity); + UpdateMeterWorkers(); +} + +void CAuiMeter::SetRemainder(int rem) { + xd0_value = CMath::Clamp(0, rem, xcc_capacity); + UpdateMeterWorkers(); +} + +void CAuiMeter::OnVisible() { + if (GetIsVisible()) { + UpdateMeterWorkers(); + } +} + +void CAuiMeter::UpdateMeterWorkers() { + float scale = xd4_workers.size() / float(xc8_maxCapacity); + int etankCap; + int etankFill; + int workerCount = xd4_workers.size(); + if (xc4_noRoundUp) + etankCap = scale * xcc_capacity; + else + etankCap = 0.5f + (scale * xcc_capacity); + + if (xc4_noRoundUp) + etankFill = scale * xd0_value; + else + etankFill = 0.5f + scale * xd0_value; + + for (int i = 0; i < workerCount; ++i) { + CGuiGroup* worker = xd4_workers[i]; + if (!worker) + continue; + + CGuiWidget* fullTank = worker->GetWorkerWidget(0); + CGuiWidget* emptyTank = worker->GetWorkerWidget(1); + + if (i < etankFill) { + if (fullTank) + fullTank->SetIsVisible(true); + if (emptyTank) + emptyTank->SetIsVisible(false); + } else if (i < etankCap) { + if (fullTank) + fullTank->SetIsVisible(false); + if (emptyTank) + emptyTank->SetIsVisible(true); + } else { + if (fullTank) + fullTank->SetIsVisible(false); + if (emptyTank) + emptyTank->SetIsVisible(false); + } + } +} diff --git a/src/GuiSys/CGuiWidgetIdDB.cpp b/src/GuiSys/CGuiWidgetIdDB.cpp new file mode 100644 index 00000000..f9498c61 --- /dev/null +++ b/src/GuiSys/CGuiWidgetIdDB.cpp @@ -0,0 +1,38 @@ +#include +#include + +CGuiWidgetIdDB::CGuiWidgetIdDB() { + x0_db.reserve(4); + AddWidget(rstl::string_l("kGSYS_DummyWidgetID")); + AddWidget(rstl::string_l("kGSYS_HeadWidgetID")); + AddWidget(rstl::string_l("kGSYS_DefaultCameraID")); + AddWidget(rstl::string_l("kGSYS_DefaultLightID")); +} + +void CGuiWidgetIdDB::Reserve(int size) { + x0_db.reserve(size + x0_db.size()); +} + +int CGuiWidgetIdDB::AddWidget(const rstl::string& name) { + short id = FindWidgetID(name); + if (id == CGuiWidget::InvalidWidgetId()) { + x0_db.push_back(name); + id = x0_db.size() - 1; + } + + return id; +} + +short CGuiWidgetIdDB::FindWidgetID(const rstl::string& name) const { + for (int i = 0; i < x0_db.size(); ++i) { + if (x0_db[i] == name) { + return i; + } + } + + return CGuiWidget::InvalidWidgetId(); +} + +static void keep_string() { + static const char* derp ="not found"; +}