mirror of https://github.com/AxioDL/metaforce.git
Initial CTextRenderBuffer rewrite
This commit is contained in:
parent
22dfd3b3f7
commit
0ca2786302
|
@ -91,6 +91,7 @@ public:
|
|||
CToken(IObj* obj);
|
||||
CToken(std::unique_ptr<IObj>&& obj);
|
||||
const SObjectTag* GetObjectTag() const;
|
||||
const CObjectReference* GetObjectReference() const { return x0_objRef; }
|
||||
~CToken();
|
||||
};
|
||||
|
||||
|
|
|
@ -19,8 +19,11 @@
|
|||
namespace metaforce {
|
||||
static logvisor::Module Log("CCubeRenderer");
|
||||
|
||||
/* TODO: This is to fix some areas exceeding the max drawable count, the proper number is 128 drawables per bucket */
|
||||
// using BucketHolderType = rstl::reserved_vector<CDrawable*, 128>;
|
||||
using BucketHolderType = rstl::reserved_vector<CDrawable*, 132>;
|
||||
static rstl::reserved_vector<CDrawable, 512> sDataHolder;
|
||||
static rstl::reserved_vector<rstl::reserved_vector<CDrawable*, 128>, 50> sBucketsHolder;
|
||||
static rstl::reserved_vector<BucketHolderType, 50> sBucketsHolder;
|
||||
static rstl::reserved_vector<CDrawablePlaneObject, 8> sPlaneObjectDataHolder;
|
||||
static rstl::reserved_vector<u16, 8> sPlaneObjectBucketHolder;
|
||||
|
||||
|
@ -29,11 +32,11 @@ class Buckets {
|
|||
|
||||
static inline rstl::reserved_vector<u16, 50> sBucketIndex;
|
||||
static inline rstl::reserved_vector<CDrawable, 512>* sData = nullptr;
|
||||
static inline rstl::reserved_vector<rstl::reserved_vector<CDrawable*, 128>, 50>* sBuckets = nullptr;
|
||||
static inline rstl::reserved_vector<BucketHolderType, 50>* sBuckets = nullptr;
|
||||
static inline rstl::reserved_vector<CDrawablePlaneObject, 8>* sPlaneObjectData = nullptr;
|
||||
static inline rstl::reserved_vector<u16, 8>* sPlaneObjectBucket = nullptr;
|
||||
static constexpr std::array skWorstMinMaxDistance{99999.0f, -99999.0f};
|
||||
static inline std::array sMinMaxDistance{0.0f, 0.0f};
|
||||
static inline std::array sMinMaxDistance{99999.0f, -99999.0f};
|
||||
|
||||
public:
|
||||
static void Clear();
|
||||
|
@ -51,7 +54,7 @@ void Buckets::Clear() {
|
|||
sBucketIndex.clear();
|
||||
sPlaneObjectData->clear();
|
||||
sPlaneObjectBucket->clear();
|
||||
for (rstl::reserved_vector<CDrawable*, 128>& bucket : *sBuckets) {
|
||||
for (BucketHolderType& bucket : *sBuckets) {
|
||||
bucket.clear();
|
||||
}
|
||||
sMinMaxDistance = skWorstMinMaxDistance;
|
||||
|
@ -60,12 +63,14 @@ void Buckets::Clear() {
|
|||
void Buckets::Sort() {
|
||||
float delta = std::max(1.f, sMinMaxDistance[1] - sMinMaxDistance[0]);
|
||||
float pitch = 49.f / delta;
|
||||
for (auto it = sPlaneObjectData->begin(); it != sPlaneObjectData->end(); ++it)
|
||||
if (sPlaneObjectBucket->size() != sPlaneObjectBucket->capacity())
|
||||
for (auto it = sPlaneObjectData->begin(); it != sPlaneObjectData->end(); ++it) {
|
||||
if (sPlaneObjectBucket->size() != sPlaneObjectBucket->capacity()) {
|
||||
sPlaneObjectBucket->push_back(s16(it - sPlaneObjectData->begin()));
|
||||
}
|
||||
}
|
||||
|
||||
u32 precision = 50;
|
||||
if (sPlaneObjectBucket->size()) {
|
||||
if (!sPlaneObjectBucket->empty()) {
|
||||
std::sort(sPlaneObjectBucket->begin(), sPlaneObjectBucket->end(),
|
||||
[](u16 a, u16 b) { return (*sPlaneObjectData)[a].GetDistance() < (*sPlaneObjectData)[b].GetDistance(); });
|
||||
precision = 50 / u32(sPlaneObjectBucket->size() + 1);
|
||||
|
@ -80,7 +85,7 @@ void Buckets::Sort() {
|
|||
}
|
||||
|
||||
for (CDrawable& drawable : *sData) {
|
||||
s32 slot;
|
||||
s32 slot = -1;
|
||||
float relDist = drawable.GetDistance() - sMinMaxDistance[0];
|
||||
if (sPlaneObjectBucket->empty()) {
|
||||
slot = zeus::clamp(1, s32(relDist * pitch), 49);
|
||||
|
@ -88,7 +93,8 @@ void Buckets::Sort() {
|
|||
slot = zeus::clamp(0, s32(relDist * pitch), s32(precision) - 2);
|
||||
for (u16 idx : *sPlaneObjectBucket) {
|
||||
CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[idx];
|
||||
bool partial, full;
|
||||
bool partial = false;
|
||||
bool full = false;
|
||||
if (planeObj.x3c_25_zOnly) {
|
||||
partial = drawable.GetBounds().max.z() > planeObj.GetPlane().d();
|
||||
full = drawable.GetBounds().min.z() > planeObj.GetPlane().d();
|
||||
|
@ -98,22 +104,26 @@ void Buckets::Sort() {
|
|||
full = planeObj.GetPlane().pointToPlaneDist(
|
||||
drawable.GetBounds().furthestPointAlongVector(planeObj.GetPlane().normal())) > 0.f;
|
||||
}
|
||||
bool cont;
|
||||
if (drawable.GetType() == EDrawableType::Particle)
|
||||
bool cont = false;
|
||||
if (drawable.GetType() == EDrawableType::Particle) {
|
||||
cont = planeObj.x3c_24_invertTest ? !partial : full;
|
||||
else
|
||||
} else {
|
||||
cont = planeObj.x3c_24_invertTest ? (!partial || !full) : (partial || full);
|
||||
if (!cont)
|
||||
}
|
||||
if (!cont) {
|
||||
break;
|
||||
slot += precision;
|
||||
}
|
||||
slot += s32(precision);
|
||||
}
|
||||
}
|
||||
|
||||
if (slot == -1)
|
||||
if (slot == -1) {
|
||||
slot = 49;
|
||||
rstl::reserved_vector<CDrawable*, 128>& bucket = (*sBuckets)[slot];
|
||||
if (bucket.size() < bucket.capacity())
|
||||
}
|
||||
BucketHolderType& bucket = (*sBuckets)[slot];
|
||||
if (bucket.size() < bucket.capacity()) {
|
||||
bucket.push_back(&drawable);
|
||||
}
|
||||
// else
|
||||
// Log.report(logvisor::Fatal, FMT_STRING("Full bucket!!!"));
|
||||
}
|
||||
|
@ -122,7 +132,7 @@ void Buckets::Sort() {
|
|||
for (auto it = sBuckets->rbegin(); it != sBuckets->rend(); ++it) {
|
||||
--bucketIdx;
|
||||
sBucketIndex.push_back(bucketIdx);
|
||||
rstl::reserved_vector<CDrawable*, 128>& bucket = *it;
|
||||
BucketHolderType& bucket = *it;
|
||||
if (bucket.size()) {
|
||||
std::sort(bucket.begin(), bucket.end(), [](CDrawable* a, CDrawable* b) {
|
||||
if (a->GetDistance() == b->GetDistance())
|
||||
|
@ -134,7 +144,7 @@ void Buckets::Sort() {
|
|||
|
||||
for (auto it = sPlaneObjectBucket->rbegin(); it != sPlaneObjectBucket->rend(); ++it) {
|
||||
CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[*it];
|
||||
rstl::reserved_vector<CDrawable*, 128>& bucket = (*sBuckets)[planeObj.x24_targetBucket];
|
||||
BucketHolderType& bucket = (*sBuckets)[planeObj.x24_targetBucket];
|
||||
bucket.push_back(&planeObj);
|
||||
}
|
||||
}
|
||||
|
@ -394,7 +404,8 @@ void CCubeRenderer::DrawUnsortedGeometry(s32 areaIdx, s32 mask, s32 targetMask)
|
|||
void CCubeRenderer::DrawSortedGeometry(s32 areaIdx, s32 mask, s32 targetMask) {
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP(
|
||||
fmt::format(FMT_STRING("CCubeRenderer::DrawSortedGeometry areaIdx={} mask={} targetMask={}"), areaIdx, mask,
|
||||
targetMask).c_str(),
|
||||
targetMask)
|
||||
.c_str(),
|
||||
zeus::skBlue);
|
||||
|
||||
SetupRendererStates(true);
|
||||
|
@ -427,7 +438,8 @@ void CCubeRenderer::DrawStaticGeometry(s32 areaIdx, s32 mask, s32 targetMask) {
|
|||
void CCubeRenderer::DrawAreaGeometry(s32 areaIdx, s32 mask, s32 targetMask) {
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP(
|
||||
fmt::format(FMT_STRING("CCubeRenderer::DrawAreaGeometry areaIdx={} mask={} targetMask={}"), areaIdx, mask,
|
||||
targetMask).c_str(),
|
||||
targetMask)
|
||||
.c_str(),
|
||||
zeus::skBlue);
|
||||
|
||||
x318_30_inAreaDraw = true;
|
||||
|
@ -476,7 +488,7 @@ void CCubeRenderer::RenderBucketItems(const CAreaListItem* item) {
|
|||
CCubeModel* lastModel = nullptr;
|
||||
EDrawableType lastDrawableType = EDrawableType::Invalid;
|
||||
for (u16 idx : Buckets::sBucketIndex) {
|
||||
rstl::reserved_vector<CDrawable*, 128>& bucket = (*Buckets::sBuckets)[idx];
|
||||
BucketHolderType& bucket = (*Buckets::sBuckets)[idx];
|
||||
for (CDrawable* drawable : bucket) {
|
||||
EDrawableType type = drawable->GetType();
|
||||
switch (type) {
|
||||
|
|
|
@ -24,8 +24,6 @@ void CGraphicsPalette::Load() {
|
|||
x4_frameLoaded = sCurrentFrameCount;
|
||||
}
|
||||
|
||||
void CGraphicsPalette::Lock() { x1c_locked = true; }
|
||||
|
||||
void CGraphicsPalette::UnLock() {
|
||||
// DCStoreRange(xc_lut, x8_numEntries << 1);
|
||||
GXInitTlutObj(&x10_tlutObj, xc_entries.get(), static_cast<GXTlutFmt>(x0_fmt), x8_entryCount);
|
||||
|
|
|
@ -28,9 +28,9 @@ public:
|
|||
explicit CGraphicsPalette(EPaletteFormat fmt, int count);
|
||||
explicit CGraphicsPalette(CInputStream& in);
|
||||
|
||||
void Load();
|
||||
void Lock();
|
||||
void Lock() { x1c_locked = true; }
|
||||
void UnLock();
|
||||
void Load();
|
||||
|
||||
[[nodiscard]] u8* GetPaletteData() { return xc_entries.get(); }
|
||||
[[nodiscard]] const u8* GetPaletteData() const { return xc_entries.get(); }
|
||||
|
|
|
@ -68,48 +68,44 @@ const CTextRenderBuffer* CGuiTextSupport::GetCurrentPageRenderBuffer() const {
|
|||
|
||||
float CGuiTextSupport::GetCurrentAnimationOverAge() const {
|
||||
float ret = 0.f;
|
||||
// TODO
|
||||
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
// if (x50_typeEnable) {
|
||||
// if (x40_primStartTimes.size()) {
|
||||
// const auto& lastTime = x40_primStartTimes.back();
|
||||
// ret = std::max(ret, (buf->GetPrimitiveCount() - lastTime.second) / x58_chRate + lastTime.first);
|
||||
// } else {
|
||||
// ret = std::max(ret, buf->GetPrimitiveCount() / x58_chRate);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
if (x50_typeEnable) {
|
||||
if (!x40_primStartTimes.empty()) {
|
||||
const auto& lastTime = x40_primStartTimes.back();
|
||||
ret = std::max(ret, (buf->GetPrimitiveCount() - lastTime.second) / x58_chRate + lastTime.first);
|
||||
} else {
|
||||
ret = std::max(ret, buf->GetPrimitiveCount() / x58_chRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
float CGuiTextSupport::GetNumCharsTotal() const {
|
||||
// TODO
|
||||
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
// if (x50_typeEnable) {
|
||||
// return buf->GetPrimitiveCount();
|
||||
// }
|
||||
// }
|
||||
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
if (x50_typeEnable) {
|
||||
return buf->GetPrimitiveCount();
|
||||
}
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
float CGuiTextSupport::GetNumCharsPrinted() const {
|
||||
// TODO
|
||||
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
// if (x50_typeEnable) {
|
||||
// const float charsPrinted = x3c_curTime * x58_chRate;
|
||||
// return std::min(charsPrinted, float(buf->GetPrimitiveCount()));
|
||||
// }
|
||||
// }
|
||||
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
if (x50_typeEnable) {
|
||||
const float charsPrinted = x3c_curTime * x58_chRate;
|
||||
return std::min(charsPrinted, float(buf->GetPrimitiveCount()));
|
||||
}
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
float CGuiTextSupport::GetTotalAnimationTime() const {
|
||||
// TODO
|
||||
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
// if (x50_typeEnable) {
|
||||
// return buf->GetPrimitiveCount() / x58_chRate;
|
||||
// }
|
||||
// }
|
||||
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
if (x50_typeEnable) {
|
||||
return buf->GetPrimitiveCount() / x58_chRate;
|
||||
}
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
|
@ -121,21 +117,20 @@ void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, f
|
|||
x58_chRate = std::max(chRate, 1.f);
|
||||
if (enable) {
|
||||
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
// TODO
|
||||
// float chStartTime = 0.f;
|
||||
// for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
|
||||
// for (const std::pair<float, int>& p : x40_primStartTimes) {
|
||||
// if (p.second < i)
|
||||
// continue;
|
||||
// if (p.second != i)
|
||||
// break;
|
||||
// chStartTime = p.first;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
float chStartTime = 0.f;
|
||||
for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
|
||||
for (const std::pair<float, int>& p : x40_primStartTimes) {
|
||||
if (p.second < i)
|
||||
continue;
|
||||
if (p.second != i)
|
||||
break;
|
||||
chStartTime = p.first;
|
||||
break;
|
||||
}
|
||||
|
||||
//buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
|
||||
// chStartTime += 1.f / x58_chRate;
|
||||
// }
|
||||
chStartTime += 1.f / x58_chRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,21 +138,20 @@ void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, f
|
|||
void CGuiTextSupport::Update(float dt) {
|
||||
if (x50_typeEnable) {
|
||||
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
// TODO
|
||||
// float chStartTime = 0.f;
|
||||
// for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
|
||||
// for (const std::pair<float, int>& p : x40_primStartTimes) {
|
||||
// if (p.second < i)
|
||||
// continue;
|
||||
// if (p.second != i)
|
||||
// break;
|
||||
// chStartTime = p.first;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
float chStartTime = 0.f;
|
||||
for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
|
||||
for (const std::pair<float, int>& p : x40_primStartTimes) {
|
||||
if (p.second < i)
|
||||
continue;
|
||||
if (p.second != i)
|
||||
break;
|
||||
chStartTime = p.first;
|
||||
break;
|
||||
}
|
||||
|
||||
//buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
|
||||
// chStartTime += 1.f / x58_chRate;
|
||||
// }
|
||||
chStartTime += 1.f / x58_chRate;
|
||||
}
|
||||
}
|
||||
x3c_curTime += dt;
|
||||
}
|
||||
|
@ -190,9 +184,11 @@ void CGuiTextSupport::CheckAndRebuildTextBuffer() {
|
|||
}
|
||||
|
||||
bool CGuiTextSupport::CheckAndRebuildRenderBuffer() {
|
||||
if (x308_multipageFlag || x60_renderBuf)
|
||||
if (!x308_multipageFlag || x2ec_renderBufferPages.size())
|
||||
if (x308_multipageFlag || x60_renderBuf) {
|
||||
if (!x308_multipageFlag || x2ec_renderBufferPages.size()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CheckAndRebuildTextBuffer();
|
||||
x2bc_assets = g_TextExecuteBuf->GetAssets();
|
||||
|
@ -259,8 +255,7 @@ void CGuiTextSupport::SetFontColor(const zeus::CColor& col) {
|
|||
void CGuiTextSupport::AddText(std::u16string_view str) {
|
||||
if (x60_renderBuf) {
|
||||
const float t = GetCurrentAnimationOverAge();
|
||||
// TODO
|
||||
// x40_primStartTimes.emplace_back(std::max(t, x3c_curTime), x60_renderBuf->GetPrimitiveCount());
|
||||
x40_primStartTimes.emplace_back(std::max(t, x3c_curTime), x60_renderBuf->GetPrimitiveCount());
|
||||
}
|
||||
x0_string += str;
|
||||
ClearRenderBuffer();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "Runtime/CSimplePool.hpp"
|
||||
#include "Runtime/Graphics/CGX.hpp"
|
||||
#include "Runtime/Graphics/CTexture.hpp"
|
||||
#include "Runtime/GuiSys/CDrawStringOptions.hpp"
|
||||
#include "Runtime/GuiSys/CTextRenderBuffer.hpp"
|
||||
|
@ -151,17 +152,15 @@ void CRasterFont::DrawString(const CDrawStringOptions& opts, int x, int y, int&
|
|||
if (!x0_initialized)
|
||||
return;
|
||||
|
||||
if (renderBuf) {
|
||||
/* CGraphicsPalette pal = CGraphicsPalette::CGraphcisPalette(2, 4); */
|
||||
/* zeus::CColor color = zeus::CColor(0.f, 0.f, 0.f, 0.f) */
|
||||
/* tmp = color.ToRGB5A3(); */
|
||||
/* tmp2 = opts.x8_.ToRGB5A3(); */
|
||||
/* tmp3 = opts.xc_.ToRGB5A3(); */
|
||||
/* tmp4 = zeus::CColor(0.f, 0.f, 0.f, 0.f); */
|
||||
/* tmp5 = tmp4.ToRGBA5A3(); */
|
||||
/* pal.UnLock(); */
|
||||
/* renderBuf->AddPaletteChange(pal); */
|
||||
renderBuf->AddPaletteChange(opts.x4_colors[0], opts.x4_colors[1]);
|
||||
if (renderBuf != nullptr) {
|
||||
CGraphicsPalette pal(EPaletteFormat::RGB5A3, 4);
|
||||
pal.Lock();
|
||||
*reinterpret_cast<u16*>(pal.GetPaletteData() + 0) = SBIG(zeus::CColor(0.f, 0.f, 0.f, 0.f).toRGB5A3());
|
||||
*reinterpret_cast<u16*>(pal.GetPaletteData() + 2) = SBIG(opts.x4_colors[0].toRGB5A3());
|
||||
*reinterpret_cast<u16*>(pal.GetPaletteData() + 4) = SBIG(opts.x4_colors[1].toRGB5A3());
|
||||
*reinterpret_cast<u16*>(pal.GetPaletteData() + 6) = SBIG(zeus::CColor(0.f, 0.f, 0.f, 0.f).toRGB5A3());
|
||||
pal.UnLock();
|
||||
renderBuf->AddPaletteChange(pal);
|
||||
}
|
||||
|
||||
SinglePassDrawString(opts, x, y, xout, yout, renderBuf, str, len);
|
||||
|
@ -210,6 +209,28 @@ bool CRasterFont::IsFinishedLoading() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
void CRasterFont::SetupRenderState() {
|
||||
static const GX::VtxDescList skDescList[3] = {
|
||||
{GX::VA_POS, GX::DIRECT},
|
||||
{GX::VA_TEX0, GX::DIRECT},
|
||||
{GX::VA_NULL, GX::NONE}
|
||||
};
|
||||
|
||||
x80_texture->Load(GX::TEXMAP0, EClampMode::Clamp);
|
||||
CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A);
|
||||
CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0);
|
||||
CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_ZERO);
|
||||
CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_ZERO);
|
||||
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0);
|
||||
CGX::SetTevDirect(GX::TEVSTAGE0);
|
||||
CGX::SetVtxDescv(skDescList);
|
||||
CGX::SetNumChans(0);
|
||||
CGX::SetNumTexGens(1);
|
||||
CGX::SetNumTevStages(1);
|
||||
CGX::SetNumIndStages(0);
|
||||
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL);
|
||||
CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY);
|
||||
}
|
||||
std::unique_ptr<IObj> FRasterFontFactory([[maybe_unused]] const SObjectTag& tag, CInputStream& in,
|
||||
const CVParamTransfer& vparms, [[maybe_unused]] CObjectReference* selfRef) {
|
||||
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
|
||||
|
|
|
@ -151,6 +151,8 @@ public:
|
|||
CTexture& GetTexture() { return *x80_texture; }
|
||||
|
||||
bool IsFinishedLoading() const;
|
||||
|
||||
void SetupRenderState();
|
||||
};
|
||||
|
||||
std::unique_ptr<IObj> FRasterFontFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
namespace metaforce {
|
||||
|
||||
CTextRenderBuffer CTextExecuteBuffer::BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const {
|
||||
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df);
|
||||
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally);//, df);
|
||||
|
||||
{
|
||||
CFontRenderState rendState;
|
||||
|
@ -35,7 +35,7 @@ CTextRenderBuffer CTextExecuteBuffer::BuildRenderBufferPage(InstList::const_iter
|
|||
InstList::const_iterator pgStart,
|
||||
InstList::const_iterator pgEnd,
|
||||
CGuiWidget::EGuiModelDrawFlags df) const {
|
||||
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df);
|
||||
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally);//, df);
|
||||
|
||||
{
|
||||
CFontRenderState rendState;
|
||||
|
@ -71,7 +71,7 @@ std::list<CTextRenderBuffer> CTextExecuteBuffer::BuildRenderBufferPages(const ze
|
|||
std::list<CTextRenderBuffer> ret;
|
||||
|
||||
for (auto it = x0_instList.begin(); it != x0_instList.end();) {
|
||||
CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally, df);
|
||||
CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally);//, df);
|
||||
|
||||
{
|
||||
CFontRenderState rstate;
|
||||
|
|
|
@ -12,285 +12,29 @@
|
|||
|
||||
namespace metaforce {
|
||||
|
||||
//struct CTextRenderBuffer::BooFontCharacters {
|
||||
// TLockedToken<CRasterFont> m_font;
|
||||
// hecl::VertexBufferPool<CTextSupportShader::CharacterInstance>::Token m_instBuf;
|
||||
// boo::ObjToken<boo::IShaderDataBinding> m_dataBinding;
|
||||
// boo::ObjToken<boo::IShaderDataBinding> m_dataBinding2;
|
||||
// std::vector<CTextSupportShader::CharacterInstance> m_charData;
|
||||
// u32 m_charCount = 0;
|
||||
// bool m_dirty = true;
|
||||
//
|
||||
// BooFontCharacters(const CToken& token) : m_font(token) {}
|
||||
//};
|
||||
//
|
||||
//struct CTextRenderBuffer::BooImage {
|
||||
// CFontImageDef m_imageDef;
|
||||
// hecl::VertexBufferPool<CTextSupportShader::ImageInstance>::Token m_instBuf;
|
||||
// std::vector<boo::ObjToken<boo::IShaderDataBinding>> m_dataBinding;
|
||||
// std::vector<boo::ObjToken<boo::IShaderDataBinding>> m_dataBinding2;
|
||||
// CTextSupportShader::ImageInstance m_imageData;
|
||||
// bool m_dirty = true;
|
||||
//
|
||||
// BooImage(const CFontImageDef& imgDef, const zeus::CVector2i& offset) : m_imageDef(imgDef) {
|
||||
// m_imageData.SetMetrics(imgDef, offset);
|
||||
// }
|
||||
//};
|
||||
//
|
||||
//struct CTextRenderBuffer::BooPrimitiveMark {
|
||||
// Command m_cmd;
|
||||
// u32 m_bindIdx;
|
||||
// u32 m_instIdx;
|
||||
//
|
||||
// void SetOpacity(CTextRenderBuffer& rb, float opacity) {
|
||||
// switch (m_cmd) {
|
||||
// case Command::CharacterRender: {
|
||||
// BooFontCharacters& fc = rb.m_fontCharacters[m_bindIdx];
|
||||
// CTextSupportShader::CharacterInstance& inst = fc.m_charData[m_instIdx];
|
||||
// inst.m_mulColor.a() = opacity;
|
||||
// fc.m_dirty = true;
|
||||
// break;
|
||||
// }
|
||||
// case Command::ImageRender: {
|
||||
// BooImage& img = rb.m_images[m_bindIdx];
|
||||
// img.m_imageData.m_color.a() = opacity;
|
||||
// img.m_dirty = true;
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//};
|
||||
|
||||
CTextRenderBuffer::CTextRenderBuffer(CTextRenderBuffer&&) noexcept = default;
|
||||
|
||||
CTextRenderBuffer::CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df) : x0_mode(mode)/*, m_drawFlags(df)*/ {}
|
||||
CTextRenderBuffer::CTextRenderBuffer(EMode mode) : x0_mode(mode) {}
|
||||
|
||||
CTextRenderBuffer::~CTextRenderBuffer() = default;
|
||||
|
||||
CTextRenderBuffer& CTextRenderBuffer::operator=(CTextRenderBuffer&&) noexcept = default;
|
||||
|
||||
//void CTextRenderBuffer::CommitResources() {
|
||||
// if (m_committed)
|
||||
// return;
|
||||
// m_committed = true;
|
||||
//
|
||||
// /* Ensure font textures are ready outside transaction */
|
||||
// for (BooFontCharacters& chs : m_fontCharacters)
|
||||
// chs.m_font->GetTexture();
|
||||
//
|
||||
// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||
// m_uniBuf = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory);
|
||||
// auto uBufInfo = m_uniBuf.getBufferInfo();
|
||||
// decltype(uBufInfo) uBufInfo2;
|
||||
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
|
||||
// m_uniBuf2 = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory);
|
||||
// uBufInfo2 = m_uniBuf2.getBufferInfo();
|
||||
// }
|
||||
//
|
||||
// for (BooFontCharacters& chs : m_fontCharacters) {
|
||||
// chs.m_instBuf = CTextSupportShader::s_CharInsts.allocateBlock(CGraphics::g_BooFactory, chs.m_charCount);
|
||||
// auto iBufInfo = chs.m_instBuf.getBufferInfo();
|
||||
//
|
||||
// boo::ObjToken<boo::IGraphicsBuffer> uniforms[] = {uBufInfo.first.get()};
|
||||
// boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex};
|
||||
// size_t unioffs[] = {size_t(uBufInfo.second)};
|
||||
// size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)};
|
||||
// boo::ObjToken<boo::ITexture> texs[] = {chs.m_font->GetTexture()};
|
||||
// chs.m_dataBinding = ctx.newShaderDataBinding(CTextSupportShader::SelectTextPipeline(m_drawFlags), nullptr,
|
||||
// iBufInfo.first.get(), nullptr, 1, uniforms, unistages, unioffs,
|
||||
// unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second);
|
||||
//
|
||||
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
|
||||
// uniforms[0] = uBufInfo2.first.get();
|
||||
// unioffs[0] = size_t(uBufInfo2.second);
|
||||
// chs.m_dataBinding2 = ctx.newShaderDataBinding(CTextSupportShader::GetTextAdditiveOverdrawPipeline(), nullptr,
|
||||
// iBufInfo.first.get(), nullptr, 1, uniforms, unistages, unioffs,
|
||||
// unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for (BooImage& img : m_images) {
|
||||
// img.m_instBuf = CTextSupportShader::s_ImgInsts.allocateBlock(CGraphics::g_BooFactory, 1);
|
||||
// auto iBufInfo = img.m_instBuf.getBufferInfo();
|
||||
//
|
||||
// boo::ObjToken<boo::IGraphicsBuffer> uniforms[] = {uBufInfo.first.get()};
|
||||
// boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex};
|
||||
// size_t unioffs[] = {size_t(uBufInfo.second)};
|
||||
// size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)};
|
||||
// img.m_dataBinding.reserve(img.m_imageDef.x4_texs.size());
|
||||
// for (TToken<CTexture>& tex : img.m_imageDef.x4_texs) {
|
||||
// boo::ObjToken<boo::ITexture> texs[] = {tex->GetBooTexture()};
|
||||
// texs[0]->setClampMode(boo::TextureClampMode::ClampToEdge);
|
||||
// img.m_dataBinding.push_back(ctx.newShaderDataBinding(
|
||||
// CTextSupportShader::SelectImagePipeline(m_drawFlags), nullptr, iBufInfo.first.get(), nullptr, 1, uniforms,
|
||||
// unistages, unioffs, unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second));
|
||||
// }
|
||||
//
|
||||
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
|
||||
// uniforms[0] = uBufInfo2.first.get();
|
||||
// unioffs[0] = size_t(uBufInfo2.second);
|
||||
// img.m_dataBinding2.reserve(img.m_imageDef.x4_texs.size());
|
||||
// for (TToken<CTexture>& tex : img.m_imageDef.x4_texs) {
|
||||
// boo::ObjToken<boo::ITexture> texs[] = {tex->GetBooTexture()};
|
||||
// img.m_dataBinding2.push_back(ctx.newShaderDataBinding(
|
||||
// CTextSupportShader::GetImageAdditiveOverdrawPipeline(), nullptr, iBufInfo.first.get(), nullptr, 1,
|
||||
// uniforms, unistages, unioffs, unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// } BooTrace);
|
||||
//}
|
||||
|
||||
void CTextRenderBuffer::SetMode(EMode mode) {
|
||||
x0_mode = mode;
|
||||
}
|
||||
|
||||
//void CTextRenderBuffer::SetPrimitiveOpacity(int idx, float opacity) {
|
||||
// m_primitiveMarks[idx].SetOpacity(*this, opacity);
|
||||
//}
|
||||
//
|
||||
//u32 CTextRenderBuffer::GetPrimitiveCount() const { return m_primitiveMarks.size(); }
|
||||
|
||||
void CTextRenderBuffer::Render(const zeus::CColor& col, float time) {
|
||||
// CommitResources();
|
||||
|
||||
// const zeus::CMatrix4f mv = CGraphics::g_GXModelView.toMatrix4f();
|
||||
// const zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(true);
|
||||
// const zeus::CMatrix4f mat = proj * mv;
|
||||
|
||||
// m_uniBuf.access() = CTextSupportShader::Uniform{mat, col};
|
||||
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
|
||||
// zeus::CColor colPremul = col * col.a();
|
||||
// colPremul.a() = col.a();
|
||||
// m_uniBuf2.access() = CTextSupportShader::Uniform{mat, colPremul};
|
||||
// }
|
||||
|
||||
// for (BooFontCharacters& chs : m_fontCharacters) {
|
||||
// if (chs.m_charData.size()) {
|
||||
// if (chs.m_dirty) {
|
||||
// std::memmove(chs.m_instBuf.access(), chs.m_charData.data(),
|
||||
// sizeof(CTextSupportShader::CharacterInstance) * chs.m_charData.size());
|
||||
// chs.m_dirty = false;
|
||||
// }
|
||||
// CGraphics::SetShaderDataBinding(chs.m_dataBinding);
|
||||
// CGraphics::DrawInstances(0, 4, chs.m_charData.size());
|
||||
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
|
||||
// CGraphics::SetShaderDataBinding(chs.m_dataBinding2);
|
||||
// CGraphics::DrawInstances(0, 4, chs.m_charData.size());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// for (BooImage& img : m_images) {
|
||||
// if (img.m_dirty) {
|
||||
// *img.m_instBuf.access() = img.m_imageData;
|
||||
// img.m_dirty = false;
|
||||
// }
|
||||
// const int idx = int(img.m_imageDef.x0_fps * time) % img.m_dataBinding.size();
|
||||
// CGraphics::SetShaderDataBinding(img.m_dataBinding[idx]);
|
||||
// CGraphics::DrawInstances(0, 4, 1);
|
||||
// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) {
|
||||
// CGraphics::SetShaderDataBinding(img.m_dataBinding2[idx]);
|
||||
// CGraphics::DrawInstances(0, 4, 1);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImageDef& image) {
|
||||
// if (x0_mode == EMode::AllocTally)
|
||||
// m_primitiveMarks.push_back({Command::ImageRender, m_imagesCount++, 0});
|
||||
// else
|
||||
// m_images.emplace_back(image, offset);
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color) {
|
||||
// if (m_activeFontCh == UINT32_MAX)
|
||||
// return;
|
||||
// BooFontCharacters& chs = m_fontCharacters[m_activeFontCh];
|
||||
// if (x0_mode == EMode::AllocTally)
|
||||
// m_primitiveMarks.push_back({Command::CharacterRender, m_activeFontCh, chs.m_charCount++});
|
||||
// else {
|
||||
// const CGlyph* glyph = chs.m_font.GetObj()->GetGlyph(ch);
|
||||
//
|
||||
// CTextSupportShader::CharacterInstance& inst = chs.m_charData.emplace_back();
|
||||
// inst.SetMetrics(*glyph, offset);
|
||||
// inst.m_fontColor = m_main * color;
|
||||
// inst.m_outlineColor = m_outline * color;
|
||||
// inst.m_mulColor = zeus::skWhite;
|
||||
// }
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline) {
|
||||
// m_main = main;
|
||||
// m_outline = outline;
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::AddFontChange(const TToken<CRasterFont>& font) {
|
||||
// for (size_t i = 0; i < m_fontCharacters.size(); ++i) {
|
||||
// BooFontCharacters& chs = m_fontCharacters[i];
|
||||
// if (*chs.m_font.GetObjectTag() == *font.GetObjectTag()) {
|
||||
// m_activeFontCh = i;
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// m_activeFontCh = m_fontCharacters.size();
|
||||
// m_fontCharacters.emplace_back(font);
|
||||
}
|
||||
|
||||
bool CTextRenderBuffer::HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) const {
|
||||
std::pair<zeus::CVector2i, zeus::CVector2i> bounds = AccumulateTextBounds();
|
||||
if (bounds.first.x > bounds.second.x)
|
||||
return true;
|
||||
|
||||
if (0 < origin.y)
|
||||
return false;
|
||||
|
||||
zeus::CVector2i size = bounds.second - bounds.first;
|
||||
return size.y <= extent.y;
|
||||
}
|
||||
|
||||
std::pair<zeus::CVector2i, zeus::CVector2i> CTextRenderBuffer::AccumulateTextBounds() const {
|
||||
std::pair<zeus::CVector2i, zeus::CVector2i> ret =
|
||||
std::make_pair(zeus::CVector2i{INT_MAX, INT_MAX}, zeus::CVector2i{INT_MIN, INT_MIN});
|
||||
|
||||
// for (const BooFontCharacters& chars : m_fontCharacters) {
|
||||
// for (const CTextSupportShader::CharacterInstance& charInst : chars.m_charData) {
|
||||
// ret.first.x = std::min(ret.first.x, int(charInst.m_pos[0].x()));
|
||||
// ret.first.y = std::min(ret.first.y, int(charInst.m_pos[0].z()));
|
||||
// ret.second.x = std::max(ret.second.x, int(charInst.m_pos[3].x()));
|
||||
// ret.second.y = std::max(ret.second.y, int(charInst.m_pos[3].z()));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for (const BooImage& imgs : m_images) {
|
||||
// ret.first.x = std::min(ret.first.x, int(imgs.m_imageData.m_pos[0].x()));
|
||||
// ret.first.y = std::min(ret.first.y, int(imgs.m_imageData.m_pos[0].z()));
|
||||
// ret.second.x = std::max(ret.second.x, int(imgs.m_imageData.m_pos[3].x()));
|
||||
// ret.second.y = std::max(ret.second.y, int(imgs.m_imageData.m_pos[3].z()));
|
||||
// }
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::SetPrimitive(const Primitive& prim, s32 idx) {
|
||||
CMemoryStreamOut out(reinterpret_cast<u8*>(x34_bytecode.data() + x24_primOffsets[idx]),
|
||||
x44_blobSize - x24_primOffsets[idx]);
|
||||
if (prim.x4_command == Command::ImageRender) {
|
||||
out.WriteUint8(1);
|
||||
out.WriteUint8(static_cast<u8>(Command::ImageRender));
|
||||
out.Put(prim.x8_xPos);
|
||||
out.Put(prim.xa_zPos);
|
||||
out.Put(prim.xe_imageIndex);
|
||||
// out.Put(prim.x0_color1.toRGBA());
|
||||
out.Put(prim.x0_color1.toRGBA());
|
||||
} else if (prim.x4_command == Command::CharacterRender) {
|
||||
out.WriteUint8(0);
|
||||
out.WriteUint8(static_cast<u8>(Command::CharacterRender));
|
||||
out.Put(prim.x8_xPos);
|
||||
out.Put(prim.xa_zPos);
|
||||
out.Put(u16(prim.xc_glyph));
|
||||
// out.Put(prim.x0_color1.toRGBA());
|
||||
out.Put(prim.x0_color1.toRGBA());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,4 +62,202 @@ CTextRenderBuffer::Primitive CTextRenderBuffer::GetPrimitive(s32 idx) const {
|
|||
return {CTextColor(zeus::Comp32(0)), Command::Invalid, 0, 0, u'\0', 0};
|
||||
}
|
||||
|
||||
u8* CTextRenderBuffer::GetOutStream() {
|
||||
VerifyBuffer();
|
||||
return reinterpret_cast<u8*>(x34_bytecode.data()) + x48_curBytecodeOffset;
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::VerifyBuffer() {
|
||||
if (x34_bytecode.empty()) {
|
||||
x34_bytecode.resize(x44_blobSize);
|
||||
}
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::SetMode(EMode mode) { x0_mode = mode; }
|
||||
|
||||
int CTextRenderBuffer::GetMatchingPaletteIndex(const CGraphicsPalette& palette) {
|
||||
for (int i = 0; i < x50_palettes.size(); ++i) {
|
||||
if (memcmp(x50_palettes[i]->GetPaletteData(), palette.GetPaletteData(), 8) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
CGraphicsPalette* CTextRenderBuffer::GetNextAvailablePalette() {
|
||||
if (x254_nextPalette < 64) {
|
||||
x50_palettes.push_back(std::make_unique<CGraphicsPalette>(EPaletteFormat::RGB5A3, 4));
|
||||
} else {
|
||||
x254_nextPalette = 0;
|
||||
}
|
||||
++x254_nextPalette;
|
||||
return x50_palettes[x254_nextPalette - 1].get();
|
||||
}
|
||||
|
||||
u32 CTextRenderBuffer::GetCurLen() {
|
||||
VerifyBuffer();
|
||||
return x44_blobSize - x48_curBytecodeOffset;
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::Render(const zeus::CColor& col, float time) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::AddPaletteChange(const CGraphicsPalette& palette) {
|
||||
if (x0_mode == EMode::BufferFill) {
|
||||
{
|
||||
u8* buf = GetOutStream();
|
||||
CMemoryStreamOut out(buf, GetCurLen());
|
||||
s32 paletteIndex = GetMatchingPaletteIndex(palette);
|
||||
if (paletteIndex == -1) {
|
||||
GetNextAvailablePalette();
|
||||
paletteIndex = x254_nextPalette - 1;
|
||||
CGraphicsPalette* destPalette = x50_palettes[x254_nextPalette - 1].get();
|
||||
destPalette->Lock();
|
||||
memcpy(destPalette->GetPaletteData(), palette.GetPaletteData(), 8);
|
||||
destPalette->UnLock();
|
||||
}
|
||||
out.WriteUint8(static_cast<u8>(Command::PaletteChange));
|
||||
out.WriteUint8(paletteIndex);
|
||||
x48_curBytecodeOffset += out.GetNumWrites();
|
||||
}
|
||||
} else {
|
||||
x44_blobSize += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImageDef& image) {
|
||||
if (x0_mode == EMode::BufferFill) {
|
||||
CMemoryStreamOut out(GetOutStream(), GetCurLen());
|
||||
x24_primOffsets.reserve(x24_primOffsets.size() + 1);
|
||||
u32 primCap = x24_primOffsets.capacity();
|
||||
if (x24_primOffsets.capacity() <= x24_primOffsets.size()) {
|
||||
x24_primOffsets.reserve(primCap != 0 ? primCap * 2 : 4);
|
||||
}
|
||||
x24_primOffsets.push_back(x48_curBytecodeOffset);
|
||||
x14_images.reserve(x14_images.size() + 1);
|
||||
u32 imgIdx = x14_images.size();
|
||||
x14_images.push_back(image);
|
||||
out.WriteUint8(static_cast<u8>(Command::ImageRender));
|
||||
out.WriteShort(offset.x);
|
||||
out.WriteShort(offset.y);
|
||||
out.WriteUint8(imgIdx);
|
||||
out.WriteLong(zeus::skWhite.toRGBA());
|
||||
x48_curBytecodeOffset += out.GetNumWrites();
|
||||
} else {
|
||||
x44_blobSize += 10;
|
||||
}
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, const CTextColor& color) {
|
||||
if (x0_mode == EMode::BufferFill) {
|
||||
CMemoryStreamOut out(GetOutStream(), GetCurLen());
|
||||
x24_primOffsets.reserve(x24_primOffsets.size() + 1);
|
||||
u32 primCap = x24_primOffsets.capacity();
|
||||
if (x24_primOffsets.capacity() <= x24_primOffsets.size()) {
|
||||
x24_primOffsets.reserve(primCap != 0 ? primCap * 2 : 4);
|
||||
}
|
||||
x24_primOffsets.push_back(x48_curBytecodeOffset);
|
||||
out.WriteUint8(u32(Command::CharacterRender));
|
||||
out.WriteShort(offset.x);
|
||||
out.WriteShort(offset.y);
|
||||
out.WriteShort(ch);
|
||||
out.WriteUint32(color.toRGBA());
|
||||
x48_curBytecodeOffset += out.GetNumWrites();
|
||||
} else {
|
||||
x44_blobSize += 11;
|
||||
}
|
||||
}
|
||||
|
||||
void CTextRenderBuffer::AddFontChange(const TToken<CRasterFont>& font) {
|
||||
if (x0_mode == EMode::BufferFill) {
|
||||
CMemoryStreamOut out(GetOutStream(), GetCurLen());
|
||||
u32 fontCount = x4_fonts.size();
|
||||
bool found = false;
|
||||
u8 fontIndex = 0;
|
||||
if (fontCount > 0) {
|
||||
for (const auto& tok : x4_fonts) {
|
||||
if (tok.GetObjectReference() == font.GetObjectReference()) {
|
||||
out.WriteUint8(static_cast<u8>(Command::FontChange));
|
||||
out.WriteUint8(fontIndex);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
++fontIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
x4_fonts.reserve(x4_fonts.size() + 1);
|
||||
u32 fontIdx = x4_fonts.size();
|
||||
x4_fonts.push_back(font);
|
||||
out.WriteUint8(static_cast<u8>(Command::FontChange));
|
||||
out.WriteUint8(fontIdx);
|
||||
}
|
||||
x48_curBytecodeOffset += out.GetNumWrites();
|
||||
} else {
|
||||
x44_blobSize += 2;
|
||||
}
|
||||
}
|
||||
|
||||
bool CTextRenderBuffer::HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) {
|
||||
std::pair<zeus::CVector2i, zeus::CVector2i> bounds = AccumulateTextBounds();
|
||||
if (bounds.first.x > bounds.second.x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (0 < origin.y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
zeus::CVector2i size = bounds.second - bounds.first;
|
||||
return size.y <= extent.y;
|
||||
}
|
||||
|
||||
std::pair<zeus::CVector2i, zeus::CVector2i> CTextRenderBuffer::AccumulateTextBounds() {
|
||||
zeus::CVector2i min{INT_MAX, INT_MAX};
|
||||
zeus::CVector2i max{INT_MIN, INT_MIN};
|
||||
CMemoryInStream in(x34_bytecode.data(), x44_blobSize);
|
||||
|
||||
while (in.GetReadPosition() < x48_curBytecodeOffset) {
|
||||
auto cmd = static_cast<Command>(in.ReadChar());
|
||||
if (cmd == Command::FontChange) {
|
||||
x4c_activeFont = in.ReadChar();
|
||||
} else if (cmd == Command::CharacterRender) {
|
||||
u16 offX = in.ReadShort();
|
||||
u16 offY = in.ReadShort();
|
||||
char16_t chr = in.ReadShort();
|
||||
in.ReadLong();
|
||||
if (x4c_activeFont != -1) {
|
||||
auto font = x4_fonts[x4c_activeFont];
|
||||
if (font) {
|
||||
const auto* glyph = font->GetGlyph(chr);
|
||||
if (glyph != nullptr) {
|
||||
max.x = std::max(max.x, offX + glyph->GetCellWidth());
|
||||
max.y = std::max(max.y, offY + glyph->GetCellHeight());
|
||||
min.x = std::min<int>(min.x, offX);
|
||||
min.y = std::min<int>(min.y, offY);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (cmd == Command::ImageRender) {
|
||||
u16 offX = in.ReadShort();
|
||||
u16 offY = in.ReadShort();
|
||||
u8 imageIdx = in.ReadChar();
|
||||
in.ReadLong();
|
||||
const auto& image = x14_images[imageIdx];
|
||||
max.x = std::max(max.x, offX + static_cast<int>(static_cast<float>(image.x4_texs.front()->GetWidth()) *
|
||||
image.x14_cropFactor.x()));
|
||||
max.y = std::max(max.y, offY + static_cast<int>(static_cast<float>(image.x4_texs.front()->GetHeight()) *
|
||||
image.x14_cropFactor.y()));
|
||||
min.x = std::min<int>(min.x, offX);
|
||||
min.y = std::min<int>(min.y, offY);
|
||||
} else if (cmd == Command::PaletteChange) {
|
||||
in.ReadChar();
|
||||
}
|
||||
}
|
||||
return {min, max};
|
||||
}
|
||||
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -27,7 +27,8 @@ class CTextRenderBuffer {
|
|||
friend class CTextSupportShader;
|
||||
|
||||
public:
|
||||
enum class Command { CharacterRender, ImageRender, FontChange, PaletteChange, Invalid };
|
||||
enum class Command { CharacterRender, ImageRender, FontChange, PaletteChange, Invalid = -1 };
|
||||
#if 1
|
||||
struct Primitive {
|
||||
CTextColor x0_color1;
|
||||
Command x4_command;
|
||||
|
@ -36,6 +37,7 @@ public:
|
|||
char16_t xc_glyph;
|
||||
u8 xe_imageIndex;
|
||||
};
|
||||
#endif
|
||||
enum class EMode { AllocTally, BufferFill };
|
||||
|
||||
private:
|
||||
|
@ -46,34 +48,37 @@ private:
|
|||
std::vector<char> x34_bytecode;
|
||||
u32 x44_blobSize = 0;
|
||||
u32 x48_curBytecodeOffset = 0;
|
||||
u8 x4c_activeFont;
|
||||
u32 x50_paletteCount = 0;
|
||||
std::array<std::unique_ptr<CGraphicsPalette>, 64> x54_palettes;
|
||||
u32 x254_nextPalette = 0;
|
||||
s8 x4c_activeFont = -1;
|
||||
s8 x4d_ = -1;
|
||||
s8 x4e_ = -1;
|
||||
s8 x4f_curPalette = -1;
|
||||
rstl::reserved_vector<std::unique_ptr<CGraphicsPalette>, 64> x50_palettes;
|
||||
s32 x254_nextPalette = 0;
|
||||
|
||||
public:
|
||||
CTextRenderBuffer(CTextRenderBuffer&& other) noexcept;
|
||||
CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df);
|
||||
CTextRenderBuffer(EMode mode);
|
||||
~CTextRenderBuffer();
|
||||
|
||||
CTextRenderBuffer& operator=(CTextRenderBuffer&& other) noexcept;
|
||||
|
||||
void SetPrimitive(const Primitive&, int);
|
||||
[[nodiscard]] Primitive GetPrimitive(int) const;
|
||||
void GetOutStream();
|
||||
[[nodiscard]] u32 GetPrimitiveCount() const { return x24_primOffsets.size(); }
|
||||
[[nodiscard]] u8* GetOutStream();
|
||||
[[nodiscard]] u32 GetCurLen();
|
||||
void VerifyBuffer();
|
||||
int GetMatchingPaletteIndex(const CGraphicsPalette& palette);
|
||||
CGraphicsPalette* GetNextAvailablePalette();
|
||||
[[nodiscard]] CGraphicsPalette* GetNextAvailablePalette();
|
||||
void AddPaletteChange(const CGraphicsPalette& palette);
|
||||
void SetMode(EMode mode);
|
||||
void Render(const zeus::CColor& col, float time);
|
||||
void Render(const CTextColor& col, float time);
|
||||
void AddImage(const zeus::CVector2i& offset, const CFontImageDef& image);
|
||||
void AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color);
|
||||
void AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline);
|
||||
void AddCharacter(const zeus::CVector2i& offset, char16_t ch, const CTextColor& color);
|
||||
void AddFontChange(const TToken<CRasterFont>& font);
|
||||
|
||||
bool HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) const;
|
||||
std::pair<zeus::CVector2i, zeus::CVector2i> AccumulateTextBounds() const;
|
||||
[[nodiscard]] bool HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent);
|
||||
[[nodiscard]] std::pair<zeus::CVector2i, zeus::CVector2i> AccumulateTextBounds();
|
||||
};
|
||||
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -5,8 +5,8 @@ namespace metaforce {
|
|||
class CMemoryInStream final : public CInputStream {
|
||||
public:
|
||||
enum class EOwnerShip {
|
||||
NotOwned,
|
||||
Owned,
|
||||
NotOwned,
|
||||
};
|
||||
|
||||
CMemoryInStream(const void* ptr, u32 len) : CInputStream(ptr, len, false) {}
|
||||
|
|
|
@ -5,8 +5,8 @@ namespace metaforce {
|
|||
class CMemoryStreamOut final : public COutputStream {
|
||||
public:
|
||||
enum class EOwnerShip {
|
||||
NotOwned,
|
||||
Owned,
|
||||
NotOwned,
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
COutputStream(s32 unk);
|
||||
virtual ~COutputStream();
|
||||
|
||||
u32 GetNumWrites() const { return x10_numWrites; }
|
||||
void WriteBits(u32 val, u32 bitCount);
|
||||
void WriteChar(u8 c);
|
||||
void WriteShort(u16 s);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 8e4dfb022a97aee2c245d8a2ec9b92ce3d865fbd
|
||||
Subproject commit 8410394d4bd90f8783b68ab064b13d838e29d6a1
|
Loading…
Reference in New Issue