mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-05-14 13:11:21 +00:00
Many functions are modifying internals of CBooModel and const-casting is performed in order to work around functions being const when they really shouldn't be. This amends the function signatures in order to allow these functions to exist without const_cast, making code much nicer to read.
199 lines
7.5 KiB
C++
199 lines
7.5 KiB
C++
#include "Runtime/GuiSys/CAuiImagePane.hpp"
|
|
|
|
#include "Runtime/CSimplePool.hpp"
|
|
#include "Runtime/Camera/CCameraFilter.hpp"
|
|
#include "Runtime/Graphics/CTexture.hpp"
|
|
#include "Runtime/GuiSys/CGuiWidgetDrawParms.hpp"
|
|
|
|
namespace urde {
|
|
|
|
CAuiImagePane::CAuiImagePane(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId tex0, CAssetId tex1,
|
|
rstl::reserved_vector<zeus::CVector3f, 4>&& coords,
|
|
rstl::reserved_vector<zeus::CVector2f, 4>&& uvs, bool initTex)
|
|
: CGuiWidget(parms), xc8_tex0(tex0), xcc_tex1(tex1), xe0_coords(std::move(coords)), x114_uvs(std::move(uvs)) {
|
|
if (initTex)
|
|
SetTextureID0(tex0, sp);
|
|
}
|
|
|
|
std::shared_ptr<CGuiWidget> CAuiImagePane::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) {
|
|
CGuiWidgetParms parms = ReadWidgetHeader(frame, in);
|
|
in.readUint32Big();
|
|
in.readUint32Big();
|
|
in.readUint32Big();
|
|
u32 coordCount = in.readUint32Big();
|
|
rstl::reserved_vector<zeus::CVector3f, 4> coords;
|
|
for (u32 i = 0; i < coordCount; ++i)
|
|
coords.push_back(zeus::CVector3f::ReadBig(in));
|
|
u32 uvCount = in.readUint32Big();
|
|
rstl::reserved_vector<zeus::CVector2f, 4> uvs;
|
|
for (u32 i = 0; i < uvCount; ++i)
|
|
uvs.push_back(zeus::CVector2f::ReadBig(in));
|
|
std::shared_ptr<CGuiWidget> ret =
|
|
std::make_shared<CAuiImagePane>(parms, sp, -1, -1, std::move(coords), std::move(uvs), true);
|
|
ret->ParseBaseInfo(frame, in, parms);
|
|
return ret;
|
|
}
|
|
|
|
void CAuiImagePane::Reset(ETraversalMode mode) {
|
|
xc8_tex0 = CAssetId();
|
|
xb8_tex0Tok = TLockedToken<CTexture>();
|
|
CGuiWidget::Reset(mode);
|
|
}
|
|
|
|
void CAuiImagePane::Update(float dt) {
|
|
xd0_uvBias0.x() = std::fmod(xd0_uvBias0.x(), 1.f);
|
|
xd0_uvBias0.y() = std::fmod(xd0_uvBias0.y(), 1.f);
|
|
if (x138_tileSize != zeus::skZero2f && xb8_tex0Tok.IsLoaded()) {
|
|
zeus::CVector2f tmp = zeus::CVector2f(xb8_tex0Tok->GetWidth(), xb8_tex0Tok->GetHeight()) / x138_tileSize;
|
|
x144_frameTimer = std::fmod(x144_frameTimer + dt * x140_interval, std::floor(tmp.x()) * std::floor(tmp.y()));
|
|
}
|
|
|
|
CGuiWidget::Update(dt);
|
|
}
|
|
|
|
CAuiImagePane::Filters::Filters(TLockedToken<CTexture>& tex)
|
|
: m_texId(tex.GetObjectTag()->id)
|
|
, m_darkenerQuad(EFilterType::Blend, tex)
|
|
, m_flashQuad{{{EFilterType::Add, tex}, {EFilterType::Add, tex}}}
|
|
, m_alphaQuad{{{EFilterType::Blend, tex}, {EFilterType::Blend, tex}}}
|
|
, m_addQuad{{{EFilterType::Add, tex}, {EFilterType::Add, tex}}} {}
|
|
|
|
void CAuiImagePane::DoDrawImagePane(const zeus::CColor& color, const CTexture& tex, int frame, float alpha, bool noBlur,
|
|
CTexturedQuadFilterAlpha& quad) const {
|
|
zeus::CColor useColor = color;
|
|
useColor.a() *= alpha;
|
|
|
|
rstl::reserved_vector<zeus::CVector2f, 4> vec;
|
|
const rstl::reserved_vector<zeus::CVector2f, 4>* useUVs;
|
|
if (x138_tileSize != zeus::skZero2f) {
|
|
const zeus::CVector2f res(xb8_tex0Tok->GetWidth(), xb8_tex0Tok->GetHeight());
|
|
const zeus::CVector2f tmp = res / x138_tileSize;
|
|
const zeus::CVector2f tmpRecip = x138_tileSize / res;
|
|
const float x0 = tmpRecip.x() * (frame % int(tmp.x()));
|
|
const float x1 = x0 + tmpRecip.x();
|
|
const float y0 = tmpRecip.y() * (frame % int(tmp.y()));
|
|
const float y1 = y0 + tmpRecip.y();
|
|
vec.push_back(zeus::CVector2f(x0, y0));
|
|
vec.push_back(zeus::CVector2f(x0, y1));
|
|
vec.push_back(zeus::CVector2f(x1, y0));
|
|
vec.push_back(zeus::CVector2f(x1, y1));
|
|
useUVs = &vec;
|
|
} else {
|
|
useUVs = &x114_uvs;
|
|
}
|
|
|
|
const std::array<CTexturedQuadFilter::Vert, 4> verts{{
|
|
{xe0_coords[0], (*useUVs)[0] + xd0_uvBias0},
|
|
{xe0_coords[1], (*useUVs)[1] + xd0_uvBias0},
|
|
{xe0_coords[3], (*useUVs)[3] + xd0_uvBias0},
|
|
{xe0_coords[2], (*useUVs)[2] + xd0_uvBias0},
|
|
}};
|
|
|
|
if (noBlur) {
|
|
quad.drawVerts(useColor, verts.data());
|
|
} else if ((x14c_deResFactor == 0.f && alpha == 1.f) || tex.GetNumMips() == 1) {
|
|
quad.drawVerts(useColor, verts.data(), 0.f);
|
|
} else {
|
|
const float tmp = (1.f - x14c_deResFactor) * alpha;
|
|
const float tmp3 = 1.f - tmp * tmp * tmp;
|
|
const float mip = tmp3 * (tex.GetNumMips() - 1);
|
|
quad.drawVerts(useColor, verts.data(), mip);
|
|
}
|
|
}
|
|
|
|
void CAuiImagePane::Draw(const CGuiWidgetDrawParms& params) {
|
|
CGraphics::SetModelMatrix(x34_worldXF);
|
|
if (!GetIsVisible() || !xb8_tex0Tok.IsLoaded()) {
|
|
return;
|
|
}
|
|
SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CAuiImagePane::Draw {}"), m_name).c_str(), zeus::skCyan);
|
|
GetIsFinishedLoadingWidgetSpecific();
|
|
if (!m_filters || m_filters->m_texId != xb8_tex0Tok.GetObjectTag()->id) {
|
|
m_filters.emplace(xb8_tex0Tok);
|
|
}
|
|
Filters& filters = *m_filters;
|
|
zeus::CColor color = xa8_color2;
|
|
color.a() *= params.x0_alphaMod;
|
|
// SetZUpdate(xac_drawFlags == EGuiModelDrawFlags::Shadeless || xac_drawFlags == EGuiModelDrawFlags::Opaque);
|
|
float blur0 = 1.f;
|
|
float blur1 = 0.f;
|
|
int frame0 = x144_frameTimer;
|
|
int frame1 = 0;
|
|
if (x140_interval < 1.f && x140_interval > 0.f) {
|
|
zeus::CVector2f tmp = zeus::CVector2f(xb8_tex0Tok->GetWidth(), xb8_tex0Tok->GetHeight()) / x138_tileSize;
|
|
frame1 = (frame0 + 1) % int(tmp.x() * tmp.y());
|
|
if (x148_fadeDuration == 0.f)
|
|
blur1 = 1.f;
|
|
else
|
|
blur1 = std::min(std::fmod(x144_frameTimer, 1.f) / x148_fadeDuration, 1.f);
|
|
blur0 = 1.f - blur1;
|
|
}
|
|
|
|
// Alpha blend
|
|
DoDrawImagePane(color * zeus::CColor(0.f, 0.5f), *xb8_tex0Tok, frame0, 1.f, true, filters.m_darkenerQuad);
|
|
|
|
if (x150_flashFactor > 0.f) {
|
|
// Additive blend
|
|
zeus::CColor color2 = xa8_color2;
|
|
color2.a() = x150_flashFactor;
|
|
DoDrawImagePane(color2, *xb8_tex0Tok, frame0, blur0, false, filters.m_flashQuad[0]);
|
|
if (blur1 > 0.f)
|
|
DoDrawImagePane(color2, *xb8_tex0Tok, frame1, blur1, false, filters.m_flashQuad[1]);
|
|
}
|
|
|
|
switch (xac_drawFlags) {
|
|
case EGuiModelDrawFlags::Shadeless:
|
|
case EGuiModelDrawFlags::Opaque:
|
|
// Opaque blend
|
|
DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_alphaQuad[0]);
|
|
if (blur1 > 0.f)
|
|
DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_alphaQuad[1]);
|
|
break;
|
|
case EGuiModelDrawFlags::Alpha:
|
|
// Alpha blend
|
|
DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_alphaQuad[0]);
|
|
if (blur1 > 0.f)
|
|
DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_alphaQuad[1]);
|
|
break;
|
|
case EGuiModelDrawFlags::Additive:
|
|
// Additive blend
|
|
DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_addQuad[0]);
|
|
if (blur1 > 0.f)
|
|
DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_addQuad[1]);
|
|
break;
|
|
case EGuiModelDrawFlags::AlphaAdditiveOverdraw:
|
|
// Alpha blend
|
|
DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_alphaQuad[0]);
|
|
if (blur1 > 0.f)
|
|
DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_alphaQuad[1]);
|
|
// Full additive blend
|
|
DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_addQuad[0]);
|
|
if (blur1 > 0.f)
|
|
DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_addQuad[1]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool CAuiImagePane::GetIsFinishedLoadingWidgetSpecific() { return !xb8_tex0Tok || xb8_tex0Tok.IsLoaded(); }
|
|
|
|
void CAuiImagePane::SetTextureID0(CAssetId tex, CSimplePool* sp) {
|
|
xc8_tex0 = tex;
|
|
if (!sp)
|
|
return;
|
|
if (xc8_tex0.IsValid())
|
|
xb8_tex0Tok = sp->GetObj({FOURCC('TXTR'), xc8_tex0});
|
|
else
|
|
xb8_tex0Tok = TLockedToken<CTexture>();
|
|
}
|
|
|
|
void CAuiImagePane::SetAnimationParms(const zeus::CVector2f& tileSize, float interval, float fadeDuration) {
|
|
x138_tileSize = tileSize;
|
|
x140_interval = interval;
|
|
x144_frameTimer = 0.f;
|
|
x148_fadeDuration = fadeDuration;
|
|
}
|
|
|
|
} // namespace urde
|