| @@ -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_ |
| @@ -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_ |
| @@ -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_ |
| @@ -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) 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); | ||
| } | ||
|
|
||
| //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// | ||
|
|
| @@ -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_ |
| @@ -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; | ||
| } | ||
| } | ||
|
|
||
| //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// | ||
|
|
||
|
|
| @@ -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_ |
| @@ -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; | ||
| ColorF 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(ColorF& 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(ColorF& 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_ |
| @@ -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_ |
| @@ -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_ |
| @@ -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(); | ||
| } | ||
|
|
||
|
|
||
| //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// |
| @@ -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_ |
| @@ -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 ); | ||
| } |
| @@ -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_ |