Example #1
0
	private void UpdateAddMode(HEU_HoudiniAsset asset, int controlID, EventType eventType, Vector3 mousePosition, List<SerializedObject> updatedCurves)
	{
	    Event currentEvent = Event.current;

	    Color defaultHandleColor = Handles.color;

	    switch (eventType)
	    {
		case EventType.MouseDown:
		{
		    if (!currentEvent.alt && currentEvent.button == 0 && _closestCurveName != null && _closestPointIndex >= 0)
		    {
			AddPoint(_closestCurveName, _closestPointIndex, _newPointPosition, updatedCurves);
			_closestCurveName = null;

			currentEvent.Use();
		    }

		    break;
		}
		case EventType.MouseUp:
		{

		    break;
		}
		case EventType.MouseMove:
		{
		    // Use the mouse move event will force a repaint allowing for much more responsive UI
		    currentEvent.Use();
		    break;
		}
		case EventType.KeyUp:
		{
		    if (currentEvent.keyCode == KeyCode.Space && !currentEvent.alt)
		    {
			// Toggle modes
			SwitchToMode(HEU_Curve.Interaction.EDIT);
		    }
		    else if (currentEvent.keyCode == KeyCode.Escape || currentEvent.keyCode == KeyCode.Return || currentEvent.keyCode == KeyCode.KeypadEnter)
		    {
			SwitchToMode(HEU_Curve.Interaction.VIEW);
			currentEvent.Use();
		    }

		    break;
		}
		case EventType.KeyDown:
		{
		    if (currentEvent.keyCode == KeyCode.Backspace || currentEvent.keyCode == KeyCode.Delete)
		    {
			// Delete last added point
			if (_latestPointAddedCurve != null)
			{
			    HEU_Curve latestAddCurve = GetCurve(_latestPointAddedCurve);
			    if (latestAddCurve != null && _latestPointsAdded.Count > 0)
			    {
				SelectSinglePoint(latestAddCurve, _latestPointsAdded.Pop());
				DeleteSelectedPoints(updatedCurves);
			    }
			}

			currentEvent.Use();
		    }
		    else if (currentEvent.keyCode == KeyCode.A)
		    {
			int mode = (int)_newPointMode + 1;
			if (mode > (int)CurveNewPointMode.END)
			{
			    mode = (int)CurveNewPointMode.START;
			}
			_newPointMode = (CurveNewPointMode)mode;
		    }
		    else if (currentEvent.keyCode == KeyCode.F1)
		    {
			_showInfo = !_showInfo;
		    }

		    break;
		}
		case EventType.Layout:
		{
		    // This disables deselection on asset while in Add mode
		    HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));

		    break;
		}
		case EventType.Repaint:
		{
		    bool bMouseInDrawArea = HEU_GeneralUtility.IsMouseWithinSceneView(_currentCamera, mousePosition)
			    && !HEU_GeneralUtility.IsMouseOverRect(_currentCamera, mousePosition, ref _curveEditorUIRect)
			    && (!_showInfoRepaint || !HEU_GeneralUtility.IsMouseOverRect(_currentCamera, mousePosition, ref _infoRect));

		    // Plane for default collider
		    Plane collisionPlane = new Plane(Vector3.up, Vector3.zero);
		    //Ray mouseRay = _currentCamera.ScreenPointToRay(mousePosition);
		    //Vector3 planePosition = mouseRay.origin + mouseRay.direction * 100f;
		    //Plane collisionPlane = new Plane(-_currentCamera.transform.forward, planePosition);

		    HEU_Curve.CurveDrawCollision drawCollision = asset.CurveDrawCollision;
		    List<Collider> drawColliders = null;
		    LayerMask drawLayerMask = Physics.DefaultRaycastLayers;
		    if (drawCollision == HEU_Curve.CurveDrawCollision.LAYERMASK)
		    {
			drawLayerMask = asset.GetCurveDrawLayerMask();
		    }
		    else if (drawCollision == HEU_Curve.CurveDrawCollision.COLLIDERS)
		    {
			drawColliders = asset.GetCurveDrawColliders();
		    }

		    // Adding new point between line segments

		    _closestPointIndex = -1;
		    _closestCurveName = null;
		    _newPointPosition = Vector3.zero;

		    float closestDistance = float.MaxValue;

		    foreach (HEU_Curve curve in _curves)
		    {
			// Draw the cooked curve using its vertices
			DrawCurveUsingVertices(curve, _selectedCurveColor);

			DrawPointCaps(curve, _addModeDefaultPointColor);

			List<Vector3> points = curve.GetAllPoints();
			int numPoints = points.Count;

			if (_currentCamera != null && bMouseInDrawArea)
			{
			    Ray ray = _currentCamera.ScreenPointToRay(mousePosition);
			    RaycastHit[] results = null;

			    if (numPoints > 0 && (_newPointMode == CurveNewPointMode.INSIDE))
			    {
				// Control -> add point between closest line segment

				for (int i = 0; i < numPoints - 1; ++i)
				{
				    Vector3 pointPos0 = curve.GetTransformedPosition(points[i]);
				    Vector3 pointPos1 = curve.GetTransformedPosition(points[i + 1]);

				    Vector3 screenPos0 = HEU_EditorUI.GetHandleWorldToScreenPosition(pointPos0, _currentCamera);
				    Vector3 screenPos1 = HEU_EditorUI.GetHandleWorldToScreenPosition(pointPos1, _currentCamera);

				    float distance = HandleUtility.DistancePointToLineSegment(mousePosition, screenPos0, screenPos1);
				    if (distance < closestDistance)
				    {
					closestDistance = distance;
					_closestPointIndex = i + 1;
					_closestCurveName = curve.CurveName;
				    }
				}
			    }
			    else
			    {
				// Show new point from either end of curve, whichever is closest.
				// Use collision to find new point.

				Vector3 hitPoint = Vector3.zero;
				bool bHit = false;

				if (drawCollision == HEU_Curve.CurveDrawCollision.LAYERMASK)
				{
				    // Using layermask
				    RaycastHit hitInfo;
				    if (Physics.Raycast(ray, out hitInfo, _rayCastMaxDistance, drawLayerMask))
				    {
					hitPoint = hitInfo.point;
					bHit = true;
				    }
				}
				else if (drawColliders != null && drawColliders.Count > 0)
				{
				    // Using colliders
				    results = Physics.RaycastAll(ray, _rayCastMaxDistance, drawLayerMask);
				    foreach (RaycastHit hit in results)
				    {
					foreach (Collider drawCollider in drawColliders)
					{
					    if (hit.collider == drawCollider)
					    {
						hitPoint = hit.point;
						bHit = true;
						break;
					    }
					}
				    }
				}
				else
				{
				    // Using identity plane
				    float collisionEnter = 0f;
				    if (collisionPlane.Raycast(ray, out collisionEnter))
				    {
					collisionEnter = Mathf.Clamp(collisionEnter, _currentCamera.nearClipPlane, _currentCamera.farClipPlane);
					hitPoint = ray.origin + ray.direction * collisionEnter;
					bHit = true;
				    }
				}

				if (bHit)
				{
				    Vector3 hitPointScreenPosition = HEU_EditorUI.GetHandleWorldToScreenPosition(hitPoint, _currentCamera);

				    // Find the closest point to add from (either first or last point)

				    // Empty curve:
				    // If its just a single curve, we can use the hit point as closest point.
				    // For multiple curves, it gets trickier since we don't have an existing point
				    // to check for closest point. So we'll just use the parent's transform position
				    // as our anchor point.

				    Vector3 checkPoint = Vector3.zero;
				    int curveClosestPointIndex = 0;

				    if (numPoints == 0)
				    {
					if (_curves.Count > 1)
					{
					    // Multiple curves -> use position of asset
					    checkPoint = curve._targetGameObject.transform.position;
					}
					else
					{
					    // Single curve -> use hit point as closest
					    checkPoint = hitPoint;
					}
				    }
				    else if (_newPointMode == CurveNewPointMode.START)
				    {
					// Curve with at least 1 point + shift held -> use first point
					checkPoint = HEU_EditorUI.GetHandleWorldToScreenPosition(curve.GetTransformedPoint(0), _currentCamera);
					curveClosestPointIndex = 0;
				    }
				    else
				    {
					// Curve with at least 1 point -> use last point
					checkPoint = HEU_EditorUI.GetHandleWorldToScreenPosition(curve.GetTransformedPoint(numPoints - 1), _currentCamera);
					curveClosestPointIndex = numPoints;
				    }

				    float curveClosestPointDistance = Vector3.Distance(checkPoint, hitPointScreenPosition);
				    if (curveClosestPointDistance < closestDistance)
				    {
					closestDistance = curveClosestPointDistance;
					_closestPointIndex = curveClosestPointIndex;
					_closestCurveName = curve.CurveName;
					_newPointPosition = hitPoint;
				    }

				    // Snap to grid
				    _newPointPosition = HEU_EditorUI.GetSnapPosition(_newPointPosition);
				}
			    }
			}
		    }

		    // Note that curve name can be empty for valid empty curves
		    if (_closestCurveName != null && _closestPointIndex >= 0)
		    {
			HEU_Curve closestCurve = GetCurve(_closestCurveName);
			if (closestCurve != null)
			{
			    int numPoints = closestCurve.GetNumPoints();
			    if ((_newPointMode == CurveNewPointMode.INSIDE) && !currentEvent.alt && numPoints >= 2)
			    {
				// Handle adding new point at projected mouse cursor between points

				// First draw the curve line segments
				DrawCurveUsingPoints(closestCurve, Color.yellow);

				// Draw the caps again to hid the ends of line segments above (visually pleasing)
				DrawPointCaps(closestCurve, _addModeDefaultPointColor);

				Vector3 pointPos0 = closestCurve.GetTransformedPoint(_closestPointIndex - 1);
				Vector3 pointPos1 = closestCurve.GetTransformedPoint(_closestPointIndex);

				Vector3 screenPos0 = HEU_EditorUI.GetHandleWorldToScreenPosition(pointPos0, _currentCamera);
				Vector3 screenPos1 = HEU_EditorUI.GetHandleWorldToScreenPosition(pointPos1, _currentCamera);

				Vector3 curveNewPointPosition = HandleUtility.ProjectPointLine(mousePosition, screenPos0, screenPos1);

				Vector2 deltaNew = curveNewPointPosition - screenPos0;
				Vector2 deltaLine = screenPos1 - screenPos0;
				float ratio = Mathf.Clamp01(deltaNew.magnitude / deltaLine.magnitude);

				Vector3 newDir = (pointPos1 - pointPos0);
				curveNewPointPosition = pointPos0 + (newDir.normalized * newDir.magnitude * ratio);

				Handles.color = _selectedPointColor;
				HEU_EditorUI.DrawSphereCap(GUIUtility.GetControlID(FocusType.Passive), curveNewPointPosition, Quaternion.identity, HEU_EditorUI.GetHandleSize(curveNewPointPosition));

				Handles.color = Color.yellow;
				HEU_EditorUI.DrawCircleCap(0, pointPos0, Quaternion.LookRotation(_currentCamera.transform.forward), HEU_EditorUI.GetHandleSize(pointPos0));
				HEU_EditorUI.DrawCircleCap(0, pointPos1, Quaternion.LookRotation(_currentCamera.transform.forward), HEU_EditorUI.GetHandleSize(pointPos1));
				Handles.color = defaultHandleColor;

				_newPointPosition = curveNewPointPosition;

				SceneView.RepaintAll();
			    }
			    else if (!currentEvent.alt)
			    {
				// Handle adding new point at closest curve's end points

				if (closestCurve.GetNumPoints() > 0)
				{
				    // Draw dotted line from last point to newPointPosition
				    int connectionPoint = (_closestPointIndex > 0) ? _closestPointIndex - 1 : 0;
				    Vector3 pointPos0 = closestCurve.GetTransformedPoint(connectionPoint);
				    Vector3[] dottedLineSegments = new Vector3[] { pointPos0, _newPointPosition };

				    Handles.color = _dottedLineColor;
				    Handles.DrawDottedLines(dottedLineSegments, 4f);
				}

				Handles.color = _selectedPointColor;
				HEU_EditorUI.DrawSphereCap(GUIUtility.GetControlID(FocusType.Passive), _newPointPosition, Quaternion.identity, HEU_EditorUI.GetHandleSize(_newPointPosition));
				Handles.color = defaultHandleColor;

				SceneView.RepaintAll();
			    }
			}
		    }

		    break;
		}
	    }
	}