示例#1
0
        internal bool Add(pSprite p)
        {
            if (p == null)
            {
                return(false);
            }

            if (ForwardPlayOptimisations && ForwardPlayOptimisedAdd)
            {
                p.AlwaysDraw = false;
            }

            if (ForwardPlayOptimisedAdd && p.Transformations.Count > 0)
            {
                int index = ForwardPlayList.BinarySearch(p);

                if (index < 0)
                {
                    ForwardPlayList.Insert(~index, p);
                }
                else
                {
                    ForwardPlayList.Insert(index, p);
                }
                return(true);
            }

            lock (spriteList)
            {
                int index = spriteList.BinarySearch(p, pSpriteDepthComparer);
                p.HoverPriority = HoverPriorityCurrent++;
                spriteList.Insert(index < 0 ? ~index : index, p);
            }
            return(true);
        }
示例#2
0
 /// <summary>
 /// Reset click handling, useful to allow rapid clicking of a sprite when holding mouse button down.
 /// </summary>
 internal void ResetClick()
 {
     GameBase.Scheduler.Add(delegate
     {
         ClickHandledSprite            = null;
         clickHandledAtLeastOnce       = false;
         globalClickHandledAtLeastOnce = false;
     }, true);
 }
示例#3
0
 internal void Remove(pSprite p)
 {
     if (p != null)
     {
         lock (spriteList)
             spriteList.Remove(p);
         p.IsVisible = false;
     }
 }
示例#4
0
        /// <summary>
        /// Handle input for all sprites contained in this handler.
        /// </summary>
        /// <returns>true if input was handled</returns>
        internal bool CheckInput(bool highPass, bool alreadyHandled)
        {
            if (!HandleInput)
            {
                return(false);
            }

            if (highPass != HandleOverlayInput)
            {
                return(false);
            }

            if (Alpha < 0.01f || Bypass)
            {
                return(false);
            }

            pSprite lastHoverSprite = CurrentHoverSprite;

            resetHoverSprite();

            lock (SpriteList)
            {
                for (int i = 0; i < SpriteList.Count; i++)
                {
                    pDrawable s = SpriteList[i];

                    if (s.Bypass)
                    {
                        continue;
                    }

                    if (!alreadyHandled)
                    {
                        CheckHover(s);
                    }
                    else
                    {
                        s.Hovering = false;
                    }
                }
            }

            if (CurrentHoverSprite != null)
            {
                CurrentHoverSprite.Hovering = true;
            }

            if (lastHoverSprite != null && lastHoverSprite != CurrentHoverSprite)
            {
                lastHoverSprite.Hovering = false;
            }

            return(CurrentHoverSprite != null);
        }
示例#5
0
        internal void Add(List <pSprite> sprites, Object tag)
        {
            int c = sprites.Count;

            for (int i = 0; i < c; i++)
            {
                pSprite p = sprites[i];
                Add(p);
                p.Tag = tag;
            }
        }
示例#6
0
        /// <summary>
        ///   Special case scenario where we don't want to add using ForwardPlayOptimisedAdd.
        ///   Easier than toggling.
        /// </summary>
        /// <param name = "p"></param>
        internal void AddNonOptimised(pSprite p)
        {
            if (p == null)
            {
                return;
            }

            lock (SpriteLock)
            {
                int index = SpriteList.BinarySearch(p, pDrawableDepthComparer);
                //if (p.HoverPriority >= 0) p.HoverPriority = hoverPriorityCurrent++;
                SpriteList.Insert(index < 0 ? ~index : index, p);
            }
        }
示例#7
0
        private void handleClick(bool repeat)
        {
            if (Alpha == 0 || LastFrameRendered < GameBase.TotalFramesRendered - 1)
            {
                clickHandledAtLeastOnce = true;
                return;
            }

            //Force update of currently hovered sprite.
            pSprite lastHoverSprite = CurrentHoverSprite;

            resetHoverSprite();
            int count = SpriteList.Count;

            if (repeat && clickHandledAtLeastOnce)
            {
                return;
            }

            for (int i = 0; i < count; i++)
            {
                CheckHover(SpriteList[i]);
            }

            clickHandledAtLeastOnce = true;

            if (lastHoverSprite != null && lastHoverSprite != CurrentHoverSprite)
            {
                lastHoverSprite.Hovering = false;
            }

            if (CurrentHoverSprite == null)
            {
                return;
            }

            if (!HandleInput || ClickHandledSprite != null || !CurrentHoverSprite.HandleInput || !CurrentHoverSprite.IsVisible || MouseManager.MouseMiddle == ButtonState.Pressed)
            {
                return;
            }

            if (CurrentHoverSprite.Click(false))
            {
                InputManager.LastClickHandled = true;
            }

            ClickHandledSprite = CurrentHoverSprite;
        }
