예제 #1
0
        public void Matrix32()
        {
            string fs =
                @"#version 330

                  uniform mat3x2 exampleMat32;
                  out vec3 FragColor;

                  void main()
                  {
                      FragColor = vec3(exampleMat32[1].x, exampleMat32[2].x, 0.0);
                  }";

            using (GraphicsWindow window = Device.CreateWindow(1, 1))
                using (Framebuffer framebuffer = TestUtility.CreateFramebuffer(window.Context))
                    using (ShaderProgram sp = Device.CreateShaderProgram(ShaderSources.PassThroughVertexShader(), fs))
                        using (VertexArray va = TestUtility.CreateVertexArray(window.Context, sp.VertexAttributes["position"].Location))
                        {
                            Matrix32 <float> m32 = new Matrix32 <float>(
                                0.0f, 1.0f, 1.0f,
                                0.0f, 0.0f, 0.0f);
                            Uniform <Matrix32 <float> > exampleMat32 = (Uniform <Matrix32 <float> >)sp.Uniforms["exampleMat32"];
                            Assert.AreEqual("exampleMat32", exampleMat32.Name);
                            Assert.AreEqual(UniformType.FloatMatrix32, exampleMat32.Datatype);
                            Assert.AreEqual(new Matrix32 <float>(), exampleMat32.Value);
                            exampleMat32.Value = m32;
                            Assert.AreEqual(m32, exampleMat32.Value);

                            window.Context.Framebuffer = framebuffer;
                            window.Context.Draw(PrimitiveType.Points, 0, 1, new DrawState(TestUtility.CreateRenderStateWithoutDepthTest(), sp, va), new SceneState());
                            TestUtility.ValidateColor(framebuffer.ColorAttachments[0], 255, 255, 0);
                        }
        }
예제 #2
0
        void RescaleWidgets(Quadrangle originalHull, bool hullInFirstWidgetSpace, Vector2 hullsPivotPoint, List <Widget> widgets, int controlPointIndex,
                            Vector2 curMousePos, Vector2 prevMousePos, bool proportional)
        {
            Utils.ApplyTransformationToWidgetsGroupOobb(
                sv.Scene,
                widgets, hullsPivotPoint, hullInFirstWidgetSpace, curMousePos, prevMousePos,
                (originalVectorInOobbSpace, deformedVectorInOobbSpace) => {
                Vector2 deformationScaleInOobbSpace =
                    new Vector2(
                        Math.Abs(originalVectorInOobbSpace.X) < Mathf.ZeroTolerance
                                                                        ? 1
                                                                        : deformedVectorInOobbSpace.X / originalVectorInOobbSpace.X,
                        Math.Abs(originalVectorInOobbSpace.Y) < Mathf.ZeroTolerance
                                                                        ? 1
                                                                        : deformedVectorInOobbSpace.Y / originalVectorInOobbSpace.Y
                        );
                if (proportional)
                {
                    deformationScaleInOobbSpace.X = (deformationScaleInOobbSpace.X + deformationScaleInOobbSpace.Y) / 2;
                    deformationScaleInOobbSpace.Y = deformationScaleInOobbSpace.X;
                }

                if (!LookupInvolvedAxes[controlPointIndex][0])
                {
                    deformationScaleInOobbSpace.X = proportional ? deformationScaleInOobbSpace.Y : 1;
                }
                if (!LookupInvolvedAxes[controlPointIndex][1])
                {
                    deformationScaleInOobbSpace.Y = proportional ? deformationScaleInOobbSpace.X : 1;
                }

                return(Matrix32.Scaling(deformationScaleInOobbSpace));
            }
                );
        }
예제 #3
0
        void RescaleHelper(List <PointObject> points, int controlPointIndex, bool proportional, bool centerProportional)
        {
            var t = sv.Scene.CalcTransitionToSpaceOf(Document.Current.Container.AsWidget);

            t.T = Vector2.Zero;
            var     transformedMouseDelta = (sv.MousePosition - initialMousePosition) * t / Document.Current.Container.AsWidget.Size;
            Vector2 origin;
            var     idx   = (controlPointIndex + 4) % 8 / 2;
            var     next  = (idx + 1) % 4;
            var     prev  = (idx + 3) % 4;
            var     axisX = hullNormalized[next] - hullNormalized[idx];
            var     axisY = hullNormalized[prev] - hullNormalized[idx];

            if (controlPointIndex == 7 || controlPointIndex == 3 || controlPointIndex == 1 || controlPointIndex == 5)
            {
                origin = (hullNormalized[next] + hullNormalized[idx]) / 2;
            }
            else
            {
                origin = hullNormalized[idx];
            }
            axisX.Snap(Vector2.Zero);
            axisY.Snap(Vector2.Zero);
            if (axisX == Vector2.Zero)
            {
                axisX = new Vector2(-axisY.Y, axisY.X);
            }
            if (axisY == Vector2.Zero)
            {
                axisY = new Vector2(-axisX.Y, axisX.X);
            }
            var basis         = new Matrix32(axisX, axisY, centerProportional ? (hullNormalized.V1 + hullNormalized.V3) / 2 : origin);
            var basisInversed = basis.CalcInversed();
            var deltaSize     = basisInversed * transformedMouseDelta - Vector2.Zero * basisInversed;

            deltaSize = (deltaSize * (controlPointIndex % 2 == 0 ? Vector2.One : Vector2.Down)).Snap(Vector2.Zero);
            if (deltaSize == Vector2.Zero)
            {
                return;
            }
            var avSize = 0.5f * (deltaSize.X + deltaSize.Y);

            if (proportional)
            {
                if (controlPointIndex == 7 || controlPointIndex == 3 || controlPointIndex == 1 || controlPointIndex == 5)
                {
                    deltaSize.X = deltaSize.Y;
                }
                else
                {
                    deltaSize.X = avSize;
                    deltaSize.Y = avSize;
                }
            }
            for (var i = 0; i < points.Count; i++)
            {
                var deltaPos = basisInversed * points[i].Position * deltaSize * basis - Vector2.Zero * basis;
                Core.Operations.SetAnimableProperty.Perform(points[i], nameof(PointObject.Position), points[i].Position + deltaPos, CoreUserPreferences.Instance.AutoKeyframes);
            }
        }
