Ejemplo n.º 1
0
        // 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 :;
            }
        }