internal static void SetSelection(IList <GameObject> newSelection) { UndoUtility.RecordSelection(topInternal.ToArray(), "Change Selection"); ClearElementAndObjectSelection(); // if the previous tool was set to none, use Tool.Move if (Tools.current == Tool.None) { Tools.current = Tool.Move; } var newCount = newSelection != null ? newSelection.Count : 0; if (newCount > 0) { Selection.activeTransform = newSelection[newCount - 1].transform; Selection.objects = newSelection.ToArray(); } else { Selection.activeTransform = null; } OnObjectSelectionChanged(); }
/// <summary> /// Called from ProGrids. /// </summary> /// <param name="snapVal"></param> void PushToGrid(float snapVal) { UndoUtility.RecordSelection(selection.ToArray(), "Push elements to Grid"); if (selectMode == SelectMode.Object || selectMode == SelectMode.None) { return; } for (int i = 0, c = MeshSelection.selectedObjectCount; i < c; i++) { ProBuilderMesh mesh = selection[i]; if (mesh.selectedVertexCount < 1) { continue; } var indexes = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal); ProGridsSnapping.SnapVertices(mesh, indexes, Vector3.one * snapVal); mesh.ToMesh(); mesh.Refresh(); mesh.Optimize(); } UpdateSelection(); }
internal static void OnObjectSelectionChanged() { // GameObjects returns both parent and child when both are selected, where transforms only returns the top-most // transform. s_UnitySelectionChangeMeshes.Clear(); s_ElementSelection.Clear(); s_ActiveMesh = null; var gameObjects = Selection.gameObjects; for (int i = 0, c = gameObjects.Length; i < c; i++) { #if UNITY_2019_3_OR_NEWER ProBuilderMesh mesh; if (gameObjects[i].TryGetComponent <ProBuilderMesh>(out mesh)) #else var mesh = gameObjects[i].GetComponent <ProBuilderMesh>(); if (mesh != null) #endif { if (gameObjects[i] == Selection.activeGameObject) { s_ActiveMesh = mesh; } s_UnitySelectionChangeMeshes.Add(mesh); } } for (int i = 0, c = s_TopSelection.Count; i < c; i++) { if (!s_UnitySelectionChangeMeshes.Contains(s_TopSelection[i])) { if (s_TopSelection[i] != null) { UndoUtility.RecordSelection(s_TopSelection[i], "Selection Change"); } s_TopSelection[i].ClearSelection(); } } s_TopSelection.Clear(); foreach (var i in s_UnitySelectionChangeMeshes) { s_TopSelection.Add(i); } selectedObjectCount = s_TopSelection.Count; OnComponentSelectionChanged(); if (objectSelectionChanged != null) { objectSelectionChanged(); } s_UnitySelectionChangeMeshes.Clear(); }
void SelectAll() { if (MeshSelection.selectedObjectCount < 1) { return; } UndoUtility.RecordSelection("Select all"); switch (selectMode) { case SelectMode.Vertex: foreach (var mesh in MeshSelection.topInternal) { var sharedIndexes = mesh.sharedVerticesInternal; var all = new List <int>(); for (var i = 0; i < sharedIndexes.Length; i++) { all.Add(sharedIndexes[i][0]); } mesh.SetSelectedVertices(all); } break; case SelectMode.Face: case SelectMode.TextureFace: foreach (var mesh in MeshSelection.topInternal) { mesh.SetSelectedFaces(mesh.facesInternal); } break; case SelectMode.Edge: foreach (var mesh in MeshSelection.topInternal) { var universalEdges = mesh.GetSharedVertexHandleEdges(mesh.facesInternal.SelectMany(x => x.edges)).ToArray(); var all = new Edge[universalEdges.Length]; for (var n = 0; n < universalEdges.Length; n++) { all[n] = new Edge(mesh.sharedVerticesInternal[universalEdges[n].a][0], mesh.sharedVerticesInternal[universalEdges[n].b][0]); } mesh.SetSelectedEdges(all); } break; } Refresh(); SceneView.RepaintAll(); }
private static void SetFill(AutoUnwrapSettings.Fill fill, ProBuilderMesh[] sel) { UndoUtility.RecordSelection(sel, "Fill UVs"); for (int i = 0; i < sel.Length; i++) { foreach (Face q in sel[i].GetSelectedFaces()) { var uv = q.uv; uv.fill = fill; q.uv = uv; } } }
private static void SetUseWorldSpace(bool useWorldSpace, ProBuilderMesh[] sel) { UndoUtility.RecordSelection(sel, "Use World Space UVs"); for (int i = 0; i < sel.Length; i++) { foreach (Face q in sel[i].GetSelectedFaces()) { var uv = q.uv; uv.useWorldSpace = useWorldSpace; q.uv = uv; } } }
private static void SetSwapUV(bool swapUV, ProBuilderMesh[] sel) { UndoUtility.RecordSelection(sel, "Swap U, V"); for (int i = 0; i < sel.Length; i++) { foreach (Face q in sel[i].GetSelectedFaces()) { var uv = q.uv; uv.swapUV = swapUV; q.uv = uv; } } }
private static void SetFlipV(bool flipV, ProBuilderMesh[] sel) { UndoUtility.RecordSelection(sel, "Flip V"); for (int i = 0; i < sel.Length; i++) { foreach (Face q in sel[i].GetSelectedFaces()) { var uv = q.uv; uv.flipV = flipV; q.uv = uv; } } }
private static void SetFlipU(bool flipU, ProBuilderMesh[] sel) { UndoUtility.RecordSelection(sel, "Flip U"); for (int i = 0; i < sel.Length; i++) { foreach (Face q in sel[i].GetSelectedFaces()) { var uv = q.uv; uv.flipU = flipU; q.uv = uv; sel[i].SetGroupUV(q.uv, q.textureGroup); } } }
private static void SetRotation(float rot, ProBuilderMesh[] sel) { UndoUtility.RecordSelection(sel, "Rotate UVs"); for (int i = 0; i < sel.Length; i++) { foreach (Face q in sel[i].GetSelectedFaces()) { var uv = q.uv; uv.rotation = rot; q.uv = uv; } } }
private static void SetAnchor(AutoUnwrapSettings.Anchor anchor, ProBuilderMesh[] sel) { UndoUtility.RecordSelection(sel, "Set UV Anchor"); for (int i = 0; i < sel.Length; i++) { foreach (Face q in sel[i].GetSelectedFaces()) { var uv = q.uv; uv.anchor = anchor; q.uv = uv; } } }
static void SelectGroups(ProBuilderMesh pb, HashSet <int> groups) { UndoUtility.RecordSelection(pb, "Select with Smoothing Group"); if ((Event.current.modifiers & EventModifiers.Shift) == EventModifiers.Shift || (Event.current.modifiers & EventModifiers.Control) == EventModifiers.Control) { pb.SetSelectedFaces(pb.facesInternal.Where(x => groups.Contains(x.smoothingGroup) || pb.selectedFacesInternal.Contains(x))); } else { pb.SetSelectedFaces(pb.facesInternal.Where(x => groups.Contains(x.smoothingGroup))); } ProBuilderEditor.Refresh(); }
static ActionResult MenuBooleanOperation(BooleanOperation operation, ProBuilderMesh lhs, ProBuilderMesh rhs) { if (lhs == null || rhs == null) { return(new ActionResult(ActionResult.Status.Failure, "Must Select 2 Objects")); } string op_string = operation == BooleanOperation.Union ? "Union" : (operation == BooleanOperation.Subtract ? "Subtract" : "Intersect"); ProBuilderMesh[] sel = new ProBuilderMesh[] { lhs, rhs }; UndoUtility.RecordSelection(sel, op_string); UnityEngine.ProBuilder.Csg.Model result; switch (operation) { case BooleanOperation.Union: result = Boolean.Union(lhs.gameObject, rhs.gameObject); break; case BooleanOperation.Subtract: result = Boolean.Subtract(lhs.gameObject, rhs.gameObject); break; default: result = Boolean.Intersect(lhs.gameObject, rhs.gameObject); break; } var materials = result.materials.ToArray(); ProBuilderMesh pb = ProBuilderMesh.Create(); pb.GetComponent <MeshFilter>().sharedMesh = (Mesh)result; pb.GetComponent <MeshRenderer>().sharedMaterials = materials; MeshImporter importer = new MeshImporter(pb.gameObject); importer.Import(new MeshImportSettings() { quads = true, smoothing = true, smoothingAngle = 1f }); pb.Rebuild(); pb.CenterPivot(null); Selection.objects = new Object[] { pb.gameObject }; return(new ActionResult(ActionResult.Status.Success, op_string)); }
static void ApplyMaterial(IEnumerable<ProBuilderMesh> selection, Material mat) { if (mat == null) return; UndoUtility.RecordSelection(selection.ToArray(), "Set Face Materials"); foreach (var mesh in selection) { var applyPerFace = ProBuilderEditor.selectMode.ContainsFlag(SelectMode.Face) && mesh.faceCount > 0; mesh.SetMaterial(applyPerFace ? mesh.GetSelectedFaces() : mesh.facesInternal, mat); InternalMeshUtility.FilterUnusedSubmeshIndexes(mesh); mesh.Rebuild(); mesh.Optimize(); } if (ProBuilderEditor.instance != null && MeshSelection.selectedFaceCount > 0) EditorUtility.ShowNotification("Set Material\n" + mat.name); }
static ActionResult MenuBooleanOperation(BooleanOperation operation, ProBuilderMesh lhs, ProBuilderMesh rhs) { if (lhs == null || rhs == null) { return(new ActionResult(ActionResult.Status.Failure, "Must Select 2 Objects")); } string op_string = operation == BooleanOperation.Union ? "Union" : (operation == BooleanOperation.Subtract ? "Subtract" : "Intersect"); ProBuilderMesh[] sel = new ProBuilderMesh[] { lhs, rhs }; UndoUtility.RecordSelection(sel, op_string); Mesh c; switch (operation) { case BooleanOperation.Union: c = CSG.Union(lhs.gameObject, rhs.gameObject); break; case BooleanOperation.Subtract: c = CSG.Subtract(lhs.gameObject, rhs.gameObject); break; default: c = CSG.Intersect(lhs.gameObject, rhs.gameObject); break; } GameObject go = new GameObject(); go.AddComponent <MeshRenderer>().sharedMaterial = EditorMaterialUtility.GetUserMaterial(); go.AddComponent <MeshFilter>().sharedMesh = c; ProBuilderMesh pb = InternalMeshUtility.CreateMeshWithTransform(go.transform, false); DestroyImmediate(go); Selection.objects = new Object[] { pb.gameObject }; return(new ActionResult(ActionResult.Status.Success, op_string)); }
private static void TextureGroupSelectedFaces(ProBuilderMesh pb)//, pb_Face face) { if (pb.selectedFaceCount < 1) { return; } Face[] faces = pb.GetSelectedFaces(); AutoUnwrapSettings cont_uv = faces[0].uv; int texGroup = pb.GetUnusedTextureGroup(); UndoUtility.RecordSelection(pb, "Create Texture Group" + textureGroup); foreach (Face f in faces) { f.uv = new AutoUnwrapSettings(cont_uv); f.textureGroup = texGroup; } }
static void ApplyMaterial(IEnumerable <ProBuilderMesh> selection, Material mat) { if (mat == null) { return; } UndoUtility.RecordSelection(selection.ToArray(), "Set Face Materials"); foreach (var mesh in selection) { mesh.SetMaterial(mesh.selectedFaceCount > 0 ? mesh.GetSelectedFaces() : mesh.facesInternal, mat); mesh.Rebuild(); mesh.Optimize(); } if (ProBuilderEditor.instance != null && MeshSelection.selectedFaceCount > 0) { EditorUtility.ShowNotification("Set Material\n" + mat.name); } }
private static void SetTextureGroup(ProBuilderMesh[] selection, int tex) { UndoUtility.RecordSelection(selection, "Set Texture Group " + textureGroup); foreach (ProBuilderMesh pb in selection) { if (pb.selectedFaceCount < 1) { continue; } Face[] faces = pb.GetSelectedFaces(); AutoUnwrapSettings cuv = faces[0].uv; foreach (Face f in faces) { f.textureGroup = tex; f.uv = new AutoUnwrapSettings(cuv); } } }
private static void SetScale(Vector2 scale, Axis2D axis, ProBuilderMesh[] sel) { UndoUtility.RecordSelection(sel, "Scale UVs"); for (int i = 0; i < sel.Length; i++) { foreach (Face q in sel[i].GetSelectedFaces()) { switch (axis) { case Axis2D.XY: { var uv = q.uv; uv.scale = scale; q.uv = uv; break; } case Axis2D.X: { var uv = q.uv; uv.scale = new Vector2(scale.x, q.uv.scale.y); q.uv = uv; break; } case Axis2D.Y: { var uv = q.uv; uv.scale = new Vector2(q.uv.scale.x, scale.y); q.uv = uv; break; } } sel[i].SetGroupUV(q.uv, q.textureGroup); } } }
private static void SetOffset(Vector2 offset, Axis2D axis, ProBuilderMesh[] sel) { UndoUtility.RecordSelection(sel, "Offset UVs"); for (int i = 0; i < sel.Length; i++) { foreach (Face q in sel[i].GetSelectedFaces()) { switch (axis) { case Axis2D.XY: { var uv = q.uv; uv.offset = offset; q.uv = uv; break; } case Axis2D.X: { var uv = q.uv; uv.offset = new Vector2(offset.x, q.uv.offset.y); q.uv = uv; break; } case Axis2D.Y: { var uv = q.uv; uv.offset = new Vector2(q.uv.offset.x, offset.y); q.uv = uv; break; } } sel[i].SetGroupUV(q.uv, q.textureGroup); } } }
void DeselectAll() { if (MeshSelection.selectedObjectCount < 1) { return; } UndoUtility.RecordSelection("Deselect All"); switch (selectMode) { case SelectMode.Vertex: foreach (var mesh in MeshSelection.topInternal) { mesh.SetSelectedVertices(null); } break; case SelectMode.Face: case SelectMode.TextureFace: foreach (var mesh in MeshSelection.topInternal) { mesh.SetSelectedFaces((IEnumerable <Face>)null); } break; case SelectMode.Edge: foreach (var mesh in MeshSelection.topInternal) { mesh.SetSelectedEdges(null); } break; } Refresh(); SceneView.RepaintAll(); }
private static void SetRotation(float rot, ProBuilderMesh[] sel) { UndoUtility.RecordSelection(sel, "Rotate UVs"); for (int i = 0; i < sel.Length; i++) { foreach (Face q in sel[i].GetSelectedFaces()) { var uv = q.uv; uv.rotation = rot; if (uv.rotation > 360f) { uv.rotation = uv.rotation % 360f; } else if (uv.rotation < 0f) { uv.rotation = 360f + (uv.rotation % 360f); } q.uv = uv; sel[i].SetGroupUV(uv, q.textureGroup); } } }
public static void SetFaceColors(Color col) { col = PlayerSettings.colorSpace == ColorSpace.Linear ? col.linear : col; ProBuilderMesh[] selection = InternalUtility.GetComponents <ProBuilderMesh>(Selection.transforms); UndoUtility.RecordSelection(selection, "Apply Vertex Colors"); ProBuilderEditor editor = ProBuilderEditor.instance; if (editor && ProBuilderEditor.selectMode.ContainsFlag(SelectMode.Vertex | SelectMode.Edge | SelectMode.Face)) { switch (ProBuilderEditor.selectMode) { case SelectMode.Face: case SelectMode.TextureFace: foreach (ProBuilderMesh mesh in selection) { Color[] colors = mesh.GetColors(); foreach (int i in mesh.selectedIndexesInternal) { colors[i] = col; } mesh.colors = colors; } break; case SelectMode.Edge: case SelectMode.Vertex: foreach (var mesh in selection) { Color[] colors = mesh.GetColors(); foreach (int i in mesh.GetCoincidentVertices(mesh.selectedIndexesInternal)) { colors[i] = col; } mesh.colors = colors; } break; } } else { foreach (ProBuilderMesh pb in selection) { foreach (Face face in pb.facesInternal) { pb.SetFaceColor(face, col); } } } foreach (ProBuilderMesh pb in selection) { pb.ToMesh(); pb.Refresh(); pb.Optimize(); } EditorUtility.ShowNotification("Set Vertex Colors\n" + ColorUtility.GetColorName(col)); }
internal static void SetSelection(GameObject go) { UndoUtility.RecordSelection(topInternal.ToArray(), "Change Selection"); ClearElementAndObjectSelection(); AddToSelection(go); }
public static ProBuilderMesh DoMouseClick(Event evt, SelectMode selectionMode, ScenePickerPreferences pickerPreferences) { bool appendModifier = EditorHandleUtility.IsAppendModifier(evt.modifiers); if (!appendModifier) { MeshSelection.SetSelection((GameObject)null); } float pickedElementDistance = Mathf.Infinity; if (selectionMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge)) { pickedElementDistance = EdgeRaycast(evt.mousePosition, pickerPreferences, true, s_Selection); } else if (selectionMode.ContainsFlag(SelectMode.Vertex | SelectMode.TextureVertex)) { pickedElementDistance = VertexRaycast(evt.mousePosition, pickerPreferences, true, s_Selection); } else { pickedElementDistance = FaceRaycast(evt.mousePosition, pickerPreferences, true, s_Selection, evt.clickCount > 1 ? -1 : 0, false); } evt.Use(); if (pickedElementDistance > pickerPreferences.maxPointerDistance) { if (appendModifier && Selection.gameObjects.Contains(s_Selection.gameObject)) { MeshSelection.RemoveFromSelection(s_Selection.gameObject); } else { MeshSelection.AddToSelection(s_Selection.gameObject); } return(null); } MeshSelection.AddToSelection(s_Selection.gameObject); if (s_Selection.mesh != null) { var mesh = s_Selection.mesh; if (s_Selection.face != null) { // Check for other editor mouse shortcuts first (todo proper event handling for mouse shortcuts) MaterialEditor matEditor = MaterialEditor.instance; if (matEditor != null && matEditor.ClickShortcutCheck(Event.current.modifiers, mesh, s_Selection.face)) { return(null); } UVEditor uvEditor = UVEditor.instance; if (uvEditor != null && uvEditor.ClickShortcutCheck(mesh, s_Selection.face)) { return(null); } var faces = mesh.faces as Face[] ?? mesh.faces.ToArray(); var ind = Array.IndexOf <Face>(faces, s_Selection.face); var sel = mesh.selectedFaceIndexes.IndexOf(ind); UndoUtility.RecordSelection(mesh, "Select Face"); if (sel > -1) { mesh.RemoveFromFaceSelectionAtIndex(sel); } else { mesh.AddToFaceSelection(ind); } } else if (s_Selection.edge != Edge.Empty) { int ind = mesh.IndexOf(mesh.selectedEdges, s_Selection.edge); UndoUtility.RecordSelection(mesh, "Select Edge"); if (ind > -1) { mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().RemoveAt(ind)); } else { mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().Add(s_Selection.edge)); } } else if (s_Selection.vertex > -1) { int ind = Array.IndexOf(mesh.selectedIndexesInternal, s_Selection.vertex); UndoUtility.RecordSelection(mesh, "Select Vertex"); if (ind > -1) { mesh.SetSelectedVertices(mesh.selectedIndexesInternal.RemoveAt(ind)); } else { mesh.SetSelectedVertices(mesh.selectedIndexesInternal.Add(s_Selection.vertex)); } } return(mesh); } return(null); }
public static void DoMouseDrag(Rect mouseDragRect, SelectMode selectionMode, ScenePickerPreferences scenePickerPreferences) { var pickingOptions = new PickerOptions() { depthTest = scenePickerPreferences.cullMode == CullingMode.Back, rectSelectMode = scenePickerPreferences.rectSelectMode }; UndoUtility.RecordSelection("Drag Select"); bool isAppendModifier = EditorHandleUtility.IsAppendModifier(Event.current.modifiers); if (!isAppendModifier) { MeshSelection.ClearElementSelection(); } bool elementsInDragRect = false; switch (selectionMode) { case SelectMode.Vertex: case SelectMode.TextureVertex: { Dictionary <ProBuilderMesh, HashSet <int> > selected = SelectionPicker.PickVerticesInRect( SceneView.lastActiveSceneView.camera, mouseDragRect, MeshSelection.topInternal, pickingOptions, EditorGUIUtility.pixelsPerPoint); foreach (var kvp in selected) { var mesh = kvp.Key; SharedVertex[] sharedIndexes = mesh.sharedVerticesInternal; HashSet <int> common; if (isAppendModifier) { common = mesh.GetSharedVertexHandles(mesh.selectedIndexesInternal); if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Add) { common.UnionWith(kvp.Value); } else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Subtract) { common.RemoveWhere(x => kvp.Value.Contains(x)); } else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Difference) { common.SymmetricExceptWith(kvp.Value); } } else { common = kvp.Value; } elementsInDragRect |= kvp.Value.Any(); mesh.SetSelectedVertices(common.SelectMany(x => sharedIndexes[x])); } break; } case SelectMode.Face: case SelectMode.TextureFace: { Dictionary <ProBuilderMesh, HashSet <Face> > selected = SelectionPicker.PickFacesInRect( SceneView.lastActiveSceneView.camera, mouseDragRect, MeshSelection.topInternal, pickingOptions, EditorGUIUtility.pixelsPerPoint); foreach (var kvp in selected) { HashSet <Face> current; if (isAppendModifier) { current = new HashSet <Face>(kvp.Key.selectedFacesInternal); if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Add) { current.UnionWith(kvp.Value); } else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Subtract) { current.RemoveWhere(x => kvp.Value.Contains(x)); } else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Difference) { current.SymmetricExceptWith(kvp.Value); } } else { current = kvp.Value; } elementsInDragRect |= kvp.Value.Any(); kvp.Key.SetSelectedFaces(current); } break; } case SelectMode.Edge: case SelectMode.TextureEdge: { var selected = SelectionPicker.PickEdgesInRect( SceneView.lastActiveSceneView.camera, mouseDragRect, MeshSelection.topInternal, pickingOptions, EditorGUIUtility.pixelsPerPoint); foreach (var kvp in selected) { ProBuilderMesh mesh = kvp.Key; Dictionary <int, int> common = mesh.sharedVertexLookup; HashSet <EdgeLookup> selectedEdges = EdgeLookup.GetEdgeLookupHashSet(kvp.Value, common); HashSet <EdgeLookup> current; if (isAppendModifier) { current = EdgeLookup.GetEdgeLookupHashSet(mesh.selectedEdges, common); if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Add) { current.UnionWith(selectedEdges); } else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Subtract) { current.RemoveWhere(x => selectedEdges.Contains(x)); } else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Difference) { current.SymmetricExceptWith(selectedEdges); } } else { current = selectedEdges; } elementsInDragRect |= kvp.Value.Any(); mesh.SetSelectedEdges(current.Select(x => x.local)); } break; } } // if nothing was selected in the drag rect, clear the object selection too if (!elementsInDragRect && !isAppendModifier) { MeshSelection.ClearElementAndObjectSelection(); } ProBuilderEditor.Refresh(); SceneView.RepaintAll(); }
void InvertSelection() { if (MeshSelection.selectedObjectCount < 1) { return; } UndoUtility.RecordSelection("Invert Selection"); switch (selectMode) { case SelectMode.Vertex: foreach (var mesh in MeshSelection.topInternal) { var sharedIndexes = mesh.sharedVerticesInternal; var selectedSharedIndexes = new List <int>(); foreach (int i in mesh.selectedIndexesInternal) { selectedSharedIndexes.Add(mesh.GetSharedVertexHandle(i)); } var inverse = new List <int>(); for (int i = 0; i < sharedIndexes.Length; i++) { if (!selectedSharedIndexes.Contains(i)) { inverse.Add(sharedIndexes[i][0]); } } mesh.SetSelectedVertices(inverse.ToArray()); } break; case SelectMode.Face: case SelectMode.TextureFace: foreach (var mesh in MeshSelection.topInternal) { var inverse = mesh.facesInternal.Where(x => !mesh.selectedFacesInternal.Contains(x)); mesh.SetSelectedFaces(inverse.ToArray()); } break; case SelectMode.Edge: foreach (var mesh in MeshSelection.topInternal) { var universalEdges = mesh.GetSharedVertexHandleEdges(mesh.facesInternal.SelectMany(x => x.edges)).ToArray(); var universalSelectedEdges = EdgeUtility.GetSharedVertexHandleEdges(mesh, mesh.selectedEdges).Distinct(); var inverseUniversal = System.Array.FindAll(universalEdges, x => !universalSelectedEdges.Contains(x)); var inverse = new Edge[inverseUniversal.Length]; for (var n = 0; n < inverseUniversal.Length; n++) { inverse[n] = new Edge(mesh.sharedVerticesInternal[inverseUniversal[n].a][0], mesh.sharedVerticesInternal[inverseUniversal[n].b][0]); } mesh.SetSelectedEdges(inverse); } break; } Refresh(); }
public static ProBuilderMesh DoMouseClick(Event evt, SelectMode selectionMode, ScenePickerPreferences pickerPreferences) { bool appendModifier = EditorHandleUtility.IsAppendModifier(evt.modifiers); bool addToSelectionModifier = EditorHandleUtility.IsSelectionAddModifier(evt.modifiers); bool addOrRemoveIfPresentFromSelectionModifier = EditorHandleUtility.IsSelectionAppendOrRemoveIfPresentModifier(evt.modifiers); bool pathSelectionModifier = EditorHandleUtility.IsSelectionPathModifier(evt.modifiers); float pickedElementDistance; if (selectionMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge)) { pickedElementDistance = EdgeRaycast(evt.mousePosition, pickerPreferences, k_AllowUnselected, s_Selection); } else if (selectionMode.ContainsFlag(SelectMode.Vertex | SelectMode.TextureVertex)) { pickedElementDistance = VertexRaycast(evt.mousePosition, pickerPreferences, k_AllowUnselected, s_Selection); } else { pickedElementDistance = FaceRaycast(evt.mousePosition, pickerPreferences, k_AllowUnselected, s_Selection, evt.clickCount > 1 ? -1 : 0, false); } evt.Use(); if (!appendModifier) { if (s_Selection.mesh != null) { s_Selection.mesh.ClearSelection(); } MeshSelection.SetSelection((GameObject)null); } if (pickedElementDistance > ScenePickerPreferences.maxPointerDistance) { if (appendModifier && Selection.gameObjects.Contains(s_Selection.gameObject)) { MeshSelection.RemoveFromSelection(s_Selection.gameObject); } else { MeshSelection.AddToSelection(s_Selection.gameObject); } return(null); } GameObject candidateNewActiveObject = s_Selection.gameObject; bool activeObjectSelectionChanged = Selection.gameObjects.Contains(s_Selection.gameObject) && s_Selection.gameObject != Selection.activeGameObject; if (s_Selection.mesh != null) { var mesh = s_Selection.mesh; foreach (var face in s_Selection.faces) { // Check for other editor mouse shortcuts first (todo proper event handling for mouse shortcuts) MaterialEditor matEditor = MaterialEditor.instance; if (matEditor != null && matEditor.ClickShortcutCheck(Event.current.modifiers, mesh, face)) { return(null); } UVEditor uvEditor = UVEditor.instance; if (uvEditor != null && uvEditor.ClickShortcutCheck(mesh, face)) { return(null); } var faces = mesh.faces as Face[] ?? mesh.faces.ToArray(); var ind = Array.IndexOf <Face>(faces, face); var sel = mesh.selectedFaceIndexes.IndexOf(ind); UndoUtility.RecordSelection(mesh, "Select Face"); if (sel > -1) { if (!appendModifier || addOrRemoveIfPresentFromSelectionModifier || (addToSelectionModifier && face == mesh.GetActiveFace() && !activeObjectSelectionChanged)) { mesh.RemoveFromFaceSelectionAtIndex(sel); if (addOrRemoveIfPresentFromSelectionModifier && activeObjectSelectionChanged) { candidateNewActiveObject = Selection.activeGameObject; } else if (mesh.selectedFaceCount == 0) { for (var i = MeshSelection.topInternal.Count - 1; i >= 0; i--) { if (MeshSelection.topInternal[i].selectedFaceCount > 0) { candidateNewActiveObject = MeshSelection.topInternal[i].gameObject; activeObjectSelectionChanged = true; break; } } } } else { mesh.selectedFaceIndicesInternal = mesh.selectedFaceIndicesInternal.Remove(ind); mesh.SetSelectedFaces(mesh.selectedFaceIndicesInternal.Add(ind)); } } else if (pathSelectionModifier && mesh.GetActiveFace() != null) { var pathFaces = SelectPathFaces.GetPath(mesh, Array.IndexOf <Face>(faces, mesh.GetActiveFace()), Array.IndexOf <Face>(faces, face)); foreach (var pathFace in pathFaces) { mesh.AddToFaceSelection(pathFace); } } else { mesh.AddToFaceSelection(ind); } } foreach (var edge in s_Selection.edges) { int ind = mesh.IndexOf(mesh.selectedEdges, edge); UndoUtility.RecordSelection(mesh, "Select Edge"); if (ind > -1) { if (!appendModifier || addOrRemoveIfPresentFromSelectionModifier || (addToSelectionModifier && edge == mesh.GetActiveEdge() && !activeObjectSelectionChanged)) { mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().RemoveAt(ind)); if (addOrRemoveIfPresentFromSelectionModifier && activeObjectSelectionChanged) { candidateNewActiveObject = Selection.activeGameObject; } else if (mesh.selectedEdgeCount == 0) { for (var i = MeshSelection.topInternal.Count - 1; i >= 0; i--) { if (MeshSelection.topInternal[i].selectedEdgeCount > 0) { candidateNewActiveObject = MeshSelection.topInternal[i].gameObject; activeObjectSelectionChanged = true; break; } } } } else { mesh.selectedEdgesInternal = mesh.selectedEdgesInternal.Remove(edge); mesh.SetSelectedEdges(mesh.selectedEdgesInternal.Add(edge)); } } else { mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().Add(edge)); } } foreach (var vertex in s_Selection.vertexes) { int ind = Array.IndexOf(mesh.selectedIndexesInternal, vertex); UndoUtility.RecordSelection(mesh, "Select Vertex"); if (ind > -1) { var sharedIndex = mesh.sharedVertexLookup[vertex]; var sharedVertex = mesh.sharedVerticesInternal[sharedIndex]; s_IndexBuffer.Clear(); foreach (var sVertex in sharedVertex) { var index = Array.IndexOf(mesh.selectedIndexesInternal, sVertex); if (index < 0) { continue; } s_IndexBuffer.Add(index); } s_IndexBuffer.Sort(); if (!appendModifier || addOrRemoveIfPresentFromSelectionModifier || (addToSelectionModifier && vertex == mesh.GetActiveVertex() && !activeObjectSelectionChanged)) { mesh.selectedIndexesInternal = mesh.selectedIndexesInternal.SortedRemoveAt(s_IndexBuffer); mesh.SetSelectedVertices(mesh.selectedIndexesInternal); if (addOrRemoveIfPresentFromSelectionModifier && activeObjectSelectionChanged) { candidateNewActiveObject = Selection.activeGameObject; } else if (mesh.selectedIndexesInternal.Length == 0) { for (var i = MeshSelection.topInternal.Count - 1; i >= 0; i--) { if (MeshSelection.topInternal[i].selectedIndexesInternal.Length > 0) { candidateNewActiveObject = MeshSelection.topInternal[i].gameObject; activeObjectSelectionChanged = true; break; } } } } else { mesh.selectedIndexesInternal = mesh.selectedIndexesInternal.SortedRemoveAt(s_IndexBuffer); mesh.SetSelectedVertices(mesh.selectedIndexesInternal.Add(vertex)); } } else { mesh.SetSelectedVertices(mesh.selectedIndexesInternal.Add(vertex)); } } if (activeObjectSelectionChanged) { MeshSelection.MakeActiveObject(candidateNewActiveObject); } else { MeshSelection.AddToSelection(candidateNewActiveObject); } return(mesh); } return(null); }
public static bool OnGUI(ProBuilderMesh[] selection, float width) { UpdateDiffDictionary(selection); s_ScrollPosition = EditorGUILayout.BeginScrollView(s_ScrollPosition); float tempFloat = 0f; EditorGUI.BeginChangeCheck(); /** * Set Tile mode */ GUILayout.Label("Tiling & Alignment", EditorStyles.boldLabel); GUILayout.BeginHorizontal(); EditorGUI.showMixedValue = s_AutoUVSettingsDiff["fill"]; GUILayout.Label("Fill Mode", GUILayout.MaxWidth(80), GUILayout.MinWidth(80)); EditorGUI.BeginChangeCheck(); s_AutoUVSettings.fill = (AutoUnwrapSettings.Fill)EditorGUILayout.EnumPopup(s_AutoUVSettings.fill); if (EditorGUI.EndChangeCheck()) { SetFill(s_AutoUVSettings.fill, selection); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); bool enabled = GUI.enabled; GUI.enabled = !s_AutoUVSettings.useWorldSpace; EditorGUI.showMixedValue = s_AutoUVSettingsDiff["anchor"]; EditorGUI.BeginChangeCheck(); GUILayout.Label("Anchor", GUILayout.MaxWidth(80), GUILayout.MinWidth(80)); s_AutoUVSettings.anchor = (AutoUnwrapSettings.Anchor)EditorGUILayout.EnumPopup(s_AutoUVSettings.anchor); if (EditorGUI.EndChangeCheck()) { SetAnchor(s_AutoUVSettings.anchor, selection); } GUI.enabled = enabled; GUILayout.EndHorizontal(); GUI.backgroundColor = PreferenceKeys.proBuilderLightGray; UI.EditorGUIUtility.DrawSeparator(1); GUI.backgroundColor = Color.white; GUILayout.Label("Transform", EditorStyles.boldLabel); /** * Offset */ EditorGUI.showMixedValue = s_AutoUVSettingsDiff["offsetx"] || s_AutoUVSettingsDiff["offsety"]; var tempVec2 = s_AutoUVSettings.offset; UnityEngine.GUI.SetNextControlName("offset"); s_AutoUVSettings.offset = EditorGUILayout.Vector2Field("Offset", s_AutoUVSettings.offset, GUILayout.MaxWidth(width)); if (tempVec2.x != s_AutoUVSettings.offset.x) { SetOffset(s_AutoUVSettings.offset, Axis2D.X, selection); } if (tempVec2.y != s_AutoUVSettings.offset.y) { SetOffset(s_AutoUVSettings.offset, Axis2D.Y, selection); } /** * Rotation */ tempFloat = s_AutoUVSettings.rotation; EditorGUI.showMixedValue = s_AutoUVSettingsDiff["rotation"]; GUILayout.Label(new GUIContent("Rotation", "Rotation around the center of face UV bounds."), GUILayout.MaxWidth(width - 64)); UnityEngine.GUI.SetNextControlName("rotation"); EditorGUI.BeginChangeCheck(); tempFloat = EditorGUILayout.Slider(tempFloat, 0f, 360f, GUILayout.MaxWidth(width)); if (EditorGUI.EndChangeCheck()) { SetRotation(tempFloat, selection); } /** * Scale */ EditorGUI.showMixedValue = s_AutoUVSettingsDiff["scalex"] || s_AutoUVSettingsDiff["scaley"]; tempVec2 = s_AutoUVSettings.scale; GUI.SetNextControlName("scale"); EditorGUI.BeginChangeCheck(); s_AutoUVSettings.scale = EditorGUILayout.Vector2Field("Tiling", s_AutoUVSettings.scale, GUILayout.MaxWidth(width)); if (EditorGUI.EndChangeCheck()) { if (tempVec2.x != s_AutoUVSettings.scale.x) { SetScale(s_AutoUVSettings.scale, Axis2D.X, selection); } if (tempVec2.y != s_AutoUVSettings.scale.y) { SetScale(s_AutoUVSettings.scale, Axis2D.Y, selection); } } // Draw tiling shortcuts GUILayout.BeginHorizontal(); if (GUILayout.Button(".5", EditorStyles.miniButtonLeft)) { SetScale(Vector2.one * 2f, Axis2D.XY, selection); } if (GUILayout.Button("1", EditorStyles.miniButtonMid)) { SetScale(Vector2.one, Axis2D.XY, selection); } if (GUILayout.Button("2", EditorStyles.miniButtonMid)) { SetScale(Vector2.one * .5f, Axis2D.XY, selection); } if (GUILayout.Button("4", EditorStyles.miniButtonMid)) { SetScale(Vector2.one * .25f, Axis2D.XY, selection); } if (GUILayout.Button("8", EditorStyles.miniButtonMid)) { SetScale(Vector2.one * .125f, Axis2D.XY, selection); } if (GUILayout.Button("16", EditorStyles.miniButtonRight)) { SetScale(Vector2.one * .0625f, Axis2D.XY, selection); } GUILayout.EndHorizontal(); GUILayout.Space(4); UnityEngine.GUI.backgroundColor = PreferenceKeys.proBuilderLightGray; UI.EditorGUIUtility.DrawSeparator(1); UnityEngine.GUI.backgroundColor = Color.white; /** * Special */ GUILayout.Label("Special", EditorStyles.boldLabel); EditorGUI.showMixedValue = s_AutoUVSettingsDiff["useWorldSpace"]; EditorGUI.BeginChangeCheck(); s_AutoUVSettings.useWorldSpace = EditorGUILayout.Toggle("World Space", s_AutoUVSettings.useWorldSpace); if (EditorGUI.EndChangeCheck()) { SetUseWorldSpace(s_AutoUVSettings.useWorldSpace, selection); } GUI.backgroundColor = PreferenceKeys.proBuilderLightGray; UI.EditorGUIUtility.DrawSeparator(1); GUI.backgroundColor = Color.white; // Flip U EditorGUI.showMixedValue = s_AutoUVSettingsDiff["flipU"]; EditorGUI.BeginChangeCheck(); s_AutoUVSettings.flipU = EditorGUILayout.Toggle("Flip U", s_AutoUVSettings.flipU); if (EditorGUI.EndChangeCheck()) { SetFlipU(s_AutoUVSettings.flipU, selection); } // Flip V EditorGUI.showMixedValue = s_AutoUVSettingsDiff["flipV"]; EditorGUI.BeginChangeCheck(); s_AutoUVSettings.flipV = EditorGUILayout.Toggle("Flip V", s_AutoUVSettings.flipV); if (EditorGUI.EndChangeCheck()) { SetFlipV(s_AutoUVSettings.flipV, selection); } EditorGUI.showMixedValue = s_AutoUVSettingsDiff["swapUV"]; EditorGUI.BeginChangeCheck(); s_AutoUVSettings.swapUV = EditorGUILayout.Toggle("Swap U/V", s_AutoUVSettings.swapUV); if (EditorGUI.EndChangeCheck()) { SetSwapUV(s_AutoUVSettings.swapUV, selection); } /** * Texture Groups */ GUILayout.Label("Texture Groups", EditorStyles.boldLabel); EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = s_AutoUVSettingsDiff["textureGroup"]; GUI.SetNextControlName("textureGroup"); textureGroup = UI.EditorGUIUtility.IntFieldConstrained(new GUIContent("Texture Group", "Faces in a texture group will be UV mapped as a group, just as though you had selected these faces and used the \"Planar Project\" action"), textureGroup, (int)width); if (EditorGUI.EndChangeCheck()) { SetTextureGroup(selection, textureGroup); foreach (var kvp in MeshSelection.selectedFacesInEditZone) { kvp.Key.RefreshUV(kvp.Value); } SceneView.RepaintAll(); s_AutoUVSettingsDiff["textureGroup"] = false; } if (GUILayout.Button(new GUIContent("Group Selected Faces", "This sets all selected faces to share a texture group. What that means is that the UVs on these faces will all be projected as though they are a single plane. Ideal candidates for texture groups are floors with multiple faces, walls with edge loops, flat surfaces, etc."))) { for (int i = 0; i < selection.Length; i++) { TextureGroupSelectedFaces(selection[i]); } ProBuilderEditor.Refresh(); } if (GUILayout.Button(new GUIContent("Break Selected Groups", "This resets all the selected face Texture Groups."))) { SetTextureGroup(selection, -1); foreach (var kvp in MeshSelection.selectedFacesInEditZone) { kvp.Key.ToMesh(); kvp.Key.Refresh(); kvp.Key.Optimize(); } SceneView.RepaintAll(); s_AutoUVSettingsDiff["textureGroup"] = false; ProBuilderEditor.Refresh(); } /* Select all in current texture group */ if (GUILayout.Button(new GUIContent("Select Texture Group", "Selects all faces contained in this texture group."))) { for (int i = 0; i < selection.Length; i++) { selection[i].SetSelectedFaces(System.Array.FindAll(selection[i].facesInternal, x => x.textureGroup == textureGroup)); } ProBuilderEditor.Refresh(); } if (GUILayout.Button(new GUIContent("Reset UVs", "Reset UV projection parameters."))) { UndoUtility.RecordSelection(selection, "Reset UVs"); for (int i = 0; i < selection.Length; i++) { foreach (Face face in selection[i].GetSelectedFaces()) { face.uv = AutoUnwrapSettings.tile; face.textureGroup = -1; face.elementGroup = -1; } UVEditing.SplitUVs(selection[i], selection[i].GetSelectedFaces()); } ProBuilderEditor.Refresh(); } GUI.backgroundColor = PreferenceKeys.proBuilderLightGray; UI.EditorGUIUtility.DrawSeparator(1); GUI.backgroundColor = Color.white; /** * Clean up */ GUILayout.EndScrollView(); EditorGUI.showMixedValue = false; return(EditorGUI.EndChangeCheck()); }
internal static void OnObjectSelectionChanged() { // GameObjects returns both parent and child when both are selected, where transforms only returns the // top-most transform. s_UnitySelectionChangeMeshes.Clear(); s_ElementSelection.Clear(); s_ActiveMesh = null; var gameObjects = Selection.gameObjects; for (int i = 0, c = gameObjects.Length; i < c; i++) { #if UNITY_2019_3_OR_NEWER ProBuilderMesh mesh; if (gameObjects[i].TryGetComponent <ProBuilderMesh>(out mesh)) #else var mesh = gameObjects[i].GetComponent <ProBuilderMesh>(); if (mesh != null) #endif { if (gameObjects[i] == Selection.activeGameObject) { s_ActiveMesh = mesh; } s_UnitySelectionChangeMeshes.Add(mesh); } } for (int i = 0, c = s_TopSelection.Count; i < c; i++) { if (!s_UnitySelectionChangeMeshes.Contains(s_TopSelection[i])) { if (s_TopSelection[i] != null) { UndoUtility.RecordSelection(s_TopSelection[i], "Selection Change"); } s_TopSelection[i].ClearSelection(); } } s_TopSelection.Clear(); foreach (var mesh in s_UnitySelectionChangeMeshes) { // don't add prefabs or assets to the mesh selection if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(mesh.gameObject))) { EditorUtility.SynchronizeWithMeshFilter(mesh); s_TopSelection.Add(mesh); } } InvalidateCaches(); if (objectSelectionChanged != null) { objectSelectionChanged(); } s_UnitySelectionChangeMeshes.Clear(); }