예제 #4
0
 private static void BakeSkinningTransform(SkinningWeights newSkinningWeights, Node node)
 {
     if (node is PointObject)
     {
         var point                  = (PointObject)node;
         var originTranslation      = point.TransformedPosition;
         var boneArray              = node.Parent.Parent.AsWidget.BoneArray;
         var localToParentTransform = node.Parent.AsWidget.CalcLocalToParentTransform();
         var transformedPosition    = originTranslation * localToParentTransform *
                                      boneArray.CalcWeightedRelativeTransform(newSkinningWeights).CalcInversed() * localToParentTransform.CalcInversed();
         var translation = (transformedPosition - point.Offset) / point.Parent.AsWidget.Size;
         SetAnimableProperty.Perform(node, nameof(PointObject.Position), translation);
     }
     else
     {
         var widget = node.AsWidget;
         var originLocalToParent = node.AsWidget.CalcLocalToParentTransform();
         var transform           = (originLocalToParent *
                                    widget.Parent.AsWidget.BoneArray.CalcWeightedRelativeTransform(newSkinningWeights).CalcInversed()).ToTransform2();
         SetAnimableProperty.Perform(node, nameof(Widget.Rotation), transform.Rotation);
         var localToParentTransform =
             Matrix32.Translation(-(widget.Pivot * widget.Size)) *
             Matrix32.Transformation(
                 Vector2.Zero,
                 widget.Scale,
                 widget.Rotation * Mathf.Pi / 180f,
                 Vector2.Zero);
         SetAnimableProperty.Perform(node, nameof(Widget.Position), transform.Translation - localToParentTransform.T);
     }
 }
예제 #5
0
 private void CalcGeometry(Matrix32 matrix, out Vector2 a, out Vector2 b)
 {
     NineGrid.BuildLayout(parts, (Vector2)Owner.Texture.ImageSize, Owner.LeftOffset,
                          Owner.RightOffset, Owner.TopOffset, Owner.BottomOffset, Owner.Size);
     a = matrix.TransformVector(parts[IndexA].Rect.A);
     b = matrix.TransformVector(parts[IndexB].Rect.B);
 }
예제 #6
0
        public static void ApplyTransformationToWidgetsGroupOobb(IEnumerable <Widget> widgetsInParentSpace,
                                                                 Widget parentWidget, Matrix32 oobbInParentSpace,
                                                                 Vector2 curMousePosInParentSpace, Vector2 prevMousePosInParentSpace,
                                                                 Func <Vector2, Vector2, Matrix32> onCalcTransformationFromOriginalVectorInOobbSpaceAndDeformedVectorInOobbSpace)
        {
            Vector2 pivotInParentSpace = oobbInParentSpace.T;

            Vector2 pivotInOobbSpace        = pivotInParentSpace;
            Vector2 controlPointInOobbSpace = prevMousePosInParentSpace;
            Vector2 targetPointInOobbSpace  = curMousePosInParentSpace;

            Matrix32 transformationFromParentToOobb = oobbInParentSpace.CalcInversed();

            pivotInOobbSpace        = pivotInOobbSpace * transformationFromParentToOobb;
            controlPointInOobbSpace = controlPointInOobbSpace * transformationFromParentToOobb;
            targetPointInOobbSpace  = targetPointInOobbSpace * transformationFromParentToOobb;

            Vector2 originalVectorInOobbSpace = controlPointInOobbSpace - pivotInOobbSpace;
            Vector2 deformedVectorInOobbSpace = targetPointInOobbSpace - pivotInOobbSpace;

            // calculate transformation from original vector to deformed vector
            Matrix32 deformationInOobbSpace =
                onCalcTransformationFromOriginalVectorInOobbSpaceAndDeformedVectorInOobbSpace(originalVectorInOobbSpace,
                                                                                              deformedVectorInOobbSpace);

            ApplyTransformationToWidgetsGroupOobb(
                widgetsInParentSpace, parentWidget, oobbInParentSpace, deformationInOobbSpace
                );
        }
예제 #7
0
        public static void ApplyTransformationToWidgetsGroupOobb(IList <Widget> widgetsInParentSpace,
                                                                 Vector2 pivotInParentSpace, bool oobbInFirstWidgetSpace,
                                                                 Vector2 curMousePosInParentSpace, Vector2 prevMousePosInParentSpace,
                                                                 Func <Vector2, Vector2, Matrix32> onCalcTransformationFromOriginalVectorInOobbSpaceAndDeformedVectorInOobbSpace)
        {
            if (widgetsInParentSpace.Count == 0)
            {
                return;
            }

            Matrix32 originalOobbToParentSpace = Matrix32.Translation(pivotInParentSpace);

            if (oobbInFirstWidgetSpace)
            {
                Matrix32 firstWidgetToParentSpace = widgetsInParentSpace[0].CalcLocalToParentTransform();

                originalOobbToParentSpace = firstWidgetToParentSpace *
                                            Matrix32.Translation(firstWidgetToParentSpace.T).CalcInversed() * Matrix32.Translation(pivotInParentSpace);
            }

            ApplyTransformationToWidgetsGroupOobb(
                widgetsInParentSpace, widgetsInParentSpace[0].ParentWidget, originalOobbToParentSpace, curMousePosInParentSpace, prevMousePosInParentSpace,
                onCalcTransformationFromOriginalVectorInOobbSpaceAndDeformedVectorInOobbSpace
                );
        }