示例#8
0
        internal void CheckHover <T>(T d) where T : pDrawable
        {
            if (d == null || !d.IsVisible || d.Bypass)
            {
                return;
            }

            pSprite s = d as pSprite;

            if (s == null)
            {
                return;
            }

            if (s.HandleInput)
            {
                if (MouseManager.MouseInWindow &&
                    (CurrentHoverSprite == null || s.HoverPriority < CurrentHoverSprite.HoverPriority) &&
                    s.CheckHover(MouseManager.MousePosition)
                    //TODO: this will fail for circular sprites inside a masked spriteManager. see what Masking adjustments do to CurrentPositionScaled in Draw()
                    && (!Masking || ViewRectangleScaled.Contains(MouseManager.MousePoint))
                    )
                {
                    if (CurrentHoverSprite != null)
                    {
                        CurrentHoverSprite.Hovering = false;
                    }

                    CurrentHoverSprite = s;
                }
                else if (s.Hovering)
                {
                    s.Hovering = false;
                }
            }
            else if (s.Hovering)
            {
                s.Hovering = false;
            }
        }
示例#9
0
 internal static int GetSpriteTime(pSprite s)
 {
     return(s.Clock == Clocks.Game ? GameBase.Time : (int)AudioEngine.Time);
 }
示例#10
0
 private void resetHoverSprite()
 {
     CurrentHoverSprite = null;
 }
示例#11
0
 internal static int GetSpriteTime(pSprite s)
 {
     return(s.Clock == ClockTypes.Audio ? AudioTime : GameTime);
 }
