public static void TranslatePivot(CSGBrush[] brushes, Vector3 offset) { if (brushes == null || brushes.Length == 0 || offset.sqrMagnitude < MathConstants.ConsideredZero) { return; } for (int i = 0; i < brushes.Length; i++) { brushes[i].transform.position += offset; } GeometryUtility.MoveControlMeshVertices(brushes, -offset); SurfaceUtility.TranslateSurfacesInWorldSpace(brushes, -offset); ControlMeshUtility.RebuildShapes(brushes); }
public static void SetPivot(CSGBrush brush, Vector3 newCenter) { if (!brush) { return; } var transform = brush.transform; var realCenter = transform.position; var difference = newCenter - realCenter; if (difference.sqrMagnitude < MathConstants.ConsideredZero) { return; } transform.position += difference; GeometryUtility.MoveControlMeshVertices(brush, -difference); SurfaceUtility.TranslateSurfacesInWorldSpace(brush, -difference); ControlMeshUtility.RebuildShape(brush); }
protected override void HandleCreateShapeEvents(SceneView sceneView, Rect sceneRect) { /* * if (settings.vertices.Length < 2) * { * if (editMode == EditMode.Extrude2DShape || * editMode == EditMode.EditVertices) * editMode = EditMode.CreatePlane; * } */ bool pointOnEdge = false; bool havePlane = false; bool vertexOnGeometry = false; CSGBrush vertexOnBrush = null; CSGPlane hoverBuildPlane = buildPlane; var camera = sceneView.camera; if (camera != null && camera.pixelRect.Contains(Event.current.mousePosition)) { if (!hoverDefaultPlane.HasValue || settings.vertices.Length == 0) { bool forceGrid = RealtimeCSG.CSGGrid.ForceGrid; RealtimeCSG.CSGGrid.ForceGrid = false; hoverDefaultPlane = RealtimeCSG.CSGGrid.CurrentGridPlane; RealtimeCSG.CSGGrid.ForceGrid = forceGrid; firstSnappedEdges = null; firstSnappedBrush = null; firstSnappedPlanes = null; base.geometryModel = null; } if (editMode == EditMode.CreatePlane) { LegacyBrushIntersection intersection; if (!IgnoreDepthForRayCasts(camera) && !havePlane && EditorWindow.mouseOverWindow == sceneView && SceneQueryUtility.FindWorldIntersection(camera, Event.current.mousePosition, out intersection)) { worldPosition = intersection.worldIntersection; hoverBuildPlane = intersection.worldPlane; vertexOnBrush = intersection.brush; vertexOnGeometry = true; } else { hoverBuildPlane = hoverDefaultPlane.Value; vertexOnBrush = null; var mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); worldPosition = hoverBuildPlane.RayIntersection(mouseRay); vertexOnGeometry = false; } ResetVisuals(); if (snapFunction != null) { CSGBrush snappedOnBrush; worldPosition = snapFunction(camera, worldPosition, hoverBuildPlane, ref visualSnappedEdges, out snappedOnBrush, generatedBrushes); if (snappedOnBrush != null) { pointOnEdge = (visualSnappedEdges != null && visualSnappedEdges.Count > 0); vertexOnBrush = snappedOnBrush; vertexOnGeometry = true; } } if (settings.vertices.Length == 1) { if (hoverBuildPlane.normal != MathConstants.zeroVector3) { editMode = EditMode.CreateShape; havePlane = true; } } else if (settings.vertices.Length == 2) { onLastPoint = true; } } else { var mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); worldPosition = hoverBuildPlane.RayIntersection(mouseRay); ResetVisuals(); if (snapFunction != null) { CSGBrush snappedOnBrush; worldPosition = snapFunction(camera, worldPosition, hoverBuildPlane, ref visualSnappedEdges, out snappedOnBrush, generatedBrushes); if (snappedOnBrush != null) { pointOnEdge = (visualSnappedEdges != null && visualSnappedEdges.Count > 0); vertexOnBrush = snappedOnBrush; } } } if (geometryModel == null && vertexOnBrush != null) { if (vertexOnBrush.ChildData != null && vertexOnBrush.ChildData.Model) { geometryModel = vertexOnBrush.ChildData.Model; } } if (worldPosition != prevWorldPosition) { prevWorldPosition = worldPosition; if (Event.current.type != EventType.Repaint) { CSG_EditorGUIUtility.RepaintAll(); } } visualSnappedGrid = RealtimeCSG.CSGGrid.FindAllGridEdgesThatTouchPoint(camera, worldPosition); visualSnappedBrush = vertexOnBrush; } RealtimeCSG.CSGGrid.SetForcedGrid(camera, hoverBuildPlane); if (!SceneDragToolManager.IsDraggingObjectInScene && Event.current.type == EventType.Repaint) { PaintSnapVisualisation(); PaintCircle(sceneView, base.shapeId); } var type = Event.current.GetTypeForControl(base.shapeId); switch (type) { case EventType.Layout: { return; } case EventType.ValidateCommand: case EventType.KeyDown: { if (GUIUtility.hotControl == base.shapeId) { if (Keys.PerformActionKey.IsKeyPressed() || Keys.DeleteSelectionKey.IsKeyPressed() || Keys.CancelActionKey.IsKeyPressed()) { Event.current.Use(); } } return; } case EventType.KeyUp: { if (GUIUtility.hotControl == base.shapeId) { if (Keys.CylinderBuilderMode.IsKeyPressed() || Keys.PerformActionKey.IsKeyPressed()) { HotKeyReleased(); Event.current.Use(); return; } if (Keys.DeleteSelectionKey.IsKeyPressed() || Keys.CancelActionKey.IsKeyPressed()) { Cancel(); Event.current.Use(); return; } } return; } case EventType.MouseDown: { if (!sceneRect.Contains(Event.current.mousePosition)) { break; } if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan) { return; } if ((GUIUtility.hotControl != 0 && GUIUtility.hotControl != shapeEditId && GUIUtility.hotControl != base.shapeId) || Event.current.button != 0) { return; } Event.current.Use(); if (settings.vertices.Length == 0) { if ((GUIUtility.hotControl == 0 || GUIUtility.hotControl == base.shapeEditId) && base.shapeId != -1) { base.CalculateWorldSpaceTangents(camera); GUIUtility.hotControl = base.shapeId; GUIUtility.keyboardControl = base.shapeId; EditorGUIUtility.editingTextField = false; } } if (GUIUtility.hotControl == base.shapeId && settings.vertices.Length < 2) { if (!float.IsNaN(worldPosition.x) && !float.IsInfinity(worldPosition.x) && !float.IsNaN(worldPosition.y) && !float.IsInfinity(worldPosition.y) && !float.IsNaN(worldPosition.z) && !float.IsInfinity(worldPosition.z)) { if (hoverBuildPlane.normal.sqrMagnitude != 0) { buildPlane = hoverBuildPlane; } CalculateWorldSpaceTangents(camera); if (settings.vertices.Length == 0) { if (pointOnEdge) { firstSnappedEdges = visualSnappedEdges.ToArray(); firstSnappedBrush = visualSnappedBrush; firstSnappedPlanes = null; } else { firstSnappedBrush = null; firstSnappedEdges = null; firstSnappedPlanes = null; } geometryPlane = buildPlane; planeOnGeometry = vertexOnGeometry; } else { if (firstSnappedEdges != null) { if (firstSnappedPlanes == null) { CreateSnappedPlanes(); } bool outside = true; for (int i = 0; i < firstSnappedPlanes.Length; i++) { if (firstSnappedPlanes[i].Distance(worldPosition) <= MathConstants.DistanceEpsilon) { outside = false; break; } } planeOnGeometry = !outside; } if (vertexOnGeometry) { var plane = hoverDefaultPlane.Value; var distance = plane.Distance(worldPosition); plane.d += distance; hoverDefaultPlane = plane; for (int i = 0; i < settings.vertices.Length; i++) { if (!settings.onGeometryVertices[i]) { settings.vertices[i] = GeometryUtility.ProjectPointOnPlane(plane, settings.vertices[i]); settings.onGeometryVertices[i] = true; } } } } ArrayUtility.Add(ref settings.onGeometryVertices, vertexOnGeometry); settings.AddPoint(worldPosition); CSG_EditorGUIUtility.RepaintAll(); if (settings.vertices.Length == 2) { HotKeyReleased(); } } } return; } case EventType.MouseDrag: { if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan) { break; } if (GUIUtility.hotControl == base.shapeId && Event.current.button == 0) { Event.current.Use(); } return; } case EventType.MouseUp: { if (GUIUtility.hotControl != base.shapeId) { return; } if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan) { return; } if (Event.current.button == 0) { Event.current.Use(); ResetVisuals(); if (onLastPoint) { GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; EditorGUIUtility.editingTextField = false; editMode = EditMode.CreateShape; HotKeyReleased(); } } return; } } }
protected void GrabHeightHandle(int index, bool ignoreFirstMouseUp = false) { var camera = SceneView.currentDrawingSceneView.camera; if (camera == null) { return; } firstClick = ignoreFirstMouseUp; editMode = EditMode.ExtrudeShape; GUIUtility.hotControl = extrusionPoints[index].ID; GUIUtility.keyboardControl = extrusionPoints[index].ID; EditorGUIUtility.editingTextField = false; EditorGUIUtility.SetWantsMouseJumping(1); var surfaceDirection = buildPlane.normal; var closestAxisForward = GeometryUtility.SnapToClosestAxis(-camera.transform.forward); var closestAxisArrow = GeometryUtility.SnapToClosestAxis(surfaceDirection); Vector3 tangent, normal; float dot = Mathf.Abs(Vector3.Dot(closestAxisForward, closestAxisArrow)); if (dot != 1) { Vector3 v1, v2; if (closestAxisForward.x == 0 && closestAxisForward.y == 0) { v1 = new Vector3(1, 0, 0); v2 = new Vector3(0, 1, 0); } else if (closestAxisForward.x == 0 && closestAxisForward.z == 0) { v1 = new Vector3(1, 0, 0); v2 = new Vector3(0, 0, 1); } else //if (closestAxisForward.y == 0 && closestAxisForward.z == 0) { v1 = new Vector3(0, 1, 0); v2 = new Vector3(0, 0, 1); } var backward = -camera.transform.forward; float dot1 = Vector3.Dot(backward, v1); float dot2 = Vector3.Dot(backward, v2); if (dot1 < dot2) { tangent = v1; } else { tangent = v2; } } else { tangent = GeometryUtility.SnapToClosestAxis(Vector3.Cross(surfaceDirection, -camera.transform.forward)); } normal = Vector3.Cross(surfaceDirection, tangent); if (camera.orthographic) { normal = -camera.transform.forward; } if (normal == MathConstants.zeroVector3) { normal = GeometryUtility.SnapToClosestAxis(-camera.transform.forward); } movePlane = new CSGPlane(normal, extrusionPoints[index].Position); if (!camera.orthographic && Mathf.Abs(movePlane.Distance(camera.transform.position)) < 2.0f) { var new_tangent = Vector3.Cross(normal, closestAxisForward); if (new_tangent != MathConstants.zeroVector3) { tangent = new_tangent; normal = Vector3.Cross(surfaceDirection, tangent); movePlane = new CSGPlane(normal, extrusionPoints[index].Position); } } movePolygonDirection = haveForcedDirection ? forcedDirection : buildPlane.normal; if (!isFinished) { Grid.SetForcedGrid(movePlane); } var plane = new CSGPlane(buildPlane.normal, extrusionPoints[index].Position); heightPosition = Event.current.mousePosition; heightHandleOffset = (plane.Distance(GetHeightHandlePosition(extrusionPoints[index].Position)) * movePolygonDirection); if (float.IsInfinity(heightHandleOffset.x) || float.IsNaN(heightHandleOffset.x) || float.IsInfinity(heightHandleOffset.y) || float.IsNaN(heightHandleOffset.y) || float.IsInfinity(heightHandleOffset.z) || float.IsNaN(heightHandleOffset.z)) { heightHandleOffset = Vector3.zero; } }
public Vector3[] GetVertices(CSGPlane buildPlane, Vector3 worldPosition, Vector3 gridTangent, Vector3 gridBinormal, out bool isValid) { if (vertices.Length < 1) { isValid = false; return(vertices); } if (circleSides < 3) { circleSides = 3; } //var tangent = GeometryUtility.CalculateTangent(buildPlane.normal); var vertex1 = (vertices.Length > 1) ? vertices[1] : worldPosition; var delta = (vertex1 - vertices[0]); radiusA = delta.magnitude; if (radiusA <= MathConstants.DistanceEpsilon) { isValid = false; return(new Vector3[0]); } var matrix = GeometryUtility.Rotate2DToPlaneMatrix(buildPlane); var realVertices = new Vector3[circleSides]; float angle_offset = GeometryUtility.SignedAngle(gridTangent, delta / radiusA, buildPlane.normal); if (circleDistanceToSide) { angle_offset += 90; if ((circleSides & 1) != 1) { angle_offset += (180.0f / circleSides); } } else { angle_offset -= 90; } angle_offset += circleOffset; angle_offset *= Mathf.Deg2Rad; Vector3 p1 = MathConstants.zeroVector3; for (int i = 0; i < circleSides; i++) { var angle = ((i * Mathf.PI * 2.0f) / (float)circleSides) + angle_offset; p1.x = (Mathf.Sin(angle) * radiusA); p1.z = (Mathf.Cos(angle) * radiusA); realVertices[i] = p1; } if (circleRecenter) { var dirx = matrix.MultiplyVector(delta.normalized); var dirz = Vector3.Cross(Vector3.up, dirx); float minx = float.PositiveInfinity; float minz = float.PositiveInfinity; float maxx = float.NegativeInfinity; float maxz = float.NegativeInfinity; for (int i = 0; i < circleSides; i++) { var point = realVertices[i]; var x = Vector3.Dot(point, dirx); var z = Vector3.Dot(point, dirz); minx = Mathf.Min(x, minx); minz = Mathf.Min(z, minz); maxx = Mathf.Max(x, maxx); maxz = Mathf.Max(z, maxz); } var scalex = (radiusA * 2) / (maxx - minx); var scalez = (radiusA * 2) / (maxz - minz); var centerx = ((maxx + minx) * -0.5f) * dirx; var centerz = ((maxz + minz) * -0.5f) * dirz; for (int i = 0; i < circleSides; i++) { var point = realVertices[i]; var x = Vector3.Dot(point, dirx); var z = Vector3.Dot(point, dirz); var ptx = x * dirx; var ptz = z * dirz; ptx += centerx; ptz += centerz; ptx *= scalex; ptz *= scalez; realVertices[i] = ptx + ptz; } } for (int i = 0; i < circleSides; i++) { var point = realVertices[i]; realVertices[i] = GeometryUtility.ProjectPointOnPlane(buildPlane, vertices[0] + matrix.MultiplyPoint(point)); } isValid = true; return(realVertices); }
internal override bool CreateControlMeshForBrushIndex(CSGModel parentModel, CSGBrush brush, ShapePolygon polygon, Matrix4x4 localToWorld, float height, out ControlMesh newControlMesh, out Shape newShape) { bool smooth = settings.circleSmoothShading; bool singleSurfaceEnds = settings.circleSingleSurfaceEnds; var direction = haveForcedDirection ? forcedDirection : buildPlane.normal; if (!ShapePolygonUtility.GenerateControlMeshFromVertices(polygon, localToWorld, GeometryUtility.RotatePointIntoPlaneSpace(buildPlane, direction), height, new TexGen(), smooth, singleSurfaceEnds, out newControlMesh, out newShape)) { return(false); } var parentScale = parentTransform.lossyScale; var parentInverted = (Math.Sign(parentScale.x) * Math.Sign(parentScale.y) * Math.Sign(parentScale.z)) < 0; if (parentInverted) { ControlMeshUtility.InvertControlMesh(newControlMesh); ControlMeshUtility.InvertShape(newShape); } brush.Shape = newShape; brush.ControlMesh = newControlMesh; InternalCSGModelManager.ValidateBrush(brush, true); ControlMeshUtility.RebuildShape(brush); var vertices = polygon.Vertices; float circumference = 0.0f; for (int j = vertices.Length - 1, i = 0; i < vertices.Length; j = i, i++) { circumference += (vertices[j] - vertices[i]).magnitude; } var shape = brush.Shape; float desiredTextureLength = Mathf.Max(1.0f, Mathf.Round(circumference)); float scalar = desiredTextureLength / circumference; shape.TexGens[0].Scale.x = scalar; shape.TexGens[0].Scale.y = shape.TexGens[0].Scale.y; shape.TexGens[0].Translation.x = 0; var count = vertices.Length; if (!singleSurfaceEnds) { GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, 0, count); GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, 0, count + count); for (int j = 0, i = 1; i < count; j = i, i++) { GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, j, i); GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, i, i + count); GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, i, i + count + count); } } else { for (int j = 0, i = 1; i < count; j = i, i++) { GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, j, i); } } return(true); }
internal static bool CreateControlMeshFromPlanes(out ControlMesh controlMesh, out Shape shape, UnityEngine.Plane[] planes, Vector3[] tangents = null, Vector3[] binormals = null, Material[] materials = null, Matrix4x4[] textureMatrices = null, TextureMatrixSpace textureMatrixSpace = TextureMatrixSpace.WorldSpace, uint[] smoothingGroups = null, TexGenFlags[] texGenFlags = null) { controlMesh = null; shape = null; if (planes == null) { Debug.LogError("The planes array is not allowed to be null"); return(false); } if (planes.Length < 4) { Debug.LogError("The planes array must have at least 4 planes"); return(false); } if (materials == null) { materials = new Material[planes.Length]; for (int i = 0; i < materials.Length; i++) { materials[i] = CSGSettings.DefaultMaterial; } } if (planes.Length != materials.Length || (textureMatrices != null && planes.Length != textureMatrices.Length) || (tangents != null && tangents.Length != textureMatrices.Length) || (binormals != null && binormals.Length != textureMatrices.Length) || (smoothingGroups != null && smoothingGroups.Length != materials.Length)) { Debug.LogError("All non null arrays need to be of equal length"); return(false); } shape = new Shape(); shape.Materials = materials; shape.TexGenFlags = new TexGenFlags[planes.Length]; shape.Surfaces = new Surface[planes.Length]; shape.TexGens = new TexGen[planes.Length]; for (int i = 0; i < planes.Length; i++) { shape.Surfaces[i].Plane = new CSGPlane(planes[i].normal, -planes[i].distance); Vector3 tangent, binormal; if (tangents != null && binormals != null) { tangent = tangents[i]; binormal = binormals[i]; } else { GeometryUtility.CalculateTangents(planes[i].normal, out tangent, out binormal); } shape.Surfaces[i].Tangent = -tangent; shape.Surfaces[i].BiNormal = -binormal; shape.Surfaces[i].TexGenIndex = i; shape.TexGens[i] = new TexGen(-1); if (smoothingGroups != null) { shape.TexGens[i].SmoothingGroup = smoothingGroups[i]; } if (texGenFlags != null) { shape.TexGenFlags[i] = texGenFlags[i]; } } controlMesh = ControlMeshUtility.CreateFromShape(shape); if (controlMesh == null || !ControlMeshUtility.Validate(controlMesh, shape)) { return(false); } if (textureMatrices != null) { for (var i = 0; i < planes.Length; i++) { SurfaceUtility.AlignTextureSpaces(textureMatrices[i], textureMatrixSpace == TextureMatrixSpace.PlaneSpace, ref shape.TexGens[i], ref shape.TexGenFlags[i], ref shape.Surfaces[i]); } } ShapeUtility.CreateCutter(shape, controlMesh); return(true); }
internal static void CreateCubeControlMesh(out ControlMesh controlMesh, out Shape shape, Vector3 size) { size *= 0.5f; controlMesh = new ControlMesh(); controlMesh.Vertices = new Vector3[] { new Vector3(-size.x, -size.y, -size.z), new Vector3(-size.x, size.y, -size.z), new Vector3(size.x, size.y, -size.z), new Vector3(size.x, -size.y, -size.z), new Vector3(-size.x, -size.y, size.z), new Vector3(-size.x, size.y, size.z), new Vector3(size.x, size.y, size.z), new Vector3(size.x, -size.y, size.z) }; controlMesh.Edges = new HalfEdge[] { new HalfEdge(0, 21, 0, true), // 0 new HalfEdge(0, 9, 1, true), // 1 new HalfEdge(0, 13, 2, true), // 2 new HalfEdge(0, 17, 3, true), // 3 new HalfEdge(1, 23, 7, true), // 4 new HalfEdge(1, 19, 6, true), // 5 new HalfEdge(1, 15, 5, true), // 6 new HalfEdge(1, 11, 4, true), // 7 new HalfEdge(2, 14, 1, true), // 8 new HalfEdge(2, 1, 0, true), // 9 new HalfEdge(2, 20, 4, true), // 10 new HalfEdge(2, 7, 5, true), // 11 new HalfEdge(3, 18, 2, true), // 12 new HalfEdge(3, 2, 1, true), // 13 new HalfEdge(3, 8, 5, true), // 14 new HalfEdge(3, 6, 6, true), // 15 new HalfEdge(4, 22, 3, true), // 16 new HalfEdge(4, 3, 2, true), // 17 new HalfEdge(4, 12, 6, true), // 18 new HalfEdge(4, 5, 7, true), // 19 new HalfEdge(5, 10, 0, true), // 20 new HalfEdge(5, 0, 3, true), // 21 new HalfEdge(5, 16, 7, true), // 22 new HalfEdge(5, 4, 4, true) // 23 }; controlMesh.Polygons = new Polygon[] { // left/right new Polygon(new int[] { 0, 1, 2, 3 }, 0), // 0 new Polygon(new int[] { 7, 4, 5, 6 }, 1), // 1 // front/back new Polygon(new int[] { 9, 10, 11, 8 }, 2), // 2 new Polygon(new int[] { 13, 14, 15, 12 }, 3), // 3 // top/down new Polygon(new int[] { 16, 17, 18, 19 }, 4), // 4 new Polygon(new int[] { 20, 21, 22, 23 }, 5) // 5 }; shape = new Shape(); shape.Surfaces = new Surface[6]; shape.Surfaces[0].TexGenIndex = 0; shape.Surfaces[1].TexGenIndex = 1; shape.Surfaces[2].TexGenIndex = 2; shape.Surfaces[3].TexGenIndex = 3; shape.Surfaces[4].TexGenIndex = 4; shape.Surfaces[5].TexGenIndex = 5; shape.Surfaces[0].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 0); shape.Surfaces[1].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 1); shape.Surfaces[2].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 2); shape.Surfaces[3].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 3); shape.Surfaces[4].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 4); shape.Surfaces[5].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 5); GeometryUtility.CalculateTangents(shape.Surfaces[0].Plane.normal, out shape.Surfaces[0].Tangent, out shape.Surfaces[0].BiNormal); GeometryUtility.CalculateTangents(shape.Surfaces[1].Plane.normal, out shape.Surfaces[1].Tangent, out shape.Surfaces[1].BiNormal); GeometryUtility.CalculateTangents(shape.Surfaces[2].Plane.normal, out shape.Surfaces[2].Tangent, out shape.Surfaces[2].BiNormal); GeometryUtility.CalculateTangents(shape.Surfaces[3].Plane.normal, out shape.Surfaces[3].Tangent, out shape.Surfaces[3].BiNormal); GeometryUtility.CalculateTangents(shape.Surfaces[4].Plane.normal, out shape.Surfaces[4].Tangent, out shape.Surfaces[4].BiNormal); GeometryUtility.CalculateTangents(shape.Surfaces[5].Plane.normal, out shape.Surfaces[5].Tangent, out shape.Surfaces[5].BiNormal); shape.TexGens = new TexGen[6]; shape.TexGens[0].Scale = MathConstants.oneVector3; shape.TexGens[1].Scale = MathConstants.oneVector3; shape.TexGens[2].Scale = MathConstants.oneVector3; shape.TexGens[3].Scale = MathConstants.oneVector3; shape.TexGens[4].Scale = MathConstants.oneVector3; shape.TexGens[5].Scale = MathConstants.oneVector3; shape.TexGens[0].Color = Color.white; shape.TexGens[1].Color = Color.white; shape.TexGens[2].Color = Color.white; shape.TexGens[3].Color = Color.white; shape.TexGens[4].Color = Color.white; shape.TexGens[5].Color = Color.white; shape.TexGenFlags = new TexGenFlags[6]; shape.TexGenFlags[0] = TexGenFlags.None; shape.TexGenFlags[1] = TexGenFlags.None; shape.TexGenFlags[2] = TexGenFlags.None; shape.TexGenFlags[3] = TexGenFlags.None; shape.TexGenFlags[4] = TexGenFlags.None; shape.TexGenFlags[5] = TexGenFlags.None; shape.Materials = new Material[6]; shape.Materials[0] = CSGSettings.DefaultMaterial; shape.Materials[1] = CSGSettings.DefaultMaterial; shape.Materials[2] = CSGSettings.DefaultMaterial; shape.Materials[3] = CSGSettings.DefaultMaterial; shape.Materials[4] = CSGSettings.DefaultMaterial; shape.Materials[5] = CSGSettings.DefaultMaterial; //controlMesh.Validate(); ShapeUtility.CreateCutter(shape, controlMesh); ShapeUtility.EnsureInitialized(shape); controlMesh.IsValid = ControlMeshUtility.Validate(controlMesh, shape); }
public static Vector3 SnapDeltaToRayGrid(Ray worldRay, Vector3 worldDeltaMovement, Vector3[] worldPoints, bool snapToSelf = false) { UpdateGridOrientation(); if (gridOrientation == null || worldPoints == null || worldPoints.Length == 0) { return(worldDeltaMovement); } var snapVector = gridOrientation.gridSnapVector; var scaleVector = gridOrientation.gridSnapScale; var localDeltaMovement = VectorToGridSpace(worldDeltaMovement); var localLineDir = VectorToGridSpace(worldRay.direction); var localLineOrg = PointToGridSpace(worldRay.origin); scaleVector.x *= ((Mathf.Abs(localLineDir.y) >= 1 - MathConstants.EqualityEpsilon) || (Mathf.Abs(localLineDir.z) >= 1 - MathConstants.EqualityEpsilon)) ? 0 : 1; scaleVector.y *= ((Mathf.Abs(localLineDir.x) >= 1 - MathConstants.EqualityEpsilon) || (Mathf.Abs(localLineDir.z) >= 1 - MathConstants.EqualityEpsilon)) ? 0 : 1; scaleVector.z *= ((Mathf.Abs(localLineDir.x) >= 1 - MathConstants.EqualityEpsilon) || (Mathf.Abs(localLineDir.y) >= 1 - MathConstants.EqualityEpsilon)) ? 0 : 1; var snappedDeltaMovement = localDeltaMovement; if (Mathf.Abs(scaleVector.x) < MathConstants.EqualityEpsilon) { snappedDeltaMovement.x = 0; } if (Mathf.Abs(scaleVector.y) < MathConstants.EqualityEpsilon) { snappedDeltaMovement.y = 0; } if (Mathf.Abs(scaleVector.z) < MathConstants.EqualityEpsilon) { snappedDeltaMovement.z = 0; } Vector3[] localPoints; if (worldPoints.Length > 1) { var bounds = new AABB(); bounds.Reset(); for (int i = 0; i < worldPoints.Length; i++) { var localPoint = GeometryUtility.ProjectPointOnInfiniteLine(PointToGridSpace(worldPoints[i]), localLineOrg, localLineDir); bounds.Extend(localPoint); } localPoints = bounds.GetCorners(); } else { localPoints = new Vector3[] { GeometryUtility.ProjectPointOnInfiniteLine(PointToGridSpace(worldPoints[0]), localLineOrg, localLineDir) }; } for (int i = 0; i < localPoints.Length; i++) { var oldPoint = localPoints[i]; var newPoint = GeometryUtility.ProjectPointOnInfiniteLine(oldPoint + localDeltaMovement, localLineOrg, localLineDir); var snappedNewPoint = SnapRoundPosition(newPoint, snapVector); snappedNewPoint = GridUtility.CleanPosition(GeometryUtility.ProjectPointOnInfiniteLine(snappedNewPoint, localLineOrg, localLineDir)); var foundDeltaMovement = (snappedNewPoint - oldPoint); foundDeltaMovement.x *= scaleVector.x; foundDeltaMovement.y *= scaleVector.y; foundDeltaMovement.z *= scaleVector.z; if (i == 0 || Math.Abs(foundDeltaMovement.x) < Mathf.Abs(snappedDeltaMovement.x)) { snappedDeltaMovement.x = foundDeltaMovement.x; } if (i == 0 || Math.Abs(foundDeltaMovement.y) < Mathf.Abs(snappedDeltaMovement.y)) { snappedDeltaMovement.y = foundDeltaMovement.y; } if (i == 0 || Math.Abs(foundDeltaMovement.z) < Mathf.Abs(snappedDeltaMovement.z)) { snappedDeltaMovement.z = foundDeltaMovement.z; } } if (snapToSelf) { var snapDelta = (snappedDeltaMovement - localDeltaMovement); if (Mathf.Abs(snapDelta.x) > Mathf.Abs(localDeltaMovement.x)) { snappedDeltaMovement.x = 0; } if (Mathf.Abs(snapDelta.y) > Mathf.Abs(localDeltaMovement.y)) { snappedDeltaMovement.y = 0; } if (Mathf.Abs(snapDelta.z) > Mathf.Abs(localDeltaMovement.z)) { snappedDeltaMovement.z = 0; } } worldDeltaMovement = VectorFromGridSpace(snappedDeltaMovement); return(worldDeltaMovement); }
/* * public static bool ContinueTexGenFromSurfaceToSurface(CSGBrush srcBrush, int srcSurfaceIndex, CSGBrush dstBrush, int dstSurfaceIndex) * { * if (srcSurfaceIndex < 0 || srcSurfaceIndex >= srcBrush.Shape.Materials.Length || * srcBrush == null) * return false; * * var src_brush_cache = CSGModelManager.GetBrushCache(srcBrush); * if (src_brush_cache == null || * src_brush_cache.childData == null || * src_brush_cache.childData.modelTransform == null) * return false; * * var dst_brush_cache = CSGModelManager.GetBrushCache(dstBrush); * if (dst_brush_cache == null || * dst_brush_cache.childData == null || * dst_brush_cache.childData.modelTransform == null) * return false; * * var dstPlane = dstBrush.Shape.Surfaces[dstSurfaceIndex].Plane; * var srcPlane = srcBrush.Shape.Surfaces[srcSurfaceIndex].Plane; * * // convert planes into worldspace * dstPlane = GeometryUtility.InverseTransformPlane(dstBrush.transform.worldToLocalMatrix, dstPlane); * srcPlane = GeometryUtility.InverseTransformPlane(srcBrush.transform.worldToLocalMatrix, srcPlane); * * var dstNormal = dstPlane.normal; * var srcNormal = srcPlane.normal; * * var srcTexGenIndex = srcBrush.Shape.Surfaces[srcSurfaceIndex].TexGenIndex; * var dstTexGenIndex = dstBrush.Shape.Surfaces[dstSurfaceIndex].TexGenIndex; * * var scrShape = srcBrush.Shape; * * dstBrush.Shape.Materials[dstSurfaceIndex] = scrShape.Materials[srcSurfaceIndex]; * Vector3 srcPoint1, srcPoint2; * Vector3 dstPoint1, dstPoint2; * var edgeDirection = Vector3.Cross(dstNormal, srcNormal); * var det = edgeDirection.sqrMagnitude; * if (det < Constants.AlignmentTestEpsilon) * { * // Find 2 points on intersection of 2 planes * srcPoint1 = srcPlane.pointOnPlane; * srcPoint2 = GeometryUtility.ProjectPointOnPlane(srcPlane, srcPoint1 + MathConstants.oneVector3); * * dstPoint1 = GeometryUtility.ProjectPointOnPlane(dstPlane, srcPoint1); * dstPoint2 = GeometryUtility.ProjectPointOnPlane(dstPlane, srcPoint2); * } else * { * // Find 2 points on intersection of 2 planes * srcPoint1 = ((Vector3.Cross(edgeDirection, srcNormal) * -dstPlane.d) + * (Vector3.Cross(dstNormal, edgeDirection) * -srcPlane.d)) / det; * srcPoint2 = srcPoint1 + edgeDirection; * dstPoint1 = srcPoint1; * dstPoint2 = srcPoint2; * } * * Vector3 srcLocalPoint1 = srcBrush.transform.InverseTransformPoint(srcPoint1); * Vector3 srcLocalPoint2 = srcBrush.transform.InverseTransformPoint(srcPoint2); * * Vector3 dstLocalPoint1 = dstBrush.transform.InverseTransformPoint(dstPoint1); * Vector3 dstLocalPoint2 = dstBrush.transform.InverseTransformPoint(dstPoint2); * * var srcShape = srcBrush.Shape; * var srcTexGens = srcShape.TexGens; * var srcSurfaces = srcShape.Surfaces; * var dstShape = dstBrush.Shape; * var dstTexGens = dstShape.TexGens; * var dstSurfaces = dstShape.Surfaces; * * * // Reset destination shape to simplify calculations * dstTexGens[dstTexGenIndex].Scale = scrShape.TexGens[srcTexGenIndex].Scale; * dstTexGens[dstTexGenIndex].Translation = MathConstants.zeroVector2; * dstTexGens[dstTexGenIndex].RotationAngle = 0; * * if (!CSGModelManager.AlignTextureSpacesInLocalSpace(ref srcTexGens[srcTexGenIndex], ref srcSurfaces[srcSurfaceIndex], * srcLocalPoint1, srcLocalPoint2, * ref dstTexGens[dstTexGenIndex], ref dstSurfaces[dstSurfaceIndex], * dstLocalPoint1, dstLocalPoint2)) * return false; * return true; * } */ public static bool ContinueTexGenFromSurfaceToSurface(CSGBrush brush, int srcSurfaceIndex, int dstSurfaceIndex) { if (srcSurfaceIndex < 0 || srcSurfaceIndex >= brush.Shape.TexGens.Length || !brush) { return(false); } var shape = brush.Shape; var texGens = shape.TexGens; var texGenFlags = shape.TexGenFlags; var surfaces = shape.Surfaces; var srcTexGenIndex = surfaces[srcSurfaceIndex].TexGenIndex; var dstTexGenIndex = surfaces[dstSurfaceIndex].TexGenIndex; // var src_is_world_space = (texGenFlags[srcTexGenIndex] & TexGenFlags.WorldSpaceTexture) != TexGenFlags.None; // var dst_is_world_space = (texGenFlags[dstTexGenIndex] & TexGenFlags.WorldSpaceTexture) != TexGenFlags.None; // if (src_is_world_space) SurfaceUtility.SetTextureLock(brush, srcSurfaceIndex, true); // if (dst_is_world_space) SurfaceUtility.SetTextureLock(brush, dstSurfaceIndex, true); var dstLocalPlane = surfaces[dstSurfaceIndex].Plane; var srcLocalPlane = surfaces[srcSurfaceIndex].Plane; CSGModel parentModel; CSGOperation parentOp; InternalCSGModelManager.FindParentOperationAndModel(brush.transform, out parentOp, out parentModel); var localFromWorld = brush.transform.worldToLocalMatrix; var worldFromModel = parentModel.transform.localToWorldMatrix; var modelFromWorld = parentModel.transform.worldToLocalMatrix; var localFromModel = localFromWorld * worldFromModel; //var localToWorldMatrix = brush.transform.localToWorldMatrix; // convert planes into worldspace var dstWorldPlane = InverseTransformPlane(localFromWorld, dstLocalPlane); var srcWorldPlane = InverseTransformPlane(localFromWorld, srcLocalPlane); var dstWorldNormal = dstWorldPlane.normal; var srcWorldNormal = srcWorldPlane.normal; shape.TexGens[dstSurfaceIndex].RenderMaterial = shape.TexGens[srcSurfaceIndex].RenderMaterial; Vector3 srcWorldPoint1, srcWorldPoint2; Vector3 dstWorldPoint1, dstWorldPoint2; var edgeDirection = Vector3.Cross(dstWorldNormal, srcWorldNormal); var det = edgeDirection.sqrMagnitude; if (det < MathConstants.AlignmentTestEpsilon) { // Find 2 points on intersection of 2 planes srcWorldPoint1 = srcWorldPlane.pointOnPlane; srcWorldPoint2 = GeometryUtility.ProjectPointOnPlane(srcWorldPlane, srcWorldPoint1 + MathConstants.oneVector3); dstWorldPoint1 = GeometryUtility.ProjectPointOnPlane(dstWorldPlane, srcWorldPoint1); dstWorldPoint2 = GeometryUtility.ProjectPointOnPlane(dstWorldPlane, srcWorldPoint2); } else { // Find 2 points on intersection of 2 planes srcWorldPoint1 = ((Vector3.Cross(edgeDirection, srcWorldNormal) * -dstWorldPlane.d) + (Vector3.Cross(dstWorldNormal, edgeDirection) * -srcWorldPlane.d)) / det; srcWorldPoint2 = srcWorldPoint1 + edgeDirection; dstWorldPoint1 = srcWorldPoint1; dstWorldPoint2 = srcWorldPoint2; } var srcModelPoint1 = modelFromWorld.MultiplyPoint(srcWorldPoint1); var srcModelPoint2 = modelFromWorld.MultiplyPoint(srcWorldPoint2); var dstModelPoint1 = modelFromWorld.MultiplyPoint(dstWorldPoint1); var dstModelPoint2 = modelFromWorld.MultiplyPoint(dstWorldPoint2); var result = SurfaceUtility.AlignTextureSpaces(localFromModel, texGens[srcTexGenIndex], texGenFlags[srcTexGenIndex], ref surfaces[srcSurfaceIndex], srcModelPoint1, srcModelPoint2, localFromModel, ref texGens[dstTexGenIndex], texGenFlags[dstTexGenIndex], ref surfaces[dstSurfaceIndex], dstModelPoint1, dstModelPoint2, false, Vector3.one); // if (src_is_world_space) SurfaceUtility.SetTextureLock(brush, srcSurfaceIndex, false); // if (dst_is_world_space) SurfaceUtility.SetTextureLock(brush, dstSurfaceIndex, false); return(result); }
public void UpdatePoints(ControlMesh controlMesh, Vector3[] vertices = null) { if (controlMesh == null || controlMesh.Vertices == null || controlMesh.Edges == null || controlMesh.Polygons == null || PolygonPointIndices == null) { return; } if (vertices == null) { vertices = controlMesh.Vertices; } if (!BrushTransform) { return; } var pointCount = vertices.Length; if (WorldPoints.Length != pointCount) { AllocatePoints(pointCount); } var edgeCount = controlMesh.Edges.Length; if (Edges.Length != edgeCount) { AllocateEdges(edgeCount); } var polygonCount = controlMesh.Polygons.Length; if (PolygonControlId.Length != polygonCount) { AllocatePolygons(polygonCount); } var localToWorldMatrix = BrushTransform.localToWorldMatrix; for (var p = 0; p < pointCount; p++) { var worldPoint = localToWorldMatrix.MultiplyPoint(vertices[p]); WorldPoints[p] = worldPoint; } var brushTotalLength = 0.0f; BrushCenter = MathConstants.zeroVector3; for (var p = 0; p < polygonCount; p++) { var localCenterPoint = MathConstants.zeroVector3; var totalLength = 0.0f; var polygon = controlMesh.Polygons[p]; if (polygon == null) { continue; } var edgeIndices = polygon.EdgeIndices; if (edgeIndices == null || edgeIndices.Length == 0) { continue; } var halfEdgeIndex0 = edgeIndices[edgeIndices.Length - 1]; if (halfEdgeIndex0 < 0 || halfEdgeIndex0 >= controlMesh.Edges.Length) { continue; } var vertexIndex0 = controlMesh.Edges[halfEdgeIndex0].VertexIndex; if (vertexIndex0 < 0 || vertexIndex0 >= vertices.Length) { continue; } var vertex0 = vertices[vertexIndex0]; if (PolygonPointIndices[p] == null || PolygonPointIndices[p].Length != edgeIndices.Length) { PolygonPointIndices[p] = new int[edgeIndices.Length]; } var newPointIndices = PolygonPointIndices[p]; for (var i = 0; i < edgeIndices.Length; i++) { var halfEdgeIndex1 = edgeIndices[i]; if (halfEdgeIndex1 < 0 || halfEdgeIndex1 >= controlMesh.Edges.Length) { continue; } var vertexIndex1 = controlMesh.Edges[halfEdgeIndex1].VertexIndex; if (vertexIndex1 < 0 || vertexIndex1 >= vertices.Length) { continue; } var vertex1 = vertices[vertexIndex1]; newPointIndices[i] = vertexIndex1; var length = (vertex1 - vertex0).sqrMagnitude; localCenterPoint += (vertex1 + vertex0) * 0.5f * length; totalLength += length; brushTotalLength += length; vertex0 = vertex1; } var worldCenterPoint = Mathf.Abs(totalLength) < MathConstants.EqualityEpsilon ? localToWorldMatrix.MultiplyPoint(vertex0) : localToWorldMatrix.MultiplyPoint(localCenterPoint / totalLength); BrushCenter += localCenterPoint; PolygonCenterPoints[p] = worldCenterPoint; PolygonCenterPlanes[p] = GeometryUtility.CalcPolygonPlane(controlMesh, (short)p); } if (Mathf.Abs(brushTotalLength) >= MathConstants.EqualityEpsilon) { BrushCenter /= brushTotalLength; } BrushCenter = localToWorldMatrix.MultiplyPoint(BrushCenter); }
static void OnGUIContents(GeneratorCylinder generator, bool isSceneGUI) { GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty); { if (isSceneGUI) { CylinderSettingsGUI(generator, isSceneGUI); } } GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.BeginVertical(CSG_GUIStyleUtility.ContentEmpty); { var distanceUnit = RealtimeCSG.CSGSettings.DistanceUnit; var nextUnit = Units.CycleToNextUnit(distanceUnit); var unitText = Units.GetUnitGUIContent(distanceUnit); GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty); { GUILayout.Label(HeightContent, width65); if (isSceneGUI) { TooltipUtility.SetToolTip(HeightTooltip); } var height = generator.HaveHeight ? generator.Height : GeometryUtility.CleanLength(generator.DefaultHeight); EditorGUI.BeginChangeCheck(); { if (!isSceneGUI) { height = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, height))); } else { height = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, height), width65)); } } if (EditorGUI.EndChangeCheck()) { if (generator.HaveHeight) { generator.Height = height; } else { generator.DefaultHeight = height; } } if (GUILayout.Button(unitText, EditorStyles.miniLabel, width25)) { distanceUnit = nextUnit; RealtimeCSG.CSGSettings.DistanceUnit = distanceUnit; RealtimeCSG.CSGSettings.UpdateSnapSettings(); RealtimeCSG.CSGSettings.Save(); CSG_EditorGUIUtility.RepaintAll(); } } GUILayout.EndHorizontal(); TooltipUtility.SetToolTip(HeightTooltip); GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty); { EditorGUI.BeginDisabledGroup(!generator.CanCommit); { GUILayout.Label(RadiusContent, width65); if (isSceneGUI) { TooltipUtility.SetToolTip(RadiusTooltip); } var radius = generator.RadiusA; EditorGUI.BeginChangeCheck(); { if (!isSceneGUI) { radius = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, radius))); } else { radius = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, radius), width65)); } } if (EditorGUI.EndChangeCheck()) { generator.RadiusA = radius; } if (GUILayout.Button(unitText, EditorStyles.miniLabel, width25)) { distanceUnit = nextUnit; RealtimeCSG.CSGSettings.DistanceUnit = distanceUnit; RealtimeCSG.CSGSettings.UpdateSnapSettings(); RealtimeCSG.CSGSettings.Save(); CSG_EditorGUIUtility.RepaintAll(); } } EditorGUI.EndDisabledGroup(); } GUILayout.EndHorizontal(); if (!isSceneGUI) { TooltipUtility.SetToolTip(RadiusTooltip); } } GUILayout.EndVertical(); { generator.CircleSides = IntSettingsControl ( generator.CircleSides, 3, RealtimeCSG.CSGSettings.MaxCircleSides, SidesContent, isSceneGUI ); TooltipUtility.SetToolTip(SidesTooltip); } generator.CircleOffset = FloatSettingsControl ( generator.CircleOffset, 0, 360, OffsetContent, isSceneGUI ); TooltipUtility.SetToolTip(OffsetTooltip); if (!isSceneGUI) { GUILayout.Space(5); CylinderSettingsGUI(generator, isSceneGUI); } }
public Vector3[] GetVertices(CSGPlane buildPlane, Vector3 worldPosition, Vector3 gridTangent, Vector3 gridBinormal, out bool isValid) { if (vertices.Length < 1) { isValid = false; return(vertices); } if (sphereSplits < 1) { sphereSplits = 1; } var realSplits = (sphereSplits + 1) * 4; //var tangent = GeometryUtility.CalculateTangent(buildPlane.normal); var vertex1 = (vertices.Length > 1) ? vertices[1] : worldPosition; var delta = (vertex1 - vertices[0]); sphereRadius = delta.magnitude; if (sphereRadius <= MathConstants.DistanceEpsilon) { isValid = false; return(new Vector3[0]); } var matrix = GeometryUtility.Rotate2DToPlaneMatrix(buildPlane); var realVertices = new Vector3[realSplits]; float angle_offset = GeometryUtility.SignedAngle(gridTangent, delta / sphereRadius, buildPlane.normal); angle_offset -= 90; angle_offset += sphereOffset; angle_offset *= Mathf.Deg2Rad; Vector3 p1 = MathConstants.zeroVector3; for (int i = 0; i < realSplits; i++) { var angle = ((i * Mathf.PI * 2.0f) / (float)realSplits) + angle_offset; p1.x = (Mathf.Sin(angle) * sphereRadius); p1.z = (Mathf.Cos(angle) * sphereRadius); realVertices[i] = p1; } for (int i = 0; i < realSplits; i++) { var point = realVertices[i]; realVertices[i] = GeometryUtility.ProjectPointOnPlane(buildPlane, vertices[0] + matrix.MultiplyPoint(point)); } isValid = true; return(realVertices); }
public static Quaternion FindDragOrientation(SceneView sceneView, Vector3 normal, PrefabSourceAlignment sourceSurfaceAlignment, PrefabDestinationAlignment destinationSurfaceAlignment) { Quaternion srcRotation; switch (sourceSurfaceAlignment) { default: case PrefabSourceAlignment.AlignedFront: srcRotation = Quaternion.LookRotation(MathConstants.forwardVector3); break; case PrefabSourceAlignment.AlignedBack: srcRotation = Quaternion.LookRotation(MathConstants.backVector3); break; case PrefabSourceAlignment.AlignedLeft: srcRotation = Quaternion.LookRotation(MathConstants.rightVector3); break; case PrefabSourceAlignment.AlignedRight: srcRotation = Quaternion.LookRotation(MathConstants.leftVector3); break; case PrefabSourceAlignment.AlignedTop: srcRotation = Quaternion.LookRotation(MathConstants.upVector3, MathConstants.forwardVector3); break; case PrefabSourceAlignment.AlignedBottom: srcRotation = Quaternion.LookRotation(MathConstants.downVector3, MathConstants.backVector3); break; } switch (destinationSurfaceAlignment) { default: case PrefabDestinationAlignment.AlignToSurface: { var tangent = MathConstants.upVector3; // assume up is up in the world var absX = Mathf.Abs(normal.x); var absY = Mathf.Abs(normal.y); var absZ = Mathf.Abs(normal.z); // if our surface is a floor / ceiling then assume up is the axis // aligned vector that is most aligned with the camera's up vector if (absX <= absY && absX <= absZ && absY > absZ) { tangent = GeometryUtility.SnapToClosestAxis(sceneView.camera ? sceneView.camera.transform.up : MathConstants.upVector3); } return(Quaternion.LookRotation(normal, tangent) * srcRotation); } case PrefabDestinationAlignment.AlignSurfaceUp: { normal.y = 0; normal.Normalize(); if (normal.sqrMagnitude == 0) { normal = GeometryUtility.SnapToClosestAxis(sceneView.camera ? sceneView.camera.transform.forward : MathConstants.forwardVector3); } var tangent = MathConstants.upVector3; // assume up is up in the world var absX = Mathf.Abs(normal.x); var absY = Mathf.Abs(normal.y); var absZ = Mathf.Abs(normal.z); // if our surface is a floor / ceiling then assume up is the axis // aligned vector that is most aligned with the camera's up vector if (absX <= absY && absX <= absZ && absY > absZ) { tangent = GeometryUtility.SnapToClosestAxis(sceneView.camera ? sceneView.camera.transform.up : MathConstants.upVector3); } return(Quaternion.LookRotation(normal, tangent) * srcRotation); } case PrefabDestinationAlignment.Default: { return(Quaternion.identity); } } }
static void FreeDrawSettingsGUI(GeneratorFreeDraw generator, bool isSceneGUI) { var distanceUnit = RealtimeCSG.CSGSettings.DistanceUnit; var nextUnit = Units.CycleToNextUnit(distanceUnit); var unitText = Units.GetUnitGUIContent(distanceUnit); GUILayout.BeginVertical(CSG_GUIStyleUtility.ContentEmpty); { { GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty); { GUILayout.Label(HeightContent, width65); var height = generator.HaveHeight ? generator.Height : GeometryUtility.CleanLength(generator.DefaultHeight); EditorGUI.BeginChangeCheck(); { height = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, height))); } if (EditorGUI.EndChangeCheck()) { if (generator.HaveHeight) { generator.Height = height; } else { generator.DefaultHeight = height; } } if (GUILayout.Button(unitText, EditorStyles.miniLabel, width20)) { distanceUnit = nextUnit; RealtimeCSG.CSGSettings.DistanceUnit = distanceUnit; RealtimeCSG.CSGSettings.UpdateSnapSettings(); RealtimeCSG.CSGSettings.Save(); SceneView.RepaintAll(); } } GUILayout.EndHorizontal(); TooltipUtility.SetToolTip(HeightTooltip); } #if EVALUATION EditorGUI.BeginDisabledGroup(true); #endif { GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty); { GUILayout.Label(CurveSidesContent, width65); var subdivisions = generator.CurveSides; EditorGUI.BeginChangeCheck(); { subdivisions = (uint)Mathf.Clamp(EditorGUILayout.IntField((int)subdivisions), 0, 32); } if (EditorGUI.EndChangeCheck() && generator.CurveSides != subdivisions) { generator.CurveSides = subdivisions; } } GUILayout.EndHorizontal(); TooltipUtility.SetToolTip(CurveSidesTooltip); } { GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty); { EditorGUI.BeginDisabledGroup(!generator.HaveSelectedEdgesOrVertices); { var tangentState = generator.SelectedTangentState; EditorGUI.BeginChangeCheck(); { GUILayout.Label(EdgeTypeContent, width65); EditorGUI.showMixedValue = !tangentState.HasValue; tangentState = (HandleConstraints)EditorGUILayout.EnumPopup(tangentState.HasValue ? tangentState.Value : HandleConstraints.Straight); EditorGUI.showMixedValue = false; } if (EditorGUI.EndChangeCheck()) { generator.SelectedTangentState = tangentState; } } EditorGUI.EndDisabledGroup(); } GUILayout.EndHorizontal(); TooltipUtility.SetToolTip(EdgeTypeTooltip); } EditorGUILayout.Space(); #if EVALUATION EditorGUI.EndDisabledGroup(); #endif EditorGUI.BeginDisabledGroup(!generator.HaveSelectedEdges); { if (GUILayout.Button(SplitSelectedContent)) { generator.SplitSelectedEdge(); } TooltipUtility.SetToolTip(SplitSelectedTooltip); } EditorGUI.EndDisabledGroup(); /* * GUILayout.BeginHorizontal(GUIStyleUtility.ContentEmpty); * { * if (isSceneGUI) * GUILayout.Label(AlphaContent, width75); * else * EditorGUILayout.PrefixLabel(AlphaContent); * var alpha = generator.Alpha; * EditorGUI.BeginChangeCheck(); * { * alpha = EditorGUILayout.Slider(alpha, -1.0f, 3.0f); * } * if (EditorGUI.EndChangeCheck() && generator.Alpha != alpha) * { * generator.Alpha = alpha; * } * } * GUILayout.EndHorizontal(); */ } GUILayout.EndVertical(); }
protected void HandleHeightHandles(Rect sceneRect, bool showHeightValue) { for (int p = 0; p < extrusionPoints.Length; p++) { var type = Event.current.GetTypeForControl(extrusionPoints[p].ID); switch (type) { case EventType.Repaint: { if (SceneTools.IsDraggingObjectInScene) { break; } bool isSelected = extrusionPoints[p].ID == GUIUtility.keyboardControl; var temp = Handles.color; var origMatrix = Handles.matrix; Handles.matrix = MathConstants.identityMatrix; var rotation = Camera.current.transform.rotation; var state = SelectState.None; if (isSelected) { state |= SelectState.Selected; state |= SelectState.Hovering; } else if (HandleUtility.nearestControl == extrusionPoints[p].ID) { state |= SelectState.Hovering; } if (polygons != null && outlineVertices.Length >= 3) { var wireframeColor = ColorSettings.WireframeOutline; var topWireframeColor = ColorSettings.WireframeOutline; if (!shapeIsValid) { wireframeColor = Color.red; } var surfaceColor = ColorSettings.ShapeDrawingFill; if (GUIUtility.hotControl == extrusionPoints[p].ID) { topWireframeColor = ColorSettings.BoundsEdgeHover; surfaceColor = ColorSettings.PolygonInnerStateColor[(int)(SelectState.Selected | SelectState.Hovering)]; surfaceColor.a *= 0.5f; } else if (GUIUtility.hotControl == 0 && HandleUtility.nearestControl == extrusionPoints[p].ID) { topWireframeColor = ColorSettings.BoundsEdgeHover; surfaceColor = ColorSettings.PolygonInnerStateColor[(int)(SelectState.Selected)]; surfaceColor.a *= 0.5f; } var poly2dToWorldMatrix = Matrix4x4.TRS(extrusionPoints[p].Position, Quaternion.FromToRotation(MathConstants.upVector3, buildPlane.normal), MathConstants.oneVector3); for (int i = 0; i < polygons.Length; i++) { PaintUtility.DrawPolygon(poly2dToWorldMatrix, polygons[i].Vertices, surfaceColor); } poly2dToWorldMatrix = Matrix4x4.TRS(extrusionPoints[p].Position, Quaternion.identity, MathConstants.oneVector3); for (int i = 1; i < outlineVertices.Length; i++) { PaintUtility.DrawLine(poly2dToWorldMatrix, outlineVertices[i - 1], outlineVertices[i], ToolConstants.oldLineScale, topWireframeColor); PaintUtility.DrawDottedLine(poly2dToWorldMatrix, outlineVertices[i - 1], outlineVertices[i], topWireframeColor, 4.0f); } PaintUtility.DrawLine(poly2dToWorldMatrix, outlineVertices[outlineVertices.Length - 1], outlineVertices[0], ToolConstants.oldLineScale, topWireframeColor); PaintUtility.DrawDottedLine(poly2dToWorldMatrix, outlineVertices[outlineVertices.Length - 1], outlineVertices[0], topWireframeColor, 4.0f); if (p > 0) { var prevOffset = extrusionPoints[p - 1].Position; var prevPoly2dToWorldMatrix = Matrix4x4.TRS(prevOffset, Quaternion.identity, MathConstants.oneVector3); for (int i = 0; i < outlineVertices.Length; i++) { var from = prevPoly2dToWorldMatrix.MultiplyPoint(outlineVertices[i]); var to = poly2dToWorldMatrix.MultiplyPoint(outlineVertices[i]); PaintUtility.DrawLine(from, to, ToolConstants.oldLineScale, wireframeColor); PaintUtility.DrawDottedLine(from, to, wireframeColor, 4.0f); } } } var color = ColorSettings.PolygonInnerStateColor[(int)state]; if (!shapeIsValid) { color = Color.red; } var handleSize = GUIStyleUtility.GetHandleSize(extrusionPoints[p].Position); var scaledHandleSize = handleSize * ToolConstants.handleScale; if (p > 0) { PaintUtility.DrawDottedLine(extrusionPoints[p - 1].Position, extrusionPoints[p].Position, color, 4.0f); } Handles.color = color; PaintUtility.SquareDotCap(extrusionPoints[p].ID, extrusionPoints[p].Position, rotation, scaledHandleSize); var direction = haveForcedDirection ? forcedDirection : buildPlane.normal; var distance = new CSGPlane(direction, extrusionPoints[p].Position).Distance(extrusionPoints[1 - p].Position); if (distance <= MathConstants.DistanceEpsilon) { PaintUtility.DrawArrowCap(extrusionPoints[p].Position, direction, HandleUtility.GetHandleSize(extrusionPoints[p].Position)); } if (distance > -MathConstants.DistanceEpsilon) { PaintUtility.DrawArrowCap(extrusionPoints[p].Position, -direction, HandleUtility.GetHandleSize(extrusionPoints[p].Position)); } Handles.matrix = origMatrix; Handles.color = temp; if (p > 0 && showHeightValue) { var length = GetSegmentLength(extrusionPoints[p].Position, extrusionPoints[p - 1].Position, direction); PaintHeightMessage(extrusionPoints[p - 1].Position, extrusionPoints[p].Position, gridTangent, length); } break; } case EventType.layout: { if ((Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan)) { break; } var poly2dToWorldMatrix = Matrix4x4.TRS(extrusionPoints[p].Position, Quaternion.FromToRotation(MathConstants.upVector3, buildPlane.normal), MathConstants.oneVector3); var forceOverHandle = IsMouseOverShapePolygons(poly2dToWorldMatrix); HandleUtility.AddControl(extrusionPoints[p].ID, forceOverHandle ? 3.0f : float.PositiveInfinity); var origMatrix = Handles.matrix; Handles.matrix = MathConstants.identityMatrix; float handleSize = GUIStyleUtility.GetHandleSize(extrusionPoints[p].Position); float scaledHandleSize = handleSize * ToolConstants.handleScale * handle_extension; float distanceToCircle = HandleUtility.DistanceToCircle(extrusionPoints[p].Position, scaledHandleSize); HandleUtility.AddControl(extrusionPoints[p].ID, distanceToCircle); var direction = haveForcedDirection ? forcedDirection : buildPlane.normal; var distance = new CSGPlane(direction, extrusionPoints[p].Position).Distance(extrusionPoints[1 - p].Position); if (distance <= MathConstants.DistanceEpsilon) { PaintUtility.AddArrowCapControl(extrusionPoints[p].ID, extrusionPoints[p].Position, direction, HandleUtility.GetHandleSize(extrusionPoints[p].Position)); } if (distance > -MathConstants.DistanceEpsilon) { PaintUtility.AddArrowCapControl(extrusionPoints[p].ID, extrusionPoints[p].Position, -direction, HandleUtility.GetHandleSize(extrusionPoints[p].Position)); } if (generatedGameObjects != null && generatedGameObjects.Length > 0) { for (int g = generatedGameObjects.Length - 1; g >= 0; g--) { if (generatedGameObjects[g]) { continue; } ArrayUtility.RemoveAt(ref generatedGameObjects, g); } if (generatedGameObjects == null || generatedGameObjects.Length == 0) { Cancel(); } } Handles.matrix = origMatrix; break; } case EventType.MouseDown: { if (!sceneRect.Contains(Event.current.mousePosition)) { break; } if ((Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan) || Event.current.modifiers != EventModifiers.None) { break; } if (GUIUtility.hotControl == 0 && HandleUtility.nearestControl == extrusionPoints[p].ID && Event.current.button == 0) { if (editMode != EditMode.ExtrudeShape && !StartExtrudeMode()) { Cancel(); } else { UpdateBaseShape(registerUndo: false); dragPositionStart = extrusionPoints[p].Position; GrabHeightHandle(p); BeginExtrusion(); Event.current.Use(); } } break; } case EventType.MouseDrag: case EventType.MouseMove: { if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan) { break; } if (GUIUtility.hotControl == extrusionPoints[p].ID) // && Event.current.button == 0) { Undo.RecordObject(this, "Extrude shape"); heightPosition += Event.current.delta; Vector3 worldPosition = GetHeightHandlePosition(extrusionPoints[p].Position) - heightHandleOffset; if (float.IsInfinity(worldPosition.x) || float.IsNaN(worldPosition.x) || float.IsInfinity(worldPosition.y) || float.IsNaN(worldPosition.y) || float.IsInfinity(worldPosition.z) || float.IsNaN(worldPosition.z)) { worldPosition = extrusionPoints[p].Position; } ResetVisuals(); if (raySnapFunction != null) { CSGBrush snappedOnBrush = null; worldPosition = raySnapFunction(worldPosition, new Ray(brushPosition, movePolygonDirection), ref visualSnappedEdges, out snappedOnBrush); visualSnappedBrush = snappedOnBrush; } visualSnappedGrid = Grid.FindAllGridEdgesThatTouchPoint(worldPosition); extrusionPoints[p].Position = GeometryUtility.ProjectPointOnInfiniteLine(worldPosition, brushPosition, movePolygonDirection); if (p == 0) { MoveShape(extrusionPoints[0].Position - dragPositionStart); UpdateBaseShape(); } UpdateBrushPosition(); UpdateExtrudedShape(); GUI.changed = true; Event.current.Use(); break; } break; } case EventType.MouseUp: { forceDragHandle = false; if (GUIUtility.hotControl == extrusionPoints[p].ID && Event.current.button == 0 && (Tools.viewTool == ViewTool.None || Tools.viewTool == ViewTool.Pan)) { EndExtrusion(); if (firstClick) { firstClick = false; break; } GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; EditorGUIUtility.editingTextField = false; Event.current.Use(); ResetVisuals(); CleanupGrid(); if (!HaveExtrusion) { RevertToEditVertices(); } break; } break; } } } var shapeType = Event.current.GetTypeForControl(shapeId); HandleKeyboard(shapeType); }
public void SetBounds(AABB newBounds, bool autoAdjust = true) { var boundsSize = newBounds.Size; stairsWidth = GeometryUtility.CleanLength(boundsSize.x); stairsHeight = GeometryUtility.CleanLength(boundsSize.y); stairsDepth = GeometryUtility.CleanLength(boundsSize.z); if (float.IsInfinity(stairsWidth) || float.IsNaN(stairsWidth)) { stairsWidth = 1.0f; } if (float.IsInfinity(stairsDepth) || float.IsNaN(stairsDepth)) { stairsDepth = stepDepth; } if (float.IsInfinity(stairsHeight) || float.IsNaN(stairsHeight)) { stairsHeight = stepHeight; } stairsWidth = Mathf.Max(0, stairsWidth); stairsDepth = Mathf.Max(0, stairsDepth); stairsHeight = Mathf.Max(0, stairsHeight); if (autoAdjust) { if (!bounds.IsEmpty()) { float offsetY = (newBounds.MaxY - bounds.MaxY) + (bounds.MinY - newBounds.MinY); float offsetZ = (newBounds.MaxZ - bounds.MaxZ) + (bounds.MinZ - newBounds.MinZ); if (offsetY != 0) // scaling in height direction { if (offsetY > 0) // growing { if (extraDepth > 0) { extraDepth = stairsDepth - ((Mathf.Max(0, stairsHeight - extraHeight) / stepHeight) * stepDepth); } else { extraDepth -= offsetY; extraHeight += offsetY; } } else // shrinking { extraHeight += offsetY; extraDepth = stairsDepth - ((Mathf.Max(0, stairsHeight - extraHeight) / stepHeight) * stepDepth); } } if (offsetZ != 0) // scaling in depth direction { if (offsetZ > 0) // growing { if (extraHeight > 0) { extraHeight = stairsHeight - ((Mathf.Max(0, stairsDepth - extraDepth) / stepDepth) * stepHeight); } else { extraDepth += offsetZ; if (extraDepth < 0) { extraDepth = 0; } extraHeight -= offsetZ; } } else // shrinking { if (extraDepth > 0) { extraDepth = Mathf.Max(0, extraDepth + offsetZ); } extraHeight = stairsHeight - ((Mathf.Max(0, stairsDepth - extraDepth) / stepDepth) * stepHeight); } extraDepth = stairsDepth - ((Mathf.Max(0, stairsHeight - extraHeight) / stepHeight) * stepDepth); } if (extraDepth < 0) { extraDepth = 0; } if (extraHeight < 0) { extraHeight = 0; } } else { extraDepth = Mathf.Max(0, stairsDepth - (totalSteps * stepDepth)); extraHeight = 0; } CalcTotalSteps(); if ((totalSteps * stepDepth) > stairsDepth) { var newTotalSteps = Mathf.Max(1, Mathf.FloorToInt((stairsDepth - extraDepth) / stepDepth)); extraHeight += (totalSteps - newTotalSteps) * stepHeight; totalSteps = newTotalSteps; } } bounds = newBounds; }
public static Vector3 SnapDeltaToGrid(Vector3 worldDeltaMovement, Vector3[] worldPoints, bool snapToGridPlane = true, bool snapToSelf = false) { UpdateGridOrientation(); if (gridOrientation == null || worldPoints == null || worldPoints.Length == 0) { return(worldDeltaMovement); } var worldPlane = gridOrientation.gridWorkPlane; var scaleVector = gridOrientation.gridSnapScale; var snapVector = gridOrientation.gridSnapVector; var gridLocalDeltaMovement = VectorToGridSpace(worldDeltaMovement); var gridLocalPlane = PlaneToGridSpace(worldPlane); if (snapToGridPlane) { scaleVector.x *= (Mathf.Abs(gridLocalPlane.a) >= 1 - MathConstants.EqualityEpsilon) ? 0 : 1; scaleVector.y *= (Mathf.Abs(gridLocalPlane.b) >= 1 - MathConstants.EqualityEpsilon) ? 0 : 1; scaleVector.z *= (Mathf.Abs(gridLocalPlane.c) >= 1 - MathConstants.EqualityEpsilon) ? 0 : 1; } var snappedDeltaMovement = gridLocalDeltaMovement; if (Mathf.Abs(scaleVector.x) < MathConstants.EqualityEpsilon) { snappedDeltaMovement.x = 0; } if (Mathf.Abs(scaleVector.y) < MathConstants.EqualityEpsilon) { snappedDeltaMovement.y = 0; } if (Mathf.Abs(scaleVector.z) < MathConstants.EqualityEpsilon) { snappedDeltaMovement.z = 0; } Vector3[] gridLocalPoints; if (worldPoints.Length > 1) { var bounds = new AABB(); bounds.Reset(); for (int i = 0; i < worldPoints.Length; i++) { Vector3 localPoint = PointToGridSpace(worldPoints[i]); if (snapToGridPlane) { localPoint = GeometryUtility.ProjectPointOnPlane(gridLocalPlane, localPoint); } if (float.IsNaN(localPoint.x) || float.IsNaN(localPoint.y) || float.IsNaN(localPoint.z) || float.IsInfinity(localPoint.x) || float.IsInfinity(localPoint.y) || float.IsInfinity(localPoint.z)) { continue; } bounds.Extend(localPoint); } gridLocalPoints = bounds.GetCorners(); } else { var localGridSpacePoint = PointToGridSpace(worldPoints[0]); Vector3 projectedPoint = localGridSpacePoint; if (snapToGridPlane) { projectedPoint = GeometryUtility.ProjectPointOnPlane(gridLocalPlane, localGridSpacePoint); } if (float.IsNaN(projectedPoint.x) || float.IsNaN(projectedPoint.y) || float.IsNaN(projectedPoint.z) || float.IsInfinity(projectedPoint.x) || float.IsInfinity(projectedPoint.y) || float.IsInfinity(projectedPoint.z)) { gridLocalPoints = new Vector3[0] { } } ; else { gridLocalPoints = new Vector3[] { projectedPoint } }; } for (int i = 0; i < gridLocalPoints.Length; i++) { var oldPoint = gridLocalPoints[i]; var newPoint = gridLocalPoints[i] + gridLocalDeltaMovement; if (snapToGridPlane) { newPoint = GeometryUtility.ProjectPointOnPlane(gridLocalPlane, newPoint); } newPoint = GridUtility.CleanPosition(newPoint); var snappedNewPoint = SnapRoundPosition(newPoint, snapVector); if (snapToGridPlane) { snappedNewPoint = GeometryUtility.ProjectPointOnPlane(gridLocalPlane, snappedNewPoint); } snappedNewPoint = GridUtility.CleanPosition(snappedNewPoint); var foundDeltaMovement = (snappedNewPoint - oldPoint); foundDeltaMovement.x *= scaleVector.x; foundDeltaMovement.y *= scaleVector.y; foundDeltaMovement.z *= scaleVector.z; if (i == 0 || Math.Abs(foundDeltaMovement.x) < Mathf.Abs(snappedDeltaMovement.x)) { snappedDeltaMovement.x = foundDeltaMovement.x; } if (i == 0 || Math.Abs(foundDeltaMovement.y) < Mathf.Abs(snappedDeltaMovement.y)) { snappedDeltaMovement.y = foundDeltaMovement.y; } if (i == 0 || Math.Abs(foundDeltaMovement.z) < Mathf.Abs(snappedDeltaMovement.z)) { snappedDeltaMovement.z = foundDeltaMovement.z; } } if (snapToSelf) { var snapDelta = (snappedDeltaMovement - gridLocalDeltaMovement); if (Mathf.Abs(snapDelta.x) > Mathf.Abs(gridLocalDeltaMovement.x)) { snappedDeltaMovement.x = 0; } if (Mathf.Abs(snapDelta.y) > Mathf.Abs(gridLocalDeltaMovement.y)) { snappedDeltaMovement.y = 0; } if (Mathf.Abs(snapDelta.z) > Mathf.Abs(gridLocalDeltaMovement.z)) { snappedDeltaMovement.z = 0; } } worldDeltaMovement = VectorFromGridSpace(snappedDeltaMovement); return(worldDeltaMovement); }
public static void CalculateTangents(Vector3 normal, out Vector3 tangent, out Vector3 binormal) { tangent = GeometryUtility.CalculateTangent(normal); tangent = Vector3.Cross(normal, tangent).normalized; binormal = Vector3.Cross(normal, tangent).normalized; }
protected override void HandleCreateShapeEvents(Rect sceneRect) { bool pointOnEdge = false; bool havePlane = false; bool vertexOnGeometry = false; CSGBrush vertexOnBrush = null; CSGPlane hoverBuildPlane = buildPlane; var camera = Camera.current; if (camera != null && camera.pixelRect.Contains(Event.current.mousePosition)) { if (!hoverDefaultPlane.HasValue || settings.vertices.Length == 0) { bool forceGrid = RealtimeCSG.CSGGrid.ForceGrid; RealtimeCSG.CSGGrid.ForceGrid = false; hoverDefaultPlane = RealtimeCSG.CSGGrid.CurrentGridPlane; RealtimeCSG.CSGGrid.ForceGrid = forceGrid; firstSnappedEdges = null; firstSnappedBrush = null; firstSnappedPlanes = null; base.geometryModel = null; } if (editMode == EditMode.CreatePlane) { LegacyBrushIntersection intersection; if (!IgnoreDepthForRayCasts(camera) && !havePlane && SceneQueryUtility.FindWorldIntersection(Event.current.mousePosition, out intersection)) { worldPosition = intersection.worldIntersection; hoverBuildPlane = intersection.worldPlane; vertexOnBrush = intersection.brush; vertexOnGeometry = true; } else { hoverBuildPlane = hoverDefaultPlane.Value; vertexOnBrush = null; var mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); worldPosition = hoverBuildPlane.RayIntersection(mouseRay); vertexOnGeometry = false; } ResetVisuals(); if (snapFunction != null) { CSGBrush snappedOnBrush; worldPosition = snapFunction(worldPosition, hoverBuildPlane, ref visualSnappedEdges, out snappedOnBrush, generatedBrushes, ignoreAllBrushes: true); if (snappedOnBrush != null) { pointOnEdge = (visualSnappedEdges != null && visualSnappedEdges.Count > 0); vertexOnBrush = snappedOnBrush; vertexOnGeometry = true; } } if (settings.vertices.Length == 1) { if (hoverBuildPlane.normal != MathConstants.zeroVector3) { editMode = EditMode.CreateShape; havePlane = true; } } } else { var mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); if (settings.vertices.Length == 2) { var startPoint = settings.vertices[1]; var forward = camera.transform.forward; if (Vector3.Dot(forward, gridBinormal) < Vector3.Dot(forward, gridTangent)) { hoverBuildPlane = new CSGPlane(gridBinormal, startPoint); } else { hoverBuildPlane = new CSGPlane(gridTangent, startPoint); } worldPosition = hoverBuildPlane.RayIntersection(mouseRay); // the third point is always straight up from the second point //worldPosition = startPoint + (Vector3.Dot(worldPosition - startPoint, gridNormal) * gridNormal); RealtimeCSG.CSGGrid.SetForcedGrid(hoverBuildPlane); ResetVisuals(); if (raySnapFunction != null) { Ray ray = new Ray(startPoint, gridNormal); CSGBrush snappedOnBrush; worldPosition = raySnapFunction(worldPosition, ray, ref visualSnappedEdges, out snappedOnBrush); if (snappedOnBrush != null) { pointOnEdge = (visualSnappedEdges != null && visualSnappedEdges.Count > 0); vertexOnBrush = snappedOnBrush; } } worldPosition = GeometryUtility.ProjectPointOnInfiniteLine(worldPosition, startPoint, gridNormal); } else { worldPosition = hoverBuildPlane.RayIntersection(mouseRay); RealtimeCSG.CSGGrid.SetForcedGrid(hoverBuildPlane); ResetVisuals(); if (snapFunction != null) { CSGBrush snappedOnBrush; worldPosition = snapFunction(worldPosition, hoverBuildPlane, ref visualSnappedEdges, out snappedOnBrush, generatedBrushes, ignoreAllBrushes: true); if (snappedOnBrush != null) { pointOnEdge = (visualSnappedEdges != null && visualSnappedEdges.Count > 0); vertexOnBrush = snappedOnBrush; } } } } if (geometryModel == null && vertexOnBrush != null) { if (vertexOnBrush.ChildData != null && vertexOnBrush.ChildData.Model) { geometryModel = vertexOnBrush.ChildData.Model; } } if (worldPosition != prevWorldPosition) { prevWorldPosition = worldPosition; if (settings.vertices.Length > 0) { if ((settings.vertices[0] - worldPosition).sqrMagnitude > MathConstants.EqualityEpsilon) { UpdateSizes(); UpdateBaseShape(true); } } if (Event.current.type != EventType.Repaint) { CSG_EditorGUIUtility.RepaintAll(); } } visualSnappedGrid = RealtimeCSG.CSGGrid.FindAllGridEdgesThatTouchPoint(worldPosition); visualSnappedBrush = vertexOnBrush; } RealtimeCSG.CSGGrid.SetForcedGrid(hoverBuildPlane); if (!SceneDragToolManager.IsDraggingObjectInScene && Event.current.type == EventType.Repaint) { PaintSnapVisualisation(); PaintShape(base.shapeId); } var type = Event.current.GetTypeForControl(base.shapeId); switch (type) { case EventType.Layout: { return; } case EventType.ValidateCommand: case EventType.KeyDown: { if (GUIUtility.hotControl == base.shapeId) { if (Keys.PerformActionKey.IsKeyPressed() || Keys.DeleteSelectionKey.IsKeyPressed() || Keys.CancelActionKey.IsKeyPressed()) { Event.current.Use(); } } return; } case EventType.KeyUp: { if (GUIUtility.hotControl == base.shapeId) { if (Keys.CylinderBuilderMode.IsKeyPressed() || Keys.PerformActionKey.IsKeyPressed()) { HotKeyReleased(); Event.current.Use(); return; } if (Keys.DeleteSelectionKey.IsKeyPressed() || Keys.CancelActionKey.IsKeyPressed()) { Cancel(); Event.current.Use(); return; } } return; } case EventType.MouseDown: { if (!sceneRect.Contains(Event.current.mousePosition)) { break; } if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan) { return; } if ((GUIUtility.hotControl != 0 && GUIUtility.hotControl != shapeEditId && GUIUtility.hotControl != base.shapeId) || Event.current.button != 0) { return; } Event.current.Use(); if (settings.vertices.Length == 0) { if ((GUIUtility.hotControl == 0 || GUIUtility.hotControl == base.shapeEditId) && base.shapeId != -1) { base.CalculateWorldSpaceTangents(); GUIUtility.hotControl = base.shapeId; GUIUtility.keyboardControl = base.shapeId; EditorGUIUtility.editingTextField = false; } } if (GUIUtility.hotControl == base.shapeId && settings.vertices.Length < kMaxPoints) { if (!float.IsNaN(worldPosition.x) && !float.IsInfinity(worldPosition.x) && !float.IsNaN(worldPosition.y) && !float.IsInfinity(worldPosition.y) && !float.IsNaN(worldPosition.z) && !float.IsInfinity(worldPosition.z)) { if (settings.vertices.Length < 2 && hoverBuildPlane.normal.sqrMagnitude != 0) { buildPlane = hoverBuildPlane; } CalculateWorldSpaceTangents(); if (settings.vertices.Length == 0) { if (pointOnEdge) { firstSnappedEdges = visualSnappedEdges.ToArray(); firstSnappedBrush = visualSnappedBrush; firstSnappedPlanes = null; } else { firstSnappedBrush = null; firstSnappedEdges = null; firstSnappedPlanes = null; } planeOnGeometry = vertexOnGeometry; } else { if (firstSnappedEdges != null) { if (firstSnappedPlanes == null) { CreateSnappedPlanes(); } bool outside = true; for (int i = 0; i < firstSnappedPlanes.Length; i++) { if (firstSnappedPlanes[i].Distance(worldPosition) <= MathConstants.DistanceEpsilon) { outside = false; break; } } planeOnGeometry = !outside; } if (vertexOnGeometry) { var plane = hoverDefaultPlane.Value; var distance = plane.Distance(worldPosition); plane.d += distance; hoverDefaultPlane = plane; for (int i = 0; i < settings.vertices.Length; i++) { if (!settings.onGeometryVertices[i]) { settings.SetPoint(i, GeometryUtility.ProjectPointOnPlane(plane, settings.vertices[i])); settings.onGeometryVertices[i] = true; } } } } ArrayUtility.Add(ref settings.onGeometryVertices, vertexOnGeometry); settings.AddPoint(worldPosition); UpdateSizes(); CSG_EditorGUIUtility.RepaintAll(); if (settings.vertices.Length == kMaxPoints) { HotKeyReleased(); } } } return; } case EventType.MouseDrag: { if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan) { break; } if (GUIUtility.hotControl == base.shapeId && Event.current.button == 0) { Event.current.Use(); } return; } case EventType.MouseUp: { if (GUIUtility.hotControl != base.shapeId) { return; } if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan) { return; } if (Event.current.button == 0) { Event.current.Use(); ResetVisuals(); if (settings.vertices.Length == kMaxPoints) { GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; EditorGUIUtility.editingTextField = false; editMode = EditMode.CreateShape; HotKeyReleased(); } } return; } } }
static void OnGUIContents(CylinderGenerator generator, bool isSceneGUI) { //GUILayout.BeginVertical(GUIStyleUtility.ContentEmpty); //{ //bool enabled = generator.HaveBrushes; GUILayout.BeginHorizontal(GUIStyleUtility.ContentEmpty); { /* * EditorGUI.BeginDisabledGroup(!enabled); * { * if (isSceneGUI) * GUILayout.BeginVertical(GUI.skin.box, width100); * else * GUILayout.BeginVertical(GUIStyle.none); * { * bool mixedValues = !enabled; * CSGOperationType operation = generator.CurrentCSGOperationType; * EditorGUI.BeginChangeCheck(); * operation = GUIStyleUtility.ChooseOperation(operation, mixedValues); * if (EditorGUI.EndChangeCheck()) * { * generator.CurrentCSGOperationType = operation; * } * } * GUILayout.EndVertical(); * } * EditorGUI.EndDisabledGroup(); */ if (isSceneGUI) { CylinderSettingsGUI(generator, isSceneGUI); } } GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.BeginVertical(GUIStyleUtility.ContentEmpty); { var distanceUnit = RealtimeCSG.CSGSettings.DistanceUnit; var nextUnit = Units.CycleToNextUnit(distanceUnit); var unitText = Units.GetUnitGUIContent(distanceUnit); GUILayout.BeginHorizontal(GUIStyleUtility.ContentEmpty); { GUILayout.Label(HeightContent, width65); if (isSceneGUI) { TooltipUtility.SetToolTip(HeightTooltip); } var height = generator.HaveHeight ? generator.Height : GeometryUtility.CleanLength(generator.DefaultHeight); EditorGUI.BeginChangeCheck(); { if (!isSceneGUI) { height = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, height))); } else { height = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, height), width65)); } } if (EditorGUI.EndChangeCheck()) { if (generator.HaveHeight) { generator.Height = height; } else { generator.DefaultHeight = height; } } if (GUILayout.Button(unitText, EditorStyles.miniLabel, width20)) { distanceUnit = nextUnit; RealtimeCSG.CSGSettings.DistanceUnit = distanceUnit; RealtimeCSG.CSGSettings.UpdateSnapSettings(); RealtimeCSG.CSGSettings.Save(); SceneView.RepaintAll(); } } //if (!isSceneGUI) { GUILayout.EndHorizontal(); TooltipUtility.SetToolTip(HeightTooltip); GUILayout.BeginHorizontal(GUIStyleUtility.ContentEmpty); } //else //{ // GUILayout.Space(12); //} { EditorGUI.BeginDisabledGroup(!generator.CanCommit); { GUILayout.Label(RadiusContent, width65); if (isSceneGUI) { TooltipUtility.SetToolTip(RadiusTooltip); } var radius = generator.RadiusA; EditorGUI.BeginChangeCheck(); { if (!isSceneGUI) { radius = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, radius))); } else { radius = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, radius), width65)); } } if (EditorGUI.EndChangeCheck()) { generator.RadiusA = radius; } if (GUILayout.Button(unitText, EditorStyles.miniLabel, width20)) { distanceUnit = nextUnit; RealtimeCSG.CSGSettings.DistanceUnit = distanceUnit; RealtimeCSG.CSGSettings.UpdateSnapSettings(); RealtimeCSG.CSGSettings.Save(); SceneView.RepaintAll(); } } EditorGUI.EndDisabledGroup(); } GUILayout.EndHorizontal(); if (!isSceneGUI) { TooltipUtility.SetToolTip(RadiusTooltip); } } GUILayout.EndVertical(); { generator.CircleSides = IntSettingsSlider(generator.CircleSides, 3, 144, SidesContent, isSceneGUI); TooltipUtility.SetToolTip(SidesTooltip); } { generator.CircleOffset = SettingsSlider(generator.CircleOffset, 0, 360, OffsetContent, isSceneGUI); TooltipUtility.SetToolTip(OffsetTooltip); } if (!isSceneGUI) { GUILayout.Space(5); CylinderSettingsGUI(generator, isSceneGUI); //GUILayout.Space(10); } /*else * { * GUILayout.Space(10); * }*/ /* * EditorGUI.BeginDisabledGroup(!generator.CanCommit); * { * GUILayout.BeginHorizontal(GUIStyleUtility.ContentEmpty); * { * if (GUILayout.Button(CommitContent)) { generator.DoCommit(); } * TooltipUtility.SetToolTip(CommitTooltip); * if (GUILayout.Button(CancelContent)) { generator.DoCancel(); } * TooltipUtility.SetToolTip(CancelTooltip); * } * GUILayout.EndHorizontal(); * } * EditorGUI.EndDisabledGroup(); */ //} //GUILayout.EndVertical(); }