1 //****************************************************************************// 2 // mixer.h // 3 // Copyright (C) 2001, 2002 Bruno 'Beosil' Heidelberger // 4 // Copyright (C) 2004 Mekensleep <licensing@mekensleep.com> // 5 //****************************************************************************// 6 // This library is free software; you can redistribute it and/or modify it // 7 // under the terms of the GNU Lesser General Public License as published by // 8 // the Free Software Foundation; either version 2.1 of the License, or (at // 9 // your option) any later version. // 10 //****************************************************************************// 11 12 #ifndef CAL_MIXER_H 13 #define CAL_MIXER_H 14 15 //****************************************************************************// 16 // Includes // 17 //****************************************************************************// 18 19 #include "cal3d/global.h" 20 21 //****************************************************************************// 22 // Forward declarations // 23 //****************************************************************************// 24 25 class CalModel; 26 class CalAnimation; 27 class CalAnimationAction; 28 class CalAnimationCycle; 29 30 31 32 33 /*****************************************************************************/ 34 /** 35 * CalAbstractMixer defines the API that CalModel relies on for 36 * blending and scheduling animations. A third party mixer must 37 * implement this API in order to register itself with the 38 * CalModel::setAbstractMixer method. The default mixer (CalMixer) is 39 * an example of such implementation. 40 * 41 * cal3d expects a mixer to handle two tasks : scheduling and 42 * blending. Scheduling refers to everything related to time such 43 * as when an animation must run or when it must stop. Blending 44 * defines how concurrent animations influence each other: for 45 * instance walking and waving. 46 * 47 * If CalMixer proves to be insufficient for the applications needs, 48 * an alternate mixer can be implemented and used without notifying 49 * cal3d in any way. It is not mandatory to subclass 50 * CalAbstractMixer. However, when chosing this path, one must also 51 * avoid using the CalModel::update method because it would use the 52 * default mixer instantiated by the CalModel::create method with 53 * undesirable side effects. In addition libraries based on cal3d 54 * (think NebulaDevice or OpenSceneGraph adapters) are not aware of 55 * these constraints and will keep calling the CalModel::update method of 56 * CalModel regardless. 57 * 58 * Subclassing CalAbstractMixer when implementing an alternate mixer 59 * therefore provides a better integration with cal3d and libraries 60 * that rely on CalModel. However, an additional effort is required in 61 * order to achieve compatibility with libraries or applications that 62 * rely on the CalMixer API (i.e. that use methods such as blendCycle 63 * or executeAction). The CalMixer API is not meant to be generic and 64 * there is no reason to define an abstract class that specifies 65 * it. For historical reasons and because CalMixer is the default 66 * mixer, some applications and libraries (think Soya or CrystalSpace) 67 * depend on it. If they want to switch to a scheduler with extended 68 * capabilities it might be painfull for them to learn a completely 69 * different API. A scheduler with the ambition to obsolete CalMixer 70 * should therefore provide an API compatible with it to ease the 71 * migration process. 72 * 73 * Short summary, if you want to write a new mixer: 74 * 75 * 1) An external mixer: ignore CalAbstractMixer and implement a mixer 76 * of your own. Avoid calling CalModel::update and any library or 77 * application that will call it behind your back. Avoid libraries and 78 * applications that rely on the default mixer CalMixer, as returned 79 * by CalModel::getMixer. 80 * 81 * 2) A mixer registered in cal3d : subclass CalAbstractMixer, 82 * register it with CalModel::setAbstractMixer. Avoid libraries and 83 * applications that rely on the default mixer CalMixer, as returned 84 * by CalModel::getMixer. CalModel::getMixer will return a null 85 * pointer if CalModel::setAbstractMixer was called to set 86 * a mixer that is not an instance of CalMixer. 87 * 88 * 3) A CalMixer replacement : same as 2) and provide a subclass of 89 * your own mixer that implements the CalMixer API so that existing 90 * applications can switch to it by calling CalModel::getAbstractMixer 91 * instead of CalModel::getMixer. The existing code using the CalMixer 92 * methods will keep working and the developper will be able to 93 * switch to a new API when convenient. 94 * 95 *****************************************************************************/ 96 97 class CAL3D_API CalAbstractMixer 98 { 99 public: CalAbstractMixer()100 CalAbstractMixer() {} ~CalAbstractMixer()101 virtual ~CalAbstractMixer() {} 102 103 /*****************************************************************************/ 104 /** 105 * Is the object an instance of the default mixer (i.e. an instance of CalMixer) ? 106 * 107 * @return \li \b true if an instance of CalMixer 108 * \li \b false if not an instance of CalMixer 109 * 110 *****************************************************************************/ isDefaultMixer()111 virtual bool isDefaultMixer() const { return false; } 112 113 /*****************************************************************************/ 114 /** 115 * Notifies the instance that updateAnimation was last called 116 * deltaTime seconds ago. The internal scheduler of the instance 117 * should terminate animations or update the timing information of 118 * active animations accordingly. It should not blend animations 119 * together or otherwise modify the CalModel associated to these 120 * animations. 121 * 122 * The CalModel::update method will call updateSkeleton immediately 123 * after updateAnimation if the instance was allocated by 124 * CalModel::create (in which case it is a CalMixer instance) or if 125 * the instance was set via CalModel::setAbstractMixer. 126 * 127 * @param deltaTime The elapsed time in seconds since the last call. 128 * 129 *****************************************************************************/ 130 virtual void updateAnimation(float deltaTime) = 0; 131 132 /*****************************************************************************/ 133 /** 134 * Updates the skeleton of the corresponding CalModel (as provided to 135 * the create method) to match the current animation state (as 136 * updated by the last call to updateAnimation). The tracks of each 137 * active animation are blended to compute the position and 138 * orientation of each bone of the skeleton. The updateAnimation 139 * method should be called just before calling updateSkeleton to 140 * define the set of active animations. 141 * 142 * The CalModel::update method will call updateSkeleton immediately 143 * after updateAnimation if the instance was allocated by 144 * CalModel::create (in which case it is a CalMixer instance) or if 145 * the instance was set via CalModel::setAbstractMixer. 146 * 147 *****************************************************************************/ 148 virtual void updateSkeleton() = 0; 149 }; 150 151 152 class CAL3D_API CalMixer : public CalAbstractMixer 153 { 154 public: 155 CalMixer(CalModel* pModel); 156 virtual ~CalMixer(); 157 isDefaultMixer()158 virtual bool isDefaultMixer() const { return true; } 159 bool blendCycle(int id, float weight, float delay); 160 bool clearCycle(int id, float delay); 161 bool executeAction(int id, float delayIn, float delayOut, float weightTarget = 1.0f, bool autoLock=false); 162 bool removeAction(int id); 163 virtual void updateAnimation(float deltaTime); 164 virtual void updateSkeleton(); 165 float getAnimationTime() const; 166 float getAnimationDuration() const; 167 void setAnimationTime(float animationTime); 168 void setTimeFactor(float timeFactor); 169 float getTimeFactor() const; 170 CalModel *getCalModel(); 171 std::vector<CalAnimation *> &getAnimationVector(); 172 std::list<CalAnimationAction *> &getAnimationActionList(); 173 std::list<CalAnimationCycle *> &getAnimationCycle(); 174 175 protected: 176 CalModel *m_pModel; 177 std::vector<CalAnimation *> m_vectorAnimation; 178 std::list<CalAnimationAction *> m_listAnimationAction; 179 std::list<CalAnimationCycle *> m_listAnimationCycle; 180 float m_animationTime; 181 float m_animationDuration; 182 float m_timeFactor; 183 }; 184 185 #endif 186 187 //****************************************************************************// 188