// TODO: make selecting variants work when selecting in hierarchy/rect-select too public static void DoSelectionClick(SceneView sceneView, Vector2 mousePosition) { ChiselIntersection intersection; var gameobject = ChiselClickSelectionManager.PickClosestGameObject(mousePosition, out intersection); // If we're a child of an operation that has a "handle as one" flag set, return that instead gameobject = ChiselSceneQuery.FindSelectionBase(gameobject); var selectionType = GetCurrentSelectionType(); var selectedObjectsOnClick = new List <int>(Selection.instanceIDs); switch (selectionType) { case SelectionType.Additive: { if (!gameobject) { break; } ChiselSyncSelection.SelectBrushVariant(intersection.brushIntersection.brush, uniqueSelection: false); var instanceID = gameobject.GetInstanceID(); selectedObjectsOnClick.Add(instanceID); ChiselClickSelectionManager.ignoreSelectionChanged = true; Selection.instanceIDs = selectedObjectsOnClick.ToArray(); break; } case SelectionType.Subtractive: { if (!gameobject) { break; } Undo.RecordObject(ChiselSyncSelection.Instance, "Deselected brush variant"); ChiselSyncSelection.DeselectBrushVariant(intersection.brushIntersection.brush); // Can only deselect brush if all it's synchronized brushes have also been deselected if (!ChiselSyncSelection.IsAnyBrushVariantSelected(intersection.brushIntersection.brush)) { var instanceID = gameobject.GetInstanceID(); selectedObjectsOnClick.Remove(instanceID); } ChiselClickSelectionManager.ignoreSelectionChanged = true; Selection.instanceIDs = selectedObjectsOnClick.ToArray(); return; } default: { Undo.RecordObject(ChiselSyncSelection.Instance, "Selected brush variant"); ChiselSyncSelection.SelectBrushVariant(intersection.brushIntersection.brush, uniqueSelection: true); ChiselClickSelectionManager.ignoreSelectionChanged = true; Selection.activeGameObject = gameobject; break; } } }
void UpdateBrushState() { if (updateBrushSelection) { updateBrushSelection = false; UpdateBrushSelection(); updateBrushWireframe = true; } if (updateBrushWireframe) { updateBrushWireframe = false; UpdateBrushWireframe(); updateBrushLineCache = true; } if (updateBrushLineCache) { updateBrushLineCache = false; brushOutlineRenderer.Begin(); foreach (var pair in brushOutlines) { var wireframe = pair.Value; if (wireframe == null) { continue; } var outline = pair.Key; if (!outline.brush.Valid) { continue; } // TODO: simplify this var wireframeValue = pair.Value; var modelTransform = outline.transform; //var brushes = outline.brush.AllSynchronizedVariants; //var anySelected = ChiselSyncSelection.IsAnyBrushVariantSelected(brushes); //foreach (var brush in brushes) var brush = outline.brush; var anySelected = ChiselSyncSelection.IsBrushVariantSelected(brush); { Matrix4x4 transformation; if (modelTransform) { transformation = modelTransform.localToWorldMatrix * brush.NodeToTreeSpaceMatrix; } else { transformation = brush.NodeToTreeSpaceMatrix; } if ((VisualizationMode & VisualizationMode.Outline) == VisualizationMode.Outline) { var directSelect = !ChiselEditModeManager.EditMode.ShowCompleteOutline && ((brush == outline.brush && !anySelected) || (anySelected && ChiselSyncSelection.IsBrushVariantSelected(brush))); // TODO: tweak look of selection, figure out how to do backfaced lighting of edges, for clarity // TODO: support selecting surfaces/edges/points (without showing the entire object selection) if (directSelect) { brushOutlineRenderer.DrawOutlines(transformation, wireframeValue, ColorManager.kSelectedOutlineColor, thickness: 3.0f, onlyInnerLines: false); } else { brushOutlineRenderer.DrawOutlines(transformation, wireframeValue, ColorManager.kUnselectedOutlineColor, thickness: 1.0f, onlyInnerLines: false);// (ChiselEditModeManager.EditMode == CSGEditMode.ShapeEdit)); } } if ((VisualizationMode & VisualizationMode.SimpleOutline) == VisualizationMode.SimpleOutline) { brushOutlineRenderer.DrawSimpleOutlines(transformation, wireframeValue, ColorManager.kUnselectedOutlineColor); } } } brushOutlineRenderer.End(); } }
internal static void Update(SceneView sceneView) { if (!ChiselRectSelection.Valid) { prevStartGUIPoint = new Vector2(float.PositiveInfinity, float.PositiveInfinity); prevMouseGUIPoint = prevStartGUIPoint; prevStartScreenPoint = Vector2.zero; prevMouseScreenPoint = Vector2.zero; rectFoundGameObjects.Clear(); rectFoundTreeNodes.Clear(); return; } ChiselRectSelection.SceneView = sceneView; var rectSelectionID = ChiselRectSelection.RectSelectionID; var hotControl = GUIUtility.hotControl; var areRectSelecting = hotControl == rectSelectionID; var typeForControl = Event.current.GetTypeForControl(rectSelectionID); // check if we're rect-selecting if (areRectSelecting) { if ((typeForControl == EventType.Used || Event.current.commandName == "ModifierKeysChanged") && ChiselRectSelection.RectSelecting) { var selectStartPoint = ChiselRectSelection.SelectStartPoint; var selectMousePoint = ChiselRectSelection.SelectMousePoint; // determine if our frustum changed since the last time bool modified = false; bool needUpdate = false; if (prevStartGUIPoint != selectStartPoint) { prevStartGUIPoint = selectStartPoint; prevStartScreenPoint = Event.current.mousePosition; needUpdate = true; } if (prevMouseGUIPoint != selectMousePoint) { prevMouseGUIPoint = selectMousePoint; prevMouseScreenPoint = Event.current.mousePosition; needUpdate = true; } if (needUpdate) { var rect = ChiselCameraUtility.PointsToRect(prevStartScreenPoint, prevMouseScreenPoint); if (rect.width > 3 && rect.height > 3) { var frustum = ChiselCameraUtility.GetCameraSubFrustum(Camera.current, rect); var selectionType = GetCurrentSelectionType(); if (selectionType == SelectionType.Replace) { rectFoundTreeNodes.Clear(); rectFoundGameObjects.Clear(); } // Find all the brushes (and it's gameObjects) that are inside the frustum if (!ChiselSceneQuery.GetNodesInFrustum(frustum, UnityEditor.Tools.visibleLayers, ref rectFoundTreeNodes)) { if (rectFoundGameObjects != null && rectFoundGameObjects.Count > 0) { rectFoundTreeNodes.Clear(); rectFoundGameObjects.Clear(); modified = true; } } else { modified = true; } foreach (var treeNode in rectFoundTreeNodes) { var brush = (CSGTreeBrush)treeNode; if (brush.Valid) { switch (selectionType) { case SelectionType.Additive: { ChiselSyncSelection.SelectBrushVariant(brush, uniqueSelection: false); break; } case SelectionType.Subtractive: { ChiselSyncSelection.DeselectBrushVariant(brush); break; } default: { ChiselSyncSelection.SelectBrushVariant(brush, uniqueSelection: true); break; } } } var nodeComponent = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(treeNode); if (!nodeComponent) { continue; } var gameObject = nodeComponent.gameObject; rectFoundGameObjects.Add(gameObject); } } } UnityEngine.Object[] currentSelection = null; var originalLastSelection = ChiselRectSelection.LastSelection; var originalSelectionStart = ChiselRectSelection.SelectionStart; if (modified && rectFoundGameObjects != null && rectFoundGameObjects.Count > 0) { foreach (var obj in rectFoundGameObjects) { // if it hasn't already been added, add the obj if (!originalLastSelection.ContainsKey(obj)) { originalLastSelection.Add(obj, false); } } currentSelection = originalLastSelection.Keys.ToArray(); ChiselRectSelection.CurrentSelection = currentSelection; } else { if (currentSelection == null || modified) { currentSelection = originalLastSelection.Keys.ToArray(); } } if (RemoveGeneratedMeshesFromArray(ref originalSelectionStart)) { modified = true; } if (currentSelection != null && RemoveGeneratedMeshesFromArray(ref currentSelection)) { modified = true; } if ((Event.current.commandName == "ModifierKeysChanged" || modified)) { var foundObjects = currentSelection; RemoveGeneratedMeshesFromArray(ref foundObjects); // calling static method UpdateSelection of RectSelection ChiselRectSelection.UpdateSelection(originalSelectionStart, foundObjects, GetCurrentSelectionType()); } } hotControl = GUIUtility.hotControl; } if (hotControl != rectSelectionID) { prevStartGUIPoint = Vector2.zero; prevMouseGUIPoint = Vector2.zero; rectFoundGameObjects.Clear(); rectFoundTreeNodes.Clear(); } /*else * if (ignoreRect) * { * hotControl = 0; * GUIUtility.hotControl = 0; * } */ bool click = false; var evt = Event.current; switch (typeForControl) { case EventType.MouseDown: { rectClickDown = (Event.current.button == 0 && areRectSelecting); clickMousePosition = Event.current.mousePosition; mouseDragged = false; break; } case EventType.MouseUp: { if (!mouseDragged) { if ((UnityEditor.HandleUtility.nearestControl != 0 || evt.button != 0) && (GUIUtility.keyboardControl != 0 || evt.button != 2)) { break; } click = true; Event.current.Use(); } rectClickDown = false; break; } case EventType.MouseMove: { rectClickDown = false; break; } case EventType.MouseDrag: { mouseDragged = true; break; } case EventType.Used: { if (!mouseDragged) { var delta = Event.current.mousePosition - clickMousePosition; if (Mathf.Abs(delta.x) > 4 || Mathf.Abs(delta.y) > 4) { mouseDragged = true; } } if (mouseDragged || !rectClickDown || Event.current.button != 0 || ChiselRectSelection.RectSelecting) { rectClickDown = false; break; } click = true; Event.current.Use(); break; } case EventType.KeyUp: { if (hotControl == 0 && Event.current.keyCode == UnityEngine.KeyCode.Escape) { if (GUIUtility.hotControl == 0 && // make sure we're not actively doing anything Tools.current != Tool.Custom) { // This deselects everything and disables all tool modes Selection.activeTransform = null; Event.current.Use(); } } break; } case EventType.ValidateCommand: { if (Event.current.commandName != "SelectAll") { break; } Event.current.Use(); break; } case EventType.ExecuteCommand: { if (Event.current.commandName != "SelectAll") { break; } var transforms = new List <UnityEngine.Object>(); for (int sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++) { var scene = SceneManager.GetSceneAt(sceneIndex); foreach (var gameObject in scene.GetRootGameObjects()) { foreach (var transform in gameObject.GetComponentsInChildren <Transform>()) { if ((transform.hideFlags & (HideFlags.NotEditable | HideFlags.HideInHierarchy)) == (HideFlags.NotEditable | HideFlags.HideInHierarchy)) { continue; } transforms.Add(transform.gameObject); } } } var foundObjects = transforms.ToArray(); RemoveGeneratedMeshesFromArray(ref foundObjects); Selection.objects = foundObjects; Event.current.Use(); break; } /* * case EventType.ValidateCommand: * { * if (Event.current.commandName == "SelectAll") * { * Event.current.Use(); * break; * } * if (Keys.HandleSceneValidate(EditModeManager.CurrentTool, true)) * { * Event.current.Use(); * HandleUtility.Repaint(); * } * break; * } * case EventType.ExecuteCommand: * { * if (Event.current.commandName == "SelectAll") * { * var transforms = new List<UnityEngine.Object>(); * for (int sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++) * { * var scene = SceneManager.GetSceneAt(sceneIndex); * foreach (var gameObject in scene.GetRootGameObjects()) * { * foreach (var transform in gameObject.GetComponentsInChildren<Transform>()) * { * if ((transform.hideFlags & (HideFlags.NotEditable | HideFlags.HideInHierarchy)) == (HideFlags.NotEditable | HideFlags.HideInHierarchy)) * continue; * transforms.Add(transform.gameObject); * } * } * } * Selection.objects = transforms.ToArray(); * * Event.current.Use(); * break; * } * break; * } * * case EventType.KeyDown: * { * if (Keys.HandleSceneKeyDown(EditModeManager.CurrentTool, true)) * { * Event.current.Use(); * HandleUtility.Repaint(); * } * break; * } * * case EventType.KeyUp: * { * if (Keys.HandleSceneKeyUp(EditModeManager.CurrentTool, true)) * { * Event.current.Use(); * HandleUtility.Repaint(); * } * break; * } */ } if (click) { // make sure GeneratedMeshes are not part of our selection RemoveGeneratedMeshesFromSelection(); DoSelectionClick(sceneView, Event.current.mousePosition); } }
static void OnMoveTool() { var position = Tools.handlePosition; var rotation = Tools.handleRotation; #if SYNC_SUPPORT // TODO: finish and fix this var selectedNodes = Selection.GetFiltered <ChiselNode>(SelectionMode.Editable | SelectionMode.TopLevel); if (selectedNodes.Length == 0) { // TODO: probably need to use our own PositionHandle on non Chisel objects, to be able to snap to grid return; } var transformation = Matrix4x4.identity; var invTransformation = Matrix4x4.identity; // TODO: figure out how to handle this with selecting multiple variants of the same brush (synchronized brushes) if (selectedNodes.Length == 1) { foundTreeBrushes.Clear(); selectedNodes[0].GetAllTreeBrushes(foundTreeBrushes, ignoreSynchronizedBrushes: true); if (foundTreeBrushes.Count == 1) { var transform = ChiselNodeHierarchyManager.FindModelTransformOfTransform(selectedNodes[0].hierarchyItem.Transform); var firstBrush = foundTreeBrushes.First(); var brush = firstBrush; if (!ChiselSyncSelection.IsBrushVariantSelected(brush)) { List <CSGTreeBrush> selectedVariants = new List <CSGTreeBrush>(); if (ChiselSyncSelection.GetSelectedVariantsOfBrush(brush, selectedVariants)) { brush = selectedVariants[0]; } } if (transform) { transformation = transform.localToWorldMatrix * brush.NodeToTreeSpaceMatrix; } else { transformation = brush.NodeToTreeSpaceMatrix; } rotation = Quaternion.LookRotation(transformation.GetColumn(2), transformation.GetColumn(1)); invTransformation = selectedNodes[0].transform.localToWorldMatrix * transformation.inverse; if (Tools.pivotRotation == PivotRotation.Global) { rotation = Quaternion.identity; } position = transformation.GetColumn(3); } } #endif EditorGUI.BeginChangeCheck(); // TODO: make this work with bounds! var newPosition = UnitySceneExtensions.SceneHandles.PositionHandle(position, rotation); if (EditorGUI.EndChangeCheck()) { var delta = newPosition - position; var transforms = Selection.transforms; if (transforms != null && transforms.Length > 0) { MoveTransformsTo(transforms, delta); } } }