public static void ApplyTransformationToWidgetsGroupObb(IEnumerable <Widget> widgetsInParentSpace, Matrix32d obbInParentSpace, Vector2d currentMousePosInParentSpace, Vector2d previousMousePosInParentSpace, bool convertScaleToSize, CalculateTransformationDelegate onCalculateTransformation) { if (Math.Abs(obbInParentSpace.CalcDeterminant()) < Mathf.ZeroTolerance) { return; } Matrix32d transformationFromParentToObb = obbInParentSpace.CalcInversed(); Vector2d controlPointInObbSpace = previousMousePosInParentSpace * transformationFromParentToObb; Vector2d targetPointInObbSpace = currentMousePosInParentSpace * transformationFromParentToObb; Vector2d originalVectorInObbSpace = controlPointInObbSpace; Vector2d deformedVectorInObbSpace = targetPointInObbSpace; Transform2d obbTransformation = onCalculateTransformation( originalVectorInObbSpace, deformedVectorInObbSpace ); ApplyTransformationToWidgetsGroupObb( widgetsInParentSpace, obbInParentSpace, obbTransformation, convertScaleToSize ); }
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(); } } }