2
3
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:
rarified
2021-05-15 12:49:46 -06:00
parent c3f4a640a3
commit 96903e8dca
4002 changed files with 159 additions and 644 deletions

View 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());
}
}

View 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

View File

@ -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);
}

View 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

View 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 );
}

View 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

View 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));
}

View 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

View 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);
}

View 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

View File

@ -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;
}

View 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

View File

@ -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