예제 #8
0
파일: Rulerbar.cs 프로젝트: klenin/Citrus
 void Render(Widget widget)
 {
     widget.PrepareRendererState();
     Renderer.DrawRect(Vector2.Zero, RootWidget.Size, ColorTheme.Current.Toolbar.Background);
     Renderer.Transform1 *= Matrix32.Translation(-Timeline.Instance.Offset.X, 0);
     RenderCursor();
     for (int i = 0; i < Timeline.Instance.ColumnCount; i++)
     {
         var x = i * TimelineMetrics.ColWidth + 0.5f;
         if (i % 10 == 0)
         {
             float textHeight = Theme.Metrics.TextHeight;
             float y          = (RootWidget.Height - textHeight) / 2;
             Renderer.DrawTextLine(
                 new Vector2(x, y), i.ToString(),
                 Theme.Metrics.TextHeight,
                 Theme.Colors.BlackText,
                 0.0f);
             Renderer.DrawLine(x, 0, x, RootWidget.Height, ColorTheme.Current.TimelineRuler.Notchings);
         }
     }
     foreach (var m in Document.Current.Container.Markers)
     {
         RenderMarker(m);
     }
 }
예제 #9
0
        private static void SetupViewportAndProjectionMatrix()
        {
            Renderer.SetOrthogonalProjection(0, 0, The.World.Width, The.World.Height);
            var windowSize = The.Window.ClientSize;

            The.Window.Input.MousePositionTransform = Matrix32.Scaling(The.World.Width / windowSize.X,
                                                                       The.World.Height / windowSize.Y);
        }
예제 #10
0
        public void TransformTest()
        {
            var rectangle = new Rectangle(Vector2.Zero, Vector2.One);

            rectangle = rectangle.Transform(Matrix32.Scaling(Vector2.Half));
            var expectedRectangle = new Rectangle(Vector2.Zero, Vector2.Half);

            Assert.That(rectangle, Is.EqualTo(expectedRectangle));
        }
 internal UniformFloatMatrix32GL3x(string name, int location, ICleanableObserver observer)
     : base(name, UniformType.FloatMatrix32)
 {
     _location = location;
     _value    = new Matrix32 <float>();
     _dirty    = true;
     _observer = observer;
     _observer.NotifyDirty(this);
 }
예제 #12
0
        public void Construct1()
        {
            Matrix32<double> m = new Matrix32<double>(1.0);

            for (int i = 0; i < m.NumberOfComponents; ++i)
            {
                Assert.AreEqual(1.0, m.ReadOnlyColumnMajorValues[0], 1e-14);
            }
        }
예제 #13
0
        static void DrawRectOutline(Vector2 a, Vector2 b, Matrix32 t)
        {
            var c = ColorTheme.Current.SceneView.MouseSelection;

            Renderer.DrawLine(a * t, new Vector2(b.X, a.Y) * t, c, 1, LineCap.Square);
            Renderer.DrawLine(new Vector2(b.X, a.Y) * t, b * t, c, 1, LineCap.Square);
            Renderer.DrawLine(b * t, new Vector2(a.X, b.Y) * t, c, 1, LineCap.Square);
            Renderer.DrawLine(new Vector2(a.X, b.Y) * t, a * t, c, 1, LineCap.Square);
        }
예제 #14
0
        protected static Rectangle CalcAABBInContainer(Matrix32 contentToContainer, Rectangle contentAABB)
        {
            var result = new Rectangle(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue)
                         .IncludingPoint(contentToContainer * contentAABB.A)
                         .IncludingPoint(contentToContainer * new Vector2(contentAABB.Right, contentAABB.Top))
                         .IncludingPoint(contentToContainer * contentAABB.B)
                         .IncludingPoint(contentToContainer * new Vector2(contentAABB.Left, contentAABB.Bottom));

            return(result);
        }
예제 #15
0
        IEnumerator <object> Rotate(Quadrangle hull, List <PointObject> points)
        {
            using (Document.Current.History.BeginTransaction()) {
                var t = Document.Current.Container.AsWidget.LocalToWorldTransform.CalcInversed();
                hull *= Matrix32.Scaling(Vector2.One / Document.Current.Container.AsWidget.Size);
                var center          = (hull.V1 + hull.V3) / 2;
                var size            = Document.Current.Container.AsWidget.Size;
                var mousePosInitial = (sv.MousePosition * t - center * size) / size;
                var rotation        = 0f;
                while (sv.Input.IsMousePressed())
                {
                    Document.Current.History.RollbackTransaction();
                    Utils.ChangeCursorIfDefault(Cursors.Rotate);
                    var b     = (sv.MousePosition * t - center * size) / size;
                    var angle = 0f;
                    if (mousePosInitial.Length > Mathf.ZeroTolerance && b.Length > Mathf.ZeroTolerance)
                    {
                        angle    = Mathf.Wrap180(b.Atan2Deg - mousePosInitial.Atan2Deg);
                        rotation = angle;
                    }
                    if (Math.Abs(angle) > Mathf.ZeroTolerance)
                    {
                        var        effectiveAngle = sv.Input.IsKeyPressed(Key.Shift) ? Utils.RoundTo(rotation, 15) : angle;
                        Quadrangle newBounds      = new Quadrangle();
                        for (int i = 0; i < 4; i++)
                        {
                            newBounds[i] = Vector2.RotateDeg(hull[i] - center, effectiveAngle) + center;
                        }
                        for (var i = 0; i < points.Count; i++)
                        {
                            var offset   = center - points[i].Offset / size;
                            var position = Vector2.RotateDeg((points[i].Position - offset), effectiveAngle) + offset;
                            Core.Operations.SetAnimableProperty.Perform(points[i], nameof(PointObject.Position), position, CoreUserPreferences.Instance.AutoKeyframes);
                            if (points[i] is SplinePoint)
                            {
                                Core.Operations.SetAnimableProperty.Perform(
                                    points[i],
                                    nameof(SplinePoint.TangentAngle),
                                    (points[i] as SplinePoint).TangentAngle - effectiveAngle,
                                    CoreUserPreferences.Instance.AutoKeyframes
                                    );
                            }
                        }
                    }

                    yield return(null);
                }
                sv.Input.ConsumeKey(Key.Mouse0);
                Window.Current.Invalidate();
                Document.Current.History.CommitTransaction();
            }
        }
