Exemplo n.º 1
0
        public void FillOval(
            float centerX, float centerY, float centerZ, float radiusX, float radiusY,
            TVertexParameters parameters, int edges)
        {
            if (edges < 3)
            {
                throw new ArgumentOutOfRangeException(nameof(edges), "Must draw at least three edges.");
            }

            meshBuilder.Add(edges, (edges - 2) * 3, out var vertices, out var indices, out var indexOffset);

            var rotation = Matrix2.CreateRotation(MathHelper.TwoPi / edges);

            var xy = new Vector2(0, -1);

            vertices[0] = createVertex(new Vector3(
                                           centerX + xy.X * radiusX, centerY + xy.Y * radiusY, centerZ), parameters);

            for (var i = 1; i < edges; i++)
            {
                xy = rotation * xy;

                vertices[i] = createVertex(new Vector3(
                                               centerX + xy.X * radiusX, centerY + xy.Y * radiusY, centerZ), parameters);
            }

            for (var i = 0; i < edges - 2; i++)
            {
                var o = i * 3;
                indices[o++] = indexOffset;
                indices[o++] = (ushort)(indexOffset + i + 1);
                indices[o]   = (ushort)(indexOffset + i + 2);
            }
        }
Exemplo n.º 2
0
        public void SetTransform(float SX, float SY, float Rotate, float TX, float TY)
        {
            EnsureInitialized();

            Matrix2 Transform;

            Transform  = Matrix2.CreateScale(SX, SY);
            Transform *= Matrix2.CreateRotation(Rotate);

            Vector2 Offs = new Vector2(TX, TY);

            int CurrentProgram = GL.GetInteger(GetPName.CurrentProgram);

            GL.UseProgram(Shader.Handle);

            int TransformUniformLocation = GL.GetUniformLocation(Shader.Handle, "transform");

            GL.UniformMatrix2(TransformUniformLocation, false, ref Transform);

            int OffsetUniformLocation = GL.GetUniformLocation(Shader.Handle, "offset");

            GL.Uniform2(OffsetUniformLocation, ref Offs);

            GL.UseProgram(CurrentProgram);
        }
Exemplo n.º 3
0
        public Polygon(string Scene, ushort Corners) : base(Scene)
        {
            if (Corners < 3)
            {
                Logger.Log(new LogMessage(LogSeverity.Warning, $"I was told to create a polygon with {Corners} corners. What do I do with this?"));
                return;
            }

            List <Vector2> _verts = new();

            // FIXME: Half circle
            for (float i = 0; i < 360; i += 360f / Corners)
            {
                Matrix2.CreateRotation(i, out var _rot);
                _verts.Add(new Vector2(-1, 1) * _rot);
            }
            transform.Vertices = _verts.ToArray();
            transform.UV       = _verts.ToArray();

            List <Vector3i> _indices = new();

            for (int i = 1; i <= Corners; i++)
            {
                _indices.Add(new Vector3i(0, i, i + 1));
            }
            transform.Indices = new uint[Corners * 3];
            _indices.ForEach(x => {
                for (int i = 0; i < 3; i++)
                {
                    transform.Indices[_indices.IndexOf(x) * 3 + i] = (uint)x[i];
                }
            }
                             );
        }
