You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
312 lines
9.4 KiB
312 lines
9.4 KiB
14 years ago
|
/*==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/>.
|
||
|
|
||
|
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 "hsMatrix44.h"
|
||
|
#include "hsTypes.h"
|
||
|
#include "plListener.h"
|
||
|
#include "plgDispatch.h"
|
||
|
#include "../plAudio/plAudioSystem.h"
|
||
|
#include "../pnMessage/plTimeMsg.h"
|
||
|
#include "../pnMessage/plAudioSysMsg.h"
|
||
|
#include "../pnKeyedObject/plKey.h"
|
||
|
#include "../pnSceneObject/plSceneObject.h"
|
||
|
#include "../pnSceneObject/plCoordinateInterface.h"
|
||
|
#include "../pnSceneObject/plSimulationInterface.h"
|
||
|
#include "../pfCamera/plVirtualCamNeu.h"
|
||
|
#include "../plMessage/plListenerMsg.h"
|
||
|
#include "../plNetClient/plNetClientMgr.h"
|
||
|
#include "../plPipeline/plDebugText.h"
|
||
|
|
||
|
#include "../plAvatar/plAvatarMgr.h"
|
||
|
#include "../plAvatar/plArmatureMod.h"
|
||
|
#include "../plAvatar/plAvCallbackAction.h"
|
||
|
|
||
|
hsBool plListener::fPrintDbgInfo = false;
|
||
|
|
||
|
hsBool plListener::IEval(double secs, hsScalar del, UInt32 dirty)
|
||
|
{
|
||
|
// if (!plgAudioSys::Active())
|
||
|
// return true;
|
||
|
plSceneObject *pRefObject = nil;
|
||
|
|
||
|
int y = 16 + 12, x = 400;
|
||
|
if( fPrintDbgInfo )
|
||
|
plDebugText::Instance().DrawString( x, 16, "Listener:", (UInt32)0xffffffff, plDebugText::kStyleBold );
|
||
|
|
||
|
// Get the avatar's SceneObject
|
||
|
plKey key = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
|
||
|
if(key)
|
||
|
pRefObject = plSceneObject::ConvertNoRef(key->ObjectIsLoaded());
|
||
|
|
||
|
if( pRefObject == nil && fVCam == nil )
|
||
|
{
|
||
|
// We don't have a position to init by, so do NOT eval yet!!!
|
||
|
if( fPrintDbgInfo )
|
||
|
plDebugText::Instance().DrawString( x, y, "Not eval-ing yet", (UInt32)0xffffffff );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Changed 2.19.02 mcn - Basing it off the head bone isn't what we really want, esp. since
|
||
|
// it isn't what the camera uses. What we *really* want is a head-ish-positioned non-bobbing node
|
||
|
// that we base both off of. Until then, we're just going to have to use the avatar's root (i.e. his
|
||
|
// feet) and add in an appropriate height. See plAvBrain.cpp::BindAudioListener() for the other half
|
||
|
// of the hack.
|
||
|
// Note the 2nd: since GetAxis() is buggy, we'll just add in a constant vector. Of course, this implies
|
||
|
// that the avatar is always oriented up, but then it also implies he's always of constant height, so
|
||
|
// there.
|
||
|
const hsVector3 kAvatarHeightVector = hsVector3( 0, 0, 6.33f ); // isn't *everyone* 6'4"?
|
||
|
|
||
|
/// Collect the current values for our parameters
|
||
|
hsPoint3 position;
|
||
|
hsVector3 velocity, dir, up;
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
kInvalid = 0,
|
||
|
kVCam,
|
||
|
kObject
|
||
|
} facingType = kInvalid, posType = kInvalid, velType = kInvalid;
|
||
|
|
||
|
// Facing
|
||
|
if( fFacingRatio == 1.f )
|
||
|
{
|
||
|
if( pRefObject != nil && pRefObject->GetCoordinateInterface() )
|
||
|
{
|
||
|
hsMatrix44 facingL2W = pRefObject->GetCoordinateInterface()->GetLocalToWorld();
|
||
|
dir = facingL2W.GetAxis( hsMatrix44::kView );
|
||
|
up = facingL2W.GetAxis( hsMatrix44::kUp );
|
||
|
|
||
|
facingType = kObject;
|
||
|
}
|
||
|
}
|
||
|
else if( fVCam != nil )
|
||
|
{
|
||
|
dir = hsVector3( fVCam->GetCameraPOA() - fVCam->GetCameraPos() );
|
||
|
up = fVCam->GetCameraUp();
|
||
|
facingType = kVCam;
|
||
|
}
|
||
|
|
||
|
// Position
|
||
|
if( fPosRatio == 1.f )
|
||
|
{
|
||
|
if( pRefObject != nil && pRefObject->GetCoordinateInterface() )
|
||
|
{
|
||
|
position = pRefObject->GetCoordinateInterface()->GetLocalToWorld().GetTranslate();
|
||
|
position += kAvatarHeightVector;
|
||
|
posType = kObject;
|
||
|
}
|
||
|
}
|
||
|
else if( fVCam != nil )
|
||
|
{
|
||
|
position = fVCam->GetCameraPos();
|
||
|
posType = kVCam;
|
||
|
}
|
||
|
|
||
|
// Velocity
|
||
|
if( fVelRatio == 1.f )
|
||
|
{
|
||
|
if( pRefObject != nil )
|
||
|
{
|
||
|
plArmatureMod* arm = plAvatarMgr::GetInstance()->GetLocalAvatar();
|
||
|
if (arm)
|
||
|
{
|
||
|
plPhysicalControllerCore* controller = arm->GetController();
|
||
|
if (controller)
|
||
|
{
|
||
|
velocity = controller->GetLinearVelocity();
|
||
|
velType = kObject;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if( fVCam != nil )
|
||
|
{
|
||
|
// Darn, can't do it
|
||
|
}
|
||
|
|
||
|
if( facingType == kInvalid || posType == kInvalid || velType == kInvalid )
|
||
|
{
|
||
|
if( fPrintDbgInfo )
|
||
|
plDebugText::Instance().DrawString( x, y, "Not eval-ing: missing one or more parameter bases", (UInt32)0xff0000ff );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Got the params, now construct and send out the message, as well as update the audio system
|
||
|
plListenerMsg* msg = TRACKED_NEW plListenerMsg;
|
||
|
msg->SetDirection( dir );
|
||
|
msg->SetUp( up );
|
||
|
msg->SetPosition( position );
|
||
|
msg->SetVelocity( velocity );
|
||
|
|
||
|
plgAudioSys::SetListenerOrientation( dir, up );
|
||
|
plgAudioSys::SetListenerPos( position );
|
||
|
plgAudioSys::SetListenerVelocity( velocity );
|
||
|
|
||
|
if( fPrintDbgInfo )
|
||
|
{
|
||
|
char str[ 256 ];
|
||
|
sprintf( str, "Direction: (%3.2f,%3.2f,%3.2f) from %s", dir.fX, dir.fY, dir.fZ, ( facingType == kObject ) ? pRefObject->GetKey()->GetUoid().GetObjectName() : "VCam" );
|
||
|
plDebugText::Instance().DrawString( x, y, str, (UInt32)0xffffffff );
|
||
|
y += 12;
|
||
|
|
||
|
sprintf( str, "Up: (%3.2f,%3.2f,%3.2f) from %s", up.fX, up.fY, up.fZ, ( facingType == kObject ) ? pRefObject->GetKey()->GetUoid().GetObjectName() : "VCam" );
|
||
|
plDebugText::Instance().DrawString( x, y, str, (UInt32)0xffffffff );
|
||
|
y += 12;
|
||
|
|
||
|
sprintf( str, "Position: (%3.2f,%3.2f,%3.2f) from %s", position.fX, position.fY, position.fZ, ( posType == kObject ) ? pRefObject->GetKey()->GetUoid().GetObjectName() : "VCam" );
|
||
|
plDebugText::Instance().DrawString( x, y, str, (UInt32)0xffffffff );
|
||
|
y += 12;
|
||
|
|
||
|
sprintf( str, "Velocity: (%3.2f,%3.2f,%3.2f) from %s", velocity.fX, velocity.fY, velocity.fZ, ( velType == kObject ) ? pRefObject->GetKey()->GetUoid().GetObjectName() : "VCam" );
|
||
|
plDebugText::Instance().DrawString( x, y, str, (UInt32)0xffffffff );
|
||
|
y += 12;
|
||
|
}
|
||
|
plgDispatch::MsgSend( msg );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void plListener::ISetRef( const plKey &ref, hsBool binding, int type )
|
||
|
{
|
||
|
if( binding )
|
||
|
hsgResMgr::ResMgr()->AddViaNotify( ref, TRACKED_NEW plGenRefMsg( GetKey(), plGenRefMsg::kOnReplace, -1, type ), plRefFlags::kPassiveRef );
|
||
|
else
|
||
|
GetKey()->Release( ref );
|
||
|
}
|
||
|
|
||
|
void plListener::IEnsureVCamValid( void )
|
||
|
{
|
||
|
if( fPosRatio == 1.f && fFacingRatio == 1.f && fVelRatio == 1.f )
|
||
|
{
|
||
|
// All of our params are purely using objects, so we don't need a virtual camera pointer at all
|
||
|
if( fVCam != nil )
|
||
|
ISetRef( fVCam->GetKey(), false, kRefVCam );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// One or more of our params are using the vcam as a basis, so make sure we have it
|
||
|
if( fVCam == nil )
|
||
|
{
|
||
|
plVirtualCam1 *vCam = plVirtualCam1::Instance();
|
||
|
if( vCam == nil )
|
||
|
{
|
||
|
hsAssert( false, "Unable to grab virtual camera instance; no basis for listener!!!" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ISetRef( vCam->GetKey(), true, kRefVCam );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void plListener::ICheckAudio( void ) const
|
||
|
{
|
||
|
if( ( fPosRatio < 1.f || fFacingRatio < 1.f || fVelRatio < 1.f ) && fVCam == nil )
|
||
|
plgAudioSys::SetMuted( true );
|
||
|
}
|
||
|
|
||
|
hsBool plListener::MsgReceive(plMessage* msg)
|
||
|
{
|
||
|
plSetListenerMsg *setMsg = plSetListenerMsg::ConvertNoRef( msg );
|
||
|
if( setMsg != nil )
|
||
|
{
|
||
|
hsBool useVCam;
|
||
|
|
||
|
if( setMsg->GetType() & plSetListenerMsg::kVCam )
|
||
|
{
|
||
|
// Reset any ratios
|
||
|
if( setMsg->GetType() & plSetListenerMsg::kPosition )
|
||
|
fPosRatio = 0.f;
|
||
|
|
||
|
if( setMsg->GetType() & plSetListenerMsg::kVelocity )
|
||
|
fVelRatio = 0.f;
|
||
|
|
||
|
if( setMsg->GetType() & plSetListenerMsg::kFacing )
|
||
|
fFacingRatio = 0.f;
|
||
|
|
||
|
IEnsureVCamValid();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
useVCam = setMsg->IsBinding();
|
||
|
|
||
|
if( setMsg->GetType() & plSetListenerMsg::kPosition )
|
||
|
fPosRatio = 1.f;
|
||
|
|
||
|
if( setMsg->GetType() & plSetListenerMsg::kVelocity )
|
||
|
fVelRatio = 1.f;
|
||
|
|
||
|
if( setMsg->GetType() & plSetListenerMsg::kFacing )
|
||
|
fFacingRatio = 1.f;
|
||
|
|
||
|
if( fPosRatio > 0.f || fVelRatio > 0.f || fFacingRatio > 0.f )
|
||
|
// Need this, so store it now
|
||
|
ISetRef( setMsg->GetSrcKey(), setMsg->IsBinding(), kRefObject );
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
plEvalMsg* pEMsg = plEvalMsg::ConvertNoRef(msg);
|
||
|
if (pEMsg)
|
||
|
{
|
||
|
IEval(pEMsg->GetTimeStamp(), pEMsg->DelSeconds(), true);
|
||
|
|
||
|
if( fInitMe )
|
||
|
{
|
||
|
// By default, position and orientation are camera based
|
||
|
plSetListenerMsg *set = TRACKED_NEW plSetListenerMsg( plSetListenerMsg::kVCam | plSetListenerMsg::kFacing, nil, true );
|
||
|
set->Send();
|
||
|
set = TRACKED_NEW plSetListenerMsg( plSetListenerMsg::kVCam | plSetListenerMsg::kPosition, nil, true );
|
||
|
set->Send();
|
||
|
|
||
|
fInitMe = false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef( msg );
|
||
|
if( refMsg != nil )
|
||
|
{
|
||
|
if( refMsg->fType == kRefVCam )
|
||
|
{
|
||
|
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||
|
{
|
||
|
fVCam = plVirtualCam1::ConvertNoRef( refMsg->GetRef() );
|
||
|
}
|
||
|
else if( refMsg->GetContext() & ( plRefMsg::kOnRemove | plRefMsg::kOnDestroy ) )
|
||
|
{
|
||
|
if( plVirtualCam1::ConvertNoRef( refMsg->GetRef() ) == fVCam )
|
||
|
fVCam = nil;
|
||
|
}
|
||
|
ICheckAudio();
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return plSingleModifier::MsgReceive(msg);
|
||
|
}
|