diff --git a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h index 34b3082d..ac43faac 100644 --- a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h +++ b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h @@ -36,7 +36,7 @@ class MxControlPresenter : public MxCompositePresenter { virtual void Enable(MxBool p_enable) override; // vtable+0x54 virtual MxBool VTable0x64(undefined4 p_undefined) override; // vtable+0x64 virtual void VTable0x68(MxBool p_unk0x50); // vtable+0x68 - virtual void VTable0x6c(undefined2); // vtable+0x6c + virtual void VTable0x6c(MxS16); // vtable+0x6c MxBool FUN_10044480(LegoControlManagerEvent* p_event, MxPresenter* p_presenter); diff --git a/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp index ad19bb94..b4eccd2e 100644 --- a/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp @@ -2,8 +2,11 @@ #include "define.h" #include "legocontrolmanager.h" +#include "mxdsparallelaction.h" #include "mxticklemanager.h" +#include "mxtimer.h" #include "mxutil.h" +#include "mxvideopresenter.h" DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c) @@ -99,11 +102,110 @@ void MxControlPresenter::EndAction() } } -// STUB: LEGO1 0x10044270 +// FUNCTION: LEGO1 0x10044270 MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxPresenter* p_presenter) { - // TODO - return TRUE; + if (m_unk0x4c == 3) { + MxPresenter* first = *m_list.begin(); + if (p_presenter == first || first->GetDisplayZ() < first->GetDisplayZ()) { + MxS32 height = ((MxVideoPresenter*) first)->GetHeight(); + MxS32 width = ((MxVideoPresenter*) first)->GetWidth(); + + if (first->GetLocation().GetX() <= p_x && p_x < width - 1 + first->GetLocation().GetY() && + first->GetLocation().GetY() <= p_y && p_y < height - 1 + first->GetLocation().GetY()) { + + MxU8* start; + MxBitmap* bitmap = ((MxVideoPresenter*) first)->GetBitmap(); + + if (((MxVideoPresenter*) first)->GetAlphaMask() == NULL) { + MxLong biCompression = bitmap->GetBmiHeader()->biCompression; + MxLong height = bitmap->GetBmiHeight(); + MxLong seekRow; + + // DECOMP: Same basic layout as AlphaMask constructor + // The idea here is to again seek to the correct place in the bitmap's + // m_data buffer. The x,y args are (most likely) screen x and y, so we + // need to shift that to coordinates local to the bitmap by removing + // the MxPresenter location x and y coordinates. + if (biCompression == BI_RGB) { + if (biCompression == BI_RGB_TOPDOWN || height < 0) { + seekRow = p_y - first->GetLocation().GetY(); + } + else { + height = height > 0 ? height : -height; + seekRow = height - p_y - 1 + first->GetLocation().GetY(); + } + start = bitmap->GetBmiStride() * seekRow + bitmap->GetBitmapData() - + first->GetLocation().GetX() + p_x; + } + else if (biCompression == BI_RGB_TOPDOWN) { + start = bitmap->GetBitmapData(); + } + else { + height = height > 0 ? height : -height; + height--; + start = bitmap->GetBmiStride() * height + bitmap->GetBitmapData(); + } + } + else { + start = NULL; + } + m_unk0x56 = 0; + + if (m_unk0x58 == NULL) { + if (*start != 0) { + m_unk0x56 = 1; + } + } + else { + for (MxS16 i = 1; i <= *m_unk0x58; i++) { + if (m_unk0x58[i] == *start) { + m_unk0x56 = i; + break; + } + } + } + + if (m_unk0x56) { + return TRUE; + } + } + } + } + else { + if (HasCompositePresenter(&m_list, p_presenter)) { + if (m_unk0x4c == 2) { + MxS32 width = ((MxVideoPresenter*) p_presenter)->GetWidth(); + MxS32 height = ((MxVideoPresenter*) p_presenter)->GetHeight(); + + if (m_unk0x52 == 2 && m_unk0x54 == 2) { + MxS16 val; + if (p_x < p_presenter->GetLocation().GetX() + width / 2) { + val = 3; + if (p_y < p_presenter->GetLocation().GetY() + height / 2) { + val = 1; + } + m_unk0x56 = val; + return TRUE; + } + + val = 4; + if (p_y < p_presenter->GetLocation().GetY() + height / 2) { + val = 2; + } + + m_unk0x56 = val; + return TRUE; + } + } + else { + m_unk0x56 = -1; + } + + return TRUE; + } + } + return FALSE; } // FUNCTION: LEGO1 0x10044480 @@ -137,10 +239,28 @@ MxBool MxControlPresenter::FUN_10044480(LegoControlManagerEvent* p_event, MxPres return FALSE; } -// STUB: LEGO1 0x10044540 -void MxControlPresenter::VTable0x6c(undefined2) +// FUNCTION: LEGO1 0x10044540 +void MxControlPresenter::VTable0x6c(MxS16 p_val) { - // TODO + if (p_val == -1) { + if ((MxS16) ((MxDSParallelAction*) m_action)->GetActionList()->GetCount() - m_unk0x4e == 1) { + m_unk0x4e = 0; + } + else { + m_unk0x4e++; + } + } + else { + m_unk0x4e = p_val; + } + + m_action->SetUnknown90(Timer()->GetTime()); + + MxS16 i = 0; + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { + (*it)->Enable((m_unk0x4c == 3 && m_unk0x4e == 0 || !IsEnabled()) ? FALSE : m_unk0x4e == i); + i++; + } } // FUNCTION: LEGO1 0x10044610 diff --git a/LEGO1/omni/include/mxcompositepresenter.h b/LEGO1/omni/include/mxcompositepresenter.h index 33d00dc8..2f00af28 100644 --- a/LEGO1/omni/include/mxcompositepresenter.h +++ b/LEGO1/omni/include/mxcompositepresenter.h @@ -46,6 +46,8 @@ class MxCompositePresenter : public MxPresenter { return TRUE; }; // vtable+0x64 + inline MxCompositePresenterList* GetList() { return &m_list; } + protected: MxCompositePresenterList m_list; // 0x40 }; diff --git a/LEGO1/omni/include/mxutil.h b/LEGO1/omni/include/mxutil.h index e043ebd4..66f7be33 100644 --- a/LEGO1/omni/include/mxutil.h +++ b/LEGO1/omni/include/mxutil.h @@ -8,6 +8,8 @@ class MxDSFile; class MxDSObject; class MxDSAction; +class MxCompositePresenterList; +class MxPresenter; template inline T Abs(T p_t) @@ -71,6 +73,7 @@ MxBool GetRectIntersection( void MakeSourceName(char*, const char*); void SetOmniUserMessage(void (*)(const char*, int)); +MxBool HasCompositePresenter(MxCompositePresenterList* p_presenterList, MxPresenter* p_presenter); void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags); MxDSObject* CreateStreamObject(MxDSFile*, MxS16); diff --git a/LEGO1/omni/include/mxvideopresenter.h b/LEGO1/omni/include/mxvideopresenter.h index f338b972..8a461e5e 100644 --- a/LEGO1/omni/include/mxvideopresenter.h +++ b/LEGO1/omni/include/mxvideopresenter.h @@ -99,6 +99,7 @@ class MxVideoPresenter : public MxMediaPresenter { inline MxS32 PrepareRects(MxRect32& p_rectDest, MxRect32& p_rectSrc); inline MxBitmap* GetBitmap() { return m_bitmap; } + inline AlphaMask* GetAlphaMask() { return m_alpha; } // SYNTHETIC: LEGO1 0x1000c910 // MxVideoPresenter::`scalar deleting destructor' diff --git a/LEGO1/omni/src/common/mxutil.cpp b/LEGO1/omni/src/common/mxutil.cpp index 29b71863..cd309751 100644 --- a/LEGO1/omni/src/common/mxutil.cpp +++ b/LEGO1/omni/src/common/mxutil.cpp @@ -1,10 +1,12 @@ #include "mxutil.h" +#include "mxcompositepresenter.h" #include "mxdsaction.h" #include "mxdsactionlist.h" #include "mxdsfile.h" #include "mxdsmultiaction.h" #include "mxdsobject.h" +#include "mxpresenterlist.h" #include "mxrect32.h" // GLOBAL: LEGO1 0x101020e8 @@ -115,6 +117,19 @@ void SetOmniUserMessage(void (*p_userMsg)(const char*, int)) g_omniUserMessage = p_userMsg; } +// FUNCTION: LEGO1 0x100b7170 +MxBool HasCompositePresenter(MxCompositePresenterList* p_presenterList, MxPresenter* p_presenter) +{ + for (MxCompositePresenterList::iterator it = p_presenterList->begin(); it != p_presenterList->end(); it++) { + if (p_presenter == *it || (*it)->IsA("MxCompositePresenter") && + HasCompositePresenter(((MxCompositePresenter*) *it)->GetList(), p_presenter)) { + return TRUE; + } + } + + return FALSE; +} + // FUNCTION: LEGO1 0x100b7220 void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags) {