Ejemplo n.º 1
0
        private void moveSelectionInBounds()
        {
            var hitObjects = selectedMovableObjects;

            Quad quad = getSurroundingQuad(hitObjects);

            Vector2 delta = Vector2.Zero;

            if (quad.TopLeft.X < 0)
            {
                delta.X -= quad.TopLeft.X;
            }
            if (quad.TopLeft.Y < 0)
            {
                delta.Y -= quad.TopLeft.Y;
            }

            if (quad.BottomRight.X > DrawWidth)
            {
                delta.X -= quad.BottomRight.X - DrawWidth;
            }
            if (quad.BottomRight.Y > DrawHeight)
            {
                delta.Y -= quad.BottomRight.Y - DrawHeight;
            }

            foreach (var h in hitObjects)
            {
                h.Position += delta;
            }
        }
Ejemplo n.º 2
0
 public CrashScreenCover()
 {
     RelativeSizeAxes = Axes.Both;
     Scale            = new osuTK.Vector2(scale);
     Anchor           = Anchor.Centre;
     Origin           = Anchor.Centre;
 }
Ejemplo n.º 3
0
        private void scaleHitObjects(OsuHitObject[] hitObjects, Anchor reference, Vector2 scale)
        {
            scale = getClampedScale(hitObjects, reference, scale);

            // move the selection before scaling if dragging from top or left anchors.
            float xOffset = ((reference & Anchor.x0) > 0) ? -scale.X : 0;
            float yOffset = ((reference & Anchor.y0) > 0) ? -scale.Y : 0;

            Quad selectionQuad = getSurroundingQuad(hitObjects);

            foreach (var h in hitObjects)
            {
                var newPosition = h.Position;

                // guard against no-ops and NaN.
                if (scale.X != 0 && selectionQuad.Width > 0)
                {
                    newPosition.X = selectionQuad.TopLeft.X + xOffset + (h.X - selectionQuad.TopLeft.X) / selectionQuad.Width * (selectionQuad.Width + scale.X);
                }

                if (scale.Y != 0 && selectionQuad.Height > 0)
                {
                    newPosition.Y = selectionQuad.TopLeft.Y + yOffset + (h.Y - selectionQuad.TopLeft.Y) / selectionQuad.Height * (selectionQuad.Height + scale.Y);
                }

                h.Position = newPosition;
            }
        }
Ejemplo n.º 4
0
            public NewsCoverTest()
            {
                Spacing = new osuTK.Vector2(0, 10);

                var article = new NewsArticleCover.ArticleInfo
                {
                    Author   = "Ephemeral",
                    CoverUrl = "https://assets.ppy.sh/artists/58/header.jpg",
                    Time     = new DateTime(2019, 12, 4),
                    Title    = "New Featured Artist: Kurokotei"
                };

                Children = new Drawable[]
                {
                    new NewsArticleCover(article)
                    {
                        Height = 200
                    },
                    new NewsArticleCover(article)
                    {
                        Height = 120
                    },
                    new NewsArticleCover(article)
                    {
                        RelativeSizeAxes = Axes.None,
                        Size             = new osuTK.Vector2(400, 200),
                    }
                };
            }
Ejemplo n.º 5
0
        public static void DrawCircleImage(SKCanvas canvas, osuTK.Vector2 pos, float r, SKBitmap bitmap, byte alpha = 255)
        {
            // Scale bitmap (warning: inefficient)
            var imgPos       = new SKPoint(pos.X - r + offsetX, pos.Y - r + offsetY);
            var scaledBitmap = bitmap.Resize(new SKImageInfo((int)(r * 2), (int)(r * 2)), SKFilterQuality.High);

            canvas.DrawBitmap(scaledBitmap, imgPos, new SKPaint()
            {
                Color = new SKColor(0, 0, 0, alpha)
            });
        }
Ejemplo n.º 6
0
        public override bool HandleReverse()
        {
            var hitObjects = EditorBeatmap.SelectedHitObjects;

            double endTime   = hitObjects.Max(h => h.GetEndTime());
            double startTime = hitObjects.Min(h => h.StartTime);

            bool moreThanOneObject = hitObjects.Count > 1;

            foreach (var h in hitObjects)
            {
                if (moreThanOneObject)
                {
                    h.StartTime = endTime - (h.GetEndTime() - startTime);
                }

                if (h is Slider slider)
                {
                    var     points = slider.Path.ControlPoints.ToArray();
                    Vector2 endPos = points.Last().Position.Value;

                    slider.Path.ControlPoints.Clear();

                    slider.Position += endPos;

                    PathType?lastType = null;

                    for (var i = 0; i < points.Length; i++)
                    {
                        var p = points[i];
                        p.Position.Value -= endPos;

                        // propagate types forwards to last null type
                        if (i == points.Length - 1)
                        {
                            p.Type.Value = lastType;
                        }
                        else if (p.Type.Value != null)
                        {
                            var newType = p.Type.Value;
                            p.Type.Value = lastType;
                            lastType     = newType;
                        }

                        slider.Path.ControlPoints.Insert(0, p);
                    }
                }
            }

            return(true);
        }
