chore: initial commit

This commit is contained in:
fallenoak 2023-01-02 13:17:18 -06:00
commit 70b00c5c38
No known key found for this signature in database
GPG key ID: 7628F8E61AEA070D
965 changed files with 264882 additions and 0 deletions

View file

@ -0,0 +1,351 @@
#include "ui/CBackdropGenerator.hpp"
#include "ui/CSimpleFrame.hpp"
#include "ui/CSimpleTexture.hpp"
#include "ui/LoadXML.hpp"
#include "ui/Util.hpp"
#include "util/CStatus.hpp"
#include "util/StringTo.hpp"
#include <common/XML.hpp>
#include <storm/Error.hpp>
CBackdropGenerator::CBackdropGenerator() {
this->m_color.Set(1.0f, 1.0f, 1.0f, 1.0f);
this->m_borderColor.Set(1.0f, 1.0f, 1.0f, 1.0f);
}
void CBackdropGenerator::Generate(const CRect* rect) {
STORM_ASSERT(rect);
C2Vector texCoords[4];
float v3 = rect->maxX - rect->minX;
float v7 = rect->maxY - rect->minY;
float v4 = 1.0f / this->m_cornerSize;
float v5 = v4 * v3 - 2.0f;
float v9 = v4 * v7 - 2.0f;
float v34 = v5 < 0.0f ? 0.0f : v5;
float v17 = v9 < 0.0f ? 0.0f : v9;
const char* background = this->m_background.GetString();
if (background && *background && this->m_tileBackground) {
float v13 = this->m_backgroundSize == 0.0f
? this->m_cornerSize
: this->m_backgroundSize;
texCoords[0] = { 0.0f, 0.0f };
texCoords[1] = { 0.0f, v7 / v13 };
texCoords[2] = { v3 / v13, 0.0f };
texCoords[3] = { v3 / v13, v7 / v13 };
this->m_backgroundTexture->SetTexCoord(texCoords);
}
if (this->m_pieces & 0x1) {
texCoords[0] = { 0.0078125f, 0.0625f };
texCoords[1] = { 0.0078125f, v17 - 0.0625f };
texCoords[2] = { 0.1171875f, 0.0625f };
texCoords[3] = { 0.1171875f, v17 - 0.0625f };
this->m_leftTexture->SetTexCoord(texCoords);
}
if (this->m_pieces & 0x2) {
texCoords[0] = { 0.1328125f, 0.0625f };
texCoords[1] = { 0.1328125f, v17 - 0.0625f };
texCoords[2] = { 0.2421875f, 0.0625f };
texCoords[3] = { 0.2421875f, v17 - 0.0625f };
this->m_rightTexture->SetTexCoord(texCoords);
}
if (this->m_pieces & 0x4) {
texCoords[0] = { 0.2578125f, v34 - 0.0625f };
texCoords[1] = { 0.3671875f, v34 - 0.0625f };
texCoords[2] = { 0.2578125f, 0.0625f };
texCoords[3] = { 0.3671875f, 0.0625f };
this->m_topTexture->SetTexCoord(texCoords);
}
if (this->m_pieces & 0x8) {
texCoords[0] = { 0.3828125f, v34 - 0.0625f };
texCoords[1] = { 0.4921875f, v34 - 0.0625f };
texCoords[2] = { 0.3828125f, 0.0625f };
texCoords[3] = { 0.4921875f, 0.0625f };
this->m_bottomTexture->SetTexCoord(texCoords);
}
if (this->m_backgroundTexture) {
this->m_backgroundTexture->SetVertexColor(this->m_color);
}
this->SetBorderVertexColor(this->m_borderColor);
}
void CBackdropGenerator::LoadXML(XMLNode* node, CStatus* status) {
const char* bgFileAttr = node->GetAttributeByName("bgFile");
const char* edgeFileAttr = node->GetAttributeByName("edgeFile");
const char* tileAttr = node->GetAttributeByName("tile");
const char* alphaModeAttr = node->GetAttributeByName("alphaMode");
this->m_background.Copy(bgFileAttr);
this->m_border.Copy(edgeFileAttr);
this->m_tileBackground = tileAttr && *tileAttr
? StringToBOOL(tileAttr)
: 0;
this->m_pieces = edgeFileAttr && *edgeFileAttr
? 0xFF
: 0;
this->m_blend = GxBlend_Alpha;
if (alphaModeAttr && *alphaModeAttr) {
StringToBlendMode(alphaModeAttr, this->m_blend);
}
for (auto child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "TileSize", STORM_MAX_STR)) {
float backgroundSize;
if (LoadXML_Value(child, backgroundSize, status)) {
this->m_backgroundSize = backgroundSize;
}
} else if (!SStrCmpI(child->GetName(), "EdgeSize", STORM_MAX_STR)) {
float cornerSize;
if (LoadXML_Value(child, cornerSize, status)) {
this->m_cornerSize = cornerSize;
}
} else if (!SStrCmpI(child->GetName(), "BackgroundInsets", STORM_MAX_STR)) {
float leftInset, rightInset, topInset, bottomInset;
if (LoadXML_Insets(child, leftInset, rightInset, topInset, bottomInset, status)) {
this->m_leftInset = leftInset;
this->m_rightInset = rightInset;
this->m_topInset = topInset;
this->m_bottomInset = bottomInset;
}
} else if (!SStrCmpI(child->GetName(), "Color", STORM_MAX_STR)) {
// TODO
} else if (!SStrCmpI(child->GetName(), "BorderColor", STORM_MAX_STR)) {
// TODO
} else {
status->Add(
STATUS_WARNING,
"Unknown child node in %s element: %s",
node->GetName(),
child->GetName()
);
}
}
}
void CBackdropGenerator::SetBorderVertexColor(const CImVector& borderColor) {
// TODO
}
void CBackdropGenerator::SetOutput(CSimpleFrame* frame) {
STORM_ASSERT(frame);
C2Vector texCoords[4];
const char* background = this->m_background.GetString();
const char* border = this->m_border.GetString();
if (background && *background) {
// TODO
// CSimpleTexture* backgroundTexture = CSimpleTexture::s_allocator.GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
CSimpleTexture* backgroundTexture = new (m) CSimpleTexture(frame, DRAWLAYER_BACKGROUND, 1);
this->m_backgroundTexture = backgroundTexture;
backgroundTexture->SetPoint(FRAMEPOINT_TOPLEFT, frame, FRAMEPOINT_TOPLEFT, this->m_leftInset, -this->m_topInset, 0);
backgroundTexture->SetPoint(FRAMEPOINT_TOPRIGHT, frame, FRAMEPOINT_TOPRIGHT, -this->m_rightInset, -this->m_topInset, 0);
backgroundTexture->SetPoint(FRAMEPOINT_BOTTOMLEFT, frame, FRAMEPOINT_BOTTOMLEFT, this->m_leftInset, this->m_bottomInset, 0);
backgroundTexture->SetPoint(FRAMEPOINT_BOTTOMRIGHT, frame, FRAMEPOINT_BOTTOMRIGHT, -this->m_rightInset, this->m_topInset, 0);
backgroundTexture->Resize(0);
backgroundTexture->SetTexture(background, this->m_tileBackground, 0, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
}
if (this->m_pieces & 0x1) {
// TODO
// CSimpleTexture* leftTexture = CSimpleTexture::s_allocator.GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
CSimpleTexture* leftTexture = new (m) CSimpleTexture(frame, DRAWLAYER_BACKGROUND_BORDER, 1);
this->m_leftTexture = leftTexture;
leftTexture->SetWidth(this->m_cornerSize);
leftTexture->SetPoint(FRAMEPOINT_TOPLEFT, frame, FRAMEPOINT_TOPLEFT, 0.0f, -this->m_cornerSize, 0);
leftTexture->SetPoint(FRAMEPOINT_BOTTOMLEFT, frame, FRAMEPOINT_BOTTOMLEFT, 0.0f, this->m_cornerSize, 0);
leftTexture->Resize(0);
leftTexture->SetTexture(border, 1, 1, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
leftTexture->SetBlendMode(this->m_blend);
}
if (this->m_pieces & 0x2) {
// TODO
// CSimpleTexture* rightTexture = CSimpleTexture::s_allocator.GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
CSimpleTexture* rightTexture = new (m) CSimpleTexture(frame, DRAWLAYER_BACKGROUND_BORDER, 1);
this->m_rightTexture = rightTexture;
rightTexture->SetWidth(this->m_cornerSize);
rightTexture->SetPoint(FRAMEPOINT_TOPRIGHT, frame, FRAMEPOINT_TOPRIGHT, 0.0f, -this->m_cornerSize, 0);
rightTexture->SetPoint(FRAMEPOINT_BOTTOMRIGHT, frame, FRAMEPOINT_BOTTOMRIGHT, 0.0f, this->m_cornerSize, 0);
rightTexture->Resize(0);
rightTexture->SetTexture(border, 1, 1, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
rightTexture->SetBlendMode(this->m_blend);
}
if (this->m_pieces & 0x4) {
// TODO
// CSimpleTexture* topTexture = CSimpleTexture::s_allocator.GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
CSimpleTexture* topTexture = new (m) CSimpleTexture(frame, DRAWLAYER_BACKGROUND_BORDER, 1);
this->m_topTexture = topTexture;
topTexture->SetHeight(this->m_cornerSize);
topTexture->SetPoint(FRAMEPOINT_TOPLEFT, frame, FRAMEPOINT_TOPLEFT, this->m_cornerSize, 0.0f, 0);
topTexture->SetPoint(FRAMEPOINT_TOPRIGHT, frame, FRAMEPOINT_TOPRIGHT, -this->m_cornerSize, 0.0f, 0);
topTexture->Resize(0);
topTexture->SetTexture(border, 1, 1, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
topTexture->SetBlendMode(this->m_blend);
}
if (this->m_pieces & 0x8) {
// TODO
// CSimpleTexture* bottomTexture = CSimpleTexture::s_allocator.GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
CSimpleTexture* bottomTexture = new (m) CSimpleTexture(frame, DRAWLAYER_BACKGROUND_BORDER, 1);
this->m_bottomTexture = bottomTexture;
bottomTexture->SetHeight(this->m_cornerSize);
bottomTexture->SetPoint(FRAMEPOINT_BOTTOMLEFT, frame, FRAMEPOINT_BOTTOMLEFT, this->m_cornerSize, 0.0f, 0);
bottomTexture->SetPoint(FRAMEPOINT_BOTTOMRIGHT, frame, FRAMEPOINT_BOTTOMRIGHT, -this->m_cornerSize, 0.0f, 0);
bottomTexture->Resize(0);
bottomTexture->SetTexture(border, 1, 1, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
bottomTexture->SetBlendMode(this->m_blend);
}
if (this->m_pieces & 0x10) {
// TODO
// CSimpleTexture* topLeftTexture = CSimpleTexture::s_allocator.GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
CSimpleTexture* topLeftTexture = new (m) CSimpleTexture(frame, DRAWLAYER_BACKGROUND_BORDER, 1);
this->m_topLeftTexture = topLeftTexture;
topLeftTexture->SetWidth(this->m_cornerSize);
topLeftTexture->SetHeight(this->m_cornerSize);
topLeftTexture->SetPoint(FRAMEPOINT_TOPLEFT, frame, FRAMEPOINT_TOPLEFT, 0.0f, 0.0f, 1);
texCoords[0] = { 0.5078125f, 0.0625f };
texCoords[1] = { 0.5078125f, 0.9375f };
texCoords[2] = { 0.6171875f, 0.0625f };
texCoords[3] = { 0.6171875f, 0.9375f };
topLeftTexture->SetTexture(border, 0, 0, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
topLeftTexture->SetTexCoord(texCoords);
topLeftTexture->SetBlendMode(this->m_blend);
}
if (this->m_pieces & 0x20) {
// TODO
// CSimpleTexture* topRightTexture = CSimpleTexture::s_allocator.GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
CSimpleTexture* topRightTexture = new (m) CSimpleTexture(frame, DRAWLAYER_BACKGROUND_BORDER, 1);
this->m_topRightTexture = topRightTexture;
topRightTexture->SetWidth(this->m_cornerSize);
topRightTexture->SetHeight(this->m_cornerSize);
topRightTexture->SetPoint(FRAMEPOINT_TOPRIGHT, frame, FRAMEPOINT_TOPRIGHT, 0.0f, 0.0f, 1);
texCoords[0] = { 0.6328125f, 0.0625f };
texCoords[1] = { 0.6328125f, 0.9375f };
texCoords[2] = { 0.7421875f, 0.0625f };
texCoords[3] = { 0.7421875f, 0.9375f };
topRightTexture->SetTexture(border, 0, 0, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
topRightTexture->SetTexCoord(texCoords);
topRightTexture->SetBlendMode(this->m_blend);
}
if (this->m_pieces & 0x40) {
// TODO
// CSimpleTexture* bottomLeftTexture = CSimpleTexture::s_allocator.GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
CSimpleTexture* bottomLeftTexture = new (m) CSimpleTexture(frame, DRAWLAYER_BACKGROUND_BORDER, 1);
this->m_bottomLeftTexture = bottomLeftTexture;
bottomLeftTexture->SetWidth(this->m_cornerSize);
bottomLeftTexture->SetHeight(this->m_cornerSize);
bottomLeftTexture->SetPoint(FRAMEPOINT_BOTTOMLEFT, frame, FRAMEPOINT_BOTTOMLEFT, 0.0f, 0.0f, 1);
texCoords[0] = { 0.7578125f, 0.0625f };
texCoords[1] = { 0.7578125f, 0.9375f };
texCoords[2] = { 0.8671875f, 0.0625f };
texCoords[3] = { 0.8671875f, 0.9375f };
bottomLeftTexture->SetTexture(border, 0, 0, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
bottomLeftTexture->SetTexCoord(texCoords);
bottomLeftTexture->SetBlendMode(this->m_blend);
}
if (this->m_pieces & 0x80) {
// TODO
// CSimpleTexture* bottomRightTexture = CSimpleTexture::s_allocator.GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
CSimpleTexture* bottomRightTexture = new (m) CSimpleTexture(frame, DRAWLAYER_BACKGROUND_BORDER, 1);
this->m_bottomRightTexture = bottomRightTexture;
bottomRightTexture->SetWidth(this->m_cornerSize);
bottomRightTexture->SetHeight(this->m_cornerSize);
bottomRightTexture->SetPoint(FRAMEPOINT_BOTTOMRIGHT, frame, FRAMEPOINT_BOTTOMRIGHT, 0.0f, 0.0f, 1);
texCoords[0] = { 0.8828125f, 0.0625f };
texCoords[1] = { 0.8828125f, 0.9375f };
texCoords[2] = { 0.9921875f, 0.0625f };
texCoords[3] = { 0.9921875f, 0.9375f };
bottomRightTexture->SetTexture(border, 0, 0, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
bottomRightTexture->SetTexCoord(texCoords);
bottomRightTexture->SetBlendMode(this->m_blend);
}
}

View file

@ -0,0 +1,49 @@
#ifndef UI_C_BACKDROP_GENERATOR_HPP
#define UI_C_BACKDROP_GENERATOR_HPP
#include "gx/Types.hpp"
#include <common/String.hpp>
#include <tempest/Vector.hpp>
class CRect;
class CSimpleFrame;
class CSimpleTexture;
class CStatus;
class XMLNode;
class CBackdropGenerator {
public:
// Member variables
CSimpleTexture* m_backgroundTexture = nullptr;
CSimpleTexture* m_leftTexture = nullptr;
CSimpleTexture* m_rightTexture = nullptr;
CSimpleTexture* m_topTexture = nullptr;
CSimpleTexture* m_bottomTexture = nullptr;
CSimpleTexture* m_topLeftTexture = nullptr;
CSimpleTexture* m_topRightTexture = nullptr;
CSimpleTexture* m_bottomLeftTexture = nullptr;
CSimpleTexture* m_bottomRightTexture = nullptr;
RCString m_background;
RCString m_border;
uint32_t m_pieces = 0;
int32_t m_tileBackground = 0;
int32_t int44;
float m_cornerSize = 0.025f;
float m_backgroundSize = 0.0f;
float m_topInset = 0.0f;
float m_bottomInset = 0.0f;
float m_leftInset = 0.0f;
float m_rightInset = 0.0f;
CImVector m_color = { 0x00 };
CImVector m_borderColor = { 0x00 };
EGxBlend m_blend;
// Member functions
CBackdropGenerator();
void Generate(const CRect*);
void LoadXML(XMLNode*, CStatus*);
void SetBorderVertexColor(const CImVector&);
void SetOutput(CSimpleFrame*);
};
#endif

146
src/ui/CFramePoint.cpp Normal file
View file

@ -0,0 +1,146 @@
#include "ui/CFramePoint.hpp"
#include "ui/CLayoutFrame.hpp"
const float CFramePoint::UNDEFINED = 3.4028237e38;
CFramePoint::CFramePoint(CLayoutFrame* relative, FRAMEPOINT framePoint, float offsetX, float offsetY) {
this->m_offset = { offsetX, offsetY };
this->m_framePoint = framePoint;
this->m_relative = relative;
// TODO
// - this doesn't appear to be zeroed out
// - what is it actually checking?
this->m_flags = (this->m_flags & 0x2) >= 1 ? 0x6 : 0;
}
CLayoutFrame* CFramePoint::GetRelative() {
return this->m_relative;
}
int32_t CFramePoint::GetRelativeRect(CRect& rect) {
bool flag2initial = this->m_flags & 0x2;
if (!flag2initial) {
this->m_flags |= 0x2;
}
this->m_flags &= ~0x4;
CLayoutFrame* relative = this->GetRelative();
if (relative->IsResizePending()) {
relative->Resize(1);
if (this->m_flags & 0x4) {
if (!flag2initial) {
this->m_flags &= ~0x2;
}
return 0;
}
}
if (relative->m_flags & 0x2) {
relative->SetDeferredResize(0);
if (this->m_flags & 0x4) {
if (!flag2initial) {
this->m_flags &= ~0x2;
}
return 0;
}
}
if (!relative->GetRect(&rect)) {
if (!flag2initial) {
this->m_flags &= ~0x2;
}
return 0;
}
if (relative->IsAttachmentOrigin()) {
rect.minY -= rect.minY;
rect.minX -= rect.minX;
rect.maxY -= rect.minY;
rect.maxX -= rect.minX;
}
if (!flag2initial) {
this->m_flags &= ~0x2;
}
return 1;
}
void CFramePoint::MarkUnused() {
this->m_framePoint = FRAMEPOINT_NUMPOINTS;
this->m_offset = { 0.0f, 0.0f };
this->m_relative = nullptr;
this->m_flags = this->m_flags & 0x2 ? 0x2 | 0x4 | 0x8 : 0x8;
}
void CFramePoint::SetRelative(CLayoutFrame* relative, FRAMEPOINT relativePoint, float offsetX, float offsetY) {
this->m_offset = { offsetX, offsetY };
this->m_framePoint = relativePoint;
this->m_relative = relative;
this->m_flags = this->m_flags & 0x2 ? 0x2 | 0x4 : 0x0;
}
float CFramePoint::X(float scale) {
CRect relative = { 0.0f, 0.0f, 0.0f, 0.0f };
if (!this->GetRelativeRect(relative)) {
return UNDEFINED;
}
switch (this->m_framePoint) {
case FRAMEPOINT_TOPLEFT:
case FRAMEPOINT_LEFT:
case FRAMEPOINT_BOTTOMLEFT:
return relative.minX + (this->m_offset.x * scale);
case FRAMEPOINT_TOP:
case FRAMEPOINT_CENTER:
case FRAMEPOINT_BOTTOM:
return ((relative.minX + relative.maxX) * 0.5f) + (this->m_offset.x * scale);
case FRAMEPOINT_TOPRIGHT:
case FRAMEPOINT_RIGHT:
case FRAMEPOINT_BOTTOMRIGHT:
return relative.maxX + (this->m_offset.x * scale);
default:
return UNDEFINED;
}
}
float CFramePoint::Y(float scale) {
CRect relative = { 0.0f, 0.0f, 0.0f, 0.0f };
if (!this->GetRelativeRect(relative)) {
return UNDEFINED;
}
switch (this->m_framePoint) {
case FRAMEPOINT_TOPLEFT:
case FRAMEPOINT_TOP:
case FRAMEPOINT_TOPRIGHT:
return relative.maxY + (this->m_offset.y * scale);
case FRAMEPOINT_LEFT:
case FRAMEPOINT_CENTER:
case FRAMEPOINT_RIGHT:
return ((relative.minY + relative.maxY) * 0.5f) + (this->m_offset.y * scale);
case FRAMEPOINT_BOTTOMLEFT:
case FRAMEPOINT_BOTTOM:
case FRAMEPOINT_BOTTOMRIGHT:
return relative.minY + (this->m_offset.y * scale);
default:
return UNDEFINED;
}
}

32
src/ui/CFramePoint.hpp Normal file
View file

@ -0,0 +1,32 @@
#ifndef UI_C_FRAME_POINT_HPP
#define UI_C_FRAME_POINT_HPP
#include "ui/Types.hpp"
#include <cstdint>
#include <tempest/Vector.hpp>
class CLayoutFrame;
class CRect;
class CFramePoint {
public:
// Static variables
static float const UNDEFINED;
// Member variables
C2Vector m_offset;
CLayoutFrame* m_relative;
uint32_t m_framePoint : 8;
uint32_t m_flags : 24;
// Member functions
CFramePoint(CLayoutFrame*, FRAMEPOINT, float, float);
CLayoutFrame* GetRelative();
int32_t GetRelativeRect(CRect&);
void MarkUnused(void);
void SetRelative(CLayoutFrame*, FRAMEPOINT, float, float);
float X(float);
float Y(float);
};
#endif

168
src/ui/CFrameStrata.cpp Normal file
View file

@ -0,0 +1,168 @@
#include "ui/CFrameStrata.hpp"
#include "ui/CSimpleFrame.hpp"
#include "ui/CSimpleRender.hpp"
int32_t CFrameStrataNode::BuildBatches() {
if (!this->batchDirty) {
return 0;
}
int32_t batchDirty = this->batchDirty;
this->batchDirty = 0;
for (int32_t layer = 0; layer < NUM_SIMPLEFRAME_DRAWLAYERS; layer++) {
CRenderBatch* batch = &this->batches[layer];
this->renderList.UnlinkNode(batch);
if ((1 << layer) & batchDirty) {
batch->Clear();
for (auto frame = this->frames.Head(); frame; frame = this->frames.Link(frame)->Next()) {
if (!(frame->m_flags & 0x2000)) {
frame->OnFrameRender(batch, layer);
}
}
batch->Finish();
}
if (batch->m_count) {
this->renderList.LinkToTail(batch);
}
}
if (this->batchDirty & 0x20) {
this->batchDirty |= 0x1F;
}
return 0;
}
void CFrameStrataNode::OnLayerUpdate(float elapsedSec) {
auto frame = this->frames.Head();
while (frame) {
auto next = this->frames.Link(frame)->Next();
this->pendingFrame = next;
frame->OnLayerUpdate(elapsedSec);
frame = this->pendingFrame;
}
// TODO
// this->frames.Combine(this->pendingFrames, 2, nullptr);
}
bool CFrameStrataNode::RemoveFrame(CSimpleFrame* frame) {
if (!this->frames.Link(frame)->IsLinked()) {
return 0;
}
if (frame == this->pendingFrame) {
this->pendingFrame = this->frames.Link(frame)->Next();
}
this->frames.UnlinkNode(frame);
if (!(frame->m_flags & 0x2000)) {
this->batchDirty = -1;
}
return this->batchDirty != 0;
}
void CFrameStrata::AddFrame(CSimpleFrame* frame) {
// TODO
// - potentially an inlined TSFixedArray function?
if (frame->m_level >= this->levels.Count()) {
uint32_t count = this->levels.Count();
this->levels.SetCount(frame->m_level + 1);
for (int32_t i = count; i < frame->m_level + 1; i++) {
void* m = SMemAlloc(sizeof(CFrameStrataNode), __FILE__, __LINE__, 0);
CFrameStrataNode* node = m ? new (m) CFrameStrataNode() : nullptr;
this->levels[i] = node;
}
}
if (frame->m_level >= this->topLevel) {
this->topLevel = frame->m_level + 1;
}
auto level = this->levels[frame->m_level];
if (!frame->m_strataLink.IsLinked()) {
auto frames = level->pendingFrame ? &level->pendingFrames : &level->frames;
frames->LinkToTail(frame);
if (!(frame->m_flags & 0x2000)) {
level->batchDirty = -1;
}
}
this->levelsDirty = 1;
this->batchDirty |= (level->batchDirty != 0);
}
void CFrameStrata::CheckOcclusion() {
// TODO
}
int32_t CFrameStrata::BuildBatches(int32_t a2) {
if (this->levelsDirty) {
this->CheckOcclusion();
this->levelsDirty = 0;
}
if (!this->batchDirty) {
return this->batchDirty;
}
this->batchDirty = 0;
if (this->topLevel == 0) {
return 0;
}
for (int32_t i = 0; i < this->topLevel; i++) {
if (this->levels[i]->BuildBatches()) {
this->batchDirty = 1;
}
}
return this->batchDirty;
}
int32_t CFrameStrata::FrameOccluded(CSimpleFrame* frame) {
// TODO
return 0;
}
void CFrameStrata::OnLayerUpdate(float elapsedSec) {
if (this->topLevel) {
for (int32_t l = 0; l < this->topLevel; l++) {
this->levels[l]->OnLayerUpdate(elapsedSec);
}
}
}
void CFrameStrata::RemoveFrame(CSimpleFrame* frame) {
if (frame->m_level < this->levels.Count()) {
CFrameStrataNode* level = this->levels[frame->m_level];
int32_t batchDirty = level->RemoveFrame(frame);
this->batchDirty |= batchDirty;
this->levelsDirty = 1;
}
}
void CFrameStrata::RenderBatches() {
for (int32_t i = 0; i < this->topLevel; i++) {
auto renderList = &this->levels[i]->renderList;
for (auto batch = renderList->Head(); batch; batch = renderList->Link(batch)->Next()) {
CSimpleRender::DrawBatch(batch);
}
}
}

44
src/ui/CFrameStrata.hpp Normal file
View file

@ -0,0 +1,44 @@
#ifndef UI_C_FRAME_STRATA_HPP
#define UI_C_FRAME_STRATA_HPP
#include "ui/CRenderBatch.hpp"
#include "ui/CSimpleFrame.hpp"
#include <cstdint>
#include <storm/Array.hpp>
#include <storm/List.hpp>
class CFrameStrataNode {
public:
// Member variables
STORM_EXPLICIT_LIST(CSimpleFrame, m_strataLink) pendingFrames;
STORM_EXPLICIT_LIST(CSimpleFrame, m_strataLink) frames;
CSimpleFrame* pendingFrame = nullptr;
CRenderBatch batches[5];
int32_t batchDirty = 0;
STORM_EXPLICIT_LIST(CRenderBatch, renderLink) renderList;
// Member functions
int32_t BuildBatches(void);
void OnLayerUpdate(float);
bool RemoveFrame(CSimpleFrame*);
};
class CFrameStrata {
public:
// Member variables
int32_t batchDirty = 0;
int32_t levelsDirty = 0;
uint32_t topLevel = 0;
TSFixedArray<CFrameStrataNode*> levels;
// Member functions
void AddFrame(CSimpleFrame*);
int32_t BuildBatches(int32_t);
void CheckOcclusion(void);
int32_t FrameOccluded(CSimpleFrame*);
void OnLayerUpdate(float);
void RemoveFrame(CSimpleFrame*);
void RenderBatches(void);
};
#endif

920
src/ui/CLayoutFrame.cpp Normal file
View file

@ -0,0 +1,920 @@
#include "ui/CLayoutFrame.hpp"
#include "gx/Coordinate.hpp"
#include "math/Utils.hpp"
#include "ui/CFramePoint.hpp"
#include "ui/FrameXML.hpp"
#include "ui/LoadXML.hpp"
#include "util/CStatus.hpp"
#include <common/XML.hpp>
#include <storm/Error.hpp>
STORM_EXPLICIT_LIST(CLayoutFrame, resizeLink) LayoutFrame::s_resizePendingList;
float SynthesizeSide(float center, float opposite, float size) {
if (center != CFramePoint::UNDEFINED && opposite != CFramePoint::UNDEFINED) {
return center + center - opposite;
} else if (opposite != CFramePoint::UNDEFINED && size != 0.0f) {
return opposite + size;
} else if (center != CFramePoint::UNDEFINED && size != 0.0f) {
return center + (size * 0.5f);
} else {
return CFramePoint::UNDEFINED;
}
}
float SynthesizeCenter(float side1, float side2, float size) {
if (side1 != CFramePoint::UNDEFINED && side2 != CFramePoint::UNDEFINED) {
return (side1 + side2) * 0.5f;
} else if (side1 != CFramePoint::UNDEFINED && size != 0.0f) {
return side1 + (size * 0.5f);
} else if (side2 != CFramePoint::UNDEFINED && size != 0.0f) {
return side2 - (size * 0.5f);
} else {
return CFramePoint::UNDEFINED;
}
}
void CLayoutFrame::ResizePending() {
int32_t loading = 0;
for (CLayoutFrame* frame = LayoutFrame::s_resizePendingList.Head(); frame && loading < 32; frame = LayoutFrame::s_resizePendingList.Link(frame)->Next()) {
if (!frame->IsObjectLoaded()) {
loading++;
continue;
}
if (frame->OnFrameResize() || (frame->m_resizeCounter--, frame->m_resizeCounter == 0)) {
frame->m_flags &= ~0x4;
LayoutFrame::s_resizePendingList.UnlinkNode(frame);
}
}
}
CLayoutFrame::CLayoutFrame() {
this->m_flags = 0;
this->m_rect = { 0.0, 0.0, 0.0, 0.0 };
this->m_width = 0.0;
this->m_height = 0.0;
this->m_layoutScale = 1.0;
this->m_layoutDepth = 1.0;
this->m_guard = { 0 };
}
CLayoutFrame::~CLayoutFrame() {
this->DestroyLayout();
// TODO
}
void CLayoutFrame::AddToResizeList() {
if (LayoutFrame::s_resizePendingList.IsLinked(this)) {
return;
}
CLayoutFrame* dependent = nullptr;
for (auto frame = LayoutFrame::s_resizePendingList.Head(); frame; frame = LayoutFrame::s_resizePendingList.Link(frame)->Next()) {
for (int32_t i = 0; i < FRAMEPOINT_NUMPOINTS; i++) {
auto point = frame->m_points[i];
if (point && !(point->m_flags & 0x8) && point->GetRelative() == this) {
dependent = frame;
}
}
}
if (dependent) {
LayoutFrame::s_resizePendingList.LinkNode(this, 2, dependent);
} else {
LayoutFrame::s_resizePendingList.LinkToTail(this);
}
this->m_resizeCounter = 6;
}
float CLayoutFrame::Bottom() {
if (this->m_guard.bottom) {
return CFramePoint::UNDEFINED;
}
this->m_guard.bottom = 1;
static FRAMEPOINT sidepoints[] = {
FRAMEPOINT_BOTTOMLEFT,
FRAMEPOINT_BOTTOM,
FRAMEPOINT_BOTTOMRIGHT
};
float bottom = CFramePoint::UNDEFINED;
this->GetFirstPointY(sidepoints, 3, bottom);
if (bottom == CFramePoint::UNDEFINED) {
float size = -(this->GetHeight() * this->m_layoutScale);
float opposite = this->Top();
float center = this->CenterY();
bottom = SynthesizeSide(center, opposite, size);
}
this->m_guard.bottom = 0;
return bottom;
}
int32_t CLayoutFrame::CalculateRect(CRect* rect) {
rect->minX = this->Left();
if (rect->minX == CFramePoint::UNDEFINED) {
return 0;
}
rect->minY = this->Bottom();
if (rect->minY == CFramePoint::UNDEFINED) {
return 0;
}
rect->maxX = this->Right();
if (rect->maxX == CFramePoint::UNDEFINED) {
return 0;
}
rect->maxY = this->Top();
if (rect->maxY == CFramePoint::UNDEFINED) {
return 0;
}
if (!(this->m_flags & 0x10)) {
return 1;
}
float v14 = 0.0f;
float v15 = 0.0f;
float v16 = 0.0f;
float v17 = 0.0f;
this->GetClampRectInsets(v15, v17, v16, v14);
float v12 = -(this->m_layoutScale * v15);
float v7 = NDCToDDCWidth(1.0f);
float v13 = v7 - this->m_layoutScale * v17;
float v11 = -(this->m_layoutScale * v14);
float v8 = NDCToDDCHeight(1.0f);
float v9 = v8 - this->m_layoutScale * v16;
if (v12 > rect->minX) {
rect->maxX = rect->maxX - (rect->minX - v12);
rect->minX = v12;
}
if (v11 > rect->minY) {
rect->maxY = rect->maxY - (rect->minY - v11);
rect->minY = v11;
}
if (v13 < rect->maxX) {
rect->minX = rect->minX - (rect->maxX - v13);
rect->maxX = v13;
}
if (v9 < rect->maxY ) {
rect->minY = rect->minY - (rect->maxY - v9);
rect->maxY = v9;
}
return 1;
}
bool CLayoutFrame::CanBeAnchorFor(CLayoutFrame*) {
// TODO
return true;
}
float CLayoutFrame::CenterX() {
if (this->m_guard.centerX) {
return CFramePoint::UNDEFINED;
}
this->m_guard.centerX = 1;
static FRAMEPOINT sidepoints[] = {
FRAMEPOINT_TOP,
FRAMEPOINT_CENTER,
FRAMEPOINT_BOTTOM
};
float centerX = CFramePoint::UNDEFINED;
this->GetFirstPointX(sidepoints, 3, centerX);
if (centerX == CFramePoint::UNDEFINED) {
float size = this->GetWidth() * this->m_layoutScale;
float side2 = this->Right();
float side1 = this->Left();
centerX = SynthesizeCenter(side1, side2, size);
}
this->m_guard.centerX = 0;
return centerX;
}
float CLayoutFrame::CenterY() {
if (this->m_guard.centerY) {
return CFramePoint::UNDEFINED;
}
this->m_guard.centerY = 1;
static FRAMEPOINT sidepoints[] = {
FRAMEPOINT_LEFT,
FRAMEPOINT_CENTER,
FRAMEPOINT_RIGHT
};
float centerY = CFramePoint::UNDEFINED;
this->GetFirstPointY(sidepoints, 3, centerY);
if (centerY == CFramePoint::UNDEFINED) {
float size = this->GetHeight() * this->m_layoutScale;
float side2 = this->Top();
float side1 = this->Bottom();
centerY = SynthesizeCenter(side1, side2, size);
}
this->m_guard.centerY = 0;
return centerY;
}
void CLayoutFrame::ClearAllPoints() {
this->FreePoints();
}
void CLayoutFrame::DestroyLayout() {
for (int32_t i = 0; i < FRAMEPOINT_NUMPOINTS; i++) {
auto point = this->m_points[i];
if (point) {
if (!(point->m_flags & 0x8) && point->m_relative) {
point->m_relative->UnregisterResize(this, 1 << i);
}
delete point;
this->m_points[i] = nullptr;
}
}
for (auto node = this->m_resizeList.Head(); node; node = this->m_resizeList.Link(node)->Next()) {
auto frame = node->frame;
for (int32_t i = 0; i < FRAMEPOINT_NUMPOINTS; i++) {
auto point = this->m_points[i];
if (point && point->m_relative == this) {
point->MarkUnused();
}
}
frame->m_flags &= ~0x8;
}
this->m_resizeList.DeleteAll();
}
void CLayoutFrame::FreePoints() {
for (int32_t i = 0; i < FRAMEPOINT_NUMPOINTS; i++) {
auto point = this->m_points[i];
if (point && !(point->m_flags & 0x8)) {
if (point->m_relative) {
point->m_relative->UnregisterResize(this, 1 << i);
}
point->MarkUnused();
}
}
}
void CLayoutFrame::GetClampRectInsets(float& a1, float& a2, float& a3, float& a4) {
a4 = 0.0f;
a3 = 0.0f;
a2 = 0.0f;
a1 = 0.0f;
}
void CLayoutFrame::GetFirstPointX(const FRAMEPOINT* const pointarray, int32_t elements, float& x) {
// TODO
// - what's up with this loop?
for (int32_t i = 0; i < FRAMEPOINT_NUMPOINTS; i++) {
if (this->Sub488DB0(pointarray, elements, x)) {
break;
}
}
}
void CLayoutFrame::GetFirstPointY(const FRAMEPOINT* const pointarray, int32_t elements, float& y) {
// TODO
// - what's up with this loop?
for (int32_t i = 0; i < FRAMEPOINT_NUMPOINTS; i++) {
if (this->Sub488E40(pointarray, elements, y)) {
break;
}
}
}
CLayoutFrame* CLayoutFrame::GetLayoutFrameByName(const char* name) {
return nullptr;
}
CLayoutFrame* CLayoutFrame::GetLayoutParent() {
return nullptr;
}
int32_t CLayoutFrame::GetRect(CRect* rect) {
if (!(this->m_flags & 0x1)) {
return 0;
}
rect->minY = this->m_rect.minY;
rect->minX = this->m_rect.minX;
rect->maxY = this->m_rect.maxY;
rect->maxX = this->m_rect.maxX;
return 1;
}
float CLayoutFrame::GetHeight() {
return this->m_height;
}
float CLayoutFrame::GetWidth() {
return this->m_width;
}
int32_t CLayoutFrame::IsAttachmentOrigin() {
return 0;
}
int32_t CLayoutFrame::IsObjectLoaded() {
return 1;
}
int32_t CLayoutFrame::IsResizeDependency(CLayoutFrame* dependentFrame) {
CLayoutFrame* v2 = nullptr;
for (int32_t i = 0; i < FRAMEPOINT_NUMPOINTS; i++) {
auto framePoint = this->m_points[i];
if (!framePoint || framePoint->m_flags & 0x8) {
continue;
}
if (!framePoint->GetRelative() || framePoint->GetRelative() == v2) {
continue;
}
if (framePoint->GetRelative() == dependentFrame || framePoint->GetRelative()->IsResizeDependency(dependentFrame)) {
return 1;
}
v2 = framePoint->GetRelative();
}
return 0;
}
uint32_t CLayoutFrame::IsResizePending() {
return this->m_flags & 0x4;
}
float CLayoutFrame::Left() {
if (this->m_guard.left) {
return CFramePoint::UNDEFINED;
}
this->m_guard.left = 1;
static FRAMEPOINT sidepoints[] = {
FRAMEPOINT_TOPLEFT,
FRAMEPOINT_LEFT,
FRAMEPOINT_BOTTOMLEFT
};
float left = CFramePoint::UNDEFINED;
this->GetFirstPointX(sidepoints, 3, left);
if (left == CFramePoint::UNDEFINED) {
float size = -(this->GetWidth() * this->m_layoutScale);
float opposite = this->Right();
float center = this->CenterX();
left = SynthesizeSide(center, opposite, size);
}
this->m_guard.left = 0;
return left;
}
void CLayoutFrame::LoadXML(XMLNode* node, CStatus* status) {
XMLNode* size = node->GetChildByName("Size");
float width;
float height;
if (size && LoadXML_Dimensions(size, width, height, status)) {
this->SetWidth(width);
this->SetHeight(height);
}
CLayoutFrame* layoutParent = this->GetLayoutParent();
int32_t setAllPoints;
const char* setAllPointsAttr = node->GetAttributeByName("setAllPoints");
if (setAllPointsAttr && !SStrCmpI(setAllPointsAttr, "true", 0x7FFFFFFF)) {
setAllPoints = 1;
} else {
setAllPoints = 0;
}
const XMLNode* anchorsNode = node->GetChildByName("Anchors");
if (anchorsNode) {
if (setAllPoints) {
status->Add(
STATUS_WARNING,
"SETALLPOINTS set to true in frame with anchors (ignored)"
);
}
for (XMLNode* anchorNode = anchorsNode->m_child; anchorNode; anchorNode = anchorNode->m_next) {
const char* pointAttr = anchorNode->GetAttributeByName("point");
FRAMEPOINT point;
if (!pointAttr || !StringToFramePoint(pointAttr, point)) {
status->Add(
STATUS_WARNING,
"Invalid anchor point in frame: %s",
pointAttr
);
continue;
}
const char* relativePointAttr = anchorNode->GetAttributeByName("relativePoint");
FRAMEPOINT relativePoint;
if (relativePointAttr && *relativePointAttr) {
if (!StringToFramePoint(relativePointAttr, relativePoint)) {
status->Add(
STATUS_WARNING,
"Invalid anchor point in frame: %s",
relativePointAttr
);
continue;
}
} else {
relativePoint = point;
}
const char* relativeToAttr = anchorNode->GetAttributeByName("relativeTo");
CLayoutFrame* relative;
if (!relativeToAttr || !*relativeToAttr) {
relative = layoutParent;
} else {
relative = this->GetLayoutFrameByName(relativeToAttr);
if (!relative) {
status->Add(
STATUS_WARNING,
"Couldn't find relative frame: %s",
relativeToAttr
);
continue;
}
if (relative && relative == this) {
status->Add(
STATUS_WARNING,
"Frame anchored to itself: %s",
relativeToAttr
);
continue;
}
}
XMLNode* offsetNode = anchorNode->GetChildByName("Offset");
float offsetX = 0.0f;
float offsetY = 0.0f;
if (offsetNode) {
LoadXML_Dimensions(offsetNode, offsetX, offsetY, status);
} else {
LoadXML_Dimensions(anchorNode, offsetX, offsetY, status);
}
this->SetPoint(point, relative, relativePoint, offsetX, offsetY, 0);
}
this->Resize(0);
} else if (setAllPoints) {
this->SetAllPoints(layoutParent, 1);
}
}
int32_t CLayoutFrame::OnFrameResize() {
CRect rect = { 0.0f, 0.0f, 0.0f, 0.0f };
if (!this->CalculateRect(&rect)) {
this->m_flags = (this->m_flags & ~0x1) | 0x8;
return 0;
}
this->m_flags &= ~(0x4 | 0x8);
if (
this->m_flags & 0x1
&& AreEqual(rect.minX, this->m_rect.minX, WHOA_EPSILON_2)
&& AreEqual(rect.maxX, this->m_rect.maxX, WHOA_EPSILON_2)
&& AreEqual(rect.minY, this->m_rect.minY, WHOA_EPSILON_2)
&& AreEqual(rect.maxY, this->m_rect.maxY, WHOA_EPSILON_2)
) {
return 1;
}
CRect prevRect = {
this->m_rect.minY,
this->m_rect.minX,
this->m_rect.maxY,
this->m_rect.maxX
};
this->m_rect.minY = rect.minY;
this->m_rect.minX = rect.minX;
this->m_rect.maxY = rect.maxY;
this->m_rect.maxX = rect.maxX;
this->m_flags |= 0x1;
this->OnFrameSizeChanged(prevRect);
return this->m_flags & 0x1;
}
void CLayoutFrame::OnFrameSizeChanged(const CRect& rect) {
for (auto node = this->m_resizeList.Head(); node; node = this->m_resizeList.Link(node)->Next()) {
node->frame->Resize(0);
}
}
void CLayoutFrame::OnProtectedAttach(CLayoutFrame* frame) {
if (this->m_flags & 0x400) {
frame->SetProtectFlag(0x400);
}
if (this->m_flags & 0x300) {
frame->SetProtectFlag(0x200);
}
}
int32_t CLayoutFrame::PtInFrameRect(const C2Vector& pt) {
// TODO
return 0;
}
void CLayoutFrame::RegisterResize(CLayoutFrame* frame, uint32_t dep) {
for (auto node = this->m_resizeList.Head(); node; node = this->m_resizeList.Link(node)->Next()) {
if (node->frame == frame) {
node->dep |= dep;
return;
}
}
auto node = this->m_resizeList.NewNode(2, 0, 0x8);
node->frame = frame;
node->dep = dep;
if (static_cast<CLayoutFrame*>(frame)->m_flags & 0x400) {
this->SetProtectFlag(0x400);
}
if (static_cast<CLayoutFrame*>(frame)->m_flags & (0x100 | 0x200)) {
this->SetProtectFlag(0x200);
}
}
void CLayoutFrame::Resize(int32_t force) {
if (force && !(this->m_flags & 0x8) && this->OnFrameResize()) {
LayoutFrame::s_resizePendingList.UnlinkNode(this);
return;
}
if (this->m_flags & 0x4 && (this->m_flags & 0x2 || LayoutFrame::s_resizePendingList.IsLinked(this))) {
this->m_resizeCounter = 6;
return;
}
this->m_flags |= 0x4;
if (this->m_flags & 0x2) {
for (auto node = this->m_resizeList.Head(); node; node = this->m_resizeList.Link(node)->Next()) {
node->frame->Resize(0);
}
} else {
this->AddToResizeList();
}
}
float CLayoutFrame::Right() {
if (this->m_guard.right) {
return CFramePoint::UNDEFINED;
}
this->m_guard.right = 1;
static FRAMEPOINT sidepoints[] = {
FRAMEPOINT_TOPRIGHT,
FRAMEPOINT_RIGHT,
FRAMEPOINT_BOTTOMRIGHT
};
float right = CFramePoint::UNDEFINED;
this->GetFirstPointX(sidepoints, 3, right);
if (right == CFramePoint::UNDEFINED) {
float size = this->GetWidth() * this->m_layoutScale;
float opposite = this->Left();
float center = this->CenterX();
right = SynthesizeSide(center, opposite, size);
}
this->m_guard.right = 0;
return right;
}
void CLayoutFrame::SetAllPoints(CLayoutFrame* relative, int32_t doResize) {
STORM_ASSERT(relative);
STORM_ASSERT(relative != this);
if (!relative->CanBeAnchorFor(this)) {
return;
}
this->FreePoints();
auto topLeft = this->m_points[FRAMEPOINT_TOPLEFT];
if (topLeft) {
topLeft->SetRelative(relative, FRAMEPOINT_TOPLEFT, 0.0f, 0.0f);
} else {
// TODO
// CFramePoint::s_framePointHeap->GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CFramePoint), __FILE__, __LINE__, 0);
topLeft = m ? new (m) CFramePoint(relative, FRAMEPOINT_TOPLEFT, 0.0f, 0.0f) : nullptr;
this->m_points[FRAMEPOINT_TOPLEFT] = topLeft;
}
auto bottomRight = this->m_points[FRAMEPOINT_BOTTOMRIGHT];
if (bottomRight) {
bottomRight->SetRelative(relative, FRAMEPOINT_BOTTOMRIGHT, 0.0f, 0.0f);
} else {
// TODO
// CFramePoint::s_framePointHeap->GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CFramePoint), __FILE__, __LINE__, 0);
bottomRight = m ? new (m) CFramePoint(relative, FRAMEPOINT_BOTTOMRIGHT, 0.0f, 0.0f) : nullptr;
this->m_points[FRAMEPOINT_BOTTOMRIGHT] = bottomRight;
}
this->m_flags &= ~0x8;
relative->RegisterResize(this, (1 << FRAMEPOINT_TOPLEFT) | (1 << FRAMEPOINT_BOTTOMRIGHT));
if (doResize) {
this->Resize(0);
}
}
void CLayoutFrame::SetDeferredResize(int32_t enable) {
if (enable) {
this->m_flags |= 0x2;
if (LayoutFrame::s_resizePendingList.Link(this)->IsLinked()) {
LayoutFrame::s_resizePendingList.UnlinkNode(this);
}
return;
}
this->m_flags &= ~0x2;
if (this->m_flags & 0x4) {
this->Resize(1);
}
}
void CLayoutFrame::SetHeight(float height) {
this->m_flags &= ~0x8;
this->m_height = height;
this->Resize(0);
}
bool CLayoutFrame::SetLayoutScale(float scale, bool force) {
STORM_ASSERT(scale);
if (force || (!AreEqual(this->m_layoutScale, scale, WHOA_EPSILON_1) && scale > 0.00000011920929)) {
this->m_layoutScale = scale;
this->m_rect = { 0.0f, 0.0f, 0.0f, 0.0f };
this->m_flags &= ~0x1;
this->Resize(0);
return true;
}
return false;
}
void CLayoutFrame::SetPoint(FRAMEPOINT point, CLayoutFrame* relative, FRAMEPOINT relativePoint, float offsetX, float offsetY, int32_t doResize) {
STORM_ASSERT(relative);
STORM_ASSERT(relative != this);
if (!relative->CanBeAnchorFor(this)) {
return;
}
auto framePoint = this->m_points[point];
if (framePoint) {
if (framePoint->GetRelative()) {
if (relative == framePoint->GetRelative()) {
if (
framePoint->m_framePoint != relativePoint
|| !AreEqual(framePoint->m_offset.x, offsetX, WHOA_EPSILON_1)
|| !AreEqual(framePoint->m_offset.y, offsetY, WHOA_EPSILON_1)
) {
framePoint->SetRelative(relative, relativePoint, offsetX, offsetY);
this->m_flags &= ~0x8;
if (doResize) {
this->Resize(0);
}
}
return;
} else {
framePoint->GetRelative()->UnregisterResize(this, 1 << point);
}
}
framePoint->SetRelative(relative, relativePoint, offsetX, offsetY);
} else {
// TODO
// CFramePoint::s_framePointHeap->GetData(0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CFramePoint), __FILE__, __LINE__, 0);
framePoint = m ? new (m) CFramePoint(relative, relativePoint, offsetX, offsetY) : nullptr;
this->m_points[point] = framePoint;
}
this->m_flags &= ~0x8;
relative->RegisterResize(this, 1 << point);
if (doResize) {
this->Resize(0);
}
}
void CLayoutFrame::SetProtectFlag(uint32_t flag) {
// TODO
}
void CLayoutFrame::SetWidth(float width) {
this->m_flags &= ~0x8;
this->m_width = width;
this->Resize(0);
}
int32_t CLayoutFrame::Sub488DB0(const FRAMEPOINT* const pointarray, int32_t elements, float& x) {
for (int32_t i = 0; i < elements; i++) {
FRAMEPOINT f = pointarray[i];
CFramePoint* point = this->m_points[f];
if (point && !(point->m_flags & 0x8)) {
x = point->X(this->m_layoutScale);
if (point->m_flags & 0x4) {
x = CFramePoint::UNDEFINED;
return 0;
}
if (x != CFramePoint::UNDEFINED) {
return 1;
}
}
}
x = CFramePoint::UNDEFINED;
return 1;
}
int32_t CLayoutFrame::Sub488E40(const FRAMEPOINT* const pointarray, int32_t elements, float& y) {
for (int32_t i = 0; i < elements; i++) {
FRAMEPOINT f = pointarray[i];
CFramePoint* point = this->m_points[f];
if (point && !(point->m_flags & 0x8)) {
y = point->Y(this->m_layoutScale);
if (point->m_flags & 0x4) {
y = CFramePoint::UNDEFINED;
return 0;
}
if (y != CFramePoint::UNDEFINED) {
return 1;
}
}
}
y = CFramePoint::UNDEFINED;
return 1;
}
float CLayoutFrame::Top() {
if (this->m_guard.top) {
return CFramePoint::UNDEFINED;
}
this->m_guard.top = 1;
static FRAMEPOINT sidepoints[] = {
FRAMEPOINT_TOPLEFT,
FRAMEPOINT_TOP,
FRAMEPOINT_TOPRIGHT
};
float top = CFramePoint::UNDEFINED;
this->GetFirstPointY(sidepoints, 3, top);
if (top == CFramePoint::UNDEFINED) {
float size = this->GetHeight() * this->m_layoutScale;
float opposite = this->Bottom();
float center = this->CenterY();
top = SynthesizeSide(center, opposite, size);
}
this->m_guard.top = 0;
return top;
}
void CLayoutFrame::UnflattenFrame(CLayoutFrame* frame) {
// TODO
}
void CLayoutFrame::UnregisterResize(CLayoutFrame* frame, uint32_t dep) {
for (auto node = this->m_resizeList.Head(); node; node = this->m_resizeList.Link(node)->Next()) {
if (node->frame == frame) {
node->dep &= ~dep;
if (node->dep) {
return;
}
if (static_cast<CLayoutFrame*>(frame)->m_flags & (0x100 | 0x200 | 0x400)) {
this->SetProtectFlag(0x400);
}
this->m_resizeList.DeleteNode(node);
return;
}
}
}

99
src/ui/CLayoutFrame.hpp Normal file
View file

@ -0,0 +1,99 @@
#ifndef UI_C_LAYOUT_FRAME_HPP
#define UI_C_LAYOUT_FRAME_HPP
#include "ui/Types.hpp"
#include "ui/Util.hpp"
#include <cstdint>
#include <storm/List.hpp>
#include <tempest/Rect.hpp>
class CFramePoint;
class CStatus;
class XMLNode;
class CLayoutFrame {
public:
// Types
struct FRAMENODE : public TSLinkedNode<FRAMENODE> {
CLayoutFrame* frame;
uint32_t dep;
};
// Static functions
static void ResizePending(void);
// Member variables
TSLink<CLayoutFrame> resizeLink;
CFramePoint* m_points[FRAMEPOINT_NUMPOINTS] = {};
TSList<FRAMENODE, TSGetLink<FRAMENODE>> m_resizeList;
struct {
int32_t left : 1;
int32_t top : 1;
int32_t right : 1;
int32_t bottom : 1;
int32_t centerX : 1;
int32_t centerY : 1;
} m_guard;
uint32_t m_resizeCounter : 8;
uint32_t m_flags : 16;
CRect m_rect;
float m_width;
float m_height;
float m_layoutScale;
float m_layoutDepth;
// Virtual member functions
virtual ~CLayoutFrame();
virtual CLayoutFrame* GetLayoutParent(void);
virtual bool SetLayoutScale(float, bool);
virtual void SetWidth(float);
virtual void SetHeight(float);
virtual float GetWidth(void);
virtual float GetHeight(void);
virtual void GetClampRectInsets(float&, float&, float&, float&);
virtual int32_t IsAttachmentOrigin(void);
virtual CLayoutFrame* GetLayoutFrameByName(const char*);
virtual int32_t IsObjectLoaded(void);
virtual void OnFrameSizeChanged(const CRect&);
// Member functions
CLayoutFrame();
void AddToResizeList(void);
float Bottom(void);
int32_t CalculateRect(CRect*);
bool CanBeAnchorFor(CLayoutFrame*);
float CenterX(void);
float CenterY(void);
void ClearAllPoints(void);
void DestroyLayout();
void FreePoints(void);
void GetFirstPointX(const FRAMEPOINT* const, int32_t, float&);
void GetFirstPointY(const FRAMEPOINT* const, int32_t, float&);
int32_t GetRect(CRect*);
int32_t IsResizeDependency(CLayoutFrame*);
uint32_t IsResizePending(void);
float Left(void);
void LoadXML(XMLNode*, CStatus*);
int32_t OnFrameResize(void);
void OnProtectedAttach(CLayoutFrame*);
int32_t PtInFrameRect(const C2Vector&);
void RegisterResize(CLayoutFrame*, uint32_t);
void Resize(int32_t);
float Right(void);
void SetAllPoints(CLayoutFrame*, int32_t);
void SetDeferredResize(int32_t);
void SetPoint(FRAMEPOINT, CLayoutFrame*, FRAMEPOINT, float, float, int32_t);
void SetProtectFlag(uint32_t);
int32_t Sub488DB0(const FRAMEPOINT* const, int32_t, float&);
int32_t Sub488E40(const FRAMEPOINT* const, int32_t, float&);
float Top(void);
void UnflattenFrame(CLayoutFrame*);
void UnregisterResize(CLayoutFrame*, uint32_t);
};
namespace LayoutFrame {
// TODO put in better location
extern STORM_EXPLICIT_LIST(CLayoutFrame, resizeLink) s_resizePendingList;
}
#endif

24
src/ui/CMakeLists.txt Normal file
View file

@ -0,0 +1,24 @@
file(GLOB PRIVATE_SOURCES "*.cpp")
add_library(ui STATIC
${PRIVATE_SOURCES}
)
target_include_directories(ui
PRIVATE
${CMAKE_SOURCE_DIR}/src
)
target_link_libraries(ui
PRIVATE
event
glue
gx
math
model
util
PUBLIC
common
storm
tempest
)

220
src/ui/CRenderBatch.cpp Normal file
View file

@ -0,0 +1,220 @@
#include "ui/CRenderBatch.hpp"
#include "ui/CSimpleFontString.hpp"
#include "ui/CSimpleTexture.hpp"
#include "gx/Coordinate.hpp"
#include "gx/Font.hpp"
#include "gx/Shader.hpp"
#include "gx/font/CGxStringBatch.hpp"
#include <cstdlib>
#include <storm/Error.hpp>
int32_t SortByTexture(const void* a, const void* b) {
auto meshA = reinterpret_cast<const CSimpleBatchedMesh*>(a);
auto meshB = reinterpret_cast<const CSimpleBatchedMesh*>(b);
if (meshA->textureID != meshB->textureID) {
return meshA->textureID - meshB->textureID;
}
if (meshA->alphaMode != meshB->alphaMode) {
if ((meshA->alphaMode >= 2 || !meshA->color) && (meshB->alphaMode >= 2 || !meshB->color)) {
return meshA->alphaMode - meshB->alphaMode;
} else if (meshA->alphaMode >= 2 || !meshA->color) {
return meshA->alphaMode - 2;
} else if (meshB->alphaMode >= 2 || !meshB->color) {
return 2 - meshB->alphaMode;
}
}
if (meshA->shader != meshB->shader) {
return meshA->shader - meshB->shader;
}
return 0;
}
EGxBlend CSimpleBatchedMesh::GetAlphaMode() {
if (this->color && this->alphaMode < GxBlend_Alpha) {
return GxBlend_Alpha;
} else {
return this->alphaMode;
}
}
void CRenderBatch::Clear() {
this->m_texturelist.SetCount(0);
if (this->m_stringbatch) {
GxuFontDestroyBatch(this->m_stringbatch);
this->m_stringbatch = nullptr;
}
this->m_callbacks.DeleteAll();
this->m_count = 0;
}
void CRenderBatch::Finish() {
if (this->m_texturelist.Count() > 1) {
qsort(this->m_texturelist.m_data, this->m_texturelist.Count(), sizeof(CSimpleBatchedMesh), SortByTexture);
}
}
void CRenderBatch::Queue(CTexture* texture, EGxBlend alphaMode, int32_t posCount, const C3Vector* position, const C2Vector* texCoord, int32_t colorCount, const CImVector* color, int32_t idxCount, const uint16_t* indices, CGxShader* shader) {
CGxTex* textureID = TextureGetGxTex(texture, 1, nullptr);
if (!textureID) {
return;
}
CSimpleBatchedMesh* mesh = this->m_texturelist.New();
mesh->texture = texture;
mesh->textureID = textureID;
mesh->alphaMode = alphaMode;
mesh->shader = shader;
mesh->posCount = posCount;
mesh->position = const_cast<C3Vector*>(position);
mesh->texCoord = const_cast<C2Vector*>(texCoord);
mesh->color = const_cast<CImVector*>(color);
mesh->colorCount = colorCount;
mesh->indices = const_cast<uint16_t*>(indices);
mesh->idxCount = idxCount;
// TODO
// - implement atlas stuff
mesh->onAtlas = 0;
// mesh->onAtlas = TextureOnAtlas(texture);
// if (onAtlas) {
// TextureGetAtlasOffsetAndScale(mesh->texture, mesh->offset, mesh->scale);
// }
this->m_count++;
}
void CRenderBatch::QueueCallback(void (*callback)(void*), void* param) {
auto node = this->m_callbacks.NewNode(2, 0, 0);
node->callback = callback;
node->param = param;
this->m_count++;
}
void CRenderBatch::QueueFontString(CSimpleFontString* string) {
CRect rect = { 0.0f, 0.0f, 0.0f, 0.0f };
if (!string->GetRect(&rect)) {
return;
}
if (rect.minX > 1.0f || rect.maxX < 0.0f || rect.minY > 1.0f || rect.maxY < 0.0f) {
return;
}
if (!string->m_string) {
return;
}
auto gxString = TextBlockGetStringPtr(string->m_string);
if (gxString) {
if (!this->m_stringbatch) {
this->m_stringbatch = GxuFontCreateBatch(false, false);
STORM_ASSERT(this->m_stringbatch);
}
GxuFontAddToBatch(this->m_stringbatch, gxString);
this->m_count++;
}
}
void CRenderBatch::QueueTexture(CSimpleTexture* texture) {
CGxTex* gxTex = TextureGetGxTex(texture->m_texture, texture->m_nonBlocking ? 0 : 2, 0);
if (!gxTex) {
// TODO
// this->OnDelayedLoad();
return;
}
if (texture->IsResizePending()) {
texture->Resize(1);
}
if (texture->m_updateTexCoord) {
C2Vector texCoord[4];
texture->GetTexCoord(texCoord);
CRect rect = {
texture->m_position[1].y,
texture->m_position[0].x,
texture->m_position[0].y,
texture->m_position[2].x
};
if (texture->m_horizTile) {
float width = gxTex->GetWidth();
float ddcWidth = CoordinateGetAspectCompensation() * 1024.0f * (rect.maxX - rect.minX);
float ndcWidth = DDCToNDCWidth(ddcWidth);
if (width && ndcWidth > 0.0f) {
if (texCoord[0].x != 0.0f) {
texCoord[0].x = ndcWidth / width;
}
if (texCoord[1].x != 0.0f) {
texCoord[1].x = ndcWidth / width;
}
if (texCoord[2].x != 0.0f) {
texCoord[2].x = ndcWidth / width;
}
if (texCoord[3].x != 0.0f) {
texCoord[3].x = ndcWidth / width;
}
}
}
if (texture->m_vertTile) {
float height = gxTex->GetHeight();
float ddcHeight = CoordinateGetAspectCompensation() * 1024.0f * (rect.maxY - rect.minY);
float ndcHeight = DDCToNDCWidth(ddcHeight);
if (height && ndcHeight > 0.0f) {
if (texCoord[0].y != 0.0f) {
texCoord[0].y = ndcHeight / height;
}
if (texCoord[1].y != 0.0f) {
texCoord[1].y = ndcHeight / height;
}
if (texCoord[2].y != 0.0f) {
texCoord[2].y = ndcHeight / height;
}
if (texCoord[3].y != 0.0f) {
texCoord[3].y = ndcHeight / height;
}
}
}
texture->m_updateTexCoord = 0;
texture->SetTexCoord(texCoord);
}
this->Queue(
TextureGetTexturePtr(texture->m_texture),
texture->m_alphaMode,
4,
texture->m_position,
texture->m_texCoord,
texture->m_colorCount > 1 ? 4 : 0,
texture->m_colorCount ? texture->m_color : nullptr,
6,
CSimpleTexture::s_indices,
texture->m_shader
);
}

63
src/ui/CRenderBatch.hpp Normal file
View file

@ -0,0 +1,63 @@
#ifndef UI_C_RENDER_BATCH_HPP
#define UI_C_RENDER_BATCH_HPP
#include "gx/Types.hpp"
#include <cstdint>
#include <storm/Array.hpp>
#include <storm/List.hpp>
#include <tempest/Vector.hpp>
class CGxShader;
class CGxStringBatch;
class CGxTex;
class CSimpleFontString;
class CSimpleTexture;
class CTexture;
class RENDERCALLBACKNODE : public TSLinkedNode<RENDERCALLBACKNODE> {
public:
void (*callback)(void*);
void* param;
};
class CSimpleBatchedMesh {
public:
// Member variables
CTexture* texture;
CGxTex* textureID;
EGxBlend alphaMode;
CGxShader* shader;
int32_t posCount;
C3Vector* position;
C2Vector* texCoord;
CImVector* color;
int32_t colorCount;
uint16_t* indices;
int32_t idxCount;
int32_t onAtlas;
float atlasScale;
C2Vector atlasOffset;
// Member functions
EGxBlend GetAlphaMode(void);
};
class CRenderBatch {
public:
// Member variables
uint32_t m_count = 0;
TSGrowableArray<CSimpleBatchedMesh> m_texturelist;
CGxStringBatch* m_stringbatch = nullptr;
TSList<RENDERCALLBACKNODE,TSGetLink<RENDERCALLBACKNODE>> m_callbacks;
TSLink<CRenderBatch> renderLink;
// Member functions
void Clear(void);
void Finish(void);
void Queue(CTexture*, EGxBlend, int32_t, const C3Vector*, const C2Vector*, int32_t, const CImVector*, int32_t, const uint16_t*, CGxShader*);
void QueueCallback(void (*)(void*), void*);
void QueueFontString(CSimpleFontString*);
void QueueTexture(CSimpleTexture*);
};
#endif

131
src/ui/CScriptObject.cpp Normal file
View file

@ -0,0 +1,131 @@
#include "ui/CScriptObject.hpp"
#include "ui/CScriptObjectScript.hpp"
#include "util/CStatus.hpp"
#include "util/Lua.hpp"
#include <cstdint>
#include <common/XML.hpp>
#include <storm/String.hpp>
int32_t CScriptObject::s_objectType;
const char* CScriptObject::s_objectTypeName = "Object";
void CScriptObject::RegisterScriptMethods(lua_State* L) {
FrameScript_Object::FillScriptMethodTable(L, ScriptObjectMethods, NUM_SCRIPT_OBJECT_SCRIPT_METHODS);
}
CScriptObject* CScriptObject::GetScriptObjectByName(const char* name, int32_t type) {
lua_State* L = FrameScript_GetContext();
lua_pushstring(L, name);
lua_rawget(L, LUA_GLOBALSINDEX);
if (lua_type(L, -1) == 5) {
lua_rawgeti(L, -1, 0);
auto v4 = static_cast<CScriptObject*>(lua_touserdata(L, -1));
lua_settop(L, -3);
if (v4 && v4->IsA(type)) {
return v4;
} else {
return NULL;
}
} else {
lua_settop(L, -2);
return NULL;
}
}
CScriptObject::~CScriptObject() {
if (this->m_name.GetString()) {
this->UnregisterScriptObject(this->m_name.GetString());
this->m_name.Copy(nullptr);
}
}
/**
* @brief Converts the value of the name="" attribute into a fully resolved name.
* @param source eg. $parentCategory from <FontString name="$parentCategory" />
*/
void CScriptObject::CreateName(const char* source, char* dest, uint32_t destsize) {
// If source is not $parent, use it as the name
uint32_t v5 = SStrLen("$parent");
if (SStrCmpI(source, "$parent", v5)) {
SStrCopy(dest, source, destsize);
return;
}
SStrCopy(dest, "", 0x7FFFFFFF);
CScriptObject* parent = this->GetScriptObjectParent();
if (parent) {
const char* parentName;
while (1) {
parentName = parent->GetName();
// Found a name
if (parentName && *parentName) {
break;
}
// Didn't find a name, go up a level
parent = parent->GetScriptObjectParent();
// Out of levels to go up
if (!parent) {
goto LABEL_8;
}
}
SStrCopy(dest, parentName, destsize);
}
LABEL_8:
// Copy the part of the string after $parent into dest
int v8 = SStrLen("$parent");
SStrPack(dest, &source[v8], destsize);
}
char* CScriptObject::GetName() {
return this->m_name.m_str;
}
void CScriptObject::PreLoadXML(XMLNode* node, CStatus* status) {
const char* name = node->GetAttributeByName("name");
if (name && *name) {
this->SetName(name);
}
}
void CScriptObject::SetName(const char* name) {
// If name is already set, clear it out
if (this->m_name.m_str) {
this->UnregisterScriptObject(this->m_name.m_str);
this->m_name.Copy(0);
}
// Set the name
if (name && *name) {
// Deal with $parent in name
char fullName[1024];
this->CreateName(name, fullName, 1024);
this->m_name.Copy(fullName);
this->RegisterScriptObject(fullName);
}
}
const char* CScriptObject::GetObjectTypeName() {
return CScriptObject::s_objectTypeName;
}
bool CScriptObject::IsA(int32_t type) {
return type == CScriptObject::s_objectType;
}
bool CScriptObject::IsA(const char* typeName) {
return SStrCmpI(typeName, CScriptObject::s_objectTypeName, 0x7FFFFFFFu) == 0;
}

38
src/ui/CScriptObject.hpp Normal file
View file

@ -0,0 +1,38 @@
#ifndef UI_C_SCRIPT_OBJECT_HPP
#define UI_C_SCRIPT_OBJECT_HPP
#include "ui/FrameScript_Object.hpp"
#include <cstdint>
#include <common/String.hpp>
class CStatus;
class XMLNode;
class CScriptObject : public FrameScript_Object {
public:
// Static variables
static int32_t s_objectType;
static const char* s_objectTypeName;
// Static functions
static void RegisterScriptMethods(lua_State*);
static CScriptObject* GetScriptObjectByName(const char*, int32_t);
// Member variables
RCString m_name;
// Virtual member functions
virtual ~CScriptObject(void);
virtual char* GetName(void);
virtual bool IsA(int32_t);
virtual CScriptObject* GetScriptObjectParent(void) = 0;
virtual bool IsA(const char*);
virtual const char* GetObjectTypeName(void);
// Member functions
void CreateName(const char*, char*, uint32_t);
void PreLoadXML(XMLNode*, CStatus*);
void SetName(const char*);
};
#endif

View file

@ -0,0 +1,94 @@
#include "ui/CScriptObjectScript.hpp"
#include "ui/CScriptObject.hpp"
#include "util/Lua.hpp"
#include <cstdint>
int32_t CScriptObject_GetObjectType(lua_State* L) {
if (!CScriptObject::s_objectType) {
CScriptObject::s_objectType = ++FrameScript_Object::s_objectTypes;
}
CScriptObject* object = (CScriptObject*)FrameScript_GetObjectThis(L, CScriptObject::s_objectType);
const char* type = object->GetObjectTypeName();
lua_pushstring(L, type);
return 1;
}
int32_t CScriptObject_IsObjectType(lua_State* L) {
if (!CScriptObject::s_objectType) {
CScriptObject::s_objectType = ++FrameScript_Object::s_objectTypes;
}
CScriptObject* object = (CScriptObject*)FrameScript_GetObjectThis(L, CScriptObject::s_objectType);
if (!lua_isstring(L, 2)) {
const char* name = object->GetName();
if (!name) {
name = "<unnamed>";
}
luaL_error(L, "Usage: %s:IsObjectType(\"type\")", name);
return 0;
}
const char* type = lua_tolstring(L, 2, 0);
if (object->IsA(type)) {
lua_pushnumber(L, 1.0);
} else {
lua_pushnil(L);
}
return 1;
}
int32_t CScriptObject_GetName(lua_State* L) {
if (!CScriptObject::s_objectType) {
CScriptObject::s_objectType = ++FrameScript_Object::s_objectTypes;
}
CScriptObject* object = (CScriptObject*)FrameScript_GetObjectThis(L, CScriptObject::s_objectType);
char* name = object->GetName();
if (name && *name) {
lua_pushstring(L, name);
} else {
lua_pushnil(L);
}
return 1;
}
int32_t CScriptObject_GetParent(lua_State* L) {
if (!CScriptObject::s_objectType) {
CScriptObject::s_objectType = ++FrameScript_Object::s_objectTypes;
}
CScriptObject* object = (CScriptObject*)FrameScript_GetObjectThis(L, CScriptObject::s_objectType);
CScriptObject* parent = object->GetScriptObjectParent();
if (parent) {
if (!parent->lua_registered) {
parent->RegisterScriptObject(0);
}
lua_rawgeti(L, LUA_REGISTRYINDEX, parent->lua_objectRef);
} else {
lua_pushnil(L);
}
return 1;
}
FrameScript_Method ScriptObjectMethods[NUM_SCRIPT_OBJECT_SCRIPT_METHODS] = {
{ "GetObjectType", &CScriptObject_GetObjectType },
{ "IsObjectType", &CScriptObject_IsObjectType },
{ "GetName", &CScriptObject_GetName },
{ "GetParent", &CScriptObject_GetParent }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SCRIPT_OBJECT_SCRIPT_HPP
#define UI_C_SCRIPT_OBJECT_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SCRIPT_OBJECT_SCRIPT_METHODS 4
extern FrameScript_Method ScriptObjectMethods[NUM_SCRIPT_OBJECT_SCRIPT_METHODS];
#endif

122
src/ui/CScriptRegion.cpp Normal file
View file

@ -0,0 +1,122 @@
#include "ui/CScriptRegion.hpp"
#include "ui/CScriptObject.hpp"
#include "ui/CScriptRegionScript.hpp"
#include "ui/CSimpleTop.hpp"
#include "util/Lua.hpp"
#include <common/XML.hpp>
int32_t CScriptRegion::s_objectType;
const char* CScriptRegion::s_objectTypeName = "Region";
int32_t CScriptRegion::GetObjectType() {
if (!CScriptRegion::s_objectType) {
CScriptRegion::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CScriptRegion::s_objectType;
}
void CScriptRegion::RegisterScriptMethods(lua_State* L) {
CScriptObject::RegisterScriptMethods(L);
FrameScript_Object::FillScriptMethodTable(L, ScriptRegionMethods, NUM_SCRIPT_REGION_SCRIPT_METHODS);
}
// TODO verify return type
CLayoutFrame* CScriptRegion::GetLayoutParent() {
if (!this->m_parent || this->m_parent->m_layoutScale == 0.0f) {
return CSimpleTop::s_instance;
} else {
return (CLayoutFrame*)this->m_parent;
}
}
CLayoutFrame* CScriptRegion::GetLayoutFrameByName(const char* name) {
char fullName[1024];
this->CreateName(name, fullName, 1024);
int32_t type = CScriptRegion::GetObjectType();
CScriptRegion* object = static_cast<CScriptRegion*>(this->GetScriptObjectByName(fullName, type));
return static_cast<CLayoutFrame*>(object);
}
const char* CScriptRegion::GetObjectTypeName() {
return CScriptRegion::s_objectTypeName;
}
// TODO verify return type
CScriptObject* CScriptRegion::GetScriptObjectParent() {
return (CScriptObject*)(this->m_parent);
}
bool CScriptRegion::IsA(int32_t type) {
return type == CScriptRegion::s_objectType
|| type == CScriptObject::s_objectType;
}
bool CScriptRegion::IsA(const char* typeName) {
return !SStrCmpI(typeName, CScriptRegion::s_objectTypeName, 0x7FFFFFFF)
|| !SStrCmpI(typeName, CScriptObject::s_objectTypeName, 0x7FFFFFFF);
}
bool CScriptRegion::IsDragging() {
// TODO
return false;
}
void CScriptRegion::LoadXML(XMLNode* node, CStatus* status) {
CLayoutFrame::LoadXML(node, status);
const char* parentKey = node->GetAttributeByName("parentKey");
if (parentKey && *parentKey) {
lua_State* L = FrameScript_GetContext();
CScriptObject* parent = this->GetScriptObjectParent();
if (parent) {
if (!parent->lua_registered) {
parent->RegisterScriptObject(0);
}
lua_rawgeti(L, LUA_REGISTRYINDEX, parent->lua_objectRef);
lua_pushstring(L, parentKey);
if (!this->lua_registered) {
this->RegisterScriptObject(0);
}
lua_rawgeti(L, LUA_REGISTRYINDEX, this->lua_objectRef);
lua_settable(L, -3);
lua_settop(L, -2);
}
}
this->LoadXML_Animations(node, status);
}
void CScriptRegion::LoadXML_Animations(XMLNode* node, CStatus* status) {
// TODO
}
void CScriptRegion::NotifyAnimBegin(CSimpleAnimGroup* animGroup) {
// TODO
}
void CScriptRegion::NotifyAnimEnd(CSimpleAnimGroup* animGroup) {
// TODO
}
void CScriptRegion::OnLayerUpdate(float elapsedSec) {
// TODO
}
bool CScriptRegion::ProtectedFunctionsAllowed() {
// TODO
return true;
}
void CScriptRegion::StopAnimating() {
// TODO
}

52
src/ui/CScriptRegion.hpp Normal file
View file

@ -0,0 +1,52 @@
#ifndef UI_C_SCRIPT_REGION_HPP
#define UI_C_SCRIPT_REGION_HPP
#include "ui/CLayoutFrame.hpp"
#include "ui/CScriptObject.hpp"
class C2Vector;
class CSimpleAnimGroup;
class CSimpleFrame;
class XMLNode;
struct lua_State;
class CScriptRegion : public CScriptObject, public CLayoutFrame {
public:
// Static members
static int32_t s_objectType;
static const char* s_objectTypeName;
// Static functions
static void RegisterScriptMethods(lua_State*);
static int32_t GetObjectType(void);
// Member variables
CSimpleFrame* m_parent = NULL; // TODO verify type
// Virtual member functions
virtual bool IsA(int32_t);
virtual CScriptObject* GetScriptObjectParent(void);
virtual bool IsA(const char*);
virtual const char* GetObjectTypeName(void);
virtual bool IsDragging(void);
virtual void PreOnAnimUpdate(void) {};
virtual void OnLayerUpdate(float);
virtual void NotifyAnimBegin(CSimpleAnimGroup*);
virtual void NotifyAnimEnd(CSimpleAnimGroup*);
virtual void StopAnimating(void);
virtual void AnimActivated(CSimpleAnimGroup*, int32_t, int32_t) {};
virtual void AnimDeactivated(CSimpleAnimGroup*, int32_t, int32_t) {};
virtual void AddAnimTranslation(CScriptRegion*, const C2Vector&) {};
virtual void AddAnimRotation(CScriptRegion*, FRAMEPOINT, const C2Vector&, float) {};
virtual void AddAnimScale(CScriptRegion*, FRAMEPOINT, const C2Vector&, const C2Vector&) {};
virtual void AddAnimAlpha(CScriptRegion*, int16_t) {};
virtual void LoadXML(XMLNode*, CStatus*);
virtual CLayoutFrame* GetLayoutParent(void);
virtual CLayoutFrame* GetLayoutFrameByName(const char*);
// Member functions
void LoadXML_Animations(XMLNode*, CStatus*);
bool ProtectedFunctionsAllowed(void);
};
#endif

View file

@ -0,0 +1,387 @@
#include "ui/CScriptRegionScript.hpp"
#include "gx/Coordinate.hpp"
#include "ui/FrameScript_Object.hpp"
#include "ui/CScriptRegion.hpp"
#include "ui/CSimpleTop.hpp"
#include "util/Lua.hpp"
#include "util/StringTo.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
#include <tempest/Rect.hpp>
int32_t CScriptRegion_IsProtected(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_CanChangeProtectedState(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_SetParent(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_GetRect(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_GetCenter(lua_State* L) {
int32_t type = CScriptRegion::GetObjectType();
auto region = static_cast<CScriptRegion*>(FrameScript_GetObjectThis(L, type));
if (region->IsResizePending()) {
region->Resize(1);
}
CRect rect;
if (region->GetRect(&rect)) {
float width = rect.maxX - rect.minX;
float v5 = CoordinateGetAspectCompensation() * 1024.0f * ((width * 0.5f + rect.minX) / region->m_layoutScale);
float v6 = DDCToNDCWidth(v5);
lua_pushnumber(L, v6);
float height = rect.maxY - rect.minY;
float v7 = CoordinateGetAspectCompensation() * 1024.0f * ((height * 0.5f + rect.minY) / region->m_layoutScale);
float v8 = DDCToNDCWidth(v7);
lua_pushnumber(L, v8);
} else {
lua_pushnil(L);
lua_pushnil(L);
}
return 2;
}
int32_t CScriptRegion_GetLeft(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_GetRight(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_GetTop(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_GetBottom(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_GetWidth(lua_State* L) {
int32_t type = CScriptRegion::GetObjectType();
auto region = static_cast<CScriptRegion*>(FrameScript_GetObjectThis(L, type));
float width = region->GetWidth();
if (width == 0.0 && !StringToBOOL(L, 2, 0)) {
if (region->IsResizePending()) {
region->Resize(1);
}
CRect rect = { 0.0, 0.0, 0.0, 0.0 };
if (region->GetRect(&rect)) {
width = (rect.maxX - rect.minX) / region->m_layoutScale;
}
}
float ddcWidth = CoordinateGetAspectCompensation() * 1024.0 * width;
float ndcWidth = DDCToNDCWidth(ddcWidth);
lua_pushnumber(L, ndcWidth);
return 1;
}
int32_t CScriptRegion_SetWidth(lua_State* L) {
int32_t type = CScriptRegion::GetObjectType();
auto region = static_cast<CScriptRegion*>(FrameScript_GetObjectThis(L, type));
if (!region->ProtectedFunctionsAllowed()) {
// TODO
// - disallowed logic
return 0;
}
if (!lua_isnumber(L, 2)) {
return luaL_error(L, "Usage: %s:SetWidth(width)", region->GetDisplayName());
}
float width = lua_tonumber(L, 2);
float ndcWidth = width / (CoordinateGetAspectCompensation() * 1024.0f);
float ddcWidth = NDCToDDCWidth(ndcWidth);
region->SetWidth(ddcWidth);
return 0;
}
int32_t CScriptRegion_GetHeight(lua_State* L) {
int32_t type = CScriptRegion::GetObjectType();
auto region = static_cast<CScriptRegion*>(FrameScript_GetObjectThis(L, type));
float height = region->GetHeight();
if (height == 0.0f && !StringToBOOL(L, 2, 0)) {
if (region->IsResizePending()) {
region->Resize(1);
}
CRect rect = { 0.0f, 0.0f, 0.0f, 0.0f };
if (region->GetRect(&rect)) {
height = (rect.maxY - rect.minY) / region->m_layoutScale;
}
}
float ddcHeight = CoordinateGetAspectCompensation() * 1024.0f * height;
float ndcHeight = DDCToNDCWidth(ddcHeight);
lua_pushnumber(L, ndcHeight);
return 1;
}
int32_t CScriptRegion_SetHeight(lua_State* L) {
int32_t type = CScriptRegion::GetObjectType();
auto region = static_cast<CScriptRegion*>(FrameScript_GetObjectThis(L, type));
if (!region->ProtectedFunctionsAllowed()) {
// TODO
// - disallowed logic
return 0;
}
if (!lua_isnumber(L, 2)) {
return luaL_error(L, "Usage: %s:SetHeight(height)", region->GetDisplayName());
}
float height = lua_tonumber(L, 2);
float ndcHeight = height / (CoordinateGetAspectCompensation() * 1024.0f);
float ddcHeight = NDCToDDCWidth(ndcHeight);
region->SetHeight(ddcHeight);
return 0;
}
int32_t CScriptRegion_SetSize(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_GetSize(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_GetNumPoints(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_GetPoint(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_SetPoint(lua_State* L) {
int32_t type = CScriptRegion::GetObjectType();
auto region = static_cast<CScriptRegion*>(FrameScript_GetObjectThis(L, type));
if (!region->ProtectedFunctionsAllowed()) {
// TODO
// - disallowed logic
return 0;
}
if (!lua_isstring(L, 2)) {
return luaL_error(L, "Usage: %s:SetPoint(\"point\" [, region or nil] [, \"relativePoint\"] [, offsetX, offsetY])", region->GetDisplayName());
}
auto relative = region->GetLayoutParent();
const char* pointStr = lua_tolstring(L, 2, 0);
FRAMEPOINT point;
if (!StringToFramePoint(pointStr, point)) {
return luaL_error(L, "%s:SetPoint(): Unknown region point", region->GetDisplayName());
}
int32_t argsIndex = 3;
if (lua_type(L, 3) == LUA_TSTRING) {
const char* name = lua_tolstring(L, 3, 0);
relative = region->GetLayoutFrameByName(name);
argsIndex++;
} else if (lua_type(L, 3) == LUA_TTABLE) {
lua_rawgeti(L, 3, 0);
auto r = reinterpret_cast<CScriptRegion*>(lua_touserdata(L, -1));
relative = r ? static_cast<CLayoutFrame*>(r) : nullptr;
lua_settop(L, -2);
argsIndex++;
} else if (lua_type(L, 3) == LUA_TNIL) {
relative = CSimpleTop::s_instance;
argsIndex++;
}
if (!relative) {
const char* name = lua_tolstring(L, 3, 0);
return luaL_error(L, "%s:SetPoint(): Couldn't find region named '%s'", region->GetDisplayName(), name);
}
if (relative == region) {
return luaL_error(L, "%s:SetPoint(): trying to anchor to itself", region->GetDisplayName());
}
if (relative->IsResizeDependency(region)) {
return luaL_error(L, "%s:SetPoint(): %s is dependent on this", region->GetDisplayName(), static_cast<CScriptRegion*>(relative)->GetDisplayName());
}
FRAMEPOINT relativePoint = point;
if (lua_type(L, argsIndex) == LUA_TSTRING) {
const char* relativePointStr = lua_tolstring(L, argsIndex, 0);
if (!StringToFramePoint(relativePointStr, relativePoint)) {
return luaL_error(L, "%s:SetPoint(): Unknown region point", region->GetDisplayName());
}
argsIndex++;
}
float offsetX = 0.0f;
float offsetY = 0.0f;
if (lua_isnumber(L, argsIndex) && lua_isnumber(L, argsIndex + 1)) {
float x = lua_tonumber(L, argsIndex);
float ndcX = x / (CoordinateGetAspectCompensation() * 1024.0f);
float ddcX = NDCToDDCWidth(ndcX);
float y = lua_tonumber(L, argsIndex + 1);
float ndcY = y / (CoordinateGetAspectCompensation() * 1024.0f);
float ddcY = NDCToDDCWidth(ndcY);
offsetX = ddcX;
offsetY = ddcY;
}
region->SetPoint(point, relative, relativePoint, offsetX, offsetY, 1);
return 0;
}
int32_t CScriptRegion_SetAllPoints(lua_State* L) {
int32_t type = CScriptRegion::GetObjectType();
auto region = static_cast<CScriptRegion*>(FrameScript_GetObjectThis(L, type));
if (!region->ProtectedFunctionsAllowed()) {
// TODO
// - disallowed logic
return 0;
}
auto relative = region->GetLayoutParent();
if (lua_isstring(L, 2)) {
const char* name = lua_tolstring(L, 2, 0);
relative = region->GetLayoutFrameByName(name);
} else if (lua_type(L, 2) == LUA_TTABLE) {
lua_rawgeti(L, 2, 0);
auto r = reinterpret_cast<CScriptRegion*>(lua_touserdata(L, -1));
relative = r ? static_cast<CLayoutFrame*>(r) : nullptr;
lua_settop(L, -2);
} else if (lua_type(L, 2) == LUA_TNIL) {
relative = CSimpleTop::s_instance;
}
if (!relative) {
const char* name = lua_tolstring(L, 2, 0);
return luaL_error(L, "%s:SetAllPoints(): Couldn't find region named '%s'", region->GetDisplayName(), name);
}
if (relative == region) {
return luaL_error(L, "%s:SetAllPoints(): trying to anchor to itself", region->GetDisplayName());
}
if (relative->IsResizeDependency(region)) {
return luaL_error(L, "%s:SetAllPoints(): %s is dependent on this", region->GetDisplayName(), static_cast<CScriptRegion*>(relative)->GetDisplayName());
}
region->SetAllPoints(relative, 1);
return 0;
}
int32_t CScriptRegion_ClearAllPoints(lua_State* L) {
int32_t type = CScriptRegion::GetObjectType();
auto region = static_cast<CScriptRegion*>(FrameScript_GetObjectThis(L, type));
if (region->ProtectedFunctionsAllowed()) {
region->ClearAllPoints();
} else {
// TODO
// void* v3 = CSimpleTop::s_instance->Function4692;
// if (v3) {
// v3(object);
// }
}
return 0;
}
int32_t CScriptRegion_CreateAnimationGroup(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_GetAnimationGroups(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_StopAnimating(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_IsDragging(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CScriptRegion_IsMouseOver(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method ScriptRegionMethods[NUM_SCRIPT_REGION_SCRIPT_METHODS] = {
{ "IsProtected", &CScriptRegion_IsProtected },
{ "CanChangeProtectedState", &CScriptRegion_CanChangeProtectedState },
{ "SetParent", &CScriptRegion_SetParent },
{ "GetRect", &CScriptRegion_GetRect },
{ "GetCenter", &CScriptRegion_GetCenter },
{ "GetLeft", &CScriptRegion_GetLeft },
{ "GetRight", &CScriptRegion_GetRight },
{ "GetTop", &CScriptRegion_GetTop },
{ "GetBottom", &CScriptRegion_GetBottom },
{ "GetWidth", &CScriptRegion_GetWidth },
{ "SetWidth", &CScriptRegion_SetWidth },
{ "GetHeight", &CScriptRegion_GetHeight },
{ "SetHeight", &CScriptRegion_SetHeight },
{ "SetSize", &CScriptRegion_SetSize },
{ "GetSize", &CScriptRegion_GetSize },
{ "GetNumPoints", &CScriptRegion_GetNumPoints },
{ "GetPoint", &CScriptRegion_GetPoint },
{ "SetPoint", &CScriptRegion_SetPoint },
{ "SetAllPoints", &CScriptRegion_SetAllPoints },
{ "ClearAllPoints", &CScriptRegion_ClearAllPoints },
{ "CreateAnimationGroup", &CScriptRegion_CreateAnimationGroup },
{ "GetAnimationGroups", &CScriptRegion_GetAnimationGroups },
{ "StopAnimating", &CScriptRegion_StopAnimating },
{ "IsDragging", &CScriptRegion_IsDragging },
{ "IsMouseOver", &CScriptRegion_IsMouseOver }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SCRIPT_REGION_SCRIPT_HPP
#define UI_C_SCRIPT_REGION_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SCRIPT_REGION_SCRIPT_METHODS 25
extern FrameScript_Method ScriptRegionMethods[NUM_SCRIPT_REGION_SCRIPT_METHODS];
#endif

617
src/ui/CSimpleButton.cpp Normal file
View file

@ -0,0 +1,617 @@
#include "ui/CSimpleButton.hpp"
#include "event/Input.hpp"
#include "ui/CSimpleButtonScript.hpp"
#include "ui/CSimpleFont.hpp"
#include "ui/CSimpleFontString.hpp"
#include "ui/CSimpleTexture.hpp"
#include "ui/CSimpleTop.hpp"
#include "ui/LoadXML.hpp"
#include "util/CStatus.hpp"
#include "util/Lua.hpp"
#include <common/Time.hpp>
#include <common/XML.hpp>
#include <storm/String.hpp>
int32_t CSimpleButton::s_metatable;
int32_t CSimpleButton::s_objectType;
void CSimpleButton::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleButton::RegisterScriptMethods);
CSimpleButton::s_metatable = ref;
}
int32_t CSimpleButton::GetObjectType() {
if (!CSimpleButton::s_objectType) {
CSimpleButton::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CSimpleButton::s_objectType;
}
void CSimpleButton::RegisterScriptMethods(lua_State* L) {
CSimpleFrame::RegisterScriptMethods(L);
FrameScript_Object::FillScriptMethodTable(L, SimpleButtonMethods, NUM_SIMPLE_BUTTON_SCRIPT_METHODS);
}
CSimpleButton::CSimpleButton(CSimpleFrame* parent) : CSimpleFrame(parent) {
this->m_pressedOffset = { 0.001, -0.001 };
this->m_textures[BUTTONSTATE_DISABLED] = nullptr;
this->m_textures[BUTTONSTATE_NORMAL] = nullptr;
this->m_textures[BUTTONSTATE_PUSHED] = nullptr;
this->Enable(1);
this->EnableEvent(SIMPLE_EVENT_MOUSE, -1);
this->SetFrameFlag(0x10000, 1);
}
void CSimpleButton::Enable(int32_t enabled) {
if (enabled) {
if (this->m_state != BUTTONSTATE_DISABLED) {
return;
}
this->SetButtonState(BUTTONSTATE_NORMAL, 0);
if (this == this->m_top->m_mouseFocus) {
this->OnLayerCursorEnter(0);
}
if (this->m_highlightLocked) {
this->EnableDrawLayer(DRAWLAYER_HIGHLIGHT);
}
} else {
if (this->m_state == BUTTONSTATE_DISABLED) {
return;
}
if (this == this->m_top->m_mouseFocus) {
this->OnLayerCursorExit(0, 1);
}
this->DisableDrawLayer(DRAWLAYER_HIGHLIGHT);
this->SetButtonState(BUTTONSTATE_DISABLED, 0);
}
this->SetFrameFlag(0x400, enabled == 0);
auto& script = enabled ? this->m_onEnable : this->m_onDisable;
if (script.luaRef && !this->m_loading) {
this->RunScript(script, 0, nullptr);
}
}
FrameScript_Object::ScriptIx* CSimpleButton::GetScriptByName(const char* name, ScriptData& data) {
auto parentScript = CSimpleFrame::GetScriptByName(name, data);
if (parentScript) {
return parentScript;
}
if (!SStrCmpI(name, "PreClick", STORM_MAX_STR)) {
data.wrapper = "return function(self,button,down) %s end";
return &this->m_preClick;
}
if (!SStrCmpI(name, "OnClick", STORM_MAX_STR)) {
data.wrapper = "return function(self,button,down) %s end";
return &this->m_onClick;
}
if (!SStrCmpI(name, "PostClick", STORM_MAX_STR)) {
data.wrapper = "return function(self,button,down) %s end";
return &this->m_postClick;
}
if (!SStrCmpI(name, "OnDoubleClick", STORM_MAX_STR)) {
data.wrapper = "return function(self,button) %s end";
return &this->m_onDoubleClick;
}
return nullptr;
}
int32_t CSimpleButton::GetScriptMetaTable() {
return CSimpleButton::s_metatable;
}
bool CSimpleButton::IsA(int32_t type) {
return type == CSimpleButton::s_objectType
|| type == CSimpleFrame::s_objectType
|| type == CScriptRegion::s_objectType
|| type == CScriptObject::s_objectType;
}
void CSimpleButton::LoadXML(XMLNode* node, CStatus* status) {
CSimpleFrame::LoadXML(node, status);
CSimpleFontString* buttonText = nullptr;
for (XMLNode* child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "NormalTexture", STORM_MAX_STR)) {
CSimpleTexture* texture = LoadXML_Texture(child, this, status);
this->SetStateTexture(BUTTONSTATE_NORMAL, texture);
} else if (!SStrCmpI(child->GetName(), "PushedTexture", STORM_MAX_STR)) {
CSimpleTexture* texture = LoadXML_Texture(child, this, status);
this->SetStateTexture(BUTTONSTATE_PUSHED, texture);
} else if (!SStrCmpI(child->GetName(), "DisabledTexture", STORM_MAX_STR)) {
CSimpleTexture* texture = LoadXML_Texture(child, this, status);
this->SetStateTexture(BUTTONSTATE_DISABLED, texture);
} else if (!SStrCmpI(child->GetName(), "HighlightTexture", STORM_MAX_STR)) {
CSimpleTexture* texture = LoadXML_Texture(child, this, status);
this->SetHighlight(texture, texture->m_alphaMode);
} else if (!SStrCmpI(child->GetName(), "ButtonText", STORM_MAX_STR)) {
buttonText = LoadXML_String(child, this, status);
} else if (!SStrCmpI(child->GetName(), "NormalFont", STORM_MAX_STR)) {
const char* fontName = child->GetAttributeByName("style");
if (fontName && *fontName) {
CSimpleFont* font = CSimpleFont::GetFont(fontName, 0);
this->m_normalFont = font;
if (!font) {
status->Add(STATUS_WARNING, "Couldn't find NORMAL font: %s", fontName);
}
}
} else if (!SStrCmpI(child->GetName(), "DisabledFont", STORM_MAX_STR)) {
const char* fontName = child->GetAttributeByName("style");
if (fontName && *fontName) {
CSimpleFont* font = CSimpleFont::GetFont(fontName, 0);
this->m_disabledFont = font;
if (!font) {
status->Add(STATUS_WARNING, "Couldn't find DISABLED font: %s", fontName);
}
}
} else if (!SStrCmpI(child->GetName(), "HighlightFont", STORM_MAX_STR)) {
const char* fontName = child->GetAttributeByName("style");
if (fontName && *fontName) {
CSimpleFont* font = CSimpleFont::GetFont(fontName, 0);
this->m_highlightFont = font;
if (!font) {
status->Add(STATUS_WARNING, "Couldn't find HIGHLIGHT font: %s", fontName);
}
}
} else if (!SStrCmpI(child->GetName(), "NormalColor", STORM_MAX_STR)) {
// TODO
} else if (!SStrCmpI(child->GetName(), "DisabledColor", STORM_MAX_STR)) {
// TODO
} else if (!SStrCmpI(child->GetName(), "HighlightColor", STORM_MAX_STR)) {
// TODO
} else if (!SStrCmpI(child->GetName(), "PushedTextOffset", STORM_MAX_STR)) {
float x, y;
if (LoadXML_Dimensions(child, x, y, status)) {
C2Vector offset = { x, y };
this->SetPressedOffset(offset);
}
}
}
if (buttonText) {
this->SetFontString(buttonText);
} else {
// TODO
// int32_t v24 = (this + 162) << 28 >> 28;
// this->UpdateTextState(v24);
}
const char* textRef = node->GetAttributeByName("text");
if (textRef && *textRef) {
const char* text = FrameScript_GetText(textRef, -1, GENDER_NOT_APPLICABLE);
if (!text || !*text) {
text = textRef;
}
this->SetText(text);
}
// TODO
// - registerForClicks
// TODO
// - motionScriptsWhileDisabled
}
void CSimpleButton::LockHighlight(int32_t lock) {
CSimpleFrame::LockHighlight(lock);
this->UpdateTextState(this->m_state);
}
void CSimpleButton::OnClick(const char* btn, int32_t a3) {
// TODO
// - also check this->m_unk != 1
if (this->m_state != BUTTONSTATE_DISABLED) {
// TODO
// const char* old1234 = this->m_top->m_char1234;
// this->m_top->m_char1234 = btn;
// TODO
// this->m_unk = 1;
this->RunOnClickScript(btn, a3);
// TODO
// this->m_unk = 0;
// TODO
// this->m_top->m_char1234 = old1234;
}
}
void CSimpleButton::OnDoubleClick(const char* btn) {
// TODO
}
void CSimpleButton::OnLayerCursorEnter(int32_t a2) {
if (this->m_state == BUTTONSTATE_DISABLED) {
// TODO
// if (this->GetMotionScriptsWhileDisabled()) {
// if (this->m_tooltip) {
// this->m_tooltip->Show();
// }
//
// this->RunOnEnterScript(a2);
// }
} else {
CSimpleFrame::OnLayerCursorEnter(a2);
this->UpdateTextState(this->m_state);
}
}
void CSimpleButton::OnLayerCursorExit(int32_t a2, int32_t a3) {
if (this->m_state == BUTTONSTATE_DISABLED) {
// TODO
// if (this->GetMotionScriptsWhileDisabled()) {
// if (this->m_tooltip) {
// this->m_tooltip->Hide();
// }
//
// this->RunOnLeaveScript(a2);
// }
} else {
CSimpleFrame::OnLayerCursorExit(a2, a3);
this->UpdateTextState(this->m_state);
}
}
void CSimpleButton::OnLayerHide() {
if (this->m_state && !this->m_stateLocked) {
this->SetButtonState(BUTTONSTATE_NORMAL, 0);
}
CSimpleFrame::OnLayerHide();
}
int32_t CSimpleButton::OnLayerMouseDown(const CMouseEvent& evt, const char* btn) {
if (CSimpleFrame::OnLayerMouseDown(evt, btn)) {
return 1;
}
C2Vector pt = { evt.x, evt.y };
if ((btn || this->TestHitRect(pt)) && this->m_state != BUTTONSTATE_DISABLED) {
int32_t v7 = btn ? 0x7FFFFFFF : evt.button;
if (this->m_clickAction & v7) {
if (!btn) {
btn = GetButtonName(evt.button);
}
// TODO
// this->m_top->m_int1241 = 1;
this->OnClick(btn, 1);
// TODO
// this->m_top->m_int1241 = 0;
}
if (!this->m_stateLocked && this->m_state != BUTTONSTATE_DISABLED) {
this->SetButtonState(BUTTONSTATE_PUSHED, 0);
}
return 1;
}
return 0;
}
int32_t CSimpleButton::OnLayerMouseUp(const CMouseEvent& evt, const char* btn) {
if (CSimpleFrame::OnLayerMouseUp(evt, btn)) {
return 1;
}
if (this->m_state != BUTTONSTATE_PUSHED) {
return 1;
}
C2Vector pt = { evt.x, evt.y };
if (btn || this->TestHitRect(pt)) {
uint64_t v6 = btn ? 0xFFFFFFFF80000000 : static_cast<uint64_t>(evt.button) << 31;
if (this->m_clickAction & v6) {
if (!btn) {
btn = GetButtonName(evt.button);
}
// TODO
// this->m_top->m_int1241 = 1;
uint32_t currentTime = OsGetAsyncTimeMs();
if (this->m_onDoubleClick.luaRef && this->m_doubleClickTime && currentTime - this->m_doubleClickTime <= 300) {
this->OnDoubleClick(btn);
this->m_doubleClickTime = 0;
} else {
this->OnClick(btn, 0);
this->m_doubleClickTime = currentTime;
}
// TODO
// this->m_top->m_int1241 = 0;
}
}
if (!this->m_stateLocked && this->m_state != BUTTONSTATE_DISABLED) {
this->SetButtonState(BUTTONSTATE_NORMAL, 0);
}
return 1;
}
void CSimpleButton::RunOnClickScript(const char* btn, int32_t down) {
if (this->m_preClick.luaRef) {
auto L = FrameScript_GetContext();
lua_pushstring(L, btn);
lua_pushboolean(L, down);
this->RunScript(this->m_preClick, 2, 0);
}
if (this->m_onClick.luaRef) {
auto L = FrameScript_GetContext();
lua_pushstring(L, btn);
lua_pushboolean(L, down);
this->RunScript(this->m_onClick, 2, 0);
}
if (this->m_postClick.luaRef) {
auto L = FrameScript_GetContext();
lua_pushstring(L, btn);
lua_pushboolean(L, down);
this->RunScript(this->m_postClick, 2, 0);
}
}
void CSimpleButton::SetButtonState(CSimpleButtonState state, int32_t stateLocked) {
this->m_stateLocked = stateLocked;
if (state == this->m_state) {
return;
}
if (this->m_activeTexture && (this->m_textures[state] || state == BUTTONSTATE_NORMAL)) {
this->m_activeTexture->Hide();
this->m_activeTexture = nullptr;
}
if (this->m_textures[state]) {
this->m_activeTexture = this->m_textures[state];
this->m_activeTexture->Show();
}
this->UpdateTextState(state);
this->m_state = state;
}
void CSimpleButton::SetClickAction(uint64_t action) {
this->m_clickAction = action;
}
void CSimpleButton::SetHighlight(CSimpleTexture* texture, EGxBlend blend) {
if (texture == this->m_highlightTexture) {
return;
}
if (this->m_highlightTexture) {
delete this->m_highlightTexture;
}
if (texture) {
texture->SetFrame(this, DRAWLAYER_HIGHLIGHT, 1);
texture->SetBlendMode(blend);
}
this->m_highlightTexture = texture;
}
int32_t CSimpleButton::SetHighlight(const char* texFile, EGxBlend blendMode) {
if (this->m_highlightTexture) {
this->m_highlightTexture->SetTexture(texFile, false, false, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
this->m_highlightTexture->SetBlendMode(blendMode);
return 1;
}
// TODO void* m = CDataAllocator::GetData(CSimpleTexture::s_allocator, 0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
auto texture = new (m) CSimpleTexture(this, DRAWLAYER_HIGHLIGHT, 1);
if (!texture->SetTexture(texFile, false, false, CSimpleTexture::s_textureFilterMode, ImageMode_UI)) {
delete texture;
return 0;
}
texture->SetAllPoints(this, 1);
texture->SetBlendMode(blendMode);
this->m_highlightTexture = texture;
return 1;
}
void CSimpleButton::SetFontString(CSimpleFontString* text) {
if (this->m_text == text) {
return;
}
if (this->m_text) {
delete this->m_text;
}
if (text) {
text->SetFrame(this, 2, 1);
}
if (!text->Sub482AC0()) {
auto font = this->m_normalFont;
int32_t styleFlags;
if (font) {
styleFlags = font->m_attributes.m_styleFlags;
} else {
styleFlags = 0;
}
float offsetX = 0.0f;
float offsetY = 0.0f;
if (styleFlags & 0x1) {
text->SetPoint(FRAMEPOINT_LEFT, this, FRAMEPOINT_LEFT, offsetX, offsetY, 1);
} else if (styleFlags & 0x4) {
text->SetPoint(FRAMEPOINT_RIGHT, this, FRAMEPOINT_RIGHT, offsetX, offsetY, 1);
} else {
text->SetPoint(FRAMEPOINT_CENTER, this, FRAMEPOINT_CENTER, offsetX, offsetY, 1);
}
}
this->m_text = text;
this->UpdateTextState(this->m_state);
}
void CSimpleButton::SetPressedOffset(C2Vector& offset) {
this->m_pressedOffset = offset;
}
void CSimpleButton::SetStateTexture(CSimpleButtonState state, CSimpleTexture* texture) {
if (this->m_textures[state] == texture) {
return;
}
if (this->m_textures[state] == this->m_activeTexture) {
this->m_activeTexture = nullptr;
}
if (this->m_textures[state]) {
delete this->m_textures[state];
}
if (texture) {
texture->SetFrame(this, DRAWLAYER_ARTWORK, 0);
}
this->m_textures[state] = texture;
if (texture) {
if (state == this->m_state) {
this->m_activeTexture = texture;
texture->Show();
}
}
}
int32_t CSimpleButton::SetStateTexture(CSimpleButtonState state, const char* texFile) {
if (this->m_textures[state]) {
this->m_textures[state]->SetTexture(texFile, false, false, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
return 1;
}
// TODO void* m = CDataAllocator::GetData(CSimpleTexture::s_allocator, 0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0x0);
auto texture = new (m) CSimpleTexture(nullptr, 2, 1);
if (texture->SetTexture(texFile, false, false, CSimpleTexture::s_textureFilterMode, ImageMode_UI)) {
texture->SetAllPoints(this, 1);
this->SetStateTexture(state, texture);
return 1;
}
if (texture) {
delete texture;
}
return 0;
}
void CSimpleButton::SetText(const char* string) {
if ((string && *string) || this->m_text) {
if (!this->m_text) {
// TODO
// void* m = CDataAllocator::GetData(CSimpleFontString::s_allocator, 0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleFontString), __FILE__, __LINE__, 0x0);
CSimpleFontString* text;
if (m) {
text = new (m) CSimpleFontString(this, 2, 1);
} else {
text = nullptr;
}
this->SetFontString(text);
}
this->m_text->SetText(string, 1);
}
}
void CSimpleButton::UpdateTextState(CSimpleButtonState state) {
if (!this->m_text) {
return;
}
if (state == BUTTONSTATE_PUSHED) {
this->m_text->SetJustificationOffset(this->m_pressedOffset.x, this->m_pressedOffset.y);
} else {
this->m_text->SetJustificationOffset(0.0f, 0.0f);
}
if (state == BUTTONSTATE_DISABLED) {
this->m_text->SetFontObject(this->m_disabledFont);
} else if (this->m_drawenabled[DRAWLAYER_HIGHLIGHT]) {
this->m_text->SetFontObject(this->m_highlightFont);
} else {
this->m_text->SetFontObject(this->m_normalFont);
}
}

77
src/ui/CSimpleButton.hpp Normal file
View file

@ -0,0 +1,77 @@
#ifndef UI_C_SIMPLE_BUTTON_HPP
#define UI_C_SIMPLE_BUTTON_HPP
#include "ui/CSimpleFrame.hpp"
#include <tempest/Vector.hpp>
class CSimpleFont;
class CSimpleFontString;
class CSimpleTexture;
enum CSimpleButtonState {
BUTTONSTATE_DISABLED = 0x0,
BUTTONSTATE_NORMAL = 0x1,
BUTTONSTATE_PUSHED = 0x2,
NUM_BUTTONSTATES = 0x3,
};
class CSimpleButton : public CSimpleFrame {
public:
// Static variables
static int32_t s_metatable;
static int32_t s_objectType;
// Static functions
static void CreateScriptMetaTable(void);
static int32_t GetObjectType(void);
static void RegisterScriptMethods(lua_State*);
// Member variables
uint32_t m_doubleClickTime = 0;
uint64_t m_clickAction = 0x0000000080000000;
CSimpleButtonState m_state = BUTTONSTATE_DISABLED;
int32_t m_stateLocked = 0;
CSimpleFontString* m_text = nullptr;
CSimpleFont* m_normalFont = nullptr;
CSimpleFont* m_highlightFont = nullptr;
CSimpleFont* m_disabledFont = nullptr;
C2Vector m_pressedOffset;
CSimpleTexture* m_textures[NUM_BUTTONSTATES];
CSimpleTexture* m_activeTexture = nullptr;
CSimpleTexture* m_highlightTexture = nullptr;
ScriptIx m_preClick;
ScriptIx m_onClick;
ScriptIx m_postClick;
ScriptIx m_onDoubleClick;
// Virtual member functions
virtual ScriptIx* GetScriptByName(const char*, ScriptData&);
virtual bool IsA(int32_t);
virtual int32_t GetScriptMetaTable(void);
virtual void LoadXML(XMLNode*, CStatus*);
virtual void OnLayerHide(void);
virtual void OnLayerCursorEnter(int32_t);
virtual void OnLayerCursorExit(int32_t, int32_t);
virtual int32_t OnLayerMouseDown(const CMouseEvent&, const char*);
virtual int32_t OnLayerMouseUp(const CMouseEvent&, const char*);
virtual void LockHighlight(int32_t);
virtual void Enable(int32_t);
virtual void OnClick(const char*, int32_t);
virtual void OnDoubleClick(const char*);
virtual void SetButtonState(CSimpleButtonState, int32_t);
// Member functions
CSimpleButton(CSimpleFrame*);
void RunOnClickScript(const char*, int32_t);
void SetClickAction(uint64_t action);
void SetFontString(CSimpleFontString*);
void SetHighlight(CSimpleTexture*, EGxBlend);
int32_t SetHighlight(const char* texFile, EGxBlend blendMode);
void SetPressedOffset(C2Vector&);
void SetStateTexture(CSimpleButtonState, CSimpleTexture*);
int32_t SetStateTexture(CSimpleButtonState state, const char* texFile);
void SetText(const char*);
void UpdateTextState(CSimpleButtonState);
};
#endif

View file

@ -0,0 +1,349 @@
#include "ui/CSimpleButtonScript.hpp"
#include "gx/Coordinate.hpp"
#include "ui/CSimpleButton.hpp"
#include "ui/CSimpleFontString.hpp"
#include "ui/CSimpleTexture.hpp"
#include "util/Lua.hpp"
#include "util/StringTo.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleButton_SetStateTexture(lua_State* L, CSimpleButtonState state, const char* method) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
if (lua_type(L, 2) == LUA_TTABLE) {
lua_rawgeti(L, 2, 0);
auto texture = static_cast<CSimpleTexture*>(lua_touserdata(L, -1));
lua_settop(L, -2);
if (!texture) {
luaL_error(L, "%s:%s(): Couldn't find 'this' in texture", button->GetDisplayName(), method);
}
if (!texture->IsA(CSimpleTexture::GetObjectType())) {
luaL_error(L, "%s:%s(): Wrong object type, expected texture", button->GetDisplayName(), method);
}
button->SetStateTexture(state, texture);
} else if (lua_isstring(L, 2)) {
auto texFile = lua_tolstring(L, 2, nullptr);
button->SetStateTexture(state, texFile);
} else if (lua_type(L, 2) == LUA_TNIL) {
CSimpleTexture* texture = nullptr;
button->SetStateTexture(state, texture);
} else {
luaL_error(L, "Usage: %s:%s(texture or \"texture\" or nil)", button->GetDisplayName(), method);
}
return 0;
}
int32_t CSimpleButton_Enable(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
if (button->ProtectedFunctionsAllowed()) {
button->Enable(1);
} else {
// TODO
// - disallowed logic
}
return 0;
}
int32_t CSimpleButton_Disable(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
if (button->ProtectedFunctionsAllowed()) {
button->Enable(0);
} else {
// TODO
// - disallowed logic
}
return 0;
}
int32_t CSimpleButton_IsEnabled(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_GetButtonState(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_SetButtonState(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_SetNormalFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_GetNormalFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_SetDisabledFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_GetDisabledFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_SetHighlightFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_GetHighlightFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_SetFontString(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_GetFontString(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_SetText(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
const char* text = lua_tolstring(L, 2, 0);
button->SetText(text);
return 0;
}
int32_t CSimpleButton_SetFormattedText(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_GetText(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
const char* text = nullptr;
if (button->m_text && button->m_text->GetText() && *button->m_text->GetText()) {
text = button->m_text->GetText();
}
lua_pushstring(L, text);
return 1;
}
int32_t CSimpleButton_SetNormalTexture(lua_State* L) {
return CSimpleButton_SetStateTexture(L, BUTTONSTATE_NORMAL, "SetNormalTexture");
}
int32_t CSimpleButton_GetNormalTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_SetPushedTexture(lua_State* L) {
return CSimpleButton_SetStateTexture(L, BUTTONSTATE_PUSHED, "SetPushedTexture");
}
int32_t CSimpleButton_GetPushedTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_SetDisabledTexture(lua_State* L) {
return CSimpleButton_SetStateTexture(L, BUTTONSTATE_DISABLED, "SetDisabledTexture");
}
int32_t CSimpleButton_GetDisabledTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_SetHighlightTexture(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
EGxBlend blendMode = GxBlend_Add;
if (lua_isstring(L, 3)) {
auto blendString = lua_tolstring(L, 3, nullptr);
StringToBlendMode(blendString, blendMode);
}
if (lua_type(L, 2) == LUA_TTABLE) {
lua_rawgeti(L, 2, 0);
auto texture = static_cast<CSimpleTexture*>(lua_touserdata(L, -1));
lua_settop(L, -2);
if (!texture) {
luaL_error(L, "%s:SetHighlightTexture(): Couldn't find 'this' in texture", button->GetDisplayName());
}
if (!texture->IsA(CSimpleTexture::GetObjectType())) {
luaL_error(L, "%s:SetHighlightTexture(): Wrong object type, expected texture", button->GetDisplayName());
}
button->SetHighlight(texture, blendMode);
} else if (lua_isstring(L, 2)) {
auto texFile = lua_tolstring(L, 2, nullptr);
button->SetHighlight(texFile, blendMode);
} else if (lua_type(L, 2) == LUA_TNIL) {
CSimpleTexture* texture = nullptr;
button->SetHighlight(texture, GxBlend_Add);
} else {
luaL_error(L, "Usage: %s:SetHighlightTexture(texture or \"texture\" or nil [, \"blendmode\")", button->GetDisplayName());
}
return 0;
}
int32_t CSimpleButton_GetHighlightTexture(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
auto texture = button->m_highlightTexture;
if (texture) {
if (!texture->lua_registered) {
texture->RegisterScriptObject(nullptr);
}
lua_rawgeti(L, LUA_REGISTRYINDEX, texture->lua_objectRef);
} else {
lua_pushnil(L);
}
return 1;
}
int32_t CSimpleButton_SetPushedTextOffset(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_GetPushedTextOffset(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_GetTextWidth(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
auto text = button->m_text;
float width = text ? text->GetWidth() : 0.0f;
float ddcWidth = CoordinateGetAspectCompensation() * 1024.0f * width;
float ndcWidth = DDCToNDCWidth(ddcWidth);
lua_pushnumber(L, ndcWidth);
return 1;
}
int32_t CSimpleButton_GetTextHeight(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_RegisterForClicks(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
uint64_t action = 0;
for (int32_t i = 2; lua_isstring(L, i); i++) {
auto actionStr = lua_tolstring(L, i, nullptr);
action |= StringToClickAction(actionStr);
}
button->SetClickAction(action);
return 0;
}
int32_t CSimpleButton_Click(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
auto inputButton = "LeftButton";
if (lua_isstring(L, 2)) {
inputButton = lua_tolstring(L, 2, nullptr);
}
auto v6 = StringToBOOL(L, 3, 0);
button->OnClick(inputButton, v6);
return 0;
}
int32_t CSimpleButton_LockHighlight(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
button->LockHighlight(1);
return 0;
}
int32_t CSimpleButton_UnlockHighlight(lua_State* L) {
auto type = CSimpleButton::GetObjectType();
auto button = static_cast<CSimpleButton*>(FrameScript_GetObjectThis(L, type));
button->LockHighlight(0);
return 0;
}
int32_t CSimpleButton_GetMotionScriptsWhileDisabled(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleButton_SetMotionScriptsWhileDisabled(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleButtonMethods[NUM_SIMPLE_BUTTON_SCRIPT_METHODS] = {
{ "Enable", &CSimpleButton_Enable },
{ "Disable", &CSimpleButton_Disable },
{ "IsEnabled", &CSimpleButton_IsEnabled },
{ "GetButtonState", &CSimpleButton_GetButtonState },
{ "SetButtonState", &CSimpleButton_SetButtonState },
{ "SetNormalFontObject", &CSimpleButton_SetNormalFontObject },
{ "GetNormalFontObject", &CSimpleButton_GetNormalFontObject },
{ "SetDisabledFontObject", &CSimpleButton_SetDisabledFontObject },
{ "GetDisabledFontObject", &CSimpleButton_GetDisabledFontObject },
{ "SetHighlightFontObject", &CSimpleButton_SetHighlightFontObject },
{ "GetHighlightFontObject", &CSimpleButton_GetHighlightFontObject },
{ "SetFontString", &CSimpleButton_SetFontString },
{ "GetFontString", &CSimpleButton_GetFontString },
{ "SetText", &CSimpleButton_SetText },
{ "SetFormattedText", &CSimpleButton_SetFormattedText },
{ "GetText", &CSimpleButton_GetText },
{ "SetNormalTexture", &CSimpleButton_SetNormalTexture },
{ "GetNormalTexture", &CSimpleButton_GetNormalTexture },
{ "SetPushedTexture", &CSimpleButton_SetPushedTexture },
{ "GetPushedTexture", &CSimpleButton_GetPushedTexture },
{ "SetDisabledTexture", &CSimpleButton_SetDisabledTexture },
{ "GetDisabledTexture", &CSimpleButton_GetDisabledTexture },
{ "SetHighlightTexture", &CSimpleButton_SetHighlightTexture },
{ "GetHighlightTexture", &CSimpleButton_GetHighlightTexture },
{ "SetPushedTextOffset", &CSimpleButton_SetPushedTextOffset },
{ "GetPushedTextOffset", &CSimpleButton_GetPushedTextOffset },
{ "GetTextWidth", &CSimpleButton_GetTextWidth },
{ "GetTextHeight", &CSimpleButton_GetTextHeight },
{ "RegisterForClicks", &CSimpleButton_RegisterForClicks },
{ "Click", &CSimpleButton_Click },
{ "LockHighlight", &CSimpleButton_LockHighlight },
{ "UnlockHighlight", &CSimpleButton_UnlockHighlight },
{ "GetMotionScriptsWhileDisabled", &CSimpleButton_GetMotionScriptsWhileDisabled },
{ "SetMotionScriptsWhileDisabled", &CSimpleButton_SetMotionScriptsWhileDisabled }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_BUTTON_SCRIPT_HPP
#define UI_C_SIMPLE_BUTTON_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_BUTTON_SCRIPT_METHODS 34
extern FrameScript_Method SimpleButtonMethods[NUM_SIMPLE_BUTTON_SCRIPT_METHODS];
#endif

View file

@ -0,0 +1,40 @@
#include "ui/CSimpleCheckbox.hpp"
#include "ui/CSimpleCheckboxScript.hpp"
int32_t CSimpleCheckbox::s_metatable;
int32_t CSimpleCheckbox::s_objectType;
void CSimpleCheckbox::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleCheckbox::RegisterScriptMethods);
CSimpleCheckbox::s_metatable = ref;
}
int32_t CSimpleCheckbox::GetObjectType() {
if (!CSimpleCheckbox::s_objectType) {
CSimpleCheckbox::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CSimpleCheckbox::s_objectType;
}
void CSimpleCheckbox::RegisterScriptMethods(lua_State* L) {
CSimpleButton::RegisterScriptMethods(L);
FrameScript_Object::FillScriptMethodTable(L, SimpleCheckboxMethods, NUM_SIMPLE_CHECKBOX_SCRIPT_METHODS);
}
CSimpleCheckbox::CSimpleCheckbox(CSimpleFrame* parent) : CSimpleButton(parent) {
// TODO
}
int32_t CSimpleCheckbox::GetScriptMetaTable() {
return CSimpleCheckbox::s_metatable;
}
bool CSimpleCheckbox::IsA(int32_t type) {
return type == CSimpleCheckbox::s_objectType
|| type == CSimpleButton::s_objectType
|| type == CSimpleFrame::s_objectType
|| type == CScriptRegion::s_objectType
|| type == CScriptObject::s_objectType;
}

View file

@ -0,0 +1,27 @@
#ifndef UI_C_SIMPLE_CHECKBOX_HPP
#define UI_C_SIMPLE_CHECKBOX_HPP
#include "ui/CSimpleButton.hpp"
class CSimpleCheckbox : public CSimpleButton {
public:
// Static variables
static int32_t s_metatable;
static int32_t s_objectType;
// Static functions
static void CreateScriptMetaTable(void);
static int32_t GetObjectType(void);
static void RegisterScriptMethods(lua_State*);
// Member variables
// Virtual member functions
virtual bool IsA(int32_t);
virtual int32_t GetScriptMetaTable(void);
// Member functions
CSimpleCheckbox(CSimpleFrame*);
};
#endif

View file

@ -0,0 +1,36 @@
#include "ui/CSimpleCheckboxScript.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleCheckbox_SetChecked(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleCheckbox_GetChecked(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleCheckbox_GetCheckedTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleCheckbox_SetCheckedTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleCheckbox_GetDisabledCheckedTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleCheckbox_SetDisabledCheckedTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleCheckboxMethods[NUM_SIMPLE_CHECKBOX_SCRIPT_METHODS] = {
{ "SetChecked", &CSimpleCheckbox_SetChecked },
{ "GetChecked", &CSimpleCheckbox_GetChecked },
{ "GetCheckedTexture", &CSimpleCheckbox_GetCheckedTexture },
{ "SetCheckedTexture", &CSimpleCheckbox_SetCheckedTexture },
{ "GetDisabledCheckedTexture", &CSimpleCheckbox_GetDisabledCheckedTexture },
{ "SetDisabledCheckedTexture", &CSimpleCheckbox_SetDisabledCheckedTexture }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_CHECKBOX_SCRIPT_HPP
#define UI_C_SIMPLE_CHECKBOX_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_CHECKBOX_SCRIPT_METHODS 6
extern FrameScript_Method SimpleCheckboxMethods[NUM_SIMPLE_CHECKBOX_SCRIPT_METHODS];
#endif

1349
src/ui/CSimpleEditBox.cpp Normal file

File diff suppressed because it is too large Load diff

114
src/ui/CSimpleEditBox.hpp Normal file
View file

@ -0,0 +1,114 @@
#ifndef UI_C_SIMPLE_EDIT_BOX_HPP
#define UI_C_SIMPLE_EDIT_BOX_HPP
#include "ui/CSimpleFrame.hpp"
#include "ui/CSimpleFontedFrame.hpp"
class CSimpleFontString;
class CSimpleTexture;
class CSimpleEditBox : public CSimpleFrame, CSimpleFontedFrame {
public:
// Static variables
static CSimpleEditBox* s_currentFocus;
static int32_t s_metatable;
static int32_t s_objectType;
// Static functions
static void CreateScriptMetaTable(void);
static int32_t GetObjectType(void);
static void RegisterScriptMethods(lua_State*);
static void SetKeyboardFocus(CSimpleEditBox*);
// Member variables
int32_t m_autoFocus : 1;
int32_t m_multiline : 1;
int32_t m_numeric : 1;
int32_t m_password : 1;
int32_t m_ignoreArrows : 1;
int32_t m_countInvisibleLetters : 1;
int32_t m_dirtyFlags = 0x1;
CSimpleFontedFrameFont* m_font;
CSimpleFontString* m_string;
char* m_text;
uint32_t* m_textInfo;
char* m_textHidden = nullptr;
int32_t m_textLength = 0;
int32_t m_textLengthMax = -1;
int32_t m_textLettersMax = 0;
int32_t m_textSize = 32;
int32_t m_visiblePos = 0;
int32_t m_visibleLen = 0;
CSimpleTexture* m_highlight[3];
int32_t m_highlightLeft = 0;
int32_t m_highlightRight = 0;
int32_t m_highlightDrag = 0;
CSimpleTexture* m_cursor = nullptr;
int32_t m_cursorPos = 0;
float m_cursorBlinkSpeed = 0.5f;
float m_blinkElapsedTime = 0.0f;
TSGrowableArray<uint32_t> m_visibleLines;
int32_t m_imeInputMode = 0;
CRect m_editTextInset = {};
ScriptIx m_onEnterPressed;
ScriptIx m_onEscapePressed;
ScriptIx m_onSpacePressed;
ScriptIx m_onTabPressed;
ScriptIx m_onTextChanged;
ScriptIx m_onTextSet;
ScriptIx m_onCursorChanged;
ScriptIx m_onInputLanguageChanged;
ScriptIx m_onEditFocusGained;
ScriptIx m_onEditFocusLost;
ScriptIx m_onCharComposition;
// Virtual member functions
virtual ScriptIx* GetScriptByName(const char*, ScriptData&);
virtual bool IsA(int32_t);
virtual int32_t GetScriptMetaTable(void);
virtual void LoadXML(XMLNode*, CStatus*);
virtual void OnLayerUpdate(float);
virtual void OnFrameSizeChanged(float, float);
virtual int32_t OnLayerChar(const CCharEvent&);
virtual int32_t OnLayerKeyDown(const CKeyEvent&);
virtual int32_t OnLayerMouseDown(const CMouseEvent&, const char*);
virtual int32_t OnLayerMouseUp(const CMouseEvent&, const char*);
virtual void FontUpdated(CSimpleFontedFrameFont*, int32_t);
// Member functions
CSimpleEditBox(CSimpleFrame*);
int32_t ConvertCoordinateToIndex(float, float, int32_t&);
void DeleteBackward(int32_t a2);
void DeleteForward(int32_t a2);
void DeleteHighlight(int32_t);
void DeleteSubstring(int32_t left, int32_t right, int32_t a4);
int32_t GetNumToLen(int32_t, int32_t, bool);
void GrowText(int32_t);
void Insert(uint32_t);
void Insert(const char*, const char*, int32_t, int32_t, int32_t);
int32_t IsCurrentFocus(void);
void Move(int32_t distance, int32_t highlight);
void MoveBackward(int32_t highlight);
void MoveForward(int32_t highlight);
void OnEnterPressed(void);
void OnEscapePressed(void);
void OnTextChanged(void);
int32_t PrevCharOffset(int32_t);
void RunOnCursorChangedScript(float, float, float, float);
void RunOnEditFocusGainedScript(void);
void RunOnEditFocusLostScript(void);
void RunOnEnterPressedScript(void);
void RunOnTextChangedScript(int32_t);
void SetCursorPosition(int32_t);
void SetHistoryLines(int32_t);
void SetMultiLine(int32_t);
void StartHighlight(void);
void UpdateDirtyBits(void);
void UpdateSizes(void);
void UpdateTextInfo(void);
void UpdateVisibleCursor(void);
void UpdateVisibleHighlight(void);
void UpdateVisibleText(void);
};
#endif

View file

@ -0,0 +1,309 @@
#include "ui/CSimpleEditBoxScript.hpp"
#include "ui/CSimpleEditBox.hpp"
#include "util/Lua.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleEditBox_SetFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetFont(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetFont(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetTextColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetTextColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetShadowColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetShadowColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetShadowOffset(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetShadowOffset(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetSpacing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetSpacing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetJustifyH(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetJustifyH(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetJustifyV(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetJustifyV(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetIndentedWordWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetIndentedWordWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetAutoFocus(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_IsAutoFocus(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetCountInvisibleLetters(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_IsCountInvisibleLetters(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetMultiLine(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_IsMultiLine(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetNumeric(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_IsNumeric(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetPassword(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_IsPassword(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetBlinkSpeed(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetBlinkSpeed(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_Insert(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetText(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetText(lua_State* L) {
int32_t type = CSimpleEditBox::GetObjectType();
CSimpleEditBox* editBox = static_cast<CSimpleEditBox*>(FrameScript_GetObjectThis(L, type));
// TODO
// - taint management
// if (editBox->m_dwordC && lua_taintexpected && !lua_taintedclosure) {
// lua_tainted = editBox->simpleeditbox_dwordC;
// }
lua_pushstring(L, editBox->m_text);
return 1;
}
int32_t CSimpleEditBox_SetNumber(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetNumber(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_HighlightText(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_AddHistoryLine(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_ClearHistory(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetTextInsets(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetTextInsets(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetFocus(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_ClearFocus(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_HasFocus(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetMaxBytes(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetMaxBytes(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetMaxLetters(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetMaxLetters(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetNumLetters(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetHistoryLines(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetHistoryLines(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetInputLanguage(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_ToggleInputLanguage(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetAltArrowKeyMode(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetAltArrowKeyMode(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_IsInIMECompositionMode(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_SetCursorPosition(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetCursorPosition(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleEditBox_GetUTF8CursorPosition(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleEditBoxMethods[NUM_SIMPLE_EDIT_BOX_SCRIPT_METHODS] = {
{ "SetFontObject", &CSimpleEditBox_SetFontObject },
{ "GetFontObject", &CSimpleEditBox_GetFontObject },
{ "SetFont", &CSimpleEditBox_SetFont },
{ "GetFont", &CSimpleEditBox_GetFont },
{ "SetTextColor", &CSimpleEditBox_SetTextColor },
{ "GetTextColor", &CSimpleEditBox_GetTextColor },
{ "SetShadowColor", &CSimpleEditBox_SetShadowColor },
{ "GetShadowColor", &CSimpleEditBox_GetShadowColor },
{ "SetShadowOffset", &CSimpleEditBox_SetShadowOffset },
{ "GetShadowOffset", &CSimpleEditBox_GetShadowOffset },
{ "SetSpacing", &CSimpleEditBox_SetSpacing },
{ "GetSpacing", &CSimpleEditBox_GetSpacing },
{ "SetJustifyH", &CSimpleEditBox_SetJustifyH },
{ "GetJustifyH", &CSimpleEditBox_GetJustifyH },
{ "SetJustifyV", &CSimpleEditBox_SetJustifyV },
{ "GetJustifyV", &CSimpleEditBox_GetJustifyV },
{ "SetIndentedWordWrap", &CSimpleEditBox_SetIndentedWordWrap },
{ "GetIndentedWordWrap", &CSimpleEditBox_GetIndentedWordWrap },
{ "SetAutoFocus", &CSimpleEditBox_SetAutoFocus },
{ "IsAutoFocus", &CSimpleEditBox_IsAutoFocus },
{ "SetCountInvisibleLetters", &CSimpleEditBox_SetCountInvisibleLetters },
{ "IsCountInvisibleLetters", &CSimpleEditBox_IsCountInvisibleLetters },
{ "SetMultiLine", &CSimpleEditBox_SetMultiLine },
{ "IsMultiLine", &CSimpleEditBox_IsMultiLine },
{ "SetNumeric", &CSimpleEditBox_SetNumeric },
{ "IsNumeric", &CSimpleEditBox_IsNumeric },
{ "SetPassword", &CSimpleEditBox_SetPassword },
{ "IsPassword", &CSimpleEditBox_IsPassword },
{ "SetBlinkSpeed", &CSimpleEditBox_SetBlinkSpeed },
{ "GetBlinkSpeed", &CSimpleEditBox_GetBlinkSpeed },
{ "Insert", &CSimpleEditBox_Insert },
{ "SetText", &CSimpleEditBox_SetText },
{ "GetText", &CSimpleEditBox_GetText },
{ "SetNumber", &CSimpleEditBox_SetNumber },
{ "GetNumber", &CSimpleEditBox_GetNumber },
{ "HighlightText", &CSimpleEditBox_HighlightText },
{ "AddHistoryLine", &CSimpleEditBox_AddHistoryLine },
{ "ClearHistory", &CSimpleEditBox_ClearHistory },
{ "SetTextInsets", &CSimpleEditBox_SetTextInsets },
{ "GetTextInsets", &CSimpleEditBox_GetTextInsets },
{ "SetFocus", &CSimpleEditBox_SetFocus },
{ "ClearFocus", &CSimpleEditBox_ClearFocus },
{ "HasFocus", &CSimpleEditBox_HasFocus },
{ "SetMaxBytes", &CSimpleEditBox_SetMaxBytes },
{ "GetMaxBytes", &CSimpleEditBox_GetMaxBytes },
{ "SetMaxLetters", &CSimpleEditBox_SetMaxLetters },
{ "GetMaxLetters", &CSimpleEditBox_GetMaxLetters },
{ "GetNumLetters", &CSimpleEditBox_GetNumLetters },
{ "GetHistoryLines", &CSimpleEditBox_GetHistoryLines },
{ "SetHistoryLines", &CSimpleEditBox_SetHistoryLines },
{ "GetInputLanguage", &CSimpleEditBox_GetInputLanguage },
{ "ToggleInputLanguage", &CSimpleEditBox_ToggleInputLanguage },
{ "SetAltArrowKeyMode", &CSimpleEditBox_SetAltArrowKeyMode },
{ "GetAltArrowKeyMode", &CSimpleEditBox_GetAltArrowKeyMode },
{ "IsInIMECompositionMode", &CSimpleEditBox_IsInIMECompositionMode },
{ "SetCursorPosition", &CSimpleEditBox_SetCursorPosition },
{ "GetCursorPosition", &CSimpleEditBox_GetCursorPosition },
{ "GetUTF8CursorPosition", &CSimpleEditBox_GetUTF8CursorPosition }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_EDIT_BOX_SCRIPT_HPP
#define UI_C_SIMPLE_EDIT_BOX_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_EDIT_BOX_SCRIPT_METHODS 58
extern FrameScript_Method SimpleEditBoxMethods[NUM_SIMPLE_EDIT_BOX_SCRIPT_METHODS];
#endif

241
src/ui/CSimpleFont.cpp Normal file
View file

@ -0,0 +1,241 @@
#include "ui/CSimpleFont.hpp"
#include "gx/Coordinate.hpp"
#include "gx/Font.hpp"
#include "ui/CSimpleFontScript.hpp"
#include "ui/FrameXML.hpp"
#include "ui/LoadXML.hpp"
#include "ui/Types.hpp"
#include "util/CStatus.hpp"
#include "util/StringTo.hpp"
#include <common/XML.hpp>
#include <storm/String.hpp>
TSHashTable<SIMPLEFONT, HASHKEY_STRI> CSimpleFont::s_fontList;
int32_t CSimpleFont::s_metatable;
int32_t CSimpleFont::s_objectType;
SIMPLEFONT::SIMPLEFONT() : TSHashObject<SIMPLEFONT, HASHKEY_STRI>() {
void* m = SMemAlloc(sizeof(CSimpleFont), __FILE__, __LINE__, 0);
if (m) {
this->font = new (m) CSimpleFont();
} else {
this->font = nullptr;
}
}
void CSimpleFont::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleFont::RegisterScriptMethods);
CSimpleFont::s_metatable = ref;
}
CSimpleFont* CSimpleFont::GetFont(const char* name, int32_t a2) {
SIMPLEFONT* hashed = CSimpleFont::s_fontList.Ptr(name);
if (hashed) {
return hashed->font;
}
if (!a2) {
return nullptr;
}
hashed = CSimpleFont::s_fontList.New(name, 0, 0);
CSimpleFont* font = hashed->font;
if (font->m_name) {
font->UnregisterScriptObject(font->m_name);
}
font->m_name = hashed->m_key.m_str;
if (font->m_name) {
font->RegisterScriptObject(font->m_name);
}
return hashed->font;
}
int32_t CSimpleFont::GetObjectType() {
if (!CSimpleFont::s_objectType) {
CSimpleFont::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CSimpleFont::s_objectType;
}
void CSimpleFont::RegisterScriptMethods(lua_State* L) {
FrameScript_Object::FillScriptMethodTable(L, SimpleFontMethods, NUM_SIMPLE_FONT_SCRIPT_METHODS);
}
CSimpleFont::CSimpleFont() : FrameScript_Object() {
// TODO
}
void CSimpleFont::FontObjectUpdated(CSimpleFontStringAttributes& attributes) {
attributes.Update(this->m_attributes, this->m_fontableFlags);
this->UpdateObjects();
}
char* CSimpleFont::GetName() {
return const_cast<char*>(this->m_name);
}
int32_t CSimpleFont::GetScriptMetaTable() {
return CSimpleFont::s_metatable;
}
bool CSimpleFont::IsA(int32_t type) {
return type == CSimpleFont::s_objectType;
}
void CSimpleFont::LoadXML(XMLNode* node, CStatus* status) {
const char* inheritsAttr = node->GetAttributeByName("inherits");
if (inheritsAttr && *inheritsAttr) {
auto font = CSimpleFont::GetFont(inheritsAttr, 0);
if (font) {
this->SetFontObject(font);
} else {
status->Add(
STATUS_WARNING,
"Couldn't find inherited font: %s",
inheritsAttr
);
}
}
const char* fontAttr = node->GetAttributeByName("font");
if (fontAttr && *fontAttr) {
auto font = CSimpleFont::GetFont(fontAttr, 0);
if (font) {
this->SetFontObject(font);
} else {
float fontHeight = 0.0f;
XMLNode* fontHeightNode = node->GetChildByName("FontHeight");
if (fontHeightNode) {
LoadXML_Value(fontHeightNode, fontHeight, status);
}
if (fontHeight == 0.0f) {
status->Add(
STATUS_WARNING,
"Font %s: Missing font height in %s element",
this->GetDisplayName(),
node->GetName()
);
return;
}
uint32_t fontFlags = 0;
const char* outlineAttr = node->GetAttributeByName("outline");
if (outlineAttr && *outlineAttr) {
if (!SStrCmpI(outlineAttr, "NORMAL", STORM_MAX_STR)) {
fontFlags |= FONT_OUTLINE;
} else if (!SStrCmpI(outlineAttr, "THICK", STORM_MAX_STR)) {
fontFlags |= (FONT_OUTLINE | FONT_THICKOUTLINE);
}
}
const char* monochromeAttr = node->GetAttributeByName("monochrome");
if (monochromeAttr && *monochromeAttr && StringToBOOL(monochromeAttr)) {
fontFlags |= FONT_MONOCHROME;
}
if (this->m_attributes.SetFont(fontAttr, fontHeight, fontFlags)) {
this->m_fontableFlags &= ~FLAG_FONT_UPDATE;
} else {
status->Add(
STATUS_WARNING,
"Font %s: Unable to load font file %s",
this->GetDisplayName(),
fontAttr
);
}
}
}
const char* spacingAttr = node->GetAttributeByName("spacing");
if (spacingAttr && *spacingAttr) {
float spacing = SStrToFloat(spacingAttr);
float ndcSpacing = spacing / (CoordinateGetAspectCompensation() * 1024.0);
float ddcSpacing = NDCToDDCWidth(ndcSpacing);
this->m_attributes.SetSpacing(ddcSpacing);
this->m_fontableFlags &= ~FLAG_SPACING_UPDATE;
}
const char* justifyVAttr = node->GetAttributeByName("justifyV");
if (justifyVAttr && *justifyVAttr) {
uint32_t justify;
if (StringToJustify(justifyVAttr, justify)) {
this->m_attributes.SetJustifyV(justify);
this->m_fontableFlags &= ~FLAG_STYLE_UPDATE;
}
}
const char* justifyHAttr = node->GetAttributeByName("justifyH");
if (justifyHAttr && *justifyHAttr) {
uint32_t justify;
if (StringToJustify(justifyHAttr, justify)) {
this->m_attributes.SetJustifyH(justify);
this->m_fontableFlags &= ~FLAG_STYLE_UPDATE;
}
}
const char* nonspacewrapAttr = node->GetAttributeByName("nonspacewrap");
if (nonspacewrapAttr && *nonspacewrapAttr) {
bool nonspacewrap = StringToBOOL(nonspacewrapAttr);
this->m_attributes.SetNonSpaceWrap(nonspacewrap);
}
const char* indentedAttr = node->GetAttributeByName("indented");
if (indentedAttr && *indentedAttr) {
bool indented = StringToBOOL(indentedAttr);
this->m_attributes.SetIndented(indented);
}
for (XMLNode* child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "Color", STORM_MAX_STR)) {
CImVector color;
LoadXML_Color(child, color);
this->m_attributes.SetColor(color);
this->m_fontableFlags &= ~FLAG_COLOR_UPDATE;
} else if(!SStrCmpI(child->GetName(), "Shadow", STORM_MAX_STR)) {
C2Vector shadowOffset = { 0.001f, -0.001f };
CImVector shadowColor = { 0x00, 0x00, 0x00, 0xFF };
auto colorChild = child->GetChildByName("Color");
if (colorChild) {
LoadXML_Color(colorChild, shadowColor);
}
auto offsetChild = child->GetChildByName("Offset");
if (offsetChild) {
LoadXML_Dimensions(offsetChild, shadowOffset.x, shadowOffset.y, status);
}
this->m_attributes.SetShadow(shadowColor, shadowOffset);
this->m_fontableFlags &= ~FLAG_SHADOW_UPDATE;
}
}
}
void CSimpleFont::UpdateObjects() {
if (this->m_attributes.m_flags) {
for (auto node = this->m_fontableList.Head(); node; node = this->m_fontableList.Link(node)->Next()) {
node->FontObjectUpdated(this->m_attributes);
}
this->m_attributes.m_flags &= ~FLAG_COMPLETE_UPDATE;
}
}

54
src/ui/CSimpleFont.hpp Normal file
View file

@ -0,0 +1,54 @@
#ifndef UI_C_SIMPLE_FONT_HPP
#define UI_C_SIMPLE_FONT_HPP
#include "ui/CSimpleFontable.hpp"
#include "ui/CSimpleFontStringAttributes.hpp"
#include "ui/FrameScript_Object.hpp"
#include <cstdint>
#include <storm/Hash.hpp>
#include <storm/List.hpp>
class CSimpleFont;
class CStatus;
class XMLNode;
class SIMPLEFONT : public TSHashObject<SIMPLEFONT, HASHKEY_STRI> {
public:
// Member variables
CSimpleFont* font = nullptr;
// Member functions
SIMPLEFONT();
};
class CSimpleFont : public FrameScript_Object, public CSimpleFontable {
public:
// Static variables
static TSHashTable<SIMPLEFONT, HASHKEY_STRI> s_fontList;
static int32_t s_metatable;
static int32_t s_objectType;
// Static functions
static void CreateScriptMetaTable(void);
static CSimpleFont* GetFont(const char*, int32_t);
static int32_t GetObjectType();
static void RegisterScriptMethods(lua_State*);
// Member variables
CSimpleFontStringAttributes m_attributes;
const char* m_name = nullptr;
STORM_EXPLICIT_LIST(CSimpleFontable, m_fontableLink) m_fontableList;
// Virtual member functions
virtual char* GetName(void);
virtual int32_t GetScriptMetaTable(void);
virtual bool IsA(int32_t);
virtual void FontObjectUpdated(CSimpleFontStringAttributes&);
// Member functions
CSimpleFont();
void LoadXML(XMLNode*, CStatus*);
void UpdateObjects(void);
};
#endif

View file

@ -0,0 +1,126 @@
#include "ui/CSimpleFontScript.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleFont_GetObjectType(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_IsObjectType(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetName(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_SetFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_CopyFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_SetFont(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetFont(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_SetAlpha(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetAlpha(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_SetTextColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetTextColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_SetShadowColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetShadowColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_SetShadowOffset(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetShadowOffset(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_SetSpacing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetSpacing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_SetJustifyH(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetJustifyH(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_SetJustifyV(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetJustifyV(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_SetIndentedWordWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFont_GetIndentedWordWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleFontMethods[NUM_SIMPLE_FONT_SCRIPT_METHODS] = {
{ "GetObjectType", &CSimpleFont_GetObjectType },
{ "IsObjectType", &CSimpleFont_IsObjectType },
{ "GetName", &CSimpleFont_GetName },
{ "SetFontObject", &CSimpleFont_SetFontObject },
{ "GetFontObject", &CSimpleFont_GetFontObject },
{ "CopyFontObject", &CSimpleFont_CopyFontObject },
{ "SetFont", &CSimpleFont_SetFont },
{ "GetFont", &CSimpleFont_GetFont },
{ "SetAlpha", &CSimpleFont_SetAlpha },
{ "GetAlpha", &CSimpleFont_GetAlpha },
{ "SetTextColor", &CSimpleFont_SetTextColor },
{ "GetTextColor", &CSimpleFont_GetTextColor },
{ "SetShadowColor", &CSimpleFont_SetShadowColor },
{ "GetShadowColor", &CSimpleFont_GetShadowColor },
{ "SetShadowOffset", &CSimpleFont_SetShadowOffset },
{ "GetShadowOffset", &CSimpleFont_GetShadowOffset },
{ "SetSpacing", &CSimpleFont_SetSpacing },
{ "GetSpacing", &CSimpleFont_GetSpacing },
{ "SetJustifyH", &CSimpleFont_SetJustifyH },
{ "GetJustifyH", &CSimpleFont_GetJustifyH },
{ "SetJustifyV", &CSimpleFont_SetJustifyV },
{ "GetJustifyV", &CSimpleFont_GetJustifyV },
{ "SetIndentedWordWrap", &CSimpleFont_SetIndentedWordWrap },
{ "GetIndentedWordWrap", &CSimpleFont_GetIndentedWordWrap }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_FONT_SCRIPT_HPP
#define UI_C_SIMPLE_FONT_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_FONT_SCRIPT_METHODS 24
extern FrameScript_Method SimpleFontMethods[NUM_SIMPLE_FONT_SCRIPT_METHODS];
#endif

View file

@ -0,0 +1,919 @@
#include "ui/CSimpleFontString.hpp"
#include "gx/Coordinate.hpp"
#include "math/Utils.hpp"
#include "ui/CFramePoint.hpp"
#include "ui/CRenderBatch.hpp"
#include "ui/CSimpleFont.hpp"
#include "ui/CSimpleFontStringScript.hpp"
#include "ui/CSimpleFrame.hpp"
#include "ui/CSimpleTop.hpp"
#include "ui/FrameXML.hpp"
#include "ui/LoadXML.hpp"
#include "ui/Types.hpp"
#include "ui/Util.hpp"
#include "util/CStatus.hpp"
#include "util/StringTo.hpp"
#include <common/XML.hpp>
#include <storm/String.hpp>
int32_t CSimpleFontString::s_count;
int32_t CSimpleFontString::s_metatable;
int32_t CSimpleFontString::s_objectType;
void CSimpleFontString::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleFontString::RegisterScriptMethods);
CSimpleFontString::s_metatable = ref;
}
int32_t CSimpleFontString::GetObjectType() {
if (!CSimpleFontString::s_objectType) {
CSimpleFontString::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CSimpleFontString::s_objectType;
}
void CSimpleFontString::RegisterScriptMethods(lua_State* L) {
CScriptRegion::RegisterScriptMethods(L);
FrameScript_Object::FillScriptMethodTable(L, SimpleFontStringMethods, NUM_SIMPLE_FONT_STRING_SCRIPT_METHODS);
}
CSimpleFontString::CSimpleFontString(CSimpleFrame* frame, uint32_t drawlayer, int32_t show) : CSimpleRegion(frame, drawlayer, show) {
this->m_maxLines = 0;
this->m_unk12b = 1;
// TODO
CSimpleFontString::s_count++;
}
CSimpleFontString::~CSimpleFontString() {
this->FreeEmbeddedTextures();
if (this->m_text) {
SMemFree(this->m_text, __FILE__, __LINE__, 0x0);
this->m_text = nullptr;
}
this->m_fontHeight = 0.0f;
if (this->m_string) {
HandleClose(this->m_string);
this->m_string = nullptr;
}
if (this->m_font) {
HandleClose(this->m_font);
this->m_font = nullptr;
}
CSimpleFontString::s_count--;
}
void CSimpleFontString::AddShadow(const CImVector& shadowColor, const C2Vector& shadowOffset) {
auto styleFlags = this->m_styleFlags;
if (
!(styleFlags & 0x100)
|| shadowColor != this->m_shadowColor
|| this->m_shadowOffset.x != shadowOffset.x
|| this->m_shadowOffset.y != shadowOffset.y
) {
this->m_styleFlags = styleFlags | 0x100;
this->m_shadowColor = shadowColor;
this->m_shadowOffset = shadowOffset;
if (this->m_string) {
auto shadowColor = this->m_shadowColor;
// TODO alpha manipulation
auto shadowOffset = this->m_shadowOffset;
shadowOffset.x *= this->m_layoutScale;
shadowOffset.y *= this->m_layoutScale;
TextBlockAddShadow(this->m_string, shadowColor, shadowOffset);
}
}
}
void CSimpleFontString::ClearString() {
this->m_cachedWidth = 0.0f;
this->m_cachedHeight = 0.0f;
if (this->m_string) {
HandleClose(this->m_string);
this->m_string = nullptr;
}
this->m_flags &= ~0x1;
this->Resize(0);
}
void CSimpleFontString::Draw(CRenderBatch* batch) {
if (this->m_font && this->m_text && *this->m_text) {
batch->QueueFontString(this);
this->DrawEmbeddedTextures(batch);
}
}
void CSimpleFontString::DrawEmbeddedTextures(CRenderBatch* batch) {
// TODO
}
bool CSimpleFontString::IsA(int32_t type) {
return type == CSimpleFontString::s_objectType
|| type == CScriptRegion::s_objectType
|| type == CScriptObject::s_objectType;
}
void CSimpleFontString::FontObjectUpdated(CSimpleFontStringAttributes& attributes) {
attributes.Update(this, this->m_fontableFlags);
}
void CSimpleFontString::FreeEmbeddedTextures() {
// TODO
}
const char* CSimpleFontString::GetDisplayText(float width, float height) {
static char buffer[8192];
if (!this->m_text || !*this->m_text) {
return nullptr;
}
if (!this->m_font || width <= 0.0f || /* TODO */ height <= 0.0f) {
return this->m_text;
}
auto fontHeight = this->GetFontHeight(true);
auto v5 = (CSimpleTop::RoundToPixelHeight(this->m_spacing) + fontHeight) * this->m_layoutScale;
// TODO
auto text = this->m_text;
auto textLen = SStrLen(text);
auto scaledSpacing = this->m_spacing * this->m_layoutScale;
auto scaledShadowOffset = this->m_shadowOffset.x * this->m_layoutScale;
auto scaledFontHeight = fontHeight * this->m_layoutScale;
auto maxChars = TextBlockGetMaxCharsWithinWidthAndHeight(
this->m_font,
text,
scaledFontHeight,
width,
height,
textLen,
scaledShadowOffset,
this->m_layoutScale,
scaledSpacing,
this->m_styleFlags
);
if (maxChars >= textLen) {
return text;
}
SStrCopy(buffer, text, sizeof(buffer));
auto end = std::min(textLen, sizeof(buffer) - 4);
do {
if (end) {
do {
end--;
} while (end && (buffer[end] & 0xC0) == 0x80);
}
SStrCopy(&buffer[end], "...", STORM_MAX_STR);
maxChars = TextBlockGetMaxCharsWithinWidthAndHeight(
this->m_font,
buffer,
scaledFontHeight,
width,
height,
end + 3,
scaledShadowOffset,
this->m_layoutScale,
scaledSpacing,
this->m_styleFlags
);
} while (end && maxChars < end + 3);
return buffer;
}
uint32_t CSimpleFontString::GetFontFlags() {
if (this->m_font) {
return TextBlockGetFontFlags(this->m_font);
}
return 0;
}
float CSimpleFontString::GetFontHeight(bool a2) {
float fontHeight = this->m_fontHeight;
if (a2 && this->m_font && this->m_styleFlags & 0x200) {
auto font = TextBlockGetFontPtr(this->m_font);
float ndcHeight = GxuFontGetOneToOneHeight(font) / this->m_layoutScale;
NDCToDDC(0.0f, ndcHeight, nullptr, &fontHeight);
}
return fontHeight;
}
const char* CSimpleFontString::GetFontName() {
return this->m_font
? TextBlockGetFontName(this->m_font)
: nullptr;
}
float CSimpleFontString::GetHeight() {
float v2 = CLayoutFrame::GetHeight();
float v9 = v2 == 0.0f ? this->GetStringHeight() : v2;
float v3 = 1.0f / (CoordinateGetAspectCompensation() * 1024.0f);
float v4 = NDCToDDCWidth(v3);
return v9 <= v4 ? v4 : v9;
}
uint32_t CSimpleFontString::GetNumCharsWithinWidth(const char* text, uint32_t textBytes, float maxWidth) {
if (!this->m_font) {
return 0;
}
if (textBytes == 0) {
textBytes = SStrLen(text);
}
float fontHeight = this->GetFontHeight(true);
float shadowWidth = this->m_shadowOffset.x;
float extent[4];
return TextBlockGetMaxCharsWithinWidth(
this->m_font,
text,
fontHeight * this->m_layoutScale,
maxWidth * this->m_layoutScale,
textBytes,
extent,
shadowWidth * this->m_layoutScale,
this->m_layoutScale,
0.0f,
this->m_styleFlags
);
}
int32_t CSimpleFontString::GetScriptMetaTable() {
return CSimpleFontString::s_metatable;
}
float CSimpleFontString::GetStringHeight() {
if (this->m_cachedHeight == 0.0f && this->m_font) {
float width = CLayoutFrame::GetWidth() * this->m_layoutScale;
float height = CLayoutFrame::GetHeight() * this->m_layoutScale;
const char* displayText = this->GetDisplayText(width, height);
if (displayText && *displayText) {
float fontHeight = this->GetFontHeight(1) * this->m_layoutScale;
C2Vector shadowSize = {
this->m_shadowOffset.x * this->m_layoutScale,
this->m_shadowOffset.y * this->m_layoutScale
};
this->m_cachedHeight = TextBlockGetWrappedTextHeight(
this->m_font,
displayText,
fontHeight,
this->GetWidth() * this->m_layoutScale,
shadowSize,
this->m_layoutScale,
this->m_spacing * this->m_layoutScale,
this->m_styleFlags
);
}
}
return this->m_cachedHeight / this->m_layoutScale;
}
float CSimpleFontString::GetStringWidth() {
if (this->m_cachedWidth == 0.0f && this->m_font) {
float width = CLayoutFrame::GetWidth() * this->m_layoutScale;
float height = CLayoutFrame::GetHeight() * this->m_layoutScale;
const char* displayText = this->GetDisplayText(width, height);
if (displayText && *displayText) {
float fontHeight = this->GetFontHeight(1) * this->m_layoutScale;
float shadowWidth = this->m_shadowOffset.x * this->m_layoutScale;
size_t displayTextLength = SStrLen(displayText);
TextBlockGetTextExtent(
this->m_font,
displayText,
displayTextLength,
fontHeight,
&this->m_cachedWidth,
shadowWidth,
this->m_layoutScale,
0.0f,
this->m_styleFlags
);
}
}
return this->m_cachedWidth / this->m_layoutScale;
}
const char* CSimpleFontString::GetText() {
return this->m_text;
}
float CSimpleFontString::GetTextWidth(const char* text, uint32_t textBytes) {
if (!this->m_font) {
return 0.0f;
}
if (textBytes == 0) {
textBytes = SStrLen(text);
}
float fontHeight = this->GetFontHeight(true);
float extent = 0.0f;
TextBlockGetTextExtent(
this->m_font,
text,
textBytes,
fontHeight * this->m_layoutScale,
&extent,
this->m_shadowOffset.x * this->m_layoutScale,
this->m_layoutScale,
0.0f,
this->m_styleFlags
);
float width = extent / this->m_layoutScale;
return width;
}
float CSimpleFontString::GetWidth() {
float v2 = CLayoutFrame::GetWidth();
float v9 = v2 == 0.0f ? this->GetStringWidth() : v2;
float v3 = 1.0f / (CoordinateGetAspectCompensation() * 1024.0f);
float v4 = NDCToDDCWidth(v3);
return v9 <= v4 ? v4 : v9;
}
void CSimpleFontString::LoadXML(XMLNode* node, CStatus* status) {
const char* inheritsAttr = node->GetAttributeByName("inherits");
if (inheritsAttr && *inheritsAttr) {
auto font = CSimpleFont::GetFont(inheritsAttr, 0);
if (font) {
if (this->m_unk12b) {
this->SetFontObject(font);
}
} else {
const char* tainted;
bool locked;
XMLNode* inheritsNode = FrameXML_AcquireHashNode(inheritsAttr, tainted, locked);
if (inheritsNode) {
if (locked) {
status->Add(STATUS_WARNING, "Recursively inherited node: %s", inheritsAttr);
} else {
this->LoadXML(inheritsNode, status);
FrameXML_ReleaseHashNode(inheritsAttr);
}
} else {
status->Add(STATUS_WARNING, "Couldn't find inherited node: %s", inheritsAttr);
}
}
}
CSimpleRegion::LoadXML(node, status);
const char* hiddenAttr = node->GetAttributeByName("hidden");
if (hiddenAttr && *hiddenAttr) {
bool hide = StringToBOOL(hiddenAttr);
if (hide) {
this->Hide();
} else {
this->Show();
}
}
const char* textAttr = node->GetAttributeByName("text");
if (textAttr && *textAttr) {
const char* text = FrameScript_GetText(textAttr, -1, GENDER_NOT_APPLICABLE);
this->SetText(text && *text ? text : textAttr, 1);
}
const char* nonSpaceWrapAttr = node->GetAttributeByName("nonspacewrap");
if (nonSpaceWrapAttr && *nonSpaceWrapAttr) {
this->SetNonSpaceWrap(StringToBOOL(nonSpaceWrapAttr));
}
const char* wordWrapAttr = node->GetAttributeByName("wordwrap");
if (wordWrapAttr && *wordWrapAttr) {
this->SetNonWordWrap(!StringToBOOL(wordWrapAttr));
}
const char* bytesAttr = node->GetAttributeByName("bytes");
if (bytesAttr && *bytesAttr) {
uint32_t length = SStrToInt(bytesAttr);
this->SetTextLength(length);
}
if (!this->m_unk12b) {
return;
}
const char* fontAttr = node->GetAttributeByName("font");
if (fontAttr && *fontAttr) {
auto font = CSimpleFont::GetFont(fontAttr, 0);
if (font) {
this->SetFontObject(font);
} else {
float fontHeight = 0.0f;
XMLNode* fontHeightNode = node->GetChildByName("FontHeight");
if (fontHeightNode) {
LoadXML_Value(fontHeightNode, fontHeight, status);
}
if (fontHeight == 0.0f) {
status->Add(
STATUS_WARNING,
"FontString %s: invalid font height %f in %s element",
this->GetDisplayName(),
fontHeight,
node->GetName()
);
return;
}
uint32_t fontFlags = 0;
const char* outlineAttr = node->GetAttributeByName("outline");
if (outlineAttr && *outlineAttr) {
if (!SStrCmpI(outlineAttr, "NORMAL", STORM_MAX_STR)) {
fontFlags |= FONT_OUTLINE;
} else if (!SStrCmpI(outlineAttr, "THICK", STORM_MAX_STR)) {
fontFlags |= (FONT_OUTLINE | FONT_THICKOUTLINE);
}
}
const char* monochromeAttr = node->GetAttributeByName("monochrome");
if (monochromeAttr && *monochromeAttr && StringToBOOL(monochromeAttr)) {
fontFlags |= FONT_MONOCHROME;
}
if (this->SetFont(fontAttr, fontHeight, fontFlags, false)) {
this->m_fontableFlags &= ~FLAG_FONT_UPDATE;
} else {
status->Add(
STATUS_WARNING,
"FontString %s: Unable to load font file %s",
this->GetDisplayName(),
fontAttr
);
}
}
}
const char* spacingAttr = node->GetAttributeByName("spacing");
if (spacingAttr && *spacingAttr) {
float spacing = SStrToFloat(spacingAttr);
float ndcSpacing = spacing / (CoordinateGetAspectCompensation() * 1024.0f);
float ddcSpacing = NDCToDDCWidth(ndcSpacing);
this->SetSpacing(ddcSpacing);
this->m_fontableFlags &= ~FLAG_SPACING_UPDATE;
}
const char* justifyVAttr = node->GetAttributeByName("justifyV");
if (justifyVAttr && *justifyVAttr) {
uint32_t justify;
if (StringToJustify(justifyVAttr, justify)) {
this->SetJustifyV(justify);
this->m_fontableFlags &= ~FLAG_STYLE_UPDATE;
}
}
const char* justifyHAttr = node->GetAttributeByName("justifyH");
if (justifyHAttr && *justifyHAttr) {
uint32_t justify;
if (StringToJustify(justifyHAttr, justify)) {
this->SetJustifyH(justify);
this->m_fontableFlags &= ~FLAG_STYLE_UPDATE;
}
}
const char* indentedAttr = node->GetAttributeByName("indented");
if (indentedAttr && *indentedAttr) {
bool indented = StringToBOOL(indentedAttr);
this->SetIndentedWordWrap(indented);
}
for (XMLNode* child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "Color", STORM_MAX_STR)) {
CImVector color;
LoadXML_Color(child, color);
this->SetVertexColor(color);
this->m_fontableFlags &= ~FLAG_COLOR_UPDATE;
} else if (!SStrCmpI(child->GetName(), "Shadow", STORM_MAX_STR)) {
// TODO
}
}
// TODO
// - alpha
// TODO
// - children
}
void CSimpleFontString::OnColorChanged(bool a2) {
CSimpleRegion::OnColorChanged(a2);
if (this->m_string) {
CImVector color = { 0xFF, 0xFF, 0xFF, 0xFF };
if (this->m_colorCount == 1) {
color = this->m_color[0];
}
TextBlockUpdateColor(this->m_string, color);
if (this->m_styleFlags & 0x100) {
CImVector shadowColor = this->m_shadowColor;
C2Vector shadowOffset = {
this->m_shadowOffset.x * this->m_layoutScale,
this->m_shadowOffset.y * this->m_layoutScale
};
// TODO
// - shadow color alpha calculation
TextBlockAddShadow(this->m_string, shadowColor, shadowOffset);
}
}
// TODO
// - embedded texture color updates
}
void CSimpleFontString::OnScreenSizeChanged() {
this->m_cachedWidth = 0.0f;
this->m_cachedHeight = 0.0f;
this->Resize(0);
}
void CSimpleFontString::OnFrameSizeChanged(const CRect& rect) {
CLayoutFrame::OnFrameSizeChanged(rect);
if (
this->m_string
&& AreEqual(rect.maxX - rect.minX, this->m_rect.maxX - this->m_rect.minX, WHOA_EPSILON_2)
&& AreEqual(rect.maxY - rect.minY, this->m_rect.maxY - this->m_rect.minY, WHOA_EPSILON_2)
) {
C3Vector pos = {
this->m_justificationOffset.x * this->m_layoutScale + this->m_rect.minX,
this->m_justificationOffset.y * this->m_layoutScale + this->m_rect.minY,
this->m_layoutDepth
};
TextBlockSetStringPos(this->m_string, pos);
if (rect.Sub4826D0() != this->m_rect.Sub4826D0()) {
this->OnRegionChanged();
}
} else {
this->UpdateString();
}
// TODO logic if region flags & 0x40
if (this->m_parent) {
this->m_parent->NotifyScrollParent();
}
}
void CSimpleFontString::PostLoadXML(XMLNode* node, CStatus* status) {
if (this->m_parent) {
int32_t hasPoint = 0;
for (int32_t i = 0; i < FRAMEPOINT_NUMPOINTS; i++) {
auto point = this->m_points[i];
if (point && !(point->m_flags & 0x08)) {
hasPoint = 1;
break;
}
}
if (!hasPoint) {
float offsetX = 0.0f;
float offsetY = 0.0f;
if (this->m_styleFlags & 0x01) {
this->SetPoint(FRAMEPOINT_LEFT, this->m_parent, FRAMEPOINT_LEFT, offsetX, offsetY, 1);
} else if (this->m_styleFlags & 0x04) {
this->SetPoint(FRAMEPOINT_RIGHT, this->m_parent, FRAMEPOINT_RIGHT, offsetX, offsetY, 1);
} else {
this->SetPoint(FRAMEPOINT_CENTER, this->m_parent, FRAMEPOINT_CENTER, offsetX, offsetY, 1);
}
}
}
}
void CSimpleFontString::RefreshEmbeddedTextures() {
// TODO
}
void CSimpleFontString::RemoveShadow() {
// TODO
}
int32_t CSimpleFontString::SetFont(const char* fontName, float fontHeight, uint32_t fontFlags, bool force) {
if (!force) {
const char* curFontName = this->GetFontName();
if (
fontName
&& curFontName
&& !SStrCmpI(fontName, curFontName, STORM_MAX_STR)
&& AreEqual(fontHeight, this->m_fontHeight, WHOA_EPSILON_1)
&& fontFlags == this->GetFontFlags()
) {
return 1;
}
}
HTEXTFONT font = nullptr;
if (fontName && fontHeight != 0.0f) {
font = TextBlockGenerateFont(fontName, fontFlags, fontHeight * this->m_layoutScale);
if (!font) {
return 0;
}
}
this->m_fontHeight = fontHeight;
if (this->m_string) {
HandleClose(this->m_string);
this->m_string = nullptr;
}
if (this->m_font) {
HandleClose(this->m_font);
}
this->m_font = font;
if (font) {
this->m_cachedWidth = 0.0f;
this->m_cachedHeight = 0.0f;
}
this->m_flags &= ~0x1;
this->Resize(0);
return 1;
}
void CSimpleFontString::SetIndentedWordWrap(bool a2) {
// TODO
}
void CSimpleFontString::SetJustificationOffset(float x, float y) {
if (this->m_justificationOffset.x == x && this->m_justificationOffset.y == y) {
return;
}
this->m_justificationOffset = { x, y };
if (this->m_string) {
C3Vector pos = {
this->m_rect.minX + (this->m_justificationOffset.x * this->m_layoutScale),
this->m_rect.minY + (this->m_justificationOffset.y * this->m_layoutScale),
this->m_layoutDepth
};
TextBlockSetStringPos(this->m_string, pos);
}
}
void CSimpleFontString::SetJustifyV(uint8_t justify) {
this->m_settableStyleFlags &= ~(0x8 | 0x10 | 0x20);
uint32_t newStyleFlags = this->m_styleFlags ^ ((justify ^ this->m_styleFlags) & (0x8 | 0x10 | 0x20));
if (this->m_styleFlags != newStyleFlags) {
this->m_styleFlags = newStyleFlags;
if (this->m_string) {
this->UpdateString();
}
}
}
void CSimpleFontString::SetJustifyH(uint8_t justify) {
this->m_settableStyleFlags &= ~(0x1 | 0x2 | 0x4);
uint32_t newStyleFlags = this->m_styleFlags ^ ((justify ^ this->m_styleFlags) & (0x1 | 0x2 | 0x4));
if (this->m_styleFlags != newStyleFlags) {
this->m_styleFlags = newStyleFlags;
if (this->m_string) {
this->UpdateString();
}
}
}
void CSimpleFontString::SetNonSpaceWrap(int32_t a2) {
// TODO
}
void CSimpleFontString::SetSpacing(float spacing) {
if (spacing < 0.0f) {
spacing = 0.0f;
}
if (fabs(spacing - this->m_spacing) >= WHOA_EPSILON_1) {
this->m_spacing = spacing;
this->m_cachedHeight = 0.0f;
if (this->m_string) {
this->UpdateString();
}
}
}
void CSimpleFontString::SetStyleFlags(uint32_t styleFlags) {
uint32_t newStyleFlags = (styleFlags & this->m_settableStyleFlags) | (this->m_styleFlags & ~this->m_settableStyleFlags);
if (this->m_styleFlags != newStyleFlags) {
this->m_styleFlags = newStyleFlags;
if (this->m_string) {
this->UpdateString();
}
}
}
void CSimpleFontString::SetText(const char* text, int32_t a3) {
if (text && a3) {
text = LanguageProcess(text);
}
if (text && *text) {
if (this->m_text && !SStrCmp(text, this->m_text, STORM_MAX_STR)) {
return;
}
if (this->m_textMaxSize & 0xFFFF) {
SStrCopy(this->m_text, text, this->m_textMaxSize & 0xFFFF);
} else {
size_t textSize = SStrLen(text);
if (textSize <= this->m_textCurSize) {
SStrCopy(this->m_text, text, STORM_MAX_STR);
} else {
if (this->m_text) {
SMemFree(this->m_text, __FILE__, __LINE__, 0x0);
}
this->m_text = SStrDupA(text, __FILE__, __LINE__);
this->m_textCurSize = textSize;
}
}
} else {
if (this->m_text) {
*this->m_text = '\0';
}
}
this->ClearString();
}
int32_t CSimpleFontString::Sub482AC0() {
// TODO
return 0;
}
void CSimpleFontString::SetTextLength(uint32_t a2) {
// TODO
}
void CSimpleFontString::SetNonWordWrap(int32_t a2) {
// TODO
}
void CSimpleFontString::UpdateString() {
if (!(this->m_flags & 0x1)) {
return;
}
if (this->m_string) {
HandleClose(this->m_string);
this->m_string = nullptr;
}
this->FreeEmbeddedTextures();
if (this->m_rect.maxY <= this->m_rect.minY || this->m_rect.maxX <= this->m_rect.minX) {
return;
}
if (this->m_font && this->m_text && *this->m_text) {
C3Vector pos = {
this->m_rect.minX + this->m_justificationOffset.x * this->m_layoutScale,
this->m_rect.minY + this->m_justificationOffset.y * this->m_layoutScale,
this->m_layoutDepth
};
float width = this->GetWidth();
float blockWidth = width == 0.0f ? this->m_cachedWidth : width * this->m_layoutScale;
if (NotEqual(blockWidth, this->m_rect.maxX - this->m_rect.minX, WHOA_EPSILON_2)) {
blockWidth = this->m_rect.maxX - this->m_rect.minX;
}
float height = this->GetHeight();
float blockHeight = height == 0.0f ? this->m_cachedHeight : height * this->m_layoutScale;
if (NotEqual(blockHeight, this->m_rect.maxY - this->m_rect.minY, WHOA_EPSILON_2)) {
blockHeight = this->m_rect.maxY - this->m_rect.minY;
}
const char* displayText = this->GetDisplayText(blockWidth, blockHeight);
uint32_t styleFlags = this->m_styleFlags;
if (!(this->m_styleFlags & 0x400)) {
// TODO
styleFlags |= 0x400;
}
CImVector color = { 0xFF, 0xFF, 0xFF, 0xFF };
if (this->m_colorCount) {
color = this->m_color[0];
}
float scale = this->m_layoutScale;
float lineSpacing = this->m_spacing * this->m_layoutScale;
float fontHeight = this->GetFontHeight(true) * this->m_layoutScale;
this->m_string = TextBlockCreate(
this->m_font,
displayText,
color,
pos,
fontHeight,
blockWidth,
blockHeight,
styleFlags,
0.0f,
lineSpacing,
scale
);
if (this->m_styleFlags & 0x100) {
auto shadowColor = this->m_shadowColor;
// TODO alpha manipulation
auto shadowOffset = this->m_shadowOffset;
shadowOffset.x *= this->m_layoutScale;
shadowOffset.y *= this->m_layoutScale;
TextBlockAddShadow(this->m_string, shadowColor, shadowOffset);
}
if (this->m_alphaGradientStart > 0) {
// TODO
}
this->RefreshEmbeddedTextures();
// TODO
// - logic if region flags & 0x40, CLayoutFrame::AnimData_HasActivePosition?
}
this->OnRegionChanged();
}

View file

@ -0,0 +1,89 @@
#ifndef UI_C_SIMPLE_FONT_STRING_HPP
#define UI_C_SIMPLE_FONT_STRING_HPP
#include "gx/Font.hpp"
#include "ui/CSimpleFontable.hpp"
#include "ui/CSimpleRegion.hpp"
class CRenderBatch;
class CSimpleFrame;
class CSimpleFontString : public CSimpleRegion, public CSimpleFontable {
public:
// Static variables
static int32_t s_count;
static int32_t s_metatable;
static int32_t s_objectType;
// Static functions
static void CreateScriptMetaTable(void);
static int32_t GetObjectType(void);
static void RegisterScriptMethods(lua_State*);
// Member variables
HTEXTFONT m_font = nullptr;
float m_fontHeight = 0.0f;
uint16_t m_textMaxSize = 0;
uint16_t m_textCurSize = 0;
char* m_text = nullptr;
float m_spacing = 0.0f;
HTEXTBLOCK m_string = nullptr;
float m_cachedWidth = 0.0f;
float m_cachedHeight = 0.0f;
CImVector m_shadowColor;
C2Vector m_shadowOffset;
C2Vector m_justificationOffset;
int16_t m_alphaGradientStart = -1;
int16_t m_alphaGradientLength;
uint32_t m_styleFlags = 0x2 | 0x10 | 0x200;
uint32_t m_settableStyleFlags = 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x1000 | 0x20000;
uint32_t m_maxLines : 24;
uint32_t m_unk12b : 1;
// Virtual member functions
virtual ~CSimpleFontString();
virtual bool IsA(int32_t);
virtual int32_t GetScriptMetaTable(void);
virtual void LoadXML(XMLNode*, CStatus*);
virtual void OnColorChanged(bool);
virtual void OnScreenSizeChanged();
virtual void Draw(CRenderBatch*);
virtual float GetWidth(void);
virtual float GetHeight(void);
virtual void OnFrameSizeChanged(const CRect&);
virtual void FontObjectUpdated(CSimpleFontStringAttributes&);
// Member functions
CSimpleFontString(CSimpleFrame*, uint32_t, int32_t);
void AddShadow(const CImVector&, const C2Vector&);
void ClearString(void);
void DrawEmbeddedTextures(CRenderBatch*);
void FreeEmbeddedTextures(void);
const char* GetDisplayText(float, float);
uint32_t GetFontFlags(void);
float GetFontHeight(bool);
const char* GetFontName(void);
uint32_t GetNumCharsWithinWidth(const char*, uint32_t, float);
float GetStringHeight(void);
float GetStringWidth(void);
const char* GetText(void);
float GetTextWidth(const char*, uint32_t);
void PostLoadXML(XMLNode*, CStatus*);
void RefreshEmbeddedTextures(void);
void RemoveShadow(void);
int32_t SetFont(const char*, float, uint32_t, bool);
void SetIndentedWordWrap(bool);
void SetJustificationOffset(float, float);
void SetJustifyV(uint8_t);
void SetJustifyH(uint8_t);
void SetNonSpaceWrap(int32_t);
void SetNonWordWrap(int32_t);
void SetSpacing(float);
void SetStyleFlags(uint32_t);
void SetText(const char*, int32_t);
void SetTextLength(uint32_t);
int32_t Sub482AC0();
void UpdateString(void);
};
#endif

View file

@ -0,0 +1,179 @@
#include "ui/CSimpleFontStringAttributes.hpp"
#include "gx/Font.hpp"
#include "math/Utils.hpp"
#include "ui/CSimpleFontString.hpp"
#include <storm/Error.hpp>
void CSimpleFontStringAttributes::SetColor(const CImVector& color) {
if (this->m_color == color && this->m_flags & 0x400) {
return;
}
this->m_color = color;
this->m_flags |= (0x4 | 0x400);
}
int32_t CSimpleFontStringAttributes::SetFont(const char* fontName, float fontHeight, uint32_t fontFlags) {
if (!fontName) {
return 0;
}
// Return early if existing attributes match arguments
if (
this->m_font.GetString()
&& !SStrCmpI(fontName, this->m_font.m_str, STORM_MAX_STR)
&& AreEqual(fontHeight, this->m_fontHeight, WHOA_EPSILON_1)
&& fontFlags == this->m_fontFlags
) {
return 1;
}
if (fontHeight <= 0.0f) {
return 0;
}
auto v6 = TextBlockGenerateFont(fontName, fontFlags, fontHeight);
if (!v6) {
return 0;
}
HandleClose(v6);
this->m_font.Copy(fontName);
this->m_fontHeight = fontHeight;
this->m_fontFlags = fontFlags;
this->m_flags |= (0x1 | 0x100);
return 1;
}
void CSimpleFontStringAttributes::SetIndented(bool indented) {
uint32_t styleFlags = indented
? this->m_styleFlags | 0x20000
: this->m_styleFlags & ~0x20000;
if (this->m_styleFlags == styleFlags && this->m_flags & 0x200) {
return;
}
this->m_styleFlags = styleFlags;
this->m_flags |= (0x2 | 0x200);
}
void CSimpleFontStringAttributes::SetJustifyH(uint8_t justify) {
uint32_t styleFlags = this->m_styleFlags ^ ((justify ^ this->m_styleFlags) & 0x7);
if (this->m_styleFlags == styleFlags && this->m_flags & 0x200) {
return;
}
this->m_styleFlags = styleFlags;
this->m_flags |= (0x2 | 0x200);
}
void CSimpleFontStringAttributes::SetJustifyV(uint8_t justify) {
uint32_t styleFlags = this->m_styleFlags ^ ((justify ^ this->m_styleFlags) & 0x38);
if (this->m_styleFlags == styleFlags && this->m_flags & 0x200) {
return;
}
this->m_styleFlags = styleFlags;
this->m_flags |= (0x2 | 0x200);
}
void CSimpleFontStringAttributes::SetNonSpaceWrap(bool wrap) {
uint32_t styleFlags = wrap
? this->m_styleFlags | 0x1000
: this->m_styleFlags & ~0x1000;
if (this->m_styleFlags == styleFlags && this->m_flags & 0x200) {
return;
}
this->m_styleFlags = styleFlags;
this->m_flags |= (0x2 | 0x200);
}
void CSimpleFontStringAttributes::SetShadow(const CImVector& shadowColor, const C2Vector& shadowOffset) {
if (this->m_shadowColor == shadowColor && this->m_shadowOffset == shadowOffset && this->m_flags & 0x800) {
return;
}
this->m_shadowColor = shadowColor;
this->m_shadowOffset = shadowOffset;
this->m_flags |= (0x8 | 0x800);
}
void CSimpleFontStringAttributes::SetSpacing(float spacing) {
if (AreEqual(spacing, this->m_spacing, WHOA_EPSILON_1) && this->m_flags & 0x1000) {
return;
}
this->m_spacing = spacing;
this->m_flags |= (0x10 | 0x1000);
}
void CSimpleFontStringAttributes::SetStyleFlags(uint32_t styleFlags) {
if (this->m_styleFlags == styleFlags && this->m_flags & 0x200) {
return;
}
this->m_styleFlags = styleFlags;
this->m_flags |= (0x2 | 0x200);
}
void CSimpleFontStringAttributes::Update(CSimpleFontString* fontString, uint32_t flags) {
STORM_ASSERT(fontString);
uint32_t v5 = flags & this->m_flags;
if (this->m_flags & 0x100 && v5 & 0x1) {
fontString->SetFont(this->m_font.GetString(), this->m_fontHeight, this->m_fontFlags, 0);
}
if (this->m_flags & 0x200 && v5 & 0x2) {
fontString->SetStyleFlags(this->m_styleFlags);
}
if (this->m_flags & 0x400 && v5 & 0x4) {
fontString->SetVertexColor(this->m_color);
}
if (this->m_flags & 0x800 && v5 & 0x8) {
if (this->m_shadowOffset.x == 0.0f && this->m_shadowOffset.y == 0.0f) {
fontString->RemoveShadow();
} else {
fontString->AddShadow(this->m_shadowColor, this->m_shadowOffset);
}
}
if (this->m_flags & 0x1000 && v5 & 0x10) {
fontString->SetSpacing(this->m_spacing);
}
}
void CSimpleFontStringAttributes::Update(CSimpleFontStringAttributes& attributes, uint32_t flags) {
uint32_t v4 = flags & this->m_flags;
if (this->m_flags & 0x100 && v4 & 0x1) {
attributes.SetFont(this->m_font.GetString(), this->m_fontHeight, this->m_fontFlags);
}
if (this->m_flags & 0x200 && v4 & 0x2) {
attributes.SetStyleFlags(this->m_styleFlags);
}
if (this->m_flags & 0x400 && v4 & 0x4) {
attributes.SetColor(this->m_color);
}
if (this->m_flags & 0x800 && v4 & 0x8) {
attributes.SetShadow(this->m_shadowColor, this->m_shadowOffset);
}
if (this->m_flags & 0x1000 && v4 & 0x10) {
attributes.SetSpacing(this->m_spacing);
}
}

View file

@ -0,0 +1,37 @@
#ifndef UI_C_SIMPLE_FONT_STRING_ATTRIBUTES_HPP
#define UI_C_SIMPLE_FONT_STRING_ATTRIBUTES_HPP
#include <cstdint>
#include <common/String.hpp>
#include <tempest/Vector.hpp>
class CSimpleFontString;
class CSimpleFontStringAttributes {
public:
// Member variables
uint32_t m_flags = 0;
RCString m_font;
float m_fontHeight = 0.0f;
uint32_t m_fontFlags = 0;
float m_spacing = 0.0f;
uint32_t m_styleFlags = 0x2 | 0x10 | 0x200;
CImVector m_color = { 0, 0, 0, 0 };
CImVector m_shadowColor = { 0, 0, 0, 0 };
C2Vector m_shadowOffset;
// Member functions
void SetColor(const CImVector&);
int32_t SetFont(const char*, float, uint32_t);
void SetIndented(bool);
void SetJustifyV(uint8_t);
void SetJustifyH(uint8_t);
void SetNonSpaceWrap(bool);
void SetShadow(const CImVector&, const C2Vector&);
void SetSpacing(float);
void SetStyleFlags(uint32_t);
void Update(CSimpleFontString*, uint32_t);
void Update(CSimpleFontStringAttributes&, uint32_t);
};
#endif

View file

@ -0,0 +1,264 @@
#include "ui/CSimpleFontStringScript.hpp"
#include "ui/CSimpleFont.hpp"
#include "ui/CSimpleFontString.hpp"
#include "util/Lua.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleFontString_IsObjectType(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetObjectType(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetDrawLayer(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetDrawLayer(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetVertexColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetAlpha(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetAlpha(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetAlphaGradient(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_Show(lua_State* L) {
auto type = CSimpleFontString::GetObjectType();
auto string = static_cast<CSimpleFontString*>(FrameScript_GetObjectThis(L, type));
string->Show();
return 0;
}
int32_t CSimpleFontString_Hide(lua_State* L) {
auto type = CSimpleFontString::GetObjectType();
auto string = static_cast<CSimpleFontString*>(FrameScript_GetObjectThis(L, type));
string->Hide();
return 0;
}
int32_t CSimpleFontString_IsVisible(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_IsShown(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetFontObject(lua_State* L) {
auto type = CSimpleFontString::GetObjectType();
auto string = static_cast<CSimpleFontString*>(FrameScript_GetObjectThis(L, type));
CSimpleFont* font = nullptr;
if (lua_type(L, 2) == LUA_TTABLE) {
lua_rawgeti(L, 2, 0);
font = static_cast<CSimpleFont*>(lua_touserdata(L, -1));
lua_settop(L, -2);
if (!font) {
luaL_error(L, "%s:SetFontObject(): Couldn't find 'this' in font object", string->GetDisplayName());
}
if (!font->IsA(CSimpleFont::GetObjectType())) {
luaL_error(L, "%s:SetFontObject(): Wrong object type, expected font", string->GetDisplayName());
}
} else if (lua_type(L, 2) == LUA_TSTRING) {
auto fontName = lua_tolstring(L, 2, nullptr);
font = CSimpleFont::GetFont(fontName, 0);
if (!font) {
luaL_error(L, "%s:SetFontObject(): Couldn't find font named %s", string->GetDisplayName(), fontName);
}
} else if (lua_type(L, 2) != LUA_TNIL) {
luaL_error(L, "Usage: %s:SetFontObject(font or \"font\" or nil)", string->GetDisplayName());
}
string->SetFontObject(font);
return 0;
}
int32_t CSimpleFontString_GetFont(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetFont(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetText(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetFieldSize(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetText(lua_State* L) {
auto type = CSimpleFontString::GetObjectType();
auto string = static_cast<CSimpleFontString*>(FrameScript_GetObjectThis(L, type));
if (!string->m_font) {
luaL_error(L, "%s:SetText(): Font not set", string->GetDisplayName());
}
const char* text = lua_tolstring(L, 2, 0);
string->SetText(text, 1);
return 0;
}
int32_t CSimpleFontString_SetFormattedText(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetTextColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetTextColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetShadowColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetShadowColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetShadowOffset(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetShadowOffset(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetSpacing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetSpacing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetTextHeight(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetStringWidth(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetStringHeight(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetJustifyH(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetJustifyH(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetJustifyV(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetJustifyV(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_CanNonSpaceWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetNonSpaceWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_CanWordWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetWordWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_GetIndentedWordWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFontString_SetIndentedWordWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleFontStringMethods[NUM_SIMPLE_FONT_STRING_SCRIPT_METHODS] = {
{ "IsObjectType", &CSimpleFontString_IsObjectType },
{ "GetObjectType", &CSimpleFontString_GetObjectType },
{ "GetDrawLayer", &CSimpleFontString_GetDrawLayer },
{ "SetDrawLayer", &CSimpleFontString_SetDrawLayer },
{ "SetVertexColor", &CSimpleFontString_SetVertexColor },
{ "GetAlpha", &CSimpleFontString_GetAlpha },
{ "SetAlpha", &CSimpleFontString_SetAlpha },
{ "SetAlphaGradient", &CSimpleFontString_SetAlphaGradient },
{ "Show", &CSimpleFontString_Show },
{ "Hide", &CSimpleFontString_Hide },
{ "IsVisible", &CSimpleFontString_IsVisible },
{ "IsShown", &CSimpleFontString_IsShown },
{ "GetFontObject", &CSimpleFontString_GetFontObject },
{ "SetFontObject", &CSimpleFontString_SetFontObject },
{ "GetFont", &CSimpleFontString_GetFont },
{ "SetFont", &CSimpleFontString_SetFont },
{ "GetText", &CSimpleFontString_GetText },
{ "GetFieldSize", &CSimpleFontString_GetFieldSize },
{ "SetText", &CSimpleFontString_SetText },
{ "SetFormattedText", &CSimpleFontString_SetFormattedText },
{ "GetTextColor", &CSimpleFontString_GetTextColor },
{ "SetTextColor", &CSimpleFontString_SetTextColor },
{ "GetShadowColor", &CSimpleFontString_GetShadowColor },
{ "SetShadowColor", &CSimpleFontString_SetShadowColor },
{ "GetShadowOffset", &CSimpleFontString_GetShadowOffset },
{ "SetShadowOffset", &CSimpleFontString_SetShadowOffset },
{ "GetSpacing", &CSimpleFontString_GetSpacing },
{ "SetSpacing", &CSimpleFontString_SetSpacing },
{ "SetTextHeight", &CSimpleFontString_SetTextHeight },
{ "GetStringWidth", &CSimpleFontString_GetStringWidth },
{ "GetStringHeight", &CSimpleFontString_GetStringHeight },
{ "GetJustifyH", &CSimpleFontString_GetJustifyH },
{ "SetJustifyH", &CSimpleFontString_SetJustifyH },
{ "GetJustifyV", &CSimpleFontString_GetJustifyV },
{ "SetJustifyV", &CSimpleFontString_SetJustifyV },
{ "CanNonSpaceWrap", &CSimpleFontString_CanNonSpaceWrap },
{ "SetNonSpaceWrap", &CSimpleFontString_SetNonSpaceWrap },
{ "CanWordWrap", &CSimpleFontString_CanWordWrap },
{ "SetWordWrap", &CSimpleFontString_SetWordWrap },
{ "GetIndentedWordWrap", &CSimpleFontString_GetIndentedWordWrap },
{ "SetIndentedWordWrap", &CSimpleFontString_SetIndentedWordWrap }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_FONT_STRING_SCRIPT_HPP
#define UI_C_SIMPLE_FONT_STRING_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_FONT_STRING_SCRIPT_METHODS 41
extern FrameScript_Method SimpleFontStringMethods[NUM_SIMPLE_FONT_STRING_SCRIPT_METHODS];
#endif

View file

@ -0,0 +1,30 @@
#include "ui/CSimpleFontable.hpp"
#include "ui/CSimpleFont.hpp"
CSimpleFontable::~CSimpleFontable() {
this->SetFontObject(nullptr);
}
CSimpleFont* CSimpleFontable::GetFontObject() {
return this->m_fontObject;
}
void CSimpleFontable::SetFontObject(CSimpleFont* fontObject) {
if (this->m_fontObject == fontObject) {
return;
}
if (this->m_fontObject) {
this->m_fontObject->m_fontableList.UnlinkNode(this);
}
this->m_fontObject = fontObject;
if (fontObject) {
fontObject->m_fontableList.LinkToTail(this);
fontObject->m_attributes.m_flags |= FLAG_COMPLETE_UPDATE;
this->FontObjectUpdated(fontObject->m_attributes);
fontObject->m_attributes.m_flags &= ~(FLAG_COMPLETE_UPDATE);
}
}

View file

@ -0,0 +1,26 @@
#ifndef UI_C_SIMPLE_FONTABLE_HPP
#define UI_C_SIMPLE_FONTABLE_HPP
#include "ui/Types.hpp"
#include <storm/List.hpp>
class CSimpleFont;
class CSimpleFontStringAttributes;
class CSimpleFontable {
public:
// Member variables
CSimpleFont* m_fontObject = nullptr;
uint32_t m_fontableFlags = FLAG_COMPLETE_UPDATE;
TSLink<CSimpleFontable> m_fontableLink;
// Virtual member functions
virtual ~CSimpleFontable();
virtual void FontObjectUpdated(CSimpleFontStringAttributes&) = 0;
// Member functions
CSimpleFont* GetFontObject(void);
void SetFontObject(CSimpleFont*);
};
#endif

View file

@ -0,0 +1,14 @@
#ifndef UI_C_SIMPLE_FONTED_FRAME_HPP
#define UI_C_SIMPLE_FONTED_FRAME_HPP
#include <cstdint>
class CSimpleFontedFrameFont;
class CSimpleFontedFrame {
public:
// Virtual member functions
virtual void FontUpdated(CSimpleFontedFrameFont*, int32_t) = 0;
};
#endif

View file

@ -0,0 +1,19 @@
#ifndef UI_C_SIMPLE_FONTED_FRAME_FONT_HPP
#define UI_C_SIMPLE_FONTED_FRAME_FONT_HPP
#include "ui/CSimpleFont.hpp"
class CSimpleFontedFrame;
class CSimpleFontedFrameFont : public CSimpleFont {
public:
// Member variables
CSimpleFontedFrame* m_frame;
// Member functions
CSimpleFontedFrameFont(CSimpleFontedFrame* frame)
: m_frame(frame)
{};
};
#endif

1584
src/ui/CSimpleFrame.cpp Normal file

File diff suppressed because it is too large Load diff

162
src/ui/CSimpleFrame.hpp Normal file
View file

@ -0,0 +1,162 @@
#ifndef UI_C_SIMPLE_FRAME_HPP
#define UI_C_SIMPLE_FRAME_HPP
#include "ui/CRenderBatch.hpp"
#include "ui/CScriptRegion.hpp"
#include "ui/CSimpleRegion.hpp"
#include "ui/Types.hpp"
#include <cstdint>
#include <storm/List.hpp>
class CBackdropGenerator;
class CCharEvent;
class CKeyEvent;
class CMouseEvent;
class CSimpleTitleRegion;
class CSimpleTop;
struct lua_State;
class CSimpleFrame : public CScriptRegion {
public:
// Static members
static int32_t s_metatable;
static int32_t s_objectType;
// Static functions
static void CreateScriptMetaTable(void);
static int32_t GetObjectType(void);
static void RegisterScriptMethods(lua_State*);
// Member variables
CSimpleTop* m_top = NULL;
CSimpleTitleRegion* m_titleRegion = NULL;
int32_t m_intAC = 1;
int32_t m_id = 0;
uint32_t m_flags = 0;
float m_frameScale = 1.0f;
float m_depth = 0.0;
FRAME_STRATA m_strata = FRAME_STRATA_MEDIUM;
int32_t m_level = 0;
uint32_t m_eventmask = 0;
int32_t m_shown = 0;
int32_t m_visible = 0;
CRect m_hitRect = {};
CRect m_hitOffset = {};
int32_t m_highlightLocked = 0;
uint32_t m_lookForDrag = 0;
int32_t m_mouseDown = 0;
int32_t m_dragging = 0;
int32_t m_dragButton;
C2Vector m_clickPoint;
int32_t m_loading = 0;
ScriptIx m_onLoad;
ScriptIx m_onSizeChanged;
ScriptIx m_onUpdate;
ScriptIx m_onShow;
ScriptIx m_onHide;
ScriptIx m_onEnter;
ScriptIx m_onLeave;
ScriptIx m_onMouseDown;
ScriptIx m_onMouseUp;
ScriptIx m_onMouseWheel;
ScriptIx m_onDragStart;
ScriptIx m_onDragStop;
ScriptIx m_onReceiveDrag;
ScriptIx m_onChar;
ScriptIx m_onKeyDown;
ScriptIx m_onKeyUp;
ScriptIx m_onAttributeChange;
ScriptIx m_onEnable;
ScriptIx m_onDisable;
int32_t m_drawenabled[NUM_SIMPLEFRAME_DRAWLAYERS];
CBackdropGenerator* m_backdrop = nullptr;
STORM_EXPLICIT_LIST(CSimpleRegion, m_regionLink) m_regions;
STORM_EXPLICIT_LIST(CSimpleRegion, m_layerLink) m_drawlayers[NUM_SIMPLEFRAME_DRAWLAYERS];
uint32_t m_batchDirty = 0;
CRenderBatch* m_batch[NUM_SIMPLEFRAME_DRAWLAYERS] = {};
STORM_EXPLICIT_LIST(CRenderBatch, renderLink) m_renderList;
TSList<SIMPLEFRAMENODE, TSGetLink<SIMPLEFRAMENODE>> m_children;
TSLink<CSimpleFrame> m_framesLink;
TSLink<CSimpleFrame> m_destroyedLink;
TSLink<CSimpleFrame> m_strataLink;
// Virtual member functions
virtual ~CSimpleFrame();
virtual ScriptIx* GetScriptByName(const char*, ScriptData&);
virtual bool IsA(int32_t);
virtual int32_t GetScriptMetaTable(void);
virtual void LoadXML(XMLNode*, CStatus*);
virtual void PreOnAnimUpdate(void);
virtual void OnLayerShow(void);
virtual void OnLayerHide(void);
virtual void OnLayerUpdate(float);
virtual int32_t OnLayerTrackUpdate(const CMouseEvent&);
virtual void OnFrameRender(void);
virtual void OnFrameRender(CRenderBatch*, uint32_t);
virtual void OnScreenSizeChanged();
virtual void OnFrameSizeChanged(float, float);
virtual void OnLayerCursorEnter(int32_t);
virtual void OnLayerCursorExit(int32_t, int32_t);
virtual int32_t OnLayerChar(const CCharEvent&);
virtual int32_t OnLayerKeyDown(const CKeyEvent&);
virtual int32_t OnLayerKeyUp(const CKeyEvent&);
virtual int32_t OnLayerMouseDown(const CMouseEvent&, const char*);
virtual int32_t OnLayerMouseUp(const CMouseEvent&, const char*);
virtual void PostLoadXML(XMLNode*, CStatus*);
virtual void UnregisterRegion(CSimpleRegion*);
virtual int32_t GetBoundsRect(CRect& bounds);
virtual void PreLoadXML(XMLNode*, CStatus*);
virtual void LockHighlight(int32_t);
virtual int32_t HideThis(void);
virtual int32_t ShowThis(void);
virtual bool UpdateScale(bool);
virtual void UpdateDepth(bool);
virtual void ParentFrame(CSimpleFrame*);
virtual void OnFrameSizeChanged(const CRect&);
// Member functions
CSimpleFrame(CSimpleFrame*);
void AddFrameRegion(CSimpleRegion*, uint32_t);
void DisableDrawLayer(uint32_t);
void EnableDrawLayer(uint32_t);
void EnableEvent(CSimpleEventType, int32_t);
int32_t GetHitRect(CRect& rect);
void Hide(void);
void LoadXML_Attributes(XMLNode*, CStatus*);
void LoadXML_Backdrop(XMLNode*, CStatus*);
void LoadXML_Layers(XMLNode*, CStatus*);
void LoadXML_Scripts(XMLNode*, CStatus*);
void NotifyDrawLayerChanged(uint32_t);
void NotifyScrollParent(void);
void PostLoadXML_Frames(XMLNode*, CStatus*);
void Raise(void);
void RegisterForEvents(int32_t);
void RegisterRegion(CSimpleRegion*);
void RemoveFrameRegion(CSimpleRegion*, uint32_t);
void RunOnCharScript(const char*);
void RunOnEnterScript(int32_t);
void RunOnHideScript(void);
void RunOnKeyDownScript(const char*);
void RunOnKeyUpScript(const char*);
void RunOnLeaveScript(int32_t);
void RunOnLoadScript(void);
void RunOnMouseDownScript(const char*);
void RunOnMouseUpScript(const char*);
void RunOnShowScript(void);
void RunOnSizeChangedScript(float, float);
void RunOnUpdateScript(float);
void SetBackdrop(CBackdropGenerator*);
void SetBeingScrolled(int32_t, int32_t);
void SetFrameAlpha(uint8_t alpha);
void SetFrameFlag(int32_t, int32_t);
void SetFrameLevel(int32_t, int32_t);
bool SetFrameScale(float scale, bool a3);
void SetFrameStrata(FRAME_STRATA);
void SetHitRect(void);
void SetParent(CSimpleFrame*);
void Show(void);
int32_t TestHitRect(const C2Vector&);
void UnregisterForEvents(int32_t);
};
#endif

View file

@ -0,0 +1,580 @@
#include "ui/CSimpleFrameScript.hpp"
#include "gx/Coordinate.hpp"
#include "ui/CSimpleFrame.hpp"
#include "ui/FrameScript.hpp"
#include "util/Lua.hpp"
#include "util/Unimplemented.hpp"
#include <algorithm>
#include <cstdint>
#include <limits>
int32_t CSimpleFrame_GetTitleRegion(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_CreateTitleRegion(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_CreateTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_CreateFontString(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetBoundsRect(lua_State* L) {
int32_t type = CSimpleFrame::GetObjectType();
CSimpleFrame* frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
CRect bounds = {
std::numeric_limits<float>::max(),
std::numeric_limits<float>::max(),
0.0f,
0.0f
};
if (!frame->GetBoundsRect(bounds)) {
return 0;
}
float ooScale = 1.0f / frame->m_layoutScale;
float ddcTop = CoordinateGetAspectCompensation() * 1024.0f * ooScale * bounds.minX;
float ndcTop = DDCToNDCWidth(ddcTop);
lua_pushnumber(L, ndcTop);
float ddcLeft = CoordinateGetAspectCompensation() * 1024.0f * ooScale * bounds.minY;
float ndcLeft = DDCToNDCWidth(ddcLeft);
lua_pushnumber(L, ndcLeft);
float ddcWidth = CoordinateGetAspectCompensation() * 1024.0f * ooScale * (bounds.maxX - bounds.minX);
float ndcWidth = DDCToNDCWidth(ddcWidth);
lua_pushnumber(L, ndcWidth);
float ddcHeight = CoordinateGetAspectCompensation() * 1024.0f * ooScale * (bounds.maxY - bounds.minY);
float ndcHeight = DDCToNDCWidth(ddcHeight);
lua_pushnumber(L, ndcHeight);
return 4;
}
int32_t CSimpleFrame_GetNumRegions(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetRegions(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetNumChildren(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetChildren(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetFrameStrata(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetFrameStrata(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetFrameLevel(lua_State* L) {
int32_t type = CSimpleFrame::GetObjectType();
CSimpleFrame* frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
lua_pushnumber(L, frame->m_level);
return 1;
}
int32_t CSimpleFrame_SetFrameLevel(lua_State* L) {
int32_t type = CSimpleFrame::GetObjectType();
CSimpleFrame* frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
if (!frame->ProtectedFunctionsAllowed()) {
// TODO
// - disallowed logic
return 0;
}
if (!lua_isnumber(L, 2)) {
return luaL_error(L, "Usage: %s:SetFrameLevel(level)", frame->GetDisplayName());
}
int32_t level = lua_tonumber(L, 2);
if (level < 0) {
return luaL_error(L, "%s:SetFrameLevel(): Passed negative frame level: %d", frame->GetDisplayName(), level);
}
frame->SetFrameLevel(level, 1);
return 0;
}
int32_t CSimpleFrame_HasScript(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetScript(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetScript(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_HookScript(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_RegisterEvent(lua_State* L) {
int32_t type = CSimpleFrame::GetObjectType();
CSimpleFrame* frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
if (!lua_isstring(L, 2)) {
return luaL_error(L, "Usage: %s:RegisterEvent(\"event\")", frame->GetDisplayName());
}
const char* event = lua_tolstring(L, 2, 0);
frame->RegisterScriptEvent(event);
return 0;
}
int32_t CSimpleFrame_UnregisterEvent(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_RegisterAllEvents(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_UnregisterAllEvents(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsEventRegistered(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_AllowAttributeChanges(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_CanChangeAttributes(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetAttribute(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetAttribute(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetEffectiveScale(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetScale(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetScale(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetEffectiveAlpha(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetAlpha(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetAlpha(lua_State* L) {
auto type = CSimpleFrame::GetObjectType();
auto frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
if (!lua_isnumber(L, 2)) {
luaL_error(L, "Usage: %s:SetAlpha(alpha 0 to 1)", frame->GetDisplayName());
}
float alpha = lua_tonumber(L, 2);
alpha = std::max(std::min(alpha, 1.0f), 0.0f);
frame->SetFrameAlpha(static_cast<uint8_t>(alpha * 255.0f));
return 0;
}
int32_t CSimpleFrame_GetID(lua_State* L) {
int32_t type = CSimpleFrame::GetObjectType();
CSimpleFrame* frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
lua_pushnumber(L, frame->m_id);
return 1;
}
int32_t CSimpleFrame_SetID(lua_State* L) {
int32_t type = CSimpleFrame::GetObjectType();
CSimpleFrame* frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
if (!frame->ProtectedFunctionsAllowed()) {
// TODO
// - disallowed logic
return 0;
}
if (!lua_isnumber(L, 2)) {
return luaL_error(L, "Usage: %s:SetID(ID)", frame->GetDisplayName());
}
frame->m_id = lua_tonumber(L, 2);
return 0;
}
int32_t CSimpleFrame_SetToplevel(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsToplevel(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_EnableDrawLayer(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_DisableDrawLayer(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_Show(lua_State* L) {
int32_t type = CSimpleFrame::GetObjectType();
CSimpleFrame* frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
if (frame->ProtectedFunctionsAllowed()) {
frame->Show();
} else {
// TODO
// - disallowed logic
}
return 0;
}
int32_t CSimpleFrame_Hide(lua_State* L) {
int32_t type = CSimpleFrame::GetObjectType();
CSimpleFrame* frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
if (frame->ProtectedFunctionsAllowed()) {
frame->Hide();
} else {
// TODO
// - disallowed logic
}
return 0;
}
int32_t CSimpleFrame_IsVisible(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsShown(lua_State* L) {
int32_t type = CSimpleFrame::GetObjectType();
CSimpleFrame* frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
if (frame->m_shown) {
lua_pushnumber(L, 1.0);
} else {
lua_pushnil(L);
}
return 1;
}
int32_t CSimpleFrame_Raise(lua_State* L) {
int32_t type = CSimpleFrame::GetObjectType();
CSimpleFrame* frame = static_cast<CSimpleFrame*>(FrameScript_GetObjectThis(L, type));
if (!frame->ProtectedFunctionsAllowed()) {
// TODO
// - disallowed logic
return 0;
}
frame->Raise();
return 0;
}
int32_t CSimpleFrame_Lower(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetHitRectInsets(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetHitRectInsets(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetClampRectInsets(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetClampRectInsets(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetMinResize(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetMinResize(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetMaxResize(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetMaxResize(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetMovable(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsMovable(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetDontSavePosition(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetDontSavePosition(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetResizable(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsResizable(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_StartMoving(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_StartSizing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_StopMovingOrSizing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetUserPlaced(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsUserPlaced(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetClampedToScreen(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsClampedToScreen(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_RegisterForDrag(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_EnableKeyboard(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsKeyboardEnabled(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_EnableMouse(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsMouseEnabled(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_EnableMouseWheel(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsMouseWheelEnabled(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_EnableJoystick(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsJoystickEnabled(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetBackdrop(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetBackdrop(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetBackdropColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetBackdropColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetBackdropBorderColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetBackdropBorderColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_SetDepth(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetDepth(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_GetEffectiveDepth(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IgnoreDepth(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleFrame_IsIgnoringDepth(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleFrameMethods[NUM_SIMPLE_FRAME_SCRIPT_METHODS] = {
{ "GetTitleRegion", &CSimpleFrame_GetTitleRegion },
{ "CreateTitleRegion", &CSimpleFrame_CreateTitleRegion },
{ "CreateTexture", &CSimpleFrame_CreateTexture },
{ "CreateFontString", &CSimpleFrame_CreateFontString },
{ "GetBoundsRect", &CSimpleFrame_GetBoundsRect },
{ "GetNumRegions", &CSimpleFrame_GetNumRegions },
{ "GetRegions", &CSimpleFrame_GetRegions },
{ "GetNumChildren", &CSimpleFrame_GetNumChildren },
{ "GetChildren", &CSimpleFrame_GetChildren },
{ "GetFrameStrata", &CSimpleFrame_GetFrameStrata },
{ "SetFrameStrata", &CSimpleFrame_SetFrameStrata },
{ "GetFrameLevel", &CSimpleFrame_GetFrameLevel },
{ "SetFrameLevel", &CSimpleFrame_SetFrameLevel },
{ "HasScript", &CSimpleFrame_HasScript },
{ "GetScript", &CSimpleFrame_GetScript },
{ "SetScript", &CSimpleFrame_SetScript },
{ "HookScript", &CSimpleFrame_HookScript },
{ "RegisterEvent", &CSimpleFrame_RegisterEvent },
{ "UnregisterEvent", &CSimpleFrame_UnregisterEvent },
{ "RegisterAllEvents", &CSimpleFrame_RegisterAllEvents },
{ "UnregisterAllEvents", &CSimpleFrame_UnregisterAllEvents },
{ "IsEventRegistered", &CSimpleFrame_IsEventRegistered },
{ "AllowAttributeChanges", &CSimpleFrame_AllowAttributeChanges },
{ "CanChangeAttribute", &CSimpleFrame_CanChangeAttributes },
{ "GetAttribute", &CSimpleFrame_GetAttribute },
{ "SetAttribute", &CSimpleFrame_SetAttribute },
{ "GetEffectiveScale", &CSimpleFrame_GetEffectiveScale },
{ "GetScale", &CSimpleFrame_GetScale },
{ "SetScale", &CSimpleFrame_SetScale },
{ "GetEffectiveAlpha", &CSimpleFrame_GetEffectiveAlpha },
{ "GetAlpha", &CSimpleFrame_GetAlpha },
{ "SetAlpha", &CSimpleFrame_SetAlpha },
{ "GetID", &CSimpleFrame_GetID },
{ "SetID", &CSimpleFrame_SetID },
{ "SetToplevel", &CSimpleFrame_SetToplevel },
{ "IsToplevel", &CSimpleFrame_IsToplevel },
{ "EnableDrawLayer", &CSimpleFrame_EnableDrawLayer },
{ "DisableDrawLayer", &CSimpleFrame_DisableDrawLayer },
{ "Show", &CSimpleFrame_Show },
{ "Hide", &CSimpleFrame_Hide },
{ "IsVisible", &CSimpleFrame_IsVisible },
{ "IsShown", &CSimpleFrame_IsShown },
{ "Raise", &CSimpleFrame_Raise },
{ "Lower", &CSimpleFrame_Lower },
{ "GetHitRectInsets", &CSimpleFrame_GetHitRectInsets },
{ "SetHitRectInsets", &CSimpleFrame_SetHitRectInsets },
{ "GetClampRectInsets", &CSimpleFrame_GetClampRectInsets },
{ "SetClampRectInsets", &CSimpleFrame_SetClampRectInsets },
{ "GetMinResize", &CSimpleFrame_GetMinResize },
{ "SetMinResize", &CSimpleFrame_SetMinResize },
{ "GetMaxResize", &CSimpleFrame_GetMaxResize },
{ "SetMaxResize", &CSimpleFrame_SetMaxResize },
{ "SetMovable", &CSimpleFrame_SetMovable },
{ "IsMovable", &CSimpleFrame_IsMovable },
{ "SetDontSavePosition", &CSimpleFrame_SetDontSavePosition },
{ "GetDontSavePosition", &CSimpleFrame_GetDontSavePosition },
{ "SetResizable", &CSimpleFrame_SetResizable },
{ "IsResizable", &CSimpleFrame_IsResizable },
{ "StartMoving", &CSimpleFrame_StartMoving },
{ "StartSizing", &CSimpleFrame_StartSizing },
{ "StopMovingOrSizing", &CSimpleFrame_StopMovingOrSizing },
{ "SetUserPlaced", &CSimpleFrame_SetUserPlaced },
{ "IsUserPlaced", &CSimpleFrame_IsUserPlaced },
{ "SetClampedToScreen", &CSimpleFrame_SetClampedToScreen },
{ "IsClampedToScreen", &CSimpleFrame_IsClampedToScreen },
{ "RegisterForDrag", &CSimpleFrame_RegisterForDrag },
{ "EnableKeyboard", &CSimpleFrame_EnableKeyboard },
{ "IsKeyboardEnabled", &CSimpleFrame_IsKeyboardEnabled },
{ "EnableMouse", &CSimpleFrame_EnableMouse },
{ "IsMouseEnabled", &CSimpleFrame_IsMouseEnabled },
{ "EnableMouseWheel", &CSimpleFrame_EnableMouseWheel },
{ "IsMouseWheelEnabled", &CSimpleFrame_IsMouseWheelEnabled },
{ "EnableJoystick", &CSimpleFrame_EnableJoystick },
{ "IsJoystickEnabled", &CSimpleFrame_IsJoystickEnabled },
{ "GetBackdrop", &CSimpleFrame_GetBackdrop },
{ "SetBackdrop", &CSimpleFrame_SetBackdrop },
{ "GetBackdropColor", &CSimpleFrame_GetBackdropColor },
{ "SetBackdropColor", &CSimpleFrame_SetBackdropColor },
{ "GetBackdropBorderColor", &CSimpleFrame_GetBackdropBorderColor },
{ "SetBackdropBorderColor", &CSimpleFrame_SetBackdropBorderColor },
{ "SetDepth", &CSimpleFrame_SetDepth },
{ "GetDepth", &CSimpleFrame_GetDepth },
{ "GetEffectiveDepth", &CSimpleFrame_GetEffectiveDepth },
{ "IgnoreDepth", &CSimpleFrame_IgnoreDepth },
{ "IsIgnoringDepth", &CSimpleFrame_IsIgnoringDepth }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_FRAME_SCRIPT_HPP
#define UI_C_SIMPLE_FRAME_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_FRAME_SCRIPT_METHODS 85
extern FrameScript_Method SimpleFrameMethods[NUM_SIMPLE_FRAME_SCRIPT_METHODS];
#endif

371
src/ui/CSimpleHTML.cpp Normal file
View file

@ -0,0 +1,371 @@
#include "ui/CSimpleHTML.hpp"
#include "ui/CSimpleFontedFrameFont.hpp"
#include "ui/CSimpleFontString.hpp"
#include "ui/CSimpleHTMLScript.hpp"
#include "ui/CSimpleTop.hpp"
#include "util/CStatus.hpp"
#include "util/SFile.hpp"
#include "util/StringTo.hpp"
#include <common/XML.hpp>
int32_t CSimpleHTML::s_metatable;
int32_t CSimpleHTML::s_objectType;
CONTENTNODE::~CONTENTNODE() {
if (this->string) {
delete string;
}
}
void CSimpleHTML::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleHTML::RegisterScriptMethods);
CSimpleHTML::s_metatable = ref;
}
int32_t CSimpleHTML::GetObjectType() {
if (!CSimpleHTML::s_objectType) {
CSimpleHTML::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CSimpleHTML::s_objectType;
}
void CSimpleHTML::RegisterScriptMethods(lua_State* L) {
CSimpleFrame::RegisterScriptMethods(L);
FrameScript_Object::FillScriptMethodTable(L, SimpleHTMLMethods, NUM_SIMPLE_HTML_SCRIPT_METHODS);
}
CSimpleHTML::CSimpleHTML(CSimpleFrame* parent) : CSimpleHyperlinkedFrame(parent) {
// TODO
for (int32_t i = 0; i < NUM_HTML_TEXT_TYPES; i++) {
auto m = SMemAlloc(sizeof(CSimpleFontedFrameFont), __FILE__, __LINE__, 0x0);
auto font = new (m) CSimpleFontedFrameFont(this);
this->m_fonts[i] = font;
}
// TODO
}
void CSimpleHTML::AddText(const char* text, HTML_TEXT_TYPE type, uint32_t justify) {
// TODO void* stringMem = CDataAllocator::GetData(CSimpleFontString::s_allocator, 0x0, __FILE__, __LINE__);
void* stringMem = SMemAlloc(sizeof(CSimpleFontString), __FILE__, __LINE__, 0x0);
CSimpleFontString* string = new (stringMem) CSimpleFontString(this, DRAWLAYER_ARTWORK, 1);
if (this->m_layoutAnchor) {
string->SetPoint(
FRAMEPOINT_TOPLEFT,
this->m_layoutAnchor,
FRAMEPOINT_BOTTOMLEFT,
0.0f,
this->m_layoutOffset,
1
);
} else {
string->SetPoint(
FRAMEPOINT_TOPLEFT,
this,
FRAMEPOINT_TOPLEFT,
0.0f,
0.0f,
1
);
}
string->SetWidth(this->GetWidth());
auto font = this->m_fonts[type];
if (!font->m_attributes.m_font.GetString()) {
font = this->m_fonts[0];
}
string->SetFontObject(font);
string->SetJustifyH(justify);
// TODO something with style flag 0x1000?
string->SetText(text, 1);
this->m_layoutAnchor = string;
this->m_layoutOffset = -CSimpleTop::RoundToPixelHeight(string->m_spacing);
auto contentNode = this->m_content.NewNode(2, 0, 0x0);
contentNode->string = string;
// TODO contentNode->dword8 = SStrStr(text, "|H") != 0;
}
void CSimpleHTML::ClearContent() {
this->m_content.DeleteAll();
this->m_layoutAnchor = nullptr;
this->m_layoutOffset = 0.0f;
// TODO clear hyperlinks
}
void CSimpleHTML::FontUpdated(CSimpleFontedFrameFont* font, int32_t a3) {
// TODO
}
int32_t CSimpleHTML::GetScriptMetaTable() {
return CSimpleHTML::s_metatable;
}
bool CSimpleHTML::IsA(int32_t type) {
return type == CSimpleHTML::s_objectType
|| type == CSimpleFrame::s_objectType
|| type == CScriptRegion::s_objectType
|| type == CScriptObject::s_objectType;
}
void CSimpleHTML::LoadXML(XMLNode* node, CStatus* status) {
CSimpleFrame::LoadXML(node, status);
const char* fontAttr = node->GetAttributeByName("font");
if (fontAttr && *fontAttr) {
auto font = CSimpleFont::GetFont(fontAttr, 0);
if (font) {
for (int32_t i = 0; i < NUM_HTML_TEXT_TYPES; i++) {
this->m_fonts[i]->SetFontObject(font);
}
} else {
status->Add(
STATUS_WARNING,
"%s %s: Couldn't find font object named %s",
this->GetObjectTypeName(),
this->GetDisplayName(),
fontAttr
);
}
}
for (XMLNode* child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "FontString", STORM_MAX_STR)) {
this->m_fonts[HTML_TEXT_NORMAL]->LoadXML(child, status);
} else if (!SStrCmpI(child->GetName(), "FontStringHeader1", STORM_MAX_STR)) {
this->m_fonts[HTML_TEXT_HEADER1]->LoadXML(child, status);
} else if (!SStrCmpI(child->GetName(), "FontStringHeader2", STORM_MAX_STR)) {
this->m_fonts[HTML_TEXT_HEADER2]->LoadXML(child, status);
} else if (!SStrCmpI(child->GetName(), "FontStringHeader3", STORM_MAX_STR)) {
this->m_fonts[HTML_TEXT_HEADER3]->LoadXML(child, status);
}
}
const char* fileAttr = node->GetAttributeByName("file");
void* fileData;
if (fileAttr && SFile::Load(nullptr, fileAttr, &fileData, nullptr, 1, 0x1, nullptr)) {
this->SetText(static_cast<char*>(fileData), nullptr);
SFile::Unload(fileData);
}
// TODO hyperlinkFormat
}
void CSimpleHTML::ParseBODY(XMLNode* node, CStatus* status) {
for (auto child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "H1", STORM_MAX_STR)) {
this->ParseP(child, HTML_TEXT_HEADER1, status);
} else if (!SStrCmpI(child->GetName(), "H2", STORM_MAX_STR)) {
this->ParseP(child, HTML_TEXT_HEADER2, status);
} else if (!SStrCmpI(child->GetName(), "H3", STORM_MAX_STR)) {
this->ParseP(child, HTML_TEXT_HEADER3, status);
} else if (!SStrCmpI(child->GetName(), "P", STORM_MAX_STR)) {
this->ParseP(child, HTML_TEXT_NORMAL, status);
} else if (!SStrCmpI(child->GetName(), "BR", STORM_MAX_STR)) {
this->AddText("\n", HTML_TEXT_NORMAL, 1);
} else if (!SStrCmpI(child->GetName(), "IMG", STORM_MAX_STR)) {
this->ParseIMG(child, status);
} else {
status->Add(
STATUS_WARNING,
"Frame %s: Unknown element type: %s",
this->GetDisplayName(),
child->GetName()
);
}
}
}
void CSimpleHTML::ParseIMG(XMLNode* node, CStatus* status) {
// TODO
}
void CSimpleHTML::ParseP(XMLNode* node, HTML_TEXT_TYPE type, CStatus* status) {
uint32_t justify = 1;
auto justifyAttr = node->GetAttributeByName("align");
if (justifyAttr && *justifyAttr) {
StringToJustify(justifyAttr, justify);
}
auto body = node->GetBody();
if (!body) {
body = "";
}
auto text = SStrDupA(body, __FILE__, __LINE__);
uint32_t offset = 0;
for (auto child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "BR", STORM_MAX_STR)) {
char* newText = static_cast<char*>(SMemAlloc(SStrLen(text) + 3, __FILE__, __LINE__, 0x0));
SStrCopy(newText, text, child->m_offset + offset + 1);
SStrPack(newText, "|n", STORM_MAX_STR);
SStrPack(newText, &text[child->m_offset + offset], STORM_MAX_STR);
SMemFree(text, __FILE__, __LINE__, 0x0);
text = newText;
offset += 2;
} else if (!SStrCmpI(child->GetName(), "A", STORM_MAX_STR)) {
// TODO handle anchor child
} else {
status->Add(
STATUS_WARNING,
"Frame %s: Unknown element type: %s",
this->GetDisplayName(),
child->GetName()
);
}
}
int32_t v22 = 0;
int32_t v36 = 1;
auto v23 = text;
auto v24 = text;
if (*text) {
do {
switch (*v23) {
case '\t':
case '\n':
case '\r':
case ' ': {
if (!v36 && !v22) {
v22 = 1;
*v24 = ' ';
v24++;
}
break;
}
case '|': {
if (v23[1] != 'n') {
v22 = 0;
v36 = 0;
*v24 = *v23;
v24++;
break;
}
if (v24 > text && v22) {
v24--;
}
*v24 = '|';
v24++;
*v24 = 'n';
v24++;
v22 = 0;
v36 = 1;
v23++;
break;
}
default: {
v22 = 0;
v36 = 0;
*v24 = *v23;
v24++;
break;
}
}
v23++;
} while (*v23);
if (v24 > text && v22) {
v24--;
}
}
*v24 = '\0';
this->AddText(text, type, justify);
SMemFree(text, __FILE__, __LINE__, 0x0);
}
bool CSimpleHTML::SetText(const char* text, CStatus* status) {
static auto s_nullStatus = CStatus();
if (!status) {
status = &s_nullStatus;
}
if (!text) {
text = "";
}
// TODO some sort of guard condition
this->ClearContent();
auto textLength = SStrLen(text);
auto tree = XMLTree_Load(text, textLength);
bool success = false;
if (tree) {
auto node = XMLTree_GetRoot(tree);
if (!SStrCmpI(node->GetName(), "HTML", STORM_MAX_STR)) {
for (auto child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "BODY", STORM_MAX_STR)) {
success = true;
this->ParseBODY(child, status);
break;
}
status->Add(
STATUS_WARNING,
"Frame %s: Unknown element type: %s (expected BODY)",
this->GetDisplayName(),
node->GetName()
);
}
} else {
status->Add(
STATUS_WARNING,
"Frame %s: Unknown element type: %s (expected HTML)",
this->GetDisplayName(),
node->GetName()
);
}
XMLTree_Free(tree);
}
if (success) {
// TODO set flag
return true;
}
this->AddText(text, HTML_TEXT_NORMAL, 1);
return false;
}

51
src/ui/CSimpleHTML.hpp Normal file
View file

@ -0,0 +1,51 @@
#ifndef UI_C_SIMPLE_HTML_HPP
#define UI_C_SIMPLE_HTML_HPP
#include "ui/CSimpleFontedFrame.hpp"
#include "ui/CSimpleHyperlinkedFrame.hpp"
#include "ui/Types.hpp"
#include <storm/List.hpp>
class CStatus;
class XMLNode;
struct CONTENTNODE : TSLinkedNode<CONTENTNODE> {
CSimpleFontString* string;
~CONTENTNODE();
};
class CSimpleHTML : public CSimpleHyperlinkedFrame, CSimpleFontedFrame {
public:
// Static variables
static int32_t s_metatable;
static int32_t s_objectType;
// Static functions
static void CreateScriptMetaTable(void);
static int32_t GetObjectType(void);
static void RegisterScriptMethods(lua_State*);
// Member variables
STORM_LIST(CONTENTNODE) m_content;
CLayoutFrame* m_layoutAnchor;
float m_layoutOffset;
CSimpleFontedFrameFont* m_fonts[NUM_HTML_TEXT_TYPES];
// Virtual member functions
virtual bool IsA(int32_t type);
virtual int32_t GetScriptMetaTable(void);
virtual void LoadXML(XMLNode* node, CStatus* status);
virtual void FontUpdated(CSimpleFontedFrameFont* font, int32_t a3);
// Member functions
CSimpleHTML(CSimpleFrame*);
void AddText(const char* text, HTML_TEXT_TYPE type, uint32_t justify);
void ClearContent();
void ParseBODY(XMLNode* node, CStatus* status);
void ParseIMG(XMLNode* node, CStatus* status);
void ParseP(XMLNode* node, HTML_TEXT_TYPE type, CStatus* status);
bool SetText(const char* text, CStatus* status);
};
#endif

View file

@ -0,0 +1,129 @@
#include "ui/CSimpleHTMLScript.hpp"
#include "ui/CSimpleHTML.hpp"
#include "util/Lua.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleHTML_SetFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetFontObject(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_SetFont(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetFont(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_SetTextColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetTextColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_SetShadowColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetShadowColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_SetShadowOffset(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetShadowOffset(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_SetSpacing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetSpacing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_SetJustifyH(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetJustifyH(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_SetJustifyV(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetJustifyV(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_SetIndentedWordWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetIndentedWordWrap(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_SetText(lua_State* L) {
auto type = CSimpleHTML::GetObjectType();
auto html = static_cast<CSimpleHTML*>(FrameScript_GetObjectThis(L, type));
auto text = lua_tolstring(L, 2, nullptr);
html->SetText(text, nullptr);
return 0;
}
int32_t CSimpleHTML_SetHyperlinkFormat(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetHyperlinkFormat(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_SetHyperlinksEnabled(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleHTML_GetHyperlinksEnabled(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleHTMLMethods[NUM_SIMPLE_HTML_SCRIPT_METHODS] = {
{ "SetFontObject", &CSimpleHTML_SetFontObject },
{ "GetFontObject", &CSimpleHTML_GetFontObject },
{ "SetFont", &CSimpleHTML_SetFont },
{ "GetFont", &CSimpleHTML_GetFont },
{ "SetTextColor", &CSimpleHTML_SetTextColor },
{ "GetTextColor", &CSimpleHTML_GetTextColor },
{ "SetShadowColor", &CSimpleHTML_SetShadowColor },
{ "GetShadowColor", &CSimpleHTML_GetShadowColor },
{ "SetShadowOffset", &CSimpleHTML_SetShadowOffset },
{ "GetShadowOffset", &CSimpleHTML_GetShadowOffset },
{ "SetSpacing", &CSimpleHTML_SetSpacing },
{ "GetSpacing", &CSimpleHTML_GetSpacing },
{ "SetJustifyH", &CSimpleHTML_SetJustifyH },
{ "GetJustifyH", &CSimpleHTML_GetJustifyH },
{ "SetJustifyV", &CSimpleHTML_SetJustifyV },
{ "GetJustifyV", &CSimpleHTML_GetJustifyV },
{ "SetIndentedWordWrap", &CSimpleHTML_SetIndentedWordWrap },
{ "GetIndentedWordWrap", &CSimpleHTML_GetIndentedWordWrap },
{ "SetText", &CSimpleHTML_SetText },
{ "SetHyperlinkFormat", &CSimpleHTML_SetHyperlinkFormat },
{ "GetHyperlinkFormat", &CSimpleHTML_GetHyperlinkFormat },
{ "SetHyperlinksEnabled", &CSimpleHTML_SetHyperlinksEnabled },
{ "GetHyperlinksEnabled", &CSimpleHTML_GetHyperlinksEnabled }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_HTML_SCRIPT_HPP
#define UI_C_SIMPLE_HTML_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_HTML_SCRIPT_METHODS 23
extern FrameScript_Method SimpleHTMLMethods[NUM_SIMPLE_HTML_SCRIPT_METHODS];
#endif

View file

@ -0,0 +1,5 @@
#include "ui/CSimpleHyperlinkedFrame.hpp"
CSimpleHyperlinkedFrame::CSimpleHyperlinkedFrame(CSimpleFrame* parent) : CSimpleFrame(parent) {
// TODO
}

View file

@ -0,0 +1,12 @@
#ifndef UI_C_SIMPLE_HYPERLINKED_FRAME_HPP
#define UI_C_SIMPLE_HYPERLINKED_FRAME_HPP
#include "ui/CSimpleFrame.hpp"
class CSimpleHyperlinkedFrame : public CSimpleFrame {
public:
// Member functions
CSimpleHyperlinkedFrame(CSimpleFrame*);
};
#endif

407
src/ui/CSimpleModel.cpp Normal file
View file

@ -0,0 +1,407 @@
#include "ui/CSimpleModel.hpp"
#include "gx/Camera.hpp"
#include "gx/Coordinate.hpp"
#include "gx/Draw.hpp"
#include "gx/Shader.hpp"
#include "gx/Transform.hpp"
#include "math/Utils.hpp"
#include "model/CM2Shared.hpp"
#include "model/M2Data.hpp"
#include "ui/CSimpleModelScript.hpp"
#include "ui/LoadXML.hpp"
#include <common/XML.hpp>
#include <tempest/Math.hpp>
int32_t CSimpleModel::s_metatable;
int32_t CSimpleModel::s_objectType;
void CSimpleModel::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleModel::RegisterScriptMethods);
CSimpleModel::s_metatable = ref;
}
int32_t CSimpleModel::GetObjectType() {
if (!CSimpleModel::s_objectType) {
CSimpleModel::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CSimpleModel::s_objectType;
}
void CSimpleModel::LightingCallback(CM2Model* model, CM2Lighting* lighting, void* userArg) {
CSimpleModel* simpleModel = static_cast<CSimpleModel*>(userArg);
if (simpleModel->m_flags & 0x1) {
lighting->SetFog(simpleModel->m_fogColor, simpleModel->m_fogNear, simpleModel->m_fogFar);
}
if (simpleModel->m_light.m_visible) {
lighting->AddLight(&simpleModel->m_light);
}
}
void CSimpleModel::ModelLoaded(CM2Model* model, void* arg) {
auto simpleModel = static_cast<CSimpleModel*>(arg);
simpleModel->OnModelLoaded(model);
}
void CSimpleModel::RegisterScriptMethods(lua_State* L) {
CSimpleFrame::RegisterScriptMethods(L);
FrameScript_Object::FillScriptMethodTable(L, SimpleModelMethods, NUM_SIMPLE_MODEL_SCRIPT_METHODS);
}
void CSimpleModel::RenderModel(void* arg) {
auto simpleModel = static_cast<CSimpleModel*>(arg);
if (!simpleModel->m_model) {
return;
}
CRect viewRect;
if (!simpleModel->GetRect(&viewRect)) {
return;
}
C44Matrix proj;
GxXformProjection(proj);
C44Matrix view;
GxXformView(view);
float minX, maxX, minY, maxY, minZ, maxZ;
GxXformViewport(minX, maxX, minY, maxY, minZ, maxZ);
C3Vector cameraPos;
C3Vector cameraTarg;
if (simpleModel->m_camera) {
DataMgrGetCoord(simpleModel->m_camera, 7, &cameraPos);
DataMgrGetCoord(simpleModel->m_camera, 8, &cameraTarg);
CameraSetupWorldProjection(simpleModel->m_camera, viewRect, 0x0);
} else {
C2Vector v19 = { viewRect.minX, viewRect.minY };
CameraSetupScreenProjection(viewRect, v19, 0.0f, 1);
}
DDCToNDC(viewRect.minX, viewRect.minY, &viewRect.minX, &viewRect.minY);
DDCToNDC(viewRect.maxX, viewRect.maxY, &viewRect.maxX, &viewRect.maxY);
viewRect.minX = std::max(0.0f, std::min(viewRect.minX, 1.0f));
viewRect.maxX = std::max(0.0f, std::min(viewRect.maxX, 1.0f));
viewRect.minY = std::max(0.0f, std::min(viewRect.minY, 1.0f));
viewRect.maxY = std::max(0.0f, std::min(viewRect.maxY, 1.0f));
// Handle zero width or zero height
if (AreEqual(viewRect.minX, viewRect.maxX, WHOA_EPSILON_1) || AreEqual(viewRect.minY, viewRect.maxY, WHOA_EPSILON_1)) {
GxXformSetProjection(proj);
GxXformSetView(view);
GxXformSetViewport(minX, maxX, minY, maxY, minZ, maxZ);
return;
}
float v11 = viewRect.minX * maxX;
float v12 = viewRect.maxX * maxX;
float v13 = viewRect.minY * maxY;
float v14 = viewRect.maxY * maxY;
GxXformSetViewport(v11, v12, v13, v14, 0.0f, 1.0f);
CImVector clearColor = { 0x00, 0x00, 0x00, 0xFF };
GxSceneClear(0x2, clearColor);
CShaderEffect::UpdateProjMatrix();
simpleModel->UpdateModel();
if (simpleModel->m_pendingCameraIndex == -1u) {
simpleModel->GetScene()->Animate(cameraPos);
simpleModel->GetScene()->Draw(M2PASS_0);
simpleModel->GetScene()->Draw(M2PASS_1);
}
GxXformSetProjection(proj);
GxXformSetView(view);
GxXformSetViewport(minX, maxX, minY, maxY, minZ, maxZ);
CShaderEffect::UpdateProjMatrix();
}
CSimpleModel::CSimpleModel(CSimpleFrame* parent) : CSimpleFrame(parent) {
this->m_light.SetVisible(0);
this->m_light.SetLightType(M2LIGHT_1);
this->m_light.m_ambColor = { 1.0f, 1.0f, 1.0f };
this->m_light.m_dirColor = { 1.0f, 1.0f, 1.0f };
this->m_fogColor = { 0xFF, 0xFF, 0xFF, 0xFF };
}
CM2Scene* CSimpleModel::GetScene() {
if (!this->m_scene) {
this->m_scene = M2CreateScene();
}
return this->m_scene;
}
FrameScript_Object::ScriptIx* CSimpleModel::GetScriptByName(const char* name, ScriptData& data) {
auto parentScript = CSimpleFrame::GetScriptByName(name, data);
if (parentScript) {
return parentScript;
}
if (!SStrCmpI(name, "OnUpdateModel", STORM_MAX_STR)) {
return &this->m_onUpdateModel;
}
if (!SStrCmpI(name, "OnAnimFinished", STORM_MAX_STR)) {
return &this->m_onAnimFinished;
}
return nullptr;
}
int32_t CSimpleModel::GetScriptMetaTable() {
return CSimpleModel::s_metatable;
}
bool CSimpleModel::IsA(int32_t type) {
return type == CSimpleModel::s_objectType
|| type == CSimpleFrame::s_objectType
|| type == CScriptRegion::s_objectType
|| type == CScriptObject::s_objectType;
}
void CSimpleModel::LoadXML(XMLNode* node, CStatus* status) {
CSimpleFrame::LoadXML(node, status);
const char* fileAttr = node->GetAttributeByName("file");
if (fileAttr && *fileAttr) {
this->SetModel(fileAttr);
if (!this->m_model) {
status->Add(
STATUS_WARNING,
"Frame %s: Bad model file: %s",
this->GetDisplayName(),
fileAttr
);
}
}
const char* scaleAttr = node->GetAttributeByName("scale");
if (scaleAttr && *scaleAttr) {
float scale = SStrToFloat(scaleAttr);
if (scale <= 0.0f) {
status->Add(
STATUS_WARNING,
"Frame %s: Invalid model scale: %s",
this->GetDisplayName(),
scaleAttr
);
} else {
this->SetScale(scale);
}
}
const char* fogNearAttr = node->GetAttributeByName("fogNear");
if (fogNearAttr && *fogNearAttr) {
float fogNear = SStrToFloat(fogNearAttr);
if (fogNear < 0.0f) {
fogNear = 0.0f;
}
this->SetFogNear(fogNear);
}
const char* fogFarAttr = node->GetAttributeByName("fogFar");
if (fogFarAttr && *fogFarAttr) {
float fogFar = SStrToFloat(fogFarAttr);
if (fogFar < 0.0f) {
fogFar = 0.0f;
}
this->SetFogFar(fogFar);
}
for (XMLNode* child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "FogColor", STORM_MAX_STR)) {
CImVector color;
LoadXML_Color(child, color);
this->SetFogColor(color);
}
}
}
void CSimpleModel::OnFrameRender(CRenderBatch* batch, uint32_t layer) {
// TODO
}
void CSimpleModel::OnLayerUpdate(float elapsedSec) {
CSimpleFrame::OnLayerUpdate(elapsedSec);
if (this->m_model && this->m_visible && this->m_pendingCameraIndex == -1u) {
this->m_model->SetAnimating(1);
this->m_model->SetVisible(1);
if (this->m_model->m_attachParent) {
this->m_model->m_flag20000 = 1;
} else {
this->m_model->m_flag10000 = 1;
}
}
uint32_t advance = CMath::fuint(elapsedSec * 1000.f);
this->GetScene()->AdvanceTime(advance);
}
void CSimpleModel::OnModelLoaded(CM2Model* model) {
model->SetAnimating(1);
C3Vector cameraPos;
model->m_scene->Animate(cameraPos);
if (this->m_pendingCameraIndex != -1u) {
this->SetCameraByIndex(this->m_pendingCameraIndex);
} else if (this->m_pendingCameraId != -1u) {
this->SetCameraByID(this->m_pendingCameraId);
}
CAaBox bounds;
this->m_bounds = model->GetBoundingBox(bounds);
this->Resize(0);
}
void CSimpleModel::SetCamera(HCAMERA camera) {
if (camera) {
camera = HandleDuplicate(camera);
}
if (this->m_camera) {
HandleClose(this->m_camera);
}
this->m_camera = camera;
this->m_pendingCameraIndex = -1u;
this->m_pendingCameraId = -1u;
}
void CSimpleModel::SetCameraByID(uint32_t id) {
// TODO
}
void CSimpleModel::SetCameraByIndex(uint32_t index) {
if (!this->m_model || !this->m_model->IsLoaded(0, 0)) {
this->m_pendingCameraIndex = index;
return;
}
if (!this->m_model->m_loaded) {
this->m_model->WaitForLoad(nullptr);
}
if (index >= this->m_model->m_shared->m_data->cameras.Count()) {
if (this->m_camera) {
HandleClose(this->m_camera);
}
this->m_camera = nullptr;
this->m_pendingCameraIndex = -1u;
this->m_pendingCameraId = -1u;
return;
}
HCAMERA camera = this->m_model->GetCameraByIndex(index);
this->SetCamera(camera);
}
void CSimpleModel::SetFogColor(CImVector& fogColor) {
this->m_fogColor = fogColor;
this->m_flags |= 0x1;
}
void CSimpleModel::SetFogFar(float fogFar) {
this->m_fogFar = fogFar;
}
void CSimpleModel::SetFogNear(float fogNear) {
this->m_fogNear = fogNear;
}
void CSimpleModel::SetModel(const char* sourcefile) {
CM2Model* model = nullptr;
if (sourcefile && *sourcefile) {
if (!this->m_scene) {
this->m_scene = M2CreateScene();
}
model = this->m_scene->CreateModel(sourcefile, 1);
}
this->SetModel(model);
if (model) {
model->Release();
}
}
void CSimpleModel::SetModel(CM2Model* model) {
if (model) {
model->m_refCount++;
}
if (this->m_model) {
this->m_model->Release();
}
this->m_model = model;
if (model) {
// TODO
this->m_model->SetLightingCallback(&CSimpleModel::LightingCallback, this);
this->m_model->SetLoadedCallback(&CSimpleModel::ModelLoaded, this);
}
this->NotifyDrawLayerChanged(DRAWLAYER_ARTWORK);
}
void CSimpleModel::SetScale(float scale) {
this->m_scale = scale;
}
void CSimpleModel::SetSequence(uint32_t sequenceId) {
if (this->m_model) {
this->m_model->SetBoneSequence(-1, sequenceId, -1, 0, 1.0f, 0, 1);
}
}
int32_t CSimpleModel::SetSequenceTime(uint32_t sequence, int32_t time) {
if (this->m_model) {
this->m_model->SetBoneSequence(-1, sequence, -1, time, 1.0f, 0, 1);
}
return 1;
}
void CSimpleModel::UpdateModel() {
if (this->m_onUpdateModel.luaRef) {
this->RunScript(this->m_onUpdateModel, 0, nullptr);
}
C3Vector position = {
this->m_position.x * this->m_layoutScale,
this->m_position.y * this->m_layoutScale,
this->m_position.z * this->m_layoutScale
};
float scale = NDCToDDCHeight(1.0f) * 1.6666666 * (this->m_scale * this->m_layoutScale);
this->m_model->SetWorldTransform(position, this->m_facing, scale);
}

71
src/ui/CSimpleModel.hpp Normal file
View file

@ -0,0 +1,71 @@
#ifndef C_SIMPLE_MODEL_HPP
#define C_SIMPLE_MODEL_HPP
#include "gx/Camera.hpp"
#include "ui/CSimpleFrame.hpp"
#include "model/Model2.hpp"
#include <tempest/Vector.hpp>
#include <tempest/Box.hpp>
class CStatus;
class XMLNode;
class CSimpleModel : public CSimpleFrame {
public:
// Static variables
static int32_t s_metatable;
static int32_t s_objectType;
// Static functions
static void CreateScriptMetaTable(void);
static int32_t GetObjectType(void);
static void LightingCallback(CM2Model* model, CM2Lighting* lighting, void* userArg);
static void ModelLoaded(CM2Model* model, void* arg);
static void RegisterScriptMethods(lua_State*);
static void RenderModel(void* arg);
// Member variables
CM2Scene* m_scene = nullptr;
CM2Model* m_model = nullptr;
HCAMERA m_camera = nullptr;
uint32_t m_pendingCameraIndex = 0;
uint32_t m_pendingCameraId = 0;
CM2Light m_light;
C3Vector m_position;
float m_facing = 0.0f;
float m_scale = 1.0f;
uint32_t m_flags = 0;
CImVector m_fogColor = { 0 };
float m_fogNear = 0.0f;
float m_fogFar = 1.0f;
CAaBox m_bounds;
ScriptIx m_onUpdateModel;
ScriptIx m_onAnimFinished;
// Virtual member functions
virtual ScriptIx* GetScriptByName(const char* name, ScriptData& data);
virtual bool IsA(int32_t type);
virtual int32_t GetScriptMetaTable(void);
virtual void LoadXML(XMLNode*, CStatus*);
virtual void OnLayerUpdate(float elapsedSec);
virtual void OnFrameRender(CRenderBatch*, uint32_t);
virtual void UpdateModel(void);
virtual void OnModelLoaded(CM2Model* model);
// Member functions
CSimpleModel(CSimpleFrame*);
CM2Scene* GetScene(void);
void SetCamera(HCAMERA camera);
void SetCameraByID(uint32_t id);
void SetCameraByIndex(uint32_t index);
void SetFogColor(CImVector&);
void SetFogFar(float);
void SetFogNear(float);
void SetModel(const char*);
void SetModel(CM2Model*);
void SetScale(float);
void SetSequence(uint32_t sequence);
int32_t SetSequenceTime(uint32_t sequence, int32_t time);
};
#endif

View file

@ -0,0 +1,64 @@
#include "ui/CSimpleModelFFX.hpp"
#include "gx/Draw.hpp"
#include "ui/CRenderBatch.hpp"
#include "ui/CSimpleModelFFXScript.hpp"
#include <storm/Memory.hpp>
int32_t CSimpleModelFFX::s_metatable;
CSimpleFrame* CSimpleModelFFX::Create(CSimpleFrame* parent) {
// TODO
// void* m = CDataAllocator::GetData(CSimpleModelFFX::s_simpleModelFFXHeap, 0, __FILE__, __LINE__);
void* m = SMemAlloc(sizeof(CSimpleModelFFX), __FILE__, __LINE__, 0);
if (m) {
return new (m) CSimpleModelFFX(parent);
} else {
return nullptr;
}
}
void CSimpleModelFFX::Render(void* arg) {
CSimpleModelFFX* simpleModel = static_cast<CSimpleModelFFX*>(arg);
CImVector clearColor = { 0x00, 0x00, 0x00, 0xFF };
GxSceneClear(0x1 | 0x2, clearColor);
// TODO
GxSceneClear(0x1 | 0x2, clearColor);
if (simpleModel->m_model) {
CSimpleModel::RenderModel(simpleModel);
}
// TODO
}
void CSimpleModelFFX::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleModelFFX::RegisterScriptMethods);
CSimpleModelFFX::s_metatable = ref;
}
void CSimpleModelFFX::RegisterScriptMethods(lua_State* L) {
CSimpleModel::RegisterScriptMethods(L);
FrameScript_Object::FillScriptMethodTable(L, SimpleModelFFXMethods, NUM_SIMPLE_MODEL_FFX_SCRIPT_METHODS);
}
CSimpleModelFFX::CSimpleModelFFX(CSimpleFrame* parent) : CSimpleModel(parent) {
// TODO
}
int32_t CSimpleModelFFX::GetScriptMetaTable() {
return CSimpleModelFFX::s_metatable;
}
void CSimpleModelFFX::OnFrameRender(CRenderBatch* batch, uint32_t layer) {
CSimpleFrame::OnFrameRender(batch, layer);
if (layer == DRAWLAYER_ARTWORK) {
batch->QueueCallback(CSimpleModelFFX::Render, this);
}
}

View file

@ -0,0 +1,27 @@
#ifndef UI_C_SIMPLE_MODEL_FFX_HPP
#define UI_C_SIMPLE_MODEL_FFX_HPP
#include "ui/CSimpleModel.hpp"
class CSimpleFrame;
class CSimpleModelFFX : public CSimpleModel {
public:
// Static variables
static int32_t s_metatable;
// Static functions
static CSimpleFrame* Create(CSimpleFrame*);
static void CreateScriptMetaTable(void);
static void RegisterScriptMethods(lua_State*);
static void Render(void*);
// Virtual member functions
virtual int32_t GetScriptMetaTable(void);
virtual void OnFrameRender(CRenderBatch*, uint32_t);
// Member functions
CSimpleModelFFX(CSimpleFrame*);
};
#endif

View file

@ -0,0 +1,26 @@
#include "ui/CSimpleModelFFXScript.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleModelFFX_ResetLights(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModelFFX_AddLight(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModelFFX_AddCharacterLight(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModelFFX_AddPetLight(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleModelFFXMethods[NUM_SIMPLE_MODEL_FFX_SCRIPT_METHODS] = {
{ "ResetLights", &CSimpleModelFFX_ResetLights },
{ "AddLight", &CSimpleModelFFX_AddLight },
{ "AddCharacterLight", &CSimpleModelFFX_AddCharacterLight },
{ "AddPetLight", &CSimpleModelFFX_AddPetLight }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_MODEL_FFX_SCRIPT_HPP
#define UI_C_SIMPLE_MODEL_FFX_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_MODEL_FFX_SCRIPT_METHODS 4
extern FrameScript_Method SimpleModelFFXMethods[NUM_SIMPLE_MODEL_FFX_SCRIPT_METHODS];
#endif

View file

@ -0,0 +1,189 @@
#include "ui/CSimpleModelScript.hpp"
#include "ui/CSimpleModel.hpp"
#include "util/Lua.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleModel_SetModel(lua_State* L) {
auto type = CSimpleModel::GetObjectType();
auto model = static_cast<CSimpleModel*>(FrameScript_GetObjectThis(L, type));
if (!lua_isstring(L, 2)) {
return luaL_error(L, "Usage: %s:SetModel(\"file\")", model->GetDisplayName());
}
const char* file = lua_tolstring(L, 2, 0);
model->SetModel(file);
if (!model->m_model) {
return luaL_error(L, "Invalid model file: %s", file);
}
return 0;
}
int32_t CSimpleModel_GetModel(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_ClearModel(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_SetPosition(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_SetFacing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_SetScale(lua_State* L) {
auto type = CSimpleModel::GetObjectType();
auto model = static_cast<CSimpleModel*>(FrameScript_GetObjectThis(L, type));
if (!lua_isnumber(L, 2)) {
return luaL_error(L, "Usage: %s:SetScale(scale)", model->GetDisplayName());
}
float scale = lua_tonumber(L, 2);
model->SetScale(scale);
return 0;
}
int32_t CSimpleModel_SetSequence(lua_State* L) {
auto type = CSimpleModel::GetObjectType();
auto model = static_cast<CSimpleModel*>(FrameScript_GetObjectThis(L, type));
if (!lua_isnumber(L, 2)) {
return luaL_error(L, "Usage: %s:SetSequence(sequence)", model->GetDisplayName());
}
uint32_t sequence = lua_tonumber(L, 2);
if (sequence >= 506) {
return luaL_error(L, "Error: %s:SetSequence(sequence) exceeds valid range of 0 - %d", model->GetDisplayName(), 506);
}
model->SetSequence(sequence);
return 0;
}
int32_t CSimpleModel_SetSequenceTime(lua_State* L) {
auto type = CSimpleModel::GetObjectType();
auto model = static_cast<CSimpleModel*>(FrameScript_GetObjectThis(L, type));
if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3)) {
return luaL_error(L, "Usage: %s:SetSequenceTime(sequence, time)", model->GetDisplayName());
}
uint32_t sequence = lua_tonumber(L, 2);
int32_t time = lua_tonumber(L, 3);
model->SetSequenceTime(sequence, time);
return 0;
}
int32_t CSimpleModel_SetCamera(lua_State* L) {
auto type = CSimpleModel::GetObjectType();
auto model = static_cast<CSimpleModel*>(FrameScript_GetObjectThis(L, type));
if (!lua_isnumber(L, 2)) {
return luaL_error(L, "Usage: %s:SetCamera(index)", model->GetDisplayName());
}
int32_t index = lua_tonumber(L, 2);
model->SetCameraByIndex(index);
return 0;
}
int32_t CSimpleModel_SetLight(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_GetLight(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_GetPosition(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_GetFacing(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_GetScale(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_AdvanceTime(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_ReplaceIconTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_SetFogColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_GetFogColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_SetFogNear(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_GetFogNear(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_SetFogFar(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_GetFogFar(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_ClearFog(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleModel_SetGlow(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleModelMethods[NUM_SIMPLE_MODEL_SCRIPT_METHODS] = {
{ "SetModel", &CSimpleModel_SetModel },
{ "GetModel", &CSimpleModel_GetModel },
{ "ClearModel", &CSimpleModel_ClearModel },
{ "SetPosition", &CSimpleModel_SetPosition },
{ "SetFacing", &CSimpleModel_SetFacing },
{ "SetModelScale", &CSimpleModel_SetScale },
{ "SetSequence", &CSimpleModel_SetSequence },
{ "SetSequenceTime", &CSimpleModel_SetSequenceTime },
{ "SetCamera", &CSimpleModel_SetCamera },
{ "SetLight", &CSimpleModel_SetLight },
{ "GetLight", &CSimpleModel_GetLight },
{ "GetPosition", &CSimpleModel_GetPosition },
{ "GetFacing", &CSimpleModel_GetFacing },
{ "GetModelScale", &CSimpleModel_GetScale },
{ "AdvanceTime", &CSimpleModel_AdvanceTime },
{ "ReplaceIconTexture", &CSimpleModel_ReplaceIconTexture },
{ "SetFogColor", &CSimpleModel_SetFogColor },
{ "GetFogColor", &CSimpleModel_GetFogColor },
{ "SetFogNear", &CSimpleModel_SetFogNear },
{ "GetFogNear", &CSimpleModel_GetFogNear },
{ "SetFogFar", &CSimpleModel_SetFogFar },
{ "GetFogFar", &CSimpleModel_GetFogFar },
{ "ClearFog", &CSimpleModel_ClearFog },
{ "SetGlow", &CSimpleModel_SetGlow }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_MODEL_SCRIPT_HPP
#define UI_C_SIMPLE_MODEL_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_MODEL_SCRIPT_METHODS 24
extern FrameScript_Method SimpleModelMethods[NUM_SIMPLE_MODEL_SCRIPT_METHODS];
#endif

162
src/ui/CSimpleRegion.cpp Normal file
View file

@ -0,0 +1,162 @@
#include "ui/CSimpleRegion.hpp"
#include "ui/CSimpleFrame.hpp"
#include <cstring>
CSimpleRegion::~CSimpleRegion() {
this->SetFrame(nullptr, DRAWLAYER_BACKGROUND_BORDER, 0);
}
CSimpleRegion::CSimpleRegion(CSimpleFrame* frame, uint32_t drawlayer, int32_t show) : CScriptRegion() {
memset(this->m_color, 0, sizeof(CImVector) * this->m_colorCount);
this->m_colorCount = 0;
memset(this->m_alpha, 0, sizeof(uint8_t) * this->m_alphaCount);
this->m_alphaCount = 0;
if (frame) {
this->SetFrame(frame, drawlayer, show);
}
}
void CSimpleRegion::GetVertexColor(CImVector& color) const {
if (this->m_colorCount == 1) {
color.a = this->m_alpha[0];
color.r = this->m_color[0].r;
color.g = this->m_color[0].g;
color.b = this->m_color[0].b;
} else {
color = { 0xFF, 0xFF, 0xFF, 0xFF };
}
}
void CSimpleRegion::Hide() {
this->m_shown = 0;
this->HideThis();
}
void CSimpleRegion::HideThis() {
if (this->m_visible && this->m_parent) {
if (!this->m_parent->m_loading) {
this->SetDeferredResize(1);
}
this->m_parent->RemoveFrameRegion(this, this->m_drawlayer);
this->m_visible = 0;
}
}
bool CSimpleRegion::IsShown() {
return this->m_shown == 1;
}
void CSimpleRegion::OnColorChanged(bool a2) {
if (this->m_parent) {
// TODO adjust color based on parent
}
if (a2) {
this->OnRegionChanged();
}
}
void CSimpleRegion::OnRegionChanged() {
if (this->m_visible && this->m_parent) {
this->m_parent->NotifyDrawLayerChanged(this->m_drawlayer);
}
}
void CSimpleRegion::SetVertexColor(const CImVector& color) {
if (
this->m_colorCount == 0
&& color.a >= 0xFE
&& color.r == 0xFF
&& color.g == 0xFF
&& color.b == 0xFF
) {
return;
}
if (
this->m_colorCount == 1
&& this->m_alpha[0] == color.a
&& this->m_color[0].r == color.r
&& this->m_color[0].g == color.g
&& this->m_color[0].b == color.b
) {
return;
}
bool b1 = false;
if (this->m_colorCount != 1) {
this->m_colorCount = 1;
this->m_alphaCount = 1;
b1 = true;
}
this->m_color[0] = color;
this->m_alpha[0] = color.a;
this->OnColorChanged(b1);
}
void CSimpleRegion::SetFrame(CSimpleFrame* frame, uint32_t drawlayer, int32_t show) {
if (this->m_parent == frame) {
if (this->m_drawlayer == drawlayer) {
if (show != this->m_shown) {
if (show) {
this->Show();
} else {
this->Hide();
}
}
} else {
if (this->m_shown) {
this->Hide();
}
this->m_drawlayer = drawlayer;
if (show) {
this->Show();
}
}
} else {
if (this->m_parent) {
this->HideThis();
this->m_parent->UnregisterRegion(this);
}
this->m_parent = frame;
this->m_drawlayer = drawlayer;
if (frame) {
frame->RegisterRegion(this);
this->SetDeferredResize(static_cast<CLayoutFrame*>(this->m_parent)->m_flags & 0x2);
this->OnColorChanged(0);
if (show) {
this->Show();
} else {
this->Hide();
}
}
}
}
void CSimpleRegion::Show() {
this->m_shown = 1;
this->ShowThis();
}
void CSimpleRegion::ShowThis() {
if (this->m_shown && this->m_parent && this->m_parent->m_visible && !this->m_visible) {
if (!this->m_parent->m_loading) {
this->SetDeferredResize(0);
}
this->m_parent->AddFrameRegion(this, this->m_drawlayer);
this->m_visible = 1;
}
}

42
src/ui/CSimpleRegion.hpp Normal file
View file

@ -0,0 +1,42 @@
#ifndef UI_C_SIMPLE_REGION_HPP
#define UI_C_SIMPLE_REGION_HPP
#include "ui/CScriptRegion.hpp"
#include <storm/List.hpp>
#include <tempest/Vector.hpp>
class CRenderBatch;
class CSimpleRegion : public CScriptRegion {
public:
// Member variables
uint32_t m_alphaCount = 4;
uint8_t m_alpha[4];
uint32_t m_colorCount = 4;
CImVector m_color[4];
TSLink<CSimpleRegion> m_regionLink;
TSLink<CSimpleRegion> m_layerLink;
int32_t m_drawlayer = 0;
int32_t m_shown = 0;
int32_t m_visible = 0;
// Virtual member functions
virtual ~CSimpleRegion();
virtual void OnColorChanged(bool);
virtual void OnScreenSizeChanged() {};
virtual void Draw(CRenderBatch*) = 0;
// Member functions
CSimpleRegion(CSimpleFrame*, uint32_t, int32_t);
void GetVertexColor(CImVector& color) const;
void Hide(void);
void HideThis(void);
bool IsShown();
void OnRegionChanged(void);
void SetVertexColor(const CImVector&);
void SetFrame(CSimpleFrame*, uint32_t, int32_t);
void Show(void);
void ShowThis(void);
};
#endif

168
src/ui/CSimpleRender.cpp Normal file
View file

@ -0,0 +1,168 @@
#include "ui/CSimpleRender.hpp"
#include "gx/Buffer.hpp"
#include "gx/Device.hpp"
#include "gx/Draw.hpp"
#include "gx/Font.hpp"
#include "gx/Gx.hpp"
#include "gx/RenderState.hpp"
#include "gx/Shader.hpp"
#include "gx/Texture.hpp"
#include "gx/Transform.hpp"
#include "gx/Types.hpp"
#include "ui/CRenderBatch.hpp"
CGxShader* CSimpleRender::s_vertexShader[2];
void CSimpleRender::DrawBatch(CRenderBatch* batch) {
if (batch->m_texturelist.Count()) {
GxRsPush();
CGxShader* vs = g_theGxDevicePtr->StereoEnabled()
? CSimpleRender::s_vertexShader[1]
: CSimpleRender::s_vertexShader[0];
if (vs && vs->Valid()) {
GxRsSet(GxRs_VertexShader, vs);
C44Matrix viewProjMat;
GxXformViewProjNativeTranspose(viewProjMat);
GxShaderConstantsSet(GxSh_Vertex, 0, reinterpret_cast<float*>(&viewProjMat), 4);
} else {
GxRsSet(GxRs_Lighting, 0);
}
GxRsSet(GxRs_Fog, 0);
GxRsSet(GxRs_DepthTest, 0);
GxRsSet(GxRs_DepthWrite, 0);
CGxTex* textureID = nullptr;
EGxBlend alphaMode = GxBlends_Last;
CGxShader* ps = nullptr;
uint32_t idxCount = 0;
uint32_t posCount = 0;
for (int32_t i = 0; i < batch->m_texturelist.Count(); i++) {
auto mesh = &batch->m_texturelist[i];
auto dirty = 0;
if (mesh->textureID != textureID) {
textureID = mesh->textureID;
dirty = 1;
}
if (mesh->GetAlphaMode() != alphaMode) {
alphaMode = mesh->GetAlphaMode();
dirty = 1;
}
if (mesh->shader != ps) {
ps = mesh->shader;
dirty = 1;
}
CTexture* texture = mesh->texture;
CGxTex* gxTex = TextureGetGxTex(texture, 1, nullptr);
GxRsSet(GxRs_Texture0, gxTex);
GxRsSet(GxRs_BlendingMode, alphaMode);
GxRsSet(GxRs_PixelShader, ps);
// TODO
// - alphaRef
// TODO
// - geometry merging (CSimpleRender::s_mergeEnable)
posCount = mesh->posCount;
idxCount = mesh->idxCount;
CGxBuf* vertexStream = g_theGxDevicePtr->BufStream(GxPoolTarget_Vertex, 24, posCount);
char* vertexData = g_theGxDevicePtr->BufLock(vertexStream);
CGxVertexPCT* vertexBuf = reinterpret_cast<CGxVertexPCT*>(vertexData);
CGxBuf* indexStream = g_theGxDevicePtr->BufStream(GxPoolTarget_Index, 2, idxCount);
char* indexData = g_theGxDevicePtr->BufLock(indexStream);
uint16_t* indexBuf = reinterpret_cast<uint16_t*>(indexData);
if (mesh->indices) {
for (int32_t i = 0; i < mesh->posCount; i++) {
C3Vector* p = &mesh->position[i];
vertexBuf->p.x = p->x;
vertexBuf->p.y = p->y;
vertexBuf->p.z = p->z;
if (mesh->color) {
auto& color = mesh->color[i * mesh->colorCount >> 2];
if (GxCaps()->m_colorFormat == GxCF_rgba) {
vertexBuf->c.r = color.b;
vertexBuf->c.g = color.g;
vertexBuf->c.b = color.r;
vertexBuf->c.a = color.a;
} else {
vertexBuf->c = color;
}
} else {
vertexBuf->c.r = 0xFF;
vertexBuf->c.g = 0xFF;
vertexBuf->c.b = 0xFF;
vertexBuf->c.a = 0xFF;
}
if (mesh->onAtlas) {
// TODO
} else {
C2Vector* tc = &mesh->texCoord[i];
vertexBuf->tc[0].x = tc->x;
vertexBuf->tc[0].y = tc->y;
}
vertexBuf++;
}
for (int32_t i = 0; i < mesh->idxCount; i++) {
*indexBuf = mesh->indices[i];
indexBuf++;
}
}
GxBufUnlock(vertexStream, 24 * posCount);
GxBufUnlock(indexStream, 2 * idxCount);
GxPrimVertexPtr(vertexStream, GxVBF_PCT);
GxPrimIndexPtr(indexStream);
CGxBatch batch;
batch.m_primType = GxPrim_Triangles;
batch.m_start = 0;
batch.m_count = 6;
batch.m_minIndex = 0;
batch.m_maxIndex = 3;
GxDraw(&batch, 1);
}
GxRsPop();
}
if (batch->m_stringbatch) {
GxuFontRenderBatch(batch->m_stringbatch);
}
for (auto callback = batch->m_callbacks.Head(); callback; callback = batch->m_callbacks.Link(callback)->Next()) {
callback->callback(callback->param);
}
}
void CSimpleRender::Init() {
g_theGxDevicePtr->ShaderCreate(
CSimpleRender::s_vertexShader,
GxSh_Vertex,
"Shaders\\Vertex",
"UI",
2
);
}

17
src/ui/CSimpleRender.hpp Normal file
View file

@ -0,0 +1,17 @@
#ifndef UI_C_SIMPLE_RENDER_HPP
#define UI_C_SIMPLE_RENDER_HPP
class CGxShader;
class CRenderBatch;
class CSimpleRender {
public:
// Static variables
static CGxShader* s_vertexShader[];
// Static functions
static void DrawBatch(CRenderBatch*);
static void Init(void);
};
#endif

View file

@ -0,0 +1,410 @@
#include "ui/CSimpleScrollFrame.hpp"
#include "gx/Camera.hpp"
#include "gx/Coordinate.hpp"
#include "gx/Transform.hpp"
#include "ui/CRenderBatch.hpp"
#include "ui/CSimpleScrollFrameScript.hpp"
#include "ui/FrameXML.hpp"
#include "util/CStatus.hpp"
#include "util/Lua.hpp"
#include <cmath>
#include <limits>
#include <common/XML.hpp>
#include <tempest/Matrix.hpp>
int32_t CSimpleScrollFrame::s_metatable;
int32_t CSimpleScrollFrame::s_objectType;
void CSimpleScrollFrame::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleScrollFrame::RegisterScriptMethods);
CSimpleScrollFrame::s_metatable = ref;
}
int32_t CSimpleScrollFrame::GetObjectType() {
if (!CSimpleScrollFrame::s_objectType) {
CSimpleScrollFrame::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CSimpleScrollFrame::s_objectType;
}
void CSimpleScrollFrame::RegisterScriptMethods(lua_State* L) {
CSimpleFrame::RegisterScriptMethods(L);
FrameScript_Object::FillScriptMethodTable(L, SimpleScrollFrameMethods, NUM_SIMPLE_SCROLL_FRAME_SCRIPT_METHODS);
}
void CSimpleScrollFrame::RenderScrollChild(void* param) {
auto frame = static_cast<CSimpleScrollFrame*>(param);
CRect viewRect;
if (!frame->GetHitRect(viewRect)) {
return;
}
auto scrollChild = frame->m_scrollChild;
if (!scrollChild) {
return;
}
if (!scrollChild->m_visible) {
return;
}
C44Matrix savedProj;
GxXformProjection(savedProj);
C44Matrix savedView;
GxXformView(savedView);
float minX, maxX, minY, maxY, minZ, maxZ;
GxXformViewport(minX, maxX, minY, maxY, minZ, maxZ);
// TODO clean up
float v34 = 0.0f;
float v35 = 0.0f;
float v36 = 0.0f;
float v37 = 0.0f;
NDCToDDC(minX, minY, &v35, &v34);
NDCToDDC(maxX, maxY, &v37, &v36);
auto v4 = viewRect.minX;
if (v35 > viewRect.minX) {
v4 = v35;
viewRect.minX = v35;
}
auto v5 = viewRect.maxX;
if (v37 < viewRect.maxX) {
v5 = v37;
viewRect.maxX = v37;
}
auto v6 = viewRect.minY;
if (v34 > viewRect.minY) {
v6 = v34;
viewRect.minY = v34;
}
auto v7 = viewRect.maxY;
if (v36 < viewRect.maxY) {
v7 = v36;
viewRect.maxY = v36;
}
if (v4 != v5 && v6 != v7) {
C2Vector screenPoint = { 0.0f, 0.0f };
CameraSetupScreenProjection(viewRect, screenPoint, 0.0f, 0);
DDCToNDC(viewRect.minX, viewRect.minY, &viewRect.minX, &viewRect.minY);
DDCToNDC(viewRect.maxX, viewRect.maxY, &viewRect.maxX, &viewRect.maxY);
float v11, v12, v13, v14;
if (viewRect.minX >= 0.0f) {
v12 = viewRect.minX;
v11 = viewRect.maxX;
} else {
v11 = viewRect.maxX - viewRect.minX;
viewRect.maxX = v11;
v12 = 0.0f;
viewRect.minX = 0.0f;
}
if (v11 > 1.0f) {
v12 = v12 - (v11 - 1.0f);
viewRect.minX = v12;
viewRect.maxX = 1.0f;
v11 = 1.0f;
}
if (viewRect.minY >= 0.0f) {
v14 = viewRect.minY;
v13 = viewRect.maxY;
} else {
v13 = viewRect.maxY - viewRect.minY;
viewRect.maxY = v13;
v14 = 0.0f;
viewRect.minY = 0.0f;
}
float v15 = v14;
float v16 = v13;
float v17 = v15;
if (v16 > 1.0f) {
v17 = v17 - (v16 - 1.0f);
viewRect.minY = v17;
v16 = 1.0f;
viewRect.maxY = 1.0f;
}
float v18 = v16;
float v19 = v12;
float v20 = v18;
if (v19 < v11) {
float v21 = v19;
float v22 = v17;
float v23 = v21;
if (v22 < v20) {
float v27 = v20;
float v26 = v22;
float v25 = v11;
float v24 = v23;
GxXformSetViewport(v24, v25, v26, v27, 0.0f, 1.0f);
scrollChild->OnFrameRender();
}
}
GxXformSetProjection(savedProj);
GxXformSetView(savedView);
GxXformSetViewport(minX, maxX, minY, maxY, minZ, maxZ);
}
}
CSimpleScrollFrame::CSimpleScrollFrame(CSimpleFrame* parent) : CSimpleFrame(parent) {
// TODO
}
int32_t CSimpleScrollFrame::GetBoundsRect(CRect& bounds) {
if (this->IsResizePending()) {
this->Resize(1);
}
CRect rect = { 0.0f, 0.0f, 0.0f, 0.0f };
if (this->GetRect(&rect)) {
bounds.minX = rect.minX >= bounds.minX ? bounds.minX : rect.minX;
bounds.maxX = rect.maxX <= bounds.maxX ? bounds.maxX : rect.maxX;
bounds.minY = rect.minY >= bounds.minY ? bounds.minY : rect.minY;
bounds.maxY = rect.maxY <= bounds.maxY ? bounds.maxY : rect.maxY;
}
for (auto region = this->m_regions.Head(); region; region = this->m_regions.Next(region)) {
if (region->IsShown()) {
if (region->IsResizePending()) {
region->Resize(1);
}
if (region->GetRect(&rect)) {
bounds.minX = rect.minX >= bounds.minX ? bounds.minX : rect.minX;
bounds.maxX = rect.maxX <= bounds.maxX ? bounds.maxX : rect.maxX;
bounds.minY = rect.minY >= bounds.minY ? bounds.minY : rect.minY;
bounds.maxY = rect.maxY <= bounds.maxY ? bounds.maxY : rect.maxY;
}
}
}
for (auto child = this->m_children.Head(); child; child = this->m_children.Next(child)) {
if (child->frame != this->m_scrollChild && child->frame->m_shown) {
child->frame->GetBoundsRect(bounds);
}
}
return bounds.maxY > bounds.minY && bounds.maxX > bounds.minX;
}
FrameScript_Object::ScriptIx* CSimpleScrollFrame::GetScriptByName(const char* name, ScriptData& data) {
auto parentScript = CSimpleFrame::GetScriptByName(name, data);
if (parentScript) {
return parentScript;
}
if (!SStrCmpI(name, "OnHorizontalScroll", STORM_MAX_STR)) {
data.wrapper = "return function(self,offset) %s end";
return &this->m_onHorizontalScroll;
}
if (!SStrCmpI(name, "OnVerticalScroll", STORM_MAX_STR)) {
data.wrapper = "return function(self,offset) %s end";
return &this->m_onVerticalScroll;
}
if (!SStrCmpI(name, "OnScrollRangeChanged", STORM_MAX_STR)) {
data.wrapper = "return function(self,xrange,yrange) %s end";
return &this->m_onScrollRangeChanged;
}
return nullptr;
}
int32_t CSimpleScrollFrame::GetScriptMetaTable() {
return CSimpleScrollFrame::s_metatable;
}
bool CSimpleScrollFrame::IsA(int32_t type) {
return type == CSimpleScrollFrame::s_objectType
|| type == CSimpleFrame::s_objectType
|| type == CScriptRegion::s_objectType
|| type == CScriptObject::s_objectType;
}
void CSimpleScrollFrame::LoadXML(XMLNode* node, CStatus* status) {
CSimpleFrame::LoadXML(node, status);
XMLNode* scrollChildNode = node->GetChildByName("ScrollChild");
if (scrollChildNode) {
XMLNode* childNode = scrollChildNode->m_child;
if (childNode) {
CSimpleFrame* childFrame = FrameXML_CreateFrame(childNode, this, status);
if (childFrame) {
this->SetScrollChild(childFrame);
}
} else {
const char* frameName = this->GetName();
if (!frameName) {
frameName = "<unnamed>";
}
status->Add(
STATUS_WARNING,
"Frame %s: Scroll frame created without scroll child",
frameName
);
}
}
}
void CSimpleScrollFrame::OnFrameRender(CRenderBatch* batch, uint32_t layer) {
CSimpleFrame::OnFrameRender(batch, layer);
if (layer == DRAWLAYER_HIGHLIGHT) {
batch->QueueCallback(CSimpleScrollFrame::RenderScrollChild, this);
}
}
void CSimpleScrollFrame::OnFrameSizeChanged(float w, float h) {
CSimpleFrame::OnFrameSizeChanged(w, h);
this->m_updateScrollChild = 1;
}
void CSimpleScrollFrame::OnLayerUpdate(float elapsedSec) {
CSimpleFrame::OnLayerUpdate(elapsedSec);
if (this->m_updateScrollChild) {
CRect rect = { 0.0f, 0.0f, 0.0f, 0.0f };
if (this->GetRect(&rect)) {
float w = rect.maxX - rect.minX;
float h = rect.maxY - rect.minY;
this->UpdateScrollChildRect(w, h);
}
this->m_updateScrollChild = 0;
}
}
void CSimpleScrollFrame::RunOnScrollRangeChangedScript() {
if (!this->m_onScrollRangeChanged.luaRef) {
return;
}
auto L = FrameScript_GetContext();
auto rangeX = this->m_scrollRange.x;
auto ddcRangeX = CoordinateGetAspectCompensation() * 1024.0f * rangeX;
auto ndcRangeX = DDCToNDCWidth(ddcRangeX);
lua_pushnumber(L, ndcRangeX);
auto rangeY = this->m_scrollRange.y;
auto ddcRangeY = CoordinateGetAspectCompensation() * 1024.0f * rangeY;
auto ndcRangeY = DDCToNDCWidth(ddcRangeY);
lua_pushnumber(L, ndcRangeY);
this->RunScript(this->m_onScrollRangeChanged, 2, nullptr);
}
void CSimpleScrollFrame::RunOnVerticalScrollScript() {
if (!this->m_onVerticalScroll.luaRef) {
return;
}
auto L = FrameScript_GetContext();
auto offsetY = this->m_scrollOffset.y;
auto ddcOffsetY = CoordinateGetAspectCompensation() * 1024.0f * offsetY;
auto ndcOffsetY = DDCToNDCWidth(ddcOffsetY);
lua_pushnumber(L, ndcOffsetY);
this->RunScript(this->m_onVerticalScroll, 1, nullptr);
}
void CSimpleScrollFrame::SetScrollChild(CSimpleFrame* frame) {
if (this->m_scrollChild) {
this->m_scrollChild->SetBeingScrolled(0, 0);
this->m_scrollChild->SetParent(nullptr);
}
this->m_scrollChild = frame;
if (this->m_scrollChild) {
this->m_scrollChild->SetParent(this);
this->m_scrollChild->SetBeingScrolled(1, 1);
}
this->UpdateScrollChild();
this->m_updateScrollChild = 1;
}
void CSimpleScrollFrame::SetVerticalScroll(float offset) {
if (fabs(offset - this->m_scrollOffset.y) >= 0.00000095367432) {
this->m_scrollOffset.y = offset;
this->UpdateScrollChild();
this->RunOnVerticalScrollScript();
}
}
void CSimpleScrollFrame::UpdateScrollChild() {
if (!this->m_scrollChild) {
return;
}
this->m_scrollChild->ClearAllPoints();
this->m_scrollChild->SetPoint(
FRAMEPOINT_TOPLEFT,
this,
FRAMEPOINT_TOPLEFT,
-this->m_scrollOffset.x,
this->m_scrollOffset.y,
1
);
}
void CSimpleScrollFrame::UpdateScrollChildRect(float w, float h) {
if (!this->m_scrollChild) {
return;
}
float rangeX = this->m_scrollRange.x;
float rangeY = this->m_scrollRange.y;
CRect childBounds = {
std::numeric_limits<float>::max(),
std::numeric_limits<float>::max(),
0.0f,
0.0f
};
this->m_scrollChild->GetBoundsRect(childBounds);
auto ooScale = 1.0f / this->m_layoutScale;
auto v7 = std::max(childBounds.maxX - childBounds.minX - w, 0.0f);
this->m_scrollRange.x = v7 * ooScale;
auto v12 = std::max(childBounds.maxY - childBounds.minY - h, 0.0f);
this->m_scrollRange.y = v12 * ooScale;
if (
fabs(this->m_scrollRange.x - rangeX) >= 0.00000095367432
|| fabs(this->m_scrollRange.y - rangeY) >= 0.00000095367432
) {
this->RunOnScrollRangeChangedScript();
}
}

View file

@ -0,0 +1,51 @@
#ifndef UI_C_SIMPLE_SCROLL_FRAME_HPP
#define UI_C_SIMPLE_SCROLL_FRAME_HPP
#include "ui/CSimpleFrame.hpp"
#include <tempest/Vector.hpp>
class CRect;
class CRenderBatch;
class CSimpleScrollFrame : public CSimpleFrame {
public:
// Static variables
static int32_t s_metatable;
static int32_t s_objectType;
// Static functions
static void CreateScriptMetaTable(void);
static int32_t GetObjectType(void);
static void RegisterScriptMethods(lua_State*);
static void RenderScrollChild(void* param);
// Member variables
int32_t m_updateScrollChild = 0;
CSimpleFrame* m_scrollChild = nullptr;
C2Vector m_scrollRange;
C2Vector m_scrollOffset;
ScriptIx m_onHorizontalScroll;
ScriptIx m_onVerticalScroll;
ScriptIx m_onScrollRangeChanged;
// Virtual member functions
virtual ScriptIx* GetScriptByName(const char*, ScriptData&);
virtual bool IsA(int32_t);
virtual int32_t GetScriptMetaTable(void);
virtual void LoadXML(XMLNode*, CStatus*);
virtual int32_t GetBoundsRect(CRect& bounds);
virtual void OnLayerUpdate(float elapsedSec);
virtual void OnFrameRender(CRenderBatch* batch, uint32_t layer);
virtual void OnFrameSizeChanged(float w, float h);
// Member functions
CSimpleScrollFrame(CSimpleFrame*);
void RunOnScrollRangeChangedScript();
void RunOnVerticalScrollScript();
void SetScrollChild(CSimpleFrame*);
void SetVerticalScroll(float offset);
void UpdateScrollChild();
void UpdateScrollChildRect(float w, float h);
};
#endif

View file

@ -0,0 +1,105 @@
#include "ui/CSimpleScrollFrameScript.hpp"
#include "gx/Coordinate.hpp"
#include "ui/CSimpleScrollFrame.hpp"
#include "util/Lua.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleScrollFrame_SetScrollChild(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleScrollFrame_GetScrollChild(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleScrollFrame_SetHorizontalScroll(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleScrollFrame_SetVerticalScroll(lua_State* L) {
auto type = CSimpleScrollFrame::GetObjectType();
auto scrollFrame = static_cast<CSimpleScrollFrame*>(FrameScript_GetObjectThis(L, type));
if (!scrollFrame->ProtectedFunctionsAllowed()) {
// TODO handle check
return 0;
}
if (!lua_isnumber(L, 2)) {
luaL_error(L, "Usage: %s:SetVerticalScroll(offset)", scrollFrame->GetDisplayName());
}
float offset = lua_tonumber(L, 2);
float ndcOffset = offset / (CoordinateGetAspectCompensation() * 1024.0f);
float ddcOffset = NDCToDDCWidth(ndcOffset);
scrollFrame->SetVerticalScroll(ddcOffset);
return 0;
}
int32_t CSimpleScrollFrame_GetHorizontalScroll(lua_State* L) {
auto type = CSimpleScrollFrame::GetObjectType();
auto scrollFrame = static_cast<CSimpleScrollFrame*>(FrameScript_GetObjectThis(L, type));
float ddcOffset = CoordinateGetAspectCompensation() * 1024.0f * scrollFrame->m_scrollOffset.x;
float ndcOffset = DDCToNDCWidth(ddcOffset);
lua_pushnumber(L, ndcOffset);
return 1;
}
int32_t CSimpleScrollFrame_GetVerticalScroll(lua_State* L) {
auto type = CSimpleScrollFrame::GetObjectType();
auto scrollFrame = static_cast<CSimpleScrollFrame*>(FrameScript_GetObjectThis(L, type));
float ddcOffset = CoordinateGetAspectCompensation() * 1024.0f * scrollFrame->m_scrollOffset.y;
float ndcOffset = DDCToNDCWidth(ddcOffset);
lua_pushnumber(L, ndcOffset);
return 1;
}
int32_t CSimpleScrollFrame_GetHorizontalScrollRange(lua_State* L) {
auto type = CSimpleScrollFrame::GetObjectType();
auto scrollFrame = static_cast<CSimpleScrollFrame*>(FrameScript_GetObjectThis(L, type));
float ddcRange = CoordinateGetAspectCompensation() * 1024.0f * scrollFrame->m_scrollRange.x;
float ndcRange = DDCToNDCWidth(ddcRange);
lua_pushnumber(L, ndcRange);
return 1;
}
int32_t CSimpleScrollFrame_GetVerticalScrollRange(lua_State* L) {
auto type = CSimpleScrollFrame::GetObjectType();
auto scrollFrame = static_cast<CSimpleScrollFrame*>(FrameScript_GetObjectThis(L, type));
float ddcRange = CoordinateGetAspectCompensation() * 1024.0f * scrollFrame->m_scrollRange.y;
float ndcRange = DDCToNDCWidth(ddcRange);
lua_pushnumber(L, ndcRange);
return 1;
}
int32_t CSimpleScrollFrame_UpdateScrollChildRect(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleScrollFrameMethods[NUM_SIMPLE_SCROLL_FRAME_SCRIPT_METHODS] = {
{ "SetScrollChild", &CSimpleScrollFrame_SetScrollChild },
{ "GetScrollChild", &CSimpleScrollFrame_GetScrollChild },
{ "SetHorizontalScroll", &CSimpleScrollFrame_SetHorizontalScroll },
{ "SetVerticalScroll", &CSimpleScrollFrame_SetVerticalScroll },
{ "GetHorizontalScroll", &CSimpleScrollFrame_GetHorizontalScroll },
{ "GetVerticalScroll", &CSimpleScrollFrame_GetVerticalScroll },
{ "GetHorizontalScrollRange", &CSimpleScrollFrame_GetHorizontalScrollRange },
{ "GetVerticalScrollRange", &CSimpleScrollFrame_GetVerticalScrollRange },
{ "UpdateScrollChildRect", &CSimpleScrollFrame_UpdateScrollChildRect }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_SCROLL_FRAME_SCRIPT_HPP
#define UI_C_SIMPLE_SCROLL_FRAME_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_SCROLL_FRAME_SCRIPT_METHODS 9
extern FrameScript_Method SimpleScrollFrameMethods[NUM_SIMPLE_SCROLL_FRAME_SCRIPT_METHODS];
#endif

145
src/ui/CSimpleSlider.cpp Normal file
View file

@ -0,0 +1,145 @@
#include "ui/CSimpleSlider.hpp"
#include "math/Utils.hpp"
#include "ui/CSimpleSliderScript.hpp"
#include "util/Lua.hpp"
int32_t CSimpleSlider::s_metatable;
int32_t CSimpleSlider::s_objectType;
void CSimpleSlider::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleSlider::RegisterScriptMethods);
CSimpleSlider::s_metatable = ref;
}
int32_t CSimpleSlider::GetObjectType() {
if (!CSimpleSlider::s_objectType) {
CSimpleSlider::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CSimpleSlider::s_objectType;
}
void CSimpleSlider::RegisterScriptMethods(lua_State* L) {
CSimpleFrame::RegisterScriptMethods(L);
FrameScript_Object::FillScriptMethodTable(L, SimpleSliderMethods, NUM_SIMPLE_SLIDER_SCRIPT_METHODS);
}
FrameScript_Object::ScriptIx* CSimpleSlider::GetScriptByName(const char* name, ScriptData& data) {
auto parentScript = CSimpleFrame::GetScriptByName(name, data);
if (parentScript) {
return parentScript;
}
if (!SStrCmpI(name, "OnValueChanged", STORM_MAX_STR)) {
data.wrapper = "return function(self,value) %s end";
return &this->m_onValueChanged;
}
if (!SStrCmpI(name, "OnMinMaxChanged", STORM_MAX_STR)) {
data.wrapper = "return function(self,min,max) %s end";
return &this->m_onMinMaxChanged;
}
return nullptr;
}
int32_t CSimpleSlider::GetScriptMetaTable() {
return CSimpleSlider::s_metatable;
}
bool CSimpleSlider::IsA(int32_t type) {
return type == CSimpleSlider::s_objectType
|| type == CSimpleFrame::s_objectType
|| type == CScriptRegion::s_objectType
|| type == CScriptObject::s_objectType;
}
void CSimpleSlider::RunOnMinMaxChangedScript() {
if (!this->m_onMinMaxChanged.luaRef) {
return;
}
auto L = FrameScript_GetContext();
lua_pushnumber(L, this->m_baseValue);
lua_pushnumber(L, this->m_range + this->m_baseValue);
this->RunScript(this->m_onMinMaxChanged, 2, nullptr);
}
void CSimpleSlider::RunOnValueChangedScript() {
if (!this->m_onValueChanged.luaRef) {
return;
}
auto L = FrameScript_GetContext();
lua_pushnumber(L, this->m_value);
this->RunScript(this->m_onValueChanged, 1, nullptr);
}
void CSimpleSlider::SetMinMaxValues(float min, float max) {
float range = max - min;
if (this->m_rangeSet && AreEqual(this->m_range, range, WHOA_EPSILON_1) && AreEqual(this->m_baseValue, min, WHOA_EPSILON_1)) {
return;
}
this->m_baseValue = min;
this->m_range = range;
this->m_changed = 1;
this->m_rangeSet = 1;
this->RunOnMinMaxChangedScript();
if (this->m_valueSet) {
// Fit current value within range
this->SetValue(this->m_value);
}
}
void CSimpleSlider::SetValue(float value) {
if (!this->m_rangeSet) {
return;
}
auto v4 = value;
auto v5 = std::max(value, this->m_baseValue);
auto maxValue = this->m_range + this->m_baseValue;
if (maxValue >= v5) {
if (v4 < this->m_baseValue) {
v4 = this->m_baseValue;
}
} else {
v4 = maxValue;
}
auto newValue = this->Sub96BC10(v4);
// Clamp to max value
if (newValue + this->m_valueStep >= maxValue) {
newValue = maxValue;
}
// Clamp to base value
if (newValue - this->m_valueStep < this->m_baseValue) {
newValue = this->m_baseValue;
}
if (!this->m_valueSet || fabs(newValue - this->m_value) >= 0.00000023841858) {
this->m_value = newValue;
this->m_changed = 1;
this->m_valueSet = 1;
this->RunOnValueChangedScript();
}
}
float CSimpleSlider::Sub96BC10(float value) {
// TODO
return value;
}

51
src/ui/CSimpleSlider.hpp Normal file
View file

@ -0,0 +1,51 @@
#ifndef UI_C_SIMPLE_SLIDER_HPP
#define UI_C_SIMPLE_SLIDER_HPP
#include "ui/CSimpleFrame.hpp"
class CSimpleSlider : public CSimpleFrame {
public:
// Static variables
static int32_t s_metatable;
static int32_t s_objectType;
// Static functions
static void CreateScriptMetaTable(void);
static int32_t GetObjectType(void);
static void RegisterScriptMethods(lua_State*);
// Member variables
int32_t m_changed : 1;
int32_t m_rangeSet : 1;
int32_t m_valueSet : 1;
int32_t m_buttonDown : 1;
float m_baseValue = 0.0f;
float m_range = 0.0f;
float m_value = 0.0f;
float m_valueStep = 0.0f;
ScriptIx m_onValueChanged;
ScriptIx m_onMinMaxChanged;
// Virtual member functions
virtual ScriptIx* GetScriptByName(const char*, ScriptData&);
virtual bool IsA(int32_t);
virtual int32_t GetScriptMetaTable(void);
// Member functions
CSimpleSlider(CSimpleFrame* parent)
: CSimpleFrame(parent)
, m_changed(0)
, m_rangeSet(0)
, m_valueSet(0)
, m_buttonDown(0)
{
this->EnableEvent(SIMPLE_EVENT_MOUSE, -1);
};
void RunOnMinMaxChangedScript();
void RunOnValueChangedScript();
void SetMinMaxValues(float min, float max);
void SetValue(float value);
float Sub96BC10(float value);
};
#endif

View file

@ -0,0 +1,108 @@
#include "ui/CSimpleSliderScript.hpp"
#include "ui/CSimpleSlider.hpp"
#include "util/Lua.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleSlider_GetThumbTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleSlider_SetThumbTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleSlider_GetOrientation(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleSlider_SetOrientation(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleSlider_GetMinMaxValues(lua_State* L) {
auto type = CSimpleSlider::GetObjectType();
auto slider = static_cast<CSimpleSlider*>(FrameScript_GetObjectThis(L, type));
lua_pushnumber(L, slider->m_baseValue);
lua_pushnumber(L, slider->m_range + slider->m_baseValue);
return 2;
}
int32_t CSimpleSlider_SetMinMaxValues(lua_State* L) {
auto type = CSimpleSlider::GetObjectType();
auto slider = static_cast<CSimpleSlider*>(FrameScript_GetObjectThis(L, type));
if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || lua_tonumber(L, 2) > lua_tonumber(L, 3)) {
luaL_error(L, "Usage: %s:SetMinMaxValues(min, max)", slider->GetDisplayName());
}
float min = lua_tonumber(L, 2);
float max = lua_tonumber(L, 3);
slider->SetMinMaxValues(min, max);
return 0;
}
int32_t CSimpleSlider_GetValue(lua_State* L) {
auto type = CSimpleSlider::GetObjectType();
auto slider = static_cast<CSimpleSlider*>(FrameScript_GetObjectThis(L, type));
float value = slider->m_value;
lua_pushnumber(L, value);
return 1;
}
int32_t CSimpleSlider_SetValue(lua_State* L) {
auto type = CSimpleSlider::GetObjectType();
auto slider = static_cast<CSimpleSlider*>(FrameScript_GetObjectThis(L, type));
if (!lua_isnumber(L, 2)) {
luaL_error(L, "Usage: %s:SetValue(value)", slider->GetDisplayName());
}
float value = lua_tonumber(L, 2);
slider->SetValue(value);
return 0;
}
int32_t CSimpleSlider_GetValueStep(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleSlider_SetValueStep(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleSlider_Enable(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleSlider_Disable(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleSlider_IsEnabled(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleSliderMethods[NUM_SIMPLE_SLIDER_SCRIPT_METHODS] = {
{ "GetThumbTexture", &CSimpleSlider_GetThumbTexture },
{ "SetThumbTexture", &CSimpleSlider_SetThumbTexture },
{ "GetOrientation", &CSimpleSlider_GetOrientation },
{ "SetOrientation", &CSimpleSlider_SetOrientation },
{ "GetMinMaxValues", &CSimpleSlider_GetMinMaxValues },
{ "SetMinMaxValues", &CSimpleSlider_SetMinMaxValues },
{ "GetValue", &CSimpleSlider_GetValue },
{ "SetValue", &CSimpleSlider_SetValue },
{ "GetValueStep", &CSimpleSlider_GetValueStep },
{ "SetValueStep", &CSimpleSlider_SetValueStep },
{ "Enable", &CSimpleSlider_Enable },
{ "Disable", &CSimpleSlider_Disable },
{ "IsEnabled", &CSimpleSlider_IsEnabled }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_SLIDER_SCRIPT_HPP
#define UI_C_SIMPLE_SLIDER_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_SLIDER_SCRIPT_METHODS 13
extern FrameScript_Method SimpleSliderMethods[NUM_SIMPLE_SLIDER_SCRIPT_METHODS];
#endif

537
src/ui/CSimpleTexture.cpp Normal file
View file

@ -0,0 +1,537 @@
#include "ui/CSimpleTexture.hpp"
#include "gx/Coordinate.hpp"
#include "gx/Device.hpp"
#include "gx/Shader.hpp"
#include "ui/CFramePoint.hpp"
#include "ui/CRenderBatch.hpp"
#include "ui/CSimpleFrame.hpp"
#include "ui/CSimpleTextureScript.hpp"
#include "ui/FrameXML.hpp"
#include "ui/LoadXML.hpp"
#include "ui/Util.hpp"
#include "util/StringTo.hpp"
#include <algorithm>
#include <climits>
#include <common/XML.hpp>
#include <storm/String.hpp>
CGxShader* CSimpleTexture::s_imageModePixelShaders[2] = {};
uint16_t CSimpleTexture::s_indices[] = {
0, 1, 2,
2, 1, 3
};
int32_t CSimpleTexture::s_metatable;
int32_t CSimpleTexture::s_objectType;
EGxTexFilter CSimpleTexture::s_textureFilterMode = GxTex_Linear;
void CSimpleTexture::CreateScriptMetaTable() {
lua_State* L = FrameScript_GetContext();
int32_t ref = FrameScript_Object::CreateScriptMetaTable(L, &CSimpleTexture::RegisterScriptMethods);
CSimpleTexture::s_metatable = ref;
}
CGxShader* CSimpleTexture::GetImageModePixelShader(TextureImageMode mode) {
CGxShader* shader = CSimpleTexture::s_imageModePixelShaders[mode];
if (shader && shader->Valid()) {
return shader;
} else {
return nullptr;
}
}
int32_t CSimpleTexture::GetObjectType() {
if (!CSimpleTexture::s_objectType) {
CSimpleTexture::s_objectType = ++FrameScript_Object::s_objectTypes;
}
return CSimpleTexture::s_objectType;
}
void CSimpleTexture::Init() {
static const char* paths[] = { "UI", "Desaturate" };
for (int32_t i = 0; i < 2; i++) {
g_theGxDevicePtr->ShaderCreate(
&s_imageModePixelShaders[i],
GxSh_Pixel,
"Shaders\\Pixel",
paths[i],
1
);
}
}
void CSimpleTexture::RegisterScriptMethods(lua_State* L) {
CScriptRegion::RegisterScriptMethods(L);
FrameScript_Object::FillScriptMethodTable(L, SimpleTextureMethods, NUM_SIMPLE_TEXTURE_SCRIPT_METHODS);
}
CSimpleTexture::CSimpleTexture(CSimpleFrame* frame, uint32_t drawlayer, int32_t show) : CSimpleRegion(frame, drawlayer, show) {
this->m_nonBlocking = 0;
this->m_updateTexCoord = 0;
this->m_horizTile = 0;
this->m_vertTile = 0;
this->m_shader = CSimpleTexture::GetImageModePixelShader(ImageMode_UI);
// TODO
// CSimpleTexture::s_count++;
this->m_texCoord[0] = { 0.0f, 0.0f };
this->m_texCoord[1] = { 0.0f, 1.0f };
this->m_texCoord[2] = { 1.0f, 0.0f };
this->m_texCoord[3] = { 1.0f, 1.0f };
}
CSimpleTexture::~CSimpleTexture() {
if (this->m_texture) {
HandleClose(this->m_texture);
}
// TODO CSimpleTexture::s_count++;
}
void CSimpleTexture::Draw(CRenderBatch* batch) {
if (this->m_texture) {
batch->QueueTexture(this);
}
}
float CSimpleTexture::GetHeight() {
float layoutHeight = CLayoutFrame::GetHeight();
if (layoutHeight != 0.0f) {
return layoutHeight;
}
uint32_t textureHeight;
if (TextureGetDimensions(this->m_texture, nullptr, &textureHeight, 0)) {
float ndcHeight = static_cast<float>(textureHeight) / (CoordinateGetAspectCompensation() * 1024.0f);
float ddcHeight = NDCToDDCWidth(ndcHeight);
return ddcHeight;
}
return 0.0f;
}
int32_t CSimpleTexture::GetScriptMetaTable() {
return CSimpleTexture::s_metatable;
}
void CSimpleTexture::GetTexCoord(C2Vector* texCoord) {
texCoord[0] = { this->m_texCoord[0].x, this->m_texCoord[0].y };
texCoord[1] = { this->m_texCoord[1].x, this->m_texCoord[1].y };
texCoord[2] = { this->m_texCoord[2].x, this->m_texCoord[2].y };
texCoord[3] = { this->m_texCoord[3].x, this->m_texCoord[3].y };
}
float CSimpleTexture::GetWidth() {
float layoutWidth = CLayoutFrame::GetWidth();
if (layoutWidth != 0.0f) {
return layoutWidth;
}
uint32_t textureWidth;
if (TextureGetDimensions(this->m_texture, &textureWidth, nullptr, 0)) {
float ndcWidth = static_cast<float>(textureWidth) / (CoordinateGetAspectCompensation() * 1024.0f);
float ddcWidth = NDCToDDCWidth(ndcWidth);
return ddcWidth;
}
return 0.0f;
}
bool CSimpleTexture::IsA(int32_t type) {
return type == CSimpleTexture::s_objectType
|| type == CScriptRegion::s_objectType
|| type == CScriptObject::s_objectType;
}
void CSimpleTexture::LoadXML(XMLNode* node, CStatus* status) {
const char* inheritsAttr = node->GetAttributeByName("inherits");
if (inheritsAttr && *inheritsAttr) {
const char* tainted;
bool locked;
XMLNode* inheritsNode = FrameXML_AcquireHashNode(inheritsAttr, tainted, locked);
if (inheritsNode) {
if (locked) {
status->Add(STATUS_WARNING, "Recursively inherited node: %s", inheritsAttr);
} else {
this->LoadXML(inheritsNode, status);
FrameXML_ReleaseHashNode(inheritsAttr);
}
} else {
status->Add(STATUS_WARNING, "Couldn't find inherited node: %s", inheritsAttr);
}
}
CScriptRegion::LoadXML(node, status);
const char* hiddenAttr = node->GetAttributeByName("hidden");
if (hiddenAttr && *hiddenAttr) {
bool hide = StringToBOOL(hiddenAttr);
if (hide) {
this->Hide();
} else {
this->Show();
}
}
int32_t wrapU = 0;
int32_t wrapV = 0;
CImVector color = { 0 };
const char* horizTileAttr = node->GetAttributeByName("horizTile");
if (horizTileAttr && *horizTileAttr) {
this->m_horizTile = StringToBOOL(horizTileAttr);
wrapU = 1;
}
const char* vertTileAttr = node->GetAttributeByName("vertTile");
if (vertTileAttr && *vertTileAttr) {
this->m_vertTile = StringToBOOL(vertTileAttr);
wrapV = 1;
}
for (XMLNode* child = node->m_child; child; child = child->m_next) {
if (!SStrCmpI(child->GetName(), "TexCoords", INT_MAX)) {
int32_t valid = 1;
float left = 0.0f;
float right = 1.0f;
float top = 0.0f;
float bottom = 1.0f;
const char* name = this->GetName();
if (!name) {
name = "<unnamed>";
}
const XMLNode* rectNode = child->GetChildByName("Rect");
if (rectNode) {
// TODO
} else {
const char* leftAttr = child->GetAttributeByName("left");
if (leftAttr && *leftAttr) {
if (this->m_horizTile) {
status->Add(
STATUS_ERROR,
"Texture %s: Invalid TexCoords value (horizTile is on)",
name
);
valid = 0;
}
left = SStrToFloat(leftAttr);
if (left < -10000.0f || left > 10000.0f) {
status->Add(
STATUS_ERROR,
"Texture %s: Invalid TexCoords value (out of range)",
name
);
valid = 0;
}
}
const char* rightAttr = child->GetAttributeByName("right");
if (rightAttr && *rightAttr) {
if (this->m_horizTile) {
status->Add(
STATUS_ERROR,
"Texture %s: Invalid TexCoords value (horizTile is on)",
name
);
valid = 0;
}
right = SStrToFloat(rightAttr);
if (right < -10000.0f || right > 10000.0f) {
status->Add(
STATUS_ERROR,
"Texture %s: Invalid TexCoords value (out of range)",
name
);
valid = 0;
}
}
const char* topAttr = child->GetAttributeByName("top");
if (topAttr && *topAttr) {
if (this->m_vertTile) {
status->Add(
STATUS_ERROR,
"Texture %s: Invalid TexCoords value (vertTile is on)",
name
);
valid = 0;
}
top = SStrToFloat(topAttr);
if (top < -10000.0f || top > 10000.0f) {
status->Add(
STATUS_ERROR,
"Texture %s: Invalid TexCoords value (out of range)",
name
);
valid = 0;
}
}
const char* bottomAttr = child->GetAttributeByName("bottom");
if (bottomAttr && *bottomAttr) {
if (this->m_vertTile) {
status->Add(
STATUS_ERROR,
"Texture %s: Invalid TexCoords value (vertTile is on)",
name
);
valid = 0;
}
bottom = SStrToFloat(bottomAttr);
if (bottom < -10000.0f || bottom > 10000.0f) {
status->Add(
STATUS_ERROR,
"Texture %s: Invalid TexCoords value (out of range)",
name
);
valid = 0;
}
}
}
if (valid) {
C2Vector coords[4];
coords[0].x = left;
coords[0].y = top;
coords[1].x = left;
coords[1].y = bottom;
coords[2].x = right;
coords[2].y = top;
coords[3].y = bottom;
coords[3].x = right;
this->SetTexCoord(coords);
if (left < 0.0f || left > 1.0f || right < 0.0f || right > 1.0f) {
wrapU = 1;
}
if (top < 0.0f || top > 1.0f || bottom < 0.0f || bottom > 1.0f) {
wrapV = 1;
}
}
} else if (!SStrCmpI(child->GetName(), "Color", INT_MAX)) {
LoadXML_Color(child, color);
this->SetTexture(color);
} else if (!SStrCmpI(child->GetName(), "Gradient", INT_MAX)) {
// TODO
}
}
const char* v91 = node->GetAttributeByName("file");
if (v91 && *v91) {
if (this->SetTexture(v91, wrapU, wrapV, CSimpleTexture::s_textureFilterMode, ImageMode_UI)) {
if (color.value) {
this->SetVertexColor(color);
}
} else {
const char* v94 = this->GetName();
if (!v94) {
v94 = "<unnamed>";
}
status->Add(
STATUS_WARNING,
"Texture %s: Unable to load texture file %s",
v94,
v91
);
// TODO
// CTexture* texture = TextureCreateSolid(&CRAPPY_GREEN); // 0xFF00FF00
// if (this->m_texture) {
// HandleClose(this->m_texture);
// }
// this->m_texture = texture;
// this->OnRegionChanged();
}
}
const char* alphaModeAttr = node->GetAttributeByName("alphaMode");
if (alphaModeAttr && *alphaModeAttr) {
EGxBlend alphaMode;
if (StringToBlendMode(alphaModeAttr, alphaMode)) {
this->SetBlendMode(alphaMode);
}
}
const char* alphaAttr = node->GetAttributeByName("alpha");
if (alphaAttr && *alphaAttr) {
float alpha = SStrToFloat(alphaAttr);
this->SetAlpha(alpha);
}
// TODO
// - nonBlocking
}
void CSimpleTexture::OnFrameSizeChanged(const CRect& rect) {
CLayoutFrame::OnFrameSizeChanged(rect);
if (false) {
// TODO
// - something about animations?
} else {
this->SetPosition(this->m_rect, this->m_position);
}
if (this->m_horizTile || this->m_vertTile) {
this->m_updateTexCoord = 1;
this->OnRegionChanged();
}
if (this->m_parent) {
this->m_parent->NotifyScrollParent();
}
}
void CSimpleTexture::PostLoadXML(XMLNode* node, CStatus* status) {
if (this->m_parent) {
for (int32_t i = 0; i < FRAMEPOINT_NUMPOINTS; i++) {
if (this->m_points[i] && !(this->m_points[i]->m_flags & 0x8)) {
break;
}
if (i + 1 == FRAMEPOINT_NUMPOINTS) {
this->SetAllPoints(this->m_parent, 1);
break;
}
}
}
}
void CSimpleTexture::SetAlpha(float alpha) {
// Clamp
alpha = std::max(0.0f, std::min(alpha, 1.0f));
CImVector color = { 0 };
this->GetVertexColor(color);
color.a = alpha * 255.0f;
this->SetVertexColor(color);
}
void CSimpleTexture::SetBlendMode(EGxBlend blend) {
if (blend == this->m_alphaMode) {
return;
}
this->m_alphaMode = blend;
this->OnRegionChanged();
}
void CSimpleTexture::SetPosition(const CRect& rect, C3Vector* position) {
position[0] = { rect.minX, rect.maxY, this->m_layoutDepth };
position[1] = { rect.minX, rect.minY, this->m_layoutDepth };
position[2] = { rect.maxX, rect.maxY, this->m_layoutDepth };
position[3] = { rect.maxX, rect.minY, this->m_layoutDepth };
}
void CSimpleTexture::SetTexCoord(const CRect& texRect) {
this->m_texCoord[0] = { texRect.minX, texRect.minY };
this->m_texCoord[1] = { texRect.minX, texRect.maxY };
this->m_texCoord[2] = { texRect.maxX, texRect.minY };
this->m_texCoord[3] = { texRect.maxX, texRect.maxY };
}
void CSimpleTexture::SetTexCoord(const C2Vector* texCoord) {
this->m_texCoord[0] = { texCoord[0].x, texCoord[0].y };
this->m_texCoord[1] = { texCoord[1].x, texCoord[1].y };
this->m_texCoord[2] = { texCoord[2].x, texCoord[2].y };
this->m_texCoord[3] = { texCoord[3].x, texCoord[3].y };
}
int32_t CSimpleTexture::SetTexture(const char* fileName, bool wrapU, bool wrapV, EGxTexFilter filter, TextureImageMode mode) {
if (this->m_texture && fileName && TextureIsSame(this->m_texture, fileName)) {
return 1;
}
HTEXTURE texture = nullptr;
if (fileName && *fileName) {
CStatus status;
CGxTexFlags texFlags = CGxTexFlags(filter, wrapU, wrapV, 0, 0, 0, 1);
texture = TextureCreate(fileName, texFlags, &status, 23);
// TODO
// if (status.unk4 >= 2) {
// HandleClose(texture);
// SysMsgAdd(&status);
// return 0;
// }
this->m_shader = CSimpleTexture::GetImageModePixelShader(mode);
}
if (this->m_texture) {
HandleClose(this->m_texture);
}
this->m_texture = texture;
this->OnRegionChanged();
return 1;
}
int32_t CSimpleTexture::SetTexture(const CImVector& color) {
HTEXTURE texture = TextureCreateSolid(color);
if (this->m_texture) {
HandleClose(this->m_texture);
}
this->m_texture = texture;
this->OnRegionChanged();
return 1;
}

64
src/ui/CSimpleTexture.hpp Normal file
View file

@ -0,0 +1,64 @@
#ifndef UI_C_SIMPLE_TEXTURE_HPP
#define UI_C_SIMPLE_TEXTURE_HPP
#include "gx/Texture.hpp"
#include "ui/CSimpleRegion.hpp"
#include "ui/Types.hpp"
#include <tempest/Vector.hpp>
class CGxShader;
class CRect;
class CRenderBatch;
class CSimpleFrame;
class CSimpleTexture : public CSimpleRegion {
public:
// Static variables
static CGxShader* s_imageModePixelShaders[];
static uint16_t s_indices[];
static int32_t s_metatable;
static int32_t s_objectType;
static EGxTexFilter s_textureFilterMode;
// Static functions
static void CreateScriptMetaTable(void);
static CGxShader* GetImageModePixelShader(TextureImageMode);
static int32_t GetObjectType(void);
static void Init(void);
static void RegisterScriptMethods(lua_State*);
// Member variables
HTEXTURE m_texture = nullptr;
EGxBlend m_alphaMode = GxBlend_Alpha;
CGxShader* m_shader = s_imageModePixelShaders[0];
C3Vector m_position[4];
C2Vector m_texCoord[4];
uint32_t m_nonBlocking : 1;
uint32_t m_updateTexCoord : 1;
uint32_t m_horizTile : 1;
uint32_t m_vertTile : 1;
// Virtual member functions
virtual ~CSimpleTexture();
virtual int32_t GetScriptMetaTable(void);
virtual bool IsA(int32_t);
virtual void LoadXML(XMLNode*, CStatus*);
virtual float GetWidth(void);
virtual float GetHeight(void);
virtual void Draw(CRenderBatch*);
virtual void OnFrameSizeChanged(const CRect&);
// Member functions
CSimpleTexture(CSimpleFrame*, uint32_t, int32_t);
void GetTexCoord(C2Vector*);
void PostLoadXML(XMLNode*, CStatus*);
void SetAlpha(float alpha);
void SetBlendMode(EGxBlend);
void SetPosition(const CRect&, C3Vector*);
void SetTexCoord(const CRect& texRect);
void SetTexCoord(const C2Vector*);
int32_t SetTexture(const char*, bool, bool, EGxTexFilter, TextureImageMode);
int32_t SetTexture(const CImVector&);
};
#endif

View file

@ -0,0 +1,275 @@
#include "ui/CSimpleTextureScript.hpp"
#include "ui/CSimpleTexture.hpp"
#include "ui/Types.hpp"
#include "util/Lua.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
int32_t CSimpleTexture_IsObjectType(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_GetObjectType(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_GetDrawLayer(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetDrawLayer(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_GetBlendMode(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetBlendMode(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_GetVertexColor(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetVertexColor(lua_State* L) {
int32_t type = CSimpleTexture::GetObjectType();
CSimpleTexture* texture = static_cast<CSimpleTexture*>(FrameScript_GetObjectThis(L, type));
CImVector curColor = { 0 };
texture->GetVertexColor(curColor);
CImVector newColor = { 0 };
FrameScript_GetColor(L, 2, newColor);
if (!lua_isnumber(L, 5)) {
newColor.a = curColor.a;
}
texture->SetVertexColor(newColor);
return 0;
}
int32_t CSimpleTexture_SetGradient(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetGradientAlpha(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetAlpha(lua_State* L) {
int32_t type = CSimpleTexture::GetObjectType();
CSimpleTexture* texture = static_cast<CSimpleTexture*>(FrameScript_GetObjectThis(L, type));
if (!lua_isnumber(L, 2)) {
luaL_error(L, "Usage: %s:SetAlpha(alpha)", texture->GetDisplayName());
}
float alpha = lua_tonumber(L, 2);
texture->SetAlpha(alpha);
return 0;
}
int32_t CSimpleTexture_GetAlpha(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_Show(lua_State* L) {
int32_t type = CSimpleTexture::GetObjectType();
CSimpleTexture* texture = static_cast<CSimpleTexture*>(FrameScript_GetObjectThis(L, type));
texture->Show();
return 0;
}
int32_t CSimpleTexture_Hide(lua_State* L) {
int32_t type = CSimpleTexture::GetObjectType();
CSimpleTexture* texture = static_cast<CSimpleTexture*>(FrameScript_GetObjectThis(L, type));
texture->Hide();
return 0;
}
int32_t CSimpleTexture_IsVisible(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_IsShown(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_GetTexture(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetTexture(lua_State* L) {
int32_t type = CSimpleTexture::GetObjectType();
CSimpleTexture* texture = static_cast<CSimpleTexture*>(FrameScript_GetObjectThis(L, type));
if (lua_isnumber(L, 2)) {
// TODO
// CArgb v9 = 0;
// FrameScript_GetRGBA(2, L, &v9);
// texture->SetTexture(&v9);
lua_pushnumber(L, 1.0);
return 1;
}
if (!lua_isstring(L, 2)) {
texture->SetTexture(0, 0, 0, CSimpleTexture::s_textureFilterMode, ImageMode_UI);
lua_pushnumber(L, 1.0);
return 1;
}
bool v5 = lua_toboolean(L, 3);
bool v6 = lua_toboolean(L, 3);
const char* v7 = lua_tolstring(L, 2, 0);
if (texture->SetTexture(v7, v6, v5, CSimpleTexture::s_textureFilterMode, ImageMode_UI)) {
lua_pushnumber(L, 1.0);
return 1;
}
lua_pushnil(L);
return 1;
}
int32_t CSimpleTexture_GetTexCoord(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetTexCoord(lua_State* L) {
auto type = CSimpleTexture::GetObjectType();
auto texture = static_cast<CSimpleTexture*>(FrameScript_GetObjectThis(L, type));
auto argCount = lua_gettop(L) - 1;
if (argCount == 4) {
CRect texRect = {
static_cast<float>(lua_tonumber(L, 4)),
static_cast<float>(lua_tonumber(L, 2)),
static_cast<float>(lua_tonumber(L, 5)),
static_cast<float>(lua_tonumber(L, 3))
};
if (
texRect.minX < -10000.0f
|| texRect.minX > 10000.0f
|| texRect.maxX < -10000.0f
|| texRect.maxX > 10000.0f
|| texRect.minY < -10000.0f
|| texRect.minY > 10000.0f
|| texRect.maxY < -10000.0f
|| texRect.maxY > 10000.0f
) {
luaL_error(L, "TexCoord out of range");
}
texture->SetTexCoord(texRect);
} else if (argCount == 8) {
C2Vector texCoord[4];
for (int32_t i = 0; i < 4; i++) {
texCoord[i] = {
static_cast<float>(lua_tonumber(L, 2 + (i * 2 + 0))),
static_cast<float>(lua_tonumber(L, 2 + (i * 2 + 1)))
};
if (
texCoord[i].x < -10000.0f
|| texCoord[i].x > 10000.0f
|| texCoord[i].y < -10000.0f
|| texCoord[i].y > 10000.0f
) {
luaL_error(L, "TexCoord out of range");
}
}
texture->SetTexCoord(texCoord);
} else {
luaL_error(L, "Usage: %s:SetTexCoord(minX, maxX, minY, maxY) or SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy)", texture->GetDisplayName());
}
return 0;
}
int32_t CSimpleTexture_SetRotation(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetDesaturated(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_IsDesaturated(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetNonBlocking(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_GetNonBlocking(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetHorizTile(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_GetHorizTile(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_SetVertTile(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t CSimpleTexture_GetVertTile(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
FrameScript_Method SimpleTextureMethods[NUM_SIMPLE_TEXTURE_SCRIPT_METHODS] = {
{ "IsObjectType", &CSimpleTexture_IsObjectType },
{ "GetObjectType", &CSimpleTexture_GetObjectType },
{ "GetDrawLayer", &CSimpleTexture_GetDrawLayer },
{ "SetDrawLayer", &CSimpleTexture_SetDrawLayer },
{ "GetBlendMode", &CSimpleTexture_GetBlendMode },
{ "SetBlendMode", &CSimpleTexture_SetBlendMode },
{ "GetVertexColor", &CSimpleTexture_GetVertexColor },
{ "SetVertexColor", &CSimpleTexture_SetVertexColor },
{ "SetGradient", &CSimpleTexture_SetGradient },
{ "SetGradientAlpha", &CSimpleTexture_SetGradientAlpha },
{ "SetAlpha", &CSimpleTexture_SetAlpha },
{ "GetAlpha", &CSimpleTexture_GetAlpha },
{ "Show", &CSimpleTexture_Show },
{ "Hide", &CSimpleTexture_Hide },
{ "IsVisible", &CSimpleTexture_IsVisible },
{ "IsShown", &CSimpleTexture_IsShown },
{ "GetTexture", &CSimpleTexture_GetTexture },
{ "SetTexture", &CSimpleTexture_SetTexture },
{ "GetTexCoord", &CSimpleTexture_GetTexCoord },
{ "SetTexCoord", &CSimpleTexture_SetTexCoord },
{ "SetRotation", &CSimpleTexture_SetRotation },
{ "SetDesaturated", &CSimpleTexture_SetDesaturated },
{ "IsDesaturated", &CSimpleTexture_IsDesaturated },
{ "SetNonBlocking", &CSimpleTexture_SetNonBlocking },
{ "GetNonBlocking", &CSimpleTexture_GetNonBlocking },
{ "SetHorizTile", &CSimpleTexture_SetHorizTile },
{ "GetHorizTile", &CSimpleTexture_GetHorizTile },
{ "SetVertTile", &CSimpleTexture_SetVertTile },
{ "GetVertTile", &CSimpleTexture_GetVertTile }
};

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_TEXTURE_SCRIPT_HPP
#define UI_C_SIMPLE_TEXTURE_SCRIPT_HPP
#include "ui/FrameScript.hpp"
#define NUM_SIMPLE_TEXTURE_SCRIPT_METHODS 29
extern FrameScript_Method SimpleTextureMethods[NUM_SIMPLE_TEXTURE_SCRIPT_METHODS];
#endif

View file

@ -0,0 +1,10 @@
#ifndef UI_C_SIMPLE_TITLE_REGION_HPP
#define UI_C_SIMPLE_TITLE_REGION_HPP
#include "ui/CScriptRegion.hpp"
class CSimpleTitleRegion : public CScriptRegion {
public:
};
#endif

577
src/ui/CSimpleTop.cpp Normal file
View file

@ -0,0 +1,577 @@
#include "ui/CSimpleTop.hpp"
#include "gx/Camera.hpp"
#include "gx/Coordinate.hpp"
#include "gx/Device.hpp"
#include "gx/Font.hpp"
#include "gx/Screen.hpp"
#include "ui/CSimpleFrame.hpp"
#include "ui/CSimpleRender.hpp"
#include "ui/CSimpleTexture.hpp"
#include "ui/CSimpleTitleRegion.hpp"
#include <cstring>
#include <tempest/Math.hpp>
CSimpleTop* CSimpleTop::s_instance;
uint32_t CSimpleTop::m_eventTime;
void PaintScreen(void* param, const RECTF* rect, const RECTF* visible, float elapsedSec) {
CSimpleTop::s_instance->OnLayerUpdate(elapsedSec);
CSimpleTop::s_instance->OnLayerRender();
}
int32_t CSimpleTop::OnChar(const EVENT_DATA_CHAR* pCharData, void* param) {
CSimpleTop* top = static_cast<CSimpleTop*>(param);
int32_t eaten = 0;
CCharEvent charEvent;
charEvent = *pCharData;
charEvent.id = 0x40060067;
for (int32_t strata = FRAME_STRATA_TOOLTIP; strata >= FRAME_STRATA_WORLD; strata--) {
if (eaten) {
break;
}
auto priorities = &top->m_eventqueue[strata][SIMPLE_EVENT_CHAR];
for (int32_t i = priorities->Count() - 1; i >= 0; i--) {
auto priority = priorities->operator[](i);
if (!priority || eaten) {
break;
}
auto frame = priority->frame;
eaten = frame->OnLayerChar(charEvent);
}
}
return eaten == 0;
}
int32_t CSimpleTop::OnDisplaySizeChanged(const EVENT_DATA_SIZE* pSizeData, void* param) {
CSimpleTop* top = static_cast<CSimpleTop*>(param);
GxuFontWindowSizeChanged();
for (auto frame = top->m_frames.Head(); frame; frame = top->m_frames.Link(frame)->Next()) {
frame->OnScreenSizeChanged();
}
if (top->m_displaySizeCallback) {
CSizeEvent sizeEvent;
sizeEvent = *pSizeData;
sizeEvent.id = 0x40040064;
top->m_displaySizeCallback(sizeEvent);
}
return 1;
}
int32_t CSimpleTop::OnFocusChanged(const void*, void*) {
// TODO
return 0;
}
int32_t CSimpleTop::OnIme(const void*, void*) {
// TODO
return 0;
}
int32_t CSimpleTop::OnKeyDown(const EVENT_DATA_KEY* pKeyData, void* param) {
CSimpleTop* top = static_cast<CSimpleTop*>(param);
CSimpleTop::m_eventTime = pKeyData->time;
CKeyEvent keyEvent;
keyEvent = *pKeyData;
keyEvent.id = 0x40060064;
// TODO
// if (top->unk1239) {
// top->unk1239(keyEvent);
// }
int32_t eaten = 0;
for (int32_t strata = FRAME_STRATA_TOOLTIP; strata >= FRAME_STRATA_WORLD; strata--) {
if (eaten) {
break;
}
auto priorities = &top->m_eventqueue[strata][SIMPLE_EVENT_KEY];
for (int32_t i = priorities->Count() - 1; i >= 0; i--) {
auto priority = priorities->operator[](i);
if (!priority || eaten) {
break;
}
auto frame = priority->frame;
eaten = frame->OnLayerKeyDown(keyEvent);
if (eaten) {
top->m_keydownCapture[keyEvent.key] = frame;
}
}
}
return eaten == 0;
}
int32_t CSimpleTop::OnKeyDownRepeat(const void*, void*) {
// TODO
return 0;
}
int32_t CSimpleTop::OnKeyUp(const EVENT_DATA_KEY* pKeyData, void* param) {
CSimpleTop* top = static_cast<CSimpleTop*>(param);
CSimpleTop::m_eventTime = pKeyData->time;
int32_t eaten = 0;
CSimpleFrame* frame = top->m_keydownCapture[pKeyData->key];
if (frame) {
CKeyEvent keyEvent;
keyEvent = *pKeyData;
keyEvent.id = 0x40060066;
frame->OnLayerKeyUp(keyEvent);
eaten = 1;
} else if (pKeyData->key == KEY_PRINTSCREEN) {
eaten = CSimpleTop::OnKeyDown(pKeyData, param);
}
top->m_keydownCapture[pKeyData->key] = nullptr;
return eaten == 0;
}
int32_t CSimpleTop::OnMouseDown(const EVENT_DATA_MOUSE* pMouseData, void* param) {
CSimpleTop* top = static_cast<CSimpleTop*>(param);
CMouseEvent mouseEvent;
mouseEvent = *pMouseData;
mouseEvent.id = 0x400500C8;
CSimpleTop::m_eventTime = pMouseData->time;
// TODO
// bool v4 = top->m_layout.enabled;
bool enabled = false;
memcpy(&top->m_mousePosition, pMouseData, sizeof(top->m_mousePosition));
if (enabled && (EventIsKeyDown(KEY_LCONTROL) || EventIsKeyDown(KEY_LALT))) {
int32_t v5 = EventIsKeyDown(KEY_LCONTROL);
top->StartMoveOrResizeFrame(mouseEvent, MOVERESIZE_REASON1, v5);
return 0;
}
auto mouseButtonCallback = top->m_mouseButtonCallback;
if (!top->m_mouseCapture && mouseButtonCallback && mouseButtonCallback(&mouseEvent)) {
return 0;
}
CSimpleFrame* target = top->m_mouseCapture;
if (!target) {
target = top->m_mouseFocus;
}
if (!target) {
return 1;
}
target->Raise();
CSimpleTitleRegion* titleRegion = target->m_titleRegion;
C2Vector pt = { mouseEvent.x, mouseEvent.y };
if (titleRegion && titleRegion->PtInFrameRect(pt)) {
top->StartMoveOrResizeFrame(target, MOVERESIZE_REASON2, mouseEvent.x, mouseEvent.y, 4);
} else {
top->m_mouseCapture = target;
target->OnLayerMouseDown(mouseEvent, nullptr);
}
return 0;
}
int32_t CSimpleTop::OnMouseMove(const EVENT_DATA_MOUSE* pMouseData, void* param) {
CSimpleTop* top = static_cast<CSimpleTop*>(param);
CMouseEvent mouseEvent;
mouseEvent = *pMouseData;
mouseEvent.id = 0x400500CA;
int32_t v18 = pMouseData != &top->m_mousePosition;
if (v18) {
if (pMouseData->x == top->m_mousePosition.x && pMouseData->y == top->m_mousePosition.y) {
return 0;
}
CSimpleTop::m_eventTime = pMouseData->time;
}
memcpy(&top->m_mousePosition, pMouseData, sizeof(top->m_mousePosition));
CSimpleFrame* lastFocus = top->m_mouseFocus;
CSimpleFrame* nextFocus = nullptr;
if (top->m_layout.frame) {
CMouseEvent evt;
evt = *pMouseData;
top->MoveOrResizeFrame(evt);
return 0;
}
auto mousePositionCallback = top->m_mousePositionCallback;
if (mousePositionCallback && mousePositionCallback(&mouseEvent)) {
return 0;
}
CSimpleFrame* mouseCapture = top->m_mouseCapture;
if (mouseCapture) {
mouseCapture->OnLayerTrackUpdate(mouseEvent);
}
for (int32_t strata = FRAME_STRATA_DIALOG; strata >= FRAME_STRATA_WORLD; strata--) {
auto priorities = &top->m_eventqueue[strata][SIMPLE_EVENT_MOUSE];
for (int32_t i = priorities->Count() - 1; i >= 0; i--) {
auto frame = priorities->operator[](i)->frame;
if (frame->OnLayerTrackUpdate(mouseEvent)) {
nextFocus = frame;
break;
}
}
if (nextFocus) {
break;
}
}
if (nextFocus != lastFocus) {
top->m_mouseFocus = nextFocus;
if (lastFocus) {
lastFocus->OnLayerCursorExit(v18, 0);
}
if (nextFocus) {
nextFocus->OnLayerCursorEnter(v18);
}
}
return nextFocus == nullptr;
}
int32_t CSimpleTop::OnMouseMoveRelative(const EVENT_DATA_MOUSE*, void*) {
// TODO
return 0;
}
int32_t CSimpleTop::OnMouseUp(const EVENT_DATA_MOUSE* pMouseData, void* param) {
CSimpleTop* top = static_cast<CSimpleTop*>(param);
CMouseEvent mouseEvent;
mouseEvent = *pMouseData;
mouseEvent.id = 0x400500C9;
CSimpleTop::m_eventTime = pMouseData->time;
if (top->m_layout.anchor == 1 || top->m_layout.anchor == 2) {
if (top->m_layout.frame) {
top->m_layout.frame->UnflattenFrame(top);
}
top->m_layout.frame = nullptr;
top->m_layout.anchor = FRAMEPOINT_TOPLEFT;
return 0;
}
// TODO
// if (v11 && !top->m_mouseCapture && v11(mouseEvent)) {
// return 0;
// }
if (!top->m_mouseCapture) {
return 1;
}
top->m_mouseCapture->OnLayerMouseUp(mouseEvent, nullptr);
if (!mouseEvent.buttonState) {
top->m_mouseCapture = nullptr;
}
return 0;
}
int32_t CSimpleTop::OnMouseWheel(const EVENT_DATA_MOUSE*, void*) {
// TODO
return 0;
}
float CSimpleTop::RoundToPixelHeight(float ddcHeight) {
if (abs(ddcHeight) < 0.00000023841858) {
return ddcHeight;
}
CRect windowRect = { 0.0f, 0.0f, 0.0f, 0.0f };
g_theGxDevicePtr->CapsWindowSizeInScreenCoords(windowRect);
float windowHeight = windowRect.maxY - windowRect.minY;
if (abs(windowHeight) < 0.00000023841858) {
return ddcHeight;
}
auto ndcHeight = DDCToNDCHeight(ddcHeight);
auto pixelHeight = ndcHeight * windowHeight;
auto roundedPixelHeight = CMath::fuint_pi(pixelHeight);
auto roundedNdcHeight = static_cast<float>(roundedPixelHeight) / windowHeight;
auto roundedDdcHeight = NDCToDDCHeight(roundedNdcHeight);
return roundedDdcHeight;
}
CSimpleTop::CSimpleTop() : CLayoutFrame() {
// TODO
CSimpleTop::s_instance = this;
ScrnLayerCreate(nullptr, 1.0, 0x4, nullptr, &PaintScreen, &this->m_screenLayer);
this->EnableEvents();
// TODO
// memset(this->m_keydownCapture, 0, sizeof(this->m_keydownCapture));
NDCToDDC(1.0f, 1.0f, &this->m_rect.maxX, &this->m_rect.maxY);
this->m_flags |= 0x1;
// TODO
for (int32_t s = 0; s < NUM_FRAME_STRATA; s++) {
void* m = SMemAlloc(sizeof(CFrameStrata), __FILE__, __LINE__, 0);
this->m_strata[s] = m ? new (m) CFrameStrata() : nullptr;
}
// TODO
CSimpleRender::Init();
CSimpleTexture::Init();
}
void CSimpleTop::CompressStrata(int32_t strata) {
// TODO
}
void CSimpleTop::EnableEvents() {
EventRegisterEx(EVENT_ID_CHAR, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnChar), this, 1.0);
EventRegisterEx(EVENT_ID_IME, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnIme), this, 1.0);
EventRegisterEx(EVENT_ID_KEYDOWN, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnKeyDown), this, 1.0);
EventRegisterEx(EVENT_ID_KEYUP, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnKeyUp), this, 1.0);
EventRegisterEx(EVENT_ID_KEYDOWN_REPEATING, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnKeyDownRepeat), this, 1.0);
EventRegisterEx(EVENT_ID_MOUSEMOVE, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnMouseMove), this, 1.0);
EventRegisterEx(EVENT_ID_MOUSEMOVE_RELATIVE, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnMouseMoveRelative), this, 1.0);
EventRegisterEx(EVENT_ID_MOUSEDOWN, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnMouseDown), this, 1.0);
EventRegisterEx(EVENT_ID_MOUSEUP, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnMouseUp), this, 1.0);
EventRegisterEx(EVENT_ID_MOUSEWHEEL, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnMouseWheel), this, 1.0);
EventRegisterEx(EVENT_ID_SIZE, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnDisplaySizeChanged), this, 1.0);
EventRegisterEx(EVENT_ID_FOCUS, reinterpret_cast<EVENTHANDLERFUNC>(CSimpleTop::OnFocusChanged), this, 1.0);
}
void CSimpleTop::HideFrame(CSimpleFrame* frame, int32_t a4) {
if (this->m_layout.frame == frame && !a4) {
if (this->m_layout.frame) {
this->m_layout.frame->UnflattenFrame(this);
}
this->m_layout.frame = nullptr;
this->m_layout.anchor = FRAMEPOINT_TOPLEFT;
}
frame->UnregisterForEvents(a4);
this->m_strata[frame->m_strata]->RemoveFrame(frame);
}
void CSimpleTop::OnLayerUpdate(float elapsedSec) {
// TODO
// - walk m_destroyed and perform some cleanup
CLayoutFrame::ResizePending();
for (int32_t s = 0; s < NUM_FRAME_STRATA; s++) {
auto strata = this->m_strata[s];
strata->OnLayerUpdate(elapsedSec);
}
CLayoutFrame::ResizePending();
if (this->m_checkFocus) {
this->m_checkFocus = 0;
CSimpleTop::OnMouseMove(&this->m_mousePosition, this);
}
}
void CSimpleTop::OnLayerRender() {
C2Vector v13 = { 0.0f, 0.0f };
CameraSetupScreenProjection(this->m_rect, v13, 0.0f, 0);
for (int32_t s = 0; s < NUM_FRAME_STRATA; s++) {
auto strata = this->m_strata[s];
strata->BuildBatches(this->m_mouseCapture == nullptr);
strata->RenderBatches();
}
}
void CSimpleTop::MoveOrResizeFrame(const CMouseEvent& evt) {
// TODO
}
void CSimpleTop::NotifyFrameLayerChanged(CSimpleFrame* frame, uint32_t layer) {
auto strata = this->m_strata[frame->m_strata];
auto level = strata->levels[frame->m_level];
level->batchDirty |= 1 << layer;
strata->batchDirty = 1;
}
void CSimpleTop::NotifyFrameMovedOrResized(CSimpleFrame* frame) {
auto strata = this->m_strata[frame->m_strata];
strata->levelsDirty = 1;
if (this->m_layout.frame) {
this->RaiseFrame(this->m_layout.frame, 0);
}
this->m_checkFocus = 1;
}
int32_t CSimpleTop::RaiseFrame(CSimpleFrame* frame, int32_t checkOcclusion) {
while (frame && frame->m_flags & 0x01) {
frame = frame->m_parent;
}
if (!frame) {
return 0;
}
if (checkOcclusion) {
if (!(static_cast<CLayoutFrame*>(frame)->m_flags & 0x01) || this->IsResizePending()) {
frame->Resize(1);
}
int32_t occluded = this->m_strata[frame->m_strata]->FrameOccluded(frame);
frame->SetFrameFlag(0x10, occluded);
}
if (frame->m_flags & 0x10) {
this->CompressStrata(frame->m_strata);
auto strata = this->m_strata[frame->m_strata];
frame->SetFrameLevel(strata->topLevel, 1);
this->m_checkFocus = 1;
}
return 1;
}
void CSimpleTop::RegisterForEvent(CSimpleFrame* frame, CSimpleEventType event, int32_t a4, uint32_t priority) {
auto& queue = this->m_eventqueue[frame->m_strata][event];
auto m = SMemAlloc(sizeof(FRAMEPRIORITY), __FILE__, __LINE__, 0x0);
auto framePriority = new (m) FRAMEPRIORITY();
framePriority->frame = frame;
framePriority->priority = priority == -1 ? frame->m_level : priority;
queue.Insert(framePriority);
if (!a4 || event == SIMPLE_EVENT_MOUSE) {
this->m_checkFocus = 1;
}
}
void CSimpleTop::RegisterFrame(CSimpleFrame* frame) {
this->m_frames.LinkToTail(frame);
}
void CSimpleTop::ShowFrame(CSimpleFrame* frame, int32_t a3) {
this->m_strata[frame->m_strata]->AddFrame(frame);
frame->RegisterForEvents(a3);
}
int32_t CSimpleTop::StartMoveOrResizeFrame(const CMouseEvent& start, MOVERESIZE_REASON reason, int32_t resize) {
// TODO
return 0;
}
int32_t CSimpleTop::StartMoveOrResizeFrame(CSimpleFrame* frame, MOVERESIZE_REASON reason, float startx, float starty, int32_t a6) {
// TODO
return 0;
}
int32_t CSimpleTop::StartMoveOrResizeFrame(CSimpleFrame* frame, MOVERESIZE_REASON reason, float startx, float starty, FRAMEPOINT a6) {
// TODO
return 0;
}
void CSimpleTop::UnregisterForEvent(CSimpleFrame* frame, CSimpleEventType event, int32_t a4) {
auto& queue = this->m_eventqueue[frame->m_strata][event];
int32_t found = 0;
for (int32_t i = 0; i < queue.Count(); i++) {
if (queue[i]->frame == frame) {
queue.Remove(i);
found = 1;
break;
}
}
if (!found) {
return;
}
if (!a4) {
if (event == SIMPLE_EVENT_KEY) {
for (int32_t i = 0; i < 787; i++) {
if (frame == this->m_keydownCapture[i]) {
this->m_keydownCapture[i] = nullptr;
}
}
} else if (event == SIMPLE_EVENT_MOUSE) {
if (frame == this->m_mouseCapture) {
this->m_mouseCapture = nullptr;
}
if (frame == this->m_mouseFocus) {
this->m_mouseFocus = nullptr;
this->m_checkFocus = 1;
if (frame->m_intAC != 3) {
frame->OnLayerCursorExit(0, 1);
}
}
}
}
}

84
src/ui/CSimpleTop.hpp Normal file
View file

@ -0,0 +1,84 @@
#ifndef UI_C_SIMPLE_TOP_HPP
#define UI_C_SIMPLE_TOP_HPP
#include "event/Event.hpp"
#include "gx/Screen.hpp"
#include "ui/CFrameStrata.hpp"
#include "ui/CLayoutFrame.hpp"
#include "ui/CSimpleFrame.hpp"
#include "ui/FrameScript.hpp"
#include <common/Array.hpp>
enum MOVERESIZE_REASON {
MOVERESIZE_REASON0 = 0,
MOVERESIZE_REASON1 = 1,
MOVERESIZE_REASON2 = 2
};
class CSimpleTop : public CLayoutFrame {
public:
// Types
struct frame_layout {
int32_t enabled = 0;
CSimpleFrame* frame = nullptr;
FRAMEPOINT anchor = FRAMEPOINT_TOPLEFT;
C2Vector last;
float float14 = 0.0f;
};
// Static variables
static CSimpleTop* s_instance;
static uint32_t m_eventTime;
// Static functions
static int32_t OnChar(const EVENT_DATA_CHAR*, void*);
static int32_t OnDisplaySizeChanged(const EVENT_DATA_SIZE*, void*);
static int32_t OnFocusChanged(const void*, void*);
static int32_t OnIme(const void*, void*);
static int32_t OnKeyDown(const EVENT_DATA_KEY*, void*);
static int32_t OnKeyDownRepeat(const void*, void*);
static int32_t OnKeyUp(const EVENT_DATA_KEY*, void*);
static int32_t OnMouseDown(const EVENT_DATA_MOUSE*, void*);
static int32_t OnMouseMove(const EVENT_DATA_MOUSE*, void*);
static int32_t OnMouseMoveRelative(const EVENT_DATA_MOUSE*, void*);
static int32_t OnMouseUp(const EVENT_DATA_MOUSE*, void*);
static int32_t OnMouseWheel(const EVENT_DATA_MOUSE*, void*);
static float RoundToPixelHeight(float);
// Member variables
HLAYER m_screenLayer;
CSimpleFrame* m_mouseFocus = nullptr;
CSimpleFrame* m_mouseCapture = nullptr;
CSimpleFrame* m_keydownCapture[787] = {};
STORM_EXPLICIT_LIST(CSimpleFrame, m_framesLink) m_frames;
STORM_EXPLICIT_LIST(CSimpleFrame, m_destroyedLink) m_destroyed;
CFrameStrata* m_strata[NUM_FRAME_STRATA];
frame_layout m_layout;
CSimpleSortedArray<FRAMEPRIORITY*> m_eventqueue[NUM_FRAME_STRATA][NUM_SIMPLE_EVENTS];
int32_t m_checkFocus = 1;
EVENT_DATA_MOUSE m_mousePosition;
int32_t (*m_mouseButtonCallback)(CMouseEvent*) = nullptr;
int32_t (*m_mousePositionCallback)(CMouseEvent*) = nullptr;
int32_t (*m_displaySizeCallback)(const CSizeEvent&) = nullptr;
// Member functions
CSimpleTop();
void CompressStrata(int32_t);
void EnableEvents(void);
void HideFrame(CSimpleFrame*, int32_t);
void MoveOrResizeFrame(const CMouseEvent&);
void NotifyFrameLayerChanged(CSimpleFrame*, uint32_t);
void NotifyFrameMovedOrResized(CSimpleFrame*);
void OnLayerUpdate(float);
void OnLayerRender(void);
int32_t RaiseFrame(CSimpleFrame*, int32_t);
void RegisterForEvent(CSimpleFrame*, CSimpleEventType, int32_t, uint32_t);
void RegisterFrame(CSimpleFrame*);
void ShowFrame(CSimpleFrame*, int32_t);
int32_t StartMoveOrResizeFrame(const CMouseEvent&, MOVERESIZE_REASON, int32_t);
int32_t StartMoveOrResizeFrame(CSimpleFrame*, MOVERESIZE_REASON, float, float, int32_t);
int32_t StartMoveOrResizeFrame(CSimpleFrame*, MOVERESIZE_REASON, float, float, FRAMEPOINT);
void UnregisterForEvent(CSimpleFrame*, CSimpleEventType, int32_t);
};
#endif

1566
src/ui/FrameScript.cpp Normal file

File diff suppressed because it is too large Load diff

107
src/ui/FrameScript.hpp Normal file
View file

@ -0,0 +1,107 @@
#ifndef UI_FRAME_SCRIPT_HPP
#define UI_FRAME_SCRIPT_HPP
#include "ui/Types.hpp"
#include <cmath>
#include <cstdint>
#include <common/MD5.hpp>
#include <storm/Array.hpp>
#include <storm/Hash.hpp>
#include <storm/List.hpp>
#define NUM_GLUE_SCRIPT_EVENTS 41
class CImVector;
class CSimpleFrame;
class CStatus;
class FrameScript_Object;
struct lua_State;
struct SIMPLEFRAMENODE : TSLinkedNode<SIMPLEFRAMENODE> {
CSimpleFrame *frame;
};
struct EVENTLISTENERNODE : TSLinkedNode<EVENTLISTENERNODE> {
FrameScript_Object *listener;
};
class FrameScript_EventObject : public TSHashObject<FrameScript_EventObject, HASHKEY_STRI> {
public:
// Member variables
TSList<EVENTLISTENERNODE, TSGetLink<EVENTLISTENERNODE>> listeners;
TSList<EVENTLISTENERNODE, TSGetLink<EVENTLISTENERNODE>> unregisterListeners;
TSList<EVENTLISTENERNODE, TSGetLink<EVENTLISTENERNODE>> registerListeners;
uint32_t signalCount = 0;
uint32_t pendingSignalCount = 0;
// TODO performance counters
// Member functions
FrameScript_EventObject() : TSHashObject<FrameScript_EventObject, HASHKEY_STRI>() {};
const char* GetName(void);
};
extern const char* g_glueScriptEvents[41];
extern const char* g_scriptEvents[722];
namespace FrameScript {
extern void* s_mempool;
extern int32_t s_blocksizes[9];
extern lua_State* s_context;
extern int64_t s_scriptTimeUsed;
extern int32_t s_scriptProfileEnabled;
extern int32_t s_errorHandlerFun;
extern double_t s_scriptTimeDivisor;
extern int32_t s_errorHandlerRef;
extern int32_t s_recursiveTableHash;
extern char const* s_compat_lua;
extern int32_t s_pluralRule;
extern int32_t s_handlingError;
extern TSFixedArray<FrameScript_EventObject*> s_scriptEvents;
extern TSHashTable<FrameScript_EventObject, HASHKEY_STRI> s_scriptEventsHash;
}
int32_t FrameScript_CompileFunction(const char*, const char*, const char*, CStatus*);
void FrameScript_CreateEvents(const char*[], uint32_t);
void FrameScript_Destroy(void);
void FrameScript_Execute(const char*, const char*, const char*);
void FrameScript_Execute(int32_t, FrameScript_Object*, int32_t, const char*, FrameScript_EventObject*);
int32_t FrameScript_ExecuteBuffer(const char*, size_t, const char*, CStatus*, const char*);
int32_t FrameScript_ExecuteFile(const char*, const char*, MD5_CTX*, CStatus*);
void FrameScript_Flush(void);
void FrameScript_GetColor(lua_State* L, int32_t idx, CImVector& color);
lua_State* FrameScript_GetContext(void);
const char* FrameScript_GetCurrentObject(lua_State*, int32_t);
char const* FrameScript_GetText(const char*, int32_t, FRAMESCRIPT_GENDER);
int32_t FrameScript_GetVariable(const char*, const char**);
int32_t FrameScript_HandleError(lua_State*);
int32_t FrameScript_Initialize(int32_t);
void FrameScript_RegisterFunction(const char*, int32_t (*)(lua_State*));
void FrameScript_RegisterScriptEvent(FrameScript_Object*, FrameScript_EventObject*);
void FrameScript_SetPluralRule(PLURAL_RULE);
void FrameScript_SignalEvent(uint32_t, const char*, ...);
void FrameScript_UnregisterScriptEvent(FrameScript_Object*, FrameScript_EventObject*);
void GlueScriptEventsInitialize(void);
void ScriptEventsInitialize(void);
#endif

View file

@ -0,0 +1,10 @@
#ifndef UI_FRAME_SCRIPT_INTERNAL_HPP
#define UI_FRAME_SCRIPT_INTERNAL_HPP
#include "util/Lua.hpp"
namespace FrameScriptInternal {
extern luaL_Reg extra_funcs[31];
}
#endif

View file

@ -0,0 +1,189 @@
#include "ui/FrameScript_Object.hpp"
#include "util/Lua.hpp"
#include <cstdint>
#include <storm/String.hpp>
int32_t FrameScript_Object::s_objectTypes = 0;
int32_t FrameScript_Object::CreateScriptMetaTable(lua_State* L, void (*a2)(lua_State* L)) {
lua_createtable(L, 0, 0);
lua_pushstring(L, "__index");
lua_createtable(L, 0, 0);
a2(L);
lua_settable(L, -3);
return luaL_ref(L, LUA_REGISTRYINDEX);
}
void FrameScript_Object::FillScriptMethodTable(lua_State *L, FrameScript_Method methods[], int32_t count) {
for (int32_t i = 0; i < count; i++) {
lua_pushstring(L, methods[i].name);
lua_pushcclosure(L, methods[i].method, 0);
lua_settable(L, -3);
}
}
FrameScript_Object::~FrameScript_Object() {
if (this->m_onEvent.luaRef) {
luaL_unref(FrameScript_GetContext(), LUA_REGISTRYINDEX, this->m_onEvent.luaRef);
}
}
const char* FrameScript_Object::GetDisplayName() {
const char* name = this->GetName();
return name ? name : "<unnamed>";
}
FrameScript_Object::ScriptIx* FrameScript_Object::GetScriptByName(const char* name, FrameScript_Object::ScriptData& data) {
if (!SStrCmpI(name, "OnEvent", STORM_MAX_STR)) {
data.wrapper = "return function(self,event,...) %s end";
return &this->m_onEvent;
}
return nullptr;
}
int32_t FrameScript_Object::RegisterScriptEvent(const char* name) {
auto event = FrameScript::s_scriptEventsHash.Ptr(name);
if (!event) {
return 0;
}
if (event->pendingSignalCount) {
auto node = event->unregisterListeners.Head();
while (node) {
if (node->listener == this) {
break;
}
node = node->Next();
}
if (node) {
event->unregisterListeners.DeleteNode(node);
}
}
auto node = event->listeners.Head();
while (node) {
if (node->listener == this) {
break;
}
node = node->Next();
}
if (!node) {
FrameScript_RegisterScriptEvent(this, event);
}
return 1;
}
void FrameScript_Object::RegisterScriptObject(const char* name) {
auto L = FrameScript_GetContext();
if (!this->lua_registered) {
// TODO
// v4 = lua_taintexpected++ == -1;
// v5 = lua_tainted;
// if (!v4 && !lua_taintedclosure) {
// lua_tainted = 0;
// }
lua_createtable(L, 0, 0);
lua_pushnumber(L, 0.0);
lua_pushlightuserdata(L, this);
lua_rawset(L, -3);
int32_t metatable = this->GetScriptMetaTable();
lua_rawgeti(L, LUA_REGISTRYINDEX, metatable);
lua_setmetatable(L, -2);
this->lua_objectRef = luaL_ref(L, LUA_REGISTRYINDEX);
// TODO
// if (lua_taintexpected && !lua_taintedclosure) {
// lua_tainted = v5;
// }
// if (--lua_taintexpected <= 0) {
// lua_taintexpected = 0;
// }
}
this->lua_registered++;
if (name) {
int32_t v8 = 0;
lua_pushstring(L, name);
lua_rawget(L, LUA_GLOBALSINDEX);
if (lua_type(L, -1)) {
v8 = 1;
}
lua_settop(L, -2);
if (!v8) {
lua_rawgeti(L, LUA_REGISTRYINDEX, this->lua_objectRef);
lua_pushstring(L, name);
lua_insert(L, -2);
lua_rawset(L, LUA_GLOBALSINDEX);
}
}
}
void FrameScript_Object::RunScript(ScriptIx const& script, int32_t argCount, const char* a4) {
FrameScript_Execute(script.luaRef, this, argCount, a4 ? a4 : script.unk, nullptr);
}
void FrameScript_Object::UnregisterScriptObject(const char* name) {
auto L = FrameScript_GetContext();
if (this->lua_registered > 0) {
this->lua_registered--;
if (this->lua_registered == 0) {
lua_rawgeti(L, LUA_REGISTRYINDEX, this->lua_objectRef);
lua_pushnumber(L, 0.0);
lua_pushnil(L);
lua_rawset(L, -3);
lua_settop(L, -2);
luaL_unref(L, LUA_REGISTRYINDEX, this->lua_objectRef);
this->lua_objectRef = -2;
}
}
if (name) {
lua_pushnil(L);
lua_pushstring(L, name);
lua_insert(L, -2);
lua_rawset(L, LUA_GLOBALSINDEX);
}
}
FrameScript_Object* FrameScript_GetObjectThis(lua_State* L, int32_t type) {
if (lua_type(L, 1) != LUA_TTABLE) {
luaL_error(L, "Attempt to find 'this' in non-table object (used '.' instead of ':' ?)");
}
lua_rawgeti(L, 1, 0);
auto object = static_cast<FrameScript_Object*>(lua_touserdata(L, -1));
lua_settop(L, -2);
if (!object) {
luaL_error(L, "Attempt to find 'this' in non-framescript object");
}
if (!object->IsA(type)) {
luaL_error(L, "Wrong object type for member function");
}
return object;
}

View file

@ -0,0 +1,53 @@
#ifndef UI_FRAME_SCRIPT_OBJECT_HPP
#define UI_FRAME_SCRIPT_OBJECT_HPP
#include "ui/FrameScript.hpp"
#include <cstdint>
class FrameScript_Object {
public:
// Structs
struct ScriptData {
const char* wrapper;
};
struct ScriptIx {
int32_t luaRef = 0;
const char* unk = nullptr;
};
class ScriptFunction {
public:
int32_t luaRef = 0;
};
// Static members
static int32_t s_objectTypes;
// Static functions
static int32_t CreateScriptMetaTable(lua_State* L, void(*a2)(lua_State*));
static void FillScriptMethodTable(lua_State* L, FrameScript_Method methods[], int32_t count);
// Member variables
int32_t lua_registered = 0;
int32_t lua_objectRef = -2;
ScriptIx m_onEvent;
// Virtual member functions
virtual ~FrameScript_Object();
virtual char* GetName() = 0;
virtual int32_t GetScriptMetaTable() = 0;
virtual ScriptIx* GetScriptByName(const char* name, ScriptData& data);
virtual bool IsA(int32_t type) = 0;
// Member functions
const char* GetDisplayName();
int32_t RegisterScriptEvent(const char* name);
void RegisterScriptObject(const char* name);
void RunScript(ScriptIx const& script, int32_t argCount, const char* a4);
void UnregisterScriptObject(const char* name);
};
FrameScript_Object* FrameScript_GetObjectThis(lua_State* L, int32_t type);
#endif

633
src/ui/FrameXML.cpp Normal file
View file

@ -0,0 +1,633 @@
#include "ui/FrameXML.hpp"
#include "gx/Coordinate.hpp"
#include "ui/CSimpleButton.hpp"
#include "ui/CSimpleCheckbox.hpp"
#include "ui/CSimpleEditBox.hpp"
#include "ui/CSimpleFont.hpp"
#include "ui/CSimpleFrame.hpp"
#include "ui/CSimpleHTML.hpp"
#include "ui/CSimpleModel.hpp"
#include "ui/CSimpleScrollFrame.hpp"
#include "ui/CSimpleSlider.hpp"
#include "util/CStatus.hpp"
#include "util/SFile.hpp"
#include <cstdlib>
#include <cstring>
#include <common/XML.hpp>
#include <storm/String.hpp>
int32_t FrameXML::s_debugLevel;
TSHashTable<FrameFactoryNode, HASHKEY_STRI> FrameXML::s_factoryHash;
TSHashTable<HashedNode, HASHKEY_STRI> FrameXML::s_nodeHash;
CSimpleFrame* Create_SimpleButton(CSimpleFrame* parent) {
void* m = SMemAlloc(sizeof(CSimpleButton), __FILE__, __LINE__, 0);
// TODO
// void* m = CDataAllocator::GetData(CSimpleFrame::s_simpleButtonHeap, 0, __FILE__, __LINE__);
if (m) {
return new (m) CSimpleButton(parent);
} else {
return nullptr;
}
}
CSimpleFrame* Create_SimpleCheckButton(CSimpleFrame* parent) {
void* m = SMemAlloc(sizeof(CSimpleCheckbox), __FILE__, __LINE__, 0);
// TODO
// void* m = CDataAllocator::GetData(CSimpleCheckbox::s_simpleCheckboxHeap, 0, __FILE__, __LINE__);
if (m) {
return new (m) CSimpleCheckbox(parent);
} else {
return nullptr;
}
}
CSimpleFrame* Create_SimpleEditBox(CSimpleFrame* parent) {
void* m = SMemAlloc(sizeof(CSimpleEditBox), __FILE__, __LINE__, 0);
// TODO
// void* m = CDataAllocator::GetData(CSimpleEditBox::s_simpleEditBoxHeap, 0, __FILE__, __LINE__);
if (m) {
return new (m) CSimpleEditBox(parent);
} else {
return nullptr;
}
}
CSimpleFrame* Create_SimpleFrame(CSimpleFrame* parent) {
void* m = SMemAlloc(sizeof(CSimpleFrame), __FILE__, __LINE__, 0);
// TODO
// void* m = CDataAllocator::GetData(CSimpleFrame::s_simpleFrameHeap, 0, __FILE__, __LINE__);
if (m) {
return new (m) CSimpleFrame(parent);
} else {
return nullptr;
}
}
CSimpleFrame* Create_SimpleMessageFrame(CSimpleFrame* parent) {
// TODO
return nullptr;
}
CSimpleFrame* Create_SimpleModel(CSimpleFrame* parent) {
void* m = SMemAlloc(sizeof(CSimpleModel), __FILE__, __LINE__, 0);
// TODO
// void* m = CDataAllocator::GetData(CSimpleFrame::s_simpleModelHeap, 0, __FILE__, __LINE__);
if (m) {
return new (m) CSimpleModel(parent);
} else {
return nullptr;
}
}
CSimpleFrame* Create_SimpleScrollFrame(CSimpleFrame* parent) {
void* m = SMemAlloc(sizeof(CSimpleScrollFrame), __FILE__, __LINE__, 0);
// TODO
// void* m = CDataAllocator::GetData(CSimpleScrollFrame::s_simpleScrollHeap, 0, __FILE__, __LINE__);
if (m) {
return new (m) CSimpleScrollFrame(parent);
} else {
return nullptr;
}
}
CSimpleFrame* Create_SimpleScrollingMessageFrame(CSimpleFrame* parent) {
// TODO
return nullptr;
}
CSimpleFrame* Create_SimpleSlider(CSimpleFrame* parent) {
void* m = SMemAlloc(sizeof(CSimpleSlider), __FILE__, __LINE__, 0);
// TODO
// void* m = CDataAllocator::GetData(CSimpleSlider::s_simpleSliderHeap, 0, __FILE__, __LINE__);
if (m) {
return new (m) CSimpleSlider(parent);
} else {
return nullptr;
}
}
CSimpleFrame* Create_SimpleHTML(CSimpleFrame* parent) {
void* m = SMemAlloc(sizeof(CSimpleHTML), __FILE__, __LINE__, 0);
// TODO
// void* m = CDataAllocator::GetData(CSimpleHTML::s_simpleHTMLHeap, 0, __FILE__, __LINE__);
if (m) {
return new (m) CSimpleHTML(parent);
} else {
return nullptr;
}
}
CSimpleFrame* Create_SimpleStatusBar(CSimpleFrame* parent) {
// TODO
return nullptr;
}
CSimpleFrame* Create_SimpleColorSelect(CSimpleFrame* parent) {
// TODO
return nullptr;
}
CSimpleFrame* Create_SimpleMovieFrame(CSimpleFrame* parent) {
// TODO
return nullptr;
}
XMLNode* FrameXML_AcquireHashNode(const char* name, const char*& tainted, bool& locked) {
HashedNode* hashedNode = FrameXML::s_nodeHash.Ptr(name);
if (!hashedNode) {
return nullptr;
}
locked = hashedNode->locked;
tainted = hashedNode->tainted;
hashedNode->locked = true;
return hashedNode->node;
}
int32_t FrameXML_CheckSignature(const char* tocPath, const char* a2, const unsigned char* key, unsigned char* digest) {
// TODO
return 3;
}
/**
* Find and return the appropriate parent name.
*
* Parent priorities:
* 1. parent attribute on local node
* 2. parent attribute on last inherited node with parent attribute present
*/
const char* FindParent(XMLNode* node) {
const char* parentName = node->GetAttributeByName("parent");
if (parentName && *parentName) {
return parentName;
}
const char* inheritNames = node->GetAttributeByName("inherits");
if (!inheritNames || !*inheritNames) {
return nullptr;
}
char inheritName[1024];
do {
SStrTokenize(&inheritNames, inheritName, 0x400u, " ,", 0);
if (!*inheritName) {
break;
}
auto hashedNode = FrameXML::s_nodeHash.Ptr(inheritName);
if (hashedNode) {
auto inheritNode = hashedNode->node;
int32_t v10 = hashedNode->locked;
hashedNode->locked = true;
if (inheritNode && !v10) {
parentName = inheritNode->GetAttributeByName("parent");
FrameXML::s_nodeHash.Ptr(inheritName)->locked = false;
}
}
} while (*inheritName);
return parentName;
}
CSimpleFrame* FrameXML_CreateFrame(XMLNode* node, CSimpleFrame* parent, CStatus* status) {
if (FrameXML::s_debugLevel > 0) {
const char* name = node->GetAttributeByName("name");
if (name && *name) {
status->Add(STATUS_INFO, "-- Creating %s named %s", node->m_name.m_str, name);
} else {
status->Add(STATUS_INFO, "-- Creating unnamed %s", node->m_name.m_str);
}
}
auto factoryNode = FrameXML::s_factoryHash.Ptr(node->m_name.m_str);
if (!factoryNode) {
status->Add(STATUS_WARNING, "Unknown frame type: %s", node->m_name.m_str);
return nullptr;
}
const char* parentName = FindParent(node);
if (parentName && *parentName) {
int32_t parentType = CSimpleFrame::GetObjectType();
parent = static_cast<CSimpleFrame*>(CScriptObject::GetScriptObjectByName(parentName, parentType));
if (!parent) {
status->Add(STATUS_WARNING, "Couldn't find frame parent: %s", parentName);
}
}
CSimpleFrame* frame = factoryNode->m_factory(parent);
if (frame) {
if (factoryNode->m_unique) {
// TODO
// Delete the factory node
// sub_565030(factoryNode);
// FrameXML::s_factoryHash.InternalDelete(factoryNode);
}
frame->PreLoadXML(node, status);
frame->LoadXML(node, status);
frame->PostLoadXML(node, status);
return frame;
} else {
status->Add(STATUS_WARNING, "Unable to create frame type: %s", node->m_name.m_str);
return nullptr;
}
}
int32_t FrameXML_CreateFrames(const char* tocPath, const char* a2, MD5_CTX* md5, CStatus* status) {
if (!status) {
status = new CStatus;
}
char v15[260];
v15[0] = 0;
memset(v15 + 1, 0, 259);
const char* v5 = tocPath;
const char* v6 = SStrChrR(tocPath, '\\');
if (v6) {
uintptr_t v7 = v6 - tocPath + 1;
uintptr_t v8 = v7;
if (v7 < 259) {
SStrCopy(v15, tocPath, v7 + 1);
v15[v8] = 0;
}
}
void* tocBuffer;
size_t tocBytes;
if (!SFile::Load(nullptr, tocPath, &tocBuffer, &tocBytes, 1, 1, nullptr)) {
status->Add(STATUS_ERROR, "Couldn't open %s", a2);
return 0;
}
MD5Update(md5, static_cast<unsigned char*>(tocBuffer), tocBytes);
const char* tocData = static_cast<char*>(tocBuffer);
// Advance past UTF-8 BOM if present
if (*tocData == static_cast<char>(0xEF) && *(tocData + 1) == static_cast<char>(0xBB) && *(tocData + 2) == static_cast<char>(0xBF)) {
tocData = tocData + 3;
}
CStatus v21;
char tocLine[1024];
char tocEntryPath[260];
do {
SStrTokenize(&tocData, tocLine, 1024, "\r\n", 0);
if (!*tocLine) {
break;
}
if (*tocLine == '#') {
continue;
}
SStrCopy(tocEntryPath, v15, 260);
SStrPack(tocEntryPath, tocLine, 260);
size_t v10 = SStrLen(tocEntryPath);
bool v11 = tocEntryPath[v10 - 1] == ' ';
char* v12 = &tocEntryPath[v10];
if (v11) {
do {
if (v12 <= tocEntryPath) {
break;
}
--v12;
} while (*(v12 - 1) == ' ');
}
*v12 = 0;
FrameXML_ProcessFile(tocEntryPath, a2, md5, &v21);
// TODO
// if (s_progressCallback && s_progressFiles < s_progressTotal) {
// ++s_progressFiles;
// v20 = s_progressTotal;
// v13 = (double)(unsigned int)s_progressFiles / (double)(unsigned int)s_progressTotal;
// s_progressCallback(LODWORD(v13), s_progressParam);
// v5 = a2;
// }
} while (*tocLine);
// TODO
// XMLTree_Cleanup();
SFile::Unload(tocBuffer);
// TODO
// if (s_debugLevel > 0 || v25 > 0) {
// v21.Prepend(STATUS_INFO, "** Loading table of contents %s", v5);
// }
// TODO
// status->Add(v21);
return 1;
}
void FrameXML_FreeHashNodes() {
FrameXML::s_nodeHash.Clear();
}
XMLTree* FrameXML_LoadXML(const char* filePath, MD5_CTX* md5, CStatus* status) {
void* xmlBuffer;
size_t xmlBytes;
if (SFile::Load(nullptr, filePath, &xmlBuffer, &xmlBytes, 0, 1, nullptr)) {
MD5Update(md5, static_cast<unsigned char*>(xmlBuffer), xmlBytes);
XMLTree* tree = XMLTree_Load(static_cast<char*>(xmlBuffer), xmlBytes);
if (!tree) {
status->Add(STATUS_ERROR, "Couldn't parse XML in %s", filePath);
}
SFile::Unload(xmlBuffer);
return tree;
} else {
status->Add(STATUS_ERROR, "Couldn't open %s", filePath);
return nullptr;
}
}
int32_t FrameXML_ProcessFile(const char* filePath, const char* a2, MD5_CTX* md5, CStatus* status) {
const char* v5 = filePath;
char v25[260];
char* i;
char* j;
// Deal with relative file paths
if (SStrStr(filePath, "..")) {
SStrCopy(v25, filePath, 260);
for (i = (char*)SStrStr(v25, ".."); i; i = (char*)SStrStr(v25, "..")) {
char v7 = *(i - 1);
if (v7 != '\\' && v7 != '/') {
break;
}
char v8 = i[2];
if (v8 != '\\' && v8 != '/') {
break;
}
for (j = i - 2; j >= v25; --j) {
if (*j == '\\') {
break;
}
if (*j == '/') {
break;
}
}
SStrCopy(j + 1, i + 3, 0x7FFFFFFF);
}
filePath = v25;
v5 = v25;
}
const char* v10 = SStrChrR(v5, '.');
// If file ends in .lua, execute it and return
if (v10 && !SStrCmpI(v10, ".lua", 0x7FFFFFFFu)) {
return FrameScript_ExecuteFile(v5, a2, md5, status);
}
// Assume all other files are xml
XMLTree* tree = FrameXML_LoadXML(v5, md5, status);
if (!tree) {
return 0;
}
CStatus unkStatus;
XMLNode* node = XMLTree_GetRoot(tree)->m_child;
char v26[271];
char v27[264];
// TODO
// Should come from some kind of Lua headers
const char* lua_tainted = nullptr;
while (node) {
// <Include>
if (!SStrCmpI(node->GetName(), "Include", 0x7FFFFFFFu)) {
const char* v14 = node->GetAttributeByName("file");
if (v14) {
const char* v15 = SStrChrR(v5, 92);
if (v15) {
uint32_t v13 = v15 - v5 + 1;
if (v13 < 260 ) {
SStrCopy(v27, v5, 260);
v27[v13] = 0;
SStrPack(v27, v14, 260);
}
} else {
SStrCopy(v27, v14, 260);
}
FrameXML_ProcessFile(v27, a2, md5, &unkStatus);
} else {
unkStatus.Add(STATUS_ERROR, "Element 'Include' without file attribute");
}
// <Script>
} else if (!SStrCmpI(node->GetName(), "Script", 0x7FFFFFFFu)) {
const char* v16 = node->GetAttributeByName("file");
if (v16) {
const char* v17 = SStrChrR(v5, 92);
if (v17) {
uint32_t v18 = v17 - v5 + 1;
if (v18 < 260) {
SStrCopy(v27, filePath, 260);
v27[v18] = 0;
SStrPack(v27, v16, 260);
}
v5 = filePath;
} else {
SStrCopy(v27, v16, 260);
}
FrameScript_ExecuteFile(v27, a2, md5, &unkStatus);
}
char* v19 = node->m_body;
if (v19 && *v19) {
SStrPrintf(v26, 271, "%s:<Scripts>", v5);
FrameScript_Execute(v19, v26, lua_tainted);
}
// <Font>
} else if (!SStrCmpI(node->GetName(), "Font", 0x7FFFFFFFu)) {
const char* fontName = node->GetAttributeByName("name");
if (fontName && *fontName) {
CSimpleFont* font = CSimpleFont::GetFont(fontName, 1);
font->LoadXML(node, status);
} else {
unkStatus.Add(STATUS_WARNING, "Unnamed font node at top level");
}
// Everything else (frame nodes)
} else {
const char* v22 = node->GetAttributeByName("virtual");
if (!v22 || SStrCmpI(v22, "true", 0x7FFFFFFFu)) {
FrameXML_CreateFrame(node, nullptr, &unkStatus);
// TODO
// CLayoutFrame::ResizePending();
} else {
const char* v23 = node->GetAttributeByName("name");
if (v23 && *v23) {
FrameXML_StoreHashNode(node, v23, lua_tainted, &unkStatus);
} else {
unkStatus.Add(STATUS_WARNING, "Unnamed virtual node at top level");
}
}
}
node = node->m_next;
}
XMLTree_Free(tree);
// TODO
// if (s_debugLevel > 0 || v34 > 0) {
// unkStatus.Prepend(STATUS_INFO, "++ Loading file %s", v5);
// }
// TODO
// status->Unk8(unkStatus);
return 1;
}
int32_t FrameXML_RegisterFactory(const char* type, CSimpleFrame* (*factory)(CSimpleFrame*), bool a3) {
if (FrameXML::s_factoryHash.Ptr(type)) {
// Already registered
return 0;
}
FrameFactoryNode* node = FrameXML::s_factoryHash.New(type, 0, 0);
node->m_factory = factory;
node->m_unique = a3;
return 1;
}
void FrameXML_RegisterDefault() {
FrameXML_RegisterFactory("Button", &Create_SimpleButton, 0);
FrameXML_RegisterFactory("CheckButton", &Create_SimpleCheckButton, 0);
FrameXML_RegisterFactory("EditBox", &Create_SimpleEditBox, 0);
FrameXML_RegisterFactory("Frame", &Create_SimpleFrame, 0);
FrameXML_RegisterFactory("MessageFrame", &Create_SimpleMessageFrame, 0);
FrameXML_RegisterFactory("Model", &Create_SimpleModel, 0);
FrameXML_RegisterFactory("ScrollFrame", &Create_SimpleScrollFrame, 0);
FrameXML_RegisterFactory("ScrollingMessageFrame", &Create_SimpleScrollingMessageFrame, 0);
FrameXML_RegisterFactory("Slider", &Create_SimpleSlider, 0);
FrameXML_RegisterFactory("SimpleHTML", &Create_SimpleHTML, 0);
FrameXML_RegisterFactory("StatusBar", &Create_SimpleStatusBar, 0);
FrameXML_RegisterFactory("ColorSelect", &Create_SimpleColorSelect, 0);
FrameXML_RegisterFactory("MovieFrame", &Create_SimpleMovieFrame, 0);
}
void FrameXML_ReleaseHashNode(const char* name) {
HashedNode* hashedNode = FrameXML::s_nodeHash.Ptr(name);
hashedNode->locked = false;
}
void FrameXML_StoreHashNode(XMLNode* node, const char* name, const char* a3, CStatus* status) {
HashedNode* hashed = FrameXML::s_nodeHash.Ptr(name);
if (hashed) {
if (!hashed->tainted || a3) {
status->Add(STATUS_WARNING, "Virtual object named %s already exists", name);
return;
}
XMLNode *v6 = hashed->node;
if (v6) {
delete v6;
// TODO
// CDataAllocator::PutData((int)XMLNode::s_XMLNodeHeap, v6, 0, 0);
}
} else {
HashedNode* hashed = FrameXML::s_nodeHash.New(name, 0, 0);
hashed->node = node;
hashed->tainted = a3;
}
// TODO
// sub_814650(a1);
if (FrameXML::s_debugLevel > 0) {
status->Add(STATUS_INFO, "-- Added virtual frame %s", name);
}
}

55
src/ui/FrameXML.hpp Normal file
View file

@ -0,0 +1,55 @@
#ifndef UI_FRAME_XML_HPP
#define UI_FRAME_XML_HPP
#include <common/MD5.hpp>
#include <storm/Hash.hpp>
class CSimpleFrame;
class CStatus;
class XMLNode;
class XMLTree;
class FrameFactoryNode : public TSHashObject<FrameFactoryNode, HASHKEY_STRI> {
public:
CSimpleFrame* (*m_factory)(CSimpleFrame*);
uint32_t m_unique;
FrameFactoryNode() : TSHashObject<FrameFactoryNode, HASHKEY_STRI>() {};
};
class HashedNode : public TSHashObject<HashedNode, HASHKEY_STRI> {
public:
XMLNode* node;
const char* tainted;
uint32_t locked;
};
namespace FrameXML {
extern int32_t s_debugLevel;
extern TSHashTable<FrameFactoryNode, HASHKEY_STRI> s_factoryHash;
extern TSHashTable<HashedNode, HASHKEY_STRI> s_nodeHash;
}
XMLNode* FrameXML_AcquireHashNode(const char*, const char*&, bool&);
int32_t FrameXML_CheckSignature(const char*, const char*, const unsigned char*, unsigned char*);
CSimpleFrame* FrameXML_CreateFrame(XMLNode*, CSimpleFrame*, CStatus*);
int32_t FrameXML_CreateFrames(const char*, const char*, MD5_CTX*, CStatus*);
void FrameXML_FreeHashNodes(void);
XMLTree* FrameXML_LoadXML(const char*, MD5_CTX*, CStatus*);
int32_t FrameXML_ProcessFile(const char*, const char*, MD5_CTX*, CStatus*);
void FrameXML_RegisterDefault(void);
int32_t FrameXML_RegisterFactory(const char*, CSimpleFrame* (*)(CSimpleFrame*), bool);
void FrameXML_ReleaseHashNode(const char*);
void FrameXML_StoreHashNode(XMLNode*, const char*, const char*, CStatus*);
#endif

5
src/ui/Interface.cpp Normal file
View file

@ -0,0 +1,5 @@
#include "ui/Interface.hpp"
void DeleteInterfaceFiles(void) {
// TODO
}

6
src/ui/Interface.hpp Normal file
View file

@ -0,0 +1,6 @@
#ifndef UI_INTERFACE_HPP
#define UI_INTERFACE_HPP
void DeleteInterfaceFiles(void);
#endif

334
src/ui/LoadXML.cpp Normal file
View file

@ -0,0 +1,334 @@
#include "ui/LoadXML.hpp"
#include "gx/Coordinate.hpp"
#include "ui/CSimpleFontString.hpp"
#include "ui/CSimpleTexture.hpp"
#include "util/CStatus.hpp"
#include <common/XML.hpp>
#include <storm/String.hpp>
int32_t LoadXML_Color(XMLNode* node, CImVector& color) {
float r = 0.0f;
float g = 0.0f;
float b = 0.0f;
float a = 1.0f;
auto rAttr = node->GetAttributeByName("r");
if (rAttr && *rAttr) {
if (SStrToFloat(rAttr) <= 0.0f) {
r = 0.0f;
} else if (SStrToFloat(rAttr) >= 1.0f) {
r = 1.0f;
} else {
r = SStrToFloat(rAttr);
}
}
auto gAttr = node->GetAttributeByName("g");
if (gAttr && *gAttr) {
if (SStrToFloat(gAttr) <= 0.0f) {
g = 0.0f;
} else if (SStrToFloat(gAttr) >= 1.0f) {
g = 1.0f;
} else {
g = SStrToFloat(gAttr);
}
}
auto bAttr = node->GetAttributeByName("b");
if (bAttr && *bAttr) {
if (SStrToFloat(bAttr) <= 0.0f) {
b = 0.0f;
} else if (SStrToFloat(bAttr) >= 1.0f) {
b = 1.0f;
} else {
b = SStrToFloat(bAttr);
}
}
auto aAttr = node->GetAttributeByName("a");
if (aAttr && *aAttr) {
if (SStrToFloat(aAttr) <= 0.0f) {
a = 0.0f;
} else if (SStrToFloat(aAttr) >= 1.0f) {
a = 1.0f;
} else {
a = SStrToFloat(aAttr);
}
}
color.Set(a, r, g, b);
return 1;
}
int32_t LoadXML_Dimensions(XMLNode* node, float& x, float& y, CStatus* status) {
const char* xAttr = node->GetAttributeByName("x");
if (xAttr && *xAttr) {
float v18 = SStrToFloat(xAttr);
float v6 = v18 / (CoordinateGetAspectCompensation() * 1024.0f);
x = NDCToDDCWidth(v6);
}
const char* yAttr = node->GetAttributeByName("y");
if (yAttr && *yAttr) {
float v19 = SStrToFloat(yAttr);
float v9 = v19 / (CoordinateGetAspectCompensation() * 1024.0f);
y = NDCToDDCWidth(v9);
}
XMLNode* childNode = node->m_child;
if (!childNode) {
return yAttr != nullptr;
}
if (!SStrCmpI(childNode->GetName(), "RelDimension", 0x7FFFFFFF)) {
const char* xAttrRel = childNode->GetAttributeByName("x");
if (xAttrRel && *xAttrRel) {
x = SStrToFloat(xAttrRel);
}
const char* yAttrRel = childNode->GetAttributeByName("y");
if (yAttrRel && *yAttrRel) {
y = SStrToFloat(yAttrRel);
}
return 1;
} else if (!SStrCmpI(childNode->GetName(), "AbsDimension", 0x7FFFFFFF)) {
const char* xAttrAbs = childNode->GetAttributeByName("x");
if (xAttrAbs && *xAttrAbs) {
float v20 = SStrToFloat(xAttrAbs);
float v13 = v20 / (CoordinateGetAspectCompensation() * 1024.0f);
x = NDCToDDCWidth(v13);
}
const char* yAttrAbs = childNode->GetAttributeByName("y");
if (yAttrAbs && *yAttrAbs) {
float v21 = SStrToFloat(yAttrAbs);
float v15 = v21 / (CoordinateGetAspectCompensation() * 1024.0f);
y = NDCToDDCWidth(v15);
}
return 1;
} else {
status->Add(
STATUS_WARNING,
"Unknown child node in %s element: %s",
node->GetName(),
childNode->GetName()
);
return 0;
}
}
int32_t LoadXML_Insets(XMLNode* node, float& left, float& right, float& top, float& bottom, CStatus* status) {
left = 0.0f;
right = 0.0f;
top = 0.0f;
bottom = 0.0f;
const char* leftAttr = node->GetAttributeByName("left");
if (leftAttr && *leftAttr) {
float l = SStrToFloat(leftAttr);
float ndcl = l / (CoordinateGetAspectCompensation() * 1024.0f);
left = NDCToDDCWidth(ndcl);
}
const char* rightAttr = node->GetAttributeByName("right");
if (rightAttr && *rightAttr) {
float r = SStrToFloat(rightAttr);
float ndcr = r / (CoordinateGetAspectCompensation() * 1024.0f);
right = NDCToDDCWidth(ndcr);
}
const char* topAttr = node->GetAttributeByName("top");
if (topAttr && *topAttr) {
float t = SStrToFloat(topAttr);
float ndct = t / (CoordinateGetAspectCompensation() * 1024.0f);
top = NDCToDDCWidth(ndct);
}
const char* bottomAttr = node->GetAttributeByName("bottom");
if (bottomAttr && *bottomAttr) {
float b = SStrToFloat(bottomAttr);
float ndcb = b / (CoordinateGetAspectCompensation() * 1024.0f);
bottom = NDCToDDCWidth(ndcb);
}
auto child = node->m_child;
if (!child) {
if (!bottomAttr) {
status->Add(
STATUS_WARNING,
"No \"right\", \"left\", \"top\", or \"bottom\" attributes in element: %s",
node->GetName()
);
return 0;
}
return 1;
}
if (!SStrCmpI(child->GetName(), "AbsInset", STORM_MAX_STR)) {
const char* leftAttr = child->GetAttributeByName("left");
if (leftAttr && *leftAttr) {
float l = SStrToFloat(leftAttr);
float ndcl = l / (CoordinateGetAspectCompensation() * 1024.0f);
left = NDCToDDCWidth(ndcl);
}
const char* rightAttr = child->GetAttributeByName("right");
if (rightAttr && *rightAttr) {
float r = SStrToFloat(rightAttr);
float ndcr = r / (CoordinateGetAspectCompensation() * 1024.0f);
right = NDCToDDCWidth(ndcr);
}
const char* topAttr = child->GetAttributeByName("top");
if (topAttr && *topAttr) {
float t = SStrToFloat(topAttr);
float ndct = t / (CoordinateGetAspectCompensation() * 1024.0f);
top = NDCToDDCWidth(ndct);
}
const char* bottomAttr = child->GetAttributeByName("bottom");
if (bottomAttr && *bottomAttr) {
float b = SStrToFloat(bottomAttr);
float ndcb = b / (CoordinateGetAspectCompensation() * 1024.0f);
bottom = NDCToDDCWidth(ndcb);
}
return 1;
}
if (!SStrCmpI(child->GetName(), "RelInset", STORM_MAX_STR)) {
const char* leftAttr = child->GetAttributeByName("left");
if (leftAttr && *leftAttr) {
left = SStrToFloat(leftAttr);
}
const char* rightAttr = child->GetAttributeByName("right");
if (rightAttr && *rightAttr) {
right = SStrToFloat(rightAttr);
}
const char* topAttr = child->GetAttributeByName("top");
if (topAttr && *topAttr) {
top = SStrToFloat(topAttr);
}
const char* bottomAttr = child->GetAttributeByName("bottom");
if (bottomAttr && *bottomAttr) {
bottom = SStrToFloat(bottomAttr);
}
return 1;
}
status->Add(
STATUS_WARNING,
"Unknown child node in %s element: %s",
child->GetName()
);
return 0;
}
CSimpleFontString* LoadXML_String(XMLNode* node, CSimpleFrame* frame, CStatus* status) {
// TODO
// v3 = CDataAllocator::GetData(CSimpleFontString::s_allocator, 0, a__avcsimplefon, -2);
void* m = SMemAlloc(sizeof(CSimpleFontString), __FILE__, __LINE__, 0);
CSimpleFontString* fontString;
if (m) {
fontString = new (m) CSimpleFontString(frame, 2, 1);
} else {
fontString = NULL;
}
fontString->PreLoadXML(node, status);
fontString->LoadXML(node, status);
fontString->PostLoadXML(node, status);
return fontString;
}
CSimpleTexture* LoadXML_Texture(XMLNode* node, CSimpleFrame* frame, CStatus* status) {
// TODO
// v3 = (CSimpleTexture *)CDataAllocator::GetData((int)CSimpleTexture::s_allocator, 0, a__avcsimpletex, -2);
void* m = SMemAlloc(sizeof(CSimpleTexture), __FILE__, __LINE__, 0);
CSimpleTexture* texture;
if (m) {
texture = new (m) CSimpleTexture(frame, 2, 1);
} else {
texture = NULL;
}
texture->PreLoadXML(node, status);
texture->LoadXML(node, status);
texture->PostLoadXML(node, status);
return texture;
}
int32_t LoadXML_Value(XMLNode* node, float& value, CStatus* status) {
value = 0.0;
const char* v4 = node->GetAttributeByName("val");
if (v4 && *v4) {
float v = SStrToFloat(v4);
float ndc = v / (CoordinateGetAspectCompensation() * 1024.0);
value = NDCToDDCWidth(ndc);
}
XMLNode* child = node->m_child;
if (!child) {
if (v4) {
return 1;
} else {
status->Add(STATUS_WARNING, "No \"val\" attribute in element: %s", node->GetName());
return 0;
}
}
if (!SStrCmpI(child->GetName(), "AbsValue", 0x7FFFFFFF)) {
const char* v9 = child->GetAttributeByName("val");
if (v9 && *v9) {
float v = SStrToFloat(v9);
float ndc = v / (CoordinateGetAspectCompensation() * 1024.0);
value = NDCToDDCWidth(ndc);
}
return 1;
} else if (!SStrCmpI(child->GetName(), "RelValue", 0x7FFFFFFF)) {
const char* v11 = child->GetAttributeByName("val");
if (v11 && *v11) {
value = SStrToFloat(v11);
}
return 1;
} else {
status->Add(STATUS_WARNING, "Unknown child node in %s element: %s", child->GetName(), node->GetName());
return 0;
}
}

25
src/ui/LoadXML.hpp Normal file
View file

@ -0,0 +1,25 @@
#ifndef UI_LOAD_XML_HPP
#define UI_LOAD_XML_HPP
#include <cstdint>
class CSimpleFontString;
class CSimpleFrame;
class CSimpleTexture;
class CStatus;
class XMLNode;
class CImVector;
int32_t LoadXML_Color(XMLNode*, CImVector&);
int32_t LoadXML_Dimensions(XMLNode*, float&, float&, CStatus*);
int32_t LoadXML_Insets(XMLNode*, float&, float&, float&, float&, CStatus*);
CSimpleFontString* LoadXML_String(XMLNode*, CSimpleFrame*, CStatus*);
CSimpleTexture* LoadXML_Texture(XMLNode*, CSimpleFrame*, CStatus*);
int32_t LoadXML_Value(XMLNode*, float&, CStatus*);
#endif

171
src/ui/LuaExtraFuncs.cpp Normal file
View file

@ -0,0 +1,171 @@
#include "ui/LuaExtraFuncs.hpp"
#include "ui/FrameScript.hpp"
#include "ui/FrameScriptInternal.hpp"
#include "util/Lua.hpp"
#include "util/Unimplemented.hpp"
#include <cstdint>
luaL_Reg FrameScriptInternal::extra_funcs[31] = {
{ "setglobal", &sub_8168D0 },
{ "getglobal", &sub_816910 },
{ "strtrim", &strtrim },
{ "strsplit", &strsplit },
{ "strjoin", &strjoin },
{ "strreplace", &sub_816C40 },
{ "strconcat", &sub_816D80 },
{ "strlenutf8", &strlenutf8 },
{ "issecure", &issecure },
{ "issecurevariable", &issecurevariable },
{ "forceinsecure", &forceinsecure },
{ "securecall", &securecall },
{ "hooksecurefunc", &hooksecurefunc },
{ "debugload", &debugload },
{ "debuginfo", &debuginfo },
{ "debugprint", &debugprint },
{ "debugdump", &debugdump },
{ "debugbreak", &debugbreak },
{ "debughook", &debughook },
{ "debugtimestamp", &debugtimestamp },
{ "debugprofilestart", &debugprofilestart },
{ "debugprofilestop", &debugprofilestop },
{ "seterrorhandler", &seterrorhandler },
{ "geterrorhandler", &geterrorhandler },
{ "date", &os_date },
{ "time", &os_time },
{ "difftime", &os_difftime },
{ "debugstack", &debugstack },
{ "debuglocals", &debuglocals },
{ "scrub", &scrub },
{ NULL, NULL }
};
int32_t sub_8168D0(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t sub_816910(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t strtrim(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t strsplit(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t strjoin(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t sub_816C40(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t sub_816D80(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t strlenutf8(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t issecure(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t issecurevariable(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t forceinsecure(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t securecall(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t hooksecurefunc(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debugload(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debuginfo(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debugprint(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debugdump(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debugbreak(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debughook(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debugtimestamp(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debugprofilestart(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debugprofilestop(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t seterrorhandler(lua_State* L) {
if (lua_type(L, 1) != LUA_TFUNCTION) {
luaL_error(L, "Usage: seterrorhandler(errfunc)");
return 0;
}
if (FrameScript::s_errorHandlerFun != -1) {
luaL_unref(L, LUA_REGISTRYINDEX, FrameScript::s_errorHandlerFun);
}
FrameScript::s_errorHandlerFun = luaL_ref(L, LUA_REGISTRYINDEX);
return 0;
}
int32_t geterrorhandler(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t os_date(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t os_time(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t os_difftime(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debugstack(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t debuglocals(lua_State* L) {
WHOA_UNIMPLEMENTED();
}
int32_t scrub(lua_State* L) {
WHOA_UNIMPLEMENTED();
}

39
src/ui/LuaExtraFuncs.hpp Normal file
View file

@ -0,0 +1,39 @@
#ifndef UI_LUA_EXTRA_FUNCS_HPP
#define UI_LUA_EXTRA_FUNCS_HPP
#include <cstdint>
struct lua_State;
int32_t sub_8168D0(lua_State*);
int32_t sub_816910(lua_State*);
int32_t strtrim(lua_State*);
int32_t strsplit(lua_State*);
int32_t strjoin(lua_State*);
int32_t sub_816C40(lua_State*);
int32_t sub_816D80(lua_State*);
int32_t strlenutf8(lua_State*);
int32_t issecure(lua_State*);
int32_t issecurevariable(lua_State*);
int32_t forceinsecure(lua_State*);
int32_t securecall(lua_State*);
int32_t hooksecurefunc(lua_State*);
int32_t debugload(lua_State*);
int32_t debuginfo(lua_State*);
int32_t debugprint(lua_State*);
int32_t debugdump(lua_State*);
int32_t debugbreak(lua_State*);
int32_t debughook(lua_State*);
int32_t debugtimestamp(lua_State*);
int32_t debugprofilestart(lua_State*);
int32_t debugprofilestop(lua_State*);
int32_t seterrorhandler(lua_State*);
int32_t geterrorhandler(lua_State*);
int32_t os_date(lua_State*);
int32_t os_time(lua_State*);
int32_t os_difftime(lua_State*);
int32_t debugstack(lua_State*);
int32_t debuglocals(lua_State*);
int32_t scrub(lua_State*);
#endif

138
src/ui/LuaMemory.cpp Normal file
View file

@ -0,0 +1,138 @@
#include "ui/LuaMemory.hpp"
#include "ui/FrameScript.hpp"
#include <cstring>
#include <new>
#include <common/MemPool.hpp>
#include <storm/Memory.hpp>
void* luaM_initPool() {
void* v0 = SMemAlloc(sizeof(MemPool*) * 9, ".\\src\\lmemPool.cpp", 243, 0);
MemPool** pools = (MemPool**)v0;
uint32_t v2 = 0;
void* v3;
MemPool* v4;
size_t v5;
size_t v6;
do {
v3 = SMemAlloc(sizeof(MemPool), ".\\src\\lmemPool.cpp", 245, 0);
if (v3) {
v4 = new (v3) MemPool();
} else {
v4 = 0;
}
pools[v2] = v4;
v5 = FrameScript::s_blocksizes[v2];
v6 = FrameScript::s_blocksizes[v2] << 10;
v4->Init(v5, v6);
++v2;
} while (v2 < 9);
return pools;
}
void* luaM_reallocPool(void* ud, void *ptr, size_t osize, size_t nsize) {
void* result; // eax
signed int v5; // esi
signed int v6; // edx
signed int v7; // ecx
signed int v8; // ecx
void *v9; // eax
void *v10; // edi
size_t v11; // eax
signed int v12; // [esp+Ch] [ebp-4h]
MemPool** mempool = (MemPool**)ud;
result = ptr;
v5 = -1;
v6 = -1;
v12 = -1;
if (ptr) {
v7 = 0;
while (osize > FrameScript::s_blocksizes[v7]) {
if (++v7 >= 9) {
goto LABEL_7;
}
}
v12 = v7;
v5 = v7;
}
LABEL_7:
if (nsize) {
v8 = 0;
while (nsize > FrameScript::s_blocksizes[v8]) {
if (++v8 >= 9) {
goto LABEL_18;
}
}
v6 = v8;
LABEL_18:
if (v5 == v6) {
if (v5 < 0) {
result = SMemReAlloc(ptr, nsize, ".\\src\\lmemPool.cpp", 311, 0);
}
} else {
if (v6 < 0) {
v9 = SMemAlloc(nsize, ".\\src\\lmemPool.cpp", 326, 0);
} else {
// Pretty sure: MemPool::MemAlloc
// v9 = sub_855820(*((_DWORD *)a1 + v6));
v9 = mempool[v6]->MemAlloc();
}
v10 = v9;
if (ptr) {
v11 = osize;
if (osize >= nsize) {
v11 = nsize;
}
memcpy(v10, ptr, v11);
if (v12 >= 0) {
// Pretty sure: MemPool::MemFree
// sub_855670(*((_DWORD *)a1 + v12), ptr);
mempool[v12]->MemFree(ptr);
return v10;
}
SMemFree(ptr, ".\\src\\lmemPool.cpp", 338, 0);
}
result = v10;
}
} else {
if (ptr) {
if (v5 >= 0) {
// Pretty sure: MemPool::MemFree
// sub_855670(*((_DWORD *)a1 + v5), ptr);
mempool[v5]->MemFree(ptr);
return 0;
}
SMemFree(ptr, ".\\src\\lmemPool.cpp", 276, 0);
}
result = 0;
}
return result;
}

9
src/ui/LuaMemory.hpp Normal file
View file

@ -0,0 +1,9 @@
#ifndef UI_LUA_MEMORY_HPP
#define UI_LUA_MEMORY_HPP
#include <cstdlib>
void* luaM_initPool(void);
void* luaM_reallocPool(void*, void*, size_t, size_t);
#endif

View file

@ -0,0 +1,92 @@
#include "ui/ScriptFunctions.hpp"
#include "ui/CSimpleButton.hpp"
#include "ui/CSimpleCheckbox.hpp"
#include "ui/CSimpleEditBox.hpp"
#include "ui/CSimpleFont.hpp"
#include "ui/CSimpleFontString.hpp"
#include "ui/CSimpleFrame.hpp"
#include "ui/CSimpleHTML.hpp"
#include "ui/CSimpleModel.hpp"
#include "ui/CSimpleModelFFX.hpp"
#include "ui/CSimpleScrollFrame.hpp"
#include "ui/CSimpleSlider.hpp"
#include "ui/CSimpleTexture.hpp"
#include "ui/FrameScript.hpp"
void CharacterCreateRegisterScriptFunctions() {
for (int32_t i = 0; i < NUM_SCRIPT_FUNCTIONS_CHAR_CREATE; ++i) {
FrameScript_RegisterFunction(
FrameScript::s_ScriptFunctions_CharCreate[i].name,
FrameScript::s_ScriptFunctions_CharCreate[i].method
);
}
}
void CharSelectRegisterScriptFunctions() {
for (int32_t i = 0; i < NUM_SCRIPT_FUNCTIONS_CHAR_SELECT; ++i) {
FrameScript_RegisterFunction(
FrameScript::s_ScriptFunctions_CharSelect[i].name,
FrameScript::s_ScriptFunctions_CharSelect[i].method
);
}
}
void GlueScriptEventsRegisterFunctions() {
for (int32_t i = 0; i < NUM_SCRIPT_FUNCTIONS_GLUE_SCRIPT_EVENTS; ++i) {
FrameScript_RegisterFunction(
FrameScript::s_ScriptFunctions_GlueScriptEvents[i].name,
FrameScript::s_ScriptFunctions_GlueScriptEvents[i].method
);
}
}
void RegisterSimpleFrameScriptMethods() {
for (int32_t i = 0; i < NUM_SCRIPT_FUNCTIONS_SIMPLE_FRAME; ++i) {
FrameScript_RegisterFunction(
FrameScript::s_ScriptFunctions_SimpleFrame[i].name,
FrameScript::s_ScriptFunctions_SimpleFrame[i].method
);
}
// TODO
// CSimpleAnim::CreateScriptMetaTable();
// CSimpleTranslationAnim::CreateScriptMetaTable();
// CSimpleRotationAnim::CreateScriptMetaTable();
// CSimpleScaleAnim::CreateScriptMetaTable();
// CSimpleControlPoint::CreateScriptMetaTable();
// CSimplePathAnim::CreateScriptMetaTable();
// CSimpleAlphaAnim::CreateScriptMetaTable();
// CSimpleAnimGroup::CreateScriptMetaTable();
CSimpleFont::CreateScriptMetaTable();
CSimpleTexture::CreateScriptMetaTable();
CSimpleFontString::CreateScriptMetaTable();
CSimpleFrame::CreateScriptMetaTable();
CSimpleButton::CreateScriptMetaTable();
CSimpleCheckbox::CreateScriptMetaTable();
CSimpleEditBox::CreateScriptMetaTable();
CSimpleHTML::CreateScriptMetaTable();
// TODO
// CSimpleMessageFrame::CreateScriptMetaTable();
// CSimpleMessageScrollFrame::CreateScriptMetaTable();
CSimpleModel::CreateScriptMetaTable();
CSimpleModelFFX::CreateScriptMetaTable();
CSimpleScrollFrame::CreateScriptMetaTable();
CSimpleSlider::CreateScriptMetaTable();
// TODO
// CSimpleStatusBar::CreateScriptMetaTable();
// CSimpleColorSelect::CreateScriptMetaTable();
// CSimpleMovieFrame::CreateScriptMetaTable();
}
void SystemRegisterFunctions() {
for (int32_t i = 0; i < NUM_SCRIPT_FUNCTIONS_SYSTEM; ++i) {
FrameScript_RegisterFunction(
FrameScript::s_ScriptFunctions_System[i].name,
FrameScript::s_ScriptFunctions_System[i].method
);
}
}

211
src/ui/ScriptFunctions.hpp Normal file
View file

@ -0,0 +1,211 @@
#ifndef UI_SCRIPT_FUNCTIONS_HPP
#define UI_SCRIPT_FUNCTIONS_HPP
#include "ui/Types.hpp"
#include <cstdint>
struct lua_State;
#define NUM_SCRIPT_FUNCTIONS_CHAR_CREATE 32
#define NUM_SCRIPT_FUNCTIONS_CHAR_SELECT 13
#define NUM_SCRIPT_FUNCTIONS_GLUE_SCRIPT_EVENTS 113
#define NUM_SCRIPT_FUNCTIONS_SIMPLE_FRAME 7
#define NUM_SCRIPT_FUNCTIONS_SYSTEM 7
namespace FrameScript {
extern FrameScript_Method s_ScriptFunctions_CharCreate[NUM_SCRIPT_FUNCTIONS_CHAR_CREATE];
extern FrameScript_Method s_ScriptFunctions_CharSelect[NUM_SCRIPT_FUNCTIONS_CHAR_SELECT];
extern FrameScript_Method s_ScriptFunctions_GlueScriptEvents[NUM_SCRIPT_FUNCTIONS_GLUE_SCRIPT_EVENTS];
extern FrameScript_Method s_ScriptFunctions_SimpleFrame[NUM_SCRIPT_FUNCTIONS_SIMPLE_FRAME];
extern FrameScript_Method s_ScriptFunctions_System[NUM_SCRIPT_FUNCTIONS_SYSTEM];
}
// Utility
void CharacterCreateRegisterScriptFunctions(void);
void CharSelectRegisterScriptFunctions(void);
void GlueScriptEventsRegisterFunctions(void);
void RegisterSimpleFrameScriptMethods(void);
void SystemRegisterFunctions(void);
// Shared
int32_t Script_GetAccountExpansionLevel(lua_State*);
// CharCreate
int32_t Script_SetCharCustomizeFrame(lua_State*);
int32_t Script_SetCharCustomizeBackground(lua_State*);
int32_t Script_ResetCharCustomize(lua_State*);
int32_t Script_GetNameForRace(lua_State*);
int32_t Script_GetFactionForRace(lua_State*);
int32_t Script_GetAvailableRaces(lua_State*);
int32_t Script_GetAvailableClasses(lua_State*);
int32_t Script_GetClassesForRace(lua_State*);
int32_t Script_GetHairCustomization(lua_State*);
int32_t Script_GetFacialHairCustomization(lua_State*);
int32_t Script_GetSelectedRace(lua_State*);
int32_t Script_GetSelectedSex(lua_State*);
int32_t Script_GetSelectedClass(lua_State*);
int32_t Script_SetSelectedRace(lua_State*);
int32_t Script_SetSelectedSex(lua_State*);
int32_t Script_SetSelectedClass(lua_State*);
int32_t Script_UpdateCustomizationBackground(lua_State*);
int32_t Script_UpdateCustomizationScene(lua_State*);
int32_t Script_CycleCharCustomization(lua_State*);
int32_t Script_RandomizeCharCustomization(lua_State*);
int32_t Script_GetCharacterCreateFacing(lua_State*);
int32_t Script_SetCharacterCreateFacing(lua_State*);
int32_t Script_GetRandomName(lua_State*);
int32_t Script_CreateCharacter(lua_State*);
int32_t Script_CustomizeExistingCharacter(lua_State*);
int32_t Script_PaidChange_GetPreviousRaceIndex(lua_State*);
int32_t Script_PaidChange_GetCurrentRaceIndex(lua_State*);
int32_t Script_PaidChange_GetCurrentClassIndex(lua_State*);
int32_t Script_PaidChange_GetName(lua_State*);
int32_t Script_IsRaceClassValid(lua_State*);
int32_t Script_IsRaceClassRestricted(lua_State*);
int32_t Script_GetCreateBackgroundModel(lua_State*);
// CharSelect
int32_t Script_SetCharSelectModelFrame(lua_State*);
int32_t Script_SetCharSelectBackground(lua_State*);
int32_t Script_GetCharacterListUpdate(lua_State*);
int32_t Script_GetNumCharacters(lua_State*);
int32_t Script_GetCharacterInfo(lua_State*);
int32_t Script_SelectCharacter(lua_State*);
int32_t Script_DeleteCharacter(lua_State*);
int32_t Script_RenameCharacter(lua_State*);
int32_t Script_DeclineCharacter(lua_State*);
int32_t Script_UpdateSelectionCustomizationScene(lua_State*);
int32_t Script_GetCharacterSelectFacing(lua_State*);
int32_t Script_SetCharacterSelectFacing(lua_State*);
int32_t Script_GetSelectBackgroundModel(lua_State*);
// GlueScriptEvents
int32_t Script_IsShiftKeyDown(lua_State*);
int32_t Script_GetBuildInfo(lua_State*);
int32_t Script_GetLocale(lua_State*);
int32_t Script_GetSavedAccountName(lua_State*);
int32_t Script_SetSavedAccountName(lua_State*);
int32_t Script_GetUsesToken(lua_State*);
int32_t Script_SetUsesToken(lua_State*);
int32_t Script_GetSavedAccountList(lua_State*);
int32_t Script_SetSavedAccountList(lua_State*);
int32_t Script_SetCurrentScreen(lua_State*);
int32_t Script_QuitGame(lua_State*);
int32_t Script_QuitGameAndRunLauncher(lua_State*);
int32_t Script_PlayGlueMusic(lua_State*);
int32_t Script_PlayCreditsMusic(lua_State*);
int32_t Script_StopGlueMusic(lua_State*);
int32_t Script_GetMovieResolution(lua_State*);
int32_t Script_GetScreenWidth(lua_State*);
int32_t Script_GetScreenHeight(lua_State*);
int32_t Script_LaunchURL(lua_State*);
int32_t Script_ShowTOSNotice(lua_State*);
int32_t Script_TOSAccepted(lua_State*);
int32_t Script_AcceptTOS(lua_State*);
int32_t Script_ShowEULANotice(lua_State*);
int32_t Script_EULAAccepted(lua_State*);
int32_t Script_AcceptEULA(lua_State*);
int32_t Script_ShowTerminationWithoutNoticeNotice(lua_State*);
int32_t Script_TerminationWithoutNoticeAccepted(lua_State*);
int32_t Script_AcceptTerminationWithoutNotice(lua_State*);
int32_t Script_ShowScanningNotice(lua_State*);
int32_t Script_ScanningAccepted(lua_State*);
int32_t Script_AcceptScanning(lua_State*);
int32_t Script_ShowContestNotice(lua_State*);
int32_t Script_ContestAccepted(lua_State*);
int32_t Script_AcceptContest(lua_State*);
int32_t Script_DefaultServerLogin(lua_State*);
int32_t Script_StatusDialogClick(lua_State*);
int32_t Script_GetServerName(lua_State*);
int32_t Script_DisconnectFromServer(lua_State*);
int32_t Script_IsConnectedToServer(lua_State*);
int32_t Script_EnterWorld(lua_State*);
int32_t Script_Screenshot(lua_State*);
int32_t Script_PatchDownloadProgress(lua_State*);
int32_t Script_PatchDownloadCancel(lua_State*);
int32_t Script_PatchDownloadApply(lua_State*);
int32_t Script_GetNumAddOns(lua_State*);
int32_t Script_GetAddOnInfo(lua_State*);
int32_t Script_LaunchAddOnURL(lua_State*);
int32_t Script_GetAddOnDependencies(lua_State*);
int32_t Script_GetAddOnEnableState(lua_State*);
int32_t Script_EnableAddOn(lua_State*);
int32_t Script_EnableAllAddOns(lua_State*);
int32_t Script_DisableAddOn(lua_State*);
int32_t Script_DisableAllAddOns(lua_State*);
int32_t Script_SaveAddOns(lua_State*);
int32_t Script_ResetAddOns(lua_State*);
int32_t Script_IsAddonVersionCheckEnabled(lua_State*);
int32_t Script_SetAddonVersionCheck(lua_State*);
int32_t Script_GetCursorPosition(lua_State*);
int32_t Script_ShowCursor(lua_State*);
int32_t Script_HideCursor(lua_State*);
int32_t Script_GetBillingTimeRemaining(lua_State*);
int32_t Script_GetBillingPlan(lua_State*);
int32_t Script_GetBillingTimeRested(lua_State*);
int32_t Script_SurveyNotificationDone(lua_State*);
int32_t Script_PINEntered(lua_State*);
int32_t Script_PlayGlueAmbience(lua_State*);
int32_t Script_StopGlueAmbience(lua_State*);
int32_t Script_GetCreditsText(lua_State*);
int32_t Script_GetClientExpansionLevel(lua_State*);
int32_t Script_MatrixEntered(lua_State*);
int32_t Script_MatrixRevert(lua_State*);
int32_t Script_MatrixCommit(lua_State*);
int32_t Script_GetMatrixCoordinates(lua_State*);
int32_t Script_ScanDLLStart(lua_State*);
int32_t Script_ScanDLLContinueAnyway(lua_State*);
int32_t Script_IsScanDLLFinished(lua_State*);
int32_t Script_IsWindowsClient(lua_State*);
int32_t Script_IsOtherPlatformClient(lua_State*);
int32_t Script_SetRealmSplitState(lua_State*);
int32_t Script_RequestRealmSplitInfo(lua_State*);
int32_t Script_CancelLogin(lua_State*);
int32_t Script_GetCVar(lua_State*);
int32_t Script_GetCVarBool(lua_State*);
int32_t Script_SetCVar(lua_State*);
int32_t Script_GetCVarDefault(lua_State*);
int32_t Script_GetCVarMin(lua_State*);
int32_t Script_GetCVarMax(lua_State*);
int32_t Script_GetCVarAbsoluteMin(lua_State*);
int32_t Script_GetCVarAbsoluteMax(lua_State*);
int32_t Script_GetChangedOptionWarnings(lua_State*);
int32_t Script_AcceptChangedOptionWarnings(lua_State*);
int32_t Script_ShowChangedOptionWarnings(lua_State*);
int32_t Script_TokenEntered(lua_State*);
int32_t Script_GetNumDeclensionSets(lua_State*);
int32_t Script_DeclineName(lua_State*);
int32_t Script_GetNumGameAccounts(lua_State*);
int32_t Script_GetGameAccountInfo(lua_State*);
int32_t Script_SetGameAccount(lua_State*);
int32_t Script_StopAllSFX(lua_State*);
int32_t Script_SetClearConfigData(lua_State*);
int32_t Script_RestartGx(lua_State*);
int32_t Script_RestoreVideoResolutionDefaults(lua_State*);
int32_t Script_RestoreVideoEffectsDefaults(lua_State*);
int32_t Script_RestoreVideoStereoDefaults(lua_State*);
int32_t Script_IsStreamingMode(lua_State*);
int32_t Script_IsStreamingTrial(lua_State*);
int32_t Script_IsConsoleActive(lua_State*);
int32_t Script_RunScript(lua_State*);
int32_t Script_ReadyForAccountDataTimes(lua_State*);
int32_t Script_IsTrialAccount(lua_State*);
int32_t Script_IsSystemSupported(lua_State*);
// SimpleFrame
int32_t Script_GetText(lua_State*);
int32_t Script_GetNumFrames(lua_State*);
int32_t Script_EnumerateFrames(lua_State*);
int32_t Script_CreateFont(lua_State*);
int32_t Script_CreateFrame(lua_State*);
int32_t Script_GetFramesRegisteredForEvent(lua_State*);
int32_t Script_GetCurrentKeyBoardFocus(lua_State*);
// System
int32_t Script_GetTime(lua_State*);
int32_t Script_GetGameTime(lua_State*);
int32_t Script_ConsoleExec(lua_State*);
int32_t Script_AccessDenied(lua_State*);
#endif

View file

@ -0,0 +1,231 @@
#include "ui/ScriptFunctions.hpp"
#include "ui/Types.hpp"
#include "util/Lua.hpp"
#include <cstdint>
int32_t Script_SetCharCustomizeFrame(lua_State* L) {
// TODO
return 0;
}
int32_t Script_SetCharCustomizeBackground(lua_State* L) {
// TODO
return 0;
}
int32_t Script_ResetCharCustomize(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetNameForRace(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetFactionForRace(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetAvailableRaces(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetAvailableClasses(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetClassesForRace(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetHairCustomization(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetFacialHairCustomization(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetSelectedRace(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetSelectedSex(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetSelectedClass(lua_State* L) {
// TODO
return 0;
}
int32_t Script_SetSelectedRace(lua_State* L) {
// TODO
return 0;
}
int32_t Script_SetSelectedSex(lua_State* L) {
// TODO
return 0;
}
int32_t Script_SetSelectedClass(lua_State* L) {
// TODO
return 0;
}
int32_t Script_UpdateCustomizationBackground(lua_State* L) {
// TODO
return 0;
}
int32_t Script_UpdateCustomizationScene(lua_State* L) {
// TODO
return 0;
}
int32_t Script_CycleCharCustomization(lua_State* L) {
// TODO
return 0;
}
int32_t Script_RandomizeCharCustomization(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetCharacterCreateFacing(lua_State* L) {
// TODO
return 0;
}
int32_t Script_SetCharacterCreateFacing(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetRandomName(lua_State* L) {
// TODO
return 0;
}
int32_t Script_CreateCharacter(lua_State* L) {
// TODO
return 0;
}
int32_t Script_CustomizeExistingCharacter(lua_State* L) {
// TODO
return 0;
}
int32_t Script_PaidChange_GetPreviousRaceIndex(lua_State* L) {
// TODO
return 0;
}
int32_t Script_PaidChange_GetCurrentRaceIndex(lua_State* L) {
// TODO
return 0;
}
int32_t Script_PaidChange_GetCurrentClassIndex(lua_State* L) {
// TODO
return 0;
}
int32_t Script_PaidChange_GetName(lua_State* L) {
// TODO
return 0;
}
int32_t Script_IsRaceClassValid(lua_State* L) {
// TODO
return 0;
}
int32_t Script_IsRaceClassRestricted(lua_State* L) {
// TODO
return 0;
}
int32_t Script_GetCreateBackgroundModel(lua_State* L) {
// TODO
return 0;
}
FrameScript_Method FrameScript::s_ScriptFunctions_CharCreate[NUM_SCRIPT_FUNCTIONS_CHAR_CREATE] = {
{ "SetCharCustomizeFrame", &Script_SetCharCustomizeFrame },
{ "SetCharCustomizeBackground", &Script_SetCharCustomizeBackground },
{ "ResetCharCustomize", &Script_ResetCharCustomize },
{ "GetNameForRace", &Script_GetNameForRace },
{ "GetFactionForRace", &Script_GetFactionForRace },
{ "GetAvailableRaces", &Script_GetAvailableRaces },
{ "GetAvailableClasses", &Script_GetAvailableClasses },
{ "GetClassesForRace", &Script_GetClassesForRace },
{ "GetHairCustomization", &Script_GetHairCustomization },
{ "GetFacialHairCustomization", &Script_GetFacialHairCustomization },
{ "GetSelectedRace", &Script_GetSelectedRace },
{ "GetSelectedSex", &Script_GetSelectedSex },
{ "GetSelectedClass", &Script_GetSelectedClass },
{ "SetSelectedRace", &Script_SetSelectedRace },
{ "SetSelectedSex", &Script_SetSelectedSex },
{ "SetSelectedClass", &Script_SetSelectedClass },
{ "UpdateCustomizationBackground", &Script_UpdateCustomizationBackground },
{ "UpdateCustomizationScene", &Script_UpdateCustomizationScene },
{ "CycleCharCustomization", &Script_CycleCharCustomization },
{ "RandomizeCharCustomization", &Script_RandomizeCharCustomization },
{ "GetCharacterCreateFacing", &Script_GetCharacterCreateFacing },
{ "SetCharacterCreateFacing", &Script_SetCharacterCreateFacing },
{ "GetRandomName", &Script_GetRandomName },
{ "CreateCharacter", &Script_CreateCharacter },
{ "CustomizeExistingCharacter", &Script_CustomizeExistingCharacter },
{ "PaidChange_GetPreviousRaceIndex", &Script_PaidChange_GetPreviousRaceIndex },
{ "PaidChange_GetCurrentRaceIndex", &Script_PaidChange_GetCurrentRaceIndex },
{ "PaidChange_GetCurrentClassIndex", &Script_PaidChange_GetCurrentClassIndex },
{ "PaidChange_GetName", &Script_PaidChange_GetName },
{ "IsRaceClassValid", &Script_IsRaceClassValid },
{ "IsRaceClassRestricted", &Script_IsRaceClassRestricted },
{ "GetCreateBackgroundModel", &Script_GetCreateBackgroundModel }
};

Some files were not shown because too many files have changed in this diff Show more