public IFloodArea FetchWalkableFlood(Position center, int floodRange) { // performance: maybe we should keep a few last calculated results for center-floodRange pairs if (_cachedFloodArea == null) { _cachedFloodArea = new FloodArea(center, floodRange); } int expectedMatrixSize = floodRange * 2 + 1; if (_cachedFloodArea.ArraySize < expectedMatrixSize) { _cachedFloodArea.IncreaseMatrix(expectedMatrixSize); } if (_cachedFloodArea.Center != center) { _cachedFloodArea.Center = center; int boundsSize = floodRange * 2; _cachedFloodArea.Bounds = new Bounds(center.x - floodRange, center.y - floodRange, boundsSize, boundsSize); } var findHighestMark = new FindHighestMarkNeighbourProcessor(); var parameters = new FloodParameters(center.x, center.y) { Qualifier = (x, y) => _grid.IsWalkable(new Position(x, y)), BoundsRestriction = BoundsUtilities.ToFloodBounds(_cachedFloodArea.Bounds), NeighbourProcessor = findHighestMark.Process }; Position furthestPosition = center; _floodSpiller.SpillFlood(parameters, _cachedFloodArea.ValueMatrix); _cachedFloodArea.FurthestPosition = furthestPosition; return(_cachedFloodArea); }
public static void Flip(CSGBrush[] brushes, Matrix4x4 flipMatrix, string undoDescription = "Flip brushes") { var fail = false; Undo.IncrementCurrentGroup(); Undo.RegisterCompleteObjectUndo(brushes.ToArray <UnityEngine.Object>(), undoDescription); var isGlobal = Tools.pivotRotation == PivotRotation.Global; var centerAll = BoundsUtilities.GetCenter(brushes); for (var t = 0; t < brushes.Length; t++) { var brush = brushes[t]; var position = brush.transform.position; Matrix4x4 brushFlip; Vector3 brushCenter; if (isGlobal) { brushFlip = brush.transform.localToWorldMatrix * flipMatrix * brush.transform.worldToLocalMatrix; brushCenter = brush.transform.InverseTransformPoint(centerAll) - position; } else { brushFlip = flipMatrix; brushCenter = brush.transform.InverseTransformPoint(centerAll); } brushFlip = Matrix4x4.TRS(brushCenter, Quaternion.identity, Vector3.one) * brushFlip * Matrix4x4.TRS(-brushCenter, Quaternion.identity, Vector3.one); brush.EnsureInitialized(); var shape = brush.Shape; for (var s = 0; s < shape.Surfaces.Length; s++) { var plane = shape.Surfaces[s].Plane; var normal = brushFlip.MultiplyVector(plane.normal); var biNormal = brushFlip.MultiplyVector(shape.Surfaces[s].BiNormal); var tangent = brushFlip.MultiplyVector(shape.Surfaces[s].Tangent); var pointOnPlane = plane.pointOnPlane; pointOnPlane = brushFlip.MultiplyPoint(pointOnPlane); shape.Surfaces[s].Plane = new CSGPlane(normal, pointOnPlane); shape.Surfaces[s].BiNormal = biNormal; shape.Surfaces[s].Tangent = tangent; } var controlMesh = brush.ControlMesh; var vertices = controlMesh.Vertices; for (var v = 0; v < vertices.Length; v++) { vertices[v] = brushFlip.MultiplyPoint(vertices[v]); } var polygons = controlMesh.Polygons; for (var p = 0; p < polygons.Length; p++) { Array.Reverse(polygons[p].EdgeIndices); } var edges = controlMesh.Edges; var twinVertices = new short[edges.Length]; for (var e = 0; e < edges.Length; e++) { twinVertices[e] = edges[edges[e].TwinIndex].VertexIndex; } for (var e = 0; e < edges.Length; e++) { edges[e].VertexIndex = twinVertices[e]; } brush.ControlMesh.SetDirty(); EditorUtility.SetDirty(brush); InternalCSGModelManager.CheckSurfaceModifications(brush, true); ControlMeshUtility.RebuildShape(brush); } if (fail) { Debug.LogWarning("Failed to perform operation"); Undo.RevertAllInCurrentGroup(); } InternalCSGModelManager.Refresh(); }
static bool GetFullBounds(GameObject go, out Bounds bounds, out Vector3 worldCenter) { bounds = new Bounds(); worldCenter = new Vector3(); var rens = go.GetComponentsInChildren <Renderer>(); if (rens.Length > 0) { for (int i = 0; i < rens.Length; i++) { if (i == 0) { bounds = rens[i].bounds; } else { bounds.Encapsulate(rens[i].bounds); } } worldCenter = bounds.center; return(true); } var cols = go.GetComponentsInChildren <Collider>(); if (cols.Length > 0) { for (int i = 0; i < cols.Length; i++) { if (i == 0) { bounds = cols[i].bounds; } else { bounds.Encapsulate(cols[i].bounds); } } worldCenter = go.transform.TransformPoint(bounds.center); return(true); } var brush = go.GetComponent <CSGBrush>(); if (brush) { var brushBounds = BoundsUtilities.GetBounds(brush); worldCenter = brushBounds.Center; bounds = new Bounds() { center = brushBounds.Center, extents = brushBounds.Size * .5f, max = brushBounds.Max, min = brushBounds.Min, size = brushBounds.Size }; return(true); } return(false); }
private void Awake() { _boundsUtilities = GameObject.Find("Table").GetComponent <BoundsUtilities>(); }
internal static AABB Do(AABB bounds, Quaternion worldToLocalRotation, bool showEdgePoints = true) { for (int i = 0; i < sideControlIDs.Length; i++) { sideControlIDs[i] = GUIUtility.GetControlID(BoundsHash, FocusType.Passive); } for (int i = 0; i < edgeControlIDs.Length; i++) { edgeControlIDs[i] = GUIUtility.GetControlID(BoundsHash, FocusType.Passive); } UpdateColors(bounds, worldToLocalRotation, showEdgePoints); var evt = Event.current; switch (evt.type) { case EventType.Repaint: { Render(bounds, worldToLocalRotation, showEdgePoints); break; } } //var isStatic = (!Tools.hidden && EditorApplication.isPlaying && ContainsStatic(Selection.gameObjects)); //var prevDisabled = CSGHandles.disabled; var localToWorldRotation = Quaternion.Inverse(worldToLocalRotation); var localToWorld = Matrix4x4.TRS(Vector3.zero, localToWorldRotation, Vector3.one); var origMatrix = Handles.matrix; Handles.matrix = localToWorld; RealtimeCSG.Helpers.CSGHandles.InitFunction init = delegate { originalBounds = bounds; }; RealtimeCSG.Helpers.CSGHandles.InitFunction shutdown = delegate { originalBounds = bounds; }; var toggleSnapping = (Event.current.modifiers & EventModifiers.Control) == EventModifiers.Control; var doSnapping = RealtimeCSG.CSGSettings.SnapToGrid ^ toggleSnapping; for (int i = 0; i < sidePoints.Length; i++) { Handles.color = sideColors[(i * 2) + 1]; var position = sidePoints[i]; var normal = BoundsUtilities.AABBSideNormal[i]; var size = sideSizes[i]; var id = sideControlIDs[i]; EditorGUI.BeginChangeCheck(); position = CSGSlider1D.Do(id, position, normal, size, CSGHandles.HoverArrowHandleCap, doSnapping, null, init, shutdown); if (EditorGUI.EndChangeCheck()) { var originalPoint = BoundsUtilities.GetBoundsSidePoint(originalBounds, i); bounds = originalBounds; var delta = Vector3.Dot(normal, (position - originalPoint)); if (normal.x < 0) { bounds.MinX -= delta; } else if (normal.x > 0) { bounds.MaxX += delta; } else if (normal.y < 0) { bounds.MinY -= delta; } else if (normal.y > 0) { bounds.MaxY += delta; } else if (normal.z < 0) { bounds.MinZ -= delta; } else if (normal.z > 0) { bounds.MaxZ += delta; } } } if (showEdgePoints) { for (int i = 0; i < edgePoints.Length; i++) { Handles.color = edgeColors[(i * 2) + 1]; var position = edgePoints[i]; var sideIndices = BoundsUtilities.AABBEdgeSides[i]; var normal = BoundsUtilities.AABBEdgeTangents[i]; var direction1 = BoundsUtilities.AABBSideNormal[sideIndices[0]]; var direction2 = BoundsUtilities.AABBSideNormal[sideIndices[1]]; var size = edgeSizes[i] / 20.0f; var id = edgeControlIDs[i]; EditorGUI.BeginChangeCheck(); position = CSGHandles.Slider2D(id, position, Vector3.zero, normal, direction1, direction2, size, null, doSnapping, null, init, shutdown); if (EditorGUI.EndChangeCheck()) { var originalPoint = BoundsUtilities.GetBoundsEdgePoint(originalBounds, i); bounds = originalBounds; var delta = (position - originalPoint); var sides = BoundsUtilities.AABBEdgeCubeSides[i]; switch (sides[0]) { case CubeSide.NegativeX: bounds.MinX += delta.x; break; case CubeSide.PositiveX: bounds.MaxX += delta.x; break; case CubeSide.NegativeY: bounds.MinY += delta.y; break; case CubeSide.PositiveY: bounds.MaxY += delta.y; break; case CubeSide.NegativeZ: bounds.MinZ += delta.z; break; case CubeSide.PositiveZ: bounds.MaxZ += delta.z; break; } switch (sides[1]) { case CubeSide.NegativeX: bounds.MinX += delta.x; break; case CubeSide.PositiveX: bounds.MaxX += delta.x; break; case CubeSide.NegativeY: bounds.MinY += delta.y; break; case CubeSide.PositiveY: bounds.MaxY += delta.y; break; case CubeSide.NegativeZ: bounds.MinZ += delta.z; break; case CubeSide.PositiveZ: bounds.MaxZ += delta.z; break; } } } } Handles.matrix = origMatrix; if (bounds.MinX > bounds.MaxX) { float t = bounds.MinX; bounds.MinX = bounds.MaxX; bounds.MaxX = t; } if (bounds.MinY > bounds.MaxY) { float t = bounds.MinY; bounds.MinY = bounds.MaxY; bounds.MaxY = t; } if (bounds.MinZ > bounds.MaxZ) { float t = bounds.MinZ; bounds.MinZ = bounds.MaxZ; bounds.MaxZ = t; } return(bounds); }
internal static void UpdateColors(AABB bounds, Quaternion worldToLocalRotation, bool showEdgePoints) { var camera = Camera.current; if (!camera) { return; } var localToWorldRotation = Quaternion.Inverse(worldToLocalRotation); BoundsUtilities.GetBoundsCornerPoints(bounds, cornerPoints); BoundsUtilities.GetBoundsSidePoints(bounds, sidePoints); BoundsUtilities.GetBoundsEdgePoints(bounds, edgePoints); var boundOutlinesColor = ColorSettings.MeshEdgeOutline; var localToWorld = Matrix4x4.TRS(Vector3.zero, localToWorldRotation, Vector3.one); PaintUtility.DrawDottedLines(localToWorld, cornerPoints, BoundsUtilities.AABBLineIndices, boundOutlinesColor, 4.0f); PaintUtility.DrawLines(localToWorld, cornerPoints, BoundsUtilities.AABBLineIndices, ToolConstants.oldLineScale, boundOutlinesColor); var isOrtho = camera.orthographic; if (isOrtho) { var cameraDirection = worldToLocalRotation * camera.transform.forward; for (int i = 0; i < BoundsUtilities.AABBSideNormal.Length; i++) { var normal = BoundsUtilities.AABBSideNormal[i]; sideBackfaced[i] = Mathf.Abs(Vector3.Dot(normal, cameraDirection)) > 0.9999f; } } else { var cameraPosition = worldToLocalRotation * camera.transform.position; for (int i = 0; i < BoundsUtilities.AABBSideNormal.Length; i++) { var normal = BoundsUtilities.AABBSideNormal[i]; sideBackfaced[i] = Vector3.Dot(normal, (cameraPosition - sidePoints[i])) < 0; } } var nearestControl = HandleUtility.nearestControl; var hotControl = GUIUtility.hotControl; for (int i = 0; i < sidePoints.Length; i++) { var id = sideControlIDs[i]; var state = (hotControl == id || nearestControl == id) ? SelectState.Hovering : SelectState.None; var color1 = ColorSettings.MeshEdgeOutline; var color2 = ColorSettings.PolygonInnerStateColor[(int)state]; bool disabled = false; switch (BoundsUtilities.AABBSideAxis[i]) { case PrincipleAxis.X: disabled = RealtimeCSG.CSGSettings.LockAxisX; break; case PrincipleAxis.Y: disabled = RealtimeCSG.CSGSettings.LockAxisY; break; case PrincipleAxis.Z: disabled = RealtimeCSG.CSGSettings.LockAxisZ; break; } if (disabled) { color2 = Color.red; } var handleSize = HandleUtility.GetHandleSize(localToWorldRotation * sidePoints[i]); var pointHandleSize = handleSize / 20.0f; if (sideBackfaced[i]) { if (!isOrtho) { color1.a *= ToolConstants.backfaceTransparency; color2.a *= ToolConstants.backfaceTransparency; pointHandleSize *= ToolConstants.backHandleScale; } else { pointHandleSize = 0; } } else { pointHandleSize *= ToolConstants.handleScale; } sidePointSizes[i] = pointHandleSize; sideSizes[i] = handleSize; sideColors[(i * 2) + 0] = color1; sideColors[(i * 2) + 1] = color2; } if (showEdgePoints) { for (int i = 0; i < edgePoints.Length; i++) { var id = edgeControlIDs[i]; var state = (hotControl == id || nearestControl == id) ? SelectState.Hovering : SelectState.None; var color1 = ColorSettings.MeshEdgeOutline; var color2 = ColorSettings.PointInnerStateColor[(int)state]; bool disabled1 = false; switch (BoundsUtilities.AABBEdgeAxis[i][0]) { case PrincipleAxis.X: disabled1 = RealtimeCSG.CSGSettings.LockAxisX; break; case PrincipleAxis.Y: disabled1 = RealtimeCSG.CSGSettings.LockAxisY; break; case PrincipleAxis.Z: disabled1 = RealtimeCSG.CSGSettings.LockAxisZ; break; } bool disabled2 = false; switch (BoundsUtilities.AABBEdgeAxis[i][1]) { case PrincipleAxis.X: disabled2 = RealtimeCSG.CSGSettings.LockAxisX; break; case PrincipleAxis.Y: disabled2 = RealtimeCSG.CSGSettings.LockAxisY; break; case PrincipleAxis.Z: disabled2 = RealtimeCSG.CSGSettings.LockAxisZ; break; } if (disabled1 && disabled2) { color2 = Color.red; } var handleSize = HandleUtility.GetHandleSize(localToWorldRotation * edgePoints[i]); var pointHandleSize = handleSize / 20.0f; var side1 = BoundsUtilities.AABBEdgeSides[i][0]; var side2 = BoundsUtilities.AABBEdgeSides[i][1]; if (isOrtho) { if (sideBackfaced[side1] || sideBackfaced[side2]) { pointHandleSize = 0; } else { pointHandleSize *= ToolConstants.handleScale; } } else { if (sideBackfaced[side1] && sideBackfaced[side2]) { color1.a *= ToolConstants.backfaceTransparency; color2.a *= ToolConstants.backfaceTransparency; pointHandleSize *= ToolConstants.backHandleScale; } else { pointHandleSize *= ToolConstants.handleScale; } } edgePointSizes[i] = pointHandleSize; edgeSizes[i] = handleSize; edgeColors[(i * 2) + 0] = color1; edgeColors[(i * 2) + 1] = color2; } } }
public static void Flip(CSGBrush[] brushes, Matrix4x4 flipMatrix, string undoDescription = "Flip brushes") { var fail = false; Undo.IncrementCurrentGroup(); Undo.RegisterCompleteObjectUndo(brushes.ToArray <UnityEngine.Object>(), undoDescription); var isGlobal = Tools.pivotRotation == PivotRotation.Global; var centerAll = BoundsUtilities.GetCenter(brushes); for (var t = 0; t < brushes.Length; t++) { var brush = brushes[t]; var shape = brush.Shape; var position = brush.transform.position; Matrix4x4 brushFlip; Vector3 brushCenter; if (isGlobal) { brushFlip = brush.transform.localToWorldMatrix * flipMatrix * brush.transform.worldToLocalMatrix; brushCenter = brush.transform.InverseTransformPoint(centerAll) - position; } else { brushFlip = flipMatrix; brushCenter = brush.transform.InverseTransformPoint(centerAll); } for (var s = 0; s < shape.Surfaces.Length; s++) { var plane = shape.Surfaces[s].Plane; var normal = brushFlip.MultiplyVector(plane.normal); var biNormal = brushFlip.MultiplyVector(shape.Surfaces[s].BiNormal); var tangent = brushFlip.MultiplyVector(shape.Surfaces[s].Tangent); var pointOnPlane = plane.pointOnPlane; pointOnPlane -= brushCenter; pointOnPlane = brushFlip.MultiplyPoint(pointOnPlane); pointOnPlane += brushCenter; shape.Surfaces[s].Plane = new CSGPlane(normal, pointOnPlane); shape.Surfaces[s].BiNormal = biNormal; shape.Surfaces[s].Tangent = tangent; } var controlMesh = brush.ControlMesh; brush.Shape = shape; brush.ControlMesh = ControlMeshUtility.CreateFromShape(shape); if (brush.ControlMesh == null) { brush.ControlMesh = controlMesh; fail = true; break; } ShapeUtility.CreateCutter(shape, brush.ControlMesh); brush.EnsureInitialized(); brush.ControlMesh.SetDirty(); EditorUtility.SetDirty(brush); InternalCSGModelManager.CheckSurfaceModifications(brush, true); ControlMeshUtility.RebuildShape(brush); } if (fail) { Debug.Log("Failed to perform operation"); Undo.RevertAllInCurrentGroup(); } InternalCSGModelManager.Refresh(); }