Esempio n. 1
0
        public static void ApplyTransformationToWidgetsGroupObb(IList <Widget> widgetsInParentSpace,
                                                                Vector2d?overridePivotInParentSpace, bool obbInFirstWidgetSpace,
                                                                Vector2d currentMousePosInParentSpace, Vector2d previousMousePosInParentSpace,
                                                                bool convertScaleToSize, CalculateTransformationDelegate onCalculateTransformation)
        {
            if (widgetsInParentSpace.Count == 0)
            {
                return;
            }

            // Importent. Try to correct the pivot point to the closest pivot of one of widgets.
            if (overridePivotInParentSpace != null)
            {
                foreach (Widget widget in widgetsInParentSpace)
                {
                    double length = ((Vector2d)widget.Position - overridePivotInParentSpace.Value).Length;
                    if (length <= 1e-3)
                    {
                        overridePivotInParentSpace = (Vector2d)widget.Position;
                        break;
                    }
                }
            }

            Matrix32d originalObbToParentSpace;

            if (!obbInFirstWidgetSpace)
            {
                originalObbToParentSpace =
                    Matrix32d.Translation(overridePivotInParentSpace ?? (Vector2d)widgetsInParentSpace[0].Position);
            }
            else
            {
                Widget widgetFirst = widgetsInParentSpace[0];

                WidgetZeroScalePreserver zeroScalePreserver = new WidgetZeroScalePreserver(widgetFirst);
                zeroScalePreserver.Store();

                // Nullify Pivot and Scale, to simplify transformation matrix from M = mT' * mR * mS * mT, to M = mR * mT,
                // to be able to use it with complex transformation by user (U = uT' uR * uS * uT), as
                // dM = U * M, instead of we must make dM = mT' * uR * mR * uS * mS * uT * mT,
                // and now if mT' = 1 and mS = 1 and uT = 1 it is reduced to dM = uT' * uS * uR * mR * mT = U * M.
                Matrix32d firstWidgetToParentSpace;
                Vector2   savedPivot = widgetFirst.Pivot;
                Vector2   savedScale = widgetFirst.Scale;
                widgetFirst.Pivot = Vector2.Zero;
                widgetFirst.Scale = Vector2.One;
                try {
                    firstWidgetToParentSpace = widgetFirst.CalcLocalToParentTransformDouble();
                    if (overridePivotInParentSpace != null)
                    {
                        firstWidgetToParentSpace.T = overridePivotInParentSpace.Value;
                    }
                } finally {
                    widgetFirst.Pivot = savedPivot;
                    widgetFirst.Scale = savedScale;
                    zeroScalePreserver.Restore();
                }

                originalObbToParentSpace = firstWidgetToParentSpace;
            }

            ApplyTransformationToWidgetsGroupObb(
                widgetsInParentSpace, originalObbToParentSpace,
                currentMousePosInParentSpace, previousMousePosInParentSpace,
                convertScaleToSize, onCalculateTransformation);
        }
Esempio n. 2
0
        public static void ApplyTransformationToWidgetsGroupObb(IEnumerable <Widget> widgetsInParentSpace,
                                                                Matrix32d obbInParentSpace, Transform2d obbTransformation, bool convertScaleToSize)
        {
            Matrix32d originalObbToParentSpace = obbInParentSpace;

            if (Math.Abs(originalObbToParentSpace.CalcDeterminant()) < Mathf.ZeroTolerance)
            {
                return;
            }

            Matrix32d obbTransformationMatrix = obbTransformation.ToMatrix32();

            foreach (Widget widget in widgetsInParentSpace)
            {
                WidgetZeroScalePreserver zeroScalePreserver = new WidgetZeroScalePreserver(widget);
                zeroScalePreserver.Store();
                try {
                    Matrix32d widgetToParentSpace      = widget.CalcLocalToParentTransformDouble();
                    Matrix32d widgetToOriginalObbSpace = widgetToParentSpace * originalObbToParentSpace.CalcInversed();

                    // Calculate the new obb transformation in the parent space.
                    Matrix32d deformedObbToParentSpace = obbTransformationMatrix * originalObbToParentSpace;

                    Matrix32d deformedWidgetToParentSpace = widgetToOriginalObbSpace * deformedObbToParentSpace;

                    Transform2d widgetResultTransform = widget.ExtractTransform2Double(deformedWidgetToParentSpace,
                                                                                       widget.Rotation + obbTransformation.Rotation);

                    // Correct a rotation delta, to prevent wrong values if a new angle 0 and previous is 359,
                    // then rotationDelta must be 1.
                    double rotationDelta = Mathd.Wrap180(widgetResultTransform.Rotation - widget.Rotation);

                    // Reduce an influence of small transformations (Scale, Position, Rotation).
                    bool needChangeScaleX = IsSignificantChangeOfValue(widget.Scale.X, widgetResultTransform.Scale.X);
                    bool needChangeScaleY = IsSignificantChangeOfValue(widget.Scale.Y, widgetResultTransform.Scale.Y);

                    if (needChangeScaleX || needChangeScaleY)
                    {
                        Vector2 useScale = new Vector2(
                            (float)(!needChangeScaleX ? widget.Scale.X : widgetResultTransform.Scale.X),
                            (float)(!needChangeScaleY ? widget.Scale.Y : widgetResultTransform.Scale.Y)
                            );
                        useScale = zeroScalePreserver.AdjustToScale(useScale);

                        zeroScalePreserver.Restore();

                        if (!convertScaleToSize)
                        {
                            SetAnimableProperty.Perform(widget, nameof(Widget.Scale), useScale,
                                                        CoreUserPreferences.Instance.AutoKeyframes);
                        }
                        else
                        {
                            Vector2 useSize = new Vector2(
                                Math.Abs(widget.Scale.X) < FloatSignificantDelta
                                                                        ? widget.Size.X
                                                                        : widget.Size.X * Math.Abs(useScale.X / widget.Scale.X),
                                Math.Abs(widget.Scale.Y) < FloatSignificantDelta
                                                                        ? widget.Size.Y
                                                                        : widget.Size.Y * Math.Abs(useScale.Y / widget.Scale.Y)
                                );
                            SetAnimableProperty.Perform(widget, nameof(Widget.Size), useSize,
                                                        CoreUserPreferences.Instance.AutoKeyframes);
                        }
                    }

                    bool needChangePositionX = IsSignificantChangeOfValue(widget.Position.X, widgetResultTransform.Translation.X);
                    bool needChangePositionY = IsSignificantChangeOfValue(widget.Position.Y, widgetResultTransform.Translation.Y);

                    if (needChangePositionX || needChangePositionY)
                    {
                        SetAnimableProperty.Perform(widget, nameof(Widget.Position),
                                                    new Vector2(
                                                        (float)(!needChangePositionX ? widget.Position.X : widgetResultTransform.Translation.X),
                                                        (float)(!needChangePositionY ? widget.Position.Y : widgetResultTransform.Translation.Y)
                                                        ),
                                                    CoreUserPreferences.Instance.AutoKeyframes);
                    }

                    if (IsSignificantChangeByDelta(widget.Rotation, rotationDelta))
                    {
                        SetAnimableProperty.Perform(widget, nameof(Widget.Rotation), (float)(widget.Rotation + rotationDelta),
                                                    CoreUserPreferences.Instance.AutoKeyframes);
                    }
                } finally {
                    zeroScalePreserver.Restore();
                }
            }
        }