public override void OnSceneGUI(SceneView sceneView, Event e) { base.OnSceneGUI(sceneView, e); // Allow the base logic to calculate first // If any points are selected let the handles move them if (pointSelected > -1) { EditorGUI.BeginChangeCheck(); // Display a handle and allow the user to determine a new position in world space Vector3 newWorldPosition = Handles.PositionHandle(points[pointSelected], Quaternion.identity); if (EditorGUI.EndChangeCheck()) { Vector3 newPosition = newWorldPosition; Vector3 accumulatedDelta = newPosition - startPosition; if (CurrentSettings.PositionSnappingEnabled) { float snapDistance = CurrentSettings.PositionSnapDistance; accumulatedDelta = MathHelper.RoundVector3(accumulatedDelta, snapDistance); } newPosition = startPosition + accumulatedDelta; points[pointSelected] = newPosition; e.Use(); } } // First let's see if we can select any existing points if (e.type == EventType.MouseDown || e.type == EventType.MouseUp) { if (!EditorHelper.IsMousePositionNearSceneGizmo(e.mousePosition)) { OnMouseSelection(sceneView, e); } } if (e.button == 0 && e.type == EventType.MouseDrag && !CameraPanInProgress) { planeEstablished = false; } // Forward specific events on to handlers if (e.type == EventType.MouseDown || e.type == EventType.MouseUp || e.type == EventType.MouseDrag || e.type == EventType.MouseMove) { if (sceneView.camera.orthographic && EditorHelper.GetSceneViewCamera(sceneView) != EditorHelper.SceneViewCamera.Other) { OnMouseActionOrthographic(sceneView, e); } else { OnMouseAction3D(sceneView, e); } } else if (e.type == EventType.Repaint || e.type == EventType.Layout) { OnRepaint(sceneView, e); } else if (e.type == EventType.KeyDown || e.type == EventType.KeyUp) { OnKeyAction(sceneView, e); } }
// Select any vertices void OnMouseUp(SceneView sceneView, Event e) { if (e.button == 0 && !CameraPanInProgress) { Transform sceneViewTransform = sceneView.camera.transform; Vector3 sceneViewPosition = sceneViewTransform.position; if (moveInProgress) { } else { if (isMarqueeSelection) // Marquee vertex selection { selectedEdges.Clear(); isMarqueeSelection = false; marqueeEnd = e.mousePosition; foreach (PrimitiveBrush brush in targetBrushes) { Polygon[] polygons = brush.GetPolygons(); for (int i = 0; i < polygons.Length; i++) { Polygon polygon = polygons[i]; for (int j = 0; j < polygon.Vertices.Length; j++) { Vertex vertex = polygon.Vertices[j]; Vector3 worldPosition = brush.transform.TransformPoint(vertex.Position); Vector3 screenPoint = sceneView.camera.WorldToScreenPoint(worldPosition); // Point is contained within marquee box if (SabreMouse.MarqueeContainsPoint(marqueeStart, marqueeEnd, screenPoint)) { if (EnumHelper.IsFlagSet(e.modifiers, EventModifiers.Control)) { // Only when holding control should a deselection occur from a valid point selectedVertices.Remove(vertex); } else { // Point was in marquee (and ctrl wasn't held) so select it! if (!selectedVertices.ContainsKey(vertex)) { selectedVertices.Add(vertex, brush); } } } else if (!EnumHelper.IsFlagSet(e.modifiers, EventModifiers.Control) && !EnumHelper.IsFlagSet(e.modifiers, EventModifiers.Shift)) { selectedVertices.Remove(vertex); } } } } SceneView.RepaintAll(); } else if (!EditorHelper.IsMousePositionInInvalidRects(e.mousePosition) && !marqueeCancelled) // Clicking style vertex selection { Vector2 mousePosition = e.mousePosition; bool clickedAnyPoints = false; // Vertex closestVertexFound = null; Vector3 closestVertexWorldPosition = Vector3.zero; float closestDistanceSquare = float.PositiveInfinity; foreach (PrimitiveBrush brush in targetBrushes) { Polygon[] polygons = brush.GetPolygons(); for (int i = 0; i < polygons.Length; i++) { Polygon polygon = polygons[i]; for (int j = 0; j < polygon.Vertices.Length; j++) { Vertex vertex = polygon.Vertices[j]; Vector3 worldPosition = brush.transform.TransformPoint(vertex.Position); float vertexDistanceSquare = (sceneViewPosition - worldPosition).sqrMagnitude; if (EditorHelper.InClickZone(mousePosition, worldPosition) && vertexDistanceSquare < closestDistanceSquare) { // closestVertexFound = vertex; closestVertexWorldPosition = worldPosition; clickedAnyPoints = true; closestDistanceSquare = vertexDistanceSquare; } } } } if (!EnumHelper.IsFlagSet(e.modifiers, EventModifiers.Control) && !EnumHelper.IsFlagSet(e.modifiers, EventModifiers.Shift)) { ClearSelection(); } foreach (PrimitiveBrush brush in targetBrushes) { Polygon[] polygons = brush.GetPolygons(); for (int i = 0; i < polygons.Length; i++) { Polygon polygon = polygons[i]; for (int j = 0; j < polygon.Vertices.Length; j++) { Vertex vertex = polygon.Vertices[j]; Vector3 worldPosition = brush.transform.TransformPoint(vertex.Position); if (clickedAnyPoints && worldPosition == closestVertexWorldPosition) { if (EnumHelper.IsFlagSet(e.modifiers, EventModifiers.Control)) { if (!selectedVertices.ContainsKey(vertex)) { selectedVertices.Add(vertex, brush); } else { selectedVertices.Remove(vertex); } } else { if (!selectedVertices.ContainsKey(vertex)) { selectedVertices.Add(vertex, brush); } } } else if (!EnumHelper.IsFlagSet(e.modifiers, EventModifiers.Control) && !EnumHelper.IsFlagSet(e.modifiers, EventModifiers.Shift)) { selectedVertices.Remove(vertex); } } } } if (!clickedAnyPoints) // Couldn't click any directly, next try to click an edge { Edge selectedEdge = null; Vector3 selectedEdgeWorldPosition1 = Vector3.zero; Vector3 selectedEdgeWorldPosition2 = Vector3.zero; // Used to track the closest edge clicked, so if we could click through several edges with // one click, then we only count the closest float closestFound = float.PositiveInfinity; foreach (PrimitiveBrush brush in targetBrushes) { Polygon[] polygons = brush.GetPolygons(); for (int i = 0; i < polygons.Length; i++) { Polygon polygon = polygons[i]; for (int j = 0; j < polygon.Vertices.Length; j++) { Vector3 worldPoint1 = brush.transform.TransformPoint(polygon.Vertices[j].Position); Vector3 worldPoint2 = brush.transform.TransformPoint(polygon.Vertices[(j + 1) % polygon.Vertices.Length].Position); // Distance from the mid point of the edge to the camera float squareDistance = (Vector3.Lerp(worldPoint1, worldPoint2, 0.5f) - Camera.current.transform.position).sqrMagnitude; float screenDistance = HandleUtility.DistanceToLine(worldPoint1, worldPoint2); if (screenDistance < EDGE_SCREEN_TOLERANCE && squareDistance < closestFound) { selectedEdgeWorldPosition1 = worldPoint1; selectedEdgeWorldPosition2 = worldPoint2; selectedEdge = new Edge(polygon.Vertices[j], polygon.Vertices[(j + 1) % polygon.Vertices.Length]); closestFound = squareDistance; } } } } List <Vertex> newSelectedVertices = new List <Vertex>(); if (selectedEdge != null) { newSelectedVertices.Add(selectedEdge.Vertex1); newSelectedVertices.Add(selectedEdge.Vertex2); selectedEdges.Add(selectedEdge); foreach (PrimitiveBrush brush in targetBrushes) { Polygon[] polygons = brush.GetPolygons(); for (int i = 0; i < polygons.Length; i++) { Polygon polygon = polygons[i]; for (int j = 0; j < polygon.Vertices.Length; j++) { Vertex vertex = polygon.Vertices[j]; Vector3 worldPosition = brush.transform.TransformPoint(vertex.Position); if (worldPosition == selectedEdgeWorldPosition1 || worldPosition == selectedEdgeWorldPosition2) { if (!selectedVertices.ContainsKey(vertex)) { selectedVertices.Add(vertex, brush); } } } } } } } } moveInProgress = false; // Repaint all scene views to show the selection change SceneView.RepaintAll(); } if (selectedVertices.Count > 0) { e.Use(); } } }
void OnRepaint(SceneView sceneView, Event e) { if (primaryTargetBrush != null) { // Use a helper method to draw a visualisation of the clipping plane float largestExtent = GetBounds().GetLargestExtent(); float planeSize = largestExtent * 4f; // clipPlane. SabreGraphics.DrawPlane(displayPlane, planePosition, new Color(0f, 1f, 0f, .3f), new Color(1f, 0f, 0f, .3f), planeSize); // Selected brush green outline SabreCSGResources.GetSelectedBrushMaterial().SetPass(0); // Draw black lines where the clip plane intersects the brushes if (!sceneView.camera.orthographic || EditorHelper.GetSceneViewCamera(sceneView) == EditorHelper.SceneViewCamera.Other) { GL.Begin(GL.LINES); GL.Color(Color.black); foreach (PrimitiveBrush brush in targetBrushes) { Polygon[] polygons = brush.GenerateTransformedPolygons(); foreach (Polygon polygon in polygons) { Vector3 position1; Vector3 position2; if (Polygon.PlanePolygonIntersection(polygon, out position1, out position2, displayPlane)) { GL.Vertex(position1); GL.Vertex(position2); } } } GL.End(); } if (displayPoint) { Camera sceneViewCamera = sceneView.camera; SabreCSGResources.GetVertexMaterial().SetPass(0); GL.PushMatrix(); GL.LoadPixelMatrix(); GL.Begin(GL.QUADS); // Draw points in reverse order because we want the precedence to be Red, Green, Blue GL.Color(Color.blue); Vector3 target = sceneViewCamera.WorldToScreenPoint(points[2]); if (target.z > 0) { // Make it pixel perfect target = MathHelper.RoundVector3(target); SabreGraphics.DrawBillboardQuad(target, 8, 8); } GL.Color(Color.green); target = sceneViewCamera.WorldToScreenPoint(points[1]); if (target.z > 0) { // Make it pixel perfect target = MathHelper.RoundVector3(target); SabreGraphics.DrawBillboardQuad(target, 8, 8); } GL.Color(Color.red); target = sceneViewCamera.WorldToScreenPoint(points[0]); if (target.z > 0) { // Make it pixel perfect target = MathHelper.RoundVector3(target); SabreGraphics.DrawBillboardQuad(target, 8, 8); } GL.End(); GL.PopMatrix(); } } // Draw UI specific to this editor // GUI.backgroundColor = Color.red; Rect rectangle = new Rect(0, 50, 210, 130); GUIStyle toolbar = new GUIStyle(EditorStyles.toolbar); toolbar.normal.background = SabreCSGResources.ClearTexture; toolbar.fixedHeight = rectangle.height; GUILayout.Window(140006, rectangle, OnToolbarGUI, "", toolbar); }
void OnMouseAction3D(SceneView sceneView, Event e) { if (primaryTargetBrush == null || CameraPanInProgress || e.button != 0) { return; } Vector2 mousePosition = e.mousePosition; mousePosition = EditorHelper.ConvertMousePointPosition(mousePosition); Ray ray = Camera.current.ScreenPointToRay(mousePosition); float bestDistance = float.PositiveInfinity; Polygon bestPolygon = null; float testDistance; foreach (Brush brush in targetBrushes) { List <Polygon> polygons = brush.GenerateTransformedPolygons().ToList(); Polygon testPolygon = GeometryHelper.RaycastPolygons(polygons, ray, out testDistance, 0.1f); if (testPolygon != null && testDistance < bestDistance) { bestDistance = testDistance; bestPolygon = testPolygon; } } if (bestPolygon != null) { // VisualDebug.ClearAll(); // VisualDebug.AddPolygon(hitPolygon, Color.red); Vector3 hitPoint = ray.GetPoint(bestDistance); if (e.type == EventType.MouseDown || e.type == EventType.MouseMove) { if (e.type == EventType.MouseMove && planeEstablished) { return; } points[0] = hitPoint; displayPoint = true; if (CurrentSettings.PositionSnappingEnabled) { float snapDistance = CurrentSettings.PositionSnapDistance; points[0] = MathHelper.RoundVector3(points[0], snapDistance); } points[1] = points[0]; points[2] = points[0]; isFlipped = false; } else { points[1] = hitPoint; if (CurrentSettings.PositionSnappingEnabled) { float snapDistance = CurrentSettings.PositionSnapDistance; points[1] = MathHelper.RoundVector3(points[1], snapDistance); } points[2] = points[0] - bestPolygon.Plane.normal; if (e.type == EventType.MouseUp) { planeEstablished = true; if (points[1] == points[0]) { ResetTool(); } } } SceneView.RepaintAll(); } }
void OnMouseActionOrthographic(SceneView sceneView, Event e) { if (primaryTargetBrush == null || CameraPanInProgress || e.button != 0) { return; } if (EditorHelper.IsMousePositionNearSceneGizmo(e.mousePosition)) { return; } Vector2 mousePosition = e.mousePosition; mousePosition = EditorHelper.ConvertMousePointPosition(mousePosition); Ray ray = Camera.current.ScreenPointToRay(mousePosition); Plane plane = new Plane(sceneView.camera.transform.forward, primaryTargetBrushTransform.position); Vector3 worldPoint; // This is the point on the plane that is perpendicular to the camera float distance = 0; if (plane.Raycast(ray, out distance)) { worldPoint = ray.GetPoint(distance); } else { return; } if (e.type == EventType.MouseDown || e.type == EventType.MouseMove) { if (e.type == EventType.MouseMove && planeEstablished) { return; } points[0] = worldPoint; displayPoint = true; if (CurrentSettings.PositionSnappingEnabled) { float snapDistance = CurrentSettings.PositionSnapDistance; points[0] = MathHelper.RoundVector3(points[0], snapDistance); } points[1] = points[0]; points[2] = points[0]; isFlipped = false; } else { points[1] = worldPoint; if (CurrentSettings.PositionSnappingEnabled) { float snapDistance = CurrentSettings.PositionSnapDistance; points[1] = MathHelper.RoundVector3(points[1], snapDistance); } points[2] = points[0] + sceneView.camera.transform.forward; if (e.type == EventType.MouseUp) { planeEstablished = true; if (points[1] == points[0]) { ResetTool(); } } } SceneView.RepaintAll(); }
public override void OnSceneGUI(UnityEditor.SceneView sceneView, Event e) { base.OnSceneGUI(sceneView, e); // Allow the base logic to calculate first if (primaryTargetBrush != null && AnySelected) { if (startPositions.Count == 0) { foreach (KeyValuePair <Vertex, Brush> selectedVertex in selectedVertices) { startPositions.Add(selectedVertex.Key, selectedVertex.Key.Position); } } // Make the handle respect the Unity Editor's Local/World orientation mode Quaternion handleDirection = Quaternion.identity; if (Tools.pivotRotation == PivotRotation.Local) { handleDirection = primaryTargetBrush.transform.rotation; } // Grab a source point and convert from local space to world Vector3 sourceWorldPosition = GetSelectedCenter(); if (e.type == EventType.MouseUp) { Undo.RecordObjects(targetBrushTransforms, "Moved Vertices"); Undo.RecordObjects(targetBrushes, "Moved Vertices"); AutoWeld(); foreach (PrimitiveBrush brush in targetBrushes) { brush.Invalidate(true); brush.BreakTypeRelation(); } } EditorGUI.BeginChangeCheck(); // Display a handle and allow the user to determine a new position in world space Vector3 newWorldPosition = Handles.PositionHandle(sourceWorldPosition, handleDirection); if (EditorGUI.EndChangeCheck()) { Undo.RecordObjects(targetBrushTransforms, "Moved Vertices"); Undo.RecordObjects(targetBrushes, "Moved Vertices"); Vector3 deltaWorld = newWorldPosition - sourceWorldPosition; // if(deltaLocal.sqrMagnitude > 0) // { TranslateSelectedVertices(deltaWorld); isMarqueeSelection = false; moveInProgress = true; foreach (PrimitiveBrush brush in targetBrushes) { EditorUtility.SetDirty(brush); } e.Use(); // Shouldn't reset the pivot while the vertices are being manipulated, so make sure the pivot // is set to get reset at next opportunity pivotNeedsReset = true; } else { // The user is no longer moving a handle if (pivotNeedsReset) { // Pivot needs to be reset, so reset it! foreach (PrimitiveBrush brush in targetBrushes) { brush.ResetPivot(); } pivotNeedsReset = false; } startPositions.Clear(); } } if (primaryTargetBrush != null) { if (!EditorHelper.IsMousePositionNearSceneGizmo(e.mousePosition)) { if (e.type == EventType.MouseDown) { OnMouseDown(sceneView, e); } else if (e.type == EventType.MouseDrag) { OnMouseDrag(sceneView, e); } // If you mouse up on a different scene view to the one you started on it's surpressed as Ignore, when // doing marquee selection make sure to check the real type else if (e.type == EventType.MouseUp || (isMarqueeSelection && e.rawType == EventType.MouseUp)) { OnMouseUp(sceneView, e); } } } // if(e.type == EventType.Repaint) { OnRepaint(sceneView, e); } }
/// <summary> /// Called whenever the editor updates and there was an event on the scene GUI. /// </summary> /// <param name="sceneView">The scene view.</param> /// <param name="e">The event information.</param> public override void OnSceneGUI(SceneView sceneView, Event e) { // allow the base logic to calculate first. base.OnSceneGUI(sceneView, e); // we adjust the toolbar size depending on the drawing mode. switch (drawingMode) { case DrawingMode.Color: #if UNITY_2019_3_OR_NEWER toolbarHeight = 230; #else toolbarHeight = 217; #endif break; case DrawingMode.R: case DrawingMode.G: case DrawingMode.B: case DrawingMode.Alpha: #if UNITY_2019_3_OR_NEWER toolbarHeight = 138; #else toolbarHeight = 126; #endif break; } if (e.button == 0 && !EditorHelper.IsMousePositionInInvalidRects(e.mousePosition) && !EditorHelper.IsMousePositionInIMGUIRect(e.mousePosition, actualToolbarRect) && !CameraPanInProgress) { if (e.type == EventType.MouseDown) { OnMouseDown(sceneView, e); } else if (e.type == EventType.MouseDrag) { OnMouseDrag(sceneView, e); } else if (e.type == EventType.MouseMove) { OnMouseMove(sceneView, e); } // If you mouse up on a different scene view to the one you started on it's surpressed as Ignore, so // make sure to check the real type else if (e.type == EventType.MouseUp || e.rawType == EventType.MouseUp) { OnMouseUp(sceneView, e); } } if (e.type == EventType.KeyDown || e.type == EventType.KeyUp) { OnKeyAction(sceneView, e); } if (e.type == EventType.Layout || e.type == EventType.Repaint) { OnRepaint(sceneView, e); } }