#include "Runtime/GuiSys/CGuiTextPane.hpp" #include #include "Runtime/Graphics/CGraphics.hpp" #include "Runtime/Graphics/CGraphicsPalette.hpp" #include "Runtime/GuiSys/CFontImageDef.hpp" #include "Runtime/GuiSys/CGuiFrame.hpp" #include "Runtime/GuiSys/CGuiSys.hpp" #include "Runtime/GuiSys/CGuiWidgetDrawParms.hpp" namespace metaforce { namespace { constexpr std::array NormalPoints{{ {0.f, 0.f, -1.f}, {1.f, 0.f, -1.f}, {1.f, 0.f, 0.f}, {0.f, 0.f, 0.f}, }}; bool testProjectedLine(const zeus::CVector2f& a, const zeus::CVector2f& b, const zeus::CVector2f& point) { const zeus::CVector2f normal = (b - a).perpendicularVector().normalized(); return point.dot(normal) >= a.dot(normal); } } // Anonymous namespace bool CGuiTextPane::sDrawPaneRects = false; CGuiTextPane::CGuiTextPane(const CGuiWidgetParms& parms, CSimplePool* sp, const zeus::CVector2f& dim, const zeus::CVector3f& vec, CAssetId fontId, const CGuiTextProperties& props, const zeus::CColor& fontCol, const zeus::CColor& outlineCol, s32 extentX, s32 extentY, CAssetId jpFontId, s32 jpExtentX, s32 jpExtentY) : CGuiPane(parms, dim, vec) , xd4_textSupport(fontId, props, fontCol, outlineCol, zeus::skWhite, extentX, extentY, sp, xac_drawFlags) {} void CGuiTextPane::Update(float dt) { CGuiWidget::Update(dt); xd4_textSupport.Update(dt); } bool CGuiTextPane::GetIsFinishedLoadingWidgetSpecific() { return xd4_textSupport.GetIsTextSupportFinishedLoading(); } void CGuiTextPane::SetDimensions(const zeus::CVector2f& dim, bool initVBO) { CGuiPane::SetDimensions(dim, initVBO); if (initVBO) InitializeBuffers(); } void CGuiTextPane::ScaleDimensions(const zeus::CVector3f& scale) {} void CGuiTextPane::Draw(const CGuiWidgetDrawParms& parms) { if (sDrawPaneRects) { CGuiPane::Draw({0.2f * parms.x0_alphaMod, parms.x4_cameraOffset}); } if (!GetIsVisible()) { return; } SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CGuiTextPane::Draw {}"), m_name).c_str(), zeus::skCyan); zeus::CVector2f dims = GetDimensions(); if (xd4_textSupport.x34_extentX != 0) { dims.x() /= float(xd4_textSupport.x34_extentX); } else { dims.x() = 0.f; } if (xd4_textSupport.x38_extentY != 0) { dims.y() /= float(xd4_textSupport.x38_extentY); } else { dims.y() = 0.f; } const zeus::CTransform local = zeus::CTransform::Translate(xc0_verts.front() + xc8_scaleCenter) * zeus::CTransform::Scale(dims.x(), 1.f, dims.y()); CGraphics::SetModelMatrix(x34_worldXF * local); zeus::CColor geomCol = xa8_color2; geomCol.a() *= parms.x0_alphaMod; xd4_textSupport.SetGeometryColor(geomCol); CGraphics::SetDepthWriteMode(xb6_31_depthTest, ERglEnum::LEqual, xb7_24_depthWrite); switch (xac_drawFlags) { case EGuiModelDrawFlags::Shadeless: case EGuiModelDrawFlags::Opaque: CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::Zero, ERglLogicOp::Clear); xd4_textSupport.Render(); break; case EGuiModelDrawFlags::Alpha: CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear); xd4_textSupport.Render(); break; case EGuiModelDrawFlags::Additive: CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear); xd4_textSupport.Render(); break; case EGuiModelDrawFlags::AlphaAdditiveOverdraw: CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear); xd4_textSupport.Render(); xd4_textSupport.SetGeometryColor(geomCol * zeus::CColor(geomCol.a(), 1.f)); CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear); xd4_textSupport.Render(); break; } } bool CGuiTextPane::TestCursorHit(const zeus::CMatrix4f& vp, const zeus::CVector2f& point) const { const zeus::CVector2f dims = GetDimensions(); const zeus::CTransform local = zeus::CTransform::Translate(xc0_verts.front() + xc8_scaleCenter) * zeus::CTransform::Scale(dims.x(), 1.f, dims.y()); const zeus::CMatrix4f mvp = vp * (x34_worldXF * local).toMatrix4f(); std::array projPoints; for (size_t i = 0; i < projPoints.size(); ++i) { projPoints[i] = mvp.multiplyOneOverW(NormalPoints[i]).toVec2f(); } size_t j; for (j = 0; j < 3; ++j) { if (!testProjectedLine(projPoints[j], projPoints[j + 1], point)) { break; } } return j == 3 && testProjectedLine(projPoints[3], projPoints[0], point); } std::shared_ptr CGuiTextPane::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp, u32 version) { const CGuiWidgetParms parms = ReadWidgetHeader(frame, in); const zeus::CVector2f dim = in.Get(); const zeus::CVector3f vec = in.Get(); const CAssetId fontId = in.Get(); const bool wordWrap = in.ReadBool(); const bool horizontal = in.ReadBool(); const auto justification = EJustification(in.ReadLong()); const auto vJustification = EVerticalJustification(in.ReadLong()); const CGuiTextProperties props(wordWrap, horizontal, justification, vJustification); const zeus::CColor fontCol = in.Get(); const zeus::CColor outlineCol = in.Get(); const int extentX = static_cast(in.ReadFloat()); const int extentY = static_cast(in.ReadFloat()); int jpExtentX = extentX; int jpExtentY = extentY; CAssetId jpFontId = fontId; if (version != 0) { jpFontId = in.Get(); jpExtentX = in.ReadLong(); jpExtentY = in.ReadLong(); } auto ret = std::make_shared(parms, sp, dim, vec, fontId, props, fontCol, outlineCol, extentX, extentY, jpFontId, jpExtentY, jpExtentY); ret->ParseBaseInfo(frame, in, parms); ret->InitializeBuffers(); ret->TextSupport().SetText(u""); return ret; } } // namespace metaforce