diff --git a/DataSpec/DNAMP1/FRME.hpp b/DataSpec/DNAMP1/FRME.hpp index 7b32d0358..140b94457 100644 --- a/DataSpec/DNAMP1/FRME.hpp +++ b/DataSpec/DNAMP1/FRME.hpp @@ -28,7 +28,7 @@ struct FRME : BigDNA DECL_DNA String<-1> name; String<-1> parent; - Value unk1; + Value useAnimController; Value defaultVisible; Value defaultActive; Value unk4; @@ -183,11 +183,11 @@ struct FRME : BigDNA struct TXPNInfo : IWidgetInfo { - enum class Justification + enum class Justification : atUint32 { }; - enum class VerticalJustification + enum class VerticalJustification : atUint32 { }; diff --git a/Runtime/Graphics/CGraphics.cpp b/Runtime/Graphics/CGraphics.cpp index a12a444a8..25d105821 100644 --- a/Runtime/Graphics/CGraphics.cpp +++ b/Runtime/Graphics/CGraphics.cpp @@ -126,6 +126,30 @@ void CGraphics::SetModelMatrix(const zeus::CTransform& xf) SetViewMatrix(); } +zeus::CMatrix4f CGraphics::CalculatePerspectiveMatrix(float fovy, float aspect, + float near, float far) +{ + CProjectionState st; + float tfov = std::tan(zeus::degToRad(fovy * 0.5f)); + st.x14_near = near; + st.x18_far = far; + st.xc_top = near * tfov; + st.x10_bottom = -st.xc_top; + st.x8_right = aspect * near * tfov; + st.x4_left = -st.x8_right; + + float rml = st.x8_right - st.x4_left; + float rpl = st.x8_right + st.x4_left; + float tmb = st.xc_top - st.x10_bottom; + float tpb = st.xc_top + st.x10_bottom; + float fmn = st.x18_far - st.x14_near; + float fpn = st.x18_far + st.x14_near; + return zeus::CMatrix4f(2.f * st.x14_near / rml, 0.f, rpl / rml, 0.f, + 0.f, 2.f * st.x14_near / tmb, tpb / tmb, 0.f, + 0.f, 0.f, -fpn / fmn, -2.f * st.x18_far * st.x14_near / fmn, + 0.f, 0.f, -1.f, 0.f); +} + zeus::CMatrix4f CGraphics::GetPerspectiveProjectionMatrix() { float rml = g_Proj.x8_right - g_Proj.x4_left; @@ -163,6 +187,23 @@ void CGraphics::SetPerspective(float fovy, float aspect, float near, float far) g_Proj.x10_bottom = -g_Proj.xc_top; g_Proj.x8_right = aspect * near * tfov; g_Proj.x4_left = -g_Proj.x8_right; + + FlushProjection(); +} + +void CGraphics::SetOrtho(float left, float right, + float top, float bottom, + float znear, float zfar) +{ + g_Proj.x0_persp = false; + g_Proj.x4_left = left; + g_Proj.x8_right = right; + g_Proj.xc_top = top; + g_Proj.x10_bottom = bottom; + g_Proj.x14_near = znear; + g_Proj.x18_far = zfar; + + FlushProjection(); } void CGraphics::FlushProjection() diff --git a/Runtime/Graphics/CGraphics.hpp b/Runtime/Graphics/CGraphics.hpp index 2291a31c3..624a8fd6c 100644 --- a/Runtime/Graphics/CGraphics.hpp +++ b/Runtime/Graphics/CGraphics.hpp @@ -193,10 +193,15 @@ public: static void SetViewPointMatrix(const zeus::CTransform& xf); static void SetViewMatrix(); static void SetModelMatrix(const zeus::CTransform& xf); + static zeus::CMatrix4f CalculatePerspectiveMatrix(float fovy, float aspect, + float near, float far); static zeus::CMatrix4f GetPerspectiveProjectionMatrix(); static const CProjectionState& GetProjectionState(); static void SetProjectionState(const CProjectionState&); static void SetPerspective(float fovy, float aspect, float near, float far); + static void SetOrtho(float left, float right, + float top, float bottom, + float znear, float zfar); static void FlushProjection(); static zeus::CVector2i ProjectPoint(const zeus::CVector3f& point); static SClipScreenRect ClipScreenRectFromMS(const zeus::CVector3f& p1, const zeus::CVector3f& p2); diff --git a/Runtime/GuiSys/CGuiCamera.cpp b/Runtime/GuiSys/CGuiCamera.cpp index e87c32a70..3086256be 100644 --- a/Runtime/GuiSys/CGuiCamera.cpp +++ b/Runtime/GuiSys/CGuiCamera.cpp @@ -1,6 +1,7 @@ #include "CGuiCamera.hpp" #include "CGuiFrame.hpp" #include "CGuiAnimController.hpp" +#include "Graphics/CGraphics.hpp" namespace urde { @@ -9,15 +10,39 @@ CGuiCamera::CGuiCamera(const CGuiWidgetParms& parms, float left, float right, float top, float bottom, float znear, float zfar) -: CGuiWidget(parms) -{ -} +: CGuiWidget(parms), + xfc_left(left), x100_right(right), + x104_top(top), x108_bottom(bottom), + x10c_znear(znear), x110_zfar(zfar) +{} CGuiCamera::CGuiCamera(const CGuiWidgetParms& parms, float fov, float aspect, float znear, float zfar) -: CGuiWidget(parms) +: CGuiWidget(parms), + xfc_fov(fov), x100_aspect(aspect), + x104_znear(znear), x108_zfar(zfar) +{} + +zeus::CVector3f CGuiCamera::ConvertToScreenSpace(const zeus::CVector3f& vec) const { + zeus::CVector3f local = RotateTranslateW2O(vec); + if (local.isZero()) + return {-1.f, -1.f, 1.f}; + + zeus::CMatrix4f mat = CGraphics::CalculatePerspectiveMatrix(xfc_fov, x100_aspect, + x104_znear, x108_zfar); + return mat.multiplyOneOverW(local); +} + +void CGuiCamera::Draw(const CGuiWidgetDrawParms& parms) const +{ + if (xf8_proj == Projection::Perspective) + CGraphics::SetPerspective(xfc_fov, x100_aspect, x104_znear, x108_zfar); + else + CGraphics::SetOrtho(xfc_left, x100_right, x104_top, x108_bottom, x10c_znear, x110_zfar); + CGraphics::SetViewPointMatrix(x34_worldXF); + CGuiWidget::Draw(parms); } CGuiCamera* CGuiCamera::Create(CGuiFrame* frame, CInputStream& in, bool flag) diff --git a/Runtime/GuiSys/CGuiCamera.hpp b/Runtime/GuiSys/CGuiCamera.hpp index fcbcccb0d..8b64d41d3 100644 --- a/Runtime/GuiSys/CGuiCamera.hpp +++ b/Runtime/GuiSys/CGuiCamera.hpp @@ -16,10 +16,34 @@ public: }; private: Projection xf8_proj; + union + { + struct + { + float xfc_fov; + float x100_aspect; + float x104_znear; + float x108_zfar; + }; + struct + { + float xfc_left; + float x100_right; + float x104_top; + float x108_bottom; + float x10c_znear; + float x110_zfar; + }; + }; public: - CGuiCamera(const CGuiWidgetParms& parms, float, float, float, float, float, float); + CGuiCamera(const CGuiWidgetParms& parms, float left, float right, + float top, float bottom, + float znear, float zfar); CGuiCamera(const CGuiWidgetParms& parms, float fov, float aspect, float znear, float zfar); static CGuiCamera* Create(CGuiFrame* frame, CInputStream& in, bool flag); + + zeus::CVector3f ConvertToScreenSpace(const zeus::CVector3f& vec) const; + void Draw(const CGuiWidgetDrawParms& parms) const; }; } diff --git a/Runtime/GuiSys/CGuiCompoundWidget.cpp b/Runtime/GuiSys/CGuiCompoundWidget.cpp index e69de29bb..926d76052 100644 --- a/Runtime/GuiSys/CGuiCompoundWidget.cpp +++ b/Runtime/GuiSys/CGuiCompoundWidget.cpp @@ -0,0 +1,69 @@ +#include "CGuiCompoundWidget.hpp" +#include "CGuiAnimController.hpp" +#include "CGuiLogicalEventTrigger.hpp" + +namespace urde +{ + +CGuiCompoundWidget::CGuiCompoundWidget(const CGuiWidgetParms& parms) +: CGuiWidget(parms) +{ +} + +void CGuiCompoundWidget::OnInvisible() +{ + CGuiWidget* child = static_cast(GetChildObject()); + while (child) + { + child->SetIsVisible(false); + child = static_cast(child->GetNextSibling()); + } + CGuiWidget::OnInvisible(); +} + +void CGuiCompoundWidget::OnVisible() +{ + CGuiWidget* child = static_cast(GetChildObject()); + while (child) + { + child->SetIsVisible(true); + child = static_cast(child->GetNextSibling()); + } + CGuiWidget::OnVisible(); +} + +void CGuiCompoundWidget::OnDeActivate() +{ + CGuiWidget* child = static_cast(GetChildObject()); + while (child) + { + child->SetIsActive(false, false); + child = static_cast(child->GetNextSibling()); + } + CGuiWidget::OnDeActivate(); +} + +void CGuiCompoundWidget::OnActivate(bool flag) +{ + CGuiWidget* child = static_cast(GetChildObject()); + while (child) + { + child->SetIsActive(true, flag); + child = static_cast(child->GetNextSibling()); + } + CGuiWidget::OnDeActivate(); +} + +CGuiWidget* CGuiCompoundWidget::GetWorkerWidget(int id) +{ + CGuiWidget* child = static_cast(GetChildObject()); + while (child) + { + if (child->GetWorkerId() == id) + return child; + child = static_cast(child->GetNextSibling()); + } + return nullptr; +} + +} diff --git a/Runtime/GuiSys/CGuiCompoundWidget.hpp b/Runtime/GuiSys/CGuiCompoundWidget.hpp index 52069435e..96e816549 100644 --- a/Runtime/GuiSys/CGuiCompoundWidget.hpp +++ b/Runtime/GuiSys/CGuiCompoundWidget.hpp @@ -8,6 +8,15 @@ namespace urde class CGuiCompoundWidget : public CGuiWidget { +public: + CGuiCompoundWidget(const CGuiWidgetParms& parms); + virtual FourCC GetWidgetTypeID() const {return FourCC(-1);} + + void OnInvisible(); + void OnVisible(); + void OnDeActivate(); + void OnActivate(bool); + virtual CGuiWidget* GetWorkerWidget(int id); }; } diff --git a/Runtime/GuiSys/CGuiGroup.cpp b/Runtime/GuiSys/CGuiGroup.cpp index 74e4a822e..b85ec7545 100644 --- a/Runtime/GuiSys/CGuiGroup.cpp +++ b/Runtime/GuiSys/CGuiGroup.cpp @@ -1,4 +1,7 @@ #include "CGuiGroup.hpp" +#include "CGuiAnimController.hpp" +#include "CGuiLogicalEventTrigger.hpp" +#include "CGuiControllerInfo.hpp" namespace urde { @@ -7,4 +10,92 @@ void CGuiGroup::LoadWidgetFnMap() { } +CGuiGroup::CGuiGroup(const CGuiWidgetParms& parms, int defaultWorker, bool b) +: CGuiCompoundWidget(parms), xfc_selectedWorker(defaultWorker), x100_b(b) +{ +} + +void CGuiGroup::SelectWorkerWidget(int workerId, bool setActive, bool setVisible) +{ + CGuiWidget* child = static_cast(GetChildObject()); + while (child) + { + if (child->GetWorkerId() == workerId) + { + CGuiWidget* sel = GetSelectedWidget(); + if (setActive) + { + sel->SetIsActive(false, false); + child->SetIsActive(true, false); + } + if (setVisible) + { + sel->SetVisibility(false, ETraversalMode::Single); + child->SetVisibility(true, ETraversalMode::Single); + } + break; + } + child = static_cast(child->GetNextSibling()); + } +} + +CGuiWidget* CGuiGroup::GetSelectedWidget() +{ + return GetWorkerWidget(xfc_selectedWorker); +} + +bool CGuiGroup::AddWorkerWidget(CGuiWidget* worker) +{ + ++xf8_workerCount; + return true; +} + +void CGuiGroup::OnDeActivate() +{ + CGuiWidget* sel = GetSelectedWidget(); + if (sel) + sel->SetIsActive(false, true); +} + +void CGuiGroup::OnActivate(bool flag) +{ + CGuiWidget* sel = GetSelectedWidget(); + if (sel) + sel->SetIsActive(true, flag); +} + +bool CGuiGroup::DoUnregisterEventHandler() +{ + CGuiWidget::DoUnregisterEventHandler(); + GetSelectedWidget()->UnregisterEventHandler(ETraversalMode::Children); + return true; +} + +bool CGuiGroup::DoRegisterEventHandler() +{ + CGuiWidget::DoRegisterEventHandler(); + CGuiWidget* sel = GetSelectedWidget(); + if (GetIsActive() && sel) + { + CGuiFuncParm a((intptr_t(sel->GetSelfId()))); + CGuiFuncParm b((intptr_t(3))); + CGuiFunctionDef def(0, false, a, b); + CGuiControllerInfo cInfo; + MAF_SendMessage(&def, &cInfo); + } + if (sel) + sel->RegisterEventHandler(ETraversalMode::Children); + return true; +} + +CGuiGroup* CGuiGroup::Create(CGuiFrame* frame, CInputStream& in, bool flag) +{ + CGuiWidgetParms parms = ReadWidgetHeader(frame, in, flag); + s16 defaultWorker = in.readInt16Big(); + bool b = in.readBool(); + CGuiGroup* ret = new CGuiGroup(parms, defaultWorker, b); + ret->ParseBaseInfo(frame, in, parms); + return ret; +} + } diff --git a/Runtime/GuiSys/CGuiGroup.hpp b/Runtime/GuiSys/CGuiGroup.hpp index 2cf4d4307..82a904fdf 100644 --- a/Runtime/GuiSys/CGuiGroup.hpp +++ b/Runtime/GuiSys/CGuiGroup.hpp @@ -8,7 +8,22 @@ namespace urde class CGuiGroup : public CGuiCompoundWidget { + u32 xf8_workerCount = 0; + int xfc_selectedWorker; + bool x100_b; public: + CGuiGroup(const CGuiWidgetParms& parms, int defaultWorker, bool b); + virtual FourCC GetWidgetTypeID() const {return FOURCC('GRUP');} + + void SelectWorkerWidget(int workerId, bool setActive, bool setVisible); + CGuiWidget* GetSelectedWidget(); + bool AddWorkerWidget(CGuiWidget* worker); + void OnDeActivate(); + void OnActivate(bool flag); + bool DoUnregisterEventHandler(); + bool DoRegisterEventHandler(); + + static CGuiGroup* Create(CGuiFrame* frame, CInputStream& in, bool flag); static void LoadWidgetFnMap(); }; diff --git a/Runtime/GuiSys/CGuiHeadWidget.hpp b/Runtime/GuiSys/CGuiHeadWidget.hpp index 88f6df555..e8d0e7dea 100644 --- a/Runtime/GuiSys/CGuiHeadWidget.hpp +++ b/Runtime/GuiSys/CGuiHeadWidget.hpp @@ -9,7 +9,7 @@ namespace urde class CGuiHeadWidget : public CGuiWidget { public: - FourCC GetWidgetTypeID() const {return hecl::FOURCC('HWIG');} + FourCC GetWidgetTypeID() const {return FOURCC('HWIG');} CGuiHeadWidget(const CGuiWidgetParms& parms); static CGuiHeadWidget* Create(CGuiFrame* frame, CInputStream& in, bool); }; diff --git a/Runtime/GuiSys/CGuiObject.hpp b/Runtime/GuiSys/CGuiObject.hpp index d703e7a88..fb8e89bf7 100644 --- a/Runtime/GuiSys/CGuiObject.hpp +++ b/Runtime/GuiSys/CGuiObject.hpp @@ -14,6 +14,7 @@ struct CGuiControllerInfo; class CGuiObject { +protected: zeus::CTransform x4_localXF; zeus::CTransform x34_worldXF; zeus::CVector3f x64_rotationCenter; diff --git a/Runtime/GuiSys/CGuiWidget.cpp b/Runtime/GuiSys/CGuiWidget.cpp index fd381735e..8720f3f9c 100644 --- a/Runtime/GuiSys/CGuiWidget.cpp +++ b/Runtime/GuiSys/CGuiWidget.cpp @@ -30,7 +30,7 @@ CGuiWidget::CGuiWidget(const CGuiWidgetParms& parms) xf6_27_(true), xf6_28_eventLock(false), xf6_29_pf(parms.xc_f), xf6_30_(false), xf6_31_(true), xf7_24_(false), xf7_25_(true) { - if (parms.x4_a) + if (parms.x4_useAnimController) EnsureHasAnimController(); RecalcWidgetColor(ETraversalMode::Single); } @@ -43,7 +43,7 @@ CGuiWidget::ReadWidgetHeader(CGuiFrame* frame, CInputStream& in, bool flag) std::string parent = in.readString(-1); s16 parentId = frame->GetWidgetIdDB().AddWidget(parent); - bool a = in.readBool(); + bool useAnimController = in.readBool(); bool defaultVis = in.readBool(); bool defaultActive = in.readBool(); bool f = in.readBool(); @@ -51,7 +51,8 @@ CGuiWidget::ReadWidgetHeader(CGuiFrame* frame, CInputStream& in, bool flag) color.readRGBABig(in); EGuiModelDrawFlags df = EGuiModelDrawFlags(in.readUint32Big()); - return CGuiWidget::CGuiWidgetParms(frame, a, selfId, parentId, defaultVis, defaultActive, + return CGuiWidget::CGuiWidgetParms(frame, useAnimController, selfId, + parentId, defaultVis, defaultActive, f, color, df, true, flag); } diff --git a/Runtime/GuiSys/CGuiWidget.hpp b/Runtime/GuiSys/CGuiWidget.hpp index 7a79c823b..8bde1b098 100644 --- a/Runtime/GuiSys/CGuiWidget.hpp +++ b/Runtime/GuiSys/CGuiWidget.hpp @@ -58,7 +58,7 @@ public: struct CGuiWidgetParms { CGuiFrame* x0_frame; - bool x4_a; + bool x4_useAnimController; s16 x6_selfId; s16 x8_parentId; bool xa_defaultVisible; @@ -68,15 +68,15 @@ public: bool xe_h; zeus::CColor x10_color; EGuiModelDrawFlags x14_drawFlags; - CGuiWidgetParms(CGuiFrame* frame, bool a, s16 selfId, s16 parentId, + CGuiWidgetParms(CGuiFrame* frame, bool useAnimController, s16 selfId, s16 parentId, bool defaultVisible, bool defaultActive, bool f, const zeus::CColor& color, EGuiModelDrawFlags drawFlags, bool g, bool h) - : x0_frame(frame), x4_a(a), x6_selfId(selfId), x8_parentId(parentId), xa_defaultVisible(defaultVisible), - xb_defaultActive(defaultActive), xc_f(f), xd_g(g), xe_h(h), x10_color(color), - x14_drawFlags(drawFlags) {} + : x0_frame(frame), x4_useAnimController(useAnimController), x6_selfId(selfId), + x8_parentId(parentId), xa_defaultVisible(defaultVisible), xb_defaultActive(defaultActive), + xc_f(f), xd_g(g), xe_h(h), x10_color(color), x14_drawFlags(drawFlags) {} }; static void LoadWidgetFnMap(); - virtual FourCC GetWidgetTypeID() const {return hecl::FOURCC('BWIG');} + virtual FourCC GetWidgetTypeID() const {return FOURCC('BWIG');} protected: s16 x7c_selfId; s16 x7e_parentId; @@ -136,6 +136,7 @@ public: s16 GetSelfId() const {return x7c_selfId;} s16 GetParentId() const {return x7e_parentId;} + s16 GetWorkerId() const {return xf4_workerId;} const zeus::CTransform& GetTransform() const {return x80_transform;} std::vector>* FindTriggerList(int id); void AddTrigger(std::unique_ptr&& trigger);