public PlaneIntersection(CSGTreeBrushIntersection brushIntersection, ChiselNode node, ChiselModel model) { this.point = brushIntersection.surfaceIntersection.worldIntersection; this.plane = brushIntersection.surfaceIntersection.worldPlane; this.node = node; this.model = model; }
public static bool PickFirstGameObject(Vector2 position, out CSGTreeBrushIntersection intersection) { GameObject[] ignore = null; GameObject[] filter = null; if (!PickClosestGameObjectDelegated(position, ref ignore, ref filter, out intersection)) { return(false); } return(intersection.surfaceID != -1); }
public static ChiselNode PickClosestNode(Vector2 position, out CSGTreeBrushIntersection intersection) { var camera = Camera.current; int layers = camera.cullingMask; var pickposition = GUIClip.GUIClipUnclip(position); pickposition = EditorGUIUtility.PointsToPixels(pickposition); pickposition.y = Screen.height - pickposition.y - camera.pixelRect.yMin; GameObject[] ignore = new GameObject[0]; GameObject[] filter = null; return(PickNode(camera, pickposition, layers, ref ignore, ref filter, out intersection)); }
internal static GameObject PickClosestGameObjectDelegated(Vector2 position, ref GameObject[] ignore, ref GameObject[] filter, out CSGTreeBrushIntersection intersection) { var camera = Camera.current; int layers = camera.cullingMask; var pickposition = GUIClip.GUIClipUnclip(position); pickposition = EditorGUIUtility.PointsToPixels(pickposition); pickposition.y = Screen.height - pickposition.y - camera.pixelRect.yMin; /* * GameObject picked = null; * if (pickClosestGameObjectDelegate != null) * { * // TODO: figure out how to call a delegate through reflection with an out parameter ... * }*/ intersection = new CSGTreeBrushIntersection { surfaceID = -1, brushUserID = -1 }; //if (picked == null) { ChiselNode node; ChiselModel model; var gameObject = PickNodeOrGameObject(camera, pickposition, layers, ref ignore, ref filter, out model, out node, out intersection); if (!model) { return(gameObject); } if (node) { return(gameObject); } return(null); } /* * if (CSGGeneratedComponentManager.IsObjectGenerated(picked)) * { * if (ignore == null) * return null; * ArrayUtility.Add(ref ignore, picked); * return PickClosestGameObjectDelegated(position, ref ignore, ref filter, out intersection); * } * return picked;*/ }
static ChiselIntersection Convert(CSGTreeBrushIntersection intersection) { var node = ChiselNodeHierarchyManager.FindChiselNodeByInstanceID(intersection.brush.UserID); var model = ChiselNodeHierarchyManager.FindChiselNodeByInstanceID(intersection.tree.UserID) as ChiselModel; var treeLocalToWorldMatrix = model.transform.localToWorldMatrix; var worldPlaneIntersection = treeLocalToWorldMatrix.MultiplyPoint(intersection.surfaceIntersection.treePlaneIntersection); var worldPlane = treeLocalToWorldMatrix.TransformPlane(intersection.surfaceIntersection.treePlane); return(new ChiselIntersection() { treeNode = node, model = model, worldPlane = worldPlane, worldPlaneIntersection = worldPlaneIntersection, brushIntersection = intersection }); }
public static bool FindFirstWorldIntersection(ChiselModel model, Vector3 worldRayStart, Vector3 worldRayEnd, int filterLayerParameter0, int visibleLayers, GameObject[] ignore, GameObject[] filter, out CSGTreeBrushIntersection foundIntersection) { foundIntersection = new CSGTreeBrushIntersection(); foundIntersection.surfaceIntersection.distance = float.PositiveInfinity; if (!model || !model.isActiveAndEnabled) { return(false); } CSGTreeNode[] ignoreBrushes = null; HashSet <int> ignoreInstanceIDs = null; HashSet <int> filterInstanceIDs = null; if (ignore != null) { //var ignoreBrushList = new HashSet<CSGTreeBrush>(); ignoreInstanceIDs = new HashSet <int>(); foreach (var go in ignore) { var node = go.GetComponent <ChiselNode>(); if (node) { //node.GetAllTreeBrushes(ignoreBrushList); ignoreInstanceIDs.Add(node.GetInstanceID()); } }/* * if (ignoreBrushList.Count > 0) * { * // TODO: fix this, ignorebrushes doesn't remove the brush completely, but that's not necessarily correct * // for example: another brush that is not ignored, subtracts from a brush that's ignored (so its insides should be selectable) * ignoreBrushes = new CSGTreeNode[ignoreBrushList.Count]; * int index = 0; * foreach(var brush in ignoreBrushList) * { * ignoreBrushes[index] = brush; * index++; * } * }*/ } if (filter != null) { filterInstanceIDs = new HashSet <int>(); foreach (var go in filter) { var node = go.GetComponent <ChiselNode>(); if (node) { filterInstanceIDs.Add(node.GetInstanceID()); } } } var tree = model.Node; 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) { return(false); } var query = CSGMeshQueryManager.GetMeshQuery(model); // We only accept RayCasts into this model if it's visible if (!CSGMeshQueryManager.IsVisible(query)) { 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 = tree.RayCastMulti(CSGMeshQueryManager.GetMeshQuery(model), treeRayStart, treeRayEnd, model.transform.localToWorldMatrix, filterLayerParameter0, ignoreBrushes); if (treeIntersections == null) { return(false); } bool found = false; 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.surfaceIntersection.distance) { foundIntersection = intersection; found = true; } } return(found); }
public static bool FindFirstWorldIntersection(ChiselModel model, Vector3 worldRayStart, Vector3 worldRayEnd, int filterLayerParameter0, int visibleLayers, out CSGTreeBrushIntersection foundIntersection) { return(FindFirstWorldIntersection(model, worldRayStart, worldRayEnd, filterLayerParameter0, visibleLayers, null, null, out foundIntersection)); }
public static bool FindFirstWorldIntersection(Vector3 worldRayStart, Vector3 worldRayEnd, int filterLayerParameter0, int visibleLayers, GameObject[] ignore, GameObject[] filter, out CSGTreeBrushIntersection foundIntersection) { bool found = false; foundIntersection = new CSGTreeBrushIntersection(); foundIntersection.surfaceIntersection.distance = float.PositiveInfinity; 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 = CSGNodeHierarchyManager.FindCSGNodeByTreeNode(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 = CSGMeshQueryManager.GetMeshQuery(model); // We only accept RayCasts into this model if it's visible if (!CSGMeshQueryManager.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(CSGMeshQueryManager.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; } if (intersection.surfaceIntersection.distance < foundIntersection.surfaceIntersection.distance) { foundIntersection = intersection; found = true; } } } return(found); }
internal static ChiselNode PickNode(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out CSGTreeBrushIntersection intersection) { TryNextNode: ChiselModel model; ChiselNode node; var gameObject = PickNodeOrGameObject(camera, pickposition, layers, ref ignore, ref filter, out model, out node, out intersection); if (object.Equals(gameObject, null)) { return(null); } if (model) { return(node); } ArrayUtility.Add(ref ignore, gameObject); goto TryNextNode; }
internal static GameObject PickNodeOrGameObject(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out ChiselModel model, out ChiselNode node, out CSGTreeBrushIntersection intersection) { TryNextSelection: intersection = new CSGTreeBrushIntersection { surfaceID = -1, brushUserID = -1 }; model = null; node = null; Material sharedMaterial; var gameObject = PickModel(camera, pickposition, layers, ref ignore, ref filter, out model, out sharedMaterial); if (object.Equals(gameObject, null)) { return(null); } if (model) { int filterLayerParameter0 = (sharedMaterial) ? sharedMaterial.GetInstanceID() : 0; { var worldRay = camera.ScreenPointToRay(pickposition); var worldRayStart = worldRay.origin; var worldRayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane)); var worldRayEnd = worldRayStart + worldRayVector; CSGTreeBrushIntersection tempIntersection; if (ChiselSceneQuery.FindFirstWorldIntersection(model, worldRayStart, worldRayEnd, filterLayerParameter0, layers, ignore, filter, out tempIntersection)) { var clickedBrush = tempIntersection.brush; node = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(clickedBrush.UserID); if (node) { if (ignore != null && ignore.Contains(node.gameObject)) { node = null; return(null); } intersection = tempIntersection; return(node.gameObject); } else { node = null; } } } if (ignore == null) { return(null); } ArrayUtility.Add(ref ignore, gameObject); goto TryNextSelection; } if (object.Equals(gameObject, null)) { return(null); } if (ignore != null && ignore.Contains(gameObject)) { return(null); } return(gameObject); }
public static SurfaceReference[] FindSurfaceReference(Vector2 position, bool selectAllSurfaces, out CSGTreeBrushIntersection intersection, out SurfaceReference surfaceReference) { intersection = CSGTreeBrushIntersection.None; surfaceReference = null; try { if (!PickFirstGameObject(position, out intersection)) { return(null); } var brush = intersection.brush; var node = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(brush.UserID); if (!node) { return(null); } surfaceReference = node.FindSurfaceReference(brush, intersection.surfaceID); if (selectAllSurfaces) { return(node.GetAllSurfaceReferences(brush)); } if (surfaceReference == null) { return(null); } return(new SurfaceReference[] { surfaceReference }); } catch (Exception ex) { Debug.LogException(ex); return(null); } }
// TODO: rewrite this, why do we need hashes? public static GameObject PickClosestGameObject(Vector2 mousePosition, out CSGTreeBrushIntersection intersection) { intersection = new CSGTreeBrushIntersection { surfaceID = -1, brushUserID = -1 }; s_RetainHashes = true; if (enumerator == null || (prevMousePosition - mousePosition).sqrMagnitude > 2) { enumerator = GetAllOverlapping(mousePosition).GetEnumerator(); prevMousePosition = mousePosition; } if (!enumerator.MoveNext()) { enumerator = GetAllOverlapping(mousePosition).GetEnumerator(); if (!enumerator.MoveNext()) { return(null); } } var topmost = enumerator.Current; var selectionBase = GUIClip.FindSelectionBase(topmost.Key); var first = (selectionBase == null ? topmost.Key : selectionBase); int topmostHash = topmost.GetHashCode(); int prefixHash = topmostHash; if (Selection.activeGameObject == null) { // Nothing selected // Return selection base if it exists, otherwise topmost game object s_PreviousTopmostHash = topmostHash; s_PreviousPrefixHash = prefixHash; intersection = topmost.Value; return(first); } if (topmostHash != s_PreviousTopmostHash) { // Topmost game object changed // Return selection base if exists and is not already selected, otherwise topmost game object s_PreviousTopmostHash = topmostHash; s_PreviousPrefixHash = prefixHash; intersection = topmost.Value; return(Selection.activeGameObject == selectionBase ? topmost.Key : first); } s_PreviousTopmostHash = topmostHash; // Pick potential selection base before topmost game object if (Selection.activeGameObject == selectionBase) { intersection = topmost.Value; if (prefixHash != s_PreviousPrefixHash) { s_PreviousPrefixHash = prefixHash; return(selectionBase); } return(topmost.Key); } // Check if active game object will appear in selection stack GameObject[] ignore = null; GameObject[] filter = new GameObject[] { Selection.activeGameObject }; var picked = PickClosestGameObjectDelegated(mousePosition, ref ignore, ref filter, out intersection); if (picked == Selection.activeGameObject) { // Advance enumerator to active game object while (enumerator.Current.Key != Selection.activeGameObject) { if (!enumerator.MoveNext()) { s_PreviousPrefixHash = topmostHash; intersection = topmost.Value; return(first); // Should not occur } UpdateHash(ref prefixHash, enumerator.Current); } } if (prefixHash != s_PreviousPrefixHash) { // Prefix hash changed, start over s_PreviousPrefixHash = topmostHash; intersection = topmost.Value; return(first); } // Move on to next game object if (!enumerator.MoveNext()) { s_PreviousPrefixHash = topmostHash; intersection = topmost.Value; return(first); // End reached, start over } UpdateHash(ref prefixHash, enumerator.Current); if (enumerator.Current.Key == selectionBase) { // Skip selection base if (!enumerator.MoveNext()) { s_PreviousPrefixHash = topmostHash; intersection = topmost.Value; return(first); // End reached, start over } UpdateHash(ref prefixHash, enumerator.Current); } s_PreviousPrefixHash = prefixHash; return(enumerator.Current.Key); }