// TODO: somehow get rid of this public static void Reset() { s_Points.Clear(); s_Transformation = Matrix4x4.identity; s_ModelBeneathCursor = null; s_ModifyMode = false; s_DefaultHeight = 0; s_NextHeight = 0; s_LastBounds = new Bounds(); GUIUtility.hotControl = 0; PointDrawing.Reset(); }
static void MoveTargetsUnderModel(UnityEngine.Object[] targetObjects, ChiselModel model) { var modelTransform = model.transform; var modelGameObject = model.gameObject; for (int t = 0; t < targetObjects.Length; t++) { var targetComponent = (targetObjects[t] as MonoBehaviour); var targetTransform = targetComponent.transform; Undo.SetTransformParent(targetTransform, modelTransform, "Moved GameObject under Model"); } Selection.activeObject = modelGameObject; ChiselModelManager.ActiveModel = model; // This forces the model to be opened when we create it EditorGUIUtility.PingObject(modelGameObject); for (int t = 0; t < targetObjects.Length; t++) { EditorGUIUtility.PingObject(targetObjects[t]); } }
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); }
internal static GameObject PickModel(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out ChiselModel model, out Material material) { model = null; material = null; var flagState = ChiselGeneratedComponentManager.BeginPicking(); GameObject gameObject = null; bool foundGameObject = false; try { int materialIndex = -1; if (pickClosestGO == null || pickClosestGameObjectDelegate == null) { gameObject = HandleUtility.PickGameObject(pickposition, ignore, out materialIndex); } else { gameObject = pickClosestGO(camera, layers, pickposition, ignore, filter, out materialIndex); } } finally { foundGameObject = ChiselGeneratedComponentManager.EndPicking(flagState, gameObject, out model) && model; } if (object.Equals(gameObject, null)) { return(null); } if (!foundGameObject) { return(gameObject); } var renderer = gameObject.GetComponent <Renderer>(); if (renderer) { material = renderer.sharedMaterial; if (!material) { material = null; } } return(gameObject); }
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 ShapeExtrusionState Do(Rect dragArea, out Curve2D shape, out float height, out ChiselModel modelBeneathCursor, out Matrix4x4 transformation, Axis axis) { try { if (!s_ExtrusionMode) { // TODO: handle snapping against own points // TODO: handle ability to 'commit' PointDrawing.PointDrawHandle(dragArea, ref s_Points, out s_Transformation, out s_ModelBeneathCursor, releaseOnMouseUp: true, UnitySceneExtensions.SceneHandles.OutlinedDotHandleCap); if (s_Points.Count <= 1) { return(ShapeExtrusionState.HoverMode); } if (s_Points.Count <= 3) { return(ShapeExtrusionState.ShapeMode); } if ((s_Points[s_Points.Count - 2] - s_Points[0]).sqrMagnitude < PointDrawing.kDistanceEpsilon) { s_ExtrusionMode = true; s_Points[s_Points.Count - 1] = s_Points[0]; return(ShapeExtrusionState.Create); } return(ShapeExtrusionState.ShapeMode); } else { var tempPoint = s_Points[s_Points.Count - 1]; var oldMatrix = UnityEditor.Handles.matrix; UnityEditor.Handles.matrix = UnityEditor.Handles.matrix * s_Transformation; var extrusionState = ExtrusionHandle.DoHandle(dragArea, ref tempPoint, axis); UnityEditor.Handles.matrix = oldMatrix; s_Points[s_Points.Count - 1] = tempPoint; switch (extrusionState) { case ExtrusionState.Cancel: { s_ExtrusionMode = false; return(ShapeExtrusionState.Cancel); } case ExtrusionState.Commit: { s_ExtrusionMode = false; return(ShapeExtrusionState.Commit); } case ExtrusionState.Modified: { return(ShapeExtrusionState.Modified); } } return(ShapeExtrusionState.ExtrusionMode); } } finally { modelBeneathCursor = s_ModelBeneathCursor; transformation = s_Transformation; shape = GetShape(); height = GetHeight(axis); } }
public static BoxExtrusionState Do(Rect dragArea, out Bounds bounds, out float height, out ChiselModel modelBeneathCursor, out Matrix4x4 transformation, BoxExtrusionFlags flags, Axis axis, float?snappingSteps = null) { try { if (SceneHandles.InCameraOrbitMode) { return(BoxExtrusionState.None); } if (s_Points.Count <= 2) { PointDrawing.PointDrawHandle(dragArea, ref s_Points, out s_Transformation, out s_ModelBeneathCursor, UnitySceneExtensions.SceneHandles.OutlinedDotHandleCap); if (s_Points.Count <= 1) { return(BoxExtrusionState.HoverMode); } if (s_Points.Count > 2) { s_Points[2] = s_Points[0]; return(BoxExtrusionState.Create); } return(BoxExtrusionState.SquareMode); } else { var tempPoint = s_Points[2]; var oldMatrix = UnityEditor.Handles.matrix; UnityEditor.Handles.matrix = UnityEditor.Handles.matrix * s_Transformation; var extrusionState = ExtrusionHandle.DoHandle(dragArea, ref tempPoint, axis, snappingSteps: snappingSteps); UnityEditor.Handles.matrix = oldMatrix; s_Points[2] = tempPoint; switch (extrusionState) { case ExtrusionState.Cancel: { return(BoxExtrusionState.Cancel); } case ExtrusionState.Commit: { return(BoxExtrusionState.Commit); } case ExtrusionState.Modified: { return(BoxExtrusionState.Modified); } } return(BoxExtrusionState.BoxMode); } } finally { modelBeneathCursor = s_ModelBeneathCursor; bounds = GetBounds(flags, axis); height = GetHeight(axis); var center = bounds.center; if ((flags & BoxExtrusionFlags.GenerateFromCenterY) != BoxExtrusionFlags.GenerateFromCenterY) { center[(int)axis] -= height * 0.5f; } transformation = s_Transformation * Matrix4x4.TRS(center, Quaternion.identity, Vector3.one); #if true //if (height > 0) { if ((flags & BoxExtrusionFlags.AlwaysFaceUp) == BoxExtrusionFlags.AlwaysFaceUp) { var currentUp = transformation.MultiplyVector(Vector3.up); var currentForward = transformation.MultiplyVector(Vector3.forward); var currentRight = transformation.MultiplyVector(Vector3.right); var desiredUp = Grid.ActiveGrid.Up; var dotX = Vector3.Dot(currentRight, desiredUp); var dotY = Vector3.Dot(currentUp, desiredUp); var dotZ = Vector3.Dot(currentForward, desiredUp); var absDotX = Mathf.Abs(dotX); var absDotY = Mathf.Abs(dotY); var absDotZ = Mathf.Abs(dotZ); if (absDotX > absDotZ) { if (absDotX > absDotY) { var size = bounds.size; var t = size.x; size.x = size.y; size.y = t; bounds.size = size; axis = Axis.X; var position = transformation.GetColumn(3); transformation.SetColumn(3, new Vector4(0, 0, 0, 1)); transformation *= Matrix4x4.TRS(position, Quaternion.identity, Vector3.one); transformation *= new Matrix4x4(new Vector4(0, 1, 0, 0), new Vector4(1, 0, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1)); transformation.SetColumn(3, position); } } else { if (absDotZ > absDotY) { var size = bounds.size; var t = size.z; size.z = size.y; size.y = t; bounds.size = size; axis = Axis.Z; var position = transformation.GetColumn(3); transformation.SetColumn(3, new Vector4(0, 0, 0, 1)); transformation *= Matrix4x4.TRS(position, Quaternion.identity, Vector3.one); transformation *= new Matrix4x4(new Vector4(1, 0, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 0, 1)); transformation.SetColumn(3, position); } } } if (!s_ModelBeneathCursor && (flags & BoxExtrusionFlags.AlwaysFaceCameraXZ) == BoxExtrusionFlags.AlwaysFaceCameraXZ) { // TODO: take grid orientation into account to decide what is "X" and what is "Z" var currentForward = transformation.MultiplyVector(Vector3.forward); var currentRight = transformation.MultiplyVector(Vector3.right); var cameraOffset = Camera.current.transform.forward; var cameraForward = (new Vector3(cameraOffset.x, 0, cameraOffset.z)).normalized; var dotZ = Vector3.Dot(currentForward, cameraForward); var dotX = Vector3.Dot(currentRight, cameraForward); var angle = 0; if (Mathf.Abs(dotX) < Mathf.Abs(dotZ)) { if (dotZ > 0) { angle += 180; } } else { if (dotX < 0) { angle += 90; } else { angle -= 90; } if (axis == Axis.X) { axis = Axis.Z; } var size = bounds.size; var t = size.x; size.x = size.z; size.z = t; bounds.size = size; } var position = transformation.GetColumn(3); transformation.SetColumn(3, new Vector4(0, 0, 0, 1)); transformation *= Matrix4x4.TRS(position, Quaternion.identity, Vector3.one); transformation *= Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, angle, 0), Vector3.one); transformation.SetColumn(3, position); } } #endif center = Vector3.zero; if ((flags & BoxExtrusionFlags.GenerateFromCenterY) != BoxExtrusionFlags.GenerateFromCenterY) { center[(int)axis] = height * 0.5f; } bounds.center = center; } }
static GameObject PickNodeOrGameObject(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out ChiselModel model, out ChiselNode node, out ChiselIntersection intersection) { TryNextSelection: intersection = ChiselIntersection.None; node = null; Material sharedMaterial; var gameObject = PickModelOrGameObject(camera, pickposition, layers, ref ignore, ref filter, out model, out sharedMaterial); if (object.Equals(gameObject, null)) { return(null); } if (ChiselGeneratedComponentManager.IsValidModelToBeSelected(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; if (ChiselSceneQuery.FindFirstWorldIntersection(model, worldRayStart, worldRayEnd, filterLayerParameter0, layers, ignore, filter, out var tempIntersection)) { node = tempIntersection.node; 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); }
static GameObject PickModelOrGameObject(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out ChiselModel model, out Material material) { model = null; material = null; var flagState = ChiselGeneratedComponentManager.BeginPicking(); GameObject gameObject = null; bool foundGameObject = false; int materialIndex = -1; try { if (PickClosestGO == null) { gameObject = HandleUtility.PickGameObject(pickposition, ignore, out materialIndex); } else { gameObject = PickClosestGO(camera, layers, pickposition, ignore, filter, out materialIndex); } } finally { foundGameObject = ChiselGeneratedComponentManager.EndPicking(flagState, gameObject, out model) && model; } if (object.Equals(gameObject, null)) { return(null); } if (!foundGameObject) { return(gameObject); } if (materialIndex >= 0 && gameObject.TryGetComponent <Renderer>(out var renderer)) { renderer.GetSharedMaterials(sSharedMaterials); material = materialIndex < sSharedMaterials.Count ? sSharedMaterials[materialIndex] : null; sSharedMaterials.Clear(); // We don't want to keep references to Materials alive if (!material) { material = null; } } return(gameObject); }
public static void Do(int id, Rect dragArea, ref List <Vector3> points, out Matrix4x4 transformation, out ChiselModel modelBeneathCursor, UnitySceneExtensions.SceneHandles.CapFunction capFunction) { modelBeneathCursor = null; var evt = Event.current; var type = evt.GetTypeForControl(id); switch (type) { case EventType.ValidateCommand: { if (evt.commandName == kSoftDeleteCommand) { evt.Use(); break; } break; } case EventType.ExecuteCommand: { if (evt.commandName == kSoftDeleteCommand) { Cancel(evt, ref points); break; } break; } case EventType.KeyDown: { if (evt.keyCode == kCancelKey || evt.keyCode == kCommitKey) { evt.Use(); break; } break; } case EventType.KeyUp: { if (evt.keyCode == kCancelKey) { Cancel(evt, ref points); break; } else if (evt.keyCode == kCommitKey) { Commit(evt, dragArea, ref points); break; } break; } case EventType.Layout: { if (SceneHandles.InCameraOrbitMode) { break; } if (s_StartIntersection == null) { break; } // We set the id at the maximum handle distance so that other things, such as the axis gizmo, // will block the click to create a point. If we don't we wouldn't be able to use the axis gizmo. UnityEditor.HandleUtility.AddControl(id, kMaxHandleDistance); break; } case EventType.Repaint: { if (s_StartIntersection == null) { break; } if (points.Count == 0) { break; } if (SceneHandleUtility.focusControl != id) { break; } using (new UnityEditor.Handles.DrawingScope(Matrix4x4.identity)) { var orientation = s_StartIntersection.orientation; if (capFunction != null) { using (new UnityEditor.Handles.DrawingScope(s_Transform)) { for (int i = 0; i < points.Count; i++) { capFunction(id, points[i], orientation, UnityEditor.HandleUtility.GetHandleSize(points[i]) * kPointScale, type); } } } var selectedColor = UnityEditor.Handles.selectedColor; selectedColor.a = 0.5f; using (new UnityEditor.Handles.DrawingScope(selectedColor)) { HandleRendering.RenderSnapping3D(s_Snapping2D.WorldSlideGrid, s_Snapping2D.WorldSnappedExtents, s_Snapping2D.GridSnappedPosition, s_Snapping2D.SnapResult, true); } } break; } case EventType.MouseMove: { if (GUIUtility.hotControl != 0 && GUIUtility.hotControl != id) { break; } UpdatePoints(points, GetPointAtPosition(evt.mousePosition, dragArea)); SceneView.RepaintAll(); break; } case EventType.MouseDrag: { if (GUIUtility.hotControl != id) { break; } UpdatePoints(points, GetPointAtPosition(evt.mousePosition, dragArea)); GUI.changed = true; evt.Use(); break; } case EventType.MouseDown: { if (SceneHandles.InCameraOrbitMode) { break; } if (GUIUtility.hotControl != 0) { break; } if ((UnityEditor.HandleUtility.nearestControl != id || evt.button != 0) && (GUIUtility.keyboardControl != id || evt.button != 2)) { break; } if (s_StartIntersection == null) { break; } s_CurrentPointIndex++; GUIUtility.hotControl = GUIUtility.keyboardControl = id; EditorGUIUtility.SetWantsMouseJumping(1); evt.Use(); break; } case EventType.MouseUp: { if (GUIUtility.hotControl != id || (evt.button != 0 && evt.button != 2)) { break; } GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(0); // reset the starting position UpdatePoints(points, GetPointAtPosition(evt.mousePosition, dragArea)); break; } } if (s_StartIntersection != null) { modelBeneathCursor = s_StartIntersection.model; transformation = s_Transform; } else { transformation = Matrix4x4.identity; } }
public static void PointDrawHandle(Rect dragArea, ref List <Vector3> points, out Matrix4x4 transformation, out ChiselModel modelBeneathCursor, UnitySceneExtensions.SceneHandles.CapFunction capFunction) { var id = GUIUtility.GetControlID(s_PointDrawingHash, FocusType.Keyboard); PointDrawing.Do(id, dragArea, ref points, out transformation, out modelBeneathCursor, capFunction); }
public static BoxExtrusionState Do(Rect dragArea, out Bounds bounds, out float height, out ChiselModel modelBeneathCursor, out Matrix4x4 transformation, BoxExtrusionFlags flags, Axis axis, float?snappingSteps = null) { try { if (SceneHandles.InCameraOrbitMode) { return(BoxExtrusionState.None); } if (s_Points.Count <= 2) { PointDrawing.PointDrawHandle(dragArea, ref s_Points, out s_Transformation, out s_ModelBeneathCursor, UnitySceneExtensions.SceneHandles.OutlinedDotHandleCap); if (s_Points.Count <= 1) { return(BoxExtrusionState.HoverMode); } if (s_Points.Count > 2) { s_Points[2] = s_Points[0]; return(BoxExtrusionState.Create); } return(BoxExtrusionState.SquareMode); } else { var tempPoint = s_Points[2]; var oldMatrix = UnityEditor.Handles.matrix; UnityEditor.Handles.matrix = UnityEditor.Handles.matrix * s_Transformation; var extrusionState = ExtrusionHandle.DoHandle(dragArea, ref tempPoint, axis, snappingSteps: snappingSteps); UnityEditor.Handles.matrix = oldMatrix; s_Points[2] = tempPoint; switch (extrusionState) { case ExtrusionState.Cancel: { return(BoxExtrusionState.Cancel); } case ExtrusionState.Commit: { return(BoxExtrusionState.Commit); } case ExtrusionState.Modified: { return(BoxExtrusionState.Modified); } } return(BoxExtrusionState.BoxMode); } } finally { modelBeneathCursor = s_ModelBeneathCursor; bounds = GetBounds(flags, axis); height = GetHeight(axis); var center = bounds.center; if ((flags & BoxExtrusionFlags.GenerateFromCenterY) != BoxExtrusionFlags.GenerateFromCenterY) { center[(int)axis] -= height * 0.5f; } transformation = s_Transformation * Matrix4x4.TRS(center, Quaternion.identity, Vector3.one); center = Vector3.zero; if ((flags & BoxExtrusionFlags.GenerateFromCenterY) != BoxExtrusionFlags.GenerateFromCenterY) { center[(int)axis] = height * 0.5f; } bounds.center = center; } }
/// <summary> /// Imports the specified world into the Chisel model. /// </summary> /// <param name="model">The model to import into.</param> /// <param name="world">The world to be imported.</param> public static void Import(ChiselModel model, VmfWorld world) { // create a material searcher to associate materials automatically. MaterialSearcher materialSearcher = new MaterialSearcher(); HashSet <string> materialSearcherWarnings = new HashSet <string>(); // iterate through all world solids. for (int i = 0; i < world.Solids.Count; i++) { #if UNITY_EDITOR UnityEditor.EditorUtility.DisplayProgressBar("Chisel: Importing Source Engine Map (1/3)", "Converting Hammer Solids To Chisel Brushes (" + (i + 1) + " / " + world.Solids.Count + ")...", i / (float)world.Solids.Count); #endif VmfSolid solid = world.Solids[i]; // don't add triggers to the scene. if (solid.Sides.Count > 0 && IsSpecialMaterial(solid.Sides[0].Material)) { continue; } // HACK: Fix me in the future! // HACK: Chisel doesn't support collision brushes yet- skip them completely! if (solid.Sides.Count > 0 && IsInvisibleMaterial(solid.Sides[0].Material)) { continue; } // HACK: Fix me in the future! // build a very large cube brush. ChiselBrush go = ChiselComponentFactory.Create <ChiselBrush>(model); go.definition.surfaceDefinition = new ChiselSurfaceDefinition(); go.definition.surfaceDefinition.EnsureSize(6); BrushMesh brushMesh = new BrushMesh(); go.definition.brushOutline = brushMesh; BrushMeshFactory.CreateBox(ref brushMesh, new Vector3(-4096, -4096, -4096), new Vector3(4096, 4096, 4096), in go.definition.surfaceDefinition); // prepare for any displacements. List <DisplacementSide> DisplacementSurfaces = new List <DisplacementSide>(); // prepare for uv calculations of clip planes after cutting. var planes = new float4[solid.Sides.Count]; var planeSurfaces = new ChiselSurface[solid.Sides.Count]; // compute all the sides of the brush that will be clipped. for (int j = solid.Sides.Count; j-- > 0;) { VmfSolidSide side = solid.Sides[j]; // detect excluded polygons. //if (IsExcludedMaterial(side.Material)) //polygon.UserExcludeFromFinal = true; // detect collision-only brushes. //if (IsInvisibleMaterial(side.Material)) //pr.IsVisible = false; // find the material in the unity project automatically. Material material; // try finding the fully qualified texture name with '/' replaced by '.' so 'BRICK.BRICKWALL052D'. string materialName = side.Material.Replace("/", "."); if (materialName.Contains(".")) { // try finding both 'BRICK.BRICKWALL052D' and 'BRICKWALL052D'. string tiny = materialName.Substring(materialName.LastIndexOf('.') + 1); material = materialSearcher.FindMaterial(new string[] { materialName, tiny }); if (material == null && materialSearcherWarnings.Add(materialName)) { Debug.Log("Chisel: Tried to find material '" + materialName + "' and also as '" + tiny + "' but it couldn't be found in the project."); } } else { // only try finding 'BRICKWALL052D'. material = materialSearcher.FindMaterial(new string[] { materialName }); if (material == null && materialSearcherWarnings.Add(materialName)) { Debug.Log("Chisel: Tried to find material '" + materialName + "' but it couldn't be found in the project."); } } // fallback to default material. if (material == null) { material = ChiselMaterialManager.DefaultFloorMaterial; } // create chisel surface for the clip. ChiselSurface surface = new ChiselSurface(); surface.brushMaterial = ChiselBrushMaterial.CreateInstance(material, ChiselMaterialManager.DefaultPhysicsMaterial); surface.surfaceDescription = SurfaceDescription.Default; // detect collision-only polygons. if (IsInvisibleMaterial(side.Material)) { surface.brushMaterial.LayerUsage &= ~LayerUsageFlags.RenderReceiveCastShadows; } // detect excluded polygons. if (IsExcludedMaterial(side.Material)) { surface.brushMaterial.LayerUsage &= LayerUsageFlags.CastShadows; surface.brushMaterial.LayerUsage |= LayerUsageFlags.Collidable; } // calculate the clipping planes. Plane clip = new Plane(go.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * inchesInMeters), go.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * inchesInMeters), go.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * inchesInMeters)); planes[j] = new float4(clip.normal, clip.distance); planeSurfaces[j] = surface; // check whether this surface is a displacement. if (side.Displacement != null) { // disable the brush. go.gameObject.GetComponent <ChiselBrush>().enabled = false; // keep track of the surface used to cut the mesh. DisplacementSurfaces.Add(new DisplacementSide { side = side, surface = surface }); } } // cut all the clipping planes out of the brush in one go. brushMesh.Cut(planes, planeSurfaces); // now iterate over the planes to calculate UV coordinates. int[] indices = new int[solid.Sides.Count]; for (int k = 0; k < planes.Length; k++) { var plane = planes[k]; int closestIndex = 0; float closestDistance = math.lengthsq(plane - brushMesh.planes[0]); for (int j = 1; j < brushMesh.planes.Length; j++) { float testDistance = math.lengthsq(plane - brushMesh.planes[j]); if (testDistance < closestDistance) { closestIndex = j; closestDistance = testDistance; } } indices[k] = closestIndex; } for (int j = 0; j < indices.Length; j++) { brushMesh.planes[indices[j]] = planes[j]; } for (int j = solid.Sides.Count; j-- > 0;) { VmfSolidSide side = solid.Sides[j]; var surface = brushMesh.polygons[indices[j]].surface; var material = surface.brushMaterial.RenderMaterial; // calculate the texture coordinates. int w = 256; int h = 256; if (material.mainTexture != null) { w = material.mainTexture.width; h = material.mainTexture.height; } var clip = new Plane(planes[j].xyz, planes[j].w); CalculateTextureCoordinates(go, surface, clip, w, h, side.UAxis, side.VAxis); } // build displacements. foreach (DisplacementSide displacement in DisplacementSurfaces) { // find the brush mesh polygon: for (int polyidx = 0; polyidx < brushMesh.polygons.Length; polyidx++) { if (brushMesh.polygons[polyidx].surface == displacement.surface) { // find the polygon plane. Plane plane = new Plane(brushMesh.planes[polyidx].xyz, brushMesh.planes[polyidx].w); // find all vertices that belong to this polygon: List <Vector3> vertices = new List <Vector3>(); { var polygon = brushMesh.polygons[polyidx]; var firstEdge = polygon.firstEdge; var edgeCount = polygon.edgeCount; var lastEdge = firstEdge + edgeCount; for (int e = firstEdge; e < lastEdge; e++) { vertices.Add(brushMesh.vertices[brushMesh.halfEdges[e].vertexIndex]); } } // reverse the winding order. vertices.Reverse(); var first = vertices[0]; vertices.RemoveAt(0); vertices.Add(first); // build displacement: BuildDisplacementSurface(go, displacement.side, displacement.surface, vertices, plane); } } } // finalize the brush by snapping planes and centering the pivot point. go.transform.position += brushMesh.CenterAndSnapPlanes(); foreach (Transform child in go.transform) { child.position -= go.transform.position; } } // iterate through all entities. for (int e = 0; e < world.Entities.Count; e++) { #if UNITY_EDITOR UnityEditor.EditorUtility.DisplayProgressBar("Chisel: Importing Source Engine Map (2/3)", "Converting Hammer Entities To Chisel Brushes (" + (e + 1) + " / " + world.Entities.Count + ")...", e / (float)world.Entities.Count); #endif VmfEntity entity = world.Entities[e]; // skip entities that chisel can't handle. switch (entity.ClassName) { case "func_areaportal": case "func_areaportalwindow": case "func_capturezone": case "func_changeclass": case "func_combine_ball_spawner": case "func_dustcloud": case "func_dustmotes": case "func_nobuild": case "func_nogrenades": case "func_occluder": case "func_precipitation": case "func_proprespawnzone": case "func_regenerate": case "func_respawnroom": case "func_smokevolume": case "func_viscluster": continue; } // iterate through all entity solids. for (int i = 0; i < entity.Solids.Count; i++) { VmfSolid solid = entity.Solids[i]; // don't add triggers to the scene. if (solid.Sides.Count > 0 && IsSpecialMaterial(solid.Sides[0].Material)) { continue; } // HACK: Fix me in the future! // HACK: Chisel doesn't support collision brushes yet- skip them completely! if (solid.Sides.Count > 0 && IsInvisibleMaterial(solid.Sides[0].Material)) { continue; } // HACK: Fix me in the future! // build a very large cube brush. ChiselBrush go = ChiselComponentFactory.Create <ChiselBrush>(model); go.definition.surfaceDefinition = new ChiselSurfaceDefinition(); go.definition.surfaceDefinition.EnsureSize(6); BrushMesh brushMesh = new BrushMesh(); go.definition.brushOutline = brushMesh; BrushMeshFactory.CreateBox(ref brushMesh, new Vector3(-4096, -4096, -4096), new Vector3(4096, 4096, 4096), in go.definition.surfaceDefinition); // prepare for uv calculations of clip planes after cutting. var planes = new float4[solid.Sides.Count]; var planeSurfaces = new ChiselSurface[solid.Sides.Count]; // clip all the sides out of the brush. for (int j = solid.Sides.Count; j-- > 0;) { VmfSolidSide side = solid.Sides[j]; // detect excluded polygons. //if (IsExcludedMaterial(side.Material)) // polygon.UserExcludeFromFinal = true; // detect collision-only brushes. //if (IsInvisibleMaterial(side.Material)) // pr.IsVisible = false; // find the material in the unity project automatically. Material material; // try finding the fully qualified texture name with '/' replaced by '.' so 'BRICK.BRICKWALL052D'. string materialName = side.Material.Replace("/", "."); if (materialName.Contains(".")) { // try finding both 'BRICK.BRICKWALL052D' and 'BRICKWALL052D'. string tiny = materialName.Substring(materialName.LastIndexOf('.') + 1); material = materialSearcher.FindMaterial(new string[] { materialName, tiny }); if (material == null && materialSearcherWarnings.Add(materialName)) { Debug.Log("Chisel: Tried to find material '" + materialName + "' and also as '" + tiny + "' but it couldn't be found in the project."); } } else { // only try finding 'BRICKWALL052D'. material = materialSearcher.FindMaterial(new string[] { materialName }); if (material == null && materialSearcherWarnings.Add(materialName)) { Debug.Log("Chisel: Tried to find material '" + materialName + "' but it couldn't be found in the project."); } } // fallback to default material. if (material == null) { material = ChiselMaterialManager.DefaultFloorMaterial; } // create chisel surface for the clip. ChiselSurface surface = new ChiselSurface(); surface.brushMaterial = ChiselBrushMaterial.CreateInstance(material, ChiselMaterialManager.DefaultPhysicsMaterial); surface.surfaceDescription = SurfaceDescription.Default; // detect collision-only polygons. if (IsInvisibleMaterial(side.Material)) { surface.brushMaterial.LayerUsage &= ~LayerUsageFlags.RenderReceiveCastShadows; } // detect excluded polygons. if (IsExcludedMaterial(side.Material)) { surface.brushMaterial.LayerUsage &= LayerUsageFlags.CastShadows; surface.brushMaterial.LayerUsage |= LayerUsageFlags.Collidable; } // calculate the clipping planes. Plane clip = new Plane(go.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * inchesInMeters), go.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * inchesInMeters), go.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * inchesInMeters)); planes[j] = new float4(clip.normal, clip.distance); planeSurfaces[j] = surface; } // cut all the clipping planes out of the brush in one go. brushMesh.Cut(planes, planeSurfaces); // now iterate over the planes to calculate UV coordinates. int[] indices = new int[solid.Sides.Count]; for (int k = 0; k < planes.Length; k++) { var plane = planes[k]; int closestIndex = 0; float closestDistance = math.lengthsq(plane - brushMesh.planes[0]); for (int j = 1; j < brushMesh.planes.Length; j++) { float testDistance = math.lengthsq(plane - brushMesh.planes[j]); if (testDistance < closestDistance) { closestIndex = j; closestDistance = testDistance; } } indices[k] = closestIndex; } for (int j = 0; j < indices.Length; j++) { brushMesh.planes[indices[j]] = planes[j]; } for (int j = solid.Sides.Count; j-- > 0;) { VmfSolidSide side = solid.Sides[j]; var surface = brushMesh.polygons[indices[j]].surface; var material = surface.brushMaterial.RenderMaterial; // calculate the texture coordinates. int w = 256; int h = 256; if (material.mainTexture != null) { w = material.mainTexture.width; h = material.mainTexture.height; } var clip = new Plane(planes[j].xyz, planes[j].w); CalculateTextureCoordinates(go, surface, clip, w, h, side.UAxis, side.VAxis); } // finalize the brush by snapping planes and centering the pivot point. go.transform.position += brushMesh.CenterAndSnapPlanes(); // detail brushes that do not affect the CSG world. //if (entity.ClassName == "func_detail") //pr.IsNoCSG = true; // collision only brushes. //if (entity.ClassName == "func_vehicleclip") //pr.IsVisible = false; } } }
public static GeneratorModeState Do(Rect dragArea, out Bounds bounds, out float height, out ChiselModel modelBeneathCursor, out Matrix4x4 transformation, PlacementFlags flags, Axis upAxis, float?snappingSteps = null) { // TODO: shift should do SameLengthXZ, shift control includes Y // TODO: fixed height should be possible to change sign // TODO: have some sort of click placement of previously used bounds (alt?) //bounds = s_LastBounds; bool doCommit = false; try { if (SceneHandles.InCameraOrbitMode) { return(GeneratorModeState.None); } height = GetHeight(flags, upAxis); if (s_Points.Count <= 2) { PointDrawing.PointDrawHandle(dragArea, ref s_Points, out s_Transformation, out s_ModelBeneathCursor, releaseOnMouseUp: false, UnitySceneExtensions.SceneHandles.OutlinedDotHandleCap); if (s_Points.Count <= 1) { return(GeneratorModeState.None); } } if (s_Points.Count > 2) { if (!s_ModifyMode) { PointDrawing.Release(); if ((flags & PlacementFlags.HeightEqualsHalfXZ) == PlacementFlags.HeightEqualsHalfXZ || (flags & PlacementFlags.HeightEqualsXZ) == PlacementFlags.HeightEqualsXZ || (flags & PlacementFlags.UseLastHeight) == PlacementFlags.UseLastHeight) { if (height > 0) { s_ModifyMode = false; doCommit = true; return(GeneratorModeState.Commit); } } s_Points[2] = s_Points[1]; s_ModifyMode = true; return(GeneratorModeState.Update); } if (s_ModifyMode) { var oldMatrix = UnityEditor.Handles.matrix; UnityEditor.Handles.matrix *= s_Transformation; var tempPoint = s_Points[2]; var extrusionState = ExtrusionHandle.DoHandle(ref tempPoint, upAxis, snappingSteps: snappingSteps); s_Points[2] = tempPoint; UnityEditor.Handles.matrix = oldMatrix; switch (extrusionState) { case ExtrusionState.Cancel: { s_ModifyMode = false; return(GeneratorModeState.Cancel); } case ExtrusionState.Commit: { s_ModifyMode = false; doCommit = true; return(GeneratorModeState.Commit); } } } } return(GeneratorModeState.Update); } finally { modelBeneathCursor = s_ModelBeneathCursor; bounds = GetBounds(flags, upAxis); height = bounds.size[(int)upAxis]; var center = bounds.center; if ((flags & PlacementFlags.GenerateFromCenterY) != PlacementFlags.GenerateFromCenterY) { center[(int)upAxis] -= height * 0.5f; } transformation = s_Transformation * Matrix4x4.TRS(center, Quaternion.identity, Vector3.one); #if true //if (height > 0) { if ((flags & PlacementFlags.AlwaysFaceUp) == PlacementFlags.AlwaysFaceUp) { var currentUp = transformation.MultiplyVector(Vector3.up); var currentForward = transformation.MultiplyVector(Vector3.forward); var currentRight = transformation.MultiplyVector(Vector3.right); var desiredUp = Grid.ActiveGrid.Up; var dotX = Vector3.Dot(currentRight, desiredUp); var dotY = Vector3.Dot(currentUp, desiredUp); var dotZ = Vector3.Dot(currentForward, desiredUp); var absDotX = Mathf.Abs(dotX); var absDotY = Mathf.Abs(dotY); var absDotZ = Mathf.Abs(dotZ); if (absDotX > absDotZ) { if (absDotX > absDotY) { var size = bounds.size; var t = size.x; size.x = size.y; size.y = t; bounds.size = size; upAxis = Axis.X; var position = transformation.GetColumn(3); transformation.SetColumn(3, new Vector4(0, 0, 0, 1)); transformation *= Matrix4x4.TRS(position, Quaternion.identity, Vector3.one); transformation *= new Matrix4x4(new Vector4(0, 1, 0, 0), new Vector4(1, 0, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1)); transformation.SetColumn(3, position); } } else { if (absDotZ > absDotY) { var size = bounds.size; var t = size.z; size.z = size.y; size.y = t; bounds.size = size; upAxis = Axis.Z; var position = transformation.GetColumn(3); transformation.SetColumn(3, new Vector4(0, 0, 0, 1)); transformation *= Matrix4x4.TRS(position, Quaternion.identity, Vector3.one); transformation *= new Matrix4x4(new Vector4(1, 0, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 0, 1)); transformation.SetColumn(3, position); } } } if (!s_ModelBeneathCursor && (flags & PlacementFlags.AlwaysFaceCameraXZ) == PlacementFlags.AlwaysFaceCameraXZ) { // TODO: take grid orientation into account to decide what is "X" and what is "Z" var currentForward = transformation.MultiplyVector(Vector3.forward); var currentRight = transformation.MultiplyVector(Vector3.right); var cameraOffset = Camera.current.transform.forward; var cameraForward = (new Vector3(cameraOffset.x, 0, cameraOffset.z)).normalized; var dotZ = Vector3.Dot(currentForward, cameraForward); var dotX = Vector3.Dot(currentRight, cameraForward); var angle = 0; if (Mathf.Abs(dotX) < Mathf.Abs(dotZ)) { if (dotZ > 0) { angle += 180; } } else { if (dotX < 0) { angle += 90; } else { angle -= 90; } if (upAxis == Axis.X) { upAxis = Axis.Z; } var size = bounds.size; var t = size.x; size.x = size.z; size.z = t; bounds.size = size; } var position = transformation.GetColumn(3); transformation.SetColumn(3, new Vector4(0, 0, 0, 1)); transformation *= Matrix4x4.TRS(position, Quaternion.identity, Vector3.one); transformation *= Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, angle, 0), Vector3.one); transformation.SetColumn(3, position); } } #endif center = Vector3.zero; if ((flags & PlacementFlags.GenerateFromCenterY) != PlacementFlags.GenerateFromCenterY) { center[(int)upAxis] = height * 0.5f; } else { center[(int)upAxis] = 0; } bounds.center = center; if (doCommit) { s_LastBounds = bounds; s_LastHeight = s_NextHeight; } } }