//This helps keep the size consistent no matter how far we are from it. float GetDistanceMultiplier() { if (mainTargetRoot == null) { return(0f); } return(Mathf.Max(.01f, Mathf.Abs(ExtVector3.MagnitudeInDirection(pivotPoint - transform.position, myCamera.transform.forward)))); }
//Assumes the point is already on the line somewhere public static Vector3 ClampToSegment(Vector3 point, Vector3 linePoint1, Vector3 linePoint2) { Vector3 lineDirection = linePoint2 - linePoint1; if (!ExtVector3.IsInDirection(point - linePoint1, lineDirection)) { point = linePoint1; } else if (ExtVector3.IsInDirection(point - linePoint2, lineDirection)) { point = linePoint2; } return(point); }
int AxisDirectionMultiplier(Vector3 direction, Vector3 otherDirection) { return(ExtVector3.IsInDirection(direction, otherDirection) ? 1 : -1); }
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(); }
IEnumerator TransformSelected(TransformType transType) { isTransforming = true; totalRotationAmount = Quaternion.identity; var originalPivot = pivotPoint; var axis = GetNearAxisDirection(out var otherAxis1, out var otherAxis2); var planeNormal = hasTranslatingAxisPlane ? axis : (transform.position - originalPivot).normalized; var projectedAxis = Vector3.ProjectOnPlane(axis, planeNormal).normalized; var previousMousePosition = Vector3.zero; var currentSnapMovementAmount = Vector3.zero; var currentSnapRotationAmount = 0f; 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) { switch (transType) { case 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); } break; case 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); } break; } } previousMousePosition = mousePosition; yield return(null); } totalRotationAmount = Quaternion.identity; isTransforming = false; SetTranslatingAxis(transformType, Axis.None); SetPivotPoint(); }
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(); }
IEnumerator PRTransform() { _isTransforming = true; TransformationHandleName = Manager.Instance.GET_COLLIDER_NAME; // Define what axis to project on string transformType = Manager.Instance.GET_COLLIDER_TAG; Vector3 translateAxis = GetTranslateAxis(); Plane translatePlane = GetTranslatePlane(); Vector3 savedProjectedOnPlane = translatePlane.ClosestPointOnPlane(_savedHitLoc); Quaternion quaSavedRotation = mainTargetRoot.localRotation; // Scale save Vector3 savedScale = mainTargetRoot.localScale; Vector3 scaleAxis = GetScaleAxis(); Vector3 scaleAxisLocal = GetScaleAxisLocal(); GameObject scaleCube = null; Vector3 scaleCubeLoc = Vector3.zero; Vector3 scaleCubeScale = Vector3.zero; // Edges and Vertices. PRGeo geo = mainTargetRoot.gameObject.GetComponent <PRGeo>(); if (Manager.Instance.GET_COLLIDER_TAG == "GizmoScale" || Manager.Instance.GET_COLLIDER_TAG == "GizmoScaleCenter") { scaleCube = Manager.Instance.GET_COLLIDER_GO; scaleCubeLoc = scaleCube.transform.position; scaleCubeScale = scaleCube.transform.localScale; // Unparent the edges to avoid deforming the edges whne the geometry is scaled. geo.PR_EDGE_GO.GetComponent <ParentEdge>().UnparentEdges(); // Unparent vertices geo.PR_VERTEX_GO.GetComponent <ParentVertex>().UnparentVertices(); } while (!InputUp) { if (transformType == "GizmoMove") { //Debug.Log("Move"); // Project float moveAmount = ExtVector3.MagnitudeInDirection(manipulationVec, translateAxis) * MoveMultiplier; for (int i = 0; i < targetRootsOrdered.Count; i++) { Transform target = targetRootsOrdered[i]; // Save target position, in worder to add the movement Vector. Translate gives a continuos transformation. Vector3 targetSavedPos = targetRootsOrderedSavedPos[i]; target.position = targetSavedPos + translateAxis * moveAmount; if (target.tag == "PREdge" || target.tag == "PRFace" || target.tag == "PRVertex") { target.transform.parent.parent.GetComponent <PRGeo>().EdgeDimTempParet.SetActive(true); } } } else if (transformType == "GizmoPlaneMove") { //Debug.Log("PlaneMove"); // Project the Manipulation vector onto the plane. Vector3 projectedOnPlane = Vector3.ProjectOnPlane(manipulationVec, translatePlane.normal); // Apply the projected manipulation vector for movement. for (int i = 0; i < targetRootsOrdered.Count; i++) { Transform target = targetRootsOrdered[i]; // Save target position, in worder to add the movement Vector. Translate gives a continuos transformation. Vector3 targetSavedPos = targetRootsOrderedSavedPos[i]; target.position = targetSavedPos + projectedOnPlane * MoveMultiplier; } } else if (transformType == "GizmoRotate" && Manager.Instance.SelectedGeoCO.GeoModeActive) { // Don't allow any rotation if I am not in the GeoMode. //Debug.Log("Rotate"); // Get the world location of the manipolation in respect to the savedHit location. Vector3 worldManip = savedProjectedOnPlane + manipulationVec; // Project the worlManip to the translatePlane which has Gizmo coordinates. Vector3 projectedOnPlane = translatePlane.ClosestPointOnPlane(worldManip); // Get the quaterion with rotation between the savedHit and the actualHit that have the origin as the 0,0,0 coordinate, and not the gizmo. Quaternion quaRotation = Quaternion.FromToRotation(savedProjectedOnPlane - GizmoGo.transform.position, projectedOnPlane - GizmoGo.transform.position); // Apply quaternion. for (int i = 0; i < targetRootsOrdered.Count; i++) { Transform target = targetRootsOrdered[i]; if (space == TransformSpace.Global) { target.rotation = quaRotation * quaSavedRotation; // Update the Gizmo rotation while doing the global rotation. GizmoGo.transform.rotation = quaRotation; } else if (space == TransformSpace.Local) { target.localRotation = quaRotation * quaSavedRotation; } } } else if (transformType == "GizmoScale") { //Debug.Log("Scale"); float scaleAmount = ExtVector3.MagnitudeInDirection(manipulationVec, scaleAxis) * ScaleMultiplier; for (int i = 0; i < targetRootsOrdered.Count; i++) { Transform target = targetRootsOrdered[i]; target.localScale = savedScale + scaleAxis * scaleAmount; // Update the Gizmo position for scale cubes and scale rects. scaleCube.transform.position = scaleCubeLoc + (scaleAxisLocal * scaleAmount); } // Turn ON edge dimentions geo.EdgeDimTempParet.SetActive(true); } else if (transformType == "GizmoScaleCenter") { // Get the porjection of the manipulation vector on the predifined plane during manipulation start. Vector3 closest = _scale3DPlane.ClosestPointOnPlane(GizmoGo.transform.position + manipulationVec); float magScale = 0; // To have the scale go both ways (larger and smaller) check the angle between manipulation vector and plane normal. if (Vector3.Angle(_scale3DPlane.normal, manipulationVec) < 90) { magScale = (closest - (GizmoGo.transform.position + manipulationVec)).magnitude * ScaleMultiplier; } else { magScale = -(closest - (GizmoGo.transform.position + manipulationVec)).magnitude * ScaleMultiplier; } for (int i = 0; i < targetRootsOrdered.Count; i++) { Transform target = targetRootsOrdered[i]; target.localScale = savedScale + new Vector3(magScale, magScale, magScale); // Update the Gizmo position for scale cubes and scale rects. scaleCube.transform.localScale = scaleCubeScale + new Vector3(magScale, magScale, magScale) * 2; } // Turn ON edge dimentions geo.EdgeDimTempParet.SetActive(true); } // Update the Gizmo location while doing the global rotation. GizmoGo.transform.position = mainTargetRoot.transform.position; yield return(null); } // Reset scale elements. if (scaleCube) { // Turn ON edge dimentions geo.EdgeDimTempParet.SetActive(false); // Parent the edges and vertices back to the geometry, after the scale is finished. geo.PR_EDGE_GO.GetComponent <ParentEdge>().ParentEdges(); geo.PR_VERTEX_GO.GetComponent <ParentVertex>().ParentVertices(); scaleCube.transform.position = scaleCubeLoc; scaleCube.transform.localScale = scaleCubeScale; } if (mainTargetRoot.tag == "PREdge" || mainTargetRoot.tag == "PRFace" || mainTargetRoot.tag == "PRVertex") { mainTargetRoot.transform.parent.parent.GetComponent <PRGeo>().EdgeDimTempParet.SetActive(false); } _isTransforming = false; }
IEnumerator TransformSelected(TransformType type) { isTransforming = true; totalScaleAmount = 0; totalRotationAmount = Quaternion.identity; Vector3 originalTargetPosition = target.position; Vector3 planeNormal = (transform.position - target.position).normalized; Vector3 axis = GetSelectedAxisDirection(); Vector3 projectedAxis = Vector3.ProjectOnPlane(axis, planeNormal).normalized; Vector3 previousMousePosition = Vector3.zero; while (!Input.GetMouseButtonUp(0)) { Ray mouseRay = myCamera.ScreenPointToRay(Input.mousePosition); Vector3 mousePosition = Geometry.LinePlaneIntersect(mouseRay.origin, mouseRay.direction, originalTargetPosition, planeNormal); if (previousMousePosition != Vector3.zero && mousePosition != Vector3.zero) { if (type == TransformType.Move) { float moveAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projectedAxis) * moveSpeedMultiplier; target.Translate(axis * moveAmount, Space.World); } if (type == TransformType.Scale) { Vector3 projected = (selectedAxis == 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 && selectedAxis != Axis.Any) ? target.InverseTransformDirection(axis) : axis; if (selectedAxis == Axis.Any) { target.localScale += (ExtVector3.Abs(target.localScale.normalized) * scaleAmount); } else { target.localScale += (localAxis * scaleAmount); } totalScaleAmount += scaleAmount; } if (type == TransformType.Rotate) { if (selectedAxis == Axis.Any) { Vector3 rotation = transform.TransformDirection(new Vector3(Input.GetAxis("Mouse Y"), -Input.GetAxis("Mouse X"), 0)); target.Rotate(rotation * allRotateSpeedMultiplier, Space.World); totalRotationAmount *= Quaternion.Euler(rotation * allRotateSpeedMultiplier); } else { Vector3 projected = (selectedAxis == Axis.Any || ExtVector3.IsParallel(axis, planeNormal)) ? planeNormal : Vector3.Cross(axis, planeNormal); float rotateAmount = (ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projected) * rotateSpeedMultiplier) / GetDistanceMultiplier(); target.Rotate(axis, rotateAmount, Space.World); totalRotationAmount *= Quaternion.Euler(axis * rotateAmount); } } } previousMousePosition = mousePosition; yield return(null); } totalRotationAmount = Quaternion.identity; totalScaleAmount = 0; isTransforming = false; }
IEnumerator TransformSelected(TransformType transType) { isTransforming = true; totalScaleAmount = 0; totalRotationAmount = Quaternion.identity; Vector3 originalPivot = pivotPoint; Vector3 axis = GetNearAxisDirection(out Vector3 otherAxis1, out Vector3 otherAxis2); Vector3 planeNormal = hasTranslatingAxisPlane ? axis : (transform.position - originalPivot).normalized; Vector3 projectedAxis = Vector3.ProjectOnPlane(axis, planeNormal).normalized; Vector3 previousMousePosition = Vector3.zero; Vector3 currentSnapMovementAmount = Vector3.zero; 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 (transType == TransformType.Move) { Vector3 movement; if (hasTranslatingAxisPlane) { movement = mousePosition - previousMousePosition; } else { float moveAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projectedAxis) * moveSpeedMultiplier; movement = axis * moveAmount; } Vector3 movementPerSecond = movement / Time.deltaTime; movementPerSecond = movementPerSecond.normalized * Mathf.Min(movementPerSecond.magnitude, maxMovePerSecond); movement = movementPerSecond * Time.deltaTime; for (int i = 0; i < targetRootsOrdered.Count; i++) { Transform target = targetRootsOrdered[i]; target.Translate(movement, Space.World); } SetPivotPointOffset(movement); } } previousMousePosition = mousePosition; yield return(null); } totalRotationAmount = Quaternion.identity; totalScaleAmount = 0; isTransforming = false; SetTranslatingAxis(transformType, Axis.None); SetPivotPoint(); }