Ejemplo n.º 7
0
        private void scaleSlider(Slider slider, Vector2 scale)
        {
            referencePathTypes ??= slider.Path.ControlPoints.Select(p => p.Type.Value).ToList();

            Quad sliderQuad = GetSurroundingQuad(slider.Path.ControlPoints.Select(p => p.Position.Value));

            // Limit minimum distance between control points after scaling to almost 0. Less than 0 causes the slider to flip, exactly 0 causes a crash through division by 0.
            scale = Vector2.ComponentMax(new Vector2(Precision.FLOAT_EPSILON), sliderQuad.Size + scale) - sliderQuad.Size;

            Vector2 pathRelativeDeltaScale = new Vector2(
                sliderQuad.Width == 0 ? 0 : 1 + scale.X / sliderQuad.Width,
                sliderQuad.Height == 0 ? 0 : 1 + scale.Y / sliderQuad.Height);

            Queue <Vector2> oldControlPoints = new Queue <Vector2>();

            foreach (var point in slider.Path.ControlPoints)
            {
                oldControlPoints.Enqueue(point.Position.Value);
                point.Position.Value *= pathRelativeDeltaScale;
            }

            // Maintain the path types in case they were defaulted to bezier at some point during scaling
            for (int i = 0; i < slider.Path.ControlPoints.Count; ++i)
            {
                slider.Path.ControlPoints[i].Type.Value = referencePathTypes[i];
            }

            //if sliderhead or sliderend end up outside playfield, revert scaling.
            Quad scaledQuad = getSurroundingQuad(new OsuHitObject[] { slider });

            (bool xInBounds, bool yInBounds) = isQuadInBounds(scaledQuad);

            if (xInBounds && yInBounds && slider.Path.HasValidLength)
            {
                return;
            }

            foreach (var point in slider.Path.ControlPoints)
            {
                point.Position.Value = oldControlPoints.Dequeue();
            }
        }
Ejemplo n.º 8
0
        public override bool HandleScale(Vector2 scale, Anchor reference)
        {
            adjustScaleFromAnchor(ref scale, reference);

            var hitObjects = selectedMovableObjects;

            // for the time being, allow resizing of slider paths only if the slider is
            // the only hit object selected. with a group selection, it's likely the user
            // is not looking to change the duration of the slider but expand the whole pattern.
            if (hitObjects.Length == 1 && hitObjects.First() is Slider slider)
            {
                scaleSlider(slider, scale);
            }
            else
            {
                scaleHitObjects(hitObjects, reference, scale);
            }

            moveSelectionInBounds();
            return(true);
        }
Ejemplo n.º 9
0
        private static void adjustScaleFromAnchor(ref Vector2 scale, Anchor reference)
        {
            // cancel out scale in axes we don't care about (based on which drag handle was used).
            if ((reference & Anchor.x1) > 0)
            {
                scale.X = 0;
            }
            if ((reference & Anchor.y1) > 0)
            {
                scale.Y = 0;
            }

            // reverse the scale direction if dragging from top or left.
            if ((reference & Anchor.x0) > 0)
            {
                scale.X = -scale.X;
            }
            if ((reference & Anchor.y0) > 0)
            {
                scale.Y = -scale.Y;
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Clamp scale for multi-object-scaling where selection does not exceed playfield bounds or flip.
        /// </summary>
        /// <param name="hitObjects">The hitobjects to be scaled</param>
        /// <param name="reference">The anchor from which the scale operation is performed</param>
        /// <param name="scale">The scale to be clamped</param>
        /// <returns>The clamped scale vector</returns>
        private Vector2 getClampedScale(OsuHitObject[] hitObjects, Anchor reference, Vector2 scale)
        {
            float xOffset = ((reference & Anchor.x0) > 0) ? -scale.X : 0;
            float yOffset = ((reference & Anchor.y0) > 0) ? -scale.Y : 0;

            Quad selectionQuad = getSurroundingQuad(hitObjects);

            //todo: this is not always correct for selections involving sliders. This approximation assumes each point is scaled independently, but sliderends move with the sliderhead.
            Quad scaledQuad = new Quad(selectionQuad.TopLeft.X + xOffset, selectionQuad.TopLeft.Y + yOffset, selectionQuad.Width + scale.X, selectionQuad.Height + scale.Y);

            //max Size -> playfield bounds
            if (scaledQuad.TopLeft.X < 0)
            {
                scale.X += scaledQuad.TopLeft.X;
            }
            if (scaledQuad.TopLeft.Y < 0)
            {
                scale.Y += scaledQuad.TopLeft.Y;
            }

            if (scaledQuad.BottomRight.X > DrawWidth)
            {
                scale.X -= scaledQuad.BottomRight.X - DrawWidth;
            }
            if (scaledQuad.BottomRight.Y > DrawHeight)
            {
                scale.Y -= scaledQuad.BottomRight.Y - DrawHeight;
            }

            //min Size -> almost 0. Less than 0 causes the quad to flip, exactly 0 causes scaling to get stuck at minimum scale.
            Vector2 scaledSize = selectionQuad.Size + scale;
            Vector2 minSize    = new Vector2(Precision.FLOAT_EPSILON);

            scale = Vector2.ComponentMax(minSize, scaledSize) - selectionQuad.Size;

            return(scale);
        }
Ejemplo n.º 11
0
 public static SNVector2 ToSystemNumerics(this TKVector2 vec) =>
 new SNVector2(vec.X, vec.Y);