private void DrawPaintModeScene() { if(_selectedAttributesStore == null || _selectedAttributeData == null) { // Nothing to do if no attribute selected return; } if(!_selectedAttributesStore.HasMeshForPainting()) { // Painting requires a mesh so nothing to do return; } if (!_mouseWithinSceneView) { return; } float brushRadius = GetBrushRadius(); // TODO: use Handles.DrawingScope Color originalHandleColor = Handles.color; Color newHandleColor = originalHandleColor; SerializedProperty handleColorProperty = HEU_EditorUtility.GetSerializedProperty(_toolsInfoSerializedObject, "_brushHandleColor"); if(handleColorProperty != null) { newHandleColor = handleColorProperty.colorValue; } HEU_ToolsInfo.PaintMergeMode paintMergeMode = HEU_ToolsInfo.PaintMergeMode.REPLACE; SerializedProperty paintMergeProperty = HEU_EditorUtility.GetSerializedProperty(_toolsInfoSerializedObject, "_paintMergeMode"); if (paintMergeProperty != null) { paintMergeMode = (HEU_ToolsInfo.PaintMergeMode)paintMergeProperty.intValue; } SerializedProperty isPaintingProperty = HEU_EditorUtility.GetSerializedProperty(_toolsInfoSerializedObject, "_isPainting"); // Enable the mesh collider so that we can raycast to paint using brush MeshCollider collider = _selectedAttributesStore.GetPaintMeshCollider(); if (collider != null) { Ray ray = _currentCamera.ScreenPointToRay(_mousePosition); ray.origin = _currentCamera.transform.position; RaycastHit hit; if (collider.Raycast(ray, out hit, _intersectionRayLength)) { if (_currentEvent.type == EventType.ScrollWheel && _currentEvent.shift) { // Brush resize brushRadius -= _currentEvent.delta.y * _mouseWheelBrushSizeMultiplier; brushRadius = UpdateBrushSize(brushRadius); _GUIChanged = true; _currentEvent.Use(); } else if (_currentEvent.type == EventType.MouseDrag && _currentEvent.shift) { // Brush resize brushRadius += _currentEvent.delta.x * _mouseWheelBrushSizeMultiplier; brushRadius = UpdateBrushSize(brushRadius); _GUIChanged = true; _currentEvent.Use(); } else if (_currentEvent.button == 0 && !_currentEvent.shift && !_currentEvent.alt && !_currentEvent.control && !_mouseOverInfoPanel) { // Painting if (_currentEvent.type == EventType.MouseDown && !isPaintingProperty.boolValue) { PaintingStarted(isPaintingProperty); } if (isPaintingProperty.boolValue) { if(_currentEvent.type == EventType.MouseDown || _currentEvent.type == EventType.MouseDrag) { HandlePaintEvent(hit, brushRadius, paintMergeMode); _currentEvent.Use(); } } } if (!_mouseOverInfoPanel) { Handles.color = newHandleColor; Vector3 endPt = hit.point + (Vector3.Normalize(hit.normal) * brushRadius); Handles.DrawAAPolyLine(2f, new Vector3[] { hit.point, endPt }); HEU_EditorUI.DrawCircleCap(_controlID, hit.point, Quaternion.FromToRotation(Vector3.forward, hit.normal), brushRadius); } } } switch (_currentEvent.type) { case EventType.MouseDown: { // Don't use event here as it will ignore mouse camera controls break; } case EventType.MouseUp: { if (_currentEvent.button == 0) { if(!_currentEvent.shift && !_currentEvent.alt && !_currentEvent.control) { if (isPaintingProperty != null && isPaintingProperty.boolValue) { _currentEvent.Use(); } PaintingFinished(isPaintingProperty); } } break; } case EventType.MouseMove: { // Use the mouse move event will force a repaint allowing for much more responsive UI _currentEvent.Use(); break; } case EventType.Layout: { // This disables deselection on asset while in Edit mode HandleUtility.AddDefaultControl(_controlID); break; } case EventType.Repaint: { break; } } Handles.color = originalHandleColor; }
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; } } }