예제 #16
0
        private static void DrawCreateWidgetGizmo(Vector2 a, Vector2 b, Matrix32 t)
        {
            var c = ColorTheme.Current.SceneView.MouseSelection;

            Renderer.DrawLine(a * t, new Vector2(b.X, a.Y) * t, c, 1, LineCap.Square);
            Renderer.DrawLine(new Vector2(b.X, a.Y) * t, b * t, c, 1, LineCap.Square);
            Renderer.DrawLine(b * t, new Vector2(a.X, b.Y) * t, c, 1, LineCap.Square);
            Renderer.DrawLine(new Vector2(a.X, b.Y) * t, a * t, c, 1, LineCap.Square);
            var midX = (a.X + b.X) * 0.5f;
            var midY = (a.Y + b.Y) * 0.5f;

            Renderer.DrawLine(new Vector2(midX, a.Y) * t, new Vector2(midX, b.Y) * t, c, 1, LineCap.Square);
            Renderer.DrawLine(new Vector2(a.X, midY) * t, new Vector2(b.X, midY) * t, c, 1, LineCap.Square);
        }
예제 #17
0
        public static void DrawCapsule(Vector2 a, Vector2 b, Vector2 n, Matrix32 t, int numSegments, Color4 color, float thickness = 1)
        {
            Renderer.DrawLine((a + n) * t, (b + n) * t, color, thickness);
            Renderer.DrawLine((a - n) * t, (b - n) * t, color, thickness);
            var step = 180 / numSegments;

            for (var i = 0; i < numSegments; i++)
            {
                var v1 = Vector2.RotateDeg(n, i * step);
                var v2 = Vector2.RotateDeg(n, (i + 1) * step);
                Renderer.DrawLine((v1 + a) * t, (v2 + a) * t, color, thickness);
                Renderer.DrawLine((-v1 + b) * t, (-v2 + b) * t, color, thickness);
            }
        }
예제 #18
0
        private IEnumerator <object> Resize(Quadrangle hull, int controlPointIndex, Vector2 pivot)
        {
            var cursor = WidgetContext.Current.MouseCursor;

            using (Document.Current.History.BeginTransaction()) {
                var widgets       = Document.Current.SelectedNodes().Editable().OfType <Widget>();
                var mouseStartPos = SceneView.MousePosition;
                while (SceneView.Input.IsMousePressed())
                {
                    Document.Current.History.RollbackTransaction();
                    Matrix32 transform = Matrix32.Identity;
                    Utils.ChangeCursorIfDefault(cursor);
                    var proportional    = SceneView.Input.IsKeyPressed(Key.Shift);
                    var isChangingScale = SceneView.Input.IsKeyPressed(Key.Control);
                    var toBeTransformed = widgets.Where(w => isChangingScale ?
                                                        !w.IsPropertyReadOnly(nameof(Widget.Scale)) : !w.IsPropertyReadOnly(nameof(Widget.Size))).ToList();
                    var areChildrenFreezed =
                        SceneView.Input.IsKeyPressed(Key.Z) &&
                        !isChangingScale &&
                        toBeTransformed.Count == 1;
                    if (areChildrenFreezed)
                    {
                        transform = toBeTransformed[0].CalcTransitionToSpaceOf(Document.Current.Container.AsWidget);
                    }
                    var pivotPoint =
                        isChangingScale ?
                        (toBeTransformed.Count <= 1 ? (Vector2?)null : pivot) :
                        hull[lookupPivotIndex[controlPointIndex] / 2];
                    RescaleWidgets(
                        toBeTransformed.Count <= 1,
                        pivotPoint,
                        toBeTransformed,
                        controlPointIndex,
                        SceneView.MousePosition,
                        mouseStartPos,
                        proportional,
                        !isChangingScale
                        );
                    if (areChildrenFreezed)
                    {
                        transform *= Document.Current.Container.AsWidget.CalcTransitionToSpaceOf(toBeTransformed[0]);
                        RestoreChildrenPositions(toBeTransformed[0], transform);
                    }
                    yield return(null);
                }
                SceneView.Input.ConsumeKey(Key.Mouse0);
                Document.Current.History.CommitTransaction();
            }
        }
예제 #19
0
        public void DoubleToFloat()
        {
            Matrix32<double> m = new Matrix32<double>(
                1.0, 2.0, 3.0, 
                4.0, 5.0, 6.0);

            Matrix32<float> mf = Matrix32<double>.DoubleToFloat(m);

            Assert.AreEqual(1.0f, mf.Column0Row0, 1e-7);
            Assert.AreEqual(2.0f, mf.Column1Row0, 1e-7);
            Assert.AreEqual(3.0f, mf.Column2Row0, 1e-7);
            Assert.AreEqual(4.0f, mf.Column0Row1, 1e-7);
            Assert.AreEqual(5.0f, mf.Column1Row1, 1e-7);
            Assert.AreEqual(6.0f, mf.Column2Row1, 1e-7);
        }
