metaforce/Runtime/GuiSys/CInstruction.cpp

400 lines
12 KiB
C++
Raw Normal View History

2016-03-19 00:07:31 +00:00
#include "CInstruction.hpp"
#include "CFontRenderState.hpp"
2016-03-19 03:58:01 +00:00
#include "CTextRenderBuffer.hpp"
2016-03-20 06:37:08 +00:00
#include "CRasterFont.hpp"
2016-03-21 00:25:53 +00:00
#include "Graphics/CTexture.hpp"
2016-03-19 00:07:31 +00:00
namespace urde
{
2016-12-31 00:51:51 +00:00
void CInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
}
2016-03-19 00:07:31 +00:00
void CInstruction::GetAssets(std::vector<CToken>& assetsOut) const
{
}
size_t CInstruction::GetAssetCount() const
{
return 0;
}
void CColorInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
state.SetColor(x4_cType, x8_color);
}
2016-12-31 00:51:51 +00:00
void CColorInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
Invoke(state, buf);
}
2016-03-19 00:07:31 +00:00
void CColorOverrideInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
2016-12-16 23:05:29 +00:00
state.x64_colorOverrides[x4_overrideIdx] = true;
2016-03-19 00:07:31 +00:00
zeus::CColor convCol = state.ConvertToTextureSpace(x8_color);
2016-03-21 00:25:53 +00:00
state.x0_drawStrOpts.x4_colors[x4_overrideIdx] = convCol;
2016-03-19 00:07:31 +00:00
}
2016-12-31 00:51:51 +00:00
void CColorOverrideInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
Invoke(state, buf);
}
2016-03-19 03:58:01 +00:00
void CFontInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
buf->AddFontChange(x4_font);
2016-12-16 23:05:29 +00:00
state.x48_font = x4_font;
2016-03-19 03:58:01 +00:00
state.RefreshPalette();
}
2016-12-31 00:51:51 +00:00
void CFontInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
Invoke(state, buf);
}
2016-03-19 03:58:01 +00:00
void CFontInstruction::GetAssets(std::vector<CToken>& assetsOut) const
{
assetsOut.push_back(x4_font);
}
size_t CFontInstruction::GetAssetCount() const
{
return 1;
}
2016-03-20 00:32:30 +00:00
void CLineExtraSpaceInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
2016-03-19 03:58:01 +00:00
{
2016-12-16 23:05:29 +00:00
state.x78_extraLineSpace = x4_extraSpace;
2016-03-19 03:58:01 +00:00
}
2016-12-31 00:51:51 +00:00
void CLineExtraSpaceInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
Invoke(state, buf);
}
2017-01-30 04:16:20 +00:00
void CLineInstruction::TestLargestFont(s32 w, s32 h, s32 b)
2016-03-19 03:58:01 +00:00
{
2017-01-30 04:16:20 +00:00
if (!x18_largestMonoBaseline)
x18_largestMonoBaseline = b;
2016-03-20 00:32:30 +00:00
2017-01-30 04:16:20 +00:00
if (x14_largestMonoWidth < w)
x14_largestMonoWidth = w;
2016-03-20 00:32:30 +00:00
2017-01-30 04:16:20 +00:00
if (x10_largestMonoHeight < h)
2016-03-20 00:32:30 +00:00
{
2017-01-30 04:16:20 +00:00
x10_largestMonoHeight = h;
x18_largestMonoBaseline = b;
}
}
void CLineInstruction::TestLargestImage(s32 w, s32 h, s32 b)
{
if (!x24_largestImageBaseline)
x24_largestImageBaseline = b;
if (x20_largestImageWidth < w)
x20_largestImageWidth = w;
if (x1c_largestImageHeight < h)
{
x1c_largestImageHeight = h;
x24_largestImageBaseline = b;
2016-03-20 00:32:30 +00:00
}
2016-03-19 03:58:01 +00:00
}
void CLineInstruction::InvokeLTR(CFontRenderState& state) const
{
2017-01-30 04:16:20 +00:00
switch (x28_just)
2016-03-20 06:37:08 +00:00
{
2016-03-21 00:25:53 +00:00
case EJustification::Left:
case EJustification::Full:
case EJustification::NLeft:
case EJustification::LeftMono:
2016-12-30 06:37:01 +00:00
state.xd4_curX = state.x88_curBlock->x4_offsetX;
2016-03-20 06:37:08 +00:00
break;
2016-03-21 00:25:53 +00:00
case EJustification::Center:
case EJustification::CenterMono:
2016-12-30 06:37:01 +00:00
state.xd4_curX = state.x88_curBlock->x4_offsetX +
state.x88_curBlock->xc_blockExtentX / 2 - x8_curX / 2;
2016-03-20 06:37:08 +00:00
break;
2016-03-21 00:25:53 +00:00
case EJustification::NCenter:
if (x4_wordCount == 1)
2016-03-20 06:37:08 +00:00
{
2016-12-30 06:37:01 +00:00
state.xd4_curX = state.x88_curBlock->x4_offsetX +
state.x88_curBlock->xc_blockExtentX / 2 - x8_curX / 2;
2016-03-20 06:37:08 +00:00
}
else
{
2016-12-30 06:37:01 +00:00
state.xd4_curX = state.x88_curBlock->x4_offsetX +
state.x88_curBlock->xc_blockExtentX / 2 -
state.x88_curBlock->x2c_lineX / 2;
2016-03-20 06:37:08 +00:00
}
break;
2016-03-21 00:25:53 +00:00
case EJustification::Right:
case EJustification::RightMono:
2016-12-30 06:37:01 +00:00
state.xd4_curX = state.x88_curBlock->x4_offsetX +
state.x88_curBlock->xc_blockExtentX - x8_curX;
2016-03-20 06:37:08 +00:00
break;
2016-03-21 00:25:53 +00:00
case EJustification::NRight:
2016-12-30 06:37:01 +00:00
state.xd4_curX = state.x88_curBlock->x4_offsetX +
state.x88_curBlock->xc_blockExtentX -
state.x88_curBlock->x2c_lineX;
2016-03-20 06:37:08 +00:00
break;
default: break;
}
2016-12-30 06:37:01 +00:00
if (state.xdc_currentLineInst)
2016-03-20 06:37:08 +00:00
{
2016-12-30 06:37:01 +00:00
const CLineInstruction& inst = *state.xdc_currentLineInst;
2016-03-20 06:37:08 +00:00
s32 val = 0;
2016-12-30 06:37:01 +00:00
switch (state.x88_curBlock->x1c_vertJustification)
2016-03-20 06:37:08 +00:00
{
2016-03-21 00:25:53 +00:00
case EVerticalJustification::Top:
case EVerticalJustification::Center:
case EVerticalJustification::Bottom:
case EVerticalJustification::NTop:
case EVerticalJustification::NCenter:
case EVerticalJustification::NBottom:
2016-03-20 06:37:08 +00:00
val = inst.xc_curY;
break;
2016-03-21 00:25:53 +00:00
case EVerticalJustification::Full:
2016-12-30 06:37:01 +00:00
val = state.x88_curBlock->x10_blockExtentY - state.x88_curBlock->x30_lineY;
if (state.x88_curBlock->x34_lineCount > 1)
val /= state.x88_curBlock->x34_lineCount - 1;
2016-03-20 06:37:08 +00:00
else
val = 0;
val += inst.xc_curY;
break;
case EVerticalJustification::TopMono:
2016-12-30 06:37:01 +00:00
val = state.x88_curBlock->x24_largestMonoH;
2016-03-20 06:37:08 +00:00
break;
case EVerticalJustification::CenterMono:
2016-12-30 06:37:01 +00:00
val = (inst.xc_curY - state.x88_curBlock->x24_largestMonoH) / 2 +
state.x88_curBlock->x24_largestMonoH;
2016-03-20 06:37:08 +00:00
break;
case EVerticalJustification::RightMono:
2016-12-30 06:37:01 +00:00
val = state.x88_curBlock->x24_largestMonoH * 2 - inst.xc_curY;
2016-03-20 06:37:08 +00:00
break;
}
2016-12-30 06:37:01 +00:00
if (state.x88_curBlock->x1c_vertJustification != EVerticalJustification::Full)
2016-12-16 23:05:29 +00:00
val = val * state.x74_lineSpacing + state.x78_extraLineSpace;
2016-03-20 06:37:08 +00:00
2016-12-30 06:37:01 +00:00
state.xd8_curY += val;
2016-03-20 06:37:08 +00:00
}
2016-03-19 03:58:01 +00:00
}
void CLineInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
InvokeLTR(state);
2016-12-30 06:37:01 +00:00
state.x108_lineInitialized = true;
state.xdc_currentLineInst = this;
2016-03-19 03:58:01 +00:00
}
2016-12-31 00:51:51 +00:00
void CLineInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
if (!state.xdc_currentLineInst)
Invoke(state, buf);
}
2016-03-21 00:25:53 +00:00
void CLineSpacingInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
2016-12-16 23:05:29 +00:00
state.x74_lineSpacing = x4_lineSpacing;
2016-03-21 00:25:53 +00:00
}
2016-12-31 00:51:51 +00:00
void CLineSpacingInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
Invoke(state, buf);
}
2016-03-21 00:25:53 +00:00
void CPopStateInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
state.PopState();
}
2016-12-31 00:51:51 +00:00
void CPopStateInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
Invoke(state, buf);
}
2016-03-21 00:25:53 +00:00
void CPushStateInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
state.PushState();
}
2016-12-31 00:51:51 +00:00
void CPushStateInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
Invoke(state, buf);
}
2016-03-21 00:25:53 +00:00
void CRemoveColorOverrideInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
2016-12-16 23:05:29 +00:00
state.x64_colorOverrides[x4_idx] = false;
2016-03-21 00:25:53 +00:00
}
2016-12-31 00:51:51 +00:00
void CRemoveColorOverrideInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
Invoke(state, buf);
}
2016-03-21 00:25:53 +00:00
void CImageInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
if (x4_image.IsLoaded() && x4_image.x4_texs.size())
{
2017-01-30 04:16:20 +00:00
const CTexture* tex = x4_image.x4_texs[0].GetObj();
if (state.x88_curBlock->x14_dir == ETextDirection::Horizontal)
{
if (buf)
{
int y = state.xd8_curY + state.xdc_currentLineInst->GetBaseline() - x4_image.CalculateBaseline();
zeus::CVector2i coords(state.xd4_curX, y);
buf->AddImage(coords, x4_image);
}
2017-01-30 06:58:59 +00:00
state.xd4_curX = state.xd4_curX + tex->GetWidth() * x4_image.x14_cropFactor.y;
2017-01-30 04:16:20 +00:00
}
else
2016-03-21 00:25:53 +00:00
{
2017-01-30 06:58:59 +00:00
int scale = state.xdc_currentLineInst->x8_curX - tex->GetWidth() * x4_image.x14_cropFactor.y;
2016-03-21 00:25:53 +00:00
if (buf)
{
2017-01-30 04:16:20 +00:00
zeus::CVector2i coords(scale / 2 + state.xd4_curX, state.xd8_curY);
2016-03-21 00:25:53 +00:00
buf->AddImage(coords, x4_image);
}
2017-01-30 04:16:20 +00:00
state.xd8_curY += x4_image.CalculateHeight();
2016-03-21 00:25:53 +00:00
}
}
}
2016-12-31 00:51:51 +00:00
void CImageInstruction::GetAssets(std::vector<CToken>& assetsOut) const
{
for (const CToken& tok : x4_image.x4_texs)
assetsOut.push_back(tok);
}
size_t CImageInstruction::GetAssetCount() const
{
return x4_image.x4_texs.size();
}
2016-03-20 06:37:08 +00:00
void CTextInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
2016-03-20 00:32:30 +00:00
{
2016-03-20 06:37:08 +00:00
int xOut, yOut;
2017-01-30 04:16:20 +00:00
if (state.x88_curBlock->x14_dir == ETextDirection::Horizontal)
{
state.x48_font->DrawString(state.x0_drawStrOpts, state.xd4_curX,
state.xdc_currentLineInst->GetBaseline() + state.xd8_curY,
xOut, yOut, buf, x4_str.c_str(), x4_str.size());
state.xd4_curX = xOut;
}
else
{
int scale = state.xdc_currentLineInst->x8_curX - state.x48_font->GetMonoWidth();
state.x48_font->DrawString(state.x0_drawStrOpts, scale / 2 + state.xd4_curX,
state.xd8_curY, xOut, yOut, buf, x4_str.c_str(), x4_str.size());
state.xd8_curY = yOut;
}
2016-03-20 00:32:30 +00:00
}
2016-03-20 06:37:08 +00:00
void CBlockInstruction::TestLargestFont(s32 monoW, s32 monoH, s32 baseline)
{
if (!x28_largestBaseline)
x28_largestBaseline = baseline;
if (x20_largestMonoW < monoW)
monoW = x20_largestMonoW;
if (x24_largestMonoH < monoH)
{
x24_largestMonoH = monoH;
x28_largestBaseline = baseline;
}
}
void CBlockInstruction::SetupPositionLTR(CFontRenderState& state) const
{
switch (x1c_vertJustification)
{
2016-03-21 00:25:53 +00:00
case EVerticalJustification::Top:
case EVerticalJustification::Full:
case EVerticalJustification::NTop:
case EVerticalJustification::TopMono:
2016-12-30 06:37:01 +00:00
state.xd8_curY = x8_offsetY;
2016-03-20 06:37:08 +00:00
break;
2016-03-21 00:25:53 +00:00
case EVerticalJustification::Center:
case EVerticalJustification::NCenter:
2016-12-30 06:37:01 +00:00
state.xd8_curY = x8_offsetY + (x10_blockExtentY - x30_lineY) / 2;
2016-03-20 06:37:08 +00:00
break;
case EVerticalJustification::CenterMono:
2016-12-30 06:37:01 +00:00
state.xd8_curY = x8_offsetY + (x10_blockExtentY - x34_lineCount * x24_largestMonoH) / 2;
2016-03-20 06:37:08 +00:00
break;
2016-03-21 00:25:53 +00:00
case EVerticalJustification::Bottom:
case EVerticalJustification::NBottom:
2016-12-30 06:37:01 +00:00
state.xd8_curY = x8_offsetY + x10_blockExtentY - x30_lineY;
2016-03-20 06:37:08 +00:00
break;
case EVerticalJustification::RightMono:
2016-12-30 06:37:01 +00:00
state.xd8_curY = x8_offsetY + x10_blockExtentY - x34_lineCount * x24_largestMonoH;
2016-03-20 06:37:08 +00:00
break;
}
}
void CBlockInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
2016-03-20 00:32:30 +00:00
{
2017-01-30 04:16:20 +00:00
state.x0_drawStrOpts.x0_direction = x14_dir;
state.x88_curBlock = const_cast<CBlockInstruction*>(this);
if (x14_dir == ETextDirection::Horizontal)
2016-03-20 06:37:08 +00:00
SetupPositionLTR(state);
2016-03-20 00:32:30 +00:00
}
2016-12-31 00:51:51 +00:00
void CBlockInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
Invoke(state, buf);
}
2016-03-21 00:25:53 +00:00
void CWordInstruction::InvokeLTR(CFontRenderState& state) const
{
2016-12-16 23:05:29 +00:00
CRasterFont* font = state.x48_font.GetObj();
2017-01-24 07:41:33 +00:00
char16_t space = u' ';
2016-03-21 00:25:53 +00:00
int w, h;
font->GetSize(state.x0_drawStrOpts, w, h, &space, 1);
2016-12-30 06:37:01 +00:00
const CLineInstruction& inst = *state.xdc_currentLineInst;
switch (state.x88_curBlock->x18_justification)
2016-03-21 00:25:53 +00:00
{
case EJustification::Full:
2016-12-30 06:37:01 +00:00
w += (state.x88_curBlock->xc_blockExtentX - inst.x8_curX) / (inst.x4_wordCount - 1);
2016-03-21 00:25:53 +00:00
break;
case EJustification::NLeft:
case EJustification::NCenter:
case EJustification::NRight:
2016-12-30 06:37:01 +00:00
w += (state.x88_curBlock->x2c_lineX - inst.x8_curX) / (inst.x4_wordCount - 1);
2016-03-21 00:25:53 +00:00
break;
default: break;
}
2016-12-30 06:37:01 +00:00
int wOut = state.xd4_curX;
2016-03-21 00:25:53 +00:00
font->DrawSpace(state.x0_drawStrOpts, wOut,
2016-12-30 06:37:01 +00:00
inst.xc_curY - font->GetMonoHeight() + state.xd8_curY, wOut, h, w);
state.xd4_curX = wOut;
2016-03-21 00:25:53 +00:00
}
void CWordInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
2016-12-30 06:37:01 +00:00
if (state.x108_lineInitialized)
2016-03-21 00:25:53 +00:00
{
2016-12-30 06:37:01 +00:00
state.x108_lineInitialized = false;
2016-03-21 00:25:53 +00:00
return;
}
if (state.x0_drawStrOpts.x0_direction == ETextDirection::Horizontal)
InvokeLTR(state);
}
2016-12-31 00:51:51 +00:00
void CWordInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const
{
state.x108_lineInitialized = false;
}
2016-03-19 00:07:31 +00:00
}