//Returns true if there was an animation to listen to bool CUnitScript::AddAnimListener(AnimType type, int piece, int axis, IAnimListener *listener) { std::list<AnimInfo*>::iterator animInfoIt = FindAnim(type, piece, axis); if (animInfoIt != anims[type].end()) { AnimInfo* ai = *animInfoIt; if (!ai->done) { ai->listeners.push_back(listener); return true; } // if the animation is already finished, listening for // it just adds some overhead since either the current // or the next Tick will remove it and call UnblockAll // (which calls AnimFinished for each listener) // // we could notify the listener here, but a cleaner way // is to treat the animation as if it did not exist and // simply disregard the WaitFor* (no side-effects) // // listener->AnimFinished(ai->type, ai->piece, ai->axis); } return false; }
void CVertMeshInstance::PlayAnimInternal(const char *AnimName, float Rate, bool Looped) { guard(CVertMeshInstance::PlayAnimInternal); int NewAnimIndex = FindAnim(AnimName); if (NewAnimIndex == INDEX_NONE) { // show default pose AnimIndex = INDEX_NONE; AnimTime = 0; AnimRate = 0; AnimLooped = false; return; } AnimRate = (NewAnimIndex != INDEX_NONE) ? pMesh->AnimSeqs[NewAnimIndex].Rate * Rate : 0; AnimLooped = Looped; if (NewAnimIndex == AnimIndex && Looped) { // animation not changed, just set some flags (above) return; } AnimIndex = NewAnimIndex; AnimTime = 0; unguard; }
void CUnitScript::Spin(int piece, int axis, float speed, float accel) { struct AnimInfo *ai; ai = FindAnim(ASpin, piece, axis); //If we are already spinning, we may have to decelerate to the new speed if (ai) { ai->dest = speed; if (accel > 0) { ai->accel = accel; } else { //Go there instantly. Or have a defaul accel? ai->speed = speed; ai->accel = 0; } } else { //No accel means we start at desired speed instantly if (accel <= 0) AddAnim(ASpin, piece, axis, speed, speed, 0); else AddAnim(ASpin, piece, axis, 0, speed, accel); } }
void CCobInstance::Spin(int piece, int axis, int speed, int accel) { struct AnimInfo *ai; ai = FindAnim(ASpin, piece, axis); //logOutput.Print("Spin called %d %d %d %d", piece, axis, speed, accel); //Test of default acceleration if (accel == 0) accel = 1000; //If we are already spinning, we may have to decelerate to the new speed if (ai) { ai->dest = speed; if (accel > 0) { if (ai->speed > ai->dest) ai->accel = -accel; else ai->accel = accel; } else { //Go there instantly. Or have a defaul accel? ai->speed = speed; ai->accel = 0; } } else { //No accel means we start at desired speed instantly if (accel == 0) AddAnim(ASpin, piece, axis, speed, speed, accel); else AddAnim(ASpin, piece, axis, 0, speed, accel); } }
//Overwrites old information. This means that threads blocking on turn completion //will now wait for this new turn instead. Not sure if this is the expected behaviour //Other option would be to kill them. Or perhaps unblock them. void CCobInstance::AddAnim(AnimType type, int piece, int axis, int speed, int dest, int accel, bool interpolated) { struct AnimInfo *ai; //Turns override spins.. Not sure about the other way around? If so the system should probably be redesigned //to only have two types of anims.. turns and moves, with spin as a bool if (type == ATurn) RemoveAnim(ASpin, piece, axis); if (type == ASpin) RemoveAnim(ATurn, piece, axis); ai = FindAnim(type, piece, axis); if (!ai) { ai = new struct AnimInfo; ai->type = type; ai->piece = piece; ai->axis = axis; anims.push_back(ai); //If we were not animating before, inform the engine of this so it can schedule us if (anims.size() == 1) { GCobEngine.AddInstance(this); } // Check to make sure the piece exists if (piece >= pieces.size()) { logOutput.Print("Invalid piece in anim %d (%d)", piece, pieces.size()); } } ai->speed = speed; ai->dest = dest; ai->accel = accel; ai->interpolated = interpolated; }
void AnimationComponent::PlayAnim(const std::string& name, int flags) { unsigned int anim = FindAnim(name); if (anim != NOT_FOUND) { PlayAnim(anim, flags); } }
//Returns true if there was an animation to listen to bool CUnitScript::AddAnimListener(AnimType type, int piece, int axis, IAnimListener *listener) { struct AnimInfo *ai; ai = FindAnim(type, piece, axis); if (ai) { ai->listeners.push_back(listener); return true; } else return false; }
int CCobInstance::AddMoveListener(int piece, int axis, CCobThread *listener) { struct AnimInfo *ai; ai = FindAnim(AMove, piece, axis); if (ai) { ai->listeners.push_back(listener); return 1; } else return 0; }
void CCobInstance::StopSpin(int piece, int axis, int decel) { struct AnimInfo *ai; ai = FindAnim(ASpin, piece, axis); if (!ai) return; if (decel == 0) { RemoveAnim(ASpin, piece, axis); } else AddAnim(ASpin, piece, axis, ai->speed, 0, -decel); }
void CUnitScript::StopSpin(int piece, int axis, float decel) { std::list<AnimInfo*>::iterator animInfoIt = FindAnim(ASpin, piece, axis); if (decel <= 0) { RemoveAnim(ASpin, animInfoIt); } else { if (animInfoIt == anims[ASpin].end()) return; AnimInfo* ai = *animInfoIt; ai->dest = 0; ai->accel = decel; } }
void CUnitScript::StopSpin(int piece, int axis, float decel) { if (decel <= 0) { RemoveAnim(ASpin, piece, axis); } else { struct AnimInfo *ai; ai = FindAnim(ASpin, piece, axis); if (!ai) return; ai->dest = 0; ai->accel = decel; } }
//Overwrites old information. This means that threads blocking on turn completion //will now wait for this new turn instead. Not sure if this is the expected behaviour //Other option would be to kill them. Or perhaps unblock them. void CUnitScript::AddAnim(AnimType type, int piece, int axis, float speed, float dest, float accel, bool interpolated) { if (!PieceExists(piece)) { ShowScriptError("Invalid piecenumber"); return; } float destf; if (type == AMove) { destf = pieces[piece]->original->offset[axis] + dest; } else { destf = dest; if (type == ATurn) { ClampRad(&destf); } } struct AnimInfo *ai; //Turns override spins.. Not sure about the other way around? If so the system should probably be redesigned //to only have two types of anims.. turns and moves, with spin as a bool //todo: optimize, atm RemoveAnim and FindAnim search twice through all anims if (type == ATurn) RemoveAnim(ASpin, piece, axis); if (type == ASpin) RemoveAnim(ATurn, piece, axis); ai = FindAnim(type, piece, axis); if (!ai) { // If we were not animating before, inform the engine of this so it can schedule us if (anims.empty()) { GUnitScriptEngine.AddInstance(this); } ai = new struct AnimInfo; ai->type = type; ai->piece = piece; ai->axis = axis; anims.push_back(ai); } ai->dest = destf; ai->speed = speed; ai->accel = accel; ai->interpolated = interpolated; }
void CCobInstance::MoveSmooth(int piece, int axis, int destination, int delta, int deltaTime) { //Make sure we do not overwrite animations of non-interpolated origin AnimInfo *ai = FindAnim(AMove, piece, axis); if (ai) { if (!ai->interpolated) { //logOutput.Print("Anim move overwrite"); MoveNow(piece, axis, destination); return; } } int cur = pieces[piece].coords[axis]; int dist = abs(destination - cur); int timeFactor = (1000 * 1000) / (deltaTime * deltaTime); int speed = (dist * timeFactor) / delta; //logOutput.Print("Move %d got %d %d", cur, destination, speed); Move(piece, axis, speed, destination, true); }
void CCobInstance::TurnSmooth(int piece, int axis, int destination, int delta, int deltaTime) { AnimInfo *ai = FindAnim(ATurn, piece, axis); if (ai) { if (!ai->interpolated) { //logOutput.Print("Anim turn overwrite"); TurnNow(piece, axis, destination); return; } } int cur = pieces[piece].rot[axis]; short int dist = destination - cur; int timeFactor = (1000 * 1000) / (deltaTime * deltaTime); dist = abs(dist); int speed = (dist * timeFactor) / delta; //logOutput.Print("Turnx %d:%d cur %d got %d %d dist %d", piece, axis, cur, destination, speed, dist); Turn(piece, axis, speed, destination, true); }
void CUnitScript::TurnSmooth(int piece, int axis, float destination, int delta, int deltaTime) { if (!PieceExists(piece)) { ShowScriptError("Invalid piecenumber"); return; } AnimInfo *ai = FindAnim(ATurn, piece, axis); if (ai) { if (!ai->interpolated) { TurnNow(piece, axis, destination); return; } } // not sure the ClampRad() call is necessary here float cur = ClampRad(pieces[piece]->rot[axis]); float dist = streflop::fabsf(destination - cur); int timeFactor = (1000 * 1000) / (deltaTime * deltaTime); float speed = (dist * timeFactor) / delta; Turn(piece, axis, speed, destination, true); }
void CUnitScript::MoveSmooth(int piece, int axis, float destination, int delta, int deltaTime) { if (!PieceExists(piece)) { ShowScriptError("Invalid piecenumber"); return; } //Make sure we do not overwrite animations of non-interpolated origin AnimInfo *ai = FindAnim(AMove, piece, axis); if (ai) { if (!ai->interpolated) { MoveNow(piece, axis, destination); return; } } float cur = pieces[piece]->pos[axis] - pieces[piece]->original->offset[axis]; float dist = streflop::fabsf(destination - cur); int timeFactor = (1000 * 1000) / (deltaTime * deltaTime); float speed = (dist * timeFactor) / delta; Move(piece, axis, speed, destination, true); }
//Overwrites old information. This means that threads blocking on turn completion //will now wait for this new turn instead. Not sure if this is the expected behaviour //Other option would be to kill them. Or perhaps unblock them. void CUnitScript::AddAnim(AnimType type, int piece, int axis, float speed, float dest, float accel) { if (!PieceExists(piece)) { ShowScriptError("Invalid piecenumber"); return; } float destf = 0.0f; if (type == AMove) { destf = pieces[piece]->original->offset[axis] + dest; } else { destf = dest; if (type == ATurn) { ClampRad(&destf); } } std::list<AnimInfo*>::iterator animInfoIt; AnimInfo* ai = NULL; AnimType overrideType = ANone; // first find an animation of a type we override // Turns override spins.. Not sure about the other way around? If so // the system should probably be redesigned to only have two types of // anims (turns and moves), with spin as a bool switch (type) { case ATurn: { overrideType = ASpin; animInfoIt = FindAnim(overrideType, piece, axis); } break; case ASpin: { overrideType = ATurn; animInfoIt = FindAnim(overrideType, piece, axis); } break; case AMove: { // ensure we never remove an animation of this type overrideType = AMove; animInfoIt = anims[overrideType].end(); } break; default: { } break; } if (animInfoIt != anims[overrideType].end()) RemoveAnim(overrideType, animInfoIt); // now find an animation of our own type animInfoIt = FindAnim(type, piece, axis); if (animInfoIt == anims[type].end()) { // If we were not animating before, inform the engine of this so it can schedule us // FIXME: this could be done in a cleaner way if (!HaveAnimations()) { GUnitScriptEngine.AddInstance(this); } ai = new AnimInfo(); ai->type = type; ai->piece = piece; ai->axis = axis; anims[type].push_back(ai); } else { ai = *animInfoIt; } ai->dest = destf; ai->speed = speed; ai->accel = accel; ai->done = false; }