예제 #20
0
 private static void RestoreChildrenPositions(Widget widget, Matrix32 transform)
 {
     foreach (var child in widget.Nodes.OfType <Widget>())
     {
         var newPosition = transform.TransformVector(child.Position);
         SetProperty.Perform(child, nameof(Widget.Position), newPosition);
         if (child.Animators.TryFind(nameof(Widget.Position), out var animator))
         {
             foreach (var key in animator.ReadonlyKeys.ToList())
             {
                 var newKey = key.Clone();
                 newKey.Value = transform.TransformVector((Vector2)key.Value);
                 SetKeyframe.Perform(animator, newKey);
             }
         }
     }
 }
예제 #21
0
        void Render(Widget widget)
        {
            widget.PrepareRendererState();
            Renderer.DrawRect(Vector2.Zero, RootWidget.Size, ColorTheme.Current.Toolbar.Background);
            Renderer.MultiplyTransform1(Matrix32.Translation(-Timeline.Instance.Offset.X.Round(), 0));
            RenderCursor();
            Timeline.Instance.GetVisibleColumnRange(out var minColumn, out var maxColumn);
            for (int i = minColumn; i <= maxColumn; i++)
            {
                if (i % 10 == 0)
                {
                    var   x          = i * TimelineMetrics.ColWidth + 0.5f;
                    float textHeight = Theme.Metrics.TextHeight;
                    float y          = (RootWidget.Height - textHeight) / 2;
                    Renderer.DrawTextLine(
                        new Vector2(x, y), i.ToString(),
                        Theme.Metrics.TextHeight,
                        Theme.Colors.BlackText,
                        0.0f);
                    if (!Document.Current.Animation.IsCompound)
                    {
                        Renderer.DrawLine(x, 0, x, RootWidget.Height, ColorTheme.Current.TimelineRuler.Notchings);
                    }
                }
            }
            bool metUpperMarker = false;

            foreach (var m in Document.Current.Animation.Markers)
            {
                if (upperMarker != m)
                {
                    RenderMarker(m);
                }
                else
                {
                    metUpperMarker = true;
                }
            }
            if (!metUpperMarker && upperMarker != null)
            {
                upperMarker = null;
            }
            RenderUpperMarker();
        }
예제 #22
0
        private void RotateWidgets(Vector2 pivotPoint, List <Widget> widgets, Vector2 curMousePos, Vector2 prevMousePos,
                                   bool discret, ref float accumAngle, ref float prevAngle)
        {
            List <KeyValuePair <Widget, float> > wasRotations = widgets.Select(widget => new KeyValuePair <Widget, float>(widget, widget.Rotation)).ToList();

            float rotationRes = prevAngle;

            Utils.ApplyTransformationToWidgetsGroupOobb(
                sv.Scene,
                widgets, pivotPoint, false, curMousePos, prevMousePos,
                (originalVectorInOobbSpace, deformedVectorInOobbSpace) => {
                float rotation = 0;
                if (originalVectorInOobbSpace.Length > Mathf.ZeroTolerance &&
                    deformedVectorInOobbSpace.Length > Mathf.ZeroTolerance)
                {
                    rotation = Mathf.Wrap180(deformedVectorInOobbSpace.Atan2Deg - originalVectorInOobbSpace.Atan2Deg);
                }

                if (discret)
                {
                    rotation = Utils.RoundTo(rotation, 15);
                }

                rotationRes = rotation;

                return(Matrix32.Rotation(rotation * Mathf.DegToRad));
            }
                );

            // accumulate rotation, each visual turn of widget will increase it's angle on 360,
            // without that code angle will be allways [-180; 180)
            rotationRes = rotationRes.NormalizeRotation();
            float rotationDelta = (rotationRes - prevAngle).NormalizeRotation();

            prevAngle = rotationRes;

            accumAngle += rotationDelta;

            foreach (KeyValuePair <Widget, float> wasRotation in wasRotations)
            {
                SetAnimableProperty.Perform(wasRotation.Key, nameof(Widget.Rotation), wasRotation.Value + accumAngle);
            }
        }
예제 #23
0
            private void DrawSegments(RulerData rulerData, float strokeDelta, float strokeLength, float?strokeValue = null)
            {
                var maskInverted  = rulerData.RulerOrientation.GetDirection();
                var mask          = (Vector2.One - maskInverted);
                var delta         = mask * strokeDelta;
                var j             = -(int)Math.Round(((rulerData.Origin * mask).Length - rulerData.LeftStoper) / strokeDelta);
                var b             = maskInverted * rulerData.Offset + rulerData.Origin * mask + j * strokeDelta * mask;
                var a             = b - maskInverted * strokeLength;
                var fontHeight    = 14f;
                var letterspacing = 1f;
                var textOffset    = Vector2.Zero;

                do
                {
                    if (GetVectorComponentForOrientation(a, rulerData.RulerOrientation) - rulerData.Offset >= 0)
                    {
                        Renderer.DrawLine(a, b, ColorTheme.Current.SceneView.RulerTextColor);
                        if (strokeValue != null)
                        {
                            var lengthMarkerText     = ((int)(j * strokeValue.Value)).ToString();
                            var textLength           = FontPool.Instance.DefaultFont.MeasureTextLine(lengthMarkerText, fontHeight, letterspacing);
                            var lengthMarkerPosition = a + textOffset;
                            Renderer.PushState(RenderState.Transform1);
                            Renderer.MultiplyTransform1(Matrix32.Translation(lengthMarkerPosition.X.Round(), lengthMarkerPosition.Y.Round()));
                            if (rulerData.RulerOrientation == RulerOrientation.Vertical)
                            {
                                Renderer.MultiplyTransform1(Matrix32.Rotation(-Mathf.HalfPi));
                                textOffset = Vector2.Down * (5 + textLength.X);
                            }
                            else
                            {
                                textOffset = Vector2.Right * 5;
                            }
                            Renderer.DrawTextLine(Vector2.Zero, lengthMarkerText, fontHeight, ColorTheme.Current.SceneView.RulerTextColor, letterspacing);
                            Renderer.PopState();
                        }
                    }
                    j++;
                    a += delta;
                    b += delta;
                } while (rulerData.RightStoper > GetVectorComponentForOrientation(a, rulerData.RulerOrientation));
            }