Exemplo n.º 4
0
        /// <summary>
        /// Draws a filled oval.
        /// </summary>
        /// <param name="centerX">The center X.</param>
        /// <param name="centerY">The center Y.</param>
        /// <param name="centerZ">The center Z.</param>
        /// <param name="halfWidth">Half of the width.</param>
        /// <param name="halfHeight">Half of the height.</param>
        /// <param name="edges">The number of edges to draw the oval width.</param>
        private void drawOvalFilled(float centerX, float centerY, float centerZ, float halfWidth, float halfHeight, int edges)
        {
            var vertices = new PrimitiveVertexData[edges];

            Matrix2 rotation = Matrix2.CreateRotation(MathHelper.TwoPi / edges);

            Vector2 xy = new Vector2(0, -1);

            Color argb = this.Color;

            vertices[0] = new PrimitiveVertexData(
                centerX + xy.X * halfWidth, centerY + xy.Y * halfHeight, centerZ, argb);

            for (int i = 1; i < edges; i++)
            {
                xy = rotation.Times(xy);

                vertices[i] = new PrimitiveVertexData(
                    centerX + xy.X * halfWidth, centerY + xy.Y * halfHeight, centerZ, argb);
            }

            ushort offset = this.surface.AddVertices(vertices);

            var ids = new ushort[(edges - 2) * 3];

            for (int i = 0; i < edges - 2; i++)
            {
                int o = i * 3;
                ids[o++] = offset;
                ids[o++] = (ushort)(offset + i + 1);
                ids[o]   = (ushort)(offset + i + 2);
            }

            this.surface.AddIndices(ids);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Draws an unfilled oval.
        /// </summary>
        /// <param name="centerX">The center X.</param>
        /// <param name="centerY">The center Y.</param>
        /// <param name="centerZ">The center Z.</param>
        /// <param name="halfWidth">Half of the width.</param>
        /// <param name="halfHeight">Half of the height.</param>
        /// <param name="edges">The number of edges to draw the oval width.</param>
        private void drawOvalUnfilled(float centerX, float centerY, float centerZ, float halfWidth, float halfHeight, int edges)
        {
            var vertices = new PrimitiveVertexData[edges * 2];

            Matrix2 rotation = Matrix2.CreateRotation(MathHelper.TwoPi / edges);

            Vector2 xy = new Vector2(0, -1);

            Color argb = this.Color;

            float innerW = halfWidth - this.LineWidth;
            float innerH = halfHeight - this.LineWidth;

            vertices[0] = new PrimitiveVertexData(
                centerX + xy.X * halfWidth, centerY + xy.Y * halfHeight, centerZ, argb);

            vertices[1] = new PrimitiveVertexData(
                centerX + xy.X * innerW, centerY + xy.Y * innerH, centerZ, argb);

            for (int i = 1; i < edges; i++)
            {
                xy = rotation.Times(xy);

                vertices[2 * i] = new PrimitiveVertexData(
                    centerX + xy.X * halfWidth, centerY + xy.Y * halfHeight, centerZ, argb);

                vertices[2 * i + 1] = new PrimitiveVertexData(
                    centerX + xy.X * innerW, centerY + xy.Y * innerH, centerZ, argb);
            }

            ushort offset = this.surface.AddVertices(vertices);

            var ids = new ushort[edges * 6];

            for (int i = 0; i < edges - 1; i++)
            {
                int j = i * 6;
                int o = i * 2;
                ids[j]     = (ushort)(offset + o);
                ids[j + 1] = (ushort)(offset + o + 2);
                ids[j + 2] = (ushort)(offset + o + 1);

                ids[j + 3] = (ushort)(offset + o + 1);
                ids[j + 4] = (ushort)(offset + o + 2);
                ids[j + 5] = (ushort)(offset + o + 3);
            }

            int lastJ = edges * 6 - 6;

            ids[lastJ]     = (ushort)(offset + edges * 2 - 2);
            ids[lastJ + 1] = (ushort)(offset);
            ids[lastJ + 2] = (ushort)(offset + edges * 2 - 1);

            ids[lastJ + 3] = (ushort)(offset + edges * 2 - 1);
            ids[lastJ + 4] = (ushort)(offset);
            ids[lastJ + 5] = (ushort)(offset + 1);

            this.surface.AddIndices(ids);
        }
Exemplo n.º 6
0
        public void DrawOval(
            float centerX, float centerY, float centerZ, float radiusX, float radiusY,
            float lineWidth, TVertexParameters parameters, int edges)
        {
            if (edges < 3)
            {
                throw new ArgumentOutOfRangeException(nameof(edges), "Must draw at least three edges.");
            }

            meshBuilder.Add(edges * 2, edges * 6, out var vertices, out var indices, out var indexOffset);

            var rotation = Matrix2.CreateRotation(MathHelper.TwoPi / edges);

            var xy = new Vector2(0, -1);

            var innerW = radiusX - lineWidth;
            var innerH = radiusY - lineWidth;

            vertices[0] = createVertex(new Vector3(
                                           centerX + xy.X * radiusX, centerY + xy.Y * radiusY, centerZ), parameters);

            vertices[1] = createVertex(new Vector3(
                                           centerX + xy.X * innerW, centerY + xy.Y * innerH, centerZ), parameters);

            for (var i = 1; i < edges; i++)
            {
                xy = rotation * xy;

                vertices[2 * i] = createVertex(new Vector3(
                                                   centerX + xy.X * radiusX, centerY + xy.Y * radiusY, centerZ), parameters);

                vertices[2 * i + 1] = createVertex(new Vector3(
                                                       centerX + xy.X * innerW, centerY + xy.Y * innerH, centerZ), parameters);
            }

            for (var i = 0; i < edges - 1; i++)
            {
                var j = i * 6;
                var o = i * 2;
                indices[j]     = (ushort)(indexOffset + o);
                indices[j + 1] = (ushort)(indexOffset + o + 2);
                indices[j + 2] = (ushort)(indexOffset + o + 1);

                indices[j + 3] = (ushort)(indexOffset + o + 1);
                indices[j + 4] = (ushort)(indexOffset + o + 2);
                indices[j + 5] = (ushort)(indexOffset + o + 3);
            }

            var lastJ = edges * 6 - 6;

            indices[lastJ]     = (ushort)(indexOffset + edges * 2 - 2);
            indices[lastJ + 1] = indexOffset;
            indices[lastJ + 2] = (ushort)(indexOffset + edges * 2 - 1);

            indices[lastJ + 3] = (ushort)(indexOffset + edges * 2 - 1);
            indices[lastJ + 4] = indexOffset;
            indices[lastJ + 5] = (ushort)(indexOffset + 1);
        }
Exemplo n.º 7
0
        public void GetRotatedCorners(Vector2 rotationCenter, float angle, out Vector2 topLeft, out Vector2 topRight, out Vector2 bottomLeft, out Vector2 bottomRight)
        {
            Matrix2 rotationMatrix = Matrix2.CreateRotation(angle);

            topLeft     = (new Vector2(Left, Top) - rotationCenter) * rotationMatrix + rotationCenter;
            topRight    = (new Vector2(Right, Top) - rotationCenter) * rotationMatrix + rotationCenter;
            bottomLeft  = (new Vector2(Left, Bottom) - rotationCenter) * rotationMatrix + rotationCenter;
            bottomRight = (new Vector2(Right, Bottom) - rotationCenter) * rotationMatrix + rotationCenter;
        }
Exemplo n.º 8
0
        /// <summary>
        /// Rotates the four corners of the <see cref="UVRectangle"/> by a given angle around a given point.
        /// </summary>
        /// <param name="angle">The angle by which to rotate</param>
        /// <param name="center">The point around which to rotate</param>
        public void Rotate(float angle, Vector2 center)
        {
            Matrix2 m = Matrix2.CreateRotation(angle);

            this.TopLeft     = center + m.Times(this.TopLeft - center);
            this.TopRight    = center + m.Times(this.TopRight - center);
            this.BottomLeft  = center + m.Times(this.BottomLeft - center);
            this.BottomRight = center + m.Times(this.BottomRight - center);
        }
Exemplo n.º 9
0
        public void SetFrameBufferTransform(float SX, float SY, float Rotate, float TX, float TY)
        {
            Matrix2 Transform;

            Transform  = Matrix2.CreateScale(SX, SY);
            Transform *= Matrix2.CreateRotation(Rotate);

            Vector2 Offs = new Vector2(TX, TY);

            ActionsQueue.Enqueue(() => FrameBuffer.SetTransform(Transform, Offs));
        }
Exemplo n.º 10
0
        public bool ContainsRotated(Vector2 pt, Vector2 rotationCenter, float angle)
        {
            if (angle == 0)
            {
                return(Contains(pt));
            }

            Matrix2 rotationMatrix = Matrix2.CreateRotation(-angle);
            Vector2 rotatedPt      = (pt - rotationCenter) * rotationMatrix + rotationCenter;

            return(Contains(rotatedPt.X, rotatedPt.Y));
        }
Exemplo n.º 11
0
        public void MatrixCreateRotation()
        {
            Matrix2 rot0deg   = new Matrix2(1, 0, 0, 1);
            Matrix2 rot90deg  = new Matrix2(0, -1, 1, 0);
            Matrix2 rot180deg = new Matrix2(-1, 0, 0, -1);
            Matrix2 rot270deg = new Matrix2(0, 1, -1, 0);

            CompareMatrices(Matrix2.CreateRotation((float)Math.PI * 0.0f), rot0deg, 10e-7f);
            CompareMatrices(Matrix2.CreateRotation((float)Math.PI * 0.5f), rot90deg, 10e-7f);
            CompareMatrices(Matrix2.CreateRotation((float)Math.PI * 1.0f), rot180deg, 10e-7f);
            CompareMatrices(Matrix2.CreateRotation((float)Math.PI * 1.5f), rot270deg, 10e-7f);
            CompareMatrices(Matrix2.CreateRotation((float)Math.PI * 2.0f), rot0deg, 10e-7f);
        }
Exemplo n.º 12
0
        private Line RotateLine(Line stick, float rotationAngle)
        {
            var     mtxRotation = Matrix2.CreateRotation(rotationAngle);
            Vector2 a;

            a.X = Vector2.Dot(mtxRotation.Column0, stick.Item1);
            a.Y = Vector2.Dot(mtxRotation.Column1, stick.Item1);
            Vector2 b;

            b.X = Vector2.Dot(mtxRotation.Column0, stick.Item2);
            b.Y = Vector2.Dot(mtxRotation.Column1, stick.Item2);
            return(new Line(a, b));
        }
Exemplo n.º 13
0
        public static Vector2 GetRotatedVector(Vector2 vector, float angle, bool clockwise)
        {
            if (clockwise)
            {
                angle *= -1;
            }

            Matrix2 rotationMatrix = Matrix2.CreateRotation(angle);

            float x = rotationMatrix.M11 * vector.X + rotationMatrix.M12 * vector.Y;
            float y = rotationMatrix.M21 * vector.X + rotationMatrix.M22 * vector.Y;

            return(new Vector2(x, y));
        }
Exemplo n.º 14
0
        protected override void OnBeforeUpdaters(object sender, EventArgs e)
        {
            _eyeInput.Update();
            _moveInput.Update();

            _eye.Rotation += _eyeInput.Value.Xy;
            var tmp = Matrix2.CreateRotation(MathHelper.DegreesToRadians(_eye.Rotation.X)) * new Vector2(_moveInput.Value.X, -_moveInput.Value.Z);

            _playerObject.Velocity = new Vector3d(tmp.X, Math.Min(5D, _playerObject.Velocity.Y + _moveInput.BaseInput.Value.Y * .25), -tmp.Y);

            PlayerMovement();
            Title = _playerObject.Velocity.ToString();

            base.OnBeforeUpdaters(sender, e);
        }
Exemplo n.º 15
0
        public unsafe void SetFrameBuffer(
            byte *Fb,
            int Width,
            int Height,
            float ScaleX,
            float ScaleY,
            float Rotate)
        {
            Matrix2 Transform;

            Transform  = Matrix2.CreateScale(ScaleX, ScaleY);
            Transform *= Matrix2.CreateRotation(Rotate);

            FbRenderer.Set(Fb, Width, Height, Transform);
        }
Exemplo n.º 16
0
        private void UpdateChildRotation()
        {
            //delta from previous frame to current frame
            float deltaAngle = Parent.Rotation - previousParentRotation;

            //Change Rotation
            this.Rotation += deltaAngle;

            //Change Position
            Matrix2 newRotation = Matrix2.CreateRotation(-deltaAngle);

            LocalPosition = newRotation.PerVector2(LocalPosition);
            this.position = Parent.position + LocalPosition;

            //save prev parent rot
            previousParentRotation = Parent.Rotation;
        }
Exemplo n.º 17
0
        public RelevantPoint GetRelevantObjects(RelevantPoint point1, RelevantPoint point2)
        {
            // Any point can be the origin
            if (MySettings.OriginInputPredicate.Check(point1, this) &&
                MySettings.OtherInputPredicate.Check(point2, this))
            {
                return(new RelevantPoint(Matrix2.Mult(Matrix2.CreateRotation(MathHelper.DegreesToRadians(MySettings.Angle)), point2.Child - point1.Child) * MySettings.Scalar + point1.Child));
            }

            if (MySettings.OriginInputPredicate.Check(point2, this) &&
                MySettings.OtherInputPredicate.Check(point1, this))
            {
                return(new RelevantPoint(Matrix2.Mult(Matrix2.CreateRotation(MathHelper.DegreesToRadians(MySettings.Angle)), point1.Child - point2.Child) * MySettings.Scalar + point2.Child));
            }

            return(null);
        }
Exemplo n.º 18
0
        public override void DrawSprite(Vector3 position, float angle, float scale)
        {
            Vector2 expand1 = new Vector2(expandX, expandY) * scale;
            Vector2 expand2 = new Vector2(-expand1.X, expand1.Y);

            if (angle != 0)
            {
                Matrix2 rotation = Matrix2.CreateRotation(angle);
                expand1 = rotation.Times(expand1);
                expand2 = rotation.Times(expand2);
            }

            this.Surface.AddQuad(
                new SimpleSpriteVertexData(position, this.UV.TopLeft, this.Color, expand2),
                new SimpleSpriteVertexData(position, this.UV.TopRight, this.Color, expand1),
                new SimpleSpriteVertexData(position, this.UV.BottomRight, this.Color, -expand2),
                new SimpleSpriteVertexData(position, this.UV.BottomLeft, this.Color, -expand1)
                );
        }
Exemplo n.º 19
0
        public Obj3DText(string txt, TextPlane plane, float size, float posX, float posY, float posZ, float dirAngle, string color, Texture fontTex)
        {
            Matrix2 rotMat = Matrix2.CreateRotation(MathHelper.DegreesToRadians(dirAngle));

            float [] verts = new float[txt.Length * 4 * 5];
            uint []  inds  = new uint[txt.Length * 6];
            int      vp    = 0;
            int      ip    = 0;

            for (int i = 0; i < txt.Length; i++)
            {
                char ch  = txt[i];
                uint svp = (uint)vp;                                                           // save first index
                // top left
                Vector3 v3p = GetTranslatedPoint(posX, posY, posZ, size, i, 0, rotMat, plane); // 3d vector
                Vector2 vtp = GetTextureCorner(ch, 0, 0);                                      // texture vector
                SetVertex(verts, vp++, v3p, vtp);
                // top right
                v3p = GetTranslatedPoint(posX, posY, posZ, size, i + 1, 0, rotMat, plane); // 3d vector
                vtp = GetTextureCorner(ch, 1, 0);                                          // texture vector
                SetVertex(verts, vp++, v3p, vtp);
                // bootom left
                v3p = GetTranslatedPoint(posX, posY, posZ, size, i, -1, rotMat, plane); // 3d vector
                vtp = GetTextureCorner(ch, 0, 1);                                       // texture vector
                SetVertex(verts, vp++, v3p, vtp);
                // bootom right
                v3p = GetTranslatedPoint(posX, posY, posZ, size, i + 1, -1, rotMat, plane); // 3d vector
                vtp = GetTextureCorner(ch, 1, 1);                                           // texture vector
                SetVertex(verts, vp++, v3p, vtp);

                // indexes, 2 triangles
                inds[ip++] = svp;
                inds[ip++] = svp + 2;
                inds[ip++] = svp + 1;
                inds[ip++] = svp + 2;
                inds[ip++] = svp + 3;
                inds[ip++] = svp + 1;
            }
            Init(Shader.ShadingType.Textured3D, verts, inds, fontTex);
            SetColor(color);
        }
Exemplo n.º 20
0
        private static List <Vector2> MakePenis(List <Vector2> points, double sliderLength)
        {
            // Penis shape
            List <Vector2> newPoints = new List <Vector2>
            {
                new(0, 0),
                new(40, -40),
                new(0, -70),
                new(-40, -40),
                new(0, 0),
                new(0, 0),
                new(96, 24),
                new(168, 0),
                new(168, 0),
                new(96, -24),
                new(0, 0),
                new(0, 0),
                new(-40, 40),
                new(0, 70),
                new(40, 40),
                new(0, 0)
            };

            double sizeMultiplier = sliderLength / 591 * 2;  // 591 is the size of the dick
            double normalAngle    = -(points.Last() - points.First()).Theta;
            var    mat            = Matrix2.CreateRotation(normalAngle);

            mat *= sizeMultiplier;

            for (var i = 0; i < newPoints.Count; i++)
            {
                Vector2 point = newPoints[i];
                // transform to slider
                Vector2 transformPoint = Matrix2.Mult(mat, point);
                newPoints[i] = points.First() + transformPoint;
            }

            return(newPoints);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Draws a sprite.
        /// </summary>
        /// <param name="position">The coordinates to draw the sprite at. The sprite is drawn centered around this point.</param>
        /// <param name="angle">The angle to rotate the sprite by, around the z axis, in radians.</param>
        /// <param name="scale">An additional scalar to scale the sprite by, relative to <see cref="Size"/>.</param>
        public override void DrawSprite(Vector3 position, float angle, float scale)
        {
            float   x           = this.expandX * scale;
            float   y           = this.expandY * scale;
            Vector2 topLeft     = new Vector2(-x, -y);
            Vector2 topRight    = new Vector2(x, -y);
            Vector2 bottomLeft  = new Vector2(-x, y);
            Vector2 bottomRight = new Vector2(x, y);

            if (angle != 0)
            {
                Matrix2 rotation = Matrix2.CreateRotation(angle);
                topLeft     = rotation.Times(topLeft);
                topRight    = rotation.Times(topRight);
                bottomLeft  = rotation.Times(bottomLeft);
                bottomRight = rotation.Times(bottomRight);
            }
            this.Surface.AddQuad(
                new UVColorVertexData(position.X + topLeft.X, position.Y + topLeft.Y, position.Z, this.UV.TopLeft, this.Color),
                new UVColorVertexData(position.X + topRight.X, position.Y + topRight.Y, position.Z, this.UV.TopRight, this.Color),
                new UVColorVertexData(position.X + bottomRight.X, position.Y + bottomRight.Y, position.Z, this.UV.BottomRight, this.Color),
                new UVColorVertexData(position.X + bottomLeft.X, position.Y + bottomLeft.Y, position.Z, this.UV.BottomLeft, this.Color)
                );
        }
Exemplo n.º 22
0
        public void Recalculate()
        {
            if (this.localAngleChanged)
            {
                this.rotationLocal     = Matrix2.CreateRotation(this.parameters.Angle) * this.parameters.Scale;
                this.localAngleChanged = false;
            }

            if (this.parent == null)
            {
                this.angleGlobal    = this.parameters.Angle;
                this.offsetGlobal   = this.parameters.Offset;
                this.rotationGlobal = this.rotationLocal;
                this.scaleGlobal    = this.parameters.Scale;
            }
            else
            {
                var t = parent.Transformation;
                this.angleGlobal    = t.angleGlobal + this.parameters.Angle;
                this.offsetGlobal   = t.offsetGlobal + t.rotationGlobal.Times(this.parameters.Offset);
                this.rotationGlobal = t.rotationGlobal * this.rotationLocal;
                this.scaleGlobal    = t.ScaleGlobal * this.parameters.Scale;
            }
        }
Exemplo n.º 23
0
        /// <summary>
        /// Does a procedure similar to <see cref="MapCleaner"/> which adjusts the pattern so it fits in the beatmap.
        /// It does so according to the options selected in this.
        /// </summary>
        /// <param name="patternBeatmap"></param>
        /// <param name="beatmap"></param>
        /// <param name="parts"></param>
        /// <param name="timingPointsChanges"></param>
        private void PreparePattern(Beatmap patternBeatmap, Beatmap beatmap, out List <Part> parts, out List <TimingPointsChange> timingPointsChanges)
        {
            double patternStartTime = patternBeatmap.GetHitObjectStartTime();

            Timing originalTiming = beatmap.BeatmapTiming;
            Timing patternTiming  = patternBeatmap.BeatmapTiming;

            GameMode targetMode = (GameMode)beatmap.General["Mode"].IntValue;

            double originalCircleSize = beatmap.Difficulty["CircleSize"].DoubleValue;
            double patternCircleSize  = patternBeatmap.Difficulty["CircleSize"].DoubleValue;

            double originalTickRate = beatmap.Difficulty["SliderTickRate"].DoubleValue;
            double patternTickRate  = patternBeatmap.Difficulty["SliderTickRate"].DoubleValue;

            // Don't include SV changes if it is based on nothing
            bool includePatternSliderVelocity = patternTiming.Count > 0;

            // Avoid including hitsounds if there are no timingpoints to get hitsounds from
            bool includeTimingPointHitsounds = IncludeHitsounds && patternTiming.Count > 0;

            // Don't scale to new timing if the pattern has no timing to speak of
            bool scaleToNewTiming = ScaleToNewTiming && patternTiming.Redlines.Count > 0;

            // Avoid overwriting timing if the pattern has no redlines
            TimingOverwriteMode timingOverwriteMode = patternTiming.Redlines.Count > 0
                ? TimingOverwriteMode
                : TimingOverwriteMode.OriginalTimingOnly;

            // Get the scale for custom scale x CS scale
            double csScale = Beatmap.GetHitObjectRadius(originalCircleSize) /
                             Beatmap.GetHitObjectRadius(patternCircleSize);
            double spatialScale = ScaleToNewCircleSize && !double.IsNaN(csScale) ? CustomScale * csScale : CustomScale;

            // Get a BPM multiplier to fix the tick rate
            // This multiplier is not meant to change SV so this is subtracted from the greenline SV later
            double bpmMultiplier = FixTickRate ? patternTickRate / originalTickRate : 1;

            // Dont give new combo to all hit objects which were actually new combo in the pattern,
            // because it leads to unexpected NC's at the start of patterns.

            // Collect Kiai toggles
            List <TimingPoint> kiaiToggles = new List <TimingPoint>();
            bool lastKiai = false;

            // If not including the kiai of the pattern, add the kiai of the original map.
            // This has to be done because this part of the original map might get deleted.
            foreach (TimingPoint tp in IncludeKiai ? patternTiming.TimingPoints : originalTiming.TimingPoints)
            {
                if (tp.Kiai != lastKiai || kiaiToggles.Count == 0)
                {
                    kiaiToggles.Add(tp.Copy());
                    lastKiai = tp.Kiai;
                }
            }

            // Collect SliderVelocity changes for mania/taiko
            List <TimingPoint> svChanges = new List <TimingPoint>();
            double             lastSV    = -100;

            // If not including the SV of the pattern, add the SV of the original map.
            // This has to be done because this part of the original map might get deleted.
            foreach (TimingPoint tp in includePatternSliderVelocity ? patternTiming.TimingPoints : originalTiming.TimingPoints)
            {
                if (tp.Uninherited)
                {
                    lastSV = -100;
                }
                else
                {
                    if (Math.Abs(tp.MpB - lastSV) > Precision.DOUBLE_EPSILON)
                    {
                        svChanges.Add(tp.Copy());
                        lastSV = tp.MpB;
                    }
                }
            }

            // If not including the SV of the pattern, set the SV of sliders to that of the original beatmap,
            // so the pattern will take over the SV of the original beatmap.
            if (!includePatternSliderVelocity)
            {
                foreach (var ho in patternBeatmap.HitObjects.Where(ho => ho.IsSlider))
                {
                    ho.SliderVelocity = originalTiming.GetSvAtTime(ho.Time);
                }
            }

            // Get the timeline before moving all objects so it has the correct hitsounds
            // Make sure that moving the objects in the pattern moves the timeline objects aswell
            // This method is NOT safe to use in beat time
            Timeline patternTimeline         = patternBeatmap.GetTimeline();
            Timing   transformOriginalTiming = originalTiming;
            Timing   transformPatternTiming  = patternTiming;

            if (scaleToNewTiming)
            {
                // Transform everything to beat time relative to pattern start time
                foreach (var ho in patternBeatmap.HitObjects)
                {
                    double oldEndTime = ho.GetEndTime(false);

                    ho.Time    = patternTiming.GetBeatLength(patternStartTime, ho.Time);
                    ho.EndTime = patternTiming.GetBeatLength(patternStartTime, oldEndTime);

                    // The body hitsounds are not copies of timingpoints in patternTiming so they should be copied before changing offset
                    for (int i = 0; i < ho.BodyHitsounds.Count; i++)
                    {
                        TimingPoint tp = ho.BodyHitsounds[i].Copy();
                        tp.Offset           = patternTiming.GetBeatLength(patternStartTime, tp.Offset);
                        ho.BodyHitsounds[i] = tp;
                    }
                }

                foreach (var tp in kiaiToggles.Concat(svChanges))
                {
                    tp.Offset = patternTiming.GetBeatLength(patternStartTime, tp.Offset);
                }

                // Transform the pattern redlines to beat time
                // This will not change the order of redlines (unless negative BPM exists)
                transformPatternTiming = patternTiming.Copy();
                foreach (var tp in transformPatternTiming.Redlines)
                {
                    tp.Offset = patternTiming.GetBeatLength(patternStartTime, tp.Offset);
                }

                // Transform the original timingpoints to beat time
                // This will not change the order of timingpoints (unless negative BPM exists)
                transformOriginalTiming = originalTiming.Copy();
                foreach (var tp in transformOriginalTiming.TimingPoints)
                {
                    tp.Offset = originalTiming.GetBeatLength(patternStartTime, tp.Offset);
                }
            }

            // Fix SV for the new global SV
            var globalSvFactor = transformOriginalTiming.SliderMultiplier / transformPatternTiming.SliderMultiplier;

            if (FixGlobalSv)
            {
                foreach (HitObject ho in patternBeatmap.HitObjects.Where(o => o.IsSlider))
                {
                    ho.SliderVelocity *= globalSvFactor;
                }
                foreach (TimingPoint tp in svChanges)
                {
                    tp.MpB *= globalSvFactor;
                }
            }
            else
            {
                foreach (HitObject ho in patternBeatmap.HitObjects.Where(o => o.IsSlider))
                {
                    ho.TemporalLength /= globalSvFactor;
                }
            }

            // Partition the pattern based on the timing in the pattern
            if (PatternOverwriteMode == PatternOverwriteMode.PartitionedOverwrite)
            {
                parts = PartitionBeatmap(patternBeatmap, scaleToNewTiming);
            }
            else
            {
                parts = new List <Part> {
                    new Part(patternBeatmap.HitObjects[0].Time,
                             patternBeatmap.HitObjects[patternBeatmap.HitObjects.Count - 1].Time,
                             patternBeatmap.HitObjects)
                };
            }

            // Construct a new timing which is a mix of the beatmap and the pattern.
            // If scaleToNewTiming then use beat relative values to determine the duration of timing sections in the pattern.
            // scaleToNewTiming must scale all the partitions, timingpoints, hitobjects, and events (if applicable).
            Timing newTiming = new Timing(transformOriginalTiming.SliderMultiplier);

            var lastEndTime = double.NegativeInfinity;

            foreach (var part in parts)
            {
                var startTime = part.StartTime;
                var endTime   = part.EndTime; // Subtract one to omit BPM changes right on the end of the part.

                // Add the redlines in between patterns
                newTiming.AddRange(transformOriginalTiming.GetRedlinesInRange(lastEndTime, startTime, false));

                var startOriginalRedline = transformOriginalTiming.GetRedlineAtTime(startTime);

                // Minus 1 the offset so its possible to have a custom BPM redline right on the start time if you have
                // the default BPM redline before it.
                var patternDefaultMpb = transformPatternTiming.GetMpBAtTime(startTime - 2 * Precision.DOUBLE_EPSILON);

                TimingPoint[] inPartRedlines;
                TimingPoint   startPartRedline;
                switch (timingOverwriteMode)
                {
                case TimingOverwriteMode.PatternTimingOnly:
                    // Subtract one from the end time to omit BPM changes right on the end of the part.
                    inPartRedlines = transformPatternTiming.GetRedlinesInRange(startTime,
                                                                               Math.Max(startTime, endTime - 2 * Precision.DOUBLE_EPSILON)).ToArray();
                    startPartRedline = transformPatternTiming.GetRedlineAtTime(startTime);
                    break;

                case TimingOverwriteMode.InPatternAbsoluteTiming:
                    var tempInPartRedlines = transformPatternTiming.GetRedlinesInRange(startTime, endTime - 2 * Precision.DOUBLE_EPSILON);

                    // Replace all parts in the pattern which have the default BPM to timing from the target beatmap.
                    inPartRedlines = tempInPartRedlines.Select(tp => {
                        if (Precision.AlmostEquals(tp.MpB, patternDefaultMpb))
                        {
                            var tp2    = transformOriginalTiming.GetRedlineAtTime(tp.Offset).Copy();
                            tp2.Offset = tp2.Offset;
                            return(tp2);
                        }

                        return(tp);
                    }).ToArray();

                    startPartRedline = startOriginalRedline;
                    break;

                case TimingOverwriteMode.InPatternRelativeTiming:
                    // Multiply mix the pattern timing and the original timing together.
                    // The pattern timing divided by the default BPM will be used as a scalar for the original timing.
                    var tempInPartRedlines2    = transformPatternTiming.GetRedlinesInRange(startTime, endTime - 2 * Precision.DOUBLE_EPSILON);
                    var tempInOriginalRedlines = transformOriginalTiming.GetRedlinesInRange(startTime, endTime - 2 * Precision.DOUBLE_EPSILON);

                    // Replace all parts in the pattern which have the default BPM to timing from the target beatmap.
                    inPartRedlines = tempInPartRedlines2.Select(tp => {
                        var tp2  = tp.Copy();
                        tp2.MpB *= transformOriginalTiming.GetMpBAtTime(tp.Offset) / patternDefaultMpb;
                        return(tp2);
                    }).Concat(tempInOriginalRedlines.Select(tp => {
                        var tp2  = tp.Copy();
                        tp2.MpB *= transformPatternTiming.GetMpBAtTime(tp.Offset) / patternDefaultMpb;
                        return(tp2);
                    })).ToArray();

                    startPartRedline      = transformPatternTiming.GetRedlineAtTime(startTime).Copy();
                    startPartRedline.MpB *= transformOriginalTiming.GetMpBAtTime(startTime) / patternDefaultMpb;
                    break;

                default:      // Original timing only
                    // Subtract one from the end time to omit BPM changes right on the end of the part.
                    inPartRedlines = transformOriginalTiming.GetRedlinesInRange(startTime,
                                                                                Math.Max(startTime, endTime - 2 * Precision.DOUBLE_EPSILON)).ToArray();
                    startPartRedline = transformOriginalTiming.GetRedlineAtTime(startTime);
                    break;
                }

                // Add the redlines for inside the part
                newTiming.AddRange(inPartRedlines);

                // If the pattern starts with different BPM than the map add an extra redline at the start of the pattern
                // to make sure it the pattern starts out at the right BPM as we only copy the timingpoints during the pattern itself
                // and the redline may be way before that.
                // This will probably only do something on the PatternTimingOnly mode as the other modes make sure
                // the BPM at the start of the pattern will be the same as the original beatmap anyways.
                if (Math.Abs(startPartRedline.MpB * bpmMultiplier - startOriginalRedline.MpB) > Precision.DOUBLE_EPSILON)
                {
                    // We dont have to add the redline again if its already during the pattern.
                    if (Math.Abs(startPartRedline.Offset - startTime) > Precision.DOUBLE_EPSILON)
                    {
                        var copy = startPartRedline.Copy();
                        copy.Offset = startTime;
                        newTiming.Add(copy);
                    }
                }

                // Fix SV for the new BPM, so the SV effect of the new BPM is cancelled
                if (FixBpmSv)
                {
                    if (scaleToNewTiming)
                    {
                        foreach (HitObject ho in patternBeatmap.HitObjects.Where(o => o.IsSlider))
                        {
                            var bpmSvFactor = SnapToNewTiming ?
                                              transformPatternTiming.GetMpBAtTime(ho.Time) /
                                              newTiming.GetMpBAtTime(newTiming.ResnapBeatTime(ho.Time, BeatDivisors)) :
                                              transformPatternTiming.GetMpBAtTime(ho.Time) /
                                              newTiming.GetMpBAtTime(ho.Time);
                            ho.SliderVelocity *= bpmSvFactor;
                        }
                    }
                    else
                    {
                        foreach (HitObject ho in patternBeatmap.HitObjects.Where(o => o.IsSlider))
                        {
                            var bpmSvFactor = SnapToNewTiming ?
                                              transformPatternTiming.GetMpBAtTime(ho.Time) / newTiming.GetMpBAtTime(newTiming.Resnap(ho.Time, BeatDivisors)) :
                                              transformPatternTiming.GetMpBAtTime(ho.Time) / newTiming.GetMpBAtTime(ho.Time);
                            ho.SliderVelocity *= bpmSvFactor;
                        }
                    }
                }

                // Recalculate temporal length and re-assign redline for the sliderend resnapping later
                foreach (var ho in part.HitObjects)
                {
                    ho.UnInheritedTimingPoint = newTiming.GetRedlineAtTime(ho.Time);
                    if (ho.IsSlider)
                    {
                        // If scaleToNewTiming then the end time is already at the correct beat time
                        // The SV has to be adjusted so the sliderend is really on the end time
                        if (scaleToNewTiming)
                        {
                            var wantedMsDuration = (newTiming.GetMilliseconds(ho.GetEndTime(false), patternStartTime) -
                                                    newTiming.GetMilliseconds(ho.Time, patternStartTime)) / ho.Repeat;
                            var trueMsDuration = newTiming.CalculateSliderTemporalLength(SnapToNewTiming ? newTiming.ResnapBeatTime(ho.Time, BeatDivisors) : ho.Time, ho.PixelLength, ho.SliderVelocity);
                            ho.SliderVelocity /= trueMsDuration / wantedMsDuration;
                        }
                        else
                        {
                            ho.TemporalLength = newTiming.CalculateSliderTemporalLength(SnapToNewTiming ? newTiming.Resnap(ho.Time, BeatDivisors) : ho.Time, ho.PixelLength, ho.SliderVelocity);
                        }
                    }
                }

                // Update the end time because the lengths of sliders changed
                endTime      = part.HitObjects.Max(o => o.GetEndTime(!scaleToNewTiming));
                part.EndTime = endTime;

                // Add a redline at the end of the pattern to make sure the BPM goes back to normal after the pattern.
                var endOriginalRedline = transformOriginalTiming.GetRedlineAtTime(endTime);
                var endPartRedline     = inPartRedlines.LastOrDefault() ?? startPartRedline;
                if (Math.Abs(endPartRedline.MpB * bpmMultiplier - endOriginalRedline.MpB) > Precision.DOUBLE_EPSILON)
                {
                    // We dont have to add the redline again if its already during the parts in between parts.
                    if (Math.Abs(endOriginalRedline.Offset - endTime) > Precision.DOUBLE_EPSILON)
                    {
                        var copy = endOriginalRedline.Copy();
                        copy.Offset = endTime;
                        newTiming.Add(copy);
                    }
                }

                lastEndTime = endTime;
            }

            // Transform the beat time back to millisecond time
            Timing transformNewTiming = newTiming;

            if (scaleToNewTiming)
            {
                // Transform back the timing
                transformNewTiming = newTiming.Copy();
                foreach (var tp in transformNewTiming.TimingPoints)
                {
                    tp.Offset = Math.Floor(newTiming.GetMilliseconds(tp.Offset, patternStartTime) + Precision.DOUBLE_EPSILON);
                }

                // Transform back the parts
                foreach (Part part in parts)
                {
                    part.StartTime = Math.Floor(newTiming.GetMilliseconds(part.StartTime, patternStartTime));
                    part.EndTime   = Math.Floor(newTiming.GetMilliseconds(part.EndTime, patternStartTime));
                }

                // Transform everything to millisecond time relative to pattern start time
                foreach (var ho in patternBeatmap.HitObjects)
                {
                    // Calculate the millisecond end time before changing the start time because the end time getter uses the beat time start time
                    var msEndTime = newTiming.GetMilliseconds(ho.GetEndTime(false), patternStartTime);

                    ho.Time = newTiming.GetMilliseconds(ho.Time, patternStartTime);

                    // End time has to be set after the time because the end time setter uses the millisecond start time
                    ho.EndTime = msEndTime;

                    foreach (var tp in ho.BodyHitsounds)
                    {
                        tp.Offset = newTiming.GetMilliseconds(tp.Offset, patternStartTime);
                    }

                    // It is necessary to resnap early so it can recalculate the duration using the right offset
                    if (SnapToNewTiming)
                    {
                        ho.ResnapSelf(transformNewTiming, BeatDivisors);
                    }

                    if (ho.IsSlider)
                    {
                        ho.CalculateSliderTemporalLength(transformNewTiming, true);
                    }

                    ho.UnInheritedTimingPoint = transformNewTiming.GetRedlineAtTime(ho.Time);
                    ho.UpdateTimelineObjectTimes();
                }

                foreach (var tp in kiaiToggles.Concat(svChanges))
                {
                    tp.Offset = Math.Floor(newTiming.GetMilliseconds(tp.Offset, patternStartTime));
                }
            }

            // Apply custom scale and rotate
            if (Math.Abs(spatialScale - 1) > Precision.DOUBLE_EPSILON ||
                Math.Abs(CustomRotate) > Precision.DOUBLE_EPSILON)
            {
                // Create a transformation matrix for the custom scale and rotate
                // The rotation is inverted because the default osu! rotation goes clockwise
                Matrix2 transform = Matrix2.Mult(Matrix2.CreateScale(spatialScale), Matrix2.CreateRotation(-CustomRotate));
                Vector2 centre    = new Vector2(256, 192);
                foreach (var ho in patternBeatmap.HitObjects)
                {
                    ho.Move(-centre);
                    ho.Transform(transform);
                    ho.Move(centre);

                    // Scale pixel length and SV for sliders aswell
                    if (ho.IsSlider)
                    {
                        ho.PixelLength    *= spatialScale;
                        ho.SliderVelocity /= spatialScale;
                    }
                }

                // osu! clips coordinates to the bounds (0,512), so there is some space downwards to still place the pattern
                // Calculate the new bounds of the pattern and try to place it in the playfield
                var     minX   = patternBeatmap.HitObjects.Min(o => o.Pos.X);
                var     minY   = patternBeatmap.HitObjects.Min(o => o.Pos.Y);
                Vector2 offset = new Vector2(Math.Max(-minX, 0), Math.Max(-minY, 0));
                if (offset.LengthSquared > 0)
                {
                    foreach (var ho in patternBeatmap.HitObjects)
                    {
                        ho.Move(offset);
                    }
                }
            }

            // Manualify stacks
            if (FixStackLeniency)
            {
                // If scale to new timing was used update the circle size of the pattern,
                // so it calculates stacks at the new size of the pattern.
                if (ScaleToNewCircleSize)
                {
                    patternBeatmap.Difficulty["CircleSize"].DoubleValue = originalCircleSize;
                }

                patternBeatmap.CalculateEndPositions();
                patternBeatmap.UpdateStacking(rounded: true);

                // Manualify by setting the base position to the stacked position
                foreach (var ho in patternBeatmap.HitObjects)
                {
                    var offset = ho.StackedPos - ho.Pos;
                    ho.Move(offset);
                }
            }

            // Resnap everything to the new timing.
            if (SnapToNewTiming)
            {
                // Resnap all objects
                foreach (HitObject ho in patternBeatmap.HitObjects)
                {
                    ho.ResnapSelf(transformNewTiming, BeatDivisors);
                    ho.ResnapEnd(transformNewTiming, BeatDivisors);
                    ho.ResnapPosition(targetMode, patternCircleSize);  // Resnap to column X positions for mania only
                }
                // Resnap Kiai toggles
                foreach (TimingPoint tp in kiaiToggles)
                {
                    tp.ResnapSelf(transformNewTiming, BeatDivisors);
                }

                // Resnap SliderVelocity changes
                foreach (TimingPoint tp in svChanges)
                {
                    tp.ResnapSelf(transformNewTiming, BeatDivisors);
                }
            }

            // Multiply BPM and divide SV
            foreach (var part in parts)
            {
                foreach (var tp in transformNewTiming.GetRedlinesInRange(part.StartTime - 2 * Precision.DOUBLE_EPSILON, part.EndTime, false))
                {
                    tp.MpB /= bpmMultiplier;  // MpB is the inverse of the BPM
                }

                foreach (var ho in part.HitObjects)
                {
                    ho.SliderVelocity *= bpmMultiplier;  // SliderVelocity is the inverse of the multiplier
                }
            }

            // Make new timingpoints changes for the hitsounds and other stuff

            // Add redlines
            timingPointsChanges = transformNewTiming.Redlines.Select(tp =>
                                                                     new TimingPointsChange(tp, mpb: true, meter: true, unInherited: true, omitFirstBarLine: true, fuzzyness: Precision.DOUBLE_EPSILON)).ToList();

            // Add SliderVelocity changes for taiko and mania
            if (includePatternSliderVelocity && (targetMode == GameMode.Taiko || targetMode == GameMode.Mania))
            {
                timingPointsChanges.AddRange(svChanges.Select(tp => new TimingPointsChange(tp, mpb: true, fuzzyness: 0.4)));
            }

            // Add Kiai toggles
            timingPointsChanges.AddRange(kiaiToggles.Select(tp => new TimingPointsChange(tp, kiai: true)));

            // Add Hitobject stuff
            foreach (HitObject ho in patternBeatmap.HitObjects)
            {
                if (ho.IsSlider) // SliderVelocity changes
                {
                    TimingPoint tp = ho.TimingPoint.Copy();
                    tp.Offset = ho.Time;
                    tp.MpB    = ho.SliderVelocity;
                    timingPointsChanges.Add(new TimingPointsChange(tp, mpb: true, fuzzyness: 0.4));
                }

                if (!IncludeHitsounds)
                {
                    // Remove hitsounds and skip adding body hitsounds
                    ho.ResetHitsounds();
                    continue;
                }

                if (includeTimingPointHitsounds)
                {
                    // Body hitsounds
                    bool vol = ho.IsSlider || ho.IsSpinner;
                    bool sam = ho.IsSlider && ho.SampleSet == 0;
                    bool ind = ho.IsSlider;
                    timingPointsChanges.AddRange(ho.BodyHitsounds.Select(tp =>
                                                                         new TimingPointsChange(tp, volume: vol, index: ind, sampleset: sam)));
                }
            }

            // Add timeline hitsounds
            if (includeTimingPointHitsounds)
            {
                foreach (TimelineObject tlo in patternTimeline.TimelineObjects)
                {
                    if (tlo.HasHitsound)
                    {
                        // Add greenlines for hitsounds
                        TimingPoint tp = tlo.HitsoundTimingPoint.Copy();
                        tp.Offset = tlo.Time;
                        timingPointsChanges.Add(new TimingPointsChange(tp, sampleset: true, volume: true, index: true));
                    }
                }
            }

            // Replace the old timingpoints
            patternTiming.Clear();
            TimingPointsChange.ApplyChanges(patternTiming, timingPointsChanges);

            patternBeatmap.GiveObjectsGreenlines();
            patternBeatmap.CalculateSliderEndTimes();
        }
Exemplo n.º 24
0
        /// <summary>
        /// Compiles all data necessary for rendering into a Vertex object
        /// </summary>
        public Vertex[] CompileData(Color4 ObjectColor, Scene Scene)
        {
            Vector2[] _coordinates       = Vertices;
            Vector2   _aspectRatioFactor = new((float)Camera.Resolution.Y / Camera.Resolution.X, 1);

            // -> Local <-
            Matrix2.CreateRotation(Rotation, out var _localRotation);
            Vector2 _localSkew     = Skew / GlobalScale;
            Vector2 _localSize     = Size / GlobalScale * new Vector2(Camera.Resolution.X / 720f);
            Vector2 _localPosition = (Position / GlobalScale) + Vector2.Divide(Anchor.Xy, _aspectRatioFactor);

            // -> Parent <-
            Matrix2.CreateRotation(ParentObject?.Rotation ?? 0, out var _parentRotation);
            Vector2 _parentSize     = ParentObject?.Size / GlobalScale ?? Vector2.One;
            Vector2 _parentPosition = ParentObject?.Position / GlobalScale ?? Vector2.Zero;

            // -> Scene <-
            Matrix2.CreateRotation(Scene.Rotation, out var _sceneRotation);
            Vector2 _sceneSize     = Scene.Scale;
            Vector2 _scenePosition = Scene.Position / GlobalScale;

            // -> Global <-
            Matrix2.CreateRotation(-Camera.Rotation, out var _globalRotation);
            Vector2 _globalSize     = Camera.Zoom;
            Vector2 _globalPosition = Camera.Position;

            // -> Local <-
            _coordinates = Array.ConvertAll(_coordinates, vec => vec + vec + _localSkew * vec.Yx);
            _coordinates = Array.ConvertAll(_coordinates, vec => vec * _localRotation);
            _coordinates = Array.ConvertAll(_coordinates, vec => vec * _localSize);
            _coordinates = Array.ConvertAll(_coordinates, vec => vec + _localPosition);

            // -> Parent <-
            _coordinates = Array.ConvertAll(_coordinates, vec => vec * _parentRotation);
            // Make this optional?
            //_coordinates = Array.ConvertAll(_coordinates, vec => vec * _parentSize);
            _coordinates = Array.ConvertAll(_coordinates, vec => vec + _parentPosition);

            // -> Scene <-
            _coordinates = Array.ConvertAll(_coordinates, vec => vec * _sceneRotation);
            _coordinates = Array.ConvertAll(_coordinates, vec => vec * _sceneSize);
            _coordinates = Array.ConvertAll(_coordinates, vec => vec + _scenePosition);

            // -> Global <-
            _coordinates = Array.ConvertAll(_coordinates, vec => vec * _globalRotation);
            _coordinates = Array.ConvertAll(_coordinates, vec => vec * _globalSize);
            _coordinates = Array.ConvertAll(_coordinates, vec => vec + _globalPosition);
            _coordinates = Array.ConvertAll(_coordinates, vec => vec * _aspectRatioFactor);

            List <Vertex> _output = new(); // New C# 9 syntax, nice!

            for (int i = 0; i < Vertices.Length; i++)
            {
                _output.Add(new Vertex {
                    Position    = _coordinates[i],
                    UV          = UV[i],
                    InnerBounds = UV[i],
                    Color       = ObjectColor
                });
            }
            return(_output.ToArray());
        }
Exemplo n.º 25
0
 public RelevantCircle GetRelevantObjects(RelevantPoint origin, RelevantCircle circle)
 {
     return(!MySettings.OriginInputPredicate.Check(origin, this) || !MySettings.OtherInputPredicate.Check(circle, this) ? null :
            new RelevantCircle(new Circle(Matrix2.Mult(Matrix2.CreateRotation(MathHelper.DegreesToRadians(MySettings.Angle)), circle.Child.Centre - origin.Child) * MySettings.Scalar + origin.Child, circle.Child.Radius * MySettings.Scalar)));
 }
Exemplo n.º 26
0
 public RelevantLine GetRelevantObjects(RelevantPoint origin, RelevantLine line)
 {
     return(!MySettings.OriginInputPredicate.Check(origin, this) || !MySettings.OtherInputPredicate.Check(line, this) ? null :
            new RelevantLine(Line2.FromPoints(Matrix2.Mult(Matrix2.CreateRotation(MathHelper.DegreesToRadians(MySettings.Angle)), line.Child.PositionVector - origin.Child) * MySettings.Scalar + origin.Child,
                                              Matrix2.Mult(Matrix2.CreateRotation(MathHelper.DegreesToRadians(MySettings.Angle)), line.Child.PositionVector + line.Child.DirectionVector - origin.Child) * MySettings.Scalar + origin.Child)));
 }