metaforce/Runtime/GuiSys/CGuiWidget.cpp

262 lines
7.5 KiB
C++

#include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/GuiSys/CGuiWidget.hpp"
#include "Runtime/GuiSys/CGuiFrame.hpp"
#include <logvisor/logvisor.hpp>
namespace metaforce {
static logvisor::Module Log("metaforce::CGuiWidget");
CGuiWidget::CGuiWidget(const CGuiWidgetParms& parms)
: x70_selfId(parms.x6_selfId)
, x72_parentId(parms.x8_parentId)
, m_initColor(parms.x10_color)
, xa4_color(parms.x10_color)
, xa8_color2(parms.x10_color)
, xac_drawFlags(parms.x14_drawFlags)
, xb0_frame(parms.x0_frame)
, m_name(parms.m_name) {
xb6_24_pg = parms.xd_g;
xb6_25_isVisible = parms.xa_defaultVisible;
xb6_26_isActive = parms.xb_defaultActive;
xb6_29_cullFaces = parms.xc_cullFaces;
RecalcWidgetColor(ETraversalMode::Single);
}
CGuiWidget::CGuiWidgetParms CGuiWidget::ReadWidgetHeader(CGuiFrame* frame, CInputStream& in) {
std::string name = in.Get<std::string>();
s16 selfId = frame->GetWidgetIdDB().AddWidget(name);
std::string parent = in.Get<std::string>();
s16 parentId = frame->GetWidgetIdDB().AddWidget(parent);
bool useAnimController = in.ReadBool();
bool defaultVis = in.ReadBool();
bool defaultActive = in.ReadBool();
bool cullFaces = in.ReadBool();
zeus::CColor color = in.Get<zeus::CColor>();
EGuiModelDrawFlags df = EGuiModelDrawFlags(in.ReadLong());
return CGuiWidget::CGuiWidgetParms(frame, useAnimController, selfId, parentId, defaultVis, defaultActive, cullFaces,
color, df, true, false, std::move(name));
}
std::shared_ptr<CGuiWidget> CGuiWidget::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) {
CGuiWidgetParms parms = ReadWidgetHeader(frame, in);
std::shared_ptr<CGuiWidget> ret = std::make_shared<CGuiWidget>(parms);
ret->ParseBaseInfo(frame, in, parms);
return ret;
}
void CGuiWidget::Initialize() {}
void CGuiWidget::ParseBaseInfo(CGuiFrame* frame, CInputStream& in, const CGuiWidgetParms& parms) {
CGuiWidget* parent = frame->FindWidget(parms.x8_parentId);
bool isWorker = in.ReadBool();
if (isWorker)
xb4_workerId = in.ReadInt16();
zeus::CVector3f trans = in.Get<zeus::CVector3f>();
zeus::CMatrix3f orient = in.Get<zeus::CMatrix3f>();
x74_transform = zeus::CTransform(orient, trans);
m_initTransform = x74_transform;
ReapplyXform();
in.Get<zeus::CVector3f>(); // Unused
in.ReadLong();
in.ReadShort();
if (isWorker) {
if (!parent->AddWorkerWidget(this)) {
Log.report(logvisor::Warning,
FMT_STRING("Warning: Discarding useless worker id. Parent is not a compound widget."));
xb4_workerId = -1;
}
}
parent->AddChildWidget(this, false, true);
m_initLocalXF = x4_localXF;
}
void CGuiWidget::Reset(ETraversalMode mode) {
xa4_color = m_initColor;
xa8_color2 = m_initColor;
x74_transform = m_initTransform;
ReapplyXform();
x4_localXF = m_initLocalXF;
RecalculateTransforms();
switch (mode) {
case ETraversalMode::Children: {
CGuiWidget* child = static_cast<CGuiWidget*>(GetChildObject());
if (child)
child->Reset(ETraversalMode::ChildrenAndSiblings);
break;
}
case ETraversalMode::ChildrenAndSiblings: {
CGuiWidget* child = static_cast<CGuiWidget*>(GetChildObject());
if (child)
child->Reset(ETraversalMode::ChildrenAndSiblings);
CGuiWidget* nextSib = static_cast<CGuiWidget*>(GetNextSibling());
if (nextSib)
nextSib->Reset(ETraversalMode::ChildrenAndSiblings);
break;
}
default:
break;
}
}
void CGuiWidget::Update(float dt) {
CGuiWidget* ch = static_cast<CGuiWidget*>(GetChildObject());
if (ch)
ch->Update(dt);
CGuiWidget* sib = static_cast<CGuiWidget*>(GetNextSibling());
if (sib)
sib->Update(dt);
}
void CGuiWidget::Draw(const CGuiWidgetDrawParms& parms) {}
void CGuiWidget::ProcessUserInput(const CFinalInput& input) {}
void CGuiWidget::Touch() {}
bool CGuiWidget::GetIsVisible() const { return xb6_25_isVisible; }
bool CGuiWidget::GetIsActive() const { return xb6_26_isActive; }
bool CGuiWidget::GetMouseActive() const { return m_mouseActive; }
void CGuiWidget::InitializeRGBAFactor() {
CGuiWidget* child = static_cast<CGuiWidget*>(GetChildObject());
if (child)
child->InitializeRGBAFactor();
CGuiWidget* nextSib = static_cast<CGuiWidget*>(GetNextSibling());
if (nextSib)
nextSib->InitializeRGBAFactor();
}
bool CGuiWidget::GetIsFinishedLoadingWidgetSpecific() { return true; }
void CGuiWidget::SetTransform(const zeus::CTransform& xf) {
x74_transform = xf;
ReapplyXform();
}
void CGuiWidget::SetIdlePosition(const zeus::CVector3f& pos, bool reapply) {
x74_transform.origin = pos;
if (reapply)
ReapplyXform();
}
void CGuiWidget::ReapplyXform() {
RotateReset();
SetLocalPosition(zeus::skZero3f);
MultiplyO2P(x74_transform);
}
void CGuiWidget::AddChildWidget(CGuiWidget* widget, bool makeWorldLocal, bool atEnd) {
AddChildObject(widget, makeWorldLocal, atEnd);
}
bool CGuiWidget::AddWorkerWidget(CGuiWidget* worker) { return false; }
void CGuiWidget::SetVisibility(bool visible, ETraversalMode mode) {
switch (mode) {
case ETraversalMode::Children: {
auto* child = static_cast<CGuiWidget*>(GetChildObject());
if (child) {
child->SetVisibility(visible, ETraversalMode::ChildrenAndSiblings);
}
break;
}
case ETraversalMode::ChildrenAndSiblings: {
auto* child = static_cast<CGuiWidget*>(GetChildObject());
if (child) {
child->SetVisibility(visible, ETraversalMode::ChildrenAndSiblings);
}
auto* nextSib = static_cast<CGuiWidget*>(GetNextSibling());
if (nextSib) {
nextSib->SetVisibility(visible, ETraversalMode::ChildrenAndSiblings);
}
break;
}
default:
break;
}
SetIsVisible(visible);
}
void CGuiWidget::RecalcWidgetColor(ETraversalMode mode) {
CGuiWidget* parent = static_cast<CGuiWidget*>(GetParent());
if (parent)
xa8_color2 = xa4_color * parent->xa8_color2;
else
xa8_color2 = xa4_color;
switch (mode) {
case ETraversalMode::ChildrenAndSiblings: {
CGuiWidget* nextSib = static_cast<CGuiWidget*>(GetNextSibling());
if (nextSib)
nextSib->RecalcWidgetColor(ETraversalMode::ChildrenAndSiblings);
[[fallthrough]];
}
case ETraversalMode::Children: {
CGuiWidget* child = static_cast<CGuiWidget*>(GetChildObject());
if (child)
child->RecalcWidgetColor(ETraversalMode::ChildrenAndSiblings);
break;
}
default:
break;
}
}
CGuiWidget* CGuiWidget::FindWidget(s16 id) {
if (x70_selfId == id)
return this;
CGuiWidget* child = static_cast<CGuiWidget*>(GetChildObject());
if (child) {
CGuiWidget* found = child->FindWidget(id);
if (found)
return found;
}
CGuiWidget* nextSib = static_cast<CGuiWidget*>(GetNextSibling());
if (nextSib) {
CGuiWidget* found = nextSib->FindWidget(id);
if (found)
return found;
}
return nullptr;
}
bool CGuiWidget::GetIsFinishedLoading() { return GetIsFinishedLoadingWidgetSpecific(); }
void CGuiWidget::DispatchInitialize() {
Initialize();
CGuiWidget* ch = static_cast<CGuiWidget*>(GetChildObject());
if (ch)
ch->DispatchInitialize();
CGuiWidget* sib = static_cast<CGuiWidget*>(GetNextSibling());
if (sib)
sib->DispatchInitialize();
}
void CGuiWidget::SetColor(const zeus::CColor& color) {
xa4_color = color;
RecalcWidgetColor(ETraversalMode::Children);
}
void CGuiWidget::OnActiveChange() {}
void CGuiWidget::OnVisibleChange() {}
void CGuiWidget::SetIsVisible(bool visible) {
xb6_25_isVisible = visible;
OnVisibleChange();
}
void CGuiWidget::SetIsActive(bool active) {
if (active == xb6_26_isActive) {
return;
}
xb6_26_isActive = active;
OnActiveChange();
}
} // namespace metaforce