// todo: go through all states once, remove as many as we need. refactor to not need goto public void Trigger(int frame, int decayStates) { for (; decayStates > 0 && _tsm.Count > 1;) { int baseStateIndex = _tsm.GetStateIndexByFrame(frame); int baseStateFrame = _tsm.GetStateFrameByIndex(baseStateIndex) / _step; // reduce right away int forwardPriority = -1000000; int backwardPriority = -1000000; int forwardFrame = -1; int backwardFrame = -1; for (int currentStateIndex = 1; currentStateIndex < baseStateIndex; currentStateIndex++) { int currentFrame = _tsm.GetStateFrameByIndex(currentStateIndex); if (_movie.Markers.IsMarker(currentFrame + 1)) { continue; } if (currentFrame + 1 == _movie.LastEditedFrame) { continue; } if (currentFrame % _step > 0) { // ignore the pattern if the state doesn't belong already, drop it blindly and skip everything if (_tsm.Remove(currentFrame)) { // decrementing this if no state was removed is BAD decayStates--; // this is the kind of highly complex loops that might justify goto goto next_state; } } else { // reduce to imaginary integral greenzone for all the decay logic currentFrame /= _step; } int zeroCount = _zeros[currentFrame & _mask]; int priority = (baseStateFrame - currentFrame) >> zeroCount; if (_align) { priority -= (_base * ((1 << zeroCount) * 2 - 1)) >> zeroCount; } if (priority > forwardPriority) { forwardPriority = priority; forwardFrame = currentFrame; } } for (int currentStateIndex = _tsm.Count - 1; currentStateIndex > baseStateIndex; currentStateIndex--) { int currentFrame = _tsm.GetStateFrameByIndex(currentStateIndex); if (_movie.Markers.IsMarker(currentFrame + 1)) { continue; } if (currentFrame % _step > 0 && currentFrame + 1 != _movie.LastEditedFrame) { // ignore the pattern if the state doesn't belong already, drop it blindly and skip everything if (_tsm.Remove(currentFrame)) { // decrementing this if no state was removed is BAD decayStates--; // this is the kind of highly complex loops that might justify goto goto next_state; } } else { // reduce to imaginary integral greenzone for all the decay logic currentFrame /= _step; } int zeroCount = _zeros[currentFrame & _mask]; int priority = (currentFrame - baseStateFrame) >> zeroCount; if (_align) { priority -= (_base * ((1 << zeroCount) * 2 - 1)) >> zeroCount; } if (priority > backwardPriority) { backwardPriority = priority; backwardFrame = currentFrame; } } int decayStatesLast = decayStates; if (forwardFrame > -1 && backwardFrame > -1) { if (baseStateFrame - forwardFrame > backwardFrame - baseStateFrame) { if (_tsm.Remove(forwardFrame * _step)) { // decrementing this if no state was removed is BAD decayStates--; } } else { if (_tsm.Remove(backwardFrame * _step)) { // decrementing this if no state was removed is BAD decayStates--; } } } else if (forwardFrame > -1) { if (_tsm.Remove(forwardFrame * _step)) { // decrementing this if no state was removed is BAD decayStates--; } } else if (backwardFrame > -1) { if (_tsm.Remove(backwardFrame * _step)) { // decrementing this if no state was removed is BAD decayStates--; } } // we're very sorry about failing to find states to remove, but we can't go beyond capacity, so remove at least something // this shouldn't happen, but if we don't do it here, nothing good will happen either if (decayStatesLast == decayStates) { if (_tsm.Remove(_tsm.GetStateFrameByIndex(1))) { // decrementing this if no state was removed is BAD decayStates--; } } // this is the kind of highly complex loops that might justify goto next_state :; } }