2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-15 10:54:18 +00:00

Build 918 chunk 2: update from CWE-ou

This commit is contained in:
Christian Walther
2013-07-27 16:57:46 +02:00
parent c8611a072b
commit ece6e6c063
751 changed files with 148704 additions and 76661 deletions

View File

@ -218,12 +218,12 @@ void plAgeDescription::SetAgeNameFromPath( const char *path )
}
// Construct our name from the path
char *pathSep1 = strrchr( path, '\\' );
char *pathSep2 = strrchr( path, '/' );
const char *pathSep1 = strrchr( path, '\\' );
const char *pathSep2 = strrchr( path, '/' );
if( pathSep2 > pathSep1 )
pathSep1 = pathSep2;
if( pathSep1 == nil )
pathSep1 = (char *)path;
pathSep1 = path;
else
pathSep1++; // Get past the actual character we found

View File

@ -66,8 +66,8 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plPipeline/plDebugText.h"
#include "../plStatusLog/plStatusLog.h"
#define MICROPHONE 121
#define TALKING 122
#define MICROPHONE "ui_microphone.png"
#define TALKING "ui_speaker.png"
#define NUM_CHANNELS 1
#define VOICE_STOP_MS 2000
#define MAX_DATA_SIZE 1024 * 4 // 4 KB
@ -84,13 +84,13 @@ hsBool plVoicePlayer::fEnabled = true;
plVoiceRecorder::plVoiceRecorder()
{
plPlateManager::Instance().CreatePlate( &fDisabledIcon );
fDisabledIcon->CreateFromResource( MAKEINTRESOURCE( MICROPHONE ) );
fDisabledIcon->CreateFromResource( MICROPHONE );
fDisabledIcon->SetPosition(-0.90, -0.90);
fDisabledIcon->SetSize(0.0675, 0.09);
fDisabledIcon->SetVisible(false);
plPlateManager::Instance().CreatePlate( &fTalkIcon );
fTalkIcon->CreateFromResource( MAKEINTRESOURCE( TALKING ) );
fTalkIcon->CreateFromResource( TALKING );
fTalkIcon->SetPosition(-0.9,-0.9);
fTalkIcon->SetSize(0.0675, 0.09);
fTalkIcon->SetVisible(false);
@ -208,7 +208,7 @@ void plVoiceRecorder::DrawDisabledIcon(hsBool b)
plPlateManager::Instance().CreatePlate( &fDisabledIcon );
if (fDisabledIcon)
{
fDisabledIcon->CreateFromResource( MAKEINTRESOURCE( MICROPHONE ) );
fDisabledIcon->CreateFromResource( MICROPHONE );
fDisabledIcon->SetPosition(-0.90, -0.90);
fDisabledIcon->SetSize(0.0675, 0.09);
fDisabledIcon->SetVisible(false);
@ -225,7 +225,7 @@ void plVoiceRecorder::DrawTalkIcon(hsBool b)
{
plPlateManager::Instance().CreatePlate( &fTalkIcon );
if (fTalkIcon)
{ fTalkIcon->CreateFromResource( MAKEINTRESOURCE( TALKING ) );
{ fTalkIcon->CreateFromResource( TALKING );
fTalkIcon->SetPosition(-0.9,-0.9);
fTalkIcon->SetSize(0.0675, 0.09);
fTalkIcon->SetVisible(false);

View File

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include <hvdi.h>
#include <direct.h>
#include "HeadSpin.h"
#include "hsGeometry3.h"

View File

@ -258,10 +258,10 @@ void plAGAnimInstance::DetachChannels()
do {
plAGChannel *channel = (*i).second;
channelMod->DetachChannel(channel);
} while (i != fManualDetachChannels.end() && (*++i).first == channelName);
} while (++i != fManualDetachChannels.end() && i->first == channelName);
} else {
do {
} while (i != fManualDetachChannels.end() && (*++i).first == channelName);
} while (++i != fManualDetachChannels.end() && i->first == channelName);
}
}

View File

@ -161,6 +161,9 @@ protected:
plSimulationInterface * IGetSI(const plAGModifier *modifier) const;
plObjInterface * IGetGI(const plAGModifier *modifier, UInt16 classIdx) const;
// Allow plAGModifier to declare IGet?? as friends
friend class plAGModifier;
// -- members --
plAGChannel *fChannel;
hsBool fEnabled;

View File

@ -244,9 +244,8 @@ plAGChannel * plAGModifier::MergeChannel(plAGApplicator *app,
hsBool plAGModifier::DetachChannel(plAGChannel * channel)
{
plAppTable::iterator i = fApps.begin();
hsBool done = false;
for( ; i != fApps.end(); i++)
while( i != fApps.end() )
{
plAGApplicator *app = *i;
plAGChannel *existingChannel = app->GetChannel();
@ -259,17 +258,16 @@ hsBool plAGModifier::DetachChannel(plAGChannel * channel)
app->SetChannel(replacementChannel);
if( ! replacementChannel && app->AutoDelete())
{
plAppTable::iterator old = i;
i--;
fApps.erase(old);
// Don't need to adjust the iterator since we're about to exit the loop
fApps.erase(i);
delete app;
}
done = true;
break;
return true;
}
}
++i;
}
return done;
return false;
}
// READ

View File

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include "plAvCallbackAction.h" // must be first: references havok new
// singular
#include "plAnimStage.h"

View File

@ -1,171 +0,0 @@
/*==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==*/
#if 0
// havok first
#include <hkdynamics/entity/rigidbody.h>
#include <hkdynamics/world/subspace.h>
#include "plAntiGravAction.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plHavok1/plHKPhysical.h"
#include "../plAvatar/plSwimRegion.h"
#include "hsTimer.h"
// This is meant to be a specific physicsAction for the swim behavior
plAntiGravAction::plAntiGravAction(plHKPhysical *physical, plAGApplicator *rootApp) :
plAnimatedCallbackAction(physical, rootApp),
fOnGround(false),
fBuoyancy(1.f),
fSurfaceHeight(0.f),
fCurrentRegion(nil),
fHadContacts(false)
{
}
plSimDefs::ActionType plAntiGravAction::GetType()
{
return plSimDefs::kAntiGravAction;
}
void plAntiGravAction::apply(Havok::Subspace &space, Havok::hkTime time)
{
double elapsed = time.asDouble() - getRefresh().asDouble();
setRefresh(time);
IAdjustBuoyancy();
Havok::RigidBody *body = fPhysical->GetBody();
float mass = body->getMass();
Havok::Vector3 gravity = space.getGravity();
Havok::Vector3 force = -gravity * (mass * fBuoyancy);
body->applyForce(force);
hsVector3 vel;
fPhysical->GetLinearVelocitySim(vel);
fAnimPosVel.fZ = vel.fZ;
hsVector3 linCurrent(0.f, 0.f, 0.f);
hsScalar angCurrent = 0.f;
if (fCurrentRegion != nil)
fCurrentRegion->GetCurrent(fPhysical, linCurrent, angCurrent, (hsScalar)elapsed);
int numContacts = fPhysical->GetNumContacts();
fHadContacts = (numContacts > 0);
const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f);
fOnGround = false;
int i;
for (i = 0; i < numContacts; i++)
{
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
hsScalar dotUp = straightUp.dot(contact->m_normal);
if (dotUp > .5)
{
fOnGround = true;
break;
}
}
fPhysical->SetLinearVelocitySim(fAnimPosVel + linCurrent);
fPhysical->SetAngularVelocitySim(hsVector3(0.f, 0.f, fAnimAngVel + fTurnStr + angCurrent));
}
void plAntiGravAction::SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight)
{
fCurrentRegion = region;
if (region != nil)
fSurfaceHeight = surfaceHeight;
}
void plAntiGravAction::IAdjustBuoyancy()
{
// "surface depth" refers to the depth our handle object should be below
// the surface for the avatar to be "at the surface"
static const float surfaceDepth = 4.0f;
// 1.0 = neutral buoyancy
// 0 = no buoyancy (normal gravity)
// 2.0 = opposite of gravity, floating upwards
static const float buoyancyAtSurface = 1.0f;
if (fCurrentRegion == nil)
{
fBuoyancy = 0.f;
return;
}
hsMatrix44 l2w, w2l;
fPhysical->GetTransform(l2w, w2l);
float depth = fSurfaceHeight - surfaceDepth - l2w.GetTranslate().fZ;
if (depth < -1)
fBuoyancy = 0.f; // Same as being above ground. Plain old gravity.
else if (depth < 0)
fBuoyancy = 1 + depth;
else
{
hsVector3 vel;
fPhysical->GetLinearVelocitySim(vel);
if (vel.fZ > 0)
{
if (vel.fZ > fCurrentRegion->fMaxUpwardVel)
{
vel.fZ = fCurrentRegion->fMaxUpwardVel;
fPhysical->SetLinearVelocitySim(vel);
}
else
{
if (depth > 1)
fBuoyancy = fCurrentRegion->fUpBuoyancy;
else
fBuoyancy = (fCurrentRegion->fUpBuoyancy - 1) * depth + 1;
}
}
else
{
if (depth > 1)
fBuoyancy = fCurrentRegion->fDownBuoyancy;
else
fBuoyancy = (fCurrentRegion->fDownBuoyancy - 1) * depth + 1;
}
}
}
#endif

View File

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include "plAvCallbackAction.h"
#include "../plStatusLog/plStatusLog.h"
#include "plArmatureEffects.h"

View File

@ -54,7 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAvBrainHuman.h"
#include "plMatrixChannel.h"
#include "plAvatarTasks.h"
#include "plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
#include "plAvBrainCritter.h"
// global
@ -534,8 +534,7 @@ void plArmatureModBase::EnablePhysics(hsBool status, UInt16 reason /* = kDisable
// i.e. normal enabled physical
void plArmatureModBase::EnablePhysicsKinematic(hsBool status)
{
if (fController)
fController->Kinematic(status);
EnablePhysics(!status, kDisableReasonKinematic);
}
void plArmatureModBase::EnableDrawing(hsBool status, UInt16 reason /* = kDisableReasonUnknown */)
@ -1302,7 +1301,7 @@ hsBool plArmatureMod::MsgReceive(plMessage* msg)
if(spawnSO)
{
hsMatrix44 l2w = spawnSO->GetLocalToWorld();
plWarpMsg *warpM = TRACKED_NEW plWarpMsg(nil, GetTarget(0)->GetKey(), 0, l2w);
plWarpMsg *warpM = TRACKED_NEW plWarpMsg(nil, GetTarget(0)->GetKey(), plWarpMsg::kFlushTransform, l2w);
warpM->Send();
fWaitFlags &= ~kNeedSpawn;
}
@ -2007,7 +2006,7 @@ hsBool plArmatureMod::ValidatePhysics()
return false;
if (!fController)
fController = plPhysicalControllerCore::Create(GetTarget(0)->GetKey(), fPhysHeight, fPhysWidth);
fController = plPhysicalControllerCore::Create(GetTarget(0)->GetKey(), fPhysHeight, fPhysWidth, (fBodyType == kBoneBaseMale || fBodyType == kBoneBaseFemale));
if (fController)
{
@ -2684,19 +2683,7 @@ void plArmatureMod::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *str
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
hsPoint3 kPos;
char *kinematic = "n.a.";
const char* frozen = "n.a.";
if (fController)
{
fController->GetKinematicPosition(kPos);
kinematic = fController->IsKinematic() ? "on" : "off";
}
sprintf(strBuf, "kinematc(world): %.2f, %.2f, %.2f Kinematic: %3s",
kPos.fX, kPos.fY, kPos.fZ,kinematic);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
if (fController)
frozen = fController->IsEnabled() ? "no" : "yes";

View File

@ -145,6 +145,7 @@ public:
kDisableReasonCCR = 0x0008,
kDisableReasonVehicle = 0x0010,
kDisableReasonGenericBrain = 0x0020,
kDisableReasonKinematic = 0x0040
};
void EnablePhysics(hsBool status, UInt16 reason = kDisableReasonUnknown);
void EnablePhysicsKinematic(hsBool status);

View File

@ -42,7 +42,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsConfig.h"
#include "hsWindows.h"
#include "plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
#include "plAvBrainCritter.h"
#include "plAvBrainHuman.h"
#include "plArmatureMod.h"
@ -127,7 +127,7 @@ protected:
///////////////////////////////////////////////////////////////////////////////
plAvBrainCritter::plAvBrainCritter(): fCallbackAction(nil), fCurMode(kIdle), fNextMode(kIdle), fFadingNextBehavior(true),
plAvBrainCritter::plAvBrainCritter(): fWalkingStrategy(nil), fCurMode(kIdle), fNextMode(kIdle), fFadingNextBehavior(true),
fLocallyControlled(false), fAvoidingAvatars(false), fFinalGoalPos(0, 0, 0), fImmediateGoalPos(0, 0, 0), fDotGoal(0),
fAngRight(0)
{
@ -145,8 +145,8 @@ plAvBrainCritter::~plAvBrainCritter()
fBehaviors[i] = nil;
}
delete fCallbackAction;
fCallbackAction = nil;
delete fWalkingStrategy;
fWalkingStrategy = nil;
fUserBehaviors.clear();
fReceivers.clear();
@ -169,8 +169,8 @@ hsBool plAvBrainCritter::Apply(double time, hsScalar elapsed)
IProcessBehavior(time, elapsed); // just continue with the currently running one
// update our controller to keep us turned and moving to where we want to go
fCallbackAction->RecalcVelocity(time, time - elapsed);
fCallbackAction->SetTurnStrength(IGetTurnStrength(time));
fWalkingStrategy->SetTurnStrength(IGetTurnStrength(time));
fWalkingStrategy->RecalcVelocity(time, elapsed);
return plArmatureBrain::Apply(time, elapsed);
}
@ -190,13 +190,13 @@ void plAvBrainCritter::Activate(plArmatureModBase* avMod)
IInitBaseAnimations();
// create the controller if we haven't done so already
if (!fCallbackAction)
if (!fWalkingStrategy)
{
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = avMod->GetController();
fCallbackAction = TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
controller->SetMovementStrategy(fWalkingStrategy);
}
// tell people that care that we are good to go
@ -226,7 +226,7 @@ void plAvBrainCritter::Resume()
// fade in the idle
fNextMode = kIdle;
fCallbackAction->Reset(false);
fWalkingStrategy->Reset(false);
plArmatureBrain::Resume();
}

View File

@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../pnKeyedObject/plKey.h"
class plArmatureMod;
class plWalkingController;
class plWalkingStrategy;
class plAIMsg;
class plAvBrainCritter : public plArmatureBrain
@ -127,8 +127,6 @@ public:
virtual void DumpToDebugDisplay(int& x, int& y, int lineHeight, char* strBuf, plDebugText& debugTxt);
plWalkingController* GetCallbackAction() {return fCallbackAction;}
// For the console
static bool fDrawDebug;
@ -152,7 +150,7 @@ protected:
std::vector<plArmatureMod*> IAvatarsICanSee() const;
std::vector<plArmatureMod*> IAvatarsICanHear() const;
plWalkingController* fCallbackAction;
plWalkingStrategy* fWalkingStrategy;
int fCurMode; // current behavior we are running
int fNextMode; // the next behavior to run (-1 if we aren't switching on next eval)
bool fFadingNextBehavior; // is the next behavior supposed to blend?

View File

@ -42,7 +42,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
// local includes
#include "plAvBrainDrive.h"
#include "plArmatureMod.h"
#include "plAvCallbackAction.h"
// global includes
#include "hsTimer.h"

View File

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include "plAvCallbackAction.h" // havok-contaminated file: must go first
// singular
#include "plAvBrainGeneric.h"
@ -94,7 +93,6 @@ plAvBrainGeneric::plAvBrainGeneric()
fFadeIn(0.0f),
fFadeOut(0.0f),
fMoveMode(kMoveRelative),
fCallbackAction(nil),
fBodyUsage(plAGAnim::kBodyUnknown)
{
}
@ -122,7 +120,6 @@ plAvBrainGeneric::plAvBrainGeneric(plAnimStageVec *stages,
fFadeIn(fadeIn),
fFadeOut(fadeOut),
fMoveMode(moveMode),
fCallbackAction(nil),
fBodyUsage(plAGAnim::kBodyUnknown)
{
}
@ -141,7 +138,6 @@ plAvBrainGeneric::plAvBrainGeneric(UInt32 exitFlags, float fadeIn, float fadeOut
fFadeIn(fadeIn),
fFadeOut(fadeOut),
fMoveMode(moveMode),
fCallbackAction(nil),
fBodyUsage(plAGAnim::kBodyUnknown)
{
@ -170,12 +166,6 @@ void plAvBrainGeneric::Activate(plArmatureModBase *avMod)
{
plArmatureBrain::Activate(avMod);
if ((GetType() == kEmote || GetType() == kAFK || GetType() == kSitOnGround) && fAvMod->IsLocalAvatar())
{
plInputIfaceMgrMsg* msg = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kDisableClickables );
plgDispatch::MsgSend(msg);
}
int numStages = fStages->size();
if (!numStages)
return;
@ -315,12 +305,6 @@ void plAvBrainGeneric::Deactivate()
}
plArmatureBrain::Deactivate();
if ((GetType() == kEmote || GetType() == kAFK || GetType() == kSitOnGround) && fAvMod->IsLocalAvatar())
{
plInputIfaceMgrMsg* msg = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kEnableClickables );
plgDispatch::MsgSend(msg);
}
}
// GETRECIPIENT

View File

@ -49,7 +49,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
class plAnimStage;
class plAnimStageVec;
class plAvBrainGenericMsg;
class plHorizontalFreezeAction;
class plNotifyMsg;
/** \class plAvBrainGeneric
@ -300,7 +299,6 @@ protected:
int fCurStage; // which stage are we playing? (zero-based)
BrainType fType; // what type of brain are we?
UInt32 fExitFlags; // what will cause us to exit?
plHorizontalFreezeAction *fCallbackAction;
bool fForward; // are we currently moving forward or backward through the stages?
// this is used by the "auto-" movement types in the stages

View File

@ -42,9 +42,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsConfig.h"
#include "hsWindows.h"
#include "plAvCallbackAction.h" // subclasses a havok object; must be in first include section
#include "plPhysicalControllerCore.h"
#include "plAvBrainHuman.h"
#include "plAvBrainClimb.h"
#include "plAvBrainDrive.h"
@ -142,7 +140,7 @@ plAvBrainHuman::TurnCurve plAvBrainHuman::GetTurnCurve(hsBool walk)
plAvBrainHuman::plAvBrainHuman(bool isActor /* = false */) :
fHandleAGMod(nil),
fStartedTurning(-1.0f),
fCallbackAction(nil),
fWalkingStrategy(nil),
fPreconditions(0),
fIsActor(isActor)
{
@ -156,9 +154,9 @@ hsBool plAvBrainHuman::Apply(double timeNow, hsScalar elapsed)
#endif
// SetTurnStrength runs first to make sure it's set to a sane value
// (or cleared). RunStandardBehaviors may overwrite it.
fCallbackAction->SetTurnStrength(IGetTurnStrength(timeNow));
fWalkingStrategy->SetTurnStrength(IGetTurnStrength(timeNow));
RunStandardBehaviors(timeNow, elapsed);
fCallbackAction->RecalcVelocity(timeNow, timeNow - elapsed, (fPreconditions & plHBehavior::kBehaviorTypeNeedsRecalcMask));
fWalkingStrategy->RecalcVelocity(timeNow, elapsed, (fPreconditions & plHBehavior::kBehaviorTypeNeedsRecalcMask));
plArmatureBrain::Apply(timeNow, elapsed);
#ifndef _DEBUG
@ -179,13 +177,13 @@ void plAvBrainHuman::Activate(plArmatureModBase *avMod)
IInitBoneMap();
IInitAnimations();
if (!fCallbackAction)
if (!fWalkingStrategy)
{
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = avMod->GetController();
fCallbackAction = TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
controller->SetMovementStrategy(fWalkingStrategy);
}
@ -330,8 +328,8 @@ plAvBrainHuman::~plAvBrainHuman()
delete fBehaviors[i];
fBehaviors.Reset();
delete fCallbackAction;
fCallbackAction = nil;
delete fWalkingStrategy;
fWalkingStrategy = nil;
}
void plAvBrainHuman::Deactivate()
@ -364,7 +362,7 @@ void plAvBrainHuman::Resume()
if (fAvMod->GetInputFlag(S_PUSH_TO_TALK))
IChatOn();
fCallbackAction->Reset(false);
fWalkingStrategy->Reset(false);
plArmatureBrain::Resume();
}
@ -468,25 +466,23 @@ hsBool plAvBrainHuman::MsgReceive(plMessage * msg)
{
if(ride->Entering())
{
//plAvBrainRideAnimatedPhysical *rideBrain = TRACKED_NEW plAvBrainRideAnimatedPhysical();
//fAvMod->PushBrain(rideBrain);
delete fCallbackAction;
// Switch to dynamic walking strategy
delete fWalkingStrategy;
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = fAvMod->GetController();
fCallbackAction= TRACKED_NEW plRidingAnimatedPhysicalController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
fWalkingStrategy = TRACKED_NEW plDynamicWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
controller->SetMovementStrategy(fWalkingStrategy);
}
else
{
delete fCallbackAction;
// Restore default walking strategy
delete fWalkingStrategy;
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = fAvMod->GetController();
fCallbackAction= TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
//hsStatusMessage("Got an exiting ride animated physical message");
fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
controller->SetMovementStrategy(fWalkingStrategy);
}
}
@ -560,8 +556,8 @@ hsScalar plAvBrainHuman::IGetTurnStrength(double timeNow)
// Turning based on keypress
if ((turnLeftStrength > 0.f)
|| (turnRightStrength > 0.f)
|| (!fCallbackAction->IsOnGround()
&& !fCallbackAction->IsControlledFlight())
|| (!fWalkingStrategy->IsOnGround()
&& !fWalkingStrategy->IsControlledFlight())
) {
float t = (float)(timeNow - fStartedTurning);
float turnSpeed;
@ -593,7 +589,7 @@ hsScalar plAvBrainHuman::IGetTurnStrength(double timeNow)
result += fAvMod->GetKeyTurnStrength() * turnSpeed;
}
if (!fCallbackAction->IsControlledFlight())
if (!fWalkingStrategy->IsControlledFlight())
result += fAvMod->GetAnalogTurnStrength() * maxTurnSpeed;
return result;
@ -650,7 +646,7 @@ void plAvBrainHuman::ResetIdle()
void plAvBrainHuman::IdleOnly(bool instantOff)
{
if (!fCallbackAction)
if (!fWalkingStrategy)
return;
hsScalar rate = instantOff ? 0.f : 1.f;
@ -676,7 +672,7 @@ bool plAvBrainHuman::IsMovementZeroBlend()
void plAvBrainHuman::TurnToPoint(hsPoint3 point)
{
if (!fCallbackAction->IsOnGround() || IsRunningTask() || fAvMod->GetCurrentBrain() != this || !IsMovementZeroBlend())
if (!fWalkingStrategy->IsOnGround() || IsRunningTask() || fAvMod->GetCurrentBrain() != this || !IsMovementZeroBlend())
return;
hsPoint3 avPos;
@ -875,23 +871,23 @@ void plAvBrainHuman::Spawn(double timeNow)
hsBool plAvBrainHuman::LeaveAge()
{
plPhysicalControllerCore* controller = fAvMod->GetController();
if(!controller->BehavingLikeAnAnimatedPhysical())
// If our current walking strategy is dynamic, restore the default kinematic strategy.
if (!fWalkingStrategy->IsKinematic())
{
controller->BehaveLikeAnimatedPhysical(true);
delete fCallbackAction;
delete fWalkingStrategy;
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
fCallbackAction= TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
}
plArmatureBrain::LeaveAge();
fWalkingStrategy->Reset(true);
plArmatureBrain::LeaveAge();
// pin the physical so it doesn't fall when the world is deleted
fAvMod->EnablePhysics(false);
// this will get set to true when we hit ground
fCallbackAction->Reset(true);
return false;
}
@ -901,11 +897,10 @@ void plAvBrainHuman::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *st
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
const char *grounded = fCallbackAction->IsOnGround() ? "yes" : "no";
const char *falseGrounded = fCallbackAction->IsOnFalseGround() ? "yes" : "no";
const char *pushing = (fCallbackAction->GetPushingPhysical() ? (fCallbackAction->GetFacingPushingPhysical() ? "facing" : "behind") : "none");
sprintf(strBuf, "Ground: %3s, FalseGround: %3s, AirTime: %5.2f (Peak: %5.2f), PushingPhys: %6s",
grounded, falseGrounded, fCallbackAction->GetAirTime(), fCallbackAction->GetImpactTime(), pushing);
const char *grounded = fWalkingStrategy->IsOnGround() ? "yes" : "no";
const char *pushing = (fWalkingStrategy->GetPushingPhysical() ? (fWalkingStrategy->GetFacingPushingPhysical() ? "facing" : "behind") : "none");
sprintf(strBuf, "Ground: %3s, AirTime: %5.2f (Peak: %5.2f), PushingPhys: %6s",
grounded, fWalkingStrategy->GetAirTime(), fWalkingStrategy->GetImpactTime(), pushing);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
@ -1018,8 +1013,8 @@ hsBool Run::PreCondition(double time, float elapsed)
{
if (fAnim)
{
if (fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fHuBrain->fCallbackAction->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
if (fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true;
}
return false;
@ -1029,8 +1024,8 @@ hsBool Walk::PreCondition(double time, float elapsed)
{
if (fAnim)
{
if (fAvMod->ForwardKeyDown() && !fAvMod->FastKeyDown() && fHuBrain->fCallbackAction->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
if (fAvMod->ForwardKeyDown() && !fAvMod->FastKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true;
}
return false;
@ -1040,8 +1035,8 @@ hsBool WalkBack::PreCondition(double time, float elapsed)
{
if (fAnim)
{
if (fAvMod->BackwardKeyDown() && !fAvMod->ForwardKeyDown() && fHuBrain->fCallbackAction->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
if (fAvMod->BackwardKeyDown() && !fAvMod->ForwardKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true;
}
return false;
@ -1054,7 +1049,7 @@ hsBool StepLeft::PreCondition(double time, float elapsed)
return ((fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) &&
!(fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) &&
!(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
fHuBrain->fCallbackAction->IsOnGround());
fHuBrain->fWalkingStrategy->IsOnGround());
}
return false;
}
@ -1066,7 +1061,7 @@ hsBool StepRight::PreCondition(double time, float elapsed)
return ((fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) &&
!(fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) &&
!(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
fHuBrain->fCallbackAction->IsOnGround());
fHuBrain->fWalkingStrategy->IsOnGround());
}
return false;
}
@ -1107,8 +1102,8 @@ hsBool MovingTurnLeft::PreCondition(double time, float elapsed)
{
if (fAvMod->GetTurnStrength() > 0)
{
if (fHuBrain->fCallbackAction->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
if (fHuBrain->fWalkingStrategy->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true;
}
return false;
@ -1118,8 +1113,8 @@ hsBool MovingTurnRight::PreCondition(double time, float elapsed)
{
if (fAvMod->GetTurnStrength() < 0)
{
if (fHuBrain->fCallbackAction->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
if (fHuBrain->fWalkingStrategy->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true;
}
@ -1128,14 +1123,14 @@ hsBool MovingTurnRight::PreCondition(double time, float elapsed)
void Jump::IStart()
{
fHuBrain->fCallbackAction->EnableControlledFlight(true);
fHuBrain->fWalkingStrategy->EnableControlledFlight(true);
plHBehavior::IStart();
}
void Jump::IStop()
{
fHuBrain->fCallbackAction->EnableControlledFlight(false);
fHuBrain->fWalkingStrategy->EnableControlledFlight(false);
plHBehavior::IStop();
}
@ -1146,7 +1141,7 @@ hsBool StandingJump::PreCondition(double time, float elapsed)
{
if (GetStrength() > 0.f)
{
if (!fHuBrain->fCallbackAction->IsControlledFlight() ||
if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
{
return false;
@ -1158,7 +1153,7 @@ hsBool StandingJump::PreCondition(double time, float elapsed)
if (fAvMod->JumpKeyDown() &&
!fAvMod->ForwardKeyDown() &&
fAnim->GetBlend() == 0.0f &&
fHuBrain->fCallbackAction->IsOnGround())
fHuBrain->fWalkingStrategy->IsOnGround())
{
if (fAvMod->ConsumeJump())
return true;
@ -1174,7 +1169,7 @@ hsBool WalkingJump::PreCondition(double time, float elapsed)
{
if (GetStrength() > 0.f)
{
if (!fHuBrain->fCallbackAction->IsControlledFlight() ||
if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
{
return false;
@ -1187,8 +1182,8 @@ hsBool WalkingJump::PreCondition(double time, float elapsed)
!fAvMod->FastKeyDown() &&
fAvMod->ForwardKeyDown() &&
fAnim->GetBlend() == 0.0f &&
fHuBrain->fCallbackAction->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
{
if (fAvMod->ConsumeJump())
return true;
@ -1204,7 +1199,7 @@ hsBool RunningJump::PreCondition(double time, float elapsed)
{
if (GetStrength() > 0.f)
{
if (!fHuBrain->fCallbackAction->IsControlledFlight() ||
if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
{
return false;
@ -1217,8 +1212,8 @@ hsBool RunningJump::PreCondition(double time, float elapsed)
fAvMod->ForwardKeyDown() &&
fAvMod->FastKeyDown() &&
fAnim->GetBlend() == 0.0f &&
fHuBrain->fCallbackAction->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical()))
fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
{
if (fAvMod->ConsumeJump())
return true;
@ -1243,13 +1238,13 @@ hsBool RunningImpact::PreCondition(double time, float elapsed)
{
if (fDuration > 0.0f)
fDuration = fDuration - elapsed;
else if (fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->GetImpactTime() > kMinAirTime)
else if (fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->GetImpactTime() > kMinAirTime)
{
if (fHuBrain->fCallbackAction->GetImpactVelocity().fZ < -kMinImpactVel)
if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ < -kMinImpactVel)
{
if (fHuBrain->fCallbackAction->GetImpactVelocity().fY < kRunningImpactThresh)
if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fY < kRunningImpactThresh)
{
fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fCallbackAction->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel)));
fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel)));
if (fMaxBlend > 1)
fMaxBlend = 1;
fDuration = 1.0f / fFadeIn;
@ -1273,13 +1268,13 @@ hsBool GroundImpact::PreCondition(double time, float elapsed)
bool result = false;
if (fDuration > 0.0f)
fDuration = fDuration - elapsed;
else if (fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->GetImpactTime() > kMinAirTime)
else if (fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->GetImpactTime() > kMinAirTime)
{
if (fHuBrain->fCallbackAction->GetImpactVelocity().fZ < -kMinImpactVel)
if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ < -kMinImpactVel)
{
if (fHuBrain->fCallbackAction->GetImpactVelocity().fY >= kRunningImpactThresh)
if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fY >= kRunningImpactThresh)
{
fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fCallbackAction->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel)));
fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel)));
if (fMaxBlend > 1)
fMaxBlend = 1;
fDuration = 1.0f / fFadeIn;
@ -1298,7 +1293,7 @@ void GroundImpact::IStop()
hsBool Fall::PreCondition(double time, float elapsed)
{
return !fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->HitGroundInThisAge();
return !fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->HitGroundInThisAge();
}
void Fall::Process(double time, float elapsed)
@ -1310,7 +1305,7 @@ void Fall::Process(double time, float elapsed)
if (fAnim && fAnim->GetBlend() > 0.8)
{
float panicThresh = plAvBrainHuman::kAirTimePanicThreshold;
if (panicThresh > 0.0f && fHuBrain->fCallbackAction->GetAirTime() > panicThresh)
if (panicThresh > 0.0f && fHuBrain->fWalkingStrategy->GetAirTime() > panicThresh)
{
fHuBrain->IdleOnly(); // clear the fall state; we're going somewhere new
fAvMod->PanicLink();
@ -1327,7 +1322,7 @@ void Push::Process(double time, float elapsed)
fAvMod->GetPositionAndRotationSim(&pos, &rot);
hsPoint3 lookAt;
fHuBrain->fCallbackAction->GetPushingPhysical()->GetPositionSim(lookAt);
fHuBrain->fWalkingStrategy->GetPushingPhysical()->GetPositionSim(lookAt);
hsVector3 up(0.f, 0.f, 1.f);
hsScalar angle = hsATan2(lookAt.fY - pos.fY, lookAt.fX - pos.fX) + hsScalarPI / 2;
hsQuat targRot(angle, &up);
@ -1341,23 +1336,23 @@ void Push::Process(double time, float elapsed)
globFwd = rot.Rotate(&globFwd);
if (globFwd.fX < 0)
fHuBrain->fCallbackAction->SetTurnStrength(-turnSpeed);
fHuBrain->fWalkingStrategy->SetTurnStrength(-turnSpeed);
else
fHuBrain->fCallbackAction->SetTurnStrength(turnSpeed);
fHuBrain->fWalkingStrategy->SetTurnStrength(turnSpeed);
}
//hsBool PushIdle::PreCondition(double time, float elapsed)
//{
// return (fHuBrain->fCallbackAction->GetPushingPhysical() &&
// fHuBrain->fCallbackAction->IsOnGround() &&
// return (fHuBrain->fWalkingStrategy->GetPushingPhysical() &&
// fHuBrain->fWalkingStrategy->IsOnGround() &&
// !fAvMod->TurnLeftKeyDown() && !fAvMod->TurnRightKeyDown()
// && fAvMod->GetTurnStrength() == 0);
//}
hsBool PushWalk::PreCondition(double time, float elapsed)
{
return (fHuBrain->fCallbackAction->GetPushingPhysical() && fHuBrain->fCallbackAction->GetFacingPushingPhysical() &&
fHuBrain->fCallbackAction->IsOnGround() &&
return (fHuBrain->fWalkingStrategy->GetPushingPhysical() && fHuBrain->fWalkingStrategy->GetFacingPushingPhysical() &&
fHuBrain->fWalkingStrategy->IsOnGround() &&
fAvMod->ForwardKeyDown());
}
@ -1372,7 +1367,7 @@ bool PushSimpleMultiStage(plArmatureMod *avatar, const char *enterAnim, const ch
{
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(avatar->FindBrainByClass(plAvBrainHuman::Index()));
const char *names[3] = {enterAnim, idleAnim, exitAnim};
if (!huBrain || !huBrain->fCallbackAction->IsOnGround() || !huBrain->fCallbackAction->HitGroundInThisAge() || huBrain->IsRunningTask() ||
if (!huBrain || !huBrain->fWalkingStrategy->IsOnGround() || !huBrain->fWalkingStrategy->HitGroundInThisAge() || huBrain->IsRunningTask() ||
!avatar->IsPhysicsEnabled() || avatar->FindMatchingGenericBrain(names, 3))
return false;
@ -1436,7 +1431,7 @@ bool AvatarEmote(plArmatureMod *avatar, const char *emoteName)
if (swimBrain && swimBrain->IsSwimming())
return false;
if (huBrain && huBrain->fCallbackAction->IsOnGround() && huBrain->fCallbackAction->HitGroundInThisAge() && !huBrain->IsRunningTask() &&
if (huBrain && huBrain->fWalkingStrategy->IsOnGround() && huBrain->fWalkingStrategy->HitGroundInThisAge() && !huBrain->IsRunningTask() &&
emote && !alreadyActive && avatar->IsPhysicsEnabled())
{
plKey avKey = avatar->GetKey();

View File

@ -58,7 +58,7 @@ class plAGAnimInstance;
class plAvTask;
class plAvTaskMsg;
class plAvBrainHuman;
class plWalkingController;
class plWalkingStrategy;
class plArmatureUpdateMsg;
class plClimbMsg;
class plControlEventMsg;
@ -164,7 +164,7 @@ public:
static const hsScalar kControlledFlightThreshold;
static const hsScalar kAirTimeThreshold;
static const hsScalar kAirTimePanicThreshold;
plWalkingController* fCallbackAction;
plWalkingStrategy* fWalkingStrategy;
protected:
plAGAnim *FindCustomAnim(const char *baseName);

View File

@ -44,7 +44,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAvBrainHuman.h"
#include "plAvBrain.h"
#include "plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
#include "../plMessage/plRideAnimatedPhysMsg.h"
@ -52,20 +52,19 @@ void plAvBrainRideAnimatedPhysical::Activate(plArmatureModBase *avMod)
{
plArmatureBrain::Activate(avMod);
IInitAnimations();
if (!fCallbackAction)
if (!fWalkingStrategy)
{
plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = avMod->GetController();
fCallbackAction = TRACKED_NEW plRidingAnimatedPhysicalController(avObj, agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
fWalkingStrategy = TRACKED_NEW plDynamicWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
controller->SetMovementStrategy(fWalkingStrategy);
}
}
plAvBrainRideAnimatedPhysical::~plAvBrainRideAnimatedPhysical()
{
delete fCallbackAction;
fCallbackAction=nil;
delete fWalkingStrategy;
fWalkingStrategy = nil;
}
void plAvBrainRideAnimatedPhysical::Deactivate()

View File

@ -41,8 +41,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
#include "plAvBrainHuman.h"
class plRidingAnimatedPhysicalController;
class plAvBrainRideAnimatedPhysical : public plAvBrainHuman
{
public:

View File

@ -46,10 +46,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
//
/////////////////////////////////////////////////////////////////////////////////////////
//#include <hkmath/vector3.h>
//#include <hkdynamics/entity/rigidbody.h>
#include "plAntiGravAction.h" // descends from Havok class, so must be included first, like havok objects
// singular
#include "plAvBrainSwim.h"
@ -69,7 +65,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsTimer.h"
#include "plPhysical.h"
#include "plPhysicalControllerCore.h"
#include "plAvCallbackAction.h"
// other
#include "../plPhysical/plCollisionDetector.h"
#include "../plPipeline/plDebugText.h"
@ -180,18 +175,16 @@ public:
static const float timeToMaxTurn = 0.5f;
static const float incPerSec = maxTurnSpeed / timeToMaxTurn;
// hsAssert(0, "fixme physx");
float oldSpeed = fabs(fSwimBrain->fCallbackAction->GetTurnStrength());
float oldSpeed = fabs(fSwimBrain->fSwimStrategy->GetTurnStrength());
float thisInc = elapsed * incPerSec;
float newSpeed = __min(oldSpeed + thisInc, maxTurnSpeed);
fSwimBrain->fCallbackAction->SetTurnStrength(newSpeed * fAvMod->GetKeyTurnStrength() + fAvMod->GetAnalogTurnStrength());
fSwimBrain->fSwimStrategy->SetTurnStrength(newSpeed * fAvMod->GetKeyTurnStrength() + fAvMod->GetAnalogTurnStrength());
// the turn is actually applied during PhysicsUpdate
}
virtual void IStop()
{
// hsAssert(0, "fixme physx");
if (fSwimBrain->fCallbackAction)
fSwimBrain->fCallbackAction->SetTurnStrength(0.0f);
if (fSwimBrain->fSwimStrategy)
fSwimBrain->fSwimStrategy->SetTurnStrength(0.0f);
plSwimBehavior::IStop();
}
};
@ -237,7 +230,7 @@ public:
const hsScalar plAvBrainSwim::kMinSwimDepth = 4.0f;
plAvBrainSwim::plAvBrainSwim() :
fCallbackAction(nil),
fSwimStrategy(nil),
fMode(kWalking),
fSurfaceDistance(0.f)
{
@ -250,12 +243,9 @@ plAvBrainSwim::plAvBrainSwim() :
plAvBrainSwim::~plAvBrainSwim()
{
if(fCallbackAction)
{
IDetachAction();
delete fCallbackAction;
fCallbackAction=nil;
}
delete fSwimStrategy;
fSwimStrategy = nil;
fSurfaceProbeMsg->UnRef();
int i;
@ -273,8 +263,7 @@ hsBool plAvBrainSwim::Apply(double time, hsScalar elapsed)
fMode = kWading;
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(fAvMod->GetNextBrain(this));
// hsAssert(0, "fixme physx");
if (huBrain && !huBrain->fCallbackAction->IsOnGround())
if (huBrain && !huBrain->fWalkingStrategy->IsOnGround())
{
// We're jumping in! Trigger splash effect (sound)
plArmatureEffectMsg *msg = TRACKED_NEW plArmatureEffectMsg(fAvMod->GetArmatureEffects()->GetKey(), kTime);
@ -318,8 +307,7 @@ hsBool plAvBrainSwim::Apply(double time, hsScalar elapsed)
// The contact check is so that if buoyancy bobs us a little too high, we don't
// switch to wading only to fall again.
// hsAssert(0, "fixme physx");
if (fSurfaceDistance < kMinSwimDepth-.5 && fCallbackAction->HadContacts())
if (fSurfaceDistance < kMinSwimDepth-.5 && fSwimStrategy->HadContacts())
IStartWading();
}
else if (fMode == kSwimming3D)
@ -346,13 +334,12 @@ hsBool plAvBrainSwim::MsgReceive(plMessage *msg)
else
fSurfaceDistance = -100.f;
// hsAssert(0, "fixme physx");
if (fCallbackAction)
if (fSwimStrategy)
{
if (region)
fCallbackAction->SetSurface(region, fArmature->GetTarget(0)->GetLocalToWorld().GetTranslate().fZ + fSurfaceDistance);
fSwimStrategy->SetSurface(region, fArmature->GetTarget(0)->GetLocalToWorld().GetTranslate().fZ + fSurfaceDistance);
else
fCallbackAction->SetSurface(nil, 0.f);
fSwimStrategy->SetSurface(nil, 0.f);
}
return true;
}
@ -419,20 +406,16 @@ void plAvBrainSwim::Activate(plArmatureModBase* avMod)
void plAvBrainSwim::Deactivate()
{
plArmatureBrain::Deactivate();
IDetachAction();
}
void plAvBrainSwim::Suspend()
{
if (fMode == kSwimming2D)
IDetachAction();
}
void plAvBrainSwim::Resume()
{
if (fMode == kSwimming2D)
IAttachAction();
fSwimStrategy->Reset(false);
}
bool plAvBrainSwim::IsWalking()
@ -460,8 +443,6 @@ void plAvBrainSwim::IStartWading()
for (i = 0; i < fBehaviors.GetCount(); i++)
fBehaviors[i]->SetStrength(0.f, 2.f);
IDetachAction();
if (fAvMod->IsLocalAvatar())
{
plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
@ -479,7 +460,16 @@ void plAvBrainSwim::IStartSwimming(bool is2D)
plArmatureBrain *nextBrain = fAvMod->GetNextBrain(this);
nextBrain->Suspend();
IAttachAction();
if (!fSwimStrategy)
{
plSceneObject * avObj = fArmature->GetTarget(0);
plAGModifier *agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore *controller = fAvMod->GetController();
fSwimStrategy = new plSwimStrategy(agMod->GetApplicator(kAGPinTransform), controller);
}
fSwimStrategy->Reset(false);
if (is2D)
fMode = kSwimming2D;
else
@ -509,8 +499,8 @@ hsBool plAvBrainSwim::IProcessSwimming2D(double time, float elapsed)
else
behavior->SetStrength(0.f, 2.f);
}
// hsAssert(0, "fixme physx");
fCallbackAction->RecalcVelocity(time, time - elapsed);
fSwimStrategy->RecalcVelocity(time, elapsed);
return true;
}
@ -568,59 +558,6 @@ hsBool plAvBrainSwim::IInitAnimations()
return true;
}
bool plAvBrainSwim::IAttachAction()
{
bool result = false;
if(fAvMod)
{
// hsAssert(0, "fixme physx");
plPhysicalControllerCore *physical = fAvMod->GetController();
if (physical)
{
if (!fCallbackAction)
{
plSceneObject * avObj = fArmature->GetTarget(0);
plAGModifier *agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
fCallbackAction = new plSwimmingController(avObj, agMod->GetApplicator(kAGPinTransform),physical);
// physical->AttachAction(fCallbackAction, true, false);
result = true;
}
else
{
fCallbackAction->ActivateController();
}
}
}
return result;
}
bool plAvBrainSwim::IDetachAction()
{
bool result = false;
if (fCallbackAction)
{
// hsAssert(0, "fixme physx");
// plPhysical *physical = fAvMod->GetPhysical();
//
// if(physical)
// {
// physical->RemoveAction(fCallbackAction);
// result = true; // there was an action and we removed it
// }
// TODO: We get a compiler warning about deleting a pointer to an
// undefined class. So, who knows what the code is actually doing.
// Seems bad. Just putting a note in here for whoever fixes the
// physx issue.
//delete fCallbackAction;
//fCallbackAction = nil;
}
return result;
}
void plAvBrainSwim::IProbeSurface()
{
hsPoint3 ourPos = fAvMod->GetTarget(0)->GetLocalToWorld().GetTranslate();
@ -676,21 +613,15 @@ void plAvBrainSwim::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *str
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
float buoy = fSwimStrategy ? fSwimStrategy->GetBuoyancy() : 0.0f;
sprintf(strBuf, "Distance to surface: %f Buoyancy: %f", fSurfaceDistance, buoy);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
// hsAssert(0, "fixme physx");
// float buoy = fCallbackAction? fCallbackAction->GetBuoyancy() : 0.0f;
// sprintf(strBuf, "Distance to surface: %f Buoyancy: %f", fSurfaceDistance, buoy);
// debugTxt.DrawString(x, y, strBuf);
// y += lineHeight;
//
// hsVector3 linV;
// fAvMod->GetPhysical()->GetLinearVelocitySim(linV);
// hsVector3 angV;
// fAvMod->GetPhysical()->GetAngularVelocitySim(angV);
// hsScalar angle = angV.fZ > 0 ? angV.Magnitude() : -angV.Magnitude();
// sprintf(strBuf, "Velocity: Linear (%5.2f, %5.2f, %5.2f), Angular %5.2f", linV.fX, linV.fY, linV.fZ, angle);
// debugTxt.DrawString(x, y, strBuf);
// y += lineHeight;
hsVector3 linV = fAvMod->GetController()->GetAchievedLinearVelocity();
sprintf(strBuf, "Linear Velocity: (%5.2f, %5.2f, %5.2f)", linV.fX, linV.fY, linV.fZ);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
int i;
for (i = 0; i < fBehaviors.GetCount(); i++)

View File

@ -47,11 +47,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../pnKeyedObject/plKey.h"
class plArmatureMod;
class plAntiGravAction;
class plControlEventMsg;
class plLOSRequestMsg;
class plSwimRegionInterface;
class plSwimmingController;
class plSwimStrategy;
class plAvBrainSwim : public plArmatureBrain
{
public:
@ -73,7 +72,7 @@ public:
bool IsSwimming();
hsScalar GetSurfaceDistance() { return fSurfaceDistance; }
plSwimmingController *fCallbackAction;
plSwimStrategy *fSwimStrategy;
static const hsScalar kMinSwimDepth;
protected:
@ -86,8 +85,6 @@ protected:
hsBool IProcessBehaviors(double time, float elapsed);
virtual hsBool IInitAnimations();
bool IAttachAction();
bool IDetachAction();
void IProbeSurface();
hsBool IHandleControlMsg(plControlEventMsg* msg);
float IGetTargetZ();

View File

@ -1,579 +0,0 @@
/*==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 "plAvCallbackAction.h"
#include "../plMessage/plLOSHitMsg.h"
#include "plArmatureMod.h" // for LOS enum type
#include "plMatrixChannel.h"
#include "hsTimer.h"
#include "plPhysicalControllerCore.h"
// Generic geom utils.
hsBool LinearVelocity(hsVector3 &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
void AngularVelocity(hsScalar &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
float AngleRad2d (float x1, float y1, float x3, float y3);
inline hsVector3 GetYAxis(hsMatrix44 &mat)
{
return hsVector3(mat.fMap[1][0], mat.fMap[1][1], mat.fMap[1][2]);
}
plAnimatedController::plAnimatedController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
: fRootObject(rootObject)
, fRootApp(rootApp)
, fController(controller)
, fTurnStr(0.f)
, fAnimAngVel(0.f)
, fAnimPosVel(0.f, 0.f, 0.f)
{
}
void plAnimatedController::RecalcVelocity(double timeNow, double timePrev, hsBool useAnim /* = true */)
{
if (useAnim)
{
// while you may think it would be correct to cache this,
// what we're actually asking is "what would the animation's
// position be at the previous time given its *current*
// parameters (particularly blends)"
hsMatrix44 prevMat = ((plMatrixChannel *)fRootApp->GetChannel())->Value(timePrev, true);
hsMatrix44 curMat = ((plMatrixChannel *)fRootApp->GetChannel())->Value(timeNow, true);
// If we get a valid linear velocity (ie, we didn't wrap around in the anim),
// use it. Otherwise just reuse the previous frames velocity.
hsVector3 linearVel;
if (LinearVelocity(linearVel, (float)(timeNow - timePrev), prevMat, curMat))
fAnimPosVel = linearVel;
// Automatically sets fAnimAngVel
AngularVelocity(fAnimAngVel, (float)(timeNow - timePrev), prevMat, curMat);
}
else
{
fAnimPosVel.Set(0.f, 0.f, 0.f);
fAnimAngVel = 0.f;
}
if (fController)
fController->SetVelocities(fAnimPosVel, fAnimAngVel + fTurnStr);
}
///////////////////////////////////////////////////////////////////////////
const hsScalar plWalkingController::kControlledFlightThreshold = 1.f; // seconds
plWalkingController::plWalkingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
: plAnimatedController(rootObject, rootApp, controller)
, fHitGroundInThisAge(false)
, fWaitingForGround(false)
, fControlledFlightTime(0)
, fControlledFlight(0)
, fImpactTime(0.f)
, fImpactVelocity(0.f, 0.f, 0.f)
, fClearImpact(false)
, fGroundLastFrame(false)
{
if (fController)
{
fWalkingStrategy= TRACKED_NEW plWalkingStrategy(fController);
fController->SetMovementSimulationInterface(fWalkingStrategy);
}
else
fWalkingStrategy = nil;
}
void plWalkingController::RecalcVelocity(double timeNow, double timePrev, hsBool useAnim)
{
if (!fHitGroundInThisAge && fController && fController->IsEnabled() && fWalkingStrategy->IsOnGround())
fHitGroundInThisAge = true; // if we're not pinned and we're not in an age yet, we are now.
if (fClearImpact)
{
fImpactTime = 0.f;
fImpactVelocity.Set(0.f, 0.f, 0.f);
}
if (fController && !fWalkingStrategy->IsOnGround())
{
// PhysX Hack
// LinearVelocity is always (0,0,0) outside the PhysController
fImpactTime = fWalkingStrategy->GetAirTime();
fImpactVelocity = fController->GetAchievedLinearVelocity();
// convert orientation from subworld to avatar-local coordinates
fImpactVelocity = (hsVector3)fController->GetLocalRotation().Rotate(&fImpactVelocity);
fClearImpact = false;
}
else
fClearImpact = true;
if (IsControlledFlight())
{
if (fWalkingStrategy && fWalkingStrategy->IsOnGround())
fControlledFlightTime = fWalkingStrategy->GetAirTime();
if(fGroundLastFrame&&(fWalkingStrategy && !fWalkingStrategy->IsOnGround()))
{
//we have started to leave the ground tell the movement strategy in case it cares
fWalkingStrategy->StartJump();
}
if (fControlledFlightTime > kControlledFlightThreshold)
EnableControlledFlight(false);
}
if (fWalkingStrategy)
fGroundLastFrame = fWalkingStrategy->IsOnGround();
else
fGroundLastFrame=false;
plAnimatedController::RecalcVelocity(timeNow, timePrev, useAnim);
}
void plWalkingController::Reset(bool newAge)
{
ActivateController();
if (newAge)
{
if (fWalkingStrategy)
fWalkingStrategy->ResetAirTime();
fHitGroundInThisAge = false;
}
}
void plWalkingController::ActivateController()
{
if (fWalkingStrategy)
{
fWalkingStrategy->RefreshConnectionToControllerCore();
}
else
{
fWalkingStrategy= TRACKED_NEW plWalkingStrategy(fController);
fWalkingStrategy->RefreshConnectionToControllerCore();
}
}
bool plWalkingController::EnableControlledFlight(bool status)
{
if (status)
{
if (fControlledFlight == 0)
fControlledFlightTime = 0.f;
++fControlledFlight;
fWaitingForGround = true;
}
else
fControlledFlight = __max(--fControlledFlight, 0);
return status;
}
plWalkingController::~plWalkingController()
{
delete fWalkingStrategy;
if (fController)
fController->SetMovementSimulationInterface(nil);
}
#if 0
void plWalkingController::Update()
{
// double elapsed = time.asDouble() - getRefresh().asDouble();
// setRefresh(time);
//
// hsBool isPhysical = !fPhysical->GetProperty(plSimulationInterface::kPinned);
// const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f);
// hsBool alreadyInAge = fHitGroundInThisAge;
//
// int numContacts = fPhysical->GetNumContacts();
// bool ground = false;
// fPushingPhysical = nil;
// int i, j;
/* for(i = 0; i < numContacts; i++)
{
plHKPhysical *contactPhys = fPhysical->GetContactPhysical(i);
if (!contactPhys)
continue; // Physical no longer exists. Skip it.
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
hsScalar dotUp = straightUp.dot(contact->m_normal);
if (dotUp > .5)
ground = true;
else if (contactPhys->GetProperty(plSimulationInterface::kAvAnimPushable))
{
hsPoint3 position;
hsQuat rotation;
fPhysical->GetPositionAndRotationSim(&position, &rotation);
hsQuat inverseRotation = rotation.Inverse();
hsVector3 normal(contact->m_normal.x, contact->m_normal.y, contact->m_normal.z);
fFacingPushingPhysical = (inverseRotation.Rotate(&kAvatarForward).InnerProduct(normal) < 0 ? true : false);
fPushingPhysical = contactPhys;
}
}
// We need to check for the case where the avatar hasn't collided with "ground", but is colliding
// with a few other objects so that he's not actually falling (wedged in between some slopes).
// We do this by answering the following question (in 2d top-down space): "If you sort the contact
// normals by angle, is there a large enough gap between normals?"
//
// If you think in terms of geometry, this means a collection of surfaces are all pushing on you.
// If they're pushing from all sides, you have nowhere to go, and you won't fall. There needs to be
// a gap, so that you're pushed out and have somewhere to fall. This is the same as finding a gap
// larger than 180 degrees between sorted normals.
//
// The problem is that on top of that, the avatar needs enough force to shove him out that gap (he
// has to overcome friction). I deal with that by making the threshold (360 - (180 - 60) = 240). I've
// seen up to 220 reached in actual gameplay in a situation where we'd want this to take effect.
// This is the same running into 2 walls where the angle between them is 60.
const hsScalar threshold = hsScalarDegToRad(240);
if (!ground && numContacts >= 2)
{
// Can probably do a special case for exactly 2 contacts. Not sure if it's worth it...
fCollisionAngles.SetCount(numContacts);
for (i = 0; i < numContacts; i++)
{
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
fCollisionAngles[i] = hsATan2(contact->m_normal.y, contact->m_normal.x);
}
// numContacts is rarely larger than 6, so let's do a simple bubble sort.
for (i = 0; i < numContacts; i++)
{
for (j = i + 1; j < numContacts; j++)
{
if (fCollisionAngles[i] > fCollisionAngles[j])
{
hsScalar tempAngle = fCollisionAngles[i];
fCollisionAngles[i] = fCollisionAngles[j];
fCollisionAngles[j] = tempAngle;
}
}
}
// sorted, now we check.
for (i = 1; i < numContacts; i++)
{
if (fCollisionAngles[i] - fCollisionAngles[i - 1] >= threshold)
break;
}
if (i == numContacts)
{
// We got to the end. Check the last with the first and make your decision.
if (!(fCollisionAngles[0] - fCollisionAngles[numContacts - 1] >= (threshold - 2 * hsScalarPI)))
ground = true;
}
}
*/
bool ground = fController ? fController->GotGroundHit() : true;
bool isPhysical = true;
if (!fHitGroundInThisAge && isPhysical)
fHitGroundInThisAge = true; // if we're not pinned and we're not in an age yet, we are now.
if (IsControlledFlight())
fControlledFlightTime += (hsScalar)elapsed;
if (fControlledFlightTime > kControlledFlightThreshold && numContacts > 0)
EnableControlledFlight(false);
if (ground || !isPhysical)
{
if (!IsControlledFlight() && !IsOnGround())
{
// The first ground contact in an age doesn't count.
// if (alreadyInAge)
// {
// hsVector3 vel;
// fPhysical->GetLinearVelocitySim(vel);
// fImpactVel = vel.fZ;
// fTimeInAirPeak = (hsScalar)(fTimeInAir + elapsed);
// }
fWaitingForGround = false;
}
fTimeInAir = 0;
}
else if (elapsed < plSimulationMgr::GetInstance()->GetMaxDelta())
{
// If the simultation skipped a huge chunk of time, we didn't process the
// collisions, which could trick us into thinking we've just gone a long
// time without hitting ground. So we only count the time if this wasn't
// the case.
fTimeInAir += (hsScalar)elapsed;
}
// Tweakage so that we still fall under the right conditions.
// If we're in controlled flight, or standing still with ground solidly under us (probe hit). We only use anim velocity.
// if (!IsControlledFlight() && !(ground && fProbeHitGround && fAnimPosVel.fX == 0 && fAnimPosVel.fY == 0))
// {
// hsVector3 curV;
// fPhysical->GetLinearVelocitySim(curV);
// fAnimPosVel.fZ = curV.fZ;
//
// // Prevents us from going airborn from running up bumps/inclines.
// if (IsOnGround() && fAnimPosVel.fZ > 0.f)
// fAnimPosVel.fZ = 0.f;
//
// // Unless we're on the ground and moving, or standing still with a probe hit, we use the sim's other axes too.
// if (!(IsOnGround() && (fProbeHitGround || fAnimPosVel.fX != 0 || fAnimPosVel.fY != 0)))
// {
// fAnimPosVel.fX = curV.fX;
// fAnimPosVel.fY = curV.fY;
// }
// }
//
// fPhysical->SetLinearVelocitySim(fAnimPosVel);
// fPhysical->SetSpin(fAnimAngVel + fTurnStr, hsVector3(0.0f, 0.0f, 1.0f));
}
#endif
#if 0
/////////////////////////////////////////////////////////////////////////
plSimDefs::ActionType plHorizontalFreezeAction::GetType()
{
return plSimDefs::kHorizontalFreeze;
}
void plHorizontalFreezeAction::apply(Havok::Subspace &s, Havok::hkTime time)
{
double elapsed = time.asDouble() - getRefresh().asDouble();
setRefresh(time);
int numContacts = fPhysical->GetNumContacts();
bool ground = false;
const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f);
int i;
for(i = 0; i < numContacts; i++)
{
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
hsScalar dotUp = straightUp.dot(contact->m_normal);
if (dotUp > .5)
ground = true;
}
hsVector3 vel;
fPhysical->GetLinearVelocitySim(vel);
vel.fX = 0.0;
vel.fY = 0.0;
if (ground)
vel.fZ = 0;
fPhysical->SetLinearVelocitySim(vel);
fPhysical->ClearContacts();
}
#endif
plSwimmingController::plSwimmingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
:plAnimatedController(rootObject,rootApp,controller)
{
if (controller)
fSwimmingStrategy= TRACKED_NEW plSwimStrategy(controller);
else
fSwimmingStrategy = nil;
}
plSwimmingController::~plSwimmingController()
{
delete fSwimmingStrategy;
}
plRidingAnimatedPhysicalController::plRidingAnimatedPhysicalController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
: plWalkingController(rootObject, rootApp, controller)
{
if(controller)
fWalkingStrategy = TRACKED_NEW plRidingAnimatedPhysicalStrategy(controller);
else
fWalkingStrategy = nil;
}
plRidingAnimatedPhysicalController::~plRidingAnimatedPhysicalController()
{
delete fWalkingStrategy;
fWalkingStrategy=nil;
}
//////////////////////////////////////////////////////////////////////////
/*
Purpose:
ANGLE_RAD_2D returns the angle in radians swept out between two rays in 2D.
Discussion:
Except for the zero angle case, it should be true that
ANGLE_RAD_2D(X1,Y1,X2,Y2,X3,Y3)
+ ANGLE_RAD_2D(X3,Y3,X2,Y2,X1,Y1) = 2 * PI
Modified:
19 April 1999
Author:
John Burkardt
Parameters:
Input, float X1, Y1, X2, Y2, X3, Y3, define the rays
( X1-X2, Y1-Y2 ) and ( X3-X2, Y3-Y2 ) which in turn define the
angle, counterclockwise from ( X1-X2, Y1-Y2 ).
Output, float ANGLE_RAD_2D, the angle swept out by the rays, measured
in radians. 0 <= ANGLE_DEG_2D < 2 PI. If either ray has zero length,
then ANGLE_RAD_2D is set to 0.
*/
static float AngleRad2d ( float x1, float y1, float x3, float y3 )
{
float value;
float x;
float y;
x = ( x1 ) * ( x3 ) + ( y1 ) * ( y3 );
y = ( x1 ) * ( y3 ) - ( y1 ) * ( x3 );
if ( x == 0.0 && y == 0.0 ) {
value = 0.0;
}
else
{
value = atan2 ( y, x );
if ( value < 0.0 )
{
value = (float)(value + TWO_PI);
}
}
return value;
}
static hsBool LinearVelocity(hsVector3 &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat)
{
bool result = false;
hsPoint3 startPos(0.0f, 0.0f, 0.0f); // default position (at start of anim)
hsPoint3 prevPos = prevMat.GetTranslate(); // position previous frame
hsPoint3 nowPos = curMat.GetTranslate(); // position current frame
hsVector3 prev2Now = (hsVector3)(nowPos - prevPos); // frame-to-frame delta
if (fabs(prev2Now.fX) < 0.0001f && fabs(prev2Now.fY) < 0.0001f && fabs(prev2Now.fZ) < 0.0001f)
{
outputV.Set(0.f, 0.f, 0.f);
result = true;
}
else
{
hsVector3 start2Now = (hsVector3)(nowPos - startPos); // start-to-frame delta
float prev2NowMagSqr = prev2Now.MagnitudeSquared();
float start2NowMagSqr = start2Now.MagnitudeSquared();
float dot = prev2Now.InnerProduct(start2Now);
// HANDLING ANIMATION WRAPPING:
// the vector from the animation origin to the current frame should point in roughly
// the same direction as the vector from the previous animation position to the
// current animation position.
//
// If they don't agree (dot < 0,) then we probably mpst wrapped around.
// The right answer would be to compare the current frame to the start of
// the anim loop, but it's cheaper to cheat and return false,
// telling the caller to use the previous frame's velocity.
if (dot > 0.0f)
{
prev2Now /= elapsed;
float xfabs = fabs(prev2Now.fX);
float yfabs = fabs(prev2Now.fY);
float zfabs = fabs(prev2Now.fZ);
static const float maxVel = 20.0f;
hsBool valid = xfabs < maxVel && yfabs < maxVel && zfabs < maxVel;
if (valid)
{
outputV = prev2Now;
result = true;
}
}
}
return result;
}
static void AngularVelocity(hsScalar &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat)
{
outputV = 0.f;
hsScalar appliedVelocity = 0.0f;
hsVector3 prevForward = GetYAxis(prevMat);
hsVector3 curForward = GetYAxis(curMat);
hsScalar angleSincePrev = AngleRad2d(curForward.fX, curForward.fY, prevForward.fX, prevForward.fY);
hsBool sincePrevSign = angleSincePrev > 0.0f;
if (angleSincePrev > hsScalarPI)
angleSincePrev = angleSincePrev - TWO_PI;
const hsVector3 startForward = hsVector3(0, -1.0, 0); // the Y orientation of a "resting" armature....
hsScalar angleSinceStart = AngleRad2d(curForward.fX, curForward.fY, startForward.fX, startForward.fY);
hsBool sinceStartSign = angleSinceStart > 0.0f;
if (angleSinceStart > hsScalarPI)
angleSinceStart = angleSinceStart - TWO_PI;
// HANDLING ANIMATION WRAPPING:
// under normal conditions, the angle from rest to the current frame will have the same
// sign as the angle from the previous frame to the current frame.
// if it does not, we have (most likely) wrapped the motivating animation from frame n back
// to frame zero, creating a large angle from the previous frame to the current one
if (sincePrevSign == sinceStartSign)
{
// signs are the same; didn't wrap; use the frame-to-frame angle difference
appliedVelocity = angleSincePrev / elapsed; // rotation / time
if (fabs(appliedVelocity) < 3)
{
outputV = appliedVelocity;
}
}
}

View File

@ -1,217 +0,0 @@
/*==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 PL_HK_CALLBACK_ACTION_H
#define PL_HK_CALLBACK_ACTION_H
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "hsTemplates.h"
#include "../pnKeyedObject/plKey.h"
#include "../plPhysical/plSimDefs.h"
#include "../pnMessage/plMessage.h"
#include "plPhysicalControllerCore.h"
class plLOSHitMsg;
class plAGApplicator;
class plSceneObject;
class plPhysical;
class plAvatarController;
class plCoordinateInterface;
class plPhysicalControllerCore;
// Used by the other controllers to actually move the avatar. The actual
// implementation is in the physics system.
/*class plPhysicalController
{
public:
// Implemented in the physics system. If you're linking this without that for
// some reason, just stub this function out.
//
// Pass in the key to the root sceneobject for the avatar
static plPhysicalController* Create(plKey ownerSO, hsScalar height, hsScalar width);
virtual ~plPhysicalController() {}
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
virtual void Enable(bool enable) = 0;
virtual bool IsEnabled() const = 0;
// Set the LOS DB this avatar will be in (only one)
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) = 0;
// Call this once per frame with the velocities of the avatar in avatar space.
virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel) = 0;
// Gets the actual velocity we achieved in the last step (relative to our subworld)
virtual const hsVector3& GetLinearVelocity() const = 0;
virtual void ResetAchievedLinearVelocity() = 0;
// Get and set the current subworld for the avatar. Use nil for the main world.
virtual plKey GetSubworld() const = 0;
virtual void SetSubworld(plKey world) = 0;
// If IsOnGround returns false, GetAirTime will tell you how long the avatar
// has been airborne. Use ResetAirTime to reset the air time to zero, for
// cases like when the avatar spawns into a new age.
virtual bool IsOnGround() const = 0;
virtual bool IsOnFalseGround() const = 0;
virtual hsScalar GetAirTime() const = 0;
virtual void ResetAirTime() = 0;
virtual plPhysical* GetPushingPhysical() const = 0;
virtual bool GetFacingPushingPhysical() const = 0;
// A helper function to get the coordinate interface for the avatars current
// world. Handy if you need to convert points to and from that. This will
// return nil if the avatar is in the main world (ie, you don't need to do
// any translation).
virtual const plCoordinateInterface* GetSubworldCI() const = 0;
// For the avatar SDL only
virtual void GetState(hsPoint3& pos, float& zRot) = 0;
virtual void SetState(const hsPoint3& pos, float zRot) = 0;
// kinematic stuff .... should be just for when playing a behavior...
virtual void Kinematic(bool state) = 0;
virtual bool IsKinematic() = 0;
virtual void GetKinematicPosition(hsPoint3& pos) = 0;
virtual const hsMatrix44& GetPrevSubworldW2L() = 0;
//when seeking no longer want to interact with exclusion regions
virtual void SetSeek(bool seek)=0;
};
*/
class plAvatarController
{
public:
virtual ~plAvatarController() {}
};
class plAnimatedController : public plAvatarController
{
public:
plAnimatedController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual void RecalcVelocity(double timeNow, double timePrev, hsBool useAnim = true);
void SetTurnStrength(hsScalar val) { fTurnStr = val; }
hsScalar GetTurnStrength() { return fTurnStr; }
virtual void ActivateController()=0;
protected:
plSceneObject* fRootObject;
plPhysicalControllerCore* fController;
plAGApplicator* fRootApp;
hsScalar fAnimAngVel;
hsVector3 fAnimPosVel;
hsScalar fTurnStr; // Explicit turning, separate from animations
};
class plWalkingController : public plAnimatedController
{
public:
plWalkingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plWalkingController();
virtual void RecalcVelocity(double timeNow, double timePrev, hsBool useAnim = true);
void Reset(bool newAge);
bool IsControlledFlight() const { return fControlledFlight != 0; }
bool IsOnGround() const { return fWalkingStrategy ? fWalkingStrategy->IsOnGround() : true; }
bool IsOnFalseGround() const { return fWalkingStrategy ? fWalkingStrategy->IsOnFalseGround() : true; }
bool HitGroundInThisAge() const { return fHitGroundInThisAge; }
bool EnableControlledFlight(bool status);
hsScalar GetAirTime() const { return fWalkingStrategy ? fWalkingStrategy->GetAirTime() : 0.f; }
void ResetAirTime() { if (fWalkingStrategy) fWalkingStrategy->ResetAirTime(); }
hsScalar GetForwardVelocity() const;
void ActivateController();
// Check these after the avatar the avatar hits the ground for his total
// hangtime and impact velocity.
hsScalar GetImpactTime() const { return fImpactTime; }
const hsVector3& GetImpactVelocity() const { return fImpactVelocity; }
plPhysical* GetPushingPhysical() const
{
if(fController)return fController->GetPushingPhysical();
else return nil;
}
bool GetFacingPushingPhysical() const
{ if(fController)return fController->GetFacingPushingPhysical();
else return false;
}
protected:
bool fHitGroundInThisAge;
bool fWaitingForGround; // We've gone airborne. IsOnGround() returns false until we hit ground again.
hsScalar fControlledFlightTime;
int fControlledFlight; // Count of how many are currently forcing flight
plWalkingStrategy* fWalkingStrategy;
hsScalar fImpactTime;
hsVector3 fImpactVelocity;
bool fClearImpact;
bool fGroundLastFrame;//used for a test to pass the event of first getting air during a jump
static const hsScalar kControlledFlightThreshold;
};
class plSwimmingController: public plAnimatedController
{
public :
plSwimmingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plSwimmingController();
void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight){
fSwimmingStrategy->SetSurface(region,surfaceHeight);
}
hsScalar GetBuoyancy() { return fSwimmingStrategy->GetBuoyancy(); }
hsBool IsOnGround() { return fSwimmingStrategy->IsOnGround(); }
hsBool HadContacts() { return fSwimmingStrategy->HadContacts();}
void Enable(bool en){if (fController) fController->Enable(en);}
plPhysicalControllerCore* GetController(){return fController;}
virtual void ActivateController(){fSwimmingStrategy->RefreshConnectionToControllerCore();}
protected:
plSwimStrategy* fSwimmingStrategy;
};
class plRidingAnimatedPhysicalController: public plWalkingController
{
public:
plRidingAnimatedPhysicalController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plRidingAnimatedPhysicalController();
};
#endif // PL_HK_CALLBACK_ACTION_H

View File

@ -39,7 +39,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include "../plAvatar/plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
#include "hsTypes.h"
@ -129,7 +129,7 @@ bool plAvLadderMod::IIsReadyToClimb()
if (armMod)
{
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(armMod->GetCurrentBrain());
if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround())
if (brain && brain->IsMovingForward() && brain->fWalkingStrategy->IsOnGround())
movingForward = true;
}

View File

@ -54,7 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAGAnim.h"
#include "plArmatureMod.h"
#include "plAvatarMgr.h"
#include "plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
// other
#include "../plMessage/plAvatarMsg.h"
@ -462,10 +462,10 @@ hsBool plAvTaskSeek::IFinishPosition(hsPoint3 &newPosition,
{
// While warping, we might be hovering just above the ground. Don't want that to
// trigger any falling behavior.
if(brain&&brain->fCallbackAction)
if(brain&&brain->fWalkingStrategy)
{
brain->fCallbackAction->ResetAirTime();
brain->fWalkingStrategy->ResetAirTime();
}
// how far will we translate this frame?
float thisDist = kFloatSpeed * elapsed;

View File

@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plAvatar/plAvBrainClimb.h"
#include "../plAvatar/plAvBrainDrive.h"
#include "../plAvatar/plAnimStage.h"
#include "../plAvatar/plAvCallbackAction.h"
#include "../plAvatar/plPhysicalControllerCore.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnMessage/plSDLModifierMsg.h"
#include "../plSDL/plSDL.h"

View File

@ -53,7 +53,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAGAnimInstance.h"
#include "plAGModifier.h"
#include "plMatrixChannel.h"
#include "plAvCallbackAction.h"
#include "plPhysicalControllerCore.h"
#include "plAvatarMgr.h"
// global
@ -440,7 +440,7 @@ hsBool plAvAnimTask::Start(plArmatureMod *avatar, plArmatureBrain *brain, double
}
// PROCESS
plAvAnimTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
hsBool plAvAnimTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
{
// the only reason we need this function is to watch the animation until it fades out
hsBool result = false;
@ -664,7 +664,7 @@ hsBool plAvOneShotTask::Start(plArmatureMod *avatar, plArmatureBrain *brain, dou
}
// PROCESS
plAvOneShotTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
hsBool plAvOneShotTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
{
// *** if we are under mouse control, adjust it here
@ -689,7 +689,7 @@ plAvOneShotTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, double t
if(fEnablePhysicsAtEnd)
{
#if 0//ndef PLASMA_EXTERNAL_RELEASE
if (!humanBrain || humanBrain->fCallbackAction->HitGroundInThisAge())
if (!humanBrain || humanBrain->fWalkingStrategy->HitGroundInThisAge())
{
// For some reason, calling CheckValidPosition at the beginning of
// an age can cause detectors to incorrectly report collisions. So

View File

@ -250,7 +250,7 @@ plMatrixTimeScale::~plMatrixTimeScale()
// IsStoppedAt ----------------------------
// ------------
plMatrixTimeScale::IsStoppedAt(double time)
hsBool plMatrixTimeScale::IsStoppedAt(double time)
{
return fTimeSource->IsStoppedAt(time);
}

View File

@ -41,310 +41,286 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
#ifndef PLPHYSICALCONTROLLERCORE_H
#define PLPHYSICALCONTROLLERCORE_H
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "hsQuat.h"
#include "hsTemplates.h"
#include "../pnKeyedObject/plKey.h"
#include "../plPhysical/plSimDefs.h"
#include "../pnMessage/plMessage.h"
#include "hsQuat.h"
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
#define kSLOPELIMIT (cosf(hsScalarDegToRad(55.f)))
#include <vector>
class plCoordinateInterface;
class plPhysical;
class plPXPhysical;
class plMovementStrategy;
class plAGApplicator;
class plSwimRegionInterface;
//Replacement for for plPhysicalController stripped out some walk specific code
//plPhysicalControllerCore needs to have movement strategies registered to it these will then
//be called by the controller during the simulation steps. The Strategies need to at least have an
// Apply and Update definition. Everything else should be movement specific. I hope to come back and
//and refactor when I have time this in the future.
#define kSlopeLimit (cosf(hsScalarDegToRad(55.f)))
enum plControllerCollisionFlags
{
kSides=1,
kTop= (1<<1),
kBottom=(1<<2),
{
kSides = 1,
kTop = (1 << 1),
kBottom = (1 << 2)
};
class plMovementStrategySimulationInterface
struct plControllerSweepRecord
{
public:
virtual void Apply(hsScalar delSecs)=0;
virtual void Update(hsScalar delSecs)=0;
//most strategies don't require this. Only the ones that require behavior like a physical or need
//something after the sim step. this used to be taken care of by Update, but this was moved to take care of
//some of the frame lag
virtual void PostStep(hsScalar delSecs){};
virtual void IAddContactNormals(hsVector3& vec){fContactNormals.Append(vec);}
virtual void AddOnTopOfObject(plPhysical* phys){ fOnTopOf.Append(phys);}
virtual void LeaveAge()
{
fContactNormals.SetCount(0);
fOnTopOf.SetCount(0);
}
protected:
hsTArray<hsVector3> fContactNormals;
hsTArray<plPhysical* > fOnTopOf;
};
class plControllerSweepRecord
{
public:
plPhysical *ObjHit;
hsPoint3 locHit;//World space
hsScalar TimeHit;//Normalized between 0 and 1
hsVector3 Norm;
hsPoint3 Point;
hsVector3 Normal;
};
bool operator<(const plControllerSweepRecord left, const plControllerSweepRecord right);
class plPhysicalControllerCore
{
public:
virtual ~plPhysicalControllerCore();
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults)=0;
virtual void SetMovementSimulationInterface(plMovementStrategySimulationInterface* strat){fMovementInterface=strat;}
virtual void Apply(hsScalar delSecs);
virtual void Update(hsScalar delSecs);
virtual void PostStep(hsScalar delSecs);
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
plPhysicalControllerCore(plKey ownerSceneObject, hsScalar height, hsScalar radius);
virtual ~plPhysicalControllerCore() { }
// An ArmatureMod has its own idea about when physics should be enabled/disabled.
// Use plArmatureModBase::EnablePhysics() instead.
virtual void Enable(bool enable) = 0;
virtual bool IsEnabled() {return fEnabled;}
virtual plKey GetSubworld() {return fWorldKey;}
virtual bool IsEnabled() { return fEnabled; }
// Subworld
virtual plKey GetSubworld() { return fWorldKey; }
virtual void SetSubworld(plKey world) = 0;
virtual const plCoordinateInterface* GetSubworldCI() const = 0;
virtual const plCoordinateInterface* GetSubworldCI();
// For the avatar SDL only
virtual void GetState(hsPoint3& pos, float& zRot) = 0;
virtual void SetState(const hsPoint3& pos, float zRot) = 0;
// kinematic stuff .... should be just for when playing a behavior...
virtual void Kinematic(bool state) = 0;
virtual bool IsKinematic() = 0;
virtual void GetKinematicPosition(hsPoint3& pos) = 0;
virtual const hsMatrix44& GetPrevSubworldW2L() = 0;
//when seeking no longer want to interact with exclusion regions
virtual void SetSeek(bool seek){fSeeking=seek;}
virtual bool IsSeeking(){return fSeeking;}
static plPhysicalControllerCore* Create(plKey ownerSO, hsScalar height, hsScalar radius);
virtual plMovementStrategySimulationInterface* GetMovementInterface(){return fMovementInterface;}
plPhysicalControllerCore(plKey ownerSceneObject, hsScalar height, hsScalar radius);
virtual plKey GetOwner(){return fOwner;};
// Set the LOS DB this avatar will be in (only one)
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; } ;
virtual plSimDefs::plLOSDB GetLOSDB() {return fLOSDB ; }
virtual const hsMatrix44& GetLastGlobalLoc()=0;
virtual void SetKinematicLoc(const hsMatrix44& l2w)=0;
virtual void SetGlobalLoc(const hsMatrix44& l2w)=0;
virtual bool IsEnabledChanged(){return fEnableChanged;}
virtual void HandleEnableChanged()=0;
virtual bool IsKinematicChanged(){return fKinematicChanged;}
virtual void GetPositionSim(hsPoint3& pos)=0;
virtual void HandleKinematicChanged()=0;
virtual bool IsKinematicEnableNextUpdate(){return fKinematicEnableNextUpdate;}
virtual void HandleKinematicEnableNextUpdate()=0;
virtual void MoveKinematicToController(hsPoint3& pos)=0;
virtual void UpdateControllerAndPhysicalRep()=0;
virtual void CheckAndHandleAnyStateChanges();
virtual void UpdateSubstepNonPhysical();
virtual const hsPoint3& GetLocalPosition()=0;
const hsQuat& GetLocalRotation() { return fLocalRotation; }
virtual void MoveActorToSim();
virtual void OverrideAchievedVelocity(hsVector3 newAchievedVel)
{//because of things like superjumps this is needed I'd rather not, but can't help it
fAchievedLinearVelocity=newAchievedVel;
}
//any clean up for the controller should go here
virtual void LeaveAge()=0;
hsVector3 DisplacementLastStep(){return fDisplacementThisStep;}
hsVector3 MeanVelocityForLastStep()
{
hsVector3 vel=fDisplacementThisStep;
return vel/fSimLength;
}
void SendCorrectionMessages();
// The LOS DB this avatar is in (only one)
virtual plSimDefs::plLOSDB GetLOSDB() { return fLOSDB; }
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; }
// Movement strategy
virtual void SetMovementStrategy(plMovementStrategy* strategy) = 0;
// Global location
virtual const hsMatrix44& GetLastGlobalLoc() { return fLastGlobalLoc; }
virtual void SetGlobalLoc(const hsMatrix44& l2w) = 0;
// Local sim position
virtual void GetPositionSim(hsPoint3& pos) = 0;
// Move kinematic controller
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults) = 0;
// Set linear velocity on dynamic controller
virtual void SetLinearVelocitySim(const hsVector3& linearVel) = 0;
// Sweep the controller path from startPos through endPos
virtual int SweepControllerPath(const hsPoint3& startPos,const hsPoint3& endPos, hsBool vsDynamics, hsBool vsStatics,
UInt32& vsSimGroups, std::vector<plControllerSweepRecord>& hits) = 0;
// any clean up for the controller should go here
virtual void LeaveAge() = 0;
// Local rotation
const hsQuat& GetLocalRotation() const { return fLocalRotation; }
void IncrementAngle(hsScalar deltaAngle);
void UpdateWorldRelativePos();
virtual void SetLinearVelocity(const hsVector3& linearVel){fLinearVelocity=linearVel;}
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
virtual void SetAngularVelocity(const hsScalar angvel){ fAngularVelocity=angvel;}
virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel)
{
fLinearVelocity=linearVel;
fAngularVelocity=angVel;
}
virtual const hsVector3& GetLinearVelocity() ;
virtual hsScalar GetAngularVelocity(){return fAngularVelocity;}
virtual const hsVector3& GetAchievedLinearVelocity()const {return fAchievedLinearVelocity;}
plPhysical* GetPushingPhysical();
bool GetFacingPushingPhysical();
virtual void SetPushingPhysical(plPhysical* pl){fPushingPhysical=pl;}
virtual void SetFacingPushingPhysical(bool ans){fFacingPushingPhysical=ans;}
//To be Used during runtime conversions, say to switch a tall controller to a ball for swimming
virtual void SetControllerDimensions(hsScalar radius, hsScalar height)=0;
virtual hsScalar GetControllerWidth(){return fRadius;}
virtual hsScalar GetControllerHeight(){return fHeight;}
virtual void ResetAchievedLinearVelocity()
{
fAchievedLinearVelocity.Set(0.f,0.f,0.f);
}
virtual int SweepControllerPath(const hsPoint3& startPos,const hsPoint3& endPos, hsBool vsDynamics, hsBool vsStatics, UInt32& vsSimGroups, std::multiset< plControllerSweepRecord >& WhatWasHitOut)=0;
//this should only be used to force a move it could place your head into a wall and that would be good
virtual hsScalar GetHeight() {return fHeight;}
virtual hsScalar GetRadius() {return fRadius;}
//Wether the avatar thing has mass and forces things down or not, and changes the way things move
//This is an attempt fix things like riding on an animated physical
virtual void BehaveLikeAnimatedPhysical(hsBool actLikeAnAnimatedPhys)=0;
virtual hsBool BehavingLikeAnAnimatedPhysical()=0;
// Linear velocity
void SetLinearVelocity(const hsVector3& linearVel) { fLinearVelocity = linearVel; }
const hsVector3& GetLinearVelocity() const { return fLinearVelocity; }
// Acheived linear velocity
const hsVector3& GetAchievedLinearVelocity() const { return fAchievedLinearVelocity; }
void OverrideAchievedLinearVelocity(const hsVector3& linearVel) { fAchievedLinearVelocity = linearVel; }
void ResetAchievedLinearVelocity() { fAchievedLinearVelocity.Set(0.f, 0.f, 0.f); }
// SceneObject
plKey GetOwner() { return fOwner; }
// When seeking no longer want to interact with exclude regions
void SetSeek(bool seek) { fSeeking = seek; }
bool IsSeeking() const { return fSeeking; }
// Pushing physical
plPhysical* GetPushingPhysical() const { return fPushingPhysical; }
void SetPushingPhysical(plPhysical* phys) { fPushingPhysical = phys; }
bool GetFacingPushingPhysical() const { return fFacingPushingPhysical; }
void SetFacingPushingPhysical(bool facing) { fFacingPushingPhysical = facing; }
// Controller dimensions
hsScalar GetRadius() const { return fRadius; }
hsScalar GetHeight() const { return fHeight; }
// Create a new controller instance - Implemented in the physics system
static plPhysicalControllerCore* Create(plKey ownerSO, hsScalar height, hsScalar radius, bool human);
protected:
virtual void IHandleEnableChanged() = 0;
void IApply(hsScalar delSecs);
void IUpdate(int numSubSteps, hsScalar alpha);
void IUpdateNonPhysical(hsScalar alpha);
void ISendCorrectionMessages(bool dirtySynch = false);
plKey fOwner;
plKey fWorldKey;
hsScalar fHeight;
hsScalar fRadius;
plKey fWorldKey;
plSimDefs::plLOSDB fLOSDB;
bool fSeeking;
bool fEnabled;
bool fEnableChanged;
bool fKinematic;
bool fKinematicEnableNextUpdate;
bool fKinematicChanged;
plMovementStrategySimulationInterface* fMovementInterface;
hsMatrix44 fLastGlobalLoc;
hsPoint3 fLocalPosition;
hsQuat fLocalRotation;
hsMatrix44 fPrevSubworldW2L;
hsVector3 fDisplacementThisStep;
hsScalar fSimLength;
//physical properties
plSimDefs::plLOSDB fLOSDB;
plMovementStrategy* fMovementStrategy;
hsScalar fSimLength;
hsQuat fLocalRotation;
hsPoint3 fLocalPosition;
hsPoint3 fLastLocalPosition;
hsMatrix44 fLastGlobalLoc;
hsMatrix44 fPrevSubworldW2L;
hsVector3 fLinearVelocity;
hsScalar fAngularVelocity;
hsVector3 fAchievedLinearVelocity;
plPhysical* fPushingPhysical;
bool fFacingPushingPhysical;
bool fNeedsResize;
bool fSeeking;
bool fEnabled;
bool fEnableChanged;
};
class plMovementStrategy: public plMovementStrategySimulationInterface
class plMovementStrategy
{
public:
virtual void SetControllerCore(plPhysicalControllerCore* core)
{
fCore=core;
fCore->SetMovementSimulationInterface(this);
}
virtual void RefreshConnectionToControllerCore()
{
fCore->SetMovementSimulationInterface(this);
//fCore->SetControllerDimensions(fPreferedControllerWidth,fPreferedControllerHeight);
fCore->BehaveLikeAnimatedPhysical(this->IRequireBehaviourLikeAnAnimatedPhysical());
}
plMovementStrategy(plPhysicalControllerCore* core);
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
virtual void SetLinearAcceleration(const hsVector3& accel){fLinearAcceleration=accel;}
virtual const hsVector3& GetLinearAcceleration()const{return fLinearAcceleration;}
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
virtual void ResetAchievedLinearVelocity()
{
hsVector3 AchievedLinearVelocity(0.f,0.f,0.f);
if(fCore)fCore->OverrideAchievedVelocity(AchievedLinearVelocity);
}
//proxy functions for Controller Core
virtual hsScalar GetAirTime() const { return fTimeInAir; }
virtual void ResetAirTime() { fTimeInAir = 0.f; }
plMovementStrategy(plPhysicalControllerCore* controller);
virtual ~plMovementStrategy() { }
virtual void Apply(hsScalar delSecs) = 0;
virtual void Update(hsScalar delSecs) { }
virtual void AddContactNormals(hsVector3& vec) { }
virtual void Reset(bool newAge);
virtual bool IsKinematic() { return true; }
protected:
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical()=0;
virtual void IApplyKinematic();
plPhysicalControllerCore* fCore;
hsVector3 fLinearAcceleration;
hsScalar fAngularAcceleration;
plKey fOwner;
static const hsScalar kAirTimeThreshold;
hsScalar fTimeInAir;
hsScalar fPreferedControllerWidth;
hsScalar fPreferedControllerHeight;
plPhysicalControllerCore* fController;
};
class plWalkingStrategy: public plMovementStrategy
class plAnimatedMovementStrategy : public plMovementStrategy
{
public:
plWalkingStrategy(plPhysicalControllerCore* core):plMovementStrategy(core)
{
fGroundHit=false;
fFalseGround=false;
fHitHead=false;
fCore->SetMovementSimulationInterface(this);
fPreferedControllerWidth=core->GetControllerWidth();
fPreferedControllerHeight=core->GetControllerHeight();
fOnTopOfAnimatedPhysLastFrame=false;
}
virtual ~plWalkingStrategy(){};
plAnimatedMovementStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plAnimatedMovementStrategy() { }
virtual void RecalcVelocity(double timeNow, hsScalar elapsed, hsBool useAnim = true);
void SetTurnStrength(hsScalar val) { fTurnStr = val; }
hsScalar GetTurnStrength() const { return fTurnStr; }
private:
void IRecalcLinearVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
void IRecalcAngularVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
plAGApplicator* fRootApp;
hsVector3 fAnimLinearVel;
hsScalar fAnimAngularVel;
hsScalar fTurnStr;
};
class plWalkingStrategy : public plAnimatedMovementStrategy
{
public:
plWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plWalkingStrategy() { }
virtual void Apply(hsScalar delSecs);
virtual void Update(hsScalar delSecs);
virtual void Update(hsScalar delSecs);
virtual void AddContactNormals(hsVector3& vec);
virtual void Reset(bool newAge);
virtual void RecalcVelocity(double timeNow, hsScalar elapsed, hsBool useAnim = true);
bool HitGroundInThisAge() const { return fHitGroundInThisAge; }
bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
void GroundHit() { fGroundHit = true; }
virtual void IAddContactNormals(hsVector3& vec);
virtual void StartJump(){};
hsScalar GetAirTime() const { return fTimeInAir; }
void ResetAirTime() { fTimeInAir = 0.0f; }
hsScalar GetImpactTime() const { return fImpactTime; }
const hsVector3& GetImpactVelocity() const { return fImpactVelocity; }
bool EnableControlledFlight(bool status);
bool IsControlledFlight() const { return fControlledFlight != 0; }
plPhysical* GetPushingPhysical() const;
bool GetFacingPushingPhysical() const;
protected:
static const hsScalar kAirTimeThreshold;
static const hsScalar kControlledFlightThreshold;
hsTArray<hsVector3> fSlidingNormals;
hsVector3 fImpactVelocity;
hsScalar fImpactTime;
hsScalar fTimeInAir;
void ICheckForFalseGround();
hsScalar fControlledFlightTime;
int fControlledFlight;
bool fGroundHit;
bool fFalseGround;
bool fHitHead;
bool fOnTopOfAnimatedPhysLastFrame;
hsTArray<hsVector3> fPrevSlidingNormals;
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
bool fHeadHit;
bool fSliding;
bool fClearImpact;
bool fHitGroundInThisAge;
};
class plSwimStrategy: public plMovementStrategy
class plSwimStrategy : public plAnimatedMovementStrategy
{
public:
plSwimStrategy(plPhysicalControllerCore *core);
virtual ~plSwimStrategy(){};
void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight);
plSwimStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plSwimStrategy() { }
virtual void Apply(hsScalar delSecs);
virtual void Update(hsScalar delSecs);
hsScalar GetBuoyancy() { return fBuoyancy; }
hsBool IsOnGround() { return fOnGround; }
hsBool HadContacts() { return fHadContacts; }
virtual void IAddContactNormals(hsVector3& vec);
virtual void AddContactNormals(hsVector3& vec);
void SetSurface(plSwimRegionInterface* region, hsScalar surfaceHeight);
hsScalar GetBuoyancy() const { return fBuoyancy; }
bool IsOnGround() const { return fOnGround; }
bool HadContacts() const { return fHadContacts; }
protected:
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
private:
void IAdjustBuoyancy();
hsScalar fBuoyancy;
hsBool fOnGround;
hsBool fHadContacts;
hsScalar fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
bool fOnGround;
bool fHadContacts;
};
class plRidingAnimatedPhysicalStrategy : public plWalkingStrategy
class plDynamicWalkingStrategy : public plWalkingStrategy
{
public:
plRidingAnimatedPhysicalStrategy(plPhysicalControllerCore *core ) :
fNeedVelocityOverride(false),fStartJump(false),plWalkingStrategy(core){};
virtual ~plRidingAnimatedPhysicalStrategy(){};
plDynamicWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plDynamicWalkingStrategy() { }
virtual void Apply(hsScalar delSecs);
virtual void Update(hsScalar delSecs);
virtual void PostStep(hsScalar delSecs);
bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
void GroundHit() { fGroundHit = true; }
virtual void StartJump(){fStartJump = true;}
virtual bool IsKinematic() { return false; }
protected:
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return false;}
bool ICheckMove(const hsPoint3& startPos, const hsPoint3& desiredPos);
hsBool fNeedVelocityOverride;
hsVector3 fOverrideVelocity;
bool fStartJump;
bool ICheckForGround(hsScalar& zVelocity);
};
#endif// PLPHYSICALCONTROLLERCORE_H

View File

@ -173,7 +173,7 @@ plPointTimeScale::~plPointTimeScale()
// IsStoppedAt ---------------------------
// ------------
plPointTimeScale::IsStoppedAt(double time)
hsBool plPointTimeScale::IsStoppedAt(double time)
{
return fTimeSource->IsStoppedAt(time);
}

View File

@ -186,7 +186,7 @@ plQuatTimeScale::~plQuatTimeScale()
{
}
plQuatTimeScale::IsStoppedAt(double time)
hsBool plQuatTimeScale::IsStoppedAt(double time)
{
return fTimeSource->IsStoppedAt(time);
}

View File

@ -196,7 +196,7 @@ plScalarTimeScale::~plScalarTimeScale()
{
}
plScalarTimeScale::IsStoppedAt(double time)
hsBool plScalarTimeScale::IsStoppedAt(double time)
{
return fTimeSource->IsStoppedAt(time);
}

View File

@ -0,0 +1,152 @@
/*==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 "hsUtils.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "plJPEG/plJPEG.h"
#include "plGImage/plPNG.h"
#include "plGImage/plMipmap.h"
#include "plClientResMgr.h"
//// Singleton Instance ///////////////////////////////////////////////////////
plClientResMgr& plClientResMgr::Instance(void)
{
static plClientResMgr theInstance;
return theInstance;
}
plClientResMgr::plClientResMgr()
{
this->ClientResources = TRACKED_NEW std::map<std::string, plMipmap*>;
}
plClientResMgr::~plClientResMgr()
{
if (this->ClientResources) {
std::map<std::string, plMipmap*>::iterator it;
for (it = this->ClientResources->begin(); it != this->ClientResources->end(); ++it) {
if (it->second)
it->second->UnRef();
}
delete this->ClientResources;
}
}
void plClientResMgr::ILoadResources(const char* resfile)
{
if (!resfile) {
return;
}
wchar* wFilename = hsStringToWString(resfile);
hsUNIXStream in;
if (in.Open(wFilename, L"rb")) {
UInt32 header = in.ReadSwap32();
UInt32 version = in.ReadSwap32();
UInt32 num_resources = 0;
switch (version) {
case 1:
num_resources = in.ReadSwap32();
for (int i = 0; i < num_resources; i++) {
plMipmap* res_data = NULL;
UInt32 res_size = 0;
char* tmp_name = in.ReadSafeStringLong();
std::string res_name = std::string(tmp_name);
std::string res_type = res_name.substr(res_name.length() - 4, 4);
delete tmp_name;
// Version 1 doesn't encode format, so we'll try some simple
// extension sniffing
if (res_type == ".png") {
// Read resource stream size, but the PNG has that info in the header
// so it's not needed
res_size = in.ReadSwap32();
res_data = plPNG::Instance().ReadFromStream(&in);
} else if (res_type == ".jpg") {
// Don't read resource stream size, as plJPEG's reader will need it
res_data = plJPEG::Instance().ReadFromStream(&in);
} else {
// Original Myst5 format only is known to support Targa,
// so default fallback is targa
// TODO - Add plTarga::ReadFromStream()
// for now, just skip the unknown resource and put NULL into the map
res_size = in.ReadSwap32();
in.Skip(res_size);
}
(*this->ClientResources)[res_name] = res_data;
}
break;
default:
break;
}
in.Close();
}
delete wFilename;
}
plMipmap* plClientResMgr::getResource(const char* resname)
{
plMipmap* resmipmap = NULL;
std::map<std::string, plMipmap*>::iterator it = this->ClientResources->find(resname);
if (it != this->ClientResources->end()) {
resmipmap = it->second;
} else {
hsAssert(resmipmap, "Unknown client resource requested.");
}
return resmipmap;
}

View File

@ -0,0 +1,66 @@
/*==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 _plClientResMgr_h
#define _plClientResMgr_h
#include <map>
#include <string>
class plMipmap;
class plClientResMgr {
protected:
std::map<std::string, plMipmap*>* ClientResources;
public:
plClientResMgr();
~plClientResMgr();
void ILoadResources(const char* resfile);
plMipmap* getResource(const char* resname);
static plClientResMgr& Instance(void);
};
#endif // _plClientResMgr_

View File

@ -1651,7 +1651,7 @@ plMipmap* plWaveSet7::ICreateBumpMipmapPS()
// const int sizeV = kCompositeSize;
const int sizeV = 1;
const kNumLevels = 8; // must be log2(kCompositeSize)
const int kNumLevels = 8; // must be log2(kCompositeSize)
hsAssert(kCompositeSize == (1 << kNumLevels), "Mismatch on size and num mip levels");
if( !fCosineLUT )

View File

@ -55,7 +55,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsWindows.h"
#include <ddraw.h>
#include <d3d.h>
#include <d3d9.h>
#include "hsTypes.h"
#include "hsDXTDirectXCodec.h"

View File

@ -336,22 +336,22 @@ void plFont::IRenderString( plMipmap *mip, UInt16 x, UInt16 y, const wchar_t *st
// Choose an optimal rendering function
fRenderInfo.fRenderFunc = nil;
if( justCalc )
fRenderInfo.fRenderFunc = IRenderCharNull;
fRenderInfo.fRenderFunc = &plFont::IRenderCharNull;
else if( mip->GetPixelSize() == 32 )
{
if( fBPP == 1 )
fRenderInfo.fRenderFunc = ( fRenderInfo.fFlags & kRenderScaleAA ) ? IRenderChar1To32AA : IRenderChar1To32;
fRenderInfo.fRenderFunc = ( fRenderInfo.fFlags & kRenderScaleAA ) ? &plFont::IRenderChar1To32AA : &plFont::IRenderChar1To32;
else if( fBPP == 8 )
{
if( fRenderInfo.fFlags & kRenderIntoAlpha )
{
if( ( fRenderInfo.fColor & 0xff000000 ) != 0xff000000 )
fRenderInfo.fRenderFunc = IRenderChar8To32Alpha;
fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32Alpha;
else
fRenderInfo.fRenderFunc = IRenderChar8To32FullAlpha;
fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32FullAlpha;
}
else
fRenderInfo.fRenderFunc = IRenderChar8To32;
fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32;
}
}
@ -537,7 +537,7 @@ void plFont::IRenderString( plMipmap *mip, UInt16 x, UInt16 y, const wchar_t *st
fRenderInfo.fX = 0;
CharRenderFunc oldFunc = fRenderInfo.fRenderFunc;
fRenderInfo.fRenderFunc = IRenderCharNull;
fRenderInfo.fRenderFunc = &plFont::IRenderCharNull;
IRenderLoop( string, lastWord );
@ -559,7 +559,7 @@ void plFont::IRenderString( plMipmap *mip, UInt16 x, UInt16 y, const wchar_t *st
fRenderInfo.fX = 0;
CharRenderFunc oldFunc = fRenderInfo.fRenderFunc;
fRenderInfo.fRenderFunc = IRenderCharNull;
fRenderInfo.fRenderFunc = &plFont::IRenderCharNull;
IRenderLoop( string, lastWord );
@ -658,7 +658,7 @@ void plFont::IRenderString( plMipmap *mip, UInt16 x, UInt16 y, const wchar_t *st
{
// Advance left past any clipping area
CharRenderFunc oldFunc = fRenderInfo.fRenderFunc;
fRenderInfo.fRenderFunc = IRenderCharNull;
fRenderInfo.fRenderFunc = &plFont::IRenderCharNull;
while( fRenderInfo.fX < fRenderInfo.fClipRect.fX && *string != 0 )
{
IRenderLoop( string, 1 );

View File

@ -108,7 +108,7 @@ void plLODMipmap::SetLOD(int lod)
{
hsAssert(fBase, "UnInitialized");
const kMaxLOD = 5;
const int kMaxLOD = 5;
if( lod > kMaxLOD )
lod = kMaxLOD;
if( lod >= fBase->GetNumLevels() )

View File

@ -207,7 +207,7 @@ UInt32 plMipmap::Read( hsStream *s )
// Decide to clamp if we were told to
int clampBy = fGlobalNumLevelsToChop;
const kMaxSkipLevels = 1;
const int kMaxSkipLevels = 1;
if( clampBy > kMaxSkipLevels )
clampBy = kMaxSkipLevels;
if( fFlags & kNoMaxSize )

View File

@ -0,0 +1,270 @@
/*==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 "hsStream.h"
#include "hsExceptions.h"
#include "hsUtils.h"
#include "plPNG.h"
#include "../plGImage/plMipmap.h"
#include <png.h>
#define PNGSIGSIZE 8
// Custom functions to read and write data from or to an hsStream
// used by libPNG's respective functions
void pngReadDelegate(png_structp png_ptr, png_bytep png_data, png_size_t length)
{
hsStream* inStream = (hsStream*)png_get_io_ptr(png_ptr);
inStream->Read(length, (UInt8*)png_data);
}
void pngWriteDelegate(png_structp png_ptr, png_bytep png_data, png_size_t length)
{
hsStream* outStream = (hsStream*)png_get_io_ptr(png_ptr);
outStream->Write(length, (UInt8*)png_data);
}
//// Singleton Instance ///////////////////////////////////////////////////////
plPNG& plPNG::Instance(void)
{
static plPNG theInstance;
return theInstance;
}
//// IRead ////////////////////////////////////////////////////////////////////
// Given an open hsStream, reads the PNG data off of the
// stream and decodes it into a new plMipmap. The mipmap's buffer ends up
// being a packed RGBA buffer.
// Returns a pointer to the new mipmap if successful, NULL otherwise.
plMipmap* plPNG::IRead(hsStream* inStream)
{
plMipmap* newMipmap = NULL;
png_structp png_ptr;
png_infop info_ptr;
png_infop end_info;
try {
// Check PNG Signature
png_byte sig[PNGSIGSIZE];
inStream->Read8Bytes((char*) sig);
if (!png_sig_cmp(sig, 0, PNGSIGSIZE)) {
// Allocate required structs
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
throw(false);
}
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
throw(false);
}
end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
throw(false);
}
// Assign delegate function for reading from hsStream
png_set_read_fn(png_ptr, (png_voidp)inStream, pngReadDelegate);
// Get PNG Header information
png_set_sig_bytes(png_ptr, PNGSIGSIZE);
png_read_info(png_ptr, info_ptr);
png_uint_32 imgWidth = png_get_image_width(png_ptr, info_ptr);
png_uint_32 imgHeight = png_get_image_height(png_ptr, info_ptr);
png_uint_32 bitdepth = png_get_bit_depth(png_ptr, info_ptr);
png_uint_32 channels = png_get_channels(png_ptr, info_ptr);
png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);
// Convert images to RGB color space
switch (color_type) {
case PNG_COLOR_TYPE_PALETTE:
png_set_palette_to_rgb(png_ptr);
channels = 3;
break;
case PNG_COLOR_TYPE_GRAY:
if (bitdepth < 8) {
png_set_expand_gray_1_2_4_to_8(png_ptr);
}
bitdepth = 8;
break;
}
// Convert transparency (if needed) to a full alpha channel
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png_ptr);
channels += 1;
} else if (channels == 3) {
// Add an opaque alpha channel if still none exists
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
channels = 4;
}
// Invert color byte-order as used by plMipmap for DirectX
png_set_bgr(png_ptr);
/// Construct a new mipmap to hold everything
newMipmap = TRACKED_NEW plMipmap(imgWidth, imgHeight, plMipmap::kARGB32Config, 1, plMipmap::kUncompressed);
char* destp = (char*)newMipmap->GetImage();
png_bytep* row_ptrs = TRACKED_NEW png_bytep[imgHeight];
const unsigned int stride = imgWidth * bitdepth * channels / 8;
// Assign row pointers to the appropriate locations in the newly-created Mipmap
for (size_t i = 0; i < imgHeight; i++) {
row_ptrs[i] = (png_bytep)destp + (i * stride);
}
png_read_image(png_ptr, row_ptrs);
png_read_end(png_ptr, end_info);
// Clean up allocated structs
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete [] row_ptrs;
}
} catch (...) {
if (newMipmap != NULL) {
delete newMipmap;
newMipmap = NULL;
}
}
return newMipmap;
}
plMipmap* plPNG::ReadFromFile(const char* fileName)
{
wchar* wFilename = hsStringToWString(fileName);
plMipmap* retVal = ReadFromFile(wFilename);
delete [] wFilename;
return retVal;
}
plMipmap* plPNG::ReadFromFile(const wchar* fileName)
{
hsUNIXStream in;
if (!in.Open(fileName, L"rb")) {
return false;
}
plMipmap* ret = IRead(&in);
in.Close();
return ret;
}
hsBool plPNG::IWrite(plMipmap* source, hsStream* outStream)
{
hsBool result = true;
try {
// Allocate required structs
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
throw(false);
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
throw(false);
}
// Assign delegate function for writing to hsStream
png_set_write_fn(png_ptr, (png_voidp)outStream, pngWriteDelegate, NULL);
UInt8 psize = source->GetPixelSize();
png_set_IHDR(png_ptr, info_ptr, source->GetWidth(), source->GetHeight(), 8, PNG_COLOR_TYPE_RGB_ALPHA,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
// Invert color byte-order as used by plMipmap for DirectX
png_set_bgr(png_ptr);
// Write out the image metadata
png_write_info(png_ptr, info_ptr);
char* srcp = (char*)source->GetImage();
png_bytep* row_ptrs = TRACKED_NEW png_bytep[source->GetHeight()];
const unsigned int stride = source->GetWidth() * source->GetPixelSize() / 8;
// Assign row pointers to the appropriate locations in the newly-created Mipmap
for (size_t i = 0; i < source->GetHeight(); i++) {
row_ptrs[i] = (png_bytep)srcp + (i * stride);
}
png_write_image(png_ptr, row_ptrs);
png_write_end(png_ptr, info_ptr);
// Clean up allocated structs
png_destroy_write_struct(&png_ptr, &info_ptr);
delete [] row_ptrs;
} catch (...) {
result = false;
}
return result;
}
hsBool plPNG::WriteToFile(const char* fileName, plMipmap* sourceData)
{
wchar* wFilename = hsStringToWString(fileName);
hsBool retVal = WriteToFile(wFilename, sourceData);
delete [] wFilename;
return retVal;
}
hsBool plPNG::WriteToFile(const wchar* fileName, plMipmap* sourceData)
{
hsUNIXStream out;
if (!out.Open(fileName, L"wb")) {
return false;
}
hsBool ret = IWrite(sourceData, &out);
out.Close();
return ret;
}

View File

@ -39,41 +39,33 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#if 0//ndef PL_ANTI_GRAV_ACTION_H
#define PL_ANTI_GRAV_ACTION_H
#include "plAvCallbackAction.h"
#ifndef _plPNG_h
#define _plPNG_h
class plSwimRegionInterface;
class plAntiGravAction : public plAnimatedCallbackAction
{
public:
plAntiGravAction(plHKPhysical *physical, plAGApplicator *rootApp);
//// Class Definition /////////////////////////////////////////////////////////
/** Return the type of the action as defined in the enum plSimDefs::ActionType.
Used to retrieve actions by entity/type indexing, and to
reuse actions that can be shared between entities. */
virtual plSimDefs::ActionType GetType();
class plMipmap;
class hsStream;
/** Called by Havok at substep frequency. */
void apply(Havok::Subspace &s, Havok::hkTime time);
void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight);
hsScalar GetBuoyancy() { return fBuoyancy; }
hsBool IsOnGround() { return fOnGround; }
hsBool HadContacts() { return fHadContacts; }
class plPNG {
protected:
void IAdjustBuoyancy();
hsBool fOnGround;
hsBool fHadContacts;
hsScalar fBuoyancy;
hsScalar fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
plMipmap* IRead(hsStream* inStream);
hsBool IWrite(plMipmap* source, hsStream* outStream);
public:
plMipmap* ReadFromStream(hsStream* inStream) { return IRead(inStream); }
plMipmap* ReadFromFile(const char* fileName);
plMipmap* ReadFromFile(const wchar* fileName);
hsBool WriteToStream(hsStream* outStream, plMipmap* sourceData) { return IWrite(sourceData, outStream); }
hsBool WriteToFile(const char* fileName, plMipmap* sourceData);
hsBool WriteToFile(const wchar* fileName, plMipmap* sourceData);
static plPNG& Instance(void);
};
#endif
#endif // _plPNG_h

View File

@ -55,14 +55,11 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plPipeline/plPlates.h"
#include "../plPipeline/plDebugText.h"
#include "../plGImage/plMipmap.h"
#include "hsWindows.h"
#include "../NucleusLib/inc/plPipeline.h"
// base size of the cursor
#define CURSOR_SIZE_X 0.0675f
#define CURSOR_SIZE_Y 0.09f
// The resolution that uses the base size of the cursor.
// All other resolutions will scale the cursor size to keep the same physical size.
#define BASE_WIDTH 1024
@ -447,16 +444,16 @@ void plMouseDevice::SetDisplayResolution(hsScalar Width, hsScalar Height)
IUpdateCursorSize();
}
void plMouseDevice::CreateCursor( int cursor )
void plMouseDevice::CreateCursor( char* cursor )
{
if( fCursor == nil )
{
plPlateManager::Instance().CreatePlate( &fCursor );
fCursor->CreateFromResource( MAKEINTRESOURCE( cursor ) );
fCursor->CreateFromResource(cursor);
}
else
{
fCursor->ReloadFromResource( MAKEINTRESOURCE( cursor ) );
fCursor->ReloadFromResource(cursor);
}
fCursor->SetPosition( 0, 0, 0 );
IUpdateCursorSize();
@ -470,7 +467,7 @@ void plMouseDevice::IUpdateCursorSize()
if(fCursor)
{
// set the size of the cursor based on resolution.
fCursor->SetSize( CURSOR_SIZE_X * BASE_WIDTH / fWidth, CURSOR_SIZE_Y * BASE_HEIGHT / fHeight );
fCursor->SetSize( 2*fCursor->GetMipmap()->GetWidth()/fWidth, 2*fCursor->GetMipmap()->GetHeight()/fHeight );
}
}
@ -557,7 +554,7 @@ void plMouseDevice::ShowCursor(hsBool override)
fInstance->fCursor->SetVisible( true );
}
void plMouseDevice::NewCursor(int cursor)
void plMouseDevice::NewCursor(char* cursor)
{
fInstance->fCursorID = cursor;
fInstance->CreateCursor(cursor);
@ -933,28 +930,3 @@ hsBool plMouseDevice::MsgReceive(plMessage* msg)
return false;
}
void plMouseDevice::HandleWindowActivate(bool bActive, HWND hWnd)
{
if ( bActive )
{
RECT rect;
::GetClientRect(hWnd,&rect);
// rect.right /= plInputManager::GetInstance()->GetMouseScale();
// rect.bottom /= plInputManager::GetInstance()->GetMouseScale();
::MapWindowPoints( hWnd, NULL, (POINT *)&rect, 2 );
::ClipCursor(&rect);
::ShowCursor( FALSE );
SetCapture(hWnd);
}
else
{
ReleaseCapture();
::ClipCursor(nil);
::ShowCursor( TRUE );
}
}

View File

@ -50,7 +50,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../pnInputCore/plOSMsg.h"
#include "hsBitVector.h"
#include "hsTemplates.h"
#include "../../apps/plClient/res/resource.h"
class plMessage;
enum plKeyDef;
struct plMouseInfo;
@ -142,27 +141,27 @@ protected:
class plPlate;
#define CURSOR_UP IDB_CURSOR_UP
#define CURSOR_DOWN IDB_CURSOR_DOWN
#define CURSOR_RIGHT IDB_CURSOR_RIGHT
#define CURSOR_LEFT IDB_CURSOR_LEFT
#define CURSOR_OPEN IDB_CURSOR_OPEN
#define CURSOR_GRAB IDB_CURSOR_GRAB
#define CURSOR_CLICKED IDB_CURSOR_CLICKED
#define CURSOR_POISED IDB_CURSOR_POISED
#define CURSOR_ARROW IDB_CURSOR_ARROW
#define CURSOR_4WAY_OPEN IDB_CURSOR_4WAYOPEN
#define CURSOR_4WAY_CLOSED IDB_CURSOR_4WAYCLOSED
#define CURSOR_UPDOWN_CLOSED IDB_CURSOR_UPDOWNCLOSED
#define CURSOR_UPDOWN_OPEN IDB_CURSOR_UPDOWNOPEN
#define CURSOR_LEFTRIGHT_CLOSED IDB_CURSOR_LEFTRIGHTCLOSED
#define CURSOR_LEFTRIGHT_OPEN IDB_CURSOR_LEFTRIGHTOPEN
#define CURSOR_OFFER_BOOK IDB_CURSOR_BOOK
#define CURSOR_OFFER_BOOK_HI IDB_CURSOR_BOOK_HIGHLIGHT
#define CURSOR_OFFER_BOOK_CLICKED IDB_CURSOR_BOOK_CLICKED
#define CURSOR_CLICK_DISABLED IDB_CURSOR_DISABLED
#define CURSOR_HAND IDB_CURSOR_HAND
#define CURSOR_UPWARD IDB_CURSOR_UPWARD
#define CURSOR_UP "cursor_up.png"
#define CURSOR_UPWARD "cursor_upward.png"
#define CURSOR_DOWN "cursor_down.png"
#define CURSOR_RIGHT "cursor_right.png"
#define CURSOR_LEFT "cursor_left.png"
#define CURSOR_OPEN "cursor_open.png"
#define CURSOR_GRAB "cursor_grab.png"
#define CURSOR_CLICKED "cursor_clicked.png"
#define CURSOR_POISED "cursor_poised.png"
#define CURSOR_4WAY_OPEN "cursor_4way_open.png"
#define CURSOR_4WAY_CLOSED "cursor_4way_closed.png"
#define CURSOR_UPDOWN_OPEN "cursor_updown_open.png"
#define CURSOR_UPDOWN_CLOSED "cursor_updown_closed.png"
#define CURSOR_LEFTRIGHT_OPEN "cursor_leftright_open.png"
#define CURSOR_LEFTRIGHT_CLOSED "cursor_leftright_closed.png"
#define CURSOR_OFFER_BOOK "cursor_book.png"
#define CURSOR_OFFER_BOOK_HI "cursor_book_poised.png"
#define CURSOR_OFFER_BOOK_CLICKED "cursor_book_clicked.png"
#define CURSOR_CLICK_DISABLED "cursor_disabled.png"
#define CURSOR_HAND "cursor_up.png"
#define CURSOR_ARROW "cursor_up.png"
class plInputEventMsg;
@ -173,7 +172,6 @@ public:
~plMouseDevice();
const char* GetInputName() { return "mouse"; }
void HandleWindowActivate(bool bActive, HWND hWnd);
hsBool HasControlFlag(int f) const { return fControlFlags.IsBitSet(f); }
void SetControlFlag(int f)
@ -195,7 +193,7 @@ public:
static void SetMsgAlways(bool b) { plMouseDevice::bMsgAlways = b; }
static void ShowCursor(hsBool override = false);
static void NewCursor(int cursor);
static void NewCursor(char* cursor);
static void HideCursor(hsBool override = false);
static bool GetHideCursor() { return plMouseDevice::bCursorHidden; }
static void SetCursorOpacity( hsScalar opacity = 1.f );
@ -225,11 +223,11 @@ protected:
plPlate *fCursor;
int fCursorID;
char* fCursorID;
static plMouseDevice* fInstance;
static plMouseInfo fDefaultMouseControlMap[];
void CreateCursor( int cursor );
void CreateCursor( char* cursor );
void IUpdateCursorSize();
static bool bMsgAlways;
static bool bCursorHidden;

View File

@ -251,7 +251,7 @@ void plInputInterfaceMgr::ResetClickableState()
void plInputInterfaceMgr::IUpdateCursor( Int32 newCursor )
{
int mouseCursorResID;
char* mouseCursorResID;
fCurrentCursor = newCursor;

View File

@ -563,10 +563,7 @@ void plDInputMgr::AddDevice(IDirectInputDevice8* device)
void plDInputMgr::ConfigureDevice()
{
::ClipCursor(nil);
::ShowCursor( TRUE );
ReleaseCapture();
DICOLORSET dics;
ZeroMemory(&dics, sizeof(DICOLORSET));
@ -587,13 +584,7 @@ void plDInputMgr::ConfigureDevice()
for (int i = 0; i < fDI->fSticks.Count(); i++)
fDI->fSticks[i]->fDevice->SetActionMap( fDI->fActionFormat, NULL, DIDSAM_FORCESAVE );
RECT rect;
::GetClientRect(fhWnd,&rect);
::ClientToScreen(fhWnd,(LPPOINT)&rect);
::ClipCursor(&rect);
::ShowCursor( FALSE );
SetCapture(fhWnd);
}
hsBool plDInputMgr::MsgReceive(plMessage* msg)

View File

@ -73,7 +73,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvBrain.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plAvCallbackAction.h"
#include "../plAvatar/plPhysicalControllerCore.h"
#include "../plModifier/plInterfaceInfoModifier.h"
#include "../pnModifier/plLogicModBase.h"
#include "../plVault/plVault.h"

View File

@ -288,7 +288,7 @@ plMipmap *plJPEG::IRead( hsStream *inStream )
#else
while( cinfo.output_scanline < cinfo.output_height )
{
UInt8 *startp = newMipmap->GetAddr8( 0, cinfo.output_scanline );
UInt8 *startp = (UInt8*)newMipmap->GetAddr32( 0, cinfo.output_scanline );
(void) jpeg_read_scanlines( &cinfo, &startp, 1 );
}
#endif
@ -328,11 +328,25 @@ plMipmap* plJPEG::ReadFromFile( const char *fileName )
plMipmap* plJPEG::ReadFromFile( const wchar *fileName )
{
// we use a stream because the IJL can't handle unicode
hsUNIXStream out;
if (!out.Open(fileName, L"rb"))
hsRAMStream tempstream;
hsUNIXStream in;
if (!in.Open(fileName, L"rb"))
return false;
plMipmap* ret = IRead(&out);
out.Close();
// The stream reader for JPEGs expects a 32-bit size at the start,
// so insert that into the stream before passing it on
in.FastFwd();
UInt32 fsize = in.GetPosition();
UInt8 *tempbuffer = TRACKED_NEW UInt8[fsize];
in.Rewind();
in.Read(fsize, tempbuffer);
tempstream.WriteSwap32(fsize);
tempstream.Write(fsize, tempbuffer);
delete [] tempbuffer;
tempstream.Rewind();
plMipmap* ret = IRead(&tempstream);
in.Close();
return ret;
}
@ -419,7 +433,7 @@ hsBool plJPEG::IWrite( plMipmap *source, hsStream *outStream )
jcProps.jquality = fWriteQuality;
#else
cinfo.jpeg_width = source->GetWidth(); // default
cinfo.jpeg_width = source->GetHeight(); // default
cinfo.jpeg_height = source->GetHeight(); // default
cinfo.jpeg_color_space = JCS_YCbCr; // default
// not sure how to set 4:1:1 but supposedly it's the default
jpeg_set_quality( &cinfo, fWriteQuality, TRUE );
@ -439,7 +453,7 @@ hsBool plJPEG::IWrite( plMipmap *source, hsStream *outStream )
#else
while( cinfo.next_scanline < cinfo.image_height )
{
UInt8 *startp = source->GetAddr8( 0, cinfo.next_scanline );
UInt8 *startp = (UInt8*)source->GetAddr32( 0, cinfo.next_scanline );
(void) jpeg_write_scanlines( &cinfo, &startp, 1 );
}
jpeg_finish_compress( &cinfo );
@ -487,10 +501,23 @@ hsBool plJPEG::WriteToFile( const char *fileName, plMipmap *sourceData )
hsBool plJPEG::WriteToFile( const wchar *fileName, plMipmap *sourceData )
{
// we use a stream because the IJL can't handle unicode
hsRAMStream tempstream;
hsUNIXStream out;
if (!out.Open(fileName, L"wb"))
return false;
hsBool ret = IWrite(sourceData, &out);
hsBool ret = IWrite(sourceData, &tempstream);
if (ret)
{
// The stream writer for JPEGs prepends a 32-bit size,
// so remove that from the stream before saving to a file
tempstream.Rewind();
UInt32 fsize = tempstream.ReadSwap32();
UInt8 *tempbuffer = TRACKED_NEW UInt8[fsize];
tempstream.Read(fsize, tempbuffer);
out.Write(fsize, tempbuffer);
delete [] tempbuffer;
}
out.Close();
return ret;
}

View File

@ -54,7 +54,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plMessage/plAvatarMsg.h"
#include "plPhysical.h"
#include "../plPhysical/plSimDefs.h"
#include "../plAvatar/plAvCallbackAction.h"
#include "../plAvatar/plAvBrainGeneric.h"

View File

@ -99,7 +99,10 @@ public:
{
std::set<OwnedGroup>::iterator it=IFind(grpId);
if (it != fGroups.end())
(*it).fOwnIt=ownIt;
{
fGroups.erase(it);
fGroups.insert(OwnedGroup(grpId, ownIt));
}
else
{
ISetGroupDesc(grpId);

View File

@ -275,7 +275,7 @@ void plNetObjectDebugger::LogMsgIfMatch(const char* msg) const
std::string tmp = msg;
hsStrLower((char*)tmp.c_str());
std::string objTag="object";
char* c=strstr(tmp.c_str(), objTag.c_str());
const char* c=strstr(tmp.c_str(), objTag.c_str());
if (c && c != tmp.c_str())
{
c+=objTag.size();

View File

@ -448,7 +448,7 @@ static void INetCliAuthCreatePlayerRequestCallback (
void * param,
const NetCliAuthPlayerInfo & playerInfo
) {
ref(param);
REF(param);
if (IS_NET_ERROR(result)) {
LogMsg(kLogDebug, L"Create player failed: %s", NetErrorToString(result));
@ -522,7 +522,7 @@ static void INetCliAuthChangePasswordCallback (
ENetError result,
void * param
) {
ref(param);
REF(param);
if (IS_NET_ERROR(result)) {
LogMsg(kLogDebug, L"Change password failed: %s", NetErrorToString(result));

View File

@ -82,7 +82,7 @@ void plNetClientRecorder::IMakeFilename(const char* recName, char* path)
CreateDirectory(path, NULL);
#endif
char* lastDot = strrchr(recName, '.');
const char* lastDot = strrchr(recName, '.');
if (lastDot)
strncat(path, recName, lastDot-recName);
else

View File

@ -47,6 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../pnNetCommon/plGenericVar.h"
#include "../plCompression/plZlibCompress.h"
#include <algorithm>
#include <iterator>
////////////////////////////////////////////////////////////////////

View File

@ -1241,7 +1241,8 @@ static ENetError FixupPlayerName (wchar * name) {
// Trim leading and trailing whitespace and convert
// multiple internal spaces into only one space
unsigned nonSpaceChars = 0;
for (wchar *src = name, *dst = name; *src; ) {
wchar *dst = name;
for (wchar *src = name; *src; ) {
// Skip whitespace
while (*src && ICharIsSpace(*src))
src++;
@ -1549,7 +1550,7 @@ static void AsyncLookupCallback (
unsigned addrCount,
const NetAddress addrs[]
) {
ref(param);
REF(param);
if (!addrCount) {
ReportNetError(kNetProtocolCli2Auth, kNetErrNameLookupFailed);
@ -2004,8 +2005,8 @@ static bool Recv_KickedOff (
unsigned bytes,
void * param
) {
ref(bytes);
ref(param);
REF(bytes);
REF(param);
const Auth2Cli_KickedOff & msg = *(const Auth2Cli_KickedOff *)buffer;
@ -2537,7 +2538,7 @@ bool PingRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_PingReply & reply = *(const Auth2Cli_PingReply *)msg;
@ -2600,7 +2601,7 @@ bool AccountExistsRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_AccountExistsReply & reply = *(const Auth2Cli_AccountExistsReply *)msg;
@ -2709,7 +2710,7 @@ bool LoginRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
dword msgId = (dword)*msg;
switch (msgId) {
@ -2798,7 +2799,7 @@ bool AgeRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_AgeReply & reply = *(const Auth2Cli_AgeReply *) msg;
m_gameSrvNode = reply.gameSrvNode;
m_ageMcpId = reply.ageMcpId;
@ -2871,7 +2872,7 @@ bool AccountCreateRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_AcctCreateReply & reply = *(const Auth2Cli_AcctCreateReply *) msg;
m_result = reply.result;
@ -2943,7 +2944,7 @@ bool AccountCreateFromKeyRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_AcctCreateFromKeyReply & reply = *(const Auth2Cli_AcctCreateFromKeyReply *) msg;
m_result = reply.result;
@ -3011,7 +3012,7 @@ bool PlayerCreateRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_PlayerCreateReply & reply = *(const Auth2Cli_PlayerCreateReply *) msg;
if (!IS_NET_ERROR(reply.result)) {
m_playerInfo.playerInt = reply.playerInt;
@ -3178,7 +3179,7 @@ bool SetPlayerRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_AcctSetPlayerReply & reply = *(const Auth2Cli_AcctSetPlayerReply *) msg;
m_result = reply.result;
m_state = kTransStateComplete;
@ -3240,7 +3241,7 @@ bool AccountChangePasswordRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_AcctChangePasswordReply & reply = *(const Auth2Cli_AcctChangePasswordReply *) msg;
m_result = reply.result;
@ -3296,7 +3297,7 @@ bool GetPublicAgeListTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_PublicAgeList & reply = *(const Auth2Cli_PublicAgeList *) msg;
if (IS_NET_SUCCESS(reply.result))
@ -3358,7 +3359,7 @@ bool AccountSetRolesRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_AcctSetRolesReply & reply = *(const Auth2Cli_AcctSetRolesReply *) msg;
m_result = reply.result;
@ -3416,7 +3417,7 @@ bool AccountSetBillingTypeRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_AcctSetBillingTypeReply & reply = *(const Auth2Cli_AcctSetBillingTypeReply *) msg;
m_result = reply.result;
@ -3471,7 +3472,7 @@ bool AccountActivateRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_AcctActivateReply & reply = *(const Auth2Cli_AcctActivateReply *) msg;
m_result = reply.result;
@ -3526,7 +3527,7 @@ bool FileListRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_FileListReply & reply = *(const Auth2Cli_FileListReply *) msg;
dword wcharCount = reply.wcharCount;
@ -3642,7 +3643,7 @@ bool FileDownloadRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_FileDownloadChunk & reply = *(const Auth2Cli_FileDownloadChunk *) msg;
if (IS_NET_ERROR(reply.result)) {
@ -3977,7 +3978,7 @@ bool VaultFetchNodeTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_VaultNodeFetched & reply = *(const Auth2Cli_VaultNodeFetched *) msg;
@ -4055,7 +4056,7 @@ bool VaultFindNodeTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_VaultNodeFindReply & reply = *(const Auth2Cli_VaultNodeFindReply *) msg;
@ -4125,7 +4126,7 @@ bool VaultCreateNodeTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_VaultNodeCreated & reply = *(const Auth2Cli_VaultNodeCreated *) msg;
@ -4195,7 +4196,7 @@ bool VaultSaveNodeTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_VaultSaveNodeReply & reply = *(const Auth2Cli_VaultSaveNodeReply *) msg;
@ -4260,7 +4261,7 @@ bool VaultAddNodeTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_VaultAddNodeReply & reply = *(const Auth2Cli_VaultAddNodeReply *) msg;
@ -4322,7 +4323,7 @@ bool VaultRemoveNodeTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_VaultRemoveNodeReply & reply = *(const Auth2Cli_VaultRemoveNodeReply *) msg;
@ -4395,7 +4396,7 @@ bool SetPlayerBanStatusRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_SetPlayerBanStatusReply & reply = *(const Auth2Cli_SetPlayerBanStatusReply *) msg;
m_result = reply.result;
@ -4453,7 +4454,7 @@ bool ChangePlayerNameRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_ChangePlayerNameReply & reply = *(const Auth2Cli_ChangePlayerNameReply *) msg;
m_result = reply.result;
@ -4515,7 +4516,7 @@ bool SendFriendInviteTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_SendFriendInviteReply & reply = *(const Auth2Cli_SendFriendInviteReply *) msg;
m_result = reply.result;
@ -4606,7 +4607,7 @@ bool ScoreCreateTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_ScoreCreateReply & reply = *(const Auth2Cli_ScoreCreateReply *) msg;
m_scoreId = reply.scoreId;
@ -4666,7 +4667,7 @@ bool ScoreDeleteTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_ScoreDeleteReply & reply = *(const Auth2Cli_ScoreDeleteReply *) msg;
m_result = reply.result;
@ -4733,7 +4734,7 @@ bool ScoreGetScoresTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_ScoreGetScoresReply & reply = *(const Auth2Cli_ScoreGetScoresReply *) msg;
if (reply.scoreCount > 0) {
@ -4809,7 +4810,7 @@ bool ScoreAddPointsTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_ScoreAddPointsReply & reply = *(const Auth2Cli_ScoreAddPointsReply *) msg;
m_result = reply.result;
@ -4872,7 +4873,7 @@ bool ScoreTransferPointsTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_ScoreTransferPointsReply & reply = *(const Auth2Cli_ScoreTransferPointsReply *) msg;
m_result = reply.result;
@ -4932,7 +4933,7 @@ bool ScoreSetPointsTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_ScoreSetPointsReply & reply = *(const Auth2Cli_ScoreSetPointsReply *) msg;
m_result = reply.result;
@ -5013,7 +5014,7 @@ bool ScoreGetRanksTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Auth2Cli_ScoreGetRanksReply & reply = *(const Auth2Cli_ScoreGetRanksReply *) msg;
if (reply.rankCount > 0) {
@ -5709,7 +5710,7 @@ unsigned NetCliAuthVaultNodeSave (
void NetCliAuthVaultNodeDelete (
unsigned nodeId
) {
ref(nodeId);
REF(nodeId);
hsAssert(false, "eric, implement me");
}
@ -5842,7 +5843,7 @@ void NetCliAuthSetRecvBufferHandler (
void NetCliAuthSendCCRPetition (
const wchar * petitionText
) {
ref(petitionText);
REF(petitionText);
hsAssert(false, "eric, implement me.");
}

View File

@ -187,7 +187,7 @@ static CliCsConn * GetConnIncRef_CS (const char tag[]) {
//============================================================================
static CliCsConn * GetConnIncRef (const char tag[]) {
ref(GetConnIncRef);
REF(GetConnIncRef);
CliCsConn * conn;
s_critsect.Enter();
@ -420,7 +420,7 @@ static void AsyncLookupCallback (
unsigned addrCount,
const NetAddress addrs[]
) {
ref(name);
REF(name);
if (!addrCount) {
ReportNetError(kNetProtocolCli2Auth, kNetErrNameLookupFailed);
@ -697,7 +697,7 @@ bool LoginRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Csr2Cli_LoginReply & reply = *(const Csr2Cli_LoginReply *) msg;

View File

@ -563,7 +563,7 @@ static void AsyncLookupCallback (
unsigned addrCount,
const NetAddress addrs[]
) {
ref(param);
REF(param);
if (!addrCount) {
ReportNetError(kNetProtocolCli2File, kNetErrNameLookupFailed);
@ -793,7 +793,7 @@ void CliFileConn::Dispatch (const Cli2File_MsgHeader * msg) {
bool CliFileConn::Recv_PingReply (
const File2Cli_PingReply * msg
) {
ref(msg);
REF(msg);
return true;
}
@ -874,7 +874,7 @@ bool BuildIdRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const File2Cli_BuildIdReply & reply = *(const File2Cli_BuildIdReply *) msg;
if (IS_NET_ERROR(reply.result)) {
@ -960,7 +960,7 @@ bool ManifestRequestTrans::Recv (
) {
m_timeoutAtMs = TimeGetMs() + NetTransGetTimeoutMs(); // Reset the timeout counter
ref(bytes);
REF(bytes);
const File2Cli_ManifestReply & reply = *(const File2Cli_ManifestReply *) msg;
dword numFiles = reply.numFiles;
@ -1173,7 +1173,7 @@ bool DownloadRequestTrans::Recv (
) {
m_timeoutAtMs = TimeGetMs() + NetTransGetTimeoutMs(); // Reset the timeout counter
ref(bytes);
REF(bytes);
const File2Cli_FileDownloadReply & reply = *(const File2Cli_FileDownloadReply *) msg;
dword byteCount = reply.byteCount;

View File

@ -430,9 +430,9 @@ static bool Recv_PingReply (
unsigned bytes,
void * param
) {
ref(msg);
ref(bytes);
ref(param);
REF(msg);
REF(bytes);
REF(param);
return true;
}
@ -442,8 +442,8 @@ static bool Recv_JoinAgeReply (
unsigned bytes,
void * param
) {
ref(bytes);
ref(param);
REF(bytes);
REF(param);
const Game2Cli_JoinAgeReply & reply = *(const Game2Cli_JoinAgeReply *)msg;
if (sizeof(reply) != bytes)
@ -460,8 +460,8 @@ static bool Recv_PropagateBuffer (
unsigned bytes,
void * param
) {
ref(bytes);
ref(param);
REF(bytes);
REF(param);
const Game2Cli_PropagateBuffer & reply = *(const Game2Cli_PropagateBuffer *)msg;
@ -481,8 +481,8 @@ static bool Recv_GameMgrMsg (
unsigned bytes,
void * param
) {
ref(bytes);
ref(param);
REF(bytes);
REF(param);
const Game2Cli_GameMgrMsg & reply = *(const Game2Cli_GameMgrMsg *)msg;
@ -571,7 +571,7 @@ bool JoinAgeRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const Game2Cli_JoinAgeReply & reply = *(const Game2Cli_JoinAgeReply *) msg;
m_result = reply.result;

View File

@ -488,7 +488,7 @@ static void AsyncLookupCallback (
unsigned addrCount,
const NetAddress addrs[]
) {
ref(param);
REF(param);
if (!addrCount) {
ReportNetError(kNetProtocolCli2GateKeeper, kNetErrNameLookupFailed);
@ -818,7 +818,7 @@ bool PingRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const GateKeeper2Cli_PingReply & reply = *(const GateKeeper2Cli_PingReply *)msg;
@ -882,7 +882,7 @@ bool FileSrvIpAddressRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const GateKeeper2Cli_FileSrvIpAddressReply & reply = *(const GateKeeper2Cli_FileSrvIpAddressReply *)msg;
@ -942,7 +942,7 @@ bool AuthSrvIpAddressRequestTrans::Recv (
const byte msg[],
unsigned bytes
) {
ref(bytes);
REF(bytes);
const GateKeeper2Cli_AuthSrvIpAddressReply & reply = *(const GateKeeper2Cli_AuthSrvIpAddressReply *)msg;

View File

@ -94,8 +94,7 @@ private:
}
else
{
bool isController;
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(hitActor,&isController);
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(hitActor);
if (controller)
{
objKey = controller->GetOwner();

View File

@ -1,211 +0,0 @@
/*==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 plPXPhysicalController_h_inc
#define plPXPhysicalController_h_inc
#include "../plAvatar/plAvCallbackAction.h"
#include "hsQuat.h"
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
class NxController;
class NxCapsuleController;
class NxActor;
class plCoordinateInterface;
class plPhysicalProxy;
class plDrawableSpans;
class hsGMaterial;
class NxCapsule;
#ifndef PLASMA_EXTERNAL_RELEASE
class plDbgCollisionInfo
{
public:
plSceneObject *fSO;
hsVector3 fNormal;
hsBool fOverlap;
};
#endif // PLASMA_EXTERNAL_RELEASE
class plPXPhysicalController : public plPhysicalController
{
public:
plPXPhysicalController(plKey ownerSO, hsScalar height, hsScalar radius);
virtual ~plPXPhysicalController();
virtual void Enable(bool enable);
virtual bool IsEnabled() const { return fEnable; }
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; }
plSimDefs::plLOSDB GetLOSDB() const { return fLOSDB; }
virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel)
{
fLinearVelocity = linearVel;
fAngularVelocity = angVel;
}
virtual const hsVector3& GetLinearVelocity() const { return fAchievedLinearVelocity; }
virtual void ResetAchievedLinearVelocity() { fAchievedLinearVelocity.Set(0.f, 0.f, 0.f); }
virtual plKey GetSubworld() const { return fWorldKey; }
virtual void SetSubworld(plKey world);
virtual bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
virtual bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
virtual void GroundHit() { fGroundHit = true; }
virtual hsScalar GetAirTime() const { return fTimeInAir; }
virtual void ResetAirTime() { fTimeInAir = 0.f; }
virtual void AddSlidingNormal(hsVector3 vec);
virtual hsTArray<hsVector3>* GetSlidingNormals() { return &fSlidingNormals; }
virtual plPhysical* GetPushingPhysical() const { return fPushingPhysical; }
virtual bool GetFacingPushingPhysical() const { return fFacingPushingPhysical; }
virtual const plCoordinateInterface* GetSubworldCI() const;
virtual void GetState(hsPoint3& pos, float& zRot);
virtual void SetState(const hsPoint3& pos, float zRot);
plKey GetOwner() const { return fOwner; }
// Called by the simulation mgr each frame
static void Update(bool prestep, hsScalar delSecs);
// Used by the LOS mgr to find the controller for an actor it hit
static plPXPhysicalController* GetController(NxActor& actor, bool* isController);
// test to see if there are any controllers (i.e. avatars) in this subworld
static bool plPXPhysicalController::AnyControllersInThisWorld(plKey world);
static int plPXPhysicalController::NumControllers();
static int plPXPhysicalController::GetControllersInThisSubWorld(plKey world, int maxToReturn,
plPXPhysicalController** bufferout);
static int plPXPhysicalController::GetNumberOfControllersInThisSubWorld(plKey world);
// Call this if a static physical in the scene has changed (unloaded,
// collision enabled/disabled, etc)
static void RebuildCache();
virtual void GetPositionSim(hsPoint3& pos) const { IGetPositionSim(pos); }
virtual void Kinematic(bool state);
virtual bool IsKinematic();
virtual void GetKinematicPosition(hsPoint3& pos);
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
virtual const hsMatrix44& GetPrevSubworldW2L() { return fPrevSubworldW2L; }
virtual void SetSeek(bool seek){fSeeking=seek;}
virtual void GetWorldSpaceCapsule(NxCapsule& cap);
#ifndef PLASMA_EXTERNAL_RELEASE
static hsBool fDebugDisplay;
#endif // PLASMA_EXTERNAL_RELEASE
protected:
static const hsScalar kAirTimeThreshold;
friend class PXControllerHitReport;
static plPXPhysicalController* FindController(NxController* controller);
void IApply(hsScalar delSecs);
void ISendUpdates(hsScalar delSecs);
void ICheckForFalseGround();
void ISetGlobalLoc(const hsMatrix44& l2w);
void IMatchKinematicToController();
void IMoveKinematicToController(hsPoint3& pos);
void ISetKinematicLoc(const hsMatrix44& l2w);
void IGetPositionSim(hsPoint3& pos) const;
void ICreateController();
void IDeleteController();
void IInformDetectors(bool entering);
plKey fOwner;
plKey fWorldKey;
hsScalar fRadius, fHeight;
NxCapsuleController* fController;
// this is the kinematic actor for triggering things when the avatar is collision-less during behaviors
NxActor* fKinematicActor;
hsVector3 fLinearVelocity;
hsScalar fAngularVelocity;
hsVector3 fAchievedLinearVelocity;
// The global position and rotation of the avatar last time we set it (so we
// can detect if someone else moves him)
hsMatrix44 fLastGlobalLoc;
//
hsPoint3 fLocalPosition;
hsQuat fLocalRotation;
hsMatrix44 fPrevSubworldW2L;
bool fEnable;
bool fEnableChanged;
plSimDefs::plLOSDB fLOSDB;
bool fKinematic;
bool fKinematicChanged;
bool fKinematicEnableNextUpdate;
bool fGroundHit;
bool fFalseGround;
hsScalar fTimeInAir;
hsTArray<hsVector3> fSlidingNormals;
hsTArray<hsVector3> fPrevSlidingNormals;
#ifndef PLASMA_EXTERNAL_RELEASE
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
void IDrawDebugDisplay();
#endif // PLASMA_EXTERNAL_RELEASE
plPhysical* fPushingPhysical;
bool fFacingPushingPhysical;
plPhysicalProxy* fProxyGen; // visual proxy for debugging
bool fHitHead;
bool fSeeking;
};
#endif // plPXPhysicalController_h_inc

View File

@ -40,22 +40,19 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
#include "../plAvatar/plPhysicalControllerCore.h"
#include "hsQuat.h"
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
class NxController;
class NxCapsuleController;
class NxActor;
class plCoordinateInterface;
class NxCapsule;
class PXControllerHitReport;
class plPhysicalProxy;
class plDrawableSpans;
class hsGMaterial;
class NxCapsule;
class plSceneObject;
class PXControllerHitReportWalk;
class plPXPhysical;
class plCollideMsg;
#ifndef PLASMA_EXTERNAL_RELEASE
#ifndef PLASMA_EXTERNAL_RELEASE
class plDbgCollisionInfo
{
public:
@ -64,98 +61,113 @@ public:
hsBool fOverlap;
};
#endif // PLASMA_EXTERNAL_RELEASE
class plPXPhysicalControllerCore: public plPhysicalControllerCore
{
friend PXControllerHitReportWalk;
public:
plPXPhysicalControllerCore(plKey ownerSO, hsScalar height, hsScalar radius);
plPXPhysicalControllerCore(plKey ownerSO, hsScalar height, hsScalar radius, bool human);
~plPXPhysicalControllerCore();
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
inline virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults);
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
// An ArmatureMod has its own idea about when physics should be enabled/disabled.
// Use plArmatureModBase::EnablePhysics() instead.
virtual void Enable(bool enable);
virtual void SetSubworld(plKey world) ;
virtual const plCoordinateInterface* GetSubworldCI() const ;
// Subworld
virtual void SetSubworld(plKey world);
// For the avatar SDL only
virtual void GetState(hsPoint3& pos, float& zRot);
virtual void SetState(const hsPoint3& pos, float zRot);
// kinematic stuff .... should be just for when playing a behavior...
virtual void Kinematic(bool state);
virtual bool IsKinematic();
virtual void GetKinematicPosition(hsPoint3& pos);
virtual const hsMatrix44& GetPrevSubworldW2L(){ return fPrevSubworldW2L; }
//when seeking no longer want to interact with exclusion regions
virtual void GetWorldSpaceCapsule(NxCapsule& cap) const;
static void RebuildCache();
virtual const hsMatrix44& GetLastGlobalLoc(){return fLastGlobalLoc;}
virtual void SetKinematicLoc(const hsMatrix44& l2w){ISetKinematicLoc(l2w);}
virtual void SetGlobalLoc(const hsMatrix44& l2w){ISetGlobalLoc(l2w);}
virtual void HandleEnableChanged();
virtual void HandleKinematicChanged();
virtual void HandleKinematicEnableNextUpdate();
virtual void GetPositionSim(hsPoint3& pos){IGetPositionSim(pos);}
virtual void MoveKinematicToController(hsPoint3& pos);
virtual const hsPoint3& GetLocalPosition(){return fLocalPosition;}
virtual void SetControllerDimensions(hsScalar radius, hsScalar height);
// Movement strategy
virtual void SetMovementStrategy(plMovementStrategy* strategy);
// Global location
virtual void SetGlobalLoc(const hsMatrix44& l2w);
// Local Sim Position
virtual void GetPositionSim(hsPoint3& pos);
// Move kinematic controller
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults);
// Set linear velocity on dynamic controller
virtual void SetLinearVelocitySim(const hsVector3& linearVel);
// Sweep the controller path from startPos through endPos
virtual int SweepControllerPath(const hsPoint3& startPos, const hsPoint3& endPos, hsBool vsDynamics,
hsBool vsStatics, UInt32& vsSimGroups, std::vector<plControllerSweepRecord>& hits);
// any clean up for the controller should go here
virtual void LeaveAge();
virtual void UpdateControllerAndPhysicalRep();
// Capsule
void GetWorldSpaceCapsule(NxCapsule& cap) const;
// Create Proxy for debug rendering
plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
// Dynamic hits
void AddDynamicHit(plPXPhysical* phys);
//////////////////////////////////////////
//Static Helper Functions
////////////////////////////////////////
// Used by the LOS mgr to find the controller for an actor it hit
static plPXPhysicalControllerCore* GetController(NxActor& actor, bool* isController);
// test to see if there are any controllers (i.e. avatars) in this subworld
// Call pre-sim to apply movement to controllers
static void Apply(hsScalar delSecs);
// Call post-sim to update controllers
static void Update(int numSubSteps, hsScalar alpha);
// Update controllers when not performing a physics step
static void UpdateNonPhysical(hsScalar alpha);
// Rebuild the controller cache, required when a static actor in the scene has changed.
static void RebuildCache();
// Returns the plPXPhysicalControllerCore associated with the given NxActor
static plPXPhysicalControllerCore* GetController(NxActor& actor);
// Subworld controller queries
static bool AnyControllersInThisWorld(plKey world);
static int NumControllers();
static int GetControllersInThisSubWorld(plKey world, int maxToReturn,
plPXPhysicalControllerCore** bufferout);
static int GetNumberOfControllersInThisSubWorld(plKey world);
static void UpdatePrestep(hsScalar delSecs);
static void UpdatePoststep(hsScalar delSecs);
static void UpdatePostSimStep(hsScalar delSecs);
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
static int GetControllersInThisSubWorld(plKey world, int maxToReturn, plPXPhysicalControllerCore** bufferout);
// Controller count
static int NumControllers();
static void SetMaxNumberOfControllers(int max) { fPXControllersMax = max; }
static int fPXControllersMax;
#ifndef PLASMA_EXTERNAL_RELEASE
static hsBool fDebugDisplay;
#endif // PLASMA_EXTERNAL_RELEASE
static void plPXPhysicalControllerCore::SetMaxNumberOfControllers(int max) { fPXControllersMax = max; }
static int fPXControllersMax;
virtual int SweepControllerPath(const hsPoint3& startPos, const hsPoint3& endPos, hsBool vsDynamics, hsBool vsStatics, UInt32& vsSimGroups, std::multiset< plControllerSweepRecord >& WhatWasHitOut);
virtual void BehaveLikeAnimatedPhysical(hsBool actLikeAnAnimatedPhys);
virtual hsBool BehavingLikeAnAnimatedPhysical();
virtual const hsVector3& GetLinearVelocity();
virtual void SetLinearVelocity(const hsVector3& linearVel);
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
virtual void SetAngularVelocity(const hsScalar angvel);
virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel);
#endif
protected:
friend class PXControllerHitReport;
static plPXPhysicalControllerCore* FindController(NxController* controller);
void ISetGlobalLoc(const hsMatrix44& l2w);
void IMatchKinematicToController();
void IMatchControllerToKinematic();
void ISetKinematicLoc(const hsMatrix44& l2w);
void IGetPositionSim(hsPoint3& pos) const;
void ICreateController();
virtual void IHandleEnableChanged();
void IInformDetectors(bool entering);
void ICreateController(const hsPoint3& pos);
void IDeleteController();
void IInformDetectors(bool entering,bool deferUntilNextSim);
void plPXPhysicalControllerCore::ICreateController(const hsPoint3& pos);
NxActor* fKinematicActor;
NxCapsuleController* fController;
void IDispatchQueuedMsgs();
void IProcessDynamicHits();
#ifndef PLASMA_EXTERNAL_RELEASE
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
void IDrawDebugDisplay();
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
#endif
void plPXPhysicalControllerCore::IHandleResize();
hsTArray<plCollideMsg*> fQueuedCollideMsgs;
hsScalar fPreferedRadius;
hsScalar fPreferedHeight;
// The global position and rotation of the avatar last time we set it (so we
// can detect if someone else moves him)
plPhysicalProxy* fProxyGen;
hsBool fBehavingLikeAnimatedPhys;
std::vector<plCollideMsg*> fQueuedCollideMsgs;
std::vector<plPXPhysical*> fDynamicHits;
NxCapsuleController* fController;
NxActor* fActor;
plPhysicalProxy* fProxyGen;
bool fKinematicCCT;
bool fHuman;
};

View File

@ -67,80 +67,26 @@ class SensorReport : public NxUserTriggerReport
{
virtual void onTrigger(NxShape& triggerShape, NxShape& otherShape, NxTriggerFlag status)
{
// Get our trigger physical. This should definitely have a plPXPhysical
plPXPhysical* triggerPhys = (plPXPhysical*)triggerShape.getActor().userData;
plKey otherKey = nil;
hsBool doReport = false;
// Get the triggerer. This may be an avatar, which doesn't have a
// plPXPhysical, so we have to extract the necessary info.
plKey otherKey = nil;
hsPoint3 otherPos = plPXConvert::Point(otherShape.getGlobalPosition());
if (plSimulationMgr::fExtraProfile)
DetectorLogRed("-->%s %s (status=%x) other@(%f,%f,%f)",triggerPhys->GetObjectKey()->GetName(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit",status,otherPos.fX,otherPos.fY,otherPos.fZ);
// Get our trigger physical. This should definitely have a plPXPhysical
plPXPhysical* triggerPhys = (plPXPhysical*)triggerShape.getActor().userData;
// Get the triggerer. If it doesn't have a plPXPhyscial, it's an avatar
plPXPhysical* otherPhys = (plPXPhysical*)otherShape.getActor().userData;
if (otherPhys)
{
otherKey = otherPhys->GetObjectKey();
doReport = triggerPhys->DoReportOn((plSimDefs::Group)otherPhys->GetGroup());
if (!doReport)
{
if (plSimulationMgr::fExtraProfile)
DetectorLogRed("<--Kill collision %s :failed group. US=%x OTHER=(%s)%x",triggerPhys->GetObjectKey()->GetName(),triggerPhys->GetGroup(),otherPhys->GetObjectKey()->GetName(),otherPhys->GetGroup());
}
}
else
{
bool isController;
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(otherShape.getActor(),&isController);
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(otherShape.getActor());
if (controller)
{
if (isController)
{
#ifdef PHYSX_ONLY_TRIGGER_FROM_KINEMATIC
if (plSimulationMgr::fExtraProfile)
DetectorLogRed("<--Kill collision %s : ignoring controller events.",triggerPhys->GetObjectKey()->GetName());
return;
#else // else if trigger on both controller and kinematic
// only suppress controller collision 'enters' when disabled but let 'exits' continue
// ...this is because there are detector regions that are on the edge on ladders that the exit gets missed.
if ( ( !controller->IsEnabled() /*&& (status & NX_TRIGGER_ON_ENTER)*/ ) || controller->IsKinematic() )
{
if (plSimulationMgr::fExtraProfile)
DetectorLogRed("<--Kill collision %s : controller is not enabled.",triggerPhys->GetObjectKey()->GetName());
return;
}
#endif // PHYSX_ONLY_TRIGGER_FROM_KINEMATIC
}
#ifndef PHYSX_ONLY_TRIGGER_FROM_KINEMATIC // if triggering only kinematics, then all should trigger
else
{
// only suppress kinematic collision 'enters' when disabled but let 'exits' continue
// ...this is because there are detector regions that are on the edge on ladders that the exit gets missed.
if ( !controller->IsKinematic() /*&& (status & NX_TRIGGER_ON_ENTER) */ )
{
if (plSimulationMgr::fExtraProfile)
DetectorLogRed("<--Kill collision %s : kinematic is not enabled.",triggerPhys->GetObjectKey()->GetName());
return;
}
}
#endif // PHYSX_ONLY_TRIGGER_FROM_KINEMATIC
otherKey = controller->GetOwner();
doReport = triggerPhys->DoReportOn(plSimDefs::kGroupAvatar);
if (plSimulationMgr::fExtraProfile )
{
if (!doReport)
{
DetectorLogRed("<--Kill collision %s :failed group. US=%x OTHER=(NotAvatar)",triggerPhys->GetObjectKey()->GetName(),triggerPhys->GetGroup());
}
else
{
hsPoint3 avpos;
controller->GetPositionSim(avpos);
DetectorLogRed("-->Avatar at (%f,%f,%f)",avpos.fX,avpos.fY,avpos.fZ);
}
}
}
}
@ -315,7 +261,7 @@ public:
//
/////////////////////////////////////////////////////////////////
#define kDefaultMaxDelta 0.1 // if the step is greater than .1 seconds, clamp to that
#define kDefaultMaxDelta 0.15 // if the step is greater than .15 seconds, clamp to that
#define kDefaultStepSize 1.f / 60.f // default simulation freqency is 60hz
/////////////////////////////////////////////////////////////////
@ -408,6 +354,8 @@ plSimulationMgr::plSimulationMgr()
: fSuspended(true)
, fMaxDelta(kDefaultMaxDelta)
, fStepSize(kDefaultStepSize)
, fAccumulator(0.0f)
, fStepCount(0)
, fLOSDispatch(TRACKED_NEW plLOSDispatch())
, fSoundMgr(new plPhysicsSoundMgr)
, fLog(nil)
@ -496,6 +444,7 @@ NxScene* plSimulationMgr::GetScene(plKey world)
scene->setGroupCollisionFlag(i, plSimDefs::kGroupDynamicBlocker, false);
scene->setGroupCollisionFlag(i, plSimDefs::kGroupLOSOnly, false);
scene->setGroupCollisionFlag(plSimDefs::kGroupLOSOnly, i, false);
scene->setGroupCollisionFlag(i, plSimDefs::kGroupAvatarKinematic, false);
}
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupAvatar, false);
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupAvatarBlocker, true);
@ -503,6 +452,10 @@ NxScene* plSimulationMgr::GetScene(plKey world)
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupStatic, true);
scene->setGroupCollisionFlag( plSimDefs::kGroupStatic, plSimDefs::kGroupAvatar, true);
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupDynamic, true);
// Kinematically controlled avatars interact with detectors and dynamics
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatarKinematic, plSimDefs::kGroupDetector, true);
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatarKinematic, plSimDefs::kGroupDynamic, true);
// The dynamics are in actor group 1, everything else is in 0. Request
// a callback for whenever a dynamic touches something.
@ -616,8 +569,7 @@ void plSimulationMgr::UpdateAvatarInDetector(plKey world, plPXPhysical* detector
if ( actors[i]->userData == nil )
{
// we go a controller
bool isController;
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(*actors[i],&isController);
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(*actors[i]);
if (controller && controller->IsEnabled())
{
plKey avatar = controller->GetOwner();
@ -644,20 +596,31 @@ void plSimulationMgr::Advance(float delSecs)
if (fSuspended)
return;
if (delSecs > fMaxDelta)
fAccumulator += delSecs;
if (fAccumulator < fStepSize)
{
// Not enough time has passed to perform a substep.
plPXPhysicalControllerCore::UpdateNonPhysical(fAccumulator / fStepSize);
return;
}
else if (fAccumulator > fMaxDelta)
{
if (fExtraProfile)
Log("Step clamped from %f to limit of %f", delSecs, fMaxDelta);
delSecs = fMaxDelta;
Log("Step clamped from %f to limit of %f", fAccumulator, fMaxDelta);
fAccumulator = fMaxDelta;
}
plProfile_IncCount(StepLen, (int)(delSecs*1000));
#ifndef PLASMA_EXTERNAL_RELASE
UInt32 stepTime = hsTimer::GetPrecTickCount();
#endif
++fStepCount;
// Perform as many whole substeps as possible saving the remainder in our accumulator.
int numSubSteps = (int)(fAccumulator / fStepSize + 0.000001f);
float delta = numSubSteps * fStepSize;
fAccumulator -= delta;
plProfile_IncCount(StepLen, (int)(delta*1000));
plProfile_BeginTiming(Step);
plPXPhysicalControllerCore::UpdatePrestep(delSecs);
plPXPhysicalControllerCore::UpdatePoststep( delSecs);
plPXPhysicalControllerCore::Apply(delta);
for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
{
@ -672,12 +635,13 @@ void plSimulationMgr::Advance(float delSecs)
}
if (do_advance)
{
scene->simulate(delSecs);
scene->simulate(delta);
scene->flushStream();
scene->fetchResults(NX_RIGID_BODY_FINISHED, true);
}
}
plPXPhysicalControllerCore::UpdatePostSimStep(delSecs);
plPXPhysicalControllerCore::Update(numSubSteps, fAccumulator / fStepSize);
//sending off and clearing the Collision Messages generated by scene->simulate
IDispatchCollisionMessages();
@ -754,9 +718,6 @@ void plSimulationMgr::ISendUpdates()
plPXPhysical* physical = (plPXPhysical*)actors[i]->userData;
if (physical)
{
// apply any hit forces
physical->ApplyHitForce();
if (physical->GetSceneNode())
{
physical->SendNewLocation();

View File

@ -99,6 +99,8 @@ public:
int GetMaterialIdx(NxScene* scene, hsScalar friction, hsScalar restitution);
UInt32 GetStepCount() { return fStepCount; }
// PHYSX FIXME - walk thru all the convex hull detector regions to see if we are in any... we're either coming or going
void UpdateDetectorsInScene(plKey world, plKey avatar, hsPoint3& pos, bool entering);
void UpdateAvatarInDetector(plKey world, plPXPhysical* detector);
@ -159,6 +161,9 @@ protected:
float fMaxDelta;
float fStepSize;
float fAccumulator;
UInt32 fStepCount;
// A utility class to keep track of a request for a physical synchronization.
// These requests must pass a certain criteria (see the code for the latest)

View File

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021
*==LICENSE==*/
#include "../plAvatar/plAvCallbackAction.h"
#include "hsTypes.h"
#include "plCollisionDetector.h"
@ -65,11 +64,13 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plAvBrainDrive.h"
#include "../plAvatar/plPhysicalControllerCore.h"
#include "../plModifier/plDetectorLog.h"
#define USE_PHYSX_MULTIPLE_CAMREGION_ENTER 1
#define USE_PHYSX_COLLISION_FLUTTER_WORKAROUND 1
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
#include "../plPhysX/plSimulationMgr.h"
#endif
plArmatureMod* plCollisionDetector::IGetAvatarModifier(plKey key)
{
@ -245,127 +246,40 @@ plCameraRegionDetector::~plCameraRegionDetector()
fMessages.SetCountAndZero(0);
}
void plCameraRegionDetector::ITrigger(plKey hitter, bool entering, bool immediate)
void plCameraRegionDetector::ISendTriggerMsg()
{
for (int i = 0; i < fMessages.Count(); ++i)
{
hsRefCnt_SafeRef(fMessages[i]);
if (fIsInside)
fMessages[i]->SetCmd(plCameraMsg::kEntering);
else
fMessages[i]->ClearCmd(plCameraMsg::kEntering);
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
if (entering && fNumEvals - fLastExitEval <= 1 && fSavingSendMsg)
{
DetectorLog("%s: Skipping Camera Entering volume", GetKeyName());
fLastEnterEval = fNumEvals;
if (fSavingSendMsg)
{
DetectorLog("%s: Dumping saved Camera Exiting volume", GetKeyName());
}
fSavingSendMsg = false;
return;
plgDispatch::MsgSend(fMessages[i]);
}
if (!entering && fNumEvals - fLastEnterEval <= 1 && fSavingSendMsg)
{
DetectorLog("%s: Skipping Exiting volume", GetKeyName());
fLastExitEval = fNumEvals;
if (fSavingSendMsg)
{
DetectorLog("%s: Dumping saved Camera Entering volume", GetKeyName());
}
fSavingSendMsg = false;
return;
}
// get rid of any saved messages... this should happen though
if (fSavingSendMsg)
{
DetectorLog("%s: Killing saved camera message... shouldn't happen", GetKeyName());
}
// end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
fSavingSendMsg = true;
fSavedMsgEnterFlag = entering;
if (entering)
{
//DetectorLog("%s: Saving camera Entering volume - Evals=%d", GetKeyName(),fNumEvals);
fLastEnterEval = fNumEvals;
}
else
{
//DetectorLog("%s: Saving camera Exiting volume - Evals=%d", GetKeyName(),fNumEvals);
fLastExitEval = fNumEvals;
}
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
// we're saving the message to be dispatched later...
if (immediate)
{
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
ISendSavedTriggerMsgs();
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
}
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
}
void plCameraRegionDetector::ISendSavedTriggerMsgs()
{
if (fSavingSendMsg)
{
for (int i = 0; i < fMessages.Count(); i++)
{
char str[256];
hsRefCnt_SafeRef(fMessages[i]);
if (fSavedMsgEnterFlag)
{
fMessages[i]->SetCmd(plCameraMsg::kEntering);
sprintf(str, "Entering cameraRegion: %s - Evals=%d -msg %d of %d\n", GetKeyName(),fNumEvals,i+1,fMessages.Count());
fIsInside = true;
}
else
{
fMessages[i]->ClearCmd(plCameraMsg::kEntering);
sprintf(str, "Exiting cameraRegion: %s - Evals=%d -msg %d of %d\n", GetKeyName(),fNumEvals,i+1,fMessages.Count());
fIsInside = false;
}
plgDispatch::MsgSend(fMessages[i]);
DetectorLog("%s", str);
}
}
fSavingSendMsg = false;
}
hsBool plCameraRegionDetector::MsgReceive(plMessage* msg)
{
plCollideMsg* pCollMsg = plCollideMsg::ConvertNoRef(msg);
if (pCollMsg)
{
// camera collisions are only for the local player
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pCollMsg->fOtherKey)
return true;
#ifdef USE_PHYSX_MULTIPLE_CAMREGION_ENTER
// first determine if this is a multiple camera region enter (PHYSX BUG WORKAROUND)
if (!fWaitingForEval)
{//plObjectInVolumeCollisionDetector::MsgReceive() will flip fWaitingForEval
// and registers for the Eval, child objects of plObjectInVolumeCollisionDetector
//must decide when they are no longer interested in Evals. I suggest using IHandleEvals()
fNumEvals = 0;
fLastEnterEval=-999;
fLastExitEval=-999;
}
// end of (PHYSX BUG WORKAROUND)
#endif // USE_PHYSX_MULTIPLE_CAMREG_ENTER
IRegisterForEval();
fEntering = (pCollMsg->fEntering != 0);
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
#endif
return true;
}
return plObjectInVolumeDetector::MsgReceive(msg);
}
void plCameraRegionDetector::Read(hsStream* stream, hsResMgr* mgr)
@ -388,22 +302,24 @@ void plCameraRegionDetector::Write(hsStream* stream, hsResMgr* mgr)
mgr->WriteCreatable( stream, fMessages[i] );
}
void plCameraRegionDetector::IHandleEval(plEvalMsg *pEval)
void plCameraRegionDetector::IHandleEval(plEvalMsg*)
{
fNumEvals++;
if (fNumEvals - fLastEnterEval > 1 && fNumEvals-fLastExitEval>1)
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
if (plSimulationMgr::GetInstance()->GetStepCount() - fLastStep > 1)
{
ISendSavedTriggerMsgs();
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
if (fIsInside != fEntering)
{
fIsInside = fEntering;
DetectorLog("%s CameraRegion: %s", fIsInside ? "Entering" : "Exiting", GetKeyName());
ISendTriggerMsg();
}
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
fWaitingForEval = false;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
}
else
{
if(fSavedActivatorMsg)
DetectorLog("%s didn't send its message. fNumEvals=%d fLastEnterEval=%d, fLastExit=%d",
GetKeyName(),fNumEvals, fLastEnterEval, fLastExitEval);
}
#endif
}
/////////////////////////////////
@ -412,182 +328,49 @@ void plCameraRegionDetector::IHandleEval(plEvalMsg *pEval)
/////////////////////////////////
// object-in-volume detector
void plObjectInVolumeDetector::ITrigger(plKey hitter, bool entering, bool immediate)
void plObjectInVolumeDetector::ITrigger(plKey hitter, bool entering)
{
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
/* if (entering && fNumEvals - fLastExitEval <= 1 && fSavedActivatorMsg)
for (bookKeepingList::iterator it = fCollisionList.begin(); it != fCollisionList.end(); ++it)
{
//DetectorLog("%s: Skipping Entering volume", GetKeyName());
fLastEnterEval = fNumEvals;
if (fSavedActivatorMsg)
plCollisionBookKeepingInfo* collisionInfo = *it;
if (collisionInfo->fHitter == hitter)
{
//DetectorLog("%s: Dumping saved Exiting volume", GetKeyName());
delete fSavedActivatorMsg;
collisionInfo->fEntering = entering;
collisionInfo->fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
return;
}
fSavedActivatorMsg = nil;
return;
}
if (!entering && fNumEvals - fLastEnterEval <= 1 && fSavedActivatorMsg)
{
//DetectorLog("%s: Skipping Exiting volume", GetKeyName());
fLastExitEval = fNumEvals;
if (fSavedActivatorMsg)
{
//DetectorLog("%s: Dumping saved Entering volume", GetKeyName());
delete fSavedActivatorMsg;
}
fSavedActivatorMsg = nil;
return;
}
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// get rid of any saved messages... this should happen though
if (fSavedActivatorMsg)
{
delete fSavedActivatorMsg;
DetectorLog("%s: Killing saved message... shouldn't happen", GetKeyName());
}
// end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
*/
if(!immediate)
{
bookKeepingList::iterator curit=fCollisionList.begin();
while(curit!=fCollisionList.end())
{
if(hitter==(*curit)->hitter)
{//hey the object is already in my list
//try and figure out what my real state is
if(entering)
{
(*curit)->enters++;
if(!(*curit)->fSubStepCurState)
{//We weren't already in
(*curit)->fSubStepCurState =true;
}
}
else
{
(*curit)->exits++;
if((*curit)->fSubStepCurState)
{//We were already in
(*curit)->fSubStepCurState =false;
}
}
//get out
break;
}
curit++;
}
if(curit==fCollisionList.end())
{
//hitter was not in the list add him in
//hitter was not in the current frame list
//lets find out its state in the begining of the frame
ResidentSet::iterator curres = fCurrentResidents.find(hitter);
bool initialState;
if(curres != fCurrentResidents.end())
initialState =true;
else
initialState =false;
plCollisionBookKeepingInfo* collisionInfo = new plCollisionBookKeepingInfo(hitter, entering);
fCollisionList.push_back(collisionInfo);
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
collisionInfo->fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
#endif
}
plCollisionBookKeepingInfo* BookKeeper=TRACKED_NEW plCollisionBookKeepingInfo(hitter);
if(entering)
{
BookKeeper->enters++;
BookKeeper->fSubStepCurState =true;
}
else
{
BookKeeper->exits++;
BookKeeper->fSubStepCurState =false;
}
fCollisionList.push_front(BookKeeper);
}
}
else
{
plActivatorMsg* ActivatorMsg = TRACKED_NEW plActivatorMsg;
ActivatorMsg->AddReceivers(fReceivers);
if (fProxyKey)
ActivatorMsg->fHiteeObj = fProxyKey;
else
ActivatorMsg->fHiteeObj = GetTarget()->GetKey();
ActivatorMsg->fHitterObj = hitter;
ActivatorMsg->SetSender(GetKey());
if (entering)
{
ActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter);
}
else
{
ActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit);
}
plgDispatch::MsgSend(ActivatorMsg);
}
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
/* fSavedActivatorMsg = TRACKED_NEW plActivatorMsg;
fSavedActivatorMsg->AddReceivers(fReceivers);
if (fProxyKey)
fSavedActivatorMsg->fHiteeObj = fProxyKey;
else
fSavedActivatorMsg->fHiteeObj = GetTarget()->GetKey();
fSavedActivatorMsg->fHitterObj = hitter;
fSavedActivatorMsg->SetSender(GetKey());
void plObjectInVolumeDetector::IRegisterForEval()
{
fWaitingForEval = true;
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
void plObjectInVolumeDetector::ISendTriggerMsg(plKey hitter, bool entering)
{
plActivatorMsg* activatorMsg = new plActivatorMsg();
activatorMsg->SetSender(GetKey());
activatorMsg->AddReceivers(fReceivers);
activatorMsg->fHiteeObj = fProxyKey ? fProxyKey : GetTarget()->GetKey();
activatorMsg->fHitterObj = hitter;
if (entering)
{
//DetectorLog("%s: Saving Entering volume - Evals=%d", GetKeyName(),fNumEvals);
fSavedActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter);
fLastEnterEval = fNumEvals;
}
activatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter);
else
{
//DetectorLog("%s: Saving Exiting volume - Evals=%d", GetKeyName(),fNumEvals);
fSavedActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit);
fLastExitEval = fNumEvals;
}
*/
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
// we're saving the message to be dispatched later...
if (immediate)
{
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
activatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit);
// fSavedActivatorMsg = nil;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
}
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
plgDispatch::MsgSend(activatorMsg);
}
/*
void plObjectInVolumeDetector::ISendSavedTriggerMsgs()
{
if (fSavedActivatorMsg)
{
if (fSavedActivatorMsg->fTriggerType == plActivatorMsg::kVolumeEnter)
DetectorLog("%s: Sending Entering volume - Evals=%d", GetKeyName(),fNumEvals);
else
DetectorLog("%s: Sending Exiting volume - Evals=%d", GetKeyName(),fNumEvals);
// we're saving the message to be dispatched later...
plgDispatch::MsgSend(fSavedActivatorMsg);
}
fSavedActivatorMsg = nil;
}
*/
hsBool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
{
plCollideMsg* pCollMsg = plCollideMsg::ConvertNoRef(msg);
@ -597,35 +380,16 @@ hsBool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
if (IIsDisabledAvatar(pCollMsg->fOtherKey))
return false;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
if (!fWaitingForEval)
{
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
fWaitingForEval = true;
}
// end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
ITrigger(pCollMsg->fOtherKey, (pCollMsg->fEntering != 0));
IRegisterForEval();
ITrigger(pCollMsg->fOtherKey, (pCollMsg->fEntering != 0));
return true;
}
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
plEvalMsg* pEval = plEvalMsg::ConvertNoRef(msg);
if (pEval)
{
//if (fSavedActivatorMsg)
// DetectorLog("%s: InVolumeEval=%d with saved message", GetKeyName(), fNumEvals);
//else
// DetectorLog("%s: InVolumeEval=%d without saved message", GetKeyName(), fNumEvals);
IHandleEval(pEval);
}
// end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
IHandleEval(pEval);
plPlayerPageMsg* pageMsg = plPlayerPageMsg::ConvertNoRef(msg);
if (pageMsg && pageMsg->fUnload)
@ -636,73 +400,57 @@ hsBool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
return plCollisionDetector::MsgReceive(msg);
}
void plObjectInVolumeDetector::IHandleEval(plEvalMsg* pEval)
void plObjectInVolumeDetector::IHandleEval(plEvalMsg*)
{
bookKeepingList::iterator it = fCollisionList.begin();
while (it != fCollisionList.end())
{
plCollisionBookKeepingInfo* collisionInfo = *it;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
if (plSimulationMgr::GetInstance()->GetStepCount() - collisionInfo->fLastStep > 1)
{
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
bool wasInside = fCurrentResidents.find(collisionInfo->fHitter) != fCurrentResidents.end();
if (collisionInfo->fEntering != wasInside)
{
if (collisionInfo->fEntering)
{
fCurrentResidents.insert(collisionInfo->fHitter);
DetectorLog("%s: Sending Volume Enter ActivatorMsg", GetKeyName());
ISendTriggerMsg(collisionInfo->fHitter, true);
}
else
{
fCurrentResidents.erase(collisionInfo->fHitter);
DetectorLog("%s: Sending Volume Exit ActivatorMsg", GetKeyName());
ISendTriggerMsg(collisionInfo->fHitter, false);
}
}
delete collisionInfo;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
it = fCollisionList.erase(it);
}
else
{
++it;
}
#else
++it;
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
}
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
if (fCollisionList.empty())
{
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
fWaitingForEval = false;
for(bookKeepingList::iterator it= (--fCollisionList.end());it!=(--fCollisionList.begin()); it--)
{
bool alreadyInside;
ResidentSet::iterator HitIt;
HitIt = fCurrentResidents.find((*it)->hitter);
if(HitIt != fCurrentResidents.end()) alreadyInside = true;
else alreadyInside=false;
plActivatorMsg* actout=TRACKED_NEW plActivatorMsg;
actout->fHitterObj=((*it)->hitter);
actout->SetSender(GetKey());
if (fProxyKey)
actout->fHiteeObj = fProxyKey;
else
actout->fHiteeObj = GetTarget()->GetKey();
if((*it)->fSubStepCurState)//current substate says we are entered
{//different enters and exits
//figure out what to do
if(!alreadyInside)
{//we are actuall entering
actout->SetTriggerType(plActivatorMsg::kVolumeEnter);
fCurrentResidents.insert((*it)->hitter);
actout->AddReceivers(fReceivers);
actout->Send();
DetectorLog("%s sent an Enter ActivatorMsg. To: %s", GetKeyName(), GetTarget()->GetKeyName() );
}
else
{
DetectorLog("%s squelched an Enter ActivatorMsg.", GetKeyName());
delete actout;
}
}
else
{
//fSubStepCurState says we are outside
if(alreadyInside)
{//we are actuall exiting
actout->SetTriggerType(plActivatorMsg::kVolumeExit);
fCurrentResidents.erase((*it)->hitter);
actout->AddReceivers(fReceivers);
actout->Send();
DetectorLog("%s sent an Exit ActivatorMsg. To: %s", GetKeyName(), GetTarget()->GetKeyName());
}
else
{
DetectorLog("%s squelched an Exit ActivatorMsg.", GetKeyName());
delete actout;
}
}
}
DetectorLog("*********");
for(bookKeepingList::iterator it = fCollisionList.begin(); it != fCollisionList.end(); it ++)
{
delete (*it);
}
DetectorLog("This is the regions inhabitants after the op");
for(ResidentSet::iterator it = fCurrentResidents.begin(); it!= fCurrentResidents.end(); it++)
{
DetectorLog("%s", (*it)->GetName());
}
DetectorLog("*********");
fCollisionList.clear();
}
#else
fCollisionList.clear();
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
fWaitingForEval = false;
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
}
void plObjectInVolumeDetector::SetTarget(plSceneObject* so)
@ -770,7 +518,7 @@ void plObjectInVolumeAndFacingDetector::ICheckForTrigger()
// And are we walking towards it?
plArmatureBrain* abrain = armMod->FindBrainByClass(plAvBrainHuman::Index()); //armMod->GetCurrentBrain();
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(abrain);
if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround())
if (brain && brain->IsMovingForward() && brain->fWalkingStrategy->IsOnGround())
movingForward = true;
}
else
@ -780,13 +528,13 @@ void plObjectInVolumeAndFacingDetector::ICheckForTrigger()
{
DetectorLog("%s: Trigger InVolume&Facing", GetKeyName());
fTriggered = true;
ITrigger(avatar->GetKey(), true, true);
ISendTriggerMsg(avatar->GetKey(), true);
}
else if (!facing && fTriggered)
{
DetectorLog("%s: Untrigger InVolume&Facing", GetKeyName());
fTriggered = false;
ITrigger(avatar->GetKey(), false, true);
ISendTriggerMsg(avatar->GetKey(), false);
}
}
}
@ -820,7 +568,7 @@ hsBool plObjectInVolumeAndFacingDetector::MsgReceive(plMessage* msg)
if (fTriggered)
{
fTriggered = false;
ITrigger(plNetClientApp::GetInstance()->GetLocalPlayerKey(), false, true);
ISendTriggerMsg(plNetClientApp::GetInstance()->GetLocalPlayerKey(), false);
}
}
@ -940,11 +688,11 @@ hsBool plPanicLinkRegion::MsgReceive(plMessage* msg)
plArmatureMod* avMod = IGetAvatarModifier(pCollMsg->fOtherKey);
if (avMod)
{
hsPoint3 kinPos;
hsPoint3 pos;
if (avMod->GetController())
{
avMod->GetController()->GetKinematicPosition(kinPos);
DetectorLogSpecial("Avatar is panic linking. KinPos at %f,%f,%f and is %s",kinPos.fX,kinPos.fY,kinPos.fZ,avMod->GetController()->IsEnabled() ? "enabled" : "disabled");
avMod->GetController()->GetPositionSim(pos);
DetectorLogSpecial("Avatar is panic linking. Position %f,%f,%f and is %s", pos.fX, pos.fY, pos.fZ, avMod->GetController()->IsEnabled() ? "enabled" : "disabled");
}
avMod->PanicLink(fPlayLinkOutAnim);
}
@ -1168,4 +916,4 @@ hsBool plRidingAnimatedPhysicalDetector::MsgReceive(plMessage *msg)
return true;
}
return plSimpleRegionSensor::MsgReceive(msg);
}
}

View File

@ -45,7 +45,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plDetectorModifier.h"
#include "hsGeometry3.h"
#include <list.h>
#include <list>
#include <set>
class plMessage;
class plCameraMsg;
@ -53,6 +53,8 @@ class plArmatureMod;
class plActivatorMsg;
class plEvalMsg;
#define USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
class plCollisionDetector : public plDetectorModifier
{
protected:
@ -90,34 +92,26 @@ public:
// sub type for object-in-volume detectors
class plObjectInVolumeDetector : public plCollisionDetector
{
public:
protected:
class plCollisionBookKeepingInfo
{
friend plObjectInVolumeDetector;
public:
plCollisionBookKeepingInfo(plKey& hit)
{
hitter=hit;
enters=0;
exits=0;
}
~plCollisionBookKeepingInfo()
{
hitter=nil;
}
protected:
plKey hitter;
int enters,exits;
bool fSubStepCurState;
public:
plCollisionBookKeepingInfo(plKey& key, bool entering)
: fHitter(key), fEntering(entering) { }
plKey fHitter;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
UInt32 fLastStep;
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
bool fEntering;
};
protected:
virtual void ITrigger(plKey hitter, bool entering, bool immediate=false);
//virtual void ISendSavedTriggerMsgs();
virtual void ITrigger(plKey hitter, bool entering);
virtual void ISendTriggerMsg(plKey hitter, bool entering);
virtual void IRegisterForEval();
virtual void IHandleEval(plEvalMsg* pEval);
bool fWaitingForEval;
plActivatorMsg* fSavedActivatorMsg;
typedef std::list<plCollisionBookKeepingInfo*> bookKeepingList;
bookKeepingList fCollisionList;
typedef std::set<plKey> ResidentSet;
@ -126,12 +120,12 @@ protected:
public:
plObjectInVolumeDetector()
{
fWaitingForEval=false;fSavedActivatorMsg=nil;
}
plObjectInVolumeDetector(Int8 i){fType = i;fWaitingForEval=false;fSavedActivatorMsg=nil;}
virtual ~plObjectInVolumeDetector(){;}
: plCollisionDetector(), fWaitingForEval(false) { }
plObjectInVolumeDetector(Int8 i)
: plCollisionDetector(), fWaitingForEval(false) { fType = i; }
virtual ~plObjectInVolumeDetector() { }
virtual hsBool MsgReceive(plMessage* msg);
@ -178,18 +172,19 @@ class plCameraRegionDetector : public plObjectInVolumeDetector
{
protected:
hsTArray<plCameraMsg*> fMessages;
bool fIsInside;
bool fSavingSendMsg;
bool fSavedMsgEnterFlag;
int fNumEvals;
int fLastEnterEval;
int fLastExitEval;
virtual void ITrigger(plKey hitter, bool entering, bool immediate=false);
virtual void ISendSavedTriggerMsgs();
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
UInt32 fLastStep;
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
bool fIsInside;
bool fEntering;
virtual void ISendTriggerMsg();
virtual void IHandleEval(plEvalMsg* pEval);
public:
plCameraRegionDetector(){ fIsInside = false; fSavingSendMsg = false; }
plCameraRegionDetector()
: plObjectInVolumeDetector(), fIsInside(false) { }
~plCameraRegionDetector();
virtual hsBool MsgReceive(plMessage* msg);

View File

@ -40,6 +40,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/
#include <algorithm>
#include <iterator>
#include "hsTimer.h"
#include "plPhysicsSoundMgr.h"
#include "plPhysicalSndGroup.h"
@ -84,7 +85,7 @@ void plPhysicsSoundMgr::Update()
fCurCollisions.clear();
}
void plPhysicsSoundMgr::IStartCollision(CollidePair& cp)
void plPhysicsSoundMgr::IStartCollision(const CollidePair& cp)
{
hsVector3 v1, v2;
const hsScalar strengthThreshold = 20.0f;
@ -120,7 +121,7 @@ void plPhysicsSoundMgr::IStartCollision(CollidePair& cp)
}
}
void plPhysicsSoundMgr::IStopCollision(CollidePair& cp)
void plPhysicsSoundMgr::IStopCollision(const CollidePair& cp)
{
plPhysical* physicalA = cp.FirstPhysical();
plPhysical* physicalB = cp.SecondPhysical();
@ -146,7 +147,7 @@ void plPhysicsSoundMgr::IStopCollision(CollidePair& cp)
}
}
void plPhysicsSoundMgr::IUpdateCollision(CollidePair& cp)
void plPhysicsSoundMgr::IUpdateCollision(const CollidePair& cp)
{
const hsScalar slideThreshhold = 0.f;
hsVector3 v1, v2;

View File

@ -81,9 +81,9 @@ private:
plPhysical* SecondPhysical() const;
};
void IStartCollision(CollidePair& cp);
void IStopCollision(CollidePair& cp);
void IUpdateCollision(CollidePair& cp);
void IStartCollision(const CollidePair& cp);
void IStopCollision(const CollidePair& cp);
void IUpdateCollision(const CollidePair& cp);
void IProcessSlide(plPhysicalSndGroup* sndA, plPhysicalSndGroup* sndB, hsScalar strength);
typedef std::set<CollidePair> CollideSet;

View File

@ -68,27 +68,10 @@ namespace plSimDefs
kGroupLOSOnly,
//kExcludeRegion setting up so only blocks avatars and only when not in seek mode
kGroupExcludeRegion,
// A kinematic avatar only interacts with dynamics and detectors
kGroupAvatarKinematic,
// Just for error checking
kGroupMax,
};
/** A taxonomy of action types. Crucial for doing things like making sure you don't
do things like attach duplicate actions. */
enum ActionType
{
kUnknownAction = 0x01, // don't know the type (probably forgot to override GetType())
kUnknownZAction = 0x02, // unknown type of z-order action
kAntiGravityAction = 0x03, // an action that counters gravity exactly
kUprightAction = 0x04, // an action that keeps an object upright by apply force
kPhysAnimAction = 0x05, // an action that parses keyframed animation into physical information
kConstraint = 0x06, // a general constraint.
kCallbackAction = 0x07, // an action that just hands us the physics "tick"
kPseudoPhysAction = 0x08, // replacement for the physAnim
kAntiGravAction = 0x09, // makes things float in the air
kBasicGroundAction = 0x0a, // for your basic walkAroundOnGround corrections
kHorizontalFreeze = 0x0b, // Let's you fall vertically, but otherwise keeps you in place (generic brains)
kMaxAction = 0xffff // force 16-bit
kGroupMax
};
/** Different types of line-of-sight requests. */

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==*/
#ifndef plBinkPlayer_inc
#define plBinkPlayer_inc
#include "HeadSpin.h"
#include "hsPoint2.h"
#include "hsTemplates.h"
struct D3DVertex;
class plDXPipeline;
struct IDirect3DTexture9;
class plMessage;
struct IDirectSound8;
class plBinkPlayer
{
public:
plBinkPlayer() : fFileName(nil) { }
~plBinkPlayer() { delete [] fFileName; }
static bool Init( hsWindowHndl hWnd) { return true; }
static bool DeInit() { return true; }
static void SetForeGroundTrack(UInt32 t) { }
static void SetBackGroundTrack(UInt32 t) { }
static UInt32 GetForeGroundTrack() { }
static UInt32 GetBackGroundTrack() { }
void SetDefaults() { }
bool Start(plPipeline* pipe, hsWindowHndl hWnd) { return false; }
bool NextFrame() {
// we have reached the end
return Stop();
}
bool Pause(bool on) { return false; }
bool Stop() {
for (int i = 0; i < fCallbacks.GetCount(); i++)
fCallbacks[i]->Send();
fCallbacks.Reset();
delete [] fFileName;
fFileName = nil;
return false;
}
void SetFileName(const char* filename) {
delete [] fFileName;
fFileName = hsStrcpy(filename);
}
void SetColor(const hsColorRGBA& c) { }
void SetPosition(float x, float y) { }
void SetScale(float x, float y) { }
void SetVolume(float v) { }
void SetForeVolume(float v) { }
void SetBackVolume(float v) { }
void SetPosition(const hsPoint2& p) { }
void SetScale(const hsPoint2& s) { }
const char* GetFileName() const { return fFileName; }
const hsColorRGBA GetColor() const { return hsColorRGBA(); }
const hsPoint2 GetPosition() const { return hsPoint2(); }
const hsPoint2 GetScale() const { return hsPoint2(); }
float GetBackVolume() const { return 0.0f; }
float GetForeVolume() const { return 0.0f; }
void AddCallback(plMessage* msg) { hsRefCnt_SafeRef(msg); fCallbacks.Append(msg); }
UInt32 GetNumCallbacks() const { return 0; }
plMessage* GetCallback(int i) const { return nil; }
void SetFadeFromTime(float secs) { }
void SetFadeFromColor(hsColorRGBA c) { }
void SetFadeToTime(float secs) { }
void SetFadeToColor(hsColorRGBA c) { }
float GetFadeFromTime() const { return 0.0f; }
hsColorRGBA GetFadeFromColor() const { return hsColorRGBA(); }
float GetFadeToTime() const { return 0.0f; }
hsColorRGBA GetFadeToColor() const { return hsColorRGBA(); }
private:
char* fFileName;
hsTArray<plMessage*> fCallbacks;
};
#endif // plBinkPlayer_inc

View File

@ -56,8 +56,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plDebugText.h"
#include "plPlates.h"
#include "../Apps/plClient/res/resource.h"
#include "hsTimer.h"
@ -86,7 +84,7 @@ void plDTProgressMgr::Activate()
{
plPlateManager::Instance().CreatePlate(&fStaticTextPlate);
fStaticTextPlate->CreateFromJPEGResource(MAKEINTRESOURCE(plProgressMgr::GetStaticTextID(fCurrentStaticText)), 0);
fStaticTextPlate->CreateFromResource(plProgressMgr::GetStaticTextID(fCurrentStaticText));
fStaticTextPlate->SetVisible(true);
fStaticTextPlate->SetOpacity(1.0f);
fStaticTextPlate->SetSize(2 * 0.192f, 2 * 0.041f, true);
@ -97,7 +95,7 @@ void plDTProgressMgr::Activate()
{
plPlateManager::Instance().CreatePlate( &fActivePlate );
fActivePlate->CreateFromJPEGResource( MAKEINTRESOURCE( plProgressMgr::GetLoadingFrameID(fCurrentImage) ), 0 );
fActivePlate->CreateFromResource(plProgressMgr::GetLoadingFrameID(fCurrentImage));
fActivePlate->SetVisible(true);
fActivePlate->SetOpacity(1.0f);
fActivePlate->SetSize(0.6, 0.6, true);
@ -159,7 +157,7 @@ void plDTProgressMgr::Draw( plPipeline *p )
fLastDraw = currentMs;
fActivePlate->ReloadFromJPEGResource(MAKEINTRESOURCE(plProgressMgr::GetInstance()->GetLoadingFrameID(fCurrentImage)), 0);
fActivePlate->ReloadFromResource(plProgressMgr::GetLoadingFrameID(fCurrentImage));
fActivePlate->SetVisible(true);
fActivePlate->SetOpacity(1.0f);
fActivePlate->SetSize(0.6, 0.6, true);

View File

@ -2233,7 +2233,6 @@ hsBool plDXPipeline::IResetDevice()
{
IClearShadowSlaves();
ReleaseCapture();
Sleep(100);
HRESULT coopLev = fD3DDevice->TestCooperativeLevel();
if( coopLev == D3DERR_DEVICELOST )
@ -2281,8 +2280,6 @@ hsBool plDXPipeline::IResetDevice()
/// all device-specific stuff needs to be recreated
plDeviceRecreateMsg* clean = TRACKED_NEW plDeviceRecreateMsg();
plgDispatch::MsgSend(clean);
SetCapture(fSettings.fHWnd);
}
fDevWasLost = true;
fDeviceLost = false;
@ -10575,7 +10572,7 @@ inline void inlTESTPOINT(const hsPoint3& destP,
void plDXPipeline::IBlendVertsIntoBuffer( plSpan* span,
hsMatrix44* matrixPalette, int numMatrices,
UInt8 *src, UInt8 format, UInt32 srcStride,
const UInt8 *src, UInt8 format, UInt32 srcStride,
UInt8 *dest, UInt32 destStride, UInt32 count,
UInt16 localUVWChans )
{
@ -11680,7 +11677,11 @@ void plDXPlateManager::IDrawToDevice( plPipeline *pipe )
fD3DDevice->SetFVF(dxPipe->fSettings.fCurrFVFFormat = PLD3D_PLATEFVF);
fD3DDevice->SetStreamSource( 0, fVertBuffer, 0, sizeof( plPlateVertex ) );
plProfile_Inc(VertexChange);
fD3DDevice->SetTransform( D3DTS_VIEW, &d3dIdentityMatrix );
// To get plates properly pixel-aligned, we need to compensate for D3D9's weird half-pixel
// offset (see http://drilian.com/2008/11/25/understanding-half-pixel-and-half-texel-offsets/
// or http://msdn.microsoft.com/en-us/library/bb219690(VS.85).aspx).
D3DXMatrixTranslation(&mat, -0.5f/scrnWidthDiv2, -0.5f/scrnHeightDiv2, 0.0f);
fD3DDevice->SetTransform( D3DTS_VIEW, &mat );
oldCullMode = dxPipe->fCurrCullMode;
for( plate = fPlates; plate != nil; plate = plate->GetNext() )

View File

@ -464,7 +464,7 @@ protected:
hsBool IAvatarSort(plDrawableSpans* d, const hsTArray<Int16>& visList);
void IBlendVertsIntoBuffer( plSpan* span,
hsMatrix44* matrixPalette, int numMatrices,
UInt8 *src, UInt8 format, UInt32 srcStride,
const UInt8 *src, UInt8 format, UInt32 srcStride,
UInt8 *dest, UInt32 destStride, UInt32 count, UInt16 localUVWChans );
hsBool ISoftwareVertexBlend( plDrawableSpans* drawable, const hsTArray<Int16>& visList );

View File

@ -51,6 +51,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plPlates.h"
#include "../plJPEG/plJPEG.h"
#include "../plGImage/plPNG.h"
#include "../plGImage/plMipmap.h"
#include "../plSurface/plLayer.h"
#include "../plSurface/hsGMaterial.h"
@ -59,6 +60,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsGDeviceRef.h"
#include "hsResMgr.h"
#include "plPipeDebugFlags.h"
#include "../plClientResMgr/plClientResMgr.h"
// A bit of a hack so that we will have the correct instance in the SceneViewer
@ -243,302 +245,30 @@ plMipmap *plPlate::CreateMaterial( UInt32 width, UInt32 height, hsBool withAlpha
//// CreateFromResource //////////////////////////////////////////////////////
// Creates a plate's material from a resource of the given name.
// This is where hacks beget hacks.
// We have two problems here. First, the main cursor we use most of the time (IDB_CURSOR_UP)
// is a greyscale cursor, so it's color is copied to alpha and then set to white. But its
// color doesn't go to black, it goes to 0x040404, which when used for alpha is just enough
// to be annoying in 32 bit (ghost white square around cursor).
// Second, Win98 seems to be doing some sort of dither on the cursors that use a color key
// (colorKey == 0xff00ff), so the purple parts aren't exactly matching the colorKey, so
// we have a big opaque (except for the parts that dither out to 0xff00ff) purple square
// around the cursor.
// So, when it comes to color keying, we're going to pretend we're in 16 bit mode, and only
// check the upper 5 bits of each channel. If they match the colorKey, close enough to be
// transparent.
// For grey scale, if the alpha comes out less than 8 (upper 5 bits off), again close enough
// for complete transparency.
//
// All this happens in CreateFromResource and ReloadFromResource, so I've moved the alpha setting
// code to a function they can both use, rather than cut and pasting code (what a concept, must
// be one of those new-fangled OOP patterns).
//
void plPlate::ISetResourceAlphas(UInt32 colorKey)
void plPlate::CreateFromResource(const char *resName)
{
if( !fMipmap )
return;
/// Set alphas
colorKey &= 0x00f8f8f8;
UInt32 numPix = fMipmap->GetWidth() * fMipmap->GetHeight();
UInt32 *d;
int i;
hsBool hasColorKey = false;
for( i = 0, d = (UInt32 *)(fMipmap->GetImage()); i < numPix; i++ )
if (resName)
{
if( (d[ i ] & 0x00f8f8f8) == colorKey )
{
hasColorKey = true;
break;
}
}
if( hasColorKey )
{
for( i = 0, d = (UInt32 *)(fMipmap->GetImage()); i < numPix; i++ )
{
// Win98 for some reason likes to return full alpha on the pixels,
// whereas Win2k/XP likes 0 alpha. Go figure...
if( ( d[ i ] & 0x00f8f8f8 ) == colorKey )
d[ i ] = 0;
else
d[ i ] |= 0xff000000;
}
plMipmap* resTexture = TRACKED_NEW plMipmap;
resTexture->CopyFrom(plClientResMgr::Instance().getResource(resName));
char keyName[128];
sprintf( keyName, "PlateResource#%d", fMagicUniqueKeyInt++ );
hsgResMgr::ResMgr()->NewKey(keyName, resTexture, plLocation::kGlobalFixedLoc);
CreateMaterial(resTexture->GetWidth(), resTexture->GetHeight(), true, resTexture);
}
else
{
// No color key, must be a b/w alpha mask
for( i = 0, d = (UInt32 *)(fMipmap->GetImage()); i < numPix; i++ )
{
UInt32 alpha = d[i] & 0xff;
if( !(alpha & 0xf8) )
d[i] = 0x00ffffff;
else
d[ i ] = ( alpha << 24 ) | 0x00ffffff;
}
// Null resource request - Create a blank Material instead
CreateMaterial(32, 32, true);
}
}
void plPlate::CreateFromResource( const char *resName, UInt32 colorKey )
void plPlate::ReloadFromResource(const char *resName)
{
/*
Someday the following might actually work, once we get a plugin that
exports a material in the latest format, plus have the material actually
read in its layers (or maybe we'll have to read() them in manually?)
Right now, we just keep it here so we don't have to look up how to do it
when we need it.
hsRAMStream rsrcStream;
HGLOBAL rsrcHdl;
HRSRC findInfo;
UInt8 *ptr;
UInt32 size;
findInfo = FindResource( GetModuleHandle( nil ), (LPCTSTR)1001, "HSMR" );
size = SizeofResource( GetModuleHandle( nil ), findInfo );
rsrcHdl = LoadResource( GetModuleHandle( nil ), findInfo );
ptr = (UInt8 *)LockResource( rsrcHdl );
rsrcStream.Write( size, ptr );
UnlockResource( rsrcHdl );
rsrcStream.Rewind();
fMaterial = TRACKED_NEW hsGMaterial;
fMaterial->Read( &rsrcStream );
*/
UInt32 width, height;
#if HS_BUILD_FOR_WIN32
HBITMAP rsrc;
BITMAPINFO bMapInfo;
HDC hDC = GetDC( nil );
rsrc = (HBITMAP)LoadImage( gHInstance, resName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
if( rsrc == nil )
if (resName)
{
/// Copy data into a new material
CreateMaterial( 32, 32, true );
SetSize( 0.1, 0.1 );
ReleaseDC( nil, hDC );
return;
}
// hsAssert( rsrc != nil, "Cannot find specified resource" );
memset( &bMapInfo, 0, sizeof( bMapInfo ) );
bMapInfo.bmiHeader.biSize = sizeof( bMapInfo.bmiHeader );
height = GetDIBits( hDC, rsrc, 0, 0, nil, &bMapInfo, DIB_RGB_COLORS );
hsAssert( height != 0, "Cannot get resource bitmap bits" );
width = bMapInfo.bmiHeader.biWidth;
height = bMapInfo.bmiHeader.biHeight;
bMapInfo.bmiHeader.biBitCount = 32;
bMapInfo.bmiHeader.biCompression = BI_RGB;
#endif
/// Copy data into a new material
CreateMaterial( width, height, true );
SetSize( (float)width, (float)height );
#if HS_BUILD_FOR_WIN32
bMapInfo.bmiHeader.biHeight *= -1;
GetDIBits( hDC, rsrc, 0, height, fMipmap->GetImage(), &bMapInfo, DIB_RGB_COLORS );
ReleaseDC( nil, hDC );
DeleteObject( rsrc );
#endif
ISetResourceAlphas(colorKey);
}
//// ReloadFromResource //////////////////////////////////////////////////////
// Creates a plate's material from a resource of the given name.
void plPlate::ReloadFromResource( const char *resName, UInt32 colorKey )
{
UInt32 width, height;
if( !fMaterial || fMaterial->GetNumLayers() < 1 || fMaterial->GetLayer( 0 ) == nil || fMipmap == nil )
{
hsStatusMessage( "WARNING: Not refilling plate material; bitmap not yet assigned\n" );
return;
}
#if HS_BUILD_FOR_WIN32
HBITMAP rsrc;
BITMAPINFO bMapInfo;
HDC hDC = GetDC( nil );
rsrc = (HBITMAP)LoadImage( gHInstance, resName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
if( rsrc == nil )
{
ReleaseDC( nil, hDC );
return;
}
// hsAssert( rsrc != nil, "Cannot find specified resource" );
memset( &bMapInfo, 0, sizeof( bMapInfo ) );
bMapInfo.bmiHeader.biSize = sizeof( bMapInfo.bmiHeader );
height = GetDIBits( hDC, rsrc, 0, 0, nil, &bMapInfo, DIB_RGB_COLORS );
hsAssert( height != 0, "Cannot get resource bitmap bits" );
width = bMapInfo.bmiHeader.biWidth;
height = bMapInfo.bmiHeader.biHeight;
bMapInfo.bmiHeader.biBitCount = 32;
bMapInfo.bmiHeader.biCompression = BI_RGB;
#endif
/// Copy the data into the existing material
if( fMipmap->GetWidth() != width || fMipmap->GetHeight() != height )
{
hsStatusMessage( "WARNING: Not refilling plate material; resource size does not match\n" );
}
#if HS_BUILD_FOR_WIN32
bMapInfo.bmiHeader.biHeight *= -1;
GetDIBits( hDC, rsrc, 0, height, fMipmap->GetImage(), &bMapInfo, DIB_RGB_COLORS );
ReleaseDC( nil, hDC );
DeleteObject( rsrc );
#endif
ISetResourceAlphas(colorKey);
if( fMipmap->GetDeviceRef() )
fMipmap->GetDeviceRef()->SetDirty( true );
}
void plPlate::CreateFromJPEGResource( const char *resName, UInt32 colorKey )
{
hsRAMStream stream;
plMipmap* jpgTexture = nil;
#if HS_BUILD_FOR_WIN32
HRSRC res = FindResource(NULL, resName, "JPEG");
if (!res)
goto error;
HGLOBAL resourceLoaded = LoadResource(NULL, res);
if (!resourceLoaded)
goto error;
byte* data = (byte*)LockResource(resourceLoaded);
if (!data)
goto error;
DWORD resSize = SizeofResource(NULL, res);
if (resSize == 0)
goto error;
stream.Write(sizeof(DWORD), &resSize);
stream.Write(resSize, data);
stream.Rewind();
UnlockResource(resourceLoaded);
char keyName[128];
sprintf( keyName, "PlateJPEG#%d", fMagicUniqueKeyInt++ );
jpgTexture = plJPEG::Instance().ReadFromStream(&stream);
if (jpgTexture)
{
hsgResMgr::ResMgr()->NewKey(keyName, jpgTexture, plLocation::kGlobalFixedLoc);
#endif
CreateMaterial( 256, 256, true, jpgTexture);
ISetResourceAlphas(colorKey);
return;
}
error:
/// Copy data into a new material
CreateMaterial( 32, 32, true );
SetSize( 0.1, 0.1 );
return;
}
void plPlate::ReloadFromJPEGResource( const char *resName, UInt32 colorKey )
{
hsRAMStream stream;
plMipmap* jpgTexture = nil;
#if HS_BUILD_FOR_WIN32
HRSRC res = FindResource(NULL, resName, "JPEG");
if (!res)
return;
HGLOBAL resourceLoaded = LoadResource(NULL, res);
if (!resourceLoaded)
return;
byte* data = (byte*)LockResource(resourceLoaded);
if (!data)
return;
DWORD resSize = SizeofResource(NULL, res);
if (resSize == 0)
return;
stream.Write(sizeof(DWORD), &resSize);
stream.Write(resSize, data);
stream.Rewind();
UnlockResource(resourceLoaded);
jpgTexture = plJPEG::Instance().ReadFromStream(&stream);
if (jpgTexture)
{
#endif
fMipmap->CopyFrom(jpgTexture);
ISetResourceAlphas(colorKey);
if( fMipmap->GetDeviceRef() )
fMipmap->GetDeviceRef()->SetDirty( true );
delete jpgTexture;
fMipmap->CopyFrom(plClientResMgr::Instance().getResource(resName));
}
}

View File

@ -126,6 +126,7 @@ class plPlate
hsMatrix44 &GetTransform( void ) { return fXformMatrix; }
const char *GetTitle( void ) { return fTitle; }
UInt32 GetFlags( void ) { return fFlags; }
const plMipmap *GetMipmap( void ) { return fMipmap; }
void SetVisible( hsBool vis ) { if( vis ) fFlags |= kFlagVisible; else fFlags &= ~kFlagVisible; }
hsBool IsVisible( void );
@ -142,10 +143,8 @@ class plPlate
void SetSize( hsScalar width, hsScalar height, bool adjustByAspectRatio = false );
plMipmap *CreateMaterial( UInt32 width, UInt32 height, hsBool withAlpha, plMipmap* texture = NULL );
void CreateFromResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void ReloadFromResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void CreateFromJPEGResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void ReloadFromJPEGResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void CreateFromResource( const char *resName );
void ReloadFromResource( const char *resName );
};
//// plGraphPlate Class Definition ///////////////////////////////////////////

View File

@ -55,7 +55,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsTimer.h"
#include "../plPipeline/plPlates.h"
#include "../Apps/plClient/res/resource.h"
#include <string.h>
@ -66,30 +65,14 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
plProgressMgr *plProgressMgr::fManager = nil;
int plProgressMgr::fImageRotation[] = {
IDR_LOADING_01,
IDR_LOADING_18,
IDR_LOADING_17,
IDR_LOADING_16,
IDR_LOADING_15,
IDR_LOADING_14,
IDR_LOADING_13,
IDR_LOADING_12,
IDR_LOADING_11,
IDR_LOADING_10,
IDR_LOADING_09,
IDR_LOADING_08,
IDR_LOADING_07,
IDR_LOADING_06,
IDR_LOADING_05,
IDR_LOADING_04,
IDR_LOADING_03,
IDR_LOADING_02
};
#define LOADING_RES "xLoading_Linking.%02d.png"
#define LOADING_RES_COUNT 18
int plProgressMgr::fStaticTextIDs[] = {
0,
IDR_LOADING_UPDATETEXT,
char* plProgressMgr::fImageRotation[LOADING_RES_COUNT];
char* plProgressMgr::fStaticTextIDs[] = {
"xLoading_Linking_Text.png",
"xLoading_Updating_Text.png"
};
//// Constructor & Destructor ////////////////////////////////////////////////
@ -100,10 +83,23 @@ plProgressMgr::plProgressMgr()
fManager = this;
fCallbackProc = nil;
fCurrentStaticText = kNone;
// Fill array with pre-computed loading frame IDs
for (int i=0; i < LOADING_RES_COUNT; i++)
{
char* frameID = TRACKED_NEW char[128];
sprintf(frameID, LOADING_RES, i);
fImageRotation[i] = frameID;
}
}
plProgressMgr::~plProgressMgr()
{
for (int i=0; i < LOADING_RES_COUNT; i++)
{
delete fImageRotation[i];
}
while( fOperations != nil )
delete fOperations;
fManager = nil;
@ -245,15 +241,15 @@ void plProgressMgr::CancelAllOps( void )
fCurrentStaticText = kNone;
}
int plProgressMgr::GetLoadingFrameID(int index)
char* plProgressMgr::GetLoadingFrameID(int index)
{
if (index < (sizeof(fImageRotation) / sizeof(int)))
if (index < LOADING_RES_COUNT)
return fImageRotation[index];
else
return fImageRotation[0];
}
int plProgressMgr::GetStaticTextID(StaticText staticTextType)
char* plProgressMgr::GetStaticTextID(StaticText staticTextType)
{
return fStaticTextIDs[staticTextType];
}

View File

@ -196,8 +196,8 @@ class plProgressMgr
private:
static plProgressMgr *fManager;
static int fImageRotation[];
static int fStaticTextIDs[];
static char* fImageRotation[];
static char* fStaticTextIDs[];
protected:
@ -229,8 +229,8 @@ class plProgressMgr
virtual ~plProgressMgr();
static plProgressMgr* GetInstance() { return fManager; }
static int GetLoadingFrameID(int index);
static int GetStaticTextID(StaticText staticTextType);
static char* GetLoadingFrameID(int index);
static char* GetStaticTextID(StaticText staticTextType);
virtual void Draw( plPipeline *p ) { }