Add all new AFX files

This commit is contained in:
Marc Chapman 2017-07-26 09:35:44 +01:00
parent f2b86b7df3
commit ace877b409
218 changed files with 54970 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,189 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// afxCamera implements a modified camera for demonstrating a third person camera style
// which is more common to RPG games than the standard FPS style camera. For the most part,
// it is a hybrid of the standard TGE camera and the third person mode of the Advanced Camera
// resource, authored by Thomas "Man of Ice" Lund. This camera implements the bare minimum
// required for demonstrating an RPG style camera and leaves tons of room for improvement.
// It should be replaced with a better camera if possible.
//
// Advanced Camera Resource by Thomas "Man of Ice" Lund:
// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=5471
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_CAMERA_H_
#define _AFX_CAMERA_H_
#ifndef _SHAPEBASE_H_
#include "game/shapeBase.h"
#endif
//----------------------------------------------------------------------------
struct afxCameraData: public ShapeBaseData {
typedef ShapeBaseData Parent;
static U32 sCameraCollisionMask;
//
DECLARE_CONOBJECT(afxCameraData);
DECLARE_CATEGORY("AFX");
static void initPersistFields();
virtual void packData(BitStream* stream);
virtual void unpackData(BitStream* stream);
};
//----------------------------------------------------------------------------
// Implements a basic camera object.
class afxCamera: public ShapeBase
{
typedef ShapeBase Parent;
enum MaskBits {
MoveMask = Parent::NextFreeMask,
SubjectMask = Parent::NextFreeMask << 1,
NextFreeMask = Parent::NextFreeMask << 2
};
struct StateDelta {
Point3F pos;
Point3F rot;
VectorF posVec;
VectorF rotVec;
};
enum
{
ThirdPersonMode = 1,
FlyMode = 2,
OrbitObjectMode = 3,
OrbitPointMode = 4,
CameraFirstMode = 0,
CameraLastMode = 4
};
private:
int mode;
Point3F mRot;
StateDelta delta;
SimObjectPtr<GameBase> mOrbitObject;
F32 mMinOrbitDist;
F32 mMaxOrbitDist;
F32 mCurOrbitDist;
Point3F mPosition;
bool mObservingClientObject;
SceneObject* cam_subject;
Point3F cam_offset;
Point3F coi_offset;
F32 cam_distance;
F32 cam_angle;
bool cam_dirty;
bool flymode_saved;
Point3F flymode_saved_pos;
S8 third_person_snap_c;
S8 third_person_snap_s;
void set_cam_pos(const Point3F& pos, const Point3F& viewRot);
void cam_update(F32 dt, bool on_server);
public:
/*C*/ afxCamera();
/*D*/ ~afxCamera();
Point3F& getPosition();
void setFlyMode();
void setOrbitMode(GameBase* obj, Point3F& pos, AngAxisF& rot, F32 minDist, F32 maxDist, F32 curDist, bool ownClientObject);
void validateEyePoint(F32 pos, MatrixF *mat);
GameBase* getOrbitObject() { return(mOrbitObject); }
bool isObservingClientObject() { return(mObservingClientObject); }
void snapToPosition(const Point3F& pos);
void setCameraSubject(SceneObject* subject);
void setThirdPersonOffset(const Point3F& offset);
void setThirdPersonOffset(const Point3F& offset, const Point3F& coi_offset);
const Point3F& getThirdPersonOffset() const { return cam_offset; }
const Point3F& getThirdPersonCOIOffset() const { return coi_offset; }
void setThirdPersonDistance(F32 distance);
F32 getThirdPersonDistance();
void setThirdPersonAngle(F32 angle);
F32 getThirdPersonAngle();
void setThirdPersonMode();
void setThirdPersonSnap();
void setThirdPersonSnapClient();
const char* getMode();
bool isCamera() const { return true; }
DECLARE_CONOBJECT(afxCamera);
DECLARE_CATEGORY("AFX");
private: // 3POV SECTION
U32 blockers_mask_3pov;
void cam_update_3pov(F32 dt, bool on_server);
bool avoid_blocked_view(const Point3F& start, const Point3F& end, Point3F& newpos);
bool test_blocked_line(const Point3F& start, const Point3F& end);
public: // STD OVERRIDES SECTION
virtual bool onAdd();
virtual void onRemove();
virtual void onDeleteNotify(SimObject *obj);
virtual void advanceTime(F32 dt);
virtual void processTick(const Move* move);
virtual void interpolateTick(F32 delta);
virtual void writePacketData(GameConnection *conn, BitStream *stream);
virtual void readPacketData(GameConnection *conn, BitStream *stream);
virtual U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
virtual void unpackUpdate(NetConnection *conn, BitStream *stream);
virtual void onCameraScopeQuery(NetConnection* cr, CameraScopeQuery*);
virtual void getCameraTransform(F32* pos,MatrixF* mat);
virtual void setTransform(const MatrixF& mat);
virtual void onEditorEnable();
virtual void onEditorDisable();
virtual F32 getCameraFov();
virtual F32 getDefaultCameraFov();
virtual bool isValidCameraFov(F32 fov);
virtual void setCameraFov(F32 fov);
virtual F32 getDamageFlash() const;
virtual F32 getWhiteOut() const;
virtual void setControllingClient( GameConnection* connection );
};
#endif // _AFX_CAMERA_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,222 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_CHOREOGRAPHER_H_
#define _AFX_CHOREOGRAPHER_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afxEffectDefs.h"
#include "afxEffectWrapper.h"
#include "afxMagicMissile.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxChoreographerData
class afxChoreographerData : public GameBaseData, public afxEffectDefs
{
typedef GameBaseData Parent;
public:
bool exec_on_new_clients;
U8 echo_packet_usage;
StringTableEntry client_script_file;
StringTableEntry client_init_func;
public:
/*C*/ afxChoreographerData();
/*C*/ afxChoreographerData(const afxChoreographerData&, bool = false);
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
bool preload(bool server, String &errorStr);
static void initPersistFields();
DECLARE_CONOBJECT(afxChoreographerData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxChoreographer
class afxConstraint;
class afxConstraintMgr;
class afxEffectWrapper;
class afxParticlePool;
class afxParticlePoolData;
class SimSet;
class afxForceSetMgr;
class afxChoreographer : public GameBase, public afxEffectDefs, public afxMagicMissileCallback
{
typedef GameBase Parent;
public:
enum MaskBits
{
TriggerMask = Parent::NextFreeMask << 0,
RemapConstraintMask = Parent::NextFreeMask << 1, // CONSTRAINT REMAPPING
NextFreeMask = Parent::NextFreeMask << 2
};
enum
{
USER_EXEC_CONDS_MASK = 0x00ffffff
};
protected:
struct dynConstraintDef
{
StringTableEntry cons_name;
U8 cons_type;
union
{
SceneObject* object;
Point3F* point;
MatrixF* xfm;
U16 scope_id;
} cons_obj;
};
private:
afxChoreographerData* datablock;
SimSet named_effects;
SimObject* exeblock;
afxForceSetMgr* force_set_mgr;
Vector<afxParticlePool*> particle_pools;
Vector<dynConstraintDef> dc_defs_a;
Vector<dynConstraintDef> dc_defs_b;
GameBase* proc_after_obj;
U32 trigger_mask;
protected:
Vector<dynConstraintDef>* dyn_cons_defs;
Vector<dynConstraintDef>* dyn_cons_defs2;
afxConstraintMgr* constraint_mgr;
U32 choreographer_id;
U8 ranking;
U8 lod;
U32 exec_conds_mask;
SimObject* extra;
Vector<NetConnection*> explicit_clients;
bool started_with_newop;
bool postpone_activation;
virtual void pack_constraint_info(NetConnection* conn, BitStream* stream);
virtual void unpack_constraint_info(NetConnection* conn, BitStream* stream);
void setup_dynamic_constraints();
void check_packet_usage(NetConnection*, BitStream*, S32 mark_stream_pos, const char* msg_tag);
SceneObject* get_camera(Point3F* cam_pos=0) const;
public:
/*C*/ afxChoreographer();
virtual ~afxChoreographer();
static void initPersistFields();
virtual bool onAdd();
virtual void onRemove();
virtual void onDeleteNotify(SimObject*);
virtual bool onNewDataBlock(GameBaseData* dptr, bool reload);
virtual U32 packUpdate(NetConnection*, U32, BitStream*);
virtual void unpackUpdate(NetConnection*, BitStream*);
virtual void sync_with_clients() { }
afxConstraintMgr* getConstraintMgr() { return constraint_mgr; }
afxForceSetMgr* getForceSetMgr() { return force_set_mgr; }
afxParticlePool* findParticlePool(afxParticlePoolData* key_block, U32 key_index);
void registerParticlePool(afxParticlePool*);
void unregisterParticlePool(afxParticlePool*);
void setRanking(U8 value) { ranking = value; }
U8 getRanking() const { return ranking; }
bool testRanking(U8 low, U8 high) { return (ranking <= high && ranking >= low); }
void setLevelOfDetail(U8 value) { lod = value; }
U8 getLevelOfDetail() const { return lod; }
bool testLevelOfDetail(U8 low, U8 high) { return (lod <= high && lod >= low); }
void setExecConditions(U32 mask) { exec_conds_mask = mask; }
U32 getExecConditions() const { return exec_conds_mask; }
virtual void executeScriptEvent(const char* method, afxConstraint*,
const MatrixF& xfm, const char* data);
virtual void inflictDamage(const char * label, const char* flavor, SimObjectId target,
F32 amt, U8 count, F32 ad_amt, F32 rad, Point3F pos, F32 imp) { }
void addObjectConstraint(SceneObject*, const char* cons_name);
void addObjectConstraint(U16 scope_id, const char* cons_name, bool is_shape);
void addPointConstraint(Point3F&, const char* cons_name);
void addTransformConstraint(MatrixF&, const char* cons_name);
bool addConstraint(const char* source_spec, const char* cons_name);
void addNamedEffect(afxEffectWrapper*);
void removeNamedEffect(afxEffectWrapper*);
afxEffectWrapper* findNamedEffect(StringTableEntry);
void clearChoreographerId() { choreographer_id = 0; }
U32 getChoreographerId() { return choreographer_id; }
void setGhostConstraintObject(SceneObject*, StringTableEntry cons_name);
void setExtra(SimObject* extra) { this->extra = extra; }
void addExplicitClient(NetConnection* conn);
void removeExplicitClient(NetConnection* conn);
U32 getExplicitClientCount() { return explicit_clients.size(); }
void restoreScopedObject(SceneObject* obj);
virtual void restoreObject(SceneObject*) { };
void postProcessAfterObject(GameBase* obj);
U32 getTriggerMask() const { return trigger_mask; }
void setTriggerMask(U32 trigger_mask);
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// missile watcher callbacks
public:
virtual void impactNotify(const Point3F& p, const Point3F& n, SceneObject*) { }
DECLARE_CONOBJECT(afxChoreographer);
DECLARE_CATEGORY("AFX");
// CONSTRAINT REMAPPING <<
protected:
Vector<dynConstraintDef*> remapped_cons_defs;
bool remapped_cons_sent;
virtual bool remap_builtin_constraint(SceneObject*, const char* cons_name) { return false; }
dynConstraintDef* find_cons_def_by_name(const char* cons_name);
public:
void remapObjectConstraint(SceneObject*, const char* cons_name);
void remapObjectConstraint(U16 scope_id, const char* cons_name, bool is_shape);
void remapPointConstraint(Point3F&, const char* cons_name);
void remapTransformConstraint(MatrixF&, const char* cons_name);
bool remapConstraint(const char* source_spec, const char* cons_name);
// CONSTRAINT REMAPPING >>
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_CHOREOGRAPHER_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,677 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_CONSTRAINT_H_
#define _AFX_CONSTRAINT_H_
#include "core/util/tVector.h"
#include "T3D/shapeBase.h"
#include "afxEffectDefs.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxConstraintDef
class afxEffectBaseData;
struct afxConstraintDef : public afxEffectDefs
{
enum DefType
{
CONS_UNDEFINED,
CONS_PREDEFINED,
CONS_SCENE,
CONS_EFFECT,
CONS_GHOST
};
DefType def_type;
StringTableEntry cons_src_name;
StringTableEntry cons_node_name;
F32 history_time;
U8 sample_rate;
bool runs_on_server;
bool runs_on_client;
bool pos_at_box_center;
bool treat_as_camera;
/*C*/ afxConstraintDef();
bool isDefined();
bool isArbitraryObject();
void reset();
bool parseSpec(const char* spec, bool runs_on_server, bool runs_on_client);
static void gather_cons_defs(Vector<afxConstraintDef>& defs, Vector<afxEffectBaseData*>& fx);
static StringTableEntry SCENE_CONS_KEY;
static StringTableEntry EFFECT_CONS_KEY;
static StringTableEntry GHOST_CONS_KEY;
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxConstraint
// Abstract base-class for a simple constraint mechanism used to constrain
// special effects to spell related objects such as the spellcaster, target,
// projectile, or impact location.
//
// note -- the direction vectors don't really fit... should probably consider separate
// constraint types for position, orientation, and possibly a look-at constraint.
//
class SceneObject;
class afxConstraintMgr;
class afxConstraint : public SimObject, public afxEffectDefs
{
friend class afxConstraintMgr;
typedef SimObject Parent;
protected:
afxConstraintMgr* mgr;
afxConstraintDef cons_def;
bool is_defined;
bool is_valid;
Point3F last_pos;
MatrixF last_xfm;
F32 history_time;
bool is_alive;
bool gone_missing;
U32 change_code;
public:
/*C*/ afxConstraint(afxConstraintMgr*);
virtual ~afxConstraint();
virtual bool getPosition(Point3F& pos, F32 hist=0.0f)
{ pos = last_pos; return is_valid; }
virtual bool getTransform(MatrixF& xfm, F32 hist=0.0f)
{ xfm = last_xfm; return is_valid;}
virtual bool getAltitudes(F32& terrain_alt, F32& interior_alt) { return false; }
virtual bool isDefined() { return is_defined; }
virtual bool isValid() { return is_valid; }
virtual U32 getChangeCode() { return change_code; }
virtual U32 setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans, bool is_death_anim)
{ return 0; };
virtual void resetAnimation(U32 tag) { };
virtual U32 lockAnimation() { return 0; }
virtual void unlockAnimation(U32 tag) { }
virtual F32 getAnimClipDuration(const char* clip) { return 0.0f; }
virtual S32 getDamageState() { return -1; }
virtual void setLivingState(bool state) { is_alive = state; };
virtual bool getLivingState() { return is_alive; };
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos)=0;
virtual SceneObject* getSceneObject()=0;
virtual void restoreObject(SceneObject*)=0;
virtual U16 getScopeId()=0;
virtual U32 getTriggers()=0;
virtual void set_scope_id(U16 scope_id) { }
virtual void unset() { }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxConstraintMgr
class ShapeBase;
class afxEffectWrapper;
class afxShapeConstraint;
class afxObjectConstraint;
class BitStream;
class NetConnection;
struct afxConstraintID
{
S16 index;
S16 sub_index;
afxConstraintID() { index = -1; sub_index = 0; }
afxConstraintID(S16 idx, S16 sub=0) { index = idx; sub_index = sub; }
bool undefined() const { return (index < 0); }
};
typedef Vector<afxConstraint*> afxConstraintList;
class afxConstraintMgr : public afxEffectDefs
{
typedef SimObject Parent;
struct preDef
{
StringTableEntry name;
U32 type;
};
Vector<afxConstraintList*> constraints_v;
Vector<StringTableEntry> names_on_server;
Vector<S32> ghost_ids;
Vector<preDef> predefs;
U32 starttime;
bool on_server;
bool initialized;
F32 scoping_dist_sq;
SceneObject* find_object_from_name(StringTableEntry);
S32 find_cons_idx_from_name(StringTableEntry);
S32 find_effect_cons_idx_from_name(StringTableEntry);
void create_constraint(const afxConstraintDef&);
void set_ref_shape(afxConstraintID which_id, ShapeBase*);
void set_ref_shape(afxConstraintID which_id, U16 scope_id);
public:
/*C*/ afxConstraintMgr();
/*D*/ ~afxConstraintMgr();
void defineConstraint(U32 type, StringTableEntry);
afxConstraintID setReferencePoint(StringTableEntry which, Point3F point);
afxConstraintID setReferencePoint(StringTableEntry which, Point3F point, Point3F vector);
afxConstraintID setReferenceTransform(StringTableEntry which, MatrixF& xfm);
afxConstraintID setReferenceObject(StringTableEntry which, SceneObject*);
afxConstraintID setReferenceObjectByScopeId(StringTableEntry which, U16 scope_id, bool is_shape);
afxConstraintID setReferenceEffect(StringTableEntry which, afxEffectWrapper*);
afxConstraintID createReferenceEffect(StringTableEntry which, afxEffectWrapper*);
void setReferencePoint(afxConstraintID which_id, Point3F point);
void setReferencePoint(afxConstraintID which_id, Point3F point, Point3F vector);
void setReferenceTransform(afxConstraintID which_id, MatrixF& xfm);
void setReferenceObject(afxConstraintID which_id, SceneObject*);
void setReferenceObjectByScopeId(afxConstraintID which_id, U16 scope_id, bool is_shape);
void setReferenceEffect(afxConstraintID which_id, afxEffectWrapper*);
void invalidateReference(afxConstraintID which_id);
afxConstraintID getConstraintId(const afxConstraintDef&);
afxConstraint* getConstraint(afxConstraintID cons_id);
void sample(F32 dt, U32 now, const Point3F* cam_pos=0);
void setStartTime(U32 timestamp) { starttime = timestamp; }
void initConstraintDefs(Vector<afxConstraintDef>&, bool on_server, F32 scoping_dist=-1.0f);
void packConstraintNames(NetConnection* conn, BitStream* stream);
void unpackConstraintNames(BitStream* stream);
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// scope-tracking
private:
Vector<SceneObject*> scopeable_objs;
Vector<U16> scopeable_ids;
Vector<afxConstraint*>* missing_objs;
Vector<afxConstraint*>* missing_objs2;
Vector<afxConstraint*> missing_objs_a;
Vector<afxConstraint*> missing_objs_b;
public:
void addScopeableObject(SceneObject*);
void removeScopeableObject(SceneObject*);
void clearAllScopeableObjs();
void postMissingConstraintObject(afxConstraint*, bool is_deleting=false);
void restoreScopedObject(SceneObject*, afxChoreographer* ch);
void adjustProcessOrdering(afxChoreographer*);
F32 getScopingDistanceSquared() const { return scoping_dist_sq; }
};
inline afxConstraintID afxConstraintMgr::setReferencePoint(StringTableEntry which, Point3F point)
{
return setReferencePoint(which, point, Point3F(0,0,1));
}
inline void afxConstraintMgr::setReferencePoint(afxConstraintID which, Point3F point)
{
setReferencePoint(which, point, Point3F(0,0,1));
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPointConstraint
// This constrains to a specific 3D position such as an impact location.
//
class afxPointConstraint : public afxConstraint
{
typedef afxConstraint Parent;
protected:
Point3F point;
Point3F vector;
public:
/*C*/ afxPointConstraint(afxConstraintMgr*);
virtual ~afxPointConstraint();
virtual void set(Point3F point, Point3F vector);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos);
virtual SceneObject* getSceneObject() { return 0; }
virtual void restoreObject(SceneObject*) { }
virtual U16 getScopeId() { return 0; }
virtual U32 getTriggers() { return 0; }
virtual void unset() { set(Point3F::Zero, Point3F(0,0,1)); }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxTransformConstraint
// This constrains to a specific 3D transformation.
//
class afxTransformConstraint : public afxConstraint
{
typedef afxConstraint Parent;
protected:
MatrixF xfm;
public:
/*C*/ afxTransformConstraint(afxConstraintMgr*);
virtual ~afxTransformConstraint();
virtual void set(const MatrixF& xfm);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos);
virtual SceneObject* getSceneObject() { return 0; }
virtual void restoreObject(SceneObject*) { }
virtual U16 getScopeId() { return 0; }
virtual U32 getTriggers() { return 0; }
virtual void unset() { set(MatrixF::Identity); }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxShapeConstraint
// This constrains to a hierarchical shape (subclasses of ShapeBase), such as a
// Player or a Vehicle. You can also constrain to named sub-nodes of a shape.
class ShapeBase;
class SceneObject;
class afxShapeConstraint : public afxConstraint
{
friend class afxConstraintMgr;
typedef afxConstraint Parent;
protected:
StringTableEntry arb_name;
ShapeBase* shape;
U16 scope_id;
U32 clip_tag;
U32 lock_tag;
public:
/*C*/ afxShapeConstraint(afxConstraintMgr*);
/*C*/ afxShapeConstraint(afxConstraintMgr*, StringTableEntry arb_name);
virtual ~afxShapeConstraint();
virtual void set(ShapeBase* shape);
virtual void set_scope_id(U16 scope_id);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos);
virtual U32 setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans, bool is_death_anim);
virtual void resetAnimation(U32 tag);
virtual U32 lockAnimation();
virtual void unlockAnimation(U32 tag);
virtual F32 getAnimClipDuration(const char* clip);
void remapAnimation(U32 tag, ShapeBase* other_shape);
virtual S32 getDamageState();
virtual SceneObject* getSceneObject() { return shape; }
virtual void restoreObject(SceneObject*);
virtual U16 getScopeId() { return scope_id; }
virtual U32 getTriggers();
virtual void onDeleteNotify(SimObject*);
virtual void unset() { set(0); }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxShapeNodeConstraint
class afxShapeNodeConstraint : public afxShapeConstraint
{
friend class afxConstraintMgr;
typedef afxShapeConstraint Parent;
protected:
StringTableEntry arb_node;
S32 shape_node_ID;
public:
/*C*/ afxShapeNodeConstraint(afxConstraintMgr*);
/*C*/ afxShapeNodeConstraint(afxConstraintMgr*, StringTableEntry arb_name, StringTableEntry arb_node);
virtual void set(ShapeBase* shape);
virtual void set_scope_id(U16 scope_id);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos);
virtual void restoreObject(SceneObject*);
S32 getNodeID() const { return shape_node_ID; }
virtual void onDeleteNotify(SimObject*);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxObjectConstraint
// This constrains to a simple 3D object (subclasses of SceneObject), such as an
// afxMagicMissile or a Projectile. You cannot constrain to sub-nodes with an
// afxObjectConstraint, use afxShapeConstraint instead.
class SceneObject;
class afxObjectConstraint : public afxConstraint
{
friend class afxConstraintMgr;
typedef afxConstraint Parent;
protected:
StringTableEntry arb_name;
SceneObject* obj;
U16 scope_id;
bool is_camera;
public:
afxObjectConstraint(afxConstraintMgr*);
afxObjectConstraint(afxConstraintMgr*, StringTableEntry arb_name);
virtual ~afxObjectConstraint();
virtual void set(SceneObject* obj);
virtual void set_scope_id(U16 scope_id);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos);
virtual SceneObject* getSceneObject() { return obj; }
virtual void restoreObject(SceneObject*);
virtual U16 getScopeId() { return scope_id; }
virtual U32 getTriggers();
virtual void onDeleteNotify(SimObject*);
virtual void unset() { set(0); }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxEffectConstraint
// This constrains to a hierarchical shape (subclasses of ShapeBase), such as a
// Player or a Vehicle. You can also constrain to named sub-nodes of a shape.
class afxEffectWrapper;
class afxEffectConstraint : public afxConstraint
{
friend class afxConstraintMgr;
typedef afxConstraint Parent;
protected:
StringTableEntry effect_name;
afxEffectWrapper* effect;
U32 clip_tag;
bool is_death_clip;
U32 lock_tag;
public:
/*C*/ afxEffectConstraint(afxConstraintMgr*);
/*C*/ afxEffectConstraint(afxConstraintMgr*, StringTableEntry effect_name);
virtual ~afxEffectConstraint();
virtual bool getPosition(Point3F& pos, F32 hist=0.0f);
virtual bool getTransform(MatrixF& xfm, F32 hist=0.0f);
virtual bool getAltitudes(F32& terrain_alt, F32& interior_alt);
virtual void set(afxEffectWrapper* effect);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) { }
virtual U32 setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans, bool is_death_anim);
virtual void resetAnimation(U32 tag);
virtual F32 getAnimClipDuration(const char* clip);
virtual SceneObject* getSceneObject() { return 0; }
virtual void restoreObject(SceneObject*) { }
virtual U16 getScopeId() { return 0; }
virtual U32 getTriggers();
virtual void unset() { set(0); }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxEffectNodeConstraint
class afxEffectNodeConstraint : public afxEffectConstraint
{
friend class afxConstraintMgr;
typedef afxEffectConstraint Parent;
protected:
StringTableEntry effect_node;
S32 effect_node_ID;
public:
/*C*/ afxEffectNodeConstraint(afxConstraintMgr*);
/*C*/ afxEffectNodeConstraint(afxConstraintMgr*, StringTableEntry name, StringTableEntry node);
virtual bool getPosition(Point3F& pos, F32 hist=0.0f);
virtual bool getTransform(MatrixF& xfm, F32 hist=0.0f);
virtual void set(afxEffectWrapper* effect);
S32 getNodeID() const { return effect_node_ID; }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxSampleBuffer
class afxSampleBuffer
{
protected:
U32 buffer_sz;
U32 buffer_ms;
U32 ms_per_sample;
U32 elapsed_ms;
U32 last_sample_ms;
U32 next_sample_num;
U32 n_samples;
virtual void recSample(U32 idx, void* data) = 0;
bool compute_idx_from_lag(F32 lag, U32& idx);
bool compute_idx_from_lag(F32 lag, U32& idx1, U32& idx2, F32& t);
public:
/*C*/ afxSampleBuffer();
virtual ~afxSampleBuffer();
virtual void configHistory(F32 hist_len, U8 sample_rate);
void recordSample(F32 dt, U32 elapsed_ms, void* data);
virtual void getSample(F32 lag, void* data, bool& oob) = 0;
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxSampleXfmBuffer
class afxSampleXfmBuffer : public afxSampleBuffer
{
typedef afxSampleBuffer Parent;
protected:
MatrixF* xfm_buffer;
virtual void recSample(U32 idx, void* data);
public:
/*C*/ afxSampleXfmBuffer();
virtual ~afxSampleXfmBuffer();
virtual void configHistory(F32 hist_len, U8 sample_rate);
virtual void getSample(F32 lag, void* data, bool& oob);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPointHistConstraint
// This class extends afxPointConstraint to remember its values for a period of time.
class afxPointHistConstraint : public afxPointConstraint
{
friend class afxConstraintMgr;
typedef afxPointConstraint Parent;
protected:
afxSampleBuffer* samples;
public:
/*C*/ afxPointHistConstraint(afxConstraintMgr*);
virtual ~afxPointHistConstraint();
virtual void set(Point3F point, Point3F vector);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos);
virtual bool getPosition(Point3F& pos, F32 hist=0.0f);
virtual bool getTransform(MatrixF& xfm, F32 hist=0.0f);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPointHistConstraint
// This class extends afxTransformConstraint to remember its values for a period of time.
class afxTransformHistConstraint : public afxTransformConstraint
{
friend class afxConstraintMgr;
typedef afxTransformConstraint Parent;
protected:
afxSampleBuffer* samples;
public:
/*C*/ afxTransformHistConstraint(afxConstraintMgr*);
virtual ~afxTransformHistConstraint();
virtual void set(const MatrixF& xfm);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos);
virtual bool getPosition(Point3F& pos, F32 hist=0.0f);
virtual bool getTransform(MatrixF& xfm, F32 hist=0.0f);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxShapeHistConstraint
// This class extends afxShapeConstraint to remember its values for a period of time.
class afxShapeHistConstraint : public afxShapeConstraint
{
friend class afxConstraintMgr;
typedef afxShapeConstraint Parent;
protected:
afxSampleBuffer* samples;
public:
/*C*/ afxShapeHistConstraint(afxConstraintMgr*);
/*C*/ afxShapeHistConstraint(afxConstraintMgr*, StringTableEntry arb_name);
virtual ~afxShapeHistConstraint();
virtual void set(ShapeBase* shape);
virtual void set_scope_id(U16 scope_id);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos);
virtual bool getPosition(Point3F& pos, F32 hist=0.0f);
virtual bool getTransform(MatrixF& xfm, F32 hist=0.0f);
virtual void onDeleteNotify(SimObject*);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxShapeNodeHistConstraint
// This class extends afxShapeConstraint to remember its values for a period of time.
class afxShapeNodeHistConstraint : public afxShapeNodeConstraint
{
friend class afxConstraintMgr;
typedef afxShapeNodeConstraint Parent;
protected:
afxSampleBuffer* samples;
public:
/*C*/ afxShapeNodeHistConstraint(afxConstraintMgr*);
/*C*/ afxShapeNodeHistConstraint(afxConstraintMgr*, StringTableEntry arb_name, StringTableEntry arb_node);
virtual ~afxShapeNodeHistConstraint();
virtual void set(ShapeBase* shape);
virtual void set_scope_id(U16 scope_id);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos);
virtual bool getPosition(Point3F& pos, F32 hist=0.0f);
virtual bool getTransform(MatrixF& xfm, F32 hist=0.0f);
virtual void onDeleteNotify(SimObject*);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxObjectHistConstraint
// This class extends afxObjectConstraint to remember its values for a period of time.
class SceneObject;
class afxObjectHistConstraint : public afxObjectConstraint
{
friend class afxConstraintMgr;
typedef afxObjectConstraint Parent;
protected:
afxSampleBuffer* samples;
public:
afxObjectHistConstraint(afxConstraintMgr*);
afxObjectHistConstraint(afxConstraintMgr*, StringTableEntry arb_name);
virtual ~afxObjectHistConstraint();
virtual void set(SceneObject* obj);
virtual void set_scope_id(U16 scope_id);
virtual void sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos);
virtual bool getPosition(Point3F& pos, F32 hist=0.0f);
virtual bool getTransform(MatrixF& xfm, F32 hist=0.0f);
virtual void onDeleteNotify(SimObject*);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_CONSTRAINT_H_

View file

@ -0,0 +1,114 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_EFFECT_DEFS_H_
#define _AFX_EFFECT_DEFS_H_
#include "afx/arcaneFX.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxEffectBASE
class afxEffectDefs
{
public:
enum
{
MAX_EFFECTS_PER_PHRASE = 1023,
EFFECTS_PER_PHRASE_BITS = 10
};
// effect networking
enum
{
SERVER_ONLY = BIT(0),
SCOPE_ALWAYS = BIT(1),
GHOSTABLE = BIT(2),
CLIENT_ONLY = BIT(3),
SERVER_AND_CLIENT = BIT(4)
};
// effect condititons
enum
{
DISABLED = BIT(0),
ENABLED = BIT(1),
FAILING = BIT(2),
ALIVE = ENABLED,
DEAD = DISABLED,
DYING = FAILING,
//
IMPACTED_SOMETHING = BIT(31),
IMPACTED_TARGET = BIT(30),
IMPACTED_PRIMARY = BIT(29),
IMPACT_IN_WATER = BIT(28),
CASTER_IN_WATER = BIT(27),
};
enum
{
REQUIRES_STOP = BIT(0),
RUNS_ON_SERVER = BIT(1),
RUNS_ON_CLIENT = BIT(2),
};
enum
{
MAX_XFM_MODIFIERS = 32,
INFINITE_LIFETIME = (24*60*60)
};
enum
{
POINT_CONSTRAINT,
TRANSFORM_CONSTRAINT,
OBJECT_CONSTRAINT,
CAMERA_CONSTRAINT,
OBJECT_CONSTRAINT_SANS_OBJ,
OBJECT_CONSTRAINT_SANS_SHAPE,
UNDEFINED_CONSTRAINT_TYPE
};
enum
{
DIRECT_DAMAGE,
DAMAGE_OVER_TIME,
AREA_DAMAGE
};
enum
{
TIMING_DELAY = BIT(0),
TIMING_LIFETIME = BIT(1),
TIMING_FADE_IN = BIT(2),
TIMING_FADE_OUT = BIT(3),
TIMING_BITS = 2
};
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_EFFECT_DEFS_H_

View file

@ -0,0 +1,270 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/engineAPI.h"
#include "afx/afxEffectGroup.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxEffectGroupData::egValidator
//
// When an effect is added using "addEffect", this validator intercepts the value
// and adds it to the dynamic effects list.
//
void afxEffectGroupData::egValidator::validateType(SimObject* object, void* typePtr)
{
afxEffectGroupData* eff_data = dynamic_cast<afxEffectGroupData*>(object);
afxEffectBaseData** ew = (afxEffectBaseData**)(typePtr);
if (eff_data && ew)
{
eff_data->fx_list.push_back(*ew);
*ew = 0;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxEffectGroupData
IMPLEMENT_CO_DATABLOCK_V1(afxEffectGroupData);
ConsoleDocClass( afxEffectGroupData,
"@brief A datablock that describes an Effect Group.\n\n"
"afxEffectGroupData provides a way for adding several effects to a choreographer as a "
"group and can be used wherever an afxEffectWrapperData is used. Basically, an "
"effect-group is a simple list of effect-wrappers. When an effect-group is added to a "
"choreographer, the end result is almost the same as adding all of the group's "
"effect-wrappers directly to the choreographer. The main difference is that the "
"grouped effects can be turned on and off collectively and created in multiples. "
"Effect-groups can also contain other effect-groups, forming a hierarchy of effects.\n\n"
"A great strength of effect-groups is that they have a count setting that multiplies "
"the number of times the effects in the group are added to the owning choreographer "
"and this doesn't happen until the choreographer instance is created and launched. "
"This makes a big difference for certain kinds of effects, such as fireworks, that "
"tend to consist of small groupings of effects that are repeated many times with "
"slight variations. With groups, an effect like this has a very compact representation "
"for transmitting from server to clients, that only expands when actually used.\n\n"
"Effect-groups with a count greater than one are extremely useful when some of the "
"effects use field substitutions. When an effect-group is expanded, it essentially runs "
"through a for-loop from 0 to count-1 and creates a new set of effect instances each "
"time through the loop. For each new set of effects, their group-index is set to the "
"index of this for-loop, which in turn replaces the ## token used in any field "
"substitutions in the child effects. In essence, the for-loop index becomes a parameter "
"of the child effects which can be used to vary the effects created in each loop.\n\n"
"@see afxEffectBaseData\n\n"
"@see afxEffectWrapperData\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxEffectGroupData::afxEffectGroupData()
{
group_enabled = true;
group_count = 1;
idx_offset = 0;
assign_idx = false;
// dummy entry holds effect-wrapper pointer while a special validator
// grabs it and adds it to an appropriate effects list
dummy_fx_entry = NULL;
// marked true if datablock ids need to
// be converted into pointers
do_id_convert = false;
}
afxEffectGroupData::afxEffectGroupData(const afxEffectGroupData& other, bool temp_clone) : afxEffectBaseData(other, temp_clone)
{
group_enabled = other.group_enabled;
group_count = other.group_count;
idx_offset = other.idx_offset;
assign_idx = other.assign_idx;
timing = other.timing;
dummy_fx_entry = other.dummy_fx_entry;
do_id_convert = other.do_id_convert; // --
fx_list = other.fx_list; // --
}
void afxEffectGroupData::reloadReset()
{
fx_list.clear();
}
void afxEffectGroupData::pack_fx(BitStream* stream, const afxEffectList& fx, bool packed)
{
stream->writeInt(fx.size(), EFFECTS_PER_PHRASE_BITS);
for (int i = 0; i < fx.size(); i++)
writeDatablockID(stream, fx[i], packed);
}
void afxEffectGroupData::unpack_fx(BitStream* stream, afxEffectList& fx)
{
fx.clear();
S32 n_fx = stream->readInt(EFFECTS_PER_PHRASE_BITS);
for (int i = 0; i < n_fx; i++)
fx.push_back((afxEffectWrapperData*)readDatablockID(stream));
}
#define myOffset(field) Offset(field, afxEffectGroupData)
void afxEffectGroupData::initPersistFields()
{
addField("groupEnabled", TypeBool, myOffset(group_enabled),
"...");
addField("count", TypeS32, myOffset(group_count),
"...");
addField("indexOffset", TypeS8, myOffset(idx_offset),
"...");
addField("assignIndices", TypeBool, myOffset(assign_idx),
"...");
addField("delay", TypeF32, myOffset(timing.delay),
"...");
addField("lifetime", TypeF32, myOffset(timing.lifetime),
"...");
addField("fadeInTime", TypeF32, myOffset(timing.fade_in_time),
"...");
addField("fadeOutTime", TypeF32, myOffset(timing.fade_out_time),
"...");
// effect lists
// for each of these, dummy_fx_entry is set and then a validator adds it to the appropriate effects list
static egValidator emptyValidator(0);
addFieldV("addEffect", TYPEID<afxEffectBaseData>(), myOffset(dummy_fx_entry), &emptyValidator,
"...");
Parent::initPersistFields();
// disallow some field substitutions
disableFieldSubstitutions("addEffect");
}
void afxEffectGroupData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeFlag(group_enabled);
stream->write(group_count);
stream->write(idx_offset);
stream->writeFlag(assign_idx);
stream->write(timing.delay);
stream->write(timing.lifetime);
stream->write(timing.fade_in_time);
stream->write(timing.fade_out_time);
pack_fx(stream, fx_list, packed);
}
void afxEffectGroupData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
group_enabled = stream->readFlag();
stream->read(&group_count);
stream->read(&idx_offset);
assign_idx = stream->readFlag();
stream->read(&timing.delay);
stream->read(&timing.lifetime);
stream->read(&timing.fade_in_time);
stream->read(&timing.fade_out_time);
do_id_convert = true;
unpack_fx(stream, fx_list);
}
bool afxEffectGroupData::preload(bool server, String &errorStr)
{
if (!Parent::preload(server, errorStr))
return false;
// Resolve objects transmitted from server
if (!server)
{
if (do_id_convert)
{
for (S32 i = 0; i < fx_list.size(); i++)
{
SimObjectId db_id = SimObjectId((uintptr_t)fx_list[i]);
if (db_id != 0)
{
// try to convert id to pointer
if (!Sim::findObject(db_id, fx_list[i]))
{
Con::errorf(ConsoleLogEntry::General,
"afxEffectGroupData::preload() -- bad datablockId: 0x%x",
db_id);
}
}
}
do_id_convert = false;
}
}
return true;
}
void afxEffectGroupData::gather_cons_defs(Vector<afxConstraintDef>& defs)
{
for (S32 i = 0; i < fx_list.size(); i++)
{
if (fx_list[i])
fx_list[i]->gather_cons_defs(defs);
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
DefineEngineMethod(afxEffectGroupData, reset, void, (),,
"Resets an effect-group datablock during reload.\n\n"
"@ingroup AFX")
{
object->reloadReset();
}
DefineEngineMethod(afxEffectGroupData, addEffect, void, (afxEffectBaseData* effect),,
"Adds an effect (wrapper or group) to an effect-group.\n\n"
"@ingroup AFX")
{
if (!effect)
{
Con::errorf("afxEffectGroupData::addEffect() -- missing afxEffectWrapperData.");
return;
}
object->fx_list.push_back(effect);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,103 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_EFFECT_GROUP_H_
#define _AFX_EFFECT_GROUP_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "console/typeValidators.h"
#include "afx/afxEffectDefs.h"
#include "afx/afxEffectWrapper.h"
class afxEffectWrapperData;
struct afxGroupTimingData
{
F32 delay;
F32 lifetime;
F32 fade_in_time;
F32 fade_out_time;
afxGroupTimingData()
{
delay = 0.0f;
lifetime = 0.0f;
fade_in_time = 0.0f;
fade_out_time = 0.0f;
}
};
class afxEffectGroupData : public afxEffectBaseData
{
typedef afxEffectBaseData Parent;
class egValidator : public TypeValidator
{
U32 id;
public:
egValidator(U32 id) { this->id = id; }
void validateType(SimObject *object, void *typePtr);
};
bool do_id_convert;
public:
afxEffectList fx_list;
bool group_enabled;
S32 group_count;
U8 idx_offset;
bool assign_idx;
afxGroupTimingData timing;
afxEffectBaseData* dummy_fx_entry;
private:
void pack_fx(BitStream* stream, const afxEffectList& fx, bool packed);
void unpack_fx(BitStream* stream, afxEffectList& fx);
public:
/*C*/ afxEffectGroupData();
/*C*/ afxEffectGroupData(const afxEffectGroupData&, bool = false);
virtual void reloadReset();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
bool preload(bool server, String &errorStr);
virtual void gather_cons_defs(Vector<afxConstraintDef>& defs);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxEffectGroupData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_EFFECT_GROUP_H_

View file

@ -0,0 +1,358 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "afxChoreographer.h"
#include "afxEffectVector.h"
#include "afxConstraint.h"
#include "afxEffectWrapper.h"
#include "afxEffectGroup.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxEffectVector::filter_client_server()
{
if (empty())
return;
for (S32 i = 0; i < fx_v->size(); i++)
{
if ((*fx_v)[i]->datablock->runsHere(on_server))
fx_v2->push_back((*fx_v)[i]);
else
{
delete (*fx_v)[i];
(*fx_v)[i] = 0;
}
}
swap_vecs();
fx_v2->clear();
}
void afxEffectVector::calc_fx_dur_and_afterlife()
{
total_fx_dur = 0.0f;
after_life = 0.0f;
if (empty())
return;
for (S32 i = 0; i < fx_v->size(); i++)
{
afxEffectWrapper* ew = (*fx_v)[i];
if (ew)
{
F32 ew_dur;
if (ew->ew_timing.lifetime < 0)
{
if (phrase_dur > ew->ew_timing.delay)
ew_dur = phrase_dur + ew->afterStopTime();
else
ew_dur = ew->ew_timing.delay + ew->afterStopTime();
}
else
ew_dur = ew->ew_timing.delay + ew->ew_timing.lifetime + ew->ew_timing.fade_out_time;
if (ew_dur > total_fx_dur)
total_fx_dur = ew_dur;
F32 after = ew->afterStopTime();
if (after > after_life)
after_life = after;
}
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
afxEffectVector::afxEffectVector()
{
fx_v = 0;
fx_v2 = 0;
active = false;
on_server = false;
total_fx_dur = 0;
after_life = 0;
}
afxEffectVector::~afxEffectVector()
{
stop(true);
delete fx_v;
delete fx_v2;
}
void afxEffectVector::effects_init(afxChoreographer* chor, afxEffectList& effects, bool will_stop, F32 time_factor,
S32 group_index, const afxGroupTimingData* group_timing)
{
afxConstraintMgr* cons_mgr = chor->getConstraintMgr();
for (S32 i = 0; i < effects.size(); i++)
{
if (dynamic_cast<afxEffectGroupData*>(effects[i]))
{
afxEffectGroupData* eg = (afxEffectGroupData*)effects[i];
if (eg->getSubstitutionCount() > 0)
{
// clone the datablock and perform substitutions
afxEffectGroupData* orig_db = eg;
eg = new afxEffectGroupData(*orig_db, true);
orig_db->performSubstitutions(eg, chor, group_index);
}
if (eg->group_enabled)
{
if (eg->assign_idx)
{
for (S32 j = 0; j < eg->group_count; j++)
effects_init(chor, eg->fx_list, will_stop, time_factor, j+eg->idx_offset, &eg->timing);
}
else
{
for (S32 j = 0; j < eg->group_count; j++)
effects_init(chor, eg->fx_list, will_stop, time_factor, group_index, &eg->timing);
}
}
if (eg->isTempClone())
delete eg;
}
else if (dynamic_cast<afxEffectWrapperData*>(effects[i]))
{
afxEffectWrapperData* ewd = (afxEffectWrapperData*)effects[i];
if (ewd->getSubstitutionCount() > 0)
{
// clone the ewd and perform substitutions
afxEffectWrapperData* orig_db = ewd;
ewd = new afxEffectWrapperData(*orig_db, true);
orig_db->performSubstitutions(ewd, chor, group_index);
}
if (ewd->effect_enabled)
{
static afxEffectTimingData inherited_timing;
bool use_inherited_timing = false;
if (ewd->inherit_timing != 0)
{
if (group_timing)
{
inherited_timing = ewd->ewd_timing;
if ((ewd->inherit_timing & afxEffectDefs::TIMING_DELAY) != 0)
inherited_timing.delay = group_timing->delay;
if ((ewd->inherit_timing & afxEffectDefs::TIMING_LIFETIME) != 0)
inherited_timing.lifetime = group_timing->lifetime;
if ((ewd->inherit_timing & afxEffectDefs::TIMING_FADE_IN) != 0)
inherited_timing.fade_in_time = group_timing->fade_in_time;
if ((ewd->inherit_timing & afxEffectDefs::TIMING_FADE_OUT) != 0)
inherited_timing.fade_out_time = group_timing->fade_out_time;
}
else
{
Con::warnf("afxEffectVector::effects_init() -- %s::inheritGroupTiming is non-zero but wrapper is not in a group.");
}
}
const afxEffectTimingData& timing = (use_inherited_timing) ? inherited_timing : ewd->ewd_timing;
if ( (will_stop || !ewd->requiresStop(timing)) &&
(chor->testRanking(ewd->ranking_range.low, ewd->ranking_range.high)) &&
(chor->testLevelOfDetail(ewd->lod_range.low, ewd->lod_range.high)) &&
(ewd->testExecConditions(chor->getExecConditions()))
)
{
afxEffectWrapper* effect;
effect = afxEffectWrapper::ew_create(chor, ewd, cons_mgr, time_factor, group_index);
if (effect)
fx_v->push_back(effect);
}
}
else
{
if (ewd->isTempClone())
delete ewd;
}
}
}
}
void afxEffectVector::ev_init(afxChoreographer* chor, afxEffectList& effects, bool on_server,
bool will_stop, F32 time_factor, F32 phrase_dur, S32 group_index)
{
this->on_server = on_server;
this->phrase_dur = phrase_dur;
fx_v = new Vector<afxEffectWrapper*>;
effects_init(chor, effects, will_stop, time_factor, group_index);
fx_v2 = new Vector<afxEffectWrapper*>(fx_v->size());
}
void afxEffectVector::start(F32 timestamp)
{
if (empty())
return;
// At this point both client and server effects are in the list.
// Timing adjustments are made during prestart().
for (S32 i = 0; i < fx_v->size(); i++)
(*fx_v)[i]->prestart();
// duration and afterlife values are pre-calculated here
calc_fx_dur_and_afterlife();
// now we filter out client-only or server-only effects that
// don't belong here,
filter_client_server();
active = true;
for (S32 j = 0; j < fx_v->size(); j++)
{
if ((*fx_v)[j]->start(timestamp))
fx_v2->push_back((*fx_v)[j]);
else
{
delete (*fx_v)[j];
(*fx_v)[j] = 0;
}
}
swap_vecs();
fx_v2->clear();
}
void afxEffectVector::update(F32 dt)
{
if (empty())
{
active = false;
return;
}
for (int i = 0; i < fx_v->size(); i++)
{
(*fx_v)[i]->update(dt);
if ((*fx_v)[i]->isDone() || (*fx_v)[i]->isAborted())
{
// effect has ended, cleanup and delete
(*fx_v)[i]->cleanup();
delete (*fx_v)[i];
(*fx_v)[i] = 0;
}
else
{
// effect is still going, so keep it around
fx_v2->push_back((*fx_v)[i]);
}
}
swap_vecs();
fx_v2->clear();
if (empty())
{
active = false;
delete fx_v; fx_v =0;
delete fx_v2; fx_v2 = 0;
}
}
void afxEffectVector::stop(bool force_cleanup)
{
if (empty())
{
active = false;
return;
}
for (int i = 0; i < fx_v->size(); i++)
{
(*fx_v)[i]->stop();
if (force_cleanup || (*fx_v)[i]->deleteWhenStopped())
{
// effect is over when stopped, cleanup and delete
(*fx_v)[i]->cleanup();
delete (*fx_v)[i];
(*fx_v)[i] = 0;
}
else
{
// effect needs to fadeout or something, so keep it around
fx_v2->push_back((*fx_v)[i]);
}
}
swap_vecs();
fx_v2->clear();
if (empty())
{
active = false;
delete fx_v; fx_v =0;
delete fx_v2; fx_v2 = 0;
}
}
void afxEffectVector::interrupt()
{
if (empty())
{
active = false;
return;
}
for (int i = 0; i < fx_v->size(); i++)
{
(*fx_v)[i]->stop();
(*fx_v)[i]->cleanup();
delete (*fx_v)[i];
(*fx_v)[i] = 0;
}
swap_vecs();
fx_v2->clear();
if (empty())
{
active = false;
delete fx_v; fx_v =0;
delete fx_v2; fx_v2 = 0;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,86 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_EFFECT_VECTOR_H_
#define _AFX_EFFECT_VECTOR_H_
#include "afx/afxEffectWrapper.h"
#include "afx/afxEffectGroup.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxEffectVector
class afxEffectWrapper;
class afxChoreographer;
class afxEffectVector
{
Vector<afxEffectWrapper*>* fx_v;
Vector<afxEffectWrapper*>* fx_v2;
bool active;
bool on_server;
F32 phrase_dur;
F32 total_fx_dur;
F32 after_life;
void swap_vecs();
void filter_client_server();
void calc_fx_dur_and_afterlife();
void effects_init(afxChoreographer*, afxEffectList&, bool will_stop, F32 time_factor,
S32 group_index, const afxGroupTimingData* group_timing=0);
public:
/*C*/ afxEffectVector();
/*D*/ ~afxEffectVector();
void ev_init(afxChoreographer*, afxEffectList&, bool on_server, bool will_stop,
F32 time_factor, F32 phrase_dur, S32 group_index=0);
void start(F32 timestamp);
void update(F32 dt);
void stop(bool force_cleanup=false);
void interrupt();
bool empty() { return (!fx_v || fx_v->empty()); }
bool isActive() { return active; }
S32 count() { return (fx_v) ? fx_v->size() : 0; }
F32 getTotalDur() { return total_fx_dur; }
F32 getAfterLife() { return after_life; }
Vector<afxEffectWrapper*>* getFX() { return fx_v; }
};
inline void afxEffectVector::swap_vecs()
{
Vector<afxEffectWrapper*>* tmp = fx_v;
fx_v = fx_v2;
fx_v2 = tmp;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_EFFECT_VECTOR_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,392 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_EFFECT_WRAPPER_H_
#define _AFX_EFFECT_WRAPPER_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "afxEffectDefs.h"
#include "afxConstraint.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
struct afxEffectTimingData
{
F32 delay;
F32 lifetime;
F32 fade_in_time;
F32 fade_out_time;
F32 residue_lifetime;
F32 residue_fadetime;
F32 life_bias;
Point2F fadein_ease;
Point2F fadeout_ease;
afxEffectTimingData()
{
delay = 0.0f;
lifetime = 0.0f;
fade_in_time = 0.0f;
fade_out_time = 0.0f;
residue_lifetime = 0.0f;
residue_fadetime = 0.0f;
life_bias = 1.0f;
fadein_ease.set(0.0f, 1.0f);
fadeout_ease.set(0.0f, 1.0f);
}
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxEffectWrapperData;
class afxAnimCurve;
class afxEffectAdapterDesc
{
private:
static Vector<afxEffectAdapterDesc*>* adapters;
public:
/*C*/ afxEffectAdapterDesc();
virtual bool testEffectType(const SimDataBlock*) const=0;
virtual bool requiresStop(const afxEffectWrapperData*, const afxEffectTimingData&) const=0;
virtual bool runsOnServer(const afxEffectWrapperData*) const=0;
virtual bool runsOnClient(const afxEffectWrapperData*) const=0;
virtual bool isPositional(const afxEffectWrapperData*) const { return true; }
virtual void prepEffect(afxEffectWrapperData*) const { }
virtual afxEffectWrapper* create() const=0;
static bool identifyEffect(afxEffectWrapperData*);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxXM_BaseData;
class afxEffectBaseData : public GameBaseData, public afxEffectDefs
{
typedef GameBaseData Parent;
public:
/*C*/ afxEffectBaseData() { }
/*C*/ afxEffectBaseData(const afxEffectBaseData& other, bool temp=false) : GameBaseData(other, temp){ }
virtual void gather_cons_defs(Vector<afxConstraintDef>& defs) { };
DECLARE_CONOBJECT(afxEffectBaseData);
DECLARE_CATEGORY("AFX");
};
//class afxEffectWrapperData : public GameBaseData, public afxEffectDefs
class afxEffectWrapperData : public afxEffectBaseData
{
//typedef GameBaseData Parent;
typedef afxEffectBaseData Parent;
bool do_id_convert;
public:
enum { MAX_CONDITION_STATES = 4 };
public:
StringTableEntry effect_name;
bool use_as_cons_obj;
bool use_ghost_as_cons_obj;
StringTableEntry cons_spec;
StringTableEntry pos_cons_spec;
StringTableEntry orient_cons_spec;
StringTableEntry aim_cons_spec;
StringTableEntry life_cons_spec;
//
afxConstraintDef cons_def;
afxConstraintDef pos_cons_def;
afxConstraintDef orient_cons_def;
afxConstraintDef aim_cons_def;
afxConstraintDef life_cons_def;
afxEffectTimingData ewd_timing;
U32 inherit_timing;
F32 scale_factor; // scale size if applicable
F32 rate_factor; // scale rate if applicable
F32 user_fade_out_time;
bool is_looping;
U32 n_loops;
F32 loop_gap_time;
bool ignore_time_factor;
bool propagate_time_factor;
ByteRange ranking_range;
ByteRange lod_range;
S32 life_conds;
bool effect_enabled;
U32 exec_cond_on_bits[MAX_CONDITION_STATES];
U32 exec_cond_off_bits[MAX_CONDITION_STATES];
U32 exec_cond_bitmasks[MAX_CONDITION_STATES];
S32 data_ID;
afxXM_BaseData* xfm_modifiers[MAX_XFM_MODIFIERS];
Box3F forced_bbox;
bool update_forced_bbox;
S8 sort_priority;
Point3F direction;
F32 speed;
F32 mass;
bool borrow_altitudes;
StringTableEntry vis_keys_spec;
afxAnimCurve* vis_keys;
SimDataBlock* effect_data;
afxEffectAdapterDesc* effect_desc;
S32 group_index;
void parse_cons_specs();
void parse_vis_keys();
void gather_cons_defs(Vector<afxConstraintDef>& defs);
void pack_mods(BitStream*, afxXM_BaseData* mods[], bool packed);
void unpack_mods(BitStream*, afxXM_BaseData* mods[]);
public:
/*C*/ afxEffectWrapperData();
/*C*/ afxEffectWrapperData(const afxEffectWrapperData&, bool = false);
/*D*/ ~afxEffectWrapperData();
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
bool preload(bool server, String &errorStr);
virtual void onPerformSubstitutions();
bool requiresStop(const afxEffectTimingData& timing) { return effect_desc->requiresStop(this, timing); }
bool runsOnServer() { return effect_desc->runsOnServer(this); }
bool runsOnClient() { return effect_desc->runsOnClient(this); }
bool runsHere(bool server_here) { return (server_here) ? runsOnServer() : runsOnClient(); }
bool isPositional() { return effect_desc->isPositional(this); }
bool testExecConditions(U32 conditions);
F32 afterStopTime() { return ewd_timing.fade_out_time; }
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxEffectWrapperData);
DECLARE_CATEGORY("AFX");
};
inline bool afxEffectWrapperData::testExecConditions(U32 conditions)
{
if (exec_cond_bitmasks[0] == 0)
return true;
if ((exec_cond_bitmasks[0] & conditions) == exec_cond_on_bits[0])
return true;
for (S32 i = 1; i < MAX_CONDITION_STATES; i++)
{
if (exec_cond_bitmasks[i] == 0)
return false;
if ((exec_cond_bitmasks[i] & conditions) == exec_cond_on_bits[i])
return true;
}
return false;
}
typedef Vector<afxEffectBaseData*> afxEffectList;
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxEffectWrapper
//
// NOTE -- this not a subclass of GameBase... it is only meant to exist on
// the client-side.
class ShapeBase;
class GameBase;
class TSShape;
class TSShapeInstance;
class SceneObject;
class afxConstraint;
class afxConstraintMgr;
class afxChoreographer;
class afxXM_Base;
class afxEffectWrapper : public SimObject, public afxEffectDefs
{
typedef SimObject Parent;
friend class afxEffectVector;
private:
bool test_life_conds();
protected:
afxEffectWrapperData* datablock;
afxEffectTimingData ew_timing;
F32 fade_in_end;
F32 fade_out_start;
F32 full_lifetime;
F32 time_factor;
F32 prop_time_factor;
afxChoreographer* choreographer;
afxConstraintMgr* cons_mgr;
afxConstraintID pos_cons_id;
afxConstraintID orient_cons_id;
afxConstraintID aim_cons_id;
afxConstraintID life_cons_id;
afxConstraintID effect_cons_id;
F32 elapsed;
F32 life_elapsed;
F32 life_end;
bool stopped;
bool cond_alive;
U32 n_updates;
MatrixF updated_xfm;
Point3F updated_pos;
Point3F updated_aim;
Point3F updated_scale;
LinearColorF updated_color;
F32 fade_value;
F32 last_fade_value;
bool do_fade_inout;
bool do_fades;
bool in_scope;
bool is_aborted;
U8 effect_flags;
afxXM_Base* xfm_modifiers[MAX_XFM_MODIFIERS];
F32 live_scale_factor;
F32 live_fade_factor;
F32 terrain_altitude;
F32 interior_altitude;
S32 group_index;
public:
/*C*/ afxEffectWrapper();
virtual ~afxEffectWrapper();
void ew_init(afxChoreographer*, afxEffectWrapperData*, afxConstraintMgr*,
F32 time_factor);
F32 getFullLifetime() { return ew_timing.lifetime + ew_timing.fade_out_time; }
F32 getTimeFactor() { return time_factor; }
afxConstraint* getPosConstraint() { return cons_mgr->getConstraint(pos_cons_id); }
afxConstraint* getOrientConstraint() { return cons_mgr->getConstraint(orient_cons_id); }
afxConstraint* getAimConstraint() { return cons_mgr->getConstraint(aim_cons_id); }
afxConstraint* getLifeConstraint() { return cons_mgr->getConstraint(life_cons_id); }
afxChoreographer* getChoreographer() { return choreographer; }
virtual bool isDone();
virtual bool deleteWhenStopped() { return false; }
F32 afterStopTime() { return ew_timing.fade_out_time; }
bool isAborted() const { return is_aborted; }
void prestart();
bool start(F32 timestamp);
bool update(F32 dt);
void stop();
void cleanup(bool was_stopped=false);
void setScopeStatus(bool flag);
virtual void ea_set_datablock(SimDataBlock*) { }
virtual bool ea_start() { return true; }
virtual bool ea_update(F32 dt) { return true; }
virtual void ea_finish(bool was_stopped) { }
virtual void ea_set_scope_status(bool flag) { }
virtual bool ea_is_enabled() { return true; }
virtual SceneObject* ea_get_scene_object() const { return 0; }
U32 ea_get_triggers() const { return 0; }
void getUpdatedPosition(Point3F& pos) { pos = updated_pos;}
void getUpdatedTransform(MatrixF& xfm) { xfm = updated_xfm; }
void getUpdatedScale(Point3F& scale) { scale = updated_scale; }
void getUpdatedColor(LinearColorF& color) { color = updated_color; }
virtual void getUpdatedBoxCenter(Point3F& pos) { pos = updated_pos;}
virtual void getUnconstrainedPosition(Point3F& pos) { pos.zero();}
virtual void getUnconstrainedTransform(MatrixF& xfm) { xfm.identity(); }
virtual void getBaseColor(LinearColorF& color) { color.set(1.0f, 1.0f, 1.0f, 1.0f); }
SceneObject* getSceneObject() const { return ea_get_scene_object(); }
U32 getTriggers() const { return ea_get_triggers(); }
F32 getMass() { return datablock->mass; }
Point3F getDirection() { return datablock->direction; }
F32 getSpeed() { return datablock->speed; }
virtual TSShape* getTSShape() { return 0; }
virtual TSShapeInstance* getTSShapeInstance() { return 0; }
virtual U32 setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans) { return 0; }
virtual void resetAnimation(U32 tag) { }
virtual F32 getAnimClipDuration(const char* clip) { return 0.0f; }
void setTerrainAltitude(F32 alt) { terrain_altitude = alt; }
void setInteriorAltitude(F32 alt) { interior_altitude = alt; }
void getAltitudes(F32& terr_alt, F32& inter_alt) const { terr_alt = terrain_altitude; inter_alt = interior_altitude; }
void setGroupIndex(S32 idx) { group_index = idx; }
S32 getGroupIndex() const { return group_index; }
bool inScope() const { return in_scope; }
public:
static void initPersistFields();
static afxEffectWrapper* ew_create(afxChoreographer*, afxEffectWrapperData*, afxConstraintMgr*, F32 time_factor, S32 group_index=0);
DECLARE_CONOBJECT(afxEffectWrapper);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_EFFECT_WRAPPER_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,216 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_COMPOSITE_EFFECT_H_
#define _AFX_COMPOSITE_EFFECT_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "console/typeValidators.h"
#include "afxChoreographer.h"
#include "afxEffectWrapper.h"
#include "afxPhrase.h"
class afxChoreographerData;
class afxEffectWrapperData;
class afxEffectronData : public afxChoreographerData
{
typedef afxChoreographerData Parent;
class ewValidator : public TypeValidator
{
U32 id;
public:
ewValidator(U32 id) { this->id = id; }
void validateType(SimObject *object, void *typePtr);
};
bool do_id_convert;
public:
F32 duration;
S32 n_loops;
afxEffectBaseData* dummy_fx_entry;
afxEffectList fx_list;
private:
void pack_fx(BitStream* stream, const afxEffectList& fx, bool packed);
void unpack_fx(BitStream* stream, afxEffectList& fx);
public:
/*C*/ afxEffectronData();
/*C*/ afxEffectronData(const afxEffectronData&, bool = false);
virtual void reloadReset();
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
bool preload(bool server, String &errorStr);
void gatherConstraintDefs(Vector<afxConstraintDef>&);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxEffectronData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxEffectron
class afxEffectron : public afxChoreographer
{
typedef afxChoreographer Parent;
public:
enum MaskBits
{
StateEventMask = Parent::NextFreeMask << 0,
SyncEventMask = Parent::NextFreeMask << 1,
NextFreeMask = Parent::NextFreeMask << 2
};
enum
{
NULL_EVENT,
ACTIVATE_EVENT,
SHUTDOWN_EVENT,
DEACTIVATE_EVENT,
INTERRUPT_EVENT
};
enum
{
INACTIVE_STATE,
ACTIVE_STATE,
CLEANUP_STATE,
DONE_STATE,
LATE_STATE
};
enum {
MARK_ACTIVATE = BIT(0),
MARK_SHUTDOWN = BIT(1),
MARK_DEACTIVATE = BIT(2),
MARK_INTERRUPT = BIT(3),
};
class ObjectDeleteEvent : public SimEvent
{
public:
void process(SimObject *obj) { if (obj) obj->deleteObject(); }
};
private:
static StringTableEntry CAMERA_CONS;
static StringTableEntry LISTENER_CONS;
private:
afxEffectronData* datablock;
SimObject* exeblock;
bool constraints_initialized;
bool scoping_initialized;
U8 effect_state;
F32 effect_elapsed;
U8 marks_mask;
afxConstraintID listener_cons_id;
afxConstraintID camera_cons_id;
SceneObject* camera_cons_obj;
afxPhrase* active_phrase;
F32 time_factor;
private:
void init();
bool state_expired();
void init_constraints();
void init_scoping();
void setup_active_fx();
bool cleanup_over();
public:
/*C*/ afxEffectron();
/*C*/ afxEffectron(bool not_default);
/*D*/ ~afxEffectron();
// STANDARD OVERLOADED METHODS //
virtual bool onNewDataBlock(GameBaseData* dptr, bool reload);
virtual void processTick(const Move*);
virtual void advanceTime(F32 dt);
virtual bool onAdd();
virtual U32 packUpdate(NetConnection*, U32, BitStream*);
virtual void unpackUpdate(NetConnection*, BitStream*);
virtual void inflictDamage(const char * label, const char* flavor, SimObjectId target,
F32 amt, U8 count, F32 ad_amt, F32 rad, Point3F pos, F32 imp);
virtual void sync_with_clients();
void finish_startup();
DECLARE_CONOBJECT(afxEffectron);
DECLARE_CATEGORY("AFX");
private:
void process_server();
//
void change_state_s(U8 pending_state);
//
void enter_active_state_s();
void leave_active_state_s();
void enter_cleanup_state_s();
void enter_done_state_s();
private:
void process_client(F32 dt);
//
void change_state_c(U8 pending_state);
//
void enter_active_state_c(F32 starttime);
void leave_active_state_c();
void sync_client(U16 marks, U8 state, F32 elapsed);
public:
void postEvent(U8 event);
void setTimeFactor(F32 f) { time_factor = (f > 0) ? f : 1.0f; }
F32 getTimeFactor() { return time_factor; }
bool activationCallInit(bool postponed=false);
void activate();
public:
static afxEffectron* start_effect(afxEffectronData*, SimObject* extra);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_EFFECTRON_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,435 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// afxMagicMissile is a heavily modified variation of the stock Projectile class. In
// addition to numerous AFX customizations, it also incorporates functionality based on
// the following TGE resources:
//
// Guided or Seeker Projectiles by Derk Adams
// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=6778
//
// Projectile Ballistic Coefficients (drag factors) by Mark Owen
// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=5128
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_MAGIC_MISSILE_H_
#define _AFX_MAGIC_MISSILE_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "T3D/lightDescription.h"
#include "T3D/fx/particleEmitter.h"
#include "afx/afxConstraint.h"
class SplashData;
class ShapeBase;
class TSShapeInstance;
class PhysicsWorld;
class SFXTrack;
class SFXSource;
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxMagicMissileData
class afxMagicMissileData : public GameBaseData
{
typedef GameBaseData Parent;
protected:
bool onAdd();
public:
enum { MaxLifetimeTicks = 4095 };
public:
// variables set in datablock definition:
// Shape related
StringTableEntry projectileShapeName;
//bool hasLight;
//F32 lightRadius;
//LinearColorF lightColor;
//bool hasWaterLight;
//LinearColorF waterLightColor;
/*
/// Set to true if it is a billboard and want it to always face the viewer, false otherwise
bool faceViewer;
*/
Point3F scale;
/*
/// [0,1] scale of how much velocity should be inherited from the parent object
F32 velInheritFactor;
/// Speed of the projectile when fired
*/
F32 muzzleVelocity;
/// Should it arc?
bool isBallistic;
/*
/// How HIGH should it bounce (parallel to normal), [0,1]
F32 bounceElasticity;
/// How much momentum should be lost when it bounces (perpendicular to normal), [0,1]
F32 bounceFriction;
*/
/// Should this projectile fall/rise different than a default object?
F32 gravityMod;
/// How long the projectile should exist before deleting itself
U32 lifetime; // ticks
/*
/// How long it should not detonate on impact
S32 armingDelay; // the values are converted on initialization with
*/
S32 fadeDelay; // ticks
/*
ExplosionData* explosion; // Explosion Datablock
S32 explosionId; // Explosion ID
ExplosionData* waterExplosion; // Water Explosion Datablock
S32 waterExplosionId; // Water Explosion ID
*/
SplashData* splash; // Water Splash Datablock
S32 splashId; // Water splash ID
SFXTrack* sound; // Projectile Sound
LightDescription *lightDesc;
S32 lightDescId;
/*
enum DecalConstants { // Number of decals constant
NumDecals = 6,
};
DecalData* decals[NumDecals]; // Decal Datablocks
S32 decalId[NumDecals]; // Decal IDs
U32 decalCount; // # of loaded Decal Datablocks
*/
// variables set on preload:
Resource<TSShape> projectileShape;
/*
S32 activateSeq;
S32 maintainSeq;
*/
ParticleEmitterData* particleEmitter;
S32 particleEmitterId;
ParticleEmitterData* particleWaterEmitter;
S32 particleWaterEmitterId;
U32 collision_mask;
Point3F starting_vel_vec;
// guidance behavior
bool isGuided;
F32 precision;
S32 trackDelay;
// simple physics
F32 ballisticCoefficient;
// terrain following
bool followTerrain;
F32 followTerrainHeight;
F32 followTerrainAdjustRate;
S32 followTerrainAdjustDelay;
F32 acceleration;
S32 accelDelay;
U32 accelLifetime;
StringTableEntry launch_node;
Point3F launch_offset;
Point3F launch_offset_server;
Point3F launch_offset_client;
Point3F launch_node_offset;
F32 launch_pitch;
F32 launch_pan;
bool echo_launch_offset;
StringTableEntry launch_cons_s_spec;
afxConstraintDef launch_cons_s_def;
StringTableEntry launch_cons_c_spec;
afxConstraintDef launch_cons_c_def;
// wiggle behavior
Vector<F32> wiggle_magnitudes;
Vector<F32> wiggle_speeds;
StringTableEntry wiggle_axis_string;
Point3F* wiggle_axis;
U32 wiggle_num_axis;
// hover behavior
F32 hover_altitude;
F32 hover_attack_distance;
F32 hover_attack_gradient;
U32 hover_time;
bool reverse_targeting;
U32 caster_safety_time;
public:
/*C*/ afxMagicMissileData();
/*D*/ ~afxMagicMissileData();
void packData(BitStream*);
void unpackData(BitStream*);
bool preload(bool server, String &errorStr);
static void initPersistFields();
DECLARE_CONOBJECT(afxMagicMissileData);
DECLARE_CATEGORY("AFX");
public:
/*C*/ afxMagicMissileData(const afxMagicMissileData&, bool = false);
afxMagicMissileData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
virtual bool allowSubstitutions() const { return true; }
void gather_cons_defs(Vector<afxConstraintDef>& defs);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxMagicMissile
//class afxMagicSpell;
class afxChoreographer;
class afxMagicMissile : public GameBase, public ISceneLight
{
typedef GameBase Parent;
public:
/*
// Initial conditions
enum ProjectileConstants {
SourceIdTimeoutTicks = 7, // = 231 ms
DeleteWaitTime = 500, ///< 500 ms delete timeout (for network transmission delays)
ExcessVelDirBits = 7,
MaxLivingTicks = 4095,
};
*/
enum UpdateMasks {
/*
BounceMask = Parent::NextFreeMask,
ExplosionMask = Parent::NextFreeMask << 1,
*/
GuideMask = Parent::NextFreeMask << 0,
LaunchMask = Parent::NextFreeMask << 1,
ImpactMask = Parent::NextFreeMask << 2,
NextFreeMask = Parent::NextFreeMask << 3
};
protected:
PhysicsWorld *mPhysicsWorld;
afxMagicMissileData* mDataBlock;
ParticleEmitter* mParticleEmitter;
ParticleEmitter* mParticleWaterEmitter;
SFXSource* mSound;
Point3F mCurrPosition;
Point3F mCurrVelocity;
/*
S32 mSourceObjectId;
S32 mSourceObjectSlot;
*/
// Time related variables common to all projectiles, managed by processTick
U32 mCurrTick; ///< Current time in ticks
/*
SimObjectPtr<ShapeBase> mSourceObject; ///< Actual pointer to the source object, times out after SourceIdTimeoutTicks
*/
// Rendering related variables
TSShapeInstance* mProjectileShape;
/*
TSThread* mActivateThread;
TSThread* mMaintainThread;
Point3F mLastRenderPos;
*/
// ISceneLight
virtual void submitLights( LightManager *lm, bool staticLighting );
virtual LightInfo* getLight() { return mLight; }
LightInfo *mLight;
LightState mLightState;
/*
bool mHidden; ///< set by the derived class, if true, projectile doesn't render
F32 mFadeValue; ///< set in processTick, interpolation between fadeDelay and lifetime
///< in data block
*/
/*
// Warping and back delta variables. Only valid on the client
//
Point3F mWarpStart;
Point3F mWarpEnd;
U32 mWarpTicksRemaining;
*/
Point3F mCurrDeltaBase;
Point3F mCurrBackDelta;
/*
Point3F mExplosionPosition;
Point3F mExplosionNormal;
U32 mCollideHitType;
*/
bool onAdd();
void onRemove();
bool onNewDataBlock(GameBaseData *dptr, bool reload);
// Rendering
virtual void prepRenderImage(SceneRenderState*);
void prepBatchRender( SceneRenderState *state);
void processTick(const Move *move);
/*
void advanceTime(F32 dt);
*/
void interpolateTick(F32 delta);
/*
/// What to do once this projectile collides with something
virtual void onCollision(const Point3F& p, const Point3F& n, SceneObject*);
/// What to do when this projectile explodes
virtual void explode(const Point3F& p, const Point3F& n, const U32 collideType );
/// Returns the velocity of the projectile
Point3F getVelocity() const;
*/
void emitParticles(const Point3F&, const Point3F&, const Point3F&, const U32);
void updateSound();
// Rendering
/*
void prepModelView ( SceneRenderState *state);
*/
// These are stolen from the player class ..
bool pointInWater(const Point3F &point);
U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
void unpackUpdate(NetConnection *conn, BitStream *stream);
afxChoreographer* choreographer;
bool client_only;
bool server_only;
bool use_accel;
U32 collision_mask;
F32 prec_inc;
bool did_launch;
bool did_impact;
SceneObject* missile_target;
SceneObject* collide_exempt;
bool hover_attack_go;
U32 hover_attack_tick;
F32 starting_velocity;
Point3F starting_vel_vec;
SimObject* ss_object;
S32 ss_index;
private:
void init(bool on_server, bool on_client);
void create_splash(const Point3F& pos);
SceneObject* get_default_launcher() const;
void get_launch_constraint_data(Point3F& pos, Point3F& vel);
void get_launch_data(Point3F& pos, Point3F& vel);
bool is_active() const { return (did_launch && !did_impact); }
public:
/*
F32 getUpdatePriority(CameraScopeQuery *focusObject, U32 updateMask, S32 updateSkips);
*/
/*C*/ afxMagicMissile();
/*C*/ afxMagicMissile(bool on_server, bool on_client);
/*D*/ ~afxMagicMissile();
virtual void onDeleteNotify(SimObject*);
DECLARE_CONOBJECT(afxMagicMissile);
DECLARE_CATEGORY("AFX");
static void initPersistFields();
/*
virtual bool calculateImpact(float simTime,
Point3F& pointOfImpact,
float& impactTime);
static U32 smProjectileWarpTicks;
protected:
static const U32 csmStaticCollisionMask;
static const U32 csmDynamicCollisionMask;
static const U32 csmDamageableMask;
*/
void launch();
void setChoreographer(afxChoreographer*);
void setStartingVelocityVector(const Point3F& vel_vec);
void setStartingVelocity(const F32 vel);
void getStartingVelocityValues(F32& vel, Point3F& vel_vec);
void setSubstitutionData(SimObject* obj, S32 idx=0) { ss_object = obj; ss_index = idx; }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxMagicMissileCallback
class afxMagicMissileCallback
{
public:
virtual void impactNotify(const Point3F& p, const Point3F& n, SceneObject*)=0;
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_MAGIC_MISSILE_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,390 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_MAGIC_SPELL_H_
#define _AFX_MAGIC_SPELL_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "core/util/tVector.h"
#include "console/typeValidators.h"
#include "afxChoreographer.h"
#include "afxEffectDefs.h"
#include "afxEffectWrapper.h"
#include "afxMagicMissile.h"
class afxChoreographerData;
class afxMagicMissileData;
class afxEffectWrapperData;
class SceneObject;
class afxMagicSpell;
class afxMagicSpellDefs
{
public:
enum
{
CASTING_PHRASE,
LAUNCH_PHRASE,
DELIVERY_PHRASE,
IMPACT_PHRASE,
LINGER_PHRASE,
NUM_PHRASES
};
};
class afxMagicSpellData : public afxChoreographerData, public afxMagicSpellDefs
{
typedef afxChoreographerData Parent;
class ewValidator : public TypeValidator
{
U32 id;
public:
ewValidator(U32 id) { this->id = id; }
void validateType(SimObject *object, void *typePtr);
};
bool do_id_convert;
public:
F32 casting_dur;
F32 delivery_dur;
F32 linger_dur;
//
S32 n_casting_loops;
S32 n_delivery_loops;
S32 n_linger_loops;
//
F32 extra_casting_time;
F32 extra_delivery_time;
F32 extra_linger_time;
//
bool do_move_interrupts;
F32 move_interrupt_speed;
//
afxMagicMissileData* missile_db;
bool launch_on_server_signal;
U32 primary_target_types;
//
afxEffectWrapperData* dummy_fx_entry;
// various effects lists
afxEffectList casting_fx_list;
afxEffectList launch_fx_list;
afxEffectList delivery_fx_list;
afxEffectList impact_fx_list;
afxEffectList linger_fx_list;
void pack_fx(BitStream* stream, const afxEffectList& fx, bool packed);
void unpack_fx(BitStream* stream, afxEffectList& fx);
public:
/*C*/ afxMagicSpellData();
/*C*/ afxMagicSpellData(const afxMagicSpellData&, bool = false);
virtual void reloadReset();
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool writeField(StringTableEntry fieldname, const char* value);
bool preload(bool server, String &errorStr);
void gatherConstraintDefs(Vector<afxConstraintDef>&);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxMagicSpellData);
DECLARE_CATEGORY("AFX");
/// @name Callbacks
/// @{
DECLARE_CALLBACK( void, onDamage, (afxMagicSpell* spell, const char* label, const char* flaver, U32 target_id, F32 amount, U8 n, Point3F pos, F32 ad_amount, F32 radius, F32 impulse) );
DECLARE_CALLBACK( void, onDeactivate, (afxMagicSpell* spell) );
DECLARE_CALLBACK( void, onInterrupt, (afxMagicSpell* spell, ShapeBase* caster) );
DECLARE_CALLBACK( void, onLaunch, (afxMagicSpell* spell, ShapeBase* caster, SceneObject* target, afxMagicMissile* missile) );
DECLARE_CALLBACK( void, onImpact, (afxMagicSpell* spell, ShapeBase* caster, SceneObject* impacted, Point3F pos, Point3F normal) );
DECLARE_CALLBACK( bool, onPreactivate, (SimObject* param_holder, ShapeBase* caster, SceneObject* target, SimObject* extra) );
DECLARE_CALLBACK( void, onActivate, (afxMagicSpell* spell, ShapeBase* caster, SceneObject* target) );
/// @}
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxMagicSpell
class ShapeBase;
class GameConnection;
class afxEffectVector;
class afxConstraint;
class afxConstraintMgr;
class afxMagicMissile;
class afxChoreographer;
class afxPhrase;
class afxMagicSpell : public afxChoreographer, public afxMagicSpellDefs
{
typedef afxChoreographer Parent;
friend class afxMagicMissile;
enum MaskBits
{
MagicMissileMask = Parent::NextFreeMask << 0,
StateEventMask = Parent::NextFreeMask << 1,
LaunchEventMask = Parent::NextFreeMask << 2,
ImpactEventMask = Parent::NextFreeMask << 3,
SyncEventMask = Parent::NextFreeMask << 4,
RemapConstraintMask = Parent::NextFreeMask << 5, // CONSTRAINT REMAPPING
NextFreeMask = Parent::NextFreeMask << 6
};
public:
enum
{
NULL_EVENT,
ACTIVATE_EVENT,
LAUNCH_EVENT,
IMPACT_EVENT,
SHUTDOWN_EVENT,
DEACTIVATE_EVENT,
INTERRUPT_PHASE_EVENT,
INTERRUPT_SPELL_EVENT
};
enum
{
INACTIVE_STATE,
CASTING_STATE,
DELIVERY_STATE,
LINGER_STATE,
CLEANUP_STATE,
DONE_STATE,
LATE_STATE
};
enum {
MARK_ACTIVATE = BIT(0),
MARK_LAUNCH = BIT(1),
MARK_IMPACT = BIT(2),
MARK_SHUTDOWN = BIT(3),
MARK_DEACTIVATE = BIT(4),
MARK_END_CASTING = BIT(5),
MARK_END_DELIVERY = BIT(6),
MARK_END_LINGER = BIT(7),
MARK_INTERRUPT_CASTING = BIT(8),
MARK_INTERRUPT_DELIVERY = BIT(9),
MARK_INTERRUPT_LINGER = BIT(10),
MARK_INTERRUPT_CLEANUP = BIT(11),
//
MARK_ENDINGS = MARK_END_CASTING | MARK_END_DELIVERY | MARK_END_LINGER,
MARK_INTERRUPTS = MARK_INTERRUPT_CASTING | MARK_INTERRUPT_DELIVERY | MARK_INTERRUPT_LINGER | MARK_INTERRUPT_CLEANUP
};
class ObjectDeleteEvent : public SimEvent
{
public:
void process(SimObject *obj) { if (obj) obj->deleteObject(); }
};
private:
static StringTableEntry CASTER_CONS;
static StringTableEntry TARGET_CONS;
static StringTableEntry MISSILE_CONS;
static StringTableEntry CAMERA_CONS;
static StringTableEntry LISTENER_CONS;
static StringTableEntry IMPACT_POINT_CONS;
static StringTableEntry IMPACTED_OBJECT_CONS;
private:
afxMagicSpellData* datablock;
SimObject* exeblock;
afxMagicMissileData* missile_db;
ShapeBase* caster;
SceneObject* target;
SimObject* caster_field;
SimObject* target_field;
U16 caster_scope_id;
U16 target_scope_id;
bool target_is_shape;
bool constraints_initialized;
bool scoping_initialized;
U8 spell_state;
F32 spell_elapsed;
afxConstraintID listener_cons_id;
afxConstraintID caster_cons_id;
afxConstraintID target_cons_id;
afxConstraintID impacted_cons_id;
afxConstraintID camera_cons_id;
SceneObject* camera_cons_obj;
afxPhrase* phrases[NUM_PHRASES];
F32 tfactors[NUM_PHRASES];
bool notify_castbar;
F32 overall_time_factor;
U16 marks_mask;
private:
void init();
bool state_expired();
F32 state_elapsed();
void init_constraints();
void init_scoping();
void setup_casting_fx();
void setup_launch_fx();
void setup_delivery_fx();
void setup_impact_fx();
void setup_linger_fx();
bool cleanup_over();
bool is_caster_moving();
bool is_caster_client(ShapeBase* caster, GameConnection* conn);
bool is_impact_in_water(SceneObject* obj, const Point3F& p);
protected:
virtual bool remap_builtin_constraint(SceneObject*, const char* cons_name); // CONSTRAINT REMAPPING
virtual void pack_constraint_info(NetConnection* conn, BitStream* stream);
virtual void unpack_constraint_info(NetConnection* conn, BitStream* stream);
private:
afxMagicMissile* missile;
bool missile_is_armed;
SceneObject* impacted_obj;
Point3F impact_pos;
Point3F impact_norm;
U16 impacted_scope_id;
bool impacted_is_shape;
void init_missile_s(afxMagicMissileData* mm);
void launch_missile_s();
void init_missile_c(afxMagicMissileData* mm);
void launch_missile_c();
public:
virtual void impactNotify(const Point3F& p, const Point3F& n, SceneObject*);
virtual void executeScriptEvent(const char* method, afxConstraint*,
const MatrixF& pos, const char* data);
virtual void inflictDamage(const char * label, const char* flavor, SimObjectId target,
F32 amt, U8 count, F32 ad_amt, F32 rad, Point3F pos, F32 imp);
public:
/*C*/ afxMagicSpell();
/*C*/ afxMagicSpell(ShapeBase* caster, SceneObject* target);
/*D*/ ~afxMagicSpell();
// STANDARD OVERLOADED METHODS //
virtual bool onNewDataBlock(GameBaseData* dptr, bool reload);
virtual void processTick(const Move*);
virtual void advanceTime(F32 dt);
virtual bool onAdd();
virtual void onRemove();
virtual void onDeleteNotify(SimObject*);
virtual U32 packUpdate(NetConnection*, U32, BitStream*);
virtual void unpackUpdate(NetConnection*, BitStream*);
virtual void sync_with_clients();
void finish_startup();
static void initPersistFields();
DECLARE_CONOBJECT(afxMagicSpell);
DECLARE_CATEGORY("AFX");
private:
void process_server();
//
void change_state_s(U8 pending_state);
//
void enter_casting_state_s();
void leave_casting_state_s();
void enter_delivery_state_s();
void leave_delivery_state_s();
void enter_linger_state_s();
void leave_linger_state_s();
void enter_done_state_s();
private:
void process_client(F32 dt);
//
void change_state_c(U8 pending_state);
//
void enter_casting_state_c(F32 starttime);
void leave_casting_state_c();
void enter_delivery_state_c(F32 starttime);
void leave_delivery_state_c();
void enter_linger_state_c(F32 starttime);
void leave_linger_state_c();
//
void sync_client(U16 marks, U8 state, F32 state_elapsed, F32 spell_elapsed);
public:
void postSpellEvent(U8 event);
void resolveTimeFactors();
void setTimeFactor(F32 f) { overall_time_factor = (f > 0) ? f : 1.0f; }
F32 getTimeFactor() { return overall_time_factor; }
void setTimeFactor(U8 phase, F32 f) { tfactors[phase] = (f > 0) ? f : 1.0f; }
F32 getTimeFactor(U8 phase) { return tfactors[phase]; }
ShapeBase* getCaster() const { return caster; }
SceneObject* getTarget() const { return target; }
afxMagicMissile* getMissile() const { return missile; }
SceneObject* getImpactedObject() const { return impacted_obj; }
virtual void restoreObject(SceneObject*);
bool activationCallInit(bool postponed=false);
void activate();
public:
static afxMagicSpell* cast_spell(afxMagicSpellData*, ShapeBase* caster, SceneObject* target, SimObject* extra);
static void displayScreenMessage(ShapeBase* caster, const char* msg);
static Point3F getShapeImpactPos(SceneObject*);
};
inline bool afxMagicSpell::is_caster_moving()
{
return (caster) ? (caster->getVelocity().len() > datablock->move_interrupt_speed) : false;
}
inline bool afxMagicSpell::is_caster_client(ShapeBase* caster, GameConnection* conn)
{
return (caster) ? (caster->getControllingClient() == conn) : false;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_MAGIC_SPELL_H_

View file

@ -0,0 +1,196 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "afx/afxEffectVector.h"
#include "afx/afxPhrase.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPhrase
void
afxPhrase::init_fx(S32 group_index)
{
fx->ev_init(init_chor, *init_fx_list, on_server, will_stop, init_time_factor, init_dur, group_index);
}
//~~~~~~~~~~~~~~~~~~~~//
afxPhrase::afxPhrase(bool on_server, bool will_stop)
{
this->on_server = on_server;
this->will_stop = will_stop;
init_fx_list = NULL;
init_dur = 0.0f;
init_chor = NULL;
init_time_factor = 1.0f;
fx = new afxEffectVector;
fx2 = NULL;
starttime = 0;
dur = 0;
n_loops = 1;
loop_cnt = 1;
extra_time = 0.0f;
extra_stoptime = 0.0f;
}
afxPhrase::~afxPhrase()
{
delete fx;
delete fx2;
};
void
afxPhrase::init(afxEffectList& fx_list, F32 dur, afxChoreographer* chor, F32 time_factor,
S32 n_loops, S32 group_index, F32 extra_time)
{
init_fx_list = &fx_list;
init_dur = dur;
init_chor = chor;
init_time_factor = time_factor;
this->n_loops = n_loops;
this->extra_time = extra_time;
this->dur = (init_dur < 0) ? init_dur : init_dur*init_time_factor;
init_fx(group_index);
}
void
afxPhrase::start(F32 startstamp, F32 timestamp)
{
starttime = startstamp;
F32 loopstart = timestamp - startstamp;
if (dur > 0 && loopstart > dur)
{
loop_cnt += (S32) (loopstart/dur);
loopstart = mFmod(loopstart, dur);
}
if (!fx->empty())
fx->start(loopstart);
}
void
afxPhrase::update(F32 dt, F32 timestamp)
{
if (fx->isActive())
fx->update(dt);
if (fx2 && fx2->isActive())
fx2->update(dt);
if (extra_stoptime > 0 && timestamp > extra_stoptime)
{
stop(timestamp);
}
}
void
afxPhrase::stop(F32 timestamp)
{
if (extra_time > 0 && !(extra_stoptime > 0))
{
extra_stoptime = timestamp + extra_time;
return;
}
if (fx->isActive())
fx->stop();
if (fx2 && fx2->isActive())
fx2->stop();
}
bool
afxPhrase::expired(F32 timestamp)
{
if (dur < 0)
return false;
return ((timestamp - starttime) > loop_cnt*dur);
}
F32
afxPhrase::elapsed(F32 timestamp)
{
return (timestamp - starttime);
}
bool
afxPhrase::recycle(F32 timestamp)
{
if (n_loops < 0 || loop_cnt < n_loops)
{
if (fx2)
delete fx2;
fx2 = fx;
fx = new afxEffectVector;
init_fx();
if (fx2 && !fx2->empty())
fx2->stop();
if (!fx->empty())
fx->start(0.0F);
loop_cnt++;
return true;
}
return false;
}
void
afxPhrase::interrupt(F32 timestamp)
{
if (fx->isActive())
fx->interrupt();
if (fx2 && fx2->isActive())
fx2->interrupt();
}
F32 afxPhrase::calcDoneTime()
{
return starttime + fx->getTotalDur();
}
F32 afxPhrase::calcAfterLife()
{
return fx->getAfterLife();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,87 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_PHRASE_H_
#define _AFX_PHRASE_H_
#include "afxEffectVector.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPhrase
class afxChoreographer;
class afxConstraintMgr;
class afxEffectVector;
class afxPhrase
{
protected:
afxEffectList* init_fx_list;
F32 init_dur;
afxChoreographer* init_chor;
F32 init_time_factor;
F32 extra_time;
afxEffectVector* fx;
afxEffectVector* fx2;
bool on_server;
bool will_stop;
F32 starttime;
F32 dur;
S32 n_loops;
S32 loop_cnt;
F32 extra_stoptime;
void init_fx(S32 group_index=0);
public:
/*C*/ afxPhrase(bool on_server, bool will_stop);
virtual ~afxPhrase();
virtual void init(afxEffectList&, F32 dur, afxChoreographer*, F32 time_factor,
S32 n_loops, S32 group_index=0, F32 extra_time=0.0f);
virtual void start(F32 startstamp, F32 timestamp);
virtual void update(F32 dt, F32 timestamp);
virtual void stop(F32 timestamp);
virtual void interrupt(F32 timestamp);
virtual bool expired(F32 timestamp);
virtual bool recycle(F32 timestamp);
virtual F32 elapsed(F32 timestamp);
bool isEmpty() { return fx->empty(); }
bool isInfinite() { return (init_dur < 0); }
F32 calcDoneTime();
F32 calcAfterLife();
bool willStop() { return will_stop; }
bool onServer() { return on_server; }
S32 count() { return fx->count(); }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_PHRASE_H_

View file

@ -0,0 +1,176 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// The afxRenderHighlightMgr class is adapted from the resource,
// "Silhoute selection via postFX for Torque3D" posted by Konrad Kiss.
// http://www.garagegames.com/community/resources/view/17821
// Supporting code mods in other areas of the engine are marked as
// "(selection-highlight)".
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "platform/platform.h"
#include "afxRenderHighlightMgr.h"
#include "scene/sceneManager.h"
#include "scene/sceneRenderState.h"
#include "materials/sceneData.h"
#include "materials/matInstance.h"
//#include "materials/materialFeatureTypes.h"
#include "materials/processedMaterial.h"
#include "postFx/postEffect.h"
#include "gfx/gfxTransformSaver.h"
#include "gfx/gfxDebugEvent.h"
#include "math/util/matrixSet.h"
IMPLEMENT_CONOBJECT( afxRenderHighlightMgr );
afxRenderHighlightMgr::afxRenderHighlightMgr()
: RenderTexTargetBinManager( RenderPassManager::RIT_Mesh,
1.0f,
1.0f,
GFXFormatR8G8B8A8,
Point2I( 512, 512 ) )
{
mNamedTarget.registerWithName( "highlight" );
mTargetSizeType = WindowSize;
}
afxRenderHighlightMgr::~afxRenderHighlightMgr()
{
}
PostEffect* afxRenderHighlightMgr::getSelectionEffect()
{
if ( !mSelectionEffect )
mSelectionEffect = dynamic_cast<PostEffect*>( Sim::findObject( "afxHighlightPostFX" ) );
return mSelectionEffect;
}
bool afxRenderHighlightMgr::isSelectionEnabled()
{
return getSelectionEffect() && getSelectionEffect()->isEnabled();
}
void afxRenderHighlightMgr::addElement( RenderInst *inst )
{
// Skip out if we don't have the selection post
// effect enabled at this time.
if ( !isSelectionEnabled() )
return;
// Skip it if we don't have a selection material.
BaseMatInstance *matInst = getMaterial( inst );
if ( !matInst || !matInst->needsSelectionHighlighting() )
return;
internalAddElement(inst);
}
void afxRenderHighlightMgr::render( SceneRenderState *state )
{
PROFILE_SCOPE( RenderSelectionMgr_Render );
if ( !isSelectionEnabled() )
return;
const U32 binSize = mElementList.size();
// If this is a non-diffuse pass or we have no objects to
// render then tell the effect to skip rendering.
if ( !state->isDiffusePass() || binSize == 0 )
{
getSelectionEffect()->setSkip( true );
return;
}
GFXDEBUGEVENT_SCOPE( RenderSelectionMgr_Render, ColorI::GREEN );
GFXTransformSaver saver;
// Tell the superclass we're about to render, preserve contents
const bool isRenderingToTarget = _onPreRender( state, true );
// Clear all the buffers to black.
//GFX->clear( GFXClearTarget, ColorI::BLACK, 1.0f, 0);
GFX->clear( GFXClearTarget, ColorI::ZERO, 1.0f, 0);
// Restore transforms
MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
matrixSet.restoreSceneViewProjection();
// init loop data
SceneData sgData;
sgData.init( state, SceneData::HighlightBin );
for( U32 j=0; j<binSize; )
{
MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst);
setupSGData( ri, sgData );
BaseMatInstance *mat = ri->matInst;
U32 matListEnd = j;
while( mat && mat->setupPass( state, sgData ) )
{
U32 a;
for( a=j; a<binSize; a++ )
{
MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst);
if ( newPassNeeded( ri, passRI ) )
break;
matrixSet.setWorld(*passRI->objectToWorld);
matrixSet.setView(*passRI->worldToCamera);
matrixSet.setProjection(*passRI->projection);
mat->setTransforms(matrixSet, state);
mat->setSceneInfo(state, sgData);
mat->setBuffers(passRI->vertBuff, passRI->primBuff);
if ( passRI->prim )
GFX->drawPrimitive( *passRI->prim );
else
GFX->drawPrimitive( passRI->primBuffIndex );
}
matListEnd = a;
setupSGData( ri, sgData );
}
// force increment if none happened, otherwise go to end of batch
j = ( j == matListEnd ) ? j+1 : matListEnd;
}
// Finish up.
if ( isRenderingToTarget )
_onPostRender();
// Make sure the effect is gonna render.
getSelectionEffect()->setSkip( false );
}

View file

@ -0,0 +1,76 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// The afxRenderHighlightMgr class is adapted from the resource,
// "Silhoute selection via postFX for Torque3D" posted by Konrad Kiss.
// http://www.garagegames.com/community/resources/view/17821
// Supporting code mods in other areas of the engine are marked as
// "(selection-highlight)".
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _afxRENDERHIGHLIGHTMGR_H_
#define _afxRENDERHIGHLIGHTMGR_H_
#ifndef _TEXTARGETBIN_MGR_H_
#include "renderInstance/renderTexTargetBinManager.h"
#endif
class PostEffect;
///
class afxRenderHighlightMgr : public RenderTexTargetBinManager
{
typedef RenderTexTargetBinManager Parent;
public:
afxRenderHighlightMgr();
virtual ~afxRenderHighlightMgr();
/// Returns the selection post effect.
PostEffect* getSelectionEffect();
/// Returns true if the highlight post effect is
/// enabled and the selection buffer should be updated.
bool isSelectionEnabled();
// RenderBinManager
virtual void addElement( RenderInst *inst );
virtual void render( SceneRenderState *state );
// ConsoleObject
DECLARE_CONOBJECT( afxRenderHighlightMgr );
protected:
SimObjectPtr<PostEffect> mSelectionEffect;
};
#endif // _afxRENDERHIGHLIGHTMGR_H_

View file

@ -0,0 +1,469 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "ts/tsShapeInstance.h"
#include "afx/ce/afxZodiacMgr.h"
#include "afx/ce/afxModel.h"
#include "afx/afxResidueMgr.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
int QSORT_CALLBACK afxResidueMgr::ResidueList::compare_residue(const void* p1, const void* p2)
{
const afxResidueMgr::Residue** pd1 = (const afxResidueMgr::Residue**)p1;
const afxResidueMgr::Residue** pd2 = (const afxResidueMgr::Residue**)p2;
return int(((char*)(*pd1)->data.simobject) - ((char*)(*pd2)->data.simobject));
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
inline void afxResidueMgr::ResidueList::swap_array_ptrs()
{
Vector<Residue*>* tmp = m_array;
m_array = m_scratch_array;
m_scratch_array = tmp;
}
void afxResidueMgr::ResidueList::free_residue(Residue* residue)
{
if (the_mgr == NULL)
return;
if (the_mgr->requires_delete_tracking(residue))
the_mgr->disable_delete_tracking(residue);
the_mgr->free_residue(residue);
}
afxResidueMgr::ResidueList::ResidueList()
{
VECTOR_SET_ASSOCIATION(m_array_a);
VECTOR_SET_ASSOCIATION(m_array_b);
m_array = &m_array_a;
m_scratch_array = &m_array_b ;
m_dirty = false;
m_pending = -1;
}
afxResidueMgr::ResidueList::~ResidueList()
{
clear();
}
void afxResidueMgr::ResidueList::clear()
{
if (the_mgr)
{
for (S32 i = 0; i < m_array->size(); i++)
{
Residue* r = (*m_array)[i];
the_mgr->free_residue(r);
}
}
m_array_a.clear();
m_array_b.clear();
}
void afxResidueMgr::ResidueList::sort()
{
dQsort(m_array->address(), m_array->size(), sizeof(Residue*), compare_residue);
m_dirty = false;
}
void afxResidueMgr::ResidueList::fadeAndCull(U32 now)
{
for (S32 i = 0; i < m_array->size(); i++)
{
Residue* r = (*m_array)[i];
// done
if (now >= r->stop_time)
{
free_residue(r);
}
// fading
else if (now >= r->fade_time)
{
r->fade = 1.0f - ((F32)(now - r->fade_time))/((F32)(r->stop_time - r->fade_time));
m_scratch_array->push_back(r);
}
// opaque
else
{
r->fade = 1.0f;
m_scratch_array->push_back(r);
}
}
m_array->clear();
swap_array_ptrs();
}
// removes all residue with datablock matching obj
void afxResidueMgr::ResidueList::stripMatchingObjects(SimObject* db, bool del_notify)
{
if (del_notify)
{
for (S32 i = 0; i < m_array->size(); i++)
{
Residue* r = (*m_array)[i];
if (db == r->data.simobject && the_mgr != NULL)
the_mgr->free_residue(r);
else
m_scratch_array->push_back(r);
}
}
else
{
for (S32 i = 0; i < m_array->size(); i++)
{
Residue* r = (*m_array)[i];
if (db == r->data.simobject)
free_residue(r);
else
m_scratch_array->push_back(r);
}
}
m_array->clear();
swap_array_ptrs();
}
void afxResidueMgr::ResidueList::add(Residue* residue)
{
m_array->push_back(residue);
m_dirty = true;
}
void afxResidueMgr::manage_residue(const Residue* r)
{
if (r == NULL || r->fade < 0.01f)
return;
if (r->type == ZODIAC)
{
LinearColorF zode_color = ColorI(r->params.zodiac.r, r->params.zodiac.g, r->params.zodiac.b, r->params.zodiac.a);
afxZodiacData* zd = (afxZodiacData*) r->data.zodiac;
if (zd->blend_flags == afxZodiacDefs::BLEND_SUBTRACTIVE)
zode_color *= r->fade;
else
zode_color.alpha *= r->fade;
Point3F zode_pos(r->params.zodiac.pos_x, r->params.zodiac.pos_y, r->params.zodiac.pos_z);
Point2F zode_vrange(r->params.zodiac.vrange_dn, r->params.zodiac.vrange_dn);
if (r->params.zodiac.on_terrain)
{
afxZodiacMgr::addTerrainZodiac(zode_pos, r->params.zodiac.rad, zode_color, r->params.zodiac.ang, zd);
}
else
{
afxZodiacMgr::addInteriorZodiac(zode_pos, r->params.zodiac.rad, zode_vrange, zode_color, r->params.zodiac.ang, zd);
}
}
else if (r->type == MODEL)
{
r->data.model->setFadeAmount(r->fade);
}
}
void afxResidueMgr::ResidueList::manage()
{
if (the_mgr == NULL)
return;
S32 n_residue = m_array->size();
for (S32 x = 0; x < n_residue; x++)
the_mgr->manage_residue((*m_array)[x]);
}
U32 afxResidueMgr::ResidueList::findPendingBestBump(U32 look_max)
{
U32 soonest = 1000*60*60*24;
m_pending = -1;
U32 n = m_array->size();
for (U32 i = 0; i < n && i < look_max; i++)
{
Residue* r = (*m_array)[i];
if (r->stop_time < soonest)
{
soonest = r->stop_time;
m_pending = i;
}
}
return soonest;
}
void afxResidueMgr::ResidueList::bumpPending()
{
if (m_pending >= 0 && m_pending < m_array->size())
{
Residue* r = (*m_array)[m_pending];
m_array->erase(m_pending);
free_residue(r);
}
m_pending = -1;
}
bool afxResidueMgr::requires_delete_tracking(Residue* r)
{
return (r->type == MODEL);
}
void afxResidueMgr::enable_delete_tracking(Residue* r)
{
deleteNotify(r->data.simobject);
}
void afxResidueMgr::disable_delete_tracking(Residue* r)
{
clearNotify(r->data.simobject);
r->data.simobject->deleteObject();
r->data.simobject = 0;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
afxResidueMgr* afxResidueMgr::the_mgr = NULL;
U32 afxResidueMgr::m_max_residue_objs = 256;
bool afxResidueMgr::enabled = true;
IMPLEMENT_CONOBJECT(afxResidueMgr);
ConsoleDocClass( afxResidueMgr,
"@brief A class that manages certain AFX effects that can persist for long durations.\n\n"
"A class that manages certain AFX effects that can persist much longer than the duration of choreographers.\n"
"@ingroup AFX\n"
);
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// free-list management
afxResidueMgr::Residue* afxResidueMgr::alloc_free_pool_block()
{
// allocate new block for the free-list
m_free_pool_blocks.push_back(new Residue[FREE_POOL_BLOCK_SIZE]);
// link them onto the free-list
Residue* new_block = m_free_pool_blocks.last();
for (U32 i = 0; i < FREE_POOL_BLOCK_SIZE - 1; i++)
new_block[i].next = &new_block[i + 1];
// tail of free-list points to NULL
new_block[FREE_POOL_BLOCK_SIZE - 1].next = NULL;
return new_block;
}
afxResidueMgr::Residue* afxResidueMgr::alloc_residue()
{
// need new free-list-block if m_next_free is null
if (!m_next_free)
m_next_free = alloc_free_pool_block();
// pop new residue from head of free-list
Residue* residue = m_next_free;
m_next_free = residue->next;
residue->next = NULL;
return residue;
}
void afxResidueMgr::free_residue(Residue* residue)
{
if (residue && residue->type == ZODIAC)
{
if (residue->data.zodiac && residue->data.zodiac->isTempClone())
{
delete residue->data.zodiac;
residue->data.zodiac = 0;
}
}
// push residue onto head of free-list
residue->next = m_next_free;
m_next_free = residue;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxResidueMgr::deleteResidueObject(SimObject* obj, bool del_notify)
{
m_managed.stripMatchingObjects(obj, del_notify);
}
void afxResidueMgr::bump_residue()
{
if (m_managed.findPendingBestBump())
m_managed.bumpPending();
}
void afxResidueMgr::add_residue(Residue* residue)
{
AssertFatal(residue != NULL, "residue pointer is NULL.");
if (m_managed.size() >= m_max_residue_objs)
bump_residue();
m_managed.add(residue);
manage_residue(residue);
if (requires_delete_tracking(residue))
enable_delete_tracking(residue);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
afxResidueMgr::afxResidueMgr()
{
mObjBox.minExtents.set(-1e7, -1e7, -1e7);
mObjBox.maxExtents.set( 1e7, 1e7, 1e7);
mWorldBox.minExtents.set(-1e7, -1e7, -1e7);
mWorldBox.maxExtents.set( 1e7, 1e7, 1e7);
m_next_free = NULL;
VECTOR_SET_ASSOCIATION(m_free_pool_blocks);
}
afxResidueMgr::~afxResidueMgr()
{
cleanup();
}
void afxResidueMgr::cleanup()
{
m_managed.clear();
m_next_free = NULL;
for (S32 i = 0; i < m_free_pool_blocks.size(); i++)
delete [] m_free_pool_blocks[i];
m_free_pool_blocks.clear();
}
void afxResidueMgr::onDeleteNotify(SimObject* obj)
{
deleteResidueObject(obj, true);
Parent::onDeleteNotify(obj);
}
void afxResidueMgr::residueAdvanceTime()
{
U32 now = Platform::getVirtualMilliseconds();
m_managed.fadeAndCull(now);
m_managed.sortIfDirty();
m_managed.manage();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// add ZODIAC residue
void afxResidueMgr::add_interior_zodiac(F32 dur, F32 fade_dur, afxZodiacData* zode, const Point3F& pos,
F32 rad, const Point2F& vrange, const LinearColorF& col, F32 ang)
{
add_zodiac(dur, fade_dur, zode, pos, rad, vrange, col, ang, false);
}
void afxResidueMgr::add_terrain_zodiac(F32 dur, F32 fade_dur, afxZodiacData* zode, const Point3F& pos,
F32 rad, const LinearColorF& col, F32 ang)
{
static Point2F vrange(0.0, 0.0);
add_zodiac(dur, fade_dur, zode, pos, rad, vrange, col, ang, true);
}
void afxResidueMgr::add_zodiac(F32 dur, F32 fade_dur, afxZodiacData* zode, const Point3F& pos,
F32 rad, const Point2F& vrange, const LinearColorF& col, F32 ang, bool on_terrain)
{
if (m_max_residue_objs == 0 || dur <= 0 || the_mgr == NULL)
return;
ColorI col_i = LinearColorF(col).toColorI();
U32 now = Platform::getVirtualMilliseconds();
Residue* residue = the_mgr->alloc_residue();
//
residue->type = ZODIAC;
residue->data.zodiac = zode;
residue->fade_time = now + (U32)(dur*1000);
residue->stop_time = residue->fade_time + (U32)(fade_dur*1000);
residue->fade = 1.0f;
//
residue->params.zodiac.pos_x = pos.x;
residue->params.zodiac.pos_y = pos.y;
residue->params.zodiac.pos_z = pos.z;
residue->params.zodiac.rad = rad;
residue->params.zodiac.vrange_dn = vrange.x;
residue->params.zodiac.vrange_up = vrange.y;
residue->params.zodiac.r = col_i.red;
residue->params.zodiac.g = col_i.green;
residue->params.zodiac.b = col_i.blue;
residue->params.zodiac.a = col_i.alpha;
residue->params.zodiac.ang = ang;
residue->params.zodiac.on_terrain = on_terrain;
//
residue->next = 0;
the_mgr->add_residue(residue);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// add MODEL residue
void afxResidueMgr::add(F32 dur, F32 fade_dur, afxModel* model)
{
if (m_max_residue_objs == 0 || dur <= 0 || the_mgr == NULL)
return;
U32 now = Platform::getVirtualMilliseconds();
Residue* residue = the_mgr->alloc_residue();
//
residue->type = MODEL;
residue->data.model = model;
residue->fade_time = now + (U32)(dur*1000);
residue->stop_time = residue->fade_time + (U32)(fade_dur*1000);
residue->fade = 1.0f;
//
residue->next = 0;
the_mgr->add_residue(residue);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,179 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_RESIDUE_MGR_H_
#define _AFX_RESIDUE_MGR_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxZodiacData;
class afxModel;
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxResidueMgr
//
// Manage transient objects in the world.
class afxResidueMgr : public GameBase
{
typedef GameBase Parent;
enum {
ZODIAC,
MODEL
};
struct Residue
{
struct ZodiacParams
{
F32 pos_x, pos_y, pos_z;
F32 rad, vrange_dn, vrange_up;
U8 r,g,b,a;
F32 ang;
bool on_terrain;
};
union ResidueParams
{
ZodiacParams zodiac;
};
union ResidueData
{
afxZodiacData* zodiac;
afxModel* model;
SimObject* simobject;
};
U32 type;
ResidueData data;
ResidueParams params;
U32 fade_time;
U32 stop_time;
F32 fade;
Residue* next;
};
class ResidueList
{
Vector<Residue*> m_array_a;
Vector<Residue*> m_array_b;
Vector<Residue*>* m_array;
Vector<Residue*>* m_scratch_array;
bool m_dirty;
S32 m_pending;
void swap_array_ptrs();
void free_residue(Residue*);
public:
/*C*/ ResidueList();
/*D*/ ~ResidueList();
void clear();
S32 size() { return m_array->size(); }
bool empty() { return m_array->empty(); }
void sortIfDirty() { if (m_dirty) sort(); }
void sort();
void fadeAndCull(U32 now);
void stripMatchingObjects(SimObject* db, bool del_notify=false);
void add(Residue*);
void manage();
U32 findPendingBestBump(U32 look_max=256);
void bumpPending();
static int QSORT_CALLBACK compare_residue(const void* p1, const void* p2);
};
friend class ResidueList;
private:
enum { FREE_POOL_BLOCK_SIZE = 256 };
static afxResidueMgr* the_mgr;
static U32 m_max_residue_objs;
static bool enabled;
ResidueList m_managed;
Vector<Residue*> m_free_pool_blocks;
Residue* m_next_free;
Residue* alloc_free_pool_block();
Residue* alloc_residue();
void free_residue(Residue*);
void bump_residue();
void add_residue(Residue*);
static void add_zodiac(F32 dur, F32 fade_dur, afxZodiacData*, const Point3F& pos, F32 rad,
const Point2F& vrange, const LinearColorF& col, F32 ang, bool on_terrain);
protected:
void deleteResidueObject(SimObject* obj, bool del_notify=false);
void manage_residue(const Residue* r);
bool requires_delete_tracking(Residue*);
void enable_delete_tracking(Residue*);
void disable_delete_tracking(Residue*);
public:
/*C*/ afxResidueMgr();
/*D*/ ~afxResidueMgr();
void cleanup();
virtual void onDeleteNotify(SimObject *obj);
public:
void residueAdvanceTime();
// ZODIAC
static void add_terrain_zodiac(F32 dur, F32 fade_dur, afxZodiacData*, const Point3F& pos, F32 rad,
const LinearColorF& col, F32 ang);
static void add_interior_zodiac(F32 dur, F32 fade_dur, afxZodiacData*, const Point3F& pos, F32 rad,
const Point2F& vrange, const LinearColorF& col, F32 ang);
// MODEL
static void add(F32 dur, F32 fade_dur, afxModel*);
static afxResidueMgr* getMaster() { return the_mgr; }
static void setMaster(afxResidueMgr* m) { the_mgr = m; }
DECLARE_CONOBJECT(afxResidueMgr);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_RESIDUE_MGR_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,258 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_SELECTION_EFFECT_H_
#define _AFX_SELECTION_EFFECT_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "console/typeValidators.h"
#include "afxChoreographer.h"
#include "afxEffectWrapper.h"
#include "afxPhrase.h"
class afxChoreographerData;
class afxEffectBaseData;
class afxSelectronDefs
{
public:
enum {
MAIN_PHRASE,
SELECT_PHRASE,
DESELECT_PHRASE,
NUM_PHRASES
};
};
class afxSelectronData : public afxChoreographerData, public afxSelectronDefs
{
typedef afxChoreographerData Parent;
class ewValidator : public TypeValidator
{
U32 id;
public:
ewValidator(U32 id) { this->id = id; }
void validateType(SimObject *object, void *typePtr);
};
bool do_id_convert;
public:
F32 main_dur;
F32 select_dur;
F32 deselect_dur;
S32 n_main_loops;
S32 n_select_loops;
S32 n_deselect_loops;
bool registered;
U8 obj_type_style;
U32 obj_type_mask;
afxEffectBaseData* dummy_fx_entry;
afxEffectList main_fx_list;
afxEffectList select_fx_list;
afxEffectList deselect_fx_list;
private:
void pack_fx(BitStream* stream, const afxEffectList& fx, bool packed);
void unpack_fx(BitStream* stream, afxEffectList& fx);
public:
/*C*/ afxSelectronData();
/*C*/ afxSelectronData(const afxSelectronData&, bool = false);
/*D*/ ~afxSelectronData();
virtual void reloadReset();
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
bool preload(bool server, String &errorStr);
bool matches(U32 mask, U8 style);
void gatherConstraintDefs(Vector<afxConstraintDef>&);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxSelectronData);
DECLARE_CATEGORY("AFX");
};
inline bool afxSelectronData::matches(U32 mask, U8 style)
{
if (obj_type_style != style)
return false;
if (obj_type_mask == 0 && mask == 0)
return true;
return ((obj_type_mask & mask) != 0);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxSelectron
class afxSelectron : public afxChoreographer, public afxSelectronDefs
{
typedef afxChoreographer Parent;
friend class arcaneFX;
public:
enum MaskBits
{
StateEventMask = Parent::NextFreeMask << 0,
SyncEventMask = Parent::NextFreeMask << 1,
NextFreeMask = Parent::NextFreeMask << 2
};
enum
{
NULL_EVENT,
ACTIVATE_EVENT,
SHUTDOWN_EVENT,
DEACTIVATE_EVENT,
INTERRUPT_EVENT
};
enum
{
INACTIVE_STATE,
ACTIVE_STATE,
CLEANUP_STATE,
DONE_STATE,
LATE_STATE
};
enum {
MARK_ACTIVATE = BIT(0),
MARK_SHUTDOWN = BIT(1),
MARK_DEACTIVATE = BIT(2),
MARK_INTERRUPT = BIT(3),
};
class ObjectDeleteEvent : public SimEvent
{
public:
void process(SimObject *obj) { if (obj) obj->deleteObject(); }
};
private:
static StringTableEntry CAMERA_CONS;
static StringTableEntry LISTENER_CONS;
static StringTableEntry FREE_TARGET_CONS;
private:
afxSelectronData* datablock;
SimObject* exeblock;
bool constraints_initialized;
bool client_only;
U8 effect_state;
F32 effect_elapsed;
afxConstraintID listener_cons_id;
afxConstraintID free_target_cons_id;
afxConstraintID camera_cons_id;
SceneObject* camera_cons_obj;
afxPhrase* phrases[NUM_PHRASES];
F32 time_factor;
U8 marks_mask;
private:
void init();
bool state_expired();
void init_constraints();
void setup_main_fx();
void setup_select_fx();
void setup_deselect_fx();
bool cleanup_over();
public:
/*C*/ afxSelectron();
/*C*/ afxSelectron(bool not_default);
/*D*/ ~afxSelectron();
// STANDARD OVERLOADED METHODS //
virtual bool onNewDataBlock(GameBaseData* dptr, bool reload);
virtual void processTick(const Move*);
virtual void advanceTime(F32 dt);
virtual bool onAdd();
virtual void onRemove();
virtual U32 packUpdate(NetConnection*, U32, BitStream*);
virtual void unpackUpdate(NetConnection*, BitStream*);
virtual void sync_with_clients();
void finish_startup();
DECLARE_CONOBJECT(afxSelectron);
DECLARE_CATEGORY("AFX");
private:
void process_server();
//
void change_state_s(U8 pending_state);
//
void enter_active_state_s();
void leave_active_state_s();
void enter_cleanup_state_s();
void enter_done_state_s();
private:
void process_client(F32 dt);
//
void change_state_c(U8 pending_state);
//
void enter_active_state_c(F32 starttime);
void enter_cleanup_state_c();
void enter_done_state_c();
void leave_active_state_c();
void sync_client(U16 marks, U8 state, F32 elapsed);
public:
void postEvent(U8 event);
void setTimeFactor(F32 f) { time_factor = (f > 0) ? f : 1.0f; }
F32 getTimeFactor() { return time_factor; }
void activate();
public:
static afxSelectron* start_selectron(SceneObject* picked, U8 subcode, SimObject* extra);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_SELECTION_EFFECT_H_

View file

@ -0,0 +1,357 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/engineAPI.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "T3D/gameBase/gameBase.h"
#include "afx/afxSpellBook.h"
#include "afx/afxMagicSpell.h"
#include "afx/rpg/afxRPGMagicSpell.h"
#include "afx/ui/afxSpellButton.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxSpellBookData
IMPLEMENT_CO_DATABLOCK_V1(afxSpellBookData);
ConsoleDocClass( afxSpellBookData,
"@brief A spellbook datablock.\n\n"
"@ingroup afxMisc\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxSpellBookData::afxSpellBookData()
{
spells_per_page = 12;
pages_per_book = 12;
dMemset(spells, 0, sizeof(spells));
dMemset(rpg_spells, 0, sizeof(rpg_spells));
// marked true if datablock ids need to
// be converted into pointers
do_id_convert = false;
}
#define myOffset(field) Offset(field, afxSpellBookData)
void afxSpellBookData::initPersistFields()
{
addField("spellsPerPage", TypeS8, myOffset(spells_per_page),
"...");
addField("pagesPerBook", TypeS8, myOffset(pages_per_book),
"...");
addField("spells", TYPEID<GameBaseData>(), myOffset(spells), MAX_PAGES_PER_BOOK*MAX_SPELLS_PER_PAGE,
"...");
addField("rpgSpells", TYPEID<GameBaseData>(), myOffset(rpg_spells), MAX_PAGES_PER_BOOK*MAX_SPELLS_PER_PAGE,
"...");
Parent::initPersistFields();
}
bool afxSpellBookData::preload(bool server, String &errorStr)
{
if (!Parent::preload(server, errorStr))
return false;
// Resolve objects transmitted from server
if (!server)
{
if (do_id_convert)
{
for (S32 i = 0; i < pages_per_book*spells_per_page; i++)
{
SimObjectId db_id = SimObjectId((uintptr_t)rpg_spells[i]);
if (db_id != 0)
{
// try to convert id to pointer
if (!Sim::findObject(db_id, rpg_spells[i]))
{
Con::errorf(ConsoleLogEntry::General,
"afxSpellBookData::preload() -- bad datablockId: 0x%x (afxRPGMagicSpellData)",
db_id);
}
}
}
do_id_convert = false;
}
}
return true;
}
void afxSpellBookData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(spells_per_page);
stream->write(pages_per_book);
for (S32 i = 0; i < pages_per_book*spells_per_page; i++)
writeDatablockID(stream, rpg_spells[i], packed);
}
void afxSpellBookData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&spells_per_page);
stream->read(&pages_per_book);
do_id_convert = true;
for (S32 i = 0; i < pages_per_book*spells_per_page; i++)
rpg_spells[i] = (afxRPGMagicSpellData*) readDatablockID(stream);
}
DefineEngineMethod(afxSpellBookData, getPageSlotIndex, S32, (Point2I bookSlot),,
"...\n\n"
"@ingroup AFX")
{
return object->getPageSlotIndex(bookSlot.x, bookSlot.y);
}
DefineEngineMethod(afxSpellBookData, getCapacity, S32, (),,
"Get the capacity (total number of spell slots) in a spellbook.\n\n"
"@ingroup AFX")
{
return object->spells_per_page*object->pages_per_book;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxSpellBook
IMPLEMENT_CO_NETOBJECT_V1(afxSpellBook);
ConsoleDocClass( afxSpellBook,
"@brief A spellbook object.\n\n"
"@ingroup afxMisc\n"
"@ingroup AFX\n"
);
afxSpellBook::afxSpellBook()
{
mNetFlags.set(Ghostable | ScopeAlways);
mDataBlock = NULL;
all_spell_cooldown = 1.0f;
}
afxSpellBook::~afxSpellBook()
{
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
void afxSpellBook::initPersistFields()
{
Parent::initPersistFields();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
void afxSpellBook::processTick(const Move* m)
{
Parent::processTick(m);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
void afxSpellBook::advanceTime(F32 dt)
{
Parent::advanceTime(dt);
if (all_spell_cooldown < 1.0f)
{
all_spell_cooldown += dt/2.0f;
if (all_spell_cooldown > 1.0f)
all_spell_cooldown = 1.0f;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
bool afxSpellBook::onNewDataBlock(GameBaseData* dptr, bool reload)
{
mDataBlock = dynamic_cast<afxSpellBookData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
return false;
scriptOnNewDataBlock();
return true;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
bool afxSpellBook::onAdd()
{
if (!Parent::onAdd())
return(false);
return(true);
}
void afxSpellBook::onRemove()
{
Parent::onRemove();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
U32 afxSpellBook::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
{
U32 retMask = Parent::packUpdate(con, mask, stream);
if (stream->writeFlag(mask & InitialUpdateMask))
{
}
// AllSpellCooldown
if (stream->writeFlag(mask & AllSpellCooldownMask))
{
}
return(retMask);
}
void afxSpellBook::unpackUpdate(NetConnection * con, BitStream * stream)
{
Parent::unpackUpdate(con, stream);
// InitialUpdate
if (stream->readFlag())
{
}
// AllSpellCooldown
if (stream->readFlag())
{
all_spell_cooldown = 0.0f;
}
}
#define SPELL_DATA_NOT_FOUND "\n<just:center><font:Arial:20><color:FF0000>** Spell data not found **\n\n\n\n"
char* afxSpellBook::formatDesc(char* buffer, int len, S32 page, S32 slot) const
{
S32 idx = mDataBlock->getPageSlotIndex(page, slot);
if (idx < 0 || !mDataBlock->rpg_spells[idx])
return SPELL_DATA_NOT_FOUND;
return mDataBlock->rpg_spells[idx]->formatDesc(buffer, len);
}
const char* afxSpellBook::getSpellIcon(S32 page, S32 slot) const
{
S32 idx = mDataBlock->getPageSlotIndex(page, slot);
if (idx < 0 || !mDataBlock->rpg_spells[idx])
return 0;
return mDataBlock->rpg_spells[idx]->icon_name;
}
bool afxSpellBook::isPlaceholder(S32 page, S32 slot) const
{
S32 idx = mDataBlock->getPageSlotIndex(page, slot);
if (idx < 0 || !mDataBlock->rpg_spells[idx])
return false;
return mDataBlock->rpg_spells[idx]->is_placeholder;
}
afxMagicSpellData* afxSpellBook::getSpellData(S32 page, S32 slot)
{
S32 idx = mDataBlock->getPageSlotIndex(page, slot);
if (idx < 0 || !mDataBlock->spells[idx])
return 0;
return mDataBlock->spells[idx];
}
afxRPGMagicSpellData* afxSpellBook::getSpellRPGData(S32 page, S32 slot)
{
S32 idx = mDataBlock->getPageSlotIndex(page, slot);
if (idx < 0 || !mDataBlock->rpg_spells[idx])
return 0;
return mDataBlock->rpg_spells[idx];
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxSpellBook::startAllSpellCooldown()
{
//all_spell_cooldown = 0.0f;
setMaskBits(AllSpellCooldownMask);
}
F32 afxSpellBook::getCooldownFactor(S32 page, S32 slot)
{
return all_spell_cooldown;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
DefineEngineMethod(afxSpellBook, getPageSlotIndex, S32, (Point2I bookSlot),,
"...\n\n"
"@ingroup AFX")
{
return object->getPageSlotIndex(bookSlot.x, bookSlot.y);
}
DefineEngineMethod(afxSpellBook, getSpellData, S32, (Point2I bookSlot),,
"Get spell datablock for spell stored at spellbook index, (page, slot).\n\n"
"@ingroup AFX")
{
afxMagicSpellData* spell_data = object->getSpellData(bookSlot.x, bookSlot.y);
return (spell_data) ? spell_data->getId() : 0;
}
DefineEngineMethod(afxSpellBook, getSpellRPGData, S32, (Point2I bookSlot),,
"Get spell RPG datablock for spell stored at spellbook index, (page, slot).\n\n"
"@ingroup AFX")
{
afxRPGMagicSpellData* spell_data = object->getSpellRPGData(bookSlot.x, bookSlot.y);
return (spell_data) ? spell_data->getId() : 0;
}
DefineEngineMethod(afxSpellBook, startAllSpellCooldown, void, (),,
"...\n\n"
"@ingroup AFX")
{
object->startAllSpellCooldown();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,142 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_SPELL_BOOK_H_
#define _AFX_SPELL_BOOK_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "T3D/gameBase/gameBase.h"
class afxSpellBookDefs
{
public:
enum {
MAX_SPELLS_PER_PAGE = 12,
MAX_PAGES_PER_BOOK = 12
};
};
class afxMagicSpellData;
class afxRPGMagicSpellData;
class afxSpellBookData : public GameBaseData, public afxSpellBookDefs
{
typedef GameBaseData Parent;
bool do_id_convert;
public:
U8 spells_per_page;
U8 pages_per_book;
afxMagicSpellData* spells[MAX_PAGES_PER_BOOK*MAX_SPELLS_PER_PAGE];
afxRPGMagicSpellData* rpg_spells[MAX_PAGES_PER_BOOK*MAX_SPELLS_PER_PAGE];
public:
/*C*/ afxSpellBookData();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
bool preload(bool server, String &errorStr);
bool verifyPageSlot(S32 page, S32 slot);
S32 getPageSlotIndex(S32 page, S32 slot);
static void initPersistFields();
DECLARE_CONOBJECT(afxSpellBookData);
DECLARE_CATEGORY("AFX");
};
inline bool afxSpellBookData::verifyPageSlot(S32 page, S32 slot)
{
return (page >= 0 && page < pages_per_book && slot >= 0 && slot < spells_per_page);
}
inline S32 afxSpellBookData::getPageSlotIndex(S32 page, S32 slot)
{
return (verifyPageSlot(page, slot)) ? page*spells_per_page + slot : -1;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxMagicSpellData;
class afxSpellButton;
class afxSpellBook : public GameBase, public afxSpellBookDefs
{
typedef GameBase Parent;
enum MaskBits
{
AllSpellCooldownMask = Parent::NextFreeMask << 0,
NextFreeMask = Parent::NextFreeMask << 1
};
private:
afxSpellBookData* mDataBlock;
F32 all_spell_cooldown;
public:
/*C*/ afxSpellBook();
/*D*/ ~afxSpellBook();
virtual bool onNewDataBlock(GameBaseData* dptr, bool reload);
virtual void processTick(const Move*);
virtual void advanceTime(F32 dt);
virtual bool onAdd();
virtual void onRemove();
virtual U32 packUpdate(NetConnection*, U32, BitStream*);
virtual void unpackUpdate(NetConnection*, BitStream*);
static void initPersistFields();
S32 getPageSlotIndex(S32 page, S32 slot);
char* formatDesc(char* buffer, int len, S32 page, S32 slot) const;
const char* getSpellIcon(S32 page, S32 slot) const;
bool isPlaceholder(S32 page, S32 slot) const;
afxMagicSpellData* getSpellData(S32 page, S32 slot);
afxRPGMagicSpellData* getSpellRPGData(S32 page, S32 slot);
void startAllSpellCooldown();
F32 getCooldownFactor(S32 page, S32 slot);
DECLARE_CONOBJECT(afxSpellBook);
DECLARE_CATEGORY("AFX");
};
inline S32 afxSpellBook::getPageSlotIndex(S32 page, S32 slot)
{
return (mDataBlock) ? mDataBlock->getPageSlotIndex(page, slot) : -1;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_SPELL_BOOK_H_

View file

@ -0,0 +1,311 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "materials/shaderData.h"
#include "gfx/gfxTransformSaver.h"
#include "scene/sceneRenderState.h"
#include "collision/concretePolyList.h"
#include "T3D/tsStatic.h"
#include "gfx/primBuilder.h"
#include "afx/ce/afxZodiacMgr.h"
#include "afx/afxZodiacGroundPlaneRenderer_T3D.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
const RenderInstType afxZodiacGroundPlaneRenderer::RIT_GroundPlaneZodiac("GroundPlaneZodiac");
afxZodiacGroundPlaneRenderer* afxZodiacGroundPlaneRenderer::master = 0;
IMPLEMENT_CONOBJECT(afxZodiacGroundPlaneRenderer);
ConsoleDocClass( afxZodiacGroundPlaneRenderer,
"@brief A render bin for zodiac rendering on GroundPlane objects.\n\n"
"This bin renders instances of AFX zodiac effects onto GroundPlane surfaces.\n\n"
"@ingroup RenderBin\n"
"@ingroup AFX\n"
);
afxZodiacGroundPlaneRenderer::afxZodiacGroundPlaneRenderer()
: RenderBinManager(RIT_GroundPlaneZodiac, 1.0f, 1.0f)
{
if (!master)
master = this;
shader_initialized = false;
}
afxZodiacGroundPlaneRenderer::afxZodiacGroundPlaneRenderer(F32 renderOrder, F32 processAddOrder)
: RenderBinManager(RIT_GroundPlaneZodiac, renderOrder, processAddOrder)
{
if (!master)
master = this;
shader_initialized = false;
}
afxZodiacGroundPlaneRenderer::~afxZodiacGroundPlaneRenderer()
{
if (this == master)
master = 0;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxZodiacGroundPlaneRenderer::initShader()
{
if (shader_initialized)
return;
shader_initialized = true;
shader_consts = 0;
norm_norefl_zb_SB = norm_refl_zb_SB;
add_norefl_zb_SB = add_refl_zb_SB;
sub_norefl_zb_SB = sub_refl_zb_SB;
zodiac_shader = afxZodiacMgr::getGroundPlaneZodiacShader();
if (!zodiac_shader)
return;
GFXStateBlockDesc d;
d.cullDefined = true;
d.ffLighting = false;
d.blendDefined = true;
d.blendEnable = true;
d.zDefined = false;
d.zEnable = true;
d.zWriteEnable = false;
d.zFunc = GFXCmpLessEqual;
d.zSlopeBias = 0;
d.alphaDefined = true;
d.alphaTestEnable = true;
d.alphaTestRef = 0;
d.alphaTestFunc = GFXCmpGreater;
d.samplersDefined = true;
d.samplers[0] = GFXSamplerStateDesc::getClampLinear();
// normal
d.blendSrc = GFXBlendSrcAlpha;
d.blendDest = GFXBlendInvSrcAlpha;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
norm_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
norm_refl_zb_SB = GFX->createStateBlock(d);
// additive
d.blendSrc = GFXBlendSrcAlpha;
d.blendDest = GFXBlendOne;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
add_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
add_refl_zb_SB = GFX->createStateBlock(d);
// subtractive
d.blendSrc = GFXBlendZero;
d.blendDest = GFXBlendInvSrcColor;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
sub_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
sub_refl_zb_SB = GFX->createStateBlock(d);
shader_consts = zodiac_shader->getShader()->allocConstBuffer();
projection_sc = zodiac_shader->getShader()->getShaderConstHandle("$modelView");
color_sc = zodiac_shader->getShader()->getShaderConstHandle("$zodiacColor");
}
void afxZodiacGroundPlaneRenderer::clear()
{
Parent::clear();
groundPlane_zodiacs.clear();
}
void afxZodiacGroundPlaneRenderer::addZodiac(U32 zode_idx, const Point3F& pos, F32 ang, const GroundPlane* gp, F32 camDist)
{
groundPlane_zodiacs.increment();
GroundPlaneZodiacElem& elem = groundPlane_zodiacs.last();
elem.gp = gp;
elem.zode_idx = zode_idx;
elem.ang = ang;
elem.camDist = camDist;
}
afxZodiacGroundPlaneRenderer* afxZodiacGroundPlaneRenderer::getMaster()
{
if (!master)
master = new afxZodiacGroundPlaneRenderer;
return master;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
GFXStateBlock* afxZodiacGroundPlaneRenderer::chooseStateBlock(U32 blend, bool isReflectPass)
{
GFXStateBlock* sb = 0;
switch (blend)
{
case afxZodiacData::BLEND_ADDITIVE:
sb = (isReflectPass) ? add_refl_zb_SB : add_norefl_zb_SB;
break;
case afxZodiacData::BLEND_SUBTRACTIVE:
sb = (isReflectPass) ? sub_refl_zb_SB : sub_norefl_zb_SB;
break;
default: // afxZodiacData::BLEND_NORMAL:
sb = (isReflectPass) ? norm_refl_zb_SB : norm_norefl_zb_SB;
break;
}
return sb;
}
void afxZodiacGroundPlaneRenderer::render(SceneRenderState* state)
{
PROFILE_SCOPE(afxRenderZodiacGroundPlaneMgr_render);
// Early out if no ground-plane zodiacs to draw.
if (groundPlane_zodiacs.size() == 0)
return;
initShader();
if (!zodiac_shader)
return;
bool is_reflect_pass = state->isReflectPass();
// Automagically save & restore our viewport and transforms.
GFXTransformSaver saver;
MatrixF proj = GFX->getProjectionMatrix();
// Set up world transform
MatrixF world = GFX->getWorldMatrix();
proj.mul(world);
shader_consts->set(projection_sc, proj);
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// RENDER EACH ZODIAC
//
for (S32 zz = 0; zz < groundPlane_zodiacs.size(); zz++)
{
GroundPlaneZodiacElem& elem = groundPlane_zodiacs[zz];
afxZodiacMgr::ZodiacSpec* zode = &afxZodiacMgr::terr_zodes[elem.zode_idx];
if (!zode)
continue;
if (is_reflect_pass)
{
//if ((zode->zflags & afxZodiacData::SHOW_IN_REFLECTIONS) == 0)
continue;
}
else
{
if ((zode->zflags & afxZodiacData::SHOW_IN_NON_REFLECTIONS) == 0)
continue;
}
F32 fadebias = zode->calcDistanceFadeBias(elem.camDist);
if (fadebias < 0.01f)
continue;
F32 cos_ang = mCos(elem.ang);
F32 sin_ang = mSin(elem.ang);
GFXStateBlock* sb = chooseStateBlock(zode->zflags & afxZodiacData::BLEND_MASK, is_reflect_pass);
GFX->setShader(zodiac_shader->getShader());
GFX->setStateBlock(sb);
GFX->setShaderConstBuffer(shader_consts);
// set the texture
GFX->setTexture(0, *zode->txr);
LinearColorF zode_color = (LinearColorF)zode->color;
zode_color.alpha *= fadebias;
shader_consts->set(color_sc, zode_color);
F32 rad_xy = zode->radius_xy;
F32 inv_radius = 1.0f/rad_xy;
F32 offset_xy = mSqrt(2*rad_xy*rad_xy);
F32 zx = zode->pos.x;
F32 zy = zode->pos.y;
F32 z = 0.00001f;
Point3F verts[4];
verts[0].set(zx+offset_xy, zy+offset_xy, z);
verts[1].set(zx-offset_xy, zy+offset_xy, z);
verts[2].set(zx-offset_xy, zy-offset_xy, z);
verts[3].set(zx+offset_xy, zy-offset_xy, z);
S32 vertind[6];
vertind[0] = 2;
vertind[1] = 1;
vertind[2] = 0;
vertind[3] = 3;
vertind[4] = 2;
vertind[5] = 0;
PrimBuild::begin(GFXTriangleList, 6);
for (U32 i = 0; i < 2; i++)
{
for (U32 j = 0; j < 3; j++)
{
const Point3F& vtx = verts[vertind[i*3+j]];
// compute UV
F32 u1 = (vtx.x - zode->pos.x)*inv_radius;
F32 v1 = (vtx.y - zode->pos.y)*inv_radius;
F32 ru1 = u1*cos_ang - v1*sin_ang;
F32 rv1 = u1*sin_ang + v1*cos_ang;
F32 uu = (ru1 + 1.0f)/2.0f;
F32 vv = 1.0f - (rv1 + 1.0f)/2.0f;
PrimBuild::texCoord2f(uu, vv);
PrimBuild::vertex3fv(vtx);
}
}
PrimBuild::end(false);
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,91 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_ZODIAC_GROUNDPLANE_RENDERER_H_
#define _AFX_ZODIAC_GROUNDPLANE_RENDERER_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "renderInstance/renderBinManager.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class ConcretePolyList;
class GroundPlane;
class afxZodiacGroundPlaneRenderer : public RenderBinManager
{
typedef RenderBinManager Parent;
struct GroundPlaneZodiacElem
{
const GroundPlane* gp;
U32 zode_idx;
F32 ang;
F32 camDist;
};
Vector<GroundPlaneZodiacElem> groundPlane_zodiacs;
static afxZodiacGroundPlaneRenderer* master;
GFXStateBlockRef norm_norefl_zb_SB, norm_refl_zb_SB;
GFXStateBlockRef add_norefl_zb_SB, add_refl_zb_SB;
GFXStateBlockRef sub_norefl_zb_SB, sub_refl_zb_SB;
ShaderData* zodiac_shader;
GFXShaderConstBufferRef shader_consts;
GFXShaderConstHandle* projection_sc;
GFXShaderConstHandle* color_sc;
bool shader_initialized;
GFXStateBlock* chooseStateBlock(U32 blend, bool isReflectPass);
public:
static const RenderInstType RIT_GroundPlaneZodiac;
/*C*/ afxZodiacGroundPlaneRenderer();
/*C*/ afxZodiacGroundPlaneRenderer(F32 renderOrder, F32 processAddOrder);
/*D*/ ~afxZodiacGroundPlaneRenderer();
// RenderBinManager
virtual void sort(){} // don't sort them
virtual void clear();
void initShader();
void addZodiac(U32 zode_idx, const Point3F& pos, F32 ang, const GroundPlane*, F32 camDist);
virtual void render(SceneRenderState* state);
static afxZodiacGroundPlaneRenderer* getMaster();
// ConsoleObject
DECLARE_CONOBJECT(afxZodiacGroundPlaneRenderer);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_ZODIAC_GROUNDPLANE_RENDERER_H_

View file

@ -0,0 +1,302 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "materials/shaderData.h"
#include "gfx/gfxTransformSaver.h"
#include "scene/sceneRenderState.h"
#include "collision/concretePolyList.h"
#include "T3D/tsStatic.h"
#include "gfx/primBuilder.h"
#include "afx/ce/afxZodiacMgr.h"
#include "afx/afxZodiacMeshRoadRenderer_T3D.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
const RenderInstType afxZodiacMeshRoadRenderer::RIT_MeshRoadZodiac("MeshRoadZodiac");
afxZodiacMeshRoadRenderer* afxZodiacMeshRoadRenderer::master = 0;
IMPLEMENT_CONOBJECT(afxZodiacMeshRoadRenderer);
ConsoleDocClass( afxZodiacMeshRoadRenderer,
"@brief A render bin for zodiac rendering on MeshRoad objects.\n\n"
"This bin renders instances of AFX zodiac effects onto MeshRoad surfaces.\n\n"
"@ingroup RenderBin\n"
"@ingroup AFX\n"
);
afxZodiacMeshRoadRenderer::afxZodiacMeshRoadRenderer()
: RenderBinManager(RIT_MeshRoadZodiac, 1.0f, 1.0f)
{
if (!master)
master = this;
shader_initialized = false;
}
afxZodiacMeshRoadRenderer::afxZodiacMeshRoadRenderer(F32 renderOrder, F32 processAddOrder)
: RenderBinManager(RIT_MeshRoadZodiac, renderOrder, processAddOrder)
{
if (!master)
master = this;
shader_initialized = false;
}
afxZodiacMeshRoadRenderer::~afxZodiacMeshRoadRenderer()
{
if (this == master)
master = 0;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxZodiacMeshRoadRenderer::initShader()
{
if (shader_initialized)
return;
shader_initialized = true;
shader_consts = 0;
norm_norefl_zb_SB = norm_refl_zb_SB;
add_norefl_zb_SB = add_refl_zb_SB;
sub_norefl_zb_SB = sub_refl_zb_SB;
zodiac_shader = afxZodiacMgr::getMeshRoadZodiacShader();
if (!zodiac_shader)
return;
GFXStateBlockDesc d;
d.cullDefined = true;
d.ffLighting = false;
d.blendDefined = true;
d.blendEnable = true;
d.zDefined = false;
d.zEnable = true;
d.zWriteEnable = false;
d.zFunc = GFXCmpLessEqual;
d.zSlopeBias = 0;
d.alphaDefined = true;
d.alphaTestEnable = true;
d.alphaTestRef = 0;
d.alphaTestFunc = GFXCmpGreater;
d.samplersDefined = true;
d.samplers[0] = GFXSamplerStateDesc::getClampLinear();
// normal
d.blendSrc = GFXBlendSrcAlpha;
d.blendDest = GFXBlendInvSrcAlpha;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
norm_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
norm_refl_zb_SB = GFX->createStateBlock(d);
// additive
d.blendSrc = GFXBlendSrcAlpha;
d.blendDest = GFXBlendOne;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
add_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
add_refl_zb_SB = GFX->createStateBlock(d);
// subtractive
d.blendSrc = GFXBlendZero;
d.blendDest = GFXBlendInvSrcColor;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
sub_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
sub_refl_zb_SB = GFX->createStateBlock(d);
shader_consts = zodiac_shader->getShader()->allocConstBuffer();
projection_sc = zodiac_shader->getShader()->getShaderConstHandle("$modelView");
color_sc = zodiac_shader->getShader()->getShaderConstHandle("$zodiacColor");
}
void afxZodiacMeshRoadRenderer::clear()
{
Parent::clear();
for (S32 i = 0; i < meshRoad_zodiacs.size(); i++)
if (meshRoad_zodiacs[i].polys)
delete meshRoad_zodiacs[i].polys;
meshRoad_zodiacs.clear();
}
void afxZodiacMeshRoadRenderer::addZodiac(U32 zode_idx, ConcretePolyList* polys, const Point3F& pos, F32 ang, const MeshRoad* road, F32 camDist)
{
meshRoad_zodiacs.increment();
MeshRoadZodiacElem& elem = meshRoad_zodiacs.last();
elem.road = road;
elem.polys = polys;
elem.zode_idx = zode_idx;
elem.ang = ang;
elem.camDist = camDist;
}
afxZodiacMeshRoadRenderer* afxZodiacMeshRoadRenderer::getMaster()
{
if (!master)
master = new afxZodiacMeshRoadRenderer;
return master;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
GFXStateBlock* afxZodiacMeshRoadRenderer::chooseStateBlock(U32 blend, bool isReflectPass)
{
GFXStateBlock* sb = 0;
switch (blend)
{
case afxZodiacData::BLEND_ADDITIVE:
sb = (isReflectPass) ? add_refl_zb_SB : add_norefl_zb_SB;
break;
case afxZodiacData::BLEND_SUBTRACTIVE:
sb = (isReflectPass) ? sub_refl_zb_SB : sub_norefl_zb_SB;
break;
default: // afxZodiacData::BLEND_NORMAL:
sb = (isReflectPass) ? norm_refl_zb_SB : norm_norefl_zb_SB;
break;
}
return sb;
}
void afxZodiacMeshRoadRenderer::render(SceneRenderState* state)
{
PROFILE_SCOPE(afxRenderZodiacMeshRoadMgr_render);
// Early out if no ground-plane zodiacs to draw.
if (meshRoad_zodiacs.size() == 0)
return;
initShader();
if (!zodiac_shader)
return;
bool is_reflect_pass = state->isReflectPass();
// Automagically save & restore our viewport and transforms.
GFXTransformSaver saver;
MatrixF proj = GFX->getProjectionMatrix();
// Set up world transform
MatrixF world = GFX->getWorldMatrix();
proj.mul(world);
shader_consts->set(projection_sc, proj);
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// RENDER EACH ZODIAC
//
for (S32 zz = 0; zz < meshRoad_zodiacs.size(); zz++)
{
MeshRoadZodiacElem& elem = meshRoad_zodiacs[zz];
afxZodiacMgr::ZodiacSpec* zode = &afxZodiacMgr::terr_zodes[elem.zode_idx];
if (!zode)
continue;
if (is_reflect_pass)
{
if ((zode->zflags & afxZodiacData::SHOW_IN_REFLECTIONS) == 0)
continue;
}
else
{
if ((zode->zflags & afxZodiacData::SHOW_IN_NON_REFLECTIONS) == 0)
continue;
}
F32 fadebias = zode->calcDistanceFadeBias(elem.camDist);
if (fadebias < 0.01f)
continue;
F32 cos_ang = mCos(elem.ang);
F32 sin_ang = mSin(elem.ang);
GFXStateBlock* sb = chooseStateBlock(zode->zflags & afxZodiacData::BLEND_MASK, is_reflect_pass);
GFX->setShader(zodiac_shader->getShader());
GFX->setStateBlock(sb);
GFX->setShaderConstBuffer(shader_consts);
// set the texture
GFX->setTexture(0, *zode->txr);
LinearColorF zode_color = (LinearColorF)zode->color;
zode_color.alpha *= fadebias;
shader_consts->set(color_sc, zode_color);
F32 inv_radius = 1.0f/zode->radius_xy;
PrimBuild::begin(GFXTriangleList, 3*elem.polys->mPolyList.size());
for (U32 i = 0; i < elem.polys->mPolyList.size(); i++)
{
ConcretePolyList::Poly* poly = &elem.polys->mPolyList[i];
S32 vertind[3];
vertind[0] = elem.polys->mIndexList[poly->vertexStart];
vertind[1] = elem.polys->mIndexList[poly->vertexStart + 1];
vertind[2] = elem.polys->mIndexList[poly->vertexStart + 2];
for (U32 j = 0; j < 3; j++)
{
Point3F vtx = elem.polys->mVertexList[vertind[j]];
// compute UV
F32 u1 = (vtx.x - zode->pos.x)*inv_radius;
F32 v1 = (vtx.y - zode->pos.y)*inv_radius;
F32 ru1 = u1*cos_ang - v1*sin_ang;
F32 rv1 = u1*sin_ang + v1*cos_ang;
F32 uu = (ru1 + 1.0f)/2.0f;
F32 vv = 1.0f - (rv1 + 1.0f)/2.0f;
PrimBuild::texCoord2f(uu, vv);
PrimBuild::vertex3fv(vtx);
}
}
PrimBuild::end(false);
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,92 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_ZODIAC_MESHROAD_RENDERER_H_
#define _AFX_ZODIAC_MESHROAD_RENDERER_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "renderInstance/renderBinManager.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class ConcretePolyList;
class MeshRoad;
class afxZodiacMeshRoadRenderer : public RenderBinManager
{
typedef RenderBinManager Parent;
struct MeshRoadZodiacElem
{
const MeshRoad* road;
U32 zode_idx;
ConcretePolyList* polys;
F32 ang;
F32 camDist;
};
Vector<MeshRoadZodiacElem> meshRoad_zodiacs;
static afxZodiacMeshRoadRenderer* master;
GFXStateBlockRef norm_norefl_zb_SB, norm_refl_zb_SB;
GFXStateBlockRef add_norefl_zb_SB, add_refl_zb_SB;
GFXStateBlockRef sub_norefl_zb_SB, sub_refl_zb_SB;
ShaderData* zodiac_shader;
GFXShaderConstBufferRef shader_consts;
GFXShaderConstHandle* projection_sc;
GFXShaderConstHandle* color_sc;
bool shader_initialized;
GFXStateBlock* chooseStateBlock(U32 blend, bool isReflectPass);
public:
static const RenderInstType RIT_MeshRoadZodiac;
/*C*/ afxZodiacMeshRoadRenderer();
/*C*/ afxZodiacMeshRoadRenderer(F32 renderOrder, F32 processAddOrder);
/*D*/ ~afxZodiacMeshRoadRenderer();
// RenderBinManager
virtual void sort(){} // don't sort them
virtual void clear();
void initShader();
void addZodiac(U32 zode_idx, ConcretePolyList*, const Point3F& pos, F32 ang, const MeshRoad*, F32 camDist);
virtual void render(SceneRenderState*);
static afxZodiacMeshRoadRenderer* getMaster();
// ConsoleObject
DECLARE_CONOBJECT(afxZodiacMeshRoadRenderer);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_ZODIAC_MESHROAD_RENDERER_H_

View file

@ -0,0 +1,420 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "materials/shaderData.h"
#include "gfx/gfxTransformSaver.h"
#include "scene/sceneRenderState.h"
#include "collision/concretePolyList.h"
#include "T3D/tsStatic.h"
#include "gfx/primBuilder.h"
#include "afx/ce/afxZodiacMgr.h"
#include "afx/afxZodiacPolysoupRenderer_T3D.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
const RenderInstType afxZodiacPolysoupRenderer::RIT_PolysoupZodiac("PolysoupZodiac");
afxZodiacPolysoupRenderer* afxZodiacPolysoupRenderer::master = 0;
IMPLEMENT_CONOBJECT(afxZodiacPolysoupRenderer);
ConsoleDocClass( afxZodiacPolysoupRenderer,
"@brief A render bin for zodiac rendering on polysoup TSStatic objects.\n\n"
"This bin renders instances of AFX zodiac effects onto polysoup TSStatic surfaces.\n\n"
"@ingroup RenderBin\n"
"@ingroup AFX\n"
);
afxZodiacPolysoupRenderer::afxZodiacPolysoupRenderer()
: RenderBinManager(RIT_PolysoupZodiac, 1.0f, 1.0f)
{
if (!master)
master = this;
shader_initialized = false;
}
afxZodiacPolysoupRenderer::afxZodiacPolysoupRenderer(F32 renderOrder, F32 processAddOrder)
: RenderBinManager(RIT_PolysoupZodiac, renderOrder, processAddOrder)
{
if (!master)
master = this;
shader_initialized = false;
}
afxZodiacPolysoupRenderer::~afxZodiacPolysoupRenderer()
{
if (this == master)
master = 0;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxZodiacPolysoupRenderer::initShader()
{
if (shader_initialized)
return;
shader_initialized = true;
shader_consts = 0;
norm_norefl_zb_SB = norm_refl_zb_SB;
add_norefl_zb_SB = add_refl_zb_SB;
sub_norefl_zb_SB = sub_refl_zb_SB;
zodiac_shader = afxZodiacMgr::getPolysoupZodiacShader();
if (!zodiac_shader)
return;
GFXStateBlockDesc d;
d.cullDefined = true;
d.ffLighting = false;
d.blendDefined = true;
d.blendEnable = true;
d.zDefined = false;
d.zEnable = true;
d.zWriteEnable = false;
d.zFunc = GFXCmpLessEqual;
d.zSlopeBias = 0;
d.alphaDefined = true;
d.alphaTestEnable = true;
d.alphaTestRef = 0;
d.alphaTestFunc = GFXCmpGreater;
d.samplersDefined = true;
d.samplers[0] = GFXSamplerStateDesc::getClampLinear();
// normal
d.blendSrc = GFXBlendSrcAlpha;
d.blendDest = GFXBlendInvSrcAlpha;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
norm_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
norm_refl_zb_SB = GFX->createStateBlock(d);
// additive
d.blendSrc = GFXBlendSrcAlpha;
d.blendDest = GFXBlendOne;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
add_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
add_refl_zb_SB = GFX->createStateBlock(d);
// subtractive
d.blendSrc = GFXBlendZero;
d.blendDest = GFXBlendInvSrcColor;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
sub_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sPolysoupZodiacZBias;
sub_refl_zb_SB = GFX->createStateBlock(d);
shader_consts = zodiac_shader->getShader()->allocConstBuffer();
projection_sc = zodiac_shader->getShader()->getShaderConstHandle("$modelView");
color_sc = zodiac_shader->getShader()->getShaderConstHandle("$zodiacColor");
}
void afxZodiacPolysoupRenderer::clear()
{
Parent::clear();
for (S32 i = 0; i < polysoup_zodes.size(); i++)
if (polysoup_zodes[i].polys)
delete polysoup_zodes[i].polys;
polysoup_zodes.clear();
}
void afxZodiacPolysoupRenderer::addZodiac(U32 zode_idx, ConcretePolyList* polys, const Point3F& pos, F32 ang, const TSStatic* tss, F32 camDist)
{
polysoup_zodes.increment();
PolysoupZodiacElem& elem = polysoup_zodes.last();
elem.tss = tss;
elem.polys = polys;
elem.zode_idx = zode_idx;
elem.ang = ang;
elem.camDist = camDist;
}
afxZodiacPolysoupRenderer* afxZodiacPolysoupRenderer::getMaster()
{
if (!master)
master = new afxZodiacPolysoupRenderer;
return master;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
GFXStateBlock* afxZodiacPolysoupRenderer::chooseStateBlock(U32 blend, bool isReflectPass)
{
GFXStateBlock* sb = 0;
switch (blend)
{
case afxZodiacData::BLEND_ADDITIVE:
sb = (isReflectPass) ? add_refl_zb_SB : add_norefl_zb_SB;
break;
case afxZodiacData::BLEND_SUBTRACTIVE:
sb = (isReflectPass) ? sub_refl_zb_SB : sub_norefl_zb_SB;
break;
default: // afxZodiacData::BLEND_NORMAL:
sb = (isReflectPass) ? norm_refl_zb_SB : norm_norefl_zb_SB;
break;
}
return sb;
}
void afxZodiacPolysoupRenderer::render(SceneRenderState* state)
{
PROFILE_SCOPE(afxRenderZodiacPolysoupMgr_render);
// Early out if no polysoup zodiacs to draw.
if (polysoup_zodes.size() == 0)
return;
initShader();
if (!zodiac_shader)
return;
bool is_reflect_pass = state->isReflectPass();
// Automagically save & restore our viewport and transforms.
GFXTransformSaver saver;
MatrixF proj = GFX->getProjectionMatrix();
// Set up world transform
MatrixF world = GFX->getWorldMatrix();
proj.mul(world);
shader_consts->set(projection_sc, proj);
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// RENDER EACH ZODIAC
//
for (S32 zz = 0; zz < polysoup_zodes.size(); zz++)
{
PolysoupZodiacElem& elem = polysoup_zodes[zz];
afxZodiacMgr::ZodiacSpec* zode = &afxZodiacMgr::inter_zodes[elem.zode_idx];
if (!zode)
continue;
if (is_reflect_pass)
{
if ((zode->zflags & afxZodiacData::SHOW_IN_REFLECTIONS) == 0)
continue;
}
else
{
if ((zode->zflags & afxZodiacData::SHOW_IN_NON_REFLECTIONS) == 0)
continue;
}
F32 fadebias = zode->calcDistanceFadeBias(elem.camDist);
if (fadebias < 0.01f)
continue;
F32 cos_ang = mCos(elem.ang);
F32 sin_ang = mSin(elem.ang);
GFXStateBlock* sb = chooseStateBlock(zode->zflags & afxZodiacData::BLEND_MASK, is_reflect_pass);
GFX->setShader(zodiac_shader->getShader());
GFX->setStateBlock(sb);
GFX->setShaderConstBuffer(shader_consts);
// set the texture
GFX->setTexture(0, *zode->txr);
LinearColorF zode_color = (LinearColorF)zode->color;
zode_color.alpha *= fadebias;
shader_consts->set(color_sc, zode_color);
F32 inv_radius = 1.0f/zode->radius_xy;
// FILTER USING GRADIENT RANGE
if ((zode->zflags & afxZodiacData::USE_GRADE_RANGE) != 0)
{
bool skip_oob;
F32 grade_min, grade_max;
if (elem.tss->mHasGradients && ((zode->zflags & afxZodiacData::PREFER_DEST_GRADE) != 0))
{
skip_oob = (elem.tss->mInvertGradientRange == false);
grade_min = elem.tss->mGradientRange.x;
grade_max = elem.tss->mGradientRange.y;
}
else
{
skip_oob = ((zode->zflags & afxZodiacData::INVERT_GRADE_RANGE) == 0);
grade_min = zode->grade_range.x;
grade_max = zode->grade_range.y;
}
PrimBuild::begin(GFXTriangleList, 3*elem.polys->mPolyList.size());
for (U32 i = 0; i < elem.polys->mPolyList.size(); i++)
{
ConcretePolyList::Poly* poly = &elem.polys->mPolyList[i];
const PlaneF& plane = poly->plane;
bool oob = (plane.z > grade_max || plane.z < grade_min);
if (oob == skip_oob)
continue;
S32 vertind[3];
vertind[0] = elem.polys->mIndexList[poly->vertexStart];
vertind[1] = elem.polys->mIndexList[poly->vertexStart + 1];
vertind[2] = elem.polys->mIndexList[poly->vertexStart + 2];
for (U32 j = 0; j < 3; j++)
{
Point3F vtx = elem.polys->mVertexList[vertind[j]];
// compute UV
F32 u1 = (vtx.x - zode->pos.x)*inv_radius;
F32 v1 = (vtx.y - zode->pos.y)*inv_radius;
F32 ru1 = u1*cos_ang - v1*sin_ang;
F32 rv1 = u1*sin_ang + v1*cos_ang;
F32 uu = (ru1 + 1.0f)/2.0f;
F32 vv = 1.0f - (rv1 + 1.0f)/2.0f;
PrimBuild::texCoord2f(uu, vv);
PrimBuild::vertex3fv(vtx);
}
}
PrimBuild::end(false);
}
// FILTER USING OTHER FILTERS
else if (zode->zflags & afxZodiacData::INTERIOR_FILTERS)
{
PrimBuild::begin(GFXTriangleList, 3*elem.polys->mPolyList.size());
for (U32 i = 0; i < elem.polys->mPolyList.size(); i++)
{
ConcretePolyList::Poly* poly = &elem.polys->mPolyList[i];
const PlaneF& plane = poly->plane;
if (zode->zflags & afxZodiacData::INTERIOR_HORIZ_ONLY)
{
if (!plane.isHorizontal())
continue;
if (zode->zflags & afxZodiacData::INTERIOR_BACK_IGNORE)
{
if (plane.whichSide(zode->pos) == PlaneF::Back)
continue;
}
}
else
{
if (zode->zflags & afxZodiacData::INTERIOR_VERT_IGNORE)
{
if (plane.isVertical())
continue;
}
if (zode->zflags & afxZodiacData::INTERIOR_BACK_IGNORE)
{
if (plane.whichSide(zode->pos) == PlaneF::Back)
continue;
}
}
S32 vertind[3];
vertind[0] = elem.polys->mIndexList[poly->vertexStart];
vertind[1] = elem.polys->mIndexList[poly->vertexStart + 1];
vertind[2] = elem.polys->mIndexList[poly->vertexStart + 2];
for (U32 j = 0; j < 3; j++)
{
Point3F vtx = elem.polys->mVertexList[vertind[j]];
// compute UV
F32 u1 = (vtx.x - zode->pos.x)*inv_radius;
F32 v1 = (vtx.y - zode->pos.y)*inv_radius;
F32 ru1 = u1*cos_ang - v1*sin_ang;
F32 rv1 = u1*sin_ang + v1*cos_ang;
F32 uu = (ru1 + 1.0f)/2.0f;
F32 vv = 1.0f - (rv1 + 1.0f)/2.0f;
PrimBuild::texCoord2f(uu, vv);
PrimBuild::vertex3fv(vtx);
}
}
PrimBuild::end(false);
}
// NO FILTERING
else
{
PrimBuild::begin(GFXTriangleList, 3*elem.polys->mPolyList.size());
for (U32 i = 0; i < elem.polys->mPolyList.size(); i++)
{
ConcretePolyList::Poly* poly = &elem.polys->mPolyList[i];
S32 vertind[3];
vertind[0] = elem.polys->mIndexList[poly->vertexStart];
vertind[1] = elem.polys->mIndexList[poly->vertexStart + 1];
vertind[2] = elem.polys->mIndexList[poly->vertexStart + 2];
for (U32 j = 0; j < 3; j++)
{
Point3F vtx = elem.polys->mVertexList[vertind[j]];
// compute UV
F32 u1 = (vtx.x - zode->pos.x)*inv_radius;
F32 v1 = (vtx.y - zode->pos.y)*inv_radius;
F32 ru1 = u1*cos_ang - v1*sin_ang;
F32 rv1 = u1*sin_ang + v1*cos_ang;
F32 uu = (ru1 + 1.0f)/2.0f;
F32 vv = 1.0f - (rv1 + 1.0f)/2.0f;
PrimBuild::texCoord2f(uu, vv);
PrimBuild::vertex3fv(vtx);
}
}
PrimBuild::end(false);
}
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,92 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_ZODIAC_POLYSOUP_RENDERER_H_
#define _AFX_ZODIAC_POLYSOUP_RENDERER_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "renderInstance/renderBinManager.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class ConcretePolyList;
class TSStatic;
class afxZodiacPolysoupRenderer : public RenderBinManager
{
typedef RenderBinManager Parent;
struct PolysoupZodiacElem
{
const TSStatic* tss;
U32 zode_idx;
ConcretePolyList* polys;
F32 ang;
F32 camDist;
};
Vector<PolysoupZodiacElem> polysoup_zodes;
static afxZodiacPolysoupRenderer* master;
GFXStateBlockRef norm_norefl_zb_SB, norm_refl_zb_SB;
GFXStateBlockRef add_norefl_zb_SB, add_refl_zb_SB;
GFXStateBlockRef sub_norefl_zb_SB, sub_refl_zb_SB;
ShaderData* zodiac_shader;
GFXShaderConstBufferRef shader_consts;
GFXShaderConstHandle* projection_sc;
GFXShaderConstHandle* color_sc;
bool shader_initialized;
GFXStateBlock* chooseStateBlock(U32 blend, bool isReflectPass);
public:
static const RenderInstType RIT_PolysoupZodiac;
/*C*/ afxZodiacPolysoupRenderer();
/*C*/ afxZodiacPolysoupRenderer(F32 renderOrder, F32 processAddOrder);
/*D*/ ~afxZodiacPolysoupRenderer();
// RenderBinManager
virtual void sort(){} // don't sort them
virtual void clear();
void initShader();
void addZodiac(U32 zode_idx, ConcretePolyList*, const Point3F& pos, F32 ang, const TSStatic*, F32 camDist);
virtual void render(SceneRenderState*);
static afxZodiacPolysoupRenderer* getMaster();
// ConsoleObject
DECLARE_CONOBJECT(afxZodiacPolysoupRenderer);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_ZODIAC_POLYSOUP_RENDERER_H_

View file

@ -0,0 +1,344 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "materials/shaderData.h"
#include "gfx/gfxTransformSaver.h"
#include "scene/sceneRenderState.h"
#include "terrain/terrData.h"
#include "terrain/terrCell.h"
#include "gfx/primBuilder.h"
#include "afx/ce/afxZodiacMgr.h"
#include "afx/afxZodiacTerrainRenderer_T3D.h"
#include "afx/util/afxTriBoxCheck2D_T3D.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class TerrCellSpy : public TerrCell
{
public:
static const U32 getMinCellSize() { return smMinCellSize; }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
const RenderInstType afxZodiacTerrainRenderer::RIT_TerrainZodiac("TerrainZodiac");
afxZodiacTerrainRenderer* afxZodiacTerrainRenderer::master = 0;
IMPLEMENT_CONOBJECT(afxZodiacTerrainRenderer);
ConsoleDocClass( afxZodiacTerrainRenderer,
"@brief A render bin for zodiac rendering on Terrain objects.\n\n"
"This bin renders instances of AFX zodiac effects onto Terrain surfaces.\n\n"
"@ingroup RenderBin\n"
"@ingroup AFX\n"
);
afxZodiacTerrainRenderer::afxZodiacTerrainRenderer()
: RenderBinManager(RIT_TerrainZodiac, 1.0f, 1.0f)
{
if (!master)
master = this;
shader_initialized = false;
}
afxZodiacTerrainRenderer::afxZodiacTerrainRenderer(F32 renderOrder, F32 processAddOrder)
: RenderBinManager(RIT_TerrainZodiac, renderOrder, processAddOrder)
{
if (!master)
master = this;
shader_initialized = false;
}
afxZodiacTerrainRenderer::~afxZodiacTerrainRenderer()
{
if (this == master)
master = 0;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxZodiacTerrainRenderer::initShader()
{
if (shader_initialized)
return;
shader_initialized = true;
shader_consts = 0;
norm_norefl_zb_SB = norm_refl_zb_SB;
add_norefl_zb_SB = add_refl_zb_SB;
sub_norefl_zb_SB = sub_refl_zb_SB;
zodiac_shader = afxZodiacMgr::getTerrainZodiacShader();
if (!zodiac_shader)
return;
GFXStateBlockDesc d;
d.cullDefined = true;
d.ffLighting = false;
d.blendDefined = true;
d.blendEnable = true;
d.zDefined = false;
d.zEnable = true;
d.zWriteEnable = false;
d.zFunc = GFXCmpLessEqual;
d.zSlopeBias = 0;
d.alphaDefined = true;
d.alphaTestEnable = true;
d.alphaTestRef = 0;
d.alphaTestFunc = GFXCmpGreater;
d.samplersDefined = true;
d.samplers[0] = GFXSamplerStateDesc::getClampLinear();
// normal
d.blendSrc = GFXBlendSrcAlpha;
d.blendDest = GFXBlendInvSrcAlpha;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sTerrainZodiacZBias;
norm_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sTerrainZodiacZBias;
norm_refl_zb_SB = GFX->createStateBlock(d);
// additive
d.blendSrc = GFXBlendSrcAlpha;
d.blendDest = GFXBlendOne;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sTerrainZodiacZBias;
add_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sTerrainZodiacZBias;
add_refl_zb_SB = GFX->createStateBlock(d);
// subtractive
d.blendSrc = GFXBlendZero;
d.blendDest = GFXBlendInvSrcColor;
//
d.cullMode = GFXCullCCW;
d.zBias = arcaneFX::sTerrainZodiacZBias;
sub_norefl_zb_SB = GFX->createStateBlock(d);
//
d.cullMode = GFXCullCW;
d.zBias = arcaneFX::sTerrainZodiacZBias;
sub_refl_zb_SB = GFX->createStateBlock(d);
shader_consts = zodiac_shader->getShader()->allocConstBuffer();
projection_sc = zodiac_shader->getShader()->getShaderConstHandle("$modelView");
color_sc = zodiac_shader->getShader()->getShaderConstHandle("$zodiacColor");
}
void afxZodiacTerrainRenderer::clear()
{
Parent::clear();
terrain_zodes.clear();
}
void afxZodiacTerrainRenderer::addZodiac(U32 zode_idx, const Point3F& pos, F32 ang,
const TerrainBlock* block, const TerrCell* cell,
const MatrixF& mRenderObjToWorld, F32 camDist)
{
terrain_zodes.increment();
TerrainZodiacElem& elem = terrain_zodes.last();
elem.block = block;
elem.cell = cell;
elem.zode_idx = zode_idx;
elem.ang = ang;
elem.mRenderObjToWorld = mRenderObjToWorld;
elem.camDist = camDist;
}
afxZodiacTerrainRenderer* afxZodiacTerrainRenderer::getMaster()
{
if (!master)
master = new afxZodiacTerrainRenderer;
return master;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
GFXStateBlock* afxZodiacTerrainRenderer::chooseStateBlock(U32 blend, bool isReflectPass)
{
GFXStateBlock* sb = 0;
switch (blend)
{
case afxZodiacData::BLEND_ADDITIVE:
sb = (isReflectPass) ? add_refl_zb_SB : add_norefl_zb_SB;
break;
case afxZodiacData::BLEND_SUBTRACTIVE:
sb = (isReflectPass) ? sub_refl_zb_SB : sub_norefl_zb_SB;
break;
default: // afxZodiacData::BLEND_NORMAL:
sb = (isReflectPass) ? norm_refl_zb_SB : norm_norefl_zb_SB;
break;
}
return sb;
}
void afxZodiacTerrainRenderer::render(SceneRenderState* state)
{
PROFILE_SCOPE(afxRenderZodiacTerrainMgr_render);
// Early out if no terrain zodiacs to draw.
if (terrain_zodes.size() == 0)
return;
initShader();
if (!zodiac_shader)
return;
bool is_reflect_pass = state->isReflectPass();
// Automagically save & restore our viewport and transforms.
GFXTransformSaver saver;
MatrixF proj = GFX->getProjectionMatrix();
// Set up world transform
MatrixF world = GFX->getWorldMatrix();
proj.mul(world);
shader_consts->set(projection_sc, proj);
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// RENDER EACH ZODIAC
//
for (S32 zz = 0; zz < terrain_zodes.size(); zz++)
{
TerrainZodiacElem& elem = terrain_zodes[zz];
TerrainBlock* block = (TerrainBlock*) elem.block;
afxZodiacMgr::ZodiacSpec* zode = &afxZodiacMgr::terr_zodes[elem.zode_idx];
if (!zode)
continue;
if (is_reflect_pass)
{
if ((zode->zflags & afxZodiacData::SHOW_IN_REFLECTIONS) == 0)
continue;
}
else
{
if ((zode->zflags & afxZodiacData::SHOW_IN_NON_REFLECTIONS) == 0)
continue;
}
F32 fadebias = zode->calcDistanceFadeBias(elem.camDist);
if (fadebias < 0.01f)
continue;
F32 cos_ang = mCos(elem.ang);
F32 sin_ang = mSin(elem.ang);
GFXStateBlock* sb = chooseStateBlock(zode->zflags & afxZodiacData::BLEND_MASK, is_reflect_pass);
GFX->setShader(zodiac_shader->getShader());
GFX->setStateBlock(sb);
GFX->setShaderConstBuffer(shader_consts);
// set the texture
GFX->setTexture(0, *zode->txr);
LinearColorF zode_color = (LinearColorF)zode->color;
zode_color.alpha *= fadebias;
shader_consts->set(color_sc, zode_color);
Point3F half_size(zode->radius_xy,zode->radius_xy,zode->radius_xy);
F32 inv_radius = 1.0f/zode->radius_xy;
GFXPrimitive cell_prim;
GFXVertexBufferHandle<TerrVertex> cell_verts;
GFXPrimitiveBufferHandle primBuff;
elem.cell->getRenderPrimitive(&cell_prim, &cell_verts, &primBuff);
U32 n_nonskirt_tris = TerrCellSpy::getMinCellSize()*TerrCellSpy::getMinCellSize()*2;
const Point3F* verts = ((TerrCell*)elem.cell)->getZodiacVertexBuffer();
const U16 *tris = block->getZodiacPrimitiveBuffer();
if (!tris)
continue;
PrimBuild::begin(GFXTriangleList, 3*n_nonskirt_tris);
/////////////////////////////////
U32 n_overlapping_tris = 0;
U32 idx = 0;
for (U32 i = 0; i < n_nonskirt_tris; i++)
{
Point3F tri_v[3];
tri_v[0] = verts[tris[idx++]];
tri_v[1] = verts[tris[idx++]];
tri_v[2] = verts[tris[idx++]];
elem.mRenderObjToWorld.mulP(tri_v[0]);
elem.mRenderObjToWorld.mulP(tri_v[1]);
elem.mRenderObjToWorld.mulP(tri_v[2]);
if (!afxTriBoxOverlap2D(zode->pos, half_size, tri_v[0], tri_v[1], tri_v[2]))
continue;
n_overlapping_tris++;
for (U32 j = 0; j < 3; j++)
{
// compute UV
F32 u1 = (tri_v[j].x - zode->pos.x)*inv_radius;
F32 v1 = (tri_v[j].y - zode->pos.y)*inv_radius;
F32 ru1 = u1*cos_ang - v1*sin_ang;
F32 rv1 = u1*sin_ang + v1*cos_ang;
F32 uu = (ru1 + 1.0f)/2.0f;
F32 vv = 1.0f - (rv1 + 1.0f)/2.0f;
PrimBuild::texCoord2f(uu, vv);
PrimBuild::vertex3fv(tri_v[j]);
}
}
/////////////////////////////////
PrimBuild::end(false);
}
//
// RENDER EACH ZODIAC
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,92 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_ZODIAC_TERRAIN_RENDERER_H_
#define _AFX_ZODIAC_TERRAIN_RENDERER_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "renderInstance/renderBinManager.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class TerrCell;
class afxZodiacTerrainRenderer : public RenderBinManager
{
typedef RenderBinManager Parent;
struct TerrainZodiacElem
{
const TerrainBlock* block;
const TerrCell* cell;
U32 zode_idx;
F32 ang;
MatrixF mRenderObjToWorld;
F32 camDist;
};
Vector<TerrainZodiacElem> terrain_zodes;
static afxZodiacTerrainRenderer* master;
GFXStateBlockRef norm_norefl_zb_SB, norm_refl_zb_SB;
GFXStateBlockRef add_norefl_zb_SB, add_refl_zb_SB;
GFXStateBlockRef sub_norefl_zb_SB, sub_refl_zb_SB;
ShaderData* zodiac_shader;
GFXShaderConstBufferRef shader_consts;
GFXShaderConstHandle* projection_sc;
GFXShaderConstHandle* color_sc;
bool shader_initialized;
GFXStateBlock* chooseStateBlock(U32 blend, bool isReflectPass);
public:
static const RenderInstType RIT_TerrainZodiac;
/*C*/ afxZodiacTerrainRenderer();
/*C*/ afxZodiacTerrainRenderer(F32 renderOrder, F32 processAddOrder);
/*D*/ ~afxZodiacTerrainRenderer();
// RenderBinManager
virtual void sort(){} // don't sort them
virtual void clear();
void initShader();
void addZodiac(U32 zode_idx, const Point3F& pos, F32 ang, const TerrainBlock*, const TerrCell*, const MatrixF& mRenderObjToWorld, F32 camDist);
virtual void render(SceneRenderState*);
static afxZodiacTerrainRenderer* getMaster();
// ConsoleObject
DECLARE_CONOBJECT(afxZodiacTerrainRenderer);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_ZODIAC_TERRAIN_RENDERER_H_

View file

@ -0,0 +1,959 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "scene/sceneObject.h"
#include "scene/sceneManager.h"
#include "T3D/gameBase/gameConnection.h"
#include "T3D/gameBase/gameProcess.h"
#include "T3D/player.h"
#include "math/mathUtils.h"
#include "console/compiler.h"
#include "console/engineAPI.h"
#include "afx/afxChoreographer.h"
#include "afx/afxSelectron.h"
#include "afx/afxResidueMgr.h"
#include "afx/ce/afxZodiacMgr.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#define N_LIGHTING_MODELS 6
//
// "SG - Original Advanced (Lighting Pack)"
// "SG - Original Stock (Lighting Pack)"
// "SG - Inverse Square (Lighting Pack)"
// "SG - Inverse Square Fast Falloff (Lighting Pack)"
// "SG - Near Linear (Lighting Pack)"
// "SG - Near Linear Fast Falloff (Lighting Pack)"
static StringTableEntry lm_old_names[N_LIGHTING_MODELS];
//
// "Original Advanced"
// "Original Stock"
// "Inverse Square"
// "Inverse Square Fast Falloff"
// "Near Linear"
// "Near Linear Fast Falloff"
static StringTableEntry lm_new_names[N_LIGHTING_MODELS];
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class ClientZoneInEvent : public NetEvent
{
typedef NetEvent Parent;
public:
ClientZoneInEvent() { mGuaranteeType = Guaranteed; }
~ClientZoneInEvent() { }
virtual void pack(NetConnection*, BitStream*bstream) { }
virtual void write(NetConnection*, BitStream *bstream) { }
virtual void unpack(NetConnection* /*ps*/, BitStream *bstream) { }
virtual void process(NetConnection* conn)
{
GameConnection* game_conn = dynamic_cast<GameConnection*>(conn);
if (game_conn && !game_conn->isZonedIn())
{
arcaneFX::syncToNewConnection(game_conn);
}
}
DECLARE_CONOBJECT(ClientZoneInEvent);
DECLARE_CATEGORY("AFX");
};
IMPLEMENT_CO_SERVEREVENT_V1(ClientZoneInEvent);
ConsoleDocClass( ClientZoneInEvent,
"@brief Event posted when player is fully loaded into the game and ready for interaction.\n\n"
"@internal");
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
Vector<afxChoreographer*> arcaneFX::active_choreographers;
Vector<afxChoreographer*> arcaneFX::client_choreographers;
Vector<afxSelectronData*> arcaneFX::selectrons;
Vector<SceneObject*> arcaneFX::scoped_objs;
StringTableEntry arcaneFX::NULLSTRING = 0;
U32 arcaneFX::sTargetSelectionMask = 0;
U32 arcaneFX::sFreeTargetSelectionMask = 0;
bool arcaneFX::sIsFreeTargeting = false;
Point3F arcaneFX::sFreeTargetPos = Point3F(0.0f, 0.0f, 0.0f);
bool arcaneFX::sFreeTargetPosValid = false;
F32 arcaneFX::sTargetSelectionRange = 200.0f;
U32 arcaneFX::sTargetSelectionTimeoutMS = 500;
bool arcaneFX::sClickToTargetSelf = false;
U32 arcaneFX::sMissileCollisionMask = 0;
StringTableEntry arcaneFX::sParameterFieldPrefix = 0;
F32 arcaneFX::sTerrainZodiacZBias = -0.00025f;
F32 arcaneFX::sInteriorZodiacZBias = -0.0001f;
F32 arcaneFX::sPolysoupZodiacZBias = -0.0001f;
U32 arcaneFX::master_choreographer_id = 1;
U16 arcaneFX::master_scope_id = 1;
bool arcaneFX::is_shutdown = true;
bool arcaneFX::sUsePlayerCentricListener = false;
void arcaneFX::init()
{
NULLSTRING = StringTable->insert("");
sParameterFieldPrefix = StringTable->insert("_");
#if defined(TORQUE_OS_MAC)
arcaneFX::sTerrainZodiacZBias = -0.00025f;
arcaneFX::sInteriorZodiacZBias = -0.00025f;
arcaneFX::sPolysoupZodiacZBias = -0.00025f;
#endif
Con::addVariable( "pref::AFX::targetSelectionMask", TypeS32, &sTargetSelectionMask);
Con::addVariable( "pref::AFX::freeTargetSelectionMask", TypeS32, &sFreeTargetSelectionMask);
Con::addVariable( "pref::AFX::targetSelectionRange", TypeF32, &sTargetSelectionRange);
Con::addVariable( "pref::AFX::targetSelectionTimeoutMS", TypeS32, &sTargetSelectionTimeoutMS);
Con::addVariable( "pref::AFX::missileCollisionMask", TypeS32, &sMissileCollisionMask);
Con::addVariable( "pref::AFX::clickToTargetSelf", TypeBool, &sClickToTargetSelf);
Con::addVariable( "Pref::Server::AFX::parameterFieldPrefix", TypeString, &sParameterFieldPrefix);
Con::addVariable( "pref::AFX::terrainZodiacZBias", TypeF32, &sTerrainZodiacZBias);
Con::addVariable( "pref::AFX::interiorZodiacZBias", TypeF32, &sInteriorZodiacZBias);
Con::addVariable( "pref::AFX::polysoupZodiacZBias", TypeF32, &sPolysoupZodiacZBias);
Con::setIntVariable( "$AFX::TARGETING_OFF", TARGETING_OFF);
Con::setIntVariable( "$AFX::TARGETING_STANDARD", TARGETING_STANDARD);
Con::setIntVariable( "$AFX::TARGETING_FREE", TARGETING_FREE);
Con::setIntVariable( "$AFX::TARGET_CHECK_POLL", TARGET_CHECK_POLL);
Con::setIntVariable( "$AFX::TARGET_CHECK_ON_MOUSE_MOVE", TARGET_CHECK_ON_MOUSE_MOVE);
Con::setIntVariable( "$AFX::IMPACTED_SOMETHING", afxEffectDefs::IMPACTED_SOMETHING);
Con::setIntVariable( "$AFX::IMPACTED_TARGET", afxEffectDefs::IMPACTED_TARGET);
Con::setIntVariable( "$AFX::IMPACTED_PRIMARY", afxEffectDefs::IMPACTED_PRIMARY);
Con::setIntVariable( "$AFX::IMPACT_IN_WATER", afxEffectDefs::IMPACT_IN_WATER);
Con::setIntVariable( "$AFX::CASTER_IN_WATER", afxEffectDefs::CASTER_IN_WATER);
Con::setIntVariable( "$AFX::SERVER_ONLY", afxEffectDefs::SERVER_ONLY);
Con::setIntVariable( "$AFX::SCOPE_ALWAYS", afxEffectDefs::SCOPE_ALWAYS);
Con::setIntVariable( "$AFX::GHOSTABLE", afxEffectDefs::GHOSTABLE);
Con::setIntVariable( "$AFX::CLIENT_ONLY", afxEffectDefs::CLIENT_ONLY);
Con::setIntVariable( "$AFX::SERVER_AND_CLIENT", afxEffectDefs::SERVER_AND_CLIENT);
Con::setIntVariable( "$AFX::DELAY", afxEffectDefs::TIMING_DELAY);
Con::setIntVariable( "$AFX::LIFETIME", afxEffectDefs::TIMING_LIFETIME);
Con::setIntVariable( "$AFX::FADE_IN_TIME", afxEffectDefs::TIMING_FADE_IN);
Con::setIntVariable( "$AFX::FADE_OUT_TIME", afxEffectDefs::TIMING_FADE_OUT);
Con::setFloatVariable( "$AFX::INFINITE_TIME", -1.0f);
Con::setIntVariable( "$AFX::INFINITE_REPEATS", -1);
Con::setIntVariable( "$AFX::PLAYER_MOVE_TRIGGER_0", Player::PLAYER_MOVE_TRIGGER_0);
Con::setIntVariable( "$AFX::PLAYER_MOVE_TRIGGER_1", Player::PLAYER_MOVE_TRIGGER_1);
Con::setIntVariable( "$AFX::PLAYER_MOVE_TRIGGER_2", Player::PLAYER_MOVE_TRIGGER_2);
Con::setIntVariable( "$AFX::PLAYER_MOVE_TRIGGER_3", Player::PLAYER_MOVE_TRIGGER_3);
Con::setIntVariable( "$AFX::PLAYER_MOVE_TRIGGER_4", Player::PLAYER_MOVE_TRIGGER_4);
Con::setIntVariable( "$AFX::PLAYER_MOVE_TRIGGER_5", Player::PLAYER_MOVE_TRIGGER_5);
Con::setIntVariable( "$AFX::PLAYER_FIRE_S_TRIGGER", Player::PLAYER_FIRE_S_TRIGGER);
Con::setIntVariable( "$AFX::PLAYER_FIRE_ALT_S_TRIGGER", Player::PLAYER_FIRE_ALT_S_TRIGGER);
Con::setIntVariable( "$AFX::PLAYER_JUMP_S_TRIGGER", Player::PLAYER_JUMP_S_TRIGGER);
Con::setIntVariable( "$AFX::PLAYER_LANDING_S_TRIGGER", Player::PLAYER_LANDING_S_TRIGGER);
Con::setIntVariable( "$AFX::PLAYER_LF_FOOT_C_TRIGGER", Player::PLAYER_LF_FOOT_C_TRIGGER);
Con::setIntVariable( "$AFX::PLAYER_RT_FOOT_C_TRIGGER", Player::PLAYER_RT_FOOT_C_TRIGGER);
Con::setIntVariable( "$AFX::PLAYER_LANDING_C_TRIGGER", Player::PLAYER_LANDING_C_TRIGGER);
Con::setIntVariable( "$AFX::PLAYER_IDLE_C_TRIGGER", Player::PLAYER_IDLE_C_TRIGGER);
Con::setIntVariable( "$AFX::ILLUM_TERRAIN", 0);
Con::setIntVariable( "$AFX::ILLUM_ATLAS", 0);
Con::setIntVariable( "$AFX::ILLUM_DIF", 0);
Con::setIntVariable( "$AFX::ILLUM_DTS", 0);
Con::setIntVariable( "$AFX::ILLUM_ALL", 0);
Con::setIntVariable("$TypeMasks::TerrainLikeObjectType", TerrainLikeObjectType);
Con::setIntVariable("$TypeMasks::InteriorLikeObjectType", InteriorLikeObjectType);
Con::setIntVariable("$TypeMasks::PolysoupObjectType", InteriorLikeObjectType); // deprecated
Con::addVariable("$pref::Audio::usePlayerCentricListener", TypeBool, &sUsePlayerCentricListener);
afxResidueMgr* residue_mgr = new afxResidueMgr;
afxResidueMgr::setMaster(residue_mgr);
master_scope_id = 1;
master_choreographer_id = 1;
is_shutdown = false;
if (lm_old_names[0] == 0)
{
lm_old_names[0] = StringTable->insert("SG - Original Advanced (Lighting Pack)");
lm_old_names[1] = StringTable->insert("SG - Original Stock (Lighting Pack)");
lm_old_names[2] = StringTable->insert("SG - Inverse Square (Lighting Pack)");
lm_old_names[3] = StringTable->insert("SG - Inverse Square Fast Falloff (Lighting Pack)");
lm_old_names[4] = StringTable->insert("SG - Near Linear (Lighting Pack)");
lm_old_names[5] = StringTable->insert("SG - Near Linear Fast Falloff (Lighting Pack)");
//
lm_new_names[0] = StringTable->insert("Original Advanced");
lm_new_names[1] = StringTable->insert("Original Stock");
lm_new_names[2] = StringTable->insert("Inverse Square");
lm_new_names[3] = StringTable->insert("Inverse Square Fast Falloff");
lm_new_names[4] = StringTable->insert("Near Linear");
lm_new_names[5] = StringTable->insert("Near Linear Fast Falloff");
}
}
void arcaneFX::shutdown()
{
is_shutdown = true;
for (S32 i = 0; i < scoped_objs.size(); i++)
if (scoped_objs[i])
scoped_objs[i]->setScopeRegistered(false);
scoped_objs.clear();
for (S32 i = 0; i < client_choreographers.size(); i++)
if (client_choreographers[i])
client_choreographers[i]->clearChoreographerId();
client_choreographers.clear();
for (S32 i = 0; i < selectrons.size(); i++)
if (selectrons[i])
selectrons[i]->registered = false;
selectrons.clear();
afxResidueMgr* residue_mgr = afxResidueMgr::getMaster();
delete residue_mgr;
afxResidueMgr::setMaster(NULL);
}
MODULE_BEGIN( arcaneFX )
MODULE_INIT
{
arcaneFX::init();
}
MODULE_SHUTDOWN
{
arcaneFX::shutdown();
}
MODULE_END;
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void arcaneFX::advanceTime(U32 delta)
{
GameConnection* conn = GameConnection::getConnectionToServer();
if (conn && !conn->isZonedIn() && conn->getCameraObject() != 0)
{
conn->setZonedIn();
conn->postNetEvent(new ClientZoneInEvent());
}
afxZodiacMgr::frameReset();
afxResidueMgr::getMaster()->residueAdvanceTime();
}
//
U32 arcaneFX::registerChoreographer(afxChoreographer* ch)
{
if (!ch)
return 0;
active_choreographers.push_back(ch);
//Con::printf("registerChoreographer() -- size=%d %s", active_choreographers.size(),
// (ch->isServerObject()) ? "server" : "client");
return master_choreographer_id++;
}
void arcaneFX::unregisterChoreographer(afxChoreographer* ch)
{
if (!ch)
return;
for (U32 i = 0; i < active_choreographers.size(); i++)
{
if (ch == active_choreographers[i])
{
active_choreographers.erase_fast(i);
//Con::printf("unregisterChoreographer() -- size=%d %s", active_choreographers.size(),
// (ch->isServerObject()) ? "server" : "client");
return;
}
}
Con::errorf("arcaneFX::unregisterChoreographer() -- failed to find choreographer in list.");
}
void arcaneFX::registerClientChoreographer(afxChoreographer* ch)
{
if (!ch || ch->getChoreographerId() == 0)
return;
client_choreographers.push_back(ch);
}
void arcaneFX::unregisterClientChoreographer(afxChoreographer* ch)
{
if (!ch || ch->getChoreographerId() == 0)
return;
for (U32 i = 0; i < client_choreographers.size(); i++)
{
if (ch == client_choreographers[i])
{
client_choreographers.erase_fast(i);
return;
}
}
Con::errorf("arcaneFX::unregisterClientChoreographer() -- failed to find choreographer in list.");
}
afxChoreographer* arcaneFX::findClientChoreographer(U32 id)
{
for (U32 i = 0; i < client_choreographers.size(); i++)
{
if (id == client_choreographers[i]->getChoreographerId())
return client_choreographers[i];
}
return 0;
}
//
void arcaneFX::registerSelectronData(afxSelectronData* selectron)
{
if (!selectron)
return;
selectrons.push_back(selectron);
}
void arcaneFX::unregisterSelectronData(afxSelectronData* selectron)
{
if (!selectron)
return;
for (U32 i = 0; i < selectrons.size(); i++)
{
if (selectron == selectrons[i])
{
selectrons.erase_fast(i);
return;
}
}
Con::errorf("arcaneFX::unregisterSelectronData() -- failed to find selectron in list.");
}
afxSelectronData* arcaneFX::findSelectronData(U32 mask, U8 style)
{
for (U32 i = 0; i < selectrons.size(); i++)
if (selectrons[i]->matches(mask, style))
return selectrons[i];
return 0;
}
U16 arcaneFX::generateScopeId()
{
U16 ret_id = master_scope_id++;
if (master_scope_id >= BIT(GameBase::SCOPE_ID_BITS))
master_scope_id = 1;
return ret_id;
}
void arcaneFX::registerScopedObject(SceneObject* object)
{
scoped_objs.push_back(object);
object->setScopeRegistered(true);
for (S32 i = 0; i < client_choreographers.size(); i++)
if (client_choreographers[i])
client_choreographers[i]->restoreScopedObject(object);
}
SceneObject* arcaneFX::findScopedObject(U16 scope_id)
{
if (scoped_objs.size() > 0)
{
for (S32 i = scoped_objs.size()-1; i >= 0; i--)
if (scoped_objs[i] && scoped_objs[i]->getScopeId() == scope_id)
return scoped_objs[i];
}
return 0;
}
void arcaneFX::unregisterScopedObject(SceneObject* object)
{
if (scoped_objs.size() > 0)
{
for (S32 i = scoped_objs.size()-1; i >= 0; i--)
if (scoped_objs[i] == object)
{
scoped_objs.erase_fast(i);
if (object)
object->setScopeRegistered(false);
return;
}
}
}
void arcaneFX::syncToNewConnection(GameConnection* conn)
{
if (conn)
conn->setZonedIn();
for (U32 i = 0; i < active_choreographers.size(); i++)
{
if (active_choreographers[i])
active_choreographers[i]->sync_with_clients();
}
}
void arcaneFX::endMissionNotify()
{
for (S32 i = 0; i < scoped_objs.size(); i++)
if (scoped_objs[i])
scoped_objs[i]->setScopeRegistered(false);
scoped_objs.clear();
for (S32 i = 0; i < client_choreographers.size(); i++)
if (client_choreographers[i])
client_choreographers[i]->clearChoreographerId();
client_choreographers.clear();
for (S32 i = 0; i < selectrons.size(); i++)
if (selectrons[i])
selectrons[i]->registered = false;
selectrons.clear();
if (afxResidueMgr::getMaster())
afxResidueMgr::getMaster()->cleanup();
afxZodiacMgr::missionCleanup();
}
S32 arcaneFX::rolloverRayCast(Point3F start, Point3F end, U32 mask)
{
sIsFreeTargeting = false;
#if !defined(AFX_CAP_ROLLOVER_RAYCASTS)
return -1;
#else
GameConnection* conn = GameConnection::getConnectionToServer();
SceneObject* ctrl_obj = NULL;
if (!arcaneFX::sClickToTargetSelf && conn != NULL)
ctrl_obj = conn->getControlObject();
if (ctrl_obj)
ctrl_obj->disableCollision();
SceneObject* rollover_obj = (conn) ? conn->getRolloverObj() : 0;
SceneObject* picked_obj = 0;
RayInfo hit_info;
if (gClientContainer.castRay(start, end, mask, &hit_info))
picked_obj = dynamic_cast<SceneObject*>(hit_info.object);
if (ctrl_obj)
ctrl_obj->enableCollision();
if (picked_obj != rollover_obj)
{
if (rollover_obj)
rollover_obj->setSelectionFlags(rollover_obj->getSelectionFlags() & ~SceneObject::PRE_SELECTED);
if (picked_obj)
picked_obj->setSelectionFlags(picked_obj->getSelectionFlags() | SceneObject::PRE_SELECTED);
rollover_obj = picked_obj;
if (conn)
conn->setRolloverObj(rollover_obj);
}
return (picked_obj) ? picked_obj->getId() : -1;
#endif
}
bool arcaneFX::freeTargetingRayCast(Point3F start, Point3F end, U32 mask)
{
sIsFreeTargeting = true;
RayInfo hit_info;
if (!gClientContainer.castRay(start, end, mask, &hit_info))
{
sFreeTargetPosValid = false;
return false;
}
sFreeTargetPosValid = true;
sFreeTargetPos = hit_info.point;
return true;
}
StringTableEntry arcaneFX::convertLightingModelName(StringTableEntry lm_name)
{
for (U32 i = 0; i < N_LIGHTING_MODELS; i++)
{
if (lm_name == lm_old_names[i])
return lm_new_names[i];
}
return lm_name;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Console Functions
DefineEngineFunction(afxEndMissionNotify, void, (),,
"...\n\n"
"@ingroup AFX")
{
arcaneFX::endMissionNotify();
}
DefineEngineFunction(afxGetVersion, const char*, (),,
"...\n\n"
"@ingroup AFX")
{
return AFX_VERSION_STRING;
}
DefineEngineFunction(afxGetEngine, const char*, (),,
"...\n\n"
"@ingroup AFX")
{
return "T3D";
}
#if defined(AFX_CAP_ROLLOVER_RAYCASTS)
DefineEngineFunction(rolloverRayCast, S32, (Point3F start, Point3F end, U32 mask),,
"Performs a raycast from points start to end and returns the ID of nearest "
"intersecting object with a type found in the specified mask. "
"Returns -1 if no object is found.\n\n"
"@ingroup AFX")
{
return arcaneFX::rolloverRayCast(start, end, mask);
}
#endif
DefineEngineFunction(getRandomF, F32, (float a, float b), (F32_MAX, F32_MAX),
"Get a random float number between a and b.\n\n"
"@ingroup AFX")
{
if (b == F32_MAX)
{
if (a == F32_MAX)
return gRandGen.randF();
return gRandGen.randF(0.0f, a);
}
return (a + (b-a)*gRandGen.randF());
}
DefineEngineFunction(getRandomDir, Point3F, (Point3F axis, float thetaMin, float thetaMax, float phiMin, float phiMax),
(Point3F(0.0f,0.0f,0.0f), 0.0f, 180.0f, 0.0f, 360.0f),
"Get a random direction vector.\n\n"
"@ingroup AFX")
{
return MathUtils::randomDir(axis, thetaMin, thetaMax, phiMin, phiMax);
}
ConsoleFunction( MatrixInverseMulVector, const char*, 3, 3, "(MatrixF xfrm, Point3F vector)"
"@brief Multiply the vector by the affine inverse of the transform.\n\n"
"@ingroup AFX")
{
Point3F pos1(0.0f,0.0f,0.0f);
AngAxisF aa1(Point3F(0.0f,0.0f,0.0f),0.0f);
dSscanf(argv[1], "%g %g %g %g %g %g %g", &pos1.x, &pos1.y, &pos1.z, &aa1.axis.x, &aa1.axis.y, &aa1.axis.z, &aa1.angle);
MatrixF temp1(true);
aa1.setMatrix(&temp1);
temp1.setColumn(3, pos1);
Point3F vec1(0.0f,0.0f,0.0f);
dSscanf(argv[2], "%g %g %g", &vec1.x, &vec1.y, &vec1.z);
temp1.affineInverse();
Point3F result;
temp1.mulV(vec1, &result);
char* ret = Con::getReturnBuffer(256);
dSprintf(ret, 255, "%g %g %g", result.x, result.y, result.z);
return ret;
}
ConsoleFunction(moveTransformAbs, const char*, 3, 3, "(MatrixF xfrm, Point3F pos)"
"@brief Move the transform to the new absolute position.\n\n"
"@ingroup AFX")
{
Point3F pos1(0.0f,0.0f,0.0f);
AngAxisF aa1(Point3F(0.0f,0.0f,0.0f),0.0f);
dSscanf(argv[1], "%g %g %g %g %g %g %g", &pos1.x, &pos1.y, &pos1.z, &aa1.axis.x, &aa1.axis.y, &aa1.axis.z, &aa1.angle);
Point3F pos2(0.0f,0.0f,0.0f);
dSscanf(argv[2], "%g %g %g", &pos2.x, &pos2.y, &pos2.z);
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 255, "%g %g %g %g %g %g %g",
pos2.x, pos2.y, pos2.z,
aa1.axis.x, aa1.axis.y, aa1.axis.z,
aa1.angle);
return returnBuffer;
}
ConsoleFunction(moveTransformRel, const char*, 3, 3, "(MatrixF xfrm, Point3F pos)"
"@brief Move the transform to the new relative position.\n\n"
"@ingroup AFX")
{
Point3F pos1(0.0f,0.0f,0.0f);
AngAxisF aa1(Point3F(0.0f,0.0f,0.0f),0.0f);
dSscanf(argv[1], "%g %g %g %g %g %g %g", &pos1.x, &pos1.y, &pos1.z, &aa1.axis.x, &aa1.axis.y, &aa1.axis.z, &aa1.angle);
Point3F pos2(0.0f,0.0f,0.0f);
dSscanf(argv[2], "%g %g %g", &pos2.x, &pos2.y, &pos2.z);
pos2 += pos1;
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 255, "%g %g %g %g %g %g %g",
pos2.x, pos2.y, pos2.z,
aa1.axis.x, aa1.axis.y, aa1.axis.z,
aa1.angle);
return returnBuffer;
}
DefineEngineFunction(getFreeTargetPosition, Point3F, (),,
"@brief Returns the current location of the free target.\n\n"
"@ingroup AFX")
{
if (!arcaneFX::sFreeTargetPosValid)
return Point3F(0.0f, 0.0f, 0.0f);
return arcaneFX::sFreeTargetPos;
}
DefineEngineMethod(SceneObject, getSpeed, F32, (),,
"Returns the velocity of a scene-object.\n\n"
"@ingroup AFX")
{
return object->getVelocity().len();
}
static S32 mark_modkey = -1;
DefineEngineFunction(markDataBlocks, void, (),,
"@brief Called before a series of datablocks are reloaded to "
"help distinguish reloaded datablocks from already loaded ones.\n\n"
"@ingroup AFX")
{
mark_modkey = SimDataBlock::getNextModifiedKey();
}
DefineEngineFunction(touchDataBlocks, void, (),,
"@brief Called after a series of datablocks are reloaded to "
"trigger some important actions on the reloaded datablocks.\n\n"
"@ingroup AFX")
{
if (mark_modkey < 0)
return;
SimDataBlockGroup* g = Sim::getDataBlockGroup();
U32 groupCount = g->size();
for (S32 i = groupCount-1; i >= 0; i--)
{
SimDataBlock* simdb = (SimDataBlock*)(*g)[i];
if (simdb->getModifiedKey() > mark_modkey)
{
simdb->unregisterObject();
simdb->registerObject();
}
}
mark_modkey = -1;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// Syntax Error Checking
// (for checking eval() and compile() calls)
DefineEngineFunction(wasSyntaxError, bool, (),,
"@brief Returns true if script compiler had a syntax error. Useful "
"for detecting syntax errors after reloading a script.\n\n"
"@ingroup AFX")
{
return Compiler::gSyntaxError;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
// Network Object Identification
// These useful console methods come from the following code resource:
//
// How to Identify Objects from Client to Server or Server to Client by Nathan Davies
// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=4852
//
DefineEngineMethod(NetConnection, GetGhostIndex, S32, (NetObject* obj),,
"Returns the ghost-index for an object.\n\n"
"@ingroup AFX")
{
if (obj)
return object->getGhostIndex(obj);
return 0;
}
DefineEngineMethod(NetConnection, ResolveGhost, S32, (int ghostIndex),,
"Resolves a ghost-index into an object ID.\n\n"
"@ingroup AFX")
{
if (ghostIndex != -1)
{
NetObject* pObject = NULL;
if( object->isGhostingTo())
pObject = object->resolveGhost(ghostIndex);
else if( object->isGhostingFrom())
pObject = object->resolveObjectFromGhostIndex(ghostIndex);
if (pObject)
return pObject->getId();
}
return 0;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//////////////////////////////////////////////////////////////////////////
// TypeByteRange
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_STRUCT( ByteRange, ByteRange,,
"" )
END_IMPLEMENT_STRUCT;
ConsoleType( ByteRange, TypeByteRange, ByteRange, "")
ConsoleType( ByteRange, TypeByteRange2, ByteRange, "")
ConsoleGetType( TypeByteRange )
{
ByteRange* pt = (ByteRange *) dptr;
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%u %u", pt->low, pt->high);
return returnBuffer;
}
ConsoleSetType( TypeByteRange )
{
if(argc == 1)
{
ByteRange* range = (ByteRange*) dptr;
U32 lo, hi;
S32 args = dSscanf(argv[0], "%u %u", &lo, &hi);
range->low = (args > 0) ? lo : 0;
range->high = (args > 1) ? hi : 255;
}
else
Con::printf("ByteRange must be set as \"low\" or \"low high\"");
}
ConsoleGetType( TypeByteRange2 )
{
ByteRange* pt = (ByteRange *) dptr;
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%u %u", pt->low, pt->high);
return returnBuffer;
}
ConsoleSetType( TypeByteRange2 )
{
if(argc == 1)
{
ByteRange* range = (ByteRange*) dptr;
U32 lo, hi;
S32 args = dSscanf(argv[0], "%u %u", &lo, &hi);
range->low = (args > 0) ? lo : 0;
range->high = (args > 1) ? hi : lo;
}
else
Con::printf("ByteRange must be set as \"low\" or \"low high\"");
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
static void HSVtoRGB(F32 h, F32 s, F32 v, F32& r, F32& g, F32& b)
{
h = mFmod(h, 360.0f);
if (v == 0.0f)
r = g = b = 0.0f;
else if (s == 0.0f)
r = g = b = v;
else
{
F32 hf = h/60.0f;
S32 i = (S32) mFloor(hf);
F32 f = hf - i;
F32 pv = v*(1.0f - s);
F32 qv = v*(1.0f - s*f);
F32 tv = v*(1.0f - s*(1.0f - f));
switch (i)
{
case 0:
r = v; g = tv; b = pv;
break;
case 1:
r = qv; g = v; b = pv;
break;
case 2:
r = pv; g = v; b = tv;
break;
case 3:
r = pv; g = qv; b = v;
break;
case 4:
r = tv; g = pv; b = v;
break;
case 5:
r = v; g = pv; b = qv;
break;
default:
r = g = b = 0.0f;
break;
}
}
}
DefineEngineFunction(getColorFromHSV, const char*, (float hue, float sat, float val, float alpha), (0.0, 0.0, 1.0, 1.0),
"Coverts an HSV formatted color into an RBG color.\n\n"
"@param hue The hue of the color (0-360).\n"
"@param sat The saturation of the color (0-1).\n"
"@param val The value of the color (0-1).\n"
"@param alpha The alpha of the color (0-1).\n"
"@ingroup AFX")
{
LinearColorF rgb;
HSVtoRGB(hue, sat, val, rgb.red, rgb.green, rgb.blue);
rgb.alpha = alpha;
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%g %g %g %g", rgb.red, rgb.green, rgb.blue, rgb.alpha);
return returnBuffer;
}
DefineEngineFunction(ColorScale, const char*, ( LinearColorF color, float scalar ),,
"Returns color scaled by scalar (color*scalar).\n\n"
"@param color The color to be scaled.\n"
"@param scalar The amount to scale the color.\n"
"@ingroup AFX")
{
color *= scalar;
char* returnBuffer = Con::getReturnBuffer(256);
dSprintf(returnBuffer, 256, "%g %g %g %g", color.red, color.green, color.blue, color.alpha);
return returnBuffer;
}
DefineEngineFunction(getMinF, F32, (float a, float b),,
"Returns the lesser of the two arguments.\n\n"
"@ingroup AFX")
{
return getMin(a, b);
}
DefineEngineFunction(getMaxF, F32, (float a, float b),,
"Returns the greater of the two arguments.\n\n"
"@ingroup AFX")
{
return getMax(a, b);
}
ConsoleFunction(echoThru, const char*, 2, 0, "(string passthru, string text...)"
"Like echo(), but first argument is returned.\n"
"@ingroup AFX")
{
U32 len = 0;
S32 i;
for(i = 2; i < argc; i++)
len += dStrlen(argv[i]);
char *ret = Con::getReturnBuffer(len + 1);
ret[0] = 0;
for(i = 2; i < argc; i++)
dStrcat(ret, argv[i]);
Con::printf("%s -- [%s]", ret, argv[1].getStringValue());
ret[0] = 0;
return argv[1];
}
ConsoleFunction(warnThru, const char*, 2, 0, "(string passthru, string text...)"
"Like warn(), but first argument is returned.\n"
"@ingroup AFX")
{
U32 len = 0;
S32 i;
for(i = 2; i < argc; i++)
len += dStrlen(argv[i]);
char *ret = Con::getReturnBuffer(len + 1);
ret[0] = 0;
for(i = 2; i < argc; i++)
dStrcat(ret, argv[i]);
Con::warnf("%s -- [%s]", ret, argv[1].getStringValue());
ret[0] = 0;
return argv[1];
}
ConsoleFunction(errorThru, const char*, 2, 0, "(string passthru, string text...)"
"Like error(), but first argument is returned.\n"
"@ingroup AFX")
{
U32 len = 0;
S32 i;
for(i = 2; i < argc; i++)
len += dStrlen(argv[i]);
char *ret = Con::getReturnBuffer(len + 1);
ret[0] = 0;
for(i = 2; i < argc; i++)
dStrcat(ret, argv[i]);
Con::errorf("%s -- [%s]", ret, argv[1].getStringValue());
ret[0] = 0;
return argv[1];
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,214 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _ARCANE_FX_H_
#define _ARCANE_FX_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _PLATFORM_H_
#include "platform/platform.h"
#endif
#define AFX_VERSION_STRING "2.0"
#define AFX_VERSION 2.0
// #define AFX_CUSTOMIZED_BRANCH
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
#if defined(AFX_CUSTOMIZED_BRANCH)
#elif (TORQUE_GAME_ENGINE == 1100 || TORQUE_GAME_ENGINE >= 3000)
#define AFX_CAP_SCOPE_TRACKING
#define AFX_CAP_ROLLOVER_RAYCASTS
//#define AFX_CAP_AFXMODEL_TYPE
//#define BROKEN_POINT_IN_WATER
#define BROKEN_DAMAGEFLASH_WHITEOUT_BLACKOUT
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
#else
// This version of AFX source only supports T3D 1.1
#endif
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
#ifndef _CONSOLETYPES_H_
#include "console/consoleTypes.h"
#endif
#ifndef _ENGINEAPI_H_
#include "console/engineAPI.h"
#endif
#ifndef _SIMBASE_H_
#include "console/simBase.h"
#endif
#ifndef _BITSTREAM_H_
#include "core/stream/bitStream.h"
#endif
#ifndef _GAMEBASE_H_
#include "T3D/gameBase/gameBase.h"
#endif
#if defined(DGL_GRAPHICS_LAYER)
#ifndef _DGL_H_
#include "dgl/dgl.h"
#endif
#endif
class afxChoreographer;
class afxSelectronData;
class GameConnection;
class SceneObject;
class arcaneFX
{
public:
enum {
TARGETING_OFF,
TARGETING_STANDARD,
TARGETING_FREE
};
enum {
TARGET_CHECK_POLL,
TARGET_CHECK_ON_MOUSE_MOVE
};
private:
static Vector<afxChoreographer*> active_choreographers;
static Vector<afxChoreographer*> client_choreographers;
static Vector<afxSelectronData*> selectrons;
static Vector<SceneObject*> scoped_objs;
static bool is_shutdown;
public:
static StringTableEntry NULLSTRING;
static U32 sTargetSelectionMask;
static U32 sFreeTargetSelectionMask;
static bool sIsFreeTargeting;
static Point3F sFreeTargetPos;
static bool sFreeTargetPosValid;
static F32 sTargetSelectionRange;
static U32 sTargetSelectionTimeoutMS;
static bool sClickToTargetSelf;
static U32 sMissileCollisionMask;
static StringTableEntry sParameterFieldPrefix;
static F32 sTerrainZodiacZBias;
static F32 sInteriorZodiacZBias;
static F32 sPolysoupZodiacZBias;
static U32 master_choreographer_id;
static U16 master_scope_id;
public:
static void init();
static void shutdown();
static void advanceTime(U32 delta);
static U32 registerChoreographer(afxChoreographer*);
static void unregisterChoreographer(afxChoreographer*);
static void registerClientChoreographer(afxChoreographer*);
static void unregisterClientChoreographer(afxChoreographer*);
static afxChoreographer* findClientChoreographer(U32 id);
static void registerSelectronData(afxSelectronData*);
static void unregisterSelectronData(afxSelectronData*);
static afxSelectronData* findSelectronData(U32 obj_type_mask, U8 code);
static U16 generateScopeId();
static void registerScopedObject(SceneObject*);
static SceneObject* findScopedObject(U16 scope_id);
static void unregisterScopedObject(SceneObject*);
static void syncToNewConnection(GameConnection* conn);
static void endMissionNotify();
static S32 rolloverRayCast(Point3F start, Point3F end, U32 mask);
static bool freeTargetingRayCast(Point3F start, Point3F end, U32 mask);
static bool isShutdown() { return is_shutdown; }
static StringTableEntry convertLightingModelName(StringTableEntry lm_name);
private:
static bool sUsePlayerCentricListener;
public:
static bool usePlayerCentricListener() { return sUsePlayerCentricListener; }
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
class ByteRange
{
public:
U8 low;
U8 high;
public:
/*C*/ ByteRange() { low = 0; high = 255; }
/*C*/ ByteRange(U8 l, U8 h=255) { low = l; high = h; }
void set(U8 l, U8 h=255) { low = l; high = h; }
bool outOfRange(U8 v) { return (v < low || v > high); }
bool inRange(U8 v) { return !outOfRange(v); }
S32 getSpan() const { return high - low; }
};
DefineConsoleType(TypeByteRange, ByteRange)
DefineConsoleType(TypeByteRange2, ByteRange)
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
inline void writeDatablockID(BitStream* s, SimObject* simobj, bool packed=false)
{
if (s->writeFlag(simobj))
s->writeRangedU32(packed ? SimObjectId((uintptr_t)simobj) : simobj->getId(),
DataBlockObjectIdFirst, DataBlockObjectIdLast);
}
inline S32 readDatablockID(BitStream* s)
{
return (!s->readFlag()) ? 0 : ((S32)s->readRangedU32(DataBlockObjectIdFirst,
DataBlockObjectIdLast));
}
inline void registerForCleanup(SimObject* obj)
{
SimGroup* cleanup_grp = dynamic_cast<SimGroup*>(Sim::findObject("MissionCleanup"));
if (cleanup_grp)
cleanup_grp->addObject(obj);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
#define ST_NULLSTRING (arcaneFX::NULLSTRING)
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _ARCANE_FX_H_

View file

@ -0,0 +1,217 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxAnimClip.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxAnimClipData
IMPLEMENT_CO_DATABLOCK_V1(afxAnimClipData);
ConsoleDocClass( afxAnimClipData,
"@brief A datablock that specifies an Animation Clip effect.\n\n"
"An Animation Clip forces a target ShapeBase-derived object, such as Player or AIPlayer, to perform a particular "
"animation sequence. Animation Clip does not supply any new animation data, but simply selects, by name, a "
"sequence that is already defined in the target. Animation Clip can also target afxModel effects within the same "
"choreographer."
"\n\n"
"The target of an Animation Clip is the constraint source object specified by the posConstraint field of the enclosing "
"effect wrapper. The target must be a ShapeBase-derived object, or an afxModel and it must contain an animation "
"sequence with the same name as the clipName field."
"\n\n"
"Animation Clip controls the rate of animation playback and can even play a sequence in reverse. When an Animation "
"Clip selects a blended animation sequence, it is mixed with the current animation instead of replacing it. Animation "
"Clips can be used to activate multiple, overlapping blend sequences."
"\n\n"
"Normally when an Animation Clip is applied to a user-controlled Player, any interactive user actions will override the "
"animation selected by the clip, but Animation Clips can be configured to temporarily block out some user actions for "
"the duration of the clip."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxAnimClipData::afxAnimClipData()
{
clip_name = ST_NULLSTRING;
rate = 1.0f;
pos_offset = 0.0;
trans = 0.12f;
flags = 0;
ignore_disabled = false;
ignore_enabled = false;
is_death_anim = false;
lock_anim = false;
ignore_first_person = false;
ignore_third_person = false;
}
afxAnimClipData::afxAnimClipData(const afxAnimClipData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
clip_name = other.clip_name;
rate = other.rate;
pos_offset = other.pos_offset;
trans = other.trans;
flags = other.flags;
expand_flags();
}
void afxAnimClipData::onStaticModified(const char* slot, const char* newValue)
{
Parent::onStaticModified(slot, newValue);
merge_flags();
}
#define myOffset(field) Offset(field, afxAnimClipData)
void afxAnimClipData::initPersistFields()
{
addField("clipName", TYPEID< StringTableEntry >(), myOffset(clip_name),
"The name of an animation sequence to be played by a ShapeBase-derived object to which this effect is "
"constrained. Also works on afxModel effects.\n"
"default: \"\"\n");
addField("rate", TYPEID< F32 >(), myOffset(rate),
"The desired playback speed for the sequence. A value of 1.0 indicates forward playback at a normal rate. Negative "
"values cause the sequence to play backwards.\n"
"default: 1.0\n");
addField("posOffset", TYPEID< F32 >(), myOffset(pos_offset),
"Sets a starting offset for the selected animation clip. It directly specifies an animation thread position in the 0.0 to "
"1.0 range as a fraction of the clip's duration.\n"
"default: 1.0\n");
addField("transitionTime", TYPEID< F32 >(), myOffset(trans),
"The duration in which the active animation overlaps and blends into the sequence selected by the animation clip.\n"
"default: 0.12\n");
addField("ignoreCorpse", TYPEID< bool >(), myOffset(ignore_disabled),
"Specifies if the animation clip should not be applied to corpses or anything else with a disabled damage state.\n"
"default: false\n");
addField("ignoreLiving", TYPEID< bool >(), myOffset(ignore_enabled),
"Specifies if the animation clip should not be applied to living objects or anything else with an enabled damage "
"state.\n"
"default: false\n");
addField("treatAsDeathAnim", TYPEID< bool >(), myOffset(is_death_anim),
"Indicates if the animation clip is a death animation. If the target object dies during the effect, this will prevent "
"the object from playing another standard death animation after this clip finishes.\n"
"default: false\n");
addField("lockAnimation", TYPEID< bool >(), myOffset(lock_anim),
"Indicates if user control of a Player should be temporarily blocked during the clip. (See afxAnimLockData.)\n"
"default: false\n");
addField("ignoreFirstPerson", TYPEID< bool >(), myOffset(ignore_first_person),
"If true, the clip will not be played on targets that are the control object and the camera is in first person mode.\n"
"default: false\n");
addField("ignoreThirdPerson", TYPEID< bool >(), myOffset(ignore_third_person),
"If true, the clip will not be played on targets that are the control object and the camera is in third person mode.\n"
"default: false\n");
// synonyms
addField("ignoreDisabled", TYPEID< bool >(), myOffset(ignore_disabled),
"A synonym for ignoreLiving.");
addField("ignoreEnabled", TYPEID< bool >(), myOffset(ignore_enabled),
"A synonym for ignoreCorpse.");
Parent::initPersistFields();
}
bool afxAnimClipData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxAnimClipData::packData(BitStream* stream)
{
Parent::packData(stream);
merge_flags();
stream->writeString(clip_name);
stream->write(rate);
stream->write(pos_offset);
stream->write(trans);
stream->write(flags);
}
void afxAnimClipData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
clip_name = stream->readSTString();
stream->read(&rate);
stream->read(&pos_offset);
stream->read(&trans);
stream->read(&flags);
expand_flags();
}
bool afxAnimClipData::writeField(StringTableEntry fieldname, const char* value)
{
if (!Parent::writeField(fieldname, value))
return false;
// don't write the synonyms
if( fieldname == StringTable->insert("ignoreDisabled") )
return false;
if( fieldname == StringTable->insert("ignoreEnabled") )
return false;
return true;
}
void afxAnimClipData::expand_flags()
{
ignore_disabled = ((flags & IGNORE_DISABLED) != 0);
ignore_enabled = ((flags & IGNORE_ENABLED) != 0);
lock_anim = ((flags & BLOCK_USER_CONTROL) != 0);
is_death_anim = ((flags & IS_DEATH_ANIM) != 0);
ignore_first_person = ((flags & IGNORE_FIRST_PERSON) != 0);
ignore_third_person = ((flags & IGNORE_THIRD_PERSON) != 0);
}
void afxAnimClipData::merge_flags()
{
flags = (((ignore_disabled) ? IGNORE_DISABLED : 0) |
((ignore_enabled) ? IGNORE_ENABLED : 0) |
((lock_anim) ? BLOCK_USER_CONTROL : 0) |
((ignore_first_person) ? IGNORE_FIRST_PERSON : 0) |
((ignore_third_person) ? IGNORE_THIRD_PERSON : 0) |
((is_death_anim) ? IS_DEATH_ANIM : 0));
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,81 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_ANIM_CLIP_H_
#define _AFX_ANIM_CLIP_H_
class afxAnimClipData : public GameBaseData
{
typedef GameBaseData Parent;
enum
{
IGNORE_DISABLED = BIT(0),
IGNORE_ENABLED = BIT(1),
IS_DEATH_ANIM = BIT(2),
BLOCK_USER_CONTROL = BIT(3),
IGNORE_FIRST_PERSON = BIT(4),
IGNORE_THIRD_PERSON = BIT(5)
};
public:
StringTableEntry clip_name;
F32 rate;
F32 pos_offset;
F32 trans;
U8 flags;
bool ignore_disabled;
bool ignore_enabled;
bool is_death_anim;
bool lock_anim;
bool ignore_first_person;
bool ignore_third_person;
void expand_flags();
void merge_flags();
public:
/*C*/ afxAnimClipData();
/*C*/ afxAnimClipData(const afxAnimClipData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool writeField(StringTableEntry fieldname, const char* value);
virtual void onStaticModified(const char* slotName, const char* newValue = NULL);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxAnimClipData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_ANIM_CLIP_H_

View file

@ -0,0 +1,95 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxAnimLock.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxAnimLockData
IMPLEMENT_CO_DATABLOCK_V1(afxAnimLockData);
ConsoleDocClass( afxAnimLockData,
"@brief A datablock that specifies an Animation Lock effect.\n\n"
"Animation Lock is used to temporarily lock out user-controlled Player actions, usually while an Animation Clip is "
"concurrently playing. Animation Clips can already do this, but must lock out user actions for the entire clip length. "
"Sometimes you only want to block user actions for a short section of a longer playing animation, such as the part where "
"the Player is thrown into the air from an impact. With Animation Lock, you can set a specific timespan for when user "
"actions are blocked, independent of any Animation Clip timing."
"\n\n"
"The target of an Animation Lock is the constraint source object specified by the posConstraint field of the enclosing effect "
"wrapper. The target must be a Player, a subclass of Player, or an afxModel."
"\n\n"
"The timing of the Animation Lock is determined by the timing fields of the enclosing effect wrapper."
"\n\n"
"Locking behavior timing is set by fields of the enclosing effect wrapper, so afxAnimLockData does not require any fields. "
"However, TorqueScript syntax disallows the declaration of an empty datablock. Therefore, it is recommended that you set "
"a dynamic field named 'priority' to zero in the body of the datablock as a workaround to this limitation."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxAnimLockData::afxAnimLockData()
{
}
#define myOffset(field) Offset(field, afxAnimLockData)
void afxAnimLockData::initPersistFields()
{
Parent::initPersistFields();
}
bool afxAnimLockData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxAnimLockData::packData(BitStream* stream)
{
Parent::packData(stream);
}
void afxAnimLockData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,48 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_ANIM_LOCK_H_
#define _AFX_ANIM_LOCK_H_
class afxAnimLockData : public GameBaseData
{
typedef GameBaseData Parent;
public:
/*C*/ afxAnimLockData();
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
static void initPersistFields();
DECLARE_CONOBJECT(afxAnimLockData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_ANIM_LOCK_H_

View file

@ -0,0 +1,121 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "afx/ce/afxAreaDamage.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxAreaDamageData
IMPLEMENT_CO_DATABLOCK_V1(afxAreaDamageData);
ConsoleDocClass( afxAreaDamageData,
"@brief A datablock that specifies an Area Damage effect.\n\n"
"An Area Damage effect is useful for assigning area damage with unusual timing that must be synchronized with other "
"effects. Negative damage amounts can be used for healing effects."
"\n\n"
"The primary difference between afxAreaDamageData and afxDamageData, which is also capable of inflicting area damage, "
"is that afxAreaDamageData effects calculate the area damage in C++ code rather than calling out to the script function "
"radiusDamage(). In cases where area damage needs to be inflicted repeatedly or in areas crowded with many targets, "
"afxAreaDamageData is likely to get better performance."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxAreaDamageData::afxAreaDamageData()
{
flavor = ST_NULLSTRING;
amount = 0;
radius = 0;
impulse = 0;
notify_damage_src = false;
exclude_cons_obj = false;
}
afxAreaDamageData::afxAreaDamageData(const afxAreaDamageData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
flavor = other.flavor;
amount = other.amount;
radius = other.radius;
impulse = other.impulse;
notify_damage_src = other.notify_damage_src;
exclude_cons_obj = other.exclude_cons_obj;
}
#define myOffset(field) Offset(field, afxAreaDamageData)
void afxAreaDamageData::initPersistFields()
{
addField("flavor", TypeString, myOffset(flavor),
"An arbitrary string which is passed as an argument to a spell's onDamage() script "
"method. It is used to classify a type of damage such as 'melee', 'magical', or "
"'fire'.");
addField("damage", TypeF32, myOffset(amount),
"An amount of area damage to inflict on a target. Objects within half the radius "
"receive full damage which then diminishes out to the full distance of the specified "
"radius.");
addField("radius", TypeF32, myOffset(radius),
"Radius centered at the effect position in which damage will be applied.");
addField("impulse", TypeF32, myOffset(impulse),
"Specifies an amount of force to apply to damaged objects. Objects within half the "
"radius receive full impulse which then diminishes out to the full distance of the "
"specified radius.");
addField("notifyDamageSource", TypeBool, myOffset(notify_damage_src),
"When true, the onInflictedAreaDamage() method of the damaged object will be called "
"to notify it of the damage. This is useful for starting some effects or action that "
"responds to the damage.");
addField("excludeConstraintObject", TypeBool, myOffset(exclude_cons_obj),
"When true, the object specified as the effect's primary position constraint will not "
"receive any damage.");
Parent::initPersistFields();
}
bool afxAreaDamageData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxAreaDamageData::packData(BitStream* stream)
{
Parent::packData(stream);
}
void afxAreaDamageData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,62 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_AREA_DAMAGE_H_
#define _AFX_AREA_DAMAGE_H_
#include "afx/afxEffectDefs.h"
class afxAreaDamageData : public GameBaseData, public afxEffectDefs
{
typedef GameBaseData Parent;
public:
StringTableEntry flavor;
F32 amount;
F32 radius;
F32 impulse;
bool notify_damage_src;
bool exclude_cons_obj;
public:
/*C*/ afxAreaDamageData();
/*C*/ afxAreaDamageData(const afxAreaDamageData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxAreaDamageData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_AREA_DAMAGE_H_

View file

@ -0,0 +1,246 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "sim/netConnection.h"
#include "sfx/sfxDescription.h"
#include "afx/ce/afxAudioBank.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
IMPLEMENT_CO_DATABLOCK_V1(afxAudioBank);
ConsoleDocClass( afxAudioBank,
"@brief A datablock that specifies an Audio Bank effect.\n\n"
"afxAudioBank is very similar to the stock Torque SFXProfile datablock but it allows specification of up to 32 different sound "
"files. The sound that actually plays is determined by the playIndex field."
"\n\n"
"afxAudioBank is most useful when used in combination with field substitutions, whereby a substitution statement "
"assigned to playIndex selects a different sound (perhaps randomly) each time the effect is used."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxAudioBank::afxAudioBank()
{
mPath = ST_NULLSTRING;
mDescriptionObjectID = 0;
mDescriptionObject = NULL;
mPreload = false;
play_index = -1;
for (S32 i = 0; i < 32; i++)
mFilenames[i] = ST_NULLSTRING;
}
afxAudioBank::afxAudioBank(const afxAudioBank& other, bool temp_clone) : SimDataBlock(other, temp_clone)
{
mPath = other.mPath;
mDescriptionObject = other.mDescriptionObject;
mDescriptionObjectID = other.mDescriptionObjectID; // -- for pack/unpack of mDescriptionObject ptr
mPreload = other.mPreload;
play_index = other.play_index;
for (S32 i = 0; i < 32; i++)
mFilenames[i] = other.mFilenames[i];
}
afxAudioBank::~afxAudioBank()
{
if (!isTempClone())
return;
if (mDescriptionObject && mDescriptionObject->isTempClone())
{
delete mDescriptionObject;
mDescriptionObject = 0;
}
}
afxAudioBank* afxAudioBank::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
{
if (!owner)
return this;
afxAudioBank* sub_profile_db = this;
SFXDescription* desc_db;
if (mDescriptionObject && mDescriptionObject->getSubstitutionCount() > 0)
{
SFXDescription* orig_db = mDescriptionObject;
desc_db = new SFXDescription(*orig_db, true);
orig_db->performSubstitutions(desc_db, owner, index);
}
else
desc_db = 0;
if (this->getSubstitutionCount() > 0 || desc_db)
{
sub_profile_db = new afxAudioBank(*this, true);
performSubstitutions(sub_profile_db, owner, index);
if (desc_db)
sub_profile_db->mDescriptionObject = desc_db;
}
return sub_profile_db;
}
void afxAudioBank::onPerformSubstitutions()
{
}
void afxAudioBank::initPersistFields()
{
addField("path", TypeFilename, Offset(mPath, afxAudioBank),
"A filesystem path to the folder containing the sound files specified by the "
"filenames[] field. All sound files used in a single AudioBank must be located in "
"the same folder.");
addField("filenames", TypeString, Offset(mFilenames, afxAudioBank), 32,
"Up to 32 names of sound files found in the path folder. The sound that is actually "
"played by an Audio Bank effect is determined by the playIndex field.");
addField("description", TYPEID<SFXDescription>(), Offset(mDescriptionObject, afxAudioBank),
"SFXDescription datablock to use with this set of sounds.");
addField("preload", TypeBool, Offset(mPreload, afxAudioBank),
"If set to true, file is pre-loaded, otherwise it is loaded on-demand.");
addField("playIndex", TypeS32, Offset(play_index, afxAudioBank),
"An array index that selects a sound to play from the filenames[] field. Values "
"outside of the range of assigned filename[] entries will not play any sound.");
Parent::initPersistFields();
}
bool afxAudioBank::preload(bool server, String &errorStr)
{
if(!Parent::preload(server, errorStr))
return false;
return true;
}
bool afxAudioBank::onAdd()
{
if (!Parent::onAdd())
return false;
if (!mDescriptionObject && mDescriptionObjectID)
Sim::findObject(mDescriptionObjectID , mDescriptionObject);
// if this is client side, make sure that description is as well
if(mDescriptionObject)
{ // client side dataBlock id's are not in the dataBlock id range
if (getId() >= DataBlockObjectIdFirst && getId() <= DataBlockObjectIdLast)
{
SimObjectId pid = mDescriptionObject->getId();
if (pid < DataBlockObjectIdFirst || pid > DataBlockObjectIdLast)
{
Con::errorf(ConsoleLogEntry::General,"afxAudioBank: data dataBlock not networkable (use datablock to create).");
return false;
}
}
}
return(true);
}
void afxAudioBank::packData(BitStream* stream)
{
Parent::packData(stream);
if (stream->writeFlag(mDescriptionObject))
stream->writeRangedU32(mDescriptionObject->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast);
/*
char buffer[256];
if(!mFilename)
buffer[0] = 0;
else
dStrcpy(buffer, mFilename);
stream->writeString(buffer);
*/
stream->writeString(mPath);
for (S32 i = 0; i < 32; i++)
{
stream->writeString(mFilenames[i]);
if (mFilenames[i] == ST_NULLSTRING)
break;
}
stream->writeFlag(mPreload);
if (stream->writeFlag(play_index >= 0 && play_index < 32))
stream->writeInt(play_index, 5);
}
void afxAudioBank::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
if (stream->readFlag()) // AudioDescription
{
SimObjectId id = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
mDescriptionObjectID = id;
Sim::findObject(id, mDescriptionObject);
}
// Filename
/*
char buffer[256];
stream->readString(buffer);
mFilename = StringTable->insert(buffer);
*/
char buffer[256];
stream->readString(buffer);
mPath = StringTable->insert(buffer);
for (S32 i = 0; i < 32; i++)
{
stream->readString(buffer);
mFilenames[i] = StringTable->insert(buffer);
if (mFilenames[i] == ST_NULLSTRING)
break;
}
mPreload = stream->readFlag(); // Preload
if (stream->readFlag())
play_index = stream->readInt(5);
else
play_index = -1;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,67 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_AUDIO_BANK_H_
#define _AFX_AUDIO_BANK_H_
class SFXDescription;
class afxAudioBank: public SimDataBlock
{
private:
typedef SimDataBlock Parent;
public:
SFXDescription* mDescriptionObject;
U32 mDescriptionObjectID;
StringTableEntry mPath;
StringTableEntry mFilenames[32];
bool mPreload;
S32 play_index;
public:
/*C*/ afxAudioBank();
/*C*/ afxAudioBank(const afxAudioBank&, bool = false);
/*D*/ ~afxAudioBank();
static void initPersistFields();
virtual bool onAdd();
virtual void packData(BitStream* stream);
virtual void unpackData(BitStream* stream);
bool preload(bool server, String &errorStr);
afxAudioBank* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
virtual void onPerformSubstitutions();
virtual bool allowSubstitutions() const { return true; }
DECLARE_CONOBJECT(afxAudioBank);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_AUDIO_BANK_H_

View file

@ -0,0 +1,294 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "gfx/gfxAPI.h"
#include "math/mathIO.h"
#include "afx/afxChoreographer.h"
#include "afx/ce/afxBillboard.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxBillboardData
IMPLEMENT_CO_DATABLOCK_V1(afxBillboardData);
ConsoleDocClass( afxBillboardData,
"@brief A datablock that specifies a Billboard effect.\n\n"
"A Billboard effect is a textured quadrangle which is always aligned to face towards the camera. It is much like a single "
"static particle and is rendered in a similar fashion."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxBillboardData::afxBillboardData()
{
color.set(1.0f, 1.0f, 1.0f, 1.0f);
txr_name = ST_NULLSTRING;
dimensions.set(1.0f, 1.0f);
texCoords[0].set(0.0f, 0.0f);
texCoords[1].set(0.0f, 1.0f);
texCoords[2].set(1.0f, 1.0f);
texCoords[3].set(1.0f, 0.0f);
blendStyle = BlendUndefined;
srcBlendFactor = BLEND_UNDEFINED;
dstBlendFactor = BLEND_UNDEFINED;
texFunc = TexFuncModulate;
}
afxBillboardData::afxBillboardData(const afxBillboardData& other, bool temp_clone)
: GameBaseData(other, temp_clone)
{
color = other.color;
txr_name = other.txr_name;
txr = other.txr;
dimensions = other.dimensions;
texCoords[0] = other.texCoords[0];
texCoords[1] = other.texCoords[1];
texCoords[2] = other.texCoords[2];
texCoords[3] = other.texCoords[3];
blendStyle = other.blendStyle;
srcBlendFactor = other.srcBlendFactor;
dstBlendFactor = other.dstBlendFactor;
texFunc = other.texFunc;
}
#define myOffset(field) Offset(field, afxBillboardData)
extern EnumTable srcBlendFactorTable;
extern EnumTable dstBlendFactorTable;
ImplementEnumType( afxBillboard_BlendStyle, "Possible blending types.\n" "@ingroup afxBillboard\n\n" )
{ afxBillboardData::BlendNormal, "NORMAL", "..." },
{ afxBillboardData::BlendAdditive, "ADDITIVE", "..." },
{ afxBillboardData::BlendSubtractive, "SUBTRACTIVE", "..." },
{ afxBillboardData::BlendPremultAlpha, "PREMULTALPHA", "..." },
EndImplementEnumType;
ImplementEnumType( afxBillboard_TexFuncType, "Possible texture function types.\n" "@ingroup afxBillboard\n\n" )
{ afxBillboardData::TexFuncReplace, "replace", "..." },
{ afxBillboardData::TexFuncModulate, "modulate", "..." },
{ afxBillboardData::TexFuncAdd, "add", "..." },
EndImplementEnumType;
void afxBillboardData::initPersistFields()
{
addField("color", TypeColorF, myOffset(color),
"The color assigned to the quadrangle geometry. The way it combines with the given "
"texture varies according to the setting of the textureFunction field.");
addField("texture", TypeFilename, myOffset(txr_name),
"An image to use as the billboard's texture.");
addField("dimensions", TypePoint2F, myOffset(dimensions),
"A value-pair that specifies the horizontal and vertical dimensions of the billboard "
"in scene units.");
addField("textureCoords", TypePoint2F, myOffset(texCoords), 4,
"An array of four value-pairs that specify the UV texture coordinates for the four "
"corners of the billboard's quadrangle.");
addField("blendStyle", TYPEID<afxBillboardData::BlendStyle>(), myOffset(blendStyle),
"Selects a common blend factor preset. When set to 'user', srcBlendFactor and "
"dstBlendFactor can be used to set additional blend factor combinations.\n"
"Possible values: normal, additive, subtractive, premultalpha, or user.");
addField("srcBlendFactor", TYPEID<GFXBlend>(), myOffset(srcBlendFactor),
"Specifies source blend factor when blendStyle is set to 'user'.\n"
"Possible values: GFXBlendZero, GFXBlendOne, GFXBlendDestColor, GFXBlendInvDestColor, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha, GFXBlendDestAlpha, GFXBlendInvDestAlpha, or GFXBlendSrcAlphaSat");
addField("dstBlendFactor", TYPEID<GFXBlend>(), myOffset(dstBlendFactor),
"Specifies destination blend factor when blendStyle is set to 'user'.\n"
"Possible values: GFXBlendZero, GFXBlendOne, GFXBlendSrcColor, GFXBlendInvSrcColor, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha, GFXBlendDestAlpha, or GFXBlendInvDestAlpha");
addField("textureFunction", TYPEID<afxBillboardData::TexFuncType>(), myOffset(texFunc),
"Selects a texture function that determines how the texture pixels are combined "
"with the shaded color of the billboard's quadrangle geometry.\n"
"Possible values: replace, modulate, or add.");
Parent::initPersistFields();
}
void afxBillboardData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(color);
stream->writeString(txr_name);
mathWrite(*stream, dimensions);
mathWrite(*stream, texCoords[0]);
mathWrite(*stream, texCoords[1]);
mathWrite(*stream, texCoords[2]);
mathWrite(*stream, texCoords[3]);
stream->writeInt(srcBlendFactor, 4);
stream->writeInt(dstBlendFactor, 4);
stream->writeInt(texFunc, 4);
}
void afxBillboardData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&color);
txr_name = stream->readSTString();
txr = GFXTexHandle();
mathRead(*stream, &dimensions);
mathRead(*stream, &texCoords[0]);
mathRead(*stream, &texCoords[1]);
mathRead(*stream, &texCoords[2]);
mathRead(*stream, &texCoords[3]);
srcBlendFactor = (GFXBlend) stream->readInt(4);
dstBlendFactor = (GFXBlend) stream->readInt(4);
texFunc = stream->readInt(4);
}
bool afxBillboardData::preload(bool server, String &errorStr)
{
if (!Parent::preload(server, errorStr))
return false;
if (!server)
{
if (txr_name && txr_name[0] != '\0')
{
txr.set(txr_name, &GFXStaticTextureSRGBProfile, "Billboard Texture");
}
}
// if blend-style is set to User, check for defined blend-factors
if (blendStyle == BlendUser && (srcBlendFactor == BLEND_UNDEFINED || dstBlendFactor == BLEND_UNDEFINED))
{
blendStyle = BlendUndefined;
Con::warnf(ConsoleLogEntry::General, "afxBillboardData(%s) incomplete blend factor specification.", getName());
}
// silently switch Undefined blend-style to User if blend factors are both defined
if (blendStyle == BlendUndefined && srcBlendFactor != BLEND_UNDEFINED && dstBlendFactor != BLEND_UNDEFINED)
{
blendStyle = BlendUser;
}
// set pre-defined blend-factors
switch (blendStyle)
{
case BlendNormal:
srcBlendFactor = GFXBlendSrcAlpha;
dstBlendFactor = GFXBlendInvSrcAlpha;
break;
case BlendSubtractive:
srcBlendFactor = GFXBlendZero;
dstBlendFactor = GFXBlendInvSrcColor;
break;
case BlendPremultAlpha:
srcBlendFactor = GFXBlendOne;
dstBlendFactor = GFXBlendInvSrcAlpha;
break;
case BlendUser:
break;
case BlendAdditive:
srcBlendFactor = GFXBlendSrcAlpha;
dstBlendFactor = GFXBlendOne;
break;
case BlendUndefined:
default:
blendStyle = BlendNormal;
srcBlendFactor = GFXBlendSrcAlpha;
dstBlendFactor = GFXBlendInvSrcAlpha;
break;
}
return true;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxBillboard
IMPLEMENT_CO_NETOBJECT_V1(afxBillboard);
ConsoleDocClass( afxBillboard,
"@brief A Billboard effect as defined by an afxBillboardData datablock.\n\n"
"A Billboard effect is a textured quadrangle which is always aligned to "
"face towards the camera. It is much like a single static particle and is rendered "
"in a similar fashion.\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
);
afxBillboard::afxBillboard()
{
mNetFlags.clear();
mNetFlags.set(IsGhost);
mDataBlock = 0;
fade_amt = 1.0f;
is_visible = true;
sort_priority = 0;
live_color.set(1.0f, 1.0f, 1.0f, 1.0f);
}
afxBillboard::~afxBillboard()
{
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
bool afxBillboard::onNewDataBlock(GameBaseData* dptr, bool reload)
{
mDataBlock = dynamic_cast<afxBillboardData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
return false;
live_color = mDataBlock->color;
return true;
}
bool afxBillboard::onAdd()
{
if(!Parent::onAdd())
return false;
F32 width = mDataBlock->dimensions.x * 0.5f;
F32 height = mDataBlock->dimensions.y * 0.5f;
mObjBox = Box3F(Point3F(-width, -0.01f, -height), Point3F(width, 0.01f, height));
addToScene();
return true;
}
void afxBillboard::onRemove()
{
removeFromScene();
Parent::onRemove();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,131 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_BILLBOARD_H_
#define _AFX_BILLBOARD_H_
#include "afx/afxEffectDefs.h"
#define BLEND_UNDEFINED GFXBlend_COUNT
class afxBillboardData : public GameBaseData, public afxEffectDefs
{
typedef GameBaseData Parent;
public:
// This enum specifies common blend settings with predefined values
// for src/dst blend factors.
enum BlendStyle {
BlendUndefined,
BlendNormal,
BlendAdditive,
BlendSubtractive,
BlendPremultAlpha,
BlendUser,
};
enum TexFuncType {
TexFuncReplace,
TexFuncModulate,
TexFuncAdd,
};
public:
StringTableEntry txr_name;
GFXTexHandle txr;
LinearColorF color;
Point2F texCoords[4];
Point2F dimensions;
S32 blendStyle;
GFXBlend srcBlendFactor;
GFXBlend dstBlendFactor;
S32 texFunc;
public:
/*C*/ afxBillboardData();
/*C*/ afxBillboardData(const afxBillboardData&, bool = false);
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
bool preload(bool server, String &errorStr);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxBillboardData);
DECLARE_CATEGORY("AFX");
};
typedef afxBillboardData::BlendStyle afxBillboard_BlendStyle;
DefineEnumType( afxBillboard_BlendStyle );
typedef afxBillboardData::TexFuncType afxBillboard_TexFuncType;
DefineEnumType( afxBillboard_TexFuncType );
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxBillboard
class afxBillboard : public GameBase, public afxEffectDefs
{
typedef GameBase Parent;
friend class afxEA_Billboard;
private:
afxBillboardData* mDataBlock;
F32 fade_amt;
bool is_visible;
S8 sort_priority;
LinearColorF live_color;
GFXStateBlockRef normal_sb;
GFXStateBlockRef reflected_sb;
public:
/*C*/ afxBillboard();
/*D*/ ~afxBillboard();
virtual bool onNewDataBlock(GameBaseData* dptr, bool reload);
virtual bool onAdd();
virtual void onRemove();
void setFadeAmount(F32 amt) { fade_amt = amt; }
void setSortPriority(S8 priority) { sort_priority = priority; }
void setVisibility(bool flag) { is_visible = flag; }
virtual void prepRenderImage(SceneRenderState*);
void _renderBillboard(ObjectRenderInst*, SceneRenderState*, BaseMatInstance*);
DECLARE_CONOBJECT(afxBillboard);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_BILLBOARD_H_

View file

@ -0,0 +1,145 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "gfx/gfxTransformSaver.h"
#include "gfx/primBuilder.h"
#include "afx/afxChoreographer.h"
#include "afx/ce/afxBillboard.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxBillboard::prepRenderImage(SceneRenderState* state)
{
if (!is_visible)
return;
ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
ri->renderDelegate.bind(this, &afxBillboard::_renderBillboard);
ri->type = RenderPassManager::RIT_ObjectTranslucent;
ri->translucentSort = true;
ri->defaultKey = (U32)(dsize_t)mDataBlock;
ri->sortDistSq = getWorldBox().getSqDistanceToPoint( state->getCameraPosition() );
state->getRenderPass()->addInst(ri);
}
void afxBillboard::_renderBillboard(ObjectRenderInst *ri, SceneRenderState* state, BaseMatInstance* overrideMat)
{
if (overrideMat)
return;
// predraw
if (normal_sb.isNull())
{
GFXStateBlockDesc desc;
// Culling -- it's a billboard, so no backfaces
desc.setCullMode(GFXCullCW);
// Blending
desc.setBlend(true, mDataBlock->srcBlendFactor, mDataBlock->dstBlendFactor);
desc.alphaTestEnable = (desc.blendSrc == GFXBlendSrcAlpha &&
(desc.blendDest == GFXBlendInvSrcAlpha || desc.blendDest == GFXBlendOne));
desc.alphaTestRef = 1;
desc.alphaTestFunc = GFXCmpGreaterEqual;
desc.setZReadWrite(true);
desc.zFunc = GFXCmpLessEqual;
desc.zWriteEnable = false;
desc.samplersDefined = true;
switch (mDataBlock->texFunc)
{
case afxBillboardData::TexFuncReplace:
desc.samplers[0].textureColorOp = GFXTOPDisable;
break;
case afxBillboardData::TexFuncModulate:
desc.samplers[0].textureColorOp = GFXTOPModulate;
break;
case afxBillboardData::TexFuncAdd:
desc.samplers[0].textureColorOp = GFXTOPAdd;
break;
}
desc.samplers[1].textureColorOp = GFXTOPDisable;
normal_sb = GFX->createStateBlock(desc);
desc.setCullMode(GFXCullCCW);
reflected_sb = GFX->createStateBlock(desc);
}
if (state->isReflectPass())
GFX->setStateBlock(reflected_sb);
else
GFX->setStateBlock(normal_sb);
GFXTransformSaver saver;
GFX->multWorld(getRenderTransform());
GFX->setTexture(0, mDataBlock->txr);
MatrixF worldmod = GFX->getWorldMatrix();
MatrixF viewmod = GFX->getViewMatrix();
Point4F Position;
MatrixF ModelView;
ModelView.mul(viewmod, worldmod);
ModelView.getColumn(3, &Position);
ModelView.identity();
ModelView.setColumn(3, Position);
GFX->setWorldMatrix(ModelView);
MatrixF ident;
ident.identity();
GFX->setViewMatrix(ident);
F32 width = mDataBlock->dimensions.x * 0.5f * mObjScale.x;
F32 height = mDataBlock->dimensions.y * 0.5f * mObjScale.z;
Point3F points[4];
points[0].set( width, 0.0f, -height);
points[1].set(-width, 0.0f, -height);
points[2].set(-width, 0.0f, height);
points[3].set( width, 0.0f, height);
PrimBuild::begin(GFXTriangleStrip, 4);
{
PrimBuild::color4f(live_color.red, live_color.green, live_color.blue, live_color.alpha*fade_amt);
PrimBuild::texCoord2f(mDataBlock->texCoords[1].x, mDataBlock->texCoords[1].y);
PrimBuild::vertex3fv(points[1]);
PrimBuild::texCoord2f(mDataBlock->texCoords[2].x, mDataBlock->texCoords[2].y);
PrimBuild::vertex3fv(points[0]);
PrimBuild::texCoord2f(mDataBlock->texCoords[0].x, mDataBlock->texCoords[0].y);
PrimBuild::vertex3fv(points[2]);
PrimBuild::texCoord2f(mDataBlock->texCoords[3].x, mDataBlock->texCoords[3].y);
PrimBuild::vertex3fv(points[3]);
}
PrimBuild::end();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,132 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "scene/sceneRenderState.h"
#include "math/mathIO.h"
#include "afx/afxChoreographer.h"
#include "afx/ce/afxCameraPuppet.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxCameraPuppetData
IMPLEMENT_CO_DATABLOCK_V1(afxCameraPuppetData);
ConsoleDocClass( afxCameraPuppetData,
"@brief A datablock that specifies a Camera Puppet effect.\n\n"
"A Camera Puppet effect is used to control the position and orientation of the camera using the AFX constraint system. "
"Camera Puppet effects are useful for creating small cut-scenes and can add a lot of visual drama to a spell or effectron "
"effect."
"\n\n"
"Effective use of Camera Puppet effects require a fairly advanced understanding of how Torque cameras work in a "
"server-client context. Care must be taken to prevent client cameras from drifting too far out of sync from the server camera. "
"Otherwise, obvious discontinuities in the motion will result when the Camera Puppet ends and control is restored to the "
"server camera. Scoping problems can also result if a client camera is moved to a location that is inconsistent with the "
"scene scoping done by the server camera."
"\n\n"
"Often it is useful to manage camera controlling in an isolated effectron rather than directly incorporated into a magic-spell. "
"This way the camera controlling effectron can target the specific client associated with the spellcaster. The spellcasting "
"player observes the spell in a dramatic cut-scene-like fashion while other players continue to observe from their own "
"viewing locations."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxCameraPuppetData::afxCameraPuppetData()
{
cam_spec = ST_NULLSTRING;
networking = SERVER_AND_CLIENT;
}
afxCameraPuppetData::afxCameraPuppetData(const afxCameraPuppetData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
cam_spec = other.cam_spec;
networking = other.networking;
}
#define myOffset(field) Offset(field, afxCameraPuppetData)
void afxCameraPuppetData::initPersistFields()
{
addField("cameraSpec", TypeString, myOffset(cam_spec),
"This field is like the effect-wrapper fields for specifying constraint sources, "
"but here it specifies a target for the camera-puppet effect.");
addField("networking", TypeS8, myOffset(networking),
"Specifies the networking model used for the camerapuppet effect. The effect can "
"puppet just the server camera, just the client camera, or both.\n"
"Possible values: $AFX::SERVER_ONLY, $AFX::CLIENT_ONLY, or $AFX::SERVER_AND_CLIENT.");
// disallow some field substitutions
disableFieldSubstitutions("cameraSpec");
disableFieldSubstitutions("networking");
Parent::initPersistFields();
}
bool afxCameraPuppetData::onAdd()
{
if (Parent::onAdd() == false)
return false;
bool runs_on_s = ((networking & (SERVER_ONLY | SERVER_AND_CLIENT)) != 0);
bool runs_on_c = ((networking & (CLIENT_ONLY | SERVER_AND_CLIENT)) != 0);
cam_def.parseSpec(cam_spec, runs_on_s, runs_on_c);
return true;
}
void afxCameraPuppetData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(cam_spec);
stream->write(networking);
}
void afxCameraPuppetData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
cam_spec = stream->readSTString();
stream->read(&networking);
}
void afxCameraPuppetData::gather_cons_defs(Vector<afxConstraintDef>& defs)
{
if (cam_def.isDefined())
defs.push_back(cam_def);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,64 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_CAMERA_PUPPET_H_
#define _AFX_CAMERA_PUPPET_H_
#include "afx/ce/afxComponentEffect.h"
#include "afx/afxEffectDefs.h"
#include "afx/afxConstraint.h"
class afxCameraPuppetData : public GameBaseData, public afxEffectDefs, public afxComponentEffectData
{
typedef GameBaseData Parent;
public:
StringTableEntry cam_spec;
afxConstraintDef cam_def;
U8 networking;
virtual void gather_cons_defs(Vector<afxConstraintDef>& defs);
public:
/*C*/ afxCameraPuppetData();
/*C*/ afxCameraPuppetData(const afxCameraPuppetData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxCameraPuppetData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_CAMERA_PUPPET_H_

View file

@ -0,0 +1,118 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxCameraShake.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxCameraShakeData
IMPLEMENT_CO_DATABLOCK_V1(afxCameraShakeData);
ConsoleDocClass( afxCameraShakeData,
"@brief A datablock that specifies a Camera Shake effect.\n\n"
"Camera Shake internally utilizes the standard Torque CameraShake class to implement a shaken camera effect."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxCameraShakeData::afxCameraShakeData()
{
camShakeFreq.set( 10.0, 10.0, 10.0 );
camShakeAmp.set( 1.0, 1.0, 1.0 );
camShakeRadius = 10.0;
camShakeFalloff = 10.0;
}
afxCameraShakeData::afxCameraShakeData(const afxCameraShakeData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
camShakeFreq = other.camShakeFreq;
camShakeAmp = other.camShakeAmp;
camShakeRadius = other.camShakeRadius;
camShakeFalloff = other.camShakeFalloff;
}
#define myOffset(field) Offset(field, afxCameraShakeData)
void afxCameraShakeData::initPersistFields()
{
addField("frequency", TypePoint3F, Offset(camShakeFreq, afxCameraShakeData),
"The camera shake frequencies for all three axes: X, Y, Z.");
addField("amplitude", TypePoint3F, Offset(camShakeAmp, afxCameraShakeData),
"The camera shake amplitudes for all three axes: X, Y, Z.");
addField("radius", TypeF32, Offset(camShakeRadius, afxCameraShakeData),
"Radius about the effect position in which shaking will be applied.");
addField("falloff", TypeF32, Offset(camShakeFalloff, afxCameraShakeData),
"Magnitude by which shaking decreases over distance to radius.");
Parent::initPersistFields();
}
bool afxCameraShakeData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxCameraShakeData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(camShakeFreq.x);
stream->write(camShakeFreq.y);
stream->write(camShakeFreq.z);
stream->write(camShakeAmp.x);
stream->write(camShakeAmp.y);
stream->write(camShakeAmp.z);
stream->write(camShakeRadius);
stream->write(camShakeFalloff);
}
void afxCameraShakeData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&camShakeFreq.x);
stream->read(&camShakeFreq.y);
stream->read(&camShakeFreq.z);
stream->read(&camShakeAmp.x);
stream->read(&camShakeAmp.y);
stream->read(&camShakeAmp.z);
stream->read(&camShakeRadius);
stream->read(&camShakeFalloff);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,57 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_CAMERA_SHAKE_H_
#define _AFX_CAMERA_SHAKE_H_
class afxCameraShakeData : public GameBaseData
{
typedef GameBaseData Parent;
public:
VectorF camShakeFreq;
VectorF camShakeAmp;
F32 camShakeRadius;
F32 camShakeFalloff;
public:
/*C*/ afxCameraShakeData();
/*C*/ afxCameraShakeData(const afxCameraShakeData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxCameraShakeData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_CAMERA_SHAKE_H_

View file

@ -0,0 +1,103 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxCollisionEvent.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxCollisionEventData
IMPLEMENT_CO_DATABLOCK_V1(afxCollisionEventData);
ConsoleDocClass( afxCollisionEventData,
"@brief A datablock that specifies a Collision Event effect.\n\n"
"MORE NEEDED HERE.\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxCollisionEventData::afxCollisionEventData()
{
method_name = ST_NULLSTRING;
script_data = ST_NULLSTRING;
gen_trigger = false;
trigger_bit = 0;
}
afxCollisionEventData::afxCollisionEventData(const afxCollisionEventData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
method_name = other.method_name;
script_data = other.script_data;
gen_trigger = other.gen_trigger;
trigger_bit = other.trigger_bit;
}
#define myOffset(field) Offset(field, afxCollisionEventData)
void afxCollisionEventData::initPersistFields()
{
addField("methodName", TypeString, myOffset(method_name),
"...");
addField("scriptData", TypeString, myOffset(script_data),
"...");
addField("generateTrigger", TypeBool, myOffset(gen_trigger),
"...");
addField("triggerBit", TypeS8, myOffset(trigger_bit),
"...");
Parent::initPersistFields();
}
void afxCollisionEventData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(method_name);
stream->writeString(script_data);
if (stream->writeFlag(gen_trigger))
stream->write(trigger_bit);
}
void afxCollisionEventData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
method_name = stream->readSTString();
script_data = stream->readSTString();
gen_trigger = stream->readFlag();
if (gen_trigger)
stream->read(&trigger_bit);
else
trigger_bit = 0;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,59 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_COLLISION_EVENT_H_
#define _AFX_COLLISION_EVENT_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxCollisionEventData
struct afxCollisionEventData : public GameBaseData
{
typedef GameBaseData Parent;
public:
StringTableEntry method_name;
StringTableEntry script_data;
bool gen_trigger;
U8 trigger_bit;
public:
/*C*/ afxCollisionEventData();
/*C*/ afxCollisionEventData(const afxCollisionEventData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxCollisionEventData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_COLLISION_EVENT_H_

View file

@ -0,0 +1,41 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_COMPONENT_EFFECT_H_
#define _AFX_COMPONENT_EFFECT_H_
#include "core/util/tVector.h"
#include "afx/afxConstraint.h"
class afxComponentEffectData
{
public:
virtual void gather_cons_defs(Vector<afxConstraintDef>& defs) { };
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_COMPONENT_EFFECT_H_

View file

@ -0,0 +1,93 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxConsoleMessage.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxConsoleMessageData
IMPLEMENT_CO_DATABLOCK_V1(afxConsoleMessageData);
ConsoleDocClass( afxConsoleMessageData,
"@brief A datablock that specifies a Console Message effect.\n\n"
"Console Message effects are useful for debugging purposes when you want to make sure that an effect with a certain kind "
"of timing is actually getting executed and for evaluating some kinds of field substitutions."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxConsoleMessageData::afxConsoleMessageData()
{
message_str = ST_NULLSTRING;
}
afxConsoleMessageData::afxConsoleMessageData(const afxConsoleMessageData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
message_str = other.message_str;
}
#define myOffset(field) Offset(field, afxConsoleMessageData)
void afxConsoleMessageData::initPersistFields()
{
addField("message", TypeString, myOffset(message_str),
"A text message to be displayed when the effect is executed.");
Parent::initPersistFields();
}
bool afxConsoleMessageData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxConsoleMessageData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(message_str);
}
void afxConsoleMessageData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
message_str = stream->readSTString();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,54 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_CONSOLE_MESSAGE_H_
#define _AFX_CONSOLE_MESSAGE_H_
class afxConsoleMessageData : public GameBaseData
{
typedef GameBaseData Parent;
public:
StringTableEntry message_str;
public:
/*C*/ afxConsoleMessageData();
/*C*/ afxConsoleMessageData(const afxConsoleMessageData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxConsoleMessageData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_CONSOLE_MESSAGE_H_

View file

@ -0,0 +1,140 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxDamage.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxDamageData
IMPLEMENT_CO_DATABLOCK_V1(afxDamageData);
ConsoleDocClass( afxDamageData,
"@brief A datablock that specifies a Damage effect.\n\n"
"A Damage effect is useful for assigning damage with unusual timing that must be synchronized with other effects. They "
"can be used to deal direct damage, radius damage, and damage over time. Negative damage amounts can be used for "
"healing effects."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxDamageData::afxDamageData()
{
label = ST_NULLSTRING;
flavor = ST_NULLSTRING;
amount = 0;
repeats = 1;
ad_amount = 0;
radius = 0;
impulse = 0;
}
afxDamageData::afxDamageData(const afxDamageData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
label = other.label;
flavor = other.flavor;
amount = other.amount;
repeats = other.repeats;
ad_amount = other.ad_amount;
radius = other.radius;
impulse = other.impulse;
}
#define myOffset(field) Offset(field, afxDamageData)
void afxDamageData::initPersistFields()
{
addField("label", TypeString, myOffset(label),
"An arbitrary string which is passed as an argument to a spell's onDamage() script "
"method. It can be used to identify which damage effect the damage came from in "
"cases where more than one damage effect is used in a single spell.");
addField("flavor", TypeString, myOffset(flavor),
"An arbitrary string which is passed as an argument to a spell's onDamage() script "
"method. It is used to classify a type of damage such as 'melee', 'magical', or "
"'fire'.");
addField("directDamage", TypeF32, myOffset(amount),
"An amount of direct damage to inflict on a target.");
addField("directDamageRepeats", TypeS8, myOffset(repeats),
"The number of times to inflict the damage specified by directDamage. Values "
"greater than 1 inflict damage over time, with the amount of directDamage "
"repeatedly dealt at evenly spaced intervals over the lifetime of the effect.");
addField("areaDamage", TypeF32, myOffset(ad_amount),
"An amount of area damage to inflict on a target. Objects within half the radius "
"receive full damage which then diminishes out to the full distance of "
"areaDamageRadius.");
addField("areaDamageRadius", TypeF32, myOffset(radius),
"Radius centered at the effect position in which damage will be applied.");
addField("areaDamageImpulse", TypeF32, myOffset(impulse),
"Specifies an amount of force to apply to damaged objects. Objects within half the "
"radius receive full impulse which then diminishes out to the full distance of "
"areaDamageRadius.");
Parent::initPersistFields();
}
bool afxDamageData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxDamageData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(label);
stream->writeString(flavor);
stream->write(amount);
stream->write(repeats);
stream->write(ad_amount);
stream->write(radius);
stream->write(impulse);
}
void afxDamageData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
label = stream->readSTString();
flavor = stream->readSTString();
stream->read(&amount);
stream->read(&repeats);
stream->read(&ad_amount);
stream->read(&radius);
stream->read(&impulse);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,63 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_DAMAGE_H_
#define _AFX_DAMAGE_H_
#include "afx/afxEffectDefs.h"
class afxDamageData : public GameBaseData, public afxEffectDefs
{
typedef GameBaseData Parent;
public:
StringTableEntry label;
StringTableEntry flavor;
F32 amount;
U8 repeats;
F32 ad_amount;
F32 radius;
F32 impulse;
public:
/*C*/ afxDamageData();
/*C*/ afxDamageData(const afxDamageData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxDamageData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_DAMAGE_H_

View file

@ -0,0 +1,116 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxFootSwitch.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxFootSwitchData
IMPLEMENT_CO_DATABLOCK_V1(afxFootSwitchData);
ConsoleDocClass( afxFootSwitchData,
"@brief A datablock that specifies a Foot Switch effect.\n\n"
"A Foot Switch effect is used to disable some or all of the standard built-in footstep effects generated by Player objects."
"\n\n"
"Stock Player objects generate footprint decals, footstep sounds, and puffs of particle dust in response to special "
"animation triggers embedded in the Player's dts model. With the help of Phase Effects, AFX can substitute alternatives for "
"these built-in effects. When this is done, it is often preferable to turn off some or all of the built-in footstep effects."
"\n\n"
"Foot Switch effects are only meaningful when the primary position constraint is a Player or Player-derived object."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxFootSwitchData::afxFootSwitchData()
{
override_all = false;
override_decals = false;
override_sounds = false;
override_dust = false;
}
afxFootSwitchData::afxFootSwitchData(const afxFootSwitchData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
override_all = other.override_all;
override_decals = other.override_decals;
override_sounds = other.override_sounds;
override_dust = other.override_dust;
}
#define myOffset(field) Offset(field, afxFootSwitchData)
void afxFootSwitchData::initPersistFields()
{
addField("overrideAll", TypeBool, myOffset(override_all),
"When true, all of a Player's footstep effects are turned off for the duration of "
"the foot-switch effect.");
addField("overrideDecals", TypeBool, myOffset(override_decals),
"Specifically selects whether the Player's footprint decals are enabled.");
addField("overrideSounds", TypeBool, myOffset(override_sounds),
"Specifically selects whether the Player's footstep sounds are enabled.");
addField("overrideDust", TypeBool, myOffset(override_dust),
"Specifically selects whether the Player's footstep puffs of dust are enabled.");
Parent::initPersistFields();
}
void afxFootSwitchData::packData(BitStream* stream)
{
Parent::packData(stream);
if (!stream->writeFlag(override_all))
{
stream->writeFlag(override_decals);
stream->writeFlag(override_sounds);
stream->writeFlag(override_dust);
}
}
void afxFootSwitchData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
override_all = stream->readFlag();
if (!override_all)
{
override_decals = stream->readFlag();
override_sounds = stream->readFlag();
override_dust = stream->readFlag();
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,56 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_FOOT_SWITCH_H_
#define _AFX_FOOT_SWITCH_H_
class afxFootSwitchData : public GameBaseData
{
typedef GameBaseData Parent;
public:
bool override_all;
bool override_decals;
bool override_sounds;
bool override_dust;
public:
/*C*/ afxFootSwitchData();
/*C*/ afxFootSwitchData(const afxFootSwitchData&, bool = false);
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxFootSwitchData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_FOOT_SWITCH_H_

View file

@ -0,0 +1,109 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxGuiController.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxGuiControllerData
IMPLEMENT_CO_DATABLOCK_V1(afxGuiControllerData);
ConsoleDocClass( afxGuiControllerData,
"@brief A datablock that specifies a Gui Controller effect.\n\n"
"A Gui Controller enables effect manipulation of pre-existing gui controls. With a Gui Controller effect, a regular gui control "
"is located by name, made visible during the lifetime of the effect, and potentially repositioned by projecting 3D constraint "
"positions into 2D screen space. In addition, when used with a progress-bar control, (GuiProgressCtrl, afxSpellCastBar, "
"afxStatusBar), the progress-bar will continuously reflect the elapsed progress of the effect over its lifetime."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxGuiControllerData::afxGuiControllerData()
{
control_name = ST_NULLSTRING;
preserve_pos = false;
ctrl_client_only = false;
}
afxGuiControllerData::afxGuiControllerData(const afxGuiControllerData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
control_name = other.control_name;
preserve_pos = other.preserve_pos;
ctrl_client_only = other.ctrl_client_only;
}
#define myOffset(field) Offset(field, afxGuiControllerData)
void afxGuiControllerData::initPersistFields()
{
addField("controlName", TypeString, myOffset(control_name),
"Specifies the name of an existing gui-control.");
addField("preservePosition", TypeBool, myOffset(preserve_pos),
"When true, the gui-control will retain its initial position, otherwise the "
"gui-control position will be continuously updated using a projection of the "
"3D constraint position into 2D screen coordinates.");
addField("controllingClientOnly", TypeBool, myOffset(ctrl_client_only),
"If true, the effect will only be applied to a gui-control on the client that "
"matches the controlling-client of the primary position constraint object.");
Parent::initPersistFields();
}
bool afxGuiControllerData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxGuiControllerData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(control_name);
stream->writeFlag(preserve_pos);
stream->writeFlag(ctrl_client_only);
}
void afxGuiControllerData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
control_name = stream->readSTString();
preserve_pos = stream->readFlag();
ctrl_client_only = stream->readFlag();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,58 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_GUI_CONTROLLER_H_
#define _AFX_GUI_CONTROLLER_H_
#include "afx/afxEffectDefs.h"
class afxGuiControllerData : public GameBaseData, public afxEffectDefs
{
typedef GameBaseData Parent;
public:
StringTableEntry control_name;
bool preserve_pos;
bool ctrl_client_only;
public:
/*C*/ afxGuiControllerData();
/*C*/ afxGuiControllerData(const afxGuiControllerData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxGuiControllerData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_GUI_CONTROLLER_H_

View file

@ -0,0 +1,103 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxGuiText.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxGuiTextData
IMPLEMENT_CO_DATABLOCK_V1(afxGuiTextData);
ConsoleDocClass( afxGuiTextData,
"@brief A datablock that specifies a Gui Text effect.\n\n"
"A Gui Text effect, with the help of an existing afxGuiTextHud, can be used to display 2D text effects on the Gui Canvas. "
"Essentially, using Gui Text effects with an afxGuiTextHud is like using the stock GuiShapeNameHud, but with the ability "
"to make additional text elements come and go as effects constrained to the projection of 3D positions onto the 2D screen."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxGuiTextData::afxGuiTextData()
{
text_str = ST_NULLSTRING;
text_clr.set(1,1,1,1);
}
afxGuiTextData::afxGuiTextData(const afxGuiTextData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
text_str = other.text_str;
text_clr = other.text_clr;
}
#define myOffset(field) Offset(field, afxGuiTextData)
void afxGuiTextData::initPersistFields()
{
addField("text", TypeString, myOffset(text_str),
"The literal text to display on the afxGuiTextHud. The center of the text will be "
"placed at the projection of the 3D constraint position into 2D screen space.\n"
"If the text field is set to the special string, '#shapeName', the shape name of the "
"primary position constraint object will be used. (This is only meaningful if the "
"constraint source is a ShapeBase-derived object.)");
addField("color", TypeColorF, myOffset(text_clr),
"A color value for the text label.");
Parent::initPersistFields();
}
bool afxGuiTextData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxGuiTextData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(text_str);
stream->write(text_clr);
}
void afxGuiTextData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
text_str = stream->readSTString();
stream->read(&text_clr);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,57 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_GUI_TEXT_H_
#define _AFX_GUI_TEXT_H_
#include "afx/afxEffectDefs.h"
class afxGuiTextData : public GameBaseData, public afxEffectDefs
{
typedef GameBaseData Parent;
public:
StringTableEntry text_str;
LinearColorF text_clr;
public:
/*C*/ afxGuiTextData();
/*C*/ afxGuiTextData(const afxGuiTextData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxGuiTextData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_GUI_TEXT_H_

View file

@ -0,0 +1,41 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "afx/ce/afxLight.h"
IMPLEMENT_CO_DATABLOCK_V1(afxLightData);
ConsoleDocClass( afxLightData,
"@brief afxLightData is a legacy datablock which is not supported for T3D.\n\n"
"In T3D, instead of afxLightData, use afxT3DPointLightData or afxT3DSpotLightData.\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,38 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_LIGHT_H_
#define _AFX_LIGHT_H_
struct afxLightData : public GameBaseData
{
typedef GameBaseData Parent;
DECLARE_CONOBJECT(afxLightData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_LIGHT_H_

View file

@ -0,0 +1,243 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "T3D/lightAnimData.h"
#include "afx/ce/afxLightBase_T3D.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxT3DLightBaseData
IMPLEMENT_CO_DATABLOCK_V1(afxT3DLightBaseData);
ConsoleDocClass( afxT3DLightBaseData,
"@brief A datablock baseclass for afxT3DPointLightData and afxT3DSpotLightData.\n\n"
"Not intended to be used directly, afxT3DLightBaseData exists to provide base member variables and generic functionality "
"for the derived classes afxT3DPointLightData and afxT3DSpotLightData."
"\n\n"
"@see afxT3DPointLightData\n\n"
"@see afxT3DSpotLightData\n\n"
"@see PointLight\n\n"
"@see SpotLight\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxT3DLightBaseData::afxT3DLightBaseData()
: mIsEnabled( true ),
mColor( LinearColorF::WHITE ),
mBrightness( 1.0f ),
mCastShadows( false ),
mPriority( 1.0f ),
mAnimationData( NULL ),
mFlareData( NULL ),
mFlareScale( 1.0f )
{
mLocalRenderViz = false;
// marked true if datablock ids need to
// be converted into pointers
do_id_convert = false;
}
afxT3DLightBaseData::afxT3DLightBaseData(const afxT3DLightBaseData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
mIsEnabled = other.mIsEnabled;
mColor = other.mColor;
mBrightness = other.mBrightness;
mCastShadows = other.mCastShadows;
mPriority = other.mPriority;
mAnimationData = other.mAnimationData;
mAnimState = other.mAnimState;
mFlareData = other.mFlareData;
mFlareScale = other.mFlareScale;
mLocalRenderViz = other.mLocalRenderViz;
do_id_convert = other.do_id_convert;
}
//
// NOTE: keep this as consistent as possible with LightBase::initPersistFields()
//
void afxT3DLightBaseData::initPersistFields()
{
// We only add the basic lighting options that all lighting
// systems would use... the specific lighting system options
// are injected at runtime by the lighting system itself.
addGroup( "Light" );
addField( "isEnabled", TypeBool, Offset( mIsEnabled, afxT3DLightBaseData ),
"Enables/Disables the object rendering and functionality in the scene.");
addField( "color", TypeColorF, Offset( mColor, afxT3DLightBaseData ),
"Changes the base color hue of the light.");
addField( "brightness", TypeF32, Offset( mBrightness, afxT3DLightBaseData ),
"Adjusts the lights power, 0 being off completely.");
addField( "castShadows", TypeBool, Offset( mCastShadows, afxT3DLightBaseData ),
"Enables/disables shadow casts by this light.");
addField( "priority", TypeF32, Offset( mPriority, afxT3DLightBaseData ),
"Used for sorting of lights by the light manager. Priority determines if a light "
"has a stronger effect than, those with a lower value");
addField( "localRenderViz", TypeBool, Offset( mLocalRenderViz, afxT3DLightBaseData ),
"Enables/disables a semi-transparent geometry to help visualize the light's "
"range and placement.");
endGroup( "Light" );
addGroup( "Light Animation" );
addField( "animate", TypeBool, Offset( mAnimState.active, afxT3DLightBaseData ),
"Toggles animation for the light on and off");
addField( "animationType", TYPEID<LightAnimData>(), Offset( mAnimationData, afxT3DLightBaseData ),
"Datablock containing light animation information (LightAnimData)");
addField( "animationPeriod", TypeF32, Offset( mAnimState.animationPeriod, afxT3DLightBaseData ),
"The length of time in seconds for a single playback of the light animation");
addField( "animationPhase", TypeF32, Offset( mAnimState.animationPhase, afxT3DLightBaseData ),
"The phase used to offset the animation start time to vary the animation of "
"nearby lights.");
endGroup( "Light Animation" );
addGroup( "Misc" );
addField( "flareType", TYPEID<LightFlareData>(), Offset( mFlareData, afxT3DLightBaseData ),
"Datablock containing light flare information (LightFlareData)");
addField( "flareScale", TypeF32, Offset( mFlareScale, afxT3DLightBaseData ),
"Globally scales all features of the light flare");
endGroup( "Misc" );
/*
// Now inject any light manager specific fields.
LightManager::initLightFields();
*/
// We do the parent fields at the end so that
// they show up that way in the inspector.
Parent::initPersistFields();
}
bool afxT3DLightBaseData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxT3DLightBaseData::packData(BitStream* stream)
{
Parent::packData(stream);
// note: BitStream's overloaded write() for LinearColorF will convert
// to ColorI for transfer and then back to LinearColorF. This is fine
// for most color usage but for lighting colors we want to preserve
// "pushed" color values which may be greater than 1.0 so the color
// is instead sent as individual color primaries.
stream->write( mColor.red );
stream->write( mColor.green );
stream->write( mColor.blue );
stream->write( mBrightness );
stream->writeFlag( mCastShadows );
stream->write( mAnimState.animationPeriod );
stream->write( mAnimState.animationPhase );
stream->write( mFlareScale );
writeDatablockID(stream, mAnimationData, packed);
writeDatablockID(stream, mFlareData, packed);
}
void afxT3DLightBaseData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read( &mColor.red );
stream->read( &mColor.green );
stream->read( &mColor.blue );
mColor.alpha = 1.0f;
stream->read( &mBrightness );
mCastShadows = stream->readFlag();
stream->read( &mAnimState.animationPeriod );
stream->read( &mAnimState.animationPhase );
stream->read( &mFlareScale );
mAnimationData = (LightAnimData*) readDatablockID(stream);
mFlareData = (LightFlareData*) readDatablockID(stream);
do_id_convert = true;
}
bool afxT3DLightBaseData::preload(bool server, String &errorStr)
{
if (!Parent::preload(server, errorStr))
return false;
// Resolve objects transmitted from server
if (!server)
{
if (do_id_convert)
{
SimObjectId anim_id = SimObjectId((uintptr_t)mAnimationData);
if (anim_id != 0)
{
// try to convert id to pointer
if (!Sim::findObject(anim_id, mAnimationData))
{
Con::errorf(ConsoleLogEntry::General,
"afxT3DLightBaseData::preload() -- bad datablockId: 0x%x (animationType)",
anim_id);
}
}
SimObjectId flare_id = SimObjectId((uintptr_t)mFlareData);
if (flare_id != 0)
{
// try to convert id to pointer
if (!Sim::findObject(flare_id, mFlareData))
{
Con::errorf(ConsoleLogEntry::General,
"afxT3DLightBaseData::preload() -- bad datablockId: 0x%x (flareType)",
flare_id);
}
}
do_id_convert = false;
}
}
return true;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,73 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_T3D_LIGHT_BASE_H_
#define _AFX_T3D_LIGHT_BASE_H_
#include "T3D/lightBase.h"
class LightAnimData;
class LightFlareData;
class afxT3DLightBaseData : public GameBaseData
{
typedef GameBaseData Parent;
public:
bool mIsEnabled;
LinearColorF mColor;
F32 mBrightness;
bool mCastShadows;
F32 mPriority;
LightAnimData* mAnimationData;
LightAnimState mAnimState;
bool mLocalRenderViz;
LightFlareData* mFlareData;
F32 mFlareScale;
bool do_id_convert;
public:
/*C*/ afxT3DLightBaseData();
/*C*/ afxT3DLightBaseData(const afxT3DLightBaseData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
bool preload(bool server, String &errorStr);
static void initPersistFields();
DECLARE_CONOBJECT(afxT3DLightBaseData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_T3D_LIGHT_BASE_H_

View file

@ -0,0 +1,127 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "lighting/lightInfo.h"
#include "T3D/projectile.h"
#include "afx/ce/afxMachineGun.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxMachineGunData
IMPLEMENT_CO_DATABLOCK_V1(afxMachineGunData);
ConsoleDocClass( afxMachineGunData,
"@brief A datablock that specifies a Machine Gun effect.\n\n"
"Machine Gun is a simple but useful effect for rapidly shooting standard Torque Projectile objects. For performance "
"reasons, keep in mind that each bullet is a separate Projectile object, which is not a very lightweight object."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxMachineGunData::afxMachineGunData()
{
projectile_data = 0;
rounds_per_minute = 60;
}
afxMachineGunData::afxMachineGunData(const afxMachineGunData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
projectile_data = other.projectile_data;
rounds_per_minute = other.rounds_per_minute;
}
#define myOffset(field) Offset(field, afxMachineGunData)
void afxMachineGunData::initPersistFields()
{
addField("projectile", TYPEID<ProjectileData>(), myOffset(projectile_data),
"A ProjectileData datablock describing the projectile to be launched.");
addField("roundsPerMinute", TypeS32, myOffset(rounds_per_minute),
"Specifies the number of projectiles fired over a minute of time. A value of 1200 "
"will create 20 projectiles per second.\n"
"Sample values for real machine guns:\n"
" AK-47 = 600, M16 = 750-900, UZI = 600");
Parent::initPersistFields();
// disallow some field substitutions
disableFieldSubstitutions("projectile");
}
bool afxMachineGunData::onAdd()
{
if (Parent::onAdd() == false)
return false;
if (projectile_data)
{
if (getId() >= DataBlockObjectIdFirst && getId() <= DataBlockObjectIdLast)
{
SimObjectId pid = projectile_data->getId();
if (pid < DataBlockObjectIdFirst || pid > DataBlockObjectIdLast)
{
Con::errorf(ConsoleLogEntry::General,"afxMachineGunData: bad ProjectileData datablock.");
return false;
}
}
}
return true;
}
void afxMachineGunData::packData(BitStream* stream)
{
Parent::packData(stream);
if (stream->writeFlag(projectile_data))
stream->writeRangedU32(projectile_data->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast);
stream->write(rounds_per_minute);
}
void afxMachineGunData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
if (stream->readFlag())
{
SimObjectId id = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
Sim::findObject(id, projectile_data);
}
stream->read(&rounds_per_minute);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,59 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_MACHINE_GUN_H_
#define _AFX_MACHINE_GUN_H_
#include "afx/afxEffectDefs.h"
class ProjectileData;
class afxMachineGunData : public GameBaseData, public afxEffectDefs
{
typedef GameBaseData Parent;
public:
ProjectileData* projectile_data;
S32 rounds_per_minute;
public:
/*C*/ afxMachineGunData();
/*C*/ afxMachineGunData(const afxMachineGunData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxMachineGunData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_MACHINE_GUN_H_

View file

@ -0,0 +1,770 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "T3D/objectTypes.h"
#include "T3D/gameBase/gameProcess.h"
#include "core/resourceManager.h"
#include "sim/netConnection.h"
#include "scene/sceneRenderState.h"
#include "scene/sceneManager.h"
#include "ts/tsShapeInstance.h"
#include "ts/tsMaterialList.h"
#include "afx/ce/afxModel.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxModelData
IMPLEMENT_CO_DATABLOCK_V1(afxModelData);
ConsoleDocClass( afxModelData,
"@brief A datablock that specifies a Model effect.\n\n"
"A Model effect is a lightweight client-only geometry object useful for effect-driven props."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxModelData::afxModelData()
{
shapeName = ST_NULLSTRING;
sequence = ST_NULLSTRING;
seq_rate = 1.0f;
seq_offset = 0.0f;
alpha_mult = 1.0f;
use_vertex_alpha = false;
force_on_material_flags = 0;
force_off_material_flags = 0;
texture_filtering = true;
fog_mult = 1.0f;
remap_txr_tags = ST_NULLSTRING;
remap_buffer = 0;
overrideLightingOptions = false;
receiveSunLight = true;
receiveLMLighting = true;
useAdaptiveSelfIllumination = false;
useCustomAmbientLighting = false;
customAmbientForSelfIllumination = false;
customAmbientLighting = LinearColorF(0.0f, 0.0f, 0.0f);
shadowEnable = false;
shadowSize = 128;
shadowMaxVisibleDistance = 80.0f;
shadowProjectionDistance = 10.0f;
shadowSphereAdjust = 1.0;
}
afxModelData::afxModelData(const afxModelData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
shapeName = other.shapeName;
shape = other.shape; // --
sequence = other.sequence;
seq_rate = other.seq_rate;
seq_offset = other.seq_offset;
alpha_mult = other.alpha_mult;
use_vertex_alpha = other.use_vertex_alpha;
force_on_material_flags = other.force_on_material_flags;
force_off_material_flags = other.force_off_material_flags;
texture_filtering = other.texture_filtering;
fog_mult = other.fog_mult;
remap_txr_tags = other.remap_txr_tags;
remap_buffer = other.remap_buffer;
overrideLightingOptions = other.overrideLightingOptions;
receiveSunLight = other.receiveSunLight;
receiveLMLighting = other.receiveLMLighting;
useAdaptiveSelfIllumination = other.useAdaptiveSelfIllumination;
useCustomAmbientLighting = other.useCustomAmbientLighting;
customAmbientForSelfIllumination = other.customAmbientForSelfIllumination;
customAmbientLighting = other.customAmbientLighting;
shadowEnable = other.shadowEnable;
}
afxModelData::~afxModelData()
{
if (remap_buffer)
dFree(remap_buffer);
}
bool afxModelData::preload(bool server, String &errorStr)
{
if (Parent::preload(server, errorStr) == false)
return false;
// don't need to do this stuff on the server
if (server)
return true;
if (shapeName != ST_NULLSTRING && !shape)
{
shape = ResourceManager::get().load(shapeName);
if (!shape)
{
errorStr = String::ToString("afxModelData::load: Failed to load shape \"%s\"", shapeName);
return false;
}
// just parse up the string and collect the remappings in txr_tag_remappings.
if (remap_txr_tags != ST_NULLSTRING)
{
txr_tag_remappings.clear();
if (remap_buffer)
dFree(remap_buffer);
remap_buffer = dStrdup(remap_txr_tags);
char* remap_token = dStrtok(remap_buffer, " \t");
while (remap_token != NULL)
{
char* colon = dStrchr(remap_token, ':');
if (colon)
{
*colon = '\0';
txr_tag_remappings.increment();
txr_tag_remappings.last().old_tag = remap_token;
txr_tag_remappings.last().new_tag = colon+1;
}
remap_token = dStrtok(NULL, " \t");
}
}
// this little hack messes things up when remapping texture tags
if (txr_tag_remappings.size() == 0)
{
// this little hack forces the textures to preload
TSShapeInstance* pDummy = new TSShapeInstance(shape);
delete pDummy;
}
}
return true;
}
#define myOffset(field) Offset(field, afxModelData)
void afxModelData::initPersistFields()
{
addField("shapeFile", TypeFilename, myOffset(shapeName),
"The name of a .dts format file to use for the model.");
addField("sequence", TypeFilename, myOffset(sequence),
"The name of an animation sequence to play in the model.");
addField("sequenceRate", TypeF32, myOffset(seq_rate),
"The rate of playback for the sequence.");
addField("sequenceOffset", TypeF32, myOffset(seq_offset),
"An offset in seconds indicating a starting point for the animation sequence "
"specified by the sequence field. A rate of 1.0 (rather than sequenceRate) is used "
"to convert from seconds to the thread offset.");
addField("alphaMult", TypeF32, myOffset(alpha_mult),
"An alpha multiplier used to set maximum opacity of the model.");
addField("fogMult", TypeF32, myOffset(fog_mult),
"");
addField("remapTextureTags", TypeString, myOffset(remap_txr_tags),
"Rename one or more texture tags in the model. Texture tags are what link a "
"model's textures to materials.\n"
"Field should be a string containing space-separated remapping tokens. A remapping "
"token is two names separated by a colon, ':'. The first name should be a texture-tag "
"that exists in the model, while the second is a new name to replace it. The string "
"can have any number of remapping tokens as long as the total string length does not "
"exceed 255.");
addField("shadowEnable", TypeBool, myOffset(shadowEnable),
"Sets whether the model casts a shadow.");
addField("useVertexAlpha", TypeBool, myOffset(use_vertex_alpha),
"deprecated");
addField("forceOnMaterialFlags", TypeS32, myOffset(force_on_material_flags),
"deprecated");
addField("forceOffMaterialFlags", TypeS32, myOffset(force_off_material_flags),
"deprecated");
addField("textureFiltering", TypeBool, myOffset(texture_filtering),
"deprecated");
addField("overrideLightingOptions", TypeBool, myOffset(overrideLightingOptions),
"deprecated");
addField("receiveSunLight", TypeBool, myOffset(receiveSunLight),
"");
addField("receiveLMLighting", TypeBool, myOffset(receiveLMLighting),
"deprecated");
addField("useAdaptiveSelfIllumination", TypeBool, myOffset(useAdaptiveSelfIllumination),
"deprecated");
addField("useCustomAmbientLighting", TypeBool, myOffset(useCustomAmbientLighting),
"deprecated");
addField("customAmbientSelfIllumination", TypeBool, myOffset(customAmbientForSelfIllumination),
"deprecated");
addField("customAmbientLighting", TypeColorF, myOffset(customAmbientLighting),
"deprecated");
addField("shadowSize", TypeS32, myOffset(shadowSize),
"deprecated");
addField("shadowMaxVisibleDistance", TypeF32, myOffset(shadowMaxVisibleDistance),
"deprecated");
addField("shadowProjectionDistance", TypeF32, myOffset(shadowProjectionDistance),
"deprecated");
addField("shadowSphereAdjust", TypeF32, myOffset(shadowSphereAdjust),
"deprecated");
Parent::initPersistFields();
// Material Flags
Con::setIntVariable("$MaterialFlags::S_Wrap", TSMaterialList::S_Wrap);
Con::setIntVariable("$MaterialFlags::T_Wrap", TSMaterialList::T_Wrap);
Con::setIntVariable("$MaterialFlags::Translucent", TSMaterialList::Translucent);
Con::setIntVariable("$MaterialFlags::Additive", TSMaterialList::Additive);
Con::setIntVariable("$MaterialFlags::Subtractive", TSMaterialList::Subtractive);
Con::setIntVariable("$MaterialFlags::SelfIlluminating", TSMaterialList::SelfIlluminating);
Con::setIntVariable("$MaterialFlags::NeverEnvMap", TSMaterialList::NeverEnvMap);
Con::setIntVariable("$MaterialFlags::NoMipMap", TSMaterialList::NoMipMap);
Con::setIntVariable("$MaterialFlags::MipMap_ZeroBorder", TSMaterialList::MipMap_ZeroBorder);
Con::setIntVariable("$MaterialFlags::AuxiliaryMap", TSMaterialList::AuxiliaryMap);
#if defined(AFX_CAP_AFXMODEL_TYPE)
Con::setIntVariable("$TypeMasks::afxModelObjectType", afxModelObjectType);
#endif
}
void afxModelData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(shapeName);
stream->writeString(sequence);
stream->write(seq_rate);
stream->write(seq_offset);
stream->write(alpha_mult);
stream->write(use_vertex_alpha);
stream->write(force_on_material_flags);
stream->write(force_off_material_flags);
stream->writeFlag(texture_filtering);
stream->write(fog_mult);
stream->writeString(remap_txr_tags);
stream->writeFlag(overrideLightingOptions);
stream->writeFlag(receiveSunLight);
stream->writeFlag(useAdaptiveSelfIllumination);
stream->writeFlag(useCustomAmbientLighting);
stream->writeFlag(customAmbientForSelfIllumination);
stream->write(customAmbientLighting);
stream->writeFlag(receiveLMLighting);
stream->writeFlag(shadowEnable);
stream->write(shadowSize);
stream->write(shadowMaxVisibleDistance);
stream->write(shadowProjectionDistance);
stream->write(shadowSphereAdjust);
}
void afxModelData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
shapeName = stream->readSTString();
sequence = stream->readSTString();
stream->read(&seq_rate);
stream->read(&seq_offset);
stream->read(&alpha_mult);
stream->read(&use_vertex_alpha);
stream->read(&force_on_material_flags);
stream->read(&force_off_material_flags);
texture_filtering = stream->readFlag();
stream->read(&fog_mult);
remap_txr_tags = stream->readSTString();
overrideLightingOptions = stream->readFlag();
receiveSunLight = stream->readFlag();
useAdaptiveSelfIllumination = stream->readFlag();
useCustomAmbientLighting = stream->readFlag();
customAmbientForSelfIllumination = stream->readFlag();
stream->read(&customAmbientLighting);
receiveLMLighting = stream->readFlag();
shadowEnable = stream->readFlag();
stream->read(&shadowSize);
stream->read(&shadowMaxVisibleDistance);
stream->read(&shadowProjectionDistance);
stream->read(&shadowSphereAdjust);
}
void afxModelData::onPerformSubstitutions()
{
if (shapeName != ST_NULLSTRING)
{
shape = ResourceManager::get().load(shapeName);
if (!shape)
{
Con::errorf("afxModelData::onPerformSubstitutions: Failed to load shape \"%s\"", shapeName);
return;
}
// REMAP-TEXTURE-TAGS ISSUES?
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxModel
IMPLEMENT_CO_NETOBJECT_V1(afxModel);
ConsoleDocClass( afxModel,
"@brief A Model effect as defined by an afxModelData datablock.\n\n"
"A Model effect is a lightweight client-only geometry object useful for effect-driven "
"props.\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
);
afxModel::afxModel()
{
mTypeMask |= DynamicShapeObjectType;
#if defined(AFX_CAP_AFXMODEL_TYPE)
mTypeMask |= afxModelObjectType;
#endif
shape_inst = 0;
main_seq_thread = 0;
main_seq_id = -1;
seq_rate_factor = 1.0f;
last_anim_tag = 0;
seq_animates_vis = false;
fade_amt = 1.0f;
is_visible = true;
sort_priority = 0;
mNetFlags.set( IsGhost );
}
afxModel::~afxModel()
{
delete shape_inst;
}
void afxModel::setSequenceRateFactor(F32 factor)
{
seq_rate_factor = factor;
if (shape_inst != NULL && main_seq_thread != NULL)
shape_inst->setTimeScale(main_seq_thread, seq_rate_factor*mDataBlock->seq_rate);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
bool afxModel::onNewDataBlock(GameBaseData* dptr, bool reload)
{
mDataBlock = dynamic_cast<afxModelData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
return false;
return true;
}
bool afxModel::onAdd()
{
// first check if we have a server connection, if we don't then this is on the server
// and we should exit, then check if the parent fails to add the object
NetConnection* conn = NetConnection::getConnectionToServer();
if (!conn || !Parent::onAdd())
return false;
// setup our bounding box
if (mDataBlock->shape)
mObjBox = mDataBlock->shape->bounds;
else
mObjBox = Box3F(Point3F(-1, -1, -1), Point3F(1, 1, 1));
// setup the shape instance and sequence
if (mDataBlock->shape)
{
if (/*isClientObject() && */mDataBlock->txr_tag_remappings.size() > 0)
{
// temporarily substitute material tags with alternates
TSMaterialList* mat_list = mDataBlock->shape->materialList;
if (mat_list)
{
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
{
afxModelData::TextureTagRemapping* remap = &mDataBlock->txr_tag_remappings[i];
Vector<String> & mat_names = (Vector<String>&) mat_list->getMaterialNameList();
for (S32 j = 0; j < mat_names.size(); j++)
{
if (mat_names[j].compare(remap->old_tag, dStrlen(remap->old_tag), String::NoCase) == 0)
{
//Con::printf("REMAP TEXTURE TAG [%s] TO [%s]", remap->old_tag, remap->new_tag);
mat_names[j] = String(remap->new_tag);
mat_names[j].insert(0,'#');
break;
}
}
}
}
}
shape_inst = new TSShapeInstance(mDataBlock->shape);
if (true) // isClientObject())
{
shape_inst->cloneMaterialList();
// restore the material tags to original form
if (mDataBlock->txr_tag_remappings.size() > 0)
{
TSMaterialList* mat_list = mDataBlock->shape->materialList;
if (mat_list)
{
for (S32 i = 0; i < mDataBlock->txr_tag_remappings.size(); i++)
{
afxModelData::TextureTagRemapping* remap = &mDataBlock->txr_tag_remappings[i];
Vector<String> & mat_names = (Vector<String>&) mat_list->getMaterialNameList();
for (S32 j = 0; j < mat_names.size(); j++)
{
if (mat_names[j].compare(remap->new_tag, dStrlen(remap->new_tag)) == 0)
{
//Con::printf("UNREMAP TEXTURE TAG [%s] TO [%s]", remap->new_tag, remap->old_tag);
mat_names[j] = String(remap->old_tag);
break;
}
}
}
}
}
}
if (mDataBlock->sequence == ST_NULLSTRING)
{
main_seq_thread = 0;
main_seq_id = -1;
}
else
{
// here we start the default animation sequence
TSShape* shape = shape_inst->getShape();
main_seq_id = shape->findSequence(mDataBlock->sequence);
if (main_seq_id != -1)
{
main_seq_thread = shape_inst->addThread();
F32 seq_pos = 0.0f;
if (mDataBlock->seq_offset > 0.0f && mDataBlock->seq_offset < shape_inst->getDuration(main_seq_thread))
seq_pos = mDataBlock->seq_offset / shape_inst->getDuration(main_seq_thread);
shape_inst->setTimeScale(main_seq_thread, seq_rate_factor*mDataBlock->seq_rate);
shape_inst->setSequence(main_seq_thread, main_seq_id, seq_pos);
seq_animates_vis = shape->sequences[main_seq_id].visMatters.testAll();
}
}
// deal with material changes
if (shape_inst && (mDataBlock->force_on_material_flags | mDataBlock->force_off_material_flags))
{
shape_inst->cloneMaterialList();
TSMaterialList* mats = shape_inst->getMaterialList();
if (mDataBlock->force_on_material_flags != 0)
{
for (U32 i = 0; i < mats->size(); i++)
mats->setFlags(i, mats->getFlags(i) | mDataBlock->force_on_material_flags);
}
if (mDataBlock->force_off_material_flags != 0)
{
for (U32 i = 0; i < mats->size(); i++)
mats->setFlags(i, mats->getFlags(i) & ~mDataBlock->force_off_material_flags);
}
}
}
resetWorldBox();
if (mDataBlock->shape)
{
// Scan out the collision hulls...
static const String sCollisionStr( "collision-" );
for (U32 i = 0; i < mDataBlock->shape->details.size(); i++)
{
const String &name = mDataBlock->shape->names[mDataBlock->shape->details[i].nameIndex];
if (name.compare( sCollisionStr, sCollisionStr.length(), String::NoCase ) == 0)
{
mCollisionDetails.push_back(i);
// The way LOS works is that it will check to see if there is a LOS detail that matches
// the the collision detail + 1 + MaxCollisionShapes (this variable name should change in
// the future). If it can't find a matching LOS it will simply use the collision instead.
// We check for any "unmatched" LOS's further down
mLOSDetails.increment();
char buff[128];
dSprintf(buff, sizeof(buff), "LOS-%d", i + 1 + 8/*MaxCollisionShapes*/);
U32 los = mDataBlock->shape->findDetail(buff);
if (los == -1)
mLOSDetails.last() = i;
else
mLOSDetails.last() = los;
}
}
// Snag any "unmatched" LOS details
static const String sLOSStr( "LOS-" );
for (U32 i = 0; i < mDataBlock->shape->details.size(); i++)
{
const String &name = mDataBlock->shape->names[mDataBlock->shape->details[i].nameIndex];
if (name.compare( sLOSStr, sLOSStr.length(), String::NoCase ) == 0)
{
// See if we already have this LOS
bool found = false;
for (U32 j = 0; j < mLOSDetails.size(); j++)
{
if (mLOSDetails[j] == i)
{
found = true;
break;
}
}
if (!found)
mLOSDetails.push_back(i);
}
}
// Compute the hull accelerators (actually, just force the shape to compute them)
for (U32 i = 0; i < mCollisionDetails.size(); i++)
shape_inst->getShape()->getAccelerator(mCollisionDetails[i]);
}
// tell engine the model exists
gClientSceneGraph->addObjectToScene(this);
removeFromProcessList();
ClientProcessList::get()->addObject(this);
conn->addObject(this);
return true;
}
void afxModel::onRemove()
{
mSceneManager->removeObjectFromScene(this);
getContainer()->removeObject(this);
Parent::onRemove();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
void afxModel::advanceTime(F32 dt)
{
if (main_seq_thread)
shape_inst->advanceTime(dt, main_seq_thread);
for (S32 i = 0; i < blend_clips.size(); i++)
shape_inst->advanceTime(dt, blend_clips[i].thread);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
void afxModel::prepRenderImage(SceneRenderState* state)
{
if (!is_visible || !shape_inst)
return;
// calculate distance to camera
Point3F cameraOffset;
getRenderTransform().getColumn(3, &cameraOffset);
cameraOffset -= state->getCameraPosition();
F32 dist = cameraOffset.len();
if (dist < 0.01f)
dist = 0.01f;
F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z));
shape_inst->setDetailFromDistance(state, dist*invScale);
if ( shape_inst->getCurrentDetail() < 0 )
return;
renderObject(state);
}
bool afxModel::castRay(const Point3F &start, const Point3F &end, RayInfo* info)
{
if (shape_inst)
{
RayInfo shortest;
shortest.t = 1e8;
info->object = NULL;
if (mLOSDetails.size() > 0)
{
for (U32 i = 0; i < mLOSDetails.size(); i++)
{
shape_inst->animate(mLOSDetails[i]);
if (shape_inst->castRay(start, end, info, mLOSDetails[i]))
{
info->object = this;
if (info->t < shortest.t)
shortest = *info;
}
}
}
else
{
if (mCollisionDetails.size() > 0)
{
for (U32 i = 0; i < mCollisionDetails.size(); i++)
{
shape_inst->animate(mCollisionDetails[i]);
if (shape_inst->castRay(start, end, info, mCollisionDetails[i]))
{
info->object = this;
if (info->t < shortest.t)
shortest = *info;
}
}
}
}
if (info->object == this)
{
// Copy out the shortest time...
*info = shortest;
return true;
}
}
return false;
}
U32 afxModel::unique_anim_tag_counter = 1;
#define BAD_ANIM_ID 999999999
U32 afxModel::setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans)
{
if (!shape_inst)
return 0;
TSShape* shape = shape_inst->getShape();
S32 seq_id = shape->findSequence(clip);
if (seq_id == -1)
{
Con::errorf("afxModel::setAnimClip() -- failed to find a sequence matching the name, \"%s\".", clip);
return 0;
}
// JTF Note: test if this blend implementation is working
if (shape->sequences[seq_id].isBlend())
{
BlendThread blend_clip;
blend_clip.tag = ((unique_anim_tag_counter++) | 0x80000000);
blend_clip.thread = shape_inst->addThread();
shape_inst->setSequence(blend_clip.thread, seq_id, pos);
shape_inst->setTimeScale(blend_clip.thread, rate);
blend_clips.push_back(blend_clip);
return blend_clip.tag;
}
if (!main_seq_thread)
{
main_seq_thread = shape_inst->addThread();
shape_inst->setTimeScale(main_seq_thread, seq_rate_factor*rate);
shape_inst->setSequence(main_seq_thread, seq_id, pos);
seq_animates_vis = shape->sequences[seq_id].visMatters.testAll();
}
else
{
shape_inst->setTimeScale(main_seq_thread, seq_rate_factor*rate);
F32 transTime = (trans < 0) ? 0.25 : trans;
if (transTime > 0.0f)
shape_inst->transitionToSequence(main_seq_thread, seq_id, pos, transTime, true);
else
shape_inst->setSequence(main_seq_thread, seq_id, pos);
seq_animates_vis = shape->sequences[seq_id].visMatters.testAll();
}
last_anim_tag = unique_anim_tag_counter++;
return last_anim_tag;
}
void afxModel::resetAnimation(U32 tag)
{
// check if this is a blended clip
if ((tag & 0x80000000) != 0)
{
for (S32 i = 0; i < blend_clips.size(); i++)
{
if (blend_clips[i].tag == tag)
{
if (blend_clips[i].thread)
{
//Con::printf("DESTROY THREAD %d of %d tag=%d" , i, blend_clips.size(), tag & 0x7fffffff);
shape_inst->destroyThread(blend_clips[i].thread);
}
blend_clips.erase_fast(i);
break;
}
}
return;
}
if (tag != 0 && tag == last_anim_tag)
{
// restore original non-animated state
if (main_seq_id == -1)
{
shape_inst->destroyThread(main_seq_thread);
main_seq_thread = 0;
}
// restore original sequence
else
{
shape_inst->setTimeScale(main_seq_thread, seq_rate_factor*mDataBlock->seq_rate);
shape_inst->transitionToSequence(main_seq_thread, main_seq_id , 0.0f, 0.25f, true);
}
last_anim_tag = 0;
}
}
F32 afxModel::getAnimClipDuration(const char* clip)
{
if (!shape_inst)
return 0.0f;
TSShape* shape = shape_inst->getShape();
S32 seq_id = shape->findSequence(clip);
return (seq_id != -1) ? shape->sequences[seq_id].duration : 0.0f;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,166 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_MODEL_H_
#define _AFX_MODEL_H_
#include "renderInstance/renderPassManager.h"
class ParticleEmitterData;
class ParticleEmitter;
class ExplosionData;
class TSPartInstance;
class TSShapeInstance;
class TSShape;
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxModel Data
struct afxModelData : public GameBaseData
{
typedef GameBaseData Parent;
StringTableEntry shapeName;
StringTableEntry sequence;
F32 seq_rate;
F32 seq_offset;
F32 alpha_mult;
bool use_vertex_alpha;
U32 force_on_material_flags;
U32 force_off_material_flags;
bool texture_filtering;
F32 fog_mult;
struct TextureTagRemapping
{
char* old_tag;
char* new_tag;
};
char* remap_buffer;
Vector<TextureTagRemapping> txr_tag_remappings;
StringTableEntry remap_txr_tags;
Resource<TSShape> shape;
bool overrideLightingOptions;
bool receiveSunLight;
bool receiveLMLighting;
bool useAdaptiveSelfIllumination;
bool useCustomAmbientLighting;
bool customAmbientForSelfIllumination;
LinearColorF customAmbientLighting;
bool shadowEnable;
U32 shadowSize;
F32 shadowMaxVisibleDistance;
F32 shadowProjectionDistance;
F32 shadowSphereAdjust;
public:
/*C*/ afxModelData();
/*C*/ afxModelData(const afxModelData&, bool = false);
/*D*/ ~afxModelData();
bool preload(bool server, String &errorStr);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual void onPerformSubstitutions();
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxModelData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxModel
class afxModel : public GameBase
{
typedef GameBase Parent;
private:
afxModelData* mDataBlock;
TSShapeInstance* shape_inst;
TSThread* main_seq_thread;
S32 main_seq_id;
F32 seq_rate_factor;
bool seq_animates_vis;
U32 last_anim_tag;
F32 fade_amt;
bool is_visible;
S8 sort_priority;
struct BlendThread
{
TSThread* thread;
U32 tag;
};
Vector<BlendThread> blend_clips;
static U32 unique_anim_tag_counter;
protected:
Vector<S32> mCollisionDetails;
Vector<S32> mLOSDetails;
bool castRay(const Point3F &start, const Point3F &end, RayInfo* info);
virtual void advanceTime(F32 dt);
virtual void prepRenderImage(SceneRenderState*);
void renderObject(SceneRenderState*);
virtual bool onAdd();
virtual void onRemove();
public:
/*C*/ afxModel();
/*D*/ ~afxModel();
virtual bool onNewDataBlock(GameBaseData* dptr, bool reload);
void setFadeAmount(F32 amt) { fade_amt = amt; }
void setSequenceRateFactor(F32 factor);
void setSortPriority(S8 priority) { sort_priority = priority; }
const char* getShapeFileName() const { return mDataBlock->shapeName; }
void setVisibility(bool flag) { is_visible = flag; }
TSShape* getTSShape() { return mDataBlock->shape; }
TSShapeInstance* getTSShapeInstance() { return shape_inst; }
U32 setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans);
void resetAnimation(U32 tag);
F32 getAnimClipDuration(const char* clip);
DECLARE_CONOBJECT(afxModel);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_MODEL_H_

View file

@ -0,0 +1,71 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "scene/sceneRenderState.h"
#include "scene/sceneManager.h"
#include "ts/tsShapeInstance.h"
#include "lighting/lightQuery.h"
#include "afx/ce/afxModel.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxModel::renderObject(SceneRenderState* state)
{
MatrixF proj = GFX->getProjectionMatrix();
RectI viewport = GFX->getViewport();
MatrixF world = GFX->getWorldMatrix();
GFX->pushWorldMatrix();
TSRenderState rdata;
rdata.setSceneState( state );
rdata.setFadeOverride(fade_amt*mDataBlock->alpha_mult);
// We might have some forward lit materials
// so pass down a query to gather lights.
LightQuery query;
query.init( getWorldSphere() );
rdata.setLightQuery( &query );
MatrixF mat = getRenderTransform();
mat.scale( mObjScale );
GFX->setWorldMatrix( mat );
shape_inst->animate();
shape_inst->render(rdata);
GFX->popWorldMatrix();
GFX->setProjectionMatrix( proj );
GFX->setViewport( viewport );
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,278 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "math/mathIO.h"
#include "afx/afxChoreographer.h"
#include "afx/ce/afxMooring.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxMooringData
IMPLEMENT_CO_DATABLOCK_V1(afxMooringData);
ConsoleDocClass( afxMooringData,
"@brief A datablock that specifies a Mooring effect.\n\n"
"A Mooring is an invisible effect object which can be positioned and oriented within a scene like other objects. Its main "
"purpose is to serve as a common mount point for other effects within the same choreographer. Typically one uses AFX "
"animation features to create movement for a Mooring and then other effects are bound to it using effect-to-effect "
"constraints (#effect)."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxMooringData::afxMooringData()
{
track_pos_only = false;
networking = SCOPE_ALWAYS;
display_axis_marker = false;
}
afxMooringData::afxMooringData(const afxMooringData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
track_pos_only = other.track_pos_only;
networking = other.networking;
display_axis_marker = other.display_axis_marker;
}
#define myOffset(field) Offset(field, afxMooringData)
void afxMooringData::initPersistFields()
{
addField("displayAxisMarker", TypeBool, myOffset(display_axis_marker),
"Specifies whether to display an axis to help visualize the position and orientation "
"of the mooring.");
addField("trackPosOnly", TypeBool, myOffset(track_pos_only),
"This field is only meaningful for networking settings of SCOPE_ALWAYS and GHOSTABLE. "
"In these cases, client moorings are ghosting a mooring on the server, and "
"trackPosOnly determines if the client moorings need to be updated with the server "
"mooring's complete transform or just its position. If only the position needs to be "
"tracked, setting trackPosOnly to true will reduce the network traffic.");
addField("networking", TypeS8, myOffset(networking),
"Specifies the networking model used for the mooring and should be one of: "
"$AFX::SCOPE_ALWAYS, $AFX::GHOSTABLE, $AFX::SERVER_ONLY, or $AFX::CLIENT_ONLY");
Parent::initPersistFields();
}
bool afxMooringData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxMooringData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(display_axis_marker);
stream->write(track_pos_only);
stream->write(networking);
}
void afxMooringData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&display_axis_marker);
stream->read(&track_pos_only);
stream->read(&networking);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxMooring
IMPLEMENT_CO_NETOBJECT_V1(afxMooring);
ConsoleDocClass( afxMooring,
"@brief A Mooring effect as defined by an afxMooringData datablock.\n\n"
"A Mooring is an invisible effect object which can be positioned and oriented within "
"a scene like other objects. Its main purpose is to serve as a common mount point for "
"other effects within the same choreographer. Typically one uses AFX animation "
"features to create movement for a Mooring and then other effects are bound to it "
"using effect-to-effect constraints (#effect).\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
);
afxMooring::afxMooring()
{
mNetFlags.set(Ghostable | ScopeAlways);
chor_id = 0;
hookup_with_chor = false;
ghost_cons_name = ST_NULLSTRING;
}
afxMooring::afxMooring(U32 networking, U32 chor_id, StringTableEntry cons_name)
{
if (networking & SCOPE_ALWAYS)
{
mNetFlags.clear();
mNetFlags.set(Ghostable | ScopeAlways);
}
else if (networking & GHOSTABLE)
{
mNetFlags.clear();
mNetFlags.set(Ghostable);
}
else if (networking & SERVER_ONLY)
{
mNetFlags.clear();
}
else // if (networking & CLIENT_ONLY)
{
mNetFlags.clear();
mNetFlags.set(IsGhost);
}
this->chor_id = chor_id;
hookup_with_chor = false;
this->ghost_cons_name = cons_name;
}
afxMooring::~afxMooring()
{
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
bool afxMooring::onNewDataBlock(GameBaseData* dptr, bool reload)
{
mDataBlock = dynamic_cast<afxMooringData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
return false;
return true;
}
void afxMooring::advanceTime(F32 dt)
{
Parent::advanceTime(dt);
if (hookup_with_chor)
{
afxChoreographer* chor = arcaneFX::findClientChoreographer(chor_id);
if (chor)
{
chor->setGhostConstraintObject(this, ghost_cons_name);
hookup_with_chor = false;
}
}
Point3F pos = getRenderPosition();
}
U32 afxMooring::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
{
U32 retMask = Parent::packUpdate(conn, mask, stream);
// InitialUpdate
if (stream->writeFlag(mask & InitialUpdateMask))
{
stream->write(chor_id);
stream->writeString(ghost_cons_name);
}
if (stream->writeFlag(mask & PositionMask))
{
if (mDataBlock->track_pos_only)
mathWrite(*stream, mObjToWorld.getPosition());
else
stream->writeAffineTransform(mObjToWorld);
}
return retMask;
}
//~~~~~~~~~~~~~~~~~~~~//
void afxMooring::unpackUpdate(NetConnection * conn, BitStream * stream)
{
Parent::unpackUpdate(conn, stream);
// InitialUpdate
if (stream->readFlag())
{
stream->read(&chor_id);
ghost_cons_name = stream->readSTString();
if (chor_id != 0 && ghost_cons_name != ST_NULLSTRING)
hookup_with_chor = true;
}
if (stream->readFlag())
{
if (mDataBlock->track_pos_only)
{
Point3F pos;
mathRead(*stream, &pos);
setPosition(pos);
}
else
{
MatrixF mat;
stream->readAffineTransform(&mat);
setTransform(mat);
setRenderTransform(mat);
}
}
}
void afxMooring::setTransform(const MatrixF& mat)
{
Parent::setTransform(mat);
setMaskBits(PositionMask);
}
bool afxMooring::onAdd()
{
if(!Parent::onAdd())
return false;
mObjBox = Box3F(Point3F(-0.5, -0.5, -0.5), Point3F(0.5, 0.5, 0.5));
addToScene();
return true;
}
void afxMooring::onRemove()
{
removeFromScene();
Parent::onRemove();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,102 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_MOORING_H_
#define _AFX_MOORING_H_
#include "renderInstance/renderPassManager.h"
#include "afx/afxEffectDefs.h"
class afxMooringData : public GameBaseData, public afxEffectDefs
{
typedef GameBaseData Parent;
public:
U8 networking;
bool track_pos_only;
bool display_axis_marker;
public:
/*C*/ afxMooringData();
/*C*/ afxMooringData(const afxMooringData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxMooringData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxMooring
class afxMooring : public GameBase, public afxEffectDefs
{
typedef GameBase Parent;
private:
afxMooringData* mDataBlock;
U32 chor_id;
bool hookup_with_chor;
StringTableEntry ghost_cons_name;
GFXStateBlockRef axis_sb;
void _renderAxisLines(ObjectRenderInst*, SceneRenderState*, BaseMatInstance*);
protected:
enum MaskBits
{
PositionMask = Parent::NextFreeMask,
NextFreeMask = Parent::NextFreeMask << 1
};
public:
/*C*/ afxMooring();
/*C*/ afxMooring(U32 networking, U32 chor_id, StringTableEntry cons_name);
/*D*/ ~afxMooring();
virtual bool onNewDataBlock(GameBaseData* dptr, bool reload);
virtual void advanceTime(F32 dt);
virtual bool onAdd();
virtual void onRemove();
virtual U32 packUpdate(NetConnection*, U32, BitStream*);
virtual void unpackUpdate(NetConnection*, BitStream*);
virtual void setTransform(const MatrixF&);
virtual void prepRenderImage(SceneRenderState*);
DECLARE_CONOBJECT(afxMooring);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_MOORING_H_

View file

@ -0,0 +1,88 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "gfx/gfxTransformSaver.h"
#include "gfx/primBuilder.h"
#include "afx/afxChoreographer.h"
#include "afx/ce/afxMooring.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxMooring::prepRenderImage(SceneRenderState* state)
{
if (!mDataBlock->display_axis_marker)
return;
ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
ri->renderDelegate.bind(this, &afxMooring::_renderAxisLines);
ri->type = RenderPassManager::RIT_ObjectTranslucent;
ri->translucentSort = true;
ri->defaultKey = (U32)(dsize_t)mDataBlock;
ri->sortDistSq = getWorldBox().getSqDistanceToPoint( state->getCameraPosition() );
state->getRenderPass()->addInst(ri);
}
void afxMooring::_renderAxisLines(ObjectRenderInst *ri, SceneRenderState* state, BaseMatInstance* overrideMat)
{
if (overrideMat)
return;
if (axis_sb.isNull())
{
GFXStateBlockDesc desc;
desc.blendDefined = true;
desc.blendEnable = false;
desc.cullDefined = true;
desc.cullMode = GFXCullNone;
desc.ffLighting = false;
desc.zDefined = true;
desc.zWriteEnable = false;
axis_sb = GFX->createStateBlock(desc);
}
GFX->setStateBlock(axis_sb);
GFXTransformSaver saver;
GFX->multWorld(getRenderTransform());
PrimBuild::begin(GFXLineList, 6);
PrimBuild::color(LinearColorF(1.0, 0.0, 0.0));
PrimBuild::vertex3f(-0.5, 0.0, 0.0);
PrimBuild::vertex3f( 0.5, 0.0, 0.0);
PrimBuild::color(LinearColorF(0.0, 1.0, 0.0));
PrimBuild::vertex3f( 0.0, -0.5, 0.0);
PrimBuild::vertex3f( 0.0, 0.5, 0.0);
PrimBuild::color(LinearColorF(0.0, 0.0, 1.0));
PrimBuild::vertex3f( 0.0, 0.0, -0.5);
PrimBuild::vertex3f( 0.0, 0.0, 0.5);
PrimBuild::end();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,40 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "afx/ce/afxMultiLight.h"
IMPLEMENT_CO_DATABLOCK_V1(afxMultiLightData);
ConsoleDocClass( afxMultiLightData,
"@brief afxMultiLightData is a legacy datablock which is not supported for T3D.\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,38 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_MULTI_LIGHT_H_
#define _AFX_MULTI_LIGHT_H_
struct afxMultiLightData : public GameBaseData
{
typedef GameBaseData Parent;
DECLARE_CONOBJECT(afxMultiLightData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_MULTI_LIGHT_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,350 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_EMITTER_PARTICLE_H_
#define _AFX_EMITTER_PARTICLE_H_
#include "T3D/fx/particleEmitter.h"
class afxPathData;
class afxPath3D;
class afxParticleEmitterData : public ParticleEmitterData
{
typedef ParticleEmitterData Parent;
public:
// The afx enhanced particle emitter allows fading
// of particle color, size, velocity, and/or offset.
// Fading is controlled by a common value which is
// set externally using setFadeAmount().
//
bool fade_velocity;
bool fade_offset;
Point3F pe_vector;
// new -- consider vector in world space?
bool pe_vector_is_world;
// new -- transform paths?
StringTableEntry tpaths_string; //
Vector<afxPathData*> tPathDataBlocks; // datablocks for paths
Vector<U32> tPathDataBlockIds; // datablock IDs which correspond to the pathDataBlocks
public:
/*C*/ afxParticleEmitterData();
/*C*/ afxParticleEmitterData(const afxParticleEmitterData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
bool onAdd();
bool preload(bool server, String &errorStr);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxParticleEmitterData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// VECTOR
class afxParticleEmitterVectorData : public afxParticleEmitterData
{
typedef afxParticleEmitterData Parent;
public:
/*C*/ afxParticleEmitterVectorData();
/*C*/ afxParticleEmitterVectorData(const afxParticleEmitterVectorData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
bool onAdd();
bool preload(bool server, String &errorStr);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxParticleEmitterVectorData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// CONE
class afxParticleEmitterConeData : public afxParticleEmitterData
{
typedef afxParticleEmitterData Parent;
public:
F32 spread_min;
F32 spread_max;
public:
/*C*/ afxParticleEmitterConeData();
/*C*/ afxParticleEmitterConeData(const afxParticleEmitterConeData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
bool onAdd();
bool preload(bool server, String &errorStr);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxParticleEmitterConeData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// PATH
class afxParticleEmitterPathData : public afxParticleEmitterData
{
typedef afxParticleEmitterData Parent;
public:
enum PathOriginType
{
PATHEMIT_ORIGIN,
PATHEMIT_POINT,
PATHEMIT_VECTOR,
PATHEMIT_TANGENT
};
StringTableEntry epaths_string; //
Vector<afxPathData*> epathDataBlocks; // datablocks for paths
Vector<U32> epathDataBlockIds; // datablock IDs which correspond to the pathDataBlocks
U32 path_origin_type;
bool ground_conform;
bool ground_conform_terrain;
bool ground_conform_interiors;
F32 ground_conform_height;
public:
/*C*/ afxParticleEmitterPathData();
/*C*/ afxParticleEmitterPathData(const afxParticleEmitterPathData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
bool onAdd();
bool preload(bool server, String &errorStr);
virtual void onPerformSubstitutions();
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxParticleEmitterPathData);
DECLARE_CATEGORY("AFX");
};
typedef afxParticleEmitterPathData::PathOriginType afxParticleEmitterPath_OriginType;
DefineEnumType( afxParticleEmitterPath_OriginType );
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// DISC
class afxParticleEmitterDiscData : public afxParticleEmitterData
{
typedef afxParticleEmitterData Parent;
public:
F32 pe_radius_min;
F32 pe_radius_max;
public:
/*C*/ afxParticleEmitterDiscData();
/*C*/ afxParticleEmitterDiscData(const afxParticleEmitterDiscData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
bool onAdd();
bool preload(bool server, String &errorStr);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxParticleEmitterDiscData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
class afxParticleEmitter : public ParticleEmitter
{
typedef ParticleEmitter Parent;
private:
afxParticleEmitterData* mDataBlock;
protected:
Point3F pe_vector, pe_vector_norm;
// these go with the "pathsTransform" field
Vector<afxPath3D*> tpaths;
Vector<F32> tpath_mults;
U32 n_tpath_points;
Point3F** tpath_points;
const SimObject* afx_owner;
void init_paths();
void cleanup_paths();
Particle* alloc_particle();
ParticleData* pick_particle_type();
void afx_emitParticles(const Point3F& point, const bool useLastPosition, const Point3F& velocity, const U32 numMilliseconds);
void afx_emitParticles(const Point3F& start, const Point3F& end, const Point3F& velocity, const U32 numMilliseconds);
void preCompute(const MatrixF& mat);
virtual void sub_particleUpdate(Particle*);
virtual void sub_preCompute(const MatrixF& mat)=0;
virtual void sub_addParticle(const Point3F& pos, const Point3F& vel, const U32 age_offset, S32 part_idx)=0;
public:
/*C*/ afxParticleEmitter();
/*D*/ ~afxParticleEmitter();
virtual void emitParticlesExt(const MatrixF& xfm, const Point3F& point, const Point3F& velocity, const U32 numMilliseconds);
afxParticleEmitterData* getDataBlock(){ return mDataBlock; }
void setAFXOwner(const SimObject* owner) { afx_owner = owner; }
bool onNewDataBlock(GameBaseData* dptr, bool reload);
bool onAdd();
void onRemove();
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// VECTOR
class afxParticleEmitterVector : public afxParticleEmitter
{
typedef afxParticleEmitter Parent;
private:
afxParticleEmitterVectorData* mDataBlock;
public:
/*C*/ afxParticleEmitterVector();
/*D*/ ~afxParticleEmitterVector();
bool onNewDataBlock(GameBaseData* dptr, bool reload);
protected:
void sub_preCompute(const MatrixF& mat);
void sub_addParticle(const Point3F& pos, const Point3F& vel, const U32 age_offse, S32 part_idxt);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// CONE
class afxParticleEmitterCone : public afxParticleEmitter
{
typedef afxParticleEmitter Parent;
private:
afxParticleEmitterData* mDataBlock;
Point3F cone_v, cone_s0, cone_s1;
public:
/*C*/ afxParticleEmitterCone();
/*D*/ ~afxParticleEmitterCone();
bool onNewDataBlock(GameBaseData* dptr, bool reload);
protected:
void sub_preCompute(const MatrixF& mat);
void sub_addParticle(const Point3F& pos, const Point3F& vel, const U32 age_offset, S32 part_idx);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// PATH
class afxParticleEmitterPath : public afxParticleEmitter
{
typedef afxParticleEmitter Parent;
private:
afxParticleEmitterPathData* mDataBlock;
Vector<afxPath3D*> epaths;
Vector<F32> epath_mults;
U32 n_epath_points;
Point3F** epath_points;
void init_paths();
void cleanup_paths();
void groundConformPoint(Point3F& point, const MatrixF& mat);
public:
/*C*/ afxParticleEmitterPath();
/*D*/ ~afxParticleEmitterPath();
bool onNewDataBlock(GameBaseData* dptr, bool reload);
protected:
bool onAdd();
void onRemove();
void sub_preCompute(const MatrixF& mat);
void sub_addParticle(const Point3F& pos, const Point3F& vel, const U32 age_offset, S32 part_idx);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// DISC
class afxParticleEmitterDisc : public afxParticleEmitter
{
typedef afxParticleEmitter Parent;
private:
afxParticleEmitterDiscData* mDataBlock;
Point3F disc_v, disc_r;
public:
/*C*/ afxParticleEmitterDisc();
/*D*/ ~afxParticleEmitterDisc();
bool onNewDataBlock(GameBaseData* dptr, bool reload);
protected:
void sub_preCompute(const MatrixF& mat);
void sub_addParticle(const Point3F& pos, const Point3F& vel, const U32 age_offset, S32 part_idx);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_EMITTER_PARTICLE_H_

View file

@ -0,0 +1,312 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/engineAPI.h"
#include "afx/afxEffectWrapper.h"
#include "afx/ce/afxPhraseEffect.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPhraseEffectData::ewValidator
//
// When an effect is added using "addEffect", this validator intercepts the value
// and adds it to the dynamic effects list.
//
void afxPhraseEffectData::ewValidator::validateType(SimObject* object, void* typePtr)
{
afxPhraseEffectData* eff_data = dynamic_cast<afxPhraseEffectData*>(object);
afxEffectBaseData** ew = (afxEffectBaseData**)(typePtr);
if (eff_data && ew)
{
eff_data->fx_list.push_back(*ew);
*ew = 0;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPhraseEffectData
IMPLEMENT_CO_DATABLOCK_V1(afxPhraseEffectData);
ConsoleDocClass( afxPhraseEffectData,
"@brief A datablock that specifies a Phrase Effect, a grouping of other effects.\n\n"
"A Phrase Effect is a grouping or phrase of effects that do nothing until certain trigger events occur. It's like having a whole "
"Effectron organized as an individual effect."
"\n\n"
"Phrase effects can respond to a number of different kinds of triggers:\n"
" -- Player triggers such as footsteps, jumps, landings, and idle triggers.\n"
" -- Arbitrary animation triggers on dts-based scene objects.\n"
" -- Arbitrary trigger bits assigned to active choreographer objects."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxPhraseEffectData::afxPhraseEffectData()
{
duration = 0.0f;
n_loops = 1;
// dummy entry holds effect-wrapper pointer while a special validator
// grabs it and adds it to an appropriate effects list
dummy_fx_entry = NULL;
// marked true if datablock ids need to
// be converted into pointers
do_id_convert = false;
trigger_mask = 0;
match_type = MATCH_ANY;
match_state = STATE_ON;
phrase_type = PHRASE_TRIGGERED;
no_choreographer_trigs = false;
no_cons_trigs = false;
no_player_trigs = false;
on_trig_cmd = ST_NULLSTRING;
}
afxPhraseEffectData::afxPhraseEffectData(const afxPhraseEffectData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
duration = other.duration;
n_loops = other.n_loops;
dummy_fx_entry = other.dummy_fx_entry;
do_id_convert = other.do_id_convert; // --
trigger_mask = other.trigger_mask;
match_type = other.match_type;
match_state = other.match_state;
phrase_type = other.phrase_type;
no_choreographer_trigs = other.no_choreographer_trigs;
no_cons_trigs = other.no_cons_trigs;
no_player_trigs = other.no_player_trigs;
on_trig_cmd = other.on_trig_cmd;
// fx_list; // -- ??
}
void afxPhraseEffectData::reloadReset()
{
fx_list.clear();
}
ImplementEnumType( afxPhraseEffect_MatchType, "Possible phrase effect match types.\n" "@ingroup afxPhraseEffect\n\n" )
{ afxPhraseEffectData::MATCH_ANY, "any", "..." },
{ afxPhraseEffectData::MATCH_ALL, "all", "..." },
EndImplementEnumType;
ImplementEnumType( afxPhraseEffect_StateType, "Possible phrase effect state types.\n" "@ingroup afxPhraseEffect\n\n" )
{ afxPhraseEffectData::STATE_ON, "on", "..." },
{ afxPhraseEffectData::STATE_OFF, "off", "..." },
{ afxPhraseEffectData::STATE_ON_AND_OFF, "both", "..." },
EndImplementEnumType;
ImplementEnumType( afxPhraseEffect_PhraseType, "Possible phrase effect types.\n" "@ingroup afxPhraseEffect\n\n" )
{ afxPhraseEffectData::PHRASE_TRIGGERED, "triggered", "..." },
{ afxPhraseEffectData::PHRASE_CONTINUOUS, "continuous", "..." },
EndImplementEnumType;
#define myOffset(field) Offset(field, afxPhraseEffectData)
void afxPhraseEffectData::initPersistFields()
{
addField("duration", TypeF32, myOffset(duration),
"Specifies a duration for the phrase-effect. If set to infinity, the phrase-effect "
"needs to have a phraseType of continuous. Set infinite duration using "
"$AFX::INFINITE_TIME.");
addField("numLoops", TypeS32, myOffset(n_loops),
"Specifies the number of times the phrase-effect should loop. If set to infinity, "
"the phrase-effect needs to have a phraseType of continuous. Set infinite looping "
"using $AFX::INFINITE_REPEATS.");
addField("triggerMask", TypeS32, myOffset(trigger_mask),
"Sets which bits to consider in the current trigger-state which consists of 32 "
"trigger-bits combined from (possibly overlapping) player trigger bits, constraint "
"trigger bits, and choreographer trigger bits.");
addField("matchType", TYPEID<afxPhraseEffectData::MatchType>(), myOffset(match_type),
"Selects what combination of bits in triggerMask lead to a trigger. When set to "
"'any', any bit in triggerMask matching the current trigger-state will cause a "
"trigger. If set to 'all', every bit in triggerMask must match the trigger-state. "
"Possible values: any or all.");
addField("matchState", TYPEID<afxPhraseEffectData::StateType>(), myOffset(match_state),
"Selects which bit-state(s) of bits in the triggerMask to consider when comparing to "
"the current trigger-state. Possible values: on, off, or both.");
addField("phraseType", TYPEID<afxPhraseEffectData::PhraseType>(), myOffset(phrase_type),
"Selects between triggered and continuous types of phrases. When set to 'triggered', "
"the phrase-effect is triggered when the relevant trigger-bits change state. When set "
"to 'continuous', the phrase-effect will stay active as long as the trigger-bits "
"remain in a matching state. Possible values: triggered or continuous.");
addField("ignoreChoreographerTriggers", TypeBool, myOffset(no_choreographer_trigs),
"When true, trigger-bits on the choreographer will be ignored.");
addField("ignoreConstraintTriggers", TypeBool, myOffset(no_cons_trigs),
"When true, animation triggers from dts-based constraint source objects will be "
"ignored.");
addField("ignorePlayerTriggers", TypeBool, myOffset(no_player_trigs),
"When true, Player-specific triggers from Player-derived constraint source objects "
"will be ignored.");
addField("onTriggerCommand", TypeString, myOffset(on_trig_cmd),
"Like a field substitution statement without the leading '$$' token, this eval "
"statement will be executed when a trigger occurs. Any '%%' and '##' tokens will be "
"substituted.");
// effect lists
// for each of these, dummy_fx_entry is set and then a validator adds it to the appropriate effects list
static ewValidator emptyValidator(0);
addFieldV("addEffect", TYPEID< afxEffectBaseData >(), myOffset(dummy_fx_entry), &emptyValidator,
"A field macro which adds an effect wrapper datablock to a list of effects associated "
"with the phrase-effect's single phrase. Unlike other fields, addEffect follows an "
"unusual syntax. Order is important since the effects will resolve in the order they "
"are added to each list.");
Parent::initPersistFields();
// disallow some field substitutions
disableFieldSubstitutions("addEffect");
}
bool afxPhraseEffectData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxPhraseEffectData::pack_fx(BitStream* stream, const afxEffectList& fx, bool packed)
{
stream->writeInt(fx.size(), EFFECTS_PER_PHRASE_BITS);
for (int i = 0; i < fx.size(); i++)
writeDatablockID(stream, fx[i], packed);
}
void afxPhraseEffectData::unpack_fx(BitStream* stream, afxEffectList& fx)
{
fx.clear();
S32 n_fx = stream->readInt(EFFECTS_PER_PHRASE_BITS);
for (int i = 0; i < n_fx; i++)
fx.push_back((afxEffectWrapperData*)readDatablockID(stream));
}
void afxPhraseEffectData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(duration);
stream->write(n_loops);
stream->write(trigger_mask);
stream->writeInt(match_type, 1);
stream->writeInt(match_state, 2);
stream->writeInt(phrase_type, 1);
stream->writeFlag(no_choreographer_trigs);
stream->writeFlag(no_cons_trigs);
stream->writeFlag(no_player_trigs);
stream->writeString(on_trig_cmd);
pack_fx(stream, fx_list, packed);
}
void afxPhraseEffectData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&duration);
stream->read(&n_loops);
stream->read(&trigger_mask);
match_type = stream->readInt(1);
match_state = stream->readInt(2);
phrase_type = stream->readInt(1);
no_choreographer_trigs = stream->readFlag();
no_cons_trigs = stream->readFlag();
no_player_trigs = stream->readFlag();
on_trig_cmd = stream->readSTString();
do_id_convert = true;
unpack_fx(stream, fx_list);
}
bool afxPhraseEffectData::preload(bool server, String &errorStr)
{
if (!Parent::preload(server, errorStr))
return false;
// Resolve objects transmitted from server
if (!server)
{
if (do_id_convert)
{
for (S32 i = 0; i < fx_list.size(); i++)
{
SimObjectId db_id = SimObjectId((uintptr_t)fx_list[i]);
if (db_id != 0)
{
// try to convert id to pointer
if (!Sim::findObject(db_id, fx_list[i]))
{
Con::errorf(ConsoleLogEntry::General,
"afxPhraseEffectData::preload() -- bad datablockId: 0x%x",
db_id);
}
}
}
do_id_convert = false;
}
}
return true;
}
void afxPhraseEffectData::gather_cons_defs(Vector<afxConstraintDef>& defs)
{
afxConstraintDef::gather_cons_defs(defs, fx_list);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
DefineEngineMethod( afxPhraseEffectData, addEffect, void, ( afxEffectBaseData* effectData ),,
"Add a child effect to a phrase effect datablock. Argument can be an afxEffectWrappperData or an afxEffectGroupData.\n" )
{
if (!effectData)
{
Con::errorf("afxPhraseEffectData::addEffect() -- failed to resolve effect datablock.");
return;
}
object->fx_list.push_back(effectData);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,120 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_PHRASE_EFFECT_H_
#define _AFX_PHRASE_EFFECT_H_
#include "console/typeValidators.h"
#include "afx/ce/afxComponentEffect.h"
#include "afx/afxEffectDefs.h"
#include "afx/afxEffectWrapper.h"
#include "afx/afxPhrase.h"
class afxPhraseEffectData : public GameBaseData, public afxEffectDefs, public afxComponentEffectData
{
typedef GameBaseData Parent;
class ewValidator : public TypeValidator
{
U32 id;
public:
ewValidator(U32 id) { this->id = id; }
void validateType(SimObject *object, void *typePtr);
};
bool do_id_convert;
public:
enum MatchType {
MATCH_ANY = 0,
MATCH_ALL = 1
};
enum StateType {
STATE_ON = 1,
STATE_OFF = 2,
STATE_ON_AND_OFF = STATE_ON | STATE_OFF
};
enum PhraseType
{
PHRASE_TRIGGERED = 0,
PHRASE_CONTINUOUS = 1
};
public:
afxEffectList fx_list;
F32 duration;
S32 n_loops;
U32 trigger_mask;
U32 match_type;
U32 match_state;
U32 phrase_type;
bool no_choreographer_trigs;
bool no_cons_trigs;
bool no_player_trigs;
StringTableEntry on_trig_cmd;
afxEffectBaseData* dummy_fx_entry;
private:
void pack_fx(BitStream* stream, const afxEffectList& fx, bool packed);
void unpack_fx(BitStream* stream, afxEffectList& fx);
public:
/*C*/ afxPhraseEffectData();
/*C*/ afxPhraseEffectData(const afxPhraseEffectData&, bool = false);
virtual void reloadReset();
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
bool preload(bool server, String &errorStr);
virtual void gather_cons_defs(Vector<afxConstraintDef>& defs);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxPhraseEffectData);
DECLARE_CATEGORY("AFX");
};
typedef afxPhraseEffectData::MatchType afxPhraseEffect_MatchType;
DefineEnumType( afxPhraseEffect_MatchType );
typedef afxPhraseEffectData::StateType afxPhraseEffect_StateType;
DefineEnumType( afxPhraseEffect_StateType );
typedef afxPhraseEffectData::PhraseType afxPhraseEffect_PhraseType;
DefineEnumType( afxPhraseEffect_PhraseType );
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_PHRASE_EFFECT_H_

View file

@ -0,0 +1,114 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "T3D/physicalZone.h"
#include "afx/ce/afxPhysicalZone.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPhysicalZoneData
IMPLEMENT_CO_DATABLOCK_V1(afxPhysicalZoneData);
ConsoleDocClass( afxPhysicalZoneData,
"@brief A datablock that specifies a PhysicalZone effect.\n\n"
"A Physical Zone is a Torque effect that applies physical forces to Players and other movable objects that enter a specific "
"region of influence. AFX has enhanced Physical Zones by allowing orientation of vector forces and adding radial forces. "
"AFX has also optimized Physical Zone networking so that they can be constrained to moving objects for a variety of "
"effects including repelling and flying."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxPhysicalZoneData::afxPhysicalZoneData()
{
mVelocityMod = 1.0f;
mGravityMod = 1.0f;
mAppliedForce.zero();
mPolyhedron = ST_NULLSTRING;
force_type = PhysicalZone::VECTOR;
orient_force = false;
exclude_cons_obj = false;
}
afxPhysicalZoneData::afxPhysicalZoneData(const afxPhysicalZoneData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
mVelocityMod = other.mVelocityMod;
mGravityMod = other.mGravityMod;
mAppliedForce = other.mAppliedForce;
mPolyhedron = other.mPolyhedron;
force_type = other.force_type;
orient_force = other.orient_force;
exclude_cons_obj = other.exclude_cons_obj;
}
#define myOffset(field) Offset(field, afxPhysicalZoneData)
void afxPhysicalZoneData::initPersistFields()
{
addField("velocityMod", TypeF32, myOffset(mVelocityMod),
"A multiplier that biases the velocity of an object every tick it is within the "
"zone.");
addField("gravityMod", TypeF32, myOffset(mGravityMod),
"A multiplier that biases the influence of gravity on objects within the zone.");
addField("appliedForce", TypePoint3F, myOffset(mAppliedForce),
"A three-valued vector representing a directional force applied to objects withing "
"the zone.");
addField("polyhedron", TypeString, myOffset(mPolyhedron),
"Floating point values describing the outer bounds of the PhysicalZone's region of "
"influence.");
addField("forceType", TYPEID<PhysicalZone::ForceType>(), myOffset(force_type),
"This enumerated attribute defines the type of force used in the PhysicalZone. "
"Possible values: vector, sphere, or cylinder.");
addField("orientForce", TypeBool, myOffset(orient_force),
"Determines if the force can be oriented by the PhysicalZone's transform matrix.");
addField("excludeConstraintObject", TypeBool, myOffset(exclude_cons_obj),
"When true, an object used as the primary position constraint of a physical-zone "
"effect will not be influenced by the forces of the zone.");
Parent::initPersistFields();
}
void afxPhysicalZoneData::packData(BitStream* stream)
{
Parent::packData(stream);
}
void afxPhysicalZoneData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,65 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_PHYSICAL_ZONE_H_
#define _AFX_PHYSICAL_ZONE_H_
#include "T3D/gameBase/gameBase.h"
#include "T3D/trigger.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPhysicalZoneData
class afxPhysicalZoneData : public GameBaseData
{
typedef GameBaseData Parent;
public:
F32 mVelocityMod;
F32 mGravityMod;
Point3F mAppliedForce;
StringTableEntry mPolyhedron;
S32 force_type;
bool orient_force;
bool exclude_cons_obj;
public:
/*C*/ afxPhysicalZoneData();
/*C*/ afxPhysicalZoneData(const afxPhysicalZoneData&, bool = false);
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxPhysicalZoneData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_PHYSICAL_ZONE_H_

View file

@ -0,0 +1,140 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "scene/sceneRenderState.h"
#include "math/mathIO.h"
#include "afx/afxChoreographer.h"
#include "afx/ce/afxPlayerMovement.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPlayerMovementData
IMPLEMENT_CO_DATABLOCK_V1(afxPlayerMovementData);
ConsoleDocClass( afxPlayerMovementData,
"@brief A datablock that specifies a Player Movement effect.\n\n"
"Player Movement effects are used to directly alter the speed and/or movement direction of Player objects. The Player "
"Movement effect is similar to the Player Puppet effect, but where puppet effects totally take over a Player's transformation "
"using the AFX constraint system, Player Movement effects 'steer' the player using the same mechanisms that allow "
"Player control from mouse and keyboard input. Another difference is that Player Movement effects only influence the "
"server instance of a Player. Puppet effects can influence both the Player's server instance and its client ghosts."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
static Point3F default_movement(F32_MAX, F32_MAX, F32_MAX);
afxPlayerMovementData::afxPlayerMovementData()
{
speed_bias = 1.0f;
movement = default_movement;
movement_op = OP_MULTIPLY;
}
afxPlayerMovementData::afxPlayerMovementData(const afxPlayerMovementData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
speed_bias = other.speed_bias;
movement = other.movement;
movement_op = other.movement_op;
}
ImplementEnumType( afxPlayerMovement_OpType, "Possible player movement operation types.\n" "@ingroup afxPlayerMovemen\n\n" )
{ afxPlayerMovementData::OP_ADD, "add", "..." },
{ afxPlayerMovementData::OP_MULTIPLY, "multiply", "..." },
{ afxPlayerMovementData::OP_REPLACE, "replace", "..." },
{ afxPlayerMovementData::OP_MULTIPLY, "mult", "..." },
EndImplementEnumType;
#define myOffset(field) Offset(field, afxPlayerMovementData)
void afxPlayerMovementData::initPersistFields()
{
addField("speedBias", TypeF32, myOffset(speed_bias),
"A floating-point multiplier that scales the constraint Player's movement speed.");
addField("movement", TypePoint3F, myOffset(movement),
"");
addField("movementOp", TYPEID<afxPlayerMovementData::OpType>(), myOffset(movement_op),
"Possible values: add, multiply, or replace.");
Parent::initPersistFields();
}
bool afxPlayerMovementData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxPlayerMovementData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(speed_bias);
if (stream->writeFlag(movement != default_movement))
{
stream->write(movement.x);
stream->write(movement.y);
stream->write(movement.z);
stream->writeInt(movement_op, OP_BITS);
}
}
void afxPlayerMovementData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&speed_bias);
if (stream->readFlag())
{
stream->read(&movement.x);
stream->read(&movement.y);
stream->read(&movement.z);
movement_op = stream->readInt(OP_BITS);
}
else
{
movement = default_movement;
movement_op = OP_MULTIPLY;
}
}
bool afxPlayerMovementData::hasMovementOverride()
{
return (movement != default_movement);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,73 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_PLAYER_MOVEMENT_H_
#define _AFX_PLAYER_MOVEMENT_H_
#include "afx/ce/afxComponentEffect.h"
#include "afx/afxEffectDefs.h"
#include "afx/afxConstraint.h"
class afxPlayerMovementData : public GameBaseData, public afxEffectDefs
{
typedef GameBaseData Parent;
public:
enum OpType
{
OP_ADD = 0,
OP_MULTIPLY,
OP_REPLACE,
OP_BITS = 2,
};
public:
F32 speed_bias;
Point3F movement;
U32 movement_op;
public:
/*C*/ afxPlayerMovementData();
/*C*/ afxPlayerMovementData(const afxPlayerMovementData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
bool hasMovementOverride();
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxPlayerMovementData);
DECLARE_CATEGORY("AFX");
};
typedef afxPlayerMovementData::OpType afxPlayerMovement_OpType;
DefineEnumType( afxPlayerMovement_OpType );
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_PLAYER_MOVEMENT_H_

View file

@ -0,0 +1,122 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "scene/sceneRenderState.h"
#include "math/mathIO.h"
#include "afx/afxChoreographer.h"
#include "afx/ce/afxPlayerPuppet.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxPlayerPuppetData
IMPLEMENT_CO_DATABLOCK_V1(afxPlayerPuppetData);
ConsoleDocClass( afxPlayerPuppetData,
"@brief A datablock that specifies a Player Puppet effect.\n\n"
"Player Puppet effects are defined using the afxPlayerPuppetData datablock and are used to control the movement of "
"Player objects with the AFX constraint system. The Player Puppet effect is similar to the Player Movement effect, but "
"where movement effects 'steer' the player using the same mechanisms that allow Player control from mouse and keyboard "
"input, Player Puppet effects totally take over a Player's transformation using the AFX constraint system."
"\n\n"
"Player Puppet can be configured to directly move a Player's client ghosts as well as its server instance. When doing this, "
"it is important to keep the general motion of the Player object and its ghosts somewhat consistent. Otherwise, obvious "
"discontinuities in the motion will result when the Player Puppet ends and control is restored to the server Player."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxPlayerPuppetData::afxPlayerPuppetData()
{
obj_spec = ST_NULLSTRING;
networking = SERVER_ONLY;
}
afxPlayerPuppetData::afxPlayerPuppetData(const afxPlayerPuppetData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
obj_spec = other.obj_spec;
networking = other.networking;
}
#define myOffset(field) Offset(field, afxPlayerPuppetData)
void afxPlayerPuppetData::initPersistFields()
{
addField("objectSpec", TypeString, myOffset(obj_spec),
"...");
addField("networking", TypeS8, myOffset(networking),
"...");
Parent::initPersistFields();
// disallow some field substitutions
disableFieldSubstitutions("objectSpec");
disableFieldSubstitutions("networking");
}
bool afxPlayerPuppetData::onAdd()
{
if (Parent::onAdd() == false)
return false;
bool runs_on_s = ((networking & (SERVER_ONLY | SERVER_AND_CLIENT)) != 0);
bool runs_on_c = ((networking & (CLIENT_ONLY | SERVER_AND_CLIENT)) != 0);
obj_def.parseSpec(obj_spec, runs_on_s, runs_on_c);
return true;
}
void afxPlayerPuppetData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(obj_spec);
stream->write(networking);
}
void afxPlayerPuppetData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
obj_spec = stream->readSTString();
stream->read(&networking);
}
void afxPlayerPuppetData::gather_cons_defs(Vector<afxConstraintDef>& defs)
{
if (obj_def.isDefined())
defs.push_back(obj_def);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,64 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_PLAYER_PUPPET_H_
#define _AFX_PLAYER_PUPPET_H_
#include "afx/ce/afxComponentEffect.h"
#include "afx/afxEffectDefs.h"
#include "afx/afxConstraint.h"
class afxPlayerPuppetData : public GameBaseData, public afxEffectDefs, public afxComponentEffectData
{
typedef GameBaseData Parent;
public:
StringTableEntry obj_spec;
afxConstraintDef obj_def;
U8 networking;
virtual void gather_cons_defs(Vector<afxConstraintDef>& defs);
public:
/*C*/ afxPlayerPuppetData();
/*C*/ afxPlayerPuppetData(const afxPlayerPuppetData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxPlayerPuppetData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_PLAYER_PUPPET_H_

View file

@ -0,0 +1,103 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxPointLight_T3D.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxT3DPointLightData
IMPLEMENT_CO_DATABLOCK_V1(afxT3DPointLightData);
ConsoleDocClass( afxT3DPointLightData,
"@brief A datablock that specifies a dynamic Point Light effect.\n\n"
"A Point Light effect that uses the T3D PointLight object. afxT3DPointLightData has the same fields found in PointLight but "
"in a datablock structure."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxT3DPointLightData::afxT3DPointLightData()
: mRadius( 5.0f )
{
}
afxT3DPointLightData::afxT3DPointLightData(const afxT3DPointLightData& other, bool temp_clone) : afxT3DLightBaseData(other, temp_clone)
{
mRadius = other.mRadius;
}
//
// NOTE: keep this as consistent as possible with PointLight::initPersistFields()
//
void afxT3DPointLightData::initPersistFields()
{
addGroup( "Light" );
addField( "radius", TypeF32, Offset( mRadius, afxT3DPointLightData ),
"Controls the falloff of the light emission");
endGroup( "Light" );
// We do the parent fields at the end so that
// they show up that way in the inspector.
Parent::initPersistFields();
// Remove the scale field... it's already
// defined by the light radius.
removeField( "scale" );
}
bool afxT3DPointLightData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxT3DPointLightData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write( mRadius );
}
void afxT3DPointLightData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read( &mRadius );
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,56 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_T3D_POINT_LIGHT_H_
#define _AFX_T3D_POINT_LIGHT_H_
#include "afx/ce/afxLightBase_T3D.h"
class afxT3DPointLightData : public afxT3DLightBaseData
{
typedef afxT3DLightBaseData Parent;
public:
F32 mRadius;
public:
/*C*/ afxT3DPointLightData();
/*C*/ afxT3DPointLightData(const afxT3DPointLightData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxT3DPointLightData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_T3D_POINT_LIGHT_H_

View file

@ -0,0 +1,371 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "T3D/shapeBase.h"
#include "afx/ce/afxProjectile.h"
#include "afx/afxChoreographer.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxProjectileData
IMPLEMENT_CO_DATABLOCK_V1(afxProjectileData);
ConsoleDocClass( afxProjectileData,
"@brief A datablock that specifies a Projectile effect.\n\n"
"afxProjectileData inherits from ProjectileData and adds some AFX specific fields."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxProjectileData::afxProjectileData()
{
networking = GHOSTABLE;
launch_pos_spec = ST_NULLSTRING;
launch_dir_bias.zero();
ignore_src_timeout = false;
dynamicCollisionMask = 0;
staticCollisionMask = 0;
override_collision_masks = false;
launch_dir_method = TowardPos2Constraint;
}
afxProjectileData::afxProjectileData(const afxProjectileData& other, bool temp_clone) : ProjectileData(other, temp_clone)
{
networking = other.networking;
launch_pos_spec = other.launch_pos_spec;
launch_pos_def = other.launch_pos_def;
launch_dir_bias = other.launch_dir_bias;
ignore_src_timeout = other.ignore_src_timeout;
dynamicCollisionMask = other.dynamicCollisionMask;
staticCollisionMask = other.staticCollisionMask;
override_collision_masks = other.override_collision_masks;
launch_dir_method = other.launch_dir_method;
}
ImplementEnumType( afxProjectile_LaunchDirType, "Possible projectile launch direction types.\n" "@ingroup afxProjectile\n\n" )
{ afxProjectileData::TowardPos2Constraint, "towardPos2Constraint", "..." },
{ afxProjectileData::OrientConstraint, "orientConstraint", "..." },
{ afxProjectileData::LaunchDirField, "launchDirField", "..." },
EndImplementEnumType;
#define myOffset(field) Offset(field, afxProjectileData)
void afxProjectileData::initPersistFields()
{
addField("networking", TypeS8, myOffset(networking),
"...");
addField("launchPosSpec", TypeString, myOffset(launch_pos_spec),
"...");
addField("launchDirBias", TypePoint3F, myOffset(launch_dir_bias),
"...");
addField("ignoreSourceTimeout", TypeBool, myOffset(ignore_src_timeout),
"...");
addField("dynamicCollisionMask", TypeS32, myOffset(dynamicCollisionMask),
"...");
addField("staticCollisionMask", TypeS32, myOffset(staticCollisionMask),
"...");
addField("overrideCollisionMasks", TypeBool, myOffset(override_collision_masks),
"...");
addField("launchDirMethod", TYPEID<afxProjectileData::LaunchDirType>(), myOffset(launch_dir_method),
"Possible values: towardPos2Constraint, orientConstraint, or launchDirField.");
Parent::initPersistFields();
}
bool afxProjectileData::onAdd()
{
if (Parent::onAdd() == false)
return false;
bool runs_on_s = ((networking & (SERVER_ONLY | SERVER_AND_CLIENT)) != 0);
bool runs_on_c = ((networking & (CLIENT_ONLY | SERVER_AND_CLIENT)) != 0);
launch_pos_def.parseSpec(launch_pos_spec, runs_on_s, runs_on_c);
return true;
}
void afxProjectileData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(networking);
stream->writeString(launch_pos_spec);
if (stream->writeFlag(!launch_dir_bias.isZero()))
{
stream->write(launch_dir_bias.x);
stream->write(launch_dir_bias.y);
stream->write(launch_dir_bias.z);
}
stream->writeFlag(ignore_src_timeout);
if (stream->writeFlag(override_collision_masks))
{
stream->write(dynamicCollisionMask);
stream->write(staticCollisionMask);
}
stream->writeInt(launch_dir_method, 2);
}
void afxProjectileData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&networking);
launch_pos_spec = stream->readSTString();
if (stream->readFlag())
{
stream->read(&launch_dir_bias.x);
stream->read(&launch_dir_bias.y);
stream->read(&launch_dir_bias.z);
}
else
launch_dir_bias.zero();
ignore_src_timeout = stream->readFlag();
if ((override_collision_masks = stream->readFlag()) == true)
{
stream->read(&dynamicCollisionMask);
stream->read(&staticCollisionMask);
}
else
{
dynamicCollisionMask = 0;
staticCollisionMask = 0;
}
launch_dir_method = (U32) stream->readInt(2);
}
void afxProjectileData::gather_cons_defs(Vector<afxConstraintDef>& defs)
{
if (launch_pos_def.isDefined())
defs.push_back(launch_pos_def);
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxProjectile
IMPLEMENT_CO_NETOBJECT_V1(afxProjectile);
ConsoleDocClass( afxProjectile,
"@brief A Projectile effect as defined by an afxProjectileData datablock.\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
);
afxProjectile::afxProjectile()
{
chor_id = 0;
hookup_with_chor = false;
ghost_cons_name = ST_NULLSTRING;
client_only = false;
}
afxProjectile::afxProjectile(U32 networking, U32 chor_id, StringTableEntry cons_name)
{
if (networking & SCOPE_ALWAYS)
{
mNetFlags.clear();
mNetFlags.set(Ghostable | ScopeAlways);
client_only = false;
}
else if (networking & GHOSTABLE)
{
mNetFlags.clear();
mNetFlags.set(Ghostable);
client_only = false;
}
else if (networking & SERVER_ONLY)
{
mNetFlags.clear();
client_only = false;
}
else // if (networking & CLIENT_ONLY)
{
mNetFlags.clear();
mNetFlags.set(IsGhost);
client_only = true;
}
this->chor_id = chor_id;
hookup_with_chor = false;
this->ghost_cons_name = cons_name;
}
afxProjectile::~afxProjectile()
{
}
void afxProjectile::init(Point3F& pos, Point3F& vel, ShapeBase* src_obj)
{
mCurrPosition = pos;
mCurrVelocity = vel;
if (src_obj)
{
mSourceObject = src_obj;
mSourceObjectId = src_obj->getId();
mSourceObjectSlot = 0;
}
setPosition(mCurrPosition);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
bool afxProjectile::onNewDataBlock(GameBaseData* dptr, bool reload)
{
return Parent::onNewDataBlock(dptr, reload);
}
void afxProjectile::processTick(const Move* move)
{
// note: this deletion test must occur before calling to the parent's
// processTick() because if this is a server projectile, the parent
// might decide to delete it and then client_only will no longer be
// valid after the return.
bool do_delete = (client_only && mCurrTick >= mDataBlock->lifetime);
Parent::processTick(move);
if (do_delete)
deleteObject();
}
void afxProjectile::interpolateTick(F32 delta)
{
if (client_only)
return;
Parent::interpolateTick(delta);
}
void afxProjectile::advanceTime(F32 dt)
{
Parent::advanceTime(dt);
if (hookup_with_chor)
{
afxChoreographer* chor = arcaneFX::findClientChoreographer(chor_id);
if (chor)
{
chor->setGhostConstraintObject(this, ghost_cons_name);
hookup_with_chor = false;
}
}
}
bool afxProjectile::onAdd()
{
if(!Parent::onAdd())
return false;
if (isClientObject())
{
// add to client side mission cleanup
SimGroup *cleanup = dynamic_cast<SimGroup *>( Sim::findObject( "ClientMissionCleanup") );
if( cleanup != NULL )
{
cleanup->addObject( this );
}
else
{
AssertFatal( false, "Error, could not find ClientMissionCleanup group" );
return false;
}
}
return true;
}
void afxProjectile::onRemove()
{
Parent::onRemove();
}
//~~~~~~~~~~~~~~~~~~~~
U32 afxProjectile::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
{
U32 retMask = Parent::packUpdate(conn, mask, stream);
// InitialUpdate
if (stream->writeFlag(mask & InitialUpdateMask))
{
stream->write(chor_id);
stream->writeString(ghost_cons_name);
}
return retMask;
}
//~~~~~~~~~~~~~~~~~~~~//
void afxProjectile::unpackUpdate(NetConnection * conn, BitStream * stream)
{
Parent::unpackUpdate(conn, stream);
// InitialUpdate
if (stream->readFlag())
{
stream->read(&chor_id);
ghost_cons_name = stream->readSTString();
if (chor_id != 0 && ghost_cons_name != ST_NULLSTRING)
hookup_with_chor = true;
}
}
class afxProjectileDeleteEvent : public SimEvent
{
public:
void process(SimObject *object)
{
object->deleteObject();
}
};
void afxProjectile::explode(const Point3F& p, const Point3F& n, const U32 collideType)
{
// Make sure we don't explode twice...
if ( isHidden() )
return;
Parent::explode(p, n, collideType);
if (isClientObject() && client_only)
Sim::postEvent(this, new afxProjectileDeleteEvent, Sim::getCurrentTime() + DeleteWaitTime);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,117 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_PROJECTILE_H_
#define _AFX_PROJECTILE_H_
#include "lighting/lightInfo.h"
#include "T3D/projectile.h"
#include "afx/afxEffectDefs.h"
#include "afx/afxConstraint.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxProjectileData
class afxProjectileData : public ProjectileData, public afxEffectDefs
{
typedef ProjectileData Parent;
public:
enum LaunchDirType {
TowardPos2Constraint,
OrientConstraint,
LaunchDirField
};
public:
U8 networking;
StringTableEntry launch_pos_spec;
afxConstraintDef launch_pos_def;
Point3F launch_dir_bias;
bool ignore_src_timeout;
U32 dynamicCollisionMask;
U32 staticCollisionMask;
bool override_collision_masks;
U32 launch_dir_method;
virtual void gather_cons_defs(Vector<afxConstraintDef>& defs);
public:
/*C*/ afxProjectileData();
/*C*/ afxProjectileData(const afxProjectileData&, bool = false);
virtual bool onAdd();
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxProjectileData);
DECLARE_CATEGORY("AFX");
};
typedef afxProjectileData::LaunchDirType afxProjectile_LaunchDirType;
DefineEnumType( afxProjectile_LaunchDirType );
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxProjectile
class afxProjectile : public Projectile, public afxEffectDefs
{
typedef Projectile Parent;
private:
U32 chor_id;
bool hookup_with_chor;
StringTableEntry ghost_cons_name;
bool client_only;
public:
/*C*/ afxProjectile();
/*C*/ afxProjectile(U32 networking, U32 chor_id, StringTableEntry cons_name);
/*D*/ ~afxProjectile();
void init(Point3F& pos, Point3F& vel, ShapeBase* src_obj);
virtual bool onNewDataBlock(GameBaseData* dptr, bool reload);
virtual void processTick(const Move *move);
virtual void interpolateTick(F32 delta);
virtual void advanceTime(F32 dt);
virtual bool onAdd();
virtual void onRemove();
virtual U32 packUpdate(NetConnection*, U32, BitStream*);
virtual void unpackUpdate(NetConnection*, BitStream*);
virtual void explode(const Point3F& p, const Point3F& n, const U32 collideType);
DECLARE_CONOBJECT(afxProjectile);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_PROJECTILE_H_

View file

@ -0,0 +1,94 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxScriptEvent.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxScriptEventData
IMPLEMENT_CO_DATABLOCK_V1(afxScriptEventData);
ConsoleDocClass( afxScriptEventData,
"@brief A datablock that specifies a Script Event effect.\n\n"
"Arbitrary script functions can be called as an AFX effect using afxScriptEventData. They are useful for implementing "
"high-level scripted side-effects such as character resurrection or teleportation."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxScriptEventData::afxScriptEventData()
{
method_name = ST_NULLSTRING;
script_data = ST_NULLSTRING;
}
afxScriptEventData::afxScriptEventData(const afxScriptEventData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
method_name = other.method_name;
script_data = other.script_data;
}
#define myOffset(field) Offset(field, afxScriptEventData)
void afxScriptEventData::initPersistFields()
{
addField("methodName", TypeString, myOffset(method_name),
"The name of a script method defined for the instance class of an effects "
"choreographer. The arguments used to call this method are determined by the type "
"of choreographer.");
addField("scriptData", TypeString, myOffset(script_data),
"An arbitrary blind data value which is passed in as an argument of the script event "
"method. The value of scriptData can be used to differentiate uses when handling "
"different script event effects with a single method.");
Parent::initPersistFields();
}
void afxScriptEventData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(method_name);
stream->writeString(script_data);
}
void afxScriptEventData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
method_name = stream->readSTString();
script_data = stream->readSTString();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,57 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_SCRIPT_EVENT_H_
#define _AFX_SCRIPT_EVENT_H_
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxScriptEventData
struct afxScriptEventData : public GameBaseData
{
typedef GameBaseData Parent;
public:
StringTableEntry method_name;
StringTableEntry script_data;
public:
/*C*/ afxScriptEventData();
/*C*/ afxScriptEventData(const afxScriptEventData&, bool = false);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxScriptEventData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_SCRIPT_EVENT_H_

View file

@ -0,0 +1,112 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "afx/ce/afxSpotLight_T3D.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxT3DSpotLightData
IMPLEMENT_CO_DATABLOCK_V1(afxT3DSpotLightData);
ConsoleDocClass( afxT3DSpotLightData,
"@brief A datablock that specifies a dynamic Spot Light effect.\n\n"
"A Spot Light effect that uses the T3D SpotLight object. afxT3DSpotLightData has the same fields found in SpotLight but in "
"a datablock structure."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxT3DSpotLightData::afxT3DSpotLightData()
: mRange( 10.0f ),
mInnerConeAngle( 40.0f ),
mOuterConeAngle( 45.0f )
{
}
afxT3DSpotLightData::afxT3DSpotLightData(const afxT3DSpotLightData& other, bool temp_clone) : afxT3DLightBaseData(other, temp_clone)
{
mRange = other.mRange;
mInnerConeAngle = other.mInnerConeAngle;
mOuterConeAngle = other.mOuterConeAngle;
}
//
// NOTE: keep this as consistent as possible with PointLight::initPersistFields()
//
void afxT3DSpotLightData::initPersistFields()
{
addGroup( "Light" );
addField( "range", TypeF32, Offset( mRange, afxT3DSpotLightData ),
"...");
addField( "innerAngle", TypeF32, Offset( mInnerConeAngle, afxT3DSpotLightData ),
"...");
addField( "outerAngle", TypeF32, Offset( mOuterConeAngle, afxT3DSpotLightData ),
"...");
endGroup( "Light" );
// We do the parent fields at the end so that
// they show up that way in the inspector.
Parent::initPersistFields();
}
bool afxT3DSpotLightData::onAdd()
{
if (Parent::onAdd() == false)
return false;
return true;
}
void afxT3DSpotLightData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write( mRange );
stream->write( mInnerConeAngle );
stream->write( mOuterConeAngle );
}
void afxT3DSpotLightData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read( &mRange );
stream->read( &mInnerConeAngle );
stream->read( &mOuterConeAngle );
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

View file

@ -0,0 +1,58 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _AFX_T3D_SPOT_LIGHT_H_
#define _AFX_T3D_SPOT_LIGHT_H_
#include "afx/ce/afxLightBase_T3D.h"
class afxT3DSpotLightData : public afxT3DLightBaseData
{
typedef afxT3DLightBaseData Parent;
public:
F32 mRange;
F32 mInnerConeAngle;
F32 mOuterConeAngle;
public:
/*C*/ afxT3DSpotLightData();
/*C*/ afxT3DSpotLightData(const afxT3DSpotLightData&, bool = false);
virtual bool onAdd();
virtual void packData(BitStream*);
virtual void unpackData(BitStream*);
virtual bool allowSubstitutions() const { return true; }
static void initPersistFields();
DECLARE_CONOBJECT(afxT3DSpotLightData);
DECLARE_CATEGORY("AFX");
};
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#endif // _AFX_T3D_SPOT_LIGHT_H_

View file

@ -0,0 +1,241 @@
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "ts/tsShapeInstance.h"
#include "afx/afxChoreographer.h"
#include "afx/ce/afxStaticShape.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxStaticShapeData
IMPLEMENT_CO_DATABLOCK_V1(afxStaticShapeData);
ConsoleDocClass( afxStaticShapeData,
"@brief A datablock that specifies a StaticShape effect.\n\n"
"afxStaticShapeData inherits from StaticShapeData and adds some AFX specific fields. StaticShape effects should be "
"specified using afxStaticShapeData rather than StaticShapeData datablocks."
"\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
"@ingroup Datablocks\n"
);
afxStaticShapeData::afxStaticShapeData()
{
sequence = ST_NULLSTRING;
ignore_scene_amb = false;
use_custom_scene_amb = false;
custom_scene_amb.set(0.5f, 0.5f, 0.5f);
do_spawn = false;
}
afxStaticShapeData::afxStaticShapeData(const afxStaticShapeData& other, bool temp_clone) : StaticShapeData(other, temp_clone)
{
sequence = other.sequence;
ignore_scene_amb = other.ignore_scene_amb;
use_custom_scene_amb = other.use_custom_scene_amb;
custom_scene_amb = other.custom_scene_amb;
do_spawn = other.do_spawn;
}
#define myOffset(field) Offset(field, afxStaticShapeData)
void afxStaticShapeData::initPersistFields()
{
addField("sequence", TypeFilename, myOffset(sequence),
"An animation sequence in the StaticShape to play.");
addField("ignoreSceneAmbient", TypeBool, myOffset(ignore_scene_amb),
"...");
addField("useCustomSceneAmbient", TypeBool, myOffset(use_custom_scene_amb),
"...");
addField("customSceneAmbient", TypeColorF, myOffset(custom_scene_amb),
"...");
addField("doSpawn", TypeBool, myOffset(do_spawn),
"When true, the StaticShape effect will leave behind the StaticShape object as a "
"permanent part of the scene.");
Parent::initPersistFields();
}
void afxStaticShapeData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeString(sequence);
stream->writeFlag(ignore_scene_amb);
if (stream->writeFlag(use_custom_scene_amb))
stream->write(custom_scene_amb);
stream->writeFlag(do_spawn);
}
void afxStaticShapeData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
sequence = stream->readSTString();
ignore_scene_amb = stream->readFlag();
if ((use_custom_scene_amb = stream->readFlag()) == true)
stream->read(&custom_scene_amb);
do_spawn = stream->readFlag();
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// afxStaticShape
IMPLEMENT_CO_NETOBJECT_V1(afxStaticShape);
ConsoleDocClass( afxStaticShape,
"@brief A StaticShape effect as defined by an afxStaticShapeData datablock.\n\n"
"@ingroup afxEffects\n"
"@ingroup AFX\n"
);
afxStaticShape::afxStaticShape()
{
afx_data = 0;
is_visible = true;
chor_id = 0;
hookup_with_chor = false;
ghost_cons_name = ST_NULLSTRING;
}
afxStaticShape::~afxStaticShape()
{
}
void afxStaticShape::init(U32 chor_id, StringTableEntry cons_name)
{
this->chor_id = chor_id;
ghost_cons_name = cons_name;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
bool afxStaticShape::onNewDataBlock(GameBaseData* dptr, bool reload)
{
mDataBlock = dynamic_cast<StaticShapeData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
return false;
afx_data = dynamic_cast<afxStaticShapeData*>(mDataBlock);
if (!mShapeInstance)
return true;
const char* seq_name = 0;
// if datablock is afxStaticShapeData we get the sequence setting
// directly from the datablock on the client-side only
if (afx_data)
{
if (isClientObject())
seq_name = afx_data->sequence;
}
// otherwise datablock is stock StaticShapeData and we look for
// a sequence name on a dynamic field on the server.
else
{
if (isServerObject())
seq_name = mDataBlock->getDataField(StringTable->insert("sequence"),0);
}
// if we have a sequence name, attempt to start a thread
if (seq_name)
{
TSShape* shape = mShapeInstance->getShape();
if (shape)
{
S32 seq = shape->findSequence(seq_name);
if (seq != -1)
setThreadSequence(0,seq);
}
}
return true;
}
void afxStaticShape::advanceTime(F32 dt)
{
Parent::advanceTime(dt);
if (hookup_with_chor)
{
afxChoreographer* chor = arcaneFX::findClientChoreographer(chor_id);
if (chor)
{
chor->setGhostConstraintObject(this, ghost_cons_name);
hookup_with_chor = false;
}
}
}
U32 afxStaticShape::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
{
U32 retMask = Parent::packUpdate(conn, mask, stream);
// InitialUpdate
if (stream->writeFlag(mask & InitialUpdateMask))
{
stream->write(chor_id);
stream->writeString(ghost_cons_name);
}
return retMask;
}
//~~~~~~~~~~~~~~~~~~~~//
void afxStaticShape::unpackUpdate(NetConnection * conn, BitStream * stream)
{
Parent::unpackUpdate(conn, stream);
// InitialUpdate
if (stream->readFlag())
{
stream->read(&chor_id);
ghost_cons_name = stream->readSTString();
if (chor_id != 0 && ghost_cons_name != ST_NULLSTRING)
hookup_with_chor = true;
}
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
void afxStaticShape::prepRenderImage(SceneRenderState* state)
{
if (is_visible)
Parent::prepRenderImage(state);
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

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