示例#12
0
        /// <summary>
        /// Draws this instance.
        /// </summary>
        internal void Draw()
        {
            lock (spriteList)
            {
                int spriteListCount = spriteList.Count;

                hoverSprite = null;
                hoverIndex  = -1;

                if (spriteListCount == 0 && !ForwardPlayOptimisations)
                {
                    return;
                }

                if (Alpha == 0)
                {
                    for (int m = 0; m < spriteListCount; m++)
                    {
                        spriteList[m].IsVisible = false;
                    }
                    return;
                }

                GameTime  = GameBase.Time;
                AudioTime = AudioEngine.Time;

                //Setup view rectangle
                ViewRectangleScaled        = ViewRectangle;
                ViewRectangleScaled.X      = (int)(ViewRectangleScaled.X * GameBase.WindowRatio) - 1;
                ViewRectangleScaled.Y      = (int)(ViewRectangleScaled.Y * GameBase.WindowRatio) - 1 + GameBase.WindowVOffset;
                ViewRectangleScaled.Width  = (int)(ViewRectangleScaled.Width * GameBase.WindowRatio) + 1;
                ViewRectangleScaled.Height = (int)(ViewRectangleScaled.Height * GameBase.WindowRatio) + 1;

                bool hoverFound = false;

                bool mouseInWindow = GameBase.WindowRectangle.Contains(MouseHandler.MousePoint);

                if (ForwardPlayOptimisations)
                {
                    bool success = true;
                    while (success && ForwardPlayQueue.Count > 0)
                    {
                        pSprite fpqp = ForwardPlayQueue.Peek();
                        success = fpqp != null &&
                                  (fpqp.Transformations.Count == 0 || fpqp.Transformations[0].Time1 <= GetSpriteTime(fpqp));
                        if (success)
                        {
                            if (Add(ForwardPlayQueue.Dequeue()))
                            {
                                spriteListCount++;
                            }
                        }
                    }
                }

                try
                {
                    GameBase.spriteBatch.Begin(Additive ? SpriteBlendMode.Additive : SpriteBlendMode.AlphaBlend,
                                               SpriteSortMode.Immediate, SaveStateMode.None);

                    GameBase.spriteBatch.GraphicsDevice.RenderState.SeparateAlphaBlendEnabled = true;
                    GameBase.spriteBatch.GraphicsDevice.RenderState.AlphaSourceBlend          = Blend.One;
                    GameBase.spriteBatch.GraphicsDevice.RenderState.AlphaDestinationBlend     = Blend.InverseSourceAlpha;
                    //GameBase.spriteBatch.GraphicsDevice.RenderState.AlphaTestEnable = false;

                    Blend defaultBlend = GameBase.spriteBatch.GraphicsDevice.RenderState.DestinationBlend;

                    for (int m = 0; m < spriteListCount; m++)
                    {
                        pSprite s = spriteList[m];
                        lock (s)
                        {
                            if (s == null)
                            {
                                if (firstNull)
                                {
                                    BanchoClient.SendRequest(RequestType.Osu_ErrorReport,
                                                             new bString(ConfigManager.sUsername + " Got a null"));
                                }
                                firstNull = false;
                                spriteList.Remove(s);
                                spriteListCount--;
                                m--;
                                continue;
                            }

                            int time = GetSpriteTime(s);

                            bool drawThis = s.AlwaysDraw;
                            bool hasFutureTransformations = false;
                            bool hasPastTransformations   = false;

                            bool horizontalFlip = false;
                            bool verticalFlip   = false;

                            bool hasRotation = false;
                            bool hasScale    = false;
                            bool hasFade     = false;
                            bool hasMovement = false;
                            bool hasColour   = false;

                            bool vectorScaleActive = false;

                            int indexAfter = -1;

                            int transformationCount = s.Transformations.Count;

                            for (int i = 0; i < transformationCount; i++)
                            {
                                Transformation t = s.Transformations[i];
                                if (t == null)
                                {
                                    throw new ArgumentNullException("Transformation", "transformation t was null " + s.Text);
                                }

                                if (t.Time1 > time && indexAfter == -1)
                                {
                                    hasFutureTransformations = true;
                                    indexAfter = i;
                                }
                                else if (t.Time2 <= time)
                                {
                                    hasPastTransformations = true;
                                }

                                //first check for active transformations
                                if (t.Time1 > time || t.Time2 < time)
                                {
                                    continue;
                                }

                                drawThis = true;

                                switch (t.Type)
                                {
                                case TransformationType.Fade:
                                    if (!hasFade)
                                    {
                                        double amount =
                                            tweenValues(t.StartFloat, t.EndFloat, time, t.Time1, t.Time2, t.Easing);
                                        s.CurrentColour =
                                            new Color(s.CurrentColour.R, s.CurrentColour.G, s.CurrentColour.B,
                                                      (byte)(amount * 255));

                                        hasFade = true;
                                    }
                                    break;

                                case TransformationType.Movement:
                                    if (!hasMovement)
                                    {
                                        s.CurrentPosition =
                                            tweenValues(t.StartVector, t.EndVector, time, t.Time1, t.Time2, t.Easing);
                                        if (s.TrackRotation)
                                        {
                                            Vector2 sub = t.EndVector - t.StartVector;
                                            s.CurrentRotation = (float)Math.Atan2(sub.Y, sub.X);
                                            if (s.Reverse)
                                            {
                                                s.CurrentRotation -= (float)Math.PI;
                                            }
                                        }
                                        hasMovement = true;
                                    }
                                    break;

                                case TransformationType.Scale:
                                    if (!hasScale)
                                    {
                                        s.CurrentScale =
                                            tweenValues(t.StartFloat, t.EndFloat, time, t.Time1, t.Time2, t.Easing);
                                        hasScale = true;
                                    }
                                    break;

                                case TransformationType.VectorScale:
                                    if (!hasScale)
                                    {
                                        s.VectorScale =
                                            tweenValues(t.StartVector, t.EndVector, time, t.Time1, t.Time2, t.Easing);
                                        vectorScaleActive = true;
                                        hasScale          = true;
                                    }
                                    break;

                                case TransformationType.Rotation:
                                    if (!hasRotation)
                                    {
                                        s.CurrentRotation =
                                            tweenValues(t.StartFloat, t.EndFloat, time, t.Time1, t.Time2, t.Easing);
                                        hasRotation = true;
                                    }
                                    break;

                                case TransformationType.Colour:
                                    if (!hasColour)
                                    {
                                        s.StartColour =
                                            tweenValues(t.StartColour, t.EndColour, time, t.Time1, t.Time2, t.Easing);
                                        hasColour = true;
                                    }
                                    break;

                                case TransformationType.ParameterFlipHorizonal:
                                    if (!horizontalFlip)
                                    {
                                        horizontalFlip = true;
                                    }
                                    else if (t.Type == TransformationType.ParameterFlipVertical)
                                    {
                                        if (!verticalFlip)
                                        {
                                            verticalFlip = true;
                                        }
                                    }
                                    break;
                                }
                            }

                            if ((hasFutureTransformations && hasPastTransformations) || drawThis)
                            {
                                //past
                                for (int i = transformationCount - 1; i >= 0; i--)
                                {
                                    if (s.Transformations[i].Time2 >= time)
                                    {
                                        continue;
                                    }

                                    Transformation t = s.Transformations[i];

                                    drawThis = true;

                                    switch (t.Type)
                                    {
                                    case TransformationType.Fade:
                                        if (!hasFade)
                                        {
                                            double amount = t.EndFloat;
                                            s.CurrentColour =
                                                new Color(s.CurrentColour.R, s.CurrentColour.G, s.CurrentColour.B,
                                                          (byte)(amount * 255));
                                            hasFade = true;
                                        }
                                        break;

                                    case TransformationType.Movement:
                                        if (!hasMovement)
                                        {
                                            s.CurrentPosition = t.EndVector;
                                            hasMovement       = true;
                                        }
                                        break;

                                    case TransformationType.Scale:
                                        if (!hasScale)
                                        {
                                            s.CurrentScale = t.EndFloat;
                                            hasScale       = true;
                                        }
                                        break;

                                    case TransformationType.VectorScale:
                                        if (!hasScale)
                                        {
                                            s.VectorScale     = t.EndVector;
                                            vectorScaleActive = true;
                                            hasScale          = true;
                                        }
                                        break;

                                    case TransformationType.Rotation:
                                        if (!hasRotation)
                                        {
                                            s.CurrentRotation = t.EndFloat;
                                            hasRotation       = true;
                                        }
                                        break;

                                    case TransformationType.Colour:
                                        if (!hasColour)
                                        {
                                            s.StartColour = t.EndColour;
                                            hasColour     = true;
                                        }
                                        break;
                                    }

                                    if (s.Clock == ClockTypes.Game && !t.Loop && s.AlwaysDraw)
                                    {
                                        s.Transformations.RemoveAt(i);
                                        transformationCount--;
                                    }
                                }

                                if (!(hasFutureTransformations && s.Clock == ClockTypes.Game))
                                {
                                    for (int i = 0; i < transformationCount; i++)
                                    {
                                        if (s.Transformations[i].Time1 < time)
                                        {
                                            continue;
                                        }

                                        Transformation t = s.Transformations[i];

                                        switch (t.Type)
                                        {
                                        case TransformationType.Fade:
                                            if (!hasFade)
                                            {
                                                double amount = t.StartFloat;
                                                s.CurrentColour =
                                                    new Color(s.CurrentColour.R, s.CurrentColour.G, s.CurrentColour.B,
                                                              (byte)(amount * 255));
                                                hasFade = true;
                                            }
                                            break;

                                        case TransformationType.Movement:
                                            if (!hasMovement)
                                            {
                                                s.CurrentPosition = t.StartVector;
                                                hasMovement       = true;
                                            }
                                            break;

                                        case TransformationType.Scale:
                                            if (!hasScale)
                                            {
                                                s.CurrentScale = t.StartFloat;
                                                hasScale       = true;
                                            }
                                            break;

                                        case TransformationType.VectorScale:
                                            if (!hasScale)
                                            {
                                                s.VectorScale     = t.StartVector;
                                                vectorScaleActive = true;
                                                hasScale          = true;
                                            }
                                            break;

                                        case TransformationType.Rotation:
                                            if (!hasRotation)
                                            {
                                                s.CurrentRotation = t.StartFloat;
                                                hasRotation       = true;
                                            }
                                            break;

                                        case TransformationType.Colour:
                                            if (!hasColour)
                                            {
                                                s.StartColour = t.StartColour;
                                                hasColour     = true;
                                            }
                                            break;
                                        }
                                    }
                                }

                                //Handle looping transformations.
                                if (!hasFutureTransformations && hasPastTransformations && s.IsLoopable)
                                {
                                    s.Transformations.Sort();
                                    List <Transformation> trloop = s.Transformations.FindAll(t => t.Time2 <= time && t.Loop);
                                    foreach (Transformation tr in trloop)
                                    {
                                        int diff = tr.Time2 - tr.Time1;
                                        tr.Time1 = time;
                                        tr.Time2 = time + diff;
                                    }
                                }

                                byte alpha = (byte)(s.CurrentColour.A * Alpha);

                                //Calculate current position and scale.

                                if ((s.Type == SpriteTypes.Text || s.Type == SpriteTypes.SpriteText ||
                                     ((AllowNativeTextCaching || OriginTypes.TopLeft != s.OriginType) &&
                                      s.Type == SpriteTypes.NativeText)) && s.textChanged)
                                {
                                    s.MeasureText();
                                }

                                Vector2 currentPos = s.CurrentPosition;
                                Vector2 origin     = s.OriginPosition;
                                float   scale      = s.CurrentScale;

                                if (s.Type == SpriteTypes.Text || s.Type == SpriteTypes.NativeText ||
                                    s.Type == SpriteTypes.SpriteText)
                                {
                                    switch (s.OriginType)
                                    {
                                    case OriginTypes.Centre:
                                        origin += s.lastMeasure * 0.5F;
                                        break;

                                    case OriginTypes.TopRight:
                                        origin += new Vector2(s.lastMeasure.X, 0);
                                        break;

                                    case OriginTypes.BottomCentre:
                                        origin += new Vector2(s.lastMeasure.X / 2, s.lastMeasure.Y);
                                        break;
                                    }

                                    if (s.ExactCoordinates)
                                    {
                                        origin.X = (int)origin.X;
                                        origin.Y = (int)origin.Y;
                                    }
                                }
                                else if (s.Type == SpriteTypes.Text && s.OriginType == OriginTypes.CentreLeft)
                                {
                                    origin = new Vector2(s.OriginPosition.X, s.lastMeasure.Y * 0.5F);
                                }

                                if (Masking && !s.ViewOffsetImmune)
                                {
                                    currentPos -= ViewOffset;
                                }

                                switch (s.Field)
                                {
                                case FieldTypes.WindowScaleOnly:
                                    scale = scale * GameBase.WindowRatioInverse;
                                    break;

                                case FieldTypes.Window:
                                    scale         = scale * GameBase.WindowRatioInverse;
                                    currentPos    = currentPos * GameBase.WindowRatio;
                                    currentPos.Y += GameBase.WindowVOffset;
                                    break;

                                case FieldTypes.WindowNone:
                                    currentPos    = currentPos * GameBase.WindowRatio;
                                    currentPos.Y += GameBase.WindowVOffset;
                                    break;

                                case FieldTypes.WindowNoneExact:
                                    currentPos    = currentPos * GameBase.WindowRatio;
                                    currentPos.Y += GameBase.WindowVOffset;
                                    break;

                                case FieldTypes.WindowGamefieldRatio:
                                    scale      = scale * GameBase.WindowRatio * GameBase.GamefieldRatioWindowIndependent;
                                    currentPos = GameBase.WindowRatio * currentPos;
                                    break;

                                case FieldTypes.Gamefield:
                                    scale = scale * HitObjectManager.SpriteRatio;
                                    GameBase.GamefieldToDisplay(ref currentPos);
                                    break;

                                case FieldTypes.GamefieldRatio:
                                    /*int offy =
                                     *  (int)
                                     *  ((GameBase.WindowDefaultHeight -
                                     *    (GameBase.WindowDefaultHeight*GameBase.GamefieldRatioWindowIndependent))/8*2);*/
                                    currentPos    = currentPos * GameBase.WindowRatio * GameBase.GamefieldSize;
                                    currentPos.X += GameBase.WindowWidth * ((1 - GameBase.GamefieldSize) * 0.5f);
                                    currentPos.Y += GameBase.WindowHeight * ((1 - GameBase.GamefieldSize) * 0.75f) +
                                                    GameBase.WindowVOffset;
                                    scale = scale * GameBase.GamefieldRatio;
                                    break;
                                }

                                if (s.ExactCoordinates)
                                {
                                    currentPos.X = (int)Math.Round(currentPos.X);
                                    currentPos.Y = (int)Math.Round(currentPos.Y);
                                }

                                if (drawThis && alpha > 0)
                                {
                                    if (s.Type == SpriteTypes.Text || s.Type == SpriteTypes.NativeText ||
                                        s.Type == SpriteTypes.SpriteText)
                                    {
                                        s.DrawWidth  = (int)Math.Round(s.lastMeasure.X);
                                        s.DrawHeight = (int)Math.Round(s.lastMeasure.Y);
                                    }

                                    Rectangle srcRect = new Rectangle(s.DrawLeft, s.DrawTop, s.DrawWidth, s.DrawHeight);

                                    //todo: remove this?
                                    s.CurrentPositionScaled = currentPos;

                                    Vector2 scaleVector = (s.UseVectorScale || vectorScaleActive
                                                               ? s.VectorScale * scale
                                                               : new Vector2(scale, scale));

                                    if (Masking)
                                    {
                                        currentPos.X += ViewRectangleScaled.X + 1;
                                        currentPos.Y += ViewRectangleScaled.Y + 1 - GameBase.WindowVOffset;
                                    }

                                    float scaledPosX = currentPos.X - (origin.X * scaleVector.X);
                                    float scaledPosY = currentPos.Y - (origin.Y * scaleVector.Y);

                                    if (Masking)
                                    {
                                        int rightExcess =
                                            (int)((scaledPosX + s.DrawWidth * scaleVector.X) - ViewRectangleScaled.Right);
                                        if (rightExcess > 0)
                                        {
                                            srcRect.Width -= rightExcess;
                                        }

                                        int bottomExcess =
                                            (int)((scaledPosY + s.DrawHeight * scaleVector.Y) - ViewRectangleScaled.Bottom);
                                        if (bottomExcess > 0)
                                        {
                                            if (srcRect.Height > 1)
                                            {
                                                srcRect.Height -= (int)(bottomExcess * 1F / scaleVector.Y);
                                            }
                                            else
                                            {
                                                scaleVector.Y -= bottomExcess;
                                            }
                                        }

                                        int topExcess = (int)(ViewRectangleScaled.Top - (scaledPosY));
                                        if (topExcess > 0)
                                        {
                                            if (srcRect.Height > 1)
                                            {
                                                srcRect.Y      += (int)(topExcess * 1F / scaleVector.Y);
                                                srcRect.Height -= (int)(topExcess * 1F / scaleVector.Y);
                                            }
                                            else
                                            {
                                                scaleVector.Y -= topExcess;
                                            }
                                            currentPos.Y += topExcess;
                                            scaledPosY   += topExcess;
                                        }
                                    }

                                    //todo: this doesn't reflect the displayRectangle
                                    s.Rectangle =
                                        new Rectangle((int)Math.Round(scaledPosX),
                                                      (int)Math.Round(scaledPosY),
                                                      (int)Math.Round(srcRect.Width * scaleVector.X),
                                                      (int)Math.Round(srcRect.Height * scaleVector.Y));

                                    if (((!UniversalFocusCaught && !IgnoreHover && !UniversalIgnoreHover) ||
                                         s.CatchUniversal) &&
                                        (s.IsClickable || s.IsClickRepeatable))
                                    {
                                        if ((!hoverFound || s.HoverPriority < hoverIndex) &&
                                            ((!s.Circular && s.Rectangle.Contains(MouseHandler.MousePoint)) ||
                                             (s.Circular &&
                                              Vector2.Distance(MouseHandler.MousePosition, s.CurrentPositionScaled) <
                                              (s.Radius * GameBase.WindowRatio) / 2)) && mouseInWindow)
                                        {
                                            if (hoverSprite != null)
                                            {
                                                hoverSprite.Hovering = false;
                                            }

                                            hoverFound = true;

                                            hoverSprite = s;
                                            hoverIndex  = s.HoverPriority;

                                            if (s.CatchUniversal)
                                            {
                                                UniversalFocusCaught = true;
                                            }
                                        }
                                        else if (s.Hovering)
                                        {
                                            s.Hovering = false;
                                        }
                                    }


                                    if (!s.Rectangle.Intersects(ViewRectangleScaled) ||
                                        (Masking && !ViewRectangleScaled.Intersects(s.Rectangle)))
                                    {
                                        s.IsVisible = false;
                                    }
                                    else
                                    {
                                        s.IsVisible = true;

                                        Color drawColour = s.CurrentColour;

                                        //late updating of colour to save on constructors
                                        if (Alpha != 100 || Blackness != 0 || hasColour)
                                        {
                                            byte blackByte =
                                                (byte)(MathHelper.Clamp(s.DimImmune ? 0 : Blackness, 0, 1) * 255);

                                            s.CurrentColour =
                                                new Color(s.StartColour.R, s.StartColour.G, s.StartColour.B,
                                                          s.CurrentColour.A);

                                            drawColour =
                                                new Color((byte)Math.Max(0, s.StartColour.R - blackByte),
                                                          (byte)Math.Max(0, s.StartColour.G - blackByte),
                                                          (byte)Math.Max(0, s.StartColour.B - blackByte), alpha);
                                        }


                                        GameBase.spriteBatch.GraphicsDevice.RenderState.DestinationBlend = s.Additive ? Blend.One : defaultBlend;

                                        //draw the actual sprite
                                        if (s.Type != SpriteTypes.Text && s.Type != SpriteTypes.SpriteText)
                                        {
                                            if (s.Texture != null && !s.Texture.IsDisposed)
                                            {
                                                GameBase.spriteBatch.Draw(s.Texture, currentPos,
                                                                          srcRect,
                                                                          drawColour, s.CurrentRotation, origin,
                                                                          scaleVector,
                                                                          s.SpriteEffect |
                                                                          (horizontalFlip
                                                                               ? SpriteEffects.FlipHorizontally
                                                                               : SpriteEffects.None) |
                                                                          (verticalFlip
                                                                               ? SpriteEffects.FlipVertically
                                                                               : SpriteEffects.None), 0);
                                            }
                                        }
                                        else if (!string.IsNullOrEmpty(s.Text))
                                        {
                                            //SpriteText rendering
                                            pSpriteText st = s as pSpriteText;
                                            for (int i = 0; i < st.renderCoordinates.Count; i++)
                                            {
                                                GameBase.spriteBatch.Draw(st.renderTextures[i],
                                                                          new Vector2(
                                                                              st.renderCoordinates[i].X * scale +
                                                                              scaledPosX,
                                                                              scaledPosY), null,
                                                                          drawColour, s.CurrentRotation, Vector2.Zero,
                                                                          scaleVector, s.SpriteEffect,
                                                                          s.Depth + i * 0.00001f);
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    s.IsVisible = false;
                                }
                            }
                            else
                            {
                                s.IsVisible = false;
                            }

                            if (!hasFutureTransformations && !drawThis)
                            {
                                if (!s.AlwaysDraw && (s.Clock == ClockTypes.Game || ForwardPlayOptimisations))
                                {
                                    spriteList.RemoveAt(m--);
                                    spriteListCount--;
                                    s.Dispose(s.Disposable);
                                }
                            }
                        }
                    }
                    GameBase.spriteBatch.End();
                }
                catch
                {
                    GameBase.spriteBatch.Dispose();
                    GameBase.spriteBatch = new SpriteBatch(GameBase.graphics.GraphicsDevice);
                }

                if (hoverSprite != null)
                {
                    if (hoverSprite.ToolTip != null)
                    {
                        GameBase.toolTipping  = true;
                        GameBase.toolTip.Text = hoverSprite.ToolTip;
                    }
                    if (!hoverSprite.Hovering)
                    {
                        hoverSprite.Hovering = true;
                    }
                }
            }
        }