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(IObj* obj);
|
||||||
CToken(std::unique_ptr<IObj>&& obj);
|
CToken(std::unique_ptr<IObj>&& obj);
|
||||||
const SObjectTag* GetObjectTag() const;
|
const SObjectTag* GetObjectTag() const;
|
||||||
|
const CObjectReference* GetObjectReference() const { return x0_objRef; }
|
||||||
~CToken();
|
~CToken();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,11 @@
|
||||||
namespace metaforce {
|
namespace metaforce {
|
||||||
static logvisor::Module Log("CCubeRenderer");
|
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<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<CDrawablePlaneObject, 8> sPlaneObjectDataHolder;
|
||||||
static rstl::reserved_vector<u16, 8> sPlaneObjectBucketHolder;
|
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<u16, 50> sBucketIndex;
|
||||||
static inline rstl::reserved_vector<CDrawable, 512>* sData = nullptr;
|
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<CDrawablePlaneObject, 8>* sPlaneObjectData = nullptr;
|
||||||
static inline rstl::reserved_vector<u16, 8>* sPlaneObjectBucket = nullptr;
|
static inline rstl::reserved_vector<u16, 8>* sPlaneObjectBucket = nullptr;
|
||||||
static constexpr std::array skWorstMinMaxDistance{99999.0f, -99999.0f};
|
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:
|
public:
|
||||||
static void Clear();
|
static void Clear();
|
||||||
|
@ -51,7 +54,7 @@ void Buckets::Clear() {
|
||||||
sBucketIndex.clear();
|
sBucketIndex.clear();
|
||||||
sPlaneObjectData->clear();
|
sPlaneObjectData->clear();
|
||||||
sPlaneObjectBucket->clear();
|
sPlaneObjectBucket->clear();
|
||||||
for (rstl::reserved_vector<CDrawable*, 128>& bucket : *sBuckets) {
|
for (BucketHolderType& bucket : *sBuckets) {
|
||||||
bucket.clear();
|
bucket.clear();
|
||||||
}
|
}
|
||||||
sMinMaxDistance = skWorstMinMaxDistance;
|
sMinMaxDistance = skWorstMinMaxDistance;
|
||||||
|
@ -60,12 +63,14 @@ void Buckets::Clear() {
|
||||||
void Buckets::Sort() {
|
void Buckets::Sort() {
|
||||||
float delta = std::max(1.f, sMinMaxDistance[1] - sMinMaxDistance[0]);
|
float delta = std::max(1.f, sMinMaxDistance[1] - sMinMaxDistance[0]);
|
||||||
float pitch = 49.f / delta;
|
float pitch = 49.f / delta;
|
||||||
for (auto it = sPlaneObjectData->begin(); it != sPlaneObjectData->end(); ++it)
|
for (auto it = sPlaneObjectData->begin(); it != sPlaneObjectData->end(); ++it) {
|
||||||
if (sPlaneObjectBucket->size() != sPlaneObjectBucket->capacity())
|
if (sPlaneObjectBucket->size() != sPlaneObjectBucket->capacity()) {
|
||||||
sPlaneObjectBucket->push_back(s16(it - sPlaneObjectData->begin()));
|
sPlaneObjectBucket->push_back(s16(it - sPlaneObjectData->begin()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 precision = 50;
|
u32 precision = 50;
|
||||||
if (sPlaneObjectBucket->size()) {
|
if (!sPlaneObjectBucket->empty()) {
|
||||||
std::sort(sPlaneObjectBucket->begin(), sPlaneObjectBucket->end(),
|
std::sort(sPlaneObjectBucket->begin(), sPlaneObjectBucket->end(),
|
||||||
[](u16 a, u16 b) { return (*sPlaneObjectData)[a].GetDistance() < (*sPlaneObjectData)[b].GetDistance(); });
|
[](u16 a, u16 b) { return (*sPlaneObjectData)[a].GetDistance() < (*sPlaneObjectData)[b].GetDistance(); });
|
||||||
precision = 50 / u32(sPlaneObjectBucket->size() + 1);
|
precision = 50 / u32(sPlaneObjectBucket->size() + 1);
|
||||||
|
@ -80,7 +85,7 @@ void Buckets::Sort() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CDrawable& drawable : *sData) {
|
for (CDrawable& drawable : *sData) {
|
||||||
s32 slot;
|
s32 slot = -1;
|
||||||
float relDist = drawable.GetDistance() - sMinMaxDistance[0];
|
float relDist = drawable.GetDistance() - sMinMaxDistance[0];
|
||||||
if (sPlaneObjectBucket->empty()) {
|
if (sPlaneObjectBucket->empty()) {
|
||||||
slot = zeus::clamp(1, s32(relDist * pitch), 49);
|
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);
|
slot = zeus::clamp(0, s32(relDist * pitch), s32(precision) - 2);
|
||||||
for (u16 idx : *sPlaneObjectBucket) {
|
for (u16 idx : *sPlaneObjectBucket) {
|
||||||
CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[idx];
|
CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[idx];
|
||||||
bool partial, full;
|
bool partial = false;
|
||||||
|
bool full = false;
|
||||||
if (planeObj.x3c_25_zOnly) {
|
if (planeObj.x3c_25_zOnly) {
|
||||||
partial = drawable.GetBounds().max.z() > planeObj.GetPlane().d();
|
partial = drawable.GetBounds().max.z() > planeObj.GetPlane().d();
|
||||||
full = drawable.GetBounds().min.z() > planeObj.GetPlane().d();
|
full = drawable.GetBounds().min.z() > planeObj.GetPlane().d();
|
||||||
|
@ -98,22 +104,26 @@ void Buckets::Sort() {
|
||||||
full = planeObj.GetPlane().pointToPlaneDist(
|
full = planeObj.GetPlane().pointToPlaneDist(
|
||||||
drawable.GetBounds().furthestPointAlongVector(planeObj.GetPlane().normal())) > 0.f;
|
drawable.GetBounds().furthestPointAlongVector(planeObj.GetPlane().normal())) > 0.f;
|
||||||
}
|
}
|
||||||
bool cont;
|
bool cont = false;
|
||||||
if (drawable.GetType() == EDrawableType::Particle)
|
if (drawable.GetType() == EDrawableType::Particle) {
|
||||||
cont = planeObj.x3c_24_invertTest ? !partial : full;
|
cont = planeObj.x3c_24_invertTest ? !partial : full;
|
||||||
else
|
} else {
|
||||||
cont = planeObj.x3c_24_invertTest ? (!partial || !full) : (partial || full);
|
cont = planeObj.x3c_24_invertTest ? (!partial || !full) : (partial || full);
|
||||||
if (!cont)
|
}
|
||||||
|
if (!cont) {
|
||||||
break;
|
break;
|
||||||
slot += precision;
|
}
|
||||||
|
slot += s32(precision);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot == -1)
|
if (slot == -1) {
|
||||||
slot = 49;
|
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);
|
bucket.push_back(&drawable);
|
||||||
|
}
|
||||||
// else
|
// else
|
||||||
// Log.report(logvisor::Fatal, FMT_STRING("Full bucket!!!"));
|
// Log.report(logvisor::Fatal, FMT_STRING("Full bucket!!!"));
|
||||||
}
|
}
|
||||||
|
@ -122,7 +132,7 @@ void Buckets::Sort() {
|
||||||
for (auto it = sBuckets->rbegin(); it != sBuckets->rend(); ++it) {
|
for (auto it = sBuckets->rbegin(); it != sBuckets->rend(); ++it) {
|
||||||
--bucketIdx;
|
--bucketIdx;
|
||||||
sBucketIndex.push_back(bucketIdx);
|
sBucketIndex.push_back(bucketIdx);
|
||||||
rstl::reserved_vector<CDrawable*, 128>& bucket = *it;
|
BucketHolderType& bucket = *it;
|
||||||
if (bucket.size()) {
|
if (bucket.size()) {
|
||||||
std::sort(bucket.begin(), bucket.end(), [](CDrawable* a, CDrawable* b) {
|
std::sort(bucket.begin(), bucket.end(), [](CDrawable* a, CDrawable* b) {
|
||||||
if (a->GetDistance() == b->GetDistance())
|
if (a->GetDistance() == b->GetDistance())
|
||||||
|
@ -134,7 +144,7 @@ void Buckets::Sort() {
|
||||||
|
|
||||||
for (auto it = sPlaneObjectBucket->rbegin(); it != sPlaneObjectBucket->rend(); ++it) {
|
for (auto it = sPlaneObjectBucket->rbegin(); it != sPlaneObjectBucket->rend(); ++it) {
|
||||||
CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[*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);
|
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) {
|
void CCubeRenderer::DrawSortedGeometry(s32 areaIdx, s32 mask, s32 targetMask) {
|
||||||
SCOPED_GRAPHICS_DEBUG_GROUP(
|
SCOPED_GRAPHICS_DEBUG_GROUP(
|
||||||
fmt::format(FMT_STRING("CCubeRenderer::DrawSortedGeometry areaIdx={} mask={} targetMask={}"), areaIdx, mask,
|
fmt::format(FMT_STRING("CCubeRenderer::DrawSortedGeometry areaIdx={} mask={} targetMask={}"), areaIdx, mask,
|
||||||
targetMask).c_str(),
|
targetMask)
|
||||||
|
.c_str(),
|
||||||
zeus::skBlue);
|
zeus::skBlue);
|
||||||
|
|
||||||
SetupRendererStates(true);
|
SetupRendererStates(true);
|
||||||
|
@ -427,7 +438,8 @@ void CCubeRenderer::DrawStaticGeometry(s32 areaIdx, s32 mask, s32 targetMask) {
|
||||||
void CCubeRenderer::DrawAreaGeometry(s32 areaIdx, s32 mask, s32 targetMask) {
|
void CCubeRenderer::DrawAreaGeometry(s32 areaIdx, s32 mask, s32 targetMask) {
|
||||||
SCOPED_GRAPHICS_DEBUG_GROUP(
|
SCOPED_GRAPHICS_DEBUG_GROUP(
|
||||||
fmt::format(FMT_STRING("CCubeRenderer::DrawAreaGeometry areaIdx={} mask={} targetMask={}"), areaIdx, mask,
|
fmt::format(FMT_STRING("CCubeRenderer::DrawAreaGeometry areaIdx={} mask={} targetMask={}"), areaIdx, mask,
|
||||||
targetMask).c_str(),
|
targetMask)
|
||||||
|
.c_str(),
|
||||||
zeus::skBlue);
|
zeus::skBlue);
|
||||||
|
|
||||||
x318_30_inAreaDraw = true;
|
x318_30_inAreaDraw = true;
|
||||||
|
@ -476,7 +488,7 @@ void CCubeRenderer::RenderBucketItems(const CAreaListItem* item) {
|
||||||
CCubeModel* lastModel = nullptr;
|
CCubeModel* lastModel = nullptr;
|
||||||
EDrawableType lastDrawableType = EDrawableType::Invalid;
|
EDrawableType lastDrawableType = EDrawableType::Invalid;
|
||||||
for (u16 idx : Buckets::sBucketIndex) {
|
for (u16 idx : Buckets::sBucketIndex) {
|
||||||
rstl::reserved_vector<CDrawable*, 128>& bucket = (*Buckets::sBuckets)[idx];
|
BucketHolderType& bucket = (*Buckets::sBuckets)[idx];
|
||||||
for (CDrawable* drawable : bucket) {
|
for (CDrawable* drawable : bucket) {
|
||||||
EDrawableType type = drawable->GetType();
|
EDrawableType type = drawable->GetType();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
|
@ -24,8 +24,6 @@ void CGraphicsPalette::Load() {
|
||||||
x4_frameLoaded = sCurrentFrameCount;
|
x4_frameLoaded = sCurrentFrameCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGraphicsPalette::Lock() { x1c_locked = true; }
|
|
||||||
|
|
||||||
void CGraphicsPalette::UnLock() {
|
void CGraphicsPalette::UnLock() {
|
||||||
// DCStoreRange(xc_lut, x8_numEntries << 1);
|
// DCStoreRange(xc_lut, x8_numEntries << 1);
|
||||||
GXInitTlutObj(&x10_tlutObj, xc_entries.get(), static_cast<GXTlutFmt>(x0_fmt), x8_entryCount);
|
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(EPaletteFormat fmt, int count);
|
||||||
explicit CGraphicsPalette(CInputStream& in);
|
explicit CGraphicsPalette(CInputStream& in);
|
||||||
|
|
||||||
void Load();
|
void Lock() { x1c_locked = true; }
|
||||||
void Lock();
|
|
||||||
void UnLock();
|
void UnLock();
|
||||||
|
void Load();
|
||||||
|
|
||||||
[[nodiscard]] u8* GetPaletteData() { return xc_entries.get(); }
|
[[nodiscard]] u8* GetPaletteData() { return xc_entries.get(); }
|
||||||
[[nodiscard]] const u8* GetPaletteData() const { 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 CGuiTextSupport::GetCurrentAnimationOverAge() const {
|
||||||
float ret = 0.f;
|
float ret = 0.f;
|
||||||
// TODO
|
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||||
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
if (x50_typeEnable) {
|
||||||
// if (x50_typeEnable) {
|
if (!x40_primStartTimes.empty()) {
|
||||||
// if (x40_primStartTimes.size()) {
|
const auto& lastTime = x40_primStartTimes.back();
|
||||||
// const auto& lastTime = x40_primStartTimes.back();
|
ret = std::max(ret, (buf->GetPrimitiveCount() - lastTime.second) / x58_chRate + lastTime.first);
|
||||||
// ret = std::max(ret, (buf->GetPrimitiveCount() - lastTime.second) / x58_chRate + lastTime.first);
|
} else {
|
||||||
// } else {
|
ret = std::max(ret, buf->GetPrimitiveCount() / x58_chRate);
|
||||||
// ret = std::max(ret, buf->GetPrimitiveCount() / x58_chRate);
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
float CGuiTextSupport::GetNumCharsTotal() const {
|
float CGuiTextSupport::GetNumCharsTotal() const {
|
||||||
// TODO
|
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||||
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
if (x50_typeEnable) {
|
||||||
// if (x50_typeEnable) {
|
return buf->GetPrimitiveCount();
|
||||||
// return buf->GetPrimitiveCount();
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
return 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float CGuiTextSupport::GetNumCharsPrinted() const {
|
float CGuiTextSupport::GetNumCharsPrinted() const {
|
||||||
// TODO
|
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||||
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
if (x50_typeEnable) {
|
||||||
// if (x50_typeEnable) {
|
const float charsPrinted = x3c_curTime * x58_chRate;
|
||||||
// const float charsPrinted = x3c_curTime * x58_chRate;
|
return std::min(charsPrinted, float(buf->GetPrimitiveCount()));
|
||||||
// return std::min(charsPrinted, float(buf->GetPrimitiveCount()));
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
return 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float CGuiTextSupport::GetTotalAnimationTime() const {
|
float CGuiTextSupport::GetTotalAnimationTime() const {
|
||||||
// TODO
|
if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||||
// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
if (x50_typeEnable) {
|
||||||
// if (x50_typeEnable) {
|
return buf->GetPrimitiveCount() / x58_chRate;
|
||||||
// return buf->GetPrimitiveCount() / x58_chRate;
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
return 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,21 +117,20 @@ void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, f
|
||||||
x58_chRate = std::max(chRate, 1.f);
|
x58_chRate = std::max(chRate, 1.f);
|
||||||
if (enable) {
|
if (enable) {
|
||||||
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||||
// TODO
|
float chStartTime = 0.f;
|
||||||
// float chStartTime = 0.f;
|
for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
|
||||||
// for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
|
for (const std::pair<float, int>& p : x40_primStartTimes) {
|
||||||
// for (const std::pair<float, int>& p : x40_primStartTimes) {
|
if (p.second < i)
|
||||||
// if (p.second < i)
|
continue;
|
||||||
// continue;
|
if (p.second != i)
|
||||||
// if (p.second != i)
|
break;
|
||||||
// break;
|
chStartTime = p.first;
|
||||||
// chStartTime = p.first;
|
break;
|
||||||
// break;
|
}
|
||||||
// }
|
|
||||||
//
|
|
||||||
//buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
|
//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) {
|
void CGuiTextSupport::Update(float dt) {
|
||||||
if (x50_typeEnable) {
|
if (x50_typeEnable) {
|
||||||
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||||
// TODO
|
float chStartTime = 0.f;
|
||||||
// float chStartTime = 0.f;
|
for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
|
||||||
// for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) {
|
for (const std::pair<float, int>& p : x40_primStartTimes) {
|
||||||
// for (const std::pair<float, int>& p : x40_primStartTimes) {
|
if (p.second < i)
|
||||||
// if (p.second < i)
|
continue;
|
||||||
// continue;
|
if (p.second != i)
|
||||||
// if (p.second != i)
|
break;
|
||||||
// break;
|
chStartTime = p.first;
|
||||||
// chStartTime = p.first;
|
break;
|
||||||
// break;
|
}
|
||||||
// }
|
|
||||||
//
|
|
||||||
//buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
|
//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;
|
x3c_curTime += dt;
|
||||||
}
|
}
|
||||||
|
@ -190,9 +184,11 @@ void CGuiTextSupport::CheckAndRebuildTextBuffer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGuiTextSupport::CheckAndRebuildRenderBuffer() {
|
bool CGuiTextSupport::CheckAndRebuildRenderBuffer() {
|
||||||
if (x308_multipageFlag || x60_renderBuf)
|
if (x308_multipageFlag || x60_renderBuf) {
|
||||||
if (!x308_multipageFlag || x2ec_renderBufferPages.size())
|
if (!x308_multipageFlag || x2ec_renderBufferPages.size()) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CheckAndRebuildTextBuffer();
|
CheckAndRebuildTextBuffer();
|
||||||
x2bc_assets = g_TextExecuteBuf->GetAssets();
|
x2bc_assets = g_TextExecuteBuf->GetAssets();
|
||||||
|
@ -259,8 +255,7 @@ void CGuiTextSupport::SetFontColor(const zeus::CColor& col) {
|
||||||
void CGuiTextSupport::AddText(std::u16string_view str) {
|
void CGuiTextSupport::AddText(std::u16string_view str) {
|
||||||
if (x60_renderBuf) {
|
if (x60_renderBuf) {
|
||||||
const float t = GetCurrentAnimationOverAge();
|
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;
|
x0_string += str;
|
||||||
ClearRenderBuffer();
|
ClearRenderBuffer();
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "Runtime/CSimplePool.hpp"
|
#include "Runtime/CSimplePool.hpp"
|
||||||
|
#include "Runtime/Graphics/CGX.hpp"
|
||||||
#include "Runtime/Graphics/CTexture.hpp"
|
#include "Runtime/Graphics/CTexture.hpp"
|
||||||
#include "Runtime/GuiSys/CDrawStringOptions.hpp"
|
#include "Runtime/GuiSys/CDrawStringOptions.hpp"
|
||||||
#include "Runtime/GuiSys/CTextRenderBuffer.hpp"
|
#include "Runtime/GuiSys/CTextRenderBuffer.hpp"
|
||||||
|
@ -151,17 +152,15 @@ void CRasterFont::DrawString(const CDrawStringOptions& opts, int x, int y, int&
|
||||||
if (!x0_initialized)
|
if (!x0_initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (renderBuf) {
|
if (renderBuf != nullptr) {
|
||||||
/* CGraphicsPalette pal = CGraphicsPalette::CGraphcisPalette(2, 4); */
|
CGraphicsPalette pal(EPaletteFormat::RGB5A3, 4);
|
||||||
/* zeus::CColor color = zeus::CColor(0.f, 0.f, 0.f, 0.f) */
|
pal.Lock();
|
||||||
/* tmp = color.ToRGB5A3(); */
|
*reinterpret_cast<u16*>(pal.GetPaletteData() + 0) = SBIG(zeus::CColor(0.f, 0.f, 0.f, 0.f).toRGB5A3());
|
||||||
/* tmp2 = opts.x8_.ToRGB5A3(); */
|
*reinterpret_cast<u16*>(pal.GetPaletteData() + 2) = SBIG(opts.x4_colors[0].toRGB5A3());
|
||||||
/* tmp3 = opts.xc_.ToRGB5A3(); */
|
*reinterpret_cast<u16*>(pal.GetPaletteData() + 4) = SBIG(opts.x4_colors[1].toRGB5A3());
|
||||||
/* tmp4 = zeus::CColor(0.f, 0.f, 0.f, 0.f); */
|
*reinterpret_cast<u16*>(pal.GetPaletteData() + 6) = SBIG(zeus::CColor(0.f, 0.f, 0.f, 0.f).toRGB5A3());
|
||||||
/* tmp5 = tmp4.ToRGBA5A3(); */
|
pal.UnLock();
|
||||||
/* pal.UnLock(); */
|
renderBuf->AddPaletteChange(pal);
|
||||||
/* renderBuf->AddPaletteChange(pal); */
|
|
||||||
renderBuf->AddPaletteChange(opts.x4_colors[0], opts.x4_colors[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SinglePassDrawString(opts, x, y, xout, yout, renderBuf, str, len);
|
SinglePassDrawString(opts, x, y, xout, yout, renderBuf, str, len);
|
||||||
|
@ -210,6 +209,28 @@ bool CRasterFont::IsFinishedLoading() const {
|
||||||
return true;
|
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,
|
std::unique_ptr<IObj> FRasterFontFactory([[maybe_unused]] const SObjectTag& tag, CInputStream& in,
|
||||||
const CVParamTransfer& vparms, [[maybe_unused]] CObjectReference* selfRef) {
|
const CVParamTransfer& vparms, [[maybe_unused]] CObjectReference* selfRef) {
|
||||||
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
|
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
|
||||||
|
|
|
@ -151,6 +151,8 @@ public:
|
||||||
CTexture& GetTexture() { return *x80_texture; }
|
CTexture& GetTexture() { return *x80_texture; }
|
||||||
|
|
||||||
bool IsFinishedLoading() const;
|
bool IsFinishedLoading() const;
|
||||||
|
|
||||||
|
void SetupRenderState();
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<IObj> FRasterFontFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,
|
std::unique_ptr<IObj> FRasterFontFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
namespace metaforce {
|
namespace metaforce {
|
||||||
|
|
||||||
CTextRenderBuffer CTextExecuteBuffer::BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const {
|
CTextRenderBuffer CTextExecuteBuffer::BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const {
|
||||||
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df);
|
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally);//, df);
|
||||||
|
|
||||||
{
|
{
|
||||||
CFontRenderState rendState;
|
CFontRenderState rendState;
|
||||||
|
@ -35,7 +35,7 @@ CTextRenderBuffer CTextExecuteBuffer::BuildRenderBufferPage(InstList::const_iter
|
||||||
InstList::const_iterator pgStart,
|
InstList::const_iterator pgStart,
|
||||||
InstList::const_iterator pgEnd,
|
InstList::const_iterator pgEnd,
|
||||||
CGuiWidget::EGuiModelDrawFlags df) const {
|
CGuiWidget::EGuiModelDrawFlags df) const {
|
||||||
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df);
|
CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally);//, df);
|
||||||
|
|
||||||
{
|
{
|
||||||
CFontRenderState rendState;
|
CFontRenderState rendState;
|
||||||
|
@ -71,7 +71,7 @@ std::list<CTextRenderBuffer> CTextExecuteBuffer::BuildRenderBufferPages(const ze
|
||||||
std::list<CTextRenderBuffer> ret;
|
std::list<CTextRenderBuffer> ret;
|
||||||
|
|
||||||
for (auto it = x0_instList.begin(); it != x0_instList.end();) {
|
for (auto it = x0_instList.begin(); it != x0_instList.end();) {
|
||||||
CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally, df);
|
CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally);//, df);
|
||||||
|
|
||||||
{
|
{
|
||||||
CFontRenderState rstate;
|
CFontRenderState rstate;
|
||||||
|
|
|
@ -12,285 +12,29 @@
|
||||||
|
|
||||||
namespace metaforce {
|
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(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() = default;
|
||||||
|
|
||||||
CTextRenderBuffer& CTextRenderBuffer::operator=(CTextRenderBuffer&&) noexcept = 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) {
|
void CTextRenderBuffer::SetPrimitive(const Primitive& prim, s32 idx) {
|
||||||
CMemoryStreamOut out(reinterpret_cast<u8*>(x34_bytecode.data() + x24_primOffsets[idx]),
|
CMemoryStreamOut out(reinterpret_cast<u8*>(x34_bytecode.data() + x24_primOffsets[idx]),
|
||||||
x44_blobSize - x24_primOffsets[idx]);
|
x44_blobSize - x24_primOffsets[idx]);
|
||||||
if (prim.x4_command == Command::ImageRender) {
|
if (prim.x4_command == Command::ImageRender) {
|
||||||
out.WriteUint8(1);
|
out.WriteUint8(static_cast<u8>(Command::ImageRender));
|
||||||
out.Put(prim.x8_xPos);
|
out.Put(prim.x8_xPos);
|
||||||
out.Put(prim.xa_zPos);
|
out.Put(prim.xa_zPos);
|
||||||
out.Put(prim.xe_imageIndex);
|
out.Put(prim.xe_imageIndex);
|
||||||
// out.Put(prim.x0_color1.toRGBA());
|
out.Put(prim.x0_color1.toRGBA());
|
||||||
} else if (prim.x4_command == Command::CharacterRender) {
|
} 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.x8_xPos);
|
||||||
out.Put(prim.xa_zPos);
|
out.Put(prim.xa_zPos);
|
||||||
out.Put(u16(prim.xc_glyph));
|
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};
|
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
|
} // namespace metaforce
|
||||||
|
|
|
@ -27,7 +27,8 @@ class CTextRenderBuffer {
|
||||||
friend class CTextSupportShader;
|
friend class CTextSupportShader;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Command { CharacterRender, ImageRender, FontChange, PaletteChange, Invalid };
|
enum class Command { CharacterRender, ImageRender, FontChange, PaletteChange, Invalid = -1 };
|
||||||
|
#if 1
|
||||||
struct Primitive {
|
struct Primitive {
|
||||||
CTextColor x0_color1;
|
CTextColor x0_color1;
|
||||||
Command x4_command;
|
Command x4_command;
|
||||||
|
@ -36,6 +37,7 @@ public:
|
||||||
char16_t xc_glyph;
|
char16_t xc_glyph;
|
||||||
u8 xe_imageIndex;
|
u8 xe_imageIndex;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
enum class EMode { AllocTally, BufferFill };
|
enum class EMode { AllocTally, BufferFill };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -46,34 +48,37 @@ private:
|
||||||
std::vector<char> x34_bytecode;
|
std::vector<char> x34_bytecode;
|
||||||
u32 x44_blobSize = 0;
|
u32 x44_blobSize = 0;
|
||||||
u32 x48_curBytecodeOffset = 0;
|
u32 x48_curBytecodeOffset = 0;
|
||||||
u8 x4c_activeFont;
|
s8 x4c_activeFont = -1;
|
||||||
u32 x50_paletteCount = 0;
|
s8 x4d_ = -1;
|
||||||
std::array<std::unique_ptr<CGraphicsPalette>, 64> x54_palettes;
|
s8 x4e_ = -1;
|
||||||
u32 x254_nextPalette = 0;
|
s8 x4f_curPalette = -1;
|
||||||
|
rstl::reserved_vector<std::unique_ptr<CGraphicsPalette>, 64> x50_palettes;
|
||||||
|
s32 x254_nextPalette = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CTextRenderBuffer(CTextRenderBuffer&& other) noexcept;
|
CTextRenderBuffer(CTextRenderBuffer&& other) noexcept;
|
||||||
CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df);
|
CTextRenderBuffer(EMode mode);
|
||||||
~CTextRenderBuffer();
|
~CTextRenderBuffer();
|
||||||
|
|
||||||
CTextRenderBuffer& operator=(CTextRenderBuffer&& other) noexcept;
|
CTextRenderBuffer& operator=(CTextRenderBuffer&& other) noexcept;
|
||||||
|
|
||||||
void SetPrimitive(const Primitive&, int);
|
void SetPrimitive(const Primitive&, int);
|
||||||
[[nodiscard]] Primitive GetPrimitive(int) const;
|
[[nodiscard]] Primitive GetPrimitive(int) const;
|
||||||
void GetOutStream();
|
[[nodiscard]] u32 GetPrimitiveCount() const { return x24_primOffsets.size(); }
|
||||||
|
[[nodiscard]] u8* GetOutStream();
|
||||||
|
[[nodiscard]] u32 GetCurLen();
|
||||||
void VerifyBuffer();
|
void VerifyBuffer();
|
||||||
int GetMatchingPaletteIndex(const CGraphicsPalette& palette);
|
int GetMatchingPaletteIndex(const CGraphicsPalette& palette);
|
||||||
CGraphicsPalette* GetNextAvailablePalette();
|
[[nodiscard]] CGraphicsPalette* GetNextAvailablePalette();
|
||||||
void AddPaletteChange(const CGraphicsPalette& palette);
|
void AddPaletteChange(const CGraphicsPalette& palette);
|
||||||
void SetMode(EMode mode);
|
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 AddImage(const zeus::CVector2i& offset, const CFontImageDef& image);
|
||||||
void AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color);
|
void AddCharacter(const zeus::CVector2i& offset, char16_t ch, const CTextColor& color);
|
||||||
void AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline);
|
|
||||||
void AddFontChange(const TToken<CRasterFont>& font);
|
void AddFontChange(const TToken<CRasterFont>& font);
|
||||||
|
|
||||||
bool HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) const;
|
[[nodiscard]] bool HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent);
|
||||||
std::pair<zeus::CVector2i, zeus::CVector2i> AccumulateTextBounds() const;
|
[[nodiscard]] std::pair<zeus::CVector2i, zeus::CVector2i> AccumulateTextBounds();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
|
|
@ -5,8 +5,8 @@ namespace metaforce {
|
||||||
class CMemoryInStream final : public CInputStream {
|
class CMemoryInStream final : public CInputStream {
|
||||||
public:
|
public:
|
||||||
enum class EOwnerShip {
|
enum class EOwnerShip {
|
||||||
NotOwned,
|
|
||||||
Owned,
|
Owned,
|
||||||
|
NotOwned,
|
||||||
};
|
};
|
||||||
|
|
||||||
CMemoryInStream(const void* ptr, u32 len) : CInputStream(ptr, len, false) {}
|
CMemoryInStream(const void* ptr, u32 len) : CInputStream(ptr, len, false) {}
|
||||||
|
|
|
@ -5,8 +5,8 @@ namespace metaforce {
|
||||||
class CMemoryStreamOut final : public COutputStream {
|
class CMemoryStreamOut final : public COutputStream {
|
||||||
public:
|
public:
|
||||||
enum class EOwnerShip {
|
enum class EOwnerShip {
|
||||||
NotOwned,
|
|
||||||
Owned,
|
Owned,
|
||||||
|
NotOwned,
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
COutputStream(s32 unk);
|
COutputStream(s32 unk);
|
||||||
virtual ~COutputStream();
|
virtual ~COutputStream();
|
||||||
|
|
||||||
|
u32 GetNumWrites() const { return x10_numWrites; }
|
||||||
void WriteBits(u32 val, u32 bitCount);
|
void WriteBits(u32 val, u32 bitCount);
|
||||||
void WriteChar(u8 c);
|
void WriteChar(u8 c);
|
||||||
void WriteShort(u16 s);
|
void WriteShort(u16 s);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8e4dfb022a97aee2c245d8a2ec9b92ce3d865fbd
|
Subproject commit 8410394d4bd90f8783b68ab064b13d838e29d6a1
|
Loading…
Reference in New Issue