Implement LegoMeterPresenter::DrawMeter ()

* Implement LegoMeterPresenter::DrawMeter

* New MxRect16 header, offsets and size annotations

* Missing mxtypes include
This commit is contained in:
MS 2024-05-29 10:47:25 -04:00 committed by GitHub
parent da48dfb40d
commit 5f00634b9c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 167 additions and 45 deletions
LEGO1
lego/legoomni
omni/include

View file

@ -1,10 +1,18 @@
#ifndef LEGOMETERPRESENTER_H
#define LEGOMETERPRESENTER_H
#include "mxrect16.h"
#include "mxstillpresenter.h"
#include "mxstring.h"
// SIZE 0x08
struct MeterRect : public MxRect16 {
// FUNCTION: BETA10 0x10097eb0
MeterRect() {}
};
// VTABLE: LEGO1 0x100d7ac8
// VTABLE: BETA10 0x101bca68
// SIZE 0x94
class LegoMeterPresenter : public MxStillPresenter {
public:
@ -18,17 +26,21 @@ public:
void ParseExtra() override; // vtable+0x30
private:
void FUN_10043a50();
enum MeterLayout {
e_leftToRight = 0,
e_rightToLeft,
e_bottomToTop,
e_topToBottom
};
MxU8* m_unk0x6c; // 0x6c
MxU16 m_type; // 0x70
MxString m_variable; // 0x74
MxFloat m_unk0x84; // 0x84
MxU16 m_unk0x88; // 0x88
MxU16 m_unk0x8a; // 0x8a
MxU16 m_unk0x8c; // 0x8c
MxU16 m_unk0x8e; // 0x8e
MxU16 m_layout; // 0x90
void DrawMeter();
MxU8* m_meterPixels; // 0x6c
MxU16 m_fillColor; // 0x70
MxString m_variable; // 0x74
MxFloat m_curPercent; // 0x84
MeterRect m_meterRect; // 0x88
MxS16 m_layout; // 0x90
};
// SYNTHETIC: LEGO1 0x10043760

View file

