void DrawHandle(int i) { Vector3 handlePosition = MathUtility.TransformPoint(bezierPath[i], creator.transform, bezierPath.Space); float anchorHandleSize = GetHandleDiameter(globalDisplaySettings.anchorSize * data.bezierHandleScale, bezierPath[i]); float controlHandleSize = GetHandleDiameter(globalDisplaySettings.controlSize * data.bezierHandleScale, bezierPath[i]); bool isAnchorPoint = i % 3 == 0; bool isInteractive = isAnchorPoint || bezierPath.ControlPointMode != BezierPath.ControlMode.Automatic; float handleSize = (isAnchorPoint) ? anchorHandleSize : controlHandleSize; bool doTransformHandle = i == handleIndexToDisplayAsTransform; PathHandle.HandleColours handleColours = (isAnchorPoint) ? splineAnchorColours : splineControlColours; if (i == handleIndexToDisplayAsTransform) { handleColours.defaultColour = (isAnchorPoint) ? globalDisplaySettings.anchorSelected : globalDisplaySettings.controlSelected; } var cap = capFunctions[(isAnchorPoint) ? globalDisplaySettings.anchorShape : globalDisplaySettings.controlShape]; PathHandle.HandleInputType handleInputType; handlePosition = PathHandle.DrawHandle(handlePosition, bezierPath.Space, isInteractive, handleSize, cap, handleColours, out handleInputType, i); if (doTransformHandle) { // Show normals rotate tool if (data.showNormals && Tools.current == Tool.Rotate && isAnchorPoint && bezierPath.Space == PathSpace.xyz) { Handles.color = handlesStartCol; int attachedControlIndex = (i == bezierPath.NumPoints - 1) ? i - 1 : i + 1; Vector3 dir = (bezierPath[attachedControlIndex] - handlePosition).normalized; float handleRotOffset = (360 + bezierPath.GlobalNormalsAngle) % 360; anchorAngleHandle.radius = handleSize * 3; anchorAngleHandle.angle = handleRotOffset + bezierPath.GetAnchorNormalAngle(i / 3); Vector3 handleDirection = Vector3.Cross(dir, Vector3.up); Matrix4x4 handleMatrix = Matrix4x4.TRS( handlePosition, Quaternion.LookRotation(handleDirection, dir), Vector3.one ); using (new Handles.DrawingScope(handleMatrix)) { // draw the handle EditorGUI.BeginChangeCheck(); anchorAngleHandle.DrawHandle(); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(creator, "Set angle"); bezierPath.SetAnchorNormalAngle(i / 3, anchorAngleHandle.angle - handleRotOffset); } } } else { handlePosition = Handles.DoPositionHandle(handlePosition, Quaternion.identity); } } switch (handleInputType) { case PathHandle.HandleInputType.LMBDrag: draggingHandleIndex = i; handleIndexToDisplayAsTransform = -1; Repaint(); break; case PathHandle.HandleInputType.LMBRelease: draggingHandleIndex = -1; handleIndexToDisplayAsTransform = -1; Repaint(); break; case PathHandle.HandleInputType.LMBClick: draggingHandleIndex = -1; if (Event.current.shift) { handleIndexToDisplayAsTransform = -1; // disable move tool if new point added } else { if (handleIndexToDisplayAsTransform == i) { handleIndexToDisplayAsTransform = -1; // disable move tool if clicking on point under move tool } else { handleIndexToDisplayAsTransform = i; } } Repaint(); break; case PathHandle.HandleInputType.LMBPress: if (handleIndexToDisplayAsTransform != i) { handleIndexToDisplayAsTransform = -1; Repaint(); } break; } Vector3 localHandlePosition = MathUtility.InverseTransformPoint(handlePosition, creator.transform, bezierPath.Space); if (bezierPath[i] != localHandlePosition) { Undo.RecordObject(creator, "Move point"); bezierPath.MovePoint(i, localHandlePosition); } }
void DrawHandle(int i) { Vector3 handlePosition = bezierPath[i]; float anchorHandleSize = GetHandleDiameter(globalDisplaySettings.anchorSize * data.bezierHandleScale, bezierPath[i]); float controlHandleSize = GetHandleDiameter(globalDisplaySettings.controlSize * data.bezierHandleScale, bezierPath[i]); bool isAnchorPoint = i % 3 == 0; bool isInteractive = isAnchorPoint || bezierPath.ControlPointMode != BezierPath.ControlMode.Automatic; float handleSize = (isAnchorPoint) ? anchorHandleSize : controlHandleSize; bool doTransformHandle = i == handleIndexToDisplayAsTransform; PathHandle.HandleColours handleColours = (isAnchorPoint) ? splineAnchorColours : splineControlColours; if (i == handleIndexToDisplayAsTransform) { handleColours.defaultColour = (isAnchorPoint) ? globalDisplaySettings.anchorSelected : globalDisplaySettings.controlSelected; } var cap = capFunctions[(isAnchorPoint) ? globalDisplaySettings.anchorShape : globalDisplaySettings.controlShape]; PathHandle.HandleInputType handleInputType; handlePosition = PathHandle.DrawHandle(handlePosition, bezierPath.Space, isInteractive, handleSize, cap, handleColours, out handleInputType, i); if (doTransformHandle) { // Show normals rotate tool if (data.showNormals && Tools.current == Tool.Rotate && isAnchorPoint && bezierPath.Space == PathSpace.xyz) { Handles.color = handlesStartCol; int attachedControlIndex = (i == bezierPath.NumPoints - 1) ? i - 1 : i + 1; Vector3 dir = (bezierPath[attachedControlIndex] - handlePosition).normalized; float handleRotOffset = (360 + bezierPath.GlobalNormalsAngle) % 360; anchorAngleHandle.radius = handleSize * 3; anchorAngleHandle.angle = handleRotOffset + bezierPath.GetAnchorNormalAngle(i / 3); Vector3 handleDirection = Vector3.Cross(dir, Vector3.up); Matrix4x4 handleMatrix = Matrix4x4.TRS( handlePosition, Quaternion.LookRotation(handleDirection, dir), Vector3.one ); using (new Handles.DrawingScope(handleMatrix)) { // draw the handle EditorGUI.BeginChangeCheck(); anchorAngleHandle.DrawHandle(); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(creator, "Set angle"); bezierPath.SetAnchorNormalAngle(i / 3, anchorAngleHandle.angle - handleRotOffset); } } } else { handlePosition = Handles.DoPositionHandle(handlePosition, Quaternion.identity); } } switch (handleInputType) { case PathHandle.HandleInputType.LMBDrag: draggingHandleIndex = i; handleIndexToDisplayAsTransform = -1; Repaint(); break; case PathHandle.HandleInputType.LMBRelease: draggingHandleIndex = -1; handleIndexToDisplayAsTransform = -1; Repaint(); break; case PathHandle.HandleInputType.LMBClick: if (Event.current.shift) { handleIndexToDisplayAsTransform = -1; // disable move tool if new point added } else { if (handleIndexToDisplayAsTransform == i) { handleIndexToDisplayAsTransform = -1; // disable move tool if clicking on point under move tool } else { handleIndexToDisplayAsTransform = i; } } Repaint(); break; case PathHandle.HandleInputType.LMBPress: if (handleIndexToDisplayAsTransform != i) { handleIndexToDisplayAsTransform = -1; Repaint(); } break; } if (bezierPath[i] != handlePosition) { Undo.RecordObject(creator, "Move point"); bezierPath.MovePoint(i, handlePosition); // If the use is holding alt, try and mirror the control point. if (Event.current.modifiers == EventModifiers.Alt) { // 0 = Anchor, 1 = Left Control, 2 = Right Control var pointType = i % 3; // If we are selecting a control point if (pointType != 0) { // If we are selecting the left control point if (pointType == 2) { // If the path doesn't loop and the user is selecting the last control point there isn't a control point to mirror if (i < bezierPath.NumPoints - 2 && !bezierPath.IsClosed) { return; } // Get the index of this control's anchor. var anchorIndex = (i + 1) % bezierPath.NumPoints; var anchorPoint = bezierPath[anchorIndex]; // Get the index of the anchors other control. // We don't have to loop this index b/c if it's the last control, it's anchors index will be 1. var otherControlPointIndex = anchorIndex + 1; // Move the other control point to the opposite of the selected control point's position relative to it's anchor. bezierPath.MovePoint(otherControlPointIndex, anchorPoint - (handlePosition - anchorPoint)); } // If we are selecting the right control point else if (pointType == 1) { // If the path doesn't loop and the user is selecting the first control point there isn't a control point to mirror. if (i > 1 && !bezierPath.IsClosed) { return; } // Get the index of this control's anchor. var anchorIndex = i - 1; var anchorPoint = bezierPath[anchorIndex]; // Get the index of the anchors other control. var otherControlPointIndex = anchorIndex - 1; // Make sure to loop this index back around if it is < 1. if (otherControlPointIndex < 0) { otherControlPointIndex = bezierPath.NumPoints - Mathf.Abs(otherControlPointIndex); } // Move the other control point to the opposite of the selected control point's position relative to it's anchor. bezierPath.MovePoint(otherControlPointIndex, anchorPoint - (handlePosition - anchorPoint)); } } } } }