#include "mxpresenter.h" #include "decomp.h" #include "define.h" #include "mxactionnotificationparam.h" #include "mxautolocker.h" #include "mxcompositepresenter.h" #include "mxdsanim.h" #include "mxdssound.h" #include "mxentity.h" #include "mxnotificationmanager.h" #include "mxobjectfactory.h" #include "mxparam.h" #include "mxstreamer.h" #include "mxutil.h" #include DECOMP_SIZE_ASSERT(MxPresenter, 0x40); // FUNCTION: LEGO1 0x100b4d50 void MxPresenter::Init() { m_currentTickleState = e_idle; m_action = NULL; m_location = MxPoint32(0, 0); m_displayZ = 0; m_compositePresenter = NULL; m_previousTickleStates = 0; } // FUNCTION: LEGO1 0x100b4d80 MxResult MxPresenter::StartAction(MxStreamController*, MxDSAction* p_action) { MxAutoLocker lock(&this->m_criticalSection); this->m_action = p_action; const Mx3DPointFloat& location = this->m_action->GetLocation(); MxS32 previousTickleState = this->m_currentTickleState; this->m_location = MxPoint32(this->m_action->GetLocation()[0], this->m_action->GetLocation()[1]); this->m_displayZ = this->m_action->GetLocation()[2]; ProgressTickleState(e_ready); return SUCCESS; } // FUNCTION: LEGO1 0x100b4e40 void MxPresenter::EndAction() { if (this->m_action == NULL) return; MxAutoLocker lock(&this->m_criticalSection); if (!this->m_compositePresenter) { #ifdef COMPAT_MODE { MxEndActionNotificationParam param(c_notificationEndAction, NULL, this->m_action, TRUE); MxOmni::GetInstance()->NotifyCurrentEntity(¶m); } #else MxOmni::GetInstance()->NotifyCurrentEntity( &MxEndActionNotificationParam(c_notificationEndAction, NULL, this->m_action, TRUE) ); #endif } this->m_action = NULL; MxS32 previousTickleState = 1 << m_currentTickleState; this->m_previousTickleStates |= previousTickleState; this->m_currentTickleState = e_idle; } // FUNCTION: LEGO1 0x100b4fc0 void MxPresenter::ParseExtra() { MxAutoLocker lock(&m_criticalSection); MxU16 len = m_action->GetExtraLength(); char* extraData = m_action->GetExtraData(); if (len) { // len &= MAXWORD; char extraCopy[512]; memcpy(extraCopy, extraData, len); extraCopy[len] = '\0'; char worldValue[512]; if (KeyValueStringParse(worldValue, g_strWORLD, extraCopy)) { char* token = strtok(worldValue, g_parseExtraTokens); char buf[256]; strcpy(buf, token); token = strtok(NULL, g_parseExtraTokens); MxS32 val = token ? atoi(token) : 0; MxEntity* result = MxOmni::GetInstance()->AddToWorld(buf, val, this); m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_world); if (result) { SendToCompositePresenter(MxOmni::GetInstance()); } } } } // FUNCTION: LEGO1 0x100b5120 void MxPresenter::SendToCompositePresenter(MxOmni* p_omni) { if (m_compositePresenter) { MxAutoLocker lock(&m_criticalSection); #ifdef COMPAT_MODE { MxNotificationParam param(c_notificationPresenter, this); NotificationManager()->Send(m_compositePresenter, ¶m); } #else NotificationManager()->Send(m_compositePresenter, &MxNotificationParam(c_notificationPresenter, this)); #endif m_action->SetOrigin(p_omni ? p_omni : MxOmni::GetInstance()); m_compositePresenter = NULL; } } // FUNCTION: LEGO1 0x100b5200 MxResult MxPresenter::Tickle() { MxAutoLocker lock(&this->m_criticalSection); switch (this->m_currentTickleState) { case e_ready: this->ReadyTickle(); if (m_currentTickleState != e_starting) { break; } case e_starting: this->StartingTickle(); if (m_currentTickleState != e_streaming) { break; } case e_streaming: this->StreamingTickle(); if (m_currentTickleState != e_repeating) { break; } case e_repeating: this->RepeatingTickle(); if (m_currentTickleState != e_unk5) { break; } case e_unk5: this->Unk5Tickle(); if (m_currentTickleState != e_done) { break; } case e_done: this->DoneTickle(); default: break; } return SUCCESS; } // FUNCTION: LEGO1 0x100b52d0 void MxPresenter::Enable(MxBool p_enable) { if (this->m_action && this->IsEnabled() != p_enable) { MxU32 flags = this->m_action->GetFlags(); if (p_enable) { this->m_action->SetFlags(flags | MxDSAction::c_enabled); } else { this->m_action->SetFlags(flags & ~MxDSAction::c_enabled); } } } // FUNCTION: LEGO1 0x100b5310 const char* PresenterNameDispatch(const MxDSAction& p_action) { const char* name = p_action.GetSourceName(); MxS32 format; if (!name || strlen(name) == 0) { switch (p_action.GetType()) { case MxDSObject::e_anim: format = ((MxDSAnim&) p_action).GetMediaFormat(); switch (format) { case FOURCC(' ', 'F', 'L', 'C'): name = !p_action.IsLooping() ? "MxFlcPresenter" : "MxLoopingFlcPresenter"; break; case FOURCC(' ', 'S', 'M', 'K'): name = !p_action.IsLooping() ? "MxSmkPresenter" : "MxLoopingSmkPresenter"; break; } break; case MxDSObject::e_sound: format = ((MxDSSound&) p_action).GetMediaFormat(); switch (format) { case FOURCC(' ', 'M', 'I', 'D'): name = !p_action.IsLooping() ? "MxMIDIPresenter" : "MxLoopingMIDIPresenter"; break; case FOURCC(' ', 'W', 'A', 'V'): name = "MxWavePresenter"; break; } break; case MxDSObject::e_serialAction: case MxDSObject::e_parallelAction: case MxDSObject::e_selectAction: name = "MxCompositePresenter"; break; case MxDSObject::e_event: name = "MxEventPresenter"; break; case MxDSObject::e_still: name = "MxStillPresenter"; break; } } return name; } // FUNCTION: LEGO1 0x100b5410 MxEntity* MxPresenter::CreateEntity(const char* p_name) { char buffer[512]; char buffer2[512]; strcpy(buffer, p_name); MxU16 extraLen = m_action->GetExtraLength(); buffer[0] = extraLen; buffer[1] = extraLen >> 8; if (extraLen) { extraLen &= MAXWORD; memcpy(buffer2 + 2, m_action->GetExtraData(), extraLen); buffer2[extraLen + 2] = 0; KeyValueStringParse(buffer, g_strOBJECT, buffer2 + 2); } return (MxEntity*) ObjectFactory()->Create(buffer); } // FUNCTION: LEGO1 0x100b54c0 MxBool MxPresenter::IsEnabled() { return this->m_action && this->m_action->GetFlags() & MxDSAction::c_enabled; }