コード例 #1
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;
                    }
                }
            }
        }
コード例 #2
0
        private void HoverStart()
        {
            int time = SpriteManager.GetSpriteTime(this);

            if (HoverEffect != null)
            {
                Transformations.RemoveAll(t => t.NumericalTag == 1);

                Transformation h = HoverEffect.Clone();
                h.StartVector = CurrentPosition;
                switch (HoverEffect.Type)
                {
                case TransformationType.Fade:
                    h.StartFloat = (float)CurrentColour.A / 255;
                    break;

                case TransformationType.Scale:
                    h.StartFloat = CurrentScale;
                    break;

                case TransformationType.Rotation:
                    h.StartFloat = CurrentRotation;
                    break;
                }
                h.StartColour = StartColour;


                int duration = HoverEffect.Duration;
                h.Time1 = time;
                h.Time2 = time + duration;

                h.NumericalTag = 1;

                Transformations.Add(h);
            }
            if (HoverEffects != null)
            {
                Transformations.RemoveAll(t => t.NumericalTag == 1);
                bool first = true;
                foreach (Transformation t in HoverEffects)
                {
                    Transformation h = t.Clone();
                    if (first)
                    {
                        h.StartVector = CurrentPosition;
                        switch (h.Type)
                        {
                        case TransformationType.Fade:
                            h.StartFloat = (float)CurrentColour.A / 255;
                            break;

                        case TransformationType.Scale:
                            h.StartFloat = CurrentScale;
                            break;

                        case TransformationType.Rotation:
                            h.StartFloat = CurrentRotation;
                            break;
                        }
                        h.StartColour = StartColour;
                        first         = false;
                    }
                    h.Time1 += time;
                    h.Time2 += time;

                    h.NumericalTag = 1;

                    Transformations.Add(h);
                }
            }
        }