@ -4,27 +4,34 @@
#include "define.h"
#include "mxbitmap.h"
#include "mxdsaction.h"
#include "mxmisc.h"
#include "mxutilities.h"
#include "mxvariabletable.h"
#include <assert.h>
DECOMP_SIZE_ASSERT(LegoMeterPresenter, 0x94)
// FUNCTION: LEGO1 0x10043430
// FUNCTION: BETA10 0x10097570
LegoMeterPresenter::LegoMeterPresenter()
{
m_layout = 0;
m_unk0x6c = 0;
m_unk0x84 = 0;
m_type = 1;
SetBit1(FALSE);
m_meterPixels = NULL;
m_fillColor = 1;
m_curPercent = 0;
m_layout = e_leftToRight;
m_flags.m_bit1 = FALSE;
}
// FUNCTION: LEGO1 0x10043780
// FUNCTION: BETA10 0x1009764a
LegoMeterPresenter::~LegoMeterPresenter()
{
delete m_unk0x6c;
delete m_meterPixels;
}
// FUNCTION: LEGO1 0x10043800
// FUNCTION: BETA10 0x100976ec
void LegoMeterPresenter::ParseExtra()
{
MxStillPresenter::ParseExtra();
@ -41,27 +48,28 @@ void LegoMeterPresenter::ParseExtra()
char output[256];
if (KeyValueStringParse(extraCopy, g_strTYPE, output)) {
if (!strcmpi(output, g_strLEFT_TO_RIGHT)) {
m_layout = 0;
m_layout = e_leftToRight;
}
else if (!strcmpi(output, g_strRIGHT_TO_LEFT)) {
m_layout = 1;
m_layout = e_rightToLeft;
}
else if (!strcmpi(output, g_strBOTTOM_TO_TOP)) {
m_layout = 2;
m_layout = e_bottomToTop;
}
else if (!strcmpi(output, g_strTOP_TO_BOTTOM)) {
m_layout = 3;
m_layout = e_topToBottom;
}
}
if (KeyValueStringParse(extraCopy, g_strFILLER_INDEX, output)) {
m_type = atoi(output);
m_fillColor = atoi(output);
}
if (KeyValueStringParse(extraCopy, g_strVARIABLE, output)) {
m_variable = output;
}
else {
assert(0);
EndAction();
}
}
@ -71,30 +79,84 @@ void LegoMeterPresenter::ParseExtra()
}
// FUNCTION: LEGO1 0x10043990
// FUNCTION: BETA10 0x10097917
void LegoMeterPresenter::StreamingTickle()
{
MxStillPresenter::StreamingTickle();
m_unk0x6c = new MxU8[m_frameBitmap->GetBmiStride() * m_frameBitmap->GetBmiHeightAbs()];
if (m_unk0x6c == NULL) {
m_meterPixels = new MxU8[m_frameBitmap->GetDataSize()];
if (m_meterPixels == NULL) {
assert(0);
EndAction();
}
memcpy(m_unk0x6c, m_frameBitmap->GetImage(), m_frameBitmap->GetBmiStride() * m_frameBitmap->GetBmiHeightAbs());
memcpy(m_meterPixels, m_frameBitmap->GetImage(), m_frameBitmap->GetDataSize());
m_unk0x88 = 0;
m_unk0x8a = 0;
m_unk0x8c = m_frameBitmap->GetBmiWidth() - 1;
m_unk0x8e = m_frameBitmap->GetBmiHeightAbs() - 1;
m_meterRect.SetLeft(0);
m_meterRect.SetTop(0);
m_meterRect.SetRight(m_frameBitmap->GetBmiWidth() - 1);
m_meterRect.SetBottom(m_frameBitmap->GetBmiHeightAbs() - 1);
}
// FUNCTION: LEGO1 0x10043a30
// FUNCTION: BETA10 0x10097a1a
void LegoMeterPresenter::RepeatingTickle()
{
FUN_10043a50();
DrawMeter();
MxStillPresenter::RepeatingTickle();
}
// STUB: LEGO1 0x10043a50
void LegoMeterPresenter::FUN_10043a50()
// FUNCTION: LEGO1 0x10043a50
// FUNCTION: BETA10 0x10097a40
void LegoMeterPresenter::DrawMeter()
{
const char* strval = VariableTable()->GetVariable(m_variable.GetData());
MxFloat percent = atof(strval);
MxS16 row, leftRightCol, bottomTopCol, leftRightEnd, bottomTopEnd;
if (strval != NULL && m_curPercent != percent) {
m_curPercent = percent;
// DECOMP: This clamp is retail only
if (percent > 0.99) {
m_curPercent = 0.99f;
}
else if (percent < 0.0) {
m_curPercent = 0.0f;
}
// Copy the previously drawn meter back into the bitmap
memcpy(m_frameBitmap->GetImage(), m_meterPixels, m_frameBitmap->GetDataSize());
switch (m_layout) {
case e_leftToRight:
leftRightEnd = m_meterRect.GetWidth() * m_curPercent;
for (row = m_meterRect.GetTop(); row < m_meterRect.GetBottom(); row++) {
MxU8* line = m_frameBitmap->GetStart(m_meterRect.GetLeft(), row);
for (leftRightCol = 0; leftRightCol < leftRightEnd; leftRightCol++, line++) {
if (*line) {
*line = m_fillColor;
}
}
}
break;
case e_bottomToTop:
bottomTopEnd = m_meterRect.GetBottom() - (MxS16) (m_meterRect.GetHeight() * m_curPercent);
for (row = m_meterRect.GetBottom(); row < bottomTopEnd; row--) {
MxU8* line = m_frameBitmap->GetStart(m_meterRect.GetLeft(), row);
for (bottomTopCol = 0; bottomTopCol < m_meterRect.GetWidth(); bottomTopCol++, line++) {
if (*line) {
*line = m_fillColor;
}
}
}
// break;
default:
// The other two fill options are not implemented.
break;
}
}
}

View file

@ -113,6 +113,17 @@ public:
// FUNCTION: BETA10 0x100982b0
inline MxLong GetDataSize() const { return AlignToFourByte(m_bmiHeader->biWidth) * GetBmiHeightAbs(); }
// FUNCTION: BETA10 0x1002c4b0
inline MxBool IsTopDown()
{
if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN) {
return TRUE;
}
else {
return m_bmiHeader->biHeight < 0;
}
}
inline MxLong GetAdjustedStride()
{
if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN || m_bmiHeader->biHeight < 0) {
@ -123,28 +134,18 @@ public:
}
}
inline MxLong GetLine(MxS32 p_top)
{
MxS32 height;
if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN || m_bmiHeader->biHeight < 0) {
height = p_top;
}
else {
height = GetBmiHeightAbs() - p_top - 1;
}
return GetBmiStride() * height;
}
// FUNCTION: BETA10 0x1002c320
inline MxU8* GetStart(MxS32 p_left, MxS32 p_top)
{
if (m_bmiHeader->biCompression == BI_RGB) {
return GetLine(p_top) + m_data + p_left;
return m_data + p_left +
AlignToFourByte(GetBmiWidth()) * (IsTopDown() ? p_top : (GetBmiHeightAbs() - 1) - p_top);
}
else if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN) {
return m_data;
}
else {
return GetLine(0) + m_data;
return m_data + AlignToFourByte(GetBmiWidth()) * (IsTopDown() ? 0 : (GetBmiHeightAbs() - 1));
}
}

View file

@ -0,0 +1,47 @@
#ifndef MXRECT16_H
#define MXRECT16_H
#include "mxtypes.h"
// SIZE 0x08
struct MxRect16 {
// FUNCTION: BETA10 0x10097ee0
MxRect16() {}
// FUNCTION: BETA10 0x100981f0
inline void SetLeft(MxS16 p_left) { m_left = p_left; }
// FUNCTION: BETA10 0x10098220
inline void SetTop(MxS16 p_top) { m_top = p_top; }
// FUNCTION: BETA10 0x10098250
inline void SetRight(MxS16 p_right) { m_right = p_right; }
// FUNCTION: BETA10 0x10098280
inline void SetBottom(MxS16 p_bottom) { m_bottom = p_bottom; }
// FUNCTION: BETA10 0x10098300
inline MxS16 GetLeft() const { return m_left; }
// FUNCTION: BETA10 0x10098330
inline MxS16 GetTop() const { return m_top; }
// There is no GetRight()
// FUNCTION: BETA10 0x10098360
inline MxS16 GetBottom() const { return m_bottom; }
// FUNCTION: BETA10 0x10098390
inline MxS16 GetWidth() const { return m_right - m_left + 1; }
// FUNCTION: BETA10 0x100983c0
inline MxS16 GetHeight() const { return m_bottom - m_top + 1; }
private:
MxS16 m_left; // 0x00
MxS16 m_top; // 0x02
MxS16 m_right; // 0x04
MxS16 m_bottom; // 0x06
};
#endif // MXRECT16_H