예제 #24
0
        public void Construct2()
        {
            Matrix32<double> m = new Matrix32<double>(
                1.0, 2.0, 3.0,
                4.0, 5.0, 6.0);

            Assert.AreEqual(1.0, m.Column0Row0);
            Assert.AreEqual(2.0, m.Column1Row0);
            Assert.AreEqual(3.0, m.Column2Row0);
            Assert.AreEqual(4.0, m.Column0Row1);
            Assert.AreEqual(5.0, m.Column1Row1);
            Assert.AreEqual(6.0, m.Column2Row1);

            Assert.AreEqual(1.0, m.ReadOnlyColumnMajorValues[0]);
            Assert.AreEqual(4.0, m.ReadOnlyColumnMajorValues[1]);
            Assert.AreEqual(2.0, m.ReadOnlyColumnMajorValues[2]);
            Assert.AreEqual(5.0, m.ReadOnlyColumnMajorValues[3]);
            Assert.AreEqual(3.0, m.ReadOnlyColumnMajorValues[4]);
            Assert.AreEqual(6.0, m.ReadOnlyColumnMajorValues[5]);
        }
예제 #25
0
        private static Rectangle ExpandMeshLocalAABB(
            Rectangle aabb,
            Vector2 size,
            DistortionMeshPoint point,
            BoneArray bones,
            Matrix32 weightsMatrix,
            Matrix32 weightsMatrixInversed
            )
        {
            var position = size * point.Position + point.Offset;

            if (point.SkinningWeights != null)
            {
                position = weightsMatrixInversed.TransformVector(bones.ApplySkinningToVector(
                                                                     weightsMatrix.TransformVector(position),
                                                                     point.SkinningWeights
                                                                     ));
            }
            return(aabb.IncludingPoint(position));
        }
예제 #26
0
        private void Render(Widget widget)
        {
            var maxCol = Timeline.Instance.ColumnCount;

            widget.PrepareRendererState();
            Renderer.DrawRect(Vector2.Zero, widget.ContentSize, ColorTheme.Current.TimelineGrid.PropertyRowBackground);
            var colorIndex = PropertyAttributes <TangerineKeyframeColorAttribute> .Get(animator.Animable.GetType(), animator.TargetPropertyPath)?.ColorIndex ?? 0;

            var color = KeyframePalette.Colors[colorIndex];

            for (int i = 0; i < animator.ReadonlyKeys.Count; i++)
            {
                var key = animator.ReadonlyKeys[i];
                Renderer.Transform1 =
                    Matrix32.RotationRough(Mathf.Pi / 4) *
                    Matrix32.Translation((key.Frame + 0.5f) * TimelineMetrics.ColWidth + 0.5f, widget.Height / 2 + 0.5f) *
                    widget.LocalToWorldTransform;
                var v = TimelineMetrics.ColWidth / 3 * Vector2.One;
                Renderer.DrawRect(-v, v, color);
            }
        }
예제 #27
0
        public static void ApplyTransformationToWidgetsGroupOobb(Widget sceneWidget, IList <Widget> widgetsInParentSpace,
                                                                 Vector2 pivotInSceneSpace, bool oobbInFirstWidgetSpace,
                                                                 Vector2 curMousePosInSceneSpace, Vector2 prevMousePosSceneSpace,
                                                                 Func <Vector2, Vector2, Matrix32> onCalcTransformationFromOriginalVectorInOobbSpaceAndDeformedVectorInOobbSpace)
        {
            if (widgetsInParentSpace.Count == 0)
            {
                return;
            }

            Matrix32 fromSceneToParentSpace = sceneWidget.CalcTransitionToSpaceOf(widgetsInParentSpace[0].ParentWidget);

            ApplyTransformationToWidgetsGroupOobb(
                widgetsInParentSpace,
                pivotInSceneSpace * fromSceneToParentSpace,
                oobbInFirstWidgetSpace,
                curMousePosInSceneSpace * fromSceneToParentSpace,
                prevMousePosSceneSpace * fromSceneToParentSpace,
                onCalcTransformationFromOriginalVectorInOobbSpaceAndDeformedVectorInOobbSpace
                );
        }
예제 #28
0
        public void Equals()
        {
            Matrix32<double> a = new Matrix32<double>(
                1.0, 2.0, 3.0, 
                4.0, 5.0, 6.0);
            Matrix32<double> b = new Matrix32<double>(0.0);
            Matrix32<double> c = new Matrix32<double>(
                1.0, 2.0, 3.0,
                4.0, 5.0, 6.0);

            Assert.IsTrue(a.Equals(c));
            Assert.IsTrue(c.Equals(a));
            Assert.IsTrue(a == c);
            Assert.IsTrue(c == a);
            Assert.IsFalse(c != a);
            Assert.IsFalse(c != a);
            Assert.IsFalse(a.Equals(b));
            Assert.IsFalse(b.Equals(a));
            Assert.IsFalse(a == b);
            Assert.IsFalse(b == a);
            Assert.IsTrue(a != b);
            Assert.IsTrue(b != a);

            object objA = a;
            object objB = b;
            object objC = c;

            Assert.IsTrue(a.Equals(objA));
            Assert.IsTrue(a.Equals(objC));
            Assert.IsFalse(a.Equals(objB));

            Assert.IsTrue(objA.Equals(objC));
            Assert.IsFalse(objA.Equals(objB));

            Assert.IsFalse(a.Equals(null));
            Assert.IsFalse(a.Equals(5));
        }
예제 #29
0
        public static void ApplyTransformationToWidgetsGroupOobb(IEnumerable <Widget> widgetsInParentSpace,
                                                                 Widget parentWidget, Matrix32 oobbInParentSpace, Matrix32 oobbTransformation)
        {
            Matrix32 originalOobbToWorldSpace = oobbInParentSpace * parentWidget.LocalToWorldTransform;

            foreach (Widget widget in widgetsInParentSpace)
            {
                Matrix32 widgetToOriginalOobbSpace = widget.LocalToWorldTransform * originalOobbToWorldSpace.CalcInversed();

                // calculate new oobb transformation in world space
                Matrix32 deformedOobbToWorldSpace = oobbTransformation * originalOobbToWorldSpace;

                Matrix32 deformedWidgetToWorldSpace = widgetToOriginalOobbSpace * deformedOobbToWorldSpace;

                Matrix32 deformedWidgetToParentSpace =
                    deformedWidgetToWorldSpace * widget.ParentWidget.LocalToWorldTransform.CalcInversed();

                Transform2 widgetResultTransform = widget.CalcApplicableTransfrom2(deformedWidgetToParentSpace);

                // correct rotation delta, to prevent wrong values if new angle 0 and previous is 359,
                // then rotationDelta must be 1
                float rotationDelta = (widget.Rotation - widgetResultTransform.Rotation).NormalizeRotation();

                if ((widget.Position - widgetResultTransform.Translation).Length > Mathf.ZeroTolerance)
                {
                    SetAnimableProperty.Perform(widget, nameof(Widget.Position), widgetResultTransform.Translation);
                }
                if (Mathf.Abs(rotationDelta) > Mathf.ZeroTolerance)
                {
                    SetAnimableProperty.Perform(widget, nameof(Widget.Rotation), widget.Rotation + rotationDelta);
                }
                if ((widget.Scale - widgetResultTransform.Scale).Length > Mathf.ZeroTolerance)
                {
                    SetAnimableProperty.Perform(widget, nameof(Widget.Scale), widgetResultTransform.Scale);
                }
            }
        }
예제 #30
0
        public IEnumerator <object> Task()
        {
            while (true)
            {
                if (!SceneView.Instance.InputArea.IsMouseOverThisOrDescendant())
                {
                    yield return(null);

                    continue;
                }
                var points = Document.Current.SelectedNodes().Editable().OfType <PointObject>().ToList();
                if (points.Count > 1)
                {
                    Rectangle aabb;
                    Utils.CalcAABB(points, Document.Current.Container.AsWidget, out aabb);
                    var hull     = aabb.ToQuadrangle();
                    var hullSize = hull.V3 - hull.V1;
                    hullNormalized = hull * Matrix32.Scaling(Vector2.One / Document.Current.Container.AsWidget.Size);
                    var expandedHullInSceneCoords = PointObjectsPresenter.ExpandAndTranslateToSpaceOf(hull, Document.Current.Container.AsWidget, sv.Frame) *
                                                    sv.Frame.CalcTransitionToSpaceOf(sv.Scene);
                    for (int i = 0; i < 4; i++)
                    {
                        if (Mathf.Abs(hullSize.X) > Mathf.ZeroTolerance && Mathf.Abs(hullSize.Y) > Mathf.ZeroTolerance)
                        {
                            if (sv.HitTestResizeControlPoint(expandedHullInSceneCoords[i]))
                            {
                                Utils.ChangeCursorIfDefault(MouseCursor.SizeNS);
                                if (sv.Input.ConsumeKeyPress(Key.Mouse0))
                                {
                                    yield return(Rescale(i * 2, MouseCursor.SizeNS, points));
                                }
                            }
                        }
                    }
                    for (int i = 0; i < 4; i++)
                    {
                        if (Mathf.Abs(hullSize.X) < Mathf.ZeroTolerance && i % 2 == 1 ||
                            Mathf.Abs(hullSize.Y) < Mathf.ZeroTolerance && i % 2 == 0
                            )
                        {
                            continue;
                        }
                        var a = expandedHullInSceneCoords[i];
                        var b = expandedHullInSceneCoords[(i + 1) % 4];
                        if (sv.HitTestResizeControlPoint((a + b) / 2))
                        {
                            var cursor = MouseCursor.Default;
                            if (Mathf.Abs(hullSize.X) < Mathf.ZeroTolerance)
                            {
                                cursor = MouseCursor.SizeNS;
                            }
                            else if (Mathf.Abs(hullSize.Y) < Mathf.ZeroTolerance)
                            {
                                cursor = MouseCursor.SizeWE;
                            }
                            else
                            {
                                cursor = (b.X - a.X).Abs() > (b.Y - a.Y).Abs() ? MouseCursor.SizeNS : MouseCursor.SizeWE;
                            }
                            Utils.ChangeCursorIfDefault(cursor);
                            if (sv.Input.ConsumeKeyPress(Key.Mouse0))
                            {
                                yield return(Rescale(i * 2 + 1, cursor, points));
                            }
                        }
                    }
                }
                yield return(null);
            }
        }
예제 #31
0
        public override void ExecuteTransaction()
        {
            var groups = Document.Current?.SelectedNodes().OfType <Frame>().ToList();

            if (groups?.Count == 0)
            {
                return;
            }
            var container = (Widget)Document.Current.Container;
            var p         = container.RootFolder().Find(groups[0]);

            ClearRowSelection.Perform();
            UntieWidgetsFromBones.Perform(Document.Current.Container.Nodes.OfType <Bone>(), groups);
            foreach (var group in groups)
            {
                UnlinkFolderItem.Perform(container, group);
            }

            foreach (var group in groups)
            {
                var flipXFactor            = group.Scale.X < 0 ? -1 : 1;
                var flipYFactor            = group.Scale.Y < 0 ? -1 : 1;
                var flipVector             = Vector2.Right + Vector2.Down * flipXFactor * flipYFactor;
                var groupRootBones         = new List <Bone>();
                var groupNodes             = group.Nodes.ToList().Where(GroupNodes.IsValidNode).ToList();
                var localToParentTransform = group.CalcLocalToParentTransform();
                foreach (var node in groupNodes)
                {
                    UnlinkFolderItem.Perform(group, node);
                    InsertFolderItem.Perform(container, p, node);
                    SelectNode.Perform(node);
                    p.Index++;
                    if (node is Widget)
                    {
                        GroupNodes.TransformPropertyAndKeyframes <Vector2>(node, nameof(Widget.Position), v => localToParentTransform * v);
                        GroupNodes.TransformPropertyAndKeyframes <Vector2>(node, nameof(Widget.Scale), v => v * group.Scale);
                        GroupNodes.TransformPropertyAndKeyframes <float>(node, nameof(Widget.Rotation),
                                                                         v => v * Mathf.Sign(group.Scale.X * group.Scale.Y) + group.Rotation);
                        GroupNodes.TransformPropertyAndKeyframes <Color4>(node, nameof(Widget.Color), v => group.Color * v);
                    }
                    else if (node is Bone)
                    {
                        var root = BoneUtils.FindBoneRoot((Bone)node, groupNodes);
                        if (!groupRootBones.Contains(root))
                        {
                            GroupNodes.TransformPropertyAndKeyframes <Vector2>(node, nameof(Bone.Position), v => localToParentTransform * v);
                            GroupNodes.TransformPropertyAndKeyframes <float>(node, nameof(Bone.Rotation),
                                                                             v => (Matrix32.Rotation(v * Mathf.DegToRad) * localToParentTransform).ToTransform2().Rotation);
                            groupRootBones.Add(root);
                        }
                        else if (flipVector != Vector2.One)
                        {
                            GroupNodes.TransformPropertyAndKeyframes <Vector2>(node, nameof(Bone.Position), v => v * flipVector);
                            GroupNodes.TransformPropertyAndKeyframes <float>(node, nameof(Bone.Rotation), v => - v);
                        }
                        GroupNodes.TransformPropertyAndKeyframes <Vector2>(node, nameof(Bone.RefPosition), v => localToParentTransform * v);
                        GroupNodes.TransformPropertyAndKeyframes <float>(node, nameof(Bone.RefRotation),
                                                                         v => (Matrix32.Rotation(v * Mathf.DegToRad) * localToParentTransform).ToTransform2().Rotation);
                    }
                }
            }
        }
예제 #32
0
        public void TestGetHashCode()
        {
            Matrix32<double> a = new Matrix32<double>(
                1.0, 2.0, 3.0, 
                4.0, 5.0, 6.0);
            Matrix32<double> b = new Matrix32<double>(0.0);
            Matrix32<double> c = new Matrix32<double>(
                1.0, 2.0, 3.0,
                4.0, 5.0, 6.0);

            Assert.AreEqual(a.GetHashCode(), c.GetHashCode());
            Assert.AreNotEqual(a.GetHashCode(), b.GetHashCode());
        }
예제 #33
0
        public void Matrix32()
        {
            string fs =
                @"#version 330

                  uniform mat3x2 exampleMat32;
                  out vec3 FragColor;

                  void main()
                  {
                      FragColor = vec3(exampleMat32[1].x, exampleMat32[2].x, 0.0);
                  }";

            using (GraphicsWindow window = Device.CreateWindow(1, 1))
            using (Framebuffer framebuffer = TestUtility.CreateFramebuffer(window.Context))
            using (ShaderProgram sp = Device.CreateShaderProgram(ShaderSources.PassThroughVertexShader(), fs))
            using (VertexArray va = TestUtility.CreateVertexArray(window.Context, sp.VertexAttributes["position"].Location))
            {
                Matrix32<float> m32 = new Matrix32<float>(
                        0.0f, 1.0f, 1.0f,
                        0.0f, 0.0f, 0.0f);
                Uniform<Matrix32<float>> exampleMat32 = (Uniform<Matrix32<float>>)sp.Uniforms["exampleMat32"];
                Assert.AreEqual("exampleMat32", exampleMat32.Name);
                Assert.AreEqual(UniformType.FloatMatrix32, exampleMat32.Datatype);
                Assert.AreEqual(new Matrix32<float>(), exampleMat32.Value);
                exampleMat32.Value = m32;
                Assert.AreEqual(m32, exampleMat32.Value);

                window.Context.Framebuffer = framebuffer;
                window.Context.Draw(PrimitiveType.Points, 0, 1, new DrawState(TestUtility.CreateRenderStateWithoutDepthTest(), sp, va), new SceneState());
                TestUtility.ValidateColor(framebuffer.ColorAttachments[0], 255, 255, 0);
            }
        }
예제 #34
0
        public override void MultiplyTransform2(Matrix32 transform)
        {
            var cmd = AddCommand <MultiplyTransform2Command>();

            cmd.Value = transform;
        }
예제 #35
0
 protected static Rectangle CalcAABBInContainer(Matrix32 containerWorldToLocal, Matrix32 contentLocalToWorld, Rectangle contentAABB)
 {
     return(CalcAABBInContainer(contentLocalToWorld * containerWorldToLocal, contentAABB));
 }
예제 #36
0
 public ViewRectProjector(Widget widget, Rectangle area)
 {
     Widget           = widget;
     Area             = area;
     viewWorldToLocal = Widget.LocalToWorldTransform.CalcInversed();
 }