public static void SelectBrushVariant(CSGTreeBrush brush, bool uniqueSelection = false) { Undo.RecordObject(ChiselSyncSelection.Instance, "Selected brush variant"); var node = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(brush); if (node) { node.hierarchyItem.SetBoundsDirty(); } var selectedBrushesLookup = Instance.selectedBrushesLookup; var modified = false;/* * if (uniqueSelection) * { * foreach (var variant in brush.AllSynchronizedVariants) * { * if (variant != brush) * modified = selectedBrushesLookup.Remove(variant) || modified; * } * }*/ modified = selectedBrushesLookup.Add(brush); if (modified) { ChiselOutlineRenderer.Instance.OnSelectionChanged(); } }
public static bool GetNodesInFrustum(Frustum frustum, int visibleLayers, ref HashSet <CSGTreeNode> rectFoundNodes) { var planes = new Plane[6]; Vector4 srcVector; var allTrees = CSGManager.AllTrees; for (var t = 0; t < allTrees.Length; t++) { var tree = allTrees[t]; var model = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(tree) as ChiselModel; if (!model || !model.isActiveAndEnabled) { continue; } if (((1 << model.gameObject.layer) & visibleLayers) == 0) { continue; } var query = ChiselMeshQueryManager.GetMeshQuery(model); // We only accept RayCasts into this model if it's visible if (!ChiselMeshQueryManager.IsVisible(query)) { continue; } // Transform the frustum into the space of the tree var transform = model.transform; var worldToLocalMatrixInversed = transform.localToWorldMatrix; // localToWorldMatrix == worldToLocalMatrix.inverse var worldToLocalMatrixInversedTransposed = worldToLocalMatrixInversed.transpose; for (int p = 0; p < 6; p++) { var srcPlane = frustum.Planes[p]; srcVector.x = srcPlane.normal.x; srcVector.y = srcPlane.normal.y; srcVector.z = srcPlane.normal.z; srcVector.w = srcPlane.distance; srcVector = worldToLocalMatrixInversedTransposed * srcVector; planes[p].normal = srcVector; planes[p].distance = srcVector.w; } var treeNodesInFrustum = tree.GetNodesInFrustum(planes); if (treeNodesInFrustum == null) { continue; } for (int n = 0; n < treeNodesInFrustum.Length; n++) { var treeNode = treeNodesInFrustum[n]; rectFoundNodes.Add(treeNode); } } return(rectFoundNodes.Count > 0); }
public static void ClearBrushVariants(CSGTreeBrush brush) { Undo.RecordObject(ChiselSyncSelection.Instance, "ClearBrushVariants variant"); var node = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(brush); if (node) { node.hierarchyItem.SetBoundsDirty(); } var modified = false; if (modified) { ChiselOutlineRenderer.Instance.OnSelectionChanged(); } }
public static void DeselectBrushVariant(CSGTreeBrush brush) { Undo.RecordObject(ChiselSyncSelection.Instance, "Deselected brush variant"); var node = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(brush); if (node) { node.hierarchyItem.SetBoundsDirty(); } var selectedBrushesLookup = Instance.selectedBrushesLookup; var modified = selectedBrushesLookup.Remove(brush); if (modified) { ChiselOutlineRenderer.Instance.OnSelectionChanged(); } }
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); } }
public static bool FindFirstWorldIntersection(List <ChiselIntersection> foundIntersections, Vector3 worldRayStart, Vector3 worldRayEnd, int visibleLayers = ~0, bool ignoreBackfaced = false, bool ignoreCulled = false, GameObject[] ignore = null, GameObject[] filter = null) { bool found = false; s_IgnoreInstanceIDs.Clear(); s_FilterInstanceIDs.Clear(); s_IgnoreNodes.Clear(); s_FilterNodes.Clear(); if (ignore != null) { foreach (var go in ignore) { var node = go.GetComponent <ChiselNode>(); if (node) { ChiselNodeHierarchyManager.GetChildrenOfHierarchyItem(s_IgnoreNodes, node.hierarchyItem); s_IgnoreInstanceIDs.Add(node.GetInstanceID()); } } } if (filter != null) { foreach (var go in filter) { var node = go.GetComponent <ChiselNode>(); if (node) { ChiselNodeHierarchyManager.GetChildrenOfHierarchyItem(s_FilterNodes, node.hierarchyItem); s_FilterInstanceIDs.Add(node.GetInstanceID()); if (node.hierarchyItem != null && node.hierarchyItem.Model) { s_FilterInstanceIDs.Add(node.hierarchyItem.Model.GetInstanceID()); } } } } using (var allTrees = new NativeList <CSGTree>(Allocator.Temp)) { CompactHierarchyManager.GetAllTrees(allTrees); for (var t = 0; t < allTrees.Length; t++) { var tree = allTrees[t]; var model = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(tree) as ChiselModel; if (!ChiselModelManager.IsSelectable(model)) { continue; } if (((1 << model.gameObject.layer) & visibleLayers) == 0) { continue; } var modelInstanceID = model.GetInstanceID(); if (s_IgnoreInstanceIDs.Contains(modelInstanceID) || (s_FilterInstanceIDs.Count > 0 && !s_FilterInstanceIDs.Contains(modelInstanceID))) { continue; } var query = ChiselMeshQueryManager.GetMeshQuery(model); var visibleQueries = ChiselMeshQueryManager.GetVisibleQueries(query); // We only accept RayCasts into this model if it's visible if (visibleQueries == null || visibleQueries.Length == 0) { return(false); } Vector3 treeRayStart; Vector3 treeRayEnd; var transform = model.transform; if (transform) { var worldToLocalMatrix = transform.worldToLocalMatrix; treeRayStart = worldToLocalMatrix.MultiplyPoint(worldRayStart); treeRayEnd = worldToLocalMatrix.MultiplyPoint(worldRayEnd); } else { treeRayStart = worldRayStart; treeRayEnd = worldRayEnd; } var treeIntersections = CSGQueryManager.RayCastMulti(ChiselMeshQueryManager.GetMeshQuery(model), tree, treeRayStart, treeRayEnd, s_IgnoreNodes, s_FilterNodes, ignoreBackfaced, ignoreCulled); if (treeIntersections == null) { continue; } for (var i = 0; i < treeIntersections.Length; i++) { var intersection = treeIntersections[i]; var brush = intersection.brush; var instanceID = brush.UserID; if ((s_FilterInstanceIDs.Count > 0 && !s_FilterInstanceIDs.Contains(instanceID)) || s_IgnoreInstanceIDs.Contains(instanceID)) { continue; } foundIntersections.Add(Convert(intersection)); found = true; } } return(found); } }
public static bool FindFirstWorldIntersection(Vector3 worldRayStart, Vector3 worldRayEnd, int filterLayerParameter0, int visibleLayers, GameObject[] ignore, GameObject[] filter, out ChiselIntersection foundIntersection) { bool found = false; foundIntersection = ChiselIntersection.None; HashSet <int> ignoreInstanceIDs = null; HashSet <int> filterInstanceIDs = null; if (ignore != null) { ignoreInstanceIDs = new HashSet <int>(); foreach (var go in ignore) { var node = go.GetComponent <ChiselNode>(); if (node) { ignoreInstanceIDs.Add(node.GetInstanceID()); } } } if (filter != null) { filterInstanceIDs = new HashSet <int>(); foreach (var go in filter) { var node = go.GetComponent <ChiselNode>(); if (node) { filterInstanceIDs.Add(node.GetInstanceID()); } } } var allTrees = CSGManager.AllTrees; for (var t = 0; t < allTrees.Length; t++) { var tree = allTrees[t]; var model = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(tree) as ChiselModel; if (!ChiselModelManager.IsVisible(model)) { continue; } if ((ignoreInstanceIDs != null && ignoreInstanceIDs.Contains(model.GetInstanceID()))) { return(false); } if ((filterInstanceIDs != null && !filterInstanceIDs.Contains(model.GetInstanceID()))) { return(false); } if (((1 << model.gameObject.layer) & visibleLayers) == 0) { continue; } var query = ChiselMeshQueryManager.GetMeshQuery(model); var visibleQueries = ChiselMeshQueryManager.GetVisibleQueries(query); // We only accept RayCasts into this model if it's visible if (visibleQueries == null || visibleQueries.Length == 0) { return(false); } Vector3 treeRayStart; Vector3 treeRayEnd; var transform = model.transform; if (transform) { var worldToLocalMatrix = transform.worldToLocalMatrix; treeRayStart = worldToLocalMatrix.MultiplyPoint(worldRayStart); treeRayEnd = worldToLocalMatrix.MultiplyPoint(worldRayEnd); } else { treeRayStart = worldRayStart; treeRayEnd = worldRayEnd; } var treeIntersections = CSGManager.RayCastMulti(ChiselMeshQueryManager.GetMeshQuery(model), tree, treeRayStart, treeRayEnd); if (treeIntersections == null) { continue; } for (var i = 0; i < treeIntersections.Length; i++) { var intersection = treeIntersections[i]; var brush = intersection.brush; var instanceID = brush.UserID; if ((filterInstanceIDs != null && !filterInstanceIDs.Contains(instanceID))) { continue; } if ((ignoreInstanceIDs != null && ignoreInstanceIDs.Contains(instanceID))) { continue; } if (intersection.surfaceIntersection.distance < foundIntersection.brushIntersection.surfaceIntersection.distance) { foundIntersection = Convert(intersection); found = true; } } } return(found); }
public static bool FindMultiWorldIntersection(Vector3 worldRayStart, Vector3 worldRayEnd, int filterLayerParameter0, int visibleLayers, GameObject[] ignore, GameObject[] filter, out CSGTreeBrushIntersection[] intersections) { intersections = null; __foundIntersections.Clear(); HashSet <int> ignoreInstanceIDs = null; HashSet <int> filterInstanceIDs = null; if (ignore != null) { ignoreInstanceIDs = new HashSet <int>(); foreach (var go in ignore) { var node = go.GetComponent <ChiselNode>(); if (node) { ignoreInstanceIDs.Add(node.GetInstanceID()); } } } if (filter != null) { filterInstanceIDs = new HashSet <int>(); foreach (var go in filter) { var node = go.GetComponent <ChiselNode>(); if (node) { filterInstanceIDs.Add(node.GetInstanceID()); } } } var allTrees = CSGManager.AllTrees; for (var t = 0; t < allTrees.Length; t++) { var tree = allTrees[t]; var model = ChiselNodeHierarchyManager.FindChiselNodeByTreeNode(tree) as ChiselModel; if (!model || !model.isActiveAndEnabled) { continue; } if ((ignoreInstanceIDs != null && ignoreInstanceIDs.Contains(model.GetInstanceID()))) { return(false); } if ((filterInstanceIDs != null && !filterInstanceIDs.Contains(model.GetInstanceID()))) { return(false); } if (((1 << model.gameObject.layer) & visibleLayers) == 0) { continue; } var query = ChiselMeshQueryManager.GetMeshQuery(model); // We only accept RayCasts into this model if it's visible if (!ChiselMeshQueryManager.IsVisible(query)) { continue; } Vector3 treeRayStart; Vector3 treeRayEnd; var transform = model.transform; if (transform) { var worldToLocalMatrix = transform.worldToLocalMatrix; treeRayStart = worldToLocalMatrix.MultiplyPoint(worldRayStart); treeRayEnd = worldToLocalMatrix.MultiplyPoint(worldRayEnd); } else { treeRayStart = worldRayStart; treeRayEnd = worldRayEnd; } var treeIntersections = tree.RayCastMulti(ChiselMeshQueryManager.GetMeshQuery(model), treeRayStart, treeRayEnd, model.transform.localToWorldMatrix, filterLayerParameter0); if (treeIntersections == null) { continue; } for (var i = 0; i < treeIntersections.Length; i++) { var intersection = treeIntersections[i]; var brush = intersection.brush; var instanceID = brush.UserID; if ((filterInstanceIDs != null && !filterInstanceIDs.Contains(instanceID))) { continue; } if ((ignoreInstanceIDs != null && ignoreInstanceIDs.Contains(instanceID))) { continue; } __foundIntersections[brush] = intersection; } } if (__foundIntersections.Count == 0) { return(false); } var sortedIntersections = __foundIntersections.Values.ToArray(); Array.Sort(sortedIntersections, (x, y) => (x.surfaceIntersection.distance < y.surfaceIntersection.distance) ? -1 : 0); __foundIntersections.Clear(); intersections = sortedIntersections; return(true); }