IEnumerator TransformSelected(TransformType type)
        {
            isTransforming      = true;
            totalScaleAmount    = 0;
            totalRotationAmount = Quaternion.identity;

            Vector3 originalPivot = pivotPoint;

            Vector3 planeNormal           = (transform.position - originalPivot).normalized;
            Vector3 axis                  = GetNearAxisDirection();
            Vector3 projectedAxis         = Vector3.ProjectOnPlane(axis, planeNormal).normalized;
            Vector3 previousMousePosition = Vector3.zero;

            List <ICommand> transformCommands = new List <ICommand>();

            for (int i = 0; i < targetRootsOrdered.Count; i++)
            {
                transformCommands.Add(new TransformCommand(this, targetRootsOrdered[i]));
            }

            while (!Input.GetMouseButtonUp(0))
            {
                Ray     mouseRay      = myCamera.ScreenPointToRay(Input.mousePosition);
                Vector3 mousePosition = Geometry.LinePlaneIntersect(mouseRay.origin, mouseRay.direction, originalPivot, planeNormal);

                if (previousMousePosition != Vector3.zero && mousePosition != Vector3.zero)
                {
                    if (type == TransformType.Move)
                    {
                        float   moveAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projectedAxis) * moveSpeedMultiplier;
                        Vector3 movement   = axis * moveAmount;

                        for (int i = 0; i < targetRootsOrdered.Count; i++)
                        {
                            Transform target = targetRootsOrdered[i];

                            target.Translate(movement, Space.World);
                        }

                        SetPivotPointOffset(movement);
                    }
                    else if (type == TransformType.Scale)
                    {
                        Vector3 projected   = (nearAxis == Axis.Any) ? transform.right : projectedAxis;
                        float   scaleAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projected) * scaleSpeedMultiplier;

                        //WARNING - There is a bug in unity 5.4 and 5.5 that causes InverseTransformDirection to be affected by scale which will break negative scaling. Not tested, but updating to 5.4.2 should fix it - https://issuetracker.unity3d.com/issues/transformdirection-and-inversetransformdirection-operations-are-affected-by-scale
                        Vector3 localAxis = (space == TransformSpace.Local && nearAxis != Axis.Any) ? mainTargetRoot.InverseTransformDirection(axis) : axis;

                        Vector3 targetScaleAmount = Vector3.one;
                        if (nearAxis == Axis.Any)
                        {
                            targetScaleAmount = (ExtVector3.Abs(mainTargetRoot.localScale.normalized) * scaleAmount);
                        }
                        else
                        {
                            targetScaleAmount = localAxis * scaleAmount;
                        }

                        for (int i = 0; i < targetRootsOrdered.Count; i++)
                        {
                            Transform target = targetRootsOrdered[i];

                            Vector3 targetScale = target.localScale + targetScaleAmount;

                            if (pivot == TransformPivot.Pivot)
                            {
                                target.localScale = targetScale;
                            }
                            else if (pivot == TransformPivot.Center)
                            {
                                if (scaleType == ScaleType.FromPoint)
                                {
                                    target.SetScaleFrom(originalPivot, targetScale);
                                }
                                else if (scaleType == ScaleType.FromPointOffset)
                                {
                                    target.SetScaleFromOffset(originalPivot, targetScale);
                                }
                            }
                        }

                        totalScaleAmount += scaleAmount;
                    }
                    else if (type == TransformType.Rotate)
                    {
                        float   rotateAmount = 0;
                        Vector3 rotationAxis = axis;

                        if (nearAxis == Axis.Any)
                        {
                            Vector3 rotation = transform.TransformDirection(new Vector3(Input.GetAxis("Mouse Y"), -Input.GetAxis("Mouse X"), 0));
                            Quaternion.Euler(rotation).ToAngleAxis(out rotateAmount, out rotationAxis);
                            rotateAmount *= allRotateSpeedMultiplier;
                        }
                        else
                        {
                            Vector3 projected = (nearAxis == Axis.Any || ExtVector3.IsParallel(axis, planeNormal)) ? planeNormal : Vector3.Cross(axis, planeNormal);
                            rotateAmount = (ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projected) * rotateSpeedMultiplier) / GetDistanceMultiplier();
                        }

                        for (int i = 0; i < targetRootsOrdered.Count; i++)
                        {
                            Transform target = targetRootsOrdered[i];

                            if (pivot == TransformPivot.Pivot)
                            {
                                target.Rotate(rotationAxis, rotateAmount, Space.World);
                            }
                            else if (pivot == TransformPivot.Center)
                            {
                                target.RotateAround(originalPivot, rotationAxis, rotateAmount);
                            }
                        }

                        totalRotationAmount *= Quaternion.Euler(rotationAxis * rotateAmount);
                    }
                }

                previousMousePosition = mousePosition;

                yield return(null);
            }

            for (int i = 0; i < transformCommands.Count; i++)
            {
                ((TransformCommand)transformCommands[i]).StoreNewTransformValues();
            }
            CommandGroup commandGroup = new CommandGroup();

            commandGroup.Set(transformCommands);
            UndoRedoManager.Insert(commandGroup);

            totalRotationAmount = Quaternion.identity;
            totalScaleAmount    = 0;
            isTransforming      = false;

            SetPivotPoint();
        }
Example #2
0
        IEnumerator TransformSelected(TransformType transType)
        {
            isTransforming      = true;
            totalScaleAmount    = 0;
            totalRotationAmount = Quaternion.identity;

            Vector3 originalPivot = pivotPoint;
            Vector3 otherAxis1, otherAxis2;
            Vector3 axis                  = GetNearAxisDirection(out otherAxis1, out otherAxis2);
            Vector3 planeNormal           = hasTranslatingAxisPlane ? axis : (transform.position - originalPivot).normalized;
            Vector3 projectedAxis         = Vector3.ProjectOnPlane(axis, planeNormal).normalized;
            Vector3 previousMousePosition = Vector3.zero;

            Vector3 currentSnapMovementAmount = Vector3.zero;
            float   currentSnapRotationAmount = 0;
            float   currentSnapScaleAmount    = 0;

            List <ICommand> transformCommands = new List <ICommand>();

            for (int i = 0; i < targetRootsOrdered.Count; i++)
            {
                transformCommands.Add(new TransformCommand(this, targetRootsOrdered[i]));
            }

            while (!Input.GetMouseButtonUp(0))
            {
                var mouseRay      = myCamera.ScreenPointToRay(Input.mousePosition);
                var mousePosition = Geometry.LinePlaneIntersect(mouseRay.origin, mouseRay.direction, originalPivot, planeNormal);
                var isSnapping    = Input.GetKey(translationSnapping);

                if (previousMousePosition != Vector3.zero && mousePosition != Vector3.zero)
                {
                    if (transType == TransformType.Move)
                    {
                        Vector3 movement = Vector3.zero;

                        if (hasTranslatingAxisPlane)
                        {
                            movement = mousePosition - previousMousePosition;
                        }
                        else
                        {
                            float moveAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projectedAxis) * moveSpeedMultiplier;
                            movement = axis * moveAmount;
                        }

                        if (isSnapping && movementSnap > 0)
                        {
                            currentSnapMovementAmount += movement;
                            movement = Vector3.zero;

                            if (hasTranslatingAxisPlane)
                            {
                                float amountInAxis1 = ExtVector3.MagnitudeInDirection(currentSnapMovementAmount, otherAxis1);
                                float amountInAxis2 = ExtVector3.MagnitudeInDirection(currentSnapMovementAmount, otherAxis2);

                                float snapAmount1 = CalculateSnapAmount(movementSnap, amountInAxis1, out var remainder1);
                                float snapAmount2 = CalculateSnapAmount(movementSnap, amountInAxis2, out var remainder2);

                                if (snapAmount1 != 0)
                                {
                                    var snapMove = (otherAxis1 * snapAmount1);
                                    movement += snapMove;
                                    currentSnapMovementAmount -= snapMove;
                                }
                                if (snapAmount2 != 0)
                                {
                                    var snapMove = (otherAxis2 * snapAmount2);
                                    movement += snapMove;
                                    currentSnapMovementAmount -= snapMove;
                                }
                            }
                            else
                            {
                                float snapAmount = CalculateSnapAmount(movementSnap, currentSnapMovementAmount.magnitude, out var remainder);

                                if (snapAmount != 0)
                                {
                                    movement = currentSnapMovementAmount.normalized * snapAmount;
                                    currentSnapMovementAmount = currentSnapMovementAmount.normalized * remainder;
                                }
                            }
                        }

                        for (int i = 0; i < targetRootsOrdered.Count; i++)
                        {
                            Transform target = targetRootsOrdered[i];

                            target.Translate(movement, Space.World);
                        }

                        SetPivotPointOffset(movement);
                    }
                    else if (transType == TransformType.Scale)
                    {
                        Vector3 projected   = (nearAxis == Axis.Any)? transform.right : projectedAxis;
                        float   scaleAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projected) * scaleSpeedMultiplier;

                        if (isSnapping && scaleSnap > 0)
                        {
                            currentSnapScaleAmount += scaleAmount;
                            scaleAmount             = 0;

                            float snapAmount = CalculateSnapAmount(scaleSnap, currentSnapScaleAmount, out var remainder);

                            if (snapAmount != 0)
                            {
                                scaleAmount            = snapAmount;
                                currentSnapScaleAmount = remainder;
                            }
                        }

                        //WARNING - There is a bug in unity 5.4 and 5.5 that causes InverseTransformDirection to be affected by scale which will break negative scaling. Not tested, but updating to 5.4.2 should fix it - https://issuetracker.unity3d.com/issues/transformdirection-and-inversetransformdirection-operations-are-affected-by-scale
                        Vector3 localAxis = (GetProperTransformSpace() == TransformSpace.Local && nearAxis != Axis.Any)? mainTargetRoot.InverseTransformDirection(axis) : axis;

                        Vector3 targetScaleAmount = Vector3.one;
                        if (nearAxis == Axis.Any)
                        {
                            targetScaleAmount = (ExtVector3.Abs(mainTargetRoot.localScale.normalized) * scaleAmount);
                        }
                        else
                        {
                            targetScaleAmount = localAxis * scaleAmount;
                        }

                        for (int i = 0; i < targetRootsOrdered.Count; i++)
                        {
                            Transform target = targetRootsOrdered[i];

                            Vector3 targetScale = target.localScale + targetScaleAmount;

                            if (pivot == TransformPivot.Pivot)
                            {
                                target.localScale = targetScale;
                            }
                            else if (pivot == TransformPivot.Center)
                            {
                                if (scaleType == ScaleType.FromPoint)
                                {
                                    target.SetScaleFrom(originalPivot, targetScale);
                                }
                                else if (scaleType == ScaleType.FromPointOffset)
                                {
                                    target.SetScaleFromOffset(originalPivot, targetScale);
                                }
                            }
                        }

                        totalScaleAmount += scaleAmount;
                    }
                    else if (transType == TransformType.Rotate)
                    {
                        float   rotateAmount = 0;
                        Vector3 rotationAxis = axis;

                        if (nearAxis == Axis.Any)
                        {
                            Vector3 rotation = transform.TransformDirection(new Vector3(Input.GetAxis("Mouse Y"), -Input.GetAxis("Mouse X"), 0));
                            Quaternion.Euler(rotation).ToAngleAxis(out rotateAmount, out rotationAxis);
                            rotateAmount *= allRotateSpeedMultiplier;
                        }
                        else
                        {
                            if (circularRotationMethod)
                            {
                                float angle = Vector3.SignedAngle(previousMousePosition - originalPivot, mousePosition - originalPivot, axis);
                                rotateAmount = angle * rotateSpeedMultiplier;
                            }
                            else
                            {
                                Vector3 projected = (nearAxis == Axis.Any || ExtVector3.IsParallel(axis, planeNormal))? planeNormal : Vector3.Cross(axis, planeNormal);
                                rotateAmount = (ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projected) * (rotateSpeedMultiplier * 100f)) / GetDistanceMultiplier();
                            }
                        }

                        if (isSnapping && rotationSnap > 0)
                        {
                            currentSnapRotationAmount += rotateAmount;
                            rotateAmount = 0;

                            float snapAmount = CalculateSnapAmount(rotationSnap, currentSnapRotationAmount, out var remainder);

                            if (snapAmount != 0)
                            {
                                rotateAmount = snapAmount;
                                currentSnapRotationAmount = remainder;
                            }
                        }

                        for (int i = 0; i < targetRootsOrdered.Count; i++)
                        {
                            Transform target = targetRootsOrdered[i];

                            if (pivot == TransformPivot.Pivot)
                            {
                                target.Rotate(rotationAxis, rotateAmount, Space.World);
                            }
                            else if (pivot == TransformPivot.Center)
                            {
                                target.RotateAround(originalPivot, rotationAxis, rotateAmount);
                            }
                        }

                        totalRotationAmount *= Quaternion.Euler(rotationAxis * rotateAmount);
                    }
                }

                previousMousePosition = mousePosition;

                yield return(null);
            }

            for (int i = 0; i < transformCommands.Count; i++)
            {
                ((TransformCommand)transformCommands[i]).StoreNewTransformValues();
            }
            CommandGroup commandGroup = new CommandGroup();

            commandGroup.Set(transformCommands);
            UndoRedoManager.Insert(commandGroup);

            totalRotationAmount = Quaternion.identity;
            totalScaleAmount    = 0;
            isTransforming      = false;
            SetTranslatingAxis(transformType, Axis.None);

            SetPivotPoint();
        }