2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 02:27:40 -04:00

Fix line endings and tabs

This commit is contained in:
Branan Purvine-Riley
2011-04-11 16:27:55 -07:00
parent d4250e19b5
commit 908aaeb6f6
2738 changed files with 702562 additions and 702562 deletions

View File

@ -1,108 +1,108 @@
include_directories("../../CoreLib")
include_directories("../../FeatureLib")
include_directories("../../NucleusLib/inc")
include_directories("../../NucleusLib")
include_directories("../../PubUtilLib")
include_directories(${OPENSSL_INCLUDE_DIR})
include_directories(${OPENAL_INCLUDE_DIR})
set(plAvatar_SOURCES
plAGAnim.cpp
plAGAnimInstance.cpp
plAGApplicator.cpp
plAGChannel.cpp
plAGMasterMod.cpp
plAGMasterSDLModifier.cpp
plAGModifier.cpp
plAnimStage.cpp
plAntiGravAction.cpp
plArmatureEffects.cpp
plArmatureMod.cpp
plAvatarClothing.cpp
plAvatarMgr.cpp
plAvatarSDLModifier.cpp
plAvatarTasks.cpp
plAvBehaviors.cpp
plAvBrain.cpp
plAvBrainClimb.cpp
plAvBrainCoop.cpp
plAvBrainCritter.cpp
plAvBrainDrive.cpp
plAvBrainGeneric.cpp
plAvBrainHuman.cpp
plAvBrainRideAnimatedPhysical.cpp
plAvBrainSwim.cpp
plAvCallbackAction.cpp
plAvLadderModifier.cpp
plAvTaskBrain.cpp
plAvTaskSeek.cpp
plClothingSDLModifier.cpp
plCoopCoordinator.cpp
plMatrixChannel.cpp
plMultistageBehMod.cpp
plNPCSpawnMod.cpp
plOneShotMod.cpp
plPhysicalControllerCore.cpp
plPointChannel.cpp
plQuatChannel.cpp
plScalarChannel.cpp
plSeekPointMod.cpp
plSittingModifier.cpp
plSwimRegion.cpp
)
set(plAvatar_HEADERS
plAGAnim.h
plAGAnimInstance.h
plAGApplicator.h
plAGChannel.h
plAGMasterMod.h
plAGMasterSDLModifier.h
plAGModifier.h
plAnimStage.h
plAntiGravAction.h
plArmatureEffects.h
plArmatureMod.h
plAvatarClothing.h
plAvatarCreatable.h
plAvatarMgr.h
plAvatarSDLModifier.h
plAvatarTasks.h
plAvBehaviors.h
plAvBrain.h
plAvBrainClimb.h
plAvBrainCoop.h
plAvBrainCritter.h
plAvBrainDrive.h
plAvBrainGeneric.h
plAvBrainHuman.h
plAvBrainRideAnimatedPhysical.h
plAvBrainSwim.h
plAvCallbackAction.h
plAvDefs.h
plAvLadderModifier.h
plAvTask.h
plAvTaskBrain.h
plAvTaskSeek.h
plClothingLayout.h
plClothingSDLModifier.h
plCoopCoordinator.h
plCritterCommands.h
plMatrixChannel.h
plMultistageBehMod.h
plNPCSpawnMod.h
plOneShotMod.h
plPhysicalControllerCore.h
plPointChannel.h
plQuatChannel.h
plScalarChannel.h
plSeekPointMod.h
plSittingModifier.h
plSwimRegion.h
)
add_library(plAvatar STATIC ${plAvatar_SOURCES} ${plAvatar_HEADERS})
source_group("Source Files" FILES ${plAvatar_SOURCES})
source_group("Header Files" FILES ${plAvatar_HEADERS})
include_directories("../../CoreLib")
include_directories("../../FeatureLib")
include_directories("../../NucleusLib/inc")
include_directories("../../NucleusLib")
include_directories("../../PubUtilLib")
include_directories(${OPENSSL_INCLUDE_DIR})
include_directories(${OPENAL_INCLUDE_DIR})
set(plAvatar_SOURCES
plAGAnim.cpp
plAGAnimInstance.cpp
plAGApplicator.cpp
plAGChannel.cpp
plAGMasterMod.cpp
plAGMasterSDLModifier.cpp
plAGModifier.cpp
plAnimStage.cpp
plAntiGravAction.cpp
plArmatureEffects.cpp
plArmatureMod.cpp
plAvatarClothing.cpp
plAvatarMgr.cpp
plAvatarSDLModifier.cpp
plAvatarTasks.cpp
plAvBehaviors.cpp
plAvBrain.cpp
plAvBrainClimb.cpp
plAvBrainCoop.cpp
plAvBrainCritter.cpp
plAvBrainDrive.cpp
plAvBrainGeneric.cpp
plAvBrainHuman.cpp
plAvBrainRideAnimatedPhysical.cpp
plAvBrainSwim.cpp
plAvCallbackAction.cpp
plAvLadderModifier.cpp
plAvTaskBrain.cpp
plAvTaskSeek.cpp
plClothingSDLModifier.cpp
plCoopCoordinator.cpp
plMatrixChannel.cpp
plMultistageBehMod.cpp
plNPCSpawnMod.cpp
plOneShotMod.cpp
plPhysicalControllerCore.cpp
plPointChannel.cpp
plQuatChannel.cpp
plScalarChannel.cpp
plSeekPointMod.cpp
plSittingModifier.cpp
plSwimRegion.cpp
)
set(plAvatar_HEADERS
plAGAnim.h
plAGAnimInstance.h
plAGApplicator.h
plAGChannel.h
plAGMasterMod.h
plAGMasterSDLModifier.h
plAGModifier.h
plAnimStage.h
plAntiGravAction.h
plArmatureEffects.h
plArmatureMod.h
plAvatarClothing.h
plAvatarCreatable.h
plAvatarMgr.h
plAvatarSDLModifier.h
plAvatarTasks.h
plAvBehaviors.h
plAvBrain.h
plAvBrainClimb.h
plAvBrainCoop.h
plAvBrainCritter.h
plAvBrainDrive.h
plAvBrainGeneric.h
plAvBrainHuman.h
plAvBrainRideAnimatedPhysical.h
plAvBrainSwim.h
plAvCallbackAction.h
plAvDefs.h
plAvLadderModifier.h
plAvTask.h
plAvTaskBrain.h
plAvTaskSeek.h
plClothingLayout.h
plClothingSDLModifier.h
plCoopCoordinator.h
plCritterCommands.h
plMatrixChannel.h
plMultistageBehMod.h
plNPCSpawnMod.h
plOneShotMod.h
plPhysicalControllerCore.h
plPointChannel.h
plQuatChannel.h
plScalarChannel.h
plSeekPointMod.h
plSittingModifier.h
plSwimRegion.h
)
add_library(plAvatar STATIC ${plAvatar_SOURCES} ${plAvatar_HEADERS})
source_group("Source Files" FILES ${plAvatar_SOURCES})
source_group("Header Files" FILES ${plAvatar_HEADERS})

File diff suppressed because it is too large Load Diff

View File

@ -1,430 +1,430 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAGANIM_INC
#define PLAGANIM_INC
/** \file plAGAnim.h
\brief The animation class for the AniGraph animation system
\ingroup Avatar
\ingroup AniGraph
*/
#pragma warning(disable: 4786) // don't care if mangled names are longer than 255 characters
#include "pnNetCommon/plSynchedObject.h"
#include "hsStlUtils.h"
#include "hsStlSortUtils.h"
class plTMController;
class hsAffineParts;
class plAnimTimeConvert;
struct hsMatrix44;
class plEmoteAnim;
class plAGApplicator;
class plAGChannel;
/** \class plAGAnim
This class holds reusable animation data. A single plAGAnim can be instanced
any number of times simultaneously.
In order to use a plAGAnim, you need a plAGMasterMod, which is a special type of
modifier which can be attached to multiple scene objects. A master mod is typically
applied to the root of a scene branch, but there is no requirement that all the scene
objects animated be children.
Each plAGAnim has a number of channels, each of which can animate a single parameter
of a single object. Channels are parametric, i.e. they can carry any data type.
A plAGAnim carries a name for the animation, and each channel is named as well.
Instancing a plAGAnim is done via a plAGAnimInstance.
\sa plAGAnimInstance plAGMasterMod plAGModifier
*/
class plAGAnim : public plSynchedObject
{
public:
/** How much of the body does this emote use? This is handy information for
figuring out whether you can, say, wave while sitting down. */
enum BodyUsage {
kBodyUnknown,
kBodyUpper,
kBodyFull,
kBodyLower,
kBodyMax,
kForceSize = 0xff
};
plAGAnim();
/** Construct with name, start time, and end time (within the max note track)
*/
plAGAnim(const char *name, double begin, double end);
/** Destruct, freeing the underlying animation data. */
virtual ~plAGAnim();
/** Return the total of number of channels supplied by this animation.
An object being animated by this animation does not have to have this
many channels; any which are not available will be ignored.
This is syntactic sugar: GetApplicatorCount will return the exact
same number, but some code is only interested in the channels and not
the applicators. */
int GetChannelCount() const;
/** Return the ith channel of the animation. Ordering is arbitrary but consistent.
It's currently breadth first base on the export algorithm, but don't count on this
remaining true. */
plAGChannel * GetChannel(int i) const;
/** Get the name of the channel having the given index. Useful for talking to an
an animation before it is applied and finding out what channels it's going to
affect. */
virtual const char * GetChannelName(int index);
/** Get channel by name. This corresponds to the name of the scene object this channel
will be attached to when the animation is applied.
This function is fairly slow and shouldn't be used often. */
plAGChannel * GetChannel(const char *name) const;
/** Return the number of applicators held by this animation. An applicator is used
to attach a channel to a sceneobject. */
int GetApplicatorCount() const;
/** Return the ith applicator in the channel.
Order is arbitrary but consistent, corresponding to processing order in the exporter. */
plAGApplicator * GetApplicator(int i) const; // get applicator by index
/** Add an applicator -- which must have a channel behind it.
Applicators are translator object which take the output of a
channel and apply it to a scene object. */
int AddApplicator(plAGApplicator * app);
/** Remove the ith applicator and its associated channel. Existing applicators
will be renumbered. */
hsBool RemoveApplicator(int appNum);
/** The name of the animation. This name is used in the avatar manager to reference
animations. Animations are generally indexed by name when they are loaded
by the avatar or from script, but most of the functions which take an animation
name (such as AttachAnimation on the plAGMasterMod) will also take an pointer
to a plAGAnim. */
virtual const char * GetName() const { return fName; }
/** Return the length of the animation; end - start. */
virtual hsScalar GetLength() const { return fEnd - fStart; }
/** Hacky function to extend the length of the animation to some minimum
length. Does nothing if the animation is already longer than this. */
void ExtendToLength(hsScalar length);
/** Return the start time for the beginning of the animation. The animation
contains no data prior to this time.
In practice, this always returns 0.0f and this function may be deprecated. */
virtual hsScalar GetStart() const { return fStart; }
void SetStart(hsScalar start) { fStart = start; }
/** Return the end time of the animation. Since start is typically 0, this usually
serves as the length of the animation as well. */
virtual hsScalar GetEnd() const { return fEnd; }
void SetEnd(hsScalar end) { fEnd = end; }
/** Returns true if any applicator on the arg anim tries to use the
same pin (on the same object) as we do. */
hsBool SharesPinsWith(const plAGAnim *anim) const;
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plAGAnim );
GETINTERFACE_ANY( plAGAnim, plSynchedObject );
// *** temp hack to manage animation instances
/** Add the animation by name to a global static registry.
This functionality will possibly be added to the resource
manager. */
static void AddAnim(const char * name, plAGAnim *anim);
/** See if there is an animation with the given name in the
global animation registry. */
static plAGAnim *FindAnim(const char *name);
/** Remove the given animation from the registry. */
static hsBool RemoveAnim(const char *name);
/** Clear the animation cache. Used when resetting the client
to a vanilla state, as when clearing the scene while
exporting. */
static void ClearAnimationRegistry();
/** Debugging utility. Prints out a list of all the animations
in the registry */
static void DumpAnimationRegistry();
// persistance
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
protected:
typedef std::vector<plAGApplicator*> ApplicatorVec;
ApplicatorVec fApps; /// our animation channels
float fBlend; /// requested blend factor
hsScalar fStart; /// the start time of the beginning of the animation (usually 0)
hsScalar fEnd; /// the end time of the animation
char *fName; /// the name of our animation
// ??? Can this be moved to the resource manager? If it can manage an efficient
// string-based namespace per class, we could get rid of this.
typedef std::map<const char *, plAGAnim *, stringISorter> plAnimMap; //
static plAnimMap fAllAnims; /// map of animation names to animations
typedef std::map<const char *, plEmoteAnim *, stringISorter> plEmoteMap;
static plEmoteMap fAllEmotes;
};
///////////////
// PLATCANIM
///////////////
/** \class plATCAnim
The most common subclass of plAGAnim.
Represents an animation with a standard AnimTimeConvert
(i.e. stop/start/loop/etc animation)
*/
class plATCAnim : public plAGAnim
{
public:
plATCAnim();
/** Construct with name, start time, and end time (within the max note track)
Default is to start automatically, not loop, with no ease curves. */
plATCAnim(const char *name, double begin, double end);
/** Destruct, freeing the underlying animation data. */
virtual ~plATCAnim();
/** Returns the initial position of the "playback head" for this animation.
Animations are not required to start at their actual beginning but can,
for instance, start in the middle, play to the end, and then loop to the
beginning or to their loop start point. */
virtual hsScalar GetInitial() const { return fInitial; }
void SetInitial(hsScalar initial) { fInitial = initial; }
/** Does this animation start automatically when it's applied? */
virtual bool GetAutoStart() const { return fAutoStart; }
void SetAutoStart(hsBool start) { fAutoStart = (start != 0); }
/** If the animation loops, this is where it will restart the loop. Note that
loops do not have to start at the beginning of the animation. */
virtual hsScalar GetLoopStart() const { return fLoopStart; }
void SetLoopStart(hsScalar start) { fLoopStart = start; }
/** If the animation loops, this is the end point of the loop. After passing
this point, the animation will cycle around to GetLoopStart */
virtual hsScalar GetLoopEnd() const { return fLoopEnd; }
void SetLoopEnd(hsScalar end) { fLoopEnd = end; }
/** Does this animation loop?. Note that there may be multiple loop segments defined
within a given animation. */
virtual bool GetLoop() const { return fLoop; }
void SetLoop(hsBool loop) { fLoop = (loop != 0); }
/** Set the curve type for easing in. Easing is an optional feature which allows you
to make an animation slow down gradually when you stop it.
The types are defined in plAnimEaseTypes.h
*/
virtual UInt8 GetEaseInType() const { return fEaseInType; }
void SetEaseInType(UInt8 type) { fEaseInType = type; }
/** Set the length of time the ease-in should take. */
virtual hsScalar GetEaseInLength() const { return fEaseInLength; }
/** Set the length of time the ease-in should take. */
void SetEaseInLength(hsScalar length) { fEaseInLength = length; }
/** The minimum value used at the start of the ease in. */
virtual hsScalar GetEaseInMin() const { return fEaseInMin; }
/** The minimum value used at the start of the ease in. */
void SetEaseInMin(hsScalar length) { fEaseInMin = length; }
/** The maximum value reached at the end of the ease in. */
virtual hsScalar GetEaseInMax() const { return fEaseInMax; }
/** The maximum value reached at the end of the ease in. */
void SetEaseInMax(hsScalar length) { fEaseInMax = length; }
/** The curve type for the ease out. */
virtual UInt8 GetEaseOutType() const { return fEaseOutType; }
/** The curve type for the ease out. */
void SetEaseOutType(UInt8 type) { fEaseOutType = type; }
/** The length of time for the ease out. */
virtual hsScalar GetEaseOutLength() const { return fEaseOutLength; }
/** The length of time for the ease out. */
void SetEaseOutLength(hsScalar length) { fEaseOutLength = length; }
/** Minimum value reached in ease-out */
virtual hsScalar GetEaseOutMin() const { return fEaseOutMin; }
/** Minimum value reached in ease-out */
void SetEaseOutMin(hsScalar length) { fEaseOutMin = length; }
/** Maximum value reached in ease-in */
virtual hsScalar GetEaseOutMax() const { return fEaseOutMax; }
/** Maximum value reached in ease-in */
void SetEaseOutMax(hsScalar length) { fEaseOutMax = length; }
/** Animations can have multiple defined loop segments; these
are selected using animation control messages.
Each loop segment is named using markers in the notetrack. */
void AddLoop(const char *name, float start, float end);
/** Get the loop having the given name.
\param start will return the start time of the loop.
\param end will hold the end time of the loop */
bool GetLoop(const char *name, float &start, float &end) const;
/** Lets you get a loop by index instead of name. */
bool GetLoop(UInt32 num, float &start, float &end) const;
/** Returns the number of loops defined on this anim. */
UInt32 GetNumLoops() const;
/** Add a marker to the animation. Markers can be used
for callbacks or for goto comands. A marker is a simple
name/time tuple. */
void AddMarker(const char *name, float time);
/** Returns the time value of the marker named by name. */
float GetMarker(const char *name) const;
void CopyMarkerNames(std::vector<char*> &out);
/** Add a stop point to the animation. A stop point is a
"detent" for playback - if the animation is stopping
near a stop point and fading out, the stop point will
override the fade, so that the animation stops precisely
at the defined time. */
void AddStopPoint(hsScalar time);
/** Return the number of stop points defined for this animation. */
UInt32 NumStopPoints();
/** Get the time corresponding to the given stop point. Stop points
are numbered in the order they were added. */
hsScalar GetStopPoint(UInt32 i);
/** Function to check for a zero-length loop, and set it to
the anim's start/end instead */
void CheckLoop();
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plATCAnim );
GETINTERFACE_ANY( plATCAnim, plAGAnim );
// persistance
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
protected:
hsScalar fInitial; /// the position of the playback head
bool fAutoStart; /// does the animation start automatically?
hsScalar fLoopStart; /// when wrapping a loop, start here
hsScalar fLoopEnd; /// when you reach this point, loop back
bool fLoop; /// do we loop?
UInt8 fEaseInType; /// the type (none/linear/spline) of our ease-in curve, if any
UInt8 fEaseOutType; /// the type (none/linear/spline) of our ease-out curve, if any
hsScalar fEaseInLength; /// the length of time our ease-in curve takes
hsScalar fEaseInMin; /// minimum (initial) value of our ease-in
hsScalar fEaseInMax; /// maximum (final) value of our ease-in
hsScalar fEaseOutLength; /// the length of time our ease-out curve takes
hsScalar fEaseOutMin; /// minimum (final) value of our ease-out
hsScalar fEaseOutMax; /// maximum (initial) value of our ease-out
// a map from segment names to times
typedef std::map<const char *, float, stringSorter> MarkerMap;
MarkerMap fMarkers;
typedef std::map<const char *, std::pair<float,float>, stringSorter> LoopMap;
LoopMap fLoops;
typedef std::vector<hsScalar> ScalarMap;
ScalarMap fStopPoints; /// vector of stop points
};
/** \class plEmoteAnim
An animation to be used for emotes.
Automatically registers so that it can be played from the chat field.
*/
class plEmoteAnim : public plATCAnim
{
public:
plEmoteAnim();
plEmoteAnim(const char *animName, double begin, double end, float fadeIn, float fadeOut, BodyUsage bodyUsage);
BodyUsage GetBodyUsage() const;
hsScalar GetFadeIn() const;
hsScalar GetFadeOut() const;
CLASSNAME_REGISTER( plEmoteAnim );
GETINTERFACE_ANY( plEmoteAnim, plATCAnim );
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
BodyUsage fBodyUsage; // how much of the body is used by this emote?
hsScalar fFadeIn; // how fast to fade in the emote
hsScalar fFadeOut; // how fast to fade out the emote
};
//////////////////
// PLAGEGLOBALANIM
//////////////////
/** \class plAgeGlobalAnim
An animation that bases its current position on a variable that global to the age,
like weather, time of day, etc.
*/
class plAgeGlobalAnim : public plAGAnim
{
public:
plAgeGlobalAnim();
/** Construct with name, start time, and end time (within the max note track)
*/
plAgeGlobalAnim(const char *name, double begin, double end);
/** Destruct, freeing the underlying animation data. */
virtual ~plAgeGlobalAnim();
const char * GetGlobalVarName() const { return fGlobalVarName; }
void SetGlobalVarName(char *name);
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plAgeGlobalAnim );
GETINTERFACE_ANY( plAgeGlobalAnim, plAGAnim );
// persistance
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
protected:
char *fGlobalVarName; // Name of the SDL variable we animate on.
};
// USEFUL HELPER FUNCTIONS
bool GetStartToEndTransform(const plAGAnim *anim, hsMatrix44 *startToEnd, hsMatrix44 *endToStart, const char *channelName);
bool GetRelativeTransform(const plAGAnim *anim, double timeA, double timeB, hsMatrix44 *a2b, hsMatrix44 *b2a, const char *channelName);
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAGANIM_INC
#define PLAGANIM_INC
/** \file plAGAnim.h
\brief The animation class for the AniGraph animation system
\ingroup Avatar
\ingroup AniGraph
*/
#pragma warning(disable: 4786) // don't care if mangled names are longer than 255 characters
#include "pnNetCommon/plSynchedObject.h"
#include "hsStlUtils.h"
#include "hsStlSortUtils.h"
class plTMController;
class hsAffineParts;
class plAnimTimeConvert;
struct hsMatrix44;
class plEmoteAnim;
class plAGApplicator;
class plAGChannel;
/** \class plAGAnim
This class holds reusable animation data. A single plAGAnim can be instanced
any number of times simultaneously.
In order to use a plAGAnim, you need a plAGMasterMod, which is a special type of
modifier which can be attached to multiple scene objects. A master mod is typically
applied to the root of a scene branch, but there is no requirement that all the scene
objects animated be children.
Each plAGAnim has a number of channels, each of which can animate a single parameter
of a single object. Channels are parametric, i.e. they can carry any data type.
A plAGAnim carries a name for the animation, and each channel is named as well.
Instancing a plAGAnim is done via a plAGAnimInstance.
\sa plAGAnimInstance plAGMasterMod plAGModifier
*/
class plAGAnim : public plSynchedObject
{
public:
/** How much of the body does this emote use? This is handy information for
figuring out whether you can, say, wave while sitting down. */
enum BodyUsage {
kBodyUnknown,
kBodyUpper,
kBodyFull,
kBodyLower,
kBodyMax,
kForceSize = 0xff
};
plAGAnim();
/** Construct with name, start time, and end time (within the max note track)
*/
plAGAnim(const char *name, double begin, double end);
/** Destruct, freeing the underlying animation data. */
virtual ~plAGAnim();
/** Return the total of number of channels supplied by this animation.
An object being animated by this animation does not have to have this
many channels; any which are not available will be ignored.
This is syntactic sugar: GetApplicatorCount will return the exact
same number, but some code is only interested in the channels and not
the applicators. */
int GetChannelCount() const;
/** Return the ith channel of the animation. Ordering is arbitrary but consistent.
It's currently breadth first base on the export algorithm, but don't count on this
remaining true. */
plAGChannel * GetChannel(int i) const;
/** Get the name of the channel having the given index. Useful for talking to an
an animation before it is applied and finding out what channels it's going to
affect. */
virtual const char * GetChannelName(int index);
/** Get channel by name. This corresponds to the name of the scene object this channel
will be attached to when the animation is applied.
This function is fairly slow and shouldn't be used often. */
plAGChannel * GetChannel(const char *name) const;
/** Return the number of applicators held by this animation. An applicator is used
to attach a channel to a sceneobject. */
int GetApplicatorCount() const;
/** Return the ith applicator in the channel.
Order is arbitrary but consistent, corresponding to processing order in the exporter. */
plAGApplicator * GetApplicator(int i) const; // get applicator by index
/** Add an applicator -- which must have a channel behind it.
Applicators are translator object which take the output of a
channel and apply it to a scene object. */
int AddApplicator(plAGApplicator * app);
/** Remove the ith applicator and its associated channel. Existing applicators
will be renumbered. */
hsBool RemoveApplicator(int appNum);
/** The name of the animation. This name is used in the avatar manager to reference
animations. Animations are generally indexed by name when they are loaded
by the avatar or from script, but most of the functions which take an animation
name (such as AttachAnimation on the plAGMasterMod) will also take an pointer
to a plAGAnim. */
virtual const char * GetName() const { return fName; }
/** Return the length of the animation; end - start. */
virtual hsScalar GetLength() const { return fEnd - fStart; }
/** Hacky function to extend the length of the animation to some minimum
length. Does nothing if the animation is already longer than this. */
void ExtendToLength(hsScalar length);
/** Return the start time for the beginning of the animation. The animation
contains no data prior to this time.
In practice, this always returns 0.0f and this function may be deprecated. */
virtual hsScalar GetStart() const { return fStart; }
void SetStart(hsScalar start) { fStart = start; }
/** Return the end time of the animation. Since start is typically 0, this usually
serves as the length of the animation as well. */
virtual hsScalar GetEnd() const { return fEnd; }
void SetEnd(hsScalar end) { fEnd = end; }
/** Returns true if any applicator on the arg anim tries to use the
same pin (on the same object) as we do. */
hsBool SharesPinsWith(const plAGAnim *anim) const;
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plAGAnim );
GETINTERFACE_ANY( plAGAnim, plSynchedObject );
// *** temp hack to manage animation instances
/** Add the animation by name to a global static registry.
This functionality will possibly be added to the resource
manager. */
static void AddAnim(const char * name, plAGAnim *anim);
/** See if there is an animation with the given name in the
global animation registry. */
static plAGAnim *FindAnim(const char *name);
/** Remove the given animation from the registry. */
static hsBool RemoveAnim(const char *name);
/** Clear the animation cache. Used when resetting the client
to a vanilla state, as when clearing the scene while
exporting. */
static void ClearAnimationRegistry();
/** Debugging utility. Prints out a list of all the animations
in the registry */
static void DumpAnimationRegistry();
// persistance
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
protected:
typedef std::vector<plAGApplicator*> ApplicatorVec;
ApplicatorVec fApps; /// our animation channels
float fBlend; /// requested blend factor
hsScalar fStart; /// the start time of the beginning of the animation (usually 0)
hsScalar fEnd; /// the end time of the animation
char *fName; /// the name of our animation
// ??? Can this be moved to the resource manager? If it can manage an efficient
// string-based namespace per class, we could get rid of this.
typedef std::map<const char *, plAGAnim *, stringISorter> plAnimMap; //
static plAnimMap fAllAnims; /// map of animation names to animations
typedef std::map<const char *, plEmoteAnim *, stringISorter> plEmoteMap;
static plEmoteMap fAllEmotes;
};
///////////////
// PLATCANIM
///////////////
/** \class plATCAnim
The most common subclass of plAGAnim.
Represents an animation with a standard AnimTimeConvert
(i.e. stop/start/loop/etc animation)
*/
class plATCAnim : public plAGAnim
{
public:
plATCAnim();
/** Construct with name, start time, and end time (within the max note track)
Default is to start automatically, not loop, with no ease curves. */
plATCAnim(const char *name, double begin, double end);
/** Destruct, freeing the underlying animation data. */
virtual ~plATCAnim();
/** Returns the initial position of the "playback head" for this animation.
Animations are not required to start at their actual beginning but can,
for instance, start in the middle, play to the end, and then loop to the
beginning or to their loop start point. */
virtual hsScalar GetInitial() const { return fInitial; }
void SetInitial(hsScalar initial) { fInitial = initial; }
/** Does this animation start automatically when it's applied? */
virtual bool GetAutoStart() const { return fAutoStart; }
void SetAutoStart(hsBool start) { fAutoStart = (start != 0); }
/** If the animation loops, this is where it will restart the loop. Note that
loops do not have to start at the beginning of the animation. */
virtual hsScalar GetLoopStart() const { return fLoopStart; }
void SetLoopStart(hsScalar start) { fLoopStart = start; }
/** If the animation loops, this is the end point of the loop. After passing
this point, the animation will cycle around to GetLoopStart */
virtual hsScalar GetLoopEnd() const { return fLoopEnd; }
void SetLoopEnd(hsScalar end) { fLoopEnd = end; }
/** Does this animation loop?. Note that there may be multiple loop segments defined
within a given animation. */
virtual bool GetLoop() const { return fLoop; }
void SetLoop(hsBool loop) { fLoop = (loop != 0); }
/** Set the curve type for easing in. Easing is an optional feature which allows you
to make an animation slow down gradually when you stop it.
The types are defined in plAnimEaseTypes.h
*/
virtual UInt8 GetEaseInType() const { return fEaseInType; }
void SetEaseInType(UInt8 type) { fEaseInType = type; }
/** Set the length of time the ease-in should take. */
virtual hsScalar GetEaseInLength() const { return fEaseInLength; }
/** Set the length of time the ease-in should take. */
void SetEaseInLength(hsScalar length) { fEaseInLength = length; }
/** The minimum value used at the start of the ease in. */
virtual hsScalar GetEaseInMin() const { return fEaseInMin; }
/** The minimum value used at the start of the ease in. */
void SetEaseInMin(hsScalar length) { fEaseInMin = length; }
/** The maximum value reached at the end of the ease in. */
virtual hsScalar GetEaseInMax() const { return fEaseInMax; }
/** The maximum value reached at the end of the ease in. */
void SetEaseInMax(hsScalar length) { fEaseInMax = length; }
/** The curve type for the ease out. */
virtual UInt8 GetEaseOutType() const { return fEaseOutType; }
/** The curve type for the ease out. */
void SetEaseOutType(UInt8 type) { fEaseOutType = type; }
/** The length of time for the ease out. */
virtual hsScalar GetEaseOutLength() const { return fEaseOutLength; }
/** The length of time for the ease out. */
void SetEaseOutLength(hsScalar length) { fEaseOutLength = length; }
/** Minimum value reached in ease-out */
virtual hsScalar GetEaseOutMin() const { return fEaseOutMin; }
/** Minimum value reached in ease-out */
void SetEaseOutMin(hsScalar length) { fEaseOutMin = length; }
/** Maximum value reached in ease-in */
virtual hsScalar GetEaseOutMax() const { return fEaseOutMax; }
/** Maximum value reached in ease-in */
void SetEaseOutMax(hsScalar length) { fEaseOutMax = length; }
/** Animations can have multiple defined loop segments; these
are selected using animation control messages.
Each loop segment is named using markers in the notetrack. */
void AddLoop(const char *name, float start, float end);
/** Get the loop having the given name.
\param start will return the start time of the loop.
\param end will hold the end time of the loop */
bool GetLoop(const char *name, float &start, float &end) const;
/** Lets you get a loop by index instead of name. */
bool GetLoop(UInt32 num, float &start, float &end) const;
/** Returns the number of loops defined on this anim. */
UInt32 GetNumLoops() const;
/** Add a marker to the animation. Markers can be used
for callbacks or for goto comands. A marker is a simple
name/time tuple. */
void AddMarker(const char *name, float time);
/** Returns the time value of the marker named by name. */
float GetMarker(const char *name) const;
void CopyMarkerNames(std::vector<char*> &out);
/** Add a stop point to the animation. A stop point is a
"detent" for playback - if the animation is stopping
near a stop point and fading out, the stop point will
override the fade, so that the animation stops precisely
at the defined time. */
void AddStopPoint(hsScalar time);
/** Return the number of stop points defined for this animation. */
UInt32 NumStopPoints();
/** Get the time corresponding to the given stop point. Stop points
are numbered in the order they were added. */
hsScalar GetStopPoint(UInt32 i);
/** Function to check for a zero-length loop, and set it to
the anim's start/end instead */
void CheckLoop();
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plATCAnim );
GETINTERFACE_ANY( plATCAnim, plAGAnim );
// persistance
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
protected:
hsScalar fInitial; /// the position of the playback head
bool fAutoStart; /// does the animation start automatically?
hsScalar fLoopStart; /// when wrapping a loop, start here
hsScalar fLoopEnd; /// when you reach this point, loop back
bool fLoop; /// do we loop?
UInt8 fEaseInType; /// the type (none/linear/spline) of our ease-in curve, if any
UInt8 fEaseOutType; /// the type (none/linear/spline) of our ease-out curve, if any
hsScalar fEaseInLength; /// the length of time our ease-in curve takes
hsScalar fEaseInMin; /// minimum (initial) value of our ease-in
hsScalar fEaseInMax; /// maximum (final) value of our ease-in
hsScalar fEaseOutLength; /// the length of time our ease-out curve takes
hsScalar fEaseOutMin; /// minimum (final) value of our ease-out
hsScalar fEaseOutMax; /// maximum (initial) value of our ease-out
// a map from segment names to times
typedef std::map<const char *, float, stringSorter> MarkerMap;
MarkerMap fMarkers;
typedef std::map<const char *, std::pair<float,float>, stringSorter> LoopMap;
LoopMap fLoops;
typedef std::vector<hsScalar> ScalarMap;
ScalarMap fStopPoints; /// vector of stop points
};
/** \class plEmoteAnim
An animation to be used for emotes.
Automatically registers so that it can be played from the chat field.
*/
class plEmoteAnim : public plATCAnim
{
public:
plEmoteAnim();
plEmoteAnim(const char *animName, double begin, double end, float fadeIn, float fadeOut, BodyUsage bodyUsage);
BodyUsage GetBodyUsage() const;
hsScalar GetFadeIn() const;
hsScalar GetFadeOut() const;
CLASSNAME_REGISTER( plEmoteAnim );
GETINTERFACE_ANY( plEmoteAnim, plATCAnim );
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
BodyUsage fBodyUsage; // how much of the body is used by this emote?
hsScalar fFadeIn; // how fast to fade in the emote
hsScalar fFadeOut; // how fast to fade out the emote
};
//////////////////
// PLAGEGLOBALANIM
//////////////////
/** \class plAgeGlobalAnim
An animation that bases its current position on a variable that global to the age,
like weather, time of day, etc.
*/
class plAgeGlobalAnim : public plAGAnim
{
public:
plAgeGlobalAnim();
/** Construct with name, start time, and end time (within the max note track)
*/
plAgeGlobalAnim(const char *name, double begin, double end);
/** Destruct, freeing the underlying animation data. */
virtual ~plAgeGlobalAnim();
const char * GetGlobalVarName() const { return fGlobalVarName; }
void SetGlobalVarName(char *name);
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plAgeGlobalAnim );
GETINTERFACE_ANY( plAgeGlobalAnim, plAGAnim );
// persistance
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
protected:
char *fGlobalVarName; // Name of the SDL variable we animate on.
};
// USEFUL HELPER FUNCTIONS
bool GetStartToEndTransform(const plAGAnim *anim, hsMatrix44 *startToEnd, hsMatrix44 *endToStart, const char *channelName);
bool GetRelativeTransform(const plAGAnim *anim, double timeA, double timeB, hsMatrix44 *a2b, hsMatrix44 *b2a, const char *channelName);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,278 +1,278 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAGAnimInstance.h
\brief The animation class for the AniGraph animation system
\ingroup Avatar
\ingroup AniGraph
*/
#ifndef PLAGANIMINSTANCE_INC
#define PLAGANIMINSTANCE_INC
// disable warning C4503: dcorated name length exceeded, name was truncated
// disable warning C4786: symbol greater than 255 characters,
#pragma warning(disable: 4503 4786)
// templates
#include "hsStlUtils.h"
#include "hsStlSortUtils.h"
// local
#include "plScalarChannel.h"
// other
#include "plInterp/plAnimTimeConvert.h"
// declarations
class plAGChannel;
class plAGAnim;
class plAGMasterMod;
class plAGChannelApplicator;
class plOneShotCallbacks;
/////////////////
// PLAGANIMINSTANCE
/////////////////
/** \class plAGAnimInstance
Whenever we attach an animation to a scene object hierarchy, we
create an activation record -- a plAGAnimInstance -- that remembers
all the ephemeral state associated with animation
Since animations have many channels and may involve blend operations,
one of the primary responsibilities of this class is to keep track of
all the animation node graphs that were created by the invocation of
this animation.
*/
class plAGAnimInstance {
public:
/** Used for the fade commands to select what to fade. */
enum
{
kFadeBlend, /// Fade the blend strength
kFadeAmp, /// Fade the amplitude
} FadeType;
/** Default constructor. */
plAGAnimInstance();
/** Construct from an animation and a master modifier.
This attaches the animation channels to the channels of
the master modifier and creates all the bookkeeping structures
necessary to undo it later. */
plAGAnimInstance(plAGAnim * anim, plAGMasterMod * master, hsScalar blend, UInt16 blendPriority, hsBool cache, bool useAmplitude);
/** Destructor. Removes the animation from the scene objects it's attached to. */
virtual ~plAGAnimInstance();
/** Returns the animation that this instance mediates. */
const plAGAnim * GetAnimation() { return fAnimation; };
/** Returns the timeconvert object that controls the progress of time
in this animation. */
plAnimTimeConvert *GetTimeConvert() { return fTimeConvert; }
/** Set the speed of the animation. This is expressed as a fraction of
the speed with which the animation was defined. */
void SetSpeed(hsScalar speed) { if (fTimeConvert) fTimeConvert->SetSpeed(speed); };
// \{
/**
The current blend factor of the animation. This indicates the
priority of this animation as opposed to other animations which
were attached before it. Conceptually it may help to think of this
as a layer in an stack of animations, where the blend value is the
'opacity' of this animation relative to the ones below it.
1.0 represents full strength.
You may use values higher than 1.0, but this has not
yet been seen to have any practical utility whatsoever. Note that
even if an animation has a blend strength of 1.0, it may have another
animation on top/downstream from it that is masking it completely. */
hsScalar SetBlend(hsScalar blend);
hsScalar GetBlend();
// \}
/** Set the strength of the animation with respect to its 0th frame.
This can be used to dampen the motion of the animation.
Animations must be designed to use this: frame 0 of the animation
must be a reasonable "default pose" as it will be blended with the
current frame of the animation to produce the result. */
hsScalar SetAmplitude(hsScalar amp);
/** Get the current strength of the animation. */
hsScalar GetAmplitude();
/** Make this animation loop (or not.) Note that the instance can loop
or not without regard to whether the plAGAnim it is based on loops. */
void SetLoop(hsBool status);
/** Interpret and respond to an animation command message. /sa plAnimCmdMsg */
hsBool HandleCmd(plAnimCmdMsg *msg);
/** Start playback of the animation. You may optionally provide the a world
time, which is needed for synchronizing the animation's timeline
with the global timeline. If timeNow is -1 (the default,) the system
time will be polled */
void Start(double worldTimeNow = -1);
/** Stop playback of the animation. */
void Stop();
/** Move the playback head of the animation to a specific time.
Note that this time is in animation local time, not global time.
The "jump" parameter specifies whether or not to fire callbacks
that occur between the current time and the target time. */
void SetCurrentTime(hsScalar newLocalTime, hsBool jump = false);
/** Move the playback head by the specified relative amount within
the animation. This may cause looping. If the beginning or end
of the animation is reached an looping is not on, the movement
will pin.
\param jump if true, don't look for callbacks between old time and TRACKED_NEW */
void SeekRelative(hsScalar delta, hsBool jump);
/** Gradually fade the blend strength or amplitude of the animation.
\param goal is the desired blend strength
\param rate is in blend units per second
\type is either kFadeBlend or kFadeAmp */
void Fade(hsScalar goal, hsScalar rate, UInt8 type = kFadeBlend);
/** Fade the animation and detach it after the fade is complete.
Extremely useful for situations where the controlling logic
is terminating immediately but you want the animation to fade
out gradually.
\deprecated
*/
void FadeAndDetach(hsScalar goal, hsScalar rate);
/** Has the animation terminated of natural causes?
Primarily used to see if an animation has played all the
way to the end, but will also return true if the animation
was stopped with a stop command */
hsBool IsFinished();
/** Is the animation playback head positioned at the end. */
hsBool IsAtEnd();
/** Get the name of the underlying animation. */
const char * GetName();
/** Remove all channels from the master mode and remove us from
our master modifier.
Destructs the object! */
void Detach();
/** Remove all the instance's channels from the modifiers they're attached to.
Typically called by the master mod prior to destructing the instance. */
void DetachChannels();
/** Prune any unused branches out of the animation graph; add any
newly active branches back in. */
void Optimize();
/** Convert the given world time to local animation time.
May include the effects of looping or wraparound.
If the local time passes the end of the animation, the returned
time will be pinned appropriately. */
double WorldToAnimTime(double foo) { return (fTimeConvert ? fTimeConvert->WorldToAnimTimeNoUpdate(foo) : 0); };
/** Attach a sequence of callback messages to the animation instance.
Messages are each associated with a specific (local) time
in the animation and will be sent when playback passes that time. */
void AttachCallbacks(plOneShotCallbacks *callbacks);
void ProcessFade(hsScalar elapsed); // process any outstanding fades
void SearchForGlobals(); // Util function to setup SDL channels
protected:
/** Set up bookkeeping for a fade. */
void ISetupFade(hsScalar goal, hsScalar rate, bool detach, UInt8 type);
void IRegisterDetach(const char *channelName, plAGChannel *channel);
const plAGAnim * fAnimation;
plAGMasterMod * fMaster;
std::map<char *, plAGChannelApplicator *, stringISorter> fChannels;
typedef std::multimap<const char *, plAGChannel *> plDetachMap;
plDetachMap fManualDetachChannels;
std::vector<plAGChannel*> fCleanupChannels;
std::vector<plScalarSDLChannel*> fSDLChannels;
plScalarConstant fBlend; // blend factor vs. previous animations
plScalarConstant fAmplitude; // for animation scaling
// Each activation gets its own timeline.
plAnimTimeConvert *fTimeConvert;
hsBool fFadeBlend; /// we are fading the blend
hsScalar fFadeBlendGoal; /// what blend level we're trying to reach
hsScalar fFadeBlendRate; /// how fast are we fading in blend units per second (1 blend unit = full)
hsBool fFadeDetach; /// detach after fade is finished? (only used for blend fades)
hsBool fFadeAmp; /// we are fading the amplitude
hsScalar fFadeAmpGoal; /// amplitude we're trying to reach
hsScalar fFadeAmpRate; /// how faster we're fading in blend units per second
hsScalar ICalcFade(hsBool &fade, hsScalar curVal, hsScalar goal, hsScalar rate, hsScalar elapsed);
};
//#ifdef _DEBUG
//#define TRACK_AG_ALLOCS // for now, automatically track AG allocations in debug
//#endif
#ifdef TRACK_AG_ALLOCS
extern const char *gGlobalAnimName;
extern const char *gGlobalChannelName;
void RegisterAGAlloc(plAGChannel *object, const char *chanName, const char *animName, UInt16 classIndex);
void UnRegisterAGAlloc(plAGChannel *object);
void DumpAGAllocs();
#endif // TRACK_AG_ALLOCS
#endif // PLAGANIMINSTANCE_INC
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAGAnimInstance.h
\brief The animation class for the AniGraph animation system
\ingroup Avatar
\ingroup AniGraph
*/
#ifndef PLAGANIMINSTANCE_INC
#define PLAGANIMINSTANCE_INC
// disable warning C4503: dcorated name length exceeded, name was truncated
// disable warning C4786: symbol greater than 255 characters,
#pragma warning(disable: 4503 4786)
// templates
#include "hsStlUtils.h"
#include "hsStlSortUtils.h"
// local
#include "plScalarChannel.h"
// other
#include "plInterp/plAnimTimeConvert.h"
// declarations
class plAGChannel;
class plAGAnim;
class plAGMasterMod;
class plAGChannelApplicator;
class plOneShotCallbacks;
/////////////////
// PLAGANIMINSTANCE
/////////////////
/** \class plAGAnimInstance
Whenever we attach an animation to a scene object hierarchy, we
create an activation record -- a plAGAnimInstance -- that remembers
all the ephemeral state associated with animation
Since animations have many channels and may involve blend operations,
one of the primary responsibilities of this class is to keep track of
all the animation node graphs that were created by the invocation of
this animation.
*/
class plAGAnimInstance {
public:
/** Used for the fade commands to select what to fade. */
enum
{
kFadeBlend, /// Fade the blend strength
kFadeAmp, /// Fade the amplitude
} FadeType;
/** Default constructor. */
plAGAnimInstance();
/** Construct from an animation and a master modifier.
This attaches the animation channels to the channels of
the master modifier and creates all the bookkeeping structures
necessary to undo it later. */
plAGAnimInstance(plAGAnim * anim, plAGMasterMod * master, hsScalar blend, UInt16 blendPriority, hsBool cache, bool useAmplitude);
/** Destructor. Removes the animation from the scene objects it's attached to. */
virtual ~plAGAnimInstance();
/** Returns the animation that this instance mediates. */
const plAGAnim * GetAnimation() { return fAnimation; };
/** Returns the timeconvert object that controls the progress of time
in this animation. */
plAnimTimeConvert *GetTimeConvert() { return fTimeConvert; }
/** Set the speed of the animation. This is expressed as a fraction of
the speed with which the animation was defined. */
void SetSpeed(hsScalar speed) { if (fTimeConvert) fTimeConvert->SetSpeed(speed); };
// \{
/**
The current blend factor of the animation. This indicates the
priority of this animation as opposed to other animations which
were attached before it. Conceptually it may help to think of this
as a layer in an stack of animations, where the blend value is the
'opacity' of this animation relative to the ones below it.
1.0 represents full strength.
You may use values higher than 1.0, but this has not
yet been seen to have any practical utility whatsoever. Note that
even if an animation has a blend strength of 1.0, it may have another
animation on top/downstream from it that is masking it completely. */
hsScalar SetBlend(hsScalar blend);
hsScalar GetBlend();
// \}
/** Set the strength of the animation with respect to its 0th frame.
This can be used to dampen the motion of the animation.
Animations must be designed to use this: frame 0 of the animation
must be a reasonable "default pose" as it will be blended with the
current frame of the animation to produce the result. */
hsScalar SetAmplitude(hsScalar amp);
/** Get the current strength of the animation. */
hsScalar GetAmplitude();
/** Make this animation loop (or not.) Note that the instance can loop
or not without regard to whether the plAGAnim it is based on loops. */
void SetLoop(hsBool status);
/** Interpret and respond to an animation command message. /sa plAnimCmdMsg */
hsBool HandleCmd(plAnimCmdMsg *msg);
/** Start playback of the animation. You may optionally provide the a world
time, which is needed for synchronizing the animation's timeline
with the global timeline. If timeNow is -1 (the default,) the system
time will be polled */
void Start(double worldTimeNow = -1);
/** Stop playback of the animation. */
void Stop();
/** Move the playback head of the animation to a specific time.
Note that this time is in animation local time, not global time.
The "jump" parameter specifies whether or not to fire callbacks
that occur between the current time and the target time. */
void SetCurrentTime(hsScalar newLocalTime, hsBool jump = false);
/** Move the playback head by the specified relative amount within
the animation. This may cause looping. If the beginning or end
of the animation is reached an looping is not on, the movement
will pin.
\param jump if true, don't look for callbacks between old time and TRACKED_NEW */
void SeekRelative(hsScalar delta, hsBool jump);
/** Gradually fade the blend strength or amplitude of the animation.
\param goal is the desired blend strength
\param rate is in blend units per second
\type is either kFadeBlend or kFadeAmp */
void Fade(hsScalar goal, hsScalar rate, UInt8 type = kFadeBlend);
/** Fade the animation and detach it after the fade is complete.
Extremely useful for situations where the controlling logic
is terminating immediately but you want the animation to fade
out gradually.
\deprecated
*/
void FadeAndDetach(hsScalar goal, hsScalar rate);
/** Has the animation terminated of natural causes?
Primarily used to see if an animation has played all the
way to the end, but will also return true if the animation
was stopped with a stop command */
hsBool IsFinished();
/** Is the animation playback head positioned at the end. */
hsBool IsAtEnd();
/** Get the name of the underlying animation. */
const char * GetName();
/** Remove all channels from the master mode and remove us from
our master modifier.
Destructs the object! */
void Detach();
/** Remove all the instance's channels from the modifiers they're attached to.
Typically called by the master mod prior to destructing the instance. */
void DetachChannels();
/** Prune any unused branches out of the animation graph; add any
newly active branches back in. */
void Optimize();
/** Convert the given world time to local animation time.
May include the effects of looping or wraparound.
If the local time passes the end of the animation, the returned
time will be pinned appropriately. */
double WorldToAnimTime(double foo) { return (fTimeConvert ? fTimeConvert->WorldToAnimTimeNoUpdate(foo) : 0); };
/** Attach a sequence of callback messages to the animation instance.
Messages are each associated with a specific (local) time
in the animation and will be sent when playback passes that time. */
void AttachCallbacks(plOneShotCallbacks *callbacks);
void ProcessFade(hsScalar elapsed); // process any outstanding fades
void SearchForGlobals(); // Util function to setup SDL channels
protected:
/** Set up bookkeeping for a fade. */
void ISetupFade(hsScalar goal, hsScalar rate, bool detach, UInt8 type);
void IRegisterDetach(const char *channelName, plAGChannel *channel);
const plAGAnim * fAnimation;
plAGMasterMod * fMaster;
std::map<char *, plAGChannelApplicator *, stringISorter> fChannels;
typedef std::multimap<const char *, plAGChannel *> plDetachMap;
plDetachMap fManualDetachChannels;
std::vector<plAGChannel*> fCleanupChannels;
std::vector<plScalarSDLChannel*> fSDLChannels;
plScalarConstant fBlend; // blend factor vs. previous animations
plScalarConstant fAmplitude; // for animation scaling
// Each activation gets its own timeline.
plAnimTimeConvert *fTimeConvert;
hsBool fFadeBlend; /// we are fading the blend
hsScalar fFadeBlendGoal; /// what blend level we're trying to reach
hsScalar fFadeBlendRate; /// how fast are we fading in blend units per second (1 blend unit = full)
hsBool fFadeDetach; /// detach after fade is finished? (only used for blend fades)
hsBool fFadeAmp; /// we are fading the amplitude
hsScalar fFadeAmpGoal; /// amplitude we're trying to reach
hsScalar fFadeAmpRate; /// how faster we're fading in blend units per second
hsScalar ICalcFade(hsBool &fade, hsScalar curVal, hsScalar goal, hsScalar rate, hsScalar elapsed);
};
//#ifdef _DEBUG
//#define TRACK_AG_ALLOCS // for now, automatically track AG allocations in debug
//#endif
#ifdef TRACK_AG_ALLOCS
extern const char *gGlobalAnimName;
extern const char *gGlobalChannelName;
void RegisterAGAlloc(plAGChannel *object, const char *chanName, const char *animName, UInt16 classIndex);
void UnRegisterAGAlloc(plAGChannel *object);
void DumpAGAllocs();
#endif // TRACK_AG_ALLOCS
#endif // PLAGANIMINSTANCE_INC

View File

@ -1,165 +1,165 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAGApplicator.h"
#include "plAGModifier.h"
#include "hsResMgr.h"
#include "hsUtils.h"
// ctor --------
// -----
plAGApplicator::plAGApplicator()
: fChannel(nil),
fChannelName(nil),
fEnabled(true)
{
};
// ctor -------------------------------
// -----
plAGApplicator::plAGApplicator(const char *channelName)
: fChannel(nil),
fEnabled(true)
{
fChannelName = hsStrcpy(channelName);
};
plAGApplicator::~plAGApplicator()
{
if(fChannelName)
delete[] fChannelName;
}
void plAGApplicator::Apply(const plAGModifier *mod, double time, hsBool force)
{
if (fEnabled || force)
IApply(mod, time);
}
void plAGApplicator::SetChannelName(const char *name)
{
if(name)
fChannelName = hsStrcpy(name);
};
const char * plAGApplicator::GetChannelName()
{
return fChannelName;
};
plAGChannel *plAGApplicator::MergeChannel(plAGApplicator *app, plAGChannel *channel,
plScalarChannel *blend, int blendPriority)
{
plAGChannel *result = nil;
if(fChannel)
{
if (CanCombine(app))
result = fChannel->MakeCombine(channel);
else if (CanBlend(app))
result = fChannel->MakeBlend(channel, blend, blendPriority);
} else {
result = channel;
}
if (result && result != fChannel)
SetChannel(result);
return result;
}
plAGApplicator *plAGApplicator::CloneWithChannel(plAGChannel *channel)
{
plAGApplicator *app = plAGApplicator::ConvertNoRef(plFactory::Create(ClassIndex()));
app->SetChannel(channel);
app->Enable(fEnabled);
app->SetChannelName(fChannelName);
return app;
}
hsBool plAGApplicator::CanBlend(plAGApplicator *app)
{
UInt16 ourClass = ClassIndex();
UInt16 theirClass = app->ClassIndex();
return(ourClass == theirClass);
// return(this->HasBaseClass(theirClass)
// || app->HasBaseClass(ourClass));
}
void plAGApplicator::Write(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Write(stream, mgr);
stream->WriteBool(fEnabled);
stream->WriteSafeString(fChannelName);
}
void plAGApplicator::Read(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Read(stream, mgr);
fEnabled = stream->ReadBool();
fChannel = nil; // Whatever is reading this applicator in should know what channel to assign it
fChannelName = stream->ReadSafeString();
}
// IGETxI
// Gain access to of our modifier's target's interfaces.
// This is technically in violation of the principle that only modifiers can get non-const
// reference to their target's interfaces,
// BUT since the plAGApplicator architecture is wholly "owned" by the AGModifier, this
// seemed the most graceful way to do it without const_cast or modifying plModifier or plSceneObject
// IGETAI
plAudioInterface * plAGApplicator::IGetAI(const plAGModifier *modifier) const
{
return modifier->LeakAI();
}
// IGETCI
plCoordinateInterface * plAGApplicator::IGetCI(const plAGModifier* modifier) const
{
return modifier->LeakCI();
}
// IGETDI
plDrawInterface * plAGApplicator::IGetDI(const plAGModifier * modifier) const
{
return modifier->LeakDI();
}
// IGETSI
plSimulationInterface * plAGApplicator::IGetSI(const plAGModifier * modifier) const
{
return modifier->LeakSI();
}
plObjInterface * plAGApplicator::IGetGI(const plAGModifier * modifier, UInt16 classIdx) const
{
return modifier->LeakGI(classIdx);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAGApplicator.h"
#include "plAGModifier.h"
#include "hsResMgr.h"
#include "hsUtils.h"
// ctor --------
// -----
plAGApplicator::plAGApplicator()
: fChannel(nil),
fChannelName(nil),
fEnabled(true)
{
};
// ctor -------------------------------
// -----
plAGApplicator::plAGApplicator(const char *channelName)
: fChannel(nil),
fEnabled(true)
{
fChannelName = hsStrcpy(channelName);
};
plAGApplicator::~plAGApplicator()
{
if(fChannelName)
delete[] fChannelName;
}
void plAGApplicator::Apply(const plAGModifier *mod, double time, hsBool force)
{
if (fEnabled || force)
IApply(mod, time);
}
void plAGApplicator::SetChannelName(const char *name)
{
if(name)
fChannelName = hsStrcpy(name);
};
const char * plAGApplicator::GetChannelName()
{
return fChannelName;
};
plAGChannel *plAGApplicator::MergeChannel(plAGApplicator *app, plAGChannel *channel,
plScalarChannel *blend, int blendPriority)
{
plAGChannel *result = nil;
if(fChannel)
{
if (CanCombine(app))
result = fChannel->MakeCombine(channel);
else if (CanBlend(app))
result = fChannel->MakeBlend(channel, blend, blendPriority);
} else {
result = channel;
}
if (result && result != fChannel)
SetChannel(result);
return result;
}
plAGApplicator *plAGApplicator::CloneWithChannel(plAGChannel *channel)
{
plAGApplicator *app = plAGApplicator::ConvertNoRef(plFactory::Create(ClassIndex()));
app->SetChannel(channel);
app->Enable(fEnabled);
app->SetChannelName(fChannelName);
return app;
}
hsBool plAGApplicator::CanBlend(plAGApplicator *app)
{
UInt16 ourClass = ClassIndex();
UInt16 theirClass = app->ClassIndex();
return(ourClass == theirClass);
// return(this->HasBaseClass(theirClass)
// || app->HasBaseClass(ourClass));
}
void plAGApplicator::Write(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Write(stream, mgr);
stream->WriteBool(fEnabled);
stream->WriteSafeString(fChannelName);
}
void plAGApplicator::Read(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Read(stream, mgr);
fEnabled = stream->ReadBool();
fChannel = nil; // Whatever is reading this applicator in should know what channel to assign it
fChannelName = stream->ReadSafeString();
}
// IGETxI
// Gain access to of our modifier's target's interfaces.
// This is technically in violation of the principle that only modifiers can get non-const
// reference to their target's interfaces,
// BUT since the plAGApplicator architecture is wholly "owned" by the AGModifier, this
// seemed the most graceful way to do it without const_cast or modifying plModifier or plSceneObject
// IGETAI
plAudioInterface * plAGApplicator::IGetAI(const plAGModifier *modifier) const
{
return modifier->LeakAI();
}
// IGETCI
plCoordinateInterface * plAGApplicator::IGetCI(const plAGModifier* modifier) const
{
return modifier->LeakCI();
}
// IGETDI
plDrawInterface * plAGApplicator::IGetDI(const plAGModifier * modifier) const
{
return modifier->LeakDI();
}
// IGETSI
plSimulationInterface * plAGApplicator::IGetSI(const plAGModifier * modifier) const
{
return modifier->LeakSI();
}
plObjInterface * plAGApplicator::IGetGI(const plAGModifier * modifier, UInt16 classIdx) const
{
return modifier->LeakGI(classIdx);
}

View File

@ -1,157 +1,157 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAGApplicator_h
#define plAGApplicator_h
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plAudioInterface;
class plCoordinateInterface;
class plDrawInterface;
class plSimulationInterface;
class plObjInterface;
class plAGModifier;
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "pnFactory/plCreatable.h"
#include "plAvDefs.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
class plAGChannel;
class plScalarChannel;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plAGApplicator
Takes the end of a channel tree and applies it to a scene object.
A transform applicator takes a matrix-typed-tree and applies it to
the transform of the scene object.
Other applicators might take floats and use them to animate alpha channels,
etc. */
class plAGApplicator : public plCreatable
{
public:
// -- methods --
/** Base constructor. */
plAGApplicator();
plAGApplicator(const char *channelName);
virtual ~plAGApplicator();
/** Return our single input channel. Applicators only ever
have a single input channel; you can always use blend
or combine nodes to merge channels before routing
them into the applicator. */
plAGChannel *GetChannel() { return fChannel; }
/** Set our input channel. Does not free the previous input channel. */
void SetChannel(plAGChannel *channel) { fChannel = channel; }
void SetChannelName(const char *name);
const char * GetChannelName();
/** Optionally suppress the action of this applicator.
The applicator can still be forced to apply using the force
paramater of the Apply function. */
void Enable(hsBool on) { fEnabled = on; }
/** Make a shallow copy of the applicator. Keep the same input channel
but do not clone the input channel. */
virtual plAGApplicator *CloneWithChannel(plAGChannel *channel);
/** What animation type do we have? Used to determine whether two
applicators are trying to animate the same thing or whether they
can coexist peacefully. */
virtual plAGPinType GetPinType() { return kAGPinUnknown; }
// Join the incoming channel (if possible) to ours
/** Determine whether the given applicator can be blended to ours. If so, this
would be effected by pulling the input channel from the other applicator,
blending it with our input channel via a new blend node, attaching that blend
node as our new input, and throwing the other applicator away. */
virtual hsBool CanBlend(plAGApplicator *app);
/** Combine the two applicators if possible. \sa CanBlend */
virtual plAGChannel * MergeChannel(plAGApplicator *app, plAGChannel *channel,
plScalarChannel *blend, int blendPriority);
/** \bug It makes no sense for an applicator to combine because combination always
results in a different data type, which would require a different applicator. */
virtual hsBool CanCombine(plAGApplicator *app) { return false; }
/** Apply our channel's data to the scene object, via the modifier.
This is the only function that actually changes perceivable scene state. */
void Apply(const plAGModifier *mod, double time, hsBool force = false); // Apply our channel's data to the modifier
// this is pretty much a HACK to support applicators that want to stick around when
// their channel is gone so they can operate on the next channel that comes in
// the RIGHT way to do this is to make applicators support the Detach() protocol just
// like channels...
virtual hsBool AutoDelete() { return true; } // should we remove it when its input channel is gone?
// PlOP
CLASSNAME_REGISTER( plAGApplicator );
GETINTERFACE_ANY( plAGApplicator, plCreatable );
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
protected:
// -- methods --
virtual void IApply(const plAGModifier *mod, double time) = 0;
// give derived classes access to the object interfaces
plAudioInterface * IGetAI(const plAGModifier *modifier) const;
plCoordinateInterface * IGetCI(const plAGModifier *modifier) const;
plDrawInterface * IGetDI(const plAGModifier *modifier) const;
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;
char *fChannelName;
};
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAGApplicator_h
#define plAGApplicator_h
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plAudioInterface;
class plCoordinateInterface;
class plDrawInterface;
class plSimulationInterface;
class plObjInterface;
class plAGModifier;
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "pnFactory/plCreatable.h"
#include "plAvDefs.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
class plAGChannel;
class plScalarChannel;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plAGApplicator
Takes the end of a channel tree and applies it to a scene object.
A transform applicator takes a matrix-typed-tree and applies it to
the transform of the scene object.
Other applicators might take floats and use them to animate alpha channels,
etc. */
class plAGApplicator : public plCreatable
{
public:
// -- methods --
/** Base constructor. */
plAGApplicator();
plAGApplicator(const char *channelName);
virtual ~plAGApplicator();
/** Return our single input channel. Applicators only ever
have a single input channel; you can always use blend
or combine nodes to merge channels before routing
them into the applicator. */
plAGChannel *GetChannel() { return fChannel; }
/** Set our input channel. Does not free the previous input channel. */
void SetChannel(plAGChannel *channel) { fChannel = channel; }
void SetChannelName(const char *name);
const char * GetChannelName();
/** Optionally suppress the action of this applicator.
The applicator can still be forced to apply using the force
paramater of the Apply function. */
void Enable(hsBool on) { fEnabled = on; }
/** Make a shallow copy of the applicator. Keep the same input channel
but do not clone the input channel. */
virtual plAGApplicator *CloneWithChannel(plAGChannel *channel);
/** What animation type do we have? Used to determine whether two
applicators are trying to animate the same thing or whether they
can coexist peacefully. */
virtual plAGPinType GetPinType() { return kAGPinUnknown; }
// Join the incoming channel (if possible) to ours
/** Determine whether the given applicator can be blended to ours. If so, this
would be effected by pulling the input channel from the other applicator,
blending it with our input channel via a new blend node, attaching that blend
node as our new input, and throwing the other applicator away. */
virtual hsBool CanBlend(plAGApplicator *app);
/** Combine the two applicators if possible. \sa CanBlend */
virtual plAGChannel * MergeChannel(plAGApplicator *app, plAGChannel *channel,
plScalarChannel *blend, int blendPriority);
/** \bug It makes no sense for an applicator to combine because combination always
results in a different data type, which would require a different applicator. */
virtual hsBool CanCombine(plAGApplicator *app) { return false; }
/** Apply our channel's data to the scene object, via the modifier.
This is the only function that actually changes perceivable scene state. */
void Apply(const plAGModifier *mod, double time, hsBool force = false); // Apply our channel's data to the modifier
// this is pretty much a HACK to support applicators that want to stick around when
// their channel is gone so they can operate on the next channel that comes in
// the RIGHT way to do this is to make applicators support the Detach() protocol just
// like channels...
virtual hsBool AutoDelete() { return true; } // should we remove it when its input channel is gone?
// PlOP
CLASSNAME_REGISTER( plAGApplicator );
GETINTERFACE_ANY( plAGApplicator, plCreatable );
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
protected:
// -- methods --
virtual void IApply(const plAGModifier *mod, double time) = 0;
// give derived classes access to the object interfaces
plAudioInterface * IGetAI(const plAGModifier *modifier) const;
plCoordinateInterface * IGetCI(const plAGModifier *modifier) const;
plDrawInterface * IGetDI(const plAGModifier *modifier) const;
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;
char *fChannelName;
};
#endif

View File

@ -1,112 +1,112 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plAGChannel.h"
// local
#include "plAGModifier.h"
// global
#include "hsTypes.h"
#include "hsResMgr.h"
#include "plAGAnimInstance.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// plAGChannel
//
/////////////////////////////////////////////////////////////////////////////////////////
plAGChannel::plAGChannel()
{
#ifdef TRACK_AG_ALLOCS
fName = gGlobalAnimName;
RegisterAGAlloc(this, gGlobalChannelName, gGlobalAnimName, this->ClassIndex());
#else // TRACK_AG_ALLOCS
fName = nil;
#endif // TRACK_AG_ALLOCS
}
// DTOR
plAGChannel::~plAGChannel()
{
// we do not own the "fName" string, so don't delete it!
#ifdef TRACK_AG_ALLOCS
UnRegisterAGAlloc(this);
#endif // TRACK_AG_ALLOCS
}
// MAKECOMBINE
plAGChannel * plAGChannel::MakeCombine(plAGChannel *channelA)
{
return nil;
}
// MAKEBLEND
plAGChannel * plAGChannel::MakeBlend(plAGChannel *channelA, plScalarChannel *blend, int blendPriority)
{
return nil;
}
// DETACH
// If the channel being detached is us, let our caller know to replace us
// by return NIL.
plAGChannel * plAGChannel::Detach(plAGChannel *channel)
{
if (this == channel)
{
return nil;
} else {
return this;
}
}
// OPTIMIZE
plAGChannel * plAGChannel::Optimize(double time)
{
// the basic channel can't optimize...
return this;
}
// WRITE
void plAGChannel::Write(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Write(stream, mgr);
stream->WriteSafeString(fName);
}
// READ
void plAGChannel::Read(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Read(stream, mgr);
fName = stream->ReadSafeString();
}
////////////////////////////////////////////////////////////////////////////////////
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plAGChannel.h"
// local
#include "plAGModifier.h"
// global
#include "hsTypes.h"
#include "hsResMgr.h"
#include "plAGAnimInstance.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// plAGChannel
//
/////////////////////////////////////////////////////////////////////////////////////////
plAGChannel::plAGChannel()
{
#ifdef TRACK_AG_ALLOCS
fName = gGlobalAnimName;
RegisterAGAlloc(this, gGlobalChannelName, gGlobalAnimName, this->ClassIndex());
#else // TRACK_AG_ALLOCS
fName = nil;
#endif // TRACK_AG_ALLOCS
}
// DTOR
plAGChannel::~plAGChannel()
{
// we do not own the "fName" string, so don't delete it!
#ifdef TRACK_AG_ALLOCS
UnRegisterAGAlloc(this);
#endif // TRACK_AG_ALLOCS
}
// MAKECOMBINE
plAGChannel * plAGChannel::MakeCombine(plAGChannel *channelA)
{
return nil;
}
// MAKEBLEND
plAGChannel * plAGChannel::MakeBlend(plAGChannel *channelA, plScalarChannel *blend, int blendPriority)
{
return nil;
}
// DETACH
// If the channel being detached is us, let our caller know to replace us
// by return NIL.
plAGChannel * plAGChannel::Detach(plAGChannel *channel)
{
if (this == channel)
{
return nil;
} else {
return this;
}
}
// OPTIMIZE
plAGChannel * plAGChannel::Optimize(double time)
{
// the basic channel can't optimize...
return this;
}
// WRITE
void plAGChannel::Write(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Write(stream, mgr);
stream->WriteSafeString(fName);
}
// READ
void plAGChannel::Read(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Read(stream, mgr);
fName = stream->ReadSafeString();
}
////////////////////////////////////////////////////////////////////////////////////

View File

@ -1,182 +1,182 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAGChannel.h
\brief The animation class for the AniGraph animation system
WHAT'S AG STAND FOR?
AG stands for animation graph. It's a directed acyclic graph of animation data sources and operations.
WHAT'S A CHANNEL?
A channel is a stream of animation data.
A channel is a node in an animation graph.
Animation data can come from anything; keyframes, IK, physics, etc.
Channels are often grouped together using blending nodes.
Blending nodes are also a type of channel.
See where I'm going with this?
HOW IS THIS DIFFERENT FROM PLCONTROLLER?
It's very similar, but it's designed to be extremely lightweight; animation graphs are set up and torn down
quickly and with great frequency. They are not persistent, and their only state (besides cache)
is their interconnectedness.
HOW DO THEY GET SAVED?
Their client must recreate them at read/load time. Since they are stateless, all information necessary
to recreate them is necessarily held by the client.
ARE THEY REFERENCE COUNTED?
No. The entire graph is owned by the creator.
Deleting the top node of a graph deletes the entire graph.
If we decide we want to share subgraphs, we'll add reference counting -- easy since cycles are illegal
HOW DO THEY INTEGRATE WITH PLCONTROLLERS?
Once we decide the animation graph approach is workable and effective, we'll combine the plController
concept with the plAGChannel concept.
Until then, there will be a handful of channel types that adapt controllers into animation graphs.
WHAT DOES "COMBINE" MEAN?
Merging more than one types of animation data into a single output that preserves the value
of both.
WHAT DOES "BLEND" MEAN?
Merging two similar types of animation data using a weight to "fade" from one to the other
WHAT IS ZEROSTATE?
This is a static channel that always returns the value at time zero. It is used as a reference for animation
scaling (amplitude).
WHAT'S AN APPLICATOR?
In order to cut down on the number of derived channel classes for different Value() and Apply() behaviors,
applicators were created. At the end of each graph is an applicator, which specifies what should be done
with the result of a call to Value().
\ingroup Avatar
\ingroup AniGraph
*/
#ifndef PLAGCHANNEL_H
#define PLAGCHANNEL_H
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "pnFactory/plCreatable.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plAGModifier;
class plAnimTimeConvert;
class plAGChannel;
class plScalarChannel;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plAGChannel
An object that emits data of a specific type. Fundamental building
block of the animation graph. */
class plAGChannel : public plCreatable
{
public:
// -- methods --
/** Default constructor for the base class. */
plAGChannel();
/** Free an allocated name. Does not release any upstream nodes. */
virtual ~plAGChannel();
// AG PROTOCOL
/** Combine the given channel with this channel, allocating and returning
a new node which does the combination. It's up to the caller to
manage the lifetime of the new node. */
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
/** Blend the given channel with this channel, using a third channel (which
must output a float/scalar value) to crossfade between the two.
As the blendChannel varies, the blend will vary. */
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * blendChannel, int blendPriority);
/** Create a "static clone" of this channel which always returns this channel's
value at time zero. */
virtual plAGChannel * MakeZeroState() = 0;
/** If we're potentially sharing this channel with other plAGMasterMods, we'll
want to insert a channel in the graph for cache info. This function returns
either the cache channel (replacing us) or ourself. */
virtual plAGChannel * MakeCacheChannel(plAnimTimeConvert *atc) { return this; }
/** Create a new channel which converts global time to local time
and attach it downstream from this channel. This allows you to
convert an animation from one timespace to another - critical for
blending.
local-time-animation <-- timescale <-- world-time-animation */
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource) = 0;
/** Is the animation moving at the given world time? Takes into account
start/stop messages that haven't been applied yet, ease curves, etc. */
virtual hsBool IsStoppedAt(double wSecs) { return true; }
/** Detach the given channel from our graph. If this is the channel in
question, returns any upstream channels so they can be reattached.
If this is not the channel in question, passes the request upstream
and does any reattachment necessary. */
virtual plAGChannel * Detach(plAGChannel * channel);
/** Return the optimized version of this channel. May be a completely
different channel; will collapse out inactive subgraphs. */
virtual plAGChannel * Optimize(double time);
// \{
/** The name of the channel is used to dynamically attach to sub-parts of an
object. */
virtual const char * GetName() { return fName; };
virtual void SetName(char * name) { fName = name; };
// \}
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plAGChannel );
GETINTERFACE_ANY( plAGChannel, plCreatable );
// persistence
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
protected:
const char * fName;
};
#endif PLAGCHANNEL_H
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAGChannel.h
\brief The animation class for the AniGraph animation system
WHAT'S AG STAND FOR?
AG stands for animation graph. It's a directed acyclic graph of animation data sources and operations.
WHAT'S A CHANNEL?
A channel is a stream of animation data.
A channel is a node in an animation graph.
Animation data can come from anything; keyframes, IK, physics, etc.
Channels are often grouped together using blending nodes.
Blending nodes are also a type of channel.
See where I'm going with this?
HOW IS THIS DIFFERENT FROM PLCONTROLLER?
It's very similar, but it's designed to be extremely lightweight; animation graphs are set up and torn down
quickly and with great frequency. They are not persistent, and their only state (besides cache)
is their interconnectedness.
HOW DO THEY GET SAVED?
Their client must recreate them at read/load time. Since they are stateless, all information necessary
to recreate them is necessarily held by the client.
ARE THEY REFERENCE COUNTED?
No. The entire graph is owned by the creator.
Deleting the top node of a graph deletes the entire graph.
If we decide we want to share subgraphs, we'll add reference counting -- easy since cycles are illegal
HOW DO THEY INTEGRATE WITH PLCONTROLLERS?
Once we decide the animation graph approach is workable and effective, we'll combine the plController
concept with the plAGChannel concept.
Until then, there will be a handful of channel types that adapt controllers into animation graphs.
WHAT DOES "COMBINE" MEAN?
Merging more than one types of animation data into a single output that preserves the value
of both.
WHAT DOES "BLEND" MEAN?
Merging two similar types of animation data using a weight to "fade" from one to the other
WHAT IS ZEROSTATE?
This is a static channel that always returns the value at time zero. It is used as a reference for animation
scaling (amplitude).
WHAT'S AN APPLICATOR?
In order to cut down on the number of derived channel classes for different Value() and Apply() behaviors,
applicators were created. At the end of each graph is an applicator, which specifies what should be done
with the result of a call to Value().
\ingroup Avatar
\ingroup AniGraph
*/
#ifndef PLAGCHANNEL_H
#define PLAGCHANNEL_H
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "pnFactory/plCreatable.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plAGModifier;
class plAnimTimeConvert;
class plAGChannel;
class plScalarChannel;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plAGChannel
An object that emits data of a specific type. Fundamental building
block of the animation graph. */
class plAGChannel : public plCreatable
{
public:
// -- methods --
/** Default constructor for the base class. */
plAGChannel();
/** Free an allocated name. Does not release any upstream nodes. */
virtual ~plAGChannel();
// AG PROTOCOL
/** Combine the given channel with this channel, allocating and returning
a new node which does the combination. It's up to the caller to
manage the lifetime of the new node. */
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
/** Blend the given channel with this channel, using a third channel (which
must output a float/scalar value) to crossfade between the two.
As the blendChannel varies, the blend will vary. */
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * blendChannel, int blendPriority);
/** Create a "static clone" of this channel which always returns this channel's
value at time zero. */
virtual plAGChannel * MakeZeroState() = 0;
/** If we're potentially sharing this channel with other plAGMasterMods, we'll
want to insert a channel in the graph for cache info. This function returns
either the cache channel (replacing us) or ourself. */
virtual plAGChannel * MakeCacheChannel(plAnimTimeConvert *atc) { return this; }
/** Create a new channel which converts global time to local time
and attach it downstream from this channel. This allows you to
convert an animation from one timespace to another - critical for
blending.
local-time-animation <-- timescale <-- world-time-animation */
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource) = 0;
/** Is the animation moving at the given world time? Takes into account
start/stop messages that haven't been applied yet, ease curves, etc. */
virtual hsBool IsStoppedAt(double wSecs) { return true; }
/** Detach the given channel from our graph. If this is the channel in
question, returns any upstream channels so they can be reattached.
If this is not the channel in question, passes the request upstream
and does any reattachment necessary. */
virtual plAGChannel * Detach(plAGChannel * channel);
/** Return the optimized version of this channel. May be a completely
different channel; will collapse out inactive subgraphs. */
virtual plAGChannel * Optimize(double time);
// \{
/** The name of the channel is used to dynamically attach to sub-parts of an
object. */
virtual const char * GetName() { return fName; };
virtual void SetName(char * name) { fName = name; };
// \}
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plAGChannel );
GETINTERFACE_ANY( plAGChannel, plCreatable );
// persistence
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
protected:
const char * fName;
};
#endif PLAGCHANNEL_H

File diff suppressed because it is too large Load Diff

View File

@ -1,252 +1,252 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAGMasterMod.h
\brief The animation class for the AniGraph animation system
\ingroup Avatar
\ingroup AniGraph
*/
#ifndef PLAGMASTERMOD_INC
#define PLAGMASTERMOD_INC
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "pnModifier/plModifier.h"
#include "plAGChannel.h"
#include "plAvDefs.h"
#include "pnKeyedObject/plMsgForwarder.h"
// templates
#include "hsStlUtils.h"
#include "hsStlSortUtils.h"
class plAGModifier;
class plAGAnimInstance;
class plAGAnim;
class plATCAnim;
class plAGMasterSDLModifier;
////////////////
//
// PLAGMASTERMOD
//
////////////////
/** \class plAGMasterMod
A modifier which can apply animations to scene objects.
Works together with a plAGModifier, which can apply animation to a
single scene object. A master modifier hooks up to a family of
ag modifiers to do its job.
An animation (plAGAnim) can have many different channels, but the
user can just pass it to a single master mod to apply it to all the
channels owned by that master. The master will take care of hooking
each channel up to an ag modifier.
The goal is to make an animation a conceptually (and practically) simple
object to work with, whether or not it has multiple channels.
\sa plAGAnim, plAGAnimInstance, plAGModifier
*/
class plAGMasterMod : public plModifier
{
friend class plAGMasterSDLModifier;
public:
/** Default constructor. Primarily for use by the class factory. */
plAGMasterMod();
/** Free the name and any other miscellany. */
virtual ~plAGMasterMod();
/** Find an individual plAGModifier of the given name under our control. */
plAGModifier * GetChannelMod(const char * name, hsBool dontCache = false) const;
/** \name Managing Animations */
// \{
// AGANIM PROTOCOL
/** Attach the given animation object with the given blend factor.
If there's no animation already attached to blend with, the
animation will be attached at full strength. */
plAGAnimInstance *AttachAnimationBlended(plAGAnim *anim, hsScalar blendFactor = 0,
UInt16 blendPriority = kAGMedBlendPriority,
hsBool cache = false);
/** Look up the given animation by name and attach it
with the given blend factor. */
plAGAnimInstance *AttachAnimationBlended(const char *name, hsScalar blendFactor = 0,
UInt16 blendPriority = kAGMedBlendPriority,
hsBool cache = false);
/** Play a simple anim (one that doesn't affect root) once and auto detach.
Intended for Zandi's facial animations that run seperate from the behaviors. */
void PlaySimpleAnim(const char *name);
/** Detach the given animation instance. Does nothing
if the instance is not managed by this master mod. */
void DetachAnimation(plAGAnimInstance *instance);
void DetachAllAnimations();
/** Detach the given animation by name. Searches for
any instances derived from animations with the
given name and removes them. */
void DetachAnimation(const char *name);
// \}
/** Print the current animation stack to the console.
Will list all the animations and their blend strengths.
Animations later in the list will mask animations earlier
in the list. */
void DumpCurrentAnims(const char *header);
/** Find and return any animation instances with the
given name on this master modifer. */
plAGAnimInstance *FindAnimInstance(const char *name);
/** Return the Ith animation instance, based on blend
order. Of dubious utility, but, y'know. */
plAGAnimInstance *GetAnimInstance(int i);
/** Attach the animation if it's not already attached. If
it is attached, return the instance.
Note that if it's attached by this function, it
will be on top of the stack, but if it was already
attached, it could be anywhere, including buried under
a bunch of other animations. If it's important that it be
on top of the stack, you may need to detach it first. */
plAGAnimInstance *FindOrAttachInstance(const char *name, hsScalar blendFactor);
/** Return the number of animations available. */
int GetNumAnimations();
/** Return the number of animations that are privately
owned by this modifier.
Animations may be either shared in a general pool,
or privately owned by a mastermod. */
int GetNumPrivateAnimations();
int GetNumATCAnimations();
plAGAnimInstance *GetATCAnimInstance(int i);
/** Apply all our animations to all our parts.
\param timeNow is the current world time
\param elapsed is the time since the previous frame */
void ApplyAnimations(double timeNow, hsScalar elapsed);
/** Runs through our anims and applies them, without
processing fades. This is used when we load in anim
state from the server, and need to advance it to a
certain point before enabling callbacks */
void AdvanceAnimsToTime(double time);
/** Change the connectivity in the graph so that inactive animations are bypassed.
The original connectivity information is kept, so if the activity of different
animations is changed (such as by changing blend biases or adding new animations,
the graph can be compiled again to the correct state. */
void Compile(double time);
/** We've done something that invalidates the cached connectivity in the graph.
Mark this for fixup. */
void SetNeedCompile(bool needCompile);
/** List the animationg graph to stdOut, with a ASCII representation of the tree
structure. Done by recursively dumping the graph; some types of nodes will have
more output information than others.
*/
void DumpAniGraph(const char *channel, bool optimized, double time);
/** Set whether or not this is the "group master" so grouped animations will only have
one member getting/setting sdl animation state in order to synch the anims
*/
void SetIsGrouped(bool grouped);
void SetIsGroupMaster(bool master, plMsgForwarder* msgForwarder);
// PLASMA PROTOCOL
virtual int GetNumTargets() const { return fTarget ? 1 : 0; }
virtual plSceneObject* GetTarget(int w) const { /* hsAssert(w < GetNumTargets(), "Bad target"); */ return fTarget; }
virtual void AddTarget(plSceneObject * object);
virtual void RemoveTarget(plSceneObject * object);
hsBool plAGMasterMod::MsgReceive(plMessage* msg);
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream * stream, hsResMgr *mgr);
hsBool HasRunningAnims();
hsBool DirtySynchState(const char* SDLStateName, UInt32 synchFlags);
CLASSNAME_REGISTER( plAGMasterMod );
GETINTERFACE_ANY( plAGMasterMod, plModifier );
protected:
// -- methods --
plAGModifier * ICacheChannelMod(plAGModifier *mod) const;
plAGModifier * IFindChannelMod(const plSceneObject *obj, const char *name) const;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
virtual void IApplyDynamic() {}; // dummy function required by base class
// Find markers in an anim for environment effects (footsteps)
virtual void ISetupMarkerCallbacks(plATCAnim *anim, plAnimTimeConvert *atc) {}
// -- members
plSceneObject* fTarget;
// a map from channel names to ag modifiers within our domain
typedef std::map<const char *, plAGModifier*, stringSorter> plChannelModMap;
plChannelModMap fChannelMods;
// instances which are currently attached to this master
typedef std::vector<plAGAnimInstance*> plInstanceVector;
plInstanceVector fAnimInstances; // animation instances
// animations which are owned exclusively by this master
typedef std::vector<plAGAnim*> plAnimVector;
plAnimVector fPrivateAnims;
// animations that require AnimTimeConvert state to be synched
typedef std::vector<plAGAnim*> plAnimVector;
plInstanceVector fATCAnimInstances;
hsBool fFirstEval;
hsBool fNeedEval;
void IRegForEval(hsBool val);
// SDL modifier which sends/recvs dynamics state
plAGMasterSDLModifier *fAGMasterSDLMod;
bool fNeedCompile;
bool fIsGrouped;
bool fIsGroupMaster;
plMsgForwarder* fMsgForwarder;
enum {
kPrivateAnim,
kPublicAnim,
};
};
#endif // PLAGMASTERMOD_INC
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAGMasterMod.h
\brief The animation class for the AniGraph animation system
\ingroup Avatar
\ingroup AniGraph
*/
#ifndef PLAGMASTERMOD_INC
#define PLAGMASTERMOD_INC
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "pnModifier/plModifier.h"
#include "plAGChannel.h"
#include "plAvDefs.h"
#include "pnKeyedObject/plMsgForwarder.h"
// templates
#include "hsStlUtils.h"
#include "hsStlSortUtils.h"
class plAGModifier;
class plAGAnimInstance;
class plAGAnim;
class plATCAnim;
class plAGMasterSDLModifier;
////////////////
//
// PLAGMASTERMOD
//
////////////////
/** \class plAGMasterMod
A modifier which can apply animations to scene objects.
Works together with a plAGModifier, which can apply animation to a
single scene object. A master modifier hooks up to a family of
ag modifiers to do its job.
An animation (plAGAnim) can have many different channels, but the
user can just pass it to a single master mod to apply it to all the
channels owned by that master. The master will take care of hooking
each channel up to an ag modifier.
The goal is to make an animation a conceptually (and practically) simple
object to work with, whether or not it has multiple channels.
\sa plAGAnim, plAGAnimInstance, plAGModifier
*/
class plAGMasterMod : public plModifier
{
friend class plAGMasterSDLModifier;
public:
/** Default constructor. Primarily for use by the class factory. */
plAGMasterMod();
/** Free the name and any other miscellany. */
virtual ~plAGMasterMod();
/** Find an individual plAGModifier of the given name under our control. */
plAGModifier * GetChannelMod(const char * name, hsBool dontCache = false) const;
/** \name Managing Animations */
// \{
// AGANIM PROTOCOL
/** Attach the given animation object with the given blend factor.
If there's no animation already attached to blend with, the
animation will be attached at full strength. */
plAGAnimInstance *AttachAnimationBlended(plAGAnim *anim, hsScalar blendFactor = 0,
UInt16 blendPriority = kAGMedBlendPriority,
hsBool cache = false);
/** Look up the given animation by name and attach it
with the given blend factor. */
plAGAnimInstance *AttachAnimationBlended(const char *name, hsScalar blendFactor = 0,
UInt16 blendPriority = kAGMedBlendPriority,
hsBool cache = false);
/** Play a simple anim (one that doesn't affect root) once and auto detach.
Intended for Zandi's facial animations that run seperate from the behaviors. */
void PlaySimpleAnim(const char *name);
/** Detach the given animation instance. Does nothing
if the instance is not managed by this master mod. */
void DetachAnimation(plAGAnimInstance *instance);
void DetachAllAnimations();
/** Detach the given animation by name. Searches for
any instances derived from animations with the
given name and removes them. */
void DetachAnimation(const char *name);
// \}
/** Print the current animation stack to the console.
Will list all the animations and their blend strengths.
Animations later in the list will mask animations earlier
in the list. */
void DumpCurrentAnims(const char *header);
/** Find and return any animation instances with the
given name on this master modifer. */
plAGAnimInstance *FindAnimInstance(const char *name);
/** Return the Ith animation instance, based on blend
order. Of dubious utility, but, y'know. */
plAGAnimInstance *GetAnimInstance(int i);
/** Attach the animation if it's not already attached. If
it is attached, return the instance.
Note that if it's attached by this function, it
will be on top of the stack, but if it was already
attached, it could be anywhere, including buried under
a bunch of other animations. If it's important that it be
on top of the stack, you may need to detach it first. */
plAGAnimInstance *FindOrAttachInstance(const char *name, hsScalar blendFactor);
/** Return the number of animations available. */
int GetNumAnimations();
/** Return the number of animations that are privately
owned by this modifier.
Animations may be either shared in a general pool,
or privately owned by a mastermod. */
int GetNumPrivateAnimations();
int GetNumATCAnimations();
plAGAnimInstance *GetATCAnimInstance(int i);
/** Apply all our animations to all our parts.
\param timeNow is the current world time
\param elapsed is the time since the previous frame */
void ApplyAnimations(double timeNow, hsScalar elapsed);
/** Runs through our anims and applies them, without
processing fades. This is used when we load in anim
state from the server, and need to advance it to a
certain point before enabling callbacks */
void AdvanceAnimsToTime(double time);
/** Change the connectivity in the graph so that inactive animations are bypassed.
The original connectivity information is kept, so if the activity of different
animations is changed (such as by changing blend biases or adding new animations,
the graph can be compiled again to the correct state. */
void Compile(double time);
/** We've done something that invalidates the cached connectivity in the graph.
Mark this for fixup. */
void SetNeedCompile(bool needCompile);
/** List the animationg graph to stdOut, with a ASCII representation of the tree
structure. Done by recursively dumping the graph; some types of nodes will have
more output information than others.
*/
void DumpAniGraph(const char *channel, bool optimized, double time);
/** Set whether or not this is the "group master" so grouped animations will only have
one member getting/setting sdl animation state in order to synch the anims
*/
void SetIsGrouped(bool grouped);
void SetIsGroupMaster(bool master, plMsgForwarder* msgForwarder);
// PLASMA PROTOCOL
virtual int GetNumTargets() const { return fTarget ? 1 : 0; }
virtual plSceneObject* GetTarget(int w) const { /* hsAssert(w < GetNumTargets(), "Bad target"); */ return fTarget; }
virtual void AddTarget(plSceneObject * object);
virtual void RemoveTarget(plSceneObject * object);
hsBool plAGMasterMod::MsgReceive(plMessage* msg);
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream * stream, hsResMgr *mgr);
hsBool HasRunningAnims();
hsBool DirtySynchState(const char* SDLStateName, UInt32 synchFlags);
CLASSNAME_REGISTER( plAGMasterMod );
GETINTERFACE_ANY( plAGMasterMod, plModifier );
protected:
// -- methods --
plAGModifier * ICacheChannelMod(plAGModifier *mod) const;
plAGModifier * IFindChannelMod(const plSceneObject *obj, const char *name) const;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
virtual void IApplyDynamic() {}; // dummy function required by base class
// Find markers in an anim for environment effects (footsteps)
virtual void ISetupMarkerCallbacks(plATCAnim *anim, plAnimTimeConvert *atc) {}
// -- members
plSceneObject* fTarget;
// a map from channel names to ag modifiers within our domain
typedef std::map<const char *, plAGModifier*, stringSorter> plChannelModMap;
plChannelModMap fChannelMods;
// instances which are currently attached to this master
typedef std::vector<plAGAnimInstance*> plInstanceVector;
plInstanceVector fAnimInstances; // animation instances
// animations which are owned exclusively by this master
typedef std::vector<plAGAnim*> plAnimVector;
plAnimVector fPrivateAnims;
// animations that require AnimTimeConvert state to be synched
typedef std::vector<plAGAnim*> plAnimVector;
plInstanceVector fATCAnimInstances;
hsBool fFirstEval;
hsBool fNeedEval;
void IRegForEval(hsBool val);
// SDL modifier which sends/recvs dynamics state
plAGMasterSDLModifier *fAGMasterSDLMod;
bool fNeedCompile;
bool fIsGrouped;
bool fIsGroupMaster;
plMsgForwarder* fMsgForwarder;
enum {
kPrivateAnim,
kPublicAnim,
};
};
#endif // PLAGMASTERMOD_INC

View File

@ -1,195 +1,195 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAGMasterSDLModifier.h"
#include "plSDL/plSDL.h"
#include "plInterp/plAnimTimeConvert.h"
#include "pnSceneObject/plSceneObject.h"
#include "plAGMasterMod.h"
#include "plAGAnimInstance.h"
#include "plgDispatch.h"
#include "pnMessage/plTimeMsg.h"
#include "hsTimer.h"
#include "plMessage/plAnimCmdMsg.h"
// static vars
char plAGMasterSDLModifier::AGMasterVarNames::kStrAtcs[]="atcs";
char plAGMasterSDLModifier::AGMasterVarNames::kStrBlends[]="blends";
UInt32 plAGMasterSDLModifier::IApplyModFlags(UInt32 sendFlags)
{
// ugly hack so bug light animation state isn't stored on the server
if (stricmp(GetTarget()->GetKeyName(), "RTOmni-BugLightTest") == 0)
return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState);
// ditto for the KI light
if (stricmp(GetTarget()->GetKeyName(), "RTOmniKILight") == 0)
return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState);
return sendFlags;
}
//
// copy blends values from current state into sdl
//
void plAGMasterSDLModifier::IPutBlends(plStateDataRecord* state, plAGMasterMod* agMaster)
{
int numBlends = agMaster->GetNumPrivateAnimations(); // each private anim has a blend value
plSimpleStateVariable* blendsVar = state->FindVar(AGMasterVarNames::kStrBlends);
if (blendsVar->GetCount() != numBlends)
blendsVar->Alloc(numBlends);
// sdl copy
int i;
for(i=0;i<numBlends; i++)
{
blendsVar->Set((UInt8)(agMaster->GetAnimInstance(i)->GetBlend() * 255), i);
}
}
//
// Copy atcs from current state into sdl
//
void plAGMasterSDLModifier::IPutCurrentStateIn(plStateDataRecord* dstState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plAGMasterSDLModifier, nil target");
plAGMasterMod* agMaster=IGetObjectsAGMasterMod(sobj);
hsAssert(agMaster, "nil AGMasterMod");
if (agMaster)
{
IPutBlends(dstState, agMaster);
int numAnims = agMaster->GetNumATCAnimations();
plSDStateVariable* atcsVar = dstState->FindSDVar(AGMasterVarNames::kStrAtcs);
if (atcsVar->GetCount() != numAnims)
atcsVar->Resize(numAnims);
// copy atcs to sdl
int i;
for(i=0;i<numAnims; i++)
{
plStateDataRecord* atcStateDataRec = atcsVar->GetStateDataRecord(i);
plAnimTimeConvert* animTimeConvert = agMaster->GetATCAnimInstance(i)->GetTimeConvert();
IPutATC(atcStateDataRec, animTimeConvert);
}
}
}
//
// Given a scene object, find and return it's AGMasterMod
//
plAGMasterMod* plAGMasterSDLModifier::IGetObjectsAGMasterMod(plSceneObject* obj)
{
int count = obj->GetNumModifiers();
for (int i = 0; i < count; i++)
{
plAGMasterMod * avMod = const_cast<plAGMasterMod*>(plAGMasterMod::ConvertNoRef(obj->GetModifier(i)));
if(avMod)
return avMod;
}
return nil;
}
//
// Apply state in SDL record to current animation state
//
void plAGMasterSDLModifier::ISetCurrentBlends(const plStateDataRecord* state, plAGMasterMod* objAGMaster)
{
// Check Blends
plSimpleStateVariable* blendsVar = state->FindVar(AGMasterVarNames::kStrBlends);
if (blendsVar->IsUsed())
{
int i;
if (blendsVar->GetCount() != objAGMaster->GetNumPrivateAnimations())
return; // bogus state
for (i=0;i<blendsVar->GetCount();i++)
{
UInt8 blend;
blendsVar->Get(&blend, i);
objAGMaster->GetAnimInstance(i)->SetBlend(blend / 255.f);
}
}
}
//
// Change the object's animation state to reflect what is specified in the
// stateDataRecord.
//
void plAGMasterSDLModifier::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plAGMasterSDLModifier, nil target");
plAGMasterMod* objAGMaster=IGetObjectsAGMasterMod(sobj);
hsAssert(objAGMaster, "can't find object's AGMasterSDLState");
ISetCurrentBlends(srcState, objAGMaster);
plSDStateVariable* atcsVar = srcState->FindSDVar(AGMasterVarNames::kStrAtcs);
if (atcsVar->IsUsed())
{
if (objAGMaster->GetNumATCAnimations() != atcsVar->GetCount())
return;
int i;
for(i=0;i<atcsVar->GetCount(); i++)
{
plStateDataRecord* atcStateDataRec = atcsVar->GetStateDataRecord(i);
plAnimTimeConvert* objAtc = objAGMaster->GetATCAnimInstance(i)->GetTimeConvert(); // dst
ISetCurrentATC(atcStateDataRec, objAtc);
objAtc->EnableCallbacks(false);
}
objAGMaster->IRegForEval(objAGMaster->HasRunningAnims());
// Force one eval, then re-enable all the callbacks
double time = (hsTimer::GetSysSeconds() - hsTimer::GetDelSysSeconds());
if (objAGMaster->fIsGrouped && objAGMaster->fMsgForwarder)
{
hsScalar animTimeFromWorldTime = (objAGMaster->GetNumATCAnimations() > 0) ? objAGMaster->GetATCAnimInstance(0)->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) : 0.0f;
plAGCmdMsg *msg = TRACKED_NEW plAGCmdMsg();
msg->SetCmd(plAGCmdMsg::kSetAnimTime);
msg->fAnimTime = animTimeFromWorldTime;
msg->AddReceiver(objAGMaster->fMsgForwarder->GetKey());
plgDispatch::MsgSend(msg);
}
else
{
objAGMaster->AdvanceAnimsToTime(time);
}
for (i = 0; i < objAGMaster->GetNumATCAnimations(); i++)
objAGMaster->GetATCAnimInstance(i)->GetTimeConvert()->EnableCallbacks(true);
}
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAGMasterSDLModifier.h"
#include "plSDL/plSDL.h"
#include "plInterp/plAnimTimeConvert.h"
#include "pnSceneObject/plSceneObject.h"
#include "plAGMasterMod.h"
#include "plAGAnimInstance.h"
#include "plgDispatch.h"
#include "pnMessage/plTimeMsg.h"
#include "hsTimer.h"
#include "plMessage/plAnimCmdMsg.h"
// static vars
char plAGMasterSDLModifier::AGMasterVarNames::kStrAtcs[]="atcs";
char plAGMasterSDLModifier::AGMasterVarNames::kStrBlends[]="blends";
UInt32 plAGMasterSDLModifier::IApplyModFlags(UInt32 sendFlags)
{
// ugly hack so bug light animation state isn't stored on the server
if (stricmp(GetTarget()->GetKeyName(), "RTOmni-BugLightTest") == 0)
return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState);
// ditto for the KI light
if (stricmp(GetTarget()->GetKeyName(), "RTOmniKILight") == 0)
return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState);
return sendFlags;
}
//
// copy blends values from current state into sdl
//
void plAGMasterSDLModifier::IPutBlends(plStateDataRecord* state, plAGMasterMod* agMaster)
{
int numBlends = agMaster->GetNumPrivateAnimations(); // each private anim has a blend value
plSimpleStateVariable* blendsVar = state->FindVar(AGMasterVarNames::kStrBlends);
if (blendsVar->GetCount() != numBlends)
blendsVar->Alloc(numBlends);
// sdl copy
int i;
for(i=0;i<numBlends; i++)
{
blendsVar->Set((UInt8)(agMaster->GetAnimInstance(i)->GetBlend() * 255), i);
}
}
//
// Copy atcs from current state into sdl
//
void plAGMasterSDLModifier::IPutCurrentStateIn(plStateDataRecord* dstState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plAGMasterSDLModifier, nil target");
plAGMasterMod* agMaster=IGetObjectsAGMasterMod(sobj);
hsAssert(agMaster, "nil AGMasterMod");
if (agMaster)
{
IPutBlends(dstState, agMaster);
int numAnims = agMaster->GetNumATCAnimations();
plSDStateVariable* atcsVar = dstState->FindSDVar(AGMasterVarNames::kStrAtcs);
if (atcsVar->GetCount() != numAnims)
atcsVar->Resize(numAnims);
// copy atcs to sdl
int i;
for(i=0;i<numAnims; i++)
{
plStateDataRecord* atcStateDataRec = atcsVar->GetStateDataRecord(i);
plAnimTimeConvert* animTimeConvert = agMaster->GetATCAnimInstance(i)->GetTimeConvert();
IPutATC(atcStateDataRec, animTimeConvert);
}
}
}
//
// Given a scene object, find and return it's AGMasterMod
//
plAGMasterMod* plAGMasterSDLModifier::IGetObjectsAGMasterMod(plSceneObject* obj)
{
int count = obj->GetNumModifiers();
for (int i = 0; i < count; i++)
{
plAGMasterMod * avMod = const_cast<plAGMasterMod*>(plAGMasterMod::ConvertNoRef(obj->GetModifier(i)));
if(avMod)
return avMod;
}
return nil;
}
//
// Apply state in SDL record to current animation state
//
void plAGMasterSDLModifier::ISetCurrentBlends(const plStateDataRecord* state, plAGMasterMod* objAGMaster)
{
// Check Blends
plSimpleStateVariable* blendsVar = state->FindVar(AGMasterVarNames::kStrBlends);
if (blendsVar->IsUsed())
{
int i;
if (blendsVar->GetCount() != objAGMaster->GetNumPrivateAnimations())
return; // bogus state
for (i=0;i<blendsVar->GetCount();i++)
{
UInt8 blend;
blendsVar->Get(&blend, i);
objAGMaster->GetAnimInstance(i)->SetBlend(blend / 255.f);
}
}
}
//
// Change the object's animation state to reflect what is specified in the
// stateDataRecord.
//
void plAGMasterSDLModifier::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plAGMasterSDLModifier, nil target");
plAGMasterMod* objAGMaster=IGetObjectsAGMasterMod(sobj);
hsAssert(objAGMaster, "can't find object's AGMasterSDLState");
ISetCurrentBlends(srcState, objAGMaster);
plSDStateVariable* atcsVar = srcState->FindSDVar(AGMasterVarNames::kStrAtcs);
if (atcsVar->IsUsed())
{
if (objAGMaster->GetNumATCAnimations() != atcsVar->GetCount())
return;
int i;
for(i=0;i<atcsVar->GetCount(); i++)
{
plStateDataRecord* atcStateDataRec = atcsVar->GetStateDataRecord(i);
plAnimTimeConvert* objAtc = objAGMaster->GetATCAnimInstance(i)->GetTimeConvert(); // dst
ISetCurrentATC(atcStateDataRec, objAtc);
objAtc->EnableCallbacks(false);
}
objAGMaster->IRegForEval(objAGMaster->HasRunningAnims());
// Force one eval, then re-enable all the callbacks
double time = (hsTimer::GetSysSeconds() - hsTimer::GetDelSysSeconds());
if (objAGMaster->fIsGrouped && objAGMaster->fMsgForwarder)
{
hsScalar animTimeFromWorldTime = (objAGMaster->GetNumATCAnimations() > 0) ? objAGMaster->GetATCAnimInstance(0)->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) : 0.0f;
plAGCmdMsg *msg = TRACKED_NEW plAGCmdMsg();
msg->SetCmd(plAGCmdMsg::kSetAnimTime);
msg->fAnimTime = animTimeFromWorldTime;
msg->AddReceiver(objAGMaster->fMsgForwarder->GetKey());
plgDispatch::MsgSend(msg);
}
else
{
objAGMaster->AdvanceAnimsToTime(time);
}
for (i = 0; i < objAGMaster->GetNumATCAnimations(); i++)
objAGMaster->GetATCAnimInstance(i)->GetTimeConvert()->EnableCallbacks(true);
}
}

View File

@ -1,70 +1,70 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAGMasterSDLModifier_inc
#define plAGMasterSDLModifier_inc
#include "plModifier/plAnimTimeConvertSDLModifier.h"
//
// This modifier is responsible for sending and recving
// an object's animation state
//
class plAGMasterMod;
class plSceneObject;
class plStateDataRecord;
class plAGMasterSDLModifier : public plAnimTimeConvertSDLModifier
{
protected:
// var labels
struct AGMasterVarNames
{
static char kStrAtcs[]; // animTimeConverts
static char kStrBlends[];
};
plAGMasterMod* IGetObjectsAGMasterMod(plSceneObject* obj);
void IPutBlends(plStateDataRecord* state, plAGMasterMod* objAGMaster);
void ISetCurrentBlends(const plStateDataRecord* state, plAGMasterMod* objAGMaster);
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
UInt32 IApplyModFlags(UInt32 sendFlags);
public:
CLASSNAME_REGISTER( plAGMasterSDLModifier);
GETINTERFACE_ANY( plAGMasterSDLModifier, plAnimTimeConvertSDLModifier);
plAGMasterSDLModifier() {}
~plAGMasterSDLModifier() {}
const char* GetSDLName() const { return kSDLAGMaster; }
};
#endif // plAGMasterSDLModifier_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAGMasterSDLModifier_inc
#define plAGMasterSDLModifier_inc
#include "plModifier/plAnimTimeConvertSDLModifier.h"
//
// This modifier is responsible for sending and recving
// an object's animation state
//
class plAGMasterMod;
class plSceneObject;
class plStateDataRecord;
class plAGMasterSDLModifier : public plAnimTimeConvertSDLModifier
{
protected:
// var labels
struct AGMasterVarNames
{
static char kStrAtcs[]; // animTimeConverts
static char kStrBlends[];
};
plAGMasterMod* IGetObjectsAGMasterMod(plSceneObject* obj);
void IPutBlends(plStateDataRecord* state, plAGMasterMod* objAGMaster);
void ISetCurrentBlends(const plStateDataRecord* state, plAGMasterMod* objAGMaster);
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
UInt32 IApplyModFlags(UInt32 sendFlags);
public:
CLASSNAME_REGISTER( plAGMasterSDLModifier);
GETINTERFACE_ANY( plAGMasterSDLModifier, plAnimTimeConvertSDLModifier);
plAGMasterSDLModifier() {}
~plAGMasterSDLModifier() {}
const char* GetSDLName() const { return kSDLAGMaster; }
};
#endif // plAGMasterSDLModifier_inc

View File

@ -1,304 +1,304 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// local
#include "plAGModifier.h"
#include "plMatrixChannel.h"
// global
#include "hsResMgr.h"
#include "hsTimer.h"
// other
#include "pnSceneObject/plSceneObject.h"
#include "pnSceneObject/plCoordinateInterface.h"
#include "pnSceneObject/plSimulationInterface.h"
/////////////////
//
// PLAGMODIFIER
//
/////////////////
// Applies animation graph output to a single scene object.
// CTOR
plAGModifier::plAGModifier()
: plSingleModifier()
{
fChannelName = nil;
fAutoApply = true;
fEnabled = true;
}
// CTOR(name)
plAGModifier::plAGModifier(const char *name, hsBool autoApply)
: plSingleModifier(), fAutoApply(autoApply)
{
fChannelName = hsStrcpy(name);
fEnabled = true;
}
// DTOR
plAGModifier::~plAGModifier()
{
if(fChannelName)
{
delete[] fChannelName;
fChannelName = nil;
}
int i;
for (i = 0; i < fApps.size(); i++)
{
delete fApps[i];
}
}
// GETCHANNELNAME
const char * plAGModifier::GetChannelName() const
{
return fChannelName;
}
// ENABLE
void plAGModifier::Enable(hsBool val)
{
fEnabled = val;
}
// SETCHANNELNAME
void plAGModifier::SetChannelName(char * name)
{
fChannelName = hsStrcpy(name);
}
// IAPPLYCHANNELS (time)
// One AGModifier, although applied to a single scene object, can have
// multiple channels on it affecting, say, position, color, aroma, etc.
//
// There are cases where we want to call this and won't know the delta,
// we don't seem to ever need it for this function, so I'm taking it out.
// If you run into a case where you think it's necessary, see me. -Bob
void plAGModifier::Apply(double time) const
{
if (!fEnabled)
return;
for (int i = 0; i < fApps.size(); i++)
{
plAGApplicator *app = fApps[i];
app->Apply(this, time);
}
}
// IEVAL
// Apply our channels to our scene object
hsBool plAGModifier::IEval(double time, hsScalar delta, UInt32 dirty)
{
if(fAutoApply) {
// Apply(time, delta);
}
return true;
}
// GETAPPLICATOR
plAGApplicator * plAGModifier::GetApplicator(plAGPinType pinType) const
{
int numApps = fApps.size();
for (int i = 0; i < numApps; i++)
{
plAGApplicator *app = fApps[i];
plAGPinType otherType = app->GetPinType();
if(otherType == pinType)
return app;
}
return nil;
}
// SETAPPLICATOR
void plAGModifier::SetApplicator(plAGApplicator *newApp)
{
int numApps = fApps.size();
plAGPinType newPinType = newApp->GetPinType();
// *** NOTE: this code is completely untested. Since I happened to be here
// I sketched out how it *should* work and implemented the base protocol.
// In reality, most of these code paths are not accessed now...
// -- mm
for(int i = 0; i < numApps; i++)
{
plAGApplicator *existingApp = fApps[i];
plAGPinType extPinType = existingApp->GetPinType();
if(extPinType == newPinType)
{
hsStatusMessage("Two applicators accessing same pin type...congratulations for being the first to test this.");
// these applicators both try to set the same thing; try to merge them
plAGChannel *newChannel = newApp->GetChannel();
hsAssert(newChannel = nil, "Trying to merge in new applicator which already has channel. Incomplete.");
// *** right now I just want to support the case of putting in a new applicator - not merging animations
plAGChannel *extChannel = existingApp->GetChannel();
newApp->SetChannel(extChannel);
existingApp->SetChannel(nil);
fApps[i] = newApp;
delete existingApp;
return;
// NOTE: we should make these arbitrate, but I'm not going to right now because
// there's not currently an (easy) way to merge two applicators without allowing a blend.
// if(existingApp->CanCombine(newApp))
// {
// // the existing applicator promises to provide the functionality we need...merge into it.
// existingApp->MergeChannel(newApp);
// } else {
// // couldn't merge into the existing channel; can we merge it into us instead?
// if(newApp->CanCombine(extApp))
// {
// // okay, WE can provide the functionality of the existing applicator.
// fApps[i] = newApp; // take over its spot in the applicators
// newApp->MergeChannel(existingApp); // and merge it into us
// }
// }
}
}
// didn't find any conflicts; just add our app on the end
fApps.push_back(newApp);
}
// MERGECHANNEL
// Intended as a replacement for attach/blend channel. You want to add a channel to this node,
// we do that for you. Don't ask us how, you shouldn't have to know.
plAGChannel * plAGModifier::MergeChannel(plAGApplicator *app,
plAGChannel *channel,
plScalarChannel *blend,
plAGAnimInstance *anim,
int priority)
{
int numApps = fApps.size();
plAGChannel * result = nil;
for (int i = 0; i < numApps; i++)
{
plAGApplicator *existingApp = fApps[i];
result = existingApp->MergeChannel(app, channel, blend, priority);
if (result)
return result;
}
if (!result)
{
// didn't blend or combine with an existing channel; add a new channel
plAGApplicator *newApp = app->CloneWithChannel(channel);
fApps.push_back(newApp);
}
return result;
}
// DETACHCHANNEL
hsBool plAGModifier::DetachChannel(plAGChannel * channel)
{
plAppTable::iterator i = fApps.begin();
while( i != fApps.end() )
{
plAGApplicator *app = *i;
plAGChannel *existingChannel = app->GetChannel();
if(existingChannel)
{
plAGChannel *replacementChannel = existingChannel->Detach(channel);
if (existingChannel != replacementChannel)
{
app->SetChannel(replacementChannel);
if( ! replacementChannel && app->AutoDelete())
{
// Don't need to adjust the iterator since we're about to exit the loop
fApps.erase(i);
delete app;
}
return true;
}
}
++i;
}
return false;
}
// READ
void plAGModifier::Read(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Read(stream, mgr);
// read in the name of the modifier
fChannelName = stream->ReadSafeString();
}
// WRITE
void plAGModifier::Write(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Write(stream, mgr);
// write out the name of the modifier
stream->WriteSafeString(fChannelName);
}
/////////////////////////////////////////
/////////////////////////////////////////
//
// MOVE
//
/////////////////////////////////////////
/////////////////////////////////////////
const plModifier * FindModifierByClass(const plSceneObject *obj, int classID)
{
if(obj)
{
int modCount = obj->GetNumModifiers();
for (int i = 0; i < modCount; i++)
{
const plModifier *mod = obj->GetModifier(i);
if(mod) // modifier might not be loaded yet
{
if(mod->ClassIndex() == classID)
{
return mod;
}
}
}
}
return nil;
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// local
#include "plAGModifier.h"
#include "plMatrixChannel.h"
// global
#include "hsResMgr.h"
#include "hsTimer.h"
// other
#include "pnSceneObject/plSceneObject.h"
#include "pnSceneObject/plCoordinateInterface.h"
#include "pnSceneObject/plSimulationInterface.h"
/////////////////
//
// PLAGMODIFIER
//
/////////////////
// Applies animation graph output to a single scene object.
// CTOR
plAGModifier::plAGModifier()
: plSingleModifier()
{
fChannelName = nil;
fAutoApply = true;
fEnabled = true;
}
// CTOR(name)
plAGModifier::plAGModifier(const char *name, hsBool autoApply)
: plSingleModifier(), fAutoApply(autoApply)
{
fChannelName = hsStrcpy(name);
fEnabled = true;
}
// DTOR
plAGModifier::~plAGModifier()
{
if(fChannelName)
{
delete[] fChannelName;
fChannelName = nil;
}
int i;
for (i = 0; i < fApps.size(); i++)
{
delete fApps[i];
}
}
// GETCHANNELNAME
const char * plAGModifier::GetChannelName() const
{
return fChannelName;
}
// ENABLE
void plAGModifier::Enable(hsBool val)
{
fEnabled = val;
}
// SETCHANNELNAME
void plAGModifier::SetChannelName(char * name)
{
fChannelName = hsStrcpy(name);
}
// IAPPLYCHANNELS (time)
// One AGModifier, although applied to a single scene object, can have
// multiple channels on it affecting, say, position, color, aroma, etc.
//
// There are cases where we want to call this and won't know the delta,
// we don't seem to ever need it for this function, so I'm taking it out.
// If you run into a case where you think it's necessary, see me. -Bob
void plAGModifier::Apply(double time) const
{
if (!fEnabled)
return;
for (int i = 0; i < fApps.size(); i++)
{
plAGApplicator *app = fApps[i];
app->Apply(this, time);
}
}
// IEVAL
// Apply our channels to our scene object
hsBool plAGModifier::IEval(double time, hsScalar delta, UInt32 dirty)
{
if(fAutoApply) {
// Apply(time, delta);
}
return true;
}
// GETAPPLICATOR
plAGApplicator * plAGModifier::GetApplicator(plAGPinType pinType) const
{
int numApps = fApps.size();
for (int i = 0; i < numApps; i++)
{
plAGApplicator *app = fApps[i];
plAGPinType otherType = app->GetPinType();
if(otherType == pinType)
return app;
}
return nil;
}
// SETAPPLICATOR
void plAGModifier::SetApplicator(plAGApplicator *newApp)
{
int numApps = fApps.size();
plAGPinType newPinType = newApp->GetPinType();
// *** NOTE: this code is completely untested. Since I happened to be here
// I sketched out how it *should* work and implemented the base protocol.
// In reality, most of these code paths are not accessed now...
// -- mm
for(int i = 0; i < numApps; i++)
{
plAGApplicator *existingApp = fApps[i];
plAGPinType extPinType = existingApp->GetPinType();
if(extPinType == newPinType)
{
hsStatusMessage("Two applicators accessing same pin type...congratulations for being the first to test this.");
// these applicators both try to set the same thing; try to merge them
plAGChannel *newChannel = newApp->GetChannel();
hsAssert(newChannel = nil, "Trying to merge in new applicator which already has channel. Incomplete.");
// *** right now I just want to support the case of putting in a new applicator - not merging animations
plAGChannel *extChannel = existingApp->GetChannel();
newApp->SetChannel(extChannel);
existingApp->SetChannel(nil);
fApps[i] = newApp;
delete existingApp;
return;
// NOTE: we should make these arbitrate, but I'm not going to right now because
// there's not currently an (easy) way to merge two applicators without allowing a blend.
// if(existingApp->CanCombine(newApp))
// {
// // the existing applicator promises to provide the functionality we need...merge into it.
// existingApp->MergeChannel(newApp);
// } else {
// // couldn't merge into the existing channel; can we merge it into us instead?
// if(newApp->CanCombine(extApp))
// {
// // okay, WE can provide the functionality of the existing applicator.
// fApps[i] = newApp; // take over its spot in the applicators
// newApp->MergeChannel(existingApp); // and merge it into us
// }
// }
}
}
// didn't find any conflicts; just add our app on the end
fApps.push_back(newApp);
}
// MERGECHANNEL
// Intended as a replacement for attach/blend channel. You want to add a channel to this node,
// we do that for you. Don't ask us how, you shouldn't have to know.
plAGChannel * plAGModifier::MergeChannel(plAGApplicator *app,
plAGChannel *channel,
plScalarChannel *blend,
plAGAnimInstance *anim,
int priority)
{
int numApps = fApps.size();
plAGChannel * result = nil;
for (int i = 0; i < numApps; i++)
{
plAGApplicator *existingApp = fApps[i];
result = existingApp->MergeChannel(app, channel, blend, priority);
if (result)
return result;
}
if (!result)
{
// didn't blend or combine with an existing channel; add a new channel
plAGApplicator *newApp = app->CloneWithChannel(channel);
fApps.push_back(newApp);
}
return result;
}
// DETACHCHANNEL
hsBool plAGModifier::DetachChannel(plAGChannel * channel)
{
plAppTable::iterator i = fApps.begin();
while( i != fApps.end() )
{
plAGApplicator *app = *i;
plAGChannel *existingChannel = app->GetChannel();
if(existingChannel)
{
plAGChannel *replacementChannel = existingChannel->Detach(channel);
if (existingChannel != replacementChannel)
{
app->SetChannel(replacementChannel);
if( ! replacementChannel && app->AutoDelete())
{
// Don't need to adjust the iterator since we're about to exit the loop
fApps.erase(i);
delete app;
}
return true;
}
}
++i;
}
return false;
}
// READ
void plAGModifier::Read(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Read(stream, mgr);
// read in the name of the modifier
fChannelName = stream->ReadSafeString();
}
// WRITE
void plAGModifier::Write(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Write(stream, mgr);
// write out the name of the modifier
stream->WriteSafeString(fChannelName);
}
/////////////////////////////////////////
/////////////////////////////////////////
//
// MOVE
//
/////////////////////////////////////////
/////////////////////////////////////////
const plModifier * FindModifierByClass(const plSceneObject *obj, int classID)
{
if(obj)
{
int modCount = obj->GetNumModifiers();
for (int i = 0; i < modCount; i++)
{
const plModifier *mod = obj->GetModifier(i);
if(mod) // modifier might not be loaded yet
{
if(mod->ClassIndex() == classID)
{
return mod;
}
}
}
}
return nil;
}

View File

@ -1,154 +1,154 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAGMasterMod.h
\ingroup Avatar
\ingroup AniGraph
*/
#ifndef PLAGMODIFIER_H
#define PLAGMODIFIER_H
#include "hsTypes.h" // need for plSingleModifier
#include "pnModifier/plSingleModifier.h" // inherited
// local
#include "plAvatar/plScalarChannel.h"
// stl
#include "hsStlUtils.h"
#include "hsStlSortUtils.h"
class plSceneObject;
class plAGAnimInstance;
class plAGAnim;
class plAvatarAnim;
class plAnimCmdMsg;
class plOneShotCallbacks;
///////////////
//
// PLAGMODIFIER
//
///////////////
/** \class plAGModifier
Animates a single scene object.
May apply multiple animations to that scene object, animating
the transform with one, colors with another, etc.
The basic model is that the ag modifier holds an array of
applicators, each of which is the root of a tree of animation
operations, such as a blend tree, etc. Each frame it fires
all its applicators, or (ideally) only those that need to be fired.
*/
class plAGModifier : public plSingleModifier
{
public:
/** Default constructor, primarily for the class factory. */
plAGModifier();
/** Construct given a name. This name will be used to match up
incoming channels with this modifier. You may also supply an
autoApply parameter, which indicates whether this modifier
should apply itself every frame, or only when explicitly asked to. */
plAGModifier(const char *name, hsBool autoApply = true);
/** It's a destructor. Destroys the name passed into the constructor,
and a bunch of other stuff you don't need to know anything about. */
virtual ~plAGModifier();
/** Get the name of the channel controlled by this modifier. */
const char * GetChannelName() const;
/** Change the channel name of the modifier. Will delete the previous
name. Will NOT remove any channels that are already attached, so
you could wind up with a modifier named "Fred" and a bunch of
channels attached to it that were intended for "Lamont." */
void SetChannelName(char * name);
/** Attach a TRACKED_NEW applicator to our modifier. Will arbitrate with existing
modifiers if necessary, based on pin type. May destruct existing applicators. */
plAGChannel *MergeChannel(plAGApplicator *app, plAGChannel *chan, plScalarChannel *blend,
plAGAnimInstance *anim, int priority);
/** Remove the given channel. Will also remove the channel's applicator. */
hsBool DetachChannel(plAGChannel * channel);
/** Set the applicator for a modifier.
\deprecated */
void SetApplicator(plAGApplicator *app);
/** Get the applicator for a given pintype. Note that an ag modifier can
only have one applicator of a given pin type attached at a time.
The exception is for the unknown pin type, which never conflicts
with any other pin type, including itself. */
plAGApplicator *GetApplicator(plAGPinType pin) const;
/** Apply the animation for our scene object. */
void Apply(double time) const;
/** Get the channel tied to our ith applicator */
plAGChannel * GetChannel(int i) { return fApps[i]->GetChannel(); }
void Enable(hsBool val);
// PERSISTENCE
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plAGModifier );
GETINTERFACE_ANY( plAGModifier, plSingleModifier );
protected:
typedef std::vector<plAGApplicator*> plAppTable;
plAppTable fApps; // the applicators (with respective channels) that we're applying to our scene object
char *fChannelName; // name used for matching animation channels to this modifier
hsBool fAutoApply; // evaluate animation automatically during IEval call
hsBool fEnabled; // if not enabled, we don't eval any of our anims
// APPLYING THE ANIMATION
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
virtual hsBool IHandleCmd(plAnimCmdMsg* modMsg) { return false; } // only plAGMasterMod should handle these
virtual void IApplyDynamic() {}; // dummy function required by base class
// INTERNAL ACCESSORS FOR SCENE OBJECT INTERFACES
plAudioInterface * LeakAI() const { return IGetTargetAudioInterface(0); };
plCoordinateInterface * LeakCI() const { return IGetTargetCoordinateInterface(0); };
plDrawInterface * LeakDI() const { return IGetTargetDrawInterface(0); };
plSimulationInterface * LeakSI() const { return IGetTargetSimulationInterface(0); };
plObjInterface * LeakGI(UInt32 classIdx) const { return IGetTargetGenericInterface(0, classIdx); }
friend plAudioInterface * plAGApplicator::IGetAI(const plAGModifier * modifier) const;
friend plCoordinateInterface * plAGApplicator::IGetCI(const plAGModifier * modifier) const;
friend plDrawInterface * plAGApplicator::IGetDI(const plAGModifier * modifier) const;
friend plSimulationInterface * plAGApplicator::IGetSI(const plAGModifier * modifier) const;
friend plObjInterface * plAGApplicator::IGetGI(const plAGModifier * modifier, UInt16 classIdx) const;
};
const plModifier * FindModifierByClass(const plSceneObject *obj, int classID);
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAGMasterMod.h
\ingroup Avatar
\ingroup AniGraph
*/
#ifndef PLAGMODIFIER_H
#define PLAGMODIFIER_H
#include "hsTypes.h" // need for plSingleModifier
#include "pnModifier/plSingleModifier.h" // inherited
// local
#include "plAvatar/plScalarChannel.h"
// stl
#include "hsStlUtils.h"
#include "hsStlSortUtils.h"
class plSceneObject;
class plAGAnimInstance;
class plAGAnim;
class plAvatarAnim;
class plAnimCmdMsg;
class plOneShotCallbacks;
///////////////
//
// PLAGMODIFIER
//
///////////////
/** \class plAGModifier
Animates a single scene object.
May apply multiple animations to that scene object, animating
the transform with one, colors with another, etc.
The basic model is that the ag modifier holds an array of
applicators, each of which is the root of a tree of animation
operations, such as a blend tree, etc. Each frame it fires
all its applicators, or (ideally) only those that need to be fired.
*/
class plAGModifier : public plSingleModifier
{
public:
/** Default constructor, primarily for the class factory. */
plAGModifier();
/** Construct given a name. This name will be used to match up
incoming channels with this modifier. You may also supply an
autoApply parameter, which indicates whether this modifier
should apply itself every frame, or only when explicitly asked to. */
plAGModifier(const char *name, hsBool autoApply = true);
/** It's a destructor. Destroys the name passed into the constructor,
and a bunch of other stuff you don't need to know anything about. */
virtual ~plAGModifier();
/** Get the name of the channel controlled by this modifier. */
const char * GetChannelName() const;
/** Change the channel name of the modifier. Will delete the previous
name. Will NOT remove any channels that are already attached, so
you could wind up with a modifier named "Fred" and a bunch of
channels attached to it that were intended for "Lamont." */
void SetChannelName(char * name);
/** Attach a TRACKED_NEW applicator to our modifier. Will arbitrate with existing
modifiers if necessary, based on pin type. May destruct existing applicators. */
plAGChannel *MergeChannel(plAGApplicator *app, plAGChannel *chan, plScalarChannel *blend,
plAGAnimInstance *anim, int priority);
/** Remove the given channel. Will also remove the channel's applicator. */
hsBool DetachChannel(plAGChannel * channel);
/** Set the applicator for a modifier.
\deprecated */
void SetApplicator(plAGApplicator *app);
/** Get the applicator for a given pintype. Note that an ag modifier can
only have one applicator of a given pin type attached at a time.
The exception is for the unknown pin type, which never conflicts
with any other pin type, including itself. */
plAGApplicator *GetApplicator(plAGPinType pin) const;
/** Apply the animation for our scene object. */
void Apply(double time) const;
/** Get the channel tied to our ith applicator */
plAGChannel * GetChannel(int i) { return fApps[i]->GetChannel(); }
void Enable(hsBool val);
// PERSISTENCE
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plAGModifier );
GETINTERFACE_ANY( plAGModifier, plSingleModifier );
protected:
typedef std::vector<plAGApplicator*> plAppTable;
plAppTable fApps; // the applicators (with respective channels) that we're applying to our scene object
char *fChannelName; // name used for matching animation channels to this modifier
hsBool fAutoApply; // evaluate animation automatically during IEval call
hsBool fEnabled; // if not enabled, we don't eval any of our anims
// APPLYING THE ANIMATION
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
virtual hsBool IHandleCmd(plAnimCmdMsg* modMsg) { return false; } // only plAGMasterMod should handle these
virtual void IApplyDynamic() {}; // dummy function required by base class
// INTERNAL ACCESSORS FOR SCENE OBJECT INTERFACES
plAudioInterface * LeakAI() const { return IGetTargetAudioInterface(0); };
plCoordinateInterface * LeakCI() const { return IGetTargetCoordinateInterface(0); };
plDrawInterface * LeakDI() const { return IGetTargetDrawInterface(0); };
plSimulationInterface * LeakSI() const { return IGetTargetSimulationInterface(0); };
plObjInterface * LeakGI(UInt32 classIdx) const { return IGetTargetGenericInterface(0, classIdx); }
friend plAudioInterface * plAGApplicator::IGetAI(const plAGModifier * modifier) const;
friend plCoordinateInterface * plAGApplicator::IGetCI(const plAGModifier * modifier) const;
friend plDrawInterface * plAGApplicator::IGetDI(const plAGModifier * modifier) const;
friend plSimulationInterface * plAGApplicator::IGetSI(const plAGModifier * modifier) const;
friend plObjInterface * plAGApplicator::IGetGI(const plAGModifier * modifier, UInt16 classIdx) const;
};
const plModifier * FindModifierByClass(const plSceneObject *obj, int classID);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,273 +1,273 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAnimStage.h
An intelligent avatar animation for use in a generic brain.
\ingroup Avatar
*/
#ifndef PL_ANIM_STAGE_INC
#define PL_ANIM_STAGE_INC
#include "hsMatrix44.h"
#include "hsStlUtils.h"
#include "pnFactory/plCreatable.h"
class plMessage;
class plAGAnimInstance;
class plArmatureMod;
class plArmatureMod;
class hsStream;
class hsResMgr;
class plArmatureBrain;
class plDebugText;
class plMultistageBehMod;
// PLANIMSTAGE
// In a multi-stage behavior, each stage is specified in one of these classes
/** \class plAnimStage
An animation stage is an intelligent wrapper for an avatar animation.
It provides specific control over:
- how the progress of the animation is controlled
- when the animation optionally sends messages about its progress
- whether the animation naturally progresses to the next animation after finishing
- how many times the animation loops
- whether the animation works in world space or a local space
*/
class plAnimStage : public plCreatable
{
public:
// -- forward declarations of types --
// Points to send notifications at
/** \enum NotifyType
Controls when notification messages are sent by the stage.
These can be used instead of or in combination with
normal animation callback messages.
Where the messages are sent is determined by the controlling
brain.
These are mask bits; you can have any number of them on at a time.
*/
enum NotifyType
{
kNotifyEnter = 0x1, /// Send when we enter the stage from
kNotifyLoop = 0x2, /// Sent each time the stage loops
kNotifyAdvance = 0x4, /// Sent when we advance out of the stage
kNotifyRegress = 0x8 /// Sent when we regress out of the stage
};
/** \enum ForwardType
What makes the stage progress in a forward direction?
You can only choose one of these, although a stage will always respond
to forward movement messages. */
enum ForwardType {
kForwardNone, /// move forward only in response to messages
kForwardKey, /// move forward when the user presses the move forward key
kForwardAuto, /// move forward automatically
kForwardMax,
} fForwardType;
/** \enum BackType
What makes the stage progress in a backward direction?
You can only choose one of these, although a stage will always respond
to backward movement message. */
enum BackType {
kBackNone, /// move backward only in response to messages
kBackKey, /// move backward when the user presses the move backward key
kBackAuto, /// move backward automatically (only when entered from end)
kBackMax,
} fBackType;
/** When do we advance to the next stage?
This is typically asked when we're reached the end of the current stage,
but for some advance types, you can interrupt the current stage and
advance automatically on certain events. */
enum AdvanceType {
kAdvanceNone, /// advance only when told to via a message
kAdvanceOnMove, /// advance whenever the user hits a movement key
kAdvanceAuto, /// advance automatically at the end of the current stage
kAdvanceOnAnyKey, /// advance when any key is pressed
kAdvanceMax,
} fAdvanceType;
/** When do we regress to the previous stage?
This is typically asked when we've reached the beginning of the current stage
and we still trying to move backwards.
For some regress types, however, you can abort this stage automatically when
certain events occur. */
enum RegressType {
kRegressNone, // regress only when told to via a message
kRegressOnMove, // regress whenever the user hits a movement key
kRegressAuto, // regress automatically when we reach the beginning of the current
/// stage and we're still moving backwards
kRegressOnAnyKey, // regress when any key is pressed
kRegressMax,
} fRegressType;
/** Default constructor, used primarily by the class factory. */
plAnimStage();
/** Canonical constructor.
\param animName The name of the animation controlled by this stage.
\param notify Flags for when to send notify messages
\param forward How to control forward movement
\param backward How to control backward movement
\param regress When to regress to the previous stage
\param advance When to advance to the next stage
\param loops How many times to loop this stage after its initial playthrough.
i.e. If you only want it to play once, set loops to 0
To make it play forever, pass in -1 for loops.
\param localize Align the origin of the animation to the avatar's position
when the stage start's playing. Only relevant if the
animation attempts to reposition the avatar by having a
channel attached to the avatar's handle.
*/
plAnimStage(const char *animName,
UInt8 notify,
ForwardType forward,
BackType backward,
AdvanceType advance,
RegressType regress,
int loops);
/** Most complete constructor. Specifies every aspect of the stage. Differs from
the next-most-complete constructor by the presence of doAdvanceTo, advanceTo,
doRegressTo, and regressTo. These parameters allow you to specify what stages
will be played after this one, depending on which direction the stage is
moving.
*/
plAnimStage(const char *animName,
UInt8 notify,
ForwardType forward,
BackType back,
AdvanceType advance,
RegressType regress,
int loops,
bool doAdvanceTo,
int advanceTo,
bool doRegressTo,
int regressTo);
/** Simple and common constructor: moves forward automatically, advances automatically,
no reverse, no regress.
\param animName The name of the animation controlled by this stage.
\param notify Flags for when to send notify messages
*/
plAnimStage(const char *animName, UInt8 notify);
virtual ~plAnimStage();
const plAnimStage& operator=(const plAnimStage& src);
plAGAnimInstance * Attach(plArmatureMod *armature, plArmatureBrain *brain, float initialBlend, double time);
int Detach(plArmatureMod *armature);
void Reset(double time, plArmatureMod *avMod, bool atStart);
void ResetAtTime(double time, float localTime, plArmatureMod *avMod);
bool MoveRelative(double worldTime, float delta, float &overage, plArmatureMod *avMod);
/** The name of the animation associated with this stage. */
const char * GetAnimName();
ForwardType GetForwardType();
void SetForwardType(ForwardType t);
BackType GetBackType();
void SetBackType(BackType t);
AdvanceType GetAdvanceType();
void SetAdvanceType(AdvanceType t);
RegressType GetRegressType();
void SetRegresstype(RegressType t);
UInt32 GetNotifyFlags();
void SetNotifyFlags(UInt32 newFlags);
int GetNumLoops();
void SetNumLoops(int loops);
int GetLoopValue();
void SetLoopValue(int loop);
float GetLocalTime();
void SetLocalTime(float time, hsBool noCallbacks = false);
float GetLength();
void SetMod(plMultistageBehMod* p) { fMod = p; } // for returning ID#'s to python scripts:
plMultistageBehMod* GetMod() { return fMod; }
bool GetIsAttached();
void SetIsAttached(bool status);
int GetNextStage(int curStage);
int GetPrevStage(int curStage);
plAGAnimInstance *GetAnimInstance() const { return fAnimInstance; };
bool GetReverseOnIdle() { return fReverseOnIdle; }
void SetReverseOnIdle(bool onOff) { fReverseOnIdle = onOff; }
void DumpDebug(bool active, int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
// STANDARD PLASMA PROTOCOL
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void SaveAux(hsStream *stream, hsResMgr *mgr);
virtual void LoadAux(hsStream *stream, hsResMgr *mgr, double time);
CLASSNAME_REGISTER( plAnimStage );
GETINTERFACE_ANY( plAnimStage, plCreatable);
protected:
bool IMoveBackward(double worldTime, float delta, float &underrun, plArmatureMod *avMod);
bool IMoveForward(double worldTime, float delta, float &overrun, plArmatureMod *avMod);
bool INeedFadeIn();
bool INeedFadeOut();
bool ITryAdvance(plArmatureMod *avMod);
bool ITryRegress(plArmatureMod *avMod);
hsBool ISendNotify(UInt32 notifyMask, UInt32 notifyType, plArmatureMod *armature, plArmatureBrain *brain);
char *fAnimName; // the name of our animation
UInt8 fNotify; // flags for which events will cause notification events
int fLoops; // how many times will this animation loop (after initial playthrough?)
bool fDoAdvanceTo; // advance to a specific stage instead of n + 1
UInt32 fAdvanceTo; // the stage to advance to, provided fDoAdvanceTo is true
bool fDoRegressTo; // regress to a specific stage instaed of n - 1
UInt32 fRegressTo; // the stage to regress true, provided fDoRegressTo is true
// --- these are derived & kept for bookkeeping
plAGAnimInstance *fAnimInstance;
plArmatureMod *fArmature;
plArmatureBrain *fBrain; // only valid while attached
plMultistageBehMod *fMod; // where we came from
float fLocalTime; // our time within the animation
float fLength; // the length of our animation?
int fCurLoop; // which loop are we currently in?
bool fAttached; // in the middle of reloading
bool fAnimatedHandle; // this animation moves the handle
UInt8 fSentNotifies; // which notifies have we sent?
bool fReverseOnIdle; // reverse our key interpretation if we stop. this is a special
// case for down ladders, for which the forward button means "keep going down"
// if you hold it down the whole time, but means "go up" if you press it
// again after releasing it.
bool fDone; // We've reached the end of the anim -- may be fading out, or paused.
};
class plAnimStageVec : public std::vector<plAnimStage*>
{
};
#endif // PL_ANIM_STAGE_INC
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAnimStage.h
An intelligent avatar animation for use in a generic brain.
\ingroup Avatar
*/
#ifndef PL_ANIM_STAGE_INC
#define PL_ANIM_STAGE_INC
#include "hsMatrix44.h"
#include "hsStlUtils.h"
#include "pnFactory/plCreatable.h"
class plMessage;
class plAGAnimInstance;
class plArmatureMod;
class plArmatureMod;
class hsStream;
class hsResMgr;
class plArmatureBrain;
class plDebugText;
class plMultistageBehMod;
// PLANIMSTAGE
// In a multi-stage behavior, each stage is specified in one of these classes
/** \class plAnimStage
An animation stage is an intelligent wrapper for an avatar animation.
It provides specific control over:
- how the progress of the animation is controlled
- when the animation optionally sends messages about its progress
- whether the animation naturally progresses to the next animation after finishing
- how many times the animation loops
- whether the animation works in world space or a local space
*/
class plAnimStage : public plCreatable
{
public:
// -- forward declarations of types --
// Points to send notifications at
/** \enum NotifyType
Controls when notification messages are sent by the stage.
These can be used instead of or in combination with
normal animation callback messages.
Where the messages are sent is determined by the controlling
brain.
These are mask bits; you can have any number of them on at a time.
*/
enum NotifyType
{
kNotifyEnter = 0x1, /// Send when we enter the stage from
kNotifyLoop = 0x2, /// Sent each time the stage loops
kNotifyAdvance = 0x4, /// Sent when we advance out of the stage
kNotifyRegress = 0x8 /// Sent when we regress out of the stage
};
/** \enum ForwardType
What makes the stage progress in a forward direction?
You can only choose one of these, although a stage will always respond
to forward movement messages. */
enum ForwardType {
kForwardNone, /// move forward only in response to messages
kForwardKey, /// move forward when the user presses the move forward key
kForwardAuto, /// move forward automatically
kForwardMax,
} fForwardType;
/** \enum BackType
What makes the stage progress in a backward direction?
You can only choose one of these, although a stage will always respond
to backward movement message. */
enum BackType {
kBackNone, /// move backward only in response to messages
kBackKey, /// move backward when the user presses the move backward key
kBackAuto, /// move backward automatically (only when entered from end)
kBackMax,
} fBackType;
/** When do we advance to the next stage?
This is typically asked when we're reached the end of the current stage,
but for some advance types, you can interrupt the current stage and
advance automatically on certain events. */
enum AdvanceType {
kAdvanceNone, /// advance only when told to via a message
kAdvanceOnMove, /// advance whenever the user hits a movement key
kAdvanceAuto, /// advance automatically at the end of the current stage
kAdvanceOnAnyKey, /// advance when any key is pressed
kAdvanceMax,
} fAdvanceType;
/** When do we regress to the previous stage?
This is typically asked when we've reached the beginning of the current stage
and we still trying to move backwards.
For some regress types, however, you can abort this stage automatically when
certain events occur. */
enum RegressType {
kRegressNone, // regress only when told to via a message
kRegressOnMove, // regress whenever the user hits a movement key
kRegressAuto, // regress automatically when we reach the beginning of the current
/// stage and we're still moving backwards
kRegressOnAnyKey, // regress when any key is pressed
kRegressMax,
} fRegressType;
/** Default constructor, used primarily by the class factory. */
plAnimStage();
/** Canonical constructor.
\param animName The name of the animation controlled by this stage.
\param notify Flags for when to send notify messages
\param forward How to control forward movement
\param backward How to control backward movement
\param regress When to regress to the previous stage
\param advance When to advance to the next stage
\param loops How many times to loop this stage after its initial playthrough.
i.e. If you only want it to play once, set loops to 0
To make it play forever, pass in -1 for loops.
\param localize Align the origin of the animation to the avatar's position
when the stage start's playing. Only relevant if the
animation attempts to reposition the avatar by having a
channel attached to the avatar's handle.
*/
plAnimStage(const char *animName,
UInt8 notify,
ForwardType forward,
BackType backward,
AdvanceType advance,
RegressType regress,
int loops);
/** Most complete constructor. Specifies every aspect of the stage. Differs from
the next-most-complete constructor by the presence of doAdvanceTo, advanceTo,
doRegressTo, and regressTo. These parameters allow you to specify what stages
will be played after this one, depending on which direction the stage is
moving.
*/
plAnimStage(const char *animName,
UInt8 notify,
ForwardType forward,
BackType back,
AdvanceType advance,
RegressType regress,
int loops,
bool doAdvanceTo,
int advanceTo,
bool doRegressTo,
int regressTo);
/** Simple and common constructor: moves forward automatically, advances automatically,
no reverse, no regress.
\param animName The name of the animation controlled by this stage.
\param notify Flags for when to send notify messages
*/
plAnimStage(const char *animName, UInt8 notify);
virtual ~plAnimStage();
const plAnimStage& operator=(const plAnimStage& src);
plAGAnimInstance * Attach(plArmatureMod *armature, plArmatureBrain *brain, float initialBlend, double time);
int Detach(plArmatureMod *armature);
void Reset(double time, plArmatureMod *avMod, bool atStart);
void ResetAtTime(double time, float localTime, plArmatureMod *avMod);
bool MoveRelative(double worldTime, float delta, float &overage, plArmatureMod *avMod);
/** The name of the animation associated with this stage. */
const char * GetAnimName();
ForwardType GetForwardType();
void SetForwardType(ForwardType t);
BackType GetBackType();
void SetBackType(BackType t);
AdvanceType GetAdvanceType();
void SetAdvanceType(AdvanceType t);
RegressType GetRegressType();
void SetRegresstype(RegressType t);
UInt32 GetNotifyFlags();
void SetNotifyFlags(UInt32 newFlags);
int GetNumLoops();
void SetNumLoops(int loops);
int GetLoopValue();
void SetLoopValue(int loop);
float GetLocalTime();
void SetLocalTime(float time, hsBool noCallbacks = false);
float GetLength();
void SetMod(plMultistageBehMod* p) { fMod = p; } // for returning ID#'s to python scripts:
plMultistageBehMod* GetMod() { return fMod; }
bool GetIsAttached();
void SetIsAttached(bool status);
int GetNextStage(int curStage);
int GetPrevStage(int curStage);
plAGAnimInstance *GetAnimInstance() const { return fAnimInstance; };
bool GetReverseOnIdle() { return fReverseOnIdle; }
void SetReverseOnIdle(bool onOff) { fReverseOnIdle = onOff; }
void DumpDebug(bool active, int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
// STANDARD PLASMA PROTOCOL
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void SaveAux(hsStream *stream, hsResMgr *mgr);
virtual void LoadAux(hsStream *stream, hsResMgr *mgr, double time);
CLASSNAME_REGISTER( plAnimStage );
GETINTERFACE_ANY( plAnimStage, plCreatable);
protected:
bool IMoveBackward(double worldTime, float delta, float &underrun, plArmatureMod *avMod);
bool IMoveForward(double worldTime, float delta, float &overrun, plArmatureMod *avMod);
bool INeedFadeIn();
bool INeedFadeOut();
bool ITryAdvance(plArmatureMod *avMod);
bool ITryRegress(plArmatureMod *avMod);
hsBool ISendNotify(UInt32 notifyMask, UInt32 notifyType, plArmatureMod *armature, plArmatureBrain *brain);
char *fAnimName; // the name of our animation
UInt8 fNotify; // flags for which events will cause notification events
int fLoops; // how many times will this animation loop (after initial playthrough?)
bool fDoAdvanceTo; // advance to a specific stage instead of n + 1
UInt32 fAdvanceTo; // the stage to advance to, provided fDoAdvanceTo is true
bool fDoRegressTo; // regress to a specific stage instaed of n - 1
UInt32 fRegressTo; // the stage to regress true, provided fDoRegressTo is true
// --- these are derived & kept for bookkeeping
plAGAnimInstance *fAnimInstance;
plArmatureMod *fArmature;
plArmatureBrain *fBrain; // only valid while attached
plMultistageBehMod *fMod; // where we came from
float fLocalTime; // our time within the animation
float fLength; // the length of our animation?
int fCurLoop; // which loop are we currently in?
bool fAttached; // in the middle of reloading
bool fAnimatedHandle; // this animation moves the handle
UInt8 fSentNotifies; // which notifies have we sent?
bool fReverseOnIdle; // reverse our key interpretation if we stop. this is a special
// case for down ladders, for which the forward button means "keep going down"
// if you hold it down the whole time, but means "go up" if you press it
// again after releasing it.
bool fDone; // We've reached the end of the anim -- may be fading out, or paused.
};
class plAnimStageVec : public std::vector<plAnimStage*>
{
};
#endif // PL_ANIM_STAGE_INC

View File

@ -1,155 +1,155 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#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;
}
}
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#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

@ -1,63 +1,63 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#if 0//ndef PL_ANTI_GRAV_ACTION_H
#define PL_ANTI_GRAV_ACTION_H
#include "plAvCallbackAction.h"
class plSwimRegionInterface;
class plAntiGravAction : public plAnimatedCallbackAction
{
public:
plAntiGravAction(plHKPhysical *physical, plAGApplicator *rootApp);
/** 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();
/** 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; }
protected:
void IAdjustBuoyancy();
hsBool fOnGround;
hsBool fHadContacts;
hsScalar fBuoyancy;
hsScalar fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#if 0//ndef PL_ANTI_GRAV_ACTION_H
#define PL_ANTI_GRAV_ACTION_H
#include "plAvCallbackAction.h"
class plSwimRegionInterface;
class plAntiGravAction : public plAnimatedCallbackAction
{
public:
plAntiGravAction(plHKPhysical *physical, plAGApplicator *rootApp);
/** 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();
/** 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; }
protected:
void IAdjustBuoyancy();
hsBool fOnGround;
hsBool fHadContacts;
hsScalar fBuoyancy;
hsScalar fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
};
#endif

View File

@ -1,325 +1,325 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvCallbackAction.h"
#include "plStatusLog/plStatusLog.h"
#include "plArmatureEffects.h"
#include "pfMessage/plArmatureEffectMsg.h"
#include "plMessage/plAnimCmdMsg.h"
#include "plMessage/plAvatarMsg.h"
#include "plArmatureMod.h"
#include "pnSceneObject/plAudioInterface.h"
#include "plAudio/plSound.h"
#include "plAudio/plAudioSystem.h"
#include "pfAudio/plRandomSoundMod.h"
#include "hsResMgr.h"
#include "plgDispatch.h"
const char *plArmatureEffectsMgr::SurfaceStrings[] =
{
"Dirt",
"Puddle",
"Water",
"Tile",
"Metal",
"WoodBridge",
"RopeLadder",
"Grass",
"Brush",
"HardWood",
"Rug",
"Stone",
"Mud",
"MetalLadder",
"WoodLadder",
"DeepWater",
"Maintainer(Glass)",
"Maintainer(Stone)",
"Swimming",
"(none)" // Keep this one last
};
void plArmatureEffectsMgr::Read(hsStream *s, hsResMgr *mgr)
{
hsKeyedObject::Read(s, mgr);
int numEffects = s->ReadSwap32();
while (numEffects > 0)
{
plRefMsg *msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, -1);
hsgResMgr::ResMgr()->ReadKeyNotifyMe(s, msg, plRefFlags::kActiveRef);
numEffects--;
}
plgDispatch::Dispatch()->RegisterForExactType(plAvatarStealthModeMsg::Index(), GetKey());
}
void plArmatureEffectsMgr::Write(hsStream *s, hsResMgr *mgr)
{
hsKeyedObject::Write(s, mgr);
s->WriteSwap32(fEffects.GetCount());
int i;
for (i = 0; i < fEffects.GetCount(); i++)
mgr->WriteKey(s, fEffects[i]->GetKey());
}
hsBool plArmatureEffectsMgr::MsgReceive(plMessage* msg)
{
plEventCallbackInterceptMsg *iMsg = plEventCallbackInterceptMsg::ConvertNoRef(msg);
if (iMsg)
{
if (fEnabled)
iMsg->SendMessage();
}
plArmatureEffectMsg *eMsg = plArmatureEffectMsg::ConvertNoRef(msg);
plArmatureEffectStateMsg *sMsg = plArmatureEffectStateMsg::ConvertNoRef(msg);
if (eMsg || sMsg)
{
// Always handle state messages, but only trigger actual effects if we're enabled
if (sMsg || fEnabled)
{
int i;
for (i = 0; i < fEffects.GetCount(); i++)
fEffects[i]->HandleTrigger(msg);
}
return true;
}
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef(msg);
if (refMsg)
{
plArmatureEffect *effect = plArmatureEffect::ConvertNoRef(refMsg->GetRef());
if (effect)
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
fEffects.Append(effect);
else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
fEffects.RemoveItem(effect);
return true;
}
}
plAvatarStealthModeMsg *stealthMsg = plAvatarStealthModeMsg::ConvertNoRef(msg);
if (stealthMsg && stealthMsg->GetSender() == fArmature->GetTarget(0)->GetKey())
{
if (stealthMsg->fMode == plAvatarStealthModeMsg::kStealthCloaked)
fEnabled = false;
else
fEnabled = true;
return true;
}
return hsKeyedObject::MsgReceive(msg);
}
UInt32 plArmatureEffectsMgr::GetNumEffects()
{
return fEffects.GetCount();
}
plArmatureEffect *plArmatureEffectsMgr::GetEffect(UInt32 num)
{
return fEffects[num];
}
void plArmatureEffectsMgr::ResetEffects()
{
int i;
for (i = 0; i < fEffects.GetCount(); i++)
fEffects[i]->Reset();
}
/////////////////////////////////////////////////////////////////////////////
//
// Actual Effects
//
/////////////////////////////////////////////////////////////////////////////
plArmatureEffectFootSound::plArmatureEffectFootSound()
{
plArmatureEffectFootSurface *surface = TRACKED_NEW plArmatureEffectFootSurface;
surface->fID = plArmatureEffectsMgr::kFootNoSurface;
surface->fTrigger = nil;
fSurfaces.Append(surface);
int i;
for (i = 0; i < plArmatureEffectsMgr::kMaxSurface; i++)
{
fMods[i] = nil;
}
SetFootType(kFootTypeShoe);
}
plArmatureEffectFootSound::~plArmatureEffectFootSound()
{
int i;
for (i = 0; i < fSurfaces.GetCount(); i++)
delete fSurfaces[i];
}
void plArmatureEffectFootSound::Read(hsStream* s, hsResMgr* mgr)
{
plArmatureEffect::Read(s, mgr);
int count = s->ReadByte();
int i;
for (i = 0; i < count; i++)
{
plGenRefMsg *msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, i, -1);
mgr->ReadKeyNotifyMe(s, msg, plRefFlags::kActiveRef);
}
}
UInt32 plArmatureEffectFootSound::IFindSurfaceByTrigger(plKey trigger)
{
UInt32 i;
// Skip index 0. It's the special "NoSurface" that should always be at the stack bottom
for (i = 1; i < fSurfaces.GetCount(); i++)
{
if (fSurfaces[i]->fTrigger == trigger)
return i;
}
return -1;
}
void plArmatureEffectFootSound::Write(hsStream* s, hsResMgr* mgr)
{
plArmatureEffect::Write(s, mgr);
s->WriteByte(plArmatureEffectsMgr::kMaxSurface);
int i;
for (i = 0; i < plArmatureEffectsMgr::kMaxSurface; i++)
mgr->WriteKey(s, (fMods[i] ? fMods[i]->GetKey() : nil));
}
hsBool plArmatureEffectFootSound::MsgReceive(plMessage* msg)
{
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef(msg);
if (refMsg)
{
plRandomSoundMod *rsMod = plRandomSoundMod::ConvertNoRef(refMsg->GetRef());
if (rsMod)
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
{
fMods[refMsg->fWhich] = rsMod;
}
else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
fMods[refMsg->fWhich] = nil;
return true;
}
}
return plArmatureEffect::MsgReceive(msg);
}
hsBool plArmatureEffectFootSound::HandleTrigger(plMessage* msg)
{
plArmatureEffectMsg *eMsg = plArmatureEffectMsg::ConvertNoRef(msg);
if (eMsg)
{
UInt32 curSurfaceIndex = fSurfaces[fSurfaces.GetCount() - 1]->fID;
if (curSurfaceIndex < plArmatureEffectsMgr::kMaxSurface && fMods[curSurfaceIndex] != nil)
{
if (plgAudioSys::Active() && fActiveSurfaces.IsBitSet(curSurfaceIndex))
{
fMods[curSurfaceIndex]->SetCurrentGroup(eMsg->fTriggerIdx);
plAnimCmdMsg *animMsg = TRACKED_NEW plAnimCmdMsg;
animMsg->AddReceiver(fMods[curSurfaceIndex]->GetKey());
animMsg->SetCmd(plAnimCmdMsg::kContinue);
plgDispatch::MsgSend(animMsg);
}
}
return true;
}
plArmatureEffectStateMsg *sMsg = plArmatureEffectStateMsg::ConvertNoRef(msg);
if (sMsg)
{
// It doesn't matter if we're adding or removing a surface, our load/unload is the same:
// unload the old surface and load the new one
if (sMsg->fAddSurface)
{
if (IFindSurfaceByTrigger(sMsg->GetSender()) == -1) // Check that it's not a repeat msg
{
plStatusLog::AddLineS("audio.log", "FTSP: Switching to surface - %s",
plArmatureEffectsMgr::SurfaceStrings[sMsg->fSurface]);
plArmatureEffectFootSurface *surface = TRACKED_NEW plArmatureEffectFootSurface;
surface->fID = sMsg->fSurface;
surface->fTrigger = sMsg->GetSender();
fSurfaces.Append(surface);
}
}
else
{
UInt32 index = IFindSurfaceByTrigger(sMsg->GetSender());
if (index != -1)
{
if (index == fSurfaces.GetCount() - 1) // It's the top on the stack
plStatusLog::AddLineS("audio.log", "FTSP: Switching to surface - %s",
plArmatureEffectsMgr::SurfaceStrings[fSurfaces[index - 1]->fID]);
delete fSurfaces[index];
fSurfaces.Remove(index);
}
}
return true;
}
return false;
}
void plArmatureEffectFootSound::Reset()
{
while (fSurfaces.GetCount() > 1)
delete fSurfaces.Pop();
}
void plArmatureEffectFootSound::SetFootType(UInt8 type)
{
if (type == kFootTypeBare)
{
fActiveSurfaces.Clear();
fActiveSurfaces.SetBit(plArmatureEffectsMgr::kFootDeepWater);
fActiveSurfaces.SetBit(plArmatureEffectsMgr::kFootPuddle);
fActiveSurfaces.SetBit(plArmatureEffectsMgr::kFootWater);
fActiveSurfaces.SetBit(plArmatureEffectsMgr::kFootSwimming);
}
else
{
fActiveSurfaces.Set(plArmatureEffectsMgr::kMaxSurface);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvCallbackAction.h"
#include "plStatusLog/plStatusLog.h"
#include "plArmatureEffects.h"
#include "pfMessage/plArmatureEffectMsg.h"
#include "plMessage/plAnimCmdMsg.h"
#include "plMessage/plAvatarMsg.h"
#include "plArmatureMod.h"
#include "pnSceneObject/plAudioInterface.h"
#include "plAudio/plSound.h"
#include "plAudio/plAudioSystem.h"
#include "pfAudio/plRandomSoundMod.h"
#include "hsResMgr.h"
#include "plgDispatch.h"
const char *plArmatureEffectsMgr::SurfaceStrings[] =
{
"Dirt",
"Puddle",
"Water",
"Tile",
"Metal",
"WoodBridge",
"RopeLadder",
"Grass",
"Brush",
"HardWood",
"Rug",
"Stone",
"Mud",
"MetalLadder",
"WoodLadder",
"DeepWater",
"Maintainer(Glass)",
"Maintainer(Stone)",
"Swimming",
"(none)" // Keep this one last
};
void plArmatureEffectsMgr::Read(hsStream *s, hsResMgr *mgr)
{
hsKeyedObject::Read(s, mgr);
int numEffects = s->ReadSwap32();
while (numEffects > 0)
{
plRefMsg *msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, -1);
hsgResMgr::ResMgr()->ReadKeyNotifyMe(s, msg, plRefFlags::kActiveRef);
numEffects--;
}
plgDispatch::Dispatch()->RegisterForExactType(plAvatarStealthModeMsg::Index(), GetKey());
}
void plArmatureEffectsMgr::Write(hsStream *s, hsResMgr *mgr)
{
hsKeyedObject::Write(s, mgr);
s->WriteSwap32(fEffects.GetCount());
int i;
for (i = 0; i < fEffects.GetCount(); i++)
mgr->WriteKey(s, fEffects[i]->GetKey());
}
hsBool plArmatureEffectsMgr::MsgReceive(plMessage* msg)
{
plEventCallbackInterceptMsg *iMsg = plEventCallbackInterceptMsg::ConvertNoRef(msg);
if (iMsg)
{
if (fEnabled)
iMsg->SendMessage();
}
plArmatureEffectMsg *eMsg = plArmatureEffectMsg::ConvertNoRef(msg);
plArmatureEffectStateMsg *sMsg = plArmatureEffectStateMsg::ConvertNoRef(msg);
if (eMsg || sMsg)
{
// Always handle state messages, but only trigger actual effects if we're enabled
if (sMsg || fEnabled)
{
int i;
for (i = 0; i < fEffects.GetCount(); i++)
fEffects[i]->HandleTrigger(msg);
}
return true;
}
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef(msg);
if (refMsg)
{
plArmatureEffect *effect = plArmatureEffect::ConvertNoRef(refMsg->GetRef());
if (effect)
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
fEffects.Append(effect);
else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
fEffects.RemoveItem(effect);
return true;
}
}
plAvatarStealthModeMsg *stealthMsg = plAvatarStealthModeMsg::ConvertNoRef(msg);
if (stealthMsg && stealthMsg->GetSender() == fArmature->GetTarget(0)->GetKey())
{
if (stealthMsg->fMode == plAvatarStealthModeMsg::kStealthCloaked)
fEnabled = false;
else
fEnabled = true;
return true;
}
return hsKeyedObject::MsgReceive(msg);
}
UInt32 plArmatureEffectsMgr::GetNumEffects()
{
return fEffects.GetCount();
}
plArmatureEffect *plArmatureEffectsMgr::GetEffect(UInt32 num)
{
return fEffects[num];
}
void plArmatureEffectsMgr::ResetEffects()
{
int i;
for (i = 0; i < fEffects.GetCount(); i++)
fEffects[i]->Reset();
}
/////////////////////////////////////////////////////////////////////////////
//
// Actual Effects
//
/////////////////////////////////////////////////////////////////////////////
plArmatureEffectFootSound::plArmatureEffectFootSound()
{
plArmatureEffectFootSurface *surface = TRACKED_NEW plArmatureEffectFootSurface;
surface->fID = plArmatureEffectsMgr::kFootNoSurface;
surface->fTrigger = nil;
fSurfaces.Append(surface);
int i;
for (i = 0; i < plArmatureEffectsMgr::kMaxSurface; i++)
{
fMods[i] = nil;
}
SetFootType(kFootTypeShoe);
}
plArmatureEffectFootSound::~plArmatureEffectFootSound()
{
int i;
for (i = 0; i < fSurfaces.GetCount(); i++)
delete fSurfaces[i];
}
void plArmatureEffectFootSound::Read(hsStream* s, hsResMgr* mgr)
{
plArmatureEffect::Read(s, mgr);
int count = s->ReadByte();
int i;
for (i = 0; i < count; i++)
{
plGenRefMsg *msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, i, -1);
mgr->ReadKeyNotifyMe(s, msg, plRefFlags::kActiveRef);
}
}
UInt32 plArmatureEffectFootSound::IFindSurfaceByTrigger(plKey trigger)
{
UInt32 i;
// Skip index 0. It's the special "NoSurface" that should always be at the stack bottom
for (i = 1; i < fSurfaces.GetCount(); i++)
{
if (fSurfaces[i]->fTrigger == trigger)
return i;
}
return -1;
}
void plArmatureEffectFootSound::Write(hsStream* s, hsResMgr* mgr)
{
plArmatureEffect::Write(s, mgr);
s->WriteByte(plArmatureEffectsMgr::kMaxSurface);
int i;
for (i = 0; i < plArmatureEffectsMgr::kMaxSurface; i++)
mgr->WriteKey(s, (fMods[i] ? fMods[i]->GetKey() : nil));
}
hsBool plArmatureEffectFootSound::MsgReceive(plMessage* msg)
{
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef(msg);
if (refMsg)
{
plRandomSoundMod *rsMod = plRandomSoundMod::ConvertNoRef(refMsg->GetRef());
if (rsMod)
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
{
fMods[refMsg->fWhich] = rsMod;
}
else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
fMods[refMsg->fWhich] = nil;
return true;
}
}
return plArmatureEffect::MsgReceive(msg);
}
hsBool plArmatureEffectFootSound::HandleTrigger(plMessage* msg)
{
plArmatureEffectMsg *eMsg = plArmatureEffectMsg::ConvertNoRef(msg);
if (eMsg)
{
UInt32 curSurfaceIndex = fSurfaces[fSurfaces.GetCount() - 1]->fID;
if (curSurfaceIndex < plArmatureEffectsMgr::kMaxSurface && fMods[curSurfaceIndex] != nil)
{
if (plgAudioSys::Active() && fActiveSurfaces.IsBitSet(curSurfaceIndex))
{
fMods[curSurfaceIndex]->SetCurrentGroup(eMsg->fTriggerIdx);
plAnimCmdMsg *animMsg = TRACKED_NEW plAnimCmdMsg;
animMsg->AddReceiver(fMods[curSurfaceIndex]->GetKey());
animMsg->SetCmd(plAnimCmdMsg::kContinue);
plgDispatch::MsgSend(animMsg);
}
}
return true;
}
plArmatureEffectStateMsg *sMsg = plArmatureEffectStateMsg::ConvertNoRef(msg);
if (sMsg)
{
// It doesn't matter if we're adding or removing a surface, our load/unload is the same:
// unload the old surface and load the new one
if (sMsg->fAddSurface)
{
if (IFindSurfaceByTrigger(sMsg->GetSender()) == -1) // Check that it's not a repeat msg
{
plStatusLog::AddLineS("audio.log", "FTSP: Switching to surface - %s",
plArmatureEffectsMgr::SurfaceStrings[sMsg->fSurface]);
plArmatureEffectFootSurface *surface = TRACKED_NEW plArmatureEffectFootSurface;
surface->fID = sMsg->fSurface;
surface->fTrigger = sMsg->GetSender();
fSurfaces.Append(surface);
}
}
else
{
UInt32 index = IFindSurfaceByTrigger(sMsg->GetSender());
if (index != -1)
{
if (index == fSurfaces.GetCount() - 1) // It's the top on the stack
plStatusLog::AddLineS("audio.log", "FTSP: Switching to surface - %s",
plArmatureEffectsMgr::SurfaceStrings[fSurfaces[index - 1]->fID]);
delete fSurfaces[index];
fSurfaces.Remove(index);
}
}
return true;
}
return false;
}
void plArmatureEffectFootSound::Reset()
{
while (fSurfaces.GetCount() > 1)
delete fSurfaces.Pop();
}
void plArmatureEffectFootSound::SetFootType(UInt8 type)
{
if (type == kFootTypeBare)
{
fActiveSurfaces.Clear();
fActiveSurfaces.SetBit(plArmatureEffectsMgr::kFootDeepWater);
fActiveSurfaces.SetBit(plArmatureEffectsMgr::kFootPuddle);
fActiveSurfaces.SetBit(plArmatureEffectsMgr::kFootWater);
fActiveSurfaces.SetBit(plArmatureEffectsMgr::kFootSwimming);
}
else
{
fActiveSurfaces.Set(plArmatureEffectsMgr::kMaxSurface);
}
}

View File

@ -1,148 +1,148 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plArmatureEffects.h
Manages environmental effects for the avatar.
*/
#ifndef plArmatureEffects_inc
#define plArmatureEffects_inc
#include "pnKeyedObject/hsKeyedObject.h"
#include "hsTemplates.h"
#include "hsBitVector.h"
class plArmatureMod;
class plArmatureEffect;
class plRandomSoundMod;
/** \class plArmatureEffects
Passes key avatar events to external effects generators.
Currently used for footstep sounds only, but should eventually
generalize to water splashes, etc.
More to come...*/
class plArmatureEffectsMgr : public hsKeyedObject
{
protected:
hsTArray<plArmatureEffect *> fEffects;
hsBool fEnabled;
public:
plArmatureEffectsMgr() : fArmature(nil), fEnabled(true) {}
virtual ~plArmatureEffectsMgr() {}
CLASSNAME_REGISTER( plArmatureEffectsMgr );
GETINTERFACE_ANY( plArmatureEffectsMgr, hsKeyedObject );
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
UInt32 GetNumEffects();
plArmatureEffect *GetEffect(UInt32 num);
void ResetEffects();
plArmatureMod *fArmature;
enum
{
kFootDirt,
kFootPuddle,
kFootWater,
kFootTile,
kFootMetal,
kFootWoodBridge,
kFootRopeLadder,
kFootGrass,
kFootBrush,
kFootHardWood,
kFootRug,
kFootStone,
kFootMud,
kFootMetalLadder,
kFootWoodLadder,
kFootDeepWater,
kFootMaintainerGlass,
kFootMaintainerStone,
kFootSwimming,
kMaxSurface,
kFootNoSurface = kMaxSurface,
};
static const char *SurfaceStrings[];
};
class plArmatureEffect : public hsKeyedObject
{
public:
plArmatureEffect() {}
~plArmatureEffect() {}
CLASSNAME_REGISTER( plArmatureEffect );
GETINTERFACE_ANY( plArmatureEffect, hsKeyedObject );
virtual hsBool HandleTrigger(plMessage* msg) = 0;
virtual void Reset() {}
};
class plArmatureEffectFootSurface
{
public:
UInt8 fID;
plKey fTrigger;
};
class plArmatureEffectFootSound : public plArmatureEffect
{
protected:
hsTArray<plArmatureEffectFootSurface *> fSurfaces;
hsBitVector fActiveSurfaces;
plRandomSoundMod *fMods[plArmatureEffectsMgr::kMaxSurface];
UInt32 IFindSurfaceByTrigger(plKey trigger);
public:
plArmatureEffectFootSound();
~plArmatureEffectFootSound();
CLASSNAME_REGISTER( plArmatureEffectFootSound );
GETINTERFACE_ANY( plArmatureEffectFootSound, plArmatureEffect );
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
virtual hsBool HandleTrigger(plMessage* msg);
virtual void Reset();
void SetFootType(UInt8);
enum
{
kFootTypeShoe,
kFootTypeBare,
};
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plArmatureEffects.h
Manages environmental effects for the avatar.
*/
#ifndef plArmatureEffects_inc
#define plArmatureEffects_inc
#include "pnKeyedObject/hsKeyedObject.h"
#include "hsTemplates.h"
#include "hsBitVector.h"
class plArmatureMod;
class plArmatureEffect;
class plRandomSoundMod;
/** \class plArmatureEffects
Passes key avatar events to external effects generators.
Currently used for footstep sounds only, but should eventually
generalize to water splashes, etc.
More to come...*/
class plArmatureEffectsMgr : public hsKeyedObject
{
protected:
hsTArray<plArmatureEffect *> fEffects;
hsBool fEnabled;
public:
plArmatureEffectsMgr() : fArmature(nil), fEnabled(true) {}
virtual ~plArmatureEffectsMgr() {}
CLASSNAME_REGISTER( plArmatureEffectsMgr );
GETINTERFACE_ANY( plArmatureEffectsMgr, hsKeyedObject );
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
UInt32 GetNumEffects();
plArmatureEffect *GetEffect(UInt32 num);
void ResetEffects();
plArmatureMod *fArmature;
enum
{
kFootDirt,
kFootPuddle,
kFootWater,
kFootTile,
kFootMetal,
kFootWoodBridge,
kFootRopeLadder,
kFootGrass,
kFootBrush,
kFootHardWood,
kFootRug,
kFootStone,
kFootMud,
kFootMetalLadder,
kFootWoodLadder,
kFootDeepWater,
kFootMaintainerGlass,
kFootMaintainerStone,
kFootSwimming,
kMaxSurface,
kFootNoSurface = kMaxSurface,
};
static const char *SurfaceStrings[];
};
class plArmatureEffect : public hsKeyedObject
{
public:
plArmatureEffect() {}
~plArmatureEffect() {}
CLASSNAME_REGISTER( plArmatureEffect );
GETINTERFACE_ANY( plArmatureEffect, hsKeyedObject );
virtual hsBool HandleTrigger(plMessage* msg) = 0;
virtual void Reset() {}
};
class plArmatureEffectFootSurface
{
public:
UInt8 fID;
plKey fTrigger;
};
class plArmatureEffectFootSound : public plArmatureEffect
{
protected:
hsTArray<plArmatureEffectFootSurface *> fSurfaces;
hsBitVector fActiveSurfaces;
plRandomSoundMod *fMods[plArmatureEffectsMgr::kMaxSurface];
UInt32 IFindSurfaceByTrigger(plKey trigger);
public:
plArmatureEffectFootSound();
~plArmatureEffectFootSound();
CLASSNAME_REGISTER( plArmatureEffectFootSound );
GETINTERFACE_ANY( plArmatureEffectFootSound, plArmatureEffect );
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
virtual hsBool HandleTrigger(plMessage* msg);
virtual void Reset();
void SetFootType(UInt8);
enum
{
kFootTypeShoe,
kFootTypeBare,
};
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,469 +1,469 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plArmatureMod.h
A modifier which manages multi-channel animation and has a physical body.
Designed for avatars; also good for vehicles, creatures, etc.
*/
// PLARMATUREMOD
//
// An armature is an object with both a physical presence (physics behavior) and articulated animated parts.
// (The parts are not themselves physical)
// An avatar is a type of armature, as is a critter, and anything else that moves around.
//
// This modifier combines multi-channel animation with blending (inherited from plAGMasterMod)
// with convenience functions for moving a physical body around and some specialized animation support
#ifndef plArmatureMod_inc
#define plArmatureMod_inc
#include "plAGMasterMod.h"
// other local
#include "plAvDefs.h"
#include "pnSceneObject/plSimulationInterface.h"
#include "hsMatrix44.h"
#include "plNetCommon/plNetCommon.h"
#include <float.h>
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class hsQuat;
class plMatrixChannel;
class plAGModifier;
class plAGMasterMod;
class plAGChannel;
class plClothingOutfit;
class plClothingSDLModifier;
class plAvatarSDLModifier;
class plMatrixDelayedCorrectionApplicator;
class plMatrixDifferenceApp;
class plDebugText;
class plArmatureEffectsMgr;
class plAvBoneMap; // below
class plDrawable;
class plControlEventMsg;
class plAvatarInputStateMsg;
class plLayerLinkAnimation;
class plPipeline;
class plArmatureBrain;
class plArmatureUpdateMsg;
class plPhysicalControllerCore;
typedef std::vector<plKey> plKeyVector;
typedef std::vector<plArmatureBrain*> plBrainStack;
class plArmatureModBase : public plAGMasterMod
{
public:
plArmatureModBase();
virtual ~plArmatureModBase();
CLASSNAME_REGISTER( plArmatureModBase );
GETINTERFACE_ANY( plArmatureModBase, plAGMasterMod );
virtual hsBool MsgReceive(plMessage* msg);
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
plMatrixDifferenceApp *GetRootAnimator() { return fRootAnimator; }
plPhysicalControllerCore* GetController() const { return fController; }
plKey GetWorldKey() const;
virtual hsBool ValidatePhysics();
virtual hsBool ValidateMesh();
virtual void PushBrain(plArmatureBrain *brain);
virtual void PopBrain();
plArmatureBrain *GetCurrentBrain() const;
plDrawable *FindDrawable() const;
virtual void LeaveAge();
virtual hsBool IsFinal();
// LOD stuff
void AdjustLOD(); // see if we need to switch to a different resolution
hsBool SetLOD(int newLOD); // switch to a different resolution
void RefreshTree(); // Resend an LOD update to all our nodes (for when geometry changes)
int AppendMeshKey(plKey meshKey);
int AppendBoneVec(plKeyVector *boneVec);
UInt8 GetNumLOD() const;
// A collection of reasons (flags) that things might be disabled. When all flags are gone
// The object is re-enabled.
enum
{
kDisableReasonUnknown = 0x0001,
kDisableReasonRelRegion = 0x0002,
kDisableReasonLinking = 0x0004,
kDisableReasonCCR = 0x0008,
kDisableReasonVehicle = 0x0010,
kDisableReasonGenericBrain = 0x0020,
};
void EnablePhysics(hsBool status, UInt16 reason = kDisableReasonUnknown);
void EnablePhysicsKinematic(hsBool status);
void EnableDrawing(hsBool status, UInt16 reason = kDisableReasonUnknown);
hsBool IsPhysicsEnabled() { return fDisabledPhysics == 0; }
hsBool IsDrawEnabled() { return fDisabledDraw == 0; }
static void AddressMessageToDescendants(const plCoordinateInterface * CI, plMessage *msg);
static void EnableDrawingTree(const plSceneObject *object, hsBool status);
static int fMinLOD; // throttle for lowest-indexed LOD
static double fLODDistance; // Distance for first LOD switch 2nd is 2x this distance (for now)
protected:
virtual void IFinalize();
virtual void ICustomizeApplicator();
void IEnableBones(int lod, hsBool enable);
// Some of these flags are only needed by derived classes, but I just want
// the one waitFlags variable.
enum
{
kNeedMesh = 0x01,
kNeedPhysics = 0x02,
kNeedAudio = 0x04,
kNeedCamera = 0x08,
kNeedSpawn = 0x10,
kNeedApplicator = 0x20,
kNeedBrainActivation = 0x40,
};
UInt16 fWaitFlags;
int fCurLOD;
plPhysicalControllerCore* fController;
plKeyVector fMeshKeys;
plBrainStack fBrains;
plMatrixDifferenceApp *fRootAnimator;
std::vector<plKeyVector*> fUnusedBones;
UInt16 fDisabledPhysics;
UInt16 fDisabledDraw;
};
class plArmatureMod : public plArmatureModBase
{
friend class plHBehavior;
friend class plAvatarSDLModifier;
friend class plAvatarPhysicalSDLModifier;
friend class plClothingSDLModifier;
friend class plAvOneShotLinkTask;
public:
plArmatureMod();
virtual ~plArmatureMod();
CLASSNAME_REGISTER( plArmatureMod );
GETINTERFACE_ANY( plArmatureMod, plArmatureModBase );
virtual hsBool MsgReceive(plMessage* msg);
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual hsBool ValidatePhysics();
virtual hsBool ValidateMesh();
// Get or set the position of the avatar in simulation space. Set any
// arguments you don't care about to nil.
void SetPositionAndRotationSim(const hsPoint3* position, const hsQuat* rotation);
void GetPositionAndRotationSim(hsPoint3* position, hsQuat* rotation);
hsBool IsLocalAvatar();
hsBool IsLocalAI();
virtual const plSceneObject *FindBone(const char * name) const;
virtual const plSceneObject *FindBone(UInt32 id) const; // use an id from an appropriate taxonomy, such as plAvBrainHuman::BoneID
virtual void AddBoneMapping(UInt32 id, const plSceneObject *bone);
plAGModifier *GetRootAGMod();
plAGAnim *FindCustomAnim(const char *baseName) const;
virtual void Spawn(double timeNow);
virtual void SpawnAt(int which, double timeNow);
virtual void EnterAge(hsBool reSpawn);
virtual void LeaveAge();
virtual void PanicLink(hsBool playLinkOutAnim = true);
virtual void PersonalLink();
virtual bool ToggleDontPanicLinkFlag() { fDontPanicLink = fDontPanicLink ? false : true; return fDontPanicLink; }
int GetBrainCount();
plArmatureBrain *GetNextBrain(plArmatureBrain *brain);
plArmatureBrain *GetBrain(int index) { if(index <= fBrains.size()) return fBrains.at(index); else return nil; }
plArmatureBrain *FindBrainByClass(UInt32 classID) const;
void TurnToPoint(hsPoint3 &point);
void SuspendInput();
void ResumeInput();
UInt8 IsInputSuspended() { return fSuspendInputCount; }
void IProcessQueuedInput();
void PreserveInputState();
void RestoreInputState();
hsBool GetInputFlag(int f) const;
void SetInputFlag(int which, hsBool status);
void ClearInputFlags(bool saveAlwaysRun, bool clearBackup);
hsBool HasMovementFlag() const; // Is any *movement* input flag on?
hsScalar GetTurnStrength() const;
hsScalar GetKeyTurnStrength() const;
hsScalar GetAnalogTurnStrength() const;
void SetReverseFBOnIdle(bool val);
hsBool IsFBReversed();
bool ForwardKeyDown() const;
bool BackwardKeyDown() const;
bool StrafeLeftKeyDown() const;
bool StrafeRightKeyDown() const;
bool StrafeKeyDown() const;
bool FastKeyDown() const;
bool TurnLeftKeyDown() const;
bool TurnRightKeyDown() const;
bool JumpKeyDown() const;
bool ExitModeKeyDown() const;
void SetForwardKeyDown();
void SetBackwardKeyDown();
void SetStrafeLeftKeyDown(bool on = true);
void SetStrafeRightKeyDown(bool on = true);
void SetFastKeyDown();
void SetTurnLeftKeyDown(bool status = true);
void SetTurnRightKeyDown(bool status = true);
void SetJumpKeyDown();
void DebugDumpMoveKeys(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
void GetMoveKeyString(char *buff);
void SynchIfLocal(double timeNow, int force); // Just physical state
void SynchInputState(UInt32 rcvID = kInvalidPlayerID);
hsBool DirtySynchState(const char* SDLStateName, UInt32 synchFlags );
hsBool DirtyPhysicalSynchState(UInt32 synchFlags);
plClothingOutfit *GetClothingOutfit() const { return fClothingOutfit; }
plClothingSDLModifier *GetClothingSDLMod() const { return fClothingSDLMod; }
const plSceneObject *GetClothingSO(UInt8 lod) const;
plArmatureEffectsMgr *GetArmatureEffects() const { return fEffects; }
enum
{
kWalk,
kRun,
kTurn,
kImpact,
kSwim,
};
const char *plArmatureMod::GetAnimRootName(const char *name);
Int8 AnimNameToIndex(const char *name);
void SetBodyType(int type) { fBodyType = type; }
int GetBodyType(int type) { return fBodyType; }
int GetCurrentGenericType();
bool FindMatchingGenericBrain(const char *names[], int count);
char *MakeAnimationName(const char * baseName) const;
char *GetRootName();
void SetRootName(const char *name);
int RefreshDebugDisplay();
void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
void SetDebugState(hsBool state) { fDebugOn = (state != 0); }
bool GetDebugState() { return fDebugOn; }
virtual void RefreshTree() {}
hsBool IsInStealthMode() const;
int GetStealthLevel() const { return fStealthLevel; }
bool IsOpaque();
bool IsMidLink();
hsBool ConsumeJump(); // returns true if the jump keypress was available to consume
void SendBehaviorNotify(UInt32 type, hsBool start = true) { IFireBehaviorNotify(type,start); }
// Discovered a bug which makes these values horribly out of scale. So we do the rescale
// in the Get/Set functions for backwards compatability.
static void SetMouseTurnSensitivity(hsScalar val) { fMouseTurnSensitivity = val / 150.f; }
static hsScalar GetMouseTurnSensitivity() { return fMouseTurnSensitivity * 150.f; }
static void SetSpawnPointOverride( const char *overrideObjName );
static void WindowActivate(bool active);
void SetFollowerParticleSystemSO(plSceneObject *follower);
plSceneObject *GetFollowerParticleSystemSO();
void RegisterForBehaviorNotify(plKey key);
void UnRegisterForBehaviorNotify(plKey key);
const hsBitVector& GetRelRegionCareAbout() const { return fRegionsICareAbout; }
const hsBitVector& GetRelRegionImIn() const { return fRegionsImIn; }
bool IsKILowestLevel();
int GetKILevel();
void SetLinkInAnim(const char *animName);
plKey GetLinkInAnimKey() const;
enum
{
kSwapTargetShadow,
kMaxSwapType
};
enum
{
kBoneBaseMale = 0,
kBoneBaseFemale,
kBoneBaseCritter, // AI controlled avatar
kBoneBaseActor, // human controlled, non human avatar
kMaxBoneBase
};
enum
{
kAvatarLOSGround,
kAvatarLOSSwimSurface,
};
plMatrixDelayedCorrectionApplicator *fBoneRootAnimator;
static const hsScalar kAvatarInputSynchThreshold;
static hsBool fClickToTurn;
static const char *BoneStrings[];
void SetPhysicalDims(hsScalar height, hsScalar width) { fPhysHeight = height; fPhysWidth = width; }
void SetBodyAgeName(const char* ageName) {if (ageName) fBodyAgeName = ageName; else fBodyAgeName = "";}
void SetBodyFootstepSoundPage(const char* pageName) {if (pageName) fBodyFootstepSoundPage = pageName; else fBodyFootstepSoundPage = "";}
void SetAnimationPrefix(const char* prefix) {if (prefix) fAnimationPrefix = prefix; else fAnimationPrefix = "";}
const char* GetUserStr() {return fUserStr.c_str();}
protected:
void IInitDefaults();
virtual void IFinalize();
virtual void ICustomizeApplicator();
virtual void ISetupMarkerCallbacks(plATCAnim *anim, plAnimTimeConvert *atc);
void NetworkSynch(double timeNow, int force = 0);
hsBool IHandleControlMsg(plControlEventMsg* pMsg);
void IFireBehaviorNotify(UInt32 type, hsBool behaviorStart = true);
void IHandleInputStateMsg(plAvatarInputStateMsg *msg);
void ILinkToPersonalAge();
int IFindSpawnOverride(void);
void ISetTransparentDrawOrder(bool val);
plLayerLinkAnimation *IFindLayerLinkAnim();
char *fRootName; // the name of the player root (from the max file)
hsBitVector fMoveFlags; // which keys/buttons are currently pressed
hsBitVector fMoveFlagsBackup; // a copy of fMoveFlags
typedef std::vector<plControlEventMsg*> CtrlMessageVec;
CtrlMessageVec fQueuedCtrlMessages; // input messages we haven't processed
hsScalar fMouseFrameTurnStrength; // Sum turnage from mouse delta messages since last eval.
plKey fFootSoundSOKey; // The Scene Object we attach to targets for footstep sounds
plKey fLinkSoundSOKey; // Same thing for linking... wwwwawAWAWAwawa...
plKey fLinkInAnimKey; // Set when we link out, this is the anim to play (backwards) when we link in.
static hsScalar fMouseTurnSensitivity;
plArmatureUpdateMsg *fUpdateMsg;
// Trying to be a good lad here and align all our bools and UInt8s...
bool fMidLink; // We're in between a LeaveAge and an EnterAge
bool fAlreadyPanicLinking; // Cleared when you enter an age. Prevents spamming the server with panic link requests.
bool fUnconsumedJump; // We've pressed the jump key, but haven't jumped yet
bool fReverseFBOnIdle; // see set/getters for comments
bool fPendingSynch;
bool fDebugOn;
bool fOpaque;
UInt8 fSuspendInputCount;
UInt8 fStealthMode;
int fStealthLevel; // you are invisible to other players/CCRs of lower stealthLevel
double fLastInputSynch;
plAGModifier * fRootAGMod;
plAvBoneMap * fBoneMap; // uses id codes to look up bones. set up by the brain as needed.
double fLastSynch;
int fBodyType;
plClothingOutfit *fClothingOutfit;
plClothingSDLModifier *fClothingSDLMod;
plAvatarSDLModifier *fAvatarSDLMod;
plAvatarPhysicalSDLModifier *fAvatarPhysicalSDLMod;
hsTArray<const plSceneObject*> fClothToSOMap;
plArmatureEffectsMgr *fEffects;
plSceneObject *fFollowerParticleSystemSO;
static char *fSpawnPointOverride;
// These vectors are used with relevance regions for culling out other objects
hsBitVector fRegionsImIn;
hsBitVector fRegionsICareAbout;
hsBitVector fOldRegionsImIn;
hsBitVector fOldRegionsICareAbout;
hsTArray<plKey> fNotifyKeys;
// Extra info for creating our special physical at runtime
float fPhysHeight;
float fPhysWidth;
bool fDontPanicLink;
// strings for animations, age names, footstep sounds, etc
std::string fBodyAgeName;
std::string fBodyFootstepSoundPage;
std::string fAnimationPrefix;
// user-defined string assigned to this avatar
std::string fUserStr;
};
// PLARMATURELOD
// This class has been phased into plArmatureModBase. It's left behind
// for backwards compatability.
class plArmatureLODMod : public plArmatureMod
{
public:
// tors
plArmatureLODMod();
plArmatureLODMod(const char * root_name);
virtual ~plArmatureLODMod();
CLASSNAME_REGISTER( plArmatureLODMod );
GETINTERFACE_ANY( plArmatureLODMod, plArmatureMod );
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
};
class plAvBoneMap
{
public:
plAvBoneMap();
virtual ~plAvBoneMap();
const plSceneObject * FindBone(UInt32 boneID); // you probably want to use plAvBrainHuman::BoneID;
void AddBoneMapping(UInt32 boneID, const plSceneObject *SO);
protected:
class BoneMapImp; // forward declaration to keep the header clean: see .cpp for implementation
BoneMapImp *fImp; // the thing that actually holds our map
};
#define TWO_PI (hsScalarPI * 2)
#endif plArmatureMod_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plArmatureMod.h
A modifier which manages multi-channel animation and has a physical body.
Designed for avatars; also good for vehicles, creatures, etc.
*/
// PLARMATUREMOD
//
// An armature is an object with both a physical presence (physics behavior) and articulated animated parts.
// (The parts are not themselves physical)
// An avatar is a type of armature, as is a critter, and anything else that moves around.
//
// This modifier combines multi-channel animation with blending (inherited from plAGMasterMod)
// with convenience functions for moving a physical body around and some specialized animation support
#ifndef plArmatureMod_inc
#define plArmatureMod_inc
#include "plAGMasterMod.h"
// other local
#include "plAvDefs.h"
#include "pnSceneObject/plSimulationInterface.h"
#include "hsMatrix44.h"
#include "plNetCommon/plNetCommon.h"
#include <float.h>
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class hsQuat;
class plMatrixChannel;
class plAGModifier;
class plAGMasterMod;
class plAGChannel;
class plClothingOutfit;
class plClothingSDLModifier;
class plAvatarSDLModifier;
class plMatrixDelayedCorrectionApplicator;
class plMatrixDifferenceApp;
class plDebugText;
class plArmatureEffectsMgr;
class plAvBoneMap; // below
class plDrawable;
class plControlEventMsg;
class plAvatarInputStateMsg;
class plLayerLinkAnimation;
class plPipeline;
class plArmatureBrain;
class plArmatureUpdateMsg;
class plPhysicalControllerCore;
typedef std::vector<plKey> plKeyVector;
typedef std::vector<plArmatureBrain*> plBrainStack;
class plArmatureModBase : public plAGMasterMod
{
public:
plArmatureModBase();
virtual ~plArmatureModBase();
CLASSNAME_REGISTER( plArmatureModBase );
GETINTERFACE_ANY( plArmatureModBase, plAGMasterMod );
virtual hsBool MsgReceive(plMessage* msg);
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
plMatrixDifferenceApp *GetRootAnimator() { return fRootAnimator; }
plPhysicalControllerCore* GetController() const { return fController; }
plKey GetWorldKey() const;
virtual hsBool ValidatePhysics();
virtual hsBool ValidateMesh();
virtual void PushBrain(plArmatureBrain *brain);
virtual void PopBrain();
plArmatureBrain *GetCurrentBrain() const;
plDrawable *FindDrawable() const;
virtual void LeaveAge();
virtual hsBool IsFinal();
// LOD stuff
void AdjustLOD(); // see if we need to switch to a different resolution
hsBool SetLOD(int newLOD); // switch to a different resolution
void RefreshTree(); // Resend an LOD update to all our nodes (for when geometry changes)
int AppendMeshKey(plKey meshKey);
int AppendBoneVec(plKeyVector *boneVec);
UInt8 GetNumLOD() const;
// A collection of reasons (flags) that things might be disabled. When all flags are gone
// The object is re-enabled.
enum
{
kDisableReasonUnknown = 0x0001,
kDisableReasonRelRegion = 0x0002,
kDisableReasonLinking = 0x0004,
kDisableReasonCCR = 0x0008,
kDisableReasonVehicle = 0x0010,
kDisableReasonGenericBrain = 0x0020,
};
void EnablePhysics(hsBool status, UInt16 reason = kDisableReasonUnknown);
void EnablePhysicsKinematic(hsBool status);
void EnableDrawing(hsBool status, UInt16 reason = kDisableReasonUnknown);
hsBool IsPhysicsEnabled() { return fDisabledPhysics == 0; }
hsBool IsDrawEnabled() { return fDisabledDraw == 0; }
static void AddressMessageToDescendants(const plCoordinateInterface * CI, plMessage *msg);
static void EnableDrawingTree(const plSceneObject *object, hsBool status);
static int fMinLOD; // throttle for lowest-indexed LOD
static double fLODDistance; // Distance for first LOD switch 2nd is 2x this distance (for now)
protected:
virtual void IFinalize();
virtual void ICustomizeApplicator();
void IEnableBones(int lod, hsBool enable);
// Some of these flags are only needed by derived classes, but I just want
// the one waitFlags variable.
enum
{
kNeedMesh = 0x01,
kNeedPhysics = 0x02,
kNeedAudio = 0x04,
kNeedCamera = 0x08,
kNeedSpawn = 0x10,
kNeedApplicator = 0x20,
kNeedBrainActivation = 0x40,
};
UInt16 fWaitFlags;
int fCurLOD;
plPhysicalControllerCore* fController;
plKeyVector fMeshKeys;
plBrainStack fBrains;
plMatrixDifferenceApp *fRootAnimator;
std::vector<plKeyVector*> fUnusedBones;
UInt16 fDisabledPhysics;
UInt16 fDisabledDraw;
};
class plArmatureMod : public plArmatureModBase
{
friend class plHBehavior;
friend class plAvatarSDLModifier;
friend class plAvatarPhysicalSDLModifier;
friend class plClothingSDLModifier;
friend class plAvOneShotLinkTask;
public:
plArmatureMod();
virtual ~plArmatureMod();
CLASSNAME_REGISTER( plArmatureMod );
GETINTERFACE_ANY( plArmatureMod, plArmatureModBase );
virtual hsBool MsgReceive(plMessage* msg);
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual hsBool ValidatePhysics();
virtual hsBool ValidateMesh();
// Get or set the position of the avatar in simulation space. Set any
// arguments you don't care about to nil.
void SetPositionAndRotationSim(const hsPoint3* position, const hsQuat* rotation);
void GetPositionAndRotationSim(hsPoint3* position, hsQuat* rotation);
hsBool IsLocalAvatar();
hsBool IsLocalAI();
virtual const plSceneObject *FindBone(const char * name) const;
virtual const plSceneObject *FindBone(UInt32 id) const; // use an id from an appropriate taxonomy, such as plAvBrainHuman::BoneID
virtual void AddBoneMapping(UInt32 id, const plSceneObject *bone);
plAGModifier *GetRootAGMod();
plAGAnim *FindCustomAnim(const char *baseName) const;
virtual void Spawn(double timeNow);
virtual void SpawnAt(int which, double timeNow);
virtual void EnterAge(hsBool reSpawn);
virtual void LeaveAge();
virtual void PanicLink(hsBool playLinkOutAnim = true);
virtual void PersonalLink();
virtual bool ToggleDontPanicLinkFlag() { fDontPanicLink = fDontPanicLink ? false : true; return fDontPanicLink; }
int GetBrainCount();
plArmatureBrain *GetNextBrain(plArmatureBrain *brain);
plArmatureBrain *GetBrain(int index) { if(index <= fBrains.size()) return fBrains.at(index); else return nil; }
plArmatureBrain *FindBrainByClass(UInt32 classID) const;
void TurnToPoint(hsPoint3 &point);
void SuspendInput();
void ResumeInput();
UInt8 IsInputSuspended() { return fSuspendInputCount; }
void IProcessQueuedInput();
void PreserveInputState();
void RestoreInputState();
hsBool GetInputFlag(int f) const;
void SetInputFlag(int which, hsBool status);
void ClearInputFlags(bool saveAlwaysRun, bool clearBackup);
hsBool HasMovementFlag() const; // Is any *movement* input flag on?
hsScalar GetTurnStrength() const;
hsScalar GetKeyTurnStrength() const;
hsScalar GetAnalogTurnStrength() const;
void SetReverseFBOnIdle(bool val);
hsBool IsFBReversed();
bool ForwardKeyDown() const;
bool BackwardKeyDown() const;
bool StrafeLeftKeyDown() const;
bool StrafeRightKeyDown() const;
bool StrafeKeyDown() const;
bool FastKeyDown() const;
bool TurnLeftKeyDown() const;
bool TurnRightKeyDown() const;
bool JumpKeyDown() const;
bool ExitModeKeyDown() const;
void SetForwardKeyDown();
void SetBackwardKeyDown();
void SetStrafeLeftKeyDown(bool on = true);
void SetStrafeRightKeyDown(bool on = true);
void SetFastKeyDown();
void SetTurnLeftKeyDown(bool status = true);
void SetTurnRightKeyDown(bool status = true);
void SetJumpKeyDown();
void DebugDumpMoveKeys(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
void GetMoveKeyString(char *buff);
void SynchIfLocal(double timeNow, int force); // Just physical state
void SynchInputState(UInt32 rcvID = kInvalidPlayerID);
hsBool DirtySynchState(const char* SDLStateName, UInt32 synchFlags );
hsBool DirtyPhysicalSynchState(UInt32 synchFlags);
plClothingOutfit *GetClothingOutfit() const { return fClothingOutfit; }
plClothingSDLModifier *GetClothingSDLMod() const { return fClothingSDLMod; }
const plSceneObject *GetClothingSO(UInt8 lod) const;
plArmatureEffectsMgr *GetArmatureEffects() const { return fEffects; }
enum
{
kWalk,
kRun,
kTurn,
kImpact,
kSwim,
};
const char *plArmatureMod::GetAnimRootName(const char *name);
Int8 AnimNameToIndex(const char *name);
void SetBodyType(int type) { fBodyType = type; }
int GetBodyType(int type) { return fBodyType; }
int GetCurrentGenericType();
bool FindMatchingGenericBrain(const char *names[], int count);
char *MakeAnimationName(const char * baseName) const;
char *GetRootName();
void SetRootName(const char *name);
int RefreshDebugDisplay();
void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
void SetDebugState(hsBool state) { fDebugOn = (state != 0); }
bool GetDebugState() { return fDebugOn; }
virtual void RefreshTree() {}
hsBool IsInStealthMode() const;
int GetStealthLevel() const { return fStealthLevel; }
bool IsOpaque();
bool IsMidLink();
hsBool ConsumeJump(); // returns true if the jump keypress was available to consume
void SendBehaviorNotify(UInt32 type, hsBool start = true) { IFireBehaviorNotify(type,start); }
// Discovered a bug which makes these values horribly out of scale. So we do the rescale
// in the Get/Set functions for backwards compatability.
static void SetMouseTurnSensitivity(hsScalar val) { fMouseTurnSensitivity = val / 150.f; }
static hsScalar GetMouseTurnSensitivity() { return fMouseTurnSensitivity * 150.f; }
static void SetSpawnPointOverride( const char *overrideObjName );
static void WindowActivate(bool active);
void SetFollowerParticleSystemSO(plSceneObject *follower);
plSceneObject *GetFollowerParticleSystemSO();
void RegisterForBehaviorNotify(plKey key);
void UnRegisterForBehaviorNotify(plKey key);
const hsBitVector& GetRelRegionCareAbout() const { return fRegionsICareAbout; }
const hsBitVector& GetRelRegionImIn() const { return fRegionsImIn; }
bool IsKILowestLevel();
int GetKILevel();
void SetLinkInAnim(const char *animName);
plKey GetLinkInAnimKey() const;
enum
{
kSwapTargetShadow,
kMaxSwapType
};
enum
{
kBoneBaseMale = 0,
kBoneBaseFemale,
kBoneBaseCritter, // AI controlled avatar
kBoneBaseActor, // human controlled, non human avatar
kMaxBoneBase
};
enum
{
kAvatarLOSGround,
kAvatarLOSSwimSurface,
};
plMatrixDelayedCorrectionApplicator *fBoneRootAnimator;
static const hsScalar kAvatarInputSynchThreshold;
static hsBool fClickToTurn;
static const char *BoneStrings[];
void SetPhysicalDims(hsScalar height, hsScalar width) { fPhysHeight = height; fPhysWidth = width; }
void SetBodyAgeName(const char* ageName) {if (ageName) fBodyAgeName = ageName; else fBodyAgeName = "";}
void SetBodyFootstepSoundPage(const char* pageName) {if (pageName) fBodyFootstepSoundPage = pageName; else fBodyFootstepSoundPage = "";}
void SetAnimationPrefix(const char* prefix) {if (prefix) fAnimationPrefix = prefix; else fAnimationPrefix = "";}
const char* GetUserStr() {return fUserStr.c_str();}
protected:
void IInitDefaults();
virtual void IFinalize();
virtual void ICustomizeApplicator();
virtual void ISetupMarkerCallbacks(plATCAnim *anim, plAnimTimeConvert *atc);
void NetworkSynch(double timeNow, int force = 0);
hsBool IHandleControlMsg(plControlEventMsg* pMsg);
void IFireBehaviorNotify(UInt32 type, hsBool behaviorStart = true);
void IHandleInputStateMsg(plAvatarInputStateMsg *msg);
void ILinkToPersonalAge();
int IFindSpawnOverride(void);
void ISetTransparentDrawOrder(bool val);
plLayerLinkAnimation *IFindLayerLinkAnim();
char *fRootName; // the name of the player root (from the max file)
hsBitVector fMoveFlags; // which keys/buttons are currently pressed
hsBitVector fMoveFlagsBackup; // a copy of fMoveFlags
typedef std::vector<plControlEventMsg*> CtrlMessageVec;
CtrlMessageVec fQueuedCtrlMessages; // input messages we haven't processed
hsScalar fMouseFrameTurnStrength; // Sum turnage from mouse delta messages since last eval.
plKey fFootSoundSOKey; // The Scene Object we attach to targets for footstep sounds
plKey fLinkSoundSOKey; // Same thing for linking... wwwwawAWAWAwawa...
plKey fLinkInAnimKey; // Set when we link out, this is the anim to play (backwards) when we link in.
static hsScalar fMouseTurnSensitivity;
plArmatureUpdateMsg *fUpdateMsg;
// Trying to be a good lad here and align all our bools and UInt8s...
bool fMidLink; // We're in between a LeaveAge and an EnterAge
bool fAlreadyPanicLinking; // Cleared when you enter an age. Prevents spamming the server with panic link requests.
bool fUnconsumedJump; // We've pressed the jump key, but haven't jumped yet
bool fReverseFBOnIdle; // see set/getters for comments
bool fPendingSynch;
bool fDebugOn;
bool fOpaque;
UInt8 fSuspendInputCount;
UInt8 fStealthMode;
int fStealthLevel; // you are invisible to other players/CCRs of lower stealthLevel
double fLastInputSynch;
plAGModifier * fRootAGMod;
plAvBoneMap * fBoneMap; // uses id codes to look up bones. set up by the brain as needed.
double fLastSynch;
int fBodyType;
plClothingOutfit *fClothingOutfit;
plClothingSDLModifier *fClothingSDLMod;
plAvatarSDLModifier *fAvatarSDLMod;
plAvatarPhysicalSDLModifier *fAvatarPhysicalSDLMod;
hsTArray<const plSceneObject*> fClothToSOMap;
plArmatureEffectsMgr *fEffects;
plSceneObject *fFollowerParticleSystemSO;
static char *fSpawnPointOverride;
// These vectors are used with relevance regions for culling out other objects
hsBitVector fRegionsImIn;
hsBitVector fRegionsICareAbout;
hsBitVector fOldRegionsImIn;
hsBitVector fOldRegionsICareAbout;
hsTArray<plKey> fNotifyKeys;
// Extra info for creating our special physical at runtime
float fPhysHeight;
float fPhysWidth;
bool fDontPanicLink;
// strings for animations, age names, footstep sounds, etc
std::string fBodyAgeName;
std::string fBodyFootstepSoundPage;
std::string fAnimationPrefix;
// user-defined string assigned to this avatar
std::string fUserStr;
};
// PLARMATURELOD
// This class has been phased into plArmatureModBase. It's left behind
// for backwards compatability.
class plArmatureLODMod : public plArmatureMod
{
public:
// tors
plArmatureLODMod();
plArmatureLODMod(const char * root_name);
virtual ~plArmatureLODMod();
CLASSNAME_REGISTER( plArmatureLODMod );
GETINTERFACE_ANY( plArmatureLODMod, plArmatureMod );
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
};
class plAvBoneMap
{
public:
plAvBoneMap();
virtual ~plAvBoneMap();
const plSceneObject * FindBone(UInt32 boneID); // you probably want to use plAvBrainHuman::BoneID;
void AddBoneMapping(UInt32 boneID, const plSceneObject *SO);
protected:
class BoneMapImp; // forward declaration to keep the header clean: see .cpp for implementation
BoneMapImp *fImp; // the thing that actually holds our map
};
#define TWO_PI (hsScalarPI * 2)
#endif plArmatureMod_inc

View File

@ -1,121 +1,121 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvBehaviors.h"
#include "plAvBrainHuman.h"
#include "plArmatureMod.h"
#include "plAGAnimInstance.h"
#include "plMessage/plAvatarMsg.h"
#include "plPipeline/plDebugText.h"
plArmatureBehavior::plArmatureBehavior() : fAnim(nil), fArmature(nil), fBrain(nil), fIndex((UInt8)-1), fFlags(0) {}
plArmatureBehavior::~plArmatureBehavior()
{
if (fAnim)
fAnim->Detach();
}
void plArmatureBehavior::Init(plAGAnim *anim, hsBool loop, plArmatureBrain *brain, plArmatureModBase *armature, UInt8 index)
{
fArmature = armature;
fBrain = brain;
fIndex = index;
fStrength.Set(0);
if (anim)
{
fAnim = fArmature->AttachAnimationBlended(anim, 0, 0, true);
fAnim->SetLoop(loop);
}
}
void plArmatureBehavior::Process(double time, float elapsed)
{
}
void plArmatureBehavior::SetStrength(hsScalar val, hsScalar rate /* = 0.f */)
{
hsScalar oldStrength = GetStrength();
if (rate == 0)
fStrength.Set(val);
else
fStrength.Set(val, fabs(val - oldStrength) / rate);
if (fAnim)
fAnim->Fade(val, rate);
if (val > 0 && oldStrength == 0)
IStart();
else if (val == 0 && oldStrength > 0)
IStop();
}
hsScalar plArmatureBehavior::GetStrength()
{
return fStrength.Value();
}
void plArmatureBehavior::Rewind()
{
if (fAnim)
fAnim->SetCurrentTime(0.0f, true);
}
void plArmatureBehavior::DumpDebug(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt)
{
hsScalar strength = GetStrength();
const char *onOff = strength > 0 ? "on" : "off";
char blendBar[11] = "||||||||||";
int bars = (int)__min(10 * strength, 10);
blendBar[bars] = '\0';
if (fAnim)
{
const char *animName = fAnim->GetName();
float time = fAnim->GetTimeConvert()->CurrentAnimTime();
sprintf(strBuf, "%20s %3s time: %5.2f %s", animName, onOff, time, blendBar);
}
else
sprintf(strBuf, " Behavior %2d %3s %s", fIndex, onOff, blendBar);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
}
void plArmatureBehavior::IStart()
{
if (fAnim)
{
fAnim->SetCurrentTime(0.0f, true);
fAnim->Start();
}
}
void plArmatureBehavior::IStop()
{
if (fFlags & kBehaviorFlagNotifyOnStop)
fBrain->OnBehaviorStop(fIndex);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvBehaviors.h"
#include "plAvBrainHuman.h"
#include "plArmatureMod.h"
#include "plAGAnimInstance.h"
#include "plMessage/plAvatarMsg.h"
#include "plPipeline/plDebugText.h"
plArmatureBehavior::plArmatureBehavior() : fAnim(nil), fArmature(nil), fBrain(nil), fIndex((UInt8)-1), fFlags(0) {}
plArmatureBehavior::~plArmatureBehavior()
{
if (fAnim)
fAnim->Detach();
}
void plArmatureBehavior::Init(plAGAnim *anim, hsBool loop, plArmatureBrain *brain, plArmatureModBase *armature, UInt8 index)
{
fArmature = armature;
fBrain = brain;
fIndex = index;
fStrength.Set(0);
if (anim)
{
fAnim = fArmature->AttachAnimationBlended(anim, 0, 0, true);
fAnim->SetLoop(loop);
}
}
void plArmatureBehavior::Process(double time, float elapsed)
{
}
void plArmatureBehavior::SetStrength(hsScalar val, hsScalar rate /* = 0.f */)
{
hsScalar oldStrength = GetStrength();
if (rate == 0)
fStrength.Set(val);
else
fStrength.Set(val, fabs(val - oldStrength) / rate);
if (fAnim)
fAnim->Fade(val, rate);
if (val > 0 && oldStrength == 0)
IStart();
else if (val == 0 && oldStrength > 0)
IStop();
}
hsScalar plArmatureBehavior::GetStrength()
{
return fStrength.Value();
}
void plArmatureBehavior::Rewind()
{
if (fAnim)
fAnim->SetCurrentTime(0.0f, true);
}
void plArmatureBehavior::DumpDebug(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt)
{
hsScalar strength = GetStrength();
const char *onOff = strength > 0 ? "on" : "off";
char blendBar[11] = "||||||||||";
int bars = (int)__min(10 * strength, 10);
blendBar[bars] = '\0';
if (fAnim)
{
const char *animName = fAnim->GetName();
float time = fAnim->GetTimeConvert()->CurrentAnimTime();
sprintf(strBuf, "%20s %3s time: %5.2f %s", animName, onOff, time, blendBar);
}
else
sprintf(strBuf, " Behavior %2d %3s %s", fIndex, onOff, blendBar);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
}
void plArmatureBehavior::IStart()
{
if (fAnim)
{
fAnim->SetCurrentTime(0.0f, true);
fAnim->Start();
}
}
void plArmatureBehavior::IStop()
{
if (fFlags & kBehaviorFlagNotifyOnStop)
fBrain->OnBehaviorStop(fIndex);
}

View File

@ -1,71 +1,71 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_AV_BEHAVIORS_H
#define PL_AV_BEHAVIORS_H
#include "hsTypes.h"
#include "hsTemplates.h"
#include "pnKeyedObject/plKey.h"
#include "pnTimer/plTimedValue.h"
class plAGAnim;
class plAGAnimInstance;
class plArmatureModBase;
class plArmatureBrain;
class plDebugText;
class plArmatureBehavior
{
public:
plArmatureBehavior();
virtual ~plArmatureBehavior();
void Init(plAGAnim *anim, hsBool loop, plArmatureBrain *brain, plArmatureModBase *armature, UInt8 index);
virtual void Process(double time, float elapsed);
virtual void SetStrength(hsScalar val, hsScalar rate = 0.f); // default instant change
virtual hsScalar GetStrength();
virtual void Rewind();
void DumpDebug(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
enum
{
kBehaviorFlagNotifyOnStop = 0x01,
};
UInt32 fFlags;
protected:
plAGAnimInstance *fAnim;
plArmatureModBase *fArmature;
plArmatureBrain *fBrain;
plTimedValue<hsScalar> fStrength;
UInt8 fIndex;
virtual void IStart();
virtual void IStop();
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_AV_BEHAVIORS_H
#define PL_AV_BEHAVIORS_H
#include "hsTypes.h"
#include "hsTemplates.h"
#include "pnKeyedObject/plKey.h"
#include "pnTimer/plTimedValue.h"
class plAGAnim;
class plAGAnimInstance;
class plArmatureModBase;
class plArmatureBrain;
class plDebugText;
class plArmatureBehavior
{
public:
plArmatureBehavior();
virtual ~plArmatureBehavior();
void Init(plAGAnim *anim, hsBool loop, plArmatureBrain *brain, plArmatureModBase *armature, UInt8 index);
virtual void Process(double time, float elapsed);
virtual void SetStrength(hsScalar val, hsScalar rate = 0.f); // default instant change
virtual hsScalar GetStrength();
virtual void Rewind();
void DumpDebug(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
enum
{
kBehaviorFlagNotifyOnStop = 0x01,
};
UInt32 fFlags;
protected:
plAGAnimInstance *fAnim;
plArmatureModBase *fArmature;
plArmatureBrain *fBrain;
plTimedValue<hsScalar> fStrength;
UInt8 fIndex;
virtual void IStart();
virtual void IStop();
};
#endif

View File

@ -1,184 +1,184 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// local
#include "plAvBrain.h"
#include "plAvBehaviors.h"
#include "plArmatureMod.h"
#include "plAvatarMgr.h"
#include "plAvatarTasks.h"
// global
#include "hsGeometry3.h"
#include "hsQuat.h"
// other
#include "pnSceneObject/plSceneObject.h"
#include "plPipeline/plDebugText.h"
// messages
#include "plMessage/plAvatarMsg.h"
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
plArmatureBrain::plArmatureBrain() :
fCurTask(nil),
fArmature(nil),
fAvMod(nil)
{
}
plArmatureBrain::~plArmatureBrain()
{
while (fTaskQueue.size() > 0)
{
plAvTask *task = fTaskQueue.front();
delete task;
fTaskQueue.pop_front();
}
if (fCurTask)
delete fCurTask;
}
hsBool plArmatureBrain::Apply(double timeNow, hsScalar elapsed)
{
IProcessTasks(timeNow, elapsed);
fArmature->ApplyAnimations(timeNow, elapsed);
return true;
}
void plArmatureBrain::Activate(plArmatureModBase *armature)
{
fArmature = armature;
fAvMod = plArmatureMod::ConvertNoRef(armature);
}
void plArmatureBrain::QueueTask(plAvTask *task)
{
if (task)
fTaskQueue.push_back(task);
}
hsBool plArmatureBrain::LeaveAge()
{
if (fCurTask)
fCurTask->LeaveAge(plArmatureMod::ConvertNoRef(fArmature));
plAvTaskQueue::iterator i = fTaskQueue.begin();
for (; i != fTaskQueue.end(); i++)
{
plAvTask *task = *i;
task->LeaveAge(plArmatureMod::ConvertNoRef(fArmature)); // Give it a chance to do something before we nuke it.
delete task;
}
fTaskQueue.clear();
return true;
}
hsBool plArmatureBrain::IsRunningTask() const
{
if (fCurTask)
return true;
if(fTaskQueue.size() > 0)
return true;
return false;
}
// Nothing for this class to read/write. These methods exist
// for backwards compatability with plAvBrain and plAvBrainUser
void plArmatureBrain::Write(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Write(stream, mgr);
// plAvBrain
stream->WriteSwap32(0);
stream->WriteBool(false);
// plAvBrainUser
stream->WriteSwap32(0);
stream->WriteSwapScalar(0.f);
stream->WriteSwapDouble(0.f);
}
void plArmatureBrain::Read(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Read(stream, mgr);
// plAvBrain
stream->ReadSwap32();
if (stream->ReadBool())
mgr->ReadKey(stream);
// plAvBrainUser
stream->ReadSwap32();
stream->ReadSwapScalar();
stream->ReadSwapDouble();
}
// MSGRECEIVE
hsBool plArmatureBrain::MsgReceive(plMessage * msg)
{
plAvTaskMsg *taskMsg = plAvTaskMsg::ConvertNoRef(msg);
if (taskMsg)
{
return IHandleTaskMsg(taskMsg);
}
return false;
}
void plArmatureBrain::IProcessTasks(double time, hsScalar elapsed)
{
if (!fCurTask || !fCurTask->Process(plArmatureMod::ConvertNoRef(fArmature), this, time, elapsed))
{
if (fCurTask)
{
fCurTask->Finish(plArmatureMod::ConvertNoRef(fArmature), this, time, elapsed);
delete fCurTask;
fCurTask = nil;
}
// need a new task
if (fTaskQueue.size() > 0)
{
plAvTask *newTask = fTaskQueue.front();
if (newTask && newTask->Start(plArmatureMod::ConvertNoRef(fArmature), this, time, elapsed))
{
fCurTask = newTask;
fTaskQueue.pop_front();
}
// if we couldn't start the task, we'll keep trying until we can.
}
}
}
hsBool plArmatureBrain::IHandleTaskMsg(plAvTaskMsg *msg)
{
plAvTask *task = msg->GetTask();
QueueTask(task);
return true;
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// local
#include "plAvBrain.h"
#include "plAvBehaviors.h"
#include "plArmatureMod.h"
#include "plAvatarMgr.h"
#include "plAvatarTasks.h"
// global
#include "hsGeometry3.h"
#include "hsQuat.h"
// other
#include "pnSceneObject/plSceneObject.h"
#include "plPipeline/plDebugText.h"
// messages
#include "plMessage/plAvatarMsg.h"
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
plArmatureBrain::plArmatureBrain() :
fCurTask(nil),
fArmature(nil),
fAvMod(nil)
{
}
plArmatureBrain::~plArmatureBrain()
{
while (fTaskQueue.size() > 0)
{
plAvTask *task = fTaskQueue.front();
delete task;
fTaskQueue.pop_front();
}
if (fCurTask)
delete fCurTask;
}
hsBool plArmatureBrain::Apply(double timeNow, hsScalar elapsed)
{
IProcessTasks(timeNow, elapsed);
fArmature->ApplyAnimations(timeNow, elapsed);
return true;
}
void plArmatureBrain::Activate(plArmatureModBase *armature)
{
fArmature = armature;
fAvMod = plArmatureMod::ConvertNoRef(armature);
}
void plArmatureBrain::QueueTask(plAvTask *task)
{
if (task)
fTaskQueue.push_back(task);
}
hsBool plArmatureBrain::LeaveAge()
{
if (fCurTask)
fCurTask->LeaveAge(plArmatureMod::ConvertNoRef(fArmature));
plAvTaskQueue::iterator i = fTaskQueue.begin();
for (; i != fTaskQueue.end(); i++)
{
plAvTask *task = *i;
task->LeaveAge(plArmatureMod::ConvertNoRef(fArmature)); // Give it a chance to do something before we nuke it.
delete task;
}
fTaskQueue.clear();
return true;
}
hsBool plArmatureBrain::IsRunningTask() const
{
if (fCurTask)
return true;
if(fTaskQueue.size() > 0)
return true;
return false;
}
// Nothing for this class to read/write. These methods exist
// for backwards compatability with plAvBrain and plAvBrainUser
void plArmatureBrain::Write(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Write(stream, mgr);
// plAvBrain
stream->WriteSwap32(0);
stream->WriteBool(false);
// plAvBrainUser
stream->WriteSwap32(0);
stream->WriteSwapScalar(0.f);
stream->WriteSwapDouble(0.f);
}
void plArmatureBrain::Read(hsStream *stream, hsResMgr *mgr)
{
plCreatable::Read(stream, mgr);
// plAvBrain
stream->ReadSwap32();
if (stream->ReadBool())
mgr->ReadKey(stream);
// plAvBrainUser
stream->ReadSwap32();
stream->ReadSwapScalar();
stream->ReadSwapDouble();
}
// MSGRECEIVE
hsBool plArmatureBrain::MsgReceive(plMessage * msg)
{
plAvTaskMsg *taskMsg = plAvTaskMsg::ConvertNoRef(msg);
if (taskMsg)
{
return IHandleTaskMsg(taskMsg);
}
return false;
}
void plArmatureBrain::IProcessTasks(double time, hsScalar elapsed)
{
if (!fCurTask || !fCurTask->Process(plArmatureMod::ConvertNoRef(fArmature), this, time, elapsed))
{
if (fCurTask)
{
fCurTask->Finish(plArmatureMod::ConvertNoRef(fArmature), this, time, elapsed);
delete fCurTask;
fCurTask = nil;
}
// need a new task
if (fTaskQueue.size() > 0)
{
plAvTask *newTask = fTaskQueue.front();
if (newTask && newTask->Start(plArmatureMod::ConvertNoRef(fArmature), this, time, elapsed))
{
fCurTask = newTask;
fTaskQueue.pop_front();
}
// if we couldn't start the task, we'll keep trying until we can.
}
}
}
hsBool plArmatureBrain::IHandleTaskMsg(plAvTaskMsg *msg)
{
plAvTask *task = msg->GetTask();
QueueTask(task);
return true;
}

View File

@ -1,87 +1,87 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVBRAIN_INC
#define PLAVBRAIN_INC
#include "plAGModifier.h"
#include "hsTypes.h"
#include "hsTemplates.h"
#include "hsBitVector.h"
#include "hsGeometry3.h"
#include "hsResMgr.h"
#include "pnNetCommon/plSynchedObject.h"
#pragma warning(disable: 4284)
#include <deque>
class plArmatureModBase;
class plArmatureBehavior;
class plHKAction;
class plAvTask;
class plAvTaskMsg;
class plDebugText;
class plArmatureBrain : public plCreatable
{
public:
plArmatureBrain();
virtual ~plArmatureBrain();
CLASSNAME_REGISTER( plArmatureBrain );
GETINTERFACE_ANY( plArmatureBrain, plCreatable );
virtual hsBool Apply(double timeNow, hsScalar elapsed);
virtual void Activate(plArmatureModBase *armature);
virtual void Deactivate() {}
virtual void Suspend() {}
virtual void Resume() {}
virtual void Spawn(double timeNow) {}
virtual void OnBehaviorStop(UInt8 index) {}
virtual hsBool LeaveAge();
virtual hsBool IsRunningTask() const;
virtual void QueueTask(plAvTask *task);
virtual void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt) {}
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual hsBool MsgReceive(plMessage *msg);
protected:
virtual void IProcessTasks(double time, hsScalar elapsed);
virtual hsBool IHandleTaskMsg(plAvTaskMsg *msg);
typedef std::deque<plAvTask *> plAvTaskQueue;
plAvTaskQueue fTaskQueue; // FIFO queue of tasks we're working on
plAvTask *fCurTask; // the task we're working on right now
plArmatureModBase *fArmature;
plArmatureMod *fAvMod;
hsTArray<plArmatureBehavior*> fBehaviors;
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVBRAIN_INC
#define PLAVBRAIN_INC
#include "plAGModifier.h"
#include "hsTypes.h"
#include "hsTemplates.h"
#include "hsBitVector.h"
#include "hsGeometry3.h"
#include "hsResMgr.h"
#include "pnNetCommon/plSynchedObject.h"
#pragma warning(disable: 4284)
#include <deque>
class plArmatureModBase;
class plArmatureBehavior;
class plHKAction;
class plAvTask;
class plAvTaskMsg;
class plDebugText;
class plArmatureBrain : public plCreatable
{
public:
plArmatureBrain();
virtual ~plArmatureBrain();
CLASSNAME_REGISTER( plArmatureBrain );
GETINTERFACE_ANY( plArmatureBrain, plCreatable );
virtual hsBool Apply(double timeNow, hsScalar elapsed);
virtual void Activate(plArmatureModBase *armature);
virtual void Deactivate() {}
virtual void Suspend() {}
virtual void Resume() {}
virtual void Spawn(double timeNow) {}
virtual void OnBehaviorStop(UInt8 index) {}
virtual hsBool LeaveAge();
virtual hsBool IsRunningTask() const;
virtual void QueueTask(plAvTask *task);
virtual void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt) {}
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual hsBool MsgReceive(plMessage *msg);
protected:
virtual void IProcessTasks(double time, hsScalar elapsed);
virtual hsBool IHandleTaskMsg(plAvTaskMsg *msg);
typedef std::deque<plAvTask *> plAvTaskQueue;
plAvTaskQueue fTaskQueue; // FIFO queue of tasks we're working on
plAvTask *fCurTask; // the task we're working on right now
plArmatureModBase *fArmature;
plArmatureMod *fAvMod;
hsTArray<plArmatureBehavior*> fBehaviors;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,211 +1,211 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvBrainClimb_Include
#define plAvBrainClimb_Include
#pragma once
/////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////
#include "plAvBrain.h"
#include "plMessage/plClimbMsg.h"
/////////////////////////////////////////////////////////////////
//
// PROTOTYPES
//
/////////////////////////////////////////////////////////////////
class plAnimStage;
class plLOSHitMsg;
class plStateDataRecord;
/////////////////////////////////////////////////////////////////
//
// DECLARATION
//
/////////////////////////////////////////////////////////////////
class plAvBrainClimb : public plArmatureBrain
{
public:
enum Mode {
kInactive,
kUnknown,
kFinishing,
kDone,
kClimbingUp,
kClimbingDown,
kClimbingLeft,
kClimbingRight,
kMountingUp,
kMountingDown,
kMountingLeft,
kMountingRight,
kDismountingUp,
kDismountingDown,
kDismountingLeft,
kDismountingRight,
kIdle,
kReleasing,
kFallingOff
};
plAvBrainClimb();
plAvBrainClimb(Mode initialMode);
virtual ~plAvBrainClimb();
virtual void Activate(plArmatureModBase *avMod);
virtual void Deactivate();
virtual hsBool Apply(double timeNow, hsScalar elapsed);
virtual void SaveToSDL(plStateDataRecord *sdl);
virtual void LoadFromSDL(const plStateDataRecord *sdl);
void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
const char * plAvBrainClimb::WorldDirStr(plClimbMsg::Direction dir);
const char *plAvBrainClimb::ModeStr(Mode mode);
// plasma protocol
virtual hsBool MsgReceive(plMessage *msg);
CLASSNAME_REGISTER( plAvBrainClimb );
GETINTERFACE_ANY( plAvBrainClimb, plArmatureBrain);
private:
bool IAdvanceCurrentStage(double time, float elapsed, float &overage);
bool ITryStageTransition(double time, float overage);
bool IChooseNextMode();
/** Handle a climb message. Note that the "start climbing" climb message is handled
by the human brain, since there's no climb brain there to hear it, since you
(by definition) haven't started climbing yet... */
inline hsBool IHandleClimbMsg(plClimbMsg *msg);
inline hsBool IHandleLOSMsg(plLOSHitMsg *msg);
/** Allow or block dismounting in the specified direction. */
void IEnableDismount(plClimbMsg::Direction dir, bool status);
/** Allow or block climbing in the specified direction. */
void IEnableClimb(plClimbMsg::Direction dir, bool status);
/** Figure out which directions we can go from our current position */
void ICheckAllowedDirections();
/** Look left, right, up, and down to see which directions are clear
for our movement. We could do this by positioning our actual collision
body and testing for hits, but it gives a lot more false positives *and*
we won't get the normals of intersection, so it will be more complex
to figure out which directions are actually blocked.
The approach here is to do a raycast in the aforementioned directions
and fail that direction if the raycast hits anything. */
void IProbeEnvironment();
/** When we probe to see if we can climb in some direction, we need to know
how much room we need in each direction. Right now this is hardcoded,
but we may switch to using the actual animation climb distances. */
void ICalcProbeLengths();
/** Which direction are we trying to go? (up, down, left, or right)
Just looks at keyboard input. */
void IGetDesiredDirection();
/** Let go of the wall and fall. */
void IRelease(bool intentional);
/** Decide how far forward or backward to move in the animation */
float IGetAnimDelta(double time, float elapsed);
/** Create all our animation stage objects. Doesn't actually apply any of the animations
to the avatar yet. */
virtual hsBool IInitAnimations();
/** Find the animation stage corresponding with a mode */
plAnimStage * IGetStageFromMode(Mode mode);
Mode IGetModeFromStage(plAnimStage *stage);
/** The exit stage is a special second stage that runs concurrently with the others.
It's currently used to blend the "falloff" and "release" animations seamlessly
with the others. It has a few limitations:
- it's always expected to play forwards
- it doesn't pay attention to the keyboard
*/
bool IProcessExitStage(double time, float elapsed);
void IDumpClimbDirections(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
void IDumpDismountDirections(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
void IDumpBlockedDirections(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
////////////////////////////
//
// MEMBERS
//
////////////////////////////
Mode fCurMode;
Mode fNextMode;
plClimbMsg::Direction fDesiredDirection; // up / down / left / right
float fControlDir; // 1.0 = move current stage forward -1.0 = move current stage back
UInt32 fAllowedDirections;
UInt32 fPhysicallyBlockedDirections;
UInt32 fOldPhysicallyBlockedDirections; // for debug display convenience
UInt32 fAllowedDismounts;
float fVerticalProbeLength;
float fHorizontalProbeLength;
// climbing stages
plAnimStage *fUp;
plAnimStage *fDown;
plAnimStage *fLeft;
plAnimStage *fRight;
plAnimStage *fMountUp;
plAnimStage *fMountDown;
plAnimStage *fMountLeft;
plAnimStage *fMountRight;
plAnimStage *fDismountUp;
plAnimStage *fDismountDown;
plAnimStage *fDismountLeft;
plAnimStage *fDismountRight;
plAnimStage *fIdle;
plAnimStage *fRelease;
plAnimStage *fFallOff;
// /** Current position on the climbing grid. */
// int fX;
// int fY;
/** The stage that is currently executing. */
plAnimStage *fCurStage;
/** A second stage we use (simultaneously) when we need to blend (fall or release) animations. */
plAnimStage *fExitStage;
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvBrainClimb_Include
#define plAvBrainClimb_Include
#pragma once
/////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////
#include "plAvBrain.h"
#include "plMessage/plClimbMsg.h"
/////////////////////////////////////////////////////////////////
//
// PROTOTYPES
//
/////////////////////////////////////////////////////////////////
class plAnimStage;
class plLOSHitMsg;
class plStateDataRecord;
/////////////////////////////////////////////////////////////////
//
// DECLARATION
//
/////////////////////////////////////////////////////////////////
class plAvBrainClimb : public plArmatureBrain
{
public:
enum Mode {
kInactive,
kUnknown,
kFinishing,
kDone,
kClimbingUp,
kClimbingDown,
kClimbingLeft,
kClimbingRight,
kMountingUp,
kMountingDown,
kMountingLeft,
kMountingRight,
kDismountingUp,
kDismountingDown,
kDismountingLeft,
kDismountingRight,
kIdle,
kReleasing,
kFallingOff
};
plAvBrainClimb();
plAvBrainClimb(Mode initialMode);
virtual ~plAvBrainClimb();
virtual void Activate(plArmatureModBase *avMod);
virtual void Deactivate();
virtual hsBool Apply(double timeNow, hsScalar elapsed);
virtual void SaveToSDL(plStateDataRecord *sdl);
virtual void LoadFromSDL(const plStateDataRecord *sdl);
void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
const char * plAvBrainClimb::WorldDirStr(plClimbMsg::Direction dir);
const char *plAvBrainClimb::ModeStr(Mode mode);
// plasma protocol
virtual hsBool MsgReceive(plMessage *msg);
CLASSNAME_REGISTER( plAvBrainClimb );
GETINTERFACE_ANY( plAvBrainClimb, plArmatureBrain);
private:
bool IAdvanceCurrentStage(double time, float elapsed, float &overage);
bool ITryStageTransition(double time, float overage);
bool IChooseNextMode();
/** Handle a climb message. Note that the "start climbing" climb message is handled
by the human brain, since there's no climb brain there to hear it, since you
(by definition) haven't started climbing yet... */
inline hsBool IHandleClimbMsg(plClimbMsg *msg);
inline hsBool IHandleLOSMsg(plLOSHitMsg *msg);
/** Allow or block dismounting in the specified direction. */
void IEnableDismount(plClimbMsg::Direction dir, bool status);
/** Allow or block climbing in the specified direction. */
void IEnableClimb(plClimbMsg::Direction dir, bool status);
/** Figure out which directions we can go from our current position */
void ICheckAllowedDirections();
/** Look left, right, up, and down to see which directions are clear
for our movement. We could do this by positioning our actual collision
body and testing for hits, but it gives a lot more false positives *and*
we won't get the normals of intersection, so it will be more complex
to figure out which directions are actually blocked.
The approach here is to do a raycast in the aforementioned directions
and fail that direction if the raycast hits anything. */
void IProbeEnvironment();
/** When we probe to see if we can climb in some direction, we need to know
how much room we need in each direction. Right now this is hardcoded,
but we may switch to using the actual animation climb distances. */
void ICalcProbeLengths();
/** Which direction are we trying to go? (up, down, left, or right)
Just looks at keyboard input. */
void IGetDesiredDirection();
/** Let go of the wall and fall. */
void IRelease(bool intentional);
/** Decide how far forward or backward to move in the animation */
float IGetAnimDelta(double time, float elapsed);
/** Create all our animation stage objects. Doesn't actually apply any of the animations
to the avatar yet. */
virtual hsBool IInitAnimations();
/** Find the animation stage corresponding with a mode */
plAnimStage * IGetStageFromMode(Mode mode);
Mode IGetModeFromStage(plAnimStage *stage);
/** The exit stage is a special second stage that runs concurrently with the others.
It's currently used to blend the "falloff" and "release" animations seamlessly
with the others. It has a few limitations:
- it's always expected to play forwards
- it doesn't pay attention to the keyboard
*/
bool IProcessExitStage(double time, float elapsed);
void IDumpClimbDirections(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
void IDumpDismountDirections(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
void IDumpBlockedDirections(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
////////////////////////////
//
// MEMBERS
//
////////////////////////////
Mode fCurMode;
Mode fNextMode;
plClimbMsg::Direction fDesiredDirection; // up / down / left / right
float fControlDir; // 1.0 = move current stage forward -1.0 = move current stage back
UInt32 fAllowedDirections;
UInt32 fPhysicallyBlockedDirections;
UInt32 fOldPhysicallyBlockedDirections; // for debug display convenience
UInt32 fAllowedDismounts;
float fVerticalProbeLength;
float fHorizontalProbeLength;
// climbing stages
plAnimStage *fUp;
plAnimStage *fDown;
plAnimStage *fLeft;
plAnimStage *fRight;
plAnimStage *fMountUp;
plAnimStage *fMountDown;
plAnimStage *fMountLeft;
plAnimStage *fMountRight;
plAnimStage *fDismountUp;
plAnimStage *fDismountDown;
plAnimStage *fDismountLeft;
plAnimStage *fDismountRight;
plAnimStage *fIdle;
plAnimStage *fRelease;
plAnimStage *fFallOff;
// /** Current position on the climbing grid. */
// int fX;
// int fY;
/** The stage that is currently executing. */
plAnimStage *fCurStage;
/** A second stage we use (simultaneously) when we need to blend (fall or release) animations. */
plAnimStage *fExitStage;
};
#endif

View File

@ -1,241 +1,241 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
// singular
#include "plAvBrainCoop.h"
// local
#include "plArmatureMod.h"
#include "plAnimStage.h"
#include "plAvTaskSeek.h"
#include "plAvatarMgr.h"
// other
#include "plScene/plSceneNode.h"
#include "pnNetCommon/plNetApp.h"
// messages
#include "plMessage/plAvatarMsg.h"
#include "plMessage/plAvCoopMsg.h"
#include "plMessage/plPickedMsg.h"
#include "pnMessage/plNotifyMsg.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// STATIC
//
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//
// CODE
//
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//
// plAvBrainCoop
//
/////////////////////////////////////////////////////////////////////////////////////////
plAvBrainCoop::plAvBrainCoop()
: fInitiatorID(0),
fInitiatorSerial(0)
{
}
// plAvBrainCoop ----------------------------------------------------------
// --------------
plAvBrainCoop::plAvBrainCoop(UInt32 exitFlags, float fadeIn, float fadeOut,
MoveMode moveMode, plKey guestKey)
: plAvBrainGeneric(exitFlags, fadeIn, fadeOut, moveMode),
fGuestKey(guestKey)
{
static UInt16 coopSerial = 0;
// this particular constructor is only called by the initiator...
fInitiatorID = plNetClientApp::GetInstance()->GetPlayerID();
fInitiatorSerial = coopSerial++;
}
// plAvBrainCoop ----------------------------------------------------------
// --------------
plAvBrainCoop::plAvBrainCoop(UInt32 exitFlags, float fadeIn, float fadeOut,
MoveMode moveMode, UInt32 initiatorID, UInt16 initiatorSerial,
plKey hostKey)
: plAvBrainGeneric(exitFlags, fadeIn, fadeOut, moveMode),
fInitiatorID(initiatorID), fInitiatorSerial(initiatorSerial),
fHostKey(hostKey)
{
}
// MsgReceive ----------------------------------
// -----------
hsBool plAvBrainCoop::MsgReceive(plMessage *msg)
{
plPickedMsg *pickM = plPickedMsg::ConvertNoRef(msg);
if(pickM)
{
if(fWaitingForClick)
{
fWaitingForClick = false;
// clicks are never network propagated, so we can be sure that the
// click was performed by the local player.
plKey localPlayer = plNetClientApp::GetInstance()->GetLocalPlayerKey();
if(localPlayer == fGuestKey)
{
plAvCoopMsg *coopM = TRACKED_NEW plAvCoopMsg(plAvCoopMsg::kGuestAccepted, fInitiatorID, fInitiatorSerial);
coopM->SetBCastFlag(plMessage::kNetPropagate);
coopM->Send();
}
}
}
return plAvBrainGeneric::MsgReceive(msg);
}
// RelayNotifyMsg ----------------------------------
// ---------------
bool plAvBrainCoop::RelayNotifyMsg(plNotifyMsg *msg)
{
// add a coop event so the receiver will know what coop this message is from
msg->AddCoopEvent(fInitiatorID, fInitiatorSerial);
proMultiStageEventData * mtevt = static_cast<proMultiStageEventData *>(msg->FindEventRecord(proEventData::kMultiStage));
if(mtevt)
DebugMsg("COOP: Relaying multi-stage event to %d recipients (via plAvBrainCoop)", fRecipients.size());
if(fRecipients.size() != 0)
{
bool foundARecipient = false;
for (unsigned curRecipient = 0; curRecipient < fRecipients.size(); curRecipient++)
{
if (fRecipients[curRecipient])
{
foundARecipient = true;
msg->AddReceiver(fRecipients[curRecipient]);
}
}
if (!foundARecipient)
return false;
msg->Send();
return true;
}
else
return false;
}
void plAvBrainCoop::EnableGuestClick()
{
fWaitingForClick = true;
}
// GetInitiatorID --------------------
// ---------------
UInt32 plAvBrainCoop::GetInitiatorID()
{
return fInitiatorID;
}
// GetInitiatorSerial --------------------
// -------------------
UInt16 plAvBrainCoop::GetInitiatorSerial()
{
return fInitiatorSerial;
}
// Read -------------------------------------------------
// -----
void plAvBrainCoop::Read(hsStream *stream, hsResMgr *mgr)
{
plAvBrainGeneric::Read(stream, mgr);
fInitiatorID = stream->ReadSwap32();
fInitiatorSerial = stream->ReadSwap16();
if(stream->Readbool())
{
fHostKey = mgr->ReadKey(stream);
}
if(stream->Readbool())
{
fGuestKey = mgr->ReadKey(stream);
}
fWaitingForClick = stream->Readbool();
unsigned numRecipients = stream->ReadSwap16();
for (unsigned i = 0; i < numRecipients; i++)
fRecipients.push_back(mgr->ReadKey(stream));
}
// Write -------------------------------------------------
// ------
void plAvBrainCoop::Write(hsStream *stream, hsResMgr *mgr)
{
plAvBrainGeneric::Write(stream, mgr);
stream->WriteSwap32(fInitiatorID);
stream->WriteSwap16(fInitiatorSerial);
bool hasHostKey = (fHostKey != nil);
bool hasGuestKey = (fGuestKey != nil);
stream->Writebool(hasHostKey);
if(hasHostKey)
mgr->WriteKey(stream, fHostKey);
stream->Writebool(hasGuestKey);
if(hasGuestKey)
mgr->WriteKey(stream, fGuestKey);
stream->Writebool(fWaitingForClick);
stream->WriteSwap16(fRecipients.size());
for (unsigned i = 0; i < fRecipients.size(); i++)
mgr->WriteKey(stream, fRecipients[i]);
}
plKey plAvBrainCoop::GetRecipient()
{
if (fRecipients.size() == 0)
return nil;
return fRecipients[0];
}
void plAvBrainCoop::SetRecipient(plKey &recipient)
{
fRecipients.push_back(recipient);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
// singular
#include "plAvBrainCoop.h"
// local
#include "plArmatureMod.h"
#include "plAnimStage.h"
#include "plAvTaskSeek.h"
#include "plAvatarMgr.h"
// other
#include "plScene/plSceneNode.h"
#include "pnNetCommon/plNetApp.h"
// messages
#include "plMessage/plAvatarMsg.h"
#include "plMessage/plAvCoopMsg.h"
#include "plMessage/plPickedMsg.h"
#include "pnMessage/plNotifyMsg.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// STATIC
//
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//
// CODE
//
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//
// plAvBrainCoop
//
/////////////////////////////////////////////////////////////////////////////////////////
plAvBrainCoop::plAvBrainCoop()
: fInitiatorID(0),
fInitiatorSerial(0)
{
}
// plAvBrainCoop ----------------------------------------------------------
// --------------
plAvBrainCoop::plAvBrainCoop(UInt32 exitFlags, float fadeIn, float fadeOut,
MoveMode moveMode, plKey guestKey)
: plAvBrainGeneric(exitFlags, fadeIn, fadeOut, moveMode),
fGuestKey(guestKey)
{
static UInt16 coopSerial = 0;
// this particular constructor is only called by the initiator...
fInitiatorID = plNetClientApp::GetInstance()->GetPlayerID();
fInitiatorSerial = coopSerial++;
}
// plAvBrainCoop ----------------------------------------------------------
// --------------
plAvBrainCoop::plAvBrainCoop(UInt32 exitFlags, float fadeIn, float fadeOut,
MoveMode moveMode, UInt32 initiatorID, UInt16 initiatorSerial,
plKey hostKey)
: plAvBrainGeneric(exitFlags, fadeIn, fadeOut, moveMode),
fInitiatorID(initiatorID), fInitiatorSerial(initiatorSerial),
fHostKey(hostKey)
{
}
// MsgReceive ----------------------------------
// -----------
hsBool plAvBrainCoop::MsgReceive(plMessage *msg)
{
plPickedMsg *pickM = plPickedMsg::ConvertNoRef(msg);
if(pickM)
{
if(fWaitingForClick)
{
fWaitingForClick = false;
// clicks are never network propagated, so we can be sure that the
// click was performed by the local player.
plKey localPlayer = plNetClientApp::GetInstance()->GetLocalPlayerKey();
if(localPlayer == fGuestKey)
{
plAvCoopMsg *coopM = TRACKED_NEW plAvCoopMsg(plAvCoopMsg::kGuestAccepted, fInitiatorID, fInitiatorSerial);
coopM->SetBCastFlag(plMessage::kNetPropagate);
coopM->Send();
}
}
}
return plAvBrainGeneric::MsgReceive(msg);
}
// RelayNotifyMsg ----------------------------------
// ---------------
bool plAvBrainCoop::RelayNotifyMsg(plNotifyMsg *msg)
{
// add a coop event so the receiver will know what coop this message is from
msg->AddCoopEvent(fInitiatorID, fInitiatorSerial);
proMultiStageEventData * mtevt = static_cast<proMultiStageEventData *>(msg->FindEventRecord(proEventData::kMultiStage));
if(mtevt)
DebugMsg("COOP: Relaying multi-stage event to %d recipients (via plAvBrainCoop)", fRecipients.size());
if(fRecipients.size() != 0)
{
bool foundARecipient = false;
for (unsigned curRecipient = 0; curRecipient < fRecipients.size(); curRecipient++)
{
if (fRecipients[curRecipient])
{
foundARecipient = true;
msg->AddReceiver(fRecipients[curRecipient]);
}
}
if (!foundARecipient)
return false;
msg->Send();
return true;
}
else
return false;
}
void plAvBrainCoop::EnableGuestClick()
{
fWaitingForClick = true;
}
// GetInitiatorID --------------------
// ---------------
UInt32 plAvBrainCoop::GetInitiatorID()
{
return fInitiatorID;
}
// GetInitiatorSerial --------------------
// -------------------
UInt16 plAvBrainCoop::GetInitiatorSerial()
{
return fInitiatorSerial;
}
// Read -------------------------------------------------
// -----
void plAvBrainCoop::Read(hsStream *stream, hsResMgr *mgr)
{
plAvBrainGeneric::Read(stream, mgr);
fInitiatorID = stream->ReadSwap32();
fInitiatorSerial = stream->ReadSwap16();
if(stream->Readbool())
{
fHostKey = mgr->ReadKey(stream);
}
if(stream->Readbool())
{
fGuestKey = mgr->ReadKey(stream);
}
fWaitingForClick = stream->Readbool();
unsigned numRecipients = stream->ReadSwap16();
for (unsigned i = 0; i < numRecipients; i++)
fRecipients.push_back(mgr->ReadKey(stream));
}
// Write -------------------------------------------------
// ------
void plAvBrainCoop::Write(hsStream *stream, hsResMgr *mgr)
{
plAvBrainGeneric::Write(stream, mgr);
stream->WriteSwap32(fInitiatorID);
stream->WriteSwap16(fInitiatorSerial);
bool hasHostKey = (fHostKey != nil);
bool hasGuestKey = (fGuestKey != nil);
stream->Writebool(hasHostKey);
if(hasHostKey)
mgr->WriteKey(stream, fHostKey);
stream->Writebool(hasGuestKey);
if(hasGuestKey)
mgr->WriteKey(stream, fGuestKey);
stream->Writebool(fWaitingForClick);
stream->WriteSwap16(fRecipients.size());
for (unsigned i = 0; i < fRecipients.size(); i++)
mgr->WriteKey(stream, fRecipients[i]);
}
plKey plAvBrainCoop::GetRecipient()
{
if (fRecipients.size() == 0)
return nil;
return fRecipients[0];
}
void plAvBrainCoop::SetRecipient(plKey &recipient)
{
fRecipients.push_back(recipient);
}

View File

@ -1,81 +1,81 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVBRAINGENERIC_H
#define PLAVBRAINGENERIC_H
#include "hsStlUtils.h"
#include "plAvBrainGeneric.h"
/** \class plAvBrainCoop
This is currently no different whatsoever from plAvBrainGeneric,
but it's quite possible that it will need to vary, so we're
keeping it around for the moment. */
class plAvBrainCoop : public plAvBrainGeneric
{
public:
// used only by the class factory...
plAvBrainCoop();
// use this constructor for a host brain; it sets up the unique ID
plAvBrainCoop(UInt32 exitFlags, float fadeIn, float fadeOut, MoveMode moveMode, plKey guestKey);
// use this constructor for the guest brain, when you already have the unique ID
plAvBrainCoop(UInt32 exitFlags, float fadeIn, float fadeOut, MoveMode moveMode,
UInt32 initiatorID, UInt16 initiatorSerial, plKey hostKey);
hsBool MsgReceive(plMessage *msg);
virtual bool RelayNotifyMsg(plNotifyMsg *msg);
void EnableGuestClick();
// rtti
CLASSNAME_REGISTER( plAvBrainCoop );
GETINTERFACE_ANY( plAvBrainCoop, plAvBrainGeneric);
// i/o
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
// stuff
UInt32 GetInitiatorID();
UInt16 GetInitiatorSerial();
virtual plKey GetRecipient();
virtual void SetRecipient(plKey &recipient);
private:
UInt32 fInitiatorID;
UInt16 fInitiatorSerial;
plKey fGuestKey; // only filled out if we are the host
plKey fHostKey; // only filled out if we are the guest
bool fWaitingForClick;
std::vector<plKey> fRecipients; // we have an array for a slight hack so relto book sharing works
};
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVBRAINGENERIC_H
#define PLAVBRAINGENERIC_H
#include "hsStlUtils.h"
#include "plAvBrainGeneric.h"
/** \class plAvBrainCoop
This is currently no different whatsoever from plAvBrainGeneric,
but it's quite possible that it will need to vary, so we're
keeping it around for the moment. */
class plAvBrainCoop : public plAvBrainGeneric
{
public:
// used only by the class factory...
plAvBrainCoop();
// use this constructor for a host brain; it sets up the unique ID
plAvBrainCoop(UInt32 exitFlags, float fadeIn, float fadeOut, MoveMode moveMode, plKey guestKey);
// use this constructor for the guest brain, when you already have the unique ID
plAvBrainCoop(UInt32 exitFlags, float fadeIn, float fadeOut, MoveMode moveMode,
UInt32 initiatorID, UInt16 initiatorSerial, plKey hostKey);
hsBool MsgReceive(plMessage *msg);
virtual bool RelayNotifyMsg(plNotifyMsg *msg);
void EnableGuestClick();
// rtti
CLASSNAME_REGISTER( plAvBrainCoop );
GETINTERFACE_ANY( plAvBrainCoop, plAvBrainGeneric);
// i/o
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
// stuff
UInt32 GetInitiatorID();
UInt16 GetInitiatorSerial();
virtual plKey GetRecipient();
virtual void SetRecipient(plKey &recipient);
private:
UInt32 fInitiatorID;
UInt16 fInitiatorSerial;
plKey fGuestKey; // only filled out if we are the host
plKey fHostKey; // only filled out if we are the guest
bool fWaitingForClick;
std::vector<plKey> fRecipients; // we have an array for a slight hack so relto book sharing works
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,168 +1,168 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_AV_BRAIN_CRITTER_H
#define PL_AV_BRAIN_CRITTER_H
#include "plAvBrain.h"
#include "hsTemplates.h"
#include "pnKeyedObject/plKey.h"
class plArmatureMod;
class plWalkingController;
class plAIMsg;
class plAvBrainCritter : public plArmatureBrain
{
public:
enum CritterMode
{
kIdle = 0,
kRun,
kNumDefaultModes
// anything >= kNumDefaultModes is user
};
enum Anims
{
kIdleAnim = 0,
kRunAnim,
kNumDefaultAnims
// anything >= kNumDefaultAnims this is user
};
plAvBrainCritter();
virtual ~plAvBrainCritter();
CLASSNAME_REGISTER(plAvBrainCritter);
GETINTERFACE_ANY(plAvBrainCritter, plArmatureBrain);
hsBool Apply(double time, hsScalar elapsed);
hsBool MsgReceive(plMessage* msg);
virtual void Activate(plArmatureModBase* avMod);
virtual void Deactivate();
virtual void Suspend();
virtual void Resume();
void AddBehavior(const std::string& animationName, const std::string& behaviorName, bool loop = true, bool randomStartPos = true,
float fadeInLen = 2.f, float fadeOutLen = 2.f);
void StartBehavior(const std::string& behaviorName, bool fade = true);
bool RunningBehavior(const std::string& behaviorName) const;
void LocallyControlled(bool local) {fLocallyControlled = local;}
bool LocallyControlled() const {return fLocallyControlled;}
std::string BehaviorName(int behavior) const;
std::string AnimationName(int behavior) const;
int CurBehavior() const {return fCurMode;}
int NextBehavior() const {return fNextMode;}
std::string IdleBehaviorName() const;
std::string RunBehaviorName() const;
void GoToGoal(hsPoint3 newGoal, bool avoidingAvatars = false);
hsPoint3 CurrentGoal() const {return fFinalGoalPos;}
bool AvoidingAvatars() const {return fAvoidingAvatars;}
bool AtGoal() const;
void StopDistance(hsScalar stopDistance) {fStopDistance = stopDistance; fStopDistanceSquared = fStopDistance * fStopDistance;}
hsScalar StopDistance() const {return fStopDistance;}
void SightCone(hsScalar coneRad);
hsScalar SightCone() const {return fSightConeAngle;}
void SightDistance(hsScalar sightDis) {fSightDistance = sightDis; fSightDistanceSquared = fSightDistance * fSightDistance;}
hsScalar SightDistance() const {return fSightDistance;}
void HearingDistance(hsScalar hearDis);
hsScalar HearingDistance() const {return fHearingDistance;}
bool CanSeeAvatar(unsigned long id) const;
bool CanHearAvatar(unsigned long id) const;
std::vector<unsigned long> PlayersICanSee() const;
std::vector<unsigned long> PlayersICanHear() const;
hsVector3 VectorToPlayer(unsigned long id) const;
void AddReceiver(const plKey key);
void RemoveReceiver(const plKey key);
virtual void DumpToDebugDisplay(int& x, int& y, int lineHeight, char* strBuf, plDebugText& debugTxt);
plWalkingController* GetCallbackAction() {return fCallbackAction;}
// For the console
static bool fDrawDebug;
protected:
virtual hsBool IInitBaseAnimations();
int IPickBehavior(int behavior) const;
int IPickBehavior(const std::string& behavior) const;
void IFadeOutBehavior(); // fades out fCurMode
void IStartBehavior(); // fades in and initializes fNextMode, then sets fCurMode
void IProcessBehavior(double time, float elapsed); // processes fCurMode
void IEvalGoal();
hsScalar IGetTurnStrength(double time) const;
std::vector<unsigned long> IGetAgePlayerIDList() const;
bool ICanSeeAvatar(plArmatureMod* avatar) const;
bool ICanHearAvatar(plArmatureMod* avatar) const;
std::vector<plArmatureMod*> IAvatarsICanSee() const;
std::vector<plArmatureMod*> IAvatarsICanHear() const;
plWalkingController* fCallbackAction;
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?
bool fLocallyControlled; // is our local AI script the one making all the choices?
bool fAvoidingAvatars; // are we avoiding avatars to the best of our ability when pathfinding?
hsPoint3 fFinalGoalPos; // the location we are pathfinding to
hsPoint3 fImmediateGoalPos; // the location of the point we are immediately going towards (not necessarily our final goal)
hsScalar fDotGoal; // dot product to our goal
hsScalar fAngRight; // dot product of our local right-hand vector to our goal
hsScalar fStopDistance; // how close we need to get to our goal before stopping
hsScalar fStopDistanceSquared; // the above, squared, for faster calculation
hsScalar fSightConeAngle; // in radians, the width of the cone we can see (/2 on each side of where we face, so 90deg cone is 45deg on each side)
hsScalar fSightConeDotMin; // the minimum dot-product of the cone we can see (1 - straight ahead only, 0 - 90deg either side, -1 - 180 behind, or full 360)
hsScalar fSightDistance; // how far away we can see (cone in front of us)
hsScalar fSightDistanceSquared; // the above, squared, for faster calculation
hsScalar fHearingDistance; // how far away we can hear (360 degrees)
hsScalar fHearingDistanceSquared; // the above, squared, for faster calculation
hsScalar fLoudHearingDistanceSquared; // how far away we can hear loud noises, squared, for faster calculation
std::map<std::string, std::vector<int> > fUserBehaviors; // string is behavior name, internal vector is the list of behaviors that are randomly picked from
std::vector<plKey> fReceivers; // list of people that want messages from us
};
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_AV_BRAIN_CRITTER_H
#define PL_AV_BRAIN_CRITTER_H
#include "plAvBrain.h"
#include "hsTemplates.h"
#include "pnKeyedObject/plKey.h"
class plArmatureMod;
class plWalkingController;
class plAIMsg;
class plAvBrainCritter : public plArmatureBrain
{
public:
enum CritterMode
{
kIdle = 0,
kRun,
kNumDefaultModes
// anything >= kNumDefaultModes is user
};
enum Anims
{
kIdleAnim = 0,
kRunAnim,
kNumDefaultAnims
// anything >= kNumDefaultAnims this is user
};
plAvBrainCritter();
virtual ~plAvBrainCritter();
CLASSNAME_REGISTER(plAvBrainCritter);
GETINTERFACE_ANY(plAvBrainCritter, plArmatureBrain);
hsBool Apply(double time, hsScalar elapsed);
hsBool MsgReceive(plMessage* msg);
virtual void Activate(plArmatureModBase* avMod);
virtual void Deactivate();
virtual void Suspend();
virtual void Resume();
void AddBehavior(const std::string& animationName, const std::string& behaviorName, bool loop = true, bool randomStartPos = true,
float fadeInLen = 2.f, float fadeOutLen = 2.f);
void StartBehavior(const std::string& behaviorName, bool fade = true);
bool RunningBehavior(const std::string& behaviorName) const;
void LocallyControlled(bool local) {fLocallyControlled = local;}
bool LocallyControlled() const {return fLocallyControlled;}
std::string BehaviorName(int behavior) const;
std::string AnimationName(int behavior) const;
int CurBehavior() const {return fCurMode;}
int NextBehavior() const {return fNextMode;}
std::string IdleBehaviorName() const;
std::string RunBehaviorName() const;
void GoToGoal(hsPoint3 newGoal, bool avoidingAvatars = false);
hsPoint3 CurrentGoal() const {return fFinalGoalPos;}
bool AvoidingAvatars() const {return fAvoidingAvatars;}
bool AtGoal() const;
void StopDistance(hsScalar stopDistance) {fStopDistance = stopDistance; fStopDistanceSquared = fStopDistance * fStopDistance;}
hsScalar StopDistance() const {return fStopDistance;}
void SightCone(hsScalar coneRad);
hsScalar SightCone() const {return fSightConeAngle;}
void SightDistance(hsScalar sightDis) {fSightDistance = sightDis; fSightDistanceSquared = fSightDistance * fSightDistance;}
hsScalar SightDistance() const {return fSightDistance;}
void HearingDistance(hsScalar hearDis);
hsScalar HearingDistance() const {return fHearingDistance;}
bool CanSeeAvatar(unsigned long id) const;
bool CanHearAvatar(unsigned long id) const;
std::vector<unsigned long> PlayersICanSee() const;
std::vector<unsigned long> PlayersICanHear() const;
hsVector3 VectorToPlayer(unsigned long id) const;
void AddReceiver(const plKey key);
void RemoveReceiver(const plKey key);
virtual void DumpToDebugDisplay(int& x, int& y, int lineHeight, char* strBuf, plDebugText& debugTxt);
plWalkingController* GetCallbackAction() {return fCallbackAction;}
// For the console
static bool fDrawDebug;
protected:
virtual hsBool IInitBaseAnimations();
int IPickBehavior(int behavior) const;
int IPickBehavior(const std::string& behavior) const;
void IFadeOutBehavior(); // fades out fCurMode
void IStartBehavior(); // fades in and initializes fNextMode, then sets fCurMode
void IProcessBehavior(double time, float elapsed); // processes fCurMode
void IEvalGoal();
hsScalar IGetTurnStrength(double time) const;
std::vector<unsigned long> IGetAgePlayerIDList() const;
bool ICanSeeAvatar(plArmatureMod* avatar) const;
bool ICanHearAvatar(plArmatureMod* avatar) const;
std::vector<plArmatureMod*> IAvatarsICanSee() const;
std::vector<plArmatureMod*> IAvatarsICanHear() const;
plWalkingController* fCallbackAction;
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?
bool fLocallyControlled; // is our local AI script the one making all the choices?
bool fAvoidingAvatars; // are we avoiding avatars to the best of our ability when pathfinding?
hsPoint3 fFinalGoalPos; // the location we are pathfinding to
hsPoint3 fImmediateGoalPos; // the location of the point we are immediately going towards (not necessarily our final goal)
hsScalar fDotGoal; // dot product to our goal
hsScalar fAngRight; // dot product of our local right-hand vector to our goal
hsScalar fStopDistance; // how close we need to get to our goal before stopping
hsScalar fStopDistanceSquared; // the above, squared, for faster calculation
hsScalar fSightConeAngle; // in radians, the width of the cone we can see (/2 on each side of where we face, so 90deg cone is 45deg on each side)
hsScalar fSightConeDotMin; // the minimum dot-product of the cone we can see (1 - straight ahead only, 0 - 90deg either side, -1 - 180 behind, or full 360)
hsScalar fSightDistance; // how far away we can see (cone in front of us)
hsScalar fSightDistanceSquared; // the above, squared, for faster calculation
hsScalar fHearingDistance; // how far away we can hear (360 degrees)
hsScalar fHearingDistanceSquared; // the above, squared, for faster calculation
hsScalar fLoudHearingDistanceSquared; // how far away we can hear loud noises, squared, for faster calculation
std::map<std::string, std::vector<int> > fUserBehaviors; // string is behavior name, internal vector is the list of behaviors that are randomly picked from
std::vector<plKey> fReceivers; // list of people that want messages from us
};
#endif // PL_AV_BRAIN_CRITTER_H

View File

@ -1,183 +1,183 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// local includes
#include "plAvBrainDrive.h"
#include "plArmatureMod.h"
#include "plAvCallbackAction.h"
// global includes
#include "hsTimer.h"
#include "hsGeometry3.h"
// other includes
#include "hsQuat.h"
#include "plMessage/plSimStateMsg.h"
#include "pnMessage/plCameraMsg.h"
// messages
#include "plMessage/plInputEventMsg.h"
// CTOR default
plAvBrainDrive::plAvBrainDrive()
: fMaxVelocity(20), fTurnRate(1)
{
}
// CTOR max velocity, turn rate
plAvBrainDrive::plAvBrainDrive(hsScalar maxVelocity, hsScalar turnRate)
: fMaxVelocity(maxVelocity), fTurnRate(turnRate)
{
}
// ACTIVATE
void plAvBrainDrive::Activate(plArmatureModBase *avMod)
{
plArmatureBrain::Activate(avMod);
IEnablePhysics(false, avMod->GetTarget(0)->GetKey());
plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
pMsg->SetCmd(plCameraMsg::kNonPhysOn);
pMsg->SetBCastFlag(plMessage::kBCastByExactType);
pMsg->Send();
}
// DEACTIVATE
void plAvBrainDrive::Deactivate()
{
if (fAvMod)
{
IEnablePhysics(true, fAvMod->GetTarget(0)->GetKey());
plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
pMsg->SetCmd(plCameraMsg::kNonPhysOff);
pMsg->SetBCastFlag(plMessage::kBCastByExactType);
pMsg->Send();
}
}
void plAvBrainDrive::IEnablePhysics(bool enable, plKey avKey)
{
fAvMod->EnablePhysics(enable);
}
// APPLY
hsBool plAvBrainDrive::Apply(double timeNow, hsScalar elapsed)
{
plSceneObject * avSO = fAvMod->GetTarget(0);
hsScalar eTime = hsTimer::GetDelSysSeconds();
hsMatrix44 targetMatrix = avSO->GetLocalToWorld();
hsPoint3 playerPos = targetMatrix.GetTranslate();
hsVector3 view, up, right;
targetMatrix.GetAxis(&view, &up, &right);
hsScalar speed = fMaxVelocity;
hsScalar turn = fTurnRate;
if (fAvMod->FastKeyDown())
{
turn *= 0.25;
speed *= 3.5;
}
if (fAvMod->GetInputFlag(B_CONTROL_MOVE_FORWARD))
{
playerPos += view * speed * eTime;
}
if (fAvMod->GetInputFlag(B_CONTROL_MOVE_BACKWARD))
{
playerPos += view * speed * eTime * -1;
}
if (fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown()))
{
playerPos += right * speed * eTime * -1;
}
if (fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown()))
{
playerPos += right * speed * eTime;
}
if (fAvMod->GetInputFlag(B_CONTROL_MOVE_DOWN))
{
playerPos += up * speed * eTime * -1;
}
if (fAvMod->GetInputFlag(B_CONTROL_MOVE_UP))
{
playerPos += up * speed * eTime;
}
hsPoint3 desiredPosition = playerPos;
// calculate rotation matrix
hsVector3 rotUp(0,0,1);
hsVector3 rotRight(1,0,0);
hsMatrix44 rot;
hsScalar angle = 0;
if ( fAvMod->GetInputFlag( B_CONTROL_ROTATE_RIGHT ) || fAvMod->GetInputFlag( B_CONTROL_ROTATE_LEFT ) || fAvMod->GetInputFlag( A_CONTROL_TURN ) )
{
angle = fTurnRate * eTime * fAvMod->GetTurnStrength();
}
hsMatrix44 justRot(targetMatrix);
hsPoint3 zero(0,0,0);
justRot.SetTranslate(&zero);
if( angle ) {
hsQuat q( angle, &rotUp );
q.NormalizeIfNeeded();
q.MakeMatrix( &rot );
justRot = rot * justRot;
targetMatrix = rot * targetMatrix;
}
// use the desired rotation matrix to set position and rotation:
hsMatrix44 inv;
targetMatrix.SetTranslate( &desiredPosition );
targetMatrix.GetInverse( &inv );
avSO->SetTransform( targetMatrix, inv );
avSO->FlushTransform();
return true;
}
// IHANDLECONTROLMSG
hsBool plAvBrainDrive::MsgReceive(plMessage* msg)
{
plControlEventMsg *ctrlMsg = plControlEventMsg::ConvertNoRef(msg);
if(ctrlMsg)
{
if( ctrlMsg->ControlActivated() )
{
if(ctrlMsg->GetControlCode() == B_CONTROL_TOGGLE_PHYSICAL)
{
fAvMod->PopBrain();
return true;
}
}
}
return false;
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// local includes
#include "plAvBrainDrive.h"
#include "plArmatureMod.h"
#include "plAvCallbackAction.h"
// global includes
#include "hsTimer.h"
#include "hsGeometry3.h"
// other includes
#include "hsQuat.h"
#include "plMessage/plSimStateMsg.h"
#include "pnMessage/plCameraMsg.h"
// messages
#include "plMessage/plInputEventMsg.h"
// CTOR default
plAvBrainDrive::plAvBrainDrive()
: fMaxVelocity(20), fTurnRate(1)
{
}
// CTOR max velocity, turn rate
plAvBrainDrive::plAvBrainDrive(hsScalar maxVelocity, hsScalar turnRate)
: fMaxVelocity(maxVelocity), fTurnRate(turnRate)
{
}
// ACTIVATE
void plAvBrainDrive::Activate(plArmatureModBase *avMod)
{
plArmatureBrain::Activate(avMod);
IEnablePhysics(false, avMod->GetTarget(0)->GetKey());
plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
pMsg->SetCmd(plCameraMsg::kNonPhysOn);
pMsg->SetBCastFlag(plMessage::kBCastByExactType);
pMsg->Send();
}
// DEACTIVATE
void plAvBrainDrive::Deactivate()
{
if (fAvMod)
{
IEnablePhysics(true, fAvMod->GetTarget(0)->GetKey());
plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
pMsg->SetCmd(plCameraMsg::kNonPhysOff);
pMsg->SetBCastFlag(plMessage::kBCastByExactType);
pMsg->Send();
}
}
void plAvBrainDrive::IEnablePhysics(bool enable, plKey avKey)
{
fAvMod->EnablePhysics(enable);
}
// APPLY
hsBool plAvBrainDrive::Apply(double timeNow, hsScalar elapsed)
{
plSceneObject * avSO = fAvMod->GetTarget(0);
hsScalar eTime = hsTimer::GetDelSysSeconds();
hsMatrix44 targetMatrix = avSO->GetLocalToWorld();
hsPoint3 playerPos = targetMatrix.GetTranslate();
hsVector3 view, up, right;
targetMatrix.GetAxis(&view, &up, &right);
hsScalar speed = fMaxVelocity;
hsScalar turn = fTurnRate;
if (fAvMod->FastKeyDown())
{
turn *= 0.25;
speed *= 3.5;
}
if (fAvMod->GetInputFlag(B_CONTROL_MOVE_FORWARD))
{
playerPos += view * speed * eTime;
}
if (fAvMod->GetInputFlag(B_CONTROL_MOVE_BACKWARD))
{
playerPos += view * speed * eTime * -1;
}
if (fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown()))
{
playerPos += right * speed * eTime * -1;
}
if (fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown()))
{
playerPos += right * speed * eTime;
}
if (fAvMod->GetInputFlag(B_CONTROL_MOVE_DOWN))
{
playerPos += up * speed * eTime * -1;
}
if (fAvMod->GetInputFlag(B_CONTROL_MOVE_UP))
{
playerPos += up * speed * eTime;
}
hsPoint3 desiredPosition = playerPos;
// calculate rotation matrix
hsVector3 rotUp(0,0,1);
hsVector3 rotRight(1,0,0);
hsMatrix44 rot;
hsScalar angle = 0;
if ( fAvMod->GetInputFlag( B_CONTROL_ROTATE_RIGHT ) || fAvMod->GetInputFlag( B_CONTROL_ROTATE_LEFT ) || fAvMod->GetInputFlag( A_CONTROL_TURN ) )
{
angle = fTurnRate * eTime * fAvMod->GetTurnStrength();
}
hsMatrix44 justRot(targetMatrix);
hsPoint3 zero(0,0,0);
justRot.SetTranslate(&zero);
if( angle ) {
hsQuat q( angle, &rotUp );
q.NormalizeIfNeeded();
q.MakeMatrix( &rot );
justRot = rot * justRot;
targetMatrix = rot * targetMatrix;
}
// use the desired rotation matrix to set position and rotation:
hsMatrix44 inv;
targetMatrix.SetTranslate( &desiredPosition );
targetMatrix.GetInverse( &inv );
avSO->SetTransform( targetMatrix, inv );
avSO->FlushTransform();
return true;
}
// IHANDLECONTROLMSG
hsBool plAvBrainDrive::MsgReceive(plMessage* msg)
{
plControlEventMsg *ctrlMsg = plControlEventMsg::ConvertNoRef(msg);
if(ctrlMsg)
{
if( ctrlMsg->ControlActivated() )
{
if(ctrlMsg->GetControlCode() == B_CONTROL_TOGGLE_PHYSICAL)
{
fAvMod->PopBrain();
return true;
}
}
}
return false;
}

View File

@ -1,85 +1,85 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAvBrainDrive.h
*/
#ifndef AVBRAINDRIVE_INC
#define AVBRAINDRIVE_INC
// base class
#include "plAvBrain.h"
/** A simple brain used to steer the player around without regard
for physics. Used in production to quickly fly through a scene
without having to actually solve puzzles, jump, etc.
The 'Drive Brain' uses the same input keys as the avatar, with
a few secret additions for convenience. At the time of this
writing, you invoke the drive brain by pressing shift-P, and
then use the forward and back arrows to move and th e left and
right arrows to rotate. The 'u' and 'j' keys will move your avatar
vertically.
Gravity and collision are completely suspended for avatars in
drive mode, but they *can* still trigger region detectors if
you need to fire off triggers, puzzles, or whatnot.
Note that the drive brain inherits from the user brain, which
parses control input for us.
*/
class plAvBrainDrive : public plArmatureBrain
{
public:
plAvBrainDrive();
/** Canonical constructer. Use this one.
\param maxVelocity The highest speed this avatar can fly at.
\param turnRate The speed at which we will turn, in radians per second.
*/
plAvBrainDrive(hsScalar maxVelocity, hsScalar turnRate);
// BRAIN PROTOCOL
/** Suspend physics and get in line to receive keyboard control messages. */
virtual void Activate(plArmatureModBase *avMod);
/** Restore physical reality and stop handling input messages */
virtual void Deactivate();
/** Look at the key states and figure out if and how we should move */
virtual hsBool Apply(double timeNow, hsScalar elapsed); // main control loop. called by avatar eval()
// the user brain base handles most of the details of control messages,
// so this function just looks for the special command which gets us out
// of drive mode.
virtual hsBool MsgReceive(plMessage* pMsg); // handle control input from the user
CLASSNAME_REGISTER( plAvBrainDrive );
GETINTERFACE_ANY( plAvBrainDrive, plArmatureBrain );
protected:
void IEnablePhysics(bool enable, plKey avKey);
hsScalar fMaxVelocity;
hsScalar fTurnRate;
};
#endif // AVBRAINDRIVE_INC
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAvBrainDrive.h
*/
#ifndef AVBRAINDRIVE_INC
#define AVBRAINDRIVE_INC
// base class
#include "plAvBrain.h"
/** A simple brain used to steer the player around without regard
for physics. Used in production to quickly fly through a scene
without having to actually solve puzzles, jump, etc.
The 'Drive Brain' uses the same input keys as the avatar, with
a few secret additions for convenience. At the time of this
writing, you invoke the drive brain by pressing shift-P, and
then use the forward and back arrows to move and th e left and
right arrows to rotate. The 'u' and 'j' keys will move your avatar
vertically.
Gravity and collision are completely suspended for avatars in
drive mode, but they *can* still trigger region detectors if
you need to fire off triggers, puzzles, or whatnot.
Note that the drive brain inherits from the user brain, which
parses control input for us.
*/
class plAvBrainDrive : public plArmatureBrain
{
public:
plAvBrainDrive();
/** Canonical constructer. Use this one.
\param maxVelocity The highest speed this avatar can fly at.
\param turnRate The speed at which we will turn, in radians per second.
*/
plAvBrainDrive(hsScalar maxVelocity, hsScalar turnRate);
// BRAIN PROTOCOL
/** Suspend physics and get in line to receive keyboard control messages. */
virtual void Activate(plArmatureModBase *avMod);
/** Restore physical reality and stop handling input messages */
virtual void Deactivate();
/** Look at the key states and figure out if and how we should move */
virtual hsBool Apply(double timeNow, hsScalar elapsed); // main control loop. called by avatar eval()
// the user brain base handles most of the details of control messages,
// so this function just looks for the special command which gets us out
// of drive mode.
virtual hsBool MsgReceive(plMessage* pMsg); // handle control input from the user
CLASSNAME_REGISTER( plAvBrainDrive );
GETINTERFACE_ANY( plAvBrainDrive, plArmatureBrain );
protected:
void IEnablePhysics(bool enable, plKey avKey);
hsScalar fMaxVelocity;
hsScalar fTurnRate;
};
#endif // AVBRAINDRIVE_INC

File diff suppressed because it is too large Load Diff

View File

@ -1,314 +1,314 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVBRAINGENERIC_INC
#define PLAVBRAINGENERIC_INC
// base class
#include "plAvBrain.h"
#include "plAGAnim.h"
class plAnimStage;
class plAnimStageVec;
class plAvBrainGenericMsg;
class plHorizontalFreezeAction;
class plNotifyMsg;
/** \class plAvBrainGeneric
The generic brain is designed to manage complex (and simple) sequences of animations
used in detailed puzzle sequences and the like.
It implements a model wherein each animation is wrapped in an plAnimStage object,
which provides different means of user input, support for loop types, callbacks
at significant events, and scripted control of stage transitions.
Detailed object interactions such as climbing, sitting, interacting with levers,
and the like are all handled by generic brains with varying stages.
*/
class plAvBrainGeneric : public plArmatureBrain
{
public:
/** \enum BrainType
Sometimes the brains are truly generic and opaque, and sometimes
we need to be able to tell "what this brain does" at a summary level.
This enum lists our current standard brain types.
This data is not used internally by the brain; it's just stored
for the user. */
enum BrainType {
kGeneric, /// type was not specified
kLadder, /// it's a ladder brain
kSit, /// it's a sit brain
kSitOnGround, /// sit on the ground emote
kEmote, /// yeah yeah
kAFK,
kNumBrainTypes,
kNonGeneric = kNumBrainTypes /// If we ask the avatar what its current generic type is,
/// we use this to signify that it's not currenty using
/// a generic brain.
};
/** \enum ExitFlag
The default behavior for a generic brain is to exit when all its
stages are completed. This set of bitwise indices defines other
conditions which can be used to exit a brain.
Note: For now, we're restricting the SDL for this to a byte. Change that if you add
too many flags.
*/
enum ExitFlag {
kExitNormal = 0, // for completeness; use this when you don't have an exit condition
kExitAnyTask = 0x01, // exit if anyone sends us a task
kExitNewBrain = 0x02, // exit if anyone sends us a new brain
kExitAnyInput = 0x04, // exit if we get any input control events
kExitMaxFlag = 0x08
};
enum MoveMode {
kMoveAbsolute, // the animations are taken to be in world coordinates
kMoveRelative, // the animation is played as if the starting point is the origin
kMoveNormal, // the avatar root is moved by translating the animation to velocity
kMoveStandstill, // the avatar root is held immobile
kMaxMoveMode,
kForceSize = 0xff
};
enum Mode{
kEntering = 0x01, // seeking, loading, or within the "enter" animation
kNormal = 0x02, // undistinguished animations are running
kFadingIn = 0x03, // fading in first stage; not running
kFadingOut = 0x04, // fading out last stage; not running
kExit = 0x05, // exit observing animation fadeouts, etc.
kAbort = 0x06, // exit immediately without updating animations
kMaxMode = 0x07,
kModeSize = 0xff
} fMode;
static const hsScalar kDefaultFadeIn;
static const hsScalar kDefaultFadeOut;
/** Default constructor for the class factory and descendants. */
plAvBrainGeneric();
/** Canonical constructor - use this.
\param stages A vector of stages to use for this brain. Will be copied
into our internal vector.
\param enterMessage A message to send when the brain enters begins playing.
If you need finer control over callbacks, use stage callbacks.
\param exitMessage A message to send when the brain exits.
\param recipient Callbacks from the brain *and* the stages is sent to this key.
\param exitFlags A combination of exit conditions from the ExitFlag enum */
plAvBrainGeneric(plAnimStageVec *stages, plMessage *enterMessage, plMessage *exitMessage,
plKey recipient, UInt32 exitFlags, float fadeIn, float fadeOut, MoveMode moveMode);
/** Simplified constructor
\param exitFlags Indicates which conditions will cause the brain to exit.
\param fadeIn Rate (in blend units per second) of initial animation fade in.
\param fadeOut Rate (in blend units per second) of final animation fade out.
*/
plAvBrainGeneric(UInt32 exitFlags, float fadeIn, float fadeOut, MoveMode moveMode);
/** Virtual destructor */
virtual ~plAvBrainGeneric();
static hsBool fForce3rdPerson;
/** Attaches our current stage and takes control of the armature. Note that
the brain may be in a "half-finished" state -- we may be receiving some
complex state from another client and therefore pushing on a brain that
is in the middle of its third stage, for example. */
virtual void Activate(plArmatureModBase *avMod);
/** Advance the current stage and swap in a new stage if necessary. */
virtual hsBool Apply(double timeNow, hsScalar elapsed);
/** Remove all our stages and release control of the armature. */
virtual void Deactivate();
virtual plKey GetRecipient();
virtual void SetRecipient(const plKey &recipient);
/** Send a notify message to our recipient.
Some brains, such as the coop, will use this opportunity to add annotations
to the notify. */
virtual bool RelayNotifyMsg(plNotifyMsg *msg);
/** We're leaving the age. Clean up. */
virtual hsBool LeaveAge();
virtual hsBool IsRunningTask();
/** Compare the names of the anims in our stages.
Return true on a match (order matters). */
bool MatchAnimNames(const char *names[], int count);
/** Add the given stage to the end of the stage sequence.
Returns the zero-based index of the stage.
*/
int AddStage(plAnimStage *stage);
/** The sequence number of the *given* stage -- not the current stage. Useful
if you have a pointer to a stage and want to find out where in the sequence
it lives. Notice that since stage transitions can be nonlinear, there is
no guarantee that this will be the nth stage to play, or that it will play
at all. */
int GetStageNum(plAnimStage *stage);
/** Get the sequence number of the stage that's currently playing. */
int GetCurStageNum();
void SetCurStageNum(int num) { fCurStage = num; };
/** How many stages are in this brain? */
int GetStageCount();
/** Retrieve a stage via a sequence number. Returns nil if no such stage exists
Be extremely careful about retaining this pointer, as it may be deleted at
any time. */
plAnimStage * GetStage(int which);
/** Retrieve a pointer to the currently executing stage.Returns nil if no such stage exists
Be extremely careful about retaining this pointer, as it may be deleted at
any time. */
plAnimStage * GetCurStage();
/** Set the user-specified type of the brain. Has no effect on brain behavior;
just a poor man's dynamic type system */
BrainType SetType(BrainType newType);
/** Get the user-specified type of the brain. Has no effect on brain behavior;
for external reference only. */
BrainType GetType();
/** Is the brain moving "generally" forward? This is a fairly poorly-defined concept
that is only used by stages that have "auto" progress types, i.e. they
move forward if the brain is moving forward, and move backward if the brain
is moving backward.
/deprecated Avoid. will probably be deleted. */
bool GetForward() const { return fForward; }
bool GetReverseFBControlsOnRelease() const { return fReverseFBControlsOnRelease; };
void SetReverseFBControlsOnRelease(bool val) { fReverseFBControlsOnRelease = val; };
/** Returns a pointer to the message we will send when we start our brain.
Returns nil if there is no such message *or* if it has already been sent.
/bug This message is destructed after being delivered, so we need to
nil this pointer after sending it.
*/
plMessage* GetStartMessage() const { return fStartMessage; }
/** Returns a pointer to the message we will send when we finish our brain.
Returns nil if there is no such message *or* if it has already been sent.
/bug This message is destructed after being delivered, so we need to
nil this pointer after sending it.
*/
plMessage* GetEndMessage() const { return fEndMessage; }
/** Returns the bitvector holding our exit conditions.
/sa plAvBrainGeneric::ExitFlags */
UInt32 GetExitFlags() const { return fExitFlags; }
plAGAnim::BodyUsage GetBodyUsage();
void SetBodyUsage(plAGAnim::BodyUsage bodyUsage);
Mode GetMode() { return fMode; }
void SetMode(Mode mode) { fMode = mode; }
float GetFadeIn() { return fFadeIn; }
float GetFadeOut() { return fFadeOut; }
MoveMode GetMoveMode() { return fMoveMode; }
/** Output the brain's status to the avatar debug screen. */
virtual void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
// plasma protocol
hsBool plAvBrainGeneric::MsgReceive(plMessage *msg);
CLASSNAME_REGISTER( plAvBrainGeneric );
GETINTERFACE_ANY( plAvBrainGeneric, plArmatureBrain );
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
/////////////////////////////////////////////////////////////////////////////////////
//
// CODE
//
/////////////////////////////////////////////////////////////////////////////////////
hsBool IHandleGenBrainMsg(const plAvBrainGenericMsg *msg);
hsBool IHandleTaskMsg(plAvTaskMsg *msg);
bool IBrainIsCompatible(plAvBrainGeneric *otherBrain);
float IGetAnimDelta(double time, float elapsed); // how far should we move our animation this frame?
hsBool IProcessNormal(double time, float elapsed);
hsBool IProcessFadeIn(double time, float elapsed);
hsBool IProcessFadeOut(double time, float elapsed);
hsBool ISwitchStages(int oldStage, int newStage, float delta, hsBool setTime, hsScalar newTime,
float fadeNew, hsScalar fadeOld, double worldTime);
void IEnterMoveMode(double time); // we've just entered and we're about to begin animating.
void IExitMoveMode(); // we're done animating; clean up
/////////////////////////////////////////////////////////////////////////////////////
//
// DATA
//
/////////////////////////////////////////////////////////////////////////////////////
plKey fRecipient; // this guy gets all new notify messages
plAnimStageVec *fStages; // all the stages in our animation
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
plMessage *fStartMessage; // send this message when our brain is activated
plMessage *fEndMessage; // send this message when our brain is deactivated
bool fReverseFBControlsOnRelease; // Tells the armature that we want to reverse the forward/backward controls
// if both are released. The armatureMod will tell us if this has actually happened
float fFadeIn; // if non-zero, the rate to fade in the first animation
float fFadeOut; // if non-zero, the rate to fade out the last animation
MoveMode fMoveMode; // how are we translating animation movement to
// movement in the world?
plAGAnim::BodyUsage fBodyUsage; // how much of the body does this brain use?
// this is based strictly on compatibility; i.e. a brain
// that uses only the lower body might still animate the
// hands, but it is guaranteed to look right when overlaid
// by an anim that uses only the upper body.
};
#endif // PLAVBRAINGENERIC_INC
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVBRAINGENERIC_INC
#define PLAVBRAINGENERIC_INC
// base class
#include "plAvBrain.h"
#include "plAGAnim.h"
class plAnimStage;
class plAnimStageVec;
class plAvBrainGenericMsg;
class plHorizontalFreezeAction;
class plNotifyMsg;
/** \class plAvBrainGeneric
The generic brain is designed to manage complex (and simple) sequences of animations
used in detailed puzzle sequences and the like.
It implements a model wherein each animation is wrapped in an plAnimStage object,
which provides different means of user input, support for loop types, callbacks
at significant events, and scripted control of stage transitions.
Detailed object interactions such as climbing, sitting, interacting with levers,
and the like are all handled by generic brains with varying stages.
*/
class plAvBrainGeneric : public plArmatureBrain
{
public:
/** \enum BrainType
Sometimes the brains are truly generic and opaque, and sometimes
we need to be able to tell "what this brain does" at a summary level.
This enum lists our current standard brain types.
This data is not used internally by the brain; it's just stored
for the user. */
enum BrainType {
kGeneric, /// type was not specified
kLadder, /// it's a ladder brain
kSit, /// it's a sit brain
kSitOnGround, /// sit on the ground emote
kEmote, /// yeah yeah
kAFK,
kNumBrainTypes,
kNonGeneric = kNumBrainTypes /// If we ask the avatar what its current generic type is,
/// we use this to signify that it's not currenty using
/// a generic brain.
};
/** \enum ExitFlag
The default behavior for a generic brain is to exit when all its
stages are completed. This set of bitwise indices defines other
conditions which can be used to exit a brain.
Note: For now, we're restricting the SDL for this to a byte. Change that if you add
too many flags.
*/
enum ExitFlag {
kExitNormal = 0, // for completeness; use this when you don't have an exit condition
kExitAnyTask = 0x01, // exit if anyone sends us a task
kExitNewBrain = 0x02, // exit if anyone sends us a new brain
kExitAnyInput = 0x04, // exit if we get any input control events
kExitMaxFlag = 0x08
};
enum MoveMode {
kMoveAbsolute, // the animations are taken to be in world coordinates
kMoveRelative, // the animation is played as if the starting point is the origin
kMoveNormal, // the avatar root is moved by translating the animation to velocity
kMoveStandstill, // the avatar root is held immobile
kMaxMoveMode,
kForceSize = 0xff
};
enum Mode{
kEntering = 0x01, // seeking, loading, or within the "enter" animation
kNormal = 0x02, // undistinguished animations are running
kFadingIn = 0x03, // fading in first stage; not running
kFadingOut = 0x04, // fading out last stage; not running
kExit = 0x05, // exit observing animation fadeouts, etc.
kAbort = 0x06, // exit immediately without updating animations
kMaxMode = 0x07,
kModeSize = 0xff
} fMode;
static const hsScalar kDefaultFadeIn;
static const hsScalar kDefaultFadeOut;
/** Default constructor for the class factory and descendants. */
plAvBrainGeneric();
/** Canonical constructor - use this.
\param stages A vector of stages to use for this brain. Will be copied
into our internal vector.
\param enterMessage A message to send when the brain enters begins playing.
If you need finer control over callbacks, use stage callbacks.
\param exitMessage A message to send when the brain exits.
\param recipient Callbacks from the brain *and* the stages is sent to this key.
\param exitFlags A combination of exit conditions from the ExitFlag enum */
plAvBrainGeneric(plAnimStageVec *stages, plMessage *enterMessage, plMessage *exitMessage,
plKey recipient, UInt32 exitFlags, float fadeIn, float fadeOut, MoveMode moveMode);
/** Simplified constructor
\param exitFlags Indicates which conditions will cause the brain to exit.
\param fadeIn Rate (in blend units per second) of initial animation fade in.
\param fadeOut Rate (in blend units per second) of final animation fade out.
*/
plAvBrainGeneric(UInt32 exitFlags, float fadeIn, float fadeOut, MoveMode moveMode);
/** Virtual destructor */
virtual ~plAvBrainGeneric();
static hsBool fForce3rdPerson;
/** Attaches our current stage and takes control of the armature. Note that
the brain may be in a "half-finished" state -- we may be receiving some
complex state from another client and therefore pushing on a brain that
is in the middle of its third stage, for example. */
virtual void Activate(plArmatureModBase *avMod);
/** Advance the current stage and swap in a new stage if necessary. */
virtual hsBool Apply(double timeNow, hsScalar elapsed);
/** Remove all our stages and release control of the armature. */
virtual void Deactivate();
virtual plKey GetRecipient();
virtual void SetRecipient(const plKey &recipient);
/** Send a notify message to our recipient.
Some brains, such as the coop, will use this opportunity to add annotations
to the notify. */
virtual bool RelayNotifyMsg(plNotifyMsg *msg);
/** We're leaving the age. Clean up. */
virtual hsBool LeaveAge();
virtual hsBool IsRunningTask();
/** Compare the names of the anims in our stages.
Return true on a match (order matters). */
bool MatchAnimNames(const char *names[], int count);
/** Add the given stage to the end of the stage sequence.
Returns the zero-based index of the stage.
*/
int AddStage(plAnimStage *stage);
/** The sequence number of the *given* stage -- not the current stage. Useful
if you have a pointer to a stage and want to find out where in the sequence
it lives. Notice that since stage transitions can be nonlinear, there is
no guarantee that this will be the nth stage to play, or that it will play
at all. */
int GetStageNum(plAnimStage *stage);
/** Get the sequence number of the stage that's currently playing. */
int GetCurStageNum();
void SetCurStageNum(int num) { fCurStage = num; };
/** How many stages are in this brain? */
int GetStageCount();
/** Retrieve a stage via a sequence number. Returns nil if no such stage exists
Be extremely careful about retaining this pointer, as it may be deleted at
any time. */
plAnimStage * GetStage(int which);
/** Retrieve a pointer to the currently executing stage.Returns nil if no such stage exists
Be extremely careful about retaining this pointer, as it may be deleted at
any time. */
plAnimStage * GetCurStage();
/** Set the user-specified type of the brain. Has no effect on brain behavior;
just a poor man's dynamic type system */
BrainType SetType(BrainType newType);
/** Get the user-specified type of the brain. Has no effect on brain behavior;
for external reference only. */
BrainType GetType();
/** Is the brain moving "generally" forward? This is a fairly poorly-defined concept
that is only used by stages that have "auto" progress types, i.e. they
move forward if the brain is moving forward, and move backward if the brain
is moving backward.
/deprecated Avoid. will probably be deleted. */
bool GetForward() const { return fForward; }
bool GetReverseFBControlsOnRelease() const { return fReverseFBControlsOnRelease; };
void SetReverseFBControlsOnRelease(bool val) { fReverseFBControlsOnRelease = val; };
/** Returns a pointer to the message we will send when we start our brain.
Returns nil if there is no such message *or* if it has already been sent.
/bug This message is destructed after being delivered, so we need to
nil this pointer after sending it.
*/
plMessage* GetStartMessage() const { return fStartMessage; }
/** Returns a pointer to the message we will send when we finish our brain.
Returns nil if there is no such message *or* if it has already been sent.
/bug This message is destructed after being delivered, so we need to
nil this pointer after sending it.
*/
plMessage* GetEndMessage() const { return fEndMessage; }
/** Returns the bitvector holding our exit conditions.
/sa plAvBrainGeneric::ExitFlags */
UInt32 GetExitFlags() const { return fExitFlags; }
plAGAnim::BodyUsage GetBodyUsage();
void SetBodyUsage(plAGAnim::BodyUsage bodyUsage);
Mode GetMode() { return fMode; }
void SetMode(Mode mode) { fMode = mode; }
float GetFadeIn() { return fFadeIn; }
float GetFadeOut() { return fFadeOut; }
MoveMode GetMoveMode() { return fMoveMode; }
/** Output the brain's status to the avatar debug screen. */
virtual void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
// plasma protocol
hsBool plAvBrainGeneric::MsgReceive(plMessage *msg);
CLASSNAME_REGISTER( plAvBrainGeneric );
GETINTERFACE_ANY( plAvBrainGeneric, plArmatureBrain );
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
/////////////////////////////////////////////////////////////////////////////////////
//
// CODE
//
/////////////////////////////////////////////////////////////////////////////////////
hsBool IHandleGenBrainMsg(const plAvBrainGenericMsg *msg);
hsBool IHandleTaskMsg(plAvTaskMsg *msg);
bool IBrainIsCompatible(plAvBrainGeneric *otherBrain);
float IGetAnimDelta(double time, float elapsed); // how far should we move our animation this frame?
hsBool IProcessNormal(double time, float elapsed);
hsBool IProcessFadeIn(double time, float elapsed);
hsBool IProcessFadeOut(double time, float elapsed);
hsBool ISwitchStages(int oldStage, int newStage, float delta, hsBool setTime, hsScalar newTime,
float fadeNew, hsScalar fadeOld, double worldTime);
void IEnterMoveMode(double time); // we've just entered and we're about to begin animating.
void IExitMoveMode(); // we're done animating; clean up
/////////////////////////////////////////////////////////////////////////////////////
//
// DATA
//
/////////////////////////////////////////////////////////////////////////////////////
plKey fRecipient; // this guy gets all new notify messages
plAnimStageVec *fStages; // all the stages in our animation
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
plMessage *fStartMessage; // send this message when our brain is activated
plMessage *fEndMessage; // send this message when our brain is deactivated
bool fReverseFBControlsOnRelease; // Tells the armature that we want to reverse the forward/backward controls
// if both are released. The armatureMod will tell us if this has actually happened
float fFadeIn; // if non-zero, the rate to fade in the first animation
float fFadeOut; // if non-zero, the rate to fade out the last animation
MoveMode fMoveMode; // how are we translating animation movement to
// movement in the world?
plAGAnim::BodyUsage fBodyUsage; // how much of the body does this brain use?
// this is based strictly on compatibility; i.e. a brain
// that uses only the lower body might still animate the
// hands, but it is guaranteed to look right when overlaid
// by an anim that uses only the upper body.
};
#endif // PLAVBRAINGENERIC_INC

File diff suppressed because it is too large Load Diff

View File

@ -1,393 +1,393 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVBRAINHUMAN_INC
#define PLAVBRAINHUMAN_INC
#define HI_RES_MOVEMENT
#include "plAvBrainGeneric.h"
#include "plAvBehaviors.h"
#include "plAGAnim.h"
#pragma warning(disable: 4284)
#include <deque>
#include "hsTemplates.h"
class plMatrixChannel;
class plMatrixMultiplyApplicator;
class plAGAnimInstance;
class plAvTask;
class plAvTaskMsg;
class plAvBrainHuman;
class plWalkingController;
class plArmatureUpdateMsg;
class plClimbMsg;
class plControlEventMsg;
class plAvBrainHuman : public plArmatureBrain
{
public:
plAvBrainHuman(bool isActor = false);
virtual ~plAvBrainHuman();
CLASSNAME_REGISTER( plAvBrainHuman );
GETINTERFACE_ANY( plAvBrainHuman, plArmatureBrain );
virtual hsBool Apply(double timeNow, hsScalar elapsed);
virtual void Activate(plArmatureModBase *avMod);
virtual void Deactivate();
virtual void Suspend();
virtual void Resume();
virtual void Spawn(double timeNow);
virtual hsBool LeaveAge();
bool IsActor() const {return fIsActor;}
void IsActor(bool isActor) {fIsActor = isActor;}
bool IsMovementZeroBlend();
void TurnToPoint(hsPoint3 point);
hsBool RunStandardBehaviors(double timeNow, float elapsed);
void SetStartedTurning(double when);
virtual bool IsMovingForward(); // we're either walking or running. doesn't account for sliding.
void ResetIdle();
void IdleOnly(bool instantOff = false);
bool IsBehaviorPlaying(int behavior); // returns whether the specified behavior is playing at all (see list of behaviors below)
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual hsBool MsgReceive(plMessage *msg);
virtual void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
// Hardwired Identifiers for all the canonical bones.
enum HumanBoneID {
Pelvis,
// left leg
LThigh, LCalf, LFoot, LFootPrint, LToe0,
// right leg
RThigh, RCalf, RFoot, RFootPrint, RToe0,
// spine and head, starting at base of spine
Spine, TrunkPrint, Spine1, Spine2, Neck, Head, Jaw, LMouthLower, RMouthLower,
LBrowInner, LBrowOuter, LCheek, LEye, LEyeLid01, LEyeLid02, LMouthCorner, LMouthUpper,
RBrowInner, RBrowOuter, RCheek, REye, REyeLid01, REyeLid02, RMouthCorner, RMouthUpper,
// Left Arm
LClavicle, LUpperArm, LForearm, LHand, LHandPrint, LMiddleFinger1, LMiddleFinger2, LMiddleFinger3,
LPinkyFinger1, LPinkyFinger2, LPinkyFinger3, LPointerFinger1, LPointerFinger2, LPointerFinger3,
LRingFinger1, LRingFinger2, LRingFinger3, LThumb1, LThumb2, LThumb3,
// Right Arm
RClavicle, RUpperArm, RForearm, RHand, RHandPrint, RMiddleFinger1, RMiddleFinger2, RMiddleFinger3,
RPinkyFinger1, RPinkyFinger2, RPinkyFinger3, RPointerFinger1, RPointerFinger2, RPointerFinger3,
RRingFinger1, RRingFinger2, RRingFinger3, RThumb1, RThumb2, RThumb3
};
enum TurnCurve
{
kTurnLinear,
kTurnExponential,
kTurnLogarithmic
};
enum // Indicies for the brains array of behaviors
{
kIdle,
kWalk,
kRun,
kWalkBack,
kStandingTurnLeft,
kStandingTurnRight,
kStepLeft,
kStepRight,
kFall,
kStandingJump,
kWalkingJump,
kRunningJump,
kGroundImpact,
kRunningImpact,
kMovingTurnLeft,
kMovingTurnRight,
kPushWalk,
//kPushIdle,
kHuBehaviorMax,
};
static void SetTimeToMaxTurn(float time, hsBool walk);
static float GetTimeToMaxTurn(hsBool walk);
static void SetMaxTurnSpeed(float radsPerSec, hsBool walk);
static float GetMaxTurnSpeed(hsBool walk);
static void SetTurnCurve(TurnCurve curve, hsBool walk);
static TurnCurve GetTurnCurve(hsBool walk);
static const hsScalar kControlledFlightThreshold;
static const hsScalar kAirTimeThreshold;
static const hsScalar kAirTimePanicThreshold;
plWalkingController* fCallbackAction;
protected:
plAGAnim *FindCustomAnim(const char *baseName);
virtual hsBool IHandleControlMsg(plControlEventMsg *ctrlMsg);
virtual hsBool IHandleClimbMsg(plClimbMsg *msg);
virtual hsBool IHandleTaskMsg(plAvTaskMsg *msg);
virtual hsBool IInitAnimations();
virtual void IInitBoneMap();
hsScalar IGetTurnStrength(double timeNow);
void IChatOn();
void IChatOff();
hsBool IValidateAnimations();
plAGModifier *fHandleAGMod; // the ag modifier that's attached to our top object
double fStartedTurning; // when did we start turning?
UInt32 fPreconditions;
bool fIsActor; // are we an actor with special privileges?
static float fWalkTimeToMaxTurn;
static float fRunTimeToMaxTurn;
static float fWalkMaxTurnSpeed;
static float fRunMaxTurnSpeed;
static TurnCurve fWalkTurnCurve;
static TurnCurve fRunTurnCurve;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class plHBehavior : public plArmatureBehavior
{
friend class plAvBrainHuman;
friend class plAvBrainCritter;
public:
// ID flags for human behaviors. These are used by plBehaviorNotifyMsg
// to identify what type of behavior just triggered.
// This is an old way of doing things. I'd like to remove it, but a lot of
// python scripts use it as is.
enum BehaviorType
{
kBehaviorTypeStandingJump = 0x00000001,
kBehaviorTypeWalkingJump = 0x00000002,
kBehaviorTypeRunningJump = 0x00000004,
kBehaviorTypeAnyJump = kBehaviorTypeStandingJump | kBehaviorTypeWalkingJump | kBehaviorTypeRunningJump,
kBehaviorTypeRunningImpact = 0x00000008,
kBehaviorTypeGroundImpact = 0x00000010,
kBehaviorTypeAnyImpact = kBehaviorTypeRunningImpact | kBehaviorTypeGroundImpact,
kBehaviorTypeIdle = 0x00000020,
kBehaviorTypeWalk = 0x00000040,
kBehaviorTypeRun = 0x00000080,
kBehaviorTypeWalkBack = 0x00000100,
kBehaviorTypeTurnLeft = 0x00000200,
kBehaviorTypeTurnRight = 0x00000400,
kBehaviorTypeSidestepLeft = 0x00000800,
kBehaviorTypeSidestepRight = 0x00001000,
kBehaviorTypeFall = 0x00002000,
kBehaviorTypeMovingTurnLeft = 0x00004000,
kBehaviorTypeMovingTurnRight = 0x00008000,
kBehaviorTypeLinkIn = 0x00010000,
kBehaviorTypeLinkOut = 0x00020000,
kBehaviorTypeEmote = 0x00040000,
kBehaviorTypePushWalk = 0x00080000,
//kBehaviorTypePushIdle = 0x00100000,
kBehaviorTypeNeedsRecalcMask = kBehaviorTypeAnyJump | kBehaviorTypeRunningImpact | kBehaviorTypeWalk |
kBehaviorTypeRun | kBehaviorTypeWalkBack | kBehaviorTypeTurnLeft |
kBehaviorTypeTurnRight | kBehaviorTypeSidestepLeft |
kBehaviorTypeSidestepRight | kBehaviorTypePushWalk,
};
plHBehavior();
~plHBehavior();
void Init(plAGAnim *anim, hsBool loop, plAvBrainHuman *brain, plArmatureMod *body,
float fadeIn, float fadeOut, UInt8 index, UInt32 type = 0);
virtual hsBool PreCondition(double time, float elapsed) { return true; }
UInt32 GetType() const { return fType; }
protected:
virtual void IStart();
virtual void IStop();
plArmatureMod *fAvMod;
plAvBrainHuman *fHuBrain;
float fFadeIn; // speed at which the animation fades in, in blend units per second
float fFadeOut; // speed at which the animation fades out, in blend units per second
float fMaxBlend; // the maximum blend the animation should reach
UInt32 fType; // (see the behaviorType enum)
bool fStartMsgSent; // flags to prevent multiple start and stop messages from being sent
bool fStopMsgSent;
};
class Idle : public plHBehavior
{
virtual void IStart();
};
class Run : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class Walk : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class WalkBack : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class StepLeft : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class StepRight : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class StandingTurnLeft : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class StandingTurnRight : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class MovingTurn : public plHBehavior
{
public:
protected:
void IStart();
};
class MovingTurnLeft : public MovingTurn
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class MovingTurnRight : public MovingTurn
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class Jump : public plHBehavior
{
protected:
hsBool fReleased;
virtual void IStart();
virtual void IStop();
public:
Jump() : plHBehavior(), fReleased(true) {}
};
class StandingJump : public Jump
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class WalkingJump : public Jump
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class RunningJump : public Jump
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class GroundImpact : public plHBehavior
{
public:
GroundImpact();
virtual hsBool PreCondition(double time, float elapsed);
private:
virtual void IStop();
float fDuration;
};
class RunningImpact : public plHBehavior
{
public:
RunningImpact();
virtual hsBool PreCondition(double time, float elapsed);
private:
virtual void IStop();
float fDuration;
};
class Fall : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
virtual void Process(double time, float elapsed);
};
class Push : public plHBehavior
{
public:
virtual void Process(double time, float elapsed);
};
//class PushIdle : public Push
//{
//public:
// virtual hsBool PreCondition(double time, float elapsed);
//};
class PushWalk : public Push
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
bool PushSimpleMultiStage(plArmatureMod *avatar, const char *enterAnim, const char *idleAnim,
const char *exitAnim, bool netPropagate, bool autoExit, plAGAnim::BodyUsage bodyUsage,
plAvBrainGeneric::BrainType type = plAvBrainGeneric::kGeneric);
bool AvatarEmote(plArmatureMod *avatar, const char *emoteName);
#endif // PLAVBRAINHUMAN_INC
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVBRAINHUMAN_INC
#define PLAVBRAINHUMAN_INC
#define HI_RES_MOVEMENT
#include "plAvBrainGeneric.h"
#include "plAvBehaviors.h"
#include "plAGAnim.h"
#pragma warning(disable: 4284)
#include <deque>
#include "hsTemplates.h"
class plMatrixChannel;
class plMatrixMultiplyApplicator;
class plAGAnimInstance;
class plAvTask;
class plAvTaskMsg;
class plAvBrainHuman;
class plWalkingController;
class plArmatureUpdateMsg;
class plClimbMsg;
class plControlEventMsg;
class plAvBrainHuman : public plArmatureBrain
{
public:
plAvBrainHuman(bool isActor = false);
virtual ~plAvBrainHuman();
CLASSNAME_REGISTER( plAvBrainHuman );
GETINTERFACE_ANY( plAvBrainHuman, plArmatureBrain );
virtual hsBool Apply(double timeNow, hsScalar elapsed);
virtual void Activate(plArmatureModBase *avMod);
virtual void Deactivate();
virtual void Suspend();
virtual void Resume();
virtual void Spawn(double timeNow);
virtual hsBool LeaveAge();
bool IsActor() const {return fIsActor;}
void IsActor(bool isActor) {fIsActor = isActor;}
bool IsMovementZeroBlend();
void TurnToPoint(hsPoint3 point);
hsBool RunStandardBehaviors(double timeNow, float elapsed);
void SetStartedTurning(double when);
virtual bool IsMovingForward(); // we're either walking or running. doesn't account for sliding.
void ResetIdle();
void IdleOnly(bool instantOff = false);
bool IsBehaviorPlaying(int behavior); // returns whether the specified behavior is playing at all (see list of behaviors below)
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual hsBool MsgReceive(plMessage *msg);
virtual void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
// Hardwired Identifiers for all the canonical bones.
enum HumanBoneID {
Pelvis,
// left leg
LThigh, LCalf, LFoot, LFootPrint, LToe0,
// right leg
RThigh, RCalf, RFoot, RFootPrint, RToe0,
// spine and head, starting at base of spine
Spine, TrunkPrint, Spine1, Spine2, Neck, Head, Jaw, LMouthLower, RMouthLower,
LBrowInner, LBrowOuter, LCheek, LEye, LEyeLid01, LEyeLid02, LMouthCorner, LMouthUpper,
RBrowInner, RBrowOuter, RCheek, REye, REyeLid01, REyeLid02, RMouthCorner, RMouthUpper,
// Left Arm
LClavicle, LUpperArm, LForearm, LHand, LHandPrint, LMiddleFinger1, LMiddleFinger2, LMiddleFinger3,
LPinkyFinger1, LPinkyFinger2, LPinkyFinger3, LPointerFinger1, LPointerFinger2, LPointerFinger3,
LRingFinger1, LRingFinger2, LRingFinger3, LThumb1, LThumb2, LThumb3,
// Right Arm
RClavicle, RUpperArm, RForearm, RHand, RHandPrint, RMiddleFinger1, RMiddleFinger2, RMiddleFinger3,
RPinkyFinger1, RPinkyFinger2, RPinkyFinger3, RPointerFinger1, RPointerFinger2, RPointerFinger3,
RRingFinger1, RRingFinger2, RRingFinger3, RThumb1, RThumb2, RThumb3
};
enum TurnCurve
{
kTurnLinear,
kTurnExponential,
kTurnLogarithmic
};
enum // Indicies for the brains array of behaviors
{
kIdle,
kWalk,
kRun,
kWalkBack,
kStandingTurnLeft,
kStandingTurnRight,
kStepLeft,
kStepRight,
kFall,
kStandingJump,
kWalkingJump,
kRunningJump,
kGroundImpact,
kRunningImpact,
kMovingTurnLeft,
kMovingTurnRight,
kPushWalk,
//kPushIdle,
kHuBehaviorMax,
};
static void SetTimeToMaxTurn(float time, hsBool walk);
static float GetTimeToMaxTurn(hsBool walk);
static void SetMaxTurnSpeed(float radsPerSec, hsBool walk);
static float GetMaxTurnSpeed(hsBool walk);
static void SetTurnCurve(TurnCurve curve, hsBool walk);
static TurnCurve GetTurnCurve(hsBool walk);
static const hsScalar kControlledFlightThreshold;
static const hsScalar kAirTimeThreshold;
static const hsScalar kAirTimePanicThreshold;
plWalkingController* fCallbackAction;
protected:
plAGAnim *FindCustomAnim(const char *baseName);
virtual hsBool IHandleControlMsg(plControlEventMsg *ctrlMsg);
virtual hsBool IHandleClimbMsg(plClimbMsg *msg);
virtual hsBool IHandleTaskMsg(plAvTaskMsg *msg);
virtual hsBool IInitAnimations();
virtual void IInitBoneMap();
hsScalar IGetTurnStrength(double timeNow);
void IChatOn();
void IChatOff();
hsBool IValidateAnimations();
plAGModifier *fHandleAGMod; // the ag modifier that's attached to our top object
double fStartedTurning; // when did we start turning?
UInt32 fPreconditions;
bool fIsActor; // are we an actor with special privileges?
static float fWalkTimeToMaxTurn;
static float fRunTimeToMaxTurn;
static float fWalkMaxTurnSpeed;
static float fRunMaxTurnSpeed;
static TurnCurve fWalkTurnCurve;
static TurnCurve fRunTurnCurve;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
class plHBehavior : public plArmatureBehavior
{
friend class plAvBrainHuman;
friend class plAvBrainCritter;
public:
// ID flags for human behaviors. These are used by plBehaviorNotifyMsg
// to identify what type of behavior just triggered.
// This is an old way of doing things. I'd like to remove it, but a lot of
// python scripts use it as is.
enum BehaviorType
{
kBehaviorTypeStandingJump = 0x00000001,
kBehaviorTypeWalkingJump = 0x00000002,
kBehaviorTypeRunningJump = 0x00000004,
kBehaviorTypeAnyJump = kBehaviorTypeStandingJump | kBehaviorTypeWalkingJump | kBehaviorTypeRunningJump,
kBehaviorTypeRunningImpact = 0x00000008,
kBehaviorTypeGroundImpact = 0x00000010,
kBehaviorTypeAnyImpact = kBehaviorTypeRunningImpact | kBehaviorTypeGroundImpact,
kBehaviorTypeIdle = 0x00000020,
kBehaviorTypeWalk = 0x00000040,
kBehaviorTypeRun = 0x00000080,
kBehaviorTypeWalkBack = 0x00000100,
kBehaviorTypeTurnLeft = 0x00000200,
kBehaviorTypeTurnRight = 0x00000400,
kBehaviorTypeSidestepLeft = 0x00000800,
kBehaviorTypeSidestepRight = 0x00001000,
kBehaviorTypeFall = 0x00002000,
kBehaviorTypeMovingTurnLeft = 0x00004000,
kBehaviorTypeMovingTurnRight = 0x00008000,
kBehaviorTypeLinkIn = 0x00010000,
kBehaviorTypeLinkOut = 0x00020000,
kBehaviorTypeEmote = 0x00040000,
kBehaviorTypePushWalk = 0x00080000,
//kBehaviorTypePushIdle = 0x00100000,
kBehaviorTypeNeedsRecalcMask = kBehaviorTypeAnyJump | kBehaviorTypeRunningImpact | kBehaviorTypeWalk |
kBehaviorTypeRun | kBehaviorTypeWalkBack | kBehaviorTypeTurnLeft |
kBehaviorTypeTurnRight | kBehaviorTypeSidestepLeft |
kBehaviorTypeSidestepRight | kBehaviorTypePushWalk,
};
plHBehavior();
~plHBehavior();
void Init(plAGAnim *anim, hsBool loop, plAvBrainHuman *brain, plArmatureMod *body,
float fadeIn, float fadeOut, UInt8 index, UInt32 type = 0);
virtual hsBool PreCondition(double time, float elapsed) { return true; }
UInt32 GetType() const { return fType; }
protected:
virtual void IStart();
virtual void IStop();
plArmatureMod *fAvMod;
plAvBrainHuman *fHuBrain;
float fFadeIn; // speed at which the animation fades in, in blend units per second
float fFadeOut; // speed at which the animation fades out, in blend units per second
float fMaxBlend; // the maximum blend the animation should reach
UInt32 fType; // (see the behaviorType enum)
bool fStartMsgSent; // flags to prevent multiple start and stop messages from being sent
bool fStopMsgSent;
};
class Idle : public plHBehavior
{
virtual void IStart();
};
class Run : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class Walk : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class WalkBack : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class StepLeft : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class StepRight : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class StandingTurnLeft : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class StandingTurnRight : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class MovingTurn : public plHBehavior
{
public:
protected:
void IStart();
};
class MovingTurnLeft : public MovingTurn
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class MovingTurnRight : public MovingTurn
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class Jump : public plHBehavior
{
protected:
hsBool fReleased;
virtual void IStart();
virtual void IStop();
public:
Jump() : plHBehavior(), fReleased(true) {}
};
class StandingJump : public Jump
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class WalkingJump : public Jump
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class RunningJump : public Jump
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
class GroundImpact : public plHBehavior
{
public:
GroundImpact();
virtual hsBool PreCondition(double time, float elapsed);
private:
virtual void IStop();
float fDuration;
};
class RunningImpact : public plHBehavior
{
public:
RunningImpact();
virtual hsBool PreCondition(double time, float elapsed);
private:
virtual void IStop();
float fDuration;
};
class Fall : public plHBehavior
{
public:
virtual hsBool PreCondition(double time, float elapsed);
virtual void Process(double time, float elapsed);
};
class Push : public plHBehavior
{
public:
virtual void Process(double time, float elapsed);
};
//class PushIdle : public Push
//{
//public:
// virtual hsBool PreCondition(double time, float elapsed);
//};
class PushWalk : public Push
{
public:
virtual hsBool PreCondition(double time, float elapsed);
};
bool PushSimpleMultiStage(plArmatureMod *avatar, const char *enterAnim, const char *idleAnim,
const char *exitAnim, bool netPropagate, bool autoExit, plAGAnim::BodyUsage bodyUsage,
plAvBrainGeneric::BrainType type = plAvBrainGeneric::kGeneric);
bool AvatarEmote(plArmatureMod *avatar, const char *emoteName);
#endif // PLAVBRAINHUMAN_INC

View File

@ -1,34 +1,34 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// Removed
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// Removed

View File

@ -1,26 +1,26 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// Removed

View File

@ -1,176 +1,176 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvBrainRideAnimatedPhysical.h"
#include "plArmatureMod.h"
#include "plAvBrainHuman.h"
#include "plAvBrain.h"
#include "plAvCallbackAction.h"
#include "plMessage/plRideAnimatedPhysMsg.h"
void plAvBrainRideAnimatedPhysical::Activate(plArmatureModBase *avMod)
{
plArmatureBrain::Activate(avMod);
IInitAnimations();
if (!fCallbackAction)
{
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();
}
}
plAvBrainRideAnimatedPhysical::~plAvBrainRideAnimatedPhysical()
{
delete fCallbackAction;
fCallbackAction=nil;
}
void plAvBrainRideAnimatedPhysical::Deactivate()
{
plArmatureBrain::Deactivate();
}
hsBool plAvBrainRideAnimatedPhysical::MsgReceive(plMessage *msg)
{
plRideAnimatedPhysMsg *ride = plRideAnimatedPhysMsg::ConvertNoRef(msg);
if(ride)
{
if(!ride->Entering())
{
/*this->fArmature->PopBrain();
delete this;
return true;
*/
fMode=kAbort;
}
}
return plArmatureBrain::MsgReceive(msg);
}
hsBool plAvBrainRideAnimatedPhysical::IInitAnimations()
{
hsBool result = false;
plAGAnim *idle = fAvMod->FindCustomAnim("Idle");
plAGAnim *walk = fAvMod->FindCustomAnim("Walk");
plAGAnim *run = fAvMod->FindCustomAnim("Run");
plAGAnim *walkBack = fAvMod->FindCustomAnim("WalkBack");
plAGAnim *stepLeft = fAvMod->FindCustomAnim("StepLeft");
plAGAnim *stepRight = fAvMod->FindCustomAnim("StepRight");
plAGAnim *standingLeft = fAvMod->FindCustomAnim("TurnLeft");
plAGAnim *standingRight = fAvMod->FindCustomAnim("TurnRight");
plAGAnim *fall = fAvMod->FindCustomAnim("Fall");
plAGAnim *standJump = fAvMod->FindCustomAnim("StandingJump");
plAGAnim *walkJump = fAvMod->FindCustomAnim("WalkingJump");
plAGAnim *runJump = fAvMod->FindCustomAnim("RunningJump");
plAGAnim *groundImpact = fAvMod->FindCustomAnim("GroundImpact");
plAGAnim *runningImpact = fAvMod->FindCustomAnim("RunningImpact");
plAGAnim *movingLeft = nil; // fAvMod->FindCustomAnim("LeanLeft");
plAGAnim *movingRight = nil; // fAvMod->FindCustomAnim("LeanRight");
plAGAnim *pushWalk = fAvMod->FindCustomAnim("BallPushWalk");
//plAGAnim *pushIdle = fAvMod->FindCustomAnim("BallPushIdle");
const float kDefaultFade = 3.0; // most animations fade in and out in 1/4 of a second.
if (idle && walk && run && walkBack && standingLeft && standingRight && stepLeft && stepRight)
{
plHBehavior *behavior;
fBehaviors.SetCountAndZero(kHuBehaviorMax);
fBehaviors[kIdle] = behavior = TRACKED_NEW Idle;
behavior->Init(idle, true, this, fAvMod, kDefaultFade, kDefaultFade, kIdle, plHBehavior::kBehaviorTypeIdle);
behavior->SetStrength(1.f, 0.f);
fBehaviors[kWalk] = behavior = TRACKED_NEW Walk;
behavior->Init(walk, true, this, fAvMod, kDefaultFade, 5.f, kWalk, plHBehavior::kBehaviorTypeWalk);
fBehaviors[kRun] = behavior = TRACKED_NEW Run;
behavior->Init(run, true, this, fAvMod, kDefaultFade, 2.0, kRun, plHBehavior::kBehaviorTypeRun);
fBehaviors[kWalkBack] = behavior = TRACKED_NEW WalkBack;
behavior->Init(walkBack, true, this, fAvMod, kDefaultFade, kDefaultFade, kWalkBack, plHBehavior::kBehaviorTypeWalkBack);
fBehaviors[kStandingTurnLeft] = behavior = TRACKED_NEW StandingTurnLeft;
behavior->Init(standingLeft, true, this, fAvMod, 3.0f, 6.0f, kStandingTurnLeft, plHBehavior::kBehaviorTypeTurnLeft);
fBehaviors[kStandingTurnRight] = behavior = TRACKED_NEW StandingTurnRight;
behavior->Init(standingRight, true, this, fAvMod, 3.0f, 6.0f, kStandingTurnRight, plHBehavior::kBehaviorTypeTurnRight);
fBehaviors[kStepLeft] = behavior = TRACKED_NEW StepLeft;
behavior->Init(stepLeft, true, this, fAvMod, kDefaultFade, kDefaultFade, kStepLeft, plHBehavior::kBehaviorTypeSidestepLeft);
fBehaviors[kStepRight] = behavior = TRACKED_NEW StepRight;
behavior->Init(stepRight, true, this, fAvMod, kDefaultFade, kDefaultFade, kStepRight, plHBehavior::kBehaviorTypeSidestepRight);
// Warning: Changing the blend times of the jump animations will affect the path you take, because until we're fully blended,
// we won't be using the full motion defined in the animation. This isn't an issue for standing jump, but you need to be
// aware of it for the walk/run jumps.
fBehaviors[kFall] = behavior = TRACKED_NEW Fall;
behavior->Init(fall, true, this, fAvMod, 1.0f, 10, kFall, plHBehavior::kBehaviorTypeFall);
fBehaviors[kStandingJump] = behavior = TRACKED_NEW StandingJump;
behavior->Init(standJump, false, this, fAvMod, kDefaultFade, kDefaultFade, kStandingJump, plHBehavior::kBehaviorTypeStandingJump);
fBehaviors[kWalkingJump] = behavior = TRACKED_NEW WalkingJump;
behavior->Init(walkJump, false, this, fAvMod, 10, 3.0, kWalkingJump, plHBehavior::kBehaviorTypeWalkingJump);
fBehaviors[kRunningJump] = behavior = TRACKED_NEW RunningJump;
behavior->Init(runJump, false, this, fAvMod, 10, 2.0, kRunningJump, plHBehavior::kBehaviorTypeRunningJump);
fBehaviors[kGroundImpact] = behavior = TRACKED_NEW GroundImpact;
behavior->Init(groundImpact, false, this, fAvMod, 6.0f, kDefaultFade, kGroundImpact, plHBehavior::kBehaviorTypeGroundImpact);
fBehaviors[kRunningImpact] = behavior = TRACKED_NEW RunningImpact;
behavior->Init(runningImpact, false, this, fAvMod, 6.0f, kDefaultFade, kRunningImpact, plHBehavior::kBehaviorTypeRunningImpact);
fBehaviors[kMovingTurnLeft] = behavior = TRACKED_NEW MovingTurnLeft;
behavior->Init(movingLeft, true, this, fAvMod, kDefaultFade, kDefaultFade, kMovingTurnLeft, plHBehavior::kBehaviorTypeMovingTurnLeft);
fBehaviors[kMovingTurnRight] = behavior = TRACKED_NEW MovingTurnRight;
behavior->Init(movingRight, true, this, fAvMod, kDefaultFade, kDefaultFade, kMovingTurnRight, plHBehavior::kBehaviorTypeMovingTurnRight);
fBehaviors[kPushWalk] = behavior = TRACKED_NEW PushWalk;
behavior->Init(pushWalk, true, this, fAvMod, kDefaultFade, kDefaultFade, kPushWalk, plHBehavior::kBehaviorTypePushWalk);
//fBehaviors[kPushIdle] = behavior = TRACKED_NEW PushIdle;
//behavior->Init(pushIdle, true, this, fAvMod, kDefaultFade, kDefaultFade, kPushIdle, plHBehavior::kBehaviorTypePushIdle);
result = true;
}
return result;
}
hsBool plAvBrainRideAnimatedPhysical::LeaveAge()
{
return plArmatureBrain::LeaveAge();
}
hsBool plAvBrainRideAnimatedPhysical::Apply(double timeNow, hsScalar elapsed)
{
if(this->fMode==kAbort) return false;
else return plAvBrainHuman::Apply(timeNow, elapsed);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvBrainRideAnimatedPhysical.h"
#include "plArmatureMod.h"
#include "plAvBrainHuman.h"
#include "plAvBrain.h"
#include "plAvCallbackAction.h"
#include "plMessage/plRideAnimatedPhysMsg.h"
void plAvBrainRideAnimatedPhysical::Activate(plArmatureModBase *avMod)
{
plArmatureBrain::Activate(avMod);
IInitAnimations();
if (!fCallbackAction)
{
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();
}
}
plAvBrainRideAnimatedPhysical::~plAvBrainRideAnimatedPhysical()
{
delete fCallbackAction;
fCallbackAction=nil;
}
void plAvBrainRideAnimatedPhysical::Deactivate()
{
plArmatureBrain::Deactivate();
}
hsBool plAvBrainRideAnimatedPhysical::MsgReceive(plMessage *msg)
{
plRideAnimatedPhysMsg *ride = plRideAnimatedPhysMsg::ConvertNoRef(msg);
if(ride)
{
if(!ride->Entering())
{
/*this->fArmature->PopBrain();
delete this;
return true;
*/
fMode=kAbort;
}
}
return plArmatureBrain::MsgReceive(msg);
}
hsBool plAvBrainRideAnimatedPhysical::IInitAnimations()
{
hsBool result = false;
plAGAnim *idle = fAvMod->FindCustomAnim("Idle");
plAGAnim *walk = fAvMod->FindCustomAnim("Walk");
plAGAnim *run = fAvMod->FindCustomAnim("Run");
plAGAnim *walkBack = fAvMod->FindCustomAnim("WalkBack");
plAGAnim *stepLeft = fAvMod->FindCustomAnim("StepLeft");
plAGAnim *stepRight = fAvMod->FindCustomAnim("StepRight");
plAGAnim *standingLeft = fAvMod->FindCustomAnim("TurnLeft");
plAGAnim *standingRight = fAvMod->FindCustomAnim("TurnRight");
plAGAnim *fall = fAvMod->FindCustomAnim("Fall");
plAGAnim *standJump = fAvMod->FindCustomAnim("StandingJump");
plAGAnim *walkJump = fAvMod->FindCustomAnim("WalkingJump");
plAGAnim *runJump = fAvMod->FindCustomAnim("RunningJump");
plAGAnim *groundImpact = fAvMod->FindCustomAnim("GroundImpact");
plAGAnim *runningImpact = fAvMod->FindCustomAnim("RunningImpact");
plAGAnim *movingLeft = nil; // fAvMod->FindCustomAnim("LeanLeft");
plAGAnim *movingRight = nil; // fAvMod->FindCustomAnim("LeanRight");
plAGAnim *pushWalk = fAvMod->FindCustomAnim("BallPushWalk");
//plAGAnim *pushIdle = fAvMod->FindCustomAnim("BallPushIdle");
const float kDefaultFade = 3.0; // most animations fade in and out in 1/4 of a second.
if (idle && walk && run && walkBack && standingLeft && standingRight && stepLeft && stepRight)
{
plHBehavior *behavior;
fBehaviors.SetCountAndZero(kHuBehaviorMax);
fBehaviors[kIdle] = behavior = TRACKED_NEW Idle;
behavior->Init(idle, true, this, fAvMod, kDefaultFade, kDefaultFade, kIdle, plHBehavior::kBehaviorTypeIdle);
behavior->SetStrength(1.f, 0.f);
fBehaviors[kWalk] = behavior = TRACKED_NEW Walk;
behavior->Init(walk, true, this, fAvMod, kDefaultFade, 5.f, kWalk, plHBehavior::kBehaviorTypeWalk);
fBehaviors[kRun] = behavior = TRACKED_NEW Run;
behavior->Init(run, true, this, fAvMod, kDefaultFade, 2.0, kRun, plHBehavior::kBehaviorTypeRun);
fBehaviors[kWalkBack] = behavior = TRACKED_NEW WalkBack;
behavior->Init(walkBack, true, this, fAvMod, kDefaultFade, kDefaultFade, kWalkBack, plHBehavior::kBehaviorTypeWalkBack);
fBehaviors[kStandingTurnLeft] = behavior = TRACKED_NEW StandingTurnLeft;
behavior->Init(standingLeft, true, this, fAvMod, 3.0f, 6.0f, kStandingTurnLeft, plHBehavior::kBehaviorTypeTurnLeft);
fBehaviors[kStandingTurnRight] = behavior = TRACKED_NEW StandingTurnRight;
behavior->Init(standingRight, true, this, fAvMod, 3.0f, 6.0f, kStandingTurnRight, plHBehavior::kBehaviorTypeTurnRight);
fBehaviors[kStepLeft] = behavior = TRACKED_NEW StepLeft;
behavior->Init(stepLeft, true, this, fAvMod, kDefaultFade, kDefaultFade, kStepLeft, plHBehavior::kBehaviorTypeSidestepLeft);
fBehaviors[kStepRight] = behavior = TRACKED_NEW StepRight;
behavior->Init(stepRight, true, this, fAvMod, kDefaultFade, kDefaultFade, kStepRight, plHBehavior::kBehaviorTypeSidestepRight);
// Warning: Changing the blend times of the jump animations will affect the path you take, because until we're fully blended,
// we won't be using the full motion defined in the animation. This isn't an issue for standing jump, but you need to be
// aware of it for the walk/run jumps.
fBehaviors[kFall] = behavior = TRACKED_NEW Fall;
behavior->Init(fall, true, this, fAvMod, 1.0f, 10, kFall, plHBehavior::kBehaviorTypeFall);
fBehaviors[kStandingJump] = behavior = TRACKED_NEW StandingJump;
behavior->Init(standJump, false, this, fAvMod, kDefaultFade, kDefaultFade, kStandingJump, plHBehavior::kBehaviorTypeStandingJump);
fBehaviors[kWalkingJump] = behavior = TRACKED_NEW WalkingJump;
behavior->Init(walkJump, false, this, fAvMod, 10, 3.0, kWalkingJump, plHBehavior::kBehaviorTypeWalkingJump);
fBehaviors[kRunningJump] = behavior = TRACKED_NEW RunningJump;
behavior->Init(runJump, false, this, fAvMod, 10, 2.0, kRunningJump, plHBehavior::kBehaviorTypeRunningJump);
fBehaviors[kGroundImpact] = behavior = TRACKED_NEW GroundImpact;
behavior->Init(groundImpact, false, this, fAvMod, 6.0f, kDefaultFade, kGroundImpact, plHBehavior::kBehaviorTypeGroundImpact);
fBehaviors[kRunningImpact] = behavior = TRACKED_NEW RunningImpact;
behavior->Init(runningImpact, false, this, fAvMod, 6.0f, kDefaultFade, kRunningImpact, plHBehavior::kBehaviorTypeRunningImpact);
fBehaviors[kMovingTurnLeft] = behavior = TRACKED_NEW MovingTurnLeft;
behavior->Init(movingLeft, true, this, fAvMod, kDefaultFade, kDefaultFade, kMovingTurnLeft, plHBehavior::kBehaviorTypeMovingTurnLeft);
fBehaviors[kMovingTurnRight] = behavior = TRACKED_NEW MovingTurnRight;
behavior->Init(movingRight, true, this, fAvMod, kDefaultFade, kDefaultFade, kMovingTurnRight, plHBehavior::kBehaviorTypeMovingTurnRight);
fBehaviors[kPushWalk] = behavior = TRACKED_NEW PushWalk;
behavior->Init(pushWalk, true, this, fAvMod, kDefaultFade, kDefaultFade, kPushWalk, plHBehavior::kBehaviorTypePushWalk);
//fBehaviors[kPushIdle] = behavior = TRACKED_NEW PushIdle;
//behavior->Init(pushIdle, true, this, fAvMod, kDefaultFade, kDefaultFade, kPushIdle, plHBehavior::kBehaviorTypePushIdle);
result = true;
}
return result;
}
hsBool plAvBrainRideAnimatedPhysical::LeaveAge()
{
return plArmatureBrain::LeaveAge();
}
hsBool plAvBrainRideAnimatedPhysical::Apply(double timeNow, hsScalar elapsed)
{
if(this->fMode==kAbort) return false;
else return plAvBrainHuman::Apply(timeNow, elapsed);
}

View File

@ -1,49 +1,49 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvBrainHuman.h"
class plRidingAnimatedPhysicalController;
class plAvBrainRideAnimatedPhysical : public plAvBrainHuman
{
public:
enum mode {
kWalking,
kAbort
};
CLASSNAME_REGISTER( plAvBrainRideAnimatedPhysical );
GETINTERFACE_ANY( plAvBrainRideAnimatedPhysical, plArmatureBrain );
plAvBrainRideAnimatedPhysical() : plAvBrainHuman(false),fMode(kWalking){};
~plAvBrainRideAnimatedPhysical();
virtual void Activate(plArmatureModBase *avMod);
virtual void Deactivate();
virtual hsBool MsgReceive(plMessage *msg);
virtual hsBool LeaveAge();
virtual hsBool Apply(double timeNow, hsScalar elapsed);
protected:
hsBool IInitAnimations();
mode fMode;
};
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvBrainHuman.h"
class plRidingAnimatedPhysicalController;
class plAvBrainRideAnimatedPhysical : public plAvBrainHuman
{
public:
enum mode {
kWalking,
kAbort
};
CLASSNAME_REGISTER( plAvBrainRideAnimatedPhysical );
GETINTERFACE_ANY( plAvBrainRideAnimatedPhysical, plArmatureBrain );
plAvBrainRideAnimatedPhysical() : plAvBrainHuman(false),fMode(kWalking){};
~plAvBrainRideAnimatedPhysical();
virtual void Activate(plArmatureModBase *avMod);
virtual void Deactivate();
virtual hsBool MsgReceive(plMessage *msg);
virtual hsBool LeaveAge();
virtual hsBool Apply(double timeNow, hsScalar elapsed);
protected:
hsBool IInitAnimations();
mode fMode;
};

View File

@ -1,131 +1,131 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//class plAvBrainStaticNPC : public plAvBrain
//{
//
//};
//
///** \class plAvBrain
// Virtual base class for the modular avatar & creature brains.
// A brain is a modular object which can be installed into a plArmatureMod
// to drive it around in the scene. Some brains are for creature ai;
// others intepret user input. The most interesting brain for reference is
// probably plAvBrainHuman, which implements the control system for the
// user's avatar.
// /sa plAvBrainHuman, plArmatureMod
//*/
//class plAvBrainStaticNPC : public plAvBrainStaticNPC
//{
//public:
// /** Default constructor - constructs the brain but does not attach it.
// Brains are always constructed before being Pushed onto the armature
// they seek to control. */
// plAvBrain();
//
// /** Destructor. Automatically called on a brain when it is popped from the armature. */
// virtual ~plAvBrain();
//
// // BRAIN PROTOCOL
// /** This brain has just been freshly pushed onto an armature and is now
// in primary control. Note that brains beneath it on the stack may
// still have effect on the armature; any messages which the top
// brain doesn't handle will propagate down to the next brain in line.
// */
// virtual hsBool Activate(plArmatureMod *avMod);
//
// /** Has the brain resolved all its load-time dependencies? This is a mechanism
// to allow newly loading creatures to reach a known state before they
// are asked to load secondary state or to interact with the environment.
// */
// virtual hsBool IsReady();
//
// /** This brain has just been removed from its armature and is about to be destructed. */
// virtual hsBool Deactivate();
//
// /** This is the top brain and it's time for it to evaluate. Called during eval
// time for the armature modifier. Only the topmost brain gets an apply
// call; others must do any necessary background work during MsgReceive. */
// virtual hsBool Apply(double timeNow, hsScalar elapsed);
//
// /** Another brain has been pushed atop this brain. Drop into the background.
// We'll still receive any messages that the upper brain doesn't eat. */
// virtual hsBool Suspend();
//
// /** We were suspended, but now we're on top of the brain stack again. */
// virtual hsBool Resume();
//
// // \name Spawning \{
// /** Do any necessary custom action upon spawning afresh in a new age.
// For the human brain, this simply consists of noting that we have
// spawned and we can stop trying to do so. */
// virtual void Spawn(double timeNow) {};
//
// /** Custom behavior for entering an age. Binding the camera, audio source, etc. */
// virtual void EnterAge(hsBool reSpawn) {};
//
// /** Custom behavior for leaving an age. Free any attachments to camera, audio, etc. */
// virtual void LeaveAge() {};
//
// // TASKS
// // tasks are operations that must be done in sequence.
// /** Push a new task onto the end of our FIFO task queue. Will not
// run until all the tasks ahead of it have run.
// \sa plAvTask
// */
// virtual void QueueTask(plAvTask *task);
//
//
// virtual void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
//
//
// // PLASMOTICS
// CLASSNAME_REGISTER( plAvBrain );
// GETINTERFACE_ANY( plAvBrain, plCreatable );
//
// virtual void Write(hsStream *stream, hsResMgr *mgr);
// virtual void Read(hsStream *stream, hsResMgr *mgr);
//
// virtual void SaveAux(hsStream *stream, hsResMgr *mgr);
// virtual void LoadAux(hsStream *stream, hsResMgr *mgr, double time);
//
// virtual hsBool MsgReceive(plMessage *msg);
//
//
//protected:
// plArmatureMod *fAvMod; // the avatar we're controlling
//
// // TASKS
// // -- variables
// typedef std::deque<plAvTask *> plAvTaskQueue;
// plAvTaskQueue fTaskQueue; // FIFO queue of tasks we're working on
// plAvTask *fCurTask; // the task we're working on right now
// // -- methods
// virtual hsBool IHandleTaskMsg(plAvTaskMsg *msg); // respond to a task scheduling message
// void IProcessTasks(double time, hsScalar elapsed); // process current task and start new one if necessary
//
// hsBool fSuspended;
//};
//
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//class plAvBrainStaticNPC : public plAvBrain
//{
//
//};
//
///** \class plAvBrain
// Virtual base class for the modular avatar & creature brains.
// A brain is a modular object which can be installed into a plArmatureMod
// to drive it around in the scene. Some brains are for creature ai;
// others intepret user input. The most interesting brain for reference is
// probably plAvBrainHuman, which implements the control system for the
// user's avatar.
// /sa plAvBrainHuman, plArmatureMod
//*/
//class plAvBrainStaticNPC : public plAvBrainStaticNPC
//{
//public:
// /** Default constructor - constructs the brain but does not attach it.
// Brains are always constructed before being Pushed onto the armature
// they seek to control. */
// plAvBrain();
//
// /** Destructor. Automatically called on a brain when it is popped from the armature. */
// virtual ~plAvBrain();
//
// // BRAIN PROTOCOL
// /** This brain has just been freshly pushed onto an armature and is now
// in primary control. Note that brains beneath it on the stack may
// still have effect on the armature; any messages which the top
// brain doesn't handle will propagate down to the next brain in line.
// */
// virtual hsBool Activate(plArmatureMod *avMod);
//
// /** Has the brain resolved all its load-time dependencies? This is a mechanism
// to allow newly loading creatures to reach a known state before they
// are asked to load secondary state or to interact with the environment.
// */
// virtual hsBool IsReady();
//
// /** This brain has just been removed from its armature and is about to be destructed. */
// virtual hsBool Deactivate();
//
// /** This is the top brain and it's time for it to evaluate. Called during eval
// time for the armature modifier. Only the topmost brain gets an apply
// call; others must do any necessary background work during MsgReceive. */
// virtual hsBool Apply(double timeNow, hsScalar elapsed);
//
// /** Another brain has been pushed atop this brain. Drop into the background.
// We'll still receive any messages that the upper brain doesn't eat. */
// virtual hsBool Suspend();
//
// /** We were suspended, but now we're on top of the brain stack again. */
// virtual hsBool Resume();
//
// // \name Spawning \{
// /** Do any necessary custom action upon spawning afresh in a new age.
// For the human brain, this simply consists of noting that we have
// spawned and we can stop trying to do so. */
// virtual void Spawn(double timeNow) {};
//
// /** Custom behavior for entering an age. Binding the camera, audio source, etc. */
// virtual void EnterAge(hsBool reSpawn) {};
//
// /** Custom behavior for leaving an age. Free any attachments to camera, audio, etc. */
// virtual void LeaveAge() {};
//
// // TASKS
// // tasks are operations that must be done in sequence.
// /** Push a new task onto the end of our FIFO task queue. Will not
// run until all the tasks ahead of it have run.
// \sa plAvTask
// */
// virtual void QueueTask(plAvTask *task);
//
//
// virtual void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
//
//
// // PLASMOTICS
// CLASSNAME_REGISTER( plAvBrain );
// GETINTERFACE_ANY( plAvBrain, plCreatable );
//
// virtual void Write(hsStream *stream, hsResMgr *mgr);
// virtual void Read(hsStream *stream, hsResMgr *mgr);
//
// virtual void SaveAux(hsStream *stream, hsResMgr *mgr);
// virtual void LoadAux(hsStream *stream, hsResMgr *mgr, double time);
//
// virtual hsBool MsgReceive(plMessage *msg);
//
//
//protected:
// plArmatureMod *fAvMod; // the avatar we're controlling
//
// // TASKS
// // -- variables
// typedef std::deque<plAvTask *> plAvTaskQueue;
// plAvTaskQueue fTaskQueue; // FIFO queue of tasks we're working on
// plAvTask *fCurTask; // the task we're working on right now
// // -- methods
// virtual hsBool IHandleTaskMsg(plAvTaskMsg *msg); // respond to a task scheduling message
// void IProcessTasks(double time, hsScalar elapsed); // process current task and start new one if necessary
//
// hsBool fSuspended;
//};
//

File diff suppressed because it is too large Load Diff

View File

@ -1,108 +1,108 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_AV_BRAIN_SWIM_H
#define PL_AV_BRAIN_SWIM_H
#include "plAvBrain.h"
#include "hsTemplates.h"
#include "pnKeyedObject/plKey.h"
class plArmatureMod;
class plAntiGravAction;
class plControlEventMsg;
class plLOSRequestMsg;
class plSwimRegionInterface;
class plSwimmingController;
class plAvBrainSwim : public plArmatureBrain
{
public:
plAvBrainSwim();
virtual ~plAvBrainSwim();
CLASSNAME_REGISTER( plAvBrainSwim );
GETINTERFACE_ANY( plAvBrainSwim, plArmatureBrain );
virtual void Activate(plArmatureModBase *avMod);
hsBool Apply(double time, hsScalar elapsed);
virtual void Deactivate();
virtual void Suspend();
virtual void Resume();
virtual void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
hsBool MsgReceive(plMessage *msg);
bool IsWalking();
bool IsWading();
bool IsSwimming();
hsScalar GetSurfaceDistance() { return fSurfaceDistance; }
plSwimmingController *fCallbackAction;
static const hsScalar kMinSwimDepth;
protected:
void IStartWading();
void IStartSwimming(bool is2D);
hsBool IProcessSwimming2D(double time, float elapsed);
hsBool IProcessSwimming3D(double time, float elapsed);
hsBool IProcessWading(double time, float elapsed);
hsBool IProcessClimbingOut(double time, float elapsed);
hsBool IProcessBehaviors(double time, float elapsed);
virtual hsBool IInitAnimations();
bool IAttachAction();
bool IDetachAction();
void IProbeSurface();
hsBool IHandleControlMsg(plControlEventMsg* msg);
float IGetTargetZ();
float fSurfaceDistance;
plLOSRequestMsg *fSurfaceProbeMsg;
plSwimRegionInterface *fCurrentRegion;
enum Mode {
kWading,
kSwimming2D,
kSwimming3D,
kClimbingOut,
kAbort,
kWalking,
} fMode;
enum
{
kTreadWater,
kSwimForward,
kSwimForwardFast,
kSwimBack,
kSwimLeft,
kSwimRight,
kSwimTurnLeft,
kSwimTurnRight,
kTreadTurnLeft,
kTreadTurnRight,
kSwimBehaviorMax,
};
};
#endif PL_AV_BRAIN_SWIM_H
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PL_AV_BRAIN_SWIM_H
#define PL_AV_BRAIN_SWIM_H
#include "plAvBrain.h"
#include "hsTemplates.h"
#include "pnKeyedObject/plKey.h"
class plArmatureMod;
class plAntiGravAction;
class plControlEventMsg;
class plLOSRequestMsg;
class plSwimRegionInterface;
class plSwimmingController;
class plAvBrainSwim : public plArmatureBrain
{
public:
plAvBrainSwim();
virtual ~plAvBrainSwim();
CLASSNAME_REGISTER( plAvBrainSwim );
GETINTERFACE_ANY( plAvBrainSwim, plArmatureBrain );
virtual void Activate(plArmatureModBase *avMod);
hsBool Apply(double time, hsScalar elapsed);
virtual void Deactivate();
virtual void Suspend();
virtual void Resume();
virtual void DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt);
hsBool MsgReceive(plMessage *msg);
bool IsWalking();
bool IsWading();
bool IsSwimming();
hsScalar GetSurfaceDistance() { return fSurfaceDistance; }
plSwimmingController *fCallbackAction;
static const hsScalar kMinSwimDepth;
protected:
void IStartWading();
void IStartSwimming(bool is2D);
hsBool IProcessSwimming2D(double time, float elapsed);
hsBool IProcessSwimming3D(double time, float elapsed);
hsBool IProcessWading(double time, float elapsed);
hsBool IProcessClimbingOut(double time, float elapsed);
hsBool IProcessBehaviors(double time, float elapsed);
virtual hsBool IInitAnimations();
bool IAttachAction();
bool IDetachAction();
void IProbeSurface();
hsBool IHandleControlMsg(plControlEventMsg* msg);
float IGetTargetZ();
float fSurfaceDistance;
plLOSRequestMsg *fSurfaceProbeMsg;
plSwimRegionInterface *fCurrentRegion;
enum Mode {
kWading,
kSwimming2D,
kSwimming3D,
kClimbingOut,
kAbort,
kWalking,
} fMode;
enum
{
kTreadWater,
kSwimForward,
kSwimForwardFast,
kSwimBack,
kSwimLeft,
kSwimRight,
kSwimTurnLeft,
kSwimTurnRight,
kTreadTurnLeft,
kTreadTurnRight,
kSwimBehaviorMax,
};
};
#endif PL_AV_BRAIN_SWIM_H

View File

@ -1,26 +1,26 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// Obsolete

View File

@ -1,26 +1,26 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// Obsolete

File diff suppressed because it is too large Load Diff

View File

@ -1,201 +1,201 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#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
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#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

@ -1,79 +1,79 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvDefs_h
#define plAvDefs_h
/** This is where we keep definitions that are used by different avatar classes.
Typically, these don't change very much, so there's a compile-time savings
if we don't keep them with class headers, which tend to be more volatile.
*/
#include "hsGeometry3.h" // for the hsVector3, below
// animation alignment types (used by "calcanimalignment")
// when starting oneshots, we need to first get your handle into a position to play the oneshot properly
// there are different approaches to calculating this aligment
/** \enum Alignment
There are several different ways to get into position to play a detailed
interaction animation. Interactions always have an associated "seek point"
indicating an alignment point, but there are several different types of
alignment. */
enum plAvAlignment {
kAlignHandle, /// align our handle with the seek point
kAlignHandleAnimEnd, /** align our handle at the seek point "minus" the animation
i.e. after seeking and then playing the animation, our
handle should wind up aligned with the seek point. */
kAlignWorld, /** align our handle with the world origin; the animation
is defined in global space */
kAlignBone, /// align a specific bone with the seek point
kAlignBoneAnimEnd, /** align our handle so that the bone is at the seek point
after the animation has finished playing. */
kAlignEnsure16 = 0xffff
};
const hsVector3 kAvatarUp(0,0,1);
const hsVector3 kAvatarForward(0,-1,0);
const hsVector3 kAvatarRight(-1,0,0);
/** \enum PinType
Tells us what category of animation this channel affects.
Primarly used to determine if two channels are competing,
which you can't tell strictly from the type of data the
channel handles. */
enum plAGPinType
{
kAGPinUnknown, // this applicator hasn't decided its pin type
kAGPinTransform, // this applicator munches the entire transform
kNumPinTypes
};
#define kAGMaxBlendPriority 0x0fffffff
#define kAGMinBlendPriority 0x00000000
#define kAGMedBlendPriority 0x0000ffff
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvDefs_h
#define plAvDefs_h
/** This is where we keep definitions that are used by different avatar classes.
Typically, these don't change very much, so there's a compile-time savings
if we don't keep them with class headers, which tend to be more volatile.
*/
#include "hsGeometry3.h" // for the hsVector3, below
// animation alignment types (used by "calcanimalignment")
// when starting oneshots, we need to first get your handle into a position to play the oneshot properly
// there are different approaches to calculating this aligment
/** \enum Alignment
There are several different ways to get into position to play a detailed
interaction animation. Interactions always have an associated "seek point"
indicating an alignment point, but there are several different types of
alignment. */
enum plAvAlignment {
kAlignHandle, /// align our handle with the seek point
kAlignHandleAnimEnd, /** align our handle at the seek point "minus" the animation
i.e. after seeking and then playing the animation, our
handle should wind up aligned with the seek point. */
kAlignWorld, /** align our handle with the world origin; the animation
is defined in global space */
kAlignBone, /// align a specific bone with the seek point
kAlignBoneAnimEnd, /** align our handle so that the bone is at the seek point
after the animation has finished playing. */
kAlignEnsure16 = 0xffff
};
const hsVector3 kAvatarUp(0,0,1);
const hsVector3 kAvatarForward(0,-1,0);
const hsVector3 kAvatarRight(-1,0,0);
/** \enum PinType
Tells us what category of animation this channel affects.
Primarly used to determine if two channels are competing,
which you can't tell strictly from the type of data the
channel handles. */
enum plAGPinType
{
kAGPinUnknown, // this applicator hasn't decided its pin type
kAGPinTransform, // this applicator munches the entire transform
kNumPinTypes
};
#define kAGMaxBlendPriority 0x0fffffff
#define kAGMinBlendPriority 0x00000000
#define kAGMedBlendPriority 0x0000ffff
#endif

View File

@ -1,378 +1,378 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvatar/plAvCallbackAction.h"
#include "hsTypes.h"
// singular
#include "plAvLadderModifier.h"
// local
#include "plArmatureMod.h"
#include "plAvatarMgr.h"
#include "plAvBrainGeneric.h"
#include "plAGAnim.h"
#include "plAnimStage.h"
// global
#include "plCreatableIndex.h"
// #include "plgDispatch.h" // Message Dependencies
#include "hsStream.h"
//other
#include "plMessage/plCollideMsg.h"
#include "plMessage/plAvatarMsg.h"
#include "pnMessage/plNotifyMsg.h"
#include "plStatusLog/plStatusLog.h"
#include "pnKeyedObject/plKey.h"
#include "pnMessage/plEnableMsg.h"
#include "pnMessage/plTimeMsg.h"
#include "plgDispatch.h"
#include "pnNetCommon/plNetApp.h"
#include "pnSceneObject/plCoordinateInterface.h"
#include "plAvatar/plAvBrainHuman.h"
#include "plModifier/plDetectorLog.h"
enum NotifyType
{
kNotifyTrigger,
kNotifyAvatarOnLadder,
};
// CTOR default
plAvLadderMod::plAvLadderMod()
: fGoingUp(true),
fType(kBig),
fLoops(0),
fEnabled(true),
fAvatarInBox(false),
fLadderView(0,0,0),
fAvatarMounting(false)
{
fTarget = nil;
}
// CTOR goingUp, type, loops
plAvLadderMod::plAvLadderMod(bool goingUp, int type, int loops, bool enabled, hsVector3& ladderView)
: fGoingUp(goingUp),
fType(type),
fLoops(loops),
fEnabled(enabled),
fAvatarInBox(false),
fLadderView(ladderView)
{
fTarget = nil;
}
// Must be facing within 45 degrees of the ladder
static const hsScalar kTolerance = hsCosine(hsScalarDegToRad(45));
bool plAvLadderMod::IIsReadyToClimb()
{
if (fAvatarMounting)
return false;
plArmatureMod* armMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
plSceneObject* avatar = armMod->GetTarget(0);
if (avatar)
{
hsVector3 playerView = avatar->GetCoordinateInterface()->GetLocalToWorld().GetAxis(hsMatrix44::kView);
playerView.fZ = 0;
// Are we facing towards the ladder?
hsScalar dot = playerView * fLadderView;
bool movingForward = false;
// And are we walking towards it?
hsAssert(armMod, "Avatar doesn't have an armature mod");
if (armMod)
{
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(armMod->GetCurrentBrain());
if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround())
movingForward = true;
}
if (dot >= kTolerance && movingForward)
{
DetectorLogSpecial("%s: Ladder starting climb (%f)", GetKeyName(), hsScalarRadToDeg(hsACosine(dot)));
return true;
}
else if (movingForward)
{
// DetectorLog("%s: Ladder rejecting climb (%f)", GetKeyName(), hsScalarRadToDeg(hsACosine(dot)));
return false;
}
}
return false;
}
// use a plNotify (to ourself) to propagate across the network
void plAvLadderMod::ITriggerSelf(plKey avKey)
{
if (fEnabled)
{
plKey avPhysKey = avKey;
// I'm going to lie and pretend it's from the avatar. the alternative is lengthy and unreadable.
plNotifyMsg *notifyMsg = TRACKED_NEW plNotifyMsg(avPhysKey, GetKey());
notifyMsg->fID = kNotifyTrigger;
notifyMsg->Send();
fAvatarMounting = true;
}
}
// MSGRECEIVE
hsBool plAvLadderMod::MsgReceive(plMessage* msg)
{
// Avatar is entering or exiting our detector box
plCollideMsg* collMsg = plCollideMsg::ConvertNoRef(msg);
if (collMsg)
{
// make sure this is the local player... the notify will be the thing that propagates over the network
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != collMsg->fOtherKey)
return true;
fAvatarInBox = (collMsg->fEntering != 0);
// If entering, check if ready to climb. If not, register for eval so
// we can check every frame
if (fAvatarInBox)
{
DetectorLogSpecial("%s: Avatar entered ladder region", GetKeyName());
if (IIsReadyToClimb())
ITriggerSelf(collMsg->fOtherKey);
else
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
else
{
DetectorLogSpecial("%s: Avatar exited ladder region", GetKeyName());
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
}
return true;
}
// Avatar is inside our detector box, so every frame we check if he's ready to climb
plEvalMsg* evalMsg = plEvalMsg::ConvertNoRef(msg);
if (evalMsg)
{
if (IIsReadyToClimb())
ITriggerSelf(plNetClientApp::GetInstance()->GetLocalPlayerKey());
return true;
}
plNotifyMsg *notifyMsg = plNotifyMsg::ConvertNoRef(msg);
if (notifyMsg)
{
if (notifyMsg->fID == kNotifyTrigger && fEnabled)
{
const plKey avPhysKey = notifyMsg->GetSender();
EmitCommand(avPhysKey);
}
else if (notifyMsg->fID == kNotifyAvatarOnLadder)
{
DetectorLogSpecial("%s: Avatar mounted ladder", GetKeyName());
fAvatarMounting = false;
}
return true;
}
plEnableMsg *enableMsg = plEnableMsg::ConvertNoRef(msg);
if (enableMsg)
{
if (enableMsg->Cmd(plEnableMsg::kDisable))
fEnabled = false;
else if (enableMsg->Cmd(plEnableMsg::kEnable))
fEnabled = true;
}
return plSingleModifier::MsgReceive(msg);
}
// EMITCOMMAND
void plAvLadderMod::EmitCommand(const plKey receiver)
{
hsKeyedObject *object = receiver->ObjectIsLoaded();
plSceneObject *SO = plSceneObject::ConvertNoRef(object);
if(SO)
{
const plArmatureMod *constAvMod = (plArmatureMod*)SO->GetModifierByType(plArmatureMod::Index());
if(constAvMod)
{
plAvBrainGeneric *curGenBrain = (plAvBrainGeneric *)constAvMod->FindBrainByClass(plAvBrainGeneric::Index());
// *** warning; if there's more than one generic brain active, this will only look at the first
bool alreadyOnLadder = ( curGenBrain && curGenBrain->GetType() == plAvBrainGeneric::kLadder );
if( ! alreadyOnLadder)
{
plSceneObject *seekObj = GetTarget();
plKey seekKey = seekObj->GetKey(); // this modifier's target is the seek object
char *mountName, *dismountName, *traverseName;
if(fGoingUp)
{
mountName = "LadderUpOn";
dismountName = "LadderUpOff";
traverseName = "LadderUp";
} else {
mountName = "LadderDownOn";
dismountName = "LadderDownOff";
traverseName = "LadderDown";
}
plAnimStageVec *v = TRACKED_NEW plAnimStageVec;
plAnimStage *s1 = TRACKED_NEW plAnimStage(mountName,
0,
plAnimStage::kForwardAuto,
plAnimStage::kBackAuto,
plAnimStage::kAdvanceAuto,
plAnimStage::kRegressAuto,
0);
if( ! fGoingUp)
s1->SetReverseOnIdle(true);
v->push_back(s1);
// if loops is zero, we don't need the traverse animation at all.
if(fLoops)
{
plAnimStage *s2 = TRACKED_NEW plAnimStage(traverseName,
0,
plAnimStage::kForwardKey,
plAnimStage::kBackKey,
plAnimStage::kAdvanceAuto,
plAnimStage::kRegressAuto,
fLoops - 1 // first loop is implied; zero loops means
// play this anim once, 1 loop means "loop
// once after reaching the end."
);
if( ! fGoingUp)
s2->SetReverseOnIdle(true);
v->push_back(s2);
}
plAnimStage *s3 = TRACKED_NEW plAnimStage(dismountName,
0,
plAnimStage::kForwardAuto,
plAnimStage::kBackAuto,
plAnimStage::kAdvanceAuto,
plAnimStage::kRegressAuto,
0);
if( ! fGoingUp)
s3->SetReverseOnIdle(true);
v->push_back(s3);
plNotifyMsg* enterNotify = TRACKED_NEW plNotifyMsg(GetKey(), GetKey());
enterNotify->fID = kNotifyAvatarOnLadder;
UInt32 exitFlags = plAvBrainGeneric::kExitNormal;
plAvBrainGeneric *ladBrain = TRACKED_NEW plAvBrainGeneric(v, enterNotify, nil, nil, exitFlags, plAvBrainGeneric::kDefaultFadeIn,
plAvBrainGeneric::kDefaultFadeOut, plAvBrainGeneric::kMoveRelative);
ladBrain->SetType(plAvBrainGeneric::kLadder);
ladBrain->SetReverseFBControlsOnRelease(!fGoingUp);
plKey avKey = constAvMod->GetKey();
// Very important that we dumb seek here. Otherwise you can run off the edge of a ladder, and seek will be helpless
// until you hit the ground, at which point you have no hope of successfully seeking.
plAvSeekMsg *seeker = TRACKED_NEW plAvSeekMsg(nil, avKey, seekKey, 1.0f, false);
seeker->Send();
plAvPushBrainMsg *brainer = TRACKED_NEW plAvPushBrainMsg(nil, avKey, ladBrain);
brainer->Send();
}
}
}
}
void plAvLadderMod::Read(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Read(stream, mgr);
fType = stream->ReadSwap32();
fLoops = stream->ReadSwap32();
fGoingUp = stream->Readbool();
fEnabled = stream->Readbool();
fLadderView.fX = stream->ReadSwapScalar();
fLadderView.fY = stream->ReadSwapScalar();
fLadderView.fZ = stream->ReadSwapScalar();
}
void plAvLadderMod::Write(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteSwap32(fType);
stream->WriteSwap32(fLoops);
stream->Writebool(fGoingUp);
stream->WriteBool(fEnabled);
stream->WriteSwapScalar(fLadderView.fX);
stream->WriteSwapScalar(fLadderView.fY);
stream->WriteSwapScalar(fLadderView.fZ);
}
// true is up; false is down
bool plAvLadderMod::GetGoingUp() const
{
return fGoingUp;
}
void plAvLadderMod::SetGoingUp(bool up)
{
fGoingUp = up;
}
int plAvLadderMod::GetLoops() const
{
return fLoops;
}
void plAvLadderMod::SetLoops(int loops)
{
fLoops = loops;
}
int plAvLadderMod::GetType() const
{
return fType;
}
void plAvLadderMod::SetType(int type)
{
if(type >= kNumOfTypeFields || type < 0)
{
hsStatusMessage("Invalid param to plAvLadderMod::SetType: defaulting to kBig");
fType = kBig;
} else {
fType = type;
}
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAvatar/plAvCallbackAction.h"
#include "hsTypes.h"
// singular
#include "plAvLadderModifier.h"
// local
#include "plArmatureMod.h"
#include "plAvatarMgr.h"
#include "plAvBrainGeneric.h"
#include "plAGAnim.h"
#include "plAnimStage.h"
// global
#include "plCreatableIndex.h"
// #include "plgDispatch.h" // Message Dependencies
#include "hsStream.h"
//other
#include "plMessage/plCollideMsg.h"
#include "plMessage/plAvatarMsg.h"
#include "pnMessage/plNotifyMsg.h"
#include "plStatusLog/plStatusLog.h"
#include "pnKeyedObject/plKey.h"
#include "pnMessage/plEnableMsg.h"
#include "pnMessage/plTimeMsg.h"
#include "plgDispatch.h"
#include "pnNetCommon/plNetApp.h"
#include "pnSceneObject/plCoordinateInterface.h"
#include "plAvatar/plAvBrainHuman.h"
#include "plModifier/plDetectorLog.h"
enum NotifyType
{
kNotifyTrigger,
kNotifyAvatarOnLadder,
};
// CTOR default
plAvLadderMod::plAvLadderMod()
: fGoingUp(true),
fType(kBig),
fLoops(0),
fEnabled(true),
fAvatarInBox(false),
fLadderView(0,0,0),
fAvatarMounting(false)
{
fTarget = nil;
}
// CTOR goingUp, type, loops
plAvLadderMod::plAvLadderMod(bool goingUp, int type, int loops, bool enabled, hsVector3& ladderView)
: fGoingUp(goingUp),
fType(type),
fLoops(loops),
fEnabled(enabled),
fAvatarInBox(false),
fLadderView(ladderView)
{
fTarget = nil;
}
// Must be facing within 45 degrees of the ladder
static const hsScalar kTolerance = hsCosine(hsScalarDegToRad(45));
bool plAvLadderMod::IIsReadyToClimb()
{
if (fAvatarMounting)
return false;
plArmatureMod* armMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
plSceneObject* avatar = armMod->GetTarget(0);
if (avatar)
{
hsVector3 playerView = avatar->GetCoordinateInterface()->GetLocalToWorld().GetAxis(hsMatrix44::kView);
playerView.fZ = 0;
// Are we facing towards the ladder?
hsScalar dot = playerView * fLadderView;
bool movingForward = false;
// And are we walking towards it?
hsAssert(armMod, "Avatar doesn't have an armature mod");
if (armMod)
{
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(armMod->GetCurrentBrain());
if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround())
movingForward = true;
}
if (dot >= kTolerance && movingForward)
{
DetectorLogSpecial("%s: Ladder starting climb (%f)", GetKeyName(), hsScalarRadToDeg(hsACosine(dot)));
return true;
}
else if (movingForward)
{
// DetectorLog("%s: Ladder rejecting climb (%f)", GetKeyName(), hsScalarRadToDeg(hsACosine(dot)));
return false;
}
}
return false;
}
// use a plNotify (to ourself) to propagate across the network
void plAvLadderMod::ITriggerSelf(plKey avKey)
{
if (fEnabled)
{
plKey avPhysKey = avKey;
// I'm going to lie and pretend it's from the avatar. the alternative is lengthy and unreadable.
plNotifyMsg *notifyMsg = TRACKED_NEW plNotifyMsg(avPhysKey, GetKey());
notifyMsg->fID = kNotifyTrigger;
notifyMsg->Send();
fAvatarMounting = true;
}
}
// MSGRECEIVE
hsBool plAvLadderMod::MsgReceive(plMessage* msg)
{
// Avatar is entering or exiting our detector box
plCollideMsg* collMsg = plCollideMsg::ConvertNoRef(msg);
if (collMsg)
{
// make sure this is the local player... the notify will be the thing that propagates over the network
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != collMsg->fOtherKey)
return true;
fAvatarInBox = (collMsg->fEntering != 0);
// If entering, check if ready to climb. If not, register for eval so
// we can check every frame
if (fAvatarInBox)
{
DetectorLogSpecial("%s: Avatar entered ladder region", GetKeyName());
if (IIsReadyToClimb())
ITriggerSelf(collMsg->fOtherKey);
else
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
else
{
DetectorLogSpecial("%s: Avatar exited ladder region", GetKeyName());
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
}
return true;
}
// Avatar is inside our detector box, so every frame we check if he's ready to climb
plEvalMsg* evalMsg = plEvalMsg::ConvertNoRef(msg);
if (evalMsg)
{
if (IIsReadyToClimb())
ITriggerSelf(plNetClientApp::GetInstance()->GetLocalPlayerKey());
return true;
}
plNotifyMsg *notifyMsg = plNotifyMsg::ConvertNoRef(msg);
if (notifyMsg)
{
if (notifyMsg->fID == kNotifyTrigger && fEnabled)
{
const plKey avPhysKey = notifyMsg->GetSender();
EmitCommand(avPhysKey);
}
else if (notifyMsg->fID == kNotifyAvatarOnLadder)
{
DetectorLogSpecial("%s: Avatar mounted ladder", GetKeyName());
fAvatarMounting = false;
}
return true;
}
plEnableMsg *enableMsg = plEnableMsg::ConvertNoRef(msg);
if (enableMsg)
{
if (enableMsg->Cmd(plEnableMsg::kDisable))
fEnabled = false;
else if (enableMsg->Cmd(plEnableMsg::kEnable))
fEnabled = true;
}
return plSingleModifier::MsgReceive(msg);
}
// EMITCOMMAND
void plAvLadderMod::EmitCommand(const plKey receiver)
{
hsKeyedObject *object = receiver->ObjectIsLoaded();
plSceneObject *SO = plSceneObject::ConvertNoRef(object);
if(SO)
{
const plArmatureMod *constAvMod = (plArmatureMod*)SO->GetModifierByType(plArmatureMod::Index());
if(constAvMod)
{
plAvBrainGeneric *curGenBrain = (plAvBrainGeneric *)constAvMod->FindBrainByClass(plAvBrainGeneric::Index());
// *** warning; if there's more than one generic brain active, this will only look at the first
bool alreadyOnLadder = ( curGenBrain && curGenBrain->GetType() == plAvBrainGeneric::kLadder );
if( ! alreadyOnLadder)
{
plSceneObject *seekObj = GetTarget();
plKey seekKey = seekObj->GetKey(); // this modifier's target is the seek object
char *mountName, *dismountName, *traverseName;
if(fGoingUp)
{
mountName = "LadderUpOn";
dismountName = "LadderUpOff";
traverseName = "LadderUp";
} else {
mountName = "LadderDownOn";
dismountName = "LadderDownOff";
traverseName = "LadderDown";
}
plAnimStageVec *v = TRACKED_NEW plAnimStageVec;
plAnimStage *s1 = TRACKED_NEW plAnimStage(mountName,
0,
plAnimStage::kForwardAuto,
plAnimStage::kBackAuto,
plAnimStage::kAdvanceAuto,
plAnimStage::kRegressAuto,
0);
if( ! fGoingUp)
s1->SetReverseOnIdle(true);
v->push_back(s1);
// if loops is zero, we don't need the traverse animation at all.
if(fLoops)
{
plAnimStage *s2 = TRACKED_NEW plAnimStage(traverseName,
0,
plAnimStage::kForwardKey,
plAnimStage::kBackKey,
plAnimStage::kAdvanceAuto,
plAnimStage::kRegressAuto,
fLoops - 1 // first loop is implied; zero loops means
// play this anim once, 1 loop means "loop
// once after reaching the end."
);
if( ! fGoingUp)
s2->SetReverseOnIdle(true);
v->push_back(s2);
}
plAnimStage *s3 = TRACKED_NEW plAnimStage(dismountName,
0,
plAnimStage::kForwardAuto,
plAnimStage::kBackAuto,
plAnimStage::kAdvanceAuto,
plAnimStage::kRegressAuto,
0);
if( ! fGoingUp)
s3->SetReverseOnIdle(true);
v->push_back(s3);
plNotifyMsg* enterNotify = TRACKED_NEW plNotifyMsg(GetKey(), GetKey());
enterNotify->fID = kNotifyAvatarOnLadder;
UInt32 exitFlags = plAvBrainGeneric::kExitNormal;
plAvBrainGeneric *ladBrain = TRACKED_NEW plAvBrainGeneric(v, enterNotify, nil, nil, exitFlags, plAvBrainGeneric::kDefaultFadeIn,
plAvBrainGeneric::kDefaultFadeOut, plAvBrainGeneric::kMoveRelative);
ladBrain->SetType(plAvBrainGeneric::kLadder);
ladBrain->SetReverseFBControlsOnRelease(!fGoingUp);
plKey avKey = constAvMod->GetKey();
// Very important that we dumb seek here. Otherwise you can run off the edge of a ladder, and seek will be helpless
// until you hit the ground, at which point you have no hope of successfully seeking.
plAvSeekMsg *seeker = TRACKED_NEW plAvSeekMsg(nil, avKey, seekKey, 1.0f, false);
seeker->Send();
plAvPushBrainMsg *brainer = TRACKED_NEW plAvPushBrainMsg(nil, avKey, ladBrain);
brainer->Send();
}
}
}
}
void plAvLadderMod::Read(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Read(stream, mgr);
fType = stream->ReadSwap32();
fLoops = stream->ReadSwap32();
fGoingUp = stream->Readbool();
fEnabled = stream->Readbool();
fLadderView.fX = stream->ReadSwapScalar();
fLadderView.fY = stream->ReadSwapScalar();
fLadderView.fZ = stream->ReadSwapScalar();
}
void plAvLadderMod::Write(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteSwap32(fType);
stream->WriteSwap32(fLoops);
stream->Writebool(fGoingUp);
stream->WriteBool(fEnabled);
stream->WriteSwapScalar(fLadderView.fX);
stream->WriteSwapScalar(fLadderView.fY);
stream->WriteSwapScalar(fLadderView.fZ);
}
// true is up; false is down
bool plAvLadderMod::GetGoingUp() const
{
return fGoingUp;
}
void plAvLadderMod::SetGoingUp(bool up)
{
fGoingUp = up;
}
int plAvLadderMod::GetLoops() const
{
return fLoops;
}
void plAvLadderMod::SetLoops(int loops)
{
fLoops = loops;
}
int plAvLadderMod::GetType() const
{
return fType;
}
void plAvLadderMod::SetType(int type)
{
if(type >= kNumOfTypeFields || type < 0)
{
hsStatusMessage("Invalid param to plAvLadderMod::SetType: defaulting to kBig");
fType = kBig;
} else {
fType = type;
}
}

View File

@ -1,87 +1,87 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvLadderMod_INC
#define plAvLadderMod_INC
#include "pnModifier/plSingleModifier.h"
#include "pnMessage/plMessage.h"
#include "hsGeometry3.h"
// has a detector region. when a local avatar enters that region,
// creates a ladder brain and applies it to the avatar with the relevant fields
class plAvLadderMod : public plSingleModifier
{
public:
plAvLadderMod();
plAvLadderMod(bool goingUp, int type, int loops, bool enabled, hsVector3& ladderView);
virtual ~plAvLadderMod() {};
void EmitCommand(const plKey receiver);
CLASSNAME_REGISTER( plAvLadderMod );
GETINTERFACE_ANY( plAvLadderMod, plSingleModifier );
// virtual void AddTarget(plSceneObject* so) { SetTarget(so); }
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
bool GetGoingUp() const;
void SetGoingUp(bool v);
int GetLoops() const;
void SetLoops(int v);
int GetType() const;
void SetType(int v);
void SetEnabled(bool enabled) { fEnabled = enabled; }
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) {return true;}
bool IIsReadyToClimb();
void ITriggerSelf(plKey avKey);
enum fTypeField
{
kBig, // big ladders are built from a mount, N traverse loops, and a dismount
kFourFeet, // four-foot ladders are a one-shot
kTwoFeet, // two-foot (step)ladders are a one-shot
kNumOfTypeFields,
};
bool fGoingUp; // true means heading up; false means down
int fType; // what type of ladder are we?
int fLoops; // if we're a big ladder, how many traverse loops do we need?
hsVector3 fLadderView;
bool fEnabled;
bool fAvatarInBox;
bool fAvatarMounting; // True if the avatar is in the process of mounting the ladder.
// Don't try to trigger during this time.
};
#endif plAvLadderMod_INC
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvLadderMod_INC
#define plAvLadderMod_INC
#include "pnModifier/plSingleModifier.h"
#include "pnMessage/plMessage.h"
#include "hsGeometry3.h"
// has a detector region. when a local avatar enters that region,
// creates a ladder brain and applies it to the avatar with the relevant fields
class plAvLadderMod : public plSingleModifier
{
public:
plAvLadderMod();
plAvLadderMod(bool goingUp, int type, int loops, bool enabled, hsVector3& ladderView);
virtual ~plAvLadderMod() {};
void EmitCommand(const plKey receiver);
CLASSNAME_REGISTER( plAvLadderMod );
GETINTERFACE_ANY( plAvLadderMod, plSingleModifier );
// virtual void AddTarget(plSceneObject* so) { SetTarget(so); }
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
bool GetGoingUp() const;
void SetGoingUp(bool v);
int GetLoops() const;
void SetLoops(int v);
int GetType() const;
void SetType(int v);
void SetEnabled(bool enabled) { fEnabled = enabled; }
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) {return true;}
bool IIsReadyToClimb();
void ITriggerSelf(plKey avKey);
enum fTypeField
{
kBig, // big ladders are built from a mount, N traverse loops, and a dismount
kFourFeet, // four-foot ladders are a one-shot
kTwoFeet, // two-foot (step)ladders are a one-shot
kNumOfTypeFields,
};
bool fGoingUp; // true means heading up; false means down
int fType; // what type of ladder are we?
int fLoops; // if we're a big ladder, how many traverse loops do we need?
hsVector3 fLadderView;
bool fEnabled;
bool fAvatarInBox;
bool fAvatarMounting; // True if the avatar is in the process of mounting the ladder.
// Don't try to trigger during this time.
};
#endif plAvLadderMod_INC

View File

@ -1,115 +1,115 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#pragma once
#ifndef PLAVMOTORHUMAN_INC
/*** \file plAvMotorHuman.h
*/
#include <hkdynamics\action\action.h>
class plAvBrainHuman;
/** \class plAvMotorHuman
Applies avatar at simulation frequency rather than frame frequency.
*/
class plAvMotorHuman : public Havok::Action
{
public:
plAvMotorHuman();
/** Called from havok during integration; converts time to plasma format
and asks the brain to move. Brain will sample animation at current time
and apply velocity or forces to the body.
*/
virtual void apply(Havok::Subspace &subspace, Havok::hkTime time);
/** Sets the motor to control a different human brain.
Returns the previously controlled brain, or nil.
*/
plAvBrainHuman * SetBrain(plAvBrainHuman *brain);
/** Which brain is this motor currently controlling?
*/
plAvBrainHuman * GetBrain();
private:
/** The brain we get our movement data from */
plAvBrainHuman *fBrain;
double fLastTime;
};
/*** \file plAvMotorHuman.cpp
*/
#include "plAvBrainHuman.h"
plAvMotorHuman::plAvMotorHuman()
: fBrain(0),
fLastTime(0.0f)
{
}
//plAvMotorHuman::plAvMotorHuman(plAvBrainHuman *brain)
//: fBrain(brain),
// fLastTime(0.0f);
void plAvMotorHuman::apply(Havok::Subspace &subspace, Havok::hkTime time)
{
double timeNow = time.asDouble();
double elapsedD = timeNow - fLastTime;
float elapsed = elapsedD;
if(elapsed > 1.0f)
{
elapsed = 0.1f;
hsStatusMessageF("Clamping plAvMotorHuman::apply interval to <%f>", elapsed);
fLastTime = timeNow - elapsed;
}
// fBrain->MoveViaAnimation(timeNow, elapsed);
}
plAvBrainHuman * plAvMotorHuman::SetBrain(plAvBrainHuman *brain)
{
plAvBrainHuman * oldBrain = fBrain;
fBrain = brain;
return oldBrain;
}
plAvBrainHuman * plAvMotorHuman::GetBrain()
{
return fBrain;
}
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#pragma once
#ifndef PLAVMOTORHUMAN_INC
/*** \file plAvMotorHuman.h
*/
#include <hkdynamics\action\action.h>
class plAvBrainHuman;
/** \class plAvMotorHuman
Applies avatar at simulation frequency rather than frame frequency.
*/
class plAvMotorHuman : public Havok::Action
{
public:
plAvMotorHuman();
/** Called from havok during integration; converts time to plasma format
and asks the brain to move. Brain will sample animation at current time
and apply velocity or forces to the body.
*/
virtual void apply(Havok::Subspace &subspace, Havok::hkTime time);
/** Sets the motor to control a different human brain.
Returns the previously controlled brain, or nil.
*/
plAvBrainHuman * SetBrain(plAvBrainHuman *brain);
/** Which brain is this motor currently controlling?
*/
plAvBrainHuman * GetBrain();
private:
/** The brain we get our movement data from */
plAvBrainHuman *fBrain;
double fLastTime;
};
/*** \file plAvMotorHuman.cpp
*/
#include "plAvBrainHuman.h"
plAvMotorHuman::plAvMotorHuman()
: fBrain(0),
fLastTime(0.0f)
{
}
//plAvMotorHuman::plAvMotorHuman(plAvBrainHuman *brain)
//: fBrain(brain),
// fLastTime(0.0f);
void plAvMotorHuman::apply(Havok::Subspace &subspace, Havok::hkTime time)
{
double timeNow = time.asDouble();
double elapsedD = timeNow - fLastTime;
float elapsed = elapsedD;
if(elapsed > 1.0f)
{
elapsed = 0.1f;
hsStatusMessageF("Clamping plAvMotorHuman::apply interval to <%f>", elapsed);
fLastTime = timeNow - elapsed;
}
// fBrain->MoveViaAnimation(timeNow, elapsed);
}
plAvBrainHuman * plAvMotorHuman::SetBrain(plAvBrainHuman *brain)
{
plAvBrainHuman * oldBrain = fBrain;
fBrain = brain;
return oldBrain;
}
plAvBrainHuman * plAvMotorHuman::GetBrain()
{
return fBrain;
}
#endif

View File

@ -1,25 +1,25 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/

View File

@ -1,25 +1,25 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/

View File

@ -1,100 +1,100 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvTask_h
#define plAvTask_h
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
// base class
#include "pnFactory/plCreatable.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// DECLARATIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plArmatureMod;
class plArmatureBrain;
class plDebugText;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plAvTask
Abstract class for avatar tasks
A task is an activity which completely occupies the avatar from beginning to end.
Only one task can run at a time.
Tasks are queued within a given avatar brain; you can queue several at once, and they'll
run in succession, with each waiting for the former to complete before running.
Some tasks are instantaneous (like attaching an animation,) and only use the task model for
sequencing effect. (i.e., walk here, attach this animation, etc.)
If your task requires user intervention or control, you probably should
be using an avatar brain instead. Tasks are meant to sort of run on their own.
*/
class plAvTask : public plCreatable
{
public:
plAvTask();
/** Start the task: set up initial conditions or wait for resources to become available.
Start will be called repeatedly until it returns true, indicating the task has begun. */
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** Run the task. Start is guaranteed to have returned true before Process() is called even once.
Returns false when the task has finished and epilogue code has been executed. */
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** Clean up the task. This is guaranteed to be called when Process returns false. */
virtual void Finish(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual void LeaveAge(plArmatureMod *avatar) {}
/** dump descriptive stuff to the given debug text */
virtual void DumpDebug(const char *name, int &x, int&y, int lineHeight, char *strBuf, plDebugText &debugTxt);
// plasma protocol
CLASSNAME_REGISTER( plAvTask );
GETINTERFACE_ANY( plAvTask, plCreatable );
/** Read the task from a stream. Not all tasks need to read/write, so the base implementation
gives a warning to expose tasks that are being read/written unexpectedly. */
virtual void Read(hsStream *stream, hsResMgr *mgr);
/** Write the task to a stream. Not all tasks need to read/write, so the base implementation
gives a warning to expose tasks that are being read/written unexpectedly. */
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
virtual void ILimitPlayersInput(plArmatureMod *avatar);
virtual void IUndoLimitPlayersInput(plArmatureMod *avatar);
};
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvTask_h
#define plAvTask_h
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
// base class
#include "pnFactory/plCreatable.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// DECLARATIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plArmatureMod;
class plArmatureBrain;
class plDebugText;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plAvTask
Abstract class for avatar tasks
A task is an activity which completely occupies the avatar from beginning to end.
Only one task can run at a time.
Tasks are queued within a given avatar brain; you can queue several at once, and they'll
run in succession, with each waiting for the former to complete before running.
Some tasks are instantaneous (like attaching an animation,) and only use the task model for
sequencing effect. (i.e., walk here, attach this animation, etc.)
If your task requires user intervention or control, you probably should
be using an avatar brain instead. Tasks are meant to sort of run on their own.
*/
class plAvTask : public plCreatable
{
public:
plAvTask();
/** Start the task: set up initial conditions or wait for resources to become available.
Start will be called repeatedly until it returns true, indicating the task has begun. */
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** Run the task. Start is guaranteed to have returned true before Process() is called even once.
Returns false when the task has finished and epilogue code has been executed. */
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** Clean up the task. This is guaranteed to be called when Process returns false. */
virtual void Finish(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual void LeaveAge(plArmatureMod *avatar) {}
/** dump descriptive stuff to the given debug text */
virtual void DumpDebug(const char *name, int &x, int&y, int lineHeight, char *strBuf, plDebugText &debugTxt);
// plasma protocol
CLASSNAME_REGISTER( plAvTask );
GETINTERFACE_ANY( plAvTask, plCreatable );
/** Read the task from a stream. Not all tasks need to read/write, so the base implementation
gives a warning to expose tasks that are being read/written unexpectedly. */
virtual void Read(hsStream *stream, hsResMgr *mgr);
/** Write the task to a stream. Not all tasks need to read/write, so the base implementation
gives a warning to expose tasks that are being read/written unexpectedly. */
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
virtual void ILimitPlayersInput(plArmatureMod *avatar);
virtual void IUndoLimitPlayersInput(plArmatureMod *avatar);
};
#endif

View File

@ -1,115 +1,115 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plAvTaskBrain.h"
// local
#include "plArmatureMod.h"
#include "plAvBrain.h"
// other
#include "plPipeline/plDebugText.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// PLAVTASKBRAIN
//
/////////////////////////////////////////////////////////////////////////////////////////
// CTOR default
plAvTaskBrain::plAvTaskBrain()
: fBrain(nil)
{
}
// CTOR brain
plAvTaskBrain::plAvTaskBrain(plArmatureBrain *brain)
: fBrain(brain)
{
}
plAvTaskBrain::~plAvTaskBrain()
{
delete fBrain;
}
// Start ------------------------------------------------------------------------------------------
// ------
hsBool plAvTaskBrain::Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
{
if(fBrain)
avatar->PushBrain(fBrain);
else
avatar->PopBrain();
fBrain = nil; // We've passed it on the the avatar, set our pointer to nil so we don't destroy it
return true;
}
void plAvTaskBrain::Finish(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
{
}
// DumpDebug ------------------------------------------------------------------------------------------------------
// ----------
void plAvTaskBrain::DumpDebug(const char *name, int &x, int&y, int lineHeight, char *strBuf, plDebugText &debugTxt)
{
if(fBrain)
{
debugTxt.DrawString(x, y, "Brain task -- Push New Brain.");
} else {
debugTxt.DrawString(x, y, "Brain task -- Pop Current Brain.");
}
y += lineHeight;
}
// GetBrain ------------------------
// ---------
plArmatureBrain *plAvTaskBrain::GetBrain()
{
return fBrain;
}
// Read ------------------------------------------
// -----
void plAvTaskBrain::Read(hsStream *stream, hsResMgr *mgr)
{
plAvTask::Read(stream, mgr);
fBrain = plArmatureBrain::ConvertNoRef(mgr->ReadCreatable(stream));
}
// Write ------------------------------------------
// ------
void plAvTaskBrain::Write(hsStream *stream, hsResMgr *mgr)
{
plAvTask::Write(stream, mgr);
mgr->WriteCreatable(stream, fBrain);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plAvTaskBrain.h"
// local
#include "plArmatureMod.h"
#include "plAvBrain.h"
// other
#include "plPipeline/plDebugText.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// PLAVTASKBRAIN
//
/////////////////////////////////////////////////////////////////////////////////////////
// CTOR default
plAvTaskBrain::plAvTaskBrain()
: fBrain(nil)
{
}
// CTOR brain
plAvTaskBrain::plAvTaskBrain(plArmatureBrain *brain)
: fBrain(brain)
{
}
plAvTaskBrain::~plAvTaskBrain()
{
delete fBrain;
}
// Start ------------------------------------------------------------------------------------------
// ------
hsBool plAvTaskBrain::Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
{
if(fBrain)
avatar->PushBrain(fBrain);
else
avatar->PopBrain();
fBrain = nil; // We've passed it on the the avatar, set our pointer to nil so we don't destroy it
return true;
}
void plAvTaskBrain::Finish(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
{
}
// DumpDebug ------------------------------------------------------------------------------------------------------
// ----------
void plAvTaskBrain::DumpDebug(const char *name, int &x, int&y, int lineHeight, char *strBuf, plDebugText &debugTxt)
{
if(fBrain)
{
debugTxt.DrawString(x, y, "Brain task -- Push New Brain.");
} else {
debugTxt.DrawString(x, y, "Brain task -- Pop Current Brain.");
}
y += lineHeight;
}
// GetBrain ------------------------
// ---------
plArmatureBrain *plAvTaskBrain::GetBrain()
{
return fBrain;
}
// Read ------------------------------------------
// -----
void plAvTaskBrain::Read(hsStream *stream, hsResMgr *mgr)
{
plAvTask::Read(stream, mgr);
fBrain = plArmatureBrain::ConvertNoRef(mgr->ReadCreatable(stream));
}
// Write ------------------------------------------
// ------
void plAvTaskBrain::Write(hsStream *stream, hsResMgr *mgr)
{
plAvTask::Write(stream, mgr);
mgr->WriteCreatable(stream, fBrain);
}

View File

@ -1,80 +1,80 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvTaskBrain_h
#define plAvTaskBrain_h
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "plAvTask.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plAvTaskBrain
Push a new brain onto the avatar or pull an old brain off.
If a brain is supplied, it's a push. Otherwise it's a pull.
*/
class plAvTaskBrain : public plAvTask
{
public:
/** Default constructor. Used as is, will function as a pop brain message. */
plAvTaskBrain();
/** Constructor for a push configuration. If the brain is non, nil, it
will be pushed onto the receiving avatar when the task is dequeued.
If the brain is nil, the current brain will be popped. */
plAvTaskBrain(plArmatureBrain *brain);
virtual ~plAvTaskBrain();
// task protocol
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual void Finish(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** dump descriptive stuff to the given debug text */
virtual void DumpDebug(const char *name, int &x, int&y, int lineHeight, char *strBuf, plDebugText &debugTxt);
plArmatureBrain *GetBrain();
CLASSNAME_REGISTER( plAvTaskBrain );
GETINTERFACE_ANY( plAvTaskBrain, plAvTask );
/** Read the task from a stream. Not all tasks need to read/write, so the base implementation
gives a warning to expose tasks that are being read/written unexpectedly. */
virtual void Read(hsStream *stream, hsResMgr *mgr);
/** Write the task to a stream. Not all tasks need to read/write, so the base implementation
gives a warning to expose tasks that are being read/written unexpectedly. */
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
plArmatureBrain *fBrain;
};
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvTaskBrain_h
#define plAvTaskBrain_h
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "plAvTask.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plAvTaskBrain
Push a new brain onto the avatar or pull an old brain off.
If a brain is supplied, it's a push. Otherwise it's a pull.
*/
class plAvTaskBrain : public plAvTask
{
public:
/** Default constructor. Used as is, will function as a pop brain message. */
plAvTaskBrain();
/** Constructor for a push configuration. If the brain is non, nil, it
will be pushed onto the receiving avatar when the task is dequeued.
If the brain is nil, the current brain will be popped. */
plAvTaskBrain(plArmatureBrain *brain);
virtual ~plAvTaskBrain();
// task protocol
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual void Finish(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** dump descriptive stuff to the given debug text */
virtual void DumpDebug(const char *name, int &x, int&y, int lineHeight, char *strBuf, plDebugText &debugTxt);
plArmatureBrain *GetBrain();
CLASSNAME_REGISTER( plAvTaskBrain );
GETINTERFACE_ANY( plAvTaskBrain, plAvTask );
/** Read the task from a stream. Not all tasks need to read/write, so the base implementation
gives a warning to expose tasks that are being read/written unexpectedly. */
virtual void Read(hsStream *stream, hsResMgr *mgr);
/** Write the task to a stream. Not all tasks need to read/write, so the base implementation
gives a warning to expose tasks that are being read/written unexpectedly. */
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
plArmatureBrain *fBrain;
};
#endif

View File

@ -1,26 +1,26 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// obsolete

View File

@ -1,26 +1,26 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// obsolete

File diff suppressed because it is too large Load Diff

View File

@ -1,174 +1,174 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVTASKSEEK_INC
#define PLAVTASKSEEK_INC
#pragma once
#include "plAvatarTasks.h"
#include "hsQuat.h"
#include "hsGeometry3.h"
class plArmatureMod;
class plArmatureBrain;
class plAvBrainHuman;
class plSceneObject;
// PLAVTASKSEEK
class plAvTaskSeek : public plAvTask
{
public:
static hsBool fLogProcess;
enum State {
kSeekRunNormal,
kSeekAbort,
};
UInt8 fState;
enum
{
kSeekFlagUnForce3rdPersonOnFinish = 0x1,
kSeekFlagForce3rdPersonOnStart = 0x2,
kSeekFlagNoWarpOnTimeout = 0x4,
kSeekFlagRotationOnly = 0x8,
};
plAvTaskSeek();
plAvTaskSeek(plKey target);
plAvTaskSeek(plAvSeekMsg *msg);
plAvTaskSeek(plKey target, plAvAlignment align, const char *animName, bool moving);
void SetTarget(plKey target);
void SetTarget(hsPoint3 &pos, hsPoint3 &lookAt);
/** Initiate the task; make sure we're running on the right type of brain, save off
user input state, and turn off any other running behaviors.*/
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** Progress towards the goal using a combination of walking and cheating-via-sliding.
Returns true if we're still working on it; false if we're done. */
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** Restore user input state, etc. */
virtual void Finish(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** clear our target, and when we try to eval, we'll just finish */
virtual void LeaveAge(plArmatureMod *avatar);
/** Spew "useful" information to the game screen. Used when Avatar.Debug is active. */
virtual void DumpDebug(const char *name, int &x, int&y, int lineHeight, char *strBuf, plDebugText &debugTxt);
void DumpToAvatarLog(plArmatureMod *avatar);
CLASSNAME_REGISTER( plAvTaskSeek );
GETINTERFACE_ANY( plAvTaskSeek, plAvTask );
protected:
/////////////////////////////////////////////////////////////////////////////////////
//
// METHODS
//
/////////////////////////////////////////////////////////////////////////////////////
/** Called by constructors */
void IInitDefaults();
/** Make some observations about our current relation to our target.
Done every frame. */
hsBool IAnalyze(plArmatureMod *avatar);
/** Progress towards the goal. We get as close as we can by just pushing the same
buttons as the user (forward, turn, etc.) when we're really close we slide
around a bit so we can wind up on the *exact* initial orientation. */
hsBool IMoveTowardsGoal(plArmatureMod *avatar, plAvBrainHuman *brain, double time, hsScalar elapsed);
/** Okay, we're in the pure cheating mode now. Try to wrap it up;
returns true when it's finally there. */
bool ITryFinish(plArmatureMod *avatar, plAvBrainHuman *brain, double time, hsScalar elapsed);
/** Final cheating for position */
hsBool IFinishPosition(hsPoint3 &newPosition, plArmatureMod *avatar, plAvBrainHuman *brain,
double time, hsScalar elapsed);
/** Final cheating for rotation */
hsBool IFinishRotation(hsQuat &newRotation, plArmatureMod *avatar, plAvBrainHuman *brain,
double time, hsScalar elapsed);
/** If our target's moving, cache its new position and orientation for later math */
hsBool IUpdateObjective(plArmatureMod *avatar);
/////////////////////////////////////////////////////////////////////////////////////
//
// VARS
//
/////////////////////////////////////////////////////////////////////////////////////
plSceneObject * fSeekObject; // the seek target....
hsQuat fSeekRot; // The (current) orientation of our objective
hsPoint3 fSeekPos; // The (current) position of our objective
bool fMovingTarget; // do we check our target's position each frame?
// animation alignment:
// sometimes your seek position depends on a particular animation
// for example, you can say "find a good start point so that you can play this animation
// and have your handle wind up here" i.e: aligntype = "kAlignHandleAnimEnd"
plAvAlignment fAlign; // how to line up with the seek point
const char * fAnimName; // an (optional) anim to use to line up our target
// so you can say "seek to a place where your hand
// will be here after you play animation foo"
hsPoint3 fPosition; // our current position
hsQuat fRotation; // our current rotation
// These are set to true once we EVER get close enough to the goal, so that if we fall out
// of range from the anim blend out, we don't later try and correct again, and get in a fun
// little back-and-forth loop.
hsBool fPosGoalHit;
hsBool fRotGoalHit;
hsBool fStillPositioning; // haven't yet reached the final position
hsBool fStillRotating; // haven't yet reached the final orientation
hsVector3 fGoalVec; // vec from us to the goal
hsScalar fDistance; // how far to the goal?
hsScalar fAngForward; // 1.0 = goal is forward; -1.0 = goal is backward
hsScalar fAngRight; // 1.0 = goal is directly right; -1.0 = goal is directly left
hsScalar fDistForward; // distance straight forward to goal plane
hsScalar fDistRight; // distance straight right to goal plane
hsScalar fShuffleRange;
hsScalar fMaxSidleAngle; // in right . goal
hsScalar fMaxSidleRange; // in feet
hsScalar fMinFwdAngle; // in fwd . goal
hsScalar fMaxBackAngle; // in fwd . goal
double fStartTime;
UInt8 fFlags;
plKey fNotifyFinishedKey; // Send a message to this key when we're done.
};
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVTASKSEEK_INC
#define PLAVTASKSEEK_INC
#pragma once
#include "plAvatarTasks.h"
#include "hsQuat.h"
#include "hsGeometry3.h"
class plArmatureMod;
class plArmatureBrain;
class plAvBrainHuman;
class plSceneObject;
// PLAVTASKSEEK
class plAvTaskSeek : public plAvTask
{
public:
static hsBool fLogProcess;
enum State {
kSeekRunNormal,
kSeekAbort,
};
UInt8 fState;
enum
{
kSeekFlagUnForce3rdPersonOnFinish = 0x1,
kSeekFlagForce3rdPersonOnStart = 0x2,
kSeekFlagNoWarpOnTimeout = 0x4,
kSeekFlagRotationOnly = 0x8,
};
plAvTaskSeek();
plAvTaskSeek(plKey target);
plAvTaskSeek(plAvSeekMsg *msg);
plAvTaskSeek(plKey target, plAvAlignment align, const char *animName, bool moving);
void SetTarget(plKey target);
void SetTarget(hsPoint3 &pos, hsPoint3 &lookAt);
/** Initiate the task; make sure we're running on the right type of brain, save off
user input state, and turn off any other running behaviors.*/
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** Progress towards the goal using a combination of walking and cheating-via-sliding.
Returns true if we're still working on it; false if we're done. */
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** Restore user input state, etc. */
virtual void Finish(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
/** clear our target, and when we try to eval, we'll just finish */
virtual void LeaveAge(plArmatureMod *avatar);
/** Spew "useful" information to the game screen. Used when Avatar.Debug is active. */
virtual void DumpDebug(const char *name, int &x, int&y, int lineHeight, char *strBuf, plDebugText &debugTxt);
void DumpToAvatarLog(plArmatureMod *avatar);
CLASSNAME_REGISTER( plAvTaskSeek );
GETINTERFACE_ANY( plAvTaskSeek, plAvTask );
protected:
/////////////////////////////////////////////////////////////////////////////////////
//
// METHODS
//
/////////////////////////////////////////////////////////////////////////////////////
/** Called by constructors */
void IInitDefaults();
/** Make some observations about our current relation to our target.
Done every frame. */
hsBool IAnalyze(plArmatureMod *avatar);
/** Progress towards the goal. We get as close as we can by just pushing the same
buttons as the user (forward, turn, etc.) when we're really close we slide
around a bit so we can wind up on the *exact* initial orientation. */
hsBool IMoveTowardsGoal(plArmatureMod *avatar, plAvBrainHuman *brain, double time, hsScalar elapsed);
/** Okay, we're in the pure cheating mode now. Try to wrap it up;
returns true when it's finally there. */
bool ITryFinish(plArmatureMod *avatar, plAvBrainHuman *brain, double time, hsScalar elapsed);
/** Final cheating for position */
hsBool IFinishPosition(hsPoint3 &newPosition, plArmatureMod *avatar, plAvBrainHuman *brain,
double time, hsScalar elapsed);
/** Final cheating for rotation */
hsBool IFinishRotation(hsQuat &newRotation, plArmatureMod *avatar, plAvBrainHuman *brain,
double time, hsScalar elapsed);
/** If our target's moving, cache its new position and orientation for later math */
hsBool IUpdateObjective(plArmatureMod *avatar);
/////////////////////////////////////////////////////////////////////////////////////
//
// VARS
//
/////////////////////////////////////////////////////////////////////////////////////
plSceneObject * fSeekObject; // the seek target....
hsQuat fSeekRot; // The (current) orientation of our objective
hsPoint3 fSeekPos; // The (current) position of our objective
bool fMovingTarget; // do we check our target's position each frame?
// animation alignment:
// sometimes your seek position depends on a particular animation
// for example, you can say "find a good start point so that you can play this animation
// and have your handle wind up here" i.e: aligntype = "kAlignHandleAnimEnd"
plAvAlignment fAlign; // how to line up with the seek point
const char * fAnimName; // an (optional) anim to use to line up our target
// so you can say "seek to a place where your hand
// will be here after you play animation foo"
hsPoint3 fPosition; // our current position
hsQuat fRotation; // our current rotation
// These are set to true once we EVER get close enough to the goal, so that if we fall out
// of range from the anim blend out, we don't later try and correct again, and get in a fun
// little back-and-forth loop.
hsBool fPosGoalHit;
hsBool fRotGoalHit;
hsBool fStillPositioning; // haven't yet reached the final position
hsBool fStillRotating; // haven't yet reached the final orientation
hsVector3 fGoalVec; // vec from us to the goal
hsScalar fDistance; // how far to the goal?
hsScalar fAngForward; // 1.0 = goal is forward; -1.0 = goal is backward
hsScalar fAngRight; // 1.0 = goal is directly right; -1.0 = goal is directly left
hsScalar fDistForward; // distance straight forward to goal plane
hsScalar fDistRight; // distance straight right to goal plane
hsScalar fShuffleRange;
hsScalar fMaxSidleAngle; // in right . goal
hsScalar fMaxSidleRange; // in feet
hsScalar fMinFwdAngle; // in fwd . goal
hsScalar fMaxBackAngle; // in fwd . goal
double fStartTime;
UInt8 fFlags;
plKey fNotifyFinishedKey; // Send a message to this key when we're done.
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,313 +1,313 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVATARCLOTHING_INC
#define PLAVATARCLOTHING_INC
#include "pnUtils/pnUtils.h"
#include "pnNetCommon/plSynchedObject.h"
#include "hsColorRGBA.h"
#include "hsBitVector.h"
#include "plClothingLayout.h"
class hsGMaterial;
class plMipmap;
class plLayer;
class hsStream;
class plSceneObject;
class plGeometrySpan;
class plClothingLayout;
class plClothingElement;
class plArmatureMod;
class plSharedMesh;
class plStateDataRecord;
class plDXPipeline;
class plClothingItemOptions
{
public:
hsColorRGBA fTint1;
hsColorRGBA fTint2;
plClothingItemOptions() { fTint1.Set(1.f, 1.f, 1.f, 1.f); fTint2.Set(1.f, 1.f, 1.f, 1.f); }
hsBool IsMatch(plClothingItemOptions *other) { return fTint1 == other->fTint1 && fTint2 == other->fTint2; }
};
class plClothingItem : public hsKeyedObject
{
public:
enum
{
kLODHigh,
kLODMedium,
kLODLow,
kMaxNumLODLevels,
};
// If you change the format of a clothing item, chances are you need
// to change plClothingMgr::IsLRMatch() as well
char *fName;
plSharedMesh *fMeshes[kMaxNumLODLevels];
hsTArray<plMipmap **> fTextures;
hsTArray<char *> fElementNames;
hsTArray<plClothingElement *> fElements;
UInt8 fGroup; // Each avatar can wear one of the available groups
UInt8 fType; // Each group has multiple types of clothes (shirt/pants/etc)
UInt8 fTileset;
UInt8 fSortOrder;
char *fDescription;
char *fCustomText;
plMipmap *fThumbnail;
plClothingItem *fAccessory; // Forced accessory to always wear with this item.
UInt8 fDefaultTint1[3];
UInt8 fDefaultTint2[3];
char *fAccessoryName; // Export only
plClothingItem();
~plClothingItem();
CLASSNAME_REGISTER( plClothingItem );
GETINTERFACE_ANY( plClothingItem, hsKeyedObject );
void SetName(char *name) { delete fName; fName = hsStrcpy(name); }
const char* GetName() { return fName; }
hsBool CanWearWith(plClothingItem *item);
hsBool WearBefore(plClothingItem *item); // Should we come before the arg item? (texture gen order)
hsBool HasBaseAlpha();
hsBool HasSameMeshes(plClothingItem *other);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
class plClosetItem
{
public:
plClosetItem() : fItem(nil) {}
plClothingItem *fItem;
plClothingItemOptions fOptions;
hsBool IsMatch(plClosetItem *other);
};
class plClothingBase : public hsKeyedObject
{
public:
char *fName;
plMipmap *fBaseTexture;
char *fLayoutName;
plClothingBase();
~plClothingBase();
CLASSNAME_REGISTER( plClothingBase );
GETINTERFACE_ANY( plClothingBase, hsKeyedObject );
void SetLayoutName(char *name) { delete fLayoutName; fLayoutName = hsStrcpy(name); }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
class plClothingOutfit : public plSynchedObject
{
friend class plDXPipeline;
public:
plArmatureMod *fAvatar;
plLayer *fTargetLayer;
hsGMaterial *fMaterial; // Needed to tell swapped geometry what material to use.
hsTArray<plClothingItem*> fItems;
hsTArray<plClothingItemOptions*> fOptions;
plClothingBase *fBase;
UInt8 fGroup;
bool fSynchClients; // set true if the next synch should be bcast
hsColorRGBA fSkinTint;
hsScalar fSkinBlends[plClothingElement::kLayerSkinLast - plClothingElement::kLayerSkinFirst]; // Controls the opacity between skin textures.
plClothingOutfit();
~plClothingOutfit();
CLASSNAME_REGISTER( plClothingOutfit );
GETINTERFACE_ANY( plClothingOutfit, plSynchedObject );
void SaveCustomizations(hsBool retry = true);
void AddItem(plClothingItem *item, hsBool update = true, hsBool broadcast = true, hsBool netForce=false);
void RemoveItem(plClothingItem *item, hsBool update = true, hsBool netForce=false);
void TintItem(plClothingItem *item, hsScalar red, hsScalar green, hsScalar blue, hsBool update = true, hsBool broadcast = true,
hsBool netForce = false, hsBool retry = true, UInt8 fLayer = plClothingElement::kLayerTint1);
void TintSkin(hsScalar red, hsScalar green, hsScalar blue,
hsBool update = true, hsBool broadcast = true);
void MorphItem(plClothingItem *item, UInt8 layer, UInt8 delta, hsScalar weight, hsBool retry = true);
void SetAge(hsScalar age, hsBool update = true, hsBool broadcast = true);
void SetSkinBlend(hsScalar blend, UInt8 layer, hsBool update = true, hsBool broadcast = true);
hsScalar GetSkinBlend(UInt8 layer);
hsColorRGBA GetItemTint(plClothingItem *item, UInt8 layer = 2) const;
hsScalar GetAge() const { return fSkinBlends[0]; }
hsTArray<plClothingItem*> &GetItemList() { return fItems; }
hsTArray<plClothingItemOptions*> &GetOptionList() { return fOptions; }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
hsBool DirtySynchState(const char* SDLStateName, UInt32 synchFlags);
void StripAccessories();
void WearDefaultClothing();
void WearDefaultClothingType(UInt32 clothingType);
void WearMaintainerOutfit();
void WearRandomOutfit();
void RemoveMaintainerOutfit();
hsBool ReadItems(hsStream* s, hsResMgr* mgr, hsBool broadcast = true);
void WriteItems(hsStream* s, hsResMgr* mgr);
void ForceUpdate(bool retry); // send updateTexture msg
virtual hsBool MsgReceive(plMessage* msg);
void IInstanceSharedMeshes(plClothingItem *item);
void IRemoveSharedMeshes(plClothingItem *item);
void ReadFromVault();
void WriteToVault();
void WriteToVault(const ARRAY(plStateDataRecord*) & SDRs);
void SetupMorphSDL();
// XXX Don't use this. Temp function for a temp HACK console command.
void DirtyTileset(int tileset);
protected:
hsBitVector fDirtyItems;
hsBool fVaultSaveEnabled;
bool fMorphsInitDone;
void IAddItem(plClothingItem *item);
void IRemoveItem(plClothingItem *item);
hsBool ITintItem(plClothingItem *item, hsColorRGBA color, UInt8 layer);
hsBool IMorphItem(plClothingItem *item, UInt8 layer, UInt8 delta, hsScalar weight);
void IHandleMorphSDR(plStateDataRecord *sdr);
void IUpdate();
};
class plClothingMgr : public hsKeyedObject
{
protected:
static plClothingMgr *fInstance;
hsTArray<plClothingElement*> fElements;
hsTArray<plClothingItem*> fItems;
hsTArray<plClothingLayout*> fLayouts;
void IInit();
void IAddItem(plClothingItem *item);
public:
plClothingMgr();
~plClothingMgr();
CLASSNAME_REGISTER( plClothingMgr );
GETINTERFACE_ANY( plClothingMgr, hsKeyedObject );
plClothingLayout *GetLayout(char *name);
plClothingElement *FindElementByName(char *name);
// Functions that just relate to the clothing you have permission to wear (closet)
void AddItemsToCloset(hsTArray<plClosetItem> &items);
void GetClosetItems(hsTArray<plClosetItem> &out);
// Functions that relate to all existing clothing
plClothingItem *FindItemByName(const char *name);
hsTArray<plClothingItem*>& GetItemList() { return fItems; }
void GetItemsByGroup(UInt8 group, hsTArray<plClothingItem*> &out);
void GetItemsByGroupAndType(UInt8 group, UInt8 type, hsTArray<plClothingItem*> &out);
void GetAllWithSameMesh(plClothingItem *item, hsTArray<plClothingItem*> &out);
// Give an array of items (from one of the above functions, for example)
// and this will yank out items so that only item is in the array for each mesh.
void FilterUniqueMeshes(hsTArray<plClothingItem*> &items);
// For a pair of items that go together (ie gloves) give us one, we'll give you the other
plClothingItem *GetLRMatch(plClothingItem *item);
hsBool IsLRMatch(plClothingItem *item1, plClothingItem *item2);
static void ChangeAvatar(char *name);
static plClothingMgr *GetClothingMgr() { return fInstance; }
static void Init();
static void DeInit();
//virtual void Read(hsStream* s, hsResMgr* mgr);
//virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
// NOTE:
// NOTE:
// NOTE: The following two enums are duplicated in Python, so...
// DON'T CHANGE THEIR CURRENT VALUES, ADD NEW ONES ON THE END OF THE LIST!
enum
{
kClothingBaseMale = 0,
kClothingBaseFemale,
kClothingBaseNoOptions, // Custom avatars
kMaxGroup
};
enum
{
kTypePants = 0,
kTypeShirt,
kTypeLeftHand,
kTypeRightHand,
kTypeFace,
kTypeHair,
kTypeLeftFoot,
kTypeRightFoot,
kTypeAccessory,
kMaxType,
};
static const char *GroupStrings[];
static const char *TypeStrings[];
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLAVATARCLOTHING_INC
#define PLAVATARCLOTHING_INC
#include "pnUtils/pnUtils.h"
#include "pnNetCommon/plSynchedObject.h"
#include "hsColorRGBA.h"
#include "hsBitVector.h"
#include "plClothingLayout.h"
class hsGMaterial;
class plMipmap;
class plLayer;
class hsStream;
class plSceneObject;
class plGeometrySpan;
class plClothingLayout;
class plClothingElement;
class plArmatureMod;
class plSharedMesh;
class plStateDataRecord;
class plDXPipeline;
class plClothingItemOptions
{
public:
hsColorRGBA fTint1;
hsColorRGBA fTint2;
plClothingItemOptions() { fTint1.Set(1.f, 1.f, 1.f, 1.f); fTint2.Set(1.f, 1.f, 1.f, 1.f); }
hsBool IsMatch(plClothingItemOptions *other) { return fTint1 == other->fTint1 && fTint2 == other->fTint2; }
};
class plClothingItem : public hsKeyedObject
{
public:
enum
{
kLODHigh,
kLODMedium,
kLODLow,
kMaxNumLODLevels,
};
// If you change the format of a clothing item, chances are you need
// to change plClothingMgr::IsLRMatch() as well
char *fName;
plSharedMesh *fMeshes[kMaxNumLODLevels];
hsTArray<plMipmap **> fTextures;
hsTArray<char *> fElementNames;
hsTArray<plClothingElement *> fElements;
UInt8 fGroup; // Each avatar can wear one of the available groups
UInt8 fType; // Each group has multiple types of clothes (shirt/pants/etc)
UInt8 fTileset;
UInt8 fSortOrder;
char *fDescription;
char *fCustomText;
plMipmap *fThumbnail;
plClothingItem *fAccessory; // Forced accessory to always wear with this item.
UInt8 fDefaultTint1[3];
UInt8 fDefaultTint2[3];
char *fAccessoryName; // Export only
plClothingItem();
~plClothingItem();
CLASSNAME_REGISTER( plClothingItem );
GETINTERFACE_ANY( plClothingItem, hsKeyedObject );
void SetName(char *name) { delete fName; fName = hsStrcpy(name); }
const char* GetName() { return fName; }
hsBool CanWearWith(plClothingItem *item);
hsBool WearBefore(plClothingItem *item); // Should we come before the arg item? (texture gen order)
hsBool HasBaseAlpha();
hsBool HasSameMeshes(plClothingItem *other);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
class plClosetItem
{
public:
plClosetItem() : fItem(nil) {}
plClothingItem *fItem;
plClothingItemOptions fOptions;
hsBool IsMatch(plClosetItem *other);
};
class plClothingBase : public hsKeyedObject
{
public:
char *fName;
plMipmap *fBaseTexture;
char *fLayoutName;
plClothingBase();
~plClothingBase();
CLASSNAME_REGISTER( plClothingBase );
GETINTERFACE_ANY( plClothingBase, hsKeyedObject );
void SetLayoutName(char *name) { delete fLayoutName; fLayoutName = hsStrcpy(name); }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
};
class plClothingOutfit : public plSynchedObject
{
friend class plDXPipeline;
public:
plArmatureMod *fAvatar;
plLayer *fTargetLayer;
hsGMaterial *fMaterial; // Needed to tell swapped geometry what material to use.
hsTArray<plClothingItem*> fItems;
hsTArray<plClothingItemOptions*> fOptions;
plClothingBase *fBase;
UInt8 fGroup;
bool fSynchClients; // set true if the next synch should be bcast
hsColorRGBA fSkinTint;
hsScalar fSkinBlends[plClothingElement::kLayerSkinLast - plClothingElement::kLayerSkinFirst]; // Controls the opacity between skin textures.
plClothingOutfit();
~plClothingOutfit();
CLASSNAME_REGISTER( plClothingOutfit );
GETINTERFACE_ANY( plClothingOutfit, plSynchedObject );
void SaveCustomizations(hsBool retry = true);
void AddItem(plClothingItem *item, hsBool update = true, hsBool broadcast = true, hsBool netForce=false);
void RemoveItem(plClothingItem *item, hsBool update = true, hsBool netForce=false);
void TintItem(plClothingItem *item, hsScalar red, hsScalar green, hsScalar blue, hsBool update = true, hsBool broadcast = true,
hsBool netForce = false, hsBool retry = true, UInt8 fLayer = plClothingElement::kLayerTint1);
void TintSkin(hsScalar red, hsScalar green, hsScalar blue,
hsBool update = true, hsBool broadcast = true);
void MorphItem(plClothingItem *item, UInt8 layer, UInt8 delta, hsScalar weight, hsBool retry = true);
void SetAge(hsScalar age, hsBool update = true, hsBool broadcast = true);
void SetSkinBlend(hsScalar blend, UInt8 layer, hsBool update = true, hsBool broadcast = true);
hsScalar GetSkinBlend(UInt8 layer);
hsColorRGBA GetItemTint(plClothingItem *item, UInt8 layer = 2) const;
hsScalar GetAge() const { return fSkinBlends[0]; }
hsTArray<plClothingItem*> &GetItemList() { return fItems; }
hsTArray<plClothingItemOptions*> &GetOptionList() { return fOptions; }
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
hsBool DirtySynchState(const char* SDLStateName, UInt32 synchFlags);
void StripAccessories();
void WearDefaultClothing();
void WearDefaultClothingType(UInt32 clothingType);
void WearMaintainerOutfit();
void WearRandomOutfit();
void RemoveMaintainerOutfit();
hsBool ReadItems(hsStream* s, hsResMgr* mgr, hsBool broadcast = true);
void WriteItems(hsStream* s, hsResMgr* mgr);
void ForceUpdate(bool retry); // send updateTexture msg
virtual hsBool MsgReceive(plMessage* msg);
void IInstanceSharedMeshes(plClothingItem *item);
void IRemoveSharedMeshes(plClothingItem *item);
void ReadFromVault();
void WriteToVault();
void WriteToVault(const ARRAY(plStateDataRecord*) & SDRs);
void SetupMorphSDL();
// XXX Don't use this. Temp function for a temp HACK console command.
void DirtyTileset(int tileset);
protected:
hsBitVector fDirtyItems;
hsBool fVaultSaveEnabled;
bool fMorphsInitDone;
void IAddItem(plClothingItem *item);
void IRemoveItem(plClothingItem *item);
hsBool ITintItem(plClothingItem *item, hsColorRGBA color, UInt8 layer);
hsBool IMorphItem(plClothingItem *item, UInt8 layer, UInt8 delta, hsScalar weight);
void IHandleMorphSDR(plStateDataRecord *sdr);
void IUpdate();
};
class plClothingMgr : public hsKeyedObject
{
protected:
static plClothingMgr *fInstance;
hsTArray<plClothingElement*> fElements;
hsTArray<plClothingItem*> fItems;
hsTArray<plClothingLayout*> fLayouts;
void IInit();
void IAddItem(plClothingItem *item);
public:
plClothingMgr();
~plClothingMgr();
CLASSNAME_REGISTER( plClothingMgr );
GETINTERFACE_ANY( plClothingMgr, hsKeyedObject );
plClothingLayout *GetLayout(char *name);
plClothingElement *FindElementByName(char *name);
// Functions that just relate to the clothing you have permission to wear (closet)
void AddItemsToCloset(hsTArray<plClosetItem> &items);
void GetClosetItems(hsTArray<plClosetItem> &out);
// Functions that relate to all existing clothing
plClothingItem *FindItemByName(const char *name);
hsTArray<plClothingItem*>& GetItemList() { return fItems; }
void GetItemsByGroup(UInt8 group, hsTArray<plClothingItem*> &out);
void GetItemsByGroupAndType(UInt8 group, UInt8 type, hsTArray<plClothingItem*> &out);
void GetAllWithSameMesh(plClothingItem *item, hsTArray<plClothingItem*> &out);
// Give an array of items (from one of the above functions, for example)
// and this will yank out items so that only item is in the array for each mesh.
void FilterUniqueMeshes(hsTArray<plClothingItem*> &items);
// For a pair of items that go together (ie gloves) give us one, we'll give you the other
plClothingItem *GetLRMatch(plClothingItem *item);
hsBool IsLRMatch(plClothingItem *item1, plClothingItem *item2);
static void ChangeAvatar(char *name);
static plClothingMgr *GetClothingMgr() { return fInstance; }
static void Init();
static void DeInit();
//virtual void Read(hsStream* s, hsResMgr* mgr);
//virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
// NOTE:
// NOTE:
// NOTE: The following two enums are duplicated in Python, so...
// DON'T CHANGE THEIR CURRENT VALUES, ADD NEW ONES ON THE END OF THE LIST!
enum
{
kClothingBaseMale = 0,
kClothingBaseFemale,
kClothingBaseNoOptions, // Custom avatars
kMaxGroup
};
enum
{
kTypePants = 0,
kTypeShirt,
kTypeLeftHand,
kTypeRightHand,
kTypeFace,
kTypeHair,
kTypeLeftFoot,
kTypeRightFoot,
kTypeAccessory,
kMaxType,
};
static const char *GroupStrings[];
static const char *TypeStrings[];
};
#endif

View File

@ -1,198 +1,198 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvatarCreatable_inc
#define plAvatarCreatable_inc
#include "pnFactory/plCreator.h"
#include "plAGAnim.h"
REGISTER_CREATABLE( plAGAnim );
REGISTER_CREATABLE( plATCAnim );
REGISTER_CREATABLE( plEmoteAnim );
REGISTER_CREATABLE( plAgeGlobalAnim );
#include "plAGChannel.h"
REGISTER_NONCREATABLE( plAGChannel );
REGISTER_NONCREATABLE( plAGApplicator );
#include "plMatrixChannel.h"
REGISTER_CREATABLE( plMatrixChannel );
REGISTER_CREATABLE( plMatrixConstant );
REGISTER_CREATABLE( plMatrixTimeScale );
REGISTER_CREATABLE( plMatrixBlend );
REGISTER_CREATABLE( plMatrixControllerChannel );
REGISTER_CREATABLE( plMatrixControllerCacheChannel );
REGISTER_CREATABLE( plQuatPointCombine );
REGISTER_CREATABLE( plMatrixChannelApplicator );
REGISTER_CREATABLE( plMatrixDelayedCorrectionApplicator );
REGISTER_CREATABLE( plMatrixDifferenceApp );
#include "plPointChannel.h"
REGISTER_CREATABLE( plPointChannel );
REGISTER_CREATABLE( plPointConstant );
REGISTER_CREATABLE( plPointBlend );
REGISTER_CREATABLE( plPointTimeScale );
REGISTER_CREATABLE( plPointControllerChannel );
REGISTER_CREATABLE( plPointControllerCacheChannel );
REGISTER_CREATABLE( plPointChannelApplicator );
REGISTER_CREATABLE( plLightDiffuseApplicator );
REGISTER_CREATABLE( plLightAmbientApplicator );
REGISTER_CREATABLE( plLightSpecularApplicator );
#include "plQuatChannel.h"
REGISTER_CREATABLE( plQuatChannel );
REGISTER_CREATABLE( plQuatConstant );
REGISTER_CREATABLE( plQuatBlend );
REGISTER_CREATABLE( plQuatTimeScale );
REGISTER_CREATABLE( plQuatChannelApplicator );
#include "plScalarChannel.h"
REGISTER_CREATABLE( plScalarChannel );
REGISTER_CREATABLE( plScalarConstant );
REGISTER_CREATABLE( plScalarTimeScale );
REGISTER_CREATABLE( plScalarBlend );
REGISTER_CREATABLE( plScalarControllerChannel );
REGISTER_CREATABLE( plScalarControllerCacheChannel );
REGISTER_CREATABLE( plScalarChannelApplicator );
REGISTER_CREATABLE( plSpotInnerApplicator );
REGISTER_CREATABLE( plSpotOuterApplicator );
REGISTER_CREATABLE( plATCChannel );
REGISTER_CREATABLE( plScalarSDLChannel );
REGISTER_CREATABLE( plOmniApplicator );
REGISTER_CREATABLE( plOmniSqApplicator );
REGISTER_CREATABLE( plOmniCutoffApplicator );
#include "plAGModifier.h"
REGISTER_CREATABLE( plAGModifier );
#include "plAGMasterMod.h"
REGISTER_CREATABLE( plAGMasterMod );
#include "plSeekPointMod.h"
REGISTER_CREATABLE( plSeekPointMod );
#include "plOneShotMod.h"
REGISTER_CREATABLE( plOneShotMod );
#include "plMultistageBehMod.h"
REGISTER_CREATABLE( plMultistageBehMod );
#include "plArmatureMod.h"
REGISTER_CREATABLE( plArmatureModBase );
REGISTER_CREATABLE( plArmatureMod );
REGISTER_CREATABLE( plArmatureLODMod );
#include "plArmatureEffects.h"
REGISTER_CREATABLE( plArmatureEffectsMgr );
REGISTER_NONCREATABLE( plArmatureEffect );
REGISTER_CREATABLE( plArmatureEffectFootSound );
#include "plAvBrain.h"
REGISTER_NONCREATABLE(plArmatureBrain);
#include "plAvBrainHuman.h"
REGISTER_CREATABLE(plAvBrainHuman);
#include "plAvBrainDrive.h"
REGISTER_CREATABLE(plAvBrainDrive);
#include "plAvLadderModifier.h"
REGISTER_CREATABLE( plAvLadderMod );
#include "plAvatarClothing.h"
REGISTER_CREATABLE(plClothingItem);
REGISTER_CREATABLE(plClothingOutfit);
REGISTER_CREATABLE(plClothingBase);
REGISTER_CREATABLE(plClothingMgr);
#include "plAvBrainGeneric.h"
REGISTER_CREATABLE(plAvBrainGeneric);
#include "plAvatarTasks.h"
REGISTER_NONCREATABLE( plAvTask );
REGISTER_CREATABLE( plAvAnimTask );
REGISTER_CREATABLE( plAvSeekTask )
REGISTER_CREATABLE( plAvOneShotTask );
REGISTER_CREATABLE( plAvOneShotLinkTask );
#include "plAnimStage.h"
REGISTER_CREATABLE( plAnimStage );
#include "plAvTaskSeek.h"
REGISTER_CREATABLE( plAvTaskSeek );
#include "plAGMasterSDLModifier.h"
REGISTER_CREATABLE( plAGMasterSDLModifier );
#include "plAvatarSDLModifier.h"
REGISTER_CREATABLE( plAvatarSDLModifier );
REGISTER_CREATABLE( plAvatarPhysicalSDLModifier );
#include "plClothingSDLModifier.h"
REGISTER_CREATABLE( plClothingSDLModifier );
#include "plAvatarMgr.h"
REGISTER_NONCREATABLE( plAvatarMgr );
#include "plNPCSpawnMod.h"
REGISTER_CREATABLE( plNPCSpawnMod );
#include "plAvBrainSwim.h"
REGISTER_CREATABLE( plAvBrainSwim );
#include "plAvBrainClimb.h"
REGISTER_CREATABLE( plAvBrainClimb );
#include "plAvBrainCoop.h"
REGISTER_CREATABLE( plAvBrainCoop );
#include "plCoopCoordinator.h"
REGISTER_CREATABLE( plCoopCoordinator );
#include "plAvTaskBrain.h"
REGISTER_CREATABLE( plAvTaskBrain );
#include "plSittingModifier.h"
REGISTER_CREATABLE( plSittingModifier );
#include "plSwimRegion.h"
REGISTER_CREATABLE( plSwimRegionInterface );
REGISTER_CREATABLE( plSwimCircularCurrentRegion );
REGISTER_CREATABLE( plSwimStraightCurrentRegion );
#include "plAvBrainCritter.h"
REGISTER_CREATABLE( plAvBrainCritter );
#include "plAvBrainRideAnimatedPhysical.h"
REGISTER_CREATABLE(plAvBrainRideAnimatedPhysical)
#endif // plAvatarCreatable_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvatarCreatable_inc
#define plAvatarCreatable_inc
#include "pnFactory/plCreator.h"
#include "plAGAnim.h"
REGISTER_CREATABLE( plAGAnim );
REGISTER_CREATABLE( plATCAnim );
REGISTER_CREATABLE( plEmoteAnim );
REGISTER_CREATABLE( plAgeGlobalAnim );
#include "plAGChannel.h"
REGISTER_NONCREATABLE( plAGChannel );
REGISTER_NONCREATABLE( plAGApplicator );
#include "plMatrixChannel.h"
REGISTER_CREATABLE( plMatrixChannel );
REGISTER_CREATABLE( plMatrixConstant );
REGISTER_CREATABLE( plMatrixTimeScale );
REGISTER_CREATABLE( plMatrixBlend );
REGISTER_CREATABLE( plMatrixControllerChannel );
REGISTER_CREATABLE( plMatrixControllerCacheChannel );
REGISTER_CREATABLE( plQuatPointCombine );
REGISTER_CREATABLE( plMatrixChannelApplicator );
REGISTER_CREATABLE( plMatrixDelayedCorrectionApplicator );
REGISTER_CREATABLE( plMatrixDifferenceApp );
#include "plPointChannel.h"
REGISTER_CREATABLE( plPointChannel );
REGISTER_CREATABLE( plPointConstant );
REGISTER_CREATABLE( plPointBlend );
REGISTER_CREATABLE( plPointTimeScale );
REGISTER_CREATABLE( plPointControllerChannel );
REGISTER_CREATABLE( plPointControllerCacheChannel );
REGISTER_CREATABLE( plPointChannelApplicator );
REGISTER_CREATABLE( plLightDiffuseApplicator );
REGISTER_CREATABLE( plLightAmbientApplicator );
REGISTER_CREATABLE( plLightSpecularApplicator );
#include "plQuatChannel.h"
REGISTER_CREATABLE( plQuatChannel );
REGISTER_CREATABLE( plQuatConstant );
REGISTER_CREATABLE( plQuatBlend );
REGISTER_CREATABLE( plQuatTimeScale );
REGISTER_CREATABLE( plQuatChannelApplicator );
#include "plScalarChannel.h"
REGISTER_CREATABLE( plScalarChannel );
REGISTER_CREATABLE( plScalarConstant );
REGISTER_CREATABLE( plScalarTimeScale );
REGISTER_CREATABLE( plScalarBlend );
REGISTER_CREATABLE( plScalarControllerChannel );
REGISTER_CREATABLE( plScalarControllerCacheChannel );
REGISTER_CREATABLE( plScalarChannelApplicator );
REGISTER_CREATABLE( plSpotInnerApplicator );
REGISTER_CREATABLE( plSpotOuterApplicator );
REGISTER_CREATABLE( plATCChannel );
REGISTER_CREATABLE( plScalarSDLChannel );
REGISTER_CREATABLE( plOmniApplicator );
REGISTER_CREATABLE( plOmniSqApplicator );
REGISTER_CREATABLE( plOmniCutoffApplicator );
#include "plAGModifier.h"
REGISTER_CREATABLE( plAGModifier );
#include "plAGMasterMod.h"
REGISTER_CREATABLE( plAGMasterMod );
#include "plSeekPointMod.h"
REGISTER_CREATABLE( plSeekPointMod );
#include "plOneShotMod.h"
REGISTER_CREATABLE( plOneShotMod );
#include "plMultistageBehMod.h"
REGISTER_CREATABLE( plMultistageBehMod );
#include "plArmatureMod.h"
REGISTER_CREATABLE( plArmatureModBase );
REGISTER_CREATABLE( plArmatureMod );
REGISTER_CREATABLE( plArmatureLODMod );
#include "plArmatureEffects.h"
REGISTER_CREATABLE( plArmatureEffectsMgr );
REGISTER_NONCREATABLE( plArmatureEffect );
REGISTER_CREATABLE( plArmatureEffectFootSound );
#include "plAvBrain.h"
REGISTER_NONCREATABLE(plArmatureBrain);
#include "plAvBrainHuman.h"
REGISTER_CREATABLE(plAvBrainHuman);
#include "plAvBrainDrive.h"
REGISTER_CREATABLE(plAvBrainDrive);
#include "plAvLadderModifier.h"
REGISTER_CREATABLE( plAvLadderMod );
#include "plAvatarClothing.h"
REGISTER_CREATABLE(plClothingItem);
REGISTER_CREATABLE(plClothingOutfit);
REGISTER_CREATABLE(plClothingBase);
REGISTER_CREATABLE(plClothingMgr);
#include "plAvBrainGeneric.h"
REGISTER_CREATABLE(plAvBrainGeneric);
#include "plAvatarTasks.h"
REGISTER_NONCREATABLE( plAvTask );
REGISTER_CREATABLE( plAvAnimTask );
REGISTER_CREATABLE( plAvSeekTask )
REGISTER_CREATABLE( plAvOneShotTask );
REGISTER_CREATABLE( plAvOneShotLinkTask );
#include "plAnimStage.h"
REGISTER_CREATABLE( plAnimStage );
#include "plAvTaskSeek.h"
REGISTER_CREATABLE( plAvTaskSeek );
#include "plAGMasterSDLModifier.h"
REGISTER_CREATABLE( plAGMasterSDLModifier );
#include "plAvatarSDLModifier.h"
REGISTER_CREATABLE( plAvatarSDLModifier );
REGISTER_CREATABLE( plAvatarPhysicalSDLModifier );
#include "plClothingSDLModifier.h"
REGISTER_CREATABLE( plClothingSDLModifier );
#include "plAvatarMgr.h"
REGISTER_NONCREATABLE( plAvatarMgr );
#include "plNPCSpawnMod.h"
REGISTER_CREATABLE( plNPCSpawnMod );
#include "plAvBrainSwim.h"
REGISTER_CREATABLE( plAvBrainSwim );
#include "plAvBrainClimb.h"
REGISTER_CREATABLE( plAvBrainClimb );
#include "plAvBrainCoop.h"
REGISTER_CREATABLE( plAvBrainCoop );
#include "plCoopCoordinator.h"
REGISTER_CREATABLE( plCoopCoordinator );
#include "plAvTaskBrain.h"
REGISTER_CREATABLE( plAvTaskBrain );
#include "plSittingModifier.h"
REGISTER_CREATABLE( plSittingModifier );
#include "plSwimRegion.h"
REGISTER_CREATABLE( plSwimRegionInterface );
REGISTER_CREATABLE( plSwimCircularCurrentRegion );
REGISTER_CREATABLE( plSwimStraightCurrentRegion );
#include "plAvBrainCritter.h"
REGISTER_CREATABLE( plAvBrainCritter );
#include "plAvBrainRideAnimatedPhysical.h"
REGISTER_CREATABLE(plAvBrainRideAnimatedPhysical)
#endif // plAvatarCreatable_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,220 +1,220 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAvatarMgr.h
Gathering place for global animations and miscellaneous avatar data.
Ideally this stuff will all be migrated into the resource manager. */
#ifndef PLAVATARMGR_INC
#define PLAVATARMGR_INC
#include "hsStlUtils.h"
#include "hsStlSortUtils.h"
#include "hsGeometry3.h"
#include "pnKeyedObject/hsKeyedObject.h"
#include "plMessage/plLoadAvatarMsg.h"
// This is still pretty much a hack, but it's a compartmentalized hack instead of the previous
// interwoven spaghetti hack.
class plSeekPointMod;
class plOneShotMod;
class plAGMasterMod;
class plArmatureMod;
class plSpawnModifier;
class plKey;
class plLoadAvatarMsg;
class plMaintainersMarkerModifier;
class plDniCoordinateInfo;
class plAvCoopMsg;
class plNotifyMsg;
class plCoopCoordinator;
class plLoadCloneMsg;
class plStatusLog;
/** \class plAvatarMgr
Gathering place for global animations and miscellaneous avatar data.
Ideally this stuff will all be migrated into the resource manager.
This class is 100% static and must be explictly cleared when
resetting the scene on shutdown or when rebuilding the scene for export.
*/
class plAvatarMgr : public hsKeyedObject
{
public:
typedef std::vector<plArmatureMod*> plArmatureModPtrVec;
enum AvatarTypeMask
{
Human = 1,
Player = 2
};
plAvatarMgr(); // can only be constructed by itself (singleton)
virtual ~plAvatarMgr();
CLASSNAME_REGISTER( plAvatarMgr );
GETINTERFACE_ANY( plAvatarMgr, hsKeyedObject );
// \{
/** Seek points are alignment points used for aligning
the avatar before playing a detail interaction animation.
These are registered by name here primarily for debugging
and ad-hoc scripting. In final releases, we'll be able to
do away with this bookeeping entirely. */
void AddSeekPoint(plSeekPointMod *seekpoint);
void RemoveSeekPoint(plSeekPointMod *seekpoint);
plSeekPointMod *FindSeekPoint(const char *name);
// \}
// \{
/** One shots are registered here for debugging and ad-hoc
scripting only. */
void AddOneShot(plOneShotMod *oneshot);
void RemoveOneShot(plOneShotMod *oneshot);
plOneShotMod *FindOneShot(char *name);
// \}
plKey LoadPlayer(const char* name, const char *account);
plKey LoadPlayer(const char* name, const char *account, const char *linkName);
plKey LoadAvatar(const char *name, const char *accountName, bool isPlayer, plKey spawnPoint, plAvTask *initialTask, const char *userStr = nil);
/** Unload an avatar - player or npc - both locally and remotely. */
void UnLoadAvatar(plKey avKey, bool isPlayer);
/** send our (already loaded) local player to newly-associated clients - used when linking */
void PropagateLocalPlayer(int spawnPoint = -1);
/** Unload our local player on other machines because we're leaving this age.
The player will stay around on our local machine, though. */
bool UnPropagateLocalPlayer();
void UnLoadRemotePlayer(plKey playerKey);
void UnLoadLocalPlayer();
void AddAvatar(plArmatureMod *avatar);
void RemoveAvatar(plArmatureMod *instance);
plArmatureMod *GetLocalAvatar();
plKey GetLocalAvatarKey();
static plArmatureMod *FindAvatar(plKey& avatarKey); // Key of the sceneObject
plArmatureMod *FindAvatarByPlayerID(UInt32 pid);
plArmatureMod *FindAvatarByModelName(char *name); // Probably only useful for custom NPCs. All players are
// either "Male" or "Female".
void FindAllAvatarsByModelName(const char* name, plArmatureModPtrVec& outVec);
plArmatureMod *GetFirstRemoteAvatar();
// \{
/** Spawn points are potential entry points for the
avatar. They're selected pretty randomly right now;
eventually they'll be selected by script based
on the book used to enter the scene. */
void AddSpawnPoint(plSpawnModifier *spawn);
void RemoveSpawnPoint(plSpawnModifier *spawn);
const plSpawnModifier *GetSpawnPoint(int index);
int NumSpawnPoints() { return fSpawnPoints.size(); }
int FindSpawnPoint( const char *name ) const;
// \}
static int WarpPlayerToAnother(hsBool iMove, UInt32 remoteID);
static int WarpPlayerToXYZ(hsScalar x, hsScalar y, hsScalar z);
static int WarpPlayerToXYZ(int pid, hsScalar x, hsScalar y, hsScalar z);
static plAvatarMgr *GetInstance();
static void ShutDown();
hsBool MsgReceive(plMessage *msg);
hsBool HandleCoopMsg(plAvCoopMsg *msg);
hsBool HandleNotifyMsg(plNotifyMsg *msg);
hsBool IPassMessageToActiveCoop(plMessage *msg, UInt32 id, UInt16 serial);
// similar to a spawn point, maintainers markers are used
// to generate your position in Dni coordinates
void AddMaintainersMarker(plMaintainersMarkerModifier *mm);
void RemoveMaintainersMarker(plMaintainersMarkerModifier *mm);
void PointToDniCoordinate(hsPoint3 pt, plDniCoordinateInfo* ret);
void GetDniCoordinate(plDniCoordinateInfo* ret);
static void OfferLinkingBook(plKey hostKey, plKey guestKey, plMessage *linkMsg, plKey replyKey);
bool IsACoopRunning();
plStatusLog *GetLog() { return fLog; }
protected:
/** Dump all internal data. */
void IReset();
/** Handle an incoming clone message; do any necessary post-processing
on the avatar. */
void plAvatarMgr::IFinishLoadingAvatar(plLoadAvatarMsg *cloneMsg);
/** Handle an incoming clone message which holds an unload request.
*/
void plAvatarMgr::IFinishUnloadingAvatar(plLoadAvatarMsg *cloneMsg);
/** When an armature modifier attached to the given scene object is loaded,
send it the given message.
We get notified when the avatar's scene object is loaded, but we also need to
set some information up for the avatar modifier when it comes in.
We'll get that notification via the AddAvatar call later. In this function
we're going to squirrel away an initialization message to pass to the armature
modifier when it arrives. */
void plAvatarMgr::IDeferInit(plKey playerSOKey, plMessage *initMsg);
/** See if we have an avatar type message saved for the given avatar and send them. */
void plAvatarMgr::ISendDeferredInit(plKey playerSOKey);
static plAvatarMgr* fInstance; // the single instance of the avatar manager
typedef std::map<const char *, plSeekPointMod *, stringISorter> plSeekPointMap;
plSeekPointMap fSeekPoints;
typedef std::map<char *, plOneShotMod *, stringISorter> plOneShotMap;
plOneShotMap fOneShots;
typedef std::map<plKey, plMessage *> DeferredInits;
DeferredInits fDeferredInits;
// typedef std::map<const char *, plArmatureMod *, stringISorter> plAvatarMap;
typedef std::vector<plKey> plAvatarVec;
plAvatarVec fAvatars;
typedef std::vector<const plSpawnModifier*> plSpawnVec;
plSpawnVec fSpawnPoints;
hsTArray<plMaintainersMarkerModifier*> fMaintainersMarkers;
// we're using a multimap, which is a map which allows multiple entries to
// share the same key. the key we use is the initiator's player id; in the vast
// majority of cases, there will only be one coop running for a given initiator's
// ID. By using a multimap, however, we can still handle a few different coops
// for the same user by just iterating from the first match forward until
// we run out of matches.
typedef std::multimap<UInt32, plCoopCoordinator *> plCoopMap;
plCoopMap fActiveCoops;
hsTArray<plLoadCloneMsg*> fCloneMsgQueue;
plStatusLog *fLog;
};
#endif // PLAVATARMGR_INC
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAvatarMgr.h
Gathering place for global animations and miscellaneous avatar data.
Ideally this stuff will all be migrated into the resource manager. */
#ifndef PLAVATARMGR_INC
#define PLAVATARMGR_INC
#include "hsStlUtils.h"
#include "hsStlSortUtils.h"
#include "hsGeometry3.h"
#include "pnKeyedObject/hsKeyedObject.h"
#include "plMessage/plLoadAvatarMsg.h"
// This is still pretty much a hack, but it's a compartmentalized hack instead of the previous
// interwoven spaghetti hack.
class plSeekPointMod;
class plOneShotMod;
class plAGMasterMod;
class plArmatureMod;
class plSpawnModifier;
class plKey;
class plLoadAvatarMsg;
class plMaintainersMarkerModifier;
class plDniCoordinateInfo;
class plAvCoopMsg;
class plNotifyMsg;
class plCoopCoordinator;
class plLoadCloneMsg;
class plStatusLog;
/** \class plAvatarMgr
Gathering place for global animations and miscellaneous avatar data.
Ideally this stuff will all be migrated into the resource manager.
This class is 100% static and must be explictly cleared when
resetting the scene on shutdown or when rebuilding the scene for export.
*/
class plAvatarMgr : public hsKeyedObject
{
public:
typedef std::vector<plArmatureMod*> plArmatureModPtrVec;
enum AvatarTypeMask
{
Human = 1,
Player = 2
};
plAvatarMgr(); // can only be constructed by itself (singleton)
virtual ~plAvatarMgr();
CLASSNAME_REGISTER( plAvatarMgr );
GETINTERFACE_ANY( plAvatarMgr, hsKeyedObject );
// \{
/** Seek points are alignment points used for aligning
the avatar before playing a detail interaction animation.
These are registered by name here primarily for debugging
and ad-hoc scripting. In final releases, we'll be able to
do away with this bookeeping entirely. */
void AddSeekPoint(plSeekPointMod *seekpoint);
void RemoveSeekPoint(plSeekPointMod *seekpoint);
plSeekPointMod *FindSeekPoint(const char *name);
// \}
// \{
/** One shots are registered here for debugging and ad-hoc
scripting only. */
void AddOneShot(plOneShotMod *oneshot);
void RemoveOneShot(plOneShotMod *oneshot);
plOneShotMod *FindOneShot(char *name);
// \}
plKey LoadPlayer(const char* name, const char *account);
plKey LoadPlayer(const char* name, const char *account, const char *linkName);
plKey LoadAvatar(const char *name, const char *accountName, bool isPlayer, plKey spawnPoint, plAvTask *initialTask, const char *userStr = nil);
/** Unload an avatar - player or npc - both locally and remotely. */
void UnLoadAvatar(plKey avKey, bool isPlayer);
/** send our (already loaded) local player to newly-associated clients - used when linking */
void PropagateLocalPlayer(int spawnPoint = -1);
/** Unload our local player on other machines because we're leaving this age.
The player will stay around on our local machine, though. */
bool UnPropagateLocalPlayer();
void UnLoadRemotePlayer(plKey playerKey);
void UnLoadLocalPlayer();
void AddAvatar(plArmatureMod *avatar);
void RemoveAvatar(plArmatureMod *instance);
plArmatureMod *GetLocalAvatar();
plKey GetLocalAvatarKey();
static plArmatureMod *FindAvatar(plKey& avatarKey); // Key of the sceneObject
plArmatureMod *FindAvatarByPlayerID(UInt32 pid);
plArmatureMod *FindAvatarByModelName(char *name); // Probably only useful for custom NPCs. All players are
// either "Male" or "Female".
void FindAllAvatarsByModelName(const char* name, plArmatureModPtrVec& outVec);
plArmatureMod *GetFirstRemoteAvatar();
// \{
/** Spawn points are potential entry points for the
avatar. They're selected pretty randomly right now;
eventually they'll be selected by script based
on the book used to enter the scene. */
void AddSpawnPoint(plSpawnModifier *spawn);
void RemoveSpawnPoint(plSpawnModifier *spawn);
const plSpawnModifier *GetSpawnPoint(int index);
int NumSpawnPoints() { return fSpawnPoints.size(); }
int FindSpawnPoint( const char *name ) const;
// \}
static int WarpPlayerToAnother(hsBool iMove, UInt32 remoteID);
static int WarpPlayerToXYZ(hsScalar x, hsScalar y, hsScalar z);
static int WarpPlayerToXYZ(int pid, hsScalar x, hsScalar y, hsScalar z);
static plAvatarMgr *GetInstance();
static void ShutDown();
hsBool MsgReceive(plMessage *msg);
hsBool HandleCoopMsg(plAvCoopMsg *msg);
hsBool HandleNotifyMsg(plNotifyMsg *msg);
hsBool IPassMessageToActiveCoop(plMessage *msg, UInt32 id, UInt16 serial);
// similar to a spawn point, maintainers markers are used
// to generate your position in Dni coordinates
void AddMaintainersMarker(plMaintainersMarkerModifier *mm);
void RemoveMaintainersMarker(plMaintainersMarkerModifier *mm);
void PointToDniCoordinate(hsPoint3 pt, plDniCoordinateInfo* ret);
void GetDniCoordinate(plDniCoordinateInfo* ret);
static void OfferLinkingBook(plKey hostKey, plKey guestKey, plMessage *linkMsg, plKey replyKey);
bool IsACoopRunning();
plStatusLog *GetLog() { return fLog; }
protected:
/** Dump all internal data. */
void IReset();
/** Handle an incoming clone message; do any necessary post-processing
on the avatar. */
void plAvatarMgr::IFinishLoadingAvatar(plLoadAvatarMsg *cloneMsg);
/** Handle an incoming clone message which holds an unload request.
*/
void plAvatarMgr::IFinishUnloadingAvatar(plLoadAvatarMsg *cloneMsg);
/** When an armature modifier attached to the given scene object is loaded,
send it the given message.
We get notified when the avatar's scene object is loaded, but we also need to
set some information up for the avatar modifier when it comes in.
We'll get that notification via the AddAvatar call later. In this function
we're going to squirrel away an initialization message to pass to the armature
modifier when it arrives. */
void plAvatarMgr::IDeferInit(plKey playerSOKey, plMessage *initMsg);
/** See if we have an avatar type message saved for the given avatar and send them. */
void plAvatarMgr::ISendDeferredInit(plKey playerSOKey);
static plAvatarMgr* fInstance; // the single instance of the avatar manager
typedef std::map<const char *, plSeekPointMod *, stringISorter> plSeekPointMap;
plSeekPointMap fSeekPoints;
typedef std::map<char *, plOneShotMod *, stringISorter> plOneShotMap;
plOneShotMap fOneShots;
typedef std::map<plKey, plMessage *> DeferredInits;
DeferredInits fDeferredInits;
// typedef std::map<const char *, plArmatureMod *, stringISorter> plAvatarMap;
typedef std::vector<plKey> plAvatarVec;
plAvatarVec fAvatars;
typedef std::vector<const plSpawnModifier*> plSpawnVec;
plSpawnVec fSpawnPoints;
hsTArray<plMaintainersMarkerModifier*> fMaintainersMarkers;
// we're using a multimap, which is a map which allows multiple entries to
// share the same key. the key we use is the initiator's player id; in the vast
// majority of cases, there will only be one coop running for a given initiator's
// ID. By using a multimap, however, we can still handle a few different coops
// for the same user by just iterating from the first match forward until
// we run out of matches.
typedef std::multimap<UInt32, plCoopCoordinator *> plCoopMap;
plCoopMap fActiveCoops;
hsTArray<plLoadCloneMsg*> fCloneMsgQueue;
plStatusLog *fLog;
};
#endif // PLAVATARMGR_INC

File diff suppressed because it is too large Load Diff

View File

@ -1,167 +1,167 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvatarSDLModifier_inc
#define plAvatarSDLModifier_inc
#include "hsConfig.h"
#include "hsStlUtils.h"
#include "plModifier/plSDLModifier.h"
//
// This modifier is responsible for sending and recving
// an avatar's state
//
class plStateDataRecord;
class plArmatureMod;
class plAnimStage;
class plAvBrainGeneric;
class plAvBrainClimb;
class plAvBrainDrive;
class plAvatarPhysicalSDLModifier : public plSDLModifier
{
protected:
static char kStrPosition[];
static char kStrRotation[];
static char kStrSubworld[];
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
void IPutCurrentStateIn(plStateDataRecord* dstState);
UInt32 IApplyModFlags(UInt32 sendFlags) { return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState); }
public:
CLASSNAME_REGISTER( plAvatarPhysicalSDLModifier );
GETINTERFACE_ANY( plAvatarPhysicalSDLModifier, plSDLModifier);
const char* GetSDLName() const { return kSDLAvatarPhysical; }
};
class plAvatarSDLModifier : public plSDLModifier
{
protected:
static char kStrBrainStack[];
static char kStrInvisibilityLevel[];
// var labels
struct StandardStageVarNames
{
static char kStrName[];
static char kStrNumLoops[];
static char kStrForward[];
static char kStrBackward[];
static char kStrStageAdvance[];
static char kStrStageRegress[];
static char kStrNotifyEnter[];
static char kStrNotifyLoop[];
static char kStrNotifyStageAdvance[];
static char kStrNotifyStageRegress[];
static char kStrUseGlobalCoords[];
static char kStrLocalTime[];
static char kStrCurrentLoop[];
static char kStrIsAttached[];
};
struct GenericBrainVarNames
{
static char kStrStages[];
static char kStrCurrentStage[];
static char kStrFreezePhysicalAtEnd[];
static char kStrCallbackRcvr[];
static char kStrMovingForward[];
static char kStrExitFlags[];
static char kStrType[];
static char kStrMode[];
static char kStrFadeIn[];
static char kStrFadeOut[];
static char kStrMoveMode[];
static char kStrBodyUsage[];
};
struct BrainUnionVarNames
{
static char kGenericBrain[];
static char kClimbBrain[];
static char kDriveBrain[];
};
/** Top level: gets the current avatar brain state for any number of brains
of varying type from the data record into the avatar.
Will destroy all optional brains and recreate them from the incoming SDL. */
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
/** Set the base state for the avatar. This primarily consists of the state of the
human brain, which is required for all avatars. */
void ISetBaseAvatarStateFrom(plArmatureMod *avMod, const plStateDataRecord* src);
/** We found a generic brain in the SDL stream. Build the corresponding brain and attach it. */
bool ISetGenericBrainFrom(plArmatureMod *avMod, const plStateDataRecord* srcState);
/** We found a climb brain in the SDL stream. Build the corresponding brain and attach it. */
void ISetClimbBrainFrom(plArmatureMod *avMod, const plStateDataRecord* src);
/** We found a drive brain in the SDL stream. Build the corresponding brain and attach it. */
void ISetDriveBrainFrom(plArmatureMod *avMod, const plStateDataRecord* src);
/** Generic brains have multiple "stages" parse *one* out of the SDL stream and return it. */
plAnimStage * IGetStageFrom(plArmatureMod *avMod, const plStateDataRecord* srcState);
void IPutCurrentStateIn(plStateDataRecord* dstState);
void IPutBaseAvatarStateIn(plArmatureMod *avMod, plStateDataRecord* dst);
void IPutGenericBrainIn(plArmatureMod *avMod, plAvBrainGeneric *brain, plStateDataRecord* dstState);
void IPutClimbBrainIn(plArmatureMod *avMod, plAvBrainClimb *brain, plStateDataRecord* dstState);
void IPutDriveBrainIn(plArmatureMod *avMod, plAvBrainDrive *brain, plStateDataRecord* dstState);
bool IPutStageIn(plArmatureMod *avMod, plAnimStage *stage, plStateDataRecord* dstState);
UInt32 IApplyModFlags(UInt32 sendFlags) { return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState); }
public:
CLASSNAME_REGISTER( plAvatarSDLModifier );
GETINTERFACE_ANY( plAvatarSDLModifier, plSDLModifier);
const char* GetSDLName() const { return kSDLAvatar; }
// trying a new approach, which is to let the climb brain read its own SDL.
// this allows us to synch protected data members with either creating a friend
// relationship or punching a lot of hole's in the object's encapsulation
struct ClimbBrainVarNames
{
static char kStrCurMode[];
static char kStrNextMode[];
static char kStrAllowedDirections[];
static char kStrAllowedDismounts[];
static char kStrVertProbeLength[];
static char kStrHorizProbeLength[];
static char kStrCurStageAttached[];
static char kStrCurStage[];
static char kStrCurStageTime[];
static char kStrCurStageStrength[];
static char kStrExitStageAttached[];
static char kStrExitStage[];
static char kStrExitStageTime[];
static char kStrExitStageStrength[];
};
};
#endif // plAvatarSDLModifier_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAvatarSDLModifier_inc
#define plAvatarSDLModifier_inc
#include "hsConfig.h"
#include "hsStlUtils.h"
#include "plModifier/plSDLModifier.h"
//
// This modifier is responsible for sending and recving
// an avatar's state
//
class plStateDataRecord;
class plArmatureMod;
class plAnimStage;
class plAvBrainGeneric;
class plAvBrainClimb;
class plAvBrainDrive;
class plAvatarPhysicalSDLModifier : public plSDLModifier
{
protected:
static char kStrPosition[];
static char kStrRotation[];
static char kStrSubworld[];
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
void IPutCurrentStateIn(plStateDataRecord* dstState);
UInt32 IApplyModFlags(UInt32 sendFlags) { return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState); }
public:
CLASSNAME_REGISTER( plAvatarPhysicalSDLModifier );
GETINTERFACE_ANY( plAvatarPhysicalSDLModifier, plSDLModifier);
const char* GetSDLName() const { return kSDLAvatarPhysical; }
};
class plAvatarSDLModifier : public plSDLModifier
{
protected:
static char kStrBrainStack[];
static char kStrInvisibilityLevel[];
// var labels
struct StandardStageVarNames
{
static char kStrName[];
static char kStrNumLoops[];
static char kStrForward[];
static char kStrBackward[];
static char kStrStageAdvance[];
static char kStrStageRegress[];
static char kStrNotifyEnter[];
static char kStrNotifyLoop[];
static char kStrNotifyStageAdvance[];
static char kStrNotifyStageRegress[];
static char kStrUseGlobalCoords[];
static char kStrLocalTime[];
static char kStrCurrentLoop[];
static char kStrIsAttached[];
};
struct GenericBrainVarNames
{
static char kStrStages[];
static char kStrCurrentStage[];
static char kStrFreezePhysicalAtEnd[];
static char kStrCallbackRcvr[];
static char kStrMovingForward[];
static char kStrExitFlags[];
static char kStrType[];
static char kStrMode[];
static char kStrFadeIn[];
static char kStrFadeOut[];
static char kStrMoveMode[];
static char kStrBodyUsage[];
};
struct BrainUnionVarNames
{
static char kGenericBrain[];
static char kClimbBrain[];
static char kDriveBrain[];
};
/** Top level: gets the current avatar brain state for any number of brains
of varying type from the data record into the avatar.
Will destroy all optional brains and recreate them from the incoming SDL. */
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
/** Set the base state for the avatar. This primarily consists of the state of the
human brain, which is required for all avatars. */
void ISetBaseAvatarStateFrom(plArmatureMod *avMod, const plStateDataRecord* src);
/** We found a generic brain in the SDL stream. Build the corresponding brain and attach it. */
bool ISetGenericBrainFrom(plArmatureMod *avMod, const plStateDataRecord* srcState);
/** We found a climb brain in the SDL stream. Build the corresponding brain and attach it. */
void ISetClimbBrainFrom(plArmatureMod *avMod, const plStateDataRecord* src);
/** We found a drive brain in the SDL stream. Build the corresponding brain and attach it. */
void ISetDriveBrainFrom(plArmatureMod *avMod, const plStateDataRecord* src);
/** Generic brains have multiple "stages" parse *one* out of the SDL stream and return it. */
plAnimStage * IGetStageFrom(plArmatureMod *avMod, const plStateDataRecord* srcState);
void IPutCurrentStateIn(plStateDataRecord* dstState);
void IPutBaseAvatarStateIn(plArmatureMod *avMod, plStateDataRecord* dst);
void IPutGenericBrainIn(plArmatureMod *avMod, plAvBrainGeneric *brain, plStateDataRecord* dstState);
void IPutClimbBrainIn(plArmatureMod *avMod, plAvBrainClimb *brain, plStateDataRecord* dstState);
void IPutDriveBrainIn(plArmatureMod *avMod, plAvBrainDrive *brain, plStateDataRecord* dstState);
bool IPutStageIn(plArmatureMod *avMod, plAnimStage *stage, plStateDataRecord* dstState);
UInt32 IApplyModFlags(UInt32 sendFlags) { return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState); }
public:
CLASSNAME_REGISTER( plAvatarSDLModifier );
GETINTERFACE_ANY( plAvatarSDLModifier, plSDLModifier);
const char* GetSDLName() const { return kSDLAvatar; }
// trying a new approach, which is to let the climb brain read its own SDL.
// this allows us to synch protected data members with either creating a friend
// relationship or punching a lot of hole's in the object's encapsulation
struct ClimbBrainVarNames
{
static char kStrCurMode[];
static char kStrNextMode[];
static char kStrAllowedDirections[];
static char kStrAllowedDismounts[];
static char kStrVertProbeLength[];
static char kStrHorizProbeLength[];
static char kStrCurStageAttached[];
static char kStrCurStage[];
static char kStrCurStageTime[];
static char kStrCurStageStrength[];
static char kStrExitStageAttached[];
static char kStrExitStage[];
static char kStrExitStageTime[];
static char kStrExitStageStrength[];
};
};
#endif // plAvatarSDLModifier_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,255 +1,255 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAvatarTasks.h
*/
#ifndef PLAVATARTASKS_INC
#define PLAVATARTASKS_INC
// base class
#include "plAvTask.h"
#include "plAvDefs.h"
#include "hsQuat.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "pnKeyedObject/plKey.h"
class plAGAnim;
class plAGAnimInstance;
class plAvSeekMsg;
class plAvOneShotMsg;
class plAvEnterModeMsg;
class plOneShotCallbacks;
class plMessage;
class plAvPushBrainMsg;
/** \class plAvAnimTask
Attach or detach an animation from the avatar.
Optionally begin playing.
It's perfectly reasonable to attach an animation with a blend of zero and start of false.
This will have no effect visually until you start blending the animation in. */
class plAvAnimTask : public plAvTask
{
public:
/** Default constructor for the class factory and subclases */
plAvAnimTask();
/** Canonical constructor form when attaching
\param animName The name of the animation we'll be attaching or removing
\param initialBlend Initial blend value; only relevant if we're attaching
\param targetBlend The blend value we're shooting for
\param fadeSpeed How fast (in fade units per second) to fade in
\param setTime Local time for the animation to start
\param start Start the animation, or just attach it?
\param loop Make the animation loop?
\param attach Are we attaching or detaching the animation?
*/
plAvAnimTask(const char *animName, hsScalar initialBlend, hsScalar targetBlend, hsScalar fadeSpeed,
hsScalar setTime, hsBool start, hsBool loop, hsBool attach);
/** Canonical constructor form form for detaching
\param animName The name of the animation we're detaching
\param fadeSpeed How fast to fade it out. */
plAvAnimTask(const char *animName, hsScalar fadeSpeed, hsBool attach = false);
virtual ~plAvAnimTask();
// task protocol
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual void LeaveAge(plArmatureMod *avatar);
// plasma protocol
CLASSNAME_REGISTER( plAvAnimTask );
GETINTERFACE_ANY( plAvAnimTask, plAvTask );
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *stream, hsResMgr *mgr);
protected:
// public members
char* fAnimName; // the animation we're operating on
hsScalar fInitialBlend; // the blend to establish (attaching only)
hsScalar fTargetBlend; // the blend to achieve eventually (attaching only)
hsScalar fFadeSpeed; // how fast to achieve the blend
hsScalar fSetTime; // set the animation to this time
hsBool fStart; // start the animation playing? (attaching only)
hsBool fLoop; // turn on looping? (attaching only)
hsBool fAttach; // attach? (otherwise detach)
plAGAnimInstance *fAnimInstance; // the animation we're monitoring (detaching only)
};
/** \task plAvSeekTask
Magically fly to a specific location and orientation. Not for use in final production scenes; mainly as a hack
to fly through incomplete areas of a level.
!!! Generally deprecated in favor of avBlendedSeekTask, a slightly less-gross-looking hack.
\deprecated */
class plAvSeekTask : public plAvTask
{
public:
/** Default constructor used by class factory and descendants. */
plAvSeekTask();
/** Common constructor. Seeks to the point at the normal speed. */
plAvSeekTask(plKey target);
/** Constructor form for calculated seek points: uses aligment type and (optionally) animation
The animation is used if we're trying to align some future pose with a seek target. */
plAvSeekTask(plKey target, plAvAlignment alignType, const char *animName);
// task protocol
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual void LeaveAge(plArmatureMod *avatar);
// plasma protocol
CLASSNAME_REGISTER( plAvSeekTask );
GETINTERFACE_ANY( plAvSeekTask, plAvTask );
// *** implement reader and writer if needed for network propagation
protected:
// -- specification members --
char * fAnimName; // the animation we're using, if any;
plAvAlignment fAlign; // how to line up with the seek point
double fDuration; // the time we want the task to take
plKey fTarget; // the thing we're seeking towards
// -- implementation members --
plAGAnimInstance * fAnimInstance; // the animation we're using
hsPoint3 fTargetPosition; // the position we're seeking
hsQuat fTargetRotation; // the orientation we're seeking
double fTargetTime; // the time we want to be done with the task (start + duration)
hsBool fPhysicalAtStart; // was the avatar physical before we started?
hsBool fCleanup; // last frame of processing
};
// ---- THE CUTOFF ----
/** \class plAvOneShotTask
Makes the avatar play a single animation and then return to user control.
Typically used in combination with a seek task to position the avatar
at the proper start point first.
Deprecated. Will be replaced by single-stage generic brains.
*/
class plAvOneShotTask : public plAvTask {
public:
/** Put default values for all member variables. */
void InitDefaults();
/** Default constructor for the class factor and descendants. */
plAvOneShotTask();
/** Canonical constructor
\param animName The name of the animation we're going to play
\param drivable Unused. Allows the oneshot to be controlled by keyboard input
\param reversable Unused. Allows the oneshot to be backed up by keyboard input
\param callbacks A vector of callback messages to be sent at specific times during the animation
*/
plAvOneShotTask(const char *animName, hsBool drivable, hsBool reversible, plOneShotCallbacks *callbacks);
/** Construct from a oneshot message.
\param msg The message to copy our parameters from
\param brain The brain to attach the task to.
*/
plAvOneShotTask (plAvOneShotMsg *msg, plArmatureMod *avatar, plArmatureBrain *brain);
virtual plAvOneShotTask::~plAvOneShotTask();
// task protocol
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual void LeaveAge(plArmatureMod *avatar);
void SetAnimName(char *name);
static hsBool fForce3rdPerson;
// plasma protocol
CLASSNAME_REGISTER( plAvOneShotTask );
GETINTERFACE_ANY( plAvOneShotTask, plAvTask );
hsBool fBackwards; // play the anim backwards
hsBool fDisableLooping; // explicitly kill looping on this anim;
hsBool fDisablePhysics; // disable physics when we play this oneshot
// *** implement reader and writer if needed for network propagation
protected:
char *fAnimName; // the name of the one-shot animation we want to use
hsBool fMoveHandle; // move the handle after the oneshot's done playing?
plAGAnimInstance *fAnimInstance; // the animation instance (available only after it starts playing)
hsBool fDrivable; // the user can control the animation with the mouse
hsBool fReversible; // the user can back up the animation with the mouse
hsBool fEnablePhysicsAtEnd; // was the avatar physical before we started (and did we disable physics?)
hsBool fDetachAnimation; // should we detach the animation when we're done?
hsBool fIgnore; // if this gets set before we start, we just finish without doing anything.
plOneShotCallbacks *fCallbacks; // a set of callbacks to set up on our animation
hsMatrix44 fPlayer2Anim; // matrix from player root space to animation root space
hsMatrix44 fAnim2Player; // matrix from animation root space to player root space
hsMatrix44 fWorld2Anim;
hsMatrix44 fAnim2World;
int fWaitFrames; // wait a couple frames before finalizing position to allow changes
// from any animation callbacks to propagate. based on weird interaction
// with Attach() command. sheeeit.
};
void GetPositionAndRotation(hsMatrix44 transform, hsScalarTriple *position, hsQuat *rotation);
// A quick task to play a oneshot, wait on a marker, and link to your personal age.
// Could be done with a responder, but this gives me a quick way to trigger it from code
// without the responder and callback messages flying around.
class plAvOneShotLinkTask : public plAvOneShotTask
{
public:
plAvOneShotLinkTask();
virtual ~plAvOneShotLinkTask();
// task protocol
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
CLASSNAME_REGISTER( plAvOneShotLinkTask );
GETINTERFACE_ANY( plAvOneShotLinkTask, plAvOneShotTask );
// only read/writes enough to send an unstarted task across the net. Not intended for
// use with a running task.
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *stream, hsResMgr *mgr);
void SetMarkerName(char *name);
protected:
char *fMarkerName;
double fStartTime;
hsScalar fMarkerTime;
hsBool fLinkFired;
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAvatarTasks.h
*/
#ifndef PLAVATARTASKS_INC
#define PLAVATARTASKS_INC
// base class
#include "plAvTask.h"
#include "plAvDefs.h"
#include "hsQuat.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "pnKeyedObject/plKey.h"
class plAGAnim;
class plAGAnimInstance;
class plAvSeekMsg;
class plAvOneShotMsg;
class plAvEnterModeMsg;
class plOneShotCallbacks;
class plMessage;
class plAvPushBrainMsg;
/** \class plAvAnimTask
Attach or detach an animation from the avatar.
Optionally begin playing.
It's perfectly reasonable to attach an animation with a blend of zero and start of false.
This will have no effect visually until you start blending the animation in. */
class plAvAnimTask : public plAvTask
{
public:
/** Default constructor for the class factory and subclases */
plAvAnimTask();
/** Canonical constructor form when attaching
\param animName The name of the animation we'll be attaching or removing
\param initialBlend Initial blend value; only relevant if we're attaching
\param targetBlend The blend value we're shooting for
\param fadeSpeed How fast (in fade units per second) to fade in
\param setTime Local time for the animation to start
\param start Start the animation, or just attach it?
\param loop Make the animation loop?
\param attach Are we attaching or detaching the animation?
*/
plAvAnimTask(const char *animName, hsScalar initialBlend, hsScalar targetBlend, hsScalar fadeSpeed,
hsScalar setTime, hsBool start, hsBool loop, hsBool attach);
/** Canonical constructor form form for detaching
\param animName The name of the animation we're detaching
\param fadeSpeed How fast to fade it out. */
plAvAnimTask(const char *animName, hsScalar fadeSpeed, hsBool attach = false);
virtual ~plAvAnimTask();
// task protocol
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual void LeaveAge(plArmatureMod *avatar);
// plasma protocol
CLASSNAME_REGISTER( plAvAnimTask );
GETINTERFACE_ANY( plAvAnimTask, plAvTask );
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *stream, hsResMgr *mgr);
protected:
// public members
char* fAnimName; // the animation we're operating on
hsScalar fInitialBlend; // the blend to establish (attaching only)
hsScalar fTargetBlend; // the blend to achieve eventually (attaching only)
hsScalar fFadeSpeed; // how fast to achieve the blend
hsScalar fSetTime; // set the animation to this time
hsBool fStart; // start the animation playing? (attaching only)
hsBool fLoop; // turn on looping? (attaching only)
hsBool fAttach; // attach? (otherwise detach)
plAGAnimInstance *fAnimInstance; // the animation we're monitoring (detaching only)
};
/** \task plAvSeekTask
Magically fly to a specific location and orientation. Not for use in final production scenes; mainly as a hack
to fly through incomplete areas of a level.
!!! Generally deprecated in favor of avBlendedSeekTask, a slightly less-gross-looking hack.
\deprecated */
class plAvSeekTask : public plAvTask
{
public:
/** Default constructor used by class factory and descendants. */
plAvSeekTask();
/** Common constructor. Seeks to the point at the normal speed. */
plAvSeekTask(plKey target);
/** Constructor form for calculated seek points: uses aligment type and (optionally) animation
The animation is used if we're trying to align some future pose with a seek target. */
plAvSeekTask(plKey target, plAvAlignment alignType, const char *animName);
// task protocol
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual void LeaveAge(plArmatureMod *avatar);
// plasma protocol
CLASSNAME_REGISTER( plAvSeekTask );
GETINTERFACE_ANY( plAvSeekTask, plAvTask );
// *** implement reader and writer if needed for network propagation
protected:
// -- specification members --
char * fAnimName; // the animation we're using, if any;
plAvAlignment fAlign; // how to line up with the seek point
double fDuration; // the time we want the task to take
plKey fTarget; // the thing we're seeking towards
// -- implementation members --
plAGAnimInstance * fAnimInstance; // the animation we're using
hsPoint3 fTargetPosition; // the position we're seeking
hsQuat fTargetRotation; // the orientation we're seeking
double fTargetTime; // the time we want to be done with the task (start + duration)
hsBool fPhysicalAtStart; // was the avatar physical before we started?
hsBool fCleanup; // last frame of processing
};
// ---- THE CUTOFF ----
/** \class plAvOneShotTask
Makes the avatar play a single animation and then return to user control.
Typically used in combination with a seek task to position the avatar
at the proper start point first.
Deprecated. Will be replaced by single-stage generic brains.
*/
class plAvOneShotTask : public plAvTask {
public:
/** Put default values for all member variables. */
void InitDefaults();
/** Default constructor for the class factor and descendants. */
plAvOneShotTask();
/** Canonical constructor
\param animName The name of the animation we're going to play
\param drivable Unused. Allows the oneshot to be controlled by keyboard input
\param reversable Unused. Allows the oneshot to be backed up by keyboard input
\param callbacks A vector of callback messages to be sent at specific times during the animation
*/
plAvOneShotTask(const char *animName, hsBool drivable, hsBool reversible, plOneShotCallbacks *callbacks);
/** Construct from a oneshot message.
\param msg The message to copy our parameters from
\param brain The brain to attach the task to.
*/
plAvOneShotTask (plAvOneShotMsg *msg, plArmatureMod *avatar, plArmatureBrain *brain);
virtual plAvOneShotTask::~plAvOneShotTask();
// task protocol
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual void LeaveAge(plArmatureMod *avatar);
void SetAnimName(char *name);
static hsBool fForce3rdPerson;
// plasma protocol
CLASSNAME_REGISTER( plAvOneShotTask );
GETINTERFACE_ANY( plAvOneShotTask, plAvTask );
hsBool fBackwards; // play the anim backwards
hsBool fDisableLooping; // explicitly kill looping on this anim;
hsBool fDisablePhysics; // disable physics when we play this oneshot
// *** implement reader and writer if needed for network propagation
protected:
char *fAnimName; // the name of the one-shot animation we want to use
hsBool fMoveHandle; // move the handle after the oneshot's done playing?
plAGAnimInstance *fAnimInstance; // the animation instance (available only after it starts playing)
hsBool fDrivable; // the user can control the animation with the mouse
hsBool fReversible; // the user can back up the animation with the mouse
hsBool fEnablePhysicsAtEnd; // was the avatar physical before we started (and did we disable physics?)
hsBool fDetachAnimation; // should we detach the animation when we're done?
hsBool fIgnore; // if this gets set before we start, we just finish without doing anything.
plOneShotCallbacks *fCallbacks; // a set of callbacks to set up on our animation
hsMatrix44 fPlayer2Anim; // matrix from player root space to animation root space
hsMatrix44 fAnim2Player; // matrix from animation root space to player root space
hsMatrix44 fWorld2Anim;
hsMatrix44 fAnim2World;
int fWaitFrames; // wait a couple frames before finalizing position to allow changes
// from any animation callbacks to propagate. based on weird interaction
// with Attach() command. sheeeit.
};
void GetPositionAndRotation(hsMatrix44 transform, hsScalarTriple *position, hsQuat *rotation);
// A quick task to play a oneshot, wait on a marker, and link to your personal age.
// Could be done with a responder, but this gives me a quick way to trigger it from code
// without the responder and callback messages flying around.
class plAvOneShotLinkTask : public plAvOneShotTask
{
public:
plAvOneShotLinkTask();
virtual ~plAvOneShotLinkTask();
// task protocol
virtual hsBool Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
virtual hsBool Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed);
CLASSNAME_REGISTER( plAvOneShotLinkTask );
GETINTERFACE_ANY( plAvOneShotLinkTask, plAvOneShotTask );
// only read/writes enough to send an unstarted task across the net. Not intended for
// use with a running task.
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *stream, hsResMgr *mgr);
void SetMarkerName(char *name);
protected:
char *fMarkerName;
double fStartTime;
hsScalar fMarkerTime;
hsBool fLinkFired;
};
#endif

View File

@ -1,153 +1,153 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLCLOTHINGLAYOUT_INC
#define PLCLOTHINGLAYOUT_INC
#include "hsTypes.h"
#include "hsTemplates.h"
#include "hsUtils.h"
// This file is intended to be an independent section so that plClothingMtl and plAvatarClothing
// can both use these structures, without all the plCreatable/hsKeyedObject/plSynchedObject stuff
// No virtual methods allowed, and define everything inside the class declaration. (So that we can
// #include the file where necessary and not get redundant method definition errors.)
class plClothingElement
{
public:
enum
{
kLayerBase,
kLayerSkin,
kLayerSkinBlend1,
kLayerSkinBlend2,
kLayerSkinBlend3,
kLayerSkinBlend4,
kLayerSkinBlend5,
kLayerSkinBlend6,
kLayerTint1,
kLayerTint2,
kLayerMax,
kLayerSkinFirst = kLayerSkin,
kLayerSkinLast = kLayerSkinBlend6,
};
char *fName;
UInt32 fXPos;
UInt32 fYPos;
UInt32 fWidth;
UInt32 fHeight;
plClothingElement(char *name, UInt32 xPos, UInt32 yPos, UInt32 width, UInt32 height)
{
fName = hsStrcpy(name);
fXPos = xPos;
fYPos = yPos;
fWidth = width;
fHeight = height;
}
~plClothingElement() { delete [] fName; }
static void GetElements(hsTArray<plClothingElement *> &out)
{
/*
out.Append(TRACKED_NEW plClothingElement("shirt-chest", 768, 0, 256, 512));
out.Append(TRACKED_NEW plClothingElement("shirt-sleeve", 512, 192, 256, 128));
out.Append(TRACKED_NEW plClothingElement("face", 0, 0, 512, 512));
out.Append(TRACKED_NEW plClothingElement("eyeball", 64, 512, 64, 64));
out.Append(TRACKED_NEW plClothingElement("shoe-top", 0, 832, 128, 128));
out.Append(TRACKED_NEW plClothingElement("shoe-bottom", 0, 768, 128, 64));
out.Append(TRACKED_NEW plClothingElement("pants", 512, 512, 512, 512));
out.Append(TRACKED_NEW plClothingElement("hand-LOD", 64, 576, 64, 64));
out.Append(TRACKED_NEW plClothingElement("hand-square", 128, 512, 128, 128));
out.Append(TRACKED_NEW plClothingElement("hand-wide", 0, 640, 256, 128));
out.Append(TRACKED_NEW plClothingElement("playerbook", 512, 0, 256, 128));
out.Append(TRACKED_NEW plClothingElement("backpack", 512, 256, 256, 256));
out.Append(TRACKED_NEW plClothingElement("glasses-front", 256, 512, 256, 64));
out.Append(TRACKED_NEW plClothingElement("glasses-side", 256, 576, 256, 32));
out.Append(TRACKED_NEW plClothingElement("KI", 256, 640, 256, 128));
*/
out.Append(TRACKED_NEW plClothingElement("Chest", 768, 0, 256, 512));
out.Append(TRACKED_NEW plClothingElement("Arm", 512, 192, 256, 128));
out.Append(TRACKED_NEW plClothingElement("Face", 0, 256, 512, 256));
out.Append(TRACKED_NEW plClothingElement("Eye", 64, 704, 64, 64));
out.Append(TRACKED_NEW plClothingElement("Extra Hair", 256, 0, 256, 256));
out.Append(TRACKED_NEW plClothingElement("Hat", 0, 0, 256, 256));
out.Append(TRACKED_NEW plClothingElement("Foot", 0, 768, 256, 256));
out.Append(TRACKED_NEW plClothingElement("Legs", 512, 512, 512, 512));
out.Append(TRACKED_NEW plClothingElement("LOD", 64, 640, 64, 64));
out.Append(TRACKED_NEW plClothingElement("Finger", 128, 640, 128, 128));
out.Append(TRACKED_NEW plClothingElement("Palm", 0, 512, 256, 128));
out.Append(TRACKED_NEW plClothingElement("Player Book", 256, 512, 256, 128));
out.Append(TRACKED_NEW plClothingElement("Glasses", 384, 640, 128, 128));
out.Append(TRACKED_NEW plClothingElement("KI", 256, 640, 128, 128));
}
};
class plClothingLayout
{
public:
plClothingLayout(char *name, UInt32 origWidth) { fName = hsStrcpy(name); fOrigWidth = origWidth; }
~plClothingLayout() { delete [] fName; }
char *fName;
UInt32 fOrigWidth;
hsTArray<plClothingElement*> fElements;
/*
enum
{
kSetShirt,
kSetFace,
kSetEye,
kSetShoe,
kSetPants,
kSetHand,
kSetPlayerBook,
kSetBackpack,
kSetGlasses,
kSetKI,
kMaxTileset,
};
*/
enum
{
kSetShirt,
kSetFace,
kSetShoe,
kSetPants,
kSetHand,
kSetPlayerBook,
kSetGlasses,
kSetKI,
kSetEye, // UNUSED
kSetBackpack, // UNUSED
kMaxTileset,
};
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLCLOTHINGLAYOUT_INC
#define PLCLOTHINGLAYOUT_INC
#include "hsTypes.h"
#include "hsTemplates.h"
#include "hsUtils.h"
// This file is intended to be an independent section so that plClothingMtl and plAvatarClothing
// can both use these structures, without all the plCreatable/hsKeyedObject/plSynchedObject stuff
// No virtual methods allowed, and define everything inside the class declaration. (So that we can
// #include the file where necessary and not get redundant method definition errors.)
class plClothingElement
{
public:
enum
{
kLayerBase,
kLayerSkin,
kLayerSkinBlend1,
kLayerSkinBlend2,
kLayerSkinBlend3,
kLayerSkinBlend4,
kLayerSkinBlend5,
kLayerSkinBlend6,
kLayerTint1,
kLayerTint2,
kLayerMax,
kLayerSkinFirst = kLayerSkin,
kLayerSkinLast = kLayerSkinBlend6,
};
char *fName;
UInt32 fXPos;
UInt32 fYPos;
UInt32 fWidth;
UInt32 fHeight;
plClothingElement(char *name, UInt32 xPos, UInt32 yPos, UInt32 width, UInt32 height)
{
fName = hsStrcpy(name);
fXPos = xPos;
fYPos = yPos;
fWidth = width;
fHeight = height;
}
~plClothingElement() { delete [] fName; }
static void GetElements(hsTArray<plClothingElement *> &out)
{
/*
out.Append(TRACKED_NEW plClothingElement("shirt-chest", 768, 0, 256, 512));
out.Append(TRACKED_NEW plClothingElement("shirt-sleeve", 512, 192, 256, 128));
out.Append(TRACKED_NEW plClothingElement("face", 0, 0, 512, 512));
out.Append(TRACKED_NEW plClothingElement("eyeball", 64, 512, 64, 64));
out.Append(TRACKED_NEW plClothingElement("shoe-top", 0, 832, 128, 128));
out.Append(TRACKED_NEW plClothingElement("shoe-bottom", 0, 768, 128, 64));
out.Append(TRACKED_NEW plClothingElement("pants", 512, 512, 512, 512));
out.Append(TRACKED_NEW plClothingElement("hand-LOD", 64, 576, 64, 64));
out.Append(TRACKED_NEW plClothingElement("hand-square", 128, 512, 128, 128));
out.Append(TRACKED_NEW plClothingElement("hand-wide", 0, 640, 256, 128));
out.Append(TRACKED_NEW plClothingElement("playerbook", 512, 0, 256, 128));
out.Append(TRACKED_NEW plClothingElement("backpack", 512, 256, 256, 256));
out.Append(TRACKED_NEW plClothingElement("glasses-front", 256, 512, 256, 64));
out.Append(TRACKED_NEW plClothingElement("glasses-side", 256, 576, 256, 32));
out.Append(TRACKED_NEW plClothingElement("KI", 256, 640, 256, 128));
*/
out.Append(TRACKED_NEW plClothingElement("Chest", 768, 0, 256, 512));
out.Append(TRACKED_NEW plClothingElement("Arm", 512, 192, 256, 128));
out.Append(TRACKED_NEW plClothingElement("Face", 0, 256, 512, 256));
out.Append(TRACKED_NEW plClothingElement("Eye", 64, 704, 64, 64));
out.Append(TRACKED_NEW plClothingElement("Extra Hair", 256, 0, 256, 256));
out.Append(TRACKED_NEW plClothingElement("Hat", 0, 0, 256, 256));
out.Append(TRACKED_NEW plClothingElement("Foot", 0, 768, 256, 256));
out.Append(TRACKED_NEW plClothingElement("Legs", 512, 512, 512, 512));
out.Append(TRACKED_NEW plClothingElement("LOD", 64, 640, 64, 64));
out.Append(TRACKED_NEW plClothingElement("Finger", 128, 640, 128, 128));
out.Append(TRACKED_NEW plClothingElement("Palm", 0, 512, 256, 128));
out.Append(TRACKED_NEW plClothingElement("Player Book", 256, 512, 256, 128));
out.Append(TRACKED_NEW plClothingElement("Glasses", 384, 640, 128, 128));
out.Append(TRACKED_NEW plClothingElement("KI", 256, 640, 128, 128));
}
};
class plClothingLayout
{
public:
plClothingLayout(char *name, UInt32 origWidth) { fName = hsStrcpy(name); fOrigWidth = origWidth; }
~plClothingLayout() { delete [] fName; }
char *fName;
UInt32 fOrigWidth;
hsTArray<plClothingElement*> fElements;
/*
enum
{
kSetShirt,
kSetFace,
kSetEye,
kSetShoe,
kSetPants,
kSetHand,
kSetPlayerBook,
kSetBackpack,
kSetGlasses,
kSetKI,
kMaxTileset,
};
*/
enum
{
kSetShirt,
kSetFace,
kSetShoe,
kSetPants,
kSetHand,
kSetPlayerBook,
kSetGlasses,
kSetKI,
kSetEye, // UNUSED
kSetBackpack, // UNUSED
kMaxTileset,
};
};
#endif

View File

@ -1,308 +1,308 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plClothingSDLModifier.h"
#include "plAvatarClothing.h"
#include "plClothingLayout.h"
#include "plArmatureMod.h"
#include "pnSceneObject/plSceneObject.h"
#include "pnMessage/plSDLModifierMsg.h"
#include "plSDL/plSDL.h"
#include "pnKeyedObject/plKeyImp.h"
// static vars
char plClothingSDLModifier::kStrItem[]="item";
char plClothingSDLModifier::kStrTint[]="tint";
char plClothingSDLModifier::kStrTint2[]="tint2";
char plClothingSDLModifier::kStrWardrobe[]="wardrobe";
char plClothingSDLModifier::kStrSkinTint[]="skinTint";
char plClothingSDLModifier::kStrFaceBlends[]="faceBlends";
char plClothingSDLModifier::kStrAppearance[]="appearance";
char plClothingSDLModifier::kStrClothingDescName[]="clothingItem";
char plClothingSDLModifier::kStrAppearanceDescName[]="appearanceOptions";
char plClothingSDLModifier::kStrLinkInAnim[] = "linkInAnim";
//
// init latest data
//
plClothingSDLModifier::plClothingSDLModifier() :
fClothingOutfit(nil)
{
}
//
// find armature mod and cache it's clothingOutfit
//
plClothingOutfit* plClothingSDLModifier::GetClothingOutfit()
{
if (fClothingOutfit)
return fClothingOutfit;
int i;
plSceneObject* target = GetTarget();
hsAssert(target, "plClothingSDLModifier: nil target");
for (i=0;i<target->GetNumModifiers();i++)
{
const plArmatureMod* am = plArmatureMod::ConvertNoRef(target->GetModifier(i));
if (am)
{
fClothingOutfit=am->GetClothingOutfit();
break;
}
}
return fClothingOutfit;
}
void plClothingSDLModifier::PutCurrentStateIn(plStateDataRecord* dstState)
{
IPutCurrentStateIn(dstState);
}
//
// get current state from clothingOutfit and put it in dstState
//
void plClothingSDLModifier::IPutCurrentStateIn(plStateDataRecord* dstState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plClothingSDLModifier, nil target");
plClothingOutfit* clothing = GetClothingOutfit();
hsAssert(clothing, "nil clothingOutfit");
hsTArray<plStateDataRecord*> SDRs;
hsTArray<plClothingItem*> items=clothing->GetItemList();
hsTArray<plClothingItemOptions*> options=clothing->GetOptionList();
plSDStateVariable* clothesStateDesc = dstState->FindSDVar(kStrWardrobe); // find clothes list
int itemCount=items.GetCount();
int optionsCount = options.GetCount();
hsAssert(optionsCount==itemCount, "number of items should match number of options according to clothing.sdl");
if (clothesStateDesc->GetCount() != itemCount)
clothesStateDesc->Alloc(itemCount); // set appropriate list size
int lowerCount = (itemCount <= optionsCount ? itemCount : optionsCount);
int i;
for(i = 0; i < lowerCount; i++)
{
plClosetItem closetItem;
closetItem.fItem = items[i];
closetItem.fOptions = *options[i];
PutSingleItemIntoSDR(&closetItem, clothesStateDesc->GetStateDataRecord(i));
SDRs.Append(clothesStateDesc->GetStateDataRecord(i));
}
// skin tint
plSDStateVariable* appearanceStateDesc = dstState->FindSDVar(kStrAppearance); // for skin tint
UInt8 skinTint[3];
skinTint[0] = (UInt8)(clothing->fSkinTint.r * 255);
skinTint[1] = (UInt8)(clothing->fSkinTint.g * 255);
skinTint[2] = (UInt8)(clothing->fSkinTint.b * 255);
appearanceStateDesc->GetStateDataRecord(0)->FindVar(kStrSkinTint)->Set(skinTint);
plSimpleStateVariable* faceBlends = appearanceStateDesc->GetStateDataRecord(0)->FindVar(kStrFaceBlends);
int numBlends = plClothingElement::kLayerSkinLast - plClothingElement::kLayerSkinFirst;
if (faceBlends->GetCount() != numBlends)
faceBlends->Alloc(numBlends);
for(i = 0; i < numBlends; i++)
faceBlends->Set((UInt8)(clothing->fSkinBlends[i] * 255), i);
SDRs.Append(appearanceStateDesc->GetStateDataRecord(0));
// This logically belongs in the avatar.sdl file, but clothing.sdl is already broadcast to
// other players when you join an age, and I don't want to broadcast all of avatar.sdl for
// just this one value.
plSimpleStateVariable *var = dstState->FindVar(kStrLinkInAnim);
if (var)
var->Set(clothing->fAvatar->fLinkInAnimKey);
}
void plClothingSDLModifier::PutSingleItemIntoSDR(plClosetItem *item, plStateDataRecord *sdr)
{
plKey key = item->fItem->GetKey();
sdr->FindVar(kStrItem)->Set(key);
//hsColorRGBA c = item->fOptions.fTint1;
//hsColorRGBA c2 = item->fOptions.fTint2;
UInt8 c[3];
UInt8 c2[3];
c[0] = (UInt8)(item->fOptions.fTint1.r * 255);
c[1] = (UInt8)(item->fOptions.fTint1.g * 255);
c[2] = (UInt8)(item->fOptions.fTint1.b * 255);
c2[0] = (UInt8)(item->fOptions.fTint2.r * 255);
c2[1] = (UInt8)(item->fOptions.fTint2.g * 255);
c2[2] = (UInt8)(item->fOptions.fTint2.b * 255);
sdr->FindVar(kStrTint)->Set(c);
sdr->FindVar(kStrTint2)->Set(c2);
}
//
// Apply the SDL state that is passed in to the current clothing state.
//
void plClothingSDLModifier::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plClothingSDLModifier, nil target");
plClothingOutfit* clothing = GetClothingOutfit();
if( clothing == nil )
{
hsAssert(clothing, "nil clothingOutfit");
return;
}
plSDStateVariable* clothesStateDesc = srcState->FindSDVar(kStrWardrobe); // find clothes list
int num=clothesStateDesc->GetCount(); // size of clothes list
bool update=true;
// We just remove the accessories. Any regular items will be replaced
// when we try to wear something else in the same category. (And in
// case the player lies, this guarantees they'll at least be wearing something.)
clothing->StripAccessories();
int i;
for(i=0;i<num;i++)
{
// get clothes item from clothes list
plStateDataRecord* clothingItemState=clothesStateDesc->GetStateDataRecord(i);
HandleSingleSDR(clothingItemState, clothing);
}
plSDStateVariable* appearanceStateDesc = srcState->FindSDVar(kStrAppearance); // for skin tint
plStateDataRecord* appearanceState = appearanceStateDesc->GetStateDataRecord(0);
HandleSingleSDR(appearanceState, clothing);
if (update)
clothing->ForceUpdate(true /* retry */);
plSimpleStateVariable *var;
var = srcState->FindVar(kStrLinkInAnim);
if (var)
var->Get(&clothing->fAvatar->fLinkInAnimKey);
}
void plClothingSDLModifier::HandleSingleSDR(const plStateDataRecord *sdr, plClothingOutfit *clothing /* = nil */, plClosetItem *closetItem /* = nil */)
{
if (sdr == nil)
return;
int i;
UInt8 tint[3];
hsScalar tintScalar[3];
if (!strcmp(sdr->GetDescriptor()->GetName(), kStrClothingDescName))
{
// get item from clothesItem
plSimpleStateVariable* itemVar = sdr->FindVar(kStrItem);
plClothingItem* clothingItem = nil; // clothing->GetItemList()[i];
if (itemVar->IsUsed())
{
plKey key;
itemVar->Get(&key);
clothingItem = plClothingItem::ConvertNoRef(key ? key->GetObjectPtr() : nil);
if (clothingItem)
{
if (clothing)
clothing->AddItem(clothingItem, false, false /*bcast */);
if (closetItem)
closetItem->fItem = clothingItem;
}
}
// tints
if (clothingItem)
{
// get item from clothesItem
plSimpleStateVariable* tintVar = sdr->FindVar(kStrTint);
if (tintVar->IsUsed())
{
tintVar->Get(tint);
tintScalar[0] = tint[0] / 255.f;
tintScalar[1] = tint[1] / 255.f;
tintScalar[2] = tint[2] / 255.f;
if (clothing)
clothing->TintItem(clothingItem, tintScalar[0], tintScalar[1], tintScalar[2],
false /*update*/, false /*broadcast*/, false /*netForce*/, true, plClothingElement::kLayerTint1);
if (closetItem)
closetItem->fOptions.fTint1.Set(tintScalar[0], tintScalar[1], tintScalar[2], 1.f);
}
tintVar=sdr->FindVar(kStrTint2);
if (tintVar->IsUsed())
{
tintVar->Get(tint);
tintScalar[0] = tint[0] / 255.f;
tintScalar[1] = tint[1] / 255.f;
tintScalar[2] = tint[2] / 255.f;
if (clothing)
clothing->TintItem(clothingItem, tintScalar[0], tintScalar[1], tintScalar[2],
false /*update*/, false /*broadcast*/, false /*netForce*/, true, plClothingElement::kLayerTint2);
if (closetItem)
closetItem->fOptions.fTint2.Set(tintScalar[0], tintScalar[1], tintScalar[2], 1.f);
}
}
}
else if (!strcmp(sdr->GetDescriptor()->GetName(), kStrAppearanceDescName))
{
// skin tints
plSimpleStateVariable* skinVar = sdr->FindVar(kStrSkinTint);
if (skinVar->IsUsed())
{
skinVar->Get(tint);
if (clothing)
clothing->TintSkin(tint[0] / 255.f, tint[1] / 255.f, tint[2] / 255.f, false /* update */, false /*broadcast*/);
}
plSimpleStateVariable* faceBlends = sdr->FindVar(kStrFaceBlends);
if (faceBlends->IsUsed())
{
int numBlends = plClothingElement::kLayerSkinLast - plClothingElement::kLayerSkinFirst;
for(i = 0; i < numBlends && i < faceBlends->GetCount(); i++)
{
UInt8 blend;
faceBlends->Get(&blend, i);
clothing->fSkinBlends[i] = (hsScalar)blend / 255;
}
}
}
}
// FINDARMATUREMOD
const plClothingSDLModifier *plClothingSDLModifier::FindClothingSDLModifier(const plSceneObject *obj)
{
int count = obj->GetNumModifiers();
for (int i = 0; i < count; i++)
{
const plModifier *mod = obj->GetModifier(i);
const plClothingSDLModifier *sdlMod = plClothingSDLModifier::ConvertNoRef(mod);
if(sdlMod)
return sdlMod;
}
return nil;
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plClothingSDLModifier.h"
#include "plAvatarClothing.h"
#include "plClothingLayout.h"
#include "plArmatureMod.h"
#include "pnSceneObject/plSceneObject.h"
#include "pnMessage/plSDLModifierMsg.h"
#include "plSDL/plSDL.h"
#include "pnKeyedObject/plKeyImp.h"
// static vars
char plClothingSDLModifier::kStrItem[]="item";
char plClothingSDLModifier::kStrTint[]="tint";
char plClothingSDLModifier::kStrTint2[]="tint2";
char plClothingSDLModifier::kStrWardrobe[]="wardrobe";
char plClothingSDLModifier::kStrSkinTint[]="skinTint";
char plClothingSDLModifier::kStrFaceBlends[]="faceBlends";
char plClothingSDLModifier::kStrAppearance[]="appearance";
char plClothingSDLModifier::kStrClothingDescName[]="clothingItem";
char plClothingSDLModifier::kStrAppearanceDescName[]="appearanceOptions";
char plClothingSDLModifier::kStrLinkInAnim[] = "linkInAnim";
//
// init latest data
//
plClothingSDLModifier::plClothingSDLModifier() :
fClothingOutfit(nil)
{
}
//
// find armature mod and cache it's clothingOutfit
//
plClothingOutfit* plClothingSDLModifier::GetClothingOutfit()
{
if (fClothingOutfit)
return fClothingOutfit;
int i;
plSceneObject* target = GetTarget();
hsAssert(target, "plClothingSDLModifier: nil target");
for (i=0;i<target->GetNumModifiers();i++)
{
const plArmatureMod* am = plArmatureMod::ConvertNoRef(target->GetModifier(i));
if (am)
{
fClothingOutfit=am->GetClothingOutfit();
break;
}
}
return fClothingOutfit;
}
void plClothingSDLModifier::PutCurrentStateIn(plStateDataRecord* dstState)
{
IPutCurrentStateIn(dstState);
}
//
// get current state from clothingOutfit and put it in dstState
//
void plClothingSDLModifier::IPutCurrentStateIn(plStateDataRecord* dstState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plClothingSDLModifier, nil target");
plClothingOutfit* clothing = GetClothingOutfit();
hsAssert(clothing, "nil clothingOutfit");
hsTArray<plStateDataRecord*> SDRs;
hsTArray<plClothingItem*> items=clothing->GetItemList();
hsTArray<plClothingItemOptions*> options=clothing->GetOptionList();
plSDStateVariable* clothesStateDesc = dstState->FindSDVar(kStrWardrobe); // find clothes list
int itemCount=items.GetCount();
int optionsCount = options.GetCount();
hsAssert(optionsCount==itemCount, "number of items should match number of options according to clothing.sdl");
if (clothesStateDesc->GetCount() != itemCount)
clothesStateDesc->Alloc(itemCount); // set appropriate list size
int lowerCount = (itemCount <= optionsCount ? itemCount : optionsCount);
int i;
for(i = 0; i < lowerCount; i++)
{
plClosetItem closetItem;
closetItem.fItem = items[i];
closetItem.fOptions = *options[i];
PutSingleItemIntoSDR(&closetItem, clothesStateDesc->GetStateDataRecord(i));
SDRs.Append(clothesStateDesc->GetStateDataRecord(i));
}
// skin tint
plSDStateVariable* appearanceStateDesc = dstState->FindSDVar(kStrAppearance); // for skin tint
UInt8 skinTint[3];
skinTint[0] = (UInt8)(clothing->fSkinTint.r * 255);
skinTint[1] = (UInt8)(clothing->fSkinTint.g * 255);
skinTint[2] = (UInt8)(clothing->fSkinTint.b * 255);
appearanceStateDesc->GetStateDataRecord(0)->FindVar(kStrSkinTint)->Set(skinTint);
plSimpleStateVariable* faceBlends = appearanceStateDesc->GetStateDataRecord(0)->FindVar(kStrFaceBlends);
int numBlends = plClothingElement::kLayerSkinLast - plClothingElement::kLayerSkinFirst;
if (faceBlends->GetCount() != numBlends)
faceBlends->Alloc(numBlends);
for(i = 0; i < numBlends; i++)
faceBlends->Set((UInt8)(clothing->fSkinBlends[i] * 255), i);
SDRs.Append(appearanceStateDesc->GetStateDataRecord(0));
// This logically belongs in the avatar.sdl file, but clothing.sdl is already broadcast to
// other players when you join an age, and I don't want to broadcast all of avatar.sdl for
// just this one value.
plSimpleStateVariable *var = dstState->FindVar(kStrLinkInAnim);
if (var)
var->Set(clothing->fAvatar->fLinkInAnimKey);
}
void plClothingSDLModifier::PutSingleItemIntoSDR(plClosetItem *item, plStateDataRecord *sdr)
{
plKey key = item->fItem->GetKey();
sdr->FindVar(kStrItem)->Set(key);
//hsColorRGBA c = item->fOptions.fTint1;
//hsColorRGBA c2 = item->fOptions.fTint2;
UInt8 c[3];
UInt8 c2[3];
c[0] = (UInt8)(item->fOptions.fTint1.r * 255);
c[1] = (UInt8)(item->fOptions.fTint1.g * 255);
c[2] = (UInt8)(item->fOptions.fTint1.b * 255);
c2[0] = (UInt8)(item->fOptions.fTint2.r * 255);
c2[1] = (UInt8)(item->fOptions.fTint2.g * 255);
c2[2] = (UInt8)(item->fOptions.fTint2.b * 255);
sdr->FindVar(kStrTint)->Set(c);
sdr->FindVar(kStrTint2)->Set(c2);
}
//
// Apply the SDL state that is passed in to the current clothing state.
//
void plClothingSDLModifier::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plClothingSDLModifier, nil target");
plClothingOutfit* clothing = GetClothingOutfit();
if( clothing == nil )
{
hsAssert(clothing, "nil clothingOutfit");
return;
}
plSDStateVariable* clothesStateDesc = srcState->FindSDVar(kStrWardrobe); // find clothes list
int num=clothesStateDesc->GetCount(); // size of clothes list
bool update=true;
// We just remove the accessories. Any regular items will be replaced
// when we try to wear something else in the same category. (And in
// case the player lies, this guarantees they'll at least be wearing something.)
clothing->StripAccessories();
int i;
for(i=0;i<num;i++)
{
// get clothes item from clothes list
plStateDataRecord* clothingItemState=clothesStateDesc->GetStateDataRecord(i);
HandleSingleSDR(clothingItemState, clothing);
}
plSDStateVariable* appearanceStateDesc = srcState->FindSDVar(kStrAppearance); // for skin tint
plStateDataRecord* appearanceState = appearanceStateDesc->GetStateDataRecord(0);
HandleSingleSDR(appearanceState, clothing);
if (update)
clothing->ForceUpdate(true /* retry */);
plSimpleStateVariable *var;
var = srcState->FindVar(kStrLinkInAnim);
if (var)
var->Get(&clothing->fAvatar->fLinkInAnimKey);
}
void plClothingSDLModifier::HandleSingleSDR(const plStateDataRecord *sdr, plClothingOutfit *clothing /* = nil */, plClosetItem *closetItem /* = nil */)
{
if (sdr == nil)
return;
int i;
UInt8 tint[3];
hsScalar tintScalar[3];
if (!strcmp(sdr->GetDescriptor()->GetName(), kStrClothingDescName))
{
// get item from clothesItem
plSimpleStateVariable* itemVar = sdr->FindVar(kStrItem);
plClothingItem* clothingItem = nil; // clothing->GetItemList()[i];
if (itemVar->IsUsed())
{
plKey key;
itemVar->Get(&key);
clothingItem = plClothingItem::ConvertNoRef(key ? key->GetObjectPtr() : nil);
if (clothingItem)
{
if (clothing)
clothing->AddItem(clothingItem, false, false /*bcast */);
if (closetItem)
closetItem->fItem = clothingItem;
}
}
// tints
if (clothingItem)
{
// get item from clothesItem
plSimpleStateVariable* tintVar = sdr->FindVar(kStrTint);
if (tintVar->IsUsed())
{
tintVar->Get(tint);
tintScalar[0] = tint[0] / 255.f;
tintScalar[1] = tint[1] / 255.f;
tintScalar[2] = tint[2] / 255.f;
if (clothing)
clothing->TintItem(clothingItem, tintScalar[0], tintScalar[1], tintScalar[2],
false /*update*/, false /*broadcast*/, false /*netForce*/, true, plClothingElement::kLayerTint1);
if (closetItem)
closetItem->fOptions.fTint1.Set(tintScalar[0], tintScalar[1], tintScalar[2], 1.f);
}
tintVar=sdr->FindVar(kStrTint2);
if (tintVar->IsUsed())
{
tintVar->Get(tint);
tintScalar[0] = tint[0] / 255.f;
tintScalar[1] = tint[1] / 255.f;
tintScalar[2] = tint[2] / 255.f;
if (clothing)
clothing->TintItem(clothingItem, tintScalar[0], tintScalar[1], tintScalar[2],
false /*update*/, false /*broadcast*/, false /*netForce*/, true, plClothingElement::kLayerTint2);
if (closetItem)
closetItem->fOptions.fTint2.Set(tintScalar[0], tintScalar[1], tintScalar[2], 1.f);
}
}
}
else if (!strcmp(sdr->GetDescriptor()->GetName(), kStrAppearanceDescName))
{
// skin tints
plSimpleStateVariable* skinVar = sdr->FindVar(kStrSkinTint);
if (skinVar->IsUsed())
{
skinVar->Get(tint);
if (clothing)
clothing->TintSkin(tint[0] / 255.f, tint[1] / 255.f, tint[2] / 255.f, false /* update */, false /*broadcast*/);
}
plSimpleStateVariable* faceBlends = sdr->FindVar(kStrFaceBlends);
if (faceBlends->IsUsed())
{
int numBlends = plClothingElement::kLayerSkinLast - plClothingElement::kLayerSkinFirst;
for(i = 0; i < numBlends && i < faceBlends->GetCount(); i++)
{
UInt8 blend;
faceBlends->Get(&blend, i);
clothing->fSkinBlends[i] = (hsScalar)blend / 255;
}
}
}
}
// FINDARMATUREMOD
const plClothingSDLModifier *plClothingSDLModifier::FindClothingSDLModifier(const plSceneObject *obj)
{
int count = obj->GetNumModifiers();
for (int i = 0; i < count; i++)
{
const plModifier *mod = obj->GetModifier(i);
const plClothingSDLModifier *sdlMod = plClothingSDLModifier::ConvertNoRef(mod);
if(sdlMod)
return sdlMod;
}
return nil;
}

View File

@ -1,89 +1,89 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plClothingSDLModifier_inc
#define plClothingSDLModifier_inc
#include "plModifier/plSDLModifier.h"
#include "hsColorRGBA.h"
#include "hsTemplates.h"
#include "hsTypes.h"
//
// This modifier is responsible for sending and recving
// an avatar's clothing saveState.
//
class plClothingOutfit;
class plClothingItem;
class plClothingItemOptions;
class plClosetItem;
class plStateDataRecord;
class plKey;
class plClothingSDLModifier : public plSDLModifier
{
protected:
plClothingOutfit* fClothingOutfit;
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
UInt32 IApplyModFlags(UInt32 sendFlags) { return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState); }
public:
// var labels
static char kStrItem[];
static char kStrTint[];
static char kStrTint2[];
static char kStrWardrobe[];
static char kStrSkinTint[];
static char kStrFaceBlends[];
static char kStrAppearance[];
static char kStrClothingDescName[];
static char kStrAppearanceDescName[];
static char kStrLinkInAnim[];
CLASSNAME_REGISTER( plClothingSDLModifier );
GETINTERFACE_ANY( plClothingSDLModifier, plSDLModifier);
plClothingSDLModifier();
plClothingOutfit* GetClothingOutfit();
void SetClothingOutfit(plClothingOutfit* c) { fClothingOutfit=c; }
void PutCurrentStateIn(plStateDataRecord* dstState);
const char* GetSDLName() const { return kSDLClothing; }
static const char* GetClothingItemSDRName() { return kStrClothingDescName; }
// Pass in a clothing outfit if you want to apply the clothing item. Pass in a closet item if you're just
// looking to parse the SDL info.
// Aw heck. Go crazy if you want and pass them BOTH in! Muahahaha!
static void HandleSingleSDR(const plStateDataRecord *sdr, plClothingOutfit *clothing = nil, plClosetItem *closetItem = nil);
static void PutSingleItemIntoSDR(plClosetItem *item, plStateDataRecord *sdr);
static const plClothingSDLModifier *plClothingSDLModifier::FindClothingSDLModifier(const plSceneObject *obj);
};
#endif // plClothingSDLModifier_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plClothingSDLModifier_inc
#define plClothingSDLModifier_inc
#include "plModifier/plSDLModifier.h"
#include "hsColorRGBA.h"
#include "hsTemplates.h"
#include "hsTypes.h"
//
// This modifier is responsible for sending and recving
// an avatar's clothing saveState.
//
class plClothingOutfit;
class plClothingItem;
class plClothingItemOptions;
class plClosetItem;
class plStateDataRecord;
class plKey;
class plClothingSDLModifier : public plSDLModifier
{
protected:
plClothingOutfit* fClothingOutfit;
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
UInt32 IApplyModFlags(UInt32 sendFlags) { return (sendFlags | plSynchedObject::kDontPersistOnServer | plSynchedObject::kIsAvatarState); }
public:
// var labels
static char kStrItem[];
static char kStrTint[];
static char kStrTint2[];
static char kStrWardrobe[];
static char kStrSkinTint[];
static char kStrFaceBlends[];
static char kStrAppearance[];
static char kStrClothingDescName[];
static char kStrAppearanceDescName[];
static char kStrLinkInAnim[];
CLASSNAME_REGISTER( plClothingSDLModifier );
GETINTERFACE_ANY( plClothingSDLModifier, plSDLModifier);
plClothingSDLModifier();
plClothingOutfit* GetClothingOutfit();
void SetClothingOutfit(plClothingOutfit* c) { fClothingOutfit=c; }
void PutCurrentStateIn(plStateDataRecord* dstState);
const char* GetSDLName() const { return kSDLClothing; }
static const char* GetClothingItemSDRName() { return kStrClothingDescName; }
// Pass in a clothing outfit if you want to apply the clothing item. Pass in a closet item if you're just
// looking to parse the SDL info.
// Aw heck. Go crazy if you want and pass them BOTH in! Muahahaha!
static void HandleSingleSDR(const plStateDataRecord *sdr, plClothingOutfit *clothing = nil, plClosetItem *closetItem = nil);
static void PutSingleItemIntoSDR(plClosetItem *item, plStateDataRecord *sdr);
static const plClothingSDLModifier *plClothingSDLModifier::FindClothingSDLModifier(const plSceneObject *obj);
};
#endif // plClothingSDLModifier_inc

View File

@ -1,427 +1,427 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
// singular
#include "plCoopCoordinator.h"
// local
#include "plAvBrainCoop.h"
#include "plAvatarMgr.h"
#include "plAvTaskBrain.h"
#include "plAvTaskSeek.h"
// global
#include "hsUtils.h"
// other
#include "plMessage/plAvCoopMsg.h"
#include "plMessage/plAvatarMsg.h"
#include "plMessage/plInputIfaceMgrMsg.h"
#include "pnMessage/plNotifyMsg.h"
#include "pnNetCommon/plNetApp.h"
#include "plNetClient/plNetClientMgr.h"
#include "plPhysical.h"
#include "pnTimer/plTimerCallbackManager.h"
#include "plMessage/plTimerCallbackMsg.h"
const unsigned kAbortTimer = 1;
const float kAbortTimerDuration = 15; // 15 seconds
/////////////////////////////////////////////////////////////////////////////////////////
//
// CONSTRUCTORS
//
/////////////////////////////////////////////////////////////////////////////////////////
plCoopCoordinator::plCoopCoordinator()
: fHostBrain(nil),
fGuestBrain(nil),
fInitiatorID(0),
fInitiatorSerial(0),
fHostOfferStage(0),
fGuestAcceptStage(0),
fGuestAcceptMsg(nil),
fAutoStartGuest(nil),
fGuestAccepted(false)
{
}
// plCoopCoordinator ----------------------------------------
// ------------------
plCoopCoordinator::plCoopCoordinator(plKey host, plKey guest,
plAvBrainCoop *hostBrain, plAvBrainCoop *guestBrain,
const char *synchBone,
UInt32 hostOfferStage, UInt32 guestAcceptStage,
plMessage *guestAcceptMsg,
bool autoStartGuest)
: fHostKey(host),
fGuestKey(guest),
fHostBrain(hostBrain),
fGuestBrain(guestBrain),
fInitiatorID(hostBrain->GetInitiatorID()),
fInitiatorSerial(hostBrain->GetInitiatorSerial()),
fHostOfferStage(hostOfferStage),
fGuestAcceptStage(guestAcceptStage),
fGuestAcceptMsg(guestAcceptMsg),
fAutoStartGuest(autoStartGuest),
fGuestAccepted(false),
fGuestLinked(false)
{
const char * hostName = host->GetName();
const char * guestName = guest->GetName();
static int serial = 0;
int len = strlen(hostName) + strlen(guestName) + 3 /* serial num */ + 1;
char *newName = TRACKED_NEW char[len];
serial = serial % 999;
sprintf(newName, "%s%s%3i\x000", hostName, guestName, serial++);
plKey newKey = hsgResMgr::ResMgr()->NewKey(newName, this, host->GetUoid().GetLocation());
delete[] newName;
fSynchBone = hsStrcpy(synchBone);
plKey avMgrKey = plAvatarMgr::GetInstance()->GetKey();
guestBrain->SetRecipient(avMgrKey);
hostBrain->SetRecipient(avMgrKey);
// disable our clickability here if we are the guest
if (plNetClientMgr::GetInstance()->GetLocalPlayerKey() == guest)
{
plInputIfaceMgrMsg* pMsg = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kGUIDisableAvatarClickable);
pMsg->SetAvKey(guest);
pMsg->SetBCastFlag(plMessage::kNetPropagate);
pMsg->SetBCastFlag(plMessage::kNetForce);
pMsg->Send();
}
}
// plCoopCoordinator ------------------
// ------------------
plCoopCoordinator::~plCoopCoordinator()
{
delete[] fSynchBone;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// CONSTRUCTORS
//
/////////////////////////////////////////////////////////////////////////////////////////
// MsgReceive --------------------------------------
// -----------
hsBool plCoopCoordinator::MsgReceive(plMessage *msg)
{
plNotifyMsg *notify = plNotifyMsg::ConvertNoRef(msg);
if(notify)
{
proMultiStageEventData * mtevt = static_cast<proMultiStageEventData *>(notify->FindEventRecord(proEventData::kMultiStage));
if(mtevt)
{
int stageNum = mtevt->fStage;
UInt32 stageState = mtevt->fEvent;
plKey noteSender = notify->GetSender();
bool isFromHost = (noteSender == fHostKey);
bool isFromGuest = (noteSender == fGuestKey);
DebugMsg("COOP: Received multi-stage callback - stageNum = %d, stageState = %d, isFromHost = %d", stageNum, stageState, isFromHost ? 1 : 0);
if(isFromHost)
{
if(!fGuestAccepted)
{
// we've just entered the host offer stage (i.e., the offer is ready)
if(stageNum == fHostOfferStage && stageState == proEventData::kEnterStage)
{
if(fAutoStartGuest)
{
IStartGuest();
IStartTimeout();
} else {
fHostBrain->EnableGuestClick();
}
fGuestAccepted = true;
}
}
} else if(isFromGuest)
{
if(stageNum == fGuestAcceptStage && stageState == proEventData::kEnterStage)
{
plKey localPlayer = plNetClientApp::GetInstance()->GetLocalPlayerKey();
// we only actually fire off the guest accept message if we're on the guest machine.
// if it needs to be netpropped, the client can set that up when they set up the coop.
if(fGuestAcceptMsg && localPlayer == fGuestKey)
{
fGuestAcceptMsg->Send();
}
// kill the message (along with being active)
fGuestAcceptMsg = nil;
fGuestLinked = true;
IAdvanceParticipant(true); // advance the host
// IAdvanceParticipant(false); // advance the guest
}
} else {
// not from host; not from guest
// let's assume for the moment it's from a trigger.
IStartHost();
}
}
}
plAvCoopMsg *coop = plAvCoopMsg::ConvertNoRef(msg);
if(coop)
{
DebugMsg("COOP: Received coop message: %d", coop->fCommand);
switch(coop->fCommand)
{
case plAvCoopMsg::kGuestAccepted:
IStartGuest();
IStartTimeout();
break;
case plAvCoopMsg::kGuestSeeked:
// if they did make it to their target, then continue
IContinueGuest();
break;
case plAvCoopMsg::kGuestSeekAbort:
// if they aborted then just advance the host
// kill the message (along with being active)
fGuestAcceptMsg = nil;
fGuestLinked = true;
IAdvanceParticipant(true); // advance the host
break;
}
}
plAvTaskSeekDoneMsg *seekDone = plAvTaskSeekDoneMsg::ConvertNoRef(msg);
if (seekDone)
{
DebugMsg("COOP: Received avatar seek finished msg: aborted = %d", seekDone->fAborted ? 1 : 0);
if ( seekDone->fAborted )
{
plAvCoopMsg *coopM = TRACKED_NEW plAvCoopMsg(plAvCoopMsg::kGuestSeekAbort,fInitiatorID,(UInt16)fInitiatorSerial);
coopM->SetBCastFlag(plMessage::kNetPropagate);
coopM->SetBCastFlag(plMessage::kNetForce);
coopM->AddReceiver(GetKey());
coopM->Send();
}
else
{
plAvCoopMsg *coopM = TRACKED_NEW plAvCoopMsg(plAvCoopMsg::kGuestSeeked,fInitiatorID,(UInt16)fInitiatorSerial);
coopM->SetBCastFlag(plMessage::kNetPropagate);
coopM->SetBCastFlag(plMessage::kNetForce);
coopM->AddReceiver(GetKey());
coopM->Send();
}
}
plTimerCallbackMsg* timerMsg = plTimerCallbackMsg::ConvertNoRef(msg);
if (timerMsg)
{
if (timerMsg->fID == kAbortTimer && !fGuestLinked)
ITimeout();
}
return false;
}
// Run ----------------------
// ----
void plCoopCoordinator::Run()
{
IStartHost();
}
bool plCoopCoordinator::IsActiveForReal()
{
return fGuestAcceptMsg ? true : false;
}
// GetInitiatorID ------------------------
// ---------------
UInt32 plCoopCoordinator::GetInitiatorID()
{
return fInitiatorID;
}
// GetInitiatorSerial ------------------------
UInt16 plCoopCoordinator::GetInitiatorSerial()
{
return (UInt16)fInitiatorSerial;
}
// IStartHost ----------------------
// -----------
void plCoopCoordinator::IStartHost()
{
DebugMsg("COOP: IStartHost()");
plArmatureMod *guestAv = plAvatarMgr::FindAvatar(fGuestKey);
plArmatureMod *hostAv = plAvatarMgr::FindAvatar(fHostKey);
if (guestAv && hostAv)
{
plAvSeekMsg *msg = TRACKED_NEW plAvSeekMsg(nil, hostAv->GetKey(), nil, 1.f, true);
hsClearBits(msg->fFlags, plAvSeekMsg::kSeekFlagForce3rdPersonOnStart);
guestAv->GetPositionAndRotationSim(&msg->fTargetLookAt, nil);
hostAv->GetPositionAndRotationSim(&msg->fTargetPos, nil);
msg->Send();
}
// now tell the host to initiate the thing.
plAvTaskBrain *brainT = TRACKED_NEW plAvTaskBrain(fHostBrain);
plAvTaskMsg *brainM = TRACKED_NEW plAvTaskMsg(GetKey(), fHostKey, brainT);
brainM->SetBCastFlag(plMessage::kPropagateToModifiers);
brainM->Send();
}
// IStartGuest ----------------------
// ------------
void plCoopCoordinator::IStartGuest()
{
DebugMsg("COOP: IStartGuest()");
plSceneObject *avSO = plSceneObject::ConvertNoRef(fHostKey->ObjectIsLoaded());
if ( !avSO )
return;
const plArmatureMod *hostAv = (plArmatureMod*)avSO->GetModifierByType(plArmatureMod::Index());
if ( hostAv )
{
const plSceneObject *targetBone = hostAv->FindBone(fSynchBone);
if(targetBone)
{
plAvSeekMsg *seekMsg = TRACKED_NEW plAvSeekMsg( nil, nil,targetBone->GetKey(), 0, true, kAlignHandle, nil, false, plAvSeekMsg::kSeekFlagNoWarpOnTimeout, GetKey());
plAvTaskSeek *seekT = TRACKED_NEW plAvTaskSeek(seekMsg);
plAvTaskMsg *seekM = TRACKED_NEW plAvTaskMsg(GetKey(), fGuestKey, seekT);
seekM->SetBCastFlag(plMessage::kPropagateToModifiers);
seekM->Send();
}
}
}
// IContinueGuest ----------------------
// ------------
void plCoopCoordinator::IContinueGuest()
{
DebugMsg("COOP: IContinueGuest()");
plAvTaskBrain *brainT = TRACKED_NEW plAvTaskBrain(fGuestBrain);
plAvTaskMsg *brainM = TRACKED_NEW plAvTaskMsg(GetKey(), fGuestKey, brainT);
brainM->SetBCastFlag(plMessage::kPropagateToModifiers);
brainM->Send();
fGuestBrain = nil; // the armature will destroy the brain when done.
}
// IContinueHost ----------------------
// --------------
void plCoopCoordinator::IAdvanceParticipant(bool host)
{
DebugMsg("COOP: IAdvanceParticipant(%d)", host ? 1 : 0);
plKey &who = host ? fHostKey : fGuestKey;
plAvBrainGenericMsg* pMsg = TRACKED_NEW plAvBrainGenericMsg(nil, who,
plAvBrainGenericMsg::kNextStage, 0, false, 0.0,
false, false, 0.0);
pMsg->SetBCastFlag(plMessage::kPropagateToModifiers);
pMsg->Send();
}
// IStartTimeout ----------------------
// --------------
void plCoopCoordinator::IStartTimeout()
{
plTimerCallbackMsg* timerMsg = TRACKED_NEW plTimerCallbackMsg(GetKey(), kAbortTimer);
plgTimerCallbackMgr::NewTimer(kAbortTimerDuration, timerMsg);
}
// ITimeout ---------------------------
// --------------
void plCoopCoordinator::ITimeout()
{
fGuestAcceptMsg = nil;
IAdvanceParticipant(true); // advance the host
}
// Read -------------------------------------------------------------
// -----
void plCoopCoordinator::Read(hsStream *stream, hsResMgr *mgr)
{
fHostKey = mgr->ReadKey(stream);
fGuestKey = mgr->ReadKey(stream);
fHostBrain = plAvBrainCoop::ConvertNoRef(mgr->ReadCreatable(stream));
fGuestBrain = plAvBrainCoop::ConvertNoRef(mgr->ReadCreatable(stream));
fHostOfferStage = stream->ReadByte();
fGuestAcceptStage = stream->ReadBool();
if(stream->Readbool())
fGuestAcceptMsg = plMessage::ConvertNoRef(mgr->ReadCreatable(stream));
else
fGuestAcceptMsg = nil;
fSynchBone = stream->ReadSafeString();
fAutoStartGuest = stream->Readbool();
fInitiatorID = fHostBrain->GetInitiatorID();
fInitiatorSerial = fHostBrain->GetInitiatorSerial();
}
// Write -------------------------------------------------------------
// ------
void plCoopCoordinator::Write(hsStream *stream, hsResMgr *mgr)
{
mgr->WriteKey(stream, fHostKey);
mgr->WriteKey(stream, fGuestKey);
mgr->WriteCreatable(stream, fHostBrain);
mgr->WriteCreatable(stream, fGuestBrain);
stream->WriteByte((UInt8)fHostOfferStage);
stream->WriteByte((UInt8)fGuestAcceptStage);
stream->Writebool(fGuestAcceptMsg != nil);
if(fGuestAcceptMsg)
mgr->WriteCreatable(stream, fGuestAcceptMsg);
stream->WriteSafeString(fSynchBone);
stream->Writebool(fAutoStartGuest);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
// singular
#include "plCoopCoordinator.h"
// local
#include "plAvBrainCoop.h"
#include "plAvatarMgr.h"
#include "plAvTaskBrain.h"
#include "plAvTaskSeek.h"
// global
#include "hsUtils.h"
// other
#include "plMessage/plAvCoopMsg.h"
#include "plMessage/plAvatarMsg.h"
#include "plMessage/plInputIfaceMgrMsg.h"
#include "pnMessage/plNotifyMsg.h"
#include "pnNetCommon/plNetApp.h"
#include "plNetClient/plNetClientMgr.h"
#include "plPhysical.h"
#include "pnTimer/plTimerCallbackManager.h"
#include "plMessage/plTimerCallbackMsg.h"
const unsigned kAbortTimer = 1;
const float kAbortTimerDuration = 15; // 15 seconds
/////////////////////////////////////////////////////////////////////////////////////////
//
// CONSTRUCTORS
//
/////////////////////////////////////////////////////////////////////////////////////////
plCoopCoordinator::plCoopCoordinator()
: fHostBrain(nil),
fGuestBrain(nil),
fInitiatorID(0),
fInitiatorSerial(0),
fHostOfferStage(0),
fGuestAcceptStage(0),
fGuestAcceptMsg(nil),
fAutoStartGuest(nil),
fGuestAccepted(false)
{
}
// plCoopCoordinator ----------------------------------------
// ------------------
plCoopCoordinator::plCoopCoordinator(plKey host, plKey guest,
plAvBrainCoop *hostBrain, plAvBrainCoop *guestBrain,
const char *synchBone,
UInt32 hostOfferStage, UInt32 guestAcceptStage,
plMessage *guestAcceptMsg,
bool autoStartGuest)
: fHostKey(host),
fGuestKey(guest),
fHostBrain(hostBrain),
fGuestBrain(guestBrain),
fInitiatorID(hostBrain->GetInitiatorID()),
fInitiatorSerial(hostBrain->GetInitiatorSerial()),
fHostOfferStage(hostOfferStage),
fGuestAcceptStage(guestAcceptStage),
fGuestAcceptMsg(guestAcceptMsg),
fAutoStartGuest(autoStartGuest),
fGuestAccepted(false),
fGuestLinked(false)
{
const char * hostName = host->GetName();
const char * guestName = guest->GetName();
static int serial = 0;
int len = strlen(hostName) + strlen(guestName) + 3 /* serial num */ + 1;
char *newName = TRACKED_NEW char[len];
serial = serial % 999;
sprintf(newName, "%s%s%3i\x000", hostName, guestName, serial++);
plKey newKey = hsgResMgr::ResMgr()->NewKey(newName, this, host->GetUoid().GetLocation());
delete[] newName;
fSynchBone = hsStrcpy(synchBone);
plKey avMgrKey = plAvatarMgr::GetInstance()->GetKey();
guestBrain->SetRecipient(avMgrKey);
hostBrain->SetRecipient(avMgrKey);
// disable our clickability here if we are the guest
if (plNetClientMgr::GetInstance()->GetLocalPlayerKey() == guest)
{
plInputIfaceMgrMsg* pMsg = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kGUIDisableAvatarClickable);
pMsg->SetAvKey(guest);
pMsg->SetBCastFlag(plMessage::kNetPropagate);
pMsg->SetBCastFlag(plMessage::kNetForce);
pMsg->Send();
}
}
// plCoopCoordinator ------------------
// ------------------
plCoopCoordinator::~plCoopCoordinator()
{
delete[] fSynchBone;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// CONSTRUCTORS
//
/////////////////////////////////////////////////////////////////////////////////////////
// MsgReceive --------------------------------------
// -----------
hsBool plCoopCoordinator::MsgReceive(plMessage *msg)
{
plNotifyMsg *notify = plNotifyMsg::ConvertNoRef(msg);
if(notify)
{
proMultiStageEventData * mtevt = static_cast<proMultiStageEventData *>(notify->FindEventRecord(proEventData::kMultiStage));
if(mtevt)
{
int stageNum = mtevt->fStage;
UInt32 stageState = mtevt->fEvent;
plKey noteSender = notify->GetSender();
bool isFromHost = (noteSender == fHostKey);
bool isFromGuest = (noteSender == fGuestKey);
DebugMsg("COOP: Received multi-stage callback - stageNum = %d, stageState = %d, isFromHost = %d", stageNum, stageState, isFromHost ? 1 : 0);
if(isFromHost)
{
if(!fGuestAccepted)
{
// we've just entered the host offer stage (i.e., the offer is ready)
if(stageNum == fHostOfferStage && stageState == proEventData::kEnterStage)
{
if(fAutoStartGuest)
{
IStartGuest();
IStartTimeout();
} else {
fHostBrain->EnableGuestClick();
}
fGuestAccepted = true;
}
}
} else if(isFromGuest)
{
if(stageNum == fGuestAcceptStage && stageState == proEventData::kEnterStage)
{
plKey localPlayer = plNetClientApp::GetInstance()->GetLocalPlayerKey();
// we only actually fire off the guest accept message if we're on the guest machine.
// if it needs to be netpropped, the client can set that up when they set up the coop.
if(fGuestAcceptMsg && localPlayer == fGuestKey)
{
fGuestAcceptMsg->Send();
}
// kill the message (along with being active)
fGuestAcceptMsg = nil;
fGuestLinked = true;
IAdvanceParticipant(true); // advance the host
// IAdvanceParticipant(false); // advance the guest
}
} else {
// not from host; not from guest
// let's assume for the moment it's from a trigger.
IStartHost();
}
}
}
plAvCoopMsg *coop = plAvCoopMsg::ConvertNoRef(msg);
if(coop)
{
DebugMsg("COOP: Received coop message: %d", coop->fCommand);
switch(coop->fCommand)
{
case plAvCoopMsg::kGuestAccepted:
IStartGuest();
IStartTimeout();
break;
case plAvCoopMsg::kGuestSeeked:
// if they did make it to their target, then continue
IContinueGuest();
break;
case plAvCoopMsg::kGuestSeekAbort:
// if they aborted then just advance the host
// kill the message (along with being active)
fGuestAcceptMsg = nil;
fGuestLinked = true;
IAdvanceParticipant(true); // advance the host
break;
}
}
plAvTaskSeekDoneMsg *seekDone = plAvTaskSeekDoneMsg::ConvertNoRef(msg);
if (seekDone)
{
DebugMsg("COOP: Received avatar seek finished msg: aborted = %d", seekDone->fAborted ? 1 : 0);
if ( seekDone->fAborted )
{
plAvCoopMsg *coopM = TRACKED_NEW plAvCoopMsg(plAvCoopMsg::kGuestSeekAbort,fInitiatorID,(UInt16)fInitiatorSerial);
coopM->SetBCastFlag(plMessage::kNetPropagate);
coopM->SetBCastFlag(plMessage::kNetForce);
coopM->AddReceiver(GetKey());
coopM->Send();
}
else
{
plAvCoopMsg *coopM = TRACKED_NEW plAvCoopMsg(plAvCoopMsg::kGuestSeeked,fInitiatorID,(UInt16)fInitiatorSerial);
coopM->SetBCastFlag(plMessage::kNetPropagate);
coopM->SetBCastFlag(plMessage::kNetForce);
coopM->AddReceiver(GetKey());
coopM->Send();
}
}
plTimerCallbackMsg* timerMsg = plTimerCallbackMsg::ConvertNoRef(msg);
if (timerMsg)
{
if (timerMsg->fID == kAbortTimer && !fGuestLinked)
ITimeout();
}
return false;
}
// Run ----------------------
// ----
void plCoopCoordinator::Run()
{
IStartHost();
}
bool plCoopCoordinator::IsActiveForReal()
{
return fGuestAcceptMsg ? true : false;
}
// GetInitiatorID ------------------------
// ---------------
UInt32 plCoopCoordinator::GetInitiatorID()
{
return fInitiatorID;
}
// GetInitiatorSerial ------------------------
UInt16 plCoopCoordinator::GetInitiatorSerial()
{
return (UInt16)fInitiatorSerial;
}
// IStartHost ----------------------
// -----------
void plCoopCoordinator::IStartHost()
{
DebugMsg("COOP: IStartHost()");
plArmatureMod *guestAv = plAvatarMgr::FindAvatar(fGuestKey);
plArmatureMod *hostAv = plAvatarMgr::FindAvatar(fHostKey);
if (guestAv && hostAv)
{
plAvSeekMsg *msg = TRACKED_NEW plAvSeekMsg(nil, hostAv->GetKey(), nil, 1.f, true);
hsClearBits(msg->fFlags, plAvSeekMsg::kSeekFlagForce3rdPersonOnStart);
guestAv->GetPositionAndRotationSim(&msg->fTargetLookAt, nil);
hostAv->GetPositionAndRotationSim(&msg->fTargetPos, nil);
msg->Send();
}
// now tell the host to initiate the thing.
plAvTaskBrain *brainT = TRACKED_NEW plAvTaskBrain(fHostBrain);
plAvTaskMsg *brainM = TRACKED_NEW plAvTaskMsg(GetKey(), fHostKey, brainT);
brainM->SetBCastFlag(plMessage::kPropagateToModifiers);
brainM->Send();
}
// IStartGuest ----------------------
// ------------
void plCoopCoordinator::IStartGuest()
{
DebugMsg("COOP: IStartGuest()");
plSceneObject *avSO = plSceneObject::ConvertNoRef(fHostKey->ObjectIsLoaded());
if ( !avSO )
return;
const plArmatureMod *hostAv = (plArmatureMod*)avSO->GetModifierByType(plArmatureMod::Index());
if ( hostAv )
{
const plSceneObject *targetBone = hostAv->FindBone(fSynchBone);
if(targetBone)
{
plAvSeekMsg *seekMsg = TRACKED_NEW plAvSeekMsg( nil, nil,targetBone->GetKey(), 0, true, kAlignHandle, nil, false, plAvSeekMsg::kSeekFlagNoWarpOnTimeout, GetKey());
plAvTaskSeek *seekT = TRACKED_NEW plAvTaskSeek(seekMsg);
plAvTaskMsg *seekM = TRACKED_NEW plAvTaskMsg(GetKey(), fGuestKey, seekT);
seekM->SetBCastFlag(plMessage::kPropagateToModifiers);
seekM->Send();
}
}
}
// IContinueGuest ----------------------
// ------------
void plCoopCoordinator::IContinueGuest()
{
DebugMsg("COOP: IContinueGuest()");
plAvTaskBrain *brainT = TRACKED_NEW plAvTaskBrain(fGuestBrain);
plAvTaskMsg *brainM = TRACKED_NEW plAvTaskMsg(GetKey(), fGuestKey, brainT);
brainM->SetBCastFlag(plMessage::kPropagateToModifiers);
brainM->Send();
fGuestBrain = nil; // the armature will destroy the brain when done.
}
// IContinueHost ----------------------
// --------------
void plCoopCoordinator::IAdvanceParticipant(bool host)
{
DebugMsg("COOP: IAdvanceParticipant(%d)", host ? 1 : 0);
plKey &who = host ? fHostKey : fGuestKey;
plAvBrainGenericMsg* pMsg = TRACKED_NEW plAvBrainGenericMsg(nil, who,
plAvBrainGenericMsg::kNextStage, 0, false, 0.0,
false, false, 0.0);
pMsg->SetBCastFlag(plMessage::kPropagateToModifiers);
pMsg->Send();
}
// IStartTimeout ----------------------
// --------------
void plCoopCoordinator::IStartTimeout()
{
plTimerCallbackMsg* timerMsg = TRACKED_NEW plTimerCallbackMsg(GetKey(), kAbortTimer);
plgTimerCallbackMgr::NewTimer(kAbortTimerDuration, timerMsg);
}
// ITimeout ---------------------------
// --------------
void plCoopCoordinator::ITimeout()
{
fGuestAcceptMsg = nil;
IAdvanceParticipant(true); // advance the host
}
// Read -------------------------------------------------------------
// -----
void plCoopCoordinator::Read(hsStream *stream, hsResMgr *mgr)
{
fHostKey = mgr->ReadKey(stream);
fGuestKey = mgr->ReadKey(stream);
fHostBrain = plAvBrainCoop::ConvertNoRef(mgr->ReadCreatable(stream));
fGuestBrain = plAvBrainCoop::ConvertNoRef(mgr->ReadCreatable(stream));
fHostOfferStage = stream->ReadByte();
fGuestAcceptStage = stream->ReadBool();
if(stream->Readbool())
fGuestAcceptMsg = plMessage::ConvertNoRef(mgr->ReadCreatable(stream));
else
fGuestAcceptMsg = nil;
fSynchBone = stream->ReadSafeString();
fAutoStartGuest = stream->Readbool();
fInitiatorID = fHostBrain->GetInitiatorID();
fInitiatorSerial = fHostBrain->GetInitiatorSerial();
}
// Write -------------------------------------------------------------
// ------
void plCoopCoordinator::Write(hsStream *stream, hsResMgr *mgr)
{
mgr->WriteKey(stream, fHostKey);
mgr->WriteKey(stream, fGuestKey);
mgr->WriteCreatable(stream, fHostBrain);
mgr->WriteCreatable(stream, fGuestBrain);
stream->WriteByte((UInt8)fHostOfferStage);
stream->WriteByte((UInt8)fGuestAcceptStage);
stream->Writebool(fGuestAcceptMsg != nil);
if(fGuestAcceptMsg)
mgr->WriteCreatable(stream, fGuestAcceptMsg);
stream->WriteSafeString(fSynchBone);
stream->Writebool(fAutoStartGuest);
}

View File

@ -1,118 +1,118 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plCoopCoordinator_h
#define plCoopCoordinator_h
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
// global
#include "pnKeyedObject/hsKeyedObject.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plAvBrainCoop;
class plMessage;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plCoopCoordinator
Manages cooperation betweeen several generic brains; primarily serves as a place
to send synchronization messages. Originally this was going to be the role of the
'host' brain, but that didn't provide a good interface point for Python.
This object can either be a "helper" for Python, or its functionality can be
recoded in Python.
*/
class plCoopCoordinator : public hsKeyedObject
{
public:
plCoopCoordinator();
plCoopCoordinator(plKey host, plKey guest,
plAvBrainCoop *hostBrain, plAvBrainCoop *guestBrain,
const char *synchBone, UInt32 hostOfferStage, UInt32 guestAcceptStage,
plMessage *guestAcceptMsg,
bool autoStartGuest);
~plCoopCoordinator();
virtual hsBool MsgReceive(plMessage *msg);
void Run();
UInt32 GetInitiatorID();
UInt16 GetInitiatorSerial();
bool IsActiveForReal();
// rtti
CLASSNAME_REGISTER( plCoopCoordinator );
GETINTERFACE_ANY( plCoopCoordinator, hsKeyedObject);
// i/o
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
void IStartHost();
void IStartGuest();
void IContinueGuest();
void IAdvanceParticipant(bool host);
void IStartTimeout();
void ITimeout();
plKey fHostKey;
plKey fGuestKey;
plAvBrainCoop *fHostBrain;
plAvBrainCoop *fGuestBrain;
UInt32 fInitiatorID;
UInt32 fInitiatorSerial;
UInt32 fHostOfferStage; // when we enter this stage, the offer is ready
UInt32 fGuestAcceptStage; // when we enter this stage, the offer is accepted
plMessage *fGuestAcceptMsg; // send this when the guest accepts
char *fSynchBone;
bool fAutoStartGuest;
bool fGuestAccepted;
bool fGuestLinked; // guest linked, so ignore the timeout timer
};
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plCoopCoordinator_h
#define plCoopCoordinator_h
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
// global
#include "pnKeyedObject/hsKeyedObject.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plAvBrainCoop;
class plMessage;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plCoopCoordinator
Manages cooperation betweeen several generic brains; primarily serves as a place
to send synchronization messages. Originally this was going to be the role of the
'host' brain, but that didn't provide a good interface point for Python.
This object can either be a "helper" for Python, or its functionality can be
recoded in Python.
*/
class plCoopCoordinator : public hsKeyedObject
{
public:
plCoopCoordinator();
plCoopCoordinator(plKey host, plKey guest,
plAvBrainCoop *hostBrain, plAvBrainCoop *guestBrain,
const char *synchBone, UInt32 hostOfferStage, UInt32 guestAcceptStage,
plMessage *guestAcceptMsg,
bool autoStartGuest);
~plCoopCoordinator();
virtual hsBool MsgReceive(plMessage *msg);
void Run();
UInt32 GetInitiatorID();
UInt16 GetInitiatorSerial();
bool IsActiveForReal();
// rtti
CLASSNAME_REGISTER( plCoopCoordinator );
GETINTERFACE_ANY( plCoopCoordinator, hsKeyedObject);
// i/o
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
void IStartHost();
void IStartGuest();
void IContinueGuest();
void IAdvanceParticipant(bool host);
void IStartTimeout();
void ITimeout();
plKey fHostKey;
plKey fGuestKey;
plAvBrainCoop *fHostBrain;
plAvBrainCoop *fGuestBrain;
UInt32 fInitiatorID;
UInt32 fInitiatorSerial;
UInt32 fHostOfferStage; // when we enter this stage, the offer is ready
UInt32 fGuestAcceptStage; // when we enter this stage, the offer is accepted
plMessage *fGuestAcceptMsg; // send this when the guest accepts
char *fSynchBone;
bool fAutoStartGuest;
bool fGuestAccepted;
bool fGuestLinked; // guest linked, so ignore the timeout timer
};
#endif // plCoopCoordinator_h

View File

@ -1,160 +1,160 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef __PLCRITTERCMDS_H__
#define __PLCRITTERCMDS_H__
#include "hsStlUtils.h"
typedef std::vector<std::string> VCharArray;
class plCritterCommands
{
public:
// The order of these is significant; setting the blend on an animation in this list
// to maximum will prevent all animations above it from playing.
// I.E. if "turn left" is set to maximum, it will completely hide "idle"
enum stdAnim {
kIdle,
kTurnLeft,
kTurnRight,
kForwardMedium,
kForwardFast,
kReverse,
kBankLeft,
kBankRight,
kImpactDown,
kNumStdAnims
};
VCharArray fAnimNameTypes;
//Vector is used because the []operator is handy for filling
//the dialog boxes for implementation Components. -RXA
// KEEP THIS SYNCHRONIZED with the enum above.
plCritterCommands()
{
fAnimNameTypes.push_back("Idle");
fAnimNameTypes.push_back("TurnLeft");
fAnimNameTypes.push_back("TurnRight");
fAnimNameTypes.push_back("Forward Medium");
fAnimNameTypes.push_back("Forward Fast");
fAnimNameTypes.push_back("Reverse");
fAnimNameTypes.push_back("Bank Left");
fAnimNameTypes.push_back("Bank Right");
fAnimNameTypes.push_back("Impact Down");
}
int GetNumElements() { return fAnimNameTypes.size(); }
};
/*
class plCritterCommands
{
public:
enum avStdAnim{
kTorsoStraightenOut = 0,
kTorsoSpasticRotate,
kTorsoShakeHead,
kTorsoOpenMouth,
kTorsoHover,
kTorsoForwardFlightSpeedB,
kTorsoForwardFlightSpeedA,
kTorsoBankRightFlapping,
kTorsoBankRightCoasting,
kTorsoBankLeftFlapping,
kTorsoBankLeftCoasting,
kTorsoBackwardFlight,
kRightWingSpasticRotate,
kRightWingHover,
kRightWingForwardFlightSpeedB,
kRightWingForwardFlightSpeedA,
kRightWingBankRightFlapping,
kRightWingBankRightCoasting,
kRightWingBankLeftFlapping,
kRightWingBankLeftCoasting,
kRightWingBackwardFlight,
kLeftWingSpasticRotate,
kLeftWingHover,
kLeftWingForwardFlightSpeedA,
kLeftWingForwardFlightSpeedB,
kLeftWingBankRightFlapping,
kLeftWingBankRightCoasting,
kLeftWingBankLeftFlapping,
kLeftWingBankLeftCoasting,
kLeftWingBackwardFlight,
kNumStdAnims
} ;
VCharArray fAnimNameTypes;
//Vector is used because the []operator is handy for filling
//the dialog boxes for implementation Components. -RXA
// KEEP THIS SYNCHRONIZED with the enum above.
plCritterCommands()
{
fAnimNameTypes.push_back("Torso Straighten Out");
fAnimNameTypes.push_back("Torso Spastic Rotate");
fAnimNameTypes.push_back("Torso Shake Head");
fAnimNameTypes.push_back("Torso Open Mouth");
fAnimNameTypes.push_back("Torso Hover (Idle)");
fAnimNameTypes.push_back("Torso Forward SpeedB");
fAnimNameTypes.push_back("Torso Forward SpeedA");
fAnimNameTypes.push_back("Torso RBank Flapping");
fAnimNameTypes.push_back("Torso RBank Coasting");
fAnimNameTypes.push_back("Torso LBank Flapping");
fAnimNameTypes.push_back("Torso LBank Coasting");
fAnimNameTypes.push_back("Torso Backward Flight");
fAnimNameTypes.push_back("RWing Spastic Rotate");
fAnimNameTypes.push_back("RWing Hover (Idle)");
fAnimNameTypes.push_back("RWing Forward SpeedB");
fAnimNameTypes.push_back("RWing Forward SpeedA");
fAnimNameTypes.push_back("RWing RBank Flapping");
fAnimNameTypes.push_back("RWing RBank Coasting");
fAnimNameTypes.push_back("RWing LBank Flapping");
fAnimNameTypes.push_back("RWing LBank Coasting");
fAnimNameTypes.push_back("RWing Backward Flight");
fAnimNameTypes.push_back("LWing Spastic Rotate");
fAnimNameTypes.push_back("LWing Hover (Idle)");
fAnimNameTypes.push_back("LWing Forward SpeedA");
fAnimNameTypes.push_back("LWing Forward SpeedB");
fAnimNameTypes.push_back("LWing RBank Flapping");
fAnimNameTypes.push_back("LWing RBank Coasting");
fAnimNameTypes.push_back("LWing LBank Flapping");
fAnimNameTypes.push_back("LWing LBank Coasting");
fAnimNameTypes.push_back("LWing Backward Flight");
}
int GetNumElements() { return fAnimNameTypes.size(); }
};
*/
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef __PLCRITTERCMDS_H__
#define __PLCRITTERCMDS_H__
#include "hsStlUtils.h"
typedef std::vector<std::string> VCharArray;
class plCritterCommands
{
public:
// The order of these is significant; setting the blend on an animation in this list
// to maximum will prevent all animations above it from playing.
// I.E. if "turn left" is set to maximum, it will completely hide "idle"
enum stdAnim {
kIdle,
kTurnLeft,
kTurnRight,
kForwardMedium,
kForwardFast,
kReverse,
kBankLeft,
kBankRight,
kImpactDown,
kNumStdAnims
};
VCharArray fAnimNameTypes;
//Vector is used because the []operator is handy for filling
//the dialog boxes for implementation Components. -RXA
// KEEP THIS SYNCHRONIZED with the enum above.
plCritterCommands()
{
fAnimNameTypes.push_back("Idle");
fAnimNameTypes.push_back("TurnLeft");
fAnimNameTypes.push_back("TurnRight");
fAnimNameTypes.push_back("Forward Medium");
fAnimNameTypes.push_back("Forward Fast");
fAnimNameTypes.push_back("Reverse");
fAnimNameTypes.push_back("Bank Left");
fAnimNameTypes.push_back("Bank Right");
fAnimNameTypes.push_back("Impact Down");
}
int GetNumElements() { return fAnimNameTypes.size(); }
};
/*
class plCritterCommands
{
public:
enum avStdAnim{
kTorsoStraightenOut = 0,
kTorsoSpasticRotate,
kTorsoShakeHead,
kTorsoOpenMouth,
kTorsoHover,
kTorsoForwardFlightSpeedB,
kTorsoForwardFlightSpeedA,
kTorsoBankRightFlapping,
kTorsoBankRightCoasting,
kTorsoBankLeftFlapping,
kTorsoBankLeftCoasting,
kTorsoBackwardFlight,
kRightWingSpasticRotate,
kRightWingHover,
kRightWingForwardFlightSpeedB,
kRightWingForwardFlightSpeedA,
kRightWingBankRightFlapping,
kRightWingBankRightCoasting,
kRightWingBankLeftFlapping,
kRightWingBankLeftCoasting,
kRightWingBackwardFlight,
kLeftWingSpasticRotate,
kLeftWingHover,
kLeftWingForwardFlightSpeedA,
kLeftWingForwardFlightSpeedB,
kLeftWingBankRightFlapping,
kLeftWingBankRightCoasting,
kLeftWingBankLeftFlapping,
kLeftWingBankLeftCoasting,
kLeftWingBackwardFlight,
kNumStdAnims
} ;
VCharArray fAnimNameTypes;
//Vector is used because the []operator is handy for filling
//the dialog boxes for implementation Components. -RXA
// KEEP THIS SYNCHRONIZED with the enum above.
plCritterCommands()
{
fAnimNameTypes.push_back("Torso Straighten Out");
fAnimNameTypes.push_back("Torso Spastic Rotate");
fAnimNameTypes.push_back("Torso Shake Head");
fAnimNameTypes.push_back("Torso Open Mouth");
fAnimNameTypes.push_back("Torso Hover (Idle)");
fAnimNameTypes.push_back("Torso Forward SpeedB");
fAnimNameTypes.push_back("Torso Forward SpeedA");
fAnimNameTypes.push_back("Torso RBank Flapping");
fAnimNameTypes.push_back("Torso RBank Coasting");
fAnimNameTypes.push_back("Torso LBank Flapping");
fAnimNameTypes.push_back("Torso LBank Coasting");
fAnimNameTypes.push_back("Torso Backward Flight");
fAnimNameTypes.push_back("RWing Spastic Rotate");
fAnimNameTypes.push_back("RWing Hover (Idle)");
fAnimNameTypes.push_back("RWing Forward SpeedB");
fAnimNameTypes.push_back("RWing Forward SpeedA");
fAnimNameTypes.push_back("RWing RBank Flapping");
fAnimNameTypes.push_back("RWing RBank Coasting");
fAnimNameTypes.push_back("RWing LBank Flapping");
fAnimNameTypes.push_back("RWing LBank Coasting");
fAnimNameTypes.push_back("RWing Backward Flight");
fAnimNameTypes.push_back("LWing Spastic Rotate");
fAnimNameTypes.push_back("LWing Hover (Idle)");
fAnimNameTypes.push_back("LWing Forward SpeedA");
fAnimNameTypes.push_back("LWing Forward SpeedB");
fAnimNameTypes.push_back("LWing RBank Flapping");
fAnimNameTypes.push_back("LWing RBank Coasting");
fAnimNameTypes.push_back("LWing LBank Flapping");
fAnimNameTypes.push_back("LWing LBank Coasting");
fAnimNameTypes.push_back("LWing Backward Flight");
}
int GetNumElements() { return fAnimNameTypes.size(); }
};
*/
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,368 +1,368 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLMATRIXCHANNEL_INC
#define PLMATRIXCHANNEL_INC
// local
#include "plScalarChannel.h"
// global
#include "hsTypes.h" // you need types to include Matrix
#include "hsMatrix44.h"
#include "plTransform/hsAffineParts.h"
// local prototypes
class plQuatChannel;
class plPointChannel;
// external prototypes
class plController;
class hsAffineParts;
class plAnimTimeConvert;
class plMatrixChannelApplicator;
class plControllerCacheInfo;
//////////////////
// PLMATRIXCHANNEL
//////////////////
// an animation channel that outputs matrices
class plMatrixChannel : public plAGChannel
{
protected:
hsMatrix44 fResult;
hsAffineParts fAP;
public:
plMatrixChannel();
virtual ~plMatrixChannel();
// AG PROTOCOL
virtual const hsMatrix44 & Value(double time, bool peek = false);
virtual void Value(hsMatrix44 &matrix, double time, bool peek = false);
virtual const hsAffineParts & AffineValue(double time, bool peek = false);
// combine it (allocates combine object)
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
// blend it (allocates blend object)
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority);
// const eval at time zero
virtual plAGChannel * MakeZeroState();
// make a timeScale instance
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource);
virtual plAGPinType GetPinType() { return kAGPinTransform; };
virtual void Dump(int indent, bool optimized, double time);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plMatrixChannel );
GETINTERFACE_ANY( plMatrixChannel, plAGChannel );
};
///////////////////
// PLMATRIXCONSTANT
///////////////////
// A matrix source that just keeps handing out the same value
class plMatrixConstant : public plMatrixChannel
{
public:
plMatrixConstant();
plMatrixConstant(const hsMatrix44 &value);
virtual ~plMatrixConstant();
void Set(const hsMatrix44 &value);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plMatrixConstant );
GETINTERFACE_ANY( plMatrixConstant, plMatrixChannel );
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
};
////////////////////
// PLMATRIXTIMESCALE
////////////////////
// Adapts the time scale before passing it to the next channel in line.
// Use to instance animations while allowing each instance to run at different speeds.
class plMatrixTimeScale : public plMatrixChannel
{
protected:
plScalarChannel *fTimeSource;
plMatrixChannel *fChannelIn;
public:
plMatrixTimeScale();
plMatrixTimeScale(plMatrixChannel *channel, plScalarChannel *timeSource);
virtual ~plMatrixTimeScale();
virtual hsBool IsStoppedAt(double time);
virtual const hsMatrix44 & Value(double time, bool peek = false);
virtual const hsAffineParts & AffineValue(double time, bool peek = false);
virtual plAGChannel * Detach(plAGChannel * channel);
virtual void Dump(int indent, bool optimized, double time);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plMatrixTimeScale );
GETINTERFACE_ANY( plMatrixTimeScale, plMatrixChannel );
};
////////////////
// PLMATRIXBLEND
////////////////
// blends two matrices into one with weighting
class plMatrixBlend : public plMatrixChannel
{
protected:
plMatrixChannel * fChannelA;
plMatrixChannel * fOptimizedA;
plMatrixChannel * fChannelB;
plMatrixChannel * fOptimizedB;
plScalarChannel * fChannelBias;
int fPriority;
public:
// xTORs
plMatrixBlend();
plMatrixBlend(plMatrixChannel * channelA, plMatrixChannel * channelB, plScalarChannel * channelBias, int priority);
virtual ~plMatrixBlend();
virtual plAGChannel * plMatrixBlend::MakeBlend(plAGChannel *newChannel, plScalarChannel *channelBias, int blendPriority);
// you cannot blend on top of a channel that has higher priority than you do.
virtual UInt16 GetPriority();
// SPECIFICS
const plMatrixChannel * GetChannelA() const { return fChannelA; }
void SetChannelA(plMatrixChannel * channel) { fChannelA = channel; }
const plMatrixChannel * GetChannelB() const { return fChannelB; }
void SetChannelB(plMatrixChannel * channel) { fChannelB = channel; }
const plScalarChannel * GetChannelBias() const { return fChannelBias; }
void SetChannelBias(plScalarChannel * channel) { fChannelBias = channel; }
//virtual void SetBlend(float blend) { fBlend = blend; };
//virtual float GetBlend() { return fBlend; };
virtual hsBool IsStoppedAt(double time);
// AG PROTOCOL
virtual const hsMatrix44 & Value(double time, bool peek = false);
virtual const hsAffineParts & AffineValue(double time, bool peek = false);
// remove the specified channel from our graph
virtual plAGChannel * Detach(plAGChannel * channel);
virtual void Dump(int indent, bool optimized, double time);
plAGChannel *plMatrixBlend::Optimize(double time);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plMatrixBlend );
GETINTERFACE_ANY( plMatrixBlend, plMatrixChannel );
};
/////////////////////
// PLMATRIXCONTROLLER
/////////////////////
// converts a plController-style animation into a plMatrixChannel
class plMatrixControllerChannel : public plMatrixChannel
{
protected:
plController *fController;
public:
// xTORs
plMatrixControllerChannel();
plMatrixControllerChannel(plController *controller, hsAffineParts *parts);
virtual ~plMatrixControllerChannel();
// AG PROTOCOL
virtual const hsAffineParts & AffineValue(double time, bool peek = false);
virtual const hsAffineParts & AffineValue(double time, bool peek, plControllerCacheInfo *cache);
virtual const hsMatrix44 & Value(double time, bool peek = false);
virtual const hsMatrix44 & Value(double time, bool peek, plControllerCacheInfo *cache);
virtual plAGChannel * MakeCacheChannel(plAnimTimeConvert *atc);
virtual void Dump(int indent, bool optimized, double time);
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plMatrixControllerChannel );
GETINTERFACE_ANY( plMatrixControllerChannel, plMatrixChannel );
// persistence
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
};
/////////////////////////////////
// PLMATRIXCONTROLLERCACHECHANNEL
/////////////////////////////////
// Same as plMatrixController, but with caching info
class plMatrixControllerCacheChannel : public plMatrixChannel
{
protected:
plControllerCacheInfo *fCache;
plMatrixControllerChannel *fControllerChannel;
public:
plMatrixControllerCacheChannel();
plMatrixControllerCacheChannel(plMatrixControllerChannel *channel, plControllerCacheInfo *cache);
virtual ~plMatrixControllerCacheChannel();
virtual const hsMatrix44 & Value(double time, bool peek = false);
virtual const hsAffineParts & AffineValue(double time, bool peek = false);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plMatrixControllerCacheChannel );
GETINTERFACE_ANY( plMatrixControllerCacheChannel, plMatrixChannel );
// Created at runtime only, so no Read/Write
};
/////////////////////
// PLQUATPOINTCOMBINE
/////////////////////
// combines a quaternion and a point into a matrix
class plQuatPointCombine : public plMatrixChannel
{
protected:
plQuatChannel *fQuatChannel;
plPointChannel *fPointChannel;
public:
// xTORs
plQuatPointCombine();
plQuatPointCombine(plQuatChannel *quatChannel, plPointChannel *pointChannel);
virtual ~plQuatPointCombine();
// SPECIFICS
const plQuatChannel * GetQuatChannel() const { return fQuatChannel; }
void SetQuatChannel(plQuatChannel * channel) { fQuatChannel = channel; }
plPointChannel * GetPointChannel() const { return fPointChannel; }
void SetPointChannel(plPointChannel * channel) { fPointChannel = channel; }
// AG PROTOCOL
virtual const hsMatrix44 & Value(double time);
virtual const hsAffineParts & AffineValue(double time);
// remove the specified channel from our graph
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plQuatPointCombine );
GETINTERFACE_ANY( plQuatPointCombine, plMatrixChannel );
};
/////////////////////
//
// Applicator classes
class plMatrixChannelApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plMatrixChannelApplicator );
GETINTERFACE_ANY( plMatrixChannelApplicator, plAGApplicator );
virtual hsBool CanCombine(plAGApplicator *app) { return false; }
virtual plAGPinType GetPinType() { return kAGPinTransform; }
};
// PLMATRIXDELAYEDCORRECTIONAPPLICATOR
// Used for blending in sudden location changes due to synch messages.
// This app tacks on a correction to the l2p transform
// (so l2p is set as animL2P*correction)
// interpolating this to the identity matrix over time.
class plMatrixDelayedCorrectionApplicator : public plMatrixChannelApplicator
{
protected:
hsAffineParts fCorAP; // AP of the correction.
double fDelayStart; // Start time of the delayed correction
// apply our animation * our correction to the node
virtual void IApply(const plAGModifier *mod, double time);
public:
plMatrixDelayedCorrectionApplicator() : fDelayStart(-1000.f), fIgnoreNextCorrection(true) { fCorAP.Reset(); }
CLASSNAME_REGISTER( plMatrixDelayedCorrectionApplicator );
GETINTERFACE_ANY( plMatrixDelayedCorrectionApplicator, plMatrixChannelApplicator );
void SetCorrection(hsMatrix44 &correction);
virtual hsBool AutoDelete() { return false; } // should we remove it when its input channel is gone?
// applicator arbitration...
virtual plAGPinType GetPinType() { return kAGPinTransform; }
virtual hsBool CanBlend(plAGApplicator *app);
hsBool fIgnoreNextCorrection;
static const hsScalar fDelayLength; // static var for now.
};
// PLMATRIXDIFFERENCEAPP
// Each frame, this guy takes the difference between his current value
// and his last value and applies that to the current world
// transform of the target.
// You could also call it the Temporal Matrix Difference Applicator,
// but that sucks to type.
class plMatrixDifferenceApp : public plMatrixChannelApplicator
{
public:
/** Forget the previous cached transform and start again */
void Reset(double time);
/** Should this applicator be automatically removed when its channel goes away? */
virtual hsBool AutoDelete() { return false; }
// applicator arbitration
virtual plAGPinType GetPinType() { return kAGPinTransform; }
virtual hsBool CanBlend(plAGApplicator *app);
CLASSNAME_REGISTER(plMatrixDifferenceApp);
GETINTERFACE_ANY(plMatrixDifferenceApp, plMatrixChannelApplicator);
protected:
virtual void IApply(const plAGModifier *mod, double time);
hsMatrix44 fLastL2A; // local to animation space
hsMatrix44 fLastA2L; // animation space to local
bool fNew; // true if we haven't cached anything yet
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLMATRIXCHANNEL_INC
#define PLMATRIXCHANNEL_INC
// local
#include "plScalarChannel.h"
// global
#include "hsTypes.h" // you need types to include Matrix
#include "hsMatrix44.h"
#include "plTransform/hsAffineParts.h"
// local prototypes
class plQuatChannel;
class plPointChannel;
// external prototypes
class plController;
class hsAffineParts;
class plAnimTimeConvert;
class plMatrixChannelApplicator;
class plControllerCacheInfo;
//////////////////
// PLMATRIXCHANNEL
//////////////////
// an animation channel that outputs matrices
class plMatrixChannel : public plAGChannel
{
protected:
hsMatrix44 fResult;
hsAffineParts fAP;
public:
plMatrixChannel();
virtual ~plMatrixChannel();
// AG PROTOCOL
virtual const hsMatrix44 & Value(double time, bool peek = false);
virtual void Value(hsMatrix44 &matrix, double time, bool peek = false);
virtual const hsAffineParts & AffineValue(double time, bool peek = false);
// combine it (allocates combine object)
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
// blend it (allocates blend object)
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority);
// const eval at time zero
virtual plAGChannel * MakeZeroState();
// make a timeScale instance
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource);
virtual plAGPinType GetPinType() { return kAGPinTransform; };
virtual void Dump(int indent, bool optimized, double time);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plMatrixChannel );
GETINTERFACE_ANY( plMatrixChannel, plAGChannel );
};
///////////////////
// PLMATRIXCONSTANT
///////////////////
// A matrix source that just keeps handing out the same value
class plMatrixConstant : public plMatrixChannel
{
public:
plMatrixConstant();
plMatrixConstant(const hsMatrix44 &value);
virtual ~plMatrixConstant();
void Set(const hsMatrix44 &value);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plMatrixConstant );
GETINTERFACE_ANY( plMatrixConstant, plMatrixChannel );
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
};
////////////////////
// PLMATRIXTIMESCALE
////////////////////
// Adapts the time scale before passing it to the next channel in line.
// Use to instance animations while allowing each instance to run at different speeds.
class plMatrixTimeScale : public plMatrixChannel
{
protected:
plScalarChannel *fTimeSource;
plMatrixChannel *fChannelIn;
public:
plMatrixTimeScale();
plMatrixTimeScale(plMatrixChannel *channel, plScalarChannel *timeSource);
virtual ~plMatrixTimeScale();
virtual hsBool IsStoppedAt(double time);
virtual const hsMatrix44 & Value(double time, bool peek = false);
virtual const hsAffineParts & AffineValue(double time, bool peek = false);
virtual plAGChannel * Detach(plAGChannel * channel);
virtual void Dump(int indent, bool optimized, double time);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plMatrixTimeScale );
GETINTERFACE_ANY( plMatrixTimeScale, plMatrixChannel );
};
////////////////
// PLMATRIXBLEND
////////////////
// blends two matrices into one with weighting
class plMatrixBlend : public plMatrixChannel
{
protected:
plMatrixChannel * fChannelA;
plMatrixChannel * fOptimizedA;
plMatrixChannel * fChannelB;
plMatrixChannel * fOptimizedB;
plScalarChannel * fChannelBias;
int fPriority;
public:
// xTORs
plMatrixBlend();
plMatrixBlend(plMatrixChannel * channelA, plMatrixChannel * channelB, plScalarChannel * channelBias, int priority);
virtual ~plMatrixBlend();
virtual plAGChannel * plMatrixBlend::MakeBlend(plAGChannel *newChannel, plScalarChannel *channelBias, int blendPriority);
// you cannot blend on top of a channel that has higher priority than you do.
virtual UInt16 GetPriority();
// SPECIFICS
const plMatrixChannel * GetChannelA() const { return fChannelA; }
void SetChannelA(plMatrixChannel * channel) { fChannelA = channel; }
const plMatrixChannel * GetChannelB() const { return fChannelB; }
void SetChannelB(plMatrixChannel * channel) { fChannelB = channel; }
const plScalarChannel * GetChannelBias() const { return fChannelBias; }
void SetChannelBias(plScalarChannel * channel) { fChannelBias = channel; }
//virtual void SetBlend(float blend) { fBlend = blend; };
//virtual float GetBlend() { return fBlend; };
virtual hsBool IsStoppedAt(double time);
// AG PROTOCOL
virtual const hsMatrix44 & Value(double time, bool peek = false);
virtual const hsAffineParts & AffineValue(double time, bool peek = false);
// remove the specified channel from our graph
virtual plAGChannel * Detach(plAGChannel * channel);
virtual void Dump(int indent, bool optimized, double time);
plAGChannel *plMatrixBlend::Optimize(double time);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plMatrixBlend );
GETINTERFACE_ANY( plMatrixBlend, plMatrixChannel );
};
/////////////////////
// PLMATRIXCONTROLLER
/////////////////////
// converts a plController-style animation into a plMatrixChannel
class plMatrixControllerChannel : public plMatrixChannel
{
protected:
plController *fController;
public:
// xTORs
plMatrixControllerChannel();
plMatrixControllerChannel(plController *controller, hsAffineParts *parts);
virtual ~plMatrixControllerChannel();
// AG PROTOCOL
virtual const hsAffineParts & AffineValue(double time, bool peek = false);
virtual const hsAffineParts & AffineValue(double time, bool peek, plControllerCacheInfo *cache);
virtual const hsMatrix44 & Value(double time, bool peek = false);
virtual const hsMatrix44 & Value(double time, bool peek, plControllerCacheInfo *cache);
virtual plAGChannel * MakeCacheChannel(plAnimTimeConvert *atc);
virtual void Dump(int indent, bool optimized, double time);
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plMatrixControllerChannel );
GETINTERFACE_ANY( plMatrixControllerChannel, plMatrixChannel );
// persistence
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
};
/////////////////////////////////
// PLMATRIXCONTROLLERCACHECHANNEL
/////////////////////////////////
// Same as plMatrixController, but with caching info
class plMatrixControllerCacheChannel : public plMatrixChannel
{
protected:
plControllerCacheInfo *fCache;
plMatrixControllerChannel *fControllerChannel;
public:
plMatrixControllerCacheChannel();
plMatrixControllerCacheChannel(plMatrixControllerChannel *channel, plControllerCacheInfo *cache);
virtual ~plMatrixControllerCacheChannel();
virtual const hsMatrix44 & Value(double time, bool peek = false);
virtual const hsAffineParts & AffineValue(double time, bool peek = false);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plMatrixControllerCacheChannel );
GETINTERFACE_ANY( plMatrixControllerCacheChannel, plMatrixChannel );
// Created at runtime only, so no Read/Write
};
/////////////////////
// PLQUATPOINTCOMBINE
/////////////////////
// combines a quaternion and a point into a matrix
class plQuatPointCombine : public plMatrixChannel
{
protected:
plQuatChannel *fQuatChannel;
plPointChannel *fPointChannel;
public:
// xTORs
plQuatPointCombine();
plQuatPointCombine(plQuatChannel *quatChannel, plPointChannel *pointChannel);
virtual ~plQuatPointCombine();
// SPECIFICS
const plQuatChannel * GetQuatChannel() const { return fQuatChannel; }
void SetQuatChannel(plQuatChannel * channel) { fQuatChannel = channel; }
plPointChannel * GetPointChannel() const { return fPointChannel; }
void SetPointChannel(plPointChannel * channel) { fPointChannel = channel; }
// AG PROTOCOL
virtual const hsMatrix44 & Value(double time);
virtual const hsAffineParts & AffineValue(double time);
// remove the specified channel from our graph
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plQuatPointCombine );
GETINTERFACE_ANY( plQuatPointCombine, plMatrixChannel );
};
/////////////////////
//
// Applicator classes
class plMatrixChannelApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plMatrixChannelApplicator );
GETINTERFACE_ANY( plMatrixChannelApplicator, plAGApplicator );
virtual hsBool CanCombine(plAGApplicator *app) { return false; }
virtual plAGPinType GetPinType() { return kAGPinTransform; }
};
// PLMATRIXDELAYEDCORRECTIONAPPLICATOR
// Used for blending in sudden location changes due to synch messages.
// This app tacks on a correction to the l2p transform
// (so l2p is set as animL2P*correction)
// interpolating this to the identity matrix over time.
class plMatrixDelayedCorrectionApplicator : public plMatrixChannelApplicator
{
protected:
hsAffineParts fCorAP; // AP of the correction.
double fDelayStart; // Start time of the delayed correction
// apply our animation * our correction to the node
virtual void IApply(const plAGModifier *mod, double time);
public:
plMatrixDelayedCorrectionApplicator() : fDelayStart(-1000.f), fIgnoreNextCorrection(true) { fCorAP.Reset(); }
CLASSNAME_REGISTER( plMatrixDelayedCorrectionApplicator );
GETINTERFACE_ANY( plMatrixDelayedCorrectionApplicator, plMatrixChannelApplicator );
void SetCorrection(hsMatrix44 &correction);
virtual hsBool AutoDelete() { return false; } // should we remove it when its input channel is gone?
// applicator arbitration...
virtual plAGPinType GetPinType() { return kAGPinTransform; }
virtual hsBool CanBlend(plAGApplicator *app);
hsBool fIgnoreNextCorrection;
static const hsScalar fDelayLength; // static var for now.
};
// PLMATRIXDIFFERENCEAPP
// Each frame, this guy takes the difference between his current value
// and his last value and applies that to the current world
// transform of the target.
// You could also call it the Temporal Matrix Difference Applicator,
// but that sucks to type.
class plMatrixDifferenceApp : public plMatrixChannelApplicator
{
public:
/** Forget the previous cached transform and start again */
void Reset(double time);
/** Should this applicator be automatically removed when its channel goes away? */
virtual hsBool AutoDelete() { return false; }
// applicator arbitration
virtual plAGPinType GetPinType() { return kAGPinTransform; }
virtual hsBool CanBlend(plAGApplicator *app);
CLASSNAME_REGISTER(plMatrixDifferenceApp);
GETINTERFACE_ANY(plMatrixDifferenceApp, plMatrixChannelApplicator);
protected:
virtual void IApply(const plAGModifier *mod, double time);
hsMatrix44 fLastL2A; // local to animation space
hsMatrix44 fLastA2L; // animation space to local
bool fNew; // true if we haven't cached anything yet
};
#endif

View File

@ -1,245 +1,245 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plMultistageBehMod.h"
// local
#include "plAvBrainGeneric.h"
#include "plAnimStage.h"
#include "plArmatureMod.h"
// global
#include "hsResMgr.h"
//other
#include "plMessage/plAvatarMsg.h"
#include "plMessage/plMultistageMsg.h"
#include "pnMessage/plNotifyMsg.h"
#include "pnSceneObject/plSceneObject.h"
#include "plInputCore/plAvatarInputInterface.h"
#ifdef DEBUG_MULTISTAGE
#include "plAvatarMgr.h"
#include "plStatusLog/plStatusLog.h"
#endif
plMultistageBehMod::plMultistageBehMod() : fStages(nil), fFreezePhys(false), fSmartSeek(false), fReverseFBControlsOnRelease(false), fNetProp(true), fNetForce(false)
{
}
plMultistageBehMod::plMultistageBehMod(plAnimStageVec* stages,
bool freezePhys,
bool smartSeek,
bool reverseFBControlsOnRelease,
std::vector<plKey>* receivers)
: fStages(stages),
fFreezePhys(freezePhys),
fSmartSeek(smartSeek),
fReverseFBControlsOnRelease(reverseFBControlsOnRelease),
fNetProp(true),
fNetForce(false)
{
if (receivers)
fReceivers = *receivers;
}
plMultistageBehMod::~plMultistageBehMod()
{
IDeleteStageVec();
}
void plMultistageBehMod::Init(plAnimStageVec *stages,
bool freezePhys,
bool smartSeek,
bool reverseFBControlsOnRelease,
std::vector<plKey>* receivers)
{
fStages = stages;
fFreezePhys = freezePhys;
fSmartSeek = smartSeek;
fReverseFBControlsOnRelease = reverseFBControlsOnRelease;
if (receivers)
fReceivers = *receivers;
}
void plMultistageBehMod::IDeleteStageVec()
{
if (fStages)
{
int numStages = fStages->size();
for (int i = 0; i < numStages; i++)
{
plAnimStage* stage = (*fStages)[i];
delete stage;
}
delete fStages;
fStages = nil;
}
}
hsBool plMultistageBehMod::MsgReceive(plMessage* msg)
{
plMultistageModMsg *multiMsg = nil;
plNotifyMsg* notifyMsg = plNotifyMsg::ConvertNoRef(msg);
if (notifyMsg)
{
hsAssert(fStages, "Trying to trigger multistage, but no stages are present.");
if(fStages)
{
plKey avKey = notifyMsg->GetAvatarKey();
hsAssert(avKey, "Avatar key missing trying to trigger multistage.");
if(avKey)
{
plSceneObject *avObj = plSceneObject::ConvertNoRef(avKey->ObjectIsLoaded());
hsAssert(avObj, "Avatar not loaded when trying to trigger multistage.");
if(avObj)
{
// Create a copy of our reference anim stages to give to the brain
plAnimStageVec* stages = TRACKED_NEW plAnimStageVec;
int numStages = fStages->size();
stages->reserve(numStages);
// hack hack hack
hsBool ladder = false;
for (int i = 0; i < numStages; i++)
{
plAnimStage* stage = TRACKED_NEW plAnimStage;
*stage = *((*fStages)[i]);
stages->push_back(stage);
if (strstr(stage->GetAnimName(),"adder") != nil)
ladder = true;
}
const plArmatureMod *avMod = (plArmatureMod*)avObj->GetModifierByType(plArmatureMod::Index());
hsAssert(avMod, "Missing armature mod on avatar scene object.");
if(avMod)
{
plKey sender = notifyMsg->GetSender();
plKey avModKey = avMod->GetKey();
plKey seekKey = GetTarget()->GetKey(); // our seek point
#ifdef DEBUG_MULTISTAGE
char sbuf[256];
sprintf(sbuf,"plMultistageModMsg - starting multistage from %s",sender->GetName());
plAvatarMgr::GetInstance()->GetLog()->AddLine(sbuf);
#endif
plAvSeekMsg *seeker = TRACKED_NEW plAvSeekMsg(nil, avModKey, seekKey, 1.0f, fSmartSeek);
seeker->Send();
// these (currently unused) callbacks are for the brain itself, not any of the stages
plMessage *exitCallback = nil, *enterCallback = nil;
UInt32 exitFlags = plAvBrainGeneric::kExitNormal;
plAvBrainGeneric *brain = TRACKED_NEW plAvBrainGeneric(stages, exitCallback, enterCallback, sender, exitFlags,
plAvBrainGeneric::kDefaultFadeIn, plAvBrainGeneric::kDefaultFadeOut,
plAvBrainGeneric::kMoveRelative);
if (ladder)
{
brain->SetType(plAvBrainGeneric::kLadder);
}
brain->SetReverseFBControlsOnRelease(fReverseFBControlsOnRelease);
plAvPushBrainMsg* pushBrain = TRACKED_NEW plAvPushBrainMsg(GetKey(), avModKey, brain);
pushBrain->Send();
}
}
}
}
return true;
}
else if (multiMsg = plMultistageModMsg::ConvertNoRef(msg))
{
if (multiMsg->GetCommand(plMultistageModMsg::kSetLoopCount))
{
((*fStages)[multiMsg->fStageNum])->SetNumLoops(multiMsg->fNumLoops);
}
return true;
}
else {
return plSingleModifier::MsgReceive(msg);
}
}
void plMultistageBehMod::Read(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Read(stream, mgr);
fFreezePhys = stream->Readbool();
fSmartSeek = stream->Readbool();
fReverseFBControlsOnRelease = stream->Readbool();
IDeleteStageVec();
fStages = TRACKED_NEW plAnimStageVec;
int numStages = stream->ReadSwap32();
fStages->reserve(numStages);
int i;
for (i = 0; i < numStages; i++)
{
plAnimStage* stage = TRACKED_NEW plAnimStage;
stage->Read(stream, mgr);
stage->SetMod(this);
fStages->push_back(stage);
}
int numReceivers = stream->ReadSwap32();
fReceivers.clear();
fReceivers.reserve(numReceivers);
for (i = 0; i < numReceivers; i++)
{
plKey key = mgr->ReadKey(stream);
fReceivers.push_back(key);
}
}
void plMultistageBehMod::Write(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Write(stream, mgr);
stream->Writebool(fFreezePhys);
stream->Writebool(fSmartSeek);
stream->Writebool(fReverseFBControlsOnRelease);
int numStages = fStages->size();
stream->WriteSwap32(numStages);
int i;
for (i = 0; i < numStages; i++)
{
plAnimStage* stage = (*fStages)[i];
stage->Write(stream, mgr);
}
int numReceivers = fReceivers.size();
stream->WriteSwap32(numReceivers);
for (i = 0; i < numReceivers; i++)
{
plKey key = fReceivers[i];
mgr->WriteKey(stream, key);
}
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plMultistageBehMod.h"
// local
#include "plAvBrainGeneric.h"
#include "plAnimStage.h"
#include "plArmatureMod.h"
// global
#include "hsResMgr.h"
//other
#include "plMessage/plAvatarMsg.h"
#include "plMessage/plMultistageMsg.h"
#include "pnMessage/plNotifyMsg.h"
#include "pnSceneObject/plSceneObject.h"
#include "plInputCore/plAvatarInputInterface.h"
#ifdef DEBUG_MULTISTAGE
#include "plAvatarMgr.h"
#include "plStatusLog/plStatusLog.h"
#endif
plMultistageBehMod::plMultistageBehMod() : fStages(nil), fFreezePhys(false), fSmartSeek(false), fReverseFBControlsOnRelease(false), fNetProp(true), fNetForce(false)
{
}
plMultistageBehMod::plMultistageBehMod(plAnimStageVec* stages,
bool freezePhys,
bool smartSeek,
bool reverseFBControlsOnRelease,
std::vector<plKey>* receivers)
: fStages(stages),
fFreezePhys(freezePhys),
fSmartSeek(smartSeek),
fReverseFBControlsOnRelease(reverseFBControlsOnRelease),
fNetProp(true),
fNetForce(false)
{
if (receivers)
fReceivers = *receivers;
}
plMultistageBehMod::~plMultistageBehMod()
{
IDeleteStageVec();
}
void plMultistageBehMod::Init(plAnimStageVec *stages,
bool freezePhys,
bool smartSeek,
bool reverseFBControlsOnRelease,
std::vector<plKey>* receivers)
{
fStages = stages;
fFreezePhys = freezePhys;
fSmartSeek = smartSeek;
fReverseFBControlsOnRelease = reverseFBControlsOnRelease;
if (receivers)
fReceivers = *receivers;
}
void plMultistageBehMod::IDeleteStageVec()
{
if (fStages)
{
int numStages = fStages->size();
for (int i = 0; i < numStages; i++)
{
plAnimStage* stage = (*fStages)[i];
delete stage;
}
delete fStages;
fStages = nil;
}
}
hsBool plMultistageBehMod::MsgReceive(plMessage* msg)
{
plMultistageModMsg *multiMsg = nil;
plNotifyMsg* notifyMsg = plNotifyMsg::ConvertNoRef(msg);
if (notifyMsg)
{
hsAssert(fStages, "Trying to trigger multistage, but no stages are present.");
if(fStages)
{
plKey avKey = notifyMsg->GetAvatarKey();
hsAssert(avKey, "Avatar key missing trying to trigger multistage.");
if(avKey)
{
plSceneObject *avObj = plSceneObject::ConvertNoRef(avKey->ObjectIsLoaded());
hsAssert(avObj, "Avatar not loaded when trying to trigger multistage.");
if(avObj)
{
// Create a copy of our reference anim stages to give to the brain
plAnimStageVec* stages = TRACKED_NEW plAnimStageVec;
int numStages = fStages->size();
stages->reserve(numStages);
// hack hack hack
hsBool ladder = false;
for (int i = 0; i < numStages; i++)
{
plAnimStage* stage = TRACKED_NEW plAnimStage;
*stage = *((*fStages)[i]);
stages->push_back(stage);
if (strstr(stage->GetAnimName(),"adder") != nil)
ladder = true;
}
const plArmatureMod *avMod = (plArmatureMod*)avObj->GetModifierByType(plArmatureMod::Index());
hsAssert(avMod, "Missing armature mod on avatar scene object.");
if(avMod)
{
plKey sender = notifyMsg->GetSender();
plKey avModKey = avMod->GetKey();
plKey seekKey = GetTarget()->GetKey(); // our seek point
#ifdef DEBUG_MULTISTAGE
char sbuf[256];
sprintf(sbuf,"plMultistageModMsg - starting multistage from %s",sender->GetName());
plAvatarMgr::GetInstance()->GetLog()->AddLine(sbuf);
#endif
plAvSeekMsg *seeker = TRACKED_NEW plAvSeekMsg(nil, avModKey, seekKey, 1.0f, fSmartSeek);
seeker->Send();
// these (currently unused) callbacks are for the brain itself, not any of the stages
plMessage *exitCallback = nil, *enterCallback = nil;
UInt32 exitFlags = plAvBrainGeneric::kExitNormal;
plAvBrainGeneric *brain = TRACKED_NEW plAvBrainGeneric(stages, exitCallback, enterCallback, sender, exitFlags,
plAvBrainGeneric::kDefaultFadeIn, plAvBrainGeneric::kDefaultFadeOut,
plAvBrainGeneric::kMoveRelative);
if (ladder)
{
brain->SetType(plAvBrainGeneric::kLadder);
}
brain->SetReverseFBControlsOnRelease(fReverseFBControlsOnRelease);
plAvPushBrainMsg* pushBrain = TRACKED_NEW plAvPushBrainMsg(GetKey(), avModKey, brain);
pushBrain->Send();
}
}
}
}
return true;
}
else if (multiMsg = plMultistageModMsg::ConvertNoRef(msg))
{
if (multiMsg->GetCommand(plMultistageModMsg::kSetLoopCount))
{
((*fStages)[multiMsg->fStageNum])->SetNumLoops(multiMsg->fNumLoops);
}
return true;
}
else {
return plSingleModifier::MsgReceive(msg);
}
}
void plMultistageBehMod::Read(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Read(stream, mgr);
fFreezePhys = stream->Readbool();
fSmartSeek = stream->Readbool();
fReverseFBControlsOnRelease = stream->Readbool();
IDeleteStageVec();
fStages = TRACKED_NEW plAnimStageVec;
int numStages = stream->ReadSwap32();
fStages->reserve(numStages);
int i;
for (i = 0; i < numStages; i++)
{
plAnimStage* stage = TRACKED_NEW plAnimStage;
stage->Read(stream, mgr);
stage->SetMod(this);
fStages->push_back(stage);
}
int numReceivers = stream->ReadSwap32();
fReceivers.clear();
fReceivers.reserve(numReceivers);
for (i = 0; i < numReceivers; i++)
{
plKey key = mgr->ReadKey(stream);
fReceivers.push_back(key);
}
}
void plMultistageBehMod::Write(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Write(stream, mgr);
stream->Writebool(fFreezePhys);
stream->Writebool(fSmartSeek);
stream->Writebool(fReverseFBControlsOnRelease);
int numStages = fStages->size();
stream->WriteSwap32(numStages);
int i;
for (i = 0; i < numStages; i++)
{
plAnimStage* stage = (*fStages)[i];
stage->Write(stream, mgr);
}
int numReceivers = fReceivers.size();
stream->WriteSwap32(numReceivers);
for (i = 0; i < numReceivers; i++)
{
plKey key = fReceivers[i];
mgr->WriteKey(stream, key);
}
}

View File

@ -1,72 +1,72 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plMultistageBehMod_h_inc
#define plMultistageBehMod_h_inc
#include "pnModifier/plSingleModifier.h"
#include "hsStlUtils.h"
class plAnimStageVec;
class plMultistageBehMod : public plSingleModifier
{
protected:
plAnimStageVec* fStages;
bool fFreezePhys;
bool fSmartSeek;
bool fReverseFBControlsOnRelease;
bool fNetProp;
bool fNetForce;
std::vector<plKey> fReceivers;
void IDeleteStageVec();
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
public:
plMultistageBehMod();
plMultistageBehMod(plAnimStageVec* stages, bool freezePhys, bool smartSeek, bool reverseFBControlsOnRelease, std::vector<plKey>* receivers);
virtual ~plMultistageBehMod();
CLASSNAME_REGISTER( plMultistageBehMod );
GETINTERFACE_ANY( plMultistageBehMod, plSingleModifier );
hsBool NetProp() { return fNetProp; }
hsBool NetForce() { return fNetForce; }
void SetNetProp(hsBool netProp) { fNetProp = netProp; }
void SetNetForce(hsBool netForce) { fNetForce = netForce; }
hsBool MsgReceive(plMessage* msg);
virtual void Init(plAnimStageVec *stages, bool freezePhys, bool smartSeek, bool reverseFBControlsOnRelease, std::vector<plKey>* receivers);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
};
#endif // plMultistageBehMod_h_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plMultistageBehMod_h_inc
#define plMultistageBehMod_h_inc
#include "pnModifier/plSingleModifier.h"
#include "hsStlUtils.h"
class plAnimStageVec;
class plMultistageBehMod : public plSingleModifier
{
protected:
plAnimStageVec* fStages;
bool fFreezePhys;
bool fSmartSeek;
bool fReverseFBControlsOnRelease;
bool fNetProp;
bool fNetForce;
std::vector<plKey> fReceivers;
void IDeleteStageVec();
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
public:
plMultistageBehMod();
plMultistageBehMod(plAnimStageVec* stages, bool freezePhys, bool smartSeek, bool reverseFBControlsOnRelease, std::vector<plKey>* receivers);
virtual ~plMultistageBehMod();
CLASSNAME_REGISTER( plMultistageBehMod );
GETINTERFACE_ANY( plMultistageBehMod, plSingleModifier );
hsBool NetProp() { return fNetProp; }
hsBool NetForce() { return fNetForce; }
void SetNetProp(hsBool netProp) { fNetProp = netProp; }
void SetNetForce(hsBool netForce) { fNetForce = netForce; }
hsBool MsgReceive(plMessage* msg);
virtual void Init(plAnimStageVec *stages, bool freezePhys, bool smartSeek, bool reverseFBControlsOnRelease, std::vector<plKey>* receivers);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
};
#endif // plMultistageBehMod_h_inc

View File

@ -1,184 +1,184 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plNPCSpawnMod.h"
// local
#include "plAvatarMgr.h"
// global
#include "hsMatrix44.h"
// other
#include "pnSceneObject/plSceneObject.h"
#include "pnSceneObject/plCoordinateInterface.h"
//#include "pnMessage/plWarpMsg.h"
#include "pnMessage/plNotifyMsg.h"
// plNPCSpawnMod ctor
plNPCSpawnMod::plNPCSpawnMod()
: fModelName(nil),
fAccountName(nil),
fAutoSpawn(false),
fNotify(nil)
{
}
// plNPCSpawnMod ctor modelName accountName
plNPCSpawnMod::plNPCSpawnMod(const char * modelName, const char * accountName, bool autoSpawn)
: fAutoSpawn(autoSpawn), fNotify(nil)
{
fModelName = hsStrcpy(modelName);
fAccountName = hsStrcpy(accountName);
}
// plNPCSpawnMod dtor
plNPCSpawnMod::~plNPCSpawnMod()
{
if(fModelName)
{
delete[] fModelName;
fModelName = nil;
}
if(fAccountName)
{
delete[] fAccountName;
fAccountName = nil;
}
if (fNotify)
fNotify->UnRef();
}
void plNPCSpawnMod::AddTarget(plSceneObject* so)
{
plSingleModifier::AddTarget(so);
if(fAutoSpawn)
Trigger();
}
void plNPCSpawnMod::RemoveTarget(plSceneObject *so)
{
plSingleModifier::RemoveTarget(so);
if(fSpawnedKey)
{
plAvatarMgr::GetInstance()->UnLoadAvatar(fSpawnedKey, false);
}
}
// TRIGGER
bool plNPCSpawnMod::Trigger()
{
bool result = false;
// you can ONLY spawn if you are local. the spawn message
// will netpropagate
if(this->IsLocallyOwned())
{
if(fModelName)
{
// spawn the NPC
plKey spawnPoint = GetTarget(0)->GetKey();
fSpawnedKey = plAvatarMgr::GetInstance()->LoadAvatar(fModelName, fAccountName, false, spawnPoint, nil);
ISendNotify(fSpawnedKey);
}
}
return result;
}
// SETNOTIFY
void plNPCSpawnMod::SetNotify(plNotifyMsg *notify)
{
fNotify = notify;
}
// GETNOTIFY
plNotifyMsg * plNPCSpawnMod::GetNotify()
{
return fNotify;
}
// READ
void plNPCSpawnMod::Read(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Read(stream, mgr);
fModelName = stream->ReadSafeString();
fAccountName = stream->ReadSafeString();
fAutoSpawn = stream->Readbool();
if(stream->Readbool())
fNotify = plNotifyMsg::ConvertNoRef(mgr->ReadCreatable(stream));
}
// WRITE
void plNPCSpawnMod::Write(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteSafeString(fModelName);
stream->WriteSafeString(fAccountName);
stream->Writebool(fAutoSpawn);
if(fNotify)
{
stream->Writebool(true);
mgr->WriteCreatable(stream, fNotify);
} else {
stream->Writebool(false);
}
}
// IEVAL
// attack of the bogons
hsBool plNPCSpawnMod::IEval(double secs, hsScalar del, UInt32 dirty)
{
return true;
}
// ISENDNOTIFY
void plNPCSpawnMod::ISendNotify(plKey &avatarKey)
{
if(fNotify)
{
proSpawnedEventData * event = TRACKED_NEW proSpawnedEventData;
event->fSpawner = GetKey();
event->fSpawnee = avatarKey;
fNotify->ClearEvents();
fNotify->AddEvent(event);
delete event; // fNotify->AddEvent makes a copy
int i = fNotify->GetEventCount();
fNotify->Ref(); // so we still hold onto it after it is delivered
fNotify->Send();
} else {
hsStatusMessage("NPC Spawner is spawning but there is no notify message to send.");
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plNPCSpawnMod.h"
// local
#include "plAvatarMgr.h"
// global
#include "hsMatrix44.h"
// other
#include "pnSceneObject/plSceneObject.h"
#include "pnSceneObject/plCoordinateInterface.h"
//#include "pnMessage/plWarpMsg.h"
#include "pnMessage/plNotifyMsg.h"
// plNPCSpawnMod ctor
plNPCSpawnMod::plNPCSpawnMod()
: fModelName(nil),
fAccountName(nil),
fAutoSpawn(false),
fNotify(nil)
{
}
// plNPCSpawnMod ctor modelName accountName
plNPCSpawnMod::plNPCSpawnMod(const char * modelName, const char * accountName, bool autoSpawn)
: fAutoSpawn(autoSpawn), fNotify(nil)
{
fModelName = hsStrcpy(modelName);
fAccountName = hsStrcpy(accountName);
}
// plNPCSpawnMod dtor
plNPCSpawnMod::~plNPCSpawnMod()
{
if(fModelName)
{
delete[] fModelName;
fModelName = nil;
}
if(fAccountName)
{
delete[] fAccountName;
fAccountName = nil;
}
if (fNotify)
fNotify->UnRef();
}
void plNPCSpawnMod::AddTarget(plSceneObject* so)
{
plSingleModifier::AddTarget(so);
if(fAutoSpawn)
Trigger();
}
void plNPCSpawnMod::RemoveTarget(plSceneObject *so)
{
plSingleModifier::RemoveTarget(so);
if(fSpawnedKey)
{
plAvatarMgr::GetInstance()->UnLoadAvatar(fSpawnedKey, false);
}
}
// TRIGGER
bool plNPCSpawnMod::Trigger()
{
bool result = false;
// you can ONLY spawn if you are local. the spawn message
// will netpropagate
if(this->IsLocallyOwned())
{
if(fModelName)
{
// spawn the NPC
plKey spawnPoint = GetTarget(0)->GetKey();
fSpawnedKey = plAvatarMgr::GetInstance()->LoadAvatar(fModelName, fAccountName, false, spawnPoint, nil);
ISendNotify(fSpawnedKey);
}
}
return result;
}
// SETNOTIFY
void plNPCSpawnMod::SetNotify(plNotifyMsg *notify)
{
fNotify = notify;
}
// GETNOTIFY
plNotifyMsg * plNPCSpawnMod::GetNotify()
{
return fNotify;
}
// READ
void plNPCSpawnMod::Read(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Read(stream, mgr);
fModelName = stream->ReadSafeString();
fAccountName = stream->ReadSafeString();
fAutoSpawn = stream->Readbool();
if(stream->Readbool())
fNotify = plNotifyMsg::ConvertNoRef(mgr->ReadCreatable(stream));
}
// WRITE
void plNPCSpawnMod::Write(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteSafeString(fModelName);
stream->WriteSafeString(fAccountName);
stream->Writebool(fAutoSpawn);
if(fNotify)
{
stream->Writebool(true);
mgr->WriteCreatable(stream, fNotify);
} else {
stream->Writebool(false);
}
}
// IEVAL
// attack of the bogons
hsBool plNPCSpawnMod::IEval(double secs, hsScalar del, UInt32 dirty)
{
return true;
}
// ISENDNOTIFY
void plNPCSpawnMod::ISendNotify(plKey &avatarKey)
{
if(fNotify)
{
proSpawnedEventData * event = TRACKED_NEW proSpawnedEventData;
event->fSpawner = GetKey();
event->fSpawnee = avatarKey;
fNotify->ClearEvents();
fNotify->AddEvent(event);
delete event; // fNotify->AddEvent makes a copy
int i = fNotify->GetEventCount();
fNotify->Ref(); // so we still hold onto it after it is delivered
fNotify->Send();
} else {
hsStatusMessage("NPC Spawner is spawning but there is no notify message to send.");
}
}

View File

@ -1,62 +1,62 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "pnModifier/plSingleModifier.h"
class plNotifyMsg;
class plNPCSpawnMod : public plSingleModifier
{
public:
plNPCSpawnMod();
plNPCSpawnMod(const char * modelName, const char *accountName, bool autoSpawn);
~plNPCSpawnMod();
bool Trigger();
void SetNotify(plNotifyMsg *notify);
plNotifyMsg * GetNotify();
CLASSNAME_REGISTER( plNPCSpawnMod );
GETINTERFACE_ANY( plNPCSpawnMod, plSingleModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject *so);
// hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
void ISendNotify(plKey &avatarKey); // send our notification message
private:
char *fModelName;
char *fAccountName;
bool fAutoSpawn; // spawn immediately on loading
plKey fSpawnedKey; // if we want to be able to spawn many things, we should make this a vector
plNotifyMsg *fNotify; // notify message that we send when we spawn.
};
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "pnModifier/plSingleModifier.h"
class plNotifyMsg;
class plNPCSpawnMod : public plSingleModifier
{
public:
plNPCSpawnMod();
plNPCSpawnMod(const char * modelName, const char *accountName, bool autoSpawn);
~plNPCSpawnMod();
bool Trigger();
void SetNotify(plNotifyMsg *notify);
plNotifyMsg * GetNotify();
CLASSNAME_REGISTER( plNPCSpawnMod );
GETINTERFACE_ANY( plNPCSpawnMod, plSingleModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject *so);
// hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
void ISendNotify(plKey &avatarKey); // send our notification message
private:
char *fModelName;
char *fAccountName;
bool fAutoSpawn; // spawn immediately on loading
plKey fSpawnedKey; // if we want to be able to spawn many things, we should make this a vector
plNotifyMsg *fNotify; // notify message that we send when we spawn.
};

View File

@ -1,171 +1,171 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plOneShotMod.h"
// local
#include "plArmatureMod.h"
#include "plAvatarMgr.h"
// global
#include "plgDispatch.h"
// other
#include "plMessage/plAvatarMsg.h"
// CTOR()
plOneShotMod::plOneShotMod()
: fDrivable(false),
fReversable(false),
fSeekDuration(1.0f),
fSmartSeek(false),
fAnimName(nil),
fNoSeek(false)
{
// this constructor is called from the loader.
}
// CTOR(char *)
plOneShotMod::plOneShotMod(const char *animName,
hsBool drivable,
hsBool reversable,
float seekDuration,
hsBool smartSeek,
hsBool noSeek)
: fDrivable(drivable),
fReversable(reversable),
fSeekDuration(seekDuration),
fSmartSeek((float)smartSeek),
fNoSeek(noSeek)
{
fAnimName = hsStrcpy(animName);
}
// INIT
void plOneShotMod::Init(const char *animName,
hsBool drivable,
hsBool reversable,
float seekDuration,
hsBool smartSeek,
hsBool noSeek)
{
fAnimName = hsStrcpy(animName);
fDrivable = drivable;
fReversable = reversable;
fSeekDuration = seekDuration;
fSmartSeek = (float)smartSeek;
fNoSeek = noSeek;
}
// DTOR()
plOneShotMod::~plOneShotMod()
{
if(fAnimName) {
delete[] fAnimName;
fAnimName = nil;
}
}
#include "../plMessage/plOneShotMsg.h"
#include "../plMessage/plOneShotCallbacks.h"
// MSGRECEIVE
hsBool plOneShotMod::MsgReceive(plMessage* msg)
{
plOneShotMsg *oneShotMsg = plOneShotMsg::ConvertNoRef(msg);
if (oneShotMsg)
{
// Send a one shot task request to the given target, which darn well better have an avatar modifier on it.
plKey myKey = GetKey();
plKey objKey = GetTarget(0)->GetKey();
plKey avKey = oneShotMsg->fPlayerKey;
hsAssert(avKey,"The avatar key is missing in the one shot!");
if ( avKey )
{
plSceneObject *avObj = (plSceneObject *)avKey->ObjectIsLoaded();
if(avObj)
{
const plArmatureMod *avMod = (plArmatureMod*)avObj->GetModifierByType(plArmatureMod::Index());
if(avMod)
{
char *animName = avMod->MakeAnimationName(fAnimName);
plAvOneShotMsg *avOSmsg = TRACKED_NEW plAvOneShotMsg(myKey, oneShotMsg->fPlayerKey, objKey,
fSeekDuration, (hsBool)fSmartSeek, animName, fDrivable,
fReversable);
delete [] animName; // AvOneShotMsg constructor copies.
avOSmsg->fNoSeek = fNoSeek;
avOSmsg->SetBCastFlag(plMessage::kPropagateToModifiers);
hsRefCnt_SafeRef(oneShotMsg->fCallbacks);
avOSmsg->fCallbacks = oneShotMsg->fCallbacks;
plgDispatch::MsgSend(avOSmsg);
}
}
}
return true;
}
return plMultiModifier::MsgReceive(msg);
}
// ADDTARGET
// Here I am. Announce presence to the avatar registry.
void plOneShotMod::AddTarget(plSceneObject* so)
{
plMultiModifier::AddTarget(so);
plAvatarMgr::GetInstance()->AddOneShot(this);
}
void plOneShotMod::Read(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Read(stream, mgr);
// read in the name of the animation itself
fAnimName = stream->ReadSafeString();
fSeekDuration = stream->ReadSwapScalar();
fDrivable = stream->ReadBool();
fReversable = stream->ReadBool();
fSmartSeek = (float)stream->ReadBool();
fNoSeek = stream->ReadBool();
}
void plOneShotMod::Write(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Write(stream, mgr);
stream->WriteSafeString(fAnimName);
stream->WriteSwapScalar(fSeekDuration);
stream->WriteBool(fDrivable);
stream->WriteBool(fReversable);
stream->WriteBool((hsBool)fSmartSeek);
stream->WriteBool(fNoSeek);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plOneShotMod.h"
// local
#include "plArmatureMod.h"
#include "plAvatarMgr.h"
// global
#include "plgDispatch.h"
// other
#include "plMessage/plAvatarMsg.h"
// CTOR()
plOneShotMod::plOneShotMod()
: fDrivable(false),
fReversable(false),
fSeekDuration(1.0f),
fSmartSeek(false),
fAnimName(nil),
fNoSeek(false)
{
// this constructor is called from the loader.
}
// CTOR(char *)
plOneShotMod::plOneShotMod(const char *animName,
hsBool drivable,
hsBool reversable,
float seekDuration,
hsBool smartSeek,
hsBool noSeek)
: fDrivable(drivable),
fReversable(reversable),
fSeekDuration(seekDuration),
fSmartSeek((float)smartSeek),
fNoSeek(noSeek)
{
fAnimName = hsStrcpy(animName);
}
// INIT
void plOneShotMod::Init(const char *animName,
hsBool drivable,
hsBool reversable,
float seekDuration,
hsBool smartSeek,
hsBool noSeek)
{
fAnimName = hsStrcpy(animName);
fDrivable = drivable;
fReversable = reversable;
fSeekDuration = seekDuration;
fSmartSeek = (float)smartSeek;
fNoSeek = noSeek;
}
// DTOR()
plOneShotMod::~plOneShotMod()
{
if(fAnimName) {
delete[] fAnimName;
fAnimName = nil;
}
}
#include "../plMessage/plOneShotMsg.h"
#include "../plMessage/plOneShotCallbacks.h"
// MSGRECEIVE
hsBool plOneShotMod::MsgReceive(plMessage* msg)
{
plOneShotMsg *oneShotMsg = plOneShotMsg::ConvertNoRef(msg);
if (oneShotMsg)
{
// Send a one shot task request to the given target, which darn well better have an avatar modifier on it.
plKey myKey = GetKey();
plKey objKey = GetTarget(0)->GetKey();
plKey avKey = oneShotMsg->fPlayerKey;
hsAssert(avKey,"The avatar key is missing in the one shot!");
if ( avKey )
{
plSceneObject *avObj = (plSceneObject *)avKey->ObjectIsLoaded();
if(avObj)
{
const plArmatureMod *avMod = (plArmatureMod*)avObj->GetModifierByType(plArmatureMod::Index());
if(avMod)
{
char *animName = avMod->MakeAnimationName(fAnimName);
plAvOneShotMsg *avOSmsg = TRACKED_NEW plAvOneShotMsg(myKey, oneShotMsg->fPlayerKey, objKey,
fSeekDuration, (hsBool)fSmartSeek, animName, fDrivable,
fReversable);
delete [] animName; // AvOneShotMsg constructor copies.
avOSmsg->fNoSeek = fNoSeek;
avOSmsg->SetBCastFlag(plMessage::kPropagateToModifiers);
hsRefCnt_SafeRef(oneShotMsg->fCallbacks);
avOSmsg->fCallbacks = oneShotMsg->fCallbacks;
plgDispatch::MsgSend(avOSmsg);
}
}
}
return true;
}
return plMultiModifier::MsgReceive(msg);
}
// ADDTARGET
// Here I am. Announce presence to the avatar registry.
void plOneShotMod::AddTarget(plSceneObject* so)
{
plMultiModifier::AddTarget(so);
plAvatarMgr::GetInstance()->AddOneShot(this);
}
void plOneShotMod::Read(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Read(stream, mgr);
// read in the name of the animation itself
fAnimName = stream->ReadSafeString();
fSeekDuration = stream->ReadSwapScalar();
fDrivable = stream->ReadBool();
fReversable = stream->ReadBool();
fSmartSeek = (float)stream->ReadBool();
fNoSeek = stream->ReadBool();
}
void plOneShotMod::Write(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Write(stream, mgr);
stream->WriteSafeString(fAnimName);
stream->WriteSwapScalar(fSeekDuration);
stream->WriteBool(fDrivable);
stream->WriteBool(fReversable);
stream->WriteBool((hsBool)fSmartSeek);
stream->WriteBool(fNoSeek);
}

View File

@ -1,66 +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/>.
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 plOneShotMod_INC
#define plOneShotMod_INC
#include "pnModifier/plMultiModifier.h"
#include "pnMessage/plMessage.h"
// PLONESHOTMOD
// A one shot
// - suspends user input
// - moves the avatar to a specific position
// - plays a specific animation
// - returns control to the user from the final position of the animation
// This modifier holds the information that the avatar needs to do that.
class plOneShotMod : public plMultiModifier
{
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) {return true;}
char * fAnimName; // the name of the animation associated with this one-shot
hsBool fDrivable; // whether the user can control the position of the animation
hsBool fReversable; // whether the user can back up the animation (fDrivable must be true as well)
float fSeekDuration; // how long to take to get to the seek point (??? should this be speed instead?)
float fSmartSeek; // use smart seek to walk to the seek point?
hsBool fNoSeek;
public:
plOneShotMod();
plOneShotMod(const char *animName, hsBool drivable, hsBool reversable, float seekDuration, hsBool smartSeek,hsBool noSeek = false);
virtual ~plOneShotMod();
void Init(const char *animName, hsBool drivable, hsBool reversable, float seekDuration, hsBool smartSeek, hsBool noSeek = false);
CLASSNAME_REGISTER( plOneShotMod );
GETINTERFACE_ANY( plOneShotMod, plMultiModifier );
virtual void AddTarget(plSceneObject* so);
hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plOneShotMod_INC
#define plOneShotMod_INC
#include "pnModifier/plMultiModifier.h"
#include "pnMessage/plMessage.h"
// PLONESHOTMOD
// A one shot
// - suspends user input
// - moves the avatar to a specific position
// - plays a specific animation
// - returns control to the user from the final position of the animation
// This modifier holds the information that the avatar needs to do that.
class plOneShotMod : public plMultiModifier
{
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) {return true;}
char * fAnimName; // the name of the animation associated with this one-shot
hsBool fDrivable; // whether the user can control the position of the animation
hsBool fReversable; // whether the user can back up the animation (fDrivable must be true as well)
float fSeekDuration; // how long to take to get to the seek point (??? should this be speed instead?)
float fSmartSeek; // use smart seek to walk to the seek point?
hsBool fNoSeek;
public:
plOneShotMod();
plOneShotMod(const char *animName, hsBool drivable, hsBool reversable, float seekDuration, hsBool smartSeek,hsBool noSeek = false);
virtual ~plOneShotMod();
void Init(const char *animName, hsBool drivable, hsBool reversable, float seekDuration, hsBool smartSeek, hsBool noSeek = false);
CLASSNAME_REGISTER( plOneShotMod );
GETINTERFACE_ANY( plOneShotMod, plMultiModifier );
virtual void AddTarget(plSceneObject* so);
hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,333 +1,333 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLPHYSICALCONTROLLERCORE_H
#define PLPHYSICALCONTROLLERCORE_H
#include "hsGeometry3.h"
#include "hsMatrix44.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)))
class plCoordinateInterface;
class plPhysical;
class plPXPhysical;
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.
enum plControllerCollisionFlags
{
kSides=1,
kTop= (1<<1),
kBottom=(1<<2),
};
class plMovementStrategySimulationInterface
{
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;
};
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.
virtual void Enable(bool enable) = 0;
virtual bool IsEnabled() {return fEnabled;}
virtual plKey GetSubworld() {return fWorldKey;}
virtual void SetSubworld(plKey world) = 0;
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){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;
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();
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;
protected:
plKey fOwner;
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
hsVector3 fLinearVelocity;
hsScalar fAngularVelocity;
hsVector3 fAchievedLinearVelocity;
plPhysical* fPushingPhysical;
bool fFacingPushingPhysical;
bool fNeedsResize;
};
class plMovementStrategy: public plMovementStrategySimulationInterface
{
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; }
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;
};
class plWalkingStrategy: 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(){};
virtual void Apply(hsScalar delSecs);
virtual void Update(hsScalar delSecs);
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(){};
protected:
void ICheckForFalseGround();
bool fGroundHit;
bool fFalseGround;
bool fHitHead;
bool fOnTopOfAnimatedPhysLastFrame;
hsTArray<hsVector3> fPrevSlidingNormals;
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
};
class plSwimStrategy: public plMovementStrategy
{
public:
plSwimStrategy(plPhysicalControllerCore *core);
virtual ~plSwimStrategy(){};
void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight);
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);
protected:
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
private:
void IAdjustBuoyancy();
hsScalar fBuoyancy;
hsBool fOnGround;
hsBool fHadContacts;
hsScalar fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
};
class plRidingAnimatedPhysicalStrategy : public plWalkingStrategy
{
public:
plRidingAnimatedPhysicalStrategy(plPhysicalControllerCore *core ) :
fNeedVelocityOverride(false),fStartJump(false),plWalkingStrategy(core){};
virtual ~plRidingAnimatedPhysicalStrategy(){};
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;}
protected:
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return false;}
bool ICheckMove(const hsPoint3& startPos, const hsPoint3& desiredPos);
hsBool fNeedVelocityOverride;
hsVector3 fOverrideVelocity;
bool fStartJump;
};
#endif// PLPHYSICALCONTROLLERCORE_H
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLPHYSICALCONTROLLERCORE_H
#define PLPHYSICALCONTROLLERCORE_H
#include "hsGeometry3.h"
#include "hsMatrix44.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)))
class plCoordinateInterface;
class plPhysical;
class plPXPhysical;
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.
enum plControllerCollisionFlags
{
kSides=1,
kTop= (1<<1),
kBottom=(1<<2),
};
class plMovementStrategySimulationInterface
{
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;
};
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.
virtual void Enable(bool enable) = 0;
virtual bool IsEnabled() {return fEnabled;}
virtual plKey GetSubworld() {return fWorldKey;}
virtual void SetSubworld(plKey world) = 0;
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){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;
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();
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;
protected:
plKey fOwner;
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
hsVector3 fLinearVelocity;
hsScalar fAngularVelocity;
hsVector3 fAchievedLinearVelocity;
plPhysical* fPushingPhysical;
bool fFacingPushingPhysical;
bool fNeedsResize;
};
class plMovementStrategy: public plMovementStrategySimulationInterface
{
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; }
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;
};
class plWalkingStrategy: 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(){};
virtual void Apply(hsScalar delSecs);
virtual void Update(hsScalar delSecs);
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(){};
protected:
void ICheckForFalseGround();
bool fGroundHit;
bool fFalseGround;
bool fHitHead;
bool fOnTopOfAnimatedPhysLastFrame;
hsTArray<hsVector3> fPrevSlidingNormals;
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
};
class plSwimStrategy: public plMovementStrategy
{
public:
plSwimStrategy(plPhysicalControllerCore *core);
virtual ~plSwimStrategy(){};
void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight);
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);
protected:
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
private:
void IAdjustBuoyancy();
hsScalar fBuoyancy;
hsBool fOnGround;
hsBool fHadContacts;
hsScalar fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
};
class plRidingAnimatedPhysicalStrategy : public plWalkingStrategy
{
public:
plRidingAnimatedPhysicalStrategy(plPhysicalControllerCore *core ) :
fNeedVelocityOverride(false),fStartJump(false),plWalkingStrategy(core){};
virtual ~plRidingAnimatedPhysicalStrategy(){};
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;}
protected:
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return false;}
bool ICheckMove(const hsPoint3& startPos, const hsPoint3& desiredPos);
hsBool fNeedVelocityOverride;
hsVector3 fOverrideVelocity;
bool fStartJump;
};
#endif// PLPHYSICALCONTROLLERCORE_H

View File

@ -1,485 +1,485 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plPointChannel.h"
#include "plScalarChannel.h"
#include "hsResMgr.h"
#include "pnSceneObject/plDrawInterface.h"
#include "pnSceneObject/plSimulationInterface.h"
#include "pnSceneObject/plCoordinateInterface.h"
#include "pnSceneObject/plAudioInterface.h"
#include "plInterp/plController.h"
#include "plInterp/plAnimTimeConvert.h"
#include "plGLight/plLightInfo.h"
//////////////
// PLPOINTSRCE
//////////////
// CTOR
plPointChannel::plPointChannel()
: plAGChannel(), fResult(0, 0, 0)
{
}
// DTOR
plPointChannel::~plPointChannel()
{
}
// VALUE
// default behaviour is just to return our result (constant value)
const hsPoint3 & plPointChannel::Value(double time)
{
return fResult;
}
// VALUE(point, time)
void plPointChannel::Value(hsPoint3 &point, double time)
{
point = Value(time);
}
// MAKECOMBINE
plAGChannel * plPointChannel::MakeCombine(plAGChannel *channelA)
{
return nil;
}
// MAKEBLEND
plAGChannel * plPointChannel::MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority)
{
return TRACKED_NEW plPointBlend(this, (plPointChannel *)channelB, channelBias);
}
// MAKEZEROSTATE
plAGChannel * plPointChannel::MakeZeroState()
{
return TRACKED_NEW plPointConstant(Value(0));
}
// MAKETIMESCALE
plAGChannel * plPointChannel::MakeTimeScale(plScalarChannel *timeSource)
{
return TRACKED_NEW plPointTimeScale(this, timeSource);
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// plPointConstant
//
/////////////////////////////////////////////////////////////////////////////////////////
// ctor --------------------------
// -----
plPointConstant::plPointConstant()
: plPointChannel()
{
}
// ctor -----------------------------------------------
// -----
plPointConstant::plPointConstant(const hsPoint3 &point)
{
fResult = point;
}
// dtor ---------------------------
// -----
plPointConstant::~plPointConstant()
{
}
void plPointConstant::Read(hsStream *stream, hsResMgr *mgr)
{
plPointChannel::Read(stream, mgr);
fResult.Read(stream);
}
void plPointConstant::Write(hsStream *stream, hsResMgr *mgr)
{
plPointChannel::Write(stream, mgr);
fResult.Write(stream);
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// PLPOINTTIMESCALE
//
// Insert into the graph when you need to change the speed or direction of time
// Also serves as a handy instancing node, since it just passes its data through.
//
/////////////////////////////////////////////////////////////////////////////////////////
// ctor ----------------------------
// -----
plPointTimeScale::plPointTimeScale()
: fTimeSource(nil), fChannelIn(nil)
{
}
// ctor --------------------------------------------------------------------------------
// -----
plPointTimeScale::plPointTimeScale(plPointChannel *channel, plScalarChannel *timeSource)
: fChannelIn(channel),
fTimeSource(timeSource)
{
}
// dtor -----------------------------
// -----
plPointTimeScale::~plPointTimeScale()
{
}
// IsStoppedAt ---------------------------
// ------------
hsBool plPointTimeScale::IsStoppedAt(double time)
{
return fTimeSource->IsStoppedAt(time);
}
// Value --------------------------------------------
// ------
const hsPoint3 & plPointTimeScale::Value(double time)
{
fResult = fChannelIn->Value(fTimeSource->Value(time));
return fResult;
}
// Detach ---------------------------------------------------
// -------
plAGChannel * plPointTimeScale::Detach(plAGChannel * channel)
{
plAGChannel *result = this;
fChannelIn = plPointChannel::ConvertNoRef(fChannelIn->Detach(channel));
if(!fChannelIn || channel == this)
result = nil;
if(result != this)
delete this;
return result;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// plPointBlend
//
/////////////////////////////////////////////////////////////////////////////////////////
// ctor --------------------
// -----
plPointBlend::plPointBlend()
: fPointA(nil),
fPointB(nil)
{
}
// ctor ---------------------------------------------------------------------------------
// -----
plPointBlend::plPointBlend(plPointChannel *channelA, plPointChannel *channelB,
plScalarChannel *channelBias)
: fPointA(channelA),
fPointB(channelB),
fChannelBias(channelBias)
{
}
// dtor ---------------------
// -----
plPointBlend::~plPointBlend()
{
fPointA = nil;
fPointB = nil;
fChannelBias = nil;
}
// IsStoppedAt ------------------------------
// ------------
hsBool plPointBlend::IsStoppedAt(double time)
{
hsScalar blend = fChannelBias->Value(time);
if (blend == 0)
return fPointA->IsStoppedAt(time);
if (blend == 1)
return fPointB->IsStoppedAt(time);
return (fPointA->IsStoppedAt(time) && fPointB->IsStoppedAt(time));
}
// Value ---------------------------------------
// ------
const hsPoint3 &plPointBlend::Value(double time)
{
if (fPointA && fPointB)
{
hsScalar curBlend = fChannelBias->Value(time);
if(curBlend == 0) {
fPointA->Value(fResult, time);
} else {
if(curBlend == 1) {
fPointB->Value(fResult, time);
} else {
const hsPoint3 &pointA = fPointA->Value(time);
const hsPoint3 &pointB = fPointB->Value(time);
hsPoint3 difference = pointB - pointA;
difference *= curBlend;
fResult = pointA + difference;
}
}
} else {
if (fPointA)
{
fResult = fPointA->Value(time);
} else {
if (fPointB)
{
fResult = fPointA->Value(time);
}
}
}
return fResult;
}
// Detach ------------------------------------------------------
// -------
plAGChannel * plPointBlend::Detach(plAGChannel *remove)
{
plAGChannel *result = this;
if (remove == this)
{
result = nil;
} else {
// it's possible that the incoming channel could reside down *all* of our
// branches (it's a graph, not a tree,) so we always pass down all limbs
fChannelBias = plScalarChannel::ConvertNoRef(fChannelBias->Detach(remove));
fPointA = plPointChannel::ConvertNoRef(fPointA->Detach(remove));
fPointB = plPointChannel::ConvertNoRef(fPointB->Detach(remove));
if (!fChannelBias)
{
// No more bias channel, assume it's zero from now on, (a.k.a. We just want channelA)
result = fPointA;
}
else
{
if(!fChannelBias)
result = fPointA;
else if(fPointA && !fPointB)
result = fPointA;
else if(fPointB && !fPointA)
result = fPointB;
else if(!fPointA && !fPointB)
result = nil;
if(result != this)
{
delete this;
}
}
}
return result;
}
///////////////////////////
// PLPOINTCONTROLLERCHANNEL
///////////////////////////
// CTOR
plPointControllerChannel::plPointControllerChannel()
: fController(nil)
{
}
// CTOR(name, controller)
plPointControllerChannel::plPointControllerChannel(plController *controller)
: fController(controller)
{
}
// ~DTOR()
plPointControllerChannel::~plPointControllerChannel()
{
if(fController) {
delete fController;
fController = nil;
}
}
// VALUE(time)
const hsPoint3 & plPointControllerChannel::Value(double time)
{
return Value(time, nil);
}
// VALUE(time)
const hsPoint3 & plPointControllerChannel::Value(double time, plControllerCacheInfo *cache)
{
fController->Interp((hsScalar)time, &fResult, cache);
return fResult;
}
plAGChannel *plPointControllerChannel::MakeCacheChannel(plAnimTimeConvert *atc)
{
plControllerCacheInfo *cache = fController->CreateCache();
cache->SetATC(atc);
return TRACKED_NEW plPointControllerCacheChannel(this, cache);
}
// WRITE(stream, mgr)
void plPointControllerChannel::Write(hsStream *stream, hsResMgr *mgr)
{
plPointChannel::Write(stream, mgr);
hsAssert(fController, "Trying to write plPointControllerChannel with nil controller. File will not be importable.");
mgr->WriteCreatable(stream, fController);
}
// READ(stream, mgr)
void plPointControllerChannel::Read(hsStream *stream, hsResMgr *mgr)
{
plPointChannel::Read(stream, mgr);
fController = plController::ConvertNoRef(mgr->ReadCreatable(stream));
}
/////////////////////////////////
// PLPOINTCONTROLLERCACHECHANNEL
/////////////////////////////////
// CTOR
plPointControllerCacheChannel::plPointControllerCacheChannel()
: fControllerChannel(nil),
fCache(nil)
{
}
// CTOR(name, controller)
plPointControllerCacheChannel::plPointControllerCacheChannel(plPointControllerChannel *controller, plControllerCacheInfo *cache)
: fControllerChannel(controller),
fCache(cache)
{
}
// ~DTOR()
plPointControllerCacheChannel::~plPointControllerCacheChannel()
{
delete fCache;
fControllerChannel = nil;
}
// VALUE(time)
const hsPoint3 & plPointControllerCacheChannel::Value(double time, bool peek)
{
return fControllerChannel->Value(time, fCache);
}
// DETACH
plAGChannel * plPointControllerCacheChannel::Detach(plAGChannel * channel)
{
if(channel == this)
{
return nil;
} else {
plAGChannel *result = fControllerChannel->Detach(channel);
if(result == fControllerChannel)
{
return this;
} else {
// if our controller channel has been detached, then detach ourselves as well.
return result;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// Channel applicators
void plPointChannelApplicator::IApply(const plAGModifier *modifier, double time)
{
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel);
hsAssert(pointChan, "Invalid channel given to plPointChannelApplicator");
plCoordinateInterface *CI = IGetCI(modifier);
hsMatrix44 l2p = CI->GetLocalToParent();
const hsPoint3 &point = pointChan->Value(time);
l2p.SetTranslate(&point);
hsMatrix44 p2l;
l2p.GetInverse(&p2l);
CI->SetLocalToParent(l2p, p2l);
}
void plLightDiffuseApplicator::IApply(const plAGModifier *modifier, double time)
{
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel);
hsAssert(pointChan, "Invalid channel given to plLightDiffuseApplicator");
plLightInfo *li = plLightInfo::ConvertNoRef(IGetGI(modifier, plLightInfo::Index()));
const hsPoint3 &point = pointChan->Value(time);
hsColorRGBA color;
color.Set(point.fX, point.fY, point.fZ, 1.0f);
li->SetDiffuse(color);
}
void plLightAmbientApplicator::IApply(const plAGModifier *modifier, double time)
{
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel);
hsAssert(pointChan, "Invalid channel given to plLightAmbientApplicator");
plLightInfo *li = plLightInfo::ConvertNoRef(IGetGI(modifier, plLightInfo::Index()));
const hsPoint3 &point = pointChan->Value(time);
hsColorRGBA color;
color.Set(point.fX, point.fY, point.fZ, 1.0f);
li->SetAmbient(color);
}
void plLightSpecularApplicator::IApply(const plAGModifier *modifier, double time)
{
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel);
hsAssert(pointChan, "Invalid channel given to plLightSpecularApplicator");
plLightInfo *li = plLightInfo::ConvertNoRef(IGetGI(modifier, plLightInfo::Index()));
const hsPoint3 &point = pointChan->Value(time);
hsColorRGBA color;
color.Set(point.fX, point.fY, point.fZ, 1.0f);
li->SetSpecular(color);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plPointChannel.h"
#include "plScalarChannel.h"
#include "hsResMgr.h"
#include "pnSceneObject/plDrawInterface.h"
#include "pnSceneObject/plSimulationInterface.h"
#include "pnSceneObject/plCoordinateInterface.h"
#include "pnSceneObject/plAudioInterface.h"
#include "plInterp/plController.h"
#include "plInterp/plAnimTimeConvert.h"
#include "plGLight/plLightInfo.h"
//////////////
// PLPOINTSRCE
//////////////
// CTOR
plPointChannel::plPointChannel()
: plAGChannel(), fResult(0, 0, 0)
{
}
// DTOR
plPointChannel::~plPointChannel()
{
}
// VALUE
// default behaviour is just to return our result (constant value)
const hsPoint3 & plPointChannel::Value(double time)
{
return fResult;
}
// VALUE(point, time)
void plPointChannel::Value(hsPoint3 &point, double time)
{
point = Value(time);
}
// MAKECOMBINE
plAGChannel * plPointChannel::MakeCombine(plAGChannel *channelA)
{
return nil;
}
// MAKEBLEND
plAGChannel * plPointChannel::MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority)
{
return TRACKED_NEW plPointBlend(this, (plPointChannel *)channelB, channelBias);
}
// MAKEZEROSTATE
plAGChannel * plPointChannel::MakeZeroState()
{
return TRACKED_NEW plPointConstant(Value(0));
}
// MAKETIMESCALE
plAGChannel * plPointChannel::MakeTimeScale(plScalarChannel *timeSource)
{
return TRACKED_NEW plPointTimeScale(this, timeSource);
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// plPointConstant
//
/////////////////////////////////////////////////////////////////////////////////////////
// ctor --------------------------
// -----
plPointConstant::plPointConstant()
: plPointChannel()
{
}
// ctor -----------------------------------------------
// -----
plPointConstant::plPointConstant(const hsPoint3 &point)
{
fResult = point;
}
// dtor ---------------------------
// -----
plPointConstant::~plPointConstant()
{
}
void plPointConstant::Read(hsStream *stream, hsResMgr *mgr)
{
plPointChannel::Read(stream, mgr);
fResult.Read(stream);
}
void plPointConstant::Write(hsStream *stream, hsResMgr *mgr)
{
plPointChannel::Write(stream, mgr);
fResult.Write(stream);
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// PLPOINTTIMESCALE
//
// Insert into the graph when you need to change the speed or direction of time
// Also serves as a handy instancing node, since it just passes its data through.
//
/////////////////////////////////////////////////////////////////////////////////////////
// ctor ----------------------------
// -----
plPointTimeScale::plPointTimeScale()
: fTimeSource(nil), fChannelIn(nil)
{
}
// ctor --------------------------------------------------------------------------------
// -----
plPointTimeScale::plPointTimeScale(plPointChannel *channel, plScalarChannel *timeSource)
: fChannelIn(channel),
fTimeSource(timeSource)
{
}
// dtor -----------------------------
// -----
plPointTimeScale::~plPointTimeScale()
{
}
// IsStoppedAt ---------------------------
// ------------
hsBool plPointTimeScale::IsStoppedAt(double time)
{
return fTimeSource->IsStoppedAt(time);
}
// Value --------------------------------------------
// ------
const hsPoint3 & plPointTimeScale::Value(double time)
{
fResult = fChannelIn->Value(fTimeSource->Value(time));
return fResult;
}
// Detach ---------------------------------------------------
// -------
plAGChannel * plPointTimeScale::Detach(plAGChannel * channel)
{
plAGChannel *result = this;
fChannelIn = plPointChannel::ConvertNoRef(fChannelIn->Detach(channel));
if(!fChannelIn || channel == this)
result = nil;
if(result != this)
delete this;
return result;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// plPointBlend
//
/////////////////////////////////////////////////////////////////////////////////////////
// ctor --------------------
// -----
plPointBlend::plPointBlend()
: fPointA(nil),
fPointB(nil)
{
}
// ctor ---------------------------------------------------------------------------------
// -----
plPointBlend::plPointBlend(plPointChannel *channelA, plPointChannel *channelB,
plScalarChannel *channelBias)
: fPointA(channelA),
fPointB(channelB),
fChannelBias(channelBias)
{
}
// dtor ---------------------
// -----
plPointBlend::~plPointBlend()
{
fPointA = nil;
fPointB = nil;
fChannelBias = nil;
}
// IsStoppedAt ------------------------------
// ------------
hsBool plPointBlend::IsStoppedAt(double time)
{
hsScalar blend = fChannelBias->Value(time);
if (blend == 0)
return fPointA->IsStoppedAt(time);
if (blend == 1)
return fPointB->IsStoppedAt(time);
return (fPointA->IsStoppedAt(time) && fPointB->IsStoppedAt(time));
}
// Value ---------------------------------------
// ------
const hsPoint3 &plPointBlend::Value(double time)
{
if (fPointA && fPointB)
{
hsScalar curBlend = fChannelBias->Value(time);
if(curBlend == 0) {
fPointA->Value(fResult, time);
} else {
if(curBlend == 1) {
fPointB->Value(fResult, time);
} else {
const hsPoint3 &pointA = fPointA->Value(time);
const hsPoint3 &pointB = fPointB->Value(time);
hsPoint3 difference = pointB - pointA;
difference *= curBlend;
fResult = pointA + difference;
}
}
} else {
if (fPointA)
{
fResult = fPointA->Value(time);
} else {
if (fPointB)
{
fResult = fPointA->Value(time);
}
}
}
return fResult;
}
// Detach ------------------------------------------------------
// -------
plAGChannel * plPointBlend::Detach(plAGChannel *remove)
{
plAGChannel *result = this;
if (remove == this)
{
result = nil;
} else {
// it's possible that the incoming channel could reside down *all* of our
// branches (it's a graph, not a tree,) so we always pass down all limbs
fChannelBias = plScalarChannel::ConvertNoRef(fChannelBias->Detach(remove));
fPointA = plPointChannel::ConvertNoRef(fPointA->Detach(remove));
fPointB = plPointChannel::ConvertNoRef(fPointB->Detach(remove));
if (!fChannelBias)
{
// No more bias channel, assume it's zero from now on, (a.k.a. We just want channelA)
result = fPointA;
}
else
{
if(!fChannelBias)
result = fPointA;
else if(fPointA && !fPointB)
result = fPointA;
else if(fPointB && !fPointA)
result = fPointB;
else if(!fPointA && !fPointB)
result = nil;
if(result != this)
{
delete this;
}
}
}
return result;
}
///////////////////////////
// PLPOINTCONTROLLERCHANNEL
///////////////////////////
// CTOR
plPointControllerChannel::plPointControllerChannel()
: fController(nil)
{
}
// CTOR(name, controller)
plPointControllerChannel::plPointControllerChannel(plController *controller)
: fController(controller)
{
}
// ~DTOR()
plPointControllerChannel::~plPointControllerChannel()
{
if(fController) {
delete fController;
fController = nil;
}
}
// VALUE(time)
const hsPoint3 & plPointControllerChannel::Value(double time)
{
return Value(time, nil);
}
// VALUE(time)
const hsPoint3 & plPointControllerChannel::Value(double time, plControllerCacheInfo *cache)
{
fController->Interp((hsScalar)time, &fResult, cache);
return fResult;
}
plAGChannel *plPointControllerChannel::MakeCacheChannel(plAnimTimeConvert *atc)
{
plControllerCacheInfo *cache = fController->CreateCache();
cache->SetATC(atc);
return TRACKED_NEW plPointControllerCacheChannel(this, cache);
}
// WRITE(stream, mgr)
void plPointControllerChannel::Write(hsStream *stream, hsResMgr *mgr)
{
plPointChannel::Write(stream, mgr);
hsAssert(fController, "Trying to write plPointControllerChannel with nil controller. File will not be importable.");
mgr->WriteCreatable(stream, fController);
}
// READ(stream, mgr)
void plPointControllerChannel::Read(hsStream *stream, hsResMgr *mgr)
{
plPointChannel::Read(stream, mgr);
fController = plController::ConvertNoRef(mgr->ReadCreatable(stream));
}
/////////////////////////////////
// PLPOINTCONTROLLERCACHECHANNEL
/////////////////////////////////
// CTOR
plPointControllerCacheChannel::plPointControllerCacheChannel()
: fControllerChannel(nil),
fCache(nil)
{
}
// CTOR(name, controller)
plPointControllerCacheChannel::plPointControllerCacheChannel(plPointControllerChannel *controller, plControllerCacheInfo *cache)
: fControllerChannel(controller),
fCache(cache)
{
}
// ~DTOR()
plPointControllerCacheChannel::~plPointControllerCacheChannel()
{
delete fCache;
fControllerChannel = nil;
}
// VALUE(time)
const hsPoint3 & plPointControllerCacheChannel::Value(double time, bool peek)
{
return fControllerChannel->Value(time, fCache);
}
// DETACH
plAGChannel * plPointControllerCacheChannel::Detach(plAGChannel * channel)
{
if(channel == this)
{
return nil;
} else {
plAGChannel *result = fControllerChannel->Detach(channel);
if(result == fControllerChannel)
{
return this;
} else {
// if our controller channel has been detached, then detach ourselves as well.
return result;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// Channel applicators
void plPointChannelApplicator::IApply(const plAGModifier *modifier, double time)
{
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel);
hsAssert(pointChan, "Invalid channel given to plPointChannelApplicator");
plCoordinateInterface *CI = IGetCI(modifier);
hsMatrix44 l2p = CI->GetLocalToParent();
const hsPoint3 &point = pointChan->Value(time);
l2p.SetTranslate(&point);
hsMatrix44 p2l;
l2p.GetInverse(&p2l);
CI->SetLocalToParent(l2p, p2l);
}
void plLightDiffuseApplicator::IApply(const plAGModifier *modifier, double time)
{
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel);
hsAssert(pointChan, "Invalid channel given to plLightDiffuseApplicator");
plLightInfo *li = plLightInfo::ConvertNoRef(IGetGI(modifier, plLightInfo::Index()));
const hsPoint3 &point = pointChan->Value(time);
hsColorRGBA color;
color.Set(point.fX, point.fY, point.fZ, 1.0f);
li->SetDiffuse(color);
}
void plLightAmbientApplicator::IApply(const plAGModifier *modifier, double time)
{
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel);
hsAssert(pointChan, "Invalid channel given to plLightAmbientApplicator");
plLightInfo *li = plLightInfo::ConvertNoRef(IGetGI(modifier, plLightInfo::Index()));
const hsPoint3 &point = pointChan->Value(time);
hsColorRGBA color;
color.Set(point.fX, point.fY, point.fZ, 1.0f);
li->SetAmbient(color);
}
void plLightSpecularApplicator::IApply(const plAGModifier *modifier, double time)
{
plPointChannel *pointChan = plPointChannel::ConvertNoRef(fChannel);
hsAssert(pointChan, "Invalid channel given to plLightSpecularApplicator");
plLightInfo *li = plLightInfo::ConvertNoRef(IGetGI(modifier, plLightInfo::Index()));
const hsPoint3 &point = pointChan->Value(time);
hsColorRGBA color;
color.Set(point.fX, point.fY, point.fZ, 1.0f);
li->SetSpecular(color);
}

View File

@ -1,286 +1,286 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLPOINTCHANNEL_H
#define PLPOINTCHANNEL_H
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "plAGApplicator.h"
#include "plAGChannel.h"
#include "hsGeometry3.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plController;
class plControllerCacheInfo;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
// PLPOINTCHANNEL
/////////////////
// A source of animated hsPoint3 data
class plPointChannel : public plAGChannel
{
protected:
hsPoint3 fResult;
public:
plPointChannel();
virtual ~plPointChannel();
// AG PROTOCOL
virtual const hsPoint3 & Value(double time);
virtual void Value(hsPoint3 &point, double time);
// combine it (allocates combine object)
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
// blend it (allocates blend object)
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority);
// const eval at time zero
virtual plAGChannel * MakeZeroState();
// make a timeScale instance
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plPointChannel );
GETINTERFACE_ANY( plPointChannel, plAGChannel );
};
//////////////////
// PLPOINTCONSTANT
//////////////////
// A point source that just keeps handing out the same point
class plPointConstant : public plPointChannel
{
public:
plPointConstant();
plPointConstant(const hsPoint3 &point);
virtual ~plPointConstant();
void Set(const hsPoint3 &the_Point) { fResult = the_Point; }
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plPointConstant );
GETINTERFACE_ANY( plPointConstant, plPointChannel );
void Read(hsStream *stream, hsResMgr *mgr);
void Write(hsStream *stream, hsResMgr *mgr);
};
////////////////////
// PLPOINTTIMESCALE
////////////////////
// Adapts the time scale before passing it to the next channel in line.
// Use to instance animations while allowing each instance to run at different speeds.
class plPointTimeScale : public plPointChannel
{
protected:
plScalarChannel *fTimeSource;
plPointChannel *fChannelIn;
public:
plPointTimeScale();
plPointTimeScale(plPointChannel *channel, plScalarChannel *timeSource);
virtual ~plPointTimeScale();
virtual hsBool IsStoppedAt(double time);
virtual const hsPoint3 & Value(double time);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plPointTimeScale );
GETINTERFACE_ANY( plPointTimeScale, plPointChannel );
};
// PLPOINTBLEND
///////////////
// Combines two point sources into one
class plPointBlend : public plPointChannel
{
public:
plPointBlend();
plPointBlend(plPointChannel *channelA, plPointChannel *channelB, plScalarChannel *channelBias);
virtual ~plPointBlend();
plAGChannel * plPointBlend::Remove(plAGChannel *srceToRemove);
const plPointChannel * GetPointChannelA() const { return fPointA; }
void SetPointChannelA(plPointChannel *the_PointA) { fPointA = the_PointA; }
const plPointChannel * GetPointChannelB() const { return fPointB; }
void SetPointChannelB(plPointChannel *the_PointB) { fPointB = the_PointB; }
const plScalarChannel * GetChannelBias() const { return fChannelBias; }
void SetChannelBias(plScalarChannel * channel) { fChannelBias = channel; }
//float GetBlend() const { return fBlend; }
//void SetBlend(float the_blend) { fBlend = the_blend; }
virtual hsBool IsStoppedAt(double time);
// AG PROTOCOL
virtual const hsPoint3 &Value(double time);
// remove the specified channel from our graph
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plPointBlend );
GETINTERFACE_ANY( plPointBlend, plPointChannel );
protected:
plPointChannel *fPointA;
plPointChannel *fPointB;
plScalarChannel *fChannelBias;
};
// BLENDPOINTS
// Handy little function to share with others.
hsPoint3 BlendPoints(hsPoint3 &pointA, hsPoint3 &pointB, float blend);
///////////////////////////
// PLPOINTCONTROLLERCHANNEL
///////////////////////////
// converts a plController-style animation into a plPointChannel
class plPointControllerChannel : public plPointChannel
{
protected:
plController *fController;
public:
// xTORs
plPointControllerChannel();
plPointControllerChannel(plController *controller);
virtual ~plPointControllerChannel();
// AG PROTOCOL
virtual const hsPoint3 & Value(double time);
virtual const hsPoint3 & Value(double time, plControllerCacheInfo *cache);
virtual plAGChannel * MakeCacheChannel(plAnimTimeConvert *atc);
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plPointControllerChannel );
GETINTERFACE_ANY( plPointControllerChannel, plPointChannel );
// persistence
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
};
////////////////////////////////
// PLPOINTCONTROLLERCACHECHANNEL
////////////////////////////////
// Same as plPointController, but with caching info
class plPointControllerCacheChannel : public plPointChannel
{
protected:
plControllerCacheInfo *fCache;
plPointControllerChannel *fControllerChannel;
public:
plPointControllerCacheChannel();
plPointControllerCacheChannel(plPointControllerChannel *channel, plControllerCacheInfo *cache);
virtual ~plPointControllerCacheChannel();
virtual const hsPoint3 & Value(double time, bool peek = false);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plPointControllerCacheChannel );
GETINTERFACE_ANY( plPointControllerCacheChannel, plPointChannel );
// Created at runtime only, so no Read/Write
};
////////////////////////////
//
// Channel Applicator classes
class plPointChannelApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plPointChannelApplicator );
GETINTERFACE_ANY( plPointChannelApplicator, plAGApplicator );
};
class plLightDiffuseApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plLightDiffuseApplicator );
GETINTERFACE_ANY( plLightDiffuseApplicator, plAGApplicator );
};
class plLightAmbientApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plLightAmbientApplicator );
GETINTERFACE_ANY( plLightAmbientApplicator, plAGApplicator );
};
class plLightSpecularApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plLightSpecularApplicator );
GETINTERFACE_ANY( plLightSpecularApplicator, plAGApplicator );
};
#endif // PLPOINTCHANNEL_H
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLPOINTCHANNEL_H
#define PLPOINTCHANNEL_H
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "plAGApplicator.h"
#include "plAGChannel.h"
#include "hsGeometry3.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plController;
class plControllerCacheInfo;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
// PLPOINTCHANNEL
/////////////////
// A source of animated hsPoint3 data
class plPointChannel : public plAGChannel
{
protected:
hsPoint3 fResult;
public:
plPointChannel();
virtual ~plPointChannel();
// AG PROTOCOL
virtual const hsPoint3 & Value(double time);
virtual void Value(hsPoint3 &point, double time);
// combine it (allocates combine object)
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
// blend it (allocates blend object)
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority);
// const eval at time zero
virtual plAGChannel * MakeZeroState();
// make a timeScale instance
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plPointChannel );
GETINTERFACE_ANY( plPointChannel, plAGChannel );
};
//////////////////
// PLPOINTCONSTANT
//////////////////
// A point source that just keeps handing out the same point
class plPointConstant : public plPointChannel
{
public:
plPointConstant();
plPointConstant(const hsPoint3 &point);
virtual ~plPointConstant();
void Set(const hsPoint3 &the_Point) { fResult = the_Point; }
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plPointConstant );
GETINTERFACE_ANY( plPointConstant, plPointChannel );
void Read(hsStream *stream, hsResMgr *mgr);
void Write(hsStream *stream, hsResMgr *mgr);
};
////////////////////
// PLPOINTTIMESCALE
////////////////////
// Adapts the time scale before passing it to the next channel in line.
// Use to instance animations while allowing each instance to run at different speeds.
class plPointTimeScale : public plPointChannel
{
protected:
plScalarChannel *fTimeSource;
plPointChannel *fChannelIn;
public:
plPointTimeScale();
plPointTimeScale(plPointChannel *channel, plScalarChannel *timeSource);
virtual ~plPointTimeScale();
virtual hsBool IsStoppedAt(double time);
virtual const hsPoint3 & Value(double time);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plPointTimeScale );
GETINTERFACE_ANY( plPointTimeScale, plPointChannel );
};
// PLPOINTBLEND
///////////////
// Combines two point sources into one
class plPointBlend : public plPointChannel
{
public:
plPointBlend();
plPointBlend(plPointChannel *channelA, plPointChannel *channelB, plScalarChannel *channelBias);
virtual ~plPointBlend();
plAGChannel * plPointBlend::Remove(plAGChannel *srceToRemove);
const plPointChannel * GetPointChannelA() const { return fPointA; }
void SetPointChannelA(plPointChannel *the_PointA) { fPointA = the_PointA; }
const plPointChannel * GetPointChannelB() const { return fPointB; }
void SetPointChannelB(plPointChannel *the_PointB) { fPointB = the_PointB; }
const plScalarChannel * GetChannelBias() const { return fChannelBias; }
void SetChannelBias(plScalarChannel * channel) { fChannelBias = channel; }
//float GetBlend() const { return fBlend; }
//void SetBlend(float the_blend) { fBlend = the_blend; }
virtual hsBool IsStoppedAt(double time);
// AG PROTOCOL
virtual const hsPoint3 &Value(double time);
// remove the specified channel from our graph
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plPointBlend );
GETINTERFACE_ANY( plPointBlend, plPointChannel );
protected:
plPointChannel *fPointA;
plPointChannel *fPointB;
plScalarChannel *fChannelBias;
};
// BLENDPOINTS
// Handy little function to share with others.
hsPoint3 BlendPoints(hsPoint3 &pointA, hsPoint3 &pointB, float blend);
///////////////////////////
// PLPOINTCONTROLLERCHANNEL
///////////////////////////
// converts a plController-style animation into a plPointChannel
class plPointControllerChannel : public plPointChannel
{
protected:
plController *fController;
public:
// xTORs
plPointControllerChannel();
plPointControllerChannel(plController *controller);
virtual ~plPointControllerChannel();
// AG PROTOCOL
virtual const hsPoint3 & Value(double time);
virtual const hsPoint3 & Value(double time, plControllerCacheInfo *cache);
virtual plAGChannel * MakeCacheChannel(plAnimTimeConvert *atc);
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plPointControllerChannel );
GETINTERFACE_ANY( plPointControllerChannel, plPointChannel );
// persistence
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
};
////////////////////////////////
// PLPOINTCONTROLLERCACHECHANNEL
////////////////////////////////
// Same as plPointController, but with caching info
class plPointControllerCacheChannel : public plPointChannel
{
protected:
plControllerCacheInfo *fCache;
plPointControllerChannel *fControllerChannel;
public:
plPointControllerCacheChannel();
plPointControllerCacheChannel(plPointControllerChannel *channel, plControllerCacheInfo *cache);
virtual ~plPointControllerCacheChannel();
virtual const hsPoint3 & Value(double time, bool peek = false);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plPointControllerCacheChannel );
GETINTERFACE_ANY( plPointControllerCacheChannel, plPointChannel );
// Created at runtime only, so no Read/Write
};
////////////////////////////
//
// Channel Applicator classes
class plPointChannelApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plPointChannelApplicator );
GETINTERFACE_ANY( plPointChannelApplicator, plAGApplicator );
};
class plLightDiffuseApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plLightDiffuseApplicator );
GETINTERFACE_ANY( plLightDiffuseApplicator, plAGApplicator );
};
class plLightAmbientApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plLightAmbientApplicator );
GETINTERFACE_ANY( plLightAmbientApplicator, plAGApplicator );
};
class plLightSpecularApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plLightSpecularApplicator );
GETINTERFACE_ANY( plLightSpecularApplicator, plAGApplicator );
};
#endif // PLPOINTCHANNEL_H

View File

@ -1,26 +1,26 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// removed

View File

@ -1,26 +1,26 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// Removed

View File

@ -1,314 +1,314 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plQuatChannel.h"
#include "plPointChannel.h"
#include "plMatrixChannel.h"
#include "pnSceneObject/plDrawInterface.h"
#include "pnSceneObject/plSimulationInterface.h"
#include "pnSceneObject/plCoordinateInterface.h"
#include "pnSceneObject/plAudioInterface.h"
#include "plInterp/plAnimTimeConvert.h"
#include "hsMatrix44.h"
////////////////
// PLQUATCHANNEL
////////////////
// CTOR
plQuatChannel::plQuatChannel()
: plAGChannel()
{
fResult.Identity();
}
// DTOR
plQuatChannel::~plQuatChannel()
{
}
// VALUE (time)
const hsQuat &plQuatChannel::Value(double time)
{
return fResult;
}
// VALUE (quaternion, time)
void plQuatChannel::Value(hsQuat &quat, double time)
{
quat = Value(time);
}
// CANCOMBINE
hsBool plQuatChannel::CanCombine(plAGChannel *channelA)
{
return false;
if(plPointChannel::ConvertNoRef(channelA))
{
return true;
} else {
return false;
}
}
// MAKECOMBINE
plAGChannel * plQuatChannel::MakeCombine(plAGChannel *channelA)
{
if(plPointChannel::ConvertNoRef(channelA))
{
return TRACKED_NEW plQuatPointCombine(this, (plPointChannel *)channelA);
} else {
return nil;
}
}
// MAKEBLEND
plAGChannel *plQuatChannel::MakeBlend(plAGChannel *channelB, plScalarChannel *channelBias, int blendPriority)
{
plQuatChannel *chanB = plQuatChannel::ConvertNoRef(channelB);
plScalarChannel *chanBias = plScalarChannel::ConvertNoRef(channelBias);
if(chanB && chanBias)
{
return TRACKED_NEW plQuatBlend(this, chanB, chanBias);
} else {
hsStatusMessageF("Blend operation failed.");
return this;
}
}
// MAKEZEROSTATE
plAGChannel * plQuatChannel::MakeZeroState()
{
return TRACKED_NEW plQuatConstant(Value(0));
}
// MAKETIMESCALE
plAGChannel * plQuatChannel::MakeTimeScale(plScalarChannel *timeSource)
{
return TRACKED_NEW plQuatTimeScale(this, timeSource);
}
/////////////////
// PLQUATCONSTANT
/////////////////
// CTOR
plQuatConstant::plQuatConstant()
: plQuatChannel()
{
}
// CTOR(name, quaternion)
plQuatConstant::plQuatConstant(const hsQuat &quaternion)
{
fResult = quaternion;
}
// DTOR
plQuatConstant::~plQuatConstant()
{
}
void plQuatConstant::Read(hsStream *stream, hsResMgr *mgr)
{
plQuatChannel::Read(stream, mgr);
fResult.Read(stream);
}
void plQuatConstant::Write(hsStream *stream, hsResMgr *mgr)
{
plQuatChannel::Write(stream, mgr);
fResult.Write(stream);
}
////////////////////
// PLQUATTIMESCALE
////////////////////
// Insert into the graph when you need to change the speed or direction of time
// Also serves as a handy instancing node, since it just passes its data through.
// CTOR
plQuatTimeScale::plQuatTimeScale()
: fTimeSource(nil),
fChannelIn(nil)
{
}
// CTOR (channel, converter)
plQuatTimeScale::plQuatTimeScale(plQuatChannel *channel, plScalarChannel *timeSource)
: fChannelIn(channel),
fTimeSource(timeSource)
{
}
// DTOR
plQuatTimeScale::~plQuatTimeScale()
{
}
hsBool plQuatTimeScale::IsStoppedAt(double time)
{
return fTimeSource->IsStoppedAt(time);
}
// VALUE
const hsQuat & plQuatTimeScale::Value(double time)
{
fResult = fChannelIn->Value(fTimeSource->Value(time));
return fResult;
}
// DETACH
plAGChannel * plQuatTimeScale::Detach(plAGChannel * channel)
{
plAGChannel *result = this;
fChannelIn = plQuatChannel::ConvertNoRef(fChannelIn->Detach(channel));
if(!fChannelIn || channel == this)
result = nil;
if (result != this)
delete this;
return result;
}
//////////////
// PLQUATBLEND
//////////////
// CTOR
plQuatBlend::plQuatBlend()
: fQuatA(nil),
fQuatB(nil),
fChannelBias(nil)
{
}
// CTOR(channelA, channelB, blend)
plQuatBlend::plQuatBlend(plQuatChannel *channelA, plQuatChannel *channelB, plScalarChannel *channelBias)
: fQuatA(channelA),
fQuatB(channelB),
fChannelBias(channelBias)
{
}
// DTOR
plQuatBlend::~plQuatBlend()
{
//if (fQuatA) delete fQuatA;
//if (fQuatB) delete fQuatB;
fQuatA = fQuatB = nil;
fChannelBias = nil;
}
hsBool plQuatBlend::IsStoppedAt(double time)
{
hsScalar blend = fChannelBias->Value(time);
if (blend == 0)
return fQuatA->IsStoppedAt(time);
if (blend == 1)
return fQuatB->IsStoppedAt(time);
return (fQuatA->IsStoppedAt(time) && fQuatB->IsStoppedAt(time));
}
// VALUE(time)
const hsQuat &plQuatBlend::Value(double time)
{
hsQuat quatA = fQuatA->Value(time);
hsQuat quatB = fQuatB->Value(time);
fResult.SetFromSlerp(quatA, quatB, fChannelBias->Value(time));
return fResult;
}
// REMOVE
// Remove the given channel wherever it may be in the graph (including this node)
plAGChannel * plQuatBlend::Detach(plAGChannel *remove)
{
plAGChannel *result = this;
hsAssert(remove != this, "Cannot remove blenders explicitly. Remove blended source instead.");
if (remove != this)
{
fChannelBias = plScalarChannel::ConvertNoRef(fChannelBias->Detach(remove));
if (!fChannelBias)
{
// No more bias channel, assume it's zero from now on, (a.k.a. We just want channelA)
result = fQuatA;
}
else
{
fQuatA = (plQuatChannel *)fQuatA->Detach(remove);
if(fQuatA)
{
// channel a still here(although children may be gone); try channel b
fQuatB = (plQuatChannel *)fQuatB->Detach(remove);
if(!fQuatB)
{
result = fQuatA; // channel b is gone: return channel a as blender's replacement
}
} else {
result = fQuatB; // channel a is gone: return channel b
}
if (result != this)
{
delete this; // lost one of our channels: kill the blender.
}
}
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////////
// Applicators
void plQuatChannelApplicator::IApply(const plAGModifier *mod, double time)
{
plQuatChannel *quatChan = plQuatChannel::ConvertNoRef(fChannel);
hsAssert(quatChan, "Invalid channel in plQuatChannelApplicator");
const hsQuat &rotate = quatChan->Value(time);
plCoordinateInterface *CI = IGetCI(mod);
hsMatrix44 l2w;
hsMatrix44 w2l;
rotate.MakeMatrix(&l2w);
l2w.GetInverse(&w2l);
CI->SetLocalToParent(l2w, w2l);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plQuatChannel.h"
#include "plPointChannel.h"
#include "plMatrixChannel.h"
#include "pnSceneObject/plDrawInterface.h"
#include "pnSceneObject/plSimulationInterface.h"
#include "pnSceneObject/plCoordinateInterface.h"
#include "pnSceneObject/plAudioInterface.h"
#include "plInterp/plAnimTimeConvert.h"
#include "hsMatrix44.h"
////////////////
// PLQUATCHANNEL
////////////////
// CTOR
plQuatChannel::plQuatChannel()
: plAGChannel()
{
fResult.Identity();
}
// DTOR
plQuatChannel::~plQuatChannel()
{
}
// VALUE (time)
const hsQuat &plQuatChannel::Value(double time)
{
return fResult;
}
// VALUE (quaternion, time)
void plQuatChannel::Value(hsQuat &quat, double time)
{
quat = Value(time);
}
// CANCOMBINE
hsBool plQuatChannel::CanCombine(plAGChannel *channelA)
{
return false;
if(plPointChannel::ConvertNoRef(channelA))
{
return true;
} else {
return false;
}
}
// MAKECOMBINE
plAGChannel * plQuatChannel::MakeCombine(plAGChannel *channelA)
{
if(plPointChannel::ConvertNoRef(channelA))
{
return TRACKED_NEW plQuatPointCombine(this, (plPointChannel *)channelA);
} else {
return nil;
}
}
// MAKEBLEND
plAGChannel *plQuatChannel::MakeBlend(plAGChannel *channelB, plScalarChannel *channelBias, int blendPriority)
{
plQuatChannel *chanB = plQuatChannel::ConvertNoRef(channelB);
plScalarChannel *chanBias = plScalarChannel::ConvertNoRef(channelBias);
if(chanB && chanBias)
{
return TRACKED_NEW plQuatBlend(this, chanB, chanBias);
} else {
hsStatusMessageF("Blend operation failed.");
return this;
}
}
// MAKEZEROSTATE
plAGChannel * plQuatChannel::MakeZeroState()
{
return TRACKED_NEW plQuatConstant(Value(0));
}
// MAKETIMESCALE
plAGChannel * plQuatChannel::MakeTimeScale(plScalarChannel *timeSource)
{
return TRACKED_NEW plQuatTimeScale(this, timeSource);
}
/////////////////
// PLQUATCONSTANT
/////////////////
// CTOR
plQuatConstant::plQuatConstant()
: plQuatChannel()
{
}
// CTOR(name, quaternion)
plQuatConstant::plQuatConstant(const hsQuat &quaternion)
{
fResult = quaternion;
}
// DTOR
plQuatConstant::~plQuatConstant()
{
}
void plQuatConstant::Read(hsStream *stream, hsResMgr *mgr)
{
plQuatChannel::Read(stream, mgr);
fResult.Read(stream);
}
void plQuatConstant::Write(hsStream *stream, hsResMgr *mgr)
{
plQuatChannel::Write(stream, mgr);
fResult.Write(stream);
}
////////////////////
// PLQUATTIMESCALE
////////////////////
// Insert into the graph when you need to change the speed or direction of time
// Also serves as a handy instancing node, since it just passes its data through.
// CTOR
plQuatTimeScale::plQuatTimeScale()
: fTimeSource(nil),
fChannelIn(nil)
{
}
// CTOR (channel, converter)
plQuatTimeScale::plQuatTimeScale(plQuatChannel *channel, plScalarChannel *timeSource)
: fChannelIn(channel),
fTimeSource(timeSource)
{
}
// DTOR
plQuatTimeScale::~plQuatTimeScale()
{
}
hsBool plQuatTimeScale::IsStoppedAt(double time)
{
return fTimeSource->IsStoppedAt(time);
}
// VALUE
const hsQuat & plQuatTimeScale::Value(double time)
{
fResult = fChannelIn->Value(fTimeSource->Value(time));
return fResult;
}
// DETACH
plAGChannel * plQuatTimeScale::Detach(plAGChannel * channel)
{
plAGChannel *result = this;
fChannelIn = plQuatChannel::ConvertNoRef(fChannelIn->Detach(channel));
if(!fChannelIn || channel == this)
result = nil;
if (result != this)
delete this;
return result;
}
//////////////
// PLQUATBLEND
//////////////
// CTOR
plQuatBlend::plQuatBlend()
: fQuatA(nil),
fQuatB(nil),
fChannelBias(nil)
{
}
// CTOR(channelA, channelB, blend)
plQuatBlend::plQuatBlend(plQuatChannel *channelA, plQuatChannel *channelB, plScalarChannel *channelBias)
: fQuatA(channelA),
fQuatB(channelB),
fChannelBias(channelBias)
{
}
// DTOR
plQuatBlend::~plQuatBlend()
{
//if (fQuatA) delete fQuatA;
//if (fQuatB) delete fQuatB;
fQuatA = fQuatB = nil;
fChannelBias = nil;
}
hsBool plQuatBlend::IsStoppedAt(double time)
{
hsScalar blend = fChannelBias->Value(time);
if (blend == 0)
return fQuatA->IsStoppedAt(time);
if (blend == 1)
return fQuatB->IsStoppedAt(time);
return (fQuatA->IsStoppedAt(time) && fQuatB->IsStoppedAt(time));
}
// VALUE(time)
const hsQuat &plQuatBlend::Value(double time)
{
hsQuat quatA = fQuatA->Value(time);
hsQuat quatB = fQuatB->Value(time);
fResult.SetFromSlerp(quatA, quatB, fChannelBias->Value(time));
return fResult;
}
// REMOVE
// Remove the given channel wherever it may be in the graph (including this node)
plAGChannel * plQuatBlend::Detach(plAGChannel *remove)
{
plAGChannel *result = this;
hsAssert(remove != this, "Cannot remove blenders explicitly. Remove blended source instead.");
if (remove != this)
{
fChannelBias = plScalarChannel::ConvertNoRef(fChannelBias->Detach(remove));
if (!fChannelBias)
{
// No more bias channel, assume it's zero from now on, (a.k.a. We just want channelA)
result = fQuatA;
}
else
{
fQuatA = (plQuatChannel *)fQuatA->Detach(remove);
if(fQuatA)
{
// channel a still here(although children may be gone); try channel b
fQuatB = (plQuatChannel *)fQuatB->Detach(remove);
if(!fQuatB)
{
result = fQuatA; // channel b is gone: return channel a as blender's replacement
}
} else {
result = fQuatB; // channel a is gone: return channel b
}
if (result != this)
{
delete this; // lost one of our channels: kill the blender.
}
}
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////////
// Applicators
void plQuatChannelApplicator::IApply(const plAGModifier *mod, double time)
{
plQuatChannel *quatChan = plQuatChannel::ConvertNoRef(fChannel);
hsAssert(quatChan, "Invalid channel in plQuatChannelApplicator");
const hsQuat &rotate = quatChan->Value(time);
plCoordinateInterface *CI = IGetCI(mod);
hsMatrix44 l2w;
hsMatrix44 w2l;
rotate.MakeMatrix(&l2w);
l2w.GetInverse(&w2l);
CI->SetLocalToParent(l2w, w2l);
}

View File

@ -1,171 +1,171 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLQUATCHANNEL_INC
#define PLQUATCHANNEL_INC
#include "hsQuat.h"
#include "plAGChannel.h"
#include "plAGApplicator.h"
// PLQUATCHANNEL
/////////////
// A source of animated hsQuat data
class plQuatChannel : public plAGChannel
{
protected:
hsQuat fResult;
public:
plQuatChannel();
virtual ~plQuatChannel();
// AG PROTOCOL
virtual const hsQuat & Value(double time);
virtual void Value(hsQuat &quaternion, double time);
// can this channel combine with the given channel?
virtual hsBool CanCombine(plAGChannel * channelB);
// combine it (allocates combine object)
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
// const eval at time zero
virtual plAGChannel * MakeZeroState();
// make a timeScale instance
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource);
// blend it (allocates blend object)
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plQuatChannel );
GETINTERFACE_ANY( plQuatChannel, plAGChannel );
};
// PLQUATCONSTANT
////////////
// A quat channel that just keeps handing out the same quaternion
class plQuatConstant : public plQuatChannel
{
public:
plQuatConstant();
plQuatConstant(const hsQuat &quaternion);
virtual ~plQuatConstant();
void Set(const hsQuat &the_Quat) { fResult = the_Quat; }
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plQuatConstant );
GETINTERFACE_ANY( plQuatConstant, plQuatChannel );
void Read(hsStream *stream, hsResMgr *mgr);
void Write(hsStream *stream, hsResMgr *mgr);
};
////////////////////
// PLQUATTIMESCALE
////////////////////
// Adapts the time scale before passing it to the next channel in line.
// Use to instance animations while allowing each instance to run at different speeds.
class plQuatTimeScale : public plQuatChannel
{
protected:
plScalarChannel *fTimeSource;
plQuatChannel *fChannelIn;
public:
plQuatTimeScale();
plQuatTimeScale(plQuatChannel *channel, plScalarChannel *timeSource);
virtual ~plQuatTimeScale();
virtual hsBool IsStoppedAt(double time);
virtual const hsQuat & Value(double time);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plQuatTimeScale );
GETINTERFACE_ANY( plQuatTimeScale, plQuatChannel );
};
// PLQUATBLEND
//////////////
// Combines two quaternion sources into one
class plQuatBlend : public plQuatChannel
{
public:
plQuatBlend();
plQuatBlend(plQuatChannel *channelA, plQuatChannel *channelB, plScalarChannel *channelBias);
virtual ~plQuatBlend();
// GETTERS AND SETTERS FOR CHANNELS
const plQuatChannel * GetQuatA() const { return fQuatA; }
void SetQuatA(plQuatChannel *the_QuatA) { fQuatA = the_QuatA; }
const plQuatChannel * GetQuatB() const { return fQuatB; }
void SetQuatB(plQuatChannel *the_QuatB) { fQuatB = the_QuatB; }
const plScalarChannel * GetChannelBias() const { return fChannelBias; }
void SetChannelBias(plScalarChannel *channel) { fChannelBias = channel; }
//float GetBlend() const { return fBlend; }
//void SetBlend(float the_blend) { fBlend = the_blend; }
virtual hsBool IsStoppedAt(double time);
// AG PROTOCOL
virtual const hsQuat &Value(double time);
// remove the specified channel from our graph
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plQuatBlend );
GETINTERFACE_ANY( plQuatBlend, plQuatChannel );
protected:
plQuatChannel *fQuatA;
plQuatChannel *fQuatB;
plScalarChannel *fChannelBias;
};
////////////////////////////
//
// Channel Applicator classes
class plQuatChannelApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plQuatChannelApplicator );
GETINTERFACE_ANY( plQuatChannelApplicator, plAGApplicator );
};
#endif // PLQUATCHANNEL_INC
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLQUATCHANNEL_INC
#define PLQUATCHANNEL_INC
#include "hsQuat.h"
#include "plAGChannel.h"
#include "plAGApplicator.h"
// PLQUATCHANNEL
/////////////
// A source of animated hsQuat data
class plQuatChannel : public plAGChannel
{
protected:
hsQuat fResult;
public:
plQuatChannel();
virtual ~plQuatChannel();
// AG PROTOCOL
virtual const hsQuat & Value(double time);
virtual void Value(hsQuat &quaternion, double time);
// can this channel combine with the given channel?
virtual hsBool CanCombine(plAGChannel * channelB);
// combine it (allocates combine object)
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
// const eval at time zero
virtual plAGChannel * MakeZeroState();
// make a timeScale instance
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource);
// blend it (allocates blend object)
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plQuatChannel );
GETINTERFACE_ANY( plQuatChannel, plAGChannel );
};
// PLQUATCONSTANT
////////////
// A quat channel that just keeps handing out the same quaternion
class plQuatConstant : public plQuatChannel
{
public:
plQuatConstant();
plQuatConstant(const hsQuat &quaternion);
virtual ~plQuatConstant();
void Set(const hsQuat &the_Quat) { fResult = the_Quat; }
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plQuatConstant );
GETINTERFACE_ANY( plQuatConstant, plQuatChannel );
void Read(hsStream *stream, hsResMgr *mgr);
void Write(hsStream *stream, hsResMgr *mgr);
};
////////////////////
// PLQUATTIMESCALE
////////////////////
// Adapts the time scale before passing it to the next channel in line.
// Use to instance animations while allowing each instance to run at different speeds.
class plQuatTimeScale : public plQuatChannel
{
protected:
plScalarChannel *fTimeSource;
plQuatChannel *fChannelIn;
public:
plQuatTimeScale();
plQuatTimeScale(plQuatChannel *channel, plScalarChannel *timeSource);
virtual ~plQuatTimeScale();
virtual hsBool IsStoppedAt(double time);
virtual const hsQuat & Value(double time);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plQuatTimeScale );
GETINTERFACE_ANY( plQuatTimeScale, plQuatChannel );
};
// PLQUATBLEND
//////////////
// Combines two quaternion sources into one
class plQuatBlend : public plQuatChannel
{
public:
plQuatBlend();
plQuatBlend(plQuatChannel *channelA, plQuatChannel *channelB, plScalarChannel *channelBias);
virtual ~plQuatBlend();
// GETTERS AND SETTERS FOR CHANNELS
const plQuatChannel * GetQuatA() const { return fQuatA; }
void SetQuatA(plQuatChannel *the_QuatA) { fQuatA = the_QuatA; }
const plQuatChannel * GetQuatB() const { return fQuatB; }
void SetQuatB(plQuatChannel *the_QuatB) { fQuatB = the_QuatB; }
const plScalarChannel * GetChannelBias() const { return fChannelBias; }
void SetChannelBias(plScalarChannel *channel) { fChannelBias = channel; }
//float GetBlend() const { return fBlend; }
//void SetBlend(float the_blend) { fBlend = the_blend; }
virtual hsBool IsStoppedAt(double time);
// AG PROTOCOL
virtual const hsQuat &Value(double time);
// remove the specified channel from our graph
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plQuatBlend );
GETINTERFACE_ANY( plQuatBlend, plQuatChannel );
protected:
plQuatChannel *fQuatA;
plQuatChannel *fQuatB;
plScalarChannel *fChannelBias;
};
////////////////////////////
//
// Channel Applicator classes
class plQuatChannelApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plQuatChannelApplicator );
GETINTERFACE_ANY( plQuatChannelApplicator, plAGApplicator );
};
#endif // PLQUATCHANNEL_INC

File diff suppressed because it is too large Load Diff

View File

@ -1,346 +1,346 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLSCALARCHANNEL_INC
#define PLSCALARCHANNEL_INC
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
// base
#include "plAGChannel.h"
#include "plAGApplicator.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plController;
class plAnimTimeConvert;
class plSimpleStateVariable;
class plControllerCacheInfo;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
//////////////////
// PLSCALARCHANNEL
//////////////////
// an animation channel that outputs a scalar value
class plScalarChannel : public plAGChannel
{
protected:
hsScalar fResult;
public:
plScalarChannel();
virtual ~plScalarChannel();
// AG PROTOCOL
virtual const hsScalar & Value(double time, hsBool peek = false);
virtual void Value(hsScalar &result, double time, hsBool peek = false);
// combine it (allocates combine object)
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
// blend it (allocates blend object)
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority);
// const eval at time zero
virtual plAGChannel * MakeZeroState();
// make a timeScale instance
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarChannel );
GETINTERFACE_ANY( plScalarChannel, plAGChannel );
};
///////////////////
// PLSCALARCONSTANT
///////////////////
// A scalar source that just keeps handing out the same value
class plScalarConstant : public plScalarChannel
{
public:
plScalarConstant();
plScalarConstant(hsScalar value);
virtual ~plScalarConstant();
void Set(hsScalar value) { fResult = value; }
hsScalar Get() { return fResult; }
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarConstant );
GETINTERFACE_ANY( plScalarConstant, plScalarChannel );
void Read(hsStream *stream, hsResMgr *mgr);
void Write(hsStream *stream, hsResMgr *mgr);
};
////////////////////
// PLSCALARTIMESCALE
////////////////////
// Adapts the time scale before passing it to the next channel in line.
// Use to instance animations while allowing each instance to run at different speeds.
class plScalarTimeScale : public plScalarChannel
{
protected:
plScalarChannel *fTimeSource;
plScalarChannel *fChannelIn;
public:
plScalarTimeScale();
plScalarTimeScale(plScalarChannel *channel, plScalarChannel *timeSource);
virtual ~plScalarTimeScale();
virtual hsBool IsStoppedAt(double time);
virtual const hsScalar & Value(double time, hsBool peek = false);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarTimeScale );
GETINTERFACE_ANY( plScalarTimeScale, plScalarChannel );
};
////////////////
// PLSCALARBLEND
////////////////
// blends two scalars into one with weighting
class plScalarBlend : public plScalarChannel
{
protected:
plScalarChannel * fChannelA;
plScalarChannel * fChannelB;
plScalarChannel * fChannelBias;
public:
// xTORs
plScalarBlend();
plScalarBlend(plScalarChannel * channelA, plScalarChannel * channelB, plScalarChannel * channelBias);
virtual ~plScalarBlend();
// SPECIFICS
const plScalarChannel * GetChannelA() const { return fChannelA; }
void SetChannelA(plScalarChannel * channel) { fChannelA = channel; }
const plScalarChannel * GetChannelB() const { return fChannelB; }
void SetChannelB(plScalarChannel * channel) { fChannelB = channel; }
const plScalarChannel * GetChannelBias() const { return fChannelBias; }
void SetChannelBias(plScalarChannel * channel) { fChannelBias = channel; }
virtual hsBool IsStoppedAt(double time);
// AG PROTOCOL
virtual const hsScalar & Value(double time, hsBool peek = false);
// remove the specified channel from our graph
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarBlend );
GETINTERFACE_ANY( plScalarBlend, plScalarChannel );
};
////////////////////////////
// PLSCALARCONTROLLERCHANNEL
////////////////////////////
// converts a plController-style animation into a plScalarChannel
class plScalarControllerChannel : public plScalarChannel
{
protected:
plController *fController;
public:
// xTORs
plScalarControllerChannel();
plScalarControllerChannel(plController *controller);
virtual ~plScalarControllerChannel();
// AG PROTOCOL
virtual const hsScalar & Value(double time, hsBool peek = false);
virtual const hsScalar & Value(double time, hsBool peek, plControllerCacheInfo *cache);
virtual plAGChannel *plScalarControllerChannel::MakeCacheChannel(plAnimTimeConvert *atc);
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plScalarControllerChannel );
GETINTERFACE_ANY( plScalarControllerChannel, plScalarChannel );
// persistence
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
};
/////////////////////////////////
// PLSCALARCONTROLLERCACHECHANNEL
/////////////////////////////////
// Same as plScalarController, but with caching info
class plScalarControllerCacheChannel : public plScalarChannel
{
protected:
plControllerCacheInfo *fCache;
plScalarControllerChannel *fControllerChannel;
public:
plScalarControllerCacheChannel();
plScalarControllerCacheChannel(plScalarControllerChannel *channel, plControllerCacheInfo *cache);
virtual ~plScalarControllerCacheChannel();
virtual const hsScalar & Value(double time, bool peek = false);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarControllerCacheChannel );
GETINTERFACE_ANY( plScalarControllerCacheChannel, plScalarChannel );
// Created at runtime only, so no Read/Write
};
////////////////////
// PLATCChannel
////////////////////
// Channel interface for a plAnimTimeConvert object
class plATCChannel : public plScalarChannel
{
protected:
plAnimTimeConvert *fConvert;
public:
plATCChannel();
plATCChannel(plAnimTimeConvert *convert);
virtual ~plATCChannel();
virtual hsBool IsStoppedAt(double time);
virtual const hsScalar & Value(double time, hsBool peek = false);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plATCChannel );
GETINTERFACE_ANY( plATCChannel, plScalarChannel );
};
////////////////////
// PLSCALARSDLCHANNEL
////////////////////
// Returns the value of an SDL scalar variable
class plScalarSDLChannel : public plScalarChannel
{
protected:
plSimpleStateVariable *fVar;
hsScalar fLength;
public:
plScalarSDLChannel();
plScalarSDLChannel(hsScalar length);
virtual ~plScalarSDLChannel();
virtual hsBool IsStoppedAt(double time);
virtual const hsScalar & Value(double time, hsBool peek = false);
void SetVar(plSimpleStateVariable *var) { fVar = var; }
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarSDLChannel );
GETINTERFACE_ANY( plScalarSDLChannel, plScalarChannel );
};
////////////////////////////
//
// Channel Applicator classes
class plScalarChannelApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plScalarChannelApplicator );
GETINTERFACE_ANY( plScalarChannelApplicator, plAGApplicator );
};
class plSpotInnerApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plSpotInnerApplicator );
GETINTERFACE_ANY( plSpotInnerApplicator, plAGApplicator );
};
class plSpotOuterApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plSpotOuterApplicator );
GETINTERFACE_ANY( plSpotOuterApplicator, plAGApplicator );
};
class plOmniApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plOmniApplicator );
GETINTERFACE_ANY( plOmniApplicator, plAGApplicator );
};
class plOmniSqApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plOmniSqApplicator );
GETINTERFACE_ANY( plOmniSqApplicator, plAGApplicator );
};
class plOmniCutoffApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plOmniCutoffApplicator );
GETINTERFACE_ANY( plOmniCutoffApplicator, plAGApplicator );
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLSCALARCHANNEL_INC
#define PLSCALARCHANNEL_INC
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
// base
#include "plAGChannel.h"
#include "plAGApplicator.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plController;
class plAnimTimeConvert;
class plSimpleStateVariable;
class plControllerCacheInfo;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
//////////////////
// PLSCALARCHANNEL
//////////////////
// an animation channel that outputs a scalar value
class plScalarChannel : public plAGChannel
{
protected:
hsScalar fResult;
public:
plScalarChannel();
virtual ~plScalarChannel();
// AG PROTOCOL
virtual const hsScalar & Value(double time, hsBool peek = false);
virtual void Value(hsScalar &result, double time, hsBool peek = false);
// combine it (allocates combine object)
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
// blend it (allocates blend object)
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * channelBias, int blendPriority);
// const eval at time zero
virtual plAGChannel * MakeZeroState();
// make a timeScale instance
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarChannel );
GETINTERFACE_ANY( plScalarChannel, plAGChannel );
};
///////////////////
// PLSCALARCONSTANT
///////////////////
// A scalar source that just keeps handing out the same value
class plScalarConstant : public plScalarChannel
{
public:
plScalarConstant();
plScalarConstant(hsScalar value);
virtual ~plScalarConstant();
void Set(hsScalar value) { fResult = value; }
hsScalar Get() { return fResult; }
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarConstant );
GETINTERFACE_ANY( plScalarConstant, plScalarChannel );
void Read(hsStream *stream, hsResMgr *mgr);
void Write(hsStream *stream, hsResMgr *mgr);
};
////////////////////
// PLSCALARTIMESCALE
////////////////////
// Adapts the time scale before passing it to the next channel in line.
// Use to instance animations while allowing each instance to run at different speeds.
class plScalarTimeScale : public plScalarChannel
{
protected:
plScalarChannel *fTimeSource;
plScalarChannel *fChannelIn;
public:
plScalarTimeScale();
plScalarTimeScale(plScalarChannel *channel, plScalarChannel *timeSource);
virtual ~plScalarTimeScale();
virtual hsBool IsStoppedAt(double time);
virtual const hsScalar & Value(double time, hsBool peek = false);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarTimeScale );
GETINTERFACE_ANY( plScalarTimeScale, plScalarChannel );
};
////////////////
// PLSCALARBLEND
////////////////
// blends two scalars into one with weighting
class plScalarBlend : public plScalarChannel
{
protected:
plScalarChannel * fChannelA;
plScalarChannel * fChannelB;
plScalarChannel * fChannelBias;
public:
// xTORs
plScalarBlend();
plScalarBlend(plScalarChannel * channelA, plScalarChannel * channelB, plScalarChannel * channelBias);
virtual ~plScalarBlend();
// SPECIFICS
const plScalarChannel * GetChannelA() const { return fChannelA; }
void SetChannelA(plScalarChannel * channel) { fChannelA = channel; }
const plScalarChannel * GetChannelB() const { return fChannelB; }
void SetChannelB(plScalarChannel * channel) { fChannelB = channel; }
const plScalarChannel * GetChannelBias() const { return fChannelBias; }
void SetChannelBias(plScalarChannel * channel) { fChannelBias = channel; }
virtual hsBool IsStoppedAt(double time);
// AG PROTOCOL
virtual const hsScalar & Value(double time, hsBool peek = false);
// remove the specified channel from our graph
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarBlend );
GETINTERFACE_ANY( plScalarBlend, plScalarChannel );
};
////////////////////////////
// PLSCALARCONTROLLERCHANNEL
////////////////////////////
// converts a plController-style animation into a plScalarChannel
class plScalarControllerChannel : public plScalarChannel
{
protected:
plController *fController;
public:
// xTORs
plScalarControllerChannel();
plScalarControllerChannel(plController *controller);
virtual ~plScalarControllerChannel();
// AG PROTOCOL
virtual const hsScalar & Value(double time, hsBool peek = false);
virtual const hsScalar & Value(double time, hsBool peek, plControllerCacheInfo *cache);
virtual plAGChannel *plScalarControllerChannel::MakeCacheChannel(plAnimTimeConvert *atc);
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plScalarControllerChannel );
GETINTERFACE_ANY( plScalarControllerChannel, plScalarChannel );
// persistence
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
};
/////////////////////////////////
// PLSCALARCONTROLLERCACHECHANNEL
/////////////////////////////////
// Same as plScalarController, but with caching info
class plScalarControllerCacheChannel : public plScalarChannel
{
protected:
plControllerCacheInfo *fCache;
plScalarControllerChannel *fControllerChannel;
public:
plScalarControllerCacheChannel();
plScalarControllerCacheChannel(plScalarControllerChannel *channel, plControllerCacheInfo *cache);
virtual ~plScalarControllerCacheChannel();
virtual const hsScalar & Value(double time, bool peek = false);
virtual plAGChannel * Detach(plAGChannel * channel);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarControllerCacheChannel );
GETINTERFACE_ANY( plScalarControllerCacheChannel, plScalarChannel );
// Created at runtime only, so no Read/Write
};
////////////////////
// PLATCChannel
////////////////////
// Channel interface for a plAnimTimeConvert object
class plATCChannel : public plScalarChannel
{
protected:
plAnimTimeConvert *fConvert;
public:
plATCChannel();
plATCChannel(plAnimTimeConvert *convert);
virtual ~plATCChannel();
virtual hsBool IsStoppedAt(double time);
virtual const hsScalar & Value(double time, hsBool peek = false);
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plATCChannel );
GETINTERFACE_ANY( plATCChannel, plScalarChannel );
};
////////////////////
// PLSCALARSDLCHANNEL
////////////////////
// Returns the value of an SDL scalar variable
class plScalarSDLChannel : public plScalarChannel
{
protected:
plSimpleStateVariable *fVar;
hsScalar fLength;
public:
plScalarSDLChannel();
plScalarSDLChannel(hsScalar length);
virtual ~plScalarSDLChannel();
virtual hsBool IsStoppedAt(double time);
virtual const hsScalar & Value(double time, hsBool peek = false);
void SetVar(plSimpleStateVariable *var) { fVar = var; }
// PLASMA PROTOCOL
CLASSNAME_REGISTER( plScalarSDLChannel );
GETINTERFACE_ANY( plScalarSDLChannel, plScalarChannel );
};
////////////////////////////
//
// Channel Applicator classes
class plScalarChannelApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plScalarChannelApplicator );
GETINTERFACE_ANY( plScalarChannelApplicator, plAGApplicator );
};
class plSpotInnerApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plSpotInnerApplicator );
GETINTERFACE_ANY( plSpotInnerApplicator, plAGApplicator );
};
class plSpotOuterApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plSpotOuterApplicator );
GETINTERFACE_ANY( plSpotOuterApplicator, plAGApplicator );
};
class plOmniApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plOmniApplicator );
GETINTERFACE_ANY( plOmniApplicator, plAGApplicator );
};
class plOmniSqApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plOmniSqApplicator );
GETINTERFACE_ANY( plOmniSqApplicator, plAGApplicator );
};
class plOmniCutoffApplicator : public plAGApplicator
{
protected:
virtual void IApply(const plAGModifier *mod, double time);
public:
CLASSNAME_REGISTER( plOmniCutoffApplicator );
GETINTERFACE_ANY( plOmniCutoffApplicator, plAGApplicator );
};
#endif

View File

@ -1,95 +1,95 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plSeekPointMod.h"
// local
#include "plAvatarMgr.h"
// CTOR()
plSeekPointMod::plSeekPointMod()
: fName(nil), plMultiModifier()
{
// this constructor is called from the loader.
}
// CTOR(char *)
plSeekPointMod::plSeekPointMod(char * name)
: fName(name), plMultiModifier()
{
// this constructor is called from the converter. it adds the seek point to the
// registry immediately because it has the name already
}
// DTOR()
plSeekPointMod::~plSeekPointMod()
{
if(fName) {
delete[] fName;
fName = nil;
}
}
// MSGRECEIVE
hsBool plSeekPointMod::MsgReceive(plMessage* msg)
{
return plMultiModifier::MsgReceive(msg);
}
// ADDTARGET
// Here I am. Announce presence to the avatar registry.
void plSeekPointMod::AddTarget(plSceneObject* so)
{
plMultiModifier::AddTarget(so);
// plAvatarMgr::GetInstance()->AddSeekPoint(this);
}
void plSeekPointMod::Read(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Read(stream, mgr);
// read in the name of the animation itself
int length = stream->ReadSwap32();
if(length > 0)
{
fName = TRACKED_NEW char[length + 1];
stream->Read(length, fName);
fName[length] = 0;
}
}
void plSeekPointMod::Write(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Write(stream, mgr);
int length = strlen(fName);
stream->WriteSwap32(length);
if (length > 0)
{
stream->Write(length, fName);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plSeekPointMod.h"
// local
#include "plAvatarMgr.h"
// CTOR()
plSeekPointMod::plSeekPointMod()
: fName(nil), plMultiModifier()
{
// this constructor is called from the loader.
}
// CTOR(char *)
plSeekPointMod::plSeekPointMod(char * name)
: fName(name), plMultiModifier()
{
// this constructor is called from the converter. it adds the seek point to the
// registry immediately because it has the name already
}
// DTOR()
plSeekPointMod::~plSeekPointMod()
{
if(fName) {
delete[] fName;
fName = nil;
}
}
// MSGRECEIVE
hsBool plSeekPointMod::MsgReceive(plMessage* msg)
{
return plMultiModifier::MsgReceive(msg);
}
// ADDTARGET
// Here I am. Announce presence to the avatar registry.
void plSeekPointMod::AddTarget(plSceneObject* so)
{
plMultiModifier::AddTarget(so);
// plAvatarMgr::GetInstance()->AddSeekPoint(this);
}
void plSeekPointMod::Read(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Read(stream, mgr);
// read in the name of the animation itself
int length = stream->ReadSwap32();
if(length > 0)
{
fName = TRACKED_NEW char[length + 1];
stream->Read(length, fName);
fName[length] = 0;
}
}
void plSeekPointMod::Write(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Write(stream, mgr);
int length = strlen(fName);
stream->WriteSwap32(length);
if (length > 0)
{
stream->Write(length, fName);
}
}

View File

@ -1,62 +1,62 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLSEEKPOINTMOD_INC
#define PLSEEKPOINTMOD_INC
#include "pnModifier/plMultiModifier.h"
#include "pnMessage/plMessage.h"
// PLSEEKPOINTMOD
// This modifier is something the avatar knows how to go to. (you know, seek)
// It's kind of like a magnet that, when activated, draws the avatar...
// Seen another way, it's a point with a name and a type....
class plSeekPointMod : public plMultiModifier
{
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) {return true;}
char * fName; // public because you can't change it
public:
plSeekPointMod();
plSeekPointMod(char *name);
virtual ~plSeekPointMod();
const char * GetName() { return fName; };
void SetName(char * name) { fName = name; };
CLASSNAME_REGISTER( plSeekPointMod );
GETINTERFACE_ANY( plSeekPointMod, plMultiModifier );
virtual void AddTarget(plSceneObject* so);
hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
};
#endif
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef PLSEEKPOINTMOD_INC
#define PLSEEKPOINTMOD_INC
#include "pnModifier/plMultiModifier.h"
#include "pnMessage/plMessage.h"
// PLSEEKPOINTMOD
// This modifier is something the avatar knows how to go to. (you know, seek)
// It's kind of like a magnet that, when activated, draws the avatar...
// Seen another way, it's a point with a name and a type....
class plSeekPointMod : public plMultiModifier
{
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) {return true;}
char * fName; // public because you can't change it
public:
plSeekPointMod();
plSeekPointMod(char *name);
virtual ~plSeekPointMod();
const char * GetName() { return fName; };
void SetName(char * name) { fName = name; };
CLASSNAME_REGISTER( plSeekPointMod );
GETINTERFACE_ANY( plSeekPointMod, plMultiModifier );
virtual void AddTarget(plSceneObject* so);
hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
};
#endif

View File

@ -1,374 +1,374 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plSittingModifier.h"
//other
#include "plMessage/plAvatarMsg.h"
#include "pnMessage/plNotifyMsg.h"
#include "pnMessage/plCameraMsg.h"
#include "plAvatar/plArmatureMod.h"
#include "plAvatar/plAnimStage.h"
#include "plAvatar/plAvTaskBrain.h"
#include "plAvatar/plAvBrainGeneric.h"
#include "plAvatar/plAvBrainHuman.h"
#include "plAvatar/plAvatarMgr.h"
#include "pnNetCommon/plNetApp.h"
#include "pnSceneObject/plSceneObject.h"
#include "plInputCore/plAvatarInputInterface.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// IMPLEMENTATION
//
/////////////////////////////////////////////////////////////////////////////////////////
// CTOR ------------------------------
// -----
plSittingModifier::plSittingModifier()
: fTriggeredAvatarKey(nil),
fMiscFlags(0)
{
}
// CTOR ------------------------------------------------------------------------
// -----
plSittingModifier::plSittingModifier(bool hasFront, bool hasLeft, bool hasRight)
: fTriggeredAvatarKey(nil),
fMiscFlags(0)
{
if (hasFront)
fMiscFlags |= kApproachFront;
if (hasLeft)
fMiscFlags |= kApproachLeft;
if (hasRight)
fMiscFlags |= kApproachRight;
}
// DTOR -------------------------------
// -----
plSittingModifier::~plSittingModifier()
{
}
// Read -----------------------------------------------------
// -----
void plSittingModifier::Read(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Read(stream, mgr);
fMiscFlags = stream->ReadByte();
int keyCount = stream->ReadSwap32();
for (int i = 0; i < keyCount; i++ )
fNotifyKeys.Append(mgr->ReadKey(stream));
}
// Write -----------------------------------------------------
// ------
void plSittingModifier::Write(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteByte(fMiscFlags);
stream->WriteSwap32(fNotifyKeys.GetCount());
for (int i = 0; i < fNotifyKeys.GetCount(); i++)
mgr->WriteKey(stream, fNotifyKeys[i]);
}
// ISetupNotify -------------------------------------------------------------------------
// -------------
void plSittingModifier::ISetupNotify(plNotifyMsg *notifyMsg, plNotifyMsg *originalNotify)
{
// Copy the original events to the new notify (some notify receivers need to have events)
int i;
for (i = 0; i < originalNotify->GetEventCount(); i++)
notifyMsg->AddEvent(originalNotify->GetEventRecord(i));
for (i = 0; i < fNotifyKeys.Count(); i++)
{
plKey receiver = fNotifyKeys[i];
notifyMsg->AddReceiver(receiver);
}
notifyMsg->SetSender(GetKey());
plNetClientApp::InheritNetMsgFlags(originalNotify, notifyMsg, true);
}
// MsgReceive --------------------------------------
// -----------
hsBool plSittingModifier::MsgReceive(plMessage *msg)
{
hsBool result = false;
plNotifyMsg* notifyMsg = plNotifyMsg::ConvertNoRef(msg);
if(notifyMsg)
{
if (notifyMsg->fState == 1.0)
{
// In case the previous occupant quit, lost-connection, etc.
if (fTriggeredAvatarKey && !fTriggeredAvatarKey->ObjectIsLoaded())
UnTrigger();
// only fire if we're not already triggered
if (!fTriggeredAvatarKey)
{
// a notify message with a state of 1 tells us to fire.
// we'll copy any events from this notify and use them when we send our
// own notify messages --
plKey avatarKey = notifyMsg->GetAvatarKey();
plSceneObject * obj = plSceneObject::ConvertNoRef(avatarKey->ObjectIsLoaded());
const plArmatureMod * avMod = (plArmatureMod*)obj->GetModifierByType(plArmatureMod::Index());
plAvBrainHuman *brain = (avMod ? plAvBrainHuman::ConvertNoRef(avMod->GetCurrentBrain()) : nil);
if (brain && !brain->IsRunningTask())
{
plNotifyMsg *notifyEnter = TRACKED_NEW plNotifyMsg(); // a message to send back when the brain starts
notifyEnter->fState = 1.0f; // it's an "on" event
ISetupNotify(notifyEnter, notifyMsg); // copy events and address to sender
plNotifyMsg *notifyExit = nil;
if (avatarKey == plNetClientApp::GetInstance()->GetLocalPlayerKey())
{
notifyExit = TRACKED_NEW plNotifyMsg(); // a new message to send back when the brain's done
notifyExit->fState = 0.0f; // it's an "off" event
ISetupNotify(notifyExit, notifyMsg); // copy events and address to sender
notifyExit->AddReceiver(GetKey()); // have this message come back to us as well
// A player may have joined while we're sitting. We can't update them with the exit notify at
// that point (security hole), so instead the local avatar sends the message out to everybody
// when done.
notifyExit->SetBCastFlag(plMessage::kNetStartCascade, false);
notifyExit->SetBCastFlag(plMessage::kNetPropagate, true);
notifyExit->SetBCastFlag(plMessage::kNetForce, true);
}
Trigger(avMod, notifyEnter, notifyExit);
}
}
// eat the message either way
result = true;
} else if (notifyMsg->fState == 0.0f && msg->GetSender() == GetKey()) {
// it's a notify, but off; untrigger
UnTrigger();
result = true;
}
else if (notifyMsg->GetEventCount() > 0 && notifyMsg->GetEventRecord(0)->fEventType == proEventData::kMultiStage && notifyMsg->GetAvatarKey() == plNetClientApp::GetInstance()->GetLocalPlayerKey())
{
proMultiStageEventData* mStage = (proMultiStageEventData*)notifyMsg->GetEventRecord(0);
if (mStage->fEvent == proMultiStageEventData::kEnterStage && mStage->fStage == 1)
{
plKey avatarKey = notifyMsg->GetAvatarKey();
plSceneObject * obj = plSceneObject::ConvertNoRef(avatarKey->ObjectIsLoaded());
plArmatureMod * avMod = (plArmatureMod*)obj->GetModifierByType(plArmatureMod::Index());
UInt32 flags = kBCastToClients | kUseRelevanceRegions | kForceFullSend;
avMod->DirtyPhysicalSynchState(flags);
}
}
}
return result || plSingleModifier::MsgReceive(msg);
}
// Trigger ----------------------------------------------------------------------------------------
// --------
void plSittingModifier::Trigger(const plArmatureMod *avMod, plNotifyMsg *enterNotify, plNotifyMsg *exitNotify)
{
if (avMod)
{
plKey avModKey = avMod->GetKey(); // key to the avatar MODIFIER
plKey ourKey = GetKey(); // key to this modifier
plKey seekKey = GetTarget()->GetKey(); // key to the scene object this modifier's on
// send the SEEK message
char *animName = nil; // this will be the name of our sit animation, which we
// need to know so we can seek properly.
plAvBrainGeneric *brain = IBuildSitBrain(avModKey, seekKey, &animName, enterNotify, exitNotify);
if(brain)
{
plAvSeekMsg *seekMsg = TRACKED_NEW plAvSeekMsg(ourKey, avModKey, seekKey, 0.0f, true, kAlignHandleAnimEnd, animName);
seekMsg->Send();
plAvTaskBrain *brainTask = TRACKED_NEW plAvTaskBrain(brain);
plAvTaskMsg *brainMsg = TRACKED_NEW plAvTaskMsg(ourKey, avModKey, brainTask);
brainMsg->Send();
if (avModKey == plAvatarMgr::GetInstance()->GetLocalAvatarKey())
{
plCameraMsg* pCam = TRACKED_NEW plCameraMsg;
pCam->SetBCastFlag(plMessage::kBCastByExactType);
pCam->SetCmd(plCameraMsg::kResetPanning);
pCam->Send();
plCameraMsg* pCam2 = TRACKED_NEW plCameraMsg;
pCam2->SetBCastFlag(plMessage::kBCastByExactType);
pCam2->SetCmd(plCameraMsg::kPythonSetFirstPersonOverrideEnable);
pCam2->SetActivated(false);
pCam2->Send();
plCameraMsg* pCam3 = TRACKED_NEW plCameraMsg;
pCam3->SetBCastFlag(plMessage::kBCastByExactType);
pCam3->SetCmd(plCameraMsg::kPythonUndoFirstPerson);
pCam3->Send();
}
fTriggeredAvatarKey = avModKey;
if (fMiscFlags & kDisableForward)
{
if (fTriggeredAvatarKey == plAvatarMgr::GetInstance()->GetLocalAvatarKey())
plAvatarInputInterface::GetInstance()->EnableControl(false, B_CONTROL_MOVE_FORWARD);
}
}
}
}
// IIsClosestAnim -------------------------------------------------------------------
// ---------------
bool IIsClosestAnim(const char *animName, hsMatrix44 &sitGoal, hsScalar &closestDist,
hsPoint3 curPosition, const plArmatureMod *avatar)
{
plAGAnim *anim = avatar->FindCustomAnim(animName);
if(anim)
{
hsMatrix44 animEndToStart;
// The sit target is the position we want to be at the END of the sit animation.
// We have several animations to choose from, each starting from a different
// position.
// This will look at one of those animations and figure out how far we are from
// its starting position.
// The first step is to get the transform from the end to the beginning of the
// animation. That's what this next line is doing. It's a bit unintuitive
// until you look at the parameter definitions.
GetStartToEndTransform(anim, nil, &animEndToStart, "Handle");
hsMatrix44 candidateGoal = sitGoal * animEndToStart;
hsPoint3 distP = candidateGoal.GetTranslate() - curPosition;
hsVector3 distV(distP.fX, distP.fY, distP.fZ);
hsScalar dist = distP.Magnitude();
if(closestDist == 0.0 || dist < closestDist)
{
closestDist = dist;
return true;
}
} else {
char buffy[256];
sprintf(buffy, "Missing sit animation: %s", animName);
hsAssert(false, buffy);
}
return false;
}
// IBuildSitBrain ---------------------------------------------------------------------
// ----------------
plAvBrainGeneric *plSittingModifier::IBuildSitBrain(plKey avModKey, plKey seekKey,
char **pAnimName, plNotifyMsg *enterNotify, plNotifyMsg *exitNotify)
{
plArmatureMod *avatar = plArmatureMod::ConvertNoRef(avModKey->ObjectIsLoaded());
plSceneObject *seekObj = plSceneObject::ConvertNoRef(seekKey->ObjectIsLoaded());
hsMatrix44 animEndToStart;
hsMatrix44 sitGoal = seekObj->GetLocalToWorld();
hsMatrix44 candidateGoal;
hsScalar closestDist = 0.0f;
UInt8 closestApproach = 0;
hsPoint3 curPosition = avatar->GetTarget(0)->GetLocalToWorld().GetTranslate();
char * sitAnimName = nil;
char * standAnimName = "StandUpFront"; // always prefer to stand facing front
bool frontClear = fMiscFlags & kApproachFront;
plAvBrainGeneric *brain = nil;
if(avatar)
{
if(fMiscFlags & kApproachLeft && IIsClosestAnim("SitLeft", sitGoal, closestDist, curPosition, avatar))
{
closestApproach = kApproachLeft;
sitAnimName = "SitLeft";
if(!frontClear)
standAnimName = "StandUpLeft";
}
if(fMiscFlags & kApproachRight && IIsClosestAnim("SitRight", sitGoal, closestDist, curPosition, avatar))
{
closestApproach = kApproachRight;
sitAnimName = "SitRight";
if(!frontClear)
standAnimName = "StandUpRight";
}
if(frontClear && IIsClosestAnim("SitFront", sitGoal, closestDist, curPosition, avatar))
{
sitAnimName = "SitFront";
standAnimName = "StandUpFront";
closestApproach = kApproachFront;
}
if(sitAnimName)
{
UInt32 exitFlags = plAvBrainGeneric::kExitNormal; // SOME stages can be interrupted, but not the brain itself
brain = TRACKED_NEW plAvBrainGeneric(nil, enterNotify, exitNotify, nil, exitFlags, plAvBrainGeneric::kDefaultFadeIn,
plAvBrainGeneric::kDefaultFadeOut, plAvBrainGeneric::kMoveRelative);
plAnimStage *sitStage = TRACKED_NEW plAnimStage(sitAnimName, 0, plAnimStage::kForwardAuto, plAnimStage::kBackNone,
plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone, 0);
plAnimStage *idleStage = TRACKED_NEW plAnimStage("SitIdle", plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone,
plAnimStage::kAdvanceOnMove, plAnimStage::kRegressNone, -1);
plAnimStage *standStage = TRACKED_NEW plAnimStage(standAnimName, 0, plAnimStage::kForwardAuto, plAnimStage::kBackNone,
plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone, 0);
brain->AddStage(sitStage);
brain->AddStage(idleStage);
brain->AddStage(standStage);
*pAnimName = sitAnimName;
brain->SetType(plAvBrainGeneric::kSit);
brain->SetRecipient(GetKey());
}
}
return brain;
}
// UnTrigger ----------------------
// ----------
void plSittingModifier::UnTrigger()
{
if (fTriggeredAvatarKey == plAvatarMgr::GetInstance()->GetLocalAvatarKey())
{
plCameraMsg* pCam = TRACKED_NEW plCameraMsg;
pCam->SetBCastFlag(plMessage::kBCastByExactType);
pCam->SetCmd(plCameraMsg::kResetPanning);
pCam->Send();
plCameraMsg* pCam2 = TRACKED_NEW plCameraMsg;
pCam2->SetBCastFlag(plMessage::kBCastByExactType);
pCam2->SetCmd(plCameraMsg::kPythonSetFirstPersonOverrideEnable);
pCam2->SetActivated(true);
pCam2->Send();
// The flag means we disabled it, so re-enable on UnTrigger.
if (fMiscFlags & kDisableForward)
plAvatarInputInterface::GetInstance()->EnableControl(true, B_CONTROL_MOVE_FORWARD);
}
fTriggeredAvatarKey = nil;
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// singular
#include "plSittingModifier.h"
//other
#include "plMessage/plAvatarMsg.h"
#include "pnMessage/plNotifyMsg.h"
#include "pnMessage/plCameraMsg.h"
#include "plAvatar/plArmatureMod.h"
#include "plAvatar/plAnimStage.h"
#include "plAvatar/plAvTaskBrain.h"
#include "plAvatar/plAvBrainGeneric.h"
#include "plAvatar/plAvBrainHuman.h"
#include "plAvatar/plAvatarMgr.h"
#include "pnNetCommon/plNetApp.h"
#include "pnSceneObject/plSceneObject.h"
#include "plInputCore/plAvatarInputInterface.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// IMPLEMENTATION
//
/////////////////////////////////////////////////////////////////////////////////////////
// CTOR ------------------------------
// -----
plSittingModifier::plSittingModifier()
: fTriggeredAvatarKey(nil),
fMiscFlags(0)
{
}
// CTOR ------------------------------------------------------------------------
// -----
plSittingModifier::plSittingModifier(bool hasFront, bool hasLeft, bool hasRight)
: fTriggeredAvatarKey(nil),
fMiscFlags(0)
{
if (hasFront)
fMiscFlags |= kApproachFront;
if (hasLeft)
fMiscFlags |= kApproachLeft;
if (hasRight)
fMiscFlags |= kApproachRight;
}
// DTOR -------------------------------
// -----
plSittingModifier::~plSittingModifier()
{
}
// Read -----------------------------------------------------
// -----
void plSittingModifier::Read(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Read(stream, mgr);
fMiscFlags = stream->ReadByte();
int keyCount = stream->ReadSwap32();
for (int i = 0; i < keyCount; i++ )
fNotifyKeys.Append(mgr->ReadKey(stream));
}
// Write -----------------------------------------------------
// ------
void plSittingModifier::Write(hsStream *stream, hsResMgr *mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteByte(fMiscFlags);
stream->WriteSwap32(fNotifyKeys.GetCount());
for (int i = 0; i < fNotifyKeys.GetCount(); i++)
mgr->WriteKey(stream, fNotifyKeys[i]);
}
// ISetupNotify -------------------------------------------------------------------------
// -------------
void plSittingModifier::ISetupNotify(plNotifyMsg *notifyMsg, plNotifyMsg *originalNotify)
{
// Copy the original events to the new notify (some notify receivers need to have events)
int i;
for (i = 0; i < originalNotify->GetEventCount(); i++)
notifyMsg->AddEvent(originalNotify->GetEventRecord(i));
for (i = 0; i < fNotifyKeys.Count(); i++)
{
plKey receiver = fNotifyKeys[i];
notifyMsg->AddReceiver(receiver);
}
notifyMsg->SetSender(GetKey());
plNetClientApp::InheritNetMsgFlags(originalNotify, notifyMsg, true);
}
// MsgReceive --------------------------------------
// -----------
hsBool plSittingModifier::MsgReceive(plMessage *msg)
{
hsBool result = false;
plNotifyMsg* notifyMsg = plNotifyMsg::ConvertNoRef(msg);
if(notifyMsg)
{
if (notifyMsg->fState == 1.0)
{
// In case the previous occupant quit, lost-connection, etc.
if (fTriggeredAvatarKey && !fTriggeredAvatarKey->ObjectIsLoaded())
UnTrigger();
// only fire if we're not already triggered
if (!fTriggeredAvatarKey)
{
// a notify message with a state of 1 tells us to fire.
// we'll copy any events from this notify and use them when we send our
// own notify messages --
plKey avatarKey = notifyMsg->GetAvatarKey();
plSceneObject * obj = plSceneObject::ConvertNoRef(avatarKey->ObjectIsLoaded());
const plArmatureMod * avMod = (plArmatureMod*)obj->GetModifierByType(plArmatureMod::Index());
plAvBrainHuman *brain = (avMod ? plAvBrainHuman::ConvertNoRef(avMod->GetCurrentBrain()) : nil);
if (brain && !brain->IsRunningTask())
{
plNotifyMsg *notifyEnter = TRACKED_NEW plNotifyMsg(); // a message to send back when the brain starts
notifyEnter->fState = 1.0f; // it's an "on" event
ISetupNotify(notifyEnter, notifyMsg); // copy events and address to sender
plNotifyMsg *notifyExit = nil;
if (avatarKey == plNetClientApp::GetInstance()->GetLocalPlayerKey())
{
notifyExit = TRACKED_NEW plNotifyMsg(); // a new message to send back when the brain's done
notifyExit->fState = 0.0f; // it's an "off" event
ISetupNotify(notifyExit, notifyMsg); // copy events and address to sender
notifyExit->AddReceiver(GetKey()); // have this message come back to us as well
// A player may have joined while we're sitting. We can't update them with the exit notify at
// that point (security hole), so instead the local avatar sends the message out to everybody
// when done.
notifyExit->SetBCastFlag(plMessage::kNetStartCascade, false);
notifyExit->SetBCastFlag(plMessage::kNetPropagate, true);
notifyExit->SetBCastFlag(plMessage::kNetForce, true);
}
Trigger(avMod, notifyEnter, notifyExit);
}
}
// eat the message either way
result = true;
} else if (notifyMsg->fState == 0.0f && msg->GetSender() == GetKey()) {
// it's a notify, but off; untrigger
UnTrigger();
result = true;
}
else if (notifyMsg->GetEventCount() > 0 && notifyMsg->GetEventRecord(0)->fEventType == proEventData::kMultiStage && notifyMsg->GetAvatarKey() == plNetClientApp::GetInstance()->GetLocalPlayerKey())
{
proMultiStageEventData* mStage = (proMultiStageEventData*)notifyMsg->GetEventRecord(0);
if (mStage->fEvent == proMultiStageEventData::kEnterStage && mStage->fStage == 1)
{
plKey avatarKey = notifyMsg->GetAvatarKey();
plSceneObject * obj = plSceneObject::ConvertNoRef(avatarKey->ObjectIsLoaded());
plArmatureMod * avMod = (plArmatureMod*)obj->GetModifierByType(plArmatureMod::Index());
UInt32 flags = kBCastToClients | kUseRelevanceRegions | kForceFullSend;
avMod->DirtyPhysicalSynchState(flags);
}
}
}
return result || plSingleModifier::MsgReceive(msg);
}
// Trigger ----------------------------------------------------------------------------------------
// --------
void plSittingModifier::Trigger(const plArmatureMod *avMod, plNotifyMsg *enterNotify, plNotifyMsg *exitNotify)
{
if (avMod)
{
plKey avModKey = avMod->GetKey(); // key to the avatar MODIFIER
plKey ourKey = GetKey(); // key to this modifier
plKey seekKey = GetTarget()->GetKey(); // key to the scene object this modifier's on
// send the SEEK message
char *animName = nil; // this will be the name of our sit animation, which we
// need to know so we can seek properly.
plAvBrainGeneric *brain = IBuildSitBrain(avModKey, seekKey, &animName, enterNotify, exitNotify);
if(brain)
{
plAvSeekMsg *seekMsg = TRACKED_NEW plAvSeekMsg(ourKey, avModKey, seekKey, 0.0f, true, kAlignHandleAnimEnd, animName);
seekMsg->Send();
plAvTaskBrain *brainTask = TRACKED_NEW plAvTaskBrain(brain);
plAvTaskMsg *brainMsg = TRACKED_NEW plAvTaskMsg(ourKey, avModKey, brainTask);
brainMsg->Send();
if (avModKey == plAvatarMgr::GetInstance()->GetLocalAvatarKey())
{
plCameraMsg* pCam = TRACKED_NEW plCameraMsg;
pCam->SetBCastFlag(plMessage::kBCastByExactType);
pCam->SetCmd(plCameraMsg::kResetPanning);
pCam->Send();
plCameraMsg* pCam2 = TRACKED_NEW plCameraMsg;
pCam2->SetBCastFlag(plMessage::kBCastByExactType);
pCam2->SetCmd(plCameraMsg::kPythonSetFirstPersonOverrideEnable);
pCam2->SetActivated(false);
pCam2->Send();
plCameraMsg* pCam3 = TRACKED_NEW plCameraMsg;
pCam3->SetBCastFlag(plMessage::kBCastByExactType);
pCam3->SetCmd(plCameraMsg::kPythonUndoFirstPerson);
pCam3->Send();
}
fTriggeredAvatarKey = avModKey;
if (fMiscFlags & kDisableForward)
{
if (fTriggeredAvatarKey == plAvatarMgr::GetInstance()->GetLocalAvatarKey())
plAvatarInputInterface::GetInstance()->EnableControl(false, B_CONTROL_MOVE_FORWARD);
}
}
}
}
// IIsClosestAnim -------------------------------------------------------------------
// ---------------
bool IIsClosestAnim(const char *animName, hsMatrix44 &sitGoal, hsScalar &closestDist,
hsPoint3 curPosition, const plArmatureMod *avatar)
{
plAGAnim *anim = avatar->FindCustomAnim(animName);
if(anim)
{
hsMatrix44 animEndToStart;
// The sit target is the position we want to be at the END of the sit animation.
// We have several animations to choose from, each starting from a different
// position.
// This will look at one of those animations and figure out how far we are from
// its starting position.
// The first step is to get the transform from the end to the beginning of the
// animation. That's what this next line is doing. It's a bit unintuitive
// until you look at the parameter definitions.
GetStartToEndTransform(anim, nil, &animEndToStart, "Handle");
hsMatrix44 candidateGoal = sitGoal * animEndToStart;
hsPoint3 distP = candidateGoal.GetTranslate() - curPosition;
hsVector3 distV(distP.fX, distP.fY, distP.fZ);
hsScalar dist = distP.Magnitude();
if(closestDist == 0.0 || dist < closestDist)
{
closestDist = dist;
return true;
}
} else {
char buffy[256];
sprintf(buffy, "Missing sit animation: %s", animName);
hsAssert(false, buffy);
}
return false;
}
// IBuildSitBrain ---------------------------------------------------------------------
// ----------------
plAvBrainGeneric *plSittingModifier::IBuildSitBrain(plKey avModKey, plKey seekKey,
char **pAnimName, plNotifyMsg *enterNotify, plNotifyMsg *exitNotify)
{
plArmatureMod *avatar = plArmatureMod::ConvertNoRef(avModKey->ObjectIsLoaded());
plSceneObject *seekObj = plSceneObject::ConvertNoRef(seekKey->ObjectIsLoaded());
hsMatrix44 animEndToStart;
hsMatrix44 sitGoal = seekObj->GetLocalToWorld();
hsMatrix44 candidateGoal;
hsScalar closestDist = 0.0f;
UInt8 closestApproach = 0;
hsPoint3 curPosition = avatar->GetTarget(0)->GetLocalToWorld().GetTranslate();
char * sitAnimName = nil;
char * standAnimName = "StandUpFront"; // always prefer to stand facing front
bool frontClear = fMiscFlags & kApproachFront;
plAvBrainGeneric *brain = nil;
if(avatar)
{
if(fMiscFlags & kApproachLeft && IIsClosestAnim("SitLeft", sitGoal, closestDist, curPosition, avatar))
{
closestApproach = kApproachLeft;
sitAnimName = "SitLeft";
if(!frontClear)
standAnimName = "StandUpLeft";
}
if(fMiscFlags & kApproachRight && IIsClosestAnim("SitRight", sitGoal, closestDist, curPosition, avatar))
{
closestApproach = kApproachRight;
sitAnimName = "SitRight";
if(!frontClear)
standAnimName = "StandUpRight";
}
if(frontClear && IIsClosestAnim("SitFront", sitGoal, closestDist, curPosition, avatar))
{
sitAnimName = "SitFront";
standAnimName = "StandUpFront";
closestApproach = kApproachFront;
}
if(sitAnimName)
{
UInt32 exitFlags = plAvBrainGeneric::kExitNormal; // SOME stages can be interrupted, but not the brain itself
brain = TRACKED_NEW plAvBrainGeneric(nil, enterNotify, exitNotify, nil, exitFlags, plAvBrainGeneric::kDefaultFadeIn,
plAvBrainGeneric::kDefaultFadeOut, plAvBrainGeneric::kMoveRelative);
plAnimStage *sitStage = TRACKED_NEW plAnimStage(sitAnimName, 0, plAnimStage::kForwardAuto, plAnimStage::kBackNone,
plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone, 0);
plAnimStage *idleStage = TRACKED_NEW plAnimStage("SitIdle", plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone,
plAnimStage::kAdvanceOnMove, plAnimStage::kRegressNone, -1);
plAnimStage *standStage = TRACKED_NEW plAnimStage(standAnimName, 0, plAnimStage::kForwardAuto, plAnimStage::kBackNone,
plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone, 0);
brain->AddStage(sitStage);
brain->AddStage(idleStage);
brain->AddStage(standStage);
*pAnimName = sitAnimName;
brain->SetType(plAvBrainGeneric::kSit);
brain->SetRecipient(GetKey());
}
}
return brain;
}
// UnTrigger ----------------------
// ----------
void plSittingModifier::UnTrigger()
{
if (fTriggeredAvatarKey == plAvatarMgr::GetInstance()->GetLocalAvatarKey())
{
plCameraMsg* pCam = TRACKED_NEW plCameraMsg;
pCam->SetBCastFlag(plMessage::kBCastByExactType);
pCam->SetCmd(plCameraMsg::kResetPanning);
pCam->Send();
plCameraMsg* pCam2 = TRACKED_NEW plCameraMsg;
pCam2->SetBCastFlag(plMessage::kBCastByExactType);
pCam2->SetCmd(plCameraMsg::kPythonSetFirstPersonOverrideEnable);
pCam2->SetActivated(true);
pCam2->Send();
// The flag means we disabled it, so re-enable on UnTrigger.
if (fMiscFlags & kDisableForward)
plAvatarInputInterface::GetInstance()->EnableControl(true, B_CONTROL_MOVE_FORWARD);
}
fTriggeredAvatarKey = nil;
}

View File

@ -1,112 +1,112 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plSittingModifier_inc
#define plSittingModifier_inc
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "pnModifier/plSingleModifier.h" // base class
#include "pnKeyedobject/plKey.h" // for the notification keys
#include "hsTemplates.h" // for the array they're kept in
/////////////////////////////////////////////////////////////////////////////////////////
//
// DECLARATIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plNotifyMsg;
class plAvBrainGeneric;
class plArmatureMod;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plSittingModifier : public plSingleModifier
{
public:
enum
{
kApproachFront = 0x01,
kApproachLeft = 0x02,
kApproachRight = 0x04,
kApproachRear = 0x08,
kApproachMask = kApproachFront | kApproachLeft | kApproachRight | kApproachRear,
kDisableForward = 0x10,
};
UInt8 fMiscFlags;
plSittingModifier();
plSittingModifier(bool hasFront, bool hasLeft, bool hasRight);
virtual ~plSittingModifier();
CLASSNAME_REGISTER( plSittingModifier );
GETINTERFACE_ANY( plSittingModifier, plSingleModifier );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage *msg);
void AddNotifyKey(plKey key) { fNotifyKeys.Append(key); }
virtual void Trigger(const plArmatureMod *avMod, plNotifyMsg *enterNotify, plNotifyMsg *exitNotify);
virtual void UnTrigger();
protected:
/** We've been triggered: go ahead and send the seek and brain tasks to the
triggering avatar. */
hsBool IEmitCommand(plKey playerKey, plMessage *enterCallback, plMessage *exitCallback);
/** Set up generic notification messages which were passed in by the responder /
max authoring stuff. */
void ISetupNotify(plNotifyMsg *notifyMsg, plNotifyMsg *originalNotify);
/** Figure out which approach we should use to the sit target, and add the relevant
stages to the brain. */
plAvBrainGeneric * IBuildSitBrain(plKey avModKey, plKey seekKey,char **pAnimName, plNotifyMsg *enterNotify, plNotifyMsg *exitNotify);
/** Unused. */
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
/** An array of keys to objects that are interested in receiving our sit messages. */
hsTArray<plKey> fNotifyKeys;
/** The chair in question is in use. It will untrigger when the avatar leaves it. */
//hsBool fTriggered;
plKey fTriggeredAvatarKey;
};
#endif plSittingModifier_inc
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plSittingModifier_inc
#define plSittingModifier_inc
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "pnModifier/plSingleModifier.h" // base class
#include "pnKeyedobject/plKey.h" // for the notification keys
#include "hsTemplates.h" // for the array they're kept in
/////////////////////////////////////////////////////////////////////////////////////////
//
// DECLARATIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plNotifyMsg;
class plAvBrainGeneric;
class plArmatureMod;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plSittingModifier : public plSingleModifier
{
public:
enum
{
kApproachFront = 0x01,
kApproachLeft = 0x02,
kApproachRight = 0x04,
kApproachRear = 0x08,
kApproachMask = kApproachFront | kApproachLeft | kApproachRight | kApproachRear,
kDisableForward = 0x10,
};
UInt8 fMiscFlags;
plSittingModifier();
plSittingModifier(bool hasFront, bool hasLeft, bool hasRight);
virtual ~plSittingModifier();
CLASSNAME_REGISTER( plSittingModifier );
GETINTERFACE_ANY( plSittingModifier, plSingleModifier );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage *msg);
void AddNotifyKey(plKey key) { fNotifyKeys.Append(key); }
virtual void Trigger(const plArmatureMod *avMod, plNotifyMsg *enterNotify, plNotifyMsg *exitNotify);
virtual void UnTrigger();
protected:
/** We've been triggered: go ahead and send the seek and brain tasks to the
triggering avatar. */
hsBool IEmitCommand(plKey playerKey, plMessage *enterCallback, plMessage *exitCallback);
/** Set up generic notification messages which were passed in by the responder /
max authoring stuff. */
void ISetupNotify(plNotifyMsg *notifyMsg, plNotifyMsg *originalNotify);
/** Figure out which approach we should use to the sit target, and add the relevant
stages to the brain. */
plAvBrainGeneric * IBuildSitBrain(plKey avModKey, plKey seekKey,char **pAnimName, plNotifyMsg *enterNotify, plNotifyMsg *exitNotify);
/** Unused. */
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
/** An array of keys to objects that are interested in receiving our sit messages. */
hsTArray<plKey> fNotifyKeys;
/** The chair in question is in use. It will untrigger when the avatar leaves it. */
//hsBool fTriggered;
plKey fTriggeredAvatarKey;
};
#endif plSittingModifier_inc

Some files were not shown because too many files have changed in this diff Show More