void OnDisable() { s_Instance = null; VertexManipulationTool.beforeMeshModification -= BeforeMeshModification; VertexManipulationTool.afterMeshModification -= AfterMeshModification; if (s_EditorToolbar != null) { DestroyImmediate(s_EditorToolbar); } ClearElementSelection(); UpdateSelection(); if (selectionUpdated != null) { selectionUpdated(null); } SceneView.duringSceneGui -= OnSceneGUI; ProGridsInterface.UnsubscribePushToGridEvent(PushToGrid); ProGridsInterface.UnsubscribeToolbarEvent(ProGridsToolbarOpen); MeshSelection.objectSelectionChanged -= OnObjectSelectionChanged; SetOverrideWireframe(false); if (selectModeChanged != null) { selectModeChanged(SelectMode.Object); } SceneView.RepaintAll(); }
void ProGridsToolbarOpen(bool menuOpen) { bool active = ProGridsInterface.ProGridsActive(); m_SceneInfoRect.y = active && !menuOpen ? 28 : 10; m_SceneInfoRect.x = active ? (menuOpen ? 64 : 8) : 10; }
void OnDisable() { VertexManipulationTool.beforeMeshModification -= BeforeMeshModification; VertexManipulationTool.afterMeshModification -= AfterMeshModification; ClearElementSelection(); UpdateSelection(); if (selectionUpdated != null) { selectionUpdated(null); } SceneView.duringSceneGui -= OnSceneGUI; ProGridsInterface.UnsubscribePushToGridEvent(PushToGrid); ProGridsInterface.UnsubscribeToolbarEvent(ProGridsToolbarOpen); MeshSelection.objectSelectionChanged -= OnObjectSelectionChanged; SetOverrideWireframe(false); m_Toolbar.Dispose(); if (m_ToolManager != null) { m_ToolManager.Dispose(); } OnSelectModeChanged(); ProBuilderToolManager.selectModeChanged -= OnSelectModeChanged; SceneView.RepaintAll(); if (s_Instance == this) { s_Instance = null; } }
void OnEnable() { s_Instance = this; #if UNITY_2019_1_OR_NEWER SceneView.duringSceneGui += OnSceneGUI; #else SceneView.onSceneGUIDelegate += OnSceneGUI; #endif ProGridsInterface.SubscribePushToGridEvent(PushToGrid); ProGridsInterface.SubscribeToolbarEvent(ProGridsToolbarOpen); MeshSelection.objectSelectionChanged += OnObjectSelectionChanged; ProGridsToolbarOpen(ProGridsInterface.SceneToolbarIsExtended()); #if !UNITY_2018_2_OR_NEWER s_ResetOnSceneGUIState = typeof(SceneView).GetMethod("ResetOnSceneGUIState", BindingFlags.Instance | BindingFlags.NonPublic); #endif VertexManipulationTool.beforeMeshModification += BeforeMeshModification; VertexManipulationTool.afterMeshModification += AfterMeshModification; LoadSettings(); InitGUI(); UpdateSelection(); SetOverrideWireframe(true); if (selectModeChanged != null) { selectModeChanged(selectMode); } }
void OnEnable() { // maximize does this weird crap where it doesn't disable or enable windows in the current layout when // entering or exiting maximized mode, but _does_ Enable/Disable the new maximized window instance. when // that happens the ProBuilderEditor loses the s_Instance due to that maximized instance taking over. // so in order to prevent the problems that occur when multiple instances of ProBuilderEditor, instead // ensure that there is always one true instance. we'll also skip initializing what are basically singleton // managers as well (ex, tool manager) if (s_Instance == null) { s_Instance = this; } ProBuilderToolManager.selectModeChanged += OnSelectModeChanged; m_Toolbar = new EditorToolbar(this); m_ToolManager = s_Instance == this ? new ProBuilderToolManager() : null; SceneView.duringSceneGui += OnSceneGUI; ProGridsInterface.SubscribePushToGridEvent(PushToGrid); ProGridsInterface.SubscribeToolbarEvent(ProGridsToolbarOpen); MeshSelection.objectSelectionChanged += OnObjectSelectionChanged; ProGridsToolbarOpen(ProGridsInterface.SceneToolbarIsExtended()); VertexManipulationTool.beforeMeshModification += BeforeMeshModification; VertexManipulationTool.afterMeshModification += AfterMeshModification; LoadSettings(); InitGUI(); EditorApplication.delayCall += () => UpdateSelection(); SetOverrideWireframe(true); selectMode = s_LastActiveSelectMode; }
void SetupInputPlane(Vector2 mousePosition) { m_Plane = EditorHandleUtility.FindBestPlane(mousePosition); if (ProGridsInterface.SnapEnabled()) { m_Plane.SetNormalAndPosition( m_Plane.normal, ProGridsInterface.ProGridsSnap(m_Plane.normal * -m_Plane.distance)); } var planeNormal = m_Plane.normal; var planeCenter = m_Plane.normal * -m_Plane.distance; // if hit point on plane is cardinal axis and on grid, snap to grid. if (Math.IsCardinalAxis(planeNormal)) { const float epsilon = .00001f; float snapVal = Mathf.Abs(ProGridsInterface.SnapValue()); float rem = Mathf.Abs(snapVal - (Vector3.Scale(planeNormal, planeCenter).magnitude % snapVal)); polygon.isOnGrid = (rem < epsilon || Mathf.Abs(snapVal - rem) < epsilon); } else { polygon.isOnGrid = false; } }
void OnEnable() { s_Instance = this; SceneView.duringSceneGui += OnSceneGUI; ProGridsInterface.SubscribePushToGridEvent(PushToGrid); ProGridsInterface.SubscribeToolbarEvent(ProGridsToolbarOpen); MeshSelection.objectSelectionChanged += OnObjectSelectionChanged; ProGridsToolbarOpen(ProGridsInterface.SceneToolbarIsExtended()); VertexManipulationTool.beforeMeshModification += BeforeMeshModification; VertexManipulationTool.afterMeshModification += AfterMeshModification; ToolManager.activeToolChanged += ActiveToolChanged; LoadSettings(); InitGUI(); EditorApplication.delayCall += () => UpdateSelection(); SetOverrideWireframe(true); if (selectModeChanged != null) { selectModeChanged(selectMode); } }
/// <summary> /// Snap a Vector3 to the nearest point on the current ProGrids grid if ProGrids is enabled. /// </summary> /// <param name="point"></param> /// <returns></returns> public static float ProGridsSnap(float point) { if (GetProGridsType() == null) return point; if (SnapEnabled()) return Snapping.SnapValue(point, ProGridsInterface.SnapValue()); return point; }
void SetPolyEditMode(PolyShape.PolyEditMode mode) { PolyShape.PolyEditMode old = polygon.polyEditMode; if (mode != old) { // Clear the control always GUIUtility.hotControl = 0; // Entering edit mode after the shape has been finalized once before, which means // possibly reverting manual changes. Store undo state so that if this was // not intentional user can revert. if (polygon.polyEditMode == PolyShape.PolyEditMode.None && polygon.m_Points.Count > 2) { if (ProBuilderEditor.instance != null) { ProBuilderEditor.instance.ClearElementSelection(); } UndoUtility.RecordObject(polygon, "Edit Polygon Shape"); UndoUtility.RecordObject(polygon.mesh, "Edit Polygon Shape"); } polygon.polyEditMode = mode; if (polygon.polyEditMode == PolyShape.PolyEditMode.None) { ProBuilderEditor.selectMode = ProBuilderEditor.selectMode & ~(SelectMode.InputTool); } else { ProBuilderEditor.selectMode = ProBuilderEditor.selectMode | SelectMode.InputTool; } if (polygon.polyEditMode != PolyShape.PolyEditMode.None) { Tools.current = Tool.None; } // If coming from Path -> Height set the mouse / origin offset if (old == PolyShape.PolyEditMode.Path && mode == PolyShape.PolyEditMode.Height && Event.current != null) { Vector3 up = polygon.transform.up; Vector3 origin = polygon.transform.TransformPoint(Math.Average(polygon.m_Points)); Ray r = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); Vector3 p = Math.GetNearestPointRayRay(origin, up, r.origin, r.direction); s_HeightMouseOffset = polygon.extrude - ProGridsInterface.ProGridsSnap( Vector3.Distance(origin, p) * Mathf.Sign(Vector3.Dot(p - origin, up))); } RebuildPolyShapeMesh(polygon); } }
// Returns a local space point, Vector3 GetPointInLocalSpace(Vector3 point) { var trs = polygon.transform; if (polygon.isOnGrid) { Vector3 snapMask = ProBuilderSnapping.GetSnappingMaskBasedOnNormalVector(m_Plane.normal); return(trs.InverseTransformPoint(ProGridsInterface.ProGridsSnap(point, snapMask))); } return(trs.InverseTransformPoint(point)); }
/// <summary> /// Snap a Vector3 to the nearest point on the current ProGrids grid if ProGrids is enabled, with mask. /// </summary> /// <param name="point"></param> /// <param name="mask"></param> /// <returns></returns> public static Vector3 ProGridsSnap(Vector3 point, Vector3 mask) { if (GetProGridsType() == null) return point; if (ProGridsInterface.SnapEnabled()) { float snap = ProGridsInterface.SnapValue(); return Snapping.SnapValue(point, mask * snap); } return point; }
protected override void OnToolEngaged() { // If grids are enabled and "snap on all axes" is on, initialize active axes to all. m_ActiveAxesModel = progridsSnapEnabled && !snapAxisConstraint ? Vector3Mask.XYZ : new Vector3Mask(0x0); #if PROBUILDER_ENABLE_TRANSFORM_ORIGIN_GIZMO m_DirectionOriginInitialized = false; #endif m_SnapAsGroup = progridsSnapEnabled && ProGridsInterface.GetProGridsSnapAsGroup(); }
/// <summary> /// Snap a Vector3 to the nearest point on the current ProGrids grid if ProGrids is enabled. /// </summary> /// <param name="point"></param> /// <returns></returns> public static float ProGridsSnap(float point) { if (GetProGridsType() == null) { return(point); } if (SnapEnabled()) { return(ProBuilderSnapping.SnapValue(point, ProGridsInterface.SnapValue())); } return(point); }
public static Vector3 ProGridsSnap(Vector3 point, Vector3 mask) { if (GetProGridsType() == null) { return(point); } if (ProGridsInterface.SnapEnabled()) { float snap = ProGridsInterface.SnapValue(); return(ProBuilderSnapping.Snap(point, mask * snap)); } return(point); }
internal static void SetPivotLocationAndSnap(ProBuilderMesh mesh) { if (ProGridsInterface.SnapEnabled()) { mesh.transform.position = Snapping.SnapValue(mesh.transform.position, ProGridsInterface.SnapValue()); } else if (s_SnapNewShapesToGrid) { mesh.transform.position = Snapping.SnapValue(mesh.transform.position, new Vector3( EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ"))); } mesh.Optimize(); }
void OnDisable() { s_Instance = null; VertexManipulationTool.beforeMeshModification -= BeforeMeshModification; VertexManipulationTool.afterMeshModification -= AfterMeshModification; if (s_EditorToolbar != null) { DestroyImmediate(s_EditorToolbar); } ClearElementSelection(); UpdateSelection(); if (selectionUpdated != null) { selectionUpdated(null); } #if UNITY_2019_1_OR_NEWER SceneView.duringSceneGui -= OnSceneGUI; #else SceneView.onSceneGUIDelegate -= OnSceneGUI; #endif ProGridsInterface.UnsubscribePushToGridEvent(PushToGrid); ProGridsInterface.UnsubscribeToolbarEvent(ProGridsToolbarOpen); MeshSelection.objectSelectionChanged -= OnObjectSelectionChanged; // re-enable unity wireframe // todo set wireframe override in pb_Selection, no pb_Editor foreach (var pb in FindObjectsOfType <ProBuilderMesh>()) { EditorUtility.SetSelectionRenderState(pb.gameObject.GetComponent <Renderer>(), EditorUtility.GetSelectionRenderState()); } if (selectModeChanged != null) { selectModeChanged(SelectMode.Object); } SceneView.RepaintAll(); }
protected void BeginEdit(string undoMessage) { if (m_IsEditing) { return; } // Disable iterative lightmapping Lightmapping.PushGIWorkflowMode(); var selection = MeshSelection.topInternal.ToArray(); UndoUtility.RegisterCompleteObjectUndo(selection, string.IsNullOrEmpty(undoMessage) ? "Modify Vertices" : undoMessage); if (beforeMeshModification != null) { beforeMeshModification(selection); } if (currentEvent.shift) { Extrude(); } m_IsEditing = true; m_ProgridsSnapEnabled = ProGridsInterface.SnapEnabled(); m_ProgridsSnapValue = ProGridsInterface.SnapValue(); m_SnapAxisConstraint = ProGridsInterface.UseAxisConstraints(); foreach (var mesh in selection) { mesh.ToMesh(); mesh.Refresh(); } OnToolEngaged(); }
void DoExistingPointsGUI() { Transform trs = polygon.transform; int len = polygon.m_Points.Count; Vector3 up = polygon.transform.up; Vector3 right = polygon.transform.right; Vector3 forward = polygon.transform.forward; Vector3 center = Vector3.zero; Event evt = Event.current; bool used = evt.type == EventType.Used; if (!used && (evt.type == EventType.MouseDown && evt.button == 0 && !EditorHandleUtility.IsAppendModifier(evt.modifiers))) { m_SelectedIndex = -1; Repaint(); } if (polygon.polyEditMode == PolyShape.PolyEditMode.Height) { if (!used && evt.type == EventType.MouseUp && evt.button == 0 && !EditorHandleUtility.IsAppendModifier(evt.modifiers)) { evt.Use(); SetPolyEditMode(PolyShape.PolyEditMode.Edit); } bool sceneInUse = EditorHandleUtility.SceneViewInUse(evt); Ray r = HandleUtility.GUIPointToWorldRay(evt.mousePosition); Vector3 origin = polygon.transform.TransformPoint(Math.Average(polygon.m_Points)); float extrude = polygon.extrude; if (evt.type == EventType.MouseMove && !sceneInUse) { Vector3 p = Math.GetNearestPointRayRay(origin, up, r.origin, r.direction); extrude = ProGridsInterface.ProGridsSnap(s_HeightMouseOffset + Vector3.Distance(origin, p) * Mathf.Sign(Vector3.Dot(p - origin, up))); } Vector3 extrudePoint = origin + (extrude * up); Handles.color = k_HandleColor; Handles.DotHandleCap(-1, origin, Quaternion.identity, HandleUtility.GetHandleSize(origin) * k_HandleSize, evt.type); Handles.color = k_HandleColorGreen; Handles.DrawLine(origin, extrudePoint); Handles.DotHandleCap(-1, extrudePoint, Quaternion.identity, HandleUtility.GetHandleSize(extrudePoint) * k_HandleSize, evt.type); Handles.color = Color.white; if (!sceneInUse && polygon.extrude != extrude) { OnBeginVertexMovement(); polygon.extrude = extrude; RebuildPolyShapeMesh(false); } } else { // vertex dots for (int ii = 0; ii < len; ii++) { Vector3 point = trs.TransformPoint(polygon.m_Points[ii]); center.x += point.x; center.y += point.y; center.z += point.z; float size = HandleUtility.GetHandleSize(point) * k_HandleSize; Handles.color = ii == m_SelectedIndex ? k_HandleSelectedColor : k_HandleColor; EditorGUI.BeginChangeCheck(); point = Handles.Slider2D(point, up, right, forward, size, Handles.DotHandleCap, Vector2.zero, true); if (EditorGUI.EndChangeCheck()) { UndoUtility.RecordObject(polygon, "Move Polygon Shape Point"); Vector3 snapMask = Snapping.GetSnappingMaskBasedOnNormalVector(m_Plane.normal); polygon.m_Points[ii] = ProGridsInterface.ProGridsSnap(trs.InverseTransformPoint(point), snapMask); OnBeginVertexMovement(); RebuildPolyShapeMesh(false); } // "clicked" a button if (!used && evt.type == EventType.Used) { if (ii == 0 && polygon.m_Points.Count > 2 && polygon.polyEditMode == PolyShape.PolyEditMode.Path) { m_NextMouseUpAdvancesMode = true; return; } else { used = true; m_SelectedIndex = ii; } } } Handles.color = Color.white; // height setting if (polygon.polyEditMode != PolyShape.PolyEditMode.Path && polygon.m_Points.Count > 2) { center.x /= (float)len; center.y /= (float)len; center.z /= (float)len; Vector3 extrude = center + (up * polygon.extrude); m_DistanceFromHeightHandle = Vector2.Distance(HandleUtility.WorldToGUIPoint(extrude), evt.mousePosition); EditorGUI.BeginChangeCheck(); Handles.color = k_HandleColor; Handles.DotHandleCap(-1, center, Quaternion.identity, HandleUtility.GetHandleSize(center) * k_HandleSize, evt.type); Handles.DrawLine(center, extrude); Handles.color = k_HandleColorGreen; extrude = Handles.Slider(extrude, up, HandleUtility.GetHandleSize(extrude) * k_HandleSize, Handles.DotHandleCap, 0f); Handles.color = Color.white; if (EditorGUI.EndChangeCheck()) { UndoUtility.RecordObject(polygon, "Set Polygon Shape Height"); polygon.extrude = ProGridsInterface.ProGridsSnap(Vector3.Distance(extrude, center) * Mathf.Sign(Vector3.Dot(up, extrude - center))); OnBeginVertexMovement(); RebuildPolyShapeMesh(false); } } } }
void DoPointPlacement() { Event evt = Event.current; EventType eventType = evt.type; if (m_PlacingPoint) { Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition); if (eventType == EventType.MouseDrag) { float hitDistance = Mathf.Infinity; if (m_Plane.Raycast(ray, out hitDistance)) { evt.Use(); polygon.m_Points[m_SelectedIndex] = ProGridsInterface.ProGridsSnap(polygon.transform.InverseTransformPoint(ray.GetPoint(hitDistance)), Vector3.one); RebuildPolyShapeMesh(false); SceneView.RepaintAll(); } } if (eventType == EventType.MouseUp || eventType == EventType.Ignore || eventType == EventType.KeyDown || eventType == EventType.KeyUp) { evt.Use(); m_PlacingPoint = false; m_SelectedIndex = -1; SceneView.RepaintAll(); } } else if (polygon.polyEditMode == PolyShape.PolyEditMode.Path) { if (eventType == EventType.MouseDown) { if (polygon.m_Points.Count < 1) { SetupInputPlane(evt.mousePosition); } float hitDistance = Mathf.Infinity; Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition); if (m_Plane.Raycast(ray, out hitDistance)) { UndoUtility.RecordObject(polygon, "Add Polygon Shape Point"); Vector3 hit = ray.GetPoint(hitDistance); if (polygon.m_Points.Count < 1) { polygon.transform.position = polygon.isOnGrid ? ProGridsInterface.ProGridsSnap(hit) : hit; polygon.transform.rotation = Quaternion.LookRotation(m_Plane.normal) * Quaternion.Euler(new Vector3(90f, 0f, 0f)); } Vector3 point = ProGridsInterface.ProGridsSnap(polygon.transform.InverseTransformPoint(hit), Vector3.one); if (polygon.m_Points.Count > 2 && Math.Approx3(polygon.m_Points[0], point)) { m_NextMouseUpAdvancesMode = true; return; } polygon.m_Points.Add(point); m_PlacingPoint = true; m_SelectedIndex = polygon.m_Points.Count - 1; RebuildPolyShapeMesh(polygon); evt.Use(); } } } else if (polygon.polyEditMode == PolyShape.PolyEditMode.Edit) { if (polygon.m_Points.Count < 3) { SetPolyEditMode(PolyShape.PolyEditMode.Path); return; } if (m_DistanceFromHeightHandle > PreferenceKeys.k_MaxPointDistanceFromControl) { // point insertion int index; float distanceToLine; Vector3 p = EditorHandleUtility.ClosestPointToPolyLine(polygon.m_Points, out index, out distanceToLine, true, polygon.transform); Vector3 wp = polygon.transform.TransformPoint(p); Vector2 ga = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[index % polygon.m_Points.Count])); Vector2 gb = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[(index - 1)])); Vector2 mouse = evt.mousePosition; float distanceToVertex = Mathf.Min(Vector2.Distance(mouse, ga), Vector2.Distance(mouse, gb)); if (distanceToVertex > PreferenceKeys.k_MaxPointDistanceFromControl && distanceToLine < PreferenceKeys.k_MaxPointDistanceFromControl) { Handles.color = Color.green; Handles.DotHandleCap(-1, wp, Quaternion.identity, HandleUtility.GetHandleSize(wp) * k_HandleSize, evt.type); if (evt.type == EventType.MouseDown) { evt.Use(); UndoUtility.RecordObject(polygon, "Insert Point"); polygon.m_Points.Insert(index, p); m_SelectedIndex = index; m_PlacingPoint = true; RebuildPolyShapeMesh(true); OnBeginVertexMovement(); } Handles.color = Color.white; } } } }
public override void OnInspectorGUI() { if (!m_IsEditing) { if (GUILayout.Button("Edit Bezier Shape")) { SetIsEditing(true); } EditorGUILayout.HelpBox("Editing a Bezier Shape will erase any modifications made to the mesh!\n\nIf you accidentally enter Edit Mode you can Undo to get your changes back.", MessageType.Warning); return; } if (GUILayout.Button("Editing Bezier Shape", UI.EditorGUIUtility.GetActiveStyle("Button"))) { SetIsEditing(false); } Event e = Event.current; if (m_IsMoving) { if (e.type == EventType.Ignore || e.type == EventType.MouseUp) { OnFinishVertexModification(); } } EditorGUI.BeginChangeCheck(); bool handleIsValid = (m_currentHandle > -1 && m_currentHandle < m_Points.Count); BezierPoint inspectorPoint = handleIsValid ? m_Points[m_currentHandle] : new BezierPoint(Vector3_Zero, Vector3_Backward, Vector3_Forward, Quaternion.identity); inspectorPoint = DoBezierPointGUI(inspectorPoint); if (handleIsValid && EditorGUI.EndChangeCheck()) { if (!m_IsMoving) { OnBeginVertexModification(); } m_Points[m_currentHandle] = inspectorPoint; UpdateMesh(false); } EditorGUI.BeginChangeCheck(); if (GUILayout.Button("Clear Points")) { UndoUtility.RecordObject(m_Target, "Clear Bezier Spline Points"); m_Points.Clear(); UpdateMesh(true); } if (GUILayout.Button("Add Point")) { UndoUtility.RecordObject(m_Target, "Add Bezier Spline Point"); if (m_Points.Count > 0) { m_Points.Add(new BezierPoint(m_Points[m_Points.Count - 1].position, m_Points[m_Points.Count - 1].tangentIn, m_Points[m_Points.Count - 1].tangentOut, Quaternion.identity)); UpdateMesh(true); } else { m_Target.Init(); } m_currentHandle = (BezierHandle)(m_Points.Count - 1); SceneView.RepaintAll(); } GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); m_TangentMode = (BezierTangentMode)GUILayout.Toolbar((int)m_TangentMode, s_TangentModeIcons, commandStyle); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); m_CloseLoop = EditorGUILayout.Toggle("Close Loop", m_CloseLoop); m_Smooth = EditorGUILayout.Toggle("Smooth", m_Smooth); m_Radius = Mathf.Max(.001f, EditorGUILayout.FloatField("Radius", m_Radius)); m_Rows = Math.Clamp(EditorGUILayout.IntField("Rows", m_Rows), 3, 512); m_Columns = Math.Clamp(EditorGUILayout.IntField("Columns", m_Columns), 3, 512); if (EditorGUI.EndChangeCheck()) { UpdateMesh(true); } if (ProGridsInterface.GetProGridsType() != null) { s_SnapTangents = EditorGUILayout.Toggle("Snap Tangents", s_SnapTangents); } }
void OnSceneGUI() { Event e = Event.current; bool eventHasBeenUsed = false; if (m_IsMoving) { if (e.type == EventType.Ignore || e.type == EventType.MouseUp) { eventHasBeenUsed = true; OnFinishVertexModification(); } } bool sceneViewInUse = EditorHandleUtility.SceneViewInUse(e); if (e.type == EventType.KeyDown) { if (e.keyCode == KeyCode.Backspace && m_currentHandle > -1 && m_currentHandle < m_Points.Count) { UndoUtility.RecordObject(m_Target, "Delete Bezier Point"); m_Points.RemoveAt(m_currentHandle); UpdateMesh(true); } else if (e.keyCode == KeyCode.Escape) { SetIsEditing(false); } } int count = m_Points.Count; Matrix4x4 handleMatrix = Handles.matrix; Handles.matrix = m_Target.transform.localToWorldMatrix; EditorGUI.BeginChangeCheck(); for (int index = 0; index < count; index++) { if (index < count - 1 || m_CloseLoop) { Handles.DrawBezier(m_Points[index].position, m_Points[(index + 1) % count].position, m_Points[index].tangentOut, m_Points[(index + 1) % count].tangentIn, Color.green, EditorGUIUtility.whiteTexture, 1f); } if (!m_IsEditing) { continue; } // If the index is selected show the full transform gizmo, otherwise use free move handles if (m_currentHandle == index) { BezierPoint point = m_Points[index]; if (!m_currentHandle.isTangent) { Vector3 prev = point.position; prev = Handles.PositionHandle(prev, Quaternion.identity); if (!Math.Approx3(prev, point.position)) { if (!m_IsMoving) { OnBeginVertexModification(); } prev = ProGridsInterface.ProGridsSnap(prev); Vector3 dir = prev - point.position; point.position = prev; point.tangentIn += dir; point.tangentOut += dir; } // rotation int prev_index = index > 0 ? index - 1 : (m_CloseLoop ? count - 1 : -1); int next_index = index < count - 1 ? index + 1 : (m_CloseLoop ? 0 : -1); Vector3 rd = BezierPoint.GetLookDirection(m_Points, index, prev_index, next_index); Quaternion look = Quaternion.LookRotation(rd); float size = HandleUtility.GetHandleSize(point.position); Matrix4x4 pm = Handles.matrix; Handles.matrix = pm * Matrix4x4.TRS(point.position, look, Vector3.one); point.rotation = Handles.Disc(point.rotation, Vector3.zero, Vector3.forward, size, false, 0f); Handles.matrix = pm; } else { Handles.color = bezierTangentHandleColor; if (m_currentHandle.tangent == BezierTangentDirection.In && (m_CloseLoop || index > 0)) { EditorGUI.BeginChangeCheck(); point.tangentIn = Handles.PositionHandle(point.tangentIn, Quaternion.identity); if (EditorGUI.EndChangeCheck()) { if (!m_IsMoving) { OnBeginVertexModification(); } if (s_SnapTangents) { point.tangentIn = ProGridsInterface.ProGridsSnap(point.tangentIn); } point.EnforceTangentMode(BezierTangentDirection.In, m_TangentMode); } Handles.color = Color.blue; Handles.DrawLine(m_Points[index].position, m_Points[index].tangentIn); } if (m_currentHandle.tangent == BezierTangentDirection.Out && (m_CloseLoop || index < count - 1)) { EditorGUI.BeginChangeCheck(); point.tangentOut = Handles.PositionHandle(point.tangentOut, Quaternion.identity); if (EditorGUI.EndChangeCheck()) { if (!m_IsMoving) { OnBeginVertexModification(); } if (s_SnapTangents) { point.tangentOut = ProGridsInterface.ProGridsSnap(point.tangentOut); } point.EnforceTangentMode(BezierTangentDirection.Out, m_TangentMode); } Handles.color = Color.red; Handles.DrawLine(m_Points[index].position, m_Points[index].tangentOut); } } m_Points[index] = point; } } if (!m_IsEditing) { return; } EventType eventType = e.type; if (!eventHasBeenUsed) { eventHasBeenUsed = eventType == EventType.Used; } for (int index = 0; index < count; index++) { Vector3 prev; BezierPoint point = m_Points[index]; // Position Handle float size = HandleUtility.GetHandleSize(point.position) * k_HandleSize; Handles.color = bezierPositionHandleColor; if (m_currentHandle == index && !m_currentHandle.isTangent) { Handles.DotHandleCap(0, point.position, Quaternion.identity, size, e.type); } else { prev = point.position; prev = Handles.FreeMoveHandle(prev, Quaternion.identity, size, Vector3.zero, Handles.DotHandleCap); if (!eventHasBeenUsed && eventType == EventType.MouseUp && e.type == EventType.Used) { eventHasBeenUsed = true; m_currentHandle = (BezierHandle)index; Repaint(); SceneView.RepaintAll(); } else if (!Math.Approx3(prev, point.position)) { if (!m_IsMoving) { OnBeginVertexModification(); } point.SetPosition(ProGridsInterface.ProGridsSnap(prev)); } } // Tangent handles Handles.color = bezierTangentHandleColor; // Tangent In Handle if (m_CloseLoop || index > 0) { size = HandleUtility.GetHandleSize(point.tangentIn) * k_HandleSize; Handles.DrawLine(point.position, point.tangentIn); if (index == m_currentHandle && m_currentHandle.isTangent && m_currentHandle.tangent == BezierTangentDirection.In) { Handles.DotHandleCap(0, point.tangentIn, Quaternion.identity, size, e.type); } else { prev = point.tangentIn; prev = Handles.FreeMoveHandle(prev, Quaternion.identity, size, Vector3.zero, Handles.DotHandleCap); if (!eventHasBeenUsed && eventType == EventType.MouseUp && e.type == EventType.Used) { eventHasBeenUsed = true; m_currentHandle.SetIndexAndTangent(index, BezierTangentDirection.In); Repaint(); SceneView.RepaintAll(); } else if (!Math.Approx3(prev, point.tangentIn)) { if (!m_IsMoving) { OnBeginVertexModification(); } point.tangentIn = s_SnapTangents ? ProGridsInterface.ProGridsSnap(prev) : prev; point.EnforceTangentMode(BezierTangentDirection.In, m_TangentMode); } } } // Tangent Out if (m_CloseLoop || index < count - 1) { size = HandleUtility.GetHandleSize(point.tangentOut) * k_HandleSize; Handles.DrawLine(point.position, point.tangentOut); if (index == m_currentHandle && m_currentHandle.isTangent && m_currentHandle.tangent == BezierTangentDirection.Out) { Handles.DotHandleCap(0, point.tangentOut, Quaternion.identity, size, e.type); } else { prev = point.tangentOut; prev = Handles.FreeMoveHandle(prev, Quaternion.identity, size, Vector3.zero, Handles.DotHandleCap); if (!eventHasBeenUsed && eventType == EventType.MouseUp && e.type == EventType.Used) { eventHasBeenUsed = true; m_currentHandle.SetIndexAndTangent(index, BezierTangentDirection.Out); Repaint(); SceneView.RepaintAll(); } else if (!Math.Approx3(prev, point.tangentOut)) { if (!m_IsMoving) { OnBeginVertexModification(); } point.tangentOut = s_SnapTangents ? ProGridsInterface.ProGridsSnap(prev) : prev; point.EnforceTangentMode(BezierTangentDirection.Out, m_TangentMode); } } } m_Points[index] = point; } // Do control point insertion if (!eventHasBeenUsed && m_ControlPoints != null && m_ControlPoints.Count > 1) { int index = -1; float distanceToLine; Vector3 p = EditorHandleUtility.ClosestPointToPolyLine(m_ControlPoints, out index, out distanceToLine, false, null); if (!IsHoveringHandlePoint(e.mousePosition) && distanceToLine < PreferenceKeys.k_MaxPointDistanceFromControl) { Handles.color = Color.green; Handles.DotHandleCap(-1, p, Quaternion.identity, HandleUtility.GetHandleSize(p) * .05f, e.type); Handles.color = Color.white; if (!eventHasBeenUsed && eventType == EventType.MouseDown && e.button == 0) { UndoUtility.RecordObject(m_Target, "Add Point"); Vector3 dir = m_ControlPoints[(index + 1) % m_ControlPoints.Count] - m_ControlPoints[index]; m_Points.Insert((index / m_Columns) + 1, new BezierPoint(p, p - dir, p + dir, Quaternion.identity)); UpdateMesh(true); e.Use(); } SceneView.RepaintAll(); } } if (e.type == EventType.MouseUp && !sceneViewInUse) { m_currentHandle.SetIndex(-1); } Handles.matrix = handleMatrix; if (EditorGUI.EndChangeCheck()) { UpdateMesh(false); } }
static bool GetPlaneFromProGridsAxis(Vector2 mousePosition, out Plane plane) { if (!ProGridsInterface.ProGridsActive() || !ProGridsInterface.GridVisible()) { plane = default(Plane); return(false); } Vector3 point = SceneView.lastActiveSceneView.pivot; Vector3 progridsPivot; if (ProGridsInterface.GetPivot(out progridsPivot)) { point = progridsPivot; } Vector3 normal = Vector3.up; if (ProGridsInterface.IsFullGridEnabled()) { var ray = HandleUtility.GUIPointToWorldRay(mousePosition); Plane[] planes = new Plane[3] { new Plane(Vector3.right, point), new Plane(Vector3.up, point), new Plane(Vector3.forward, point) }; float closestDistance = Mathf.Infinity; Plane closestPlane = default(Plane); for (int i = 0; i < planes.Length; ++i) { float distance; if (planes[i].Raycast(ray, out distance)) { if (distance < closestDistance) { closestDistance = distance; closestPlane = planes[i]; } } } plane = new Plane(closestPlane.normal, point); } else { var axis = ProGridsInterface.GetActiveGridAxis(); float offset = ProGridsInterface.GetActiveGridOffset(); switch (axis) { case HandleAxis.X: point.x += offset; normal = Vector3.right; break; case HandleAxis.Y: point.y += offset; normal = Vector3.up; break; case HandleAxis.Z: point.z += offset; normal = Vector3.forward; break; } plane = new Plane(normal, point); } return(true); }
void DoPointPlacement() { Event evt = Event.current; EventType eventType = evt.type; if (m_PlacingPoint) { Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition); if (eventType == EventType.MouseDrag) { float hitDistance = Mathf.Infinity; if (plane.Raycast(ray, out hitDistance)) { evt.Use(); polygon.m_Points[m_SelectedIndex] = GetPointInLocalSpace(ray.GetPoint(hitDistance)); RebuildPolyShapeMesh(false); SceneView.RepaintAll(); } } if (eventType == EventType.MouseUp || eventType == EventType.Ignore || eventType == EventType.KeyDown || eventType == EventType.KeyUp) { evt.Use(); m_PlacingPoint = false; m_SelectedIndex = -1; SceneView.RepaintAll(); } } else if (polygon.polyEditMode == PolyShape.PolyEditMode.Path) { if (eventType == EventType.MouseDown && HandleUtility.nearestControl == m_ControlId) { if (polygon.m_Points.Count < 1) { SetupInputPlane(evt.mousePosition); } float hitDistance = Mathf.Infinity; Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition); if (plane.Raycast(ray, out hitDistance)) { UndoUtility.RecordObject(polygon, "Add Polygon Shape Point"); Vector3 hit = ray.GetPoint(hitDistance); if (polygon.m_Points.Count < 1) { polygon.transform.position = polygon.isOnGrid ? ProGridsInterface.ProGridsSnap(hit) : hit; Vector3 cameraFacingPlaneNormal = plane.normal; if (Vector3.Dot(cameraFacingPlaneNormal, SceneView.lastActiveSceneView.camera.transform.forward) > 0f) { cameraFacingPlaneNormal *= -1; } polygon.transform.rotation = Quaternion.LookRotation(cameraFacingPlaneNormal) * Quaternion.Euler(new Vector3(90f, 0f, 0f)); } Vector3 point = GetPointInLocalSpace(hit); if (polygon.m_Points.Count > 2 && Math.Approx3(polygon.m_Points[0], point)) { m_NextMouseUpAdvancesMode = true; return; } polygon.m_Points.Add(point); m_PlacingPoint = true; m_SelectedIndex = polygon.m_Points.Count - 1; RebuildPolyShapeMesh(polygon); evt.Use(); } } } else if (polygon.polyEditMode == PolyShape.PolyEditMode.Edit) { if (polygon.m_Points.Count < 3) { SetPolyEditMode(PolyShape.PolyEditMode.Path); return; } if (m_DistanceFromHeightHandle > PreferenceKeys.k_MaxPointDistanceFromControl) { // point insertion Vector2 mouse = evt.mousePosition; Ray ray = HandleUtility.GUIPointToWorldRay(mouse); float hitDistance = Mathf.Infinity; if (plane.Raycast(ray, out hitDistance)) { Vector3 hit = ray.GetPoint(hitDistance); Vector3 point = GetPointInLocalSpace(hit); int polyCount = polygon.m_Points.Count; float distToLineInGUI; int index; EditorHandleUtility.ClosestPointToPolyLine(polygon.m_Points, out index, out distToLineInGUI, true, polygon.transform); Vector3 aToPoint = point - polygon.m_Points[index - 1]; Vector3 aToB = polygon.m_Points[index % polyCount] - polygon.m_Points[index - 1]; float ratio = Vector3.Dot(aToPoint, aToB.normalized) / aToB.magnitude; Vector3 wp = Vector3.Lerp(polygon.m_Points[index - 1], polygon.m_Points[index % polyCount], ratio); wp = polygon.transform.TransformPoint(wp); Vector2 aInGUI = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[index - 1])); Vector2 bInGUI = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[index % polyCount])); float distanceToVertex = Mathf.Min(Vector2.Distance(mouse, aInGUI), Vector2.Distance(mouse, bInGUI)); if (distanceToVertex > PreferenceKeys.k_MaxPointDistanceFromControl && distToLineInGUI < PreferenceKeys.k_MaxPointDistanceFromControl) { if (evt.type == EventType.Repaint) { Handles.color = Color.green; Handles.DotHandleCap(-1, wp, Quaternion.identity, HandleUtility.GetHandleSize(wp) * k_HandleSize, evt.type); } if (evt.type == EventType.MouseDown && HandleUtility.nearestControl == m_ControlId) { evt.Use(); UndoUtility.RecordObject(polygon, "Insert Point"); polygon.m_Points.Insert(index, point); m_SelectedIndex = index; m_PlacingPoint = true; RebuildPolyShapeMesh(true); OnBeginVertexMovement(); } Handles.color = Color.white; } if (evt.type != EventType.Repaint) { SceneView.RepaintAll(); } } } } }