mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
CWE Directory Reorganization
Rearrange directory structure of CWE to be loosely equivalent to the H'uru Plasma repository. Part 1: Movement of directories and files.
This commit is contained in:
377
Sources/Plasma/NucleusLib/pnSceneObject/plAudioInterface.cpp
Normal file
377
Sources/Plasma/NucleusLib/pnSceneObject/plAudioInterface.cpp
Normal file
@ -0,0 +1,377 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "plAudioInterface.h"
|
||||
#include "plAudible.h"
|
||||
#include "../pnMessage/plAudioSysMsg.h"
|
||||
#include "../pnMessage/plSoundMsg.h"
|
||||
#include "hsBounds.h"
|
||||
#include "hsStream.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "plSceneObject.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "../pnMessage/plEnableMsg.h"
|
||||
#include "../pnMessage/plIntRefMsg.h"
|
||||
#include "plCoordinateInterface.h"
|
||||
#include "../pnMessage/plNodeRefMsg.h"
|
||||
#include "../pnMessage/plProxyDrawMsg.h"
|
||||
#include "../pnNetCommon/plNetApp.h"
|
||||
#include "hsTimer.h"
|
||||
|
||||
|
||||
plAudioInterface::plAudioInterface()
|
||||
: fAudible(nil), fAudibleInited( false )
|
||||
{
|
||||
fRegisteredForASysMsg = false;
|
||||
}
|
||||
|
||||
plAudioInterface::~plAudioInterface()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void plAudioInterface::SetProperty(int prop, hsBool on)
|
||||
{
|
||||
plObjInterface::SetProperty(prop, on);
|
||||
|
||||
if( fAudible )
|
||||
fAudible->SetProperty(prop, on);
|
||||
}
|
||||
|
||||
plSound* plAudioInterface::GetSound(int i) const
|
||||
{
|
||||
if( fAudible )
|
||||
return fAudible->GetSound(i);
|
||||
return nil;
|
||||
}
|
||||
|
||||
int plAudioInterface::GetSoundIndex(const char *keyname)
|
||||
{
|
||||
if( fAudible )
|
||||
return fAudible->GetSoundIndex(keyname);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int plAudioInterface::GetNumSounds() const
|
||||
{
|
||||
if( fAudible )
|
||||
return fAudible->GetNumSounds();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// set the filename of sound[index] within the audible
|
||||
void plAudioInterface::SetSoundFilename(int index, const char *filename, bool isCompressed)
|
||||
{
|
||||
if(fAudible)
|
||||
fAudible->SetFilename(index, filename, isCompressed);
|
||||
}
|
||||
|
||||
void plAudioInterface::ISetSceneNode(plKey key)
|
||||
{
|
||||
if( fAudible )
|
||||
{
|
||||
fAudible->SetSceneNode(key);
|
||||
if( !fAudibleInited )
|
||||
{
|
||||
int isLocal = IsLocallyOwned();
|
||||
|
||||
plKey localKey = ( plNetClientApp::GetInstance() != nil ) ? plNetClientApp::GetInstance()->GetLocalPlayerKey() : nil;
|
||||
if( fOwner && fOwner->GetKey() == localKey )
|
||||
isLocal = true;
|
||||
else
|
||||
isLocal = false;
|
||||
|
||||
fAudible->Init( isLocal );//( isLocal == plSynchedObject::kYes ) );
|
||||
fAudibleInited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plAudioInterface::ISetOwner(plSceneObject* owner)
|
||||
{
|
||||
plObjInterface::ISetOwner(owner);
|
||||
|
||||
if( owner && !fRegisteredForASysMsg )
|
||||
{
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plAudioSysMsg::Index(), GetKey());
|
||||
fRegisteredForASysMsg = true;
|
||||
}
|
||||
else if( owner == nil && fRegisteredForASysMsg )
|
||||
{
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plAudioSysMsg::Index(), GetKey());
|
||||
fRegisteredForASysMsg = false;
|
||||
}
|
||||
|
||||
if (fAudible)
|
||||
fAudible->SetSceneObject(owner ? owner->GetKey() : nil);
|
||||
}
|
||||
|
||||
|
||||
void plAudioInterface::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
if( fAudible )
|
||||
fAudible->SetTransform(l2w, w2l);
|
||||
}
|
||||
|
||||
void plAudioInterface::Read(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Read(s, mgr);
|
||||
|
||||
plIntRefMsg* refMsg = TRACKED_NEW plIntRefMsg(GetKey(), plRefMsg::kOnCreate, 0, plIntRefMsg::kAudible);
|
||||
mgr->ReadKeyNotifyMe(s, refMsg, plRefFlags::kActiveRef);
|
||||
}
|
||||
|
||||
void plAudioInterface::Write(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Write(s, mgr);
|
||||
|
||||
mgr->WriteKey(s,fAudible);
|
||||
}
|
||||
|
||||
void plAudioInterface::ISetAudible(plAudible* aud)
|
||||
{
|
||||
fAudible = aud;
|
||||
if( fAudible )
|
||||
{
|
||||
fAudible->SetSceneNode(GetSceneNode());
|
||||
if (fOwner)
|
||||
fAudible->SetSceneObject(fOwner->GetKey());
|
||||
}
|
||||
|
||||
plAudioSysMsg* pMsg = TRACKED_NEW plAudioSysMsg( plAudioSysMsg::kPing );
|
||||
pMsg->SetSender(GetKey());
|
||||
// pMsg->SetBCastFlag(plMessage::kBCastByExactType, false);
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
|
||||
void plAudioInterface::IRemoveAudible(plAudible* aud)
|
||||
{
|
||||
hsAssert(aud == fAudible, "Removing Audible I don't have");
|
||||
fAudible = nil;
|
||||
}
|
||||
|
||||
hsBool plAudioInterface::MsgReceive(plMessage* msg)
|
||||
{
|
||||
plIntRefMsg* intRefMsg = plIntRefMsg::ConvertNoRef(msg);
|
||||
if( intRefMsg )
|
||||
{
|
||||
switch( intRefMsg->fType )
|
||||
{
|
||||
case plIntRefMsg::kAudible:
|
||||
if( intRefMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
|
||||
{
|
||||
IRemoveAudible(plAudible::ConvertNoRef(intRefMsg->GetRef()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ISetAudible(plAudible::ConvertNoRef(intRefMsg->GetRef()));
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
plSoundMsg* pSoundMsg = plSoundMsg::ConvertNoRef( msg );
|
||||
if (pSoundMsg)
|
||||
{
|
||||
if (!fAudible)
|
||||
return false;
|
||||
if (pSoundMsg->Cmd( plSoundMsg::kAddCallbacks))
|
||||
fAudible->AddCallbacks( pSoundMsg );
|
||||
if (pSoundMsg->Cmd( plSoundMsg::kRemoveCallbacks))
|
||||
fAudible->RemoveCallbacks( pSoundMsg );
|
||||
if (pSoundMsg->Cmd( plSoundMsg::kStop ) )
|
||||
fAudible->Stop(pSoundMsg->fIndex);
|
||||
if (pSoundMsg->Cmd( plSoundMsg::kGoToTime ) )
|
||||
fAudible->SetTime(pSoundMsg->fTime, pSoundMsg->fIndex);
|
||||
if (pSoundMsg->Cmd( plSoundMsg::kPlay ) )
|
||||
fAudible->Play(pSoundMsg->fIndex);
|
||||
if(pSoundMsg->Cmd( plSoundMsg::kSynchedPlay))
|
||||
fAudible->SynchedPlay(pSoundMsg->fIndex);
|
||||
if (pSoundMsg->Cmd( plSoundMsg::kSetLooping ) )
|
||||
fAudible->SetLooping(true,pSoundMsg->fIndex);
|
||||
if (pSoundMsg->Cmd( plSoundMsg::kUnSetLooping ) )
|
||||
fAudible->SetLooping(false,pSoundMsg->fIndex);
|
||||
if (pSoundMsg->Cmd( plSoundMsg::kToggleState ) )
|
||||
{
|
||||
if (fAudible->IsPlaying(pSoundMsg->fIndex))
|
||||
fAudible->Stop(pSoundMsg->fIndex);
|
||||
else
|
||||
fAudible->Play(pSoundMsg->fIndex);
|
||||
}
|
||||
if (pSoundMsg->Cmd( plSoundMsg::kGetStatus ) )
|
||||
{
|
||||
fAudible->GetStatus(pSoundMsg);
|
||||
}
|
||||
if (pSoundMsg->Cmd( plSoundMsg::kGetNumSounds ) )
|
||||
{
|
||||
plSoundMsg* pReply = TRACKED_NEW plSoundMsg;
|
||||
pReply->fIndex = fAudible->GetNumSounds();
|
||||
pReply->AddReceiver(pSoundMsg->GetSender());
|
||||
pReply->SetCmd( plSoundMsg::kGetNumSounds );
|
||||
plgDispatch::MsgSend(pReply);
|
||||
}
|
||||
if( pSoundMsg->Cmd( plSoundMsg::kSetVolume ) )
|
||||
{
|
||||
fAudible->SetVolume( pSoundMsg->fVolume, pSoundMsg->fIndex );
|
||||
}
|
||||
if ( pSoundMsg->Cmd( plSoundMsg::kSetTalkIcon ) )
|
||||
{
|
||||
fAudible->SetTalkIcon(pSoundMsg->fIndex, pSoundMsg->fNameStr);
|
||||
}
|
||||
if ( pSoundMsg->Cmd( plSoundMsg::kClearTalkIcon ) )
|
||||
{
|
||||
fAudible->ClearTalkIcon();
|
||||
}
|
||||
if ( pSoundMsg->Cmd( plSoundMsg::kSetFadeIn ) )
|
||||
{
|
||||
fAudible->SetFadeIn( (int)pSoundMsg->fFadeType, pSoundMsg->fVolume, pSoundMsg->fIndex );
|
||||
}
|
||||
if ( pSoundMsg->Cmd( plSoundMsg::kSetFadeOut ) )
|
||||
{
|
||||
fAudible->SetFadeOut( (int)pSoundMsg->fFadeType, pSoundMsg->fVolume, pSoundMsg->fIndex );
|
||||
}
|
||||
if( pSoundMsg->Cmd( plSoundMsg::kFastForwardPlay ) )
|
||||
{
|
||||
fAudible->FastForwardPlay(pSoundMsg->fIndex);
|
||||
}
|
||||
if(pSoundMsg->Cmd(plSoundMsg::kFastForwardToggle) )
|
||||
{
|
||||
fAudible->FastForwardToggle(pSoundMsg->fIndex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
plAudioSysMsg* pASMsg = plAudioSysMsg::ConvertNoRef( msg );
|
||||
if (pASMsg)
|
||||
{
|
||||
if (pASMsg->GetAudFlag() == plAudioSysMsg::kActivate)
|
||||
{
|
||||
if( fAudible )
|
||||
{
|
||||
if( !fAudibleInited )
|
||||
{
|
||||
int isLocal = IsLocallyOwned();
|
||||
fAudible->Init( ( isLocal == plSynchedObject::kYes ) );
|
||||
fAudibleInited = true;
|
||||
}
|
||||
if( !fAudibleInited )
|
||||
{
|
||||
// Arrgh, can't activate yet, so attempt to re-activate some time in the near future
|
||||
pASMsg = TRACKED_NEW plAudioSysMsg( plAudioSysMsg::kActivate );
|
||||
pASMsg->SetBCastFlag( plMessage::kBCastByExactType, false );
|
||||
pASMsg->SetBCastFlag( plMessage::kNetPropagate, false );
|
||||
pASMsg->SetTimeStamp( hsTimer::GetSysSeconds() + 1.f );
|
||||
pASMsg->Send( GetKey() );
|
||||
return true;
|
||||
}
|
||||
fAudible->Activate();
|
||||
if (GetOwner() && GetOwner()->GetCoordinateInterface())
|
||||
{
|
||||
hsMatrix44 l2w = GetOwner()->GetCoordinateInterface()->GetLocalToWorld();
|
||||
hsMatrix44 w2l = GetOwner()->GetCoordinateInterface()->GetWorldToLocal();;
|
||||
fAudible->SetTransform(l2w,w2l);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pASMsg->GetAudFlag() == plAudioSysMsg::kDeActivate)
|
||||
{
|
||||
if( fAudible )
|
||||
fAudible->DeActivate();
|
||||
}
|
||||
if( pASMsg->GetAudFlag() == plAudioSysMsg::kMuteAll )
|
||||
{
|
||||
if( fAudible )
|
||||
fAudible->SetMuted( true );
|
||||
}
|
||||
else if( pASMsg->GetAudFlag() == plAudioSysMsg::kUnmuteAll )
|
||||
{
|
||||
if( fAudible )
|
||||
fAudible->SetMuted( false );
|
||||
}
|
||||
else if( pASMsg->GetAudFlag() == plAudioSysMsg::kChannelVolChanged )
|
||||
{
|
||||
if( fAudible )
|
||||
return fAudible->MsgReceive( msg );
|
||||
}
|
||||
}
|
||||
|
||||
plEnableMsg* pEnableMsg = plEnableMsg::ConvertNoRef( msg );
|
||||
if (pEnableMsg)
|
||||
{
|
||||
SetProperty( kDisable, pEnableMsg->Cmd(kDisable) );
|
||||
return true;
|
||||
}
|
||||
|
||||
// proxyDrawMsg handling--just pass it on to the audible
|
||||
plProxyDrawMsg *pdMsg = plProxyDrawMsg::ConvertNoRef( msg );
|
||||
if( pdMsg != nil )
|
||||
{
|
||||
if( fAudible )
|
||||
return fAudible->MsgReceive( pdMsg );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return plObjInterface::MsgReceive(msg);
|
||||
}
|
||||
|
||||
|
||||
void plAudioInterface::ReleaseData()
|
||||
{
|
||||
if (fAudible)
|
||||
{
|
||||
// To get rid of our data, we need to release our active ref and tell the SceneNode
|
||||
// to dump it. It will autodestruct after those two active refs are released, unless
|
||||
// someone else has a ref on it as well (in which case we don't want to be nuking it
|
||||
// anyway).
|
||||
fAudible->SetSceneNode(nil);
|
||||
// Audible key is gone already, I guess the audioInterface doesn't have a ref -Colin
|
||||
// GetKey()->Release(fAudible->GetKey());
|
||||
}
|
||||
}
|
110
Sources/Plasma/NucleusLib/pnSceneObject/plAudioInterface.h
Normal file
110
Sources/Plasma/NucleusLib/pnSceneObject/plAudioInterface.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
|
||||
#ifndef plAudioInterface_inc
|
||||
#define plAudioInterface_inc
|
||||
|
||||
#include "plObjInterface.h"
|
||||
|
||||
class plSound;
|
||||
class plAudible;
|
||||
class hsStream;
|
||||
class hsResMgr;
|
||||
struct hsMatrix44;
|
||||
class hsBounds3Ext;
|
||||
|
||||
|
||||
class plAudioInterface : public plObjInterface
|
||||
{
|
||||
public:
|
||||
// Props inc by 1 (bit shift in bitvector).
|
||||
enum plAudioProperties {
|
||||
kDisable = 0, // prop 0 is always disable, declared in plObjInterface
|
||||
|
||||
kNumProps // last in the list
|
||||
};
|
||||
protected:
|
||||
plAudible* fAudible; // references into system pools
|
||||
|
||||
hsBool fRegisteredForASysMsg, fAudibleInited;
|
||||
|
||||
void ISetAudible(plAudible* aud);
|
||||
void IRemoveAudible(plAudible* aud);
|
||||
|
||||
virtual void ISetOwner(plSceneObject* owner);
|
||||
virtual void ISetSceneNode(plKey node);
|
||||
|
||||
friend class plSceneObject;
|
||||
|
||||
public:
|
||||
plAudioInterface();
|
||||
~plAudioInterface();
|
||||
|
||||
CLASSNAME_REGISTER( plAudioInterface );
|
||||
GETINTERFACE_ANY( plAudioInterface, plObjInterface );
|
||||
|
||||
virtual void Read(hsStream* stream, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* stream, hsResMgr* mgr);
|
||||
|
||||
void SetProperty(int prop, hsBool on);
|
||||
Int32 GetNumProperties() const { return kNumProps; }
|
||||
|
||||
plSound* GetSound(int i) const;
|
||||
int GetNumSounds() const;
|
||||
|
||||
virtual hsBool MsgReceive(plMessage* msg);
|
||||
|
||||
// for export only!!!!!
|
||||
plAudible* GetAudible() const { return fAudible; }
|
||||
/// don't call this otherwise!
|
||||
|
||||
// Transform settable only, if you want it get it from the coordinate interface.
|
||||
void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
|
||||
virtual void ReleaseData( void );
|
||||
void SetSoundFilename(int index, const char *filename, bool isCompressed);
|
||||
int GetSoundIndex(const char *keyname);
|
||||
};
|
||||
|
||||
|
||||
#endif // plAudioInterface_inc
|
@ -0,0 +1,660 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "plCoordinateInterface.h"
|
||||
#include "plDrawInterface.h"
|
||||
#include "plSimulationInterface.h"
|
||||
#include "plAudioInterface.h"
|
||||
#include "../pnMessage/plWarpMsg.h"
|
||||
#include "../pnMessage/plTimeMsg.h"
|
||||
#include "../pnMessage/plCorrectionMsg.h"
|
||||
#include "../pnMessage/plIntRefMsg.h"
|
||||
#include "../pnNetCommon/plSDLTypes.h"
|
||||
#include "plSceneObject.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "hsStream.h"
|
||||
|
||||
#include "plProfile.h"
|
||||
|
||||
UInt8 plCoordinateInterface::fTransformPhase = plCoordinateInterface::kTransformPhaseNormal;
|
||||
hsBool plCoordinateInterface::fDelayedTransformsEnabled = true;
|
||||
|
||||
plCoordinateInterface::plCoordinateInterface()
|
||||
: fParent(nil),
|
||||
fReason(kReasonUnknown)
|
||||
{
|
||||
fLocalToParent.Reset();
|
||||
fParentToLocal.Reset();
|
||||
|
||||
fLocalToWorld.Reset();
|
||||
fWorldToLocal.Reset();
|
||||
|
||||
fState = 0;
|
||||
}
|
||||
|
||||
plCoordinateInterface::~plCoordinateInterface()
|
||||
{
|
||||
if( fParent )
|
||||
fParent->IRemoveChild(IGetOwner());
|
||||
int i;
|
||||
for( i = fChildren.GetCount()-1; i >= 0; i-- )
|
||||
IRemoveChild(i);
|
||||
}
|
||||
|
||||
void plCoordinateInterface::ISetSceneNode(plKey newNode)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fChildren.GetCount(); i++ )
|
||||
{
|
||||
if( fChildren[i] )
|
||||
fChildren[i]->SetSceneNode(newNode);
|
||||
}
|
||||
}
|
||||
|
||||
void plCoordinateInterface::ISetOwner(plSceneObject* so)
|
||||
{
|
||||
plObjInterface::ISetOwner(so);
|
||||
|
||||
IDirtyTransform();
|
||||
fReason |= kReasonUnknown;
|
||||
}
|
||||
|
||||
void plCoordinateInterface::ISetParent(plCoordinateInterface* par)
|
||||
{
|
||||
fParent = par;
|
||||
|
||||
// This won't have any effect if my owner is NetGroupConstant
|
||||
if( fParent )
|
||||
ISetNetGroupRecur(fParent->GetNetGroup());
|
||||
|
||||
IDirtyTransform();
|
||||
fReason |= kReasonUnknown;
|
||||
}
|
||||
|
||||
plCoordinateInterface* plCoordinateInterface::GetChild(int i) const
|
||||
{
|
||||
return fChildren[i] ? fChildren[i]->GetVolatileCoordinateInterface() : nil;
|
||||
}
|
||||
|
||||
void plCoordinateInterface::IRemoveChild(int i)
|
||||
{
|
||||
if( fChildren[i] )
|
||||
{
|
||||
plCoordinateInterface* childCI = fChildren[i]->GetVolatileCoordinateInterface();
|
||||
if( childCI )
|
||||
childCI->ISetParent(nil);
|
||||
}
|
||||
fChildren.Remove(i);
|
||||
}
|
||||
|
||||
void plCoordinateInterface::IRemoveChild(plSceneObject* child)
|
||||
{
|
||||
int idx = fChildren.Find(child);
|
||||
if( idx != fChildren.kMissingIndex )
|
||||
IRemoveChild(idx);
|
||||
}
|
||||
|
||||
void plCoordinateInterface::ISetChild(plSceneObject* child, int which)
|
||||
{
|
||||
hsAssert(child, "Setting a nil child");
|
||||
plCoordinateInterface* childCI = child->GetVolatileCoordinateInterface();
|
||||
hsAssert(childCI, "Child with no coordinate interface");
|
||||
childCI->ISetParent(this);
|
||||
|
||||
if( which < 0 )
|
||||
which = fChildren.GetCount();
|
||||
fChildren.ExpandAndZero(which+1);
|
||||
fChildren[which] = child;
|
||||
|
||||
// If we can't delay our transform update, neither can any of our parents.
|
||||
if (!childCI->GetProperty(kDelayedTransformEval))
|
||||
{
|
||||
plCoordinateInterface *current = childCI->GetParent();
|
||||
while (current)
|
||||
{
|
||||
current->SetProperty(kDelayedTransformEval, false);
|
||||
current = current->GetParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plCoordinateInterface::IAddChild(plSceneObject* child)
|
||||
{
|
||||
ISetChild(child, -1);
|
||||
}
|
||||
|
||||
void plCoordinateInterface::IAttachChild(plSceneObject* child, UInt8 flags)
|
||||
{
|
||||
hsAssert(child, "Attaching a nil child");
|
||||
plCoordinateInterface* childCI = child->GetVolatileCoordinateInterface();
|
||||
hsAssert(childCI, "Owner without CoordinateInterface being attached");
|
||||
|
||||
if (childCI->GetParent() == this)
|
||||
return; // We're already attached! Who told us to do this?
|
||||
|
||||
hsMatrix44 l2w = childCI->GetLocalToWorld();
|
||||
hsMatrix44 w2l = childCI->GetWorldToLocal();
|
||||
|
||||
if( childCI->GetParent() )
|
||||
childCI->GetParent()->IDetachChild(child, flags | kAboutToAttach);
|
||||
|
||||
childCI->IUnRegisterForTransformMessage();
|
||||
|
||||
IAddChild(child);
|
||||
|
||||
if( flags & kMaintainWorldPosition )
|
||||
childCI->WarpToWorld(l2w,w2l);
|
||||
}
|
||||
|
||||
void plCoordinateInterface::IDetachChild(plSceneObject* child, UInt8 flags)
|
||||
{
|
||||
hsAssert(child, "Detaching a nil child");
|
||||
plCoordinateInterface* childCI = child->GetVolatileCoordinateInterface();
|
||||
hsAssert(childCI, "Owner without CoordinateInterface being attached");
|
||||
|
||||
hsMatrix44 l2w = childCI->GetLocalToWorld();
|
||||
hsMatrix44 w2l = childCI->GetWorldToLocal();
|
||||
|
||||
GetKey()->Release(child->GetKey());
|
||||
if( IGetOwner() && IGetOwner()->GetKey() )
|
||||
IGetOwner()->GetKey()->Release(child->GetKey());
|
||||
IRemoveChild(child);
|
||||
|
||||
if( flags & kMaintainWorldPosition )
|
||||
childCI->WarpToWorld(l2w,w2l);
|
||||
|
||||
// If the child was keeping us from delaying our transform,
|
||||
// maybe we can, now that it's gone.
|
||||
if (!childCI->GetProperty(kDelayedTransformEval))
|
||||
IUpdateDelayProp();
|
||||
}
|
||||
|
||||
/*
|
||||
* A few notes on the delay transform properties...
|
||||
*
|
||||
* The kCanEverDelayTransform prop is independent of any parents/children.
|
||||
* It means this particular node must always update its transform in response
|
||||
* to a plTransformMsg. It is intended for objects with physics, because they
|
||||
* need to be up-to-date before the simulationMgr updates the physical world.
|
||||
*
|
||||
* The kDelayedTransformEval prop is for nodes that are free of physics. (So no
|
||||
* physical descendants either). If the property is set, we won't update our
|
||||
* transform until AFTER the simulationMgr does its work.
|
||||
*
|
||||
* When we attach a child that can't delay its eval (at the moment), we recurse
|
||||
* up to the root, turning off the kDelayedTransformEval prop as we go. When we
|
||||
* remove such a child, we check if that child was the only reason we weren't
|
||||
* delaying our transform. If so, we update ourself and tell our parent to check.
|
||||
*
|
||||
* BTW: The POINT of all this is that when we update our l2w transforms because
|
||||
* we're animated, and then we update AGAIN after a parent node of ours involved
|
||||
* in physics gets a slight nudge, the first update becomes pointless. The
|
||||
* delay prop bookkeeping keeps us from doing the wasted calculations. And since
|
||||
* nearly all bones on the avatar are in this exact situation, it's worth doing.
|
||||
*/
|
||||
void plCoordinateInterface::IUpdateDelayProp()
|
||||
{
|
||||
int i;
|
||||
if (!GetProperty(kCanEverDelayTransform))
|
||||
return;
|
||||
|
||||
for (i = 0; i < GetNumChildren(); i++)
|
||||
{
|
||||
// If we still have a child that needs the delay...
|
||||
if (!GetChild(i)->GetProperty(kDelayedTransformEval))
|
||||
return;
|
||||
}
|
||||
|
||||
// Cool, we can delay now, which means maybe our parent can too.
|
||||
SetProperty(kDelayedTransformEval, true);
|
||||
if (GetParent())
|
||||
GetParent()->IUpdateDelayProp();
|
||||
}
|
||||
|
||||
plCoordinateInterface* plCoordinateInterface::IGetRoot()
|
||||
{
|
||||
return fParent ? fParent->IGetRoot() : this;
|
||||
}
|
||||
|
||||
void plCoordinateInterface::IRegisterForTransformMessage(hsBool delayed)
|
||||
{
|
||||
if( IGetOwner() )
|
||||
{
|
||||
if ((delayed || fTransformPhase == kTransformPhaseDelayed) && fDelayedTransformsEnabled)
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plDelayedTransformMsg::Index(), IGetOwner()->GetKey());
|
||||
else
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plTransformMsg::Index(), IGetOwner()->GetKey());
|
||||
}
|
||||
}
|
||||
|
||||
void plCoordinateInterface::IUnRegisterForTransformMessage()
|
||||
{
|
||||
if( IGetOwner() )
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plTransformMsg::Index(), IGetOwner()->GetKey());
|
||||
}
|
||||
|
||||
|
||||
void plCoordinateInterface::IDirtyTransform()
|
||||
{
|
||||
fState |= kTransformDirty;
|
||||
|
||||
IGetRoot()->IRegisterForTransformMessage(GetProperty(kDelayedTransformEval));
|
||||
}
|
||||
|
||||
void plCoordinateInterface::MultTransformLocal(const hsMatrix44& move, const hsMatrix44& invMove)
|
||||
{
|
||||
fReason |= kReasonUnknown;
|
||||
fLocalToParent = move * fLocalToParent;
|
||||
fParentToLocal = fParentToLocal * invMove;
|
||||
|
||||
IDirtyTransform();
|
||||
}
|
||||
|
||||
void plCoordinateInterface::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
fReason |= kReasonUnknown;
|
||||
|
||||
if( fParent )
|
||||
{
|
||||
SetLocalToParent(fParent->GetWorldToLocal() * l2w, w2l * fParent->GetLocalToWorld());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLocalToParent(l2w, w2l);
|
||||
}
|
||||
}
|
||||
|
||||
void plCoordinateInterface::SetTransformPhysical(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
// since we use public interfaces to do the details
|
||||
// AND those public interfaces could be called by anyone
|
||||
// AND those public interfaces therefore have to set their own "reason" for the transform change
|
||||
// THEREFORE: we need to preserve the "reason" flags before we call the public interfaces
|
||||
// so that we don't get reasonPhysics + reasonUnknown, just reasonPhysics
|
||||
UInt16 oldReason = fReason;
|
||||
|
||||
if( fParent )
|
||||
{
|
||||
SetLocalToParent(fParent->GetWorldToLocal() * l2w, w2l * fParent->GetLocalToWorld());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLocalToParent(l2w, w2l);
|
||||
}
|
||||
fReason = oldReason | kReasonPhysics;
|
||||
}
|
||||
|
||||
UInt16 plCoordinateInterface::GetReasons()
|
||||
{
|
||||
return fReason;
|
||||
}
|
||||
|
||||
void plCoordinateInterface::ClearReasons()
|
||||
{
|
||||
fReason = nil;
|
||||
}
|
||||
|
||||
void plCoordinateInterface::SetLocalToParent(const hsMatrix44& l2p, const hsMatrix44& p2l)
|
||||
{
|
||||
fReason |= kReasonUnknown;
|
||||
fLocalToParent = l2p;
|
||||
fParentToLocal = p2l;
|
||||
|
||||
IDirtyTransform();
|
||||
}
|
||||
|
||||
void plCoordinateInterface::WarpToLocal(const hsMatrix44& l2p, const hsMatrix44& p2l)
|
||||
{
|
||||
fReason |= kReasonUnknown;
|
||||
SetLocalToParent(l2p, p2l);
|
||||
|
||||
// update physical state when an object is warped
|
||||
if (IGetOwner())
|
||||
IGetOwner()->DirtySynchState(kSDLPhysical, 0);
|
||||
}
|
||||
|
||||
void plCoordinateInterface::WarpToWorld(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
fReason |= kReasonUnknown;
|
||||
if( fParent )
|
||||
{
|
||||
hsMatrix44 l2p = fParent->GetWorldToLocal() * l2w;
|
||||
hsMatrix44 p2l = w2l * fParent->GetLocalToWorld();
|
||||
WarpToLocal(l2p, p2l);
|
||||
}
|
||||
else
|
||||
{
|
||||
WarpToLocal(l2w, w2l);
|
||||
}
|
||||
}
|
||||
|
||||
plProfile_CreateCounter("CITrans", "Object", CITrans);
|
||||
plProfile_CreateCounter(" CIRecalc", "Object", CIRecalc);
|
||||
plProfile_CreateCounter(" CIDirty", "Object", CIDirty);
|
||||
plProfile_CreateCounter(" CISet", "Object", CISet);
|
||||
|
||||
plProfile_CreateTimer("CITransT", "Object", CITransT);
|
||||
plProfile_CreateTimer(" CIRecalcT", "Object", CIRecalcT);
|
||||
plProfile_CreateTimer(" CIDirtyT", "Object", CIDirtyT);
|
||||
plProfile_CreateTimer(" CISetT", "Object", CISetT);
|
||||
|
||||
static inline hsMatrix44 IMatrixMul34(const hsMatrix44& lhs, const hsMatrix44& rhs)
|
||||
{
|
||||
hsMatrix44 ret;
|
||||
ret.NotIdentity();
|
||||
ret.fMap[3][0] = ret.fMap[3][1] = ret.fMap[3][2] = 0;
|
||||
ret.fMap[3][3] = 1.f;
|
||||
|
||||
ret.fMap[0][0] = lhs.fMap[0][0] * rhs.fMap[0][0]
|
||||
+ lhs.fMap[0][1] * rhs.fMap[1][0]
|
||||
+ lhs.fMap[0][2] * rhs.fMap[2][0];
|
||||
|
||||
ret.fMap[0][1] = lhs.fMap[0][0] * rhs.fMap[0][1]
|
||||
+ lhs.fMap[0][1] * rhs.fMap[1][1]
|
||||
+ lhs.fMap[0][2] * rhs.fMap[2][1];
|
||||
|
||||
ret.fMap[0][2] = lhs.fMap[0][0] * rhs.fMap[0][2]
|
||||
+ lhs.fMap[0][1] * rhs.fMap[1][2]
|
||||
+ lhs.fMap[0][2] * rhs.fMap[2][2];
|
||||
|
||||
ret.fMap[0][3] = lhs.fMap[0][0] * rhs.fMap[0][3]
|
||||
+ lhs.fMap[0][1] * rhs.fMap[1][3]
|
||||
+ lhs.fMap[0][2] * rhs.fMap[2][3]
|
||||
+ lhs.fMap[0][3];
|
||||
|
||||
ret.fMap[1][0] = lhs.fMap[1][0] * rhs.fMap[0][0]
|
||||
+ lhs.fMap[1][1] * rhs.fMap[1][0]
|
||||
+ lhs.fMap[1][2] * rhs.fMap[2][0];
|
||||
|
||||
ret.fMap[1][1] = lhs.fMap[1][0] * rhs.fMap[0][1]
|
||||
+ lhs.fMap[1][1] * rhs.fMap[1][1]
|
||||
+ lhs.fMap[1][2] * rhs.fMap[2][1];
|
||||
|
||||
ret.fMap[1][2] = lhs.fMap[1][0] * rhs.fMap[0][2]
|
||||
+ lhs.fMap[1][1] * rhs.fMap[1][2]
|
||||
+ lhs.fMap[1][2] * rhs.fMap[2][2];
|
||||
|
||||
ret.fMap[1][3] = lhs.fMap[1][0] * rhs.fMap[0][3]
|
||||
+ lhs.fMap[1][1] * rhs.fMap[1][3]
|
||||
+ lhs.fMap[1][2] * rhs.fMap[2][3]
|
||||
+ lhs.fMap[1][3];
|
||||
|
||||
ret.fMap[2][0] = lhs.fMap[2][0] * rhs.fMap[0][0]
|
||||
+ lhs.fMap[2][1] * rhs.fMap[1][0]
|
||||
+ lhs.fMap[2][2] * rhs.fMap[2][0];
|
||||
|
||||
ret.fMap[2][1] = lhs.fMap[2][0] * rhs.fMap[0][1]
|
||||
+ lhs.fMap[2][1] * rhs.fMap[1][1]
|
||||
+ lhs.fMap[2][2] * rhs.fMap[2][1];
|
||||
|
||||
ret.fMap[2][2] = lhs.fMap[2][0] * rhs.fMap[0][2]
|
||||
+ lhs.fMap[2][1] * rhs.fMap[1][2]
|
||||
+ lhs.fMap[2][2] * rhs.fMap[2][2];
|
||||
|
||||
ret.fMap[2][3] = lhs.fMap[2][0] * rhs.fMap[0][3]
|
||||
+ lhs.fMap[2][1] * rhs.fMap[1][3]
|
||||
+ lhs.fMap[2][2] * rhs.fMap[2][3]
|
||||
+ lhs.fMap[2][3];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void plCoordinateInterface::IRecalcTransforms()
|
||||
{
|
||||
plProfile_IncCount(CIRecalc, 1);
|
||||
plProfile_BeginTiming(CIRecalcT);
|
||||
if( fParent )
|
||||
{
|
||||
#if 0
|
||||
fLocalToWorld = fParent->GetLocalToWorld() * fLocalToParent;
|
||||
fWorldToLocal = fParentToLocal * fParent->GetWorldToLocal();
|
||||
#else
|
||||
fLocalToWorld = IMatrixMul34(fParent->GetLocalToWorld(), fLocalToParent);
|
||||
fWorldToLocal = IMatrixMul34(fParentToLocal, fParent->GetWorldToLocal());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
fLocalToWorld = fLocalToParent;
|
||||
fWorldToLocal = fParentToLocal;
|
||||
}
|
||||
plProfile_EndTiming(CIRecalcT);
|
||||
}
|
||||
|
||||
void plCoordinateInterface::ITransformChanged(hsBool force, UInt16 reasons, hsBool checkForDelay)
|
||||
{
|
||||
plProfile_IncCount(CITrans, 1);
|
||||
plProfile_BeginTiming(CITransT);
|
||||
|
||||
// inherit reasons for transform change from our parents
|
||||
fReason |= reasons;
|
||||
|
||||
UInt16 propagateReasons = fReason;
|
||||
|
||||
hsBool process = !(checkForDelay && GetProperty(kDelayedTransformEval)) || !fDelayedTransformsEnabled;
|
||||
|
||||
if (process)
|
||||
{
|
||||
if( fState & kTransformDirty )
|
||||
force = true;
|
||||
}
|
||||
|
||||
if( force )
|
||||
{
|
||||
IRecalcTransforms();
|
||||
|
||||
plProfile_IncCount(CISet, 1);
|
||||
plProfile_BeginTiming(CISetT);
|
||||
if( IGetOwner() )
|
||||
{
|
||||
IGetOwner()->ISetTransform(fLocalToWorld, fWorldToLocal);
|
||||
}
|
||||
plProfile_EndTiming(CISetT);
|
||||
fState &= ~kTransformDirty;
|
||||
}
|
||||
|
||||
plProfile_EndTiming(CITransT);
|
||||
if (process)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fChildren.GetCount(); i++ )
|
||||
{
|
||||
if( fChildren[i] && fChildren[i]->GetVolatileCoordinateInterface() )
|
||||
fChildren[i]->GetVolatileCoordinateInterface()->ITransformChanged(force, propagateReasons, checkForDelay);
|
||||
}
|
||||
}
|
||||
else if (force)
|
||||
{
|
||||
plProfile_IncCount(CIDirty, 1);
|
||||
plProfile_BeginTiming(CITransT);
|
||||
// Our parent is dirty and we're bailing out on evaluating right now.
|
||||
// Need to ensure we'll be evaluated in the delay pass
|
||||
plProfile_BeginTiming(CIDirtyT);
|
||||
IDirtyTransform();
|
||||
plProfile_EndTiming(CIDirtyT);
|
||||
plProfile_EndTiming(CITransT);
|
||||
}
|
||||
}
|
||||
|
||||
void plCoordinateInterface::FlushTransform(hsBool fromRoot)
|
||||
{
|
||||
if( fromRoot )
|
||||
IGetRoot()->ITransformChanged(false, 0, false);
|
||||
else
|
||||
ITransformChanged(false, 0, false);
|
||||
}
|
||||
|
||||
void plCoordinateInterface::ISetNetGroupRecur(plNetGroupId netGroup)
|
||||
{
|
||||
if( !IGetOwner() )
|
||||
return;
|
||||
|
||||
if( IGetOwner()->GetSynchFlags() & kHasConstantNetGroup )
|
||||
return;
|
||||
|
||||
IGetOwner()->plSynchedObject::SetNetGroup(netGroup);
|
||||
|
||||
int i;
|
||||
for( i = 0; i < GetNumChildren(); i++ )
|
||||
{
|
||||
if( GetChild(i) )
|
||||
{
|
||||
GetChild(i)->ISetNetGroupRecur(netGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plCoordinateInterface::Read(hsStream* stream, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Read(stream, mgr);
|
||||
|
||||
fLocalToParent.Read(stream);
|
||||
fParentToLocal.Read(stream);
|
||||
|
||||
fLocalToWorld.Read(stream);
|
||||
fWorldToLocal.Read(stream);
|
||||
|
||||
int n = stream->ReadSwap32();
|
||||
int i;
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
plIntRefMsg* refMsg = TRACKED_NEW plIntRefMsg(GetKey(), plRefMsg::kOnCreate, -1, plIntRefMsg::kChildObject);
|
||||
mgr->ReadKeyNotifyMe(stream,refMsg, plRefFlags::kPassiveRef);
|
||||
}
|
||||
}
|
||||
|
||||
void plCoordinateInterface::Write(hsStream* stream, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Write(stream, mgr);
|
||||
|
||||
fLocalToParent.Write(stream);
|
||||
fParentToLocal.Write(stream);
|
||||
|
||||
fLocalToWorld.Write(stream);
|
||||
fWorldToLocal.Write(stream);
|
||||
|
||||
stream->WriteSwap32(fChildren.GetCount());
|
||||
int i;
|
||||
for( i = 0; i < fChildren.GetCount(); i++ )
|
||||
mgr->WriteKey(stream, fChildren[i]);
|
||||
|
||||
}
|
||||
|
||||
hsBool plCoordinateInterface::MsgReceive(plMessage* msg)
|
||||
{
|
||||
hsBool retVal = false;
|
||||
|
||||
plIntRefMsg* intRefMsg;
|
||||
plCorrectionMsg* corrMsg;
|
||||
|
||||
// warp message
|
||||
plWarpMsg* pWarpMsg = plWarpMsg::ConvertNoRef(msg);
|
||||
if (pWarpMsg)
|
||||
{
|
||||
hsMatrix44 l2w = pWarpMsg->GetTransform();
|
||||
hsMatrix44 inv;
|
||||
l2w.GetInverse(&inv);
|
||||
WarpToWorld(l2w,inv);
|
||||
if (pWarpMsg->GetWarpFlags() & plWarpMsg::kFlushTransform)
|
||||
ITransformChanged(false, kReasonUnknown, false);
|
||||
return true;
|
||||
}
|
||||
else if( intRefMsg = plIntRefMsg::ConvertNoRef(msg) )
|
||||
{
|
||||
switch( intRefMsg->fType )
|
||||
{
|
||||
case plIntRefMsg::kChildObject:
|
||||
case plIntRefMsg::kChild:
|
||||
{
|
||||
plSceneObject* co = nil;
|
||||
if( intRefMsg->fType == plIntRefMsg::kChildObject )
|
||||
{
|
||||
co = plSceneObject::ConvertNoRef(intRefMsg->GetRef());
|
||||
}
|
||||
else
|
||||
{
|
||||
plCoordinateInterface* ci = plCoordinateInterface::ConvertNoRef(intRefMsg->GetRef());
|
||||
co = ci ? ci->IGetOwner() : nil;
|
||||
}
|
||||
if( intRefMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnReplace) )
|
||||
{
|
||||
ISetChild(co, intRefMsg->fWhich);
|
||||
}
|
||||
else if( intRefMsg->GetContext() & plRefMsg::kOnDestroy )
|
||||
{
|
||||
IRemoveChild(co);
|
||||
}
|
||||
else if( intRefMsg->GetContext() & plRefMsg::kOnRequest )
|
||||
{
|
||||
IAttachChild(co, kMaintainWorldPosition|kMaintainSceneNode);
|
||||
}
|
||||
else if( intRefMsg->GetContext() & plRefMsg::kOnRemove )
|
||||
{
|
||||
IDetachChild(co, kMaintainWorldPosition|kMaintainSceneNode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( corrMsg = plCorrectionMsg::ConvertNoRef(msg) )
|
||||
{
|
||||
SetTransformPhysical(corrMsg->fLocalToWorld, corrMsg->fWorldToLocal);
|
||||
|
||||
if(corrMsg->fDirtySynch)
|
||||
{
|
||||
if (IGetOwner())
|
||||
IGetOwner()->DirtySynchState(kSDLPhysical, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return plObjInterface::MsgReceive(msg);
|
||||
}
|
||||
|
||||
|
203
Sources/Plasma/NucleusLib/pnSceneObject/plCoordinateInterface.h
Normal file
203
Sources/Plasma/NucleusLib/pnSceneObject/plCoordinateInterface.h
Normal file
@ -0,0 +1,203 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
|
||||
#ifndef plCoordinateInterface_inc
|
||||
#define plCoordinateInterface_inc
|
||||
|
||||
#include "plObjInterface.h"
|
||||
#include "hsTemplates.h"
|
||||
#include "hsMatrix44.h"
|
||||
#include "../pnNetCommon/plSynchedValue.h"
|
||||
|
||||
class hsStream;
|
||||
class hsResMgr;
|
||||
|
||||
|
||||
class plCoordinateInterface : public plObjInterface
|
||||
{
|
||||
public:
|
||||
enum plCoordinateProperties {
|
||||
kDisable = 0, // prop 0 is always disable, declared in plObjInterface
|
||||
kCanEverDelayTransform = 1, // we can sometimes delay our transform eval (i.e. we're on a physics object)
|
||||
kDelayedTransformEval = 2, // we're currently registering for the DelayedTransformMsg (we, and all our
|
||||
// descendants, have the kCanEverDelayTransform prop)
|
||||
|
||||
kNumProps // last in the list
|
||||
};
|
||||
|
||||
enum plCoordinateTransformPhases
|
||||
{
|
||||
kTransformPhaseNormal,
|
||||
kTransformPhaseDelayed,
|
||||
};
|
||||
|
||||
protected:
|
||||
enum {
|
||||
kTransformDirty = 0x1,
|
||||
kWarp = 0x2,
|
||||
|
||||
kMaxState = 0xffff
|
||||
};
|
||||
enum plAttachFlags {
|
||||
kMaintainWorldPosition = 0x1,
|
||||
kMaintainSceneNode = 0x2,
|
||||
kAboutToAttach = 0x4
|
||||
};
|
||||
enum Reason {
|
||||
kReasonUnknown = 0x1, // somebody moved us
|
||||
kReasonPhysics = 0x2, // physics moved us
|
||||
kMaxReasons = 0xffff // sixteen bits
|
||||
};
|
||||
|
||||
// Set by the client in IUpdate(). This tells us where we are in the update loop so that we know
|
||||
// which transform message to register for when our transform is dirtied.
|
||||
static UInt8 fTransformPhase;
|
||||
|
||||
// Temp debugging tool, so we can quickly (dis/en)able delayed transforms at runtime.
|
||||
static hsBool fDelayedTransformsEnabled;
|
||||
|
||||
UInt16 fState;
|
||||
UInt16 fReason; // why we've changed position (if we have)
|
||||
|
||||
hsTArray<plSceneObject*> fChildren;
|
||||
plCoordinateInterface* fParent; // if this changes, marks us as dirty
|
||||
|
||||
hsMatrix44 fLocalToParent;
|
||||
hsMatrix44 fParentToLocal;
|
||||
|
||||
hsMatrix44 fLocalToWorld;
|
||||
hsMatrix44 fWorldToLocal;
|
||||
|
||||
virtual void ISetOwner(plSceneObject* so);
|
||||
|
||||
virtual void ISetParent(plCoordinateInterface* par); // don't use, use AddChild on parent
|
||||
virtual void ISetSceneNode(plKey newNode);
|
||||
// objectToo moves the sceneObject to the new room, else just move the data and remove
|
||||
// the object from whatever room he's in.
|
||||
|
||||
// Network only strange functions. Do not emulate or generalize this functionality.
|
||||
void ISetNetGroupRecur(plNetGroupId netGroup);
|
||||
|
||||
virtual void ISetChild(plSceneObject* child, int which); // sets parent on child
|
||||
virtual void IAddChild(plSceneObject* child); // sets parent on child
|
||||
virtual void IRemoveChild(plSceneObject* child); // removes this as parent of child
|
||||
virtual void IRemoveChild(int i); // removes this as parent of child
|
||||
virtual void IAttachChild(plSceneObject* child, UInt8 flags); // physically attaches child to us
|
||||
virtual void IDetachChild(plSceneObject* child, UInt8 flags); // physically detach this child from us
|
||||
virtual void IUpdateDelayProp(); // Called whenever a child is added/removed
|
||||
|
||||
virtual void IRecalcTransforms(); // Called by ITransformChanged when we need to re-examine our relationship with our parent.
|
||||
virtual void ITransformChanged(hsBool force, UInt16 reasons, hsBool checkForDelay); // called by SceneObject on TransformChanged messsage
|
||||
|
||||
void IDirtyTransform();
|
||||
void IRegisterForTransformMessage(hsBool delayed);
|
||||
void IUnRegisterForTransformMessage();
|
||||
plCoordinateInterface* IGetRoot();
|
||||
|
||||
friend class plSceneObject;
|
||||
|
||||
public:
|
||||
plCoordinateInterface();
|
||||
~plCoordinateInterface();
|
||||
|
||||
CLASSNAME_REGISTER( plCoordinateInterface );
|
||||
GETINTERFACE_ANY( plCoordinateInterface, plObjInterface );
|
||||
|
||||
virtual void Read(hsStream* stream, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* stream, hsResMgr* mgr);
|
||||
|
||||
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
virtual void SetLocalToParent(const hsMatrix44& l2p, const hsMatrix44& p2l);
|
||||
// special version for setting transform from physics.
|
||||
// separate to keep from changing interface to add "reason" parameter
|
||||
virtual void SetTransformPhysical(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
|
||||
virtual void MultTransformLocal(const hsMatrix44& move, const hsMatrix44& invMove);
|
||||
virtual void WarpToWorld(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
virtual void WarpToLocal(const hsMatrix44& l2p, const hsMatrix44& p2l);
|
||||
|
||||
// Force an immediate re-sync of the transforms in the hierarchy this object belongs to,
|
||||
// as opposed to waiting for the plTransformMsg to resync.
|
||||
// There are two uses for this:
|
||||
// a) You need the transforms for this object to be valid NOW, can't wait till after a TransforMsg
|
||||
// In this case, you want to flush from the root, because something higher up the hierarchy
|
||||
// may be dirty, which invalidates this object's transforms
|
||||
// b) You've just dirtied this object's transform, and need it to propagate downward from here NOW
|
||||
// In this case, fromRoot should be false, because you haven't dirtied anything higher up
|
||||
// the hierarchy.
|
||||
// Another way to look at it is, if the transforms for the tree were correct before you messed with
|
||||
// this object, you only need to flush the transforms for this object and its recursive children,
|
||||
// so fromRoot=false.
|
||||
// If the entire tree is potentially dirty and you need to read from it, you want the entire tree
|
||||
// synced up, so fromRoot=true.
|
||||
// fromRoot=true is always safe, just potentially wasteful, so if you don't know, use fromRoot=true or
|
||||
// preferably, don't use this function.
|
||||
void FlushTransform(hsBool fromRoot=true);
|
||||
|
||||
virtual const hsMatrix44& GetLocalToParent() const { return fLocalToParent; }
|
||||
virtual const hsMatrix44& GetParentToLocal() const { return fParentToLocal; }
|
||||
|
||||
virtual const hsMatrix44& GetLocalToWorld() const { return fLocalToWorld; }
|
||||
virtual const hsMatrix44& GetWorldToLocal() const { return fWorldToLocal; }
|
||||
|
||||
virtual const hsPoint3 GetWorldPos() const { return fLocalToWorld.GetTranslate(); }
|
||||
|
||||
virtual int GetNumChildren() const { return fChildren.GetCount(); }
|
||||
virtual plCoordinateInterface* GetChild(int i) const;
|
||||
virtual plCoordinateInterface* GetParent() const { return fParent; }
|
||||
|
||||
virtual hsBool MsgReceive(plMessage* msg);
|
||||
|
||||
UInt16 GetReasons();
|
||||
void ClearReasons();
|
||||
|
||||
Int32 GetNumProperties() const { return kNumProps; }
|
||||
static UInt8 GetTransformPhase() { return fTransformPhase; }
|
||||
static void SetTransformPhase(UInt8 phase) { fTransformPhase = phase; }
|
||||
|
||||
static hsBool GetDelayedTransformsEnabled() { return fDelayedTransformsEnabled; }
|
||||
static void SetDelayedTransformsEnabled(hsBool val) { fDelayedTransformsEnabled = val; }
|
||||
};
|
||||
|
||||
|
||||
#endif // plCoordinateInterface_inc
|
387
Sources/Plasma/NucleusLib/pnSceneObject/plDrawInterface.cpp
Normal file
387
Sources/Plasma/NucleusLib/pnSceneObject/plDrawInterface.cpp
Normal file
@ -0,0 +1,387 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "plDrawInterface.h"
|
||||
#include "plDrawable.h"
|
||||
#include "hsBounds.h"
|
||||
#include "hsStream.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "plSceneObject.h"
|
||||
#include "../pnMessage/plEnableMsg.h"
|
||||
#include "../pnMessage/plIntRefMsg.h"
|
||||
#include "../pnMessage/plDISpansMsg.h"
|
||||
|
||||
plDrawInterface::plDrawInterface()
|
||||
{
|
||||
}
|
||||
|
||||
plDrawInterface::~plDrawInterface()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void plDrawInterface::SetDrawableMeshIndex( UInt8 which, UInt32 index )
|
||||
{
|
||||
ICheckDrawableIndex(which);
|
||||
|
||||
fDrawableIndices[which] = index;
|
||||
}
|
||||
|
||||
void plDrawInterface::SetProperty(int prop, hsBool on)
|
||||
{
|
||||
plObjInterface::SetProperty(prop, on);
|
||||
|
||||
int i;
|
||||
for( i = 0; i < fDrawables.GetCount(); i++ )
|
||||
{
|
||||
if( fDrawables[i] )
|
||||
fDrawables[i]->SetProperty(fDrawableIndices[i], prop, on);
|
||||
}
|
||||
}
|
||||
|
||||
void plDrawInterface::ISetSceneNode(plKey newNode)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fDrawables.GetCount(); i++ )
|
||||
{
|
||||
if( fDrawables[i] )
|
||||
fDrawables[i]->SetSceneNode(newNode);
|
||||
}
|
||||
}
|
||||
|
||||
void plDrawInterface::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
if( !GetProperty(kDisable) )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fDrawables.GetCount(); i++ )
|
||||
{
|
||||
if( fDrawables[i] )
|
||||
fDrawables[i]->SetTransform( fDrawableIndices[i], l2w, w2l );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const hsBounds3Ext plDrawInterface::GetLocalBounds() const
|
||||
{
|
||||
hsBounds3Ext retVal;
|
||||
retVal.MakeEmpty();
|
||||
int i;
|
||||
for( i = 0; i < fDrawables.GetCount(); i++ )
|
||||
{
|
||||
if( fDrawables[i] )
|
||||
retVal.Union(&fDrawables[i]->GetLocalBounds(fDrawableIndices[i]));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
const hsBounds3Ext plDrawInterface::GetWorldBounds() const
|
||||
{
|
||||
hsBounds3Ext retVal;
|
||||
retVal.MakeEmpty();
|
||||
int i;
|
||||
for( i = 0; i < fDrawables.GetCount(); i++ )
|
||||
{
|
||||
if( fDrawables[i] )
|
||||
retVal.Union(&fDrawables[i]->GetWorldBounds(fDrawableIndices[i]));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
const hsBounds3Ext plDrawInterface::GetMaxWorldBounds() const
|
||||
{
|
||||
hsBounds3Ext retVal;
|
||||
retVal.MakeEmpty();
|
||||
int i;
|
||||
for( i = 0; i < fDrawables.GetCount(); i++ )
|
||||
{
|
||||
if( fDrawables[i] )
|
||||
retVal.Union(&fDrawables[i]->GetMaxWorldBounds(fDrawableIndices[i]));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void plDrawInterface::Read(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Read(s, mgr);
|
||||
|
||||
int nDrawables = s->ReadSwap32();
|
||||
if (nDrawables > 0)
|
||||
ICheckDrawableIndex(nDrawables-1);
|
||||
int i;
|
||||
for( i = 0; i < fDrawables.GetCount(); i++ )
|
||||
{
|
||||
fDrawableIndices[i] = s->ReadSwap32();
|
||||
|
||||
plIntRefMsg* refMsg = TRACKED_NEW plIntRefMsg(GetKey(), plRefMsg::kOnCreate, i, plIntRefMsg::kDrawable);
|
||||
mgr->ReadKeyNotifyMe(s,refMsg, plRefFlags::kActiveRef);
|
||||
}
|
||||
|
||||
int nReg = s->ReadSwap32();
|
||||
fRegions.SetCountAndZero(nReg);
|
||||
for( i = 0; i < nReg; i++ )
|
||||
{
|
||||
plGenRefMsg* refMsg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefVisRegion);
|
||||
mgr->ReadKeyNotifyMe(s, refMsg, plRefFlags::kActiveRef);
|
||||
}
|
||||
}
|
||||
|
||||
void plDrawInterface::Write(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Write(s, mgr);
|
||||
|
||||
s->WriteSwap32(fDrawables.GetCount());
|
||||
int i;
|
||||
for( i = 0; i < fDrawables.GetCount(); i++ )
|
||||
{
|
||||
s->WriteSwap32(fDrawableIndices[i]);
|
||||
|
||||
mgr->WriteKey(s, fDrawables[i]);
|
||||
}
|
||||
|
||||
s->WriteSwap32(fRegions.GetCount());
|
||||
for( i = 0; i < fRegions.GetCount(); i++ )
|
||||
{
|
||||
mgr->WriteKey(s, fRegions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//// ReleaseData //////////////////////////////////////////////////////////////
|
||||
// Called by SceneViewer to release the data for this given object (when
|
||||
// its parent sceneObject is deleted).
|
||||
|
||||
void plDrawInterface::ReleaseData( void )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fDrawables.GetCount(); i++ )
|
||||
{
|
||||
if( fDrawables[i] && (fDrawableIndices[i] != UInt32(-1)) )
|
||||
{
|
||||
plDISpansMsg* diMsg = TRACKED_NEW plDISpansMsg(fDrawables[i]->GetKey(), plDISpansMsg::kRemovingSpan, fDrawableIndices[i], 0);
|
||||
diMsg->SetSender(GetKey());
|
||||
diMsg->Send();
|
||||
}
|
||||
//fDrawableIndices[i] = UInt32(-1);
|
||||
fDrawables.Reset();
|
||||
fDrawableIndices.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void plDrawInterface::ICheckDrawableIndex(UInt8 which)
|
||||
{
|
||||
if( which >= fDrawableIndices.GetCount() )
|
||||
{
|
||||
fDrawables.ExpandAndZero(which+1);
|
||||
|
||||
int n = fDrawableIndices.GetCount();
|
||||
fDrawableIndices.ExpandAndZero(which+1);
|
||||
int i;
|
||||
for( i = n; i <= which; i++ )
|
||||
fDrawableIndices[i] = UInt32(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void plDrawInterface::ISetDrawable(UInt8 which, plDrawable* dr)
|
||||
{
|
||||
ICheckDrawableIndex(which);
|
||||
fDrawables[which] = dr;
|
||||
|
||||
if( dr )
|
||||
dr->SetSceneNode(GetSceneNode());
|
||||
|
||||
// We might read the vis regions before the drawables, so
|
||||
// we have to check for any already loaded.
|
||||
ISetVisRegions(which);
|
||||
|
||||
#ifdef HS_DEBUGGING
|
||||
if( fDrawableIndices[which] != (UInt32)-1 )
|
||||
{
|
||||
plDISpansMsg* diMsg = TRACKED_NEW plDISpansMsg(dr->GetKey(), plDISpansMsg::kAddingSpan, fDrawableIndices[which], 0);
|
||||
diMsg->SetSender(GetKey());
|
||||
diMsg->Send();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void plDrawInterface::IRemoveDrawable(plDrawable *dr)
|
||||
{
|
||||
int idx = fDrawables.Find(dr);
|
||||
if( fDrawables.kMissingIndex != idx )
|
||||
{
|
||||
fDrawables[idx] = nil;
|
||||
fDrawableIndices[idx] = UInt32(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsAssert(false, "Trying to remove a drawable that doesn't belong to us");
|
||||
}
|
||||
}
|
||||
|
||||
void plDrawInterface::ISetVisRegion(hsKeyedObject* reg, hsBool on)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fDrawables.GetCount(); i++ )
|
||||
{
|
||||
if( fDrawables[i] && (fDrawableIndices[i] != UInt32(-1)) )
|
||||
{
|
||||
fDrawables[i]->SetDISpanVisSet(fDrawableIndices[i], reg, on);
|
||||
}
|
||||
}
|
||||
int idx = fRegions.Find(reg);
|
||||
if( on )
|
||||
{
|
||||
if( idx == fRegions.kMissingIndex )
|
||||
fRegions.Append(reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( idx != fRegions.kMissingIndex )
|
||||
fRegions.Remove(idx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void plDrawInterface::ISetVisRegions(int iDraw)
|
||||
{
|
||||
if( fDrawables[iDraw] && (fDrawableIndices[iDraw] != UInt32(-1)) )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fRegions.GetCount(); i++ )
|
||||
{
|
||||
fDrawables[iDraw]->SetDISpanVisSet(fDrawableIndices[iDraw], fRegions[i], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export only. Use messages for runtime
|
||||
void plDrawInterface::SetDrawable(UInt8 which, plDrawable *dr)
|
||||
{
|
||||
if( dr )
|
||||
{
|
||||
// This is a little convoluted, but it makes GCC happy and doesn't hurt anybody.
|
||||
plIntRefMsg* intRefMsg = TRACKED_NEW plIntRefMsg(GetKey(), plRefMsg::kOnCreate, which, plIntRefMsg::kDrawable);
|
||||
plRefMsg* refMsg = intRefMsg;
|
||||
// hsgResMgr::ResMgr()->SendRef(dr->GetKey(), intRefMsg, plRefFlags::kActiveRef); // THIS WON'T COMPILE UNDER GCC
|
||||
hsgResMgr::ResMgr()->SendRef(dr, refMsg, plRefFlags::kActiveRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
ISetDrawable(which, nil);
|
||||
}
|
||||
}
|
||||
|
||||
hsBool plDrawInterface::MsgReceive(plMessage* msg)
|
||||
{
|
||||
plIntRefMsg* intRefMsg = plIntRefMsg::ConvertNoRef(msg);
|
||||
if( intRefMsg )
|
||||
{
|
||||
switch( intRefMsg->fType )
|
||||
{
|
||||
case plIntRefMsg::kDrawable:
|
||||
if( intRefMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
|
||||
{
|
||||
IRemoveDrawable(plDrawable::ConvertNoRef(intRefMsg->GetRef()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ISetDrawable((UInt8)intRefMsg->fWhich, plDrawable::ConvertNoRef(intRefMsg->GetRef()));
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
plGenRefMsg* genRefMsg = plGenRefMsg::ConvertNoRef(msg);
|
||||
if( genRefMsg )
|
||||
{
|
||||
switch( genRefMsg->fType )
|
||||
{
|
||||
case kRefVisRegion:
|
||||
if( genRefMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
|
||||
ISetVisRegion(genRefMsg->GetRef(), true);
|
||||
else
|
||||
ISetVisRegion(genRefMsg->GetRef(), false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
plEnableMsg* pEnableMsg = plEnableMsg::ConvertNoRef( msg );
|
||||
if (pEnableMsg)
|
||||
{
|
||||
SetProperty(kDisable, pEnableMsg->Cmd(plEnableMsg::kDisable));
|
||||
if( GetOwner() )
|
||||
SetTransform(GetOwner()->GetLocalToWorld(), GetOwner()->GetWorldToLocal());
|
||||
return true;
|
||||
}
|
||||
return plObjInterface::MsgReceive(msg);
|
||||
}
|
||||
|
||||
void plDrawInterface::SetUpForParticleSystem( UInt32 maxNumEmitters, UInt32 maxNumParticles, hsGMaterial *material, hsTArray<plKey>& lights )
|
||||
{
|
||||
hsAssert( fDrawables[0] != nil, "No drawable to use for particle system!" );
|
||||
SetDrawableMeshIndex( 0, fDrawables[0]->CreateParticleSystem( maxNumEmitters, maxNumParticles, material ) );
|
||||
int i;
|
||||
for( i = 0; i < lights.GetCount(); i++ )
|
||||
{
|
||||
hsgResMgr::ResMgr()->AddViaNotify(lights[i], TRACKED_NEW plGenRefMsg(fDrawables[0]->GetKey(), plRefMsg::kOnCreate, fDrawableIndices[0], plDrawable::kMsgPermaLightDI), plRefFlags::kPassiveRef);
|
||||
}
|
||||
|
||||
ISetVisRegions(0);
|
||||
}
|
||||
|
||||
void plDrawInterface::ResetParticleSystem( void )
|
||||
{
|
||||
hsAssert( fDrawables[0] != nil, "No drawable to use for particle system!" );
|
||||
fDrawables[0]->ResetParticleSystem( fDrawableIndices[0] );
|
||||
}
|
||||
|
||||
void plDrawInterface::AssignEmitterToParticleSystem( plParticleEmitter *emitter )
|
||||
{
|
||||
hsAssert( fDrawables[0] != nil, "No drawable to use for particle system!" );
|
||||
fDrawables[0]->AssignEmitterToParticleSystem( fDrawableIndices[0], emitter );
|
||||
}
|
||||
|
||||
|
124
Sources/Plasma/NucleusLib/pnSceneObject/plDrawInterface.h
Normal file
124
Sources/Plasma/NucleusLib/pnSceneObject/plDrawInterface.h
Normal file
@ -0,0 +1,124 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#ifndef plDrawInterface_inc
|
||||
#define plDrawInterface_inc
|
||||
|
||||
#include "plObjInterface.h"
|
||||
|
||||
class plDrawable;
|
||||
class hsStream;
|
||||
class hsResMgr;
|
||||
struct hsMatrix44;
|
||||
class hsBounds3Ext;
|
||||
class hsGMaterial;
|
||||
class plParticleEmitter;
|
||||
|
||||
class plDrawInterface : public plObjInterface
|
||||
{
|
||||
public:
|
||||
// Props inc by 1 (bit shift in bitvector).
|
||||
enum plDrawProperties {
|
||||
kDisable = 0,
|
||||
|
||||
kNumProps // last in the list
|
||||
};
|
||||
enum {
|
||||
kRefVisRegion
|
||||
};
|
||||
|
||||
protected:
|
||||
hsTArray<plDrawable*> fDrawables;
|
||||
hsTArray<UInt32> fDrawableIndices;
|
||||
|
||||
hsTArray<hsKeyedObject*> fRegions;
|
||||
|
||||
void ISetVisRegions(int iDraw);
|
||||
void ISetVisRegion(hsKeyedObject* ref, hsBool on);
|
||||
void ISetDrawable(UInt8 which, plDrawable* dr);
|
||||
void IRemoveDrawable(plDrawable* dr);
|
||||
void ISetSceneNode(plKey newNode);
|
||||
virtual void ICheckDrawableIndex(UInt8 which);
|
||||
|
||||
friend class plSceneObject;
|
||||
|
||||
public:
|
||||
plDrawInterface();
|
||||
virtual ~plDrawInterface();
|
||||
|
||||
CLASSNAME_REGISTER( plDrawInterface );
|
||||
GETINTERFACE_ANY( plDrawInterface, plObjInterface );
|
||||
|
||||
virtual void Read(hsStream* stream, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* stream, hsResMgr* mgr);
|
||||
|
||||
void SetProperty(int prop, hsBool on);
|
||||
Int32 GetNumProperties() const { return kNumProps; }
|
||||
|
||||
// Transform settable only, if you want it get it from the coordinate interface.
|
||||
void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
|
||||
// Bounds are gettable only, they are computed on the drawable.
|
||||
const hsBounds3Ext GetLocalBounds() const;
|
||||
const hsBounds3Ext GetWorldBounds() const;
|
||||
const hsBounds3Ext GetMaxWorldBounds() const;
|
||||
|
||||
virtual hsBool MsgReceive(plMessage* msg);
|
||||
|
||||
virtual void ReleaseData( void );
|
||||
|
||||
/// Funky particle system functions
|
||||
void SetUpForParticleSystem( UInt32 maxNumEmitters, UInt32 maxNumParticles, hsGMaterial *material, hsTArray<plKey>& lights );
|
||||
void ResetParticleSystem( void );
|
||||
void AssignEmitterToParticleSystem( plParticleEmitter *emitter );
|
||||
|
||||
/// EXPORT-ONLY
|
||||
void SetDrawable(UInt8 which, plDrawable* dr);
|
||||
plDrawable* GetDrawable( UInt8 which ) const { return which < fDrawables.GetCount() ? fDrawables[which] : nil; }
|
||||
UInt32 GetNumDrawables() const { return fDrawables.GetCount(); }
|
||||
// Sets the triMesh index to be used when referring to our spans in the drawable
|
||||
void SetDrawableMeshIndex( UInt8 which, UInt32 index );
|
||||
UInt32 GetDrawableMeshIndex( UInt8 which ) const { return which < fDrawableIndices.GetCount() ? fDrawableIndices[which] : UInt32(-1); }
|
||||
};
|
||||
|
||||
|
||||
#endif // plDrawInterface_inc
|
132
Sources/Plasma/NucleusLib/pnSceneObject/plObjInterface.cpp
Normal file
132
Sources/Plasma/NucleusLib/pnSceneObject/plObjInterface.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "plObjInterface.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "plSceneObject.h"
|
||||
#include "../pnMessage/plIntRefMsg.h"
|
||||
#include "../pnMessage/plEnableMsg.h"
|
||||
|
||||
|
||||
plObjInterface::plObjInterface()
|
||||
: fOwner(nil)
|
||||
{
|
||||
}
|
||||
|
||||
plObjInterface::~plObjInterface()
|
||||
{
|
||||
}
|
||||
|
||||
void plObjInterface::ISetOwner(plSceneObject* owner)
|
||||
{
|
||||
if( fOwner != owner )
|
||||
{
|
||||
fOwner = owner;
|
||||
if( fOwner )
|
||||
fOwner->ISetInterface(this);
|
||||
}
|
||||
}
|
||||
|
||||
void plObjInterface::Read(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plSynchedObject::Read(s, mgr);
|
||||
|
||||
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plIntRefMsg(GetKey(), plRefMsg::kOnCreate, 0, plIntRefMsg::kOwner), plRefFlags::kPassiveRef);
|
||||
|
||||
fProps.Read(s);
|
||||
}
|
||||
|
||||
void plObjInterface::Write(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plSynchedObject::Write(s, mgr);
|
||||
|
||||
mgr->WriteKey(s, fOwner);
|
||||
fProps.Write(s);
|
||||
}
|
||||
|
||||
hsBool plObjInterface::MsgReceive(plMessage* msg)
|
||||
{
|
||||
hsBool retVal = false;
|
||||
|
||||
plEnableMsg* enaMsg = plEnableMsg::ConvertNoRef(msg);
|
||||
if( enaMsg )
|
||||
{
|
||||
SetProperty(kDisable, enaMsg->Cmd(plEnableMsg::kDisable));
|
||||
return true;
|
||||
}
|
||||
plIntRefMsg* intRefMsg = plIntRefMsg::ConvertNoRef(msg);
|
||||
if( intRefMsg )
|
||||
{
|
||||
switch( intRefMsg->fType )
|
||||
{
|
||||
case plIntRefMsg::kOwner:
|
||||
if( intRefMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
|
||||
{
|
||||
plSceneObject* owner = plSceneObject::ConvertNoRef(intRefMsg->GetRef());
|
||||
ISetOwner(owner);
|
||||
}
|
||||
else if( intRefMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
|
||||
{
|
||||
ISetOwner(nil);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return plSynchedObject::MsgReceive(msg);
|
||||
}
|
||||
|
||||
//
|
||||
// assign and update my properties from the bitVector passed in
|
||||
//
|
||||
void plObjInterface::ISetAllProperties(const hsBitVector& b)
|
||||
{
|
||||
// if (&b != &fProps) // don't copy if they are the same variable
|
||||
|
||||
fProps = b;
|
||||
|
||||
int i;
|
||||
for(i=0;i<GetNumProperties(); i++)
|
||||
SetProperty(i, GetProperty(i));
|
||||
}
|
||||
|
119
Sources/Plasma/NucleusLib/pnSceneObject/plObjInterface.h
Normal file
119
Sources/Plasma/NucleusLib/pnSceneObject/plObjInterface.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#ifndef plInterface_inc
|
||||
#define plInterface_inc
|
||||
|
||||
#include "../pnKeyedObject/hsKeyedObject.h"
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "plSceneObject.h"
|
||||
#include "hsStream.h"
|
||||
#include "../pnNetCommon/plSynchedObject.h"
|
||||
#include "../pnNetCommon/plSynchedValue.h"
|
||||
#include "hsBitVector.h"
|
||||
|
||||
class hsResMgr;
|
||||
class plDrawInterface;
|
||||
class plSimulationInterface;
|
||||
class plCoordinateInterface;
|
||||
class plAudioInterface;
|
||||
|
||||
//
|
||||
// Since interfaces are keyed objects with valid uoids and
|
||||
// may have dynamic data (coordinate interface), they are
|
||||
// synched (saved) objects
|
||||
//
|
||||
class plObjInterface : public plSynchedObject
|
||||
{
|
||||
protected:
|
||||
enum {
|
||||
kDisable = 0x0 // Derived interfaces duplicate this, so if you add more here, they need to know.
|
||||
};
|
||||
friend class plSynchedValueBase;
|
||||
friend class plSceneObject;
|
||||
protected:
|
||||
plSceneObject* fOwner;
|
||||
hsBitVector fProps;
|
||||
|
||||
// SetSceneNode just called by owner. If we're an interface to external data,
|
||||
// we need to pass the change on. Otherwise, do nothing.
|
||||
virtual void ISetSceneNode(plKey node) {}
|
||||
plSceneObject* IGetOwner() const { return fOwner; }
|
||||
virtual void ISetOwner(plSceneObject* owner);
|
||||
void ISetAllProperties(const hsBitVector& b);
|
||||
|
||||
plDrawInterface* IGetOwnerDrawInterface() { return fOwner ? fOwner->GetVolatileDrawInterface() : nil; }
|
||||
plSimulationInterface* IGetOwnerSimulationInterface() { return fOwner ? fOwner->GetVolatileSimulationInterface() : nil; }
|
||||
plCoordinateInterface* IGetOwnerCoordinateInterface() { return fOwner ? fOwner->GetVolatileCoordinateInterface() : nil; }
|
||||
plAudioInterface* IGetOwnerAudioInterface() { return fOwner ? fOwner->GetVolatileAudioInterface() : nil; }
|
||||
public:
|
||||
|
||||
plObjInterface();
|
||||
~plObjInterface();
|
||||
|
||||
CLASSNAME_REGISTER( plObjInterface );
|
||||
GETINTERFACE_ANY( plObjInterface, plSynchedObject );
|
||||
|
||||
virtual hsBool MsgReceive(plMessage* msg);
|
||||
|
||||
const plSceneObject* GetOwner() const { return IGetOwner(); }
|
||||
plKey GetOwnerKey() const { return IGetOwner() ? IGetOwner()->GetKey() : nil; }
|
||||
|
||||
virtual plKey GetSceneNode() const { return IGetOwner() ? IGetOwner()->GetSceneNode() : nil; }
|
||||
|
||||
// override SetProperty to pass the prop down to the pool objects
|
||||
virtual void SetProperty(int prop, hsBool on) { fProps.SetBit(prop, on); }
|
||||
|
||||
// shouldn't need to override GetProperty()
|
||||
hsBool GetProperty(int prop) const { return fProps.IsBitSet(prop); }
|
||||
virtual Int32 GetNumProperties() const = 0;
|
||||
|
||||
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l) = 0;
|
||||
|
||||
virtual void Read(hsStream* stream, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* stream, hsResMgr* mgr);
|
||||
|
||||
virtual void ReleaseData( void ) { }
|
||||
};
|
||||
|
||||
|
||||
#endif // plInterface_inc
|
886
Sources/Plasma/NucleusLib/pnSceneObject/plSceneObject.cpp
Normal file
886
Sources/Plasma/NucleusLib/pnSceneObject/plSceneObject.cpp
Normal file
@ -0,0 +1,886 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "plSceneObject.h"
|
||||
#include "plDrawInterface.h"
|
||||
#include "plSimulationInterface.h"
|
||||
#include "plCoordinateInterface.h"
|
||||
#include "plAudioInterface.h"
|
||||
#include "../pnDispatch/plDispatch.h"
|
||||
#include "../pnModifier/plModifier.h"
|
||||
#include "../pnMessage/plMessage.h"
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "plDrawable.h"
|
||||
#include "plPhysical.h"
|
||||
#include "plAudible.h"
|
||||
#include "../pnMessage/plTimeMsg.h"
|
||||
#include "../pnMessage/plCorrectionMsg.h"
|
||||
#include "../pnMessage/plWarpMsg.h"
|
||||
#include "../pnMessage/plSoundMsg.h"
|
||||
#include "../pnMessage/plEnableMsg.h"
|
||||
#include "../pnMessage/plAttachMsg.h"
|
||||
#include "../pnMessage/plObjRefMsg.h"
|
||||
#include "../pnMessage/plNodeRefMsg.h"
|
||||
#include "../pnMessage/plIntRefMsg.h"
|
||||
#include "../pnMessage/plSimulationSynchMsg.h"
|
||||
#include "../pnMessage/plSimulationMsg.h"
|
||||
#include "../pnMessage/plNodeChangeMsg.h"
|
||||
#include "../pnMessage/plSelfDestructMsg.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
|
||||
#include "hsStream.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "plCreatableIndex.h" // For plLightInfo::Index(), so we don't have to include plLightInfo.h
|
||||
|
||||
|
||||
|
||||
int dbgCurrentTest = 0;
|
||||
|
||||
plSceneObject::plSceneObject()
|
||||
: fDrawInterface(nil),
|
||||
fSimulationInterface(nil),
|
||||
fCoordinateInterface(nil),
|
||||
fAudioInterface(nil),
|
||||
fSceneNode(nil)
|
||||
{
|
||||
}
|
||||
|
||||
plSceneObject::~plSceneObject()
|
||||
{
|
||||
SetDrawInterface(nil);
|
||||
SetSimulationInterface(nil);
|
||||
SetCoordinateInterface(nil);
|
||||
SetAudioInterface(nil);
|
||||
|
||||
IRemoveAllGenerics();
|
||||
|
||||
int i;
|
||||
int knt;
|
||||
|
||||
knt = fModifiers.GetCount();
|
||||
for( i = 0; i < knt; i++ )
|
||||
{
|
||||
if( fModifiers[i] )
|
||||
fModifiers[i]->RemoveTarget(this);
|
||||
}
|
||||
}
|
||||
|
||||
void plSceneObject::Read(hsStream* stream, hsResMgr* mgr)
|
||||
{
|
||||
plSynchedObject::Read(stream, mgr);
|
||||
|
||||
// Interfaces will attach themselves to us on read.
|
||||
// DI
|
||||
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plObjRefMsg(GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface), plRefFlags::kActiveRef);
|
||||
|
||||
// SI
|
||||
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plObjRefMsg(GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface), plRefFlags::kActiveRef);
|
||||
|
||||
// CI
|
||||
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plObjRefMsg(GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface), plRefFlags::kActiveRef);
|
||||
|
||||
// AI
|
||||
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plObjRefMsg(GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface), plRefFlags::kActiveRef);
|
||||
|
||||
int i;
|
||||
|
||||
int nGen = stream->ReadSwap32();
|
||||
fGenerics.SetCount(0);
|
||||
for( i = 0; i < nGen; i++ )
|
||||
{
|
||||
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plObjRefMsg(GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface), plRefFlags::kActiveRef);
|
||||
}
|
||||
|
||||
plObjRefMsg* refMsg;
|
||||
|
||||
int nOldMods=fModifiers.GetCount(); // existng modifiers created during interface loading
|
||||
int nNewMods = stream->ReadSwap32();
|
||||
fModifiers.ExpandAndZero(nOldMods+nNewMods); // reserve space for new modifiers+existing modifiers
|
||||
for( i = nOldMods; i < nOldMods+nNewMods; i++ )
|
||||
{
|
||||
refMsg = TRACKED_NEW plObjRefMsg(GetKey(), plRefMsg::kOnCreate, i, plObjRefMsg::kModifier);
|
||||
mgr->ReadKeyNotifyMe(stream,refMsg, plRefFlags::kActiveRef);
|
||||
}
|
||||
|
||||
plKey nodeKey = mgr->ReadKey(stream);
|
||||
// SetSceneNode(nodeKey);
|
||||
fSceneNode = nodeKey;
|
||||
|
||||
}
|
||||
|
||||
void plSceneObject::Write(hsStream* stream, hsResMgr* mgr)
|
||||
{
|
||||
plSynchedObject::Write(stream, mgr);
|
||||
|
||||
mgr->WriteKey(stream, fDrawInterface);
|
||||
mgr->WriteKey(stream, fSimulationInterface);
|
||||
mgr->WriteKey(stream, fCoordinateInterface);
|
||||
mgr->WriteKey(stream, fAudioInterface);
|
||||
|
||||
int i;
|
||||
|
||||
stream->WriteSwap32(fGenerics.GetCount());
|
||||
for( i = 0; i < fGenerics.GetCount(); i++ )
|
||||
mgr->WriteKey(stream, fGenerics[i]);
|
||||
|
||||
for( i = fModifiers.GetCount() - 1; i >= 0; i--)
|
||||
if (fModifiers[i]->GetKey() == nil)
|
||||
RemoveModifier(fModifiers[i]);
|
||||
|
||||
stream->WriteSwap32(fModifiers.GetCount());
|
||||
for( i = 0; i < fModifiers.GetCount(); i++ )
|
||||
mgr->WriteKey(stream,fModifiers[i]);
|
||||
|
||||
mgr->WriteKey(stream, fSceneNode);
|
||||
}
|
||||
|
||||
//// ReleaseData //////////////////////////////////////////////////////////////
|
||||
// Called by SceneViewer to release the data for this sceneObject (really
|
||||
// just a switchboard).
|
||||
|
||||
void plSceneObject::ReleaseData( void )
|
||||
{
|
||||
if( fDrawInterface )
|
||||
fDrawInterface->ReleaseData();
|
||||
if( fSimulationInterface )
|
||||
fSimulationInterface->ReleaseData();
|
||||
if( fCoordinateInterface )
|
||||
fCoordinateInterface->ReleaseData();
|
||||
if( fAudioInterface )
|
||||
fAudioInterface->ReleaseData();
|
||||
|
||||
int i;
|
||||
for( i = 0; i < fGenerics.GetCount(); i++ )
|
||||
{
|
||||
if( fGenerics[i] )
|
||||
fGenerics[i]->ReleaseData();
|
||||
}
|
||||
}
|
||||
|
||||
void plSceneObject::FlushTransform()
|
||||
{
|
||||
if( fCoordinateInterface )
|
||||
fCoordinateInterface->FlushTransform();
|
||||
}
|
||||
|
||||
#include "plProfile.h"
|
||||
|
||||
plProfile_CreateTimer("SOTrans", "Object", SOTrans);
|
||||
plProfile_CreateTimer(" SODITrans", "Object", SODITrans);
|
||||
plProfile_CreateTimer(" SOSITrans", "Object", SOSITrans);
|
||||
plProfile_CreateTimer(" SOAITrans", "Object", SOAITrans);
|
||||
plProfile_CreateTimer(" SOGITrans", "Object", SOGITrans);
|
||||
plProfile_CreateTimer(" SOMOTrans", "Object", SOMOTrans);
|
||||
|
||||
|
||||
void plSceneObject::ISetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
plProfile_BeginTiming(SOTrans);
|
||||
plProfile_BeginTiming(SODITrans);
|
||||
if( fDrawInterface )
|
||||
fDrawInterface->SetTransform(l2w, w2l);
|
||||
plProfile_EndTiming(SODITrans);
|
||||
|
||||
plProfile_BeginTiming(SOSITrans);
|
||||
if( fSimulationInterface )
|
||||
{
|
||||
if(fCoordinateInterface)
|
||||
{
|
||||
UInt16 whyTransformed = fCoordinateInterface->GetReasons();
|
||||
if(whyTransformed != plCoordinateInterface::kReasonPhysics)
|
||||
{
|
||||
// if we were transformed by anything but physics, let physics know
|
||||
// otherwise we're not even going to tell physics
|
||||
fSimulationInterface->SetTransform(l2w, w2l);
|
||||
} else {
|
||||
int moreSunshine = 10;
|
||||
}
|
||||
fCoordinateInterface->ClearReasons();
|
||||
} else {
|
||||
int somethingToBreakOn = 10;
|
||||
// if there's not coordinate interface, there's no reason to move the simulation interface
|
||||
}
|
||||
}
|
||||
plProfile_EndTiming(SOSITrans);
|
||||
|
||||
plProfile_BeginTiming(SOAITrans);
|
||||
if( fAudioInterface )
|
||||
fAudioInterface->SetTransform(l2w, w2l);
|
||||
plProfile_EndTiming(SOAITrans);
|
||||
|
||||
plProfile_BeginTiming(SOGITrans);
|
||||
int i;
|
||||
for( i = 0; i < fGenerics.GetCount(); i++ )
|
||||
{
|
||||
if( fGenerics[i] )
|
||||
fGenerics[i]->SetTransform(l2w, w2l);
|
||||
}
|
||||
plProfile_EndTiming(SOGITrans);
|
||||
|
||||
|
||||
plProfile_BeginTiming(SOMOTrans);
|
||||
for( i = 0; i < fModifiers.GetCount(); i++ )
|
||||
{
|
||||
if( fModifiers[i] )
|
||||
fModifiers[i]->SetTransform(l2w, w2l);
|
||||
}
|
||||
plProfile_EndTiming(SOMOTrans);
|
||||
plProfile_EndTiming(SOTrans);
|
||||
}
|
||||
|
||||
void plSceneObject::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
if( fCoordinateInterface )
|
||||
fCoordinateInterface->SetTransform(l2w, w2l);
|
||||
}
|
||||
|
||||
hsMatrix44 plSceneObject::GetLocalToWorld() const
|
||||
{
|
||||
hsMatrix44 l2w;
|
||||
if( fCoordinateInterface )
|
||||
l2w = fCoordinateInterface->GetLocalToWorld();
|
||||
else
|
||||
l2w.Reset();
|
||||
return l2w;
|
||||
}
|
||||
|
||||
hsMatrix44 plSceneObject::GetWorldToLocal() const
|
||||
{
|
||||
hsMatrix44 w2l;
|
||||
if( fCoordinateInterface )
|
||||
w2l = fCoordinateInterface->GetWorldToLocal();
|
||||
else
|
||||
w2l.Reset();
|
||||
return w2l;
|
||||
}
|
||||
|
||||
hsMatrix44 plSceneObject::GetLocalToParent() const
|
||||
{
|
||||
hsMatrix44 l2p;
|
||||
if( fCoordinateInterface )
|
||||
l2p = fCoordinateInterface->GetLocalToParent();
|
||||
else
|
||||
l2p.Reset();
|
||||
return l2p;
|
||||
}
|
||||
|
||||
hsMatrix44 plSceneObject::GetParentToLocal() const
|
||||
{
|
||||
hsMatrix44 p2l;
|
||||
if( fCoordinateInterface )
|
||||
p2l = fCoordinateInterface->GetParentToLocal();
|
||||
else
|
||||
p2l.Reset();
|
||||
return p2l;
|
||||
}
|
||||
|
||||
void plSceneObject::IAddModifier(plModifier* mo, int i)
|
||||
{
|
||||
if( !mo )
|
||||
return;
|
||||
|
||||
if( i < 0 )
|
||||
i = fModifiers.GetCount();
|
||||
fModifiers.ExpandAndZero(i+1);
|
||||
fModifiers.Set(i, mo);
|
||||
mo->AddTarget(this);
|
||||
}
|
||||
|
||||
void plSceneObject::IRemoveModifier(plModifier* mo)
|
||||
{
|
||||
if( !mo )
|
||||
return;
|
||||
|
||||
int idx = fModifiers.Find(mo);
|
||||
if( idx != fModifiers.kMissingIndex )
|
||||
{
|
||||
mo->RemoveTarget(this);
|
||||
fModifiers.Remove(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void plSceneObject::ISetInterface(plObjInterface* iface)
|
||||
{
|
||||
hsAssert(iface, "Setting nil interface");
|
||||
if( plDrawInterface::ConvertNoRef(iface) )
|
||||
ISetDrawInterface(plDrawInterface::ConvertNoRef(iface));
|
||||
else if( plSimulationInterface::ConvertNoRef(iface) )
|
||||
ISetSimulationInterface(plSimulationInterface::ConvertNoRef(iface));
|
||||
else if( plCoordinateInterface::ConvertNoRef(iface) )
|
||||
ISetCoordinateInterface(plCoordinateInterface::ConvertNoRef(iface));
|
||||
else if( plAudioInterface::ConvertNoRef(iface) )
|
||||
ISetAudioInterface(plAudioInterface::ConvertNoRef(iface));
|
||||
else
|
||||
IAddGeneric(iface);
|
||||
|
||||
if( iface )
|
||||
iface->ISetSceneNode(GetSceneNode());
|
||||
}
|
||||
|
||||
void plSceneObject::IRemoveInterface(Int16 idx, plObjInterface* who)
|
||||
{
|
||||
if( plFactory::DerivesFrom(plDrawInterface::Index(), idx) )
|
||||
ISetDrawInterface(nil);
|
||||
else if( plFactory::DerivesFrom(plSimulationInterface::Index(), idx) )
|
||||
ISetSimulationInterface(nil);
|
||||
else if( plFactory::DerivesFrom(plCoordinateInterface::Index(), idx) )
|
||||
ISetCoordinateInterface(nil);
|
||||
else if( plFactory::DerivesFrom(plAudioInterface::Index(), idx) )
|
||||
ISetAudioInterface(nil);
|
||||
else
|
||||
IRemoveGeneric(who);
|
||||
}
|
||||
|
||||
hsBool plSceneObject::IPropagateToModifiers(plMessage* msg)
|
||||
{
|
||||
hsBool retVal = false;
|
||||
int i;
|
||||
int nMods = fModifiers.GetCount();
|
||||
|
||||
for( i = 0; i < nMods; i++ )
|
||||
{
|
||||
if( fModifiers[i] )
|
||||
{
|
||||
plModifier *mod = fModifiers[i];
|
||||
hsBool modRet = mod->MsgReceive(msg);
|
||||
retVal |= modRet;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
hsBool plSceneObject::Eval(double secs, hsScalar delSecs)
|
||||
{
|
||||
UInt32 dirty = ~0L;
|
||||
hsBool retVal = false;
|
||||
int i;
|
||||
for( i = 0; i < fModifiers.GetCount(); i++ )
|
||||
{
|
||||
if( fModifiers[i] )
|
||||
retVal |= fModifiers[i]->IEval(secs, delSecs, dirty);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void plSceneObject::SetSceneNode(plKey newNode)
|
||||
{
|
||||
plKey curNode=GetSceneNode();
|
||||
if( curNode == newNode )
|
||||
return;
|
||||
if( fDrawInterface )
|
||||
fDrawInterface->ISetSceneNode(newNode);
|
||||
if( fSimulationInterface )
|
||||
fSimulationInterface->ISetSceneNode(newNode);
|
||||
if( fAudioInterface )
|
||||
fAudioInterface->ISetSceneNode(newNode);
|
||||
if( fCoordinateInterface )
|
||||
fCoordinateInterface->ISetSceneNode(newNode);
|
||||
|
||||
int i;
|
||||
for( i = 0; i < GetNumGenerics(); i++ )
|
||||
{
|
||||
if( fGenerics[i] )
|
||||
fGenerics[i]->ISetSceneNode(newNode);
|
||||
}
|
||||
|
||||
if( newNode )
|
||||
{
|
||||
plNodeRefMsg* refMsg = TRACKED_NEW plNodeRefMsg(newNode, plNodeRefMsg::kOnRequest, -1, plNodeRefMsg::kObject);
|
||||
plKey key = GetKey(); // for linux build
|
||||
hsgResMgr::ResMgr()->AddViaNotify(key, refMsg, plRefFlags::kActiveRef);
|
||||
}
|
||||
if( curNode)
|
||||
{
|
||||
curNode->Release(GetKey());
|
||||
}
|
||||
fSceneNode = newNode;
|
||||
}
|
||||
|
||||
plKey plSceneObject::GetSceneNode() const
|
||||
{
|
||||
return fSceneNode;
|
||||
}
|
||||
|
||||
void plSceneObject::SetNetGroup(plNetGroupId netGroup)
|
||||
{
|
||||
if( !fCoordinateInterface )
|
||||
plSynchedObject::SetNetGroup(netGroup);
|
||||
else
|
||||
fCoordinateInterface->ISetNetGroupRecur(netGroup);
|
||||
}
|
||||
|
||||
const plModifier* plSceneObject::GetModifierByType(UInt16 classIdx) const
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < fModifiers.GetCount(); i++)
|
||||
{
|
||||
plModifier * mod = fModifiers[i];
|
||||
if (mod && plFactory::DerivesFrom(classIdx, mod->ClassIndex()))
|
||||
return mod;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
hsBool plSceneObject::MsgReceive(plMessage* msg)
|
||||
{
|
||||
|
||||
#if 0 // objects are only in the nil room when they are being paged out
|
||||
// TEMP - until we have another way to neutralize objects
|
||||
// for an object in the 'nil' room, ignore most msgs
|
||||
if (GetSceneNode()==nil && !plNodeChangeMsg::ConvertNoRef(msg) &&
|
||||
!plRefMsg::ConvertNoRef(msg)&&
|
||||
!plSelfDestructMsg::ConvertNoRef(msg))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
hsBool retVal = false;
|
||||
// If it's a bcast, let our own dispatcher find who's interested.
|
||||
plTransformMsg* trans;
|
||||
plEvalMsg* eval = plEvalMsg::ConvertNoRef(msg);
|
||||
plAttachMsg* att = nil;
|
||||
if( eval )
|
||||
{
|
||||
// Switched things over so that modifiers register for the eval message themselves,
|
||||
// and can be smart about not evaluating if they know it's unneccessary.
|
||||
|
||||
//Eval(eval->DSeconds(), eval->DelSeconds());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if( trans = plTransformMsg::ConvertNoRef(msg) ) // also catches the derived plDelayedTransformMsg
|
||||
{
|
||||
if( fCoordinateInterface )
|
||||
{
|
||||
// flush any dirty transforms
|
||||
fCoordinateInterface->ITransformChanged(false, 0, trans->ClassIndex() == plTransformMsg::Index());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if( att = plAttachMsg::ConvertNoRef(msg) )
|
||||
{
|
||||
if( fCoordinateInterface )
|
||||
{
|
||||
plSceneObject *child = plSceneObject::ConvertNoRef(att->GetRef());
|
||||
|
||||
if( child )
|
||||
{
|
||||
if( !fCoordinateInterface )
|
||||
{
|
||||
// If we have no coordinate interface, we could make ourselves one here,
|
||||
// but for now it's an error.
|
||||
hsAssert(false, "Trying to attach a child when we have no coordinateInterface");
|
||||
return true;
|
||||
}
|
||||
if( !child->GetVolatileCoordinateInterface() )
|
||||
{
|
||||
// If the child has no coordinate interface, we could add one to it here,
|
||||
// but for now it's an error.
|
||||
hsAssert(false, "Trying to attach a child who has no coordinateInterface");
|
||||
return true;
|
||||
}
|
||||
plIntRefMsg* intRefMsg = TRACKED_NEW plIntRefMsg(fCoordinateInterface->GetKey(), att->GetContext(), -1, plIntRefMsg::kChildObject);
|
||||
intRefMsg->SetRef(child);
|
||||
hsgResMgr::ResMgr()->AddViaNotify(intRefMsg, plRefFlags::kPassiveRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Am I the final destination?
|
||||
{
|
||||
retVal = IMsgHandle(msg);
|
||||
}
|
||||
|
||||
if( msg->HasBCastFlag(plMessage::kPropagateToModifiers) )
|
||||
{
|
||||
retVal |= IPropagateToModifiers(msg);
|
||||
}
|
||||
|
||||
if (msg->HasBCastFlag(plMessage::kPropagateToChildren))
|
||||
{
|
||||
const plCoordinateInterface* ci = GetCoordinateInterface();
|
||||
for (int i = 0; i < ci->GetNumChildren(); i++)
|
||||
{
|
||||
plSceneObject* child = (plSceneObject*)ci->GetChild(i)->GetOwner();
|
||||
if (child)
|
||||
{
|
||||
hsBool modRet = child->MsgReceive(msg);
|
||||
retVal |= modRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Might want an option to propagate messages to children here.
|
||||
|
||||
return plSynchedObject::MsgReceive(msg);
|
||||
}
|
||||
|
||||
hsBool plSceneObject::IMsgHandle(plMessage* msg)
|
||||
{
|
||||
// To start with, plSceneObject only handles messages to add or remove
|
||||
// references. Current references are other plSceneObjects and plModifiers
|
||||
plObjRefMsg* refMsg = plObjRefMsg::ConvertNoRef(msg);
|
||||
if( refMsg )
|
||||
{
|
||||
switch( refMsg->fType )
|
||||
{
|
||||
case plObjRefMsg::kModifier:
|
||||
{
|
||||
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
|
||||
{
|
||||
plModifier* mod = plModifier::ConvertNoRef(refMsg->GetRef());
|
||||
IAddModifier(mod, refMsg->fWhich);
|
||||
}
|
||||
else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
|
||||
{
|
||||
plModifier* mod = (plModifier*)refMsg->GetRef();
|
||||
IRemoveModifier(mod);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case plObjRefMsg::kInterface:
|
||||
{
|
||||
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
|
||||
{
|
||||
plObjInterface* oi = plObjInterface::ConvertNoRef(refMsg->GetRef());
|
||||
ISetInterface(oi);
|
||||
}
|
||||
else
|
||||
if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
|
||||
{
|
||||
plObjInterface* oi = (plObjInterface*)refMsg->GetRef();
|
||||
// TODO - This will crash if oi's already been deleted
|
||||
IRemoveInterface(oi->ClassIndex(), oi);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
plNodeChangeMsg* nodeChange = plNodeChangeMsg::ConvertNoRef(msg);
|
||||
if( nodeChange )
|
||||
{
|
||||
SetSceneNode(nodeChange->GetNodeKey());
|
||||
return true;
|
||||
}
|
||||
|
||||
if( plIntRefMsg::ConvertNoRef(msg) )
|
||||
{
|
||||
if (fCoordinateInterface)
|
||||
fCoordinateInterface->MsgReceive(msg);
|
||||
if (fAudioInterface)
|
||||
fAudioInterface->MsgReceive(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plCorrectionMsg::ConvertNoRef(msg))
|
||||
{
|
||||
hsAssert(fCoordinateInterface, "Unimplemented, also need to register this one we just made with the resource manager");
|
||||
|
||||
if (fCoordinateInterface)
|
||||
fCoordinateInterface->MsgReceive(msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for generic enable/disable message (passed to interfaces)
|
||||
|
||||
plEnableMsg* pEnableMsg = plEnableMsg::ConvertNoRef( msg );
|
||||
if (pEnableMsg)
|
||||
{
|
||||
if( pEnableMsg->Cmd(plEnableMsg::kDrawable) )
|
||||
{
|
||||
plDrawInterface* di = GetVolatileDrawInterface();
|
||||
if( di )
|
||||
di->MsgReceive(msg);
|
||||
plObjInterface* li = GetVolatileGenericInterface(CLASS_INDEX_SCOPED(plLightInfo));
|
||||
if( li )
|
||||
li->MsgReceive(msg);
|
||||
}
|
||||
if ( pEnableMsg->Cmd(plEnableMsg::kAll) && GetDrawInterface() )
|
||||
GetVolatileDrawInterface()->MsgReceive(msg);
|
||||
|
||||
if ( pEnableMsg->Cmd( plEnableMsg::kPhysical ) || pEnableMsg->Cmd( plEnableMsg::kAll) )
|
||||
{
|
||||
if ( GetSimulationInterface() )
|
||||
{
|
||||
GetVolatileSimulationInterface()->MsgReceive(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if someone is trying to disable the physics on a sceneobject that doesn't have a physics interface...
|
||||
// they might be trying to disable the avatar when the PhysX controller is being used
|
||||
// ...so, look to see if this is an avatar object, and tell the avatar to disable the physics
|
||||
IPropagateToModifiers(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if ( (pEnableMsg->Cmd( plEnableMsg::kAudible ) || pEnableMsg->Cmd( plEnableMsg::kAll )) && GetAudioInterface() )
|
||||
GetVolatileAudioInterface()->MsgReceive(msg);
|
||||
|
||||
if( pEnableMsg->Cmd( plEnableMsg::kAll ) )
|
||||
{
|
||||
IPropagateToGenerics(pEnableMsg);
|
||||
}
|
||||
else if( pEnableMsg->Cmd( plEnableMsg::kByType ) )
|
||||
{
|
||||
IPropagateToGenerics(pEnableMsg->Types(), pEnableMsg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// warp message
|
||||
if( plWarpMsg::ConvertNoRef(msg) )
|
||||
{
|
||||
// if there's a simulation interface, it needs to know about the warp
|
||||
// *** it would probably be better if it got this from the coordinate interface, as
|
||||
// *** only the coordinate interface knows to propagate it to children.
|
||||
// if(fSimulationInterface)
|
||||
// {
|
||||
// fSimulationInterface->MsgReceive(msg);
|
||||
// }
|
||||
|
||||
// the coordinate interface always gets the warp
|
||||
if (fCoordinateInterface)
|
||||
{
|
||||
fCoordinateInterface->MsgReceive(msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( plSimulationMsg::ConvertNoRef(msg) )
|
||||
{
|
||||
if(fSimulationInterface)
|
||||
{
|
||||
fSimulationInterface->MsgReceive(msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// audio message
|
||||
if (plSoundMsg::ConvertNoRef(msg) )
|
||||
{
|
||||
if( fAudioInterface )
|
||||
return(GetVolatileAudioInterface()->MsgReceive(msg));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void plSceneObject::IPropagateToGenerics(const hsBitVector& types, plMessage* msg)
|
||||
{
|
||||
hsBitIterator iter(types);
|
||||
int i;
|
||||
for( i = 0; i < fGenerics.GetCount(); i++ )
|
||||
{
|
||||
if( fGenerics[i] )
|
||||
{
|
||||
for( iter.Begin(); !iter.End(); iter.Advance() )
|
||||
{
|
||||
if( plFactory::DerivesFrom(iter.Current(), fGenerics[i]->ClassIndex()) )
|
||||
{
|
||||
fGenerics[i]->MsgReceive(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plSceneObject::IPropagateToGenerics(plMessage* msg)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fGenerics.GetCount(); i++ )
|
||||
{
|
||||
if( fGenerics[i] )
|
||||
fGenerics[i]->MsgReceive(msg);
|
||||
}
|
||||
}
|
||||
|
||||
plObjInterface* plSceneObject::GetVolatileGenericInterface(UInt16 classIdx) const
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fGenerics.GetCount(); i++ )
|
||||
{
|
||||
if( fGenerics[i] && plFactory::DerivesFrom(classIdx, fGenerics[i]->ClassIndex()) )
|
||||
return fGenerics[i];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
void plSceneObject::IAddGeneric(plObjInterface* gen)
|
||||
{
|
||||
if( gen )
|
||||
{
|
||||
if( fGenerics.kMissingIndex == fGenerics.Find(gen) )
|
||||
{
|
||||
fGenerics.Append(gen);
|
||||
gen->ISetOwner(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plSceneObject::IRemoveGeneric(plObjInterface* gen)
|
||||
{
|
||||
if( gen )
|
||||
{
|
||||
int idx = fGenerics.Find(gen);
|
||||
if( fGenerics.kMissingIndex != idx )
|
||||
{
|
||||
gen->ISetOwner(nil);
|
||||
fGenerics.Remove(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plSceneObject::IRemoveAllGenerics()
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fGenerics.GetCount(); i++ )
|
||||
{
|
||||
if( fGenerics[i] )
|
||||
fGenerics[i]->ISetOwner(nil);
|
||||
}
|
||||
fGenerics.Reset();
|
||||
}
|
||||
|
||||
void plSceneObject::ISetDrawInterface(plDrawInterface* di)
|
||||
{
|
||||
if( fDrawInterface != di )
|
||||
{
|
||||
if( fDrawInterface )
|
||||
fDrawInterface->ISetOwner(nil);
|
||||
|
||||
fDrawInterface = di;
|
||||
if( di )
|
||||
di->ISetOwner(this);
|
||||
}
|
||||
}
|
||||
|
||||
void plSceneObject::ISetSimulationInterface(plSimulationInterface* si)
|
||||
{
|
||||
if( fSimulationInterface != si )
|
||||
{
|
||||
if( fSimulationInterface )
|
||||
fSimulationInterface->ISetOwner(nil);
|
||||
|
||||
fSimulationInterface = si;
|
||||
if( si )
|
||||
si->ISetOwner(this);
|
||||
}
|
||||
}
|
||||
|
||||
void plSceneObject::ISetAudioInterface(plAudioInterface* ai)
|
||||
{
|
||||
if( fAudioInterface != ai )
|
||||
{
|
||||
if( fAudioInterface )
|
||||
fAudioInterface->ISetOwner(nil);
|
||||
fAudioInterface = ai;
|
||||
if( ai )
|
||||
ai->ISetOwner(this);
|
||||
}
|
||||
}
|
||||
|
||||
void plSceneObject::ISetCoordinateInterface(plCoordinateInterface* ci)
|
||||
{
|
||||
if( fCoordinateInterface != ci )
|
||||
{
|
||||
if( fCoordinateInterface )
|
||||
fCoordinateInterface->ISetOwner(nil);
|
||||
|
||||
fCoordinateInterface = ci;
|
||||
if( ci )
|
||||
ci->ISetOwner(this);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// "is ready to process Loads"? Check base class and modifiers.
|
||||
//
|
||||
hsBool plSceneObject::IsFinal()
|
||||
{
|
||||
if (!plSynchedObject::IsFinal())
|
||||
return false;
|
||||
|
||||
int i;
|
||||
for(i=0;i<GetNumModifiers(); i++)
|
||||
if (fModifiers[i] && !fModifiers[i]->IsFinal())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Export only. Interfaces perm on object.
|
||||
void plSceneObject::SetDrawInterface(plDrawInterface* di)
|
||||
{
|
||||
ISetDrawInterface(di);
|
||||
}
|
||||
|
||||
void plSceneObject::SetSimulationInterface(plSimulationInterface* si)
|
||||
{
|
||||
ISetSimulationInterface(si);
|
||||
}
|
||||
|
||||
void plSceneObject::SetAudioInterface(plAudioInterface* ai)
|
||||
{
|
||||
ISetAudioInterface(ai);
|
||||
}
|
||||
|
||||
void plSceneObject::SetCoordinateInterface(plCoordinateInterface* ci)
|
||||
{
|
||||
ISetCoordinateInterface(ci);
|
||||
}
|
||||
|
||||
void plSceneObject::AddModifier(plModifier* mo)
|
||||
{
|
||||
IAddModifier(mo, fModifiers.GetCount());
|
||||
}
|
||||
|
||||
void plSceneObject::RemoveModifier(plModifier* mo)
|
||||
{
|
||||
IRemoveModifier(mo);
|
||||
}
|
181
Sources/Plasma/NucleusLib/pnSceneObject/plSceneObject.h
Normal file
181
Sources/Plasma/NucleusLib/pnSceneObject/plSceneObject.h
Normal file
@ -0,0 +1,181 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#ifndef plSceneObject_inc
|
||||
#define plSceneObject_inc
|
||||
|
||||
#include "hsBitVector.h"
|
||||
#include "../pnKeyedObject/hsKeyedObject.h"
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pnNetCommon/plSynchedObject.h"
|
||||
#include "../pnNetCommon/plSynchedValue.h"
|
||||
#include "../pnModifier/plModifier.h"
|
||||
#include "hsStream.h"
|
||||
|
||||
class plObjInterface;
|
||||
class plDrawInterface;
|
||||
class plSimulationInterface;
|
||||
class plCoordinateInterface;
|
||||
class plAudioInterface;
|
||||
class plMessage;
|
||||
class hsStream;
|
||||
class hsResMgr;
|
||||
class plMessage;
|
||||
class plDispatchBase;
|
||||
struct hsMatrix44;
|
||||
|
||||
// The following two aren't dragging the Conversion side into the runtime.
|
||||
// They are just to let the converter do things we don't want done at runtime.
|
||||
// Nice that we can make friends with these opaque classes.
|
||||
class plMaxNode;
|
||||
class plMaxNodeBase;
|
||||
|
||||
class plSceneObject : public plSynchedObject {
|
||||
friend class plSynchedValueBase;
|
||||
private:
|
||||
plDrawInterface* GetVolatileDrawInterface() { return fDrawInterface; }
|
||||
plSimulationInterface* GetVolatileSimulationInterface() { return fSimulationInterface; }
|
||||
plCoordinateInterface* GetVolatileCoordinateInterface() { return fCoordinateInterface; }
|
||||
plAudioInterface* GetVolatileAudioInterface() { return fAudioInterface; }
|
||||
plObjInterface* GetVolatileGenericInterface(UInt16 classIdx) const;
|
||||
|
||||
plModifier* GetVolatileModifier(int i) { return fModifiers[i]; }
|
||||
|
||||
plKey fSceneNode;
|
||||
|
||||
friend class plModifier;
|
||||
friend class plCoordinateInterface;
|
||||
friend class plObjInterface;
|
||||
friend class plMaxNode;
|
||||
friend class plMaxNodeBase;
|
||||
|
||||
hsBool IMsgHandle(plMessage* msg);
|
||||
protected:
|
||||
|
||||
plDrawInterface* fDrawInterface;
|
||||
plSimulationInterface* fSimulationInterface;
|
||||
plCoordinateInterface* fCoordinateInterface;
|
||||
plAudioInterface* fAudioInterface;
|
||||
|
||||
hsTArray<plModifier*> fModifiers;
|
||||
|
||||
hsTArray<plObjInterface*> fGenerics;
|
||||
|
||||
void ISetDrawInterface(plDrawInterface* di);
|
||||
void ISetSimulationInterface(plSimulationInterface* si);
|
||||
void ISetAudioInterface(plAudioInterface* ai);
|
||||
void ISetCoordinateInterface(plCoordinateInterface* ci);
|
||||
|
||||
void IAddGeneric(plObjInterface* gen);
|
||||
void IRemoveGeneric(plObjInterface* gen);
|
||||
void IRemoveAllGenerics();
|
||||
void IPropagateToGenerics(plMessage* msg);
|
||||
void IPropagateToGenerics(const hsBitVector& types, plMessage* msg);
|
||||
|
||||
void IAddModifier(plModifier* mo, int i);
|
||||
void IRemoveModifier(plModifier* mo);
|
||||
hsBool IPropagateToModifiers(plMessage* msg);
|
||||
|
||||
void ISetInterface(plObjInterface* iface);
|
||||
void IRemoveInterface(plObjInterface* iface);
|
||||
void IRemoveInterface(Int16 idx, plObjInterface* iface=nil);
|
||||
|
||||
void ISetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
|
||||
public:
|
||||
|
||||
plSceneObject();
|
||||
virtual ~plSceneObject();
|
||||
|
||||
CLASSNAME_REGISTER( plSceneObject );
|
||||
GETINTERFACE_ANY( plSceneObject, plSynchedObject );
|
||||
|
||||
virtual void Read(hsStream* stream, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* stream, hsResMgr* mgr);
|
||||
|
||||
virtual const plDrawInterface* GetDrawInterface() const { return fDrawInterface; }
|
||||
virtual const plSimulationInterface* GetSimulationInterface() const { return fSimulationInterface; }
|
||||
virtual const plCoordinateInterface* GetCoordinateInterface() const { return fCoordinateInterface; }
|
||||
virtual const plAudioInterface* GetAudioInterface() const { return fAudioInterface; }
|
||||
|
||||
int GetNumGenerics() const { return fGenerics.GetCount(); }
|
||||
const plObjInterface* GetGeneric(int i) const { return fGenerics[i]; }
|
||||
|
||||
plObjInterface* GetGenericInterface(UInt16 classIdx) const { return GetVolatileGenericInterface(classIdx); }
|
||||
|
||||
int GetNumModifiers() const { return fModifiers.GetCount(); }
|
||||
const plModifier* GetModifier(int i) const { return fModifiers[i]; }
|
||||
const plModifier* GetModifierByType(UInt16 classIdx) const;
|
||||
|
||||
virtual hsBool MsgReceive(plMessage* msg);
|
||||
virtual hsBool Eval(double secs, hsScalar del);
|
||||
|
||||
void SetSceneNode(plKey newNode);
|
||||
plKey GetSceneNode() const;
|
||||
|
||||
// Network only strange function. Do not emulate or generalize this functionality.
|
||||
virtual void SetNetGroup(plNetGroupId netGroup);
|
||||
|
||||
virtual void ReleaseData( void );
|
||||
|
||||
// Force an immediate re-sync of the transforms in the hierarchy this object belongs to,
|
||||
// as opposed to waiting for the plTransformMsg to resync.
|
||||
void FlushTransform();
|
||||
void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
hsMatrix44 GetLocalToWorld() const;
|
||||
hsMatrix44 GetWorldToLocal() const;
|
||||
hsMatrix44 GetLocalToParent() const;
|
||||
hsMatrix44 GetParentToLocal() const;
|
||||
|
||||
hsBool IsFinal(); // "is ready to process Loads"
|
||||
|
||||
// Export only
|
||||
virtual void SetDrawInterface(plDrawInterface* di);
|
||||
virtual void SetSimulationInterface(plSimulationInterface* si);
|
||||
virtual void SetAudioInterface(plAudioInterface* ai);
|
||||
virtual void SetCoordinateInterface(plCoordinateInterface* ci);
|
||||
|
||||
virtual void AddModifier(plModifier* mo);
|
||||
virtual void RemoveModifier(plModifier* mo);
|
||||
};
|
||||
|
||||
#endif // plSceneObject_inc
|
@ -0,0 +1,209 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "plSimulationInterface.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "plPhysical.h"
|
||||
#include "hsBounds.h"
|
||||
#include "hsStream.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "plSceneObject.h"
|
||||
#include "../pnMessage/plEnableMsg.h"
|
||||
#include "../pnMessage/plIntRefMsg.h"
|
||||
#include "../pnMessage/plWarpMsg.h"
|
||||
#include "../pnMessage/plSimulationSynchMsg.h"
|
||||
#include "../pnMessage/plSimulationMsg.h"
|
||||
#include "../pnMessage/plNodeRefMsg.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
|
||||
plSimulationInterface::plSimulationInterface() : fPhysical(nil)
|
||||
{
|
||||
}
|
||||
|
||||
plSimulationInterface::~plSimulationInterface()
|
||||
{
|
||||
}
|
||||
|
||||
void plSimulationInterface::ISetSceneNode(plKey newNode)
|
||||
{
|
||||
if (fPhysical)
|
||||
fPhysical->SetSceneNode(newNode);
|
||||
}
|
||||
|
||||
void plSimulationInterface::SetProperty(int prop, hsBool on)
|
||||
{
|
||||
plObjInterface::SetProperty(prop, on); // set the property locally
|
||||
|
||||
if (fPhysical)
|
||||
fPhysical->SetProperty(prop, on ? true : false);
|
||||
}
|
||||
|
||||
void plSimulationInterface::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
if (fPhysical)
|
||||
fPhysical->SetTransform(l2w, w2l);
|
||||
}
|
||||
|
||||
void plSimulationInterface::ClearLinearVelocity()
|
||||
{
|
||||
if (fPhysical)
|
||||
fPhysical->ClearLinearVelocity();
|
||||
}
|
||||
|
||||
void plSimulationInterface::Read(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Read(s, mgr);
|
||||
|
||||
// fProps is already read by plObjInterface, but we'll do it again here to
|
||||
// avoid breaking the format
|
||||
fProps.Read(s);
|
||||
// Also unnecessary
|
||||
int poop = s->ReadSwap32();
|
||||
|
||||
plIntRefMsg* refMsg = TRACKED_NEW plIntRefMsg(GetKey(), plRefMsg::kOnCreate, 0, plIntRefMsg::kPhysical, 0);
|
||||
mgr->ReadKeyNotifyMe(s, refMsg, plRefFlags::kActiveRef);
|
||||
}
|
||||
|
||||
void plSimulationInterface::Write(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Write(s, mgr);
|
||||
|
||||
// Legacy crap
|
||||
fProps.Write(s);
|
||||
s->WriteSwap32(0);
|
||||
|
||||
mgr->WriteKey(s, fPhysical);
|
||||
}
|
||||
|
||||
void plSimulationInterface::ReleaseData()
|
||||
{
|
||||
plPhysical *physical = fPhysical;
|
||||
|
||||
if (physical)
|
||||
{
|
||||
// To get rid of our data, we need to release our active ref and tell the SceneNode
|
||||
// to dump it. It will autodestruct after those two active refs are released, unless
|
||||
// someone else has a ref on it as well (in which case we don't want to be nuking it
|
||||
// anyway).
|
||||
if (physical->GetSceneNode())
|
||||
{
|
||||
plKey nodeKey = physical->GetSceneNode();
|
||||
|
||||
nodeKey->Release(physical->GetKey());
|
||||
}
|
||||
|
||||
GetKey()->Release(physical->GetKey());
|
||||
}
|
||||
}
|
||||
|
||||
hsBool plSimulationInterface::MsgReceive(plMessage* msg)
|
||||
{
|
||||
plIntRefMsg* intRefMsg = plIntRefMsg::ConvertNoRef(msg);
|
||||
if (intRefMsg)
|
||||
{
|
||||
switch (intRefMsg->fType)
|
||||
{
|
||||
case plIntRefMsg::kPhysical:
|
||||
if (intRefMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove))
|
||||
{
|
||||
plPhysical* phys = plPhysical::ConvertNoRef(intRefMsg->GetRef());
|
||||
// *** for some reason, we sometimes get a null pointer here
|
||||
// *** if we do, we're just going to ignore it for now
|
||||
if (phys)
|
||||
{
|
||||
hsAssert(phys == fPhysical, "Removing Physical I don't have");
|
||||
fPhysical = nil;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fPhysical = plPhysical::ConvertNoRef(intRefMsg->GetRef());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
plEnableMsg* pEnableMsg = plEnableMsg::ConvertNoRef(msg);
|
||||
if (pEnableMsg)
|
||||
{
|
||||
SetProperty(kDisable, pEnableMsg->Cmd(kDisable));
|
||||
SetProperty(kPinned, pEnableMsg->Cmd(kDisable));
|
||||
return true;
|
||||
}
|
||||
|
||||
plWarpMsg* pWarpMsg = plWarpMsg::ConvertNoRef(msg);
|
||||
if (pWarpMsg)
|
||||
{
|
||||
if (fPhysical)
|
||||
{
|
||||
hsMatrix44 l2w = pWarpMsg->GetTransform();
|
||||
hsMatrix44 inv;
|
||||
l2w.GetInverse(&inv);
|
||||
SetTransform(l2w, inv);
|
||||
if (pWarpMsg->GetWarpFlags() & plWarpMsg::kZeroVelocity)
|
||||
{
|
||||
ClearLinearVelocity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plSimulationMsg* pSimMsg = plSimulationMsg::ConvertNoRef(msg);
|
||||
if (pSimMsg)
|
||||
{
|
||||
if (fPhysical)
|
||||
fPhysical->MsgReceive(pSimMsg);
|
||||
}
|
||||
|
||||
return plObjInterface::MsgReceive(msg);
|
||||
}
|
||||
|
||||
// Export only. Use messages for runtime.
|
||||
void plSimulationInterface::SetPhysical(plPhysical* ph)
|
||||
{
|
||||
fPhysical = ph;
|
||||
}
|
||||
|
||||
plPhysical* plSimulationInterface::GetPhysical() const
|
||||
{
|
||||
return fPhysical;
|
||||
}
|
||||
|
113
Sources/Plasma/NucleusLib/pnSceneObject/plSimulationInterface.h
Normal file
113
Sources/Plasma/NucleusLib/pnSceneObject/plSimulationInterface.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#ifndef plSimulationInterface_inc
|
||||
#define plSimulationInterface_inc
|
||||
|
||||
#include "plObjInterface.h"
|
||||
|
||||
class plPhysical;
|
||||
struct hsMatrix44;
|
||||
class hsBounds3Ext;
|
||||
|
||||
class plSimulationInterface : public plObjInterface
|
||||
{
|
||||
public:
|
||||
// Props inc by 1 (bit shift in bitvector).
|
||||
enum plSimulationProperties {
|
||||
// prop 0 is always disable, , declared in plObjInterface
|
||||
kDisable = 0, // no more interaction. no interference detection
|
||||
kWeightless_DEAD, // unaffected by gravity, but not massless
|
||||
kPinned, // stop moving. keep colliding.
|
||||
kWarp_DEAD, // keep moving, no colliding (a pattern is emerging here...)
|
||||
kUpright_DEAD, // stand upright (mainly for the player)
|
||||
kPassive, // don't push new positions to sceneobject
|
||||
kRotationForces_DEAD, // rotate using forces
|
||||
kCameraAvoidObject_DEAD, // camera will try and fly around this obsticle
|
||||
kPhysAnim, // this object is animated, and the animation can apply force
|
||||
kStartInactive, // deactive this object at start time. will reactivate when hit
|
||||
kNoSynchronize, // don't synchronize this physical
|
||||
kSuppressed_DEAD, // physical still exists but is not in simulation: no forces, contact, or reports
|
||||
kNoOwnershipChange, // Don't automatically change net ownership on this physical when it is collided with
|
||||
kAvAnimPushable, // Something the avatar should react to and push against
|
||||
kNumProps
|
||||
};
|
||||
|
||||
protected:
|
||||
plPhysical* fPhysical;
|
||||
|
||||
friend class plSceneObject;
|
||||
|
||||
virtual void ISetSceneNode(plKey newNode);
|
||||
|
||||
public:
|
||||
plSimulationInterface();
|
||||
~plSimulationInterface();
|
||||
|
||||
CLASSNAME_REGISTER( plSimulationInterface );
|
||||
GETINTERFACE_ANY( plSimulationInterface, plObjInterface );
|
||||
|
||||
virtual void Read(hsStream* stream, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* stream, hsResMgr* mgr);
|
||||
|
||||
void SetProperty(int prop, hsBool on);
|
||||
Int32 GetNumProperties() const { return kNumProps; }
|
||||
|
||||
// Transform settable only, if you want it get it from the coordinate interface.
|
||||
void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
|
||||
// Bounds are gettable only, they are computed on the physical.
|
||||
const hsBounds3Ext GetLocalBounds();
|
||||
const hsBounds3Ext GetWorldBounds() const;
|
||||
const hsBounds3Ext GetMaxWorldBounds();
|
||||
void ClearLinearVelocity();
|
||||
|
||||
virtual hsBool MsgReceive(plMessage* msg);
|
||||
|
||||
// Export only.
|
||||
void SetPhysical(plPhysical* phys);
|
||||
void ReleaseData();
|
||||
|
||||
plPhysical* GetPhysical() const;
|
||||
};
|
||||
|
||||
|
||||
#endif // plSimulationInterface_inc
|
@ -0,0 +1,73 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#ifndef plSceneObjectCreatable_inc
|
||||
#define plSceneObjectCreatable_inc
|
||||
|
||||
#include "../pnFactory/plCreator.h"
|
||||
|
||||
#include "plObjInterface.h"
|
||||
|
||||
REGISTER_NONCREATABLE( plObjInterface );
|
||||
|
||||
#include "plAudioInterface.h"
|
||||
|
||||
REGISTER_CREATABLE( plAudioInterface );
|
||||
|
||||
#include "plCoordinateInterface.h"
|
||||
|
||||
REGISTER_CREATABLE( plCoordinateInterface );
|
||||
|
||||
#include "plDrawInterface.h"
|
||||
|
||||
REGISTER_CREATABLE( plDrawInterface );
|
||||
|
||||
#include "plSimulationInterface.h"
|
||||
|
||||
REGISTER_CREATABLE( plSimulationInterface );
|
||||
|
||||
#include "plSceneObject.h"
|
||||
|
||||
REGISTER_CREATABLE( plSceneObject );
|
||||
|
||||
|
||||
#endif // plSceneObjectCreatable_inc
|
Reference in New Issue
Block a user