/* * Author: Andrew Robberts * * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef PS_EFFECT_ANCHOR_HEADER #define PS_EFFECT_ANCHOR_HEADER #include #include #include #include #include #include #include #include struct iDocumentNode; struct iEngine; struct iView; struct iMeshFactoryWrapper; struct iSector; /** * Stores data for a specific effect anchor keyframe */ class psEffectAnchorKeyFrame { public: psEffectAnchorKeyFrame(); psEffectAnchorKeyFrame(iDocumentNode * node, const psEffectAnchorKeyFrame * prevKeyFrame); ~psEffectAnchorKeyFrame(); /** Applies default values to this anchor keyframe. */ void SetDefaults(); /** Sets up this keyframe for the special case of being the first key frame in the group. */ void SetupFirstFrame(); /// this is the time of the keyframe animation (in seconds) float time; enum INTERP_TYPE { IT_NONE = 0, IT_FLOOR, IT_CEILING, IT_LERP, IT_COUNT }; enum KEY_ACTION { KA_POS_X = 1, KA_POS_Y, KA_POS_Z, KA_TOTARGET_X, KA_TOTARGET_Y, KA_TOTARGET_Z, KA_COUNT }; float actions[KA_COUNT]; inline const char * GetActionName(size_t idx) { switch (idx) { case KA_POS_X: return "Position X"; case KA_POS_Y: return "Position Y"; case KA_POS_Z: return "Position Z"; case KA_TOTARGET_X: return "To Target X"; case KA_TOTARGET_Y: return "To Target Y"; case KA_TOTARGET_Z: return "To Target Z"; } return ""; } inline bool IsActionSet(size_t idx) { return specAction.IsBitSet(idx); } /// keep track of which actions were specified for which csBitArray specAction; }; /** * Effect anchor KeyFrame group. */ class psEffectAnchorKeyFrameGroup : public csRefCount { private: csPDelArray keyFrames; public: psEffectAnchorKeyFrameGroup(); ~psEffectAnchorKeyFrameGroup(); /** returns the number of keyframes in the group. * @return the keyframe count */ size_t Length() const { return keyFrames.Length(); } /** returns the keyframe at the given index. * @param idx the index of the keyframe to grab * @return the keyframe */ psEffectAnchorKeyFrame * Get(size_t idx) const { return keyFrames[idx]; } /** returns the keyframe at the given index. * @param idx the index of the keyframe to grab * @return the keyframe */ psEffectAnchorKeyFrame * operator [] (size_t idx) const { return keyFrames[idx]; } /** pushes a keyframe onto the group. * @param keyFrame the keyframe to push */ void Push(psEffectAnchorKeyFrame * keyFrame) { keyFrames.Push(keyFrame); } /** deletes the keyframe at the given index. * @param idx the index of the keyframe to delete */ void DeleteIndex(size_t idx) { keyFrames.DeleteIndex(idx); } /** deletes all of the keyframes in this group. */ void DeleteAll() { keyFrames.DeleteAll(); } }; /** * Effect anchors provide a base location / anchor point for all effect objs. */ class psEffectAnchor { public: psEffectAnchor(); virtual ~psEffectAnchor(); /** Loads the effect anchors from an xml node. * @param node the xml node containing the effect anchor, must be valid. * @return true on success, false otherwise. */ virtual bool Load(iDocumentNode *node); /** Creates the effect anchor. * @param offset the offset of the position of the obj. * @param posAttach the mesh to attach this anchor to. * @return true on success. */ virtual bool Create(const csVector3 &offset, iMeshWrapper * posAttach); /** Updates the effect anchor -- called every frame. * @param elapsed the ticks elapsed since last update. * @return false if the anchor is useless and can be removed by its parent effect. */ virtual bool Update(csTicks elapsed); /** Convenience function to clone the base member variables * @param newAnchor reference to the new anchor that will contain the cloned variables */ void CloneBase(psEffectAnchor * newAnchor) const; /** Clones the effect anchor. This will almost always be overloaded. */ virtual psEffectAnchor * Clone() const; /** Sets a new position for the effect anchor. * @param basePos The new position of the anchor. * @param sector The new sector of the anchor * @param transf The transform of the position. */ virtual void SetPosition(const csVector3 & basePos, iSector * sector, const csMatrix3 & transf); /** Sets a new position for the effect anchor. * @param basePos The new position of the anchor. * @param sectors The new sectors of the anchor. * @param transf The transform of the position. */ virtual void SetPosition(const csVector3 & basePos, iSectorList * sectors, const csMatrix3 & transf); /** Sets the target of the effect anchor. * @param newTarget The new target. * @param transf The transform of the target. */ void SetTarget(const csVector3 & newTarget, const csMatrix3 & transf) { target = newTarget; targetTransf = transf; } /** Returns the name of this effect anchor. * @return The name of this effect anchor. */ const csString & GetName() const { return name; } /** Sets the name of this effect anchor. * @param newName The new name of the anchor. */ void SetName(const csString & newName) { name = newName; } /** Returns the mesh that's associated with this effect anchor (almost always a nullmesh). * @return Generally returns either a nullmesh or 0. */ iMeshWrapper * GetMesh() const { return mesh; } /** Sets the base rotation matrix of the effect anchor. * @param newRotBase The base rotation matrix. */ virtual void SetRotBase(const csMatrix3 & newRotBase) { matBase = newRotBase; } /** Transforms the offset according to the mesh's settings, like abs_dir, etc. * @param offset the vector to be transformed. */ void TransformOffset(csVector3 & offset); /** Returns the number of keyframes in this anchor. * @return The keyFrame count. */ size_t GetKeyFrameCount() const { return keyFrames->Length(); } /** Returns the keyframe at the given index. * @param idx The index of the keyframe to grab. * @return The keyframe at the given index. */ psEffectAnchorKeyFrame * GetKeyFrame(size_t idx) const { return keyFrames->Get(idx); } /** Gets the direction type of this anchor. * @return the direction type (none, origin, target). */ const char * GetDirectionType() const; /** Sets the direction type of this anchor. * @param newDir the new direction type (none, origin, target). */ void SetDirectionType(const char * newDir); /** Sets the animation length of the effect anchor. * @param newAnimLength the new animation length. */ void SetAnimLength(float newAnimLength) { animLength = newAnimLength; } /** Gets the animation length of the effect anchor. * @return the animation length. */ float GetAnimLength() { return animLength; } /** Creates a new keyframe and attaches it to this movable. * @param time The time of this new keyFrame. * @return the index where the new keyframe can be reached using GetKeyFrame(index). */ size_t AddKeyFrame(float time); /** Check to see if this anchor is ready. * @return true if it's ready. */ bool IsReady() const { return isReady; } enum DIR_TYPE { DT_NONE = 0, DT_ORIGIN, DT_TARGET, DT_COUNT }; /** Interpolates keyFrame actions for ones that weren't specified in each keyframe. */ void FillInLerps(); protected: /** Finds the index of the keyFrame at the specified time. * @param time The time to lookup. * @return The index of the keyFrame at the specified time. */ size_t FindKeyFrameByTime(float time) const; /** Finds the next key frame where the specific action is specified. * @param startFrame The first frame to start looking. * @param action The action to look for. * @param index A container to store the index of the found key frame. * @return true if it found one and the index is stored, false otherwise. */ bool FindNextKeyFrameWithAction(size_t startFrame, size_t action, size_t & index) const; csString name; /// A unique name identifying this anchor. float life; /// The amount of time this anchor has been alive (gets reset on loop). float animLength; /// The length of each loop of this anchor. csMatrix3 matBase; /// The base transform matrix of this anchor. /** * objEffectPos is pretty much the position of the effect, (that's not a requirement though). * It's the only position vector that can be modified externally (by the effect after creation) * and this one shouldn't be modified by the effect anchor in any way. */ csVector3 objEffectPos; /// Base pos for the effect anchor, this is used for things like the variable offset from the anchoring mesh. csVector3 objBasePos; /// Stores the delta to the effect target. csVector3 objTargetOffset; /// The complete offset, this gets modified by the position action, generally. csVector3 objOffset; csMatrix3 posTransf; /// Stores the target of the effect. csVector3 target; csMatrix3 targetTransf; /// The mesh that makes up this anchor. csRef mesh; /// What type of direction does this movable have int dir; size_t currKeyFrame; /// The current keyframe the anchor is on. size_t nextKeyFrame; /// The next keyframe the anchor will be on. /// Stores the keyframes of this anchor (this is shared between all anchor of this type). csRef keyFrames; /// Reference to CS's iEngine. csRef engine; bool isReady; /// Linear interpolation function for a floating point. inline float lerp(float f1, float f2, float t1, float t2, float t) { if (t2 == t1) return f1; return f1 + (f2-f1)*(t-t1)/(t2-t1); } /// Linear interpolation function for a 3D vector. inline csVector3 lerpVec(const csVector3 &v1, const csVector3 &v2, float t1, float t2, float t) { if (t2 == t1) return v1; return v1 + (v2-v1)*(t-t1)/(t2-t1); } }; #endif