public static void DrawLength(UnityEngine.Vector3 from, UnityEngine.Vector3 to, float forceValue) { var prevColor = SceneHandles.color; SceneHandles.color = SceneHandles.StateColor(SceneHandles.measureColor); var invMatrix = SceneHandles.inverseMatrix; var camera = UnityEngine.Camera.current; var camPos = invMatrix.MultiplyPoint(camera.transform.position); var camDir = (SceneHandleUtility.ProjectPointLine(camPos, from, to) - camPos).normalized; var delta = (to - from); var length = delta.magnitude; var forward = delta / length; var right = Vector3.Cross(forward, camDir); var fromSize = UnityEditor.HandleUtility.GetHandleSize(from); var toSize = UnityEditor.HandleUtility.GetHandleSize(to); var center = (to + from) * 0.5f; SceneHandles.DrawLine(from, to); DrawFlatArrow(from, forward, camDir, fromSize * 0.2f); DrawFlatArrow(to, -forward, camDir, toSize * 0.2f); // SceneHandles.DrawLine(from - right, from + right); // SceneHandles.DrawLine(to - right, to + right); DrawUnitLabel(center, right, 2, forceValue); SceneHandles.color = prevColor; }
public static void RenderDistance(Matrix4x4 transformation, Vector3 from, Vector3 to) { var distance = from - to; if (distance.sqrMagnitude == 0) { return; } using (new SceneHandles.DrawingScope(transformation)) { SceneHandles.DrawLine(from, to); SceneHandles.RenderBorderedDot(from, UnityEditor.HandleUtility.GetHandleSize(from) * HandleRendering.kPointScale); SceneHandles.RenderBorderedDot(to, UnityEditor.HandleUtility.GetHandleSize(to) * HandleRendering.kPointScale); } }
public static bool Radius2DHandle(Vector3 center, Vector3 up, ref Vector3 radius1, ref Vector3 radius2, float minRadius1 = 0, float minRadius2 = 0, float maxRadius1 = float.PositiveInfinity, float maxRadius2 = float.PositiveInfinity, bool renderDisc = true) { var positionId0 = GUIUtility.GetControlID(s_Radius2DHash, FocusType.Keyboard); var positionId1 = GUIUtility.GetControlID(s_Radius2DHash, FocusType.Keyboard); var positionId2 = GUIUtility.GetControlID(s_Radius2DHash, FocusType.Keyboard); var positionId3 = GUIUtility.GetControlID(s_Radius2DHash, FocusType.Keyboard); minRadius1 = Mathf.Abs(minRadius1); minRadius2 = Mathf.Abs(minRadius2); maxRadius1 = Mathf.Abs(maxRadius1); if (maxRadius1 < minRadius1) { maxRadius1 = minRadius1; } maxRadius2 = Mathf.Abs(maxRadius2); if (maxRadius2 < minRadius2) { maxRadius2 = minRadius2; } var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); var prevColor = SceneHandles.color; var prevMatrix = SceneHandles.matrix; var prevDisabled = SceneHandles.disabled; var prevChanged = GUI.changed; float size; Vector3 forward; Vector3 right; GeometryUtility.CalculateTangents(up, out right, out forward); var plane = new Plane(up, Vector3.zero); var delta1 = GeometryUtility.ProjectPointPlane(radius1 - center, plane); var delta2 = GeometryUtility.ProjectPointPlane(radius2 - center, plane); var delta1Magnitude = delta1.magnitude; var delta2Magnitude = delta2.magnitude; var delta1Normalized = (delta1Magnitude < Vector3.kEpsilon) ? Vector3.zero : (delta1 / delta1Magnitude); var delta2Normalized = (delta2Magnitude < Vector3.kEpsilon) ? Vector3.zero : (delta2 / delta2Magnitude); // useful to have when modifying the 'other' one var rotatedDelta1 = Quaternion.AngleAxis(-90, up) * delta1Normalized; var rotatedDelta2 = Quaternion.AngleAxis(90, up) * delta2Normalized; var position0 = center + delta1; var position1 = center - delta1; var position2 = center + delta2; var position3 = center - delta2; var isDisabled = isStatic || prevDisabled; SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); bool noRotation = Event.current.shift; GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position0); position0 = Slider2DHandle(positionId0, position0, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { var moveDelta = (position0 - center); Vector3 newRadius; if (noRotation) { newRadius = GeometryUtility.ProjectPointRay(center + moveDelta, center, rotatedDelta2); } else { newRadius = center + moveDelta; } var newDelta = GeometryUtility.ProjectPointPlane(newRadius - center, plane); delta1Magnitude = newDelta.magnitude; if (!noRotation && delta1Magnitude > Vector3.kEpsilon) { radius2 = center + ((Quaternion.AngleAxis(-90, up) * (newDelta / delta1Magnitude)) * delta2Magnitude); } // set this after setting radius2 since both may lead to same variable delta1 = newDelta; radius1 = newRadius; prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position1); position1 = Slider2DHandle(positionId1, position1, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { var moveDelta = (position1 - center); Vector3 newRadius; if (noRotation) { newRadius = GeometryUtility.ProjectPointRay(center - moveDelta, center, rotatedDelta2); } else { newRadius = center - moveDelta; } var newDelta = GeometryUtility.ProjectPointPlane(newRadius - center, plane); delta1Magnitude = newDelta.magnitude; if (!noRotation && delta1Magnitude > Vector3.kEpsilon) { radius2 = center + ((Quaternion.AngleAxis(-90, up) * (newDelta / delta1Magnitude)) * delta2Magnitude); } // set this after setting radius2 since both may lead to same variable delta1 = newDelta; radius1 = newRadius; prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position2); position2 = Slider2DHandle(positionId2, position2, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { var moveDelta = (position2 - center); Vector3 newRadius; if (noRotation) { newRadius = GeometryUtility.ProjectPointRay(center + moveDelta, center, rotatedDelta1); } else { newRadius = center + moveDelta; } var newDelta = GeometryUtility.ProjectPointPlane(newRadius - center, plane); delta2Magnitude = newDelta.magnitude; if (!noRotation && delta2Magnitude > Vector3.kEpsilon) { radius1 = center + ((Quaternion.AngleAxis(90, up) * (newDelta / delta2Magnitude)) * delta1Magnitude); } // set this after setting radius1 since both may lead to same variable delta2 = newDelta; radius2 = newRadius; prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position3); position3 = Slider2DHandle(positionId3, position3, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { var moveDelta = (position3 - center); Vector3 newRadius; if (noRotation) { newRadius = GeometryUtility.ProjectPointRay(center - moveDelta, center, rotatedDelta1); } else { newRadius = center - moveDelta; } var newDelta = GeometryUtility.ProjectPointPlane(newRadius - center, plane); delta2Magnitude = newDelta.magnitude; if (!noRotation && delta2Magnitude > Vector3.kEpsilon) { radius1 = center + ((Quaternion.AngleAxis(90, up) * (newDelta / delta2Magnitude)) * delta1Magnitude); } // set this after setting radius1 since both may lead to same variable delta2 = newDelta; radius2 = newRadius; prevChanged = true; } GUI.changed |= prevChanged; if (delta1Magnitude < minRadius1 || delta1Magnitude > maxRadius1) { if (delta2Magnitude < minRadius2 || delta2Magnitude > maxRadius2) { delta1Magnitude = Mathf.Max(minRadius1, Mathf.Min(delta1Magnitude, maxRadius1)); delta2Magnitude = Mathf.Max(minRadius2, Mathf.Min(delta2Magnitude, maxRadius2)); delta1Normalized = right; delta2Normalized = up; delta1 = GeometryUtility.ProjectPointPlane(delta1Normalized * delta1Magnitude, plane); delta2 = GeometryUtility.ProjectPointPlane(delta2Normalized * delta2Magnitude, plane); rotatedDelta2 = delta2Normalized; rotatedDelta1 = delta1Normalized; radius1 = center + delta1; radius2 = center + delta2; GUI.changed = true; } else { delta1Magnitude = Mathf.Max(minRadius1, Mathf.Min(delta1Magnitude, maxRadius1)); delta1Normalized = rotatedDelta2; delta1 = GeometryUtility.ProjectPointPlane(delta1Normalized * delta1Magnitude, plane); radius1 = center + delta1; GUI.changed = true; } } else if (delta2Magnitude < minRadius2 || delta2Magnitude > maxRadius2) { delta2Magnitude = Mathf.Max(minRadius2, Mathf.Min(delta2Magnitude, maxRadius2)); delta2Normalized = rotatedDelta1; delta2 = delta2Normalized * delta2Magnitude; radius2 = center + delta2; GUI.changed = true; } if (Event.current.type == EventType.Repaint) { isDisabled = isStatic || prevDisabled || (Snapping.AxisLocking[0] && Snapping.AxisLocking[1]); SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); if (delta1Magnitude > Vector3.kEpsilon && delta2Magnitude > Vector3.kEpsilon) { var ellipsis = Matrix4x4.TRS(center, Quaternion.identity, Vector3.one); ellipsis.m00 = delta1.x; ellipsis.m10 = delta1.y; ellipsis.m20 = delta1.z; ellipsis.m01 = delta2.x; ellipsis.m11 = delta2.y; ellipsis.m21 = delta2.z; ellipsis.m02 = up.x; ellipsis.m12 = up.y; ellipsis.m22 = up.z; ellipsis *= Matrix4x4.TRS(-center, Quaternion.identity, Vector3.one); var newMatrix = prevMatrix * ellipsis; SceneHandles.matrix = newMatrix; if (renderDisc) { SceneHandles.DrawWireDisc(center, Vector3.forward, 1.0f); } } else if (delta1Magnitude > Vector3.kEpsilon) { SceneHandles.DrawLine(position0, position1); } else if (delta2Magnitude > Vector3.kEpsilon) { SceneHandles.DrawLine(position2, position3); } } SceneHandles.disabled = prevDisabled; SceneHandles.matrix = prevMatrix; SceneHandles.color = prevColor; var focus = SceneHandleUtility.focusControl; return((focus == positionId0) || (focus == positionId1) || (focus == positionId2) || (focus == positionId3)); }
public static void DrawLengths(Bounds bounds, Axes activeAxes = Axes.XYZ, Axes visibleAxes = Axes.XYZ, Axes selectedAxes = Axes.None) { // TODO: what if camera is inside of bounds? // TODO: what if length is outside of camera, but other option is inside of camera view? // TODO: don't make the side lines move around when resizing, be smarter about handlesize // -> maybe limit the projected line to the screen? var invMatrix = SceneHandles.inverseMatrix; var prevColor = SceneHandles.color; var color = prevColor; var color2 = color; color2.a *= 0.5f; var camera = UnityEngine.Camera.current; var camPos = invMatrix.MultiplyPoint(camera.transform.position); var lengthX = bounds.size.x; var lengthY = bounds.size.y; var lengthZ = bounds.size.z; var absLengthX = Mathf.Abs(lengthX); var absLengthY = Mathf.Abs(lengthY); var absLengthZ = Mathf.Abs(lengthZ); var delta = (bounds.center - camPos) * 2; var dotX = delta.x < 0 ? -1 : 1; var dotY = delta.y < 0 ? -1 : 1; var dotZ = delta.z < 0 ? -1 : 1; var insideX = (delta.x >= -absLengthX && delta.x <= absLengthX); var insideY = (delta.y >= -absLengthY && delta.y <= absLengthY); var insideZ = (delta.z >= -absLengthZ && delta.z <= absLengthZ); bool showX = !(insideY && insideZ); bool showY = !(insideX && insideZ); bool showZ = !(insideX && insideY); Vector3 fromX, toX; Vector3 fromY, toY; Vector3 fromZ, toZ; var min = bounds.min; var max = bounds.max; // min/max of bounds can potentially be inverted min.x = Mathf.Min(min.x, max.x); min.y = Mathf.Min(min.y, max.y); min.z = Mathf.Min(min.z, max.z); fromX = min; toX = fromX + new Vector3(absLengthX, 0, 0); fromY = min; toY = fromY + new Vector3(0, absLengthY, 0); fromZ = min; toZ = fromZ + new Vector3(0, 0, absLengthZ); var signZ = Vector3.one; if (showZ) { bool swapX = (dotX > 0) ^ insideY; bool swapY = (dotY < 0) ^ insideY; signZ.x = swapX ? 1 : -1; signZ.y = swapY ? 1 : -1; var ofsX = swapX ? absLengthX : 0; fromZ.x += ofsX; toZ.x += ofsX; var ofsY = swapY ? absLengthY : 0; fromZ.y += ofsY; toZ.y += ofsY; } var signY = Vector3.one; if (showY) { bool swapX = (dotX > 0) ^ insideZ; bool swapZ = (dotZ < 0); signY.x = swapX ? 1 : -1; signY.z = swapZ ? 1 : -1; var ofsX = swapX ? absLengthX : 0; fromY.x += ofsX; toY.x += ofsX; var ofsZ = swapZ ? absLengthZ : 0; fromY.z += ofsZ; toY.z += ofsZ; } var signX = Vector3.one; if (showX) { bool swapY = (dotY > 0) ^ insideZ; bool swapZ = (dotZ < 0); signX.y = swapY ? 1 : -1; signX.z = swapZ ? 1 : -1; var ofsY = swapY ? absLengthY : 0; fromX.y += ofsY; toX.y += ofsY; var ofsZ = swapZ ? absLengthZ : 0; fromX.z += ofsZ; toX.z += ofsZ; } var lineHandleX = SceneHandleUtility.ProjectPointLine(camPos, fromX, toX); var lineHandleY = SceneHandleUtility.ProjectPointLine(camPos, fromY, toY); var lineHandleZ = SceneHandleUtility.ProjectPointLine(camPos, fromZ, toZ); var lineOfsX = (UnityEditor.HandleUtility.GetHandleSize(lineHandleX) * 0.25f); var lineOfsY = (UnityEditor.HandleUtility.GetHandleSize(lineHandleY) * 0.25f); var lineOfsZ = (UnityEditor.HandleUtility.GetHandleSize(lineHandleZ) * 0.25f); var angleX = lineHandleX - camPos; var angleY = lineHandleY - camPos; var angleZ = lineHandleZ - camPos; var directionX = Mathf.Abs(angleX.y) <= Mathf.Abs(angleX.z); var directionY = Mathf.Abs(angleY.x) <= Mathf.Abs(angleY.z); var directionZ = Mathf.Abs(angleZ.y) <= Mathf.Abs(angleZ.x); var disabled = SceneHandles.disabled; const int labelPadding = 2; if (showX && ((visibleAxes & Axes.X) == Axes.X)) { var axisDisabled = ((activeAxes & Axes.X) != Axes.X) || disabled; var selected = ((selectedAxes & Axes.X) == Axes.X) && !axisDisabled; var offsetY = new Vector3(0, (lineOfsY * signX.y), 0); var offsetZ = new Vector3(0, 0, (lineOfsZ * signX.z)); var offset = directionX ? offsetY : offsetZ; var fromOfs = fromX + offset; var toOfs = toX + offset; var camDir = SceneHandleUtility.ProjectPointLine(camPos, fromOfs, toOfs) - camPos; var fromSize = Mathf.Min(absLengthX / 3.0f, UnityEditor.HandleUtility.GetHandleSize(fromOfs) * 0.2f); var toSize = Mathf.Min(absLengthX / 3.0f, UnityEditor.HandleUtility.GetHandleSize(toOfs) * 0.2f); var center = (toOfs + fromOfs) * 0.5f; SceneHandles.color = SceneHandles.StateColor(color2, axisDisabled, selected); SceneHandles.DrawLine(fromX, fromOfs); SceneHandles.DrawLine(toX, toOfs); SceneHandles.color = SceneHandles.StateColor(color, axisDisabled, selected); SceneHandles.DrawLine(fromOfs, toOfs); DrawFlatArrow(fromOfs, Vector3.right, camDir, fromSize); DrawFlatArrow(toOfs, -Vector3.right, camDir, toSize); DrawUnitLabel(center, offset, labelPadding, lengthX, "X"); } if (showY && ((visibleAxes & Axes.Y) == Axes.Y)) { var axisDisabled = ((activeAxes & Axes.Y) != Axes.Y) || disabled; var selected = ((selectedAxes & Axes.Y) == Axes.Y) && !axisDisabled; var offsetX = new Vector3((lineOfsX * signY.x), 0, 0); var offsetZ = new Vector3(0, 0, (lineOfsZ * signY.z)); var offset = directionY ? offsetX : offsetZ; var fromOfs = fromY + offset; var toOfs = toY + offset; var camDir = SceneHandleUtility.ProjectPointLine(camPos, fromOfs, toOfs) - camPos; var fromSize = Mathf.Min(absLengthY / 3.0f, UnityEditor.HandleUtility.GetHandleSize(fromOfs) * 0.2f); var toSize = Mathf.Min(absLengthY / 3.0f, UnityEditor.HandleUtility.GetHandleSize(toOfs) * 0.2f); var center = (toOfs + fromOfs) * 0.5f; SceneHandles.color = SceneHandles.StateColor(color2, axisDisabled, selected); SceneHandles.DrawLine(fromY, fromOfs); SceneHandles.DrawLine(toY, toOfs); SceneHandles.color = SceneHandles.StateColor(color, axisDisabled, selected); SceneHandles.DrawLine(fromOfs, toOfs); DrawFlatArrow(fromOfs, Vector3.up, camDir, fromSize); DrawFlatArrow(toOfs, -Vector3.up, camDir, toSize); DrawUnitLabel(center, offset, labelPadding, lengthY, "Y"); } if (showZ && ((visibleAxes & Axes.Z) == Axes.Z)) { var axisDisabled = ((activeAxes & Axes.Z) != Axes.Z) || disabled; var selected = ((selectedAxes & Axes.Z) == Axes.Z) && !axisDisabled; var offsetX = new Vector3((lineOfsX * signZ.x), 0, 0); var offsetY = new Vector3(0, (lineOfsY * signZ.y), 0); var offset = directionZ ? offsetY : offsetX; var fromOfs = fromZ + offset; var toOfs = toZ + offset; var camDir = SceneHandleUtility.ProjectPointLine(camPos, fromOfs, toOfs) - camPos; var fromSize = Mathf.Min(absLengthZ / 3.0f, UnityEditor.HandleUtility.GetHandleSize(fromOfs) * 0.2f); var toSize = Mathf.Min(absLengthZ / 3.0f, UnityEditor.HandleUtility.GetHandleSize(toOfs) * 0.2f); var center = (toOfs + fromOfs) * 0.5f; SceneHandles.color = SceneHandles.StateColor(color2, axisDisabled, selected); SceneHandles.DrawLine(fromZ, fromOfs); SceneHandles.DrawLine(toZ, toOfs); SceneHandles.color = SceneHandles.StateColor(color, axisDisabled, selected); SceneHandles.DrawLine(fromOfs, toOfs); DrawFlatArrow(fromOfs, Vector3.forward, camDir, fromSize); DrawFlatArrow(toOfs, -Vector3.forward, camDir, toSize); DrawUnitLabel(center, offset, labelPadding, lengthZ, "Z"); } SceneHandles.color = prevColor; }