public static void Export(CSGModel model, ExportType exportType, bool exportColliders) { string typeName; string extension; switch (exportType) { case ExportType.FBX: typeName = "FBX"; extension = @"fbx"; break; default: //case ExportType.UnityMesh: typeName = "Mesh"; extension = @"prefab"; exportType = ExportType.UnityMesh; break; } var newPath = model.exportPath; if (exportType != ExportType.UnityMesh) { newPath = UnityFBXExporter.ExporterMenu.GetNewPath(model.gameObject, typeName, extension, model.exportPath); if (string.IsNullOrEmpty(newPath)) { return; } } model.ShowGeneratedMeshes = false; var foundModels = model.GetComponentsInChildren <CSGModel>(true); for (var index = 0; index < foundModels.Length; index++) { if (!foundModels[index].ShowGeneratedMeshes) { continue; } foundModels[index].ShowGeneratedMeshes = false; UpdateGeneratedMeshesVisibility(foundModels[index]); } GameObject tempExportObject; if (!string.IsNullOrEmpty(model.exportPath)) { tempExportObject = new GameObject(System.IO.Path.GetFileNameWithoutExtension(model.exportPath)); if (string.IsNullOrEmpty(tempExportObject.name)) { tempExportObject.name = model.name; } } else { tempExportObject = new GameObject(model.name); } tempExportObject.transform.position = MathConstants.zeroVector3; tempExportObject.transform.rotation = MathConstants.identityQuaternion; tempExportObject.transform.localScale = MathConstants.oneVector3; int colliderCounter = 1; int shadowOnlyCounter = 1; var materialMeshCounters = new Dictionary <Material, int>(); var currentScene = model.gameObject.scene; var foundMeshContainers = SceneQueryUtility.GetAllComponentsInScene <GeneratedMeshes>(currentScene); var bounds = new AABB(); bounds.Reset(); var foundMeshFilters = new List <MeshFilter>(); var foundMeshColliders = new List <MeshCollider>(); AssetDatabase.StartAssetEditing(); // We might be modifying a prefab, in which case we need to store a mesh inside it try { foreach (var meshContainer in foundMeshContainers) { var owner = meshContainer.owner; if (!owner || !ArrayUtility.Contains(foundModels, owner)) { continue; } if (!meshContainer || meshContainer.meshInstanceLookup == null) { continue; } var instances = meshContainer.meshInstanceLookup.Values; foreach (var instance in instances) { if (!instance) { continue; } Refresh(instance, model, postProcessScene: true, skipAssetDatabaseUpdate: true); var surfaceType = GetSurfaceType(instance.MeshDescription, owner.Settings); if (surfaceType != RenderSurfaceType.Normal && surfaceType != RenderSurfaceType.ShadowOnly && surfaceType != RenderSurfaceType.Collider) { continue; } int counter = 0; if (instance.RenderMaterial) { if (!materialMeshCounters.TryGetValue(instance.RenderMaterial, out counter)) { counter = 1; } else { counter++; } } var mesh = instance.SharedMesh; if (!mesh.isReadable) { //bounds.Extend(mesh.bounds.min); //bounds.Extend(mesh.bounds.max); } else { var vertices = mesh.vertices; for (int v = 0; v < vertices.Length; v++) { bounds.Extend(vertices[v]); } } var subObj = UnityEngine.Object.Instantiate(instance.gameObject, MathConstants.zeroVector3, MathConstants.identityQuaternion) as GameObject; subObj.hideFlags = HideFlags.None; subObj.transform.position = owner.transform.position; subObj.transform.rotation = owner.transform.rotation; subObj.transform.localScale = owner.transform.localScale; subObj.transform.SetParent(tempExportObject.transform, false); var genMeshInstance = subObj.GetComponent <GeneratedMeshInstance>(); UnityEngine.Object.DestroyImmediate(genMeshInstance); if (surfaceType == RenderSurfaceType.Collider) { subObj.name = "no-material Mesh (" + colliderCounter + ") COLLIDER"; colliderCounter++; } else { if (surfaceType == RenderSurfaceType.ShadowOnly) { subObj.name = "shadow-only Mesh (" + shadowOnlyCounter + ")"; shadowOnlyCounter++; var meshRenderer = subObj.GetComponent <MeshRenderer>(); if (meshRenderer) { meshRenderer.sharedMaterial = MaterialUtility.DefaultMaterial; } } else { Material renderMaterial = instance.RenderMaterial; if (!renderMaterial) { renderMaterial = MaterialUtility.DefaultMaterial; subObj.name = "missing-material Mesh (" + counter + ")"; counter++; } else { subObj.name = renderMaterial.name + " Mesh (" + counter + ")"; } counter++; materialMeshCounters[instance.RenderMaterial] = counter; } var meshFilter = subObj.GetComponent <MeshFilter>(); if (meshFilter) { foundMeshFilters.Add(meshFilter); } } var meshCollider = subObj.GetComponent <MeshCollider>(); if (meshCollider) { foundMeshColliders.Add(meshCollider); } } } } finally { AssetDatabase.StopAssetEditing(); } Undo.IncrementCurrentGroup(); var groupIndex = Undo.GetCurrentGroup(); Undo.SetCurrentGroupName("Exported model"); try { Vector3 position = model.transform.position; if (float.IsInfinity(position.x) || float.IsNaN(position.x)) { position.x = 0; } if (float.IsInfinity(position.y) || float.IsNaN(position.y)) { position.y = 0; } if (float.IsInfinity(position.z) || float.IsNaN(position.z)) { position.z = 0; } Vector3 center = bounds.Center; switch (model.originType) { default: case OriginType.ModelCenter: center = bounds.Center + position; break; case OriginType.ModelPivot: center = position; break; case OriginType.WorldSpace: center = Vector3.zero; break; } if (float.IsInfinity(center.x) || float.IsNaN(center.x)) { center.x = 0; } if (float.IsInfinity(center.y) || float.IsNaN(center.y)) { center.y = 0; } if (float.IsInfinity(center.z) || float.IsNaN(center.z)) { center.z = 0; } var modifiedMeshes = new Dictionary <Mesh, Mesh>(); foreach (var meshFilter in foundMeshFilters) { var mesh = meshFilter.sharedMesh; if (!mesh.isReadable) { continue; } Mesh newMesh; if (!modifiedMeshes.TryGetValue(mesh, out newMesh)) { newMesh = (Mesh)UnityEngine.Object.Instantiate(mesh); var vertices = mesh.vertices; for (int v = 0; v < vertices.Length; v++) { vertices[v] += position; vertices[v] -= center; } newMesh.vertices = vertices; newMesh.RecalculateBounds(); modifiedMeshes[mesh] = newMesh; } meshFilter.sharedMesh = newMesh; meshFilter.transform.position = Vector3.zero; } foreach (var meshCollider in foundMeshColliders) { var mesh = meshCollider.sharedMesh; if (!mesh.isReadable) { continue; } Mesh newMesh; if (!modifiedMeshes.TryGetValue(mesh, out newMesh)) { newMesh = (Mesh)UnityEngine.Object.Instantiate(mesh); var vertices = mesh.vertices; for (int v = 0; v < vertices.Length; v++) { vertices[v] += position; vertices[v] -= center; } newMesh.vertices = vertices; newMesh.RecalculateBounds(); modifiedMeshes[mesh] = newMesh; } meshCollider.sharedMesh = newMesh; meshCollider.transform.position = Vector3.zero; } UnityEngine.GameObject prefabObj; GameObject modelGameObject; switch (exportType) { case ExportType.FBX: { if (!UnityFBXExporter.FBXExporter.ExportGameObjToFBX(tempExportObject, newPath, exportColliders: exportColliders)) { //InternalCSGModelManager.ClearMeshInstances(); EditorUtility.DisplayDialog("Warning", "Failed to export the FBX file.", "Ok"); return; } prefabObj = AssetDatabase.LoadAssetAtPath <UnityEngine.GameObject>(newPath); modelGameObject = CSGPrefabUtility.Instantiate(prefabObj); foreach (var renderer in modelGameObject.GetComponentsInChildren <MeshRenderer>()) { var gameObject = renderer.gameObject; if (gameObject.name.EndsWith("COLLIDER")) { var filter = gameObject.GetComponent <MeshFilter>(); var meshCollider = gameObject.AddComponent <MeshCollider>(); meshCollider.sharedMesh = filter.sharedMesh; UnityEngine.Object.DestroyImmediate(renderer); UnityEngine.Object.DestroyImmediate(filter); } } model.exportPath = newPath; break; } default: //case ExportType.UnityMesh: { prefabObj = tempExportObject; // AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(newPath); modelGameObject = tempExportObject; foreach (var meshFilter in tempExportObject.GetComponentsInChildren <MeshFilter>()) { var mesh = meshFilter.sharedMesh; mesh.name = tempExportObject.name; meshFilter.mesh = mesh; } break; } } model.exportPath = newPath; if (exportType == ExportType.FBX && prefabObj) { foreach (var meshRenderer in prefabObj.GetComponentsInChildren <MeshRenderer>()) { if (meshRenderer.sharedMaterials.Length != 1) { continue; } var gameObject = meshRenderer.gameObject; var nameSplit = gameObject.name.Split('|'); if (nameSplit.Length == 1) { continue; } int instanceId; if (!int.TryParse(nameSplit[1], out instanceId)) { continue; } var realMaterial = EditorUtility.InstanceIDToObject(instanceId) as Material; if (!realMaterial) { continue; } meshRenderer.sharedMaterial = realMaterial; gameObject.name = nameSplit[0]; } } var staticFlags = GameObjectUtility.GetStaticEditorFlags(model.gameObject); var modelLayer = model.gameObject.layer; foreach (var transform in modelGameObject.GetComponentsInChildren <Transform>()) { var gameObject = transform.gameObject; GameObjectUtility.SetStaticEditorFlags(gameObject, staticFlags); gameObject.layer = modelLayer; } modelGameObject.transform.SetParent(model.transform, true); modelGameObject.transform.SetSiblingIndex(0); modelGameObject.tag = model.gameObject.tag; modelGameObject.transform.localPosition = center - position; Undo.RegisterCreatedObjectUndo(modelGameObject, "Instantiated model"); var exported = model.gameObject.AddComponent <CSGModelExported>(); exported.containedModel = null; exported.containedExportedModel = modelGameObject; exported.disarm = true; Undo.RegisterCreatedObjectUndo(exported, "Created CSGModelExported"); Undo.RegisterCompleteObjectUndo(exported, "Created CSGModelExported"); var foundBrushes = model.GetComponentsInChildren <CSGBrush>(true); var foundOperations = model.GetComponentsInChildren <CSGOperation>(true); var foundContainers = model.GetComponentsInChildren <GeneratedMeshes>(true); var foundBehaviours = new HashSet <MonoBehaviour>(); foreach (var foundBrush in foundBrushes) { foundBehaviours.Add(foundBrush); } foreach (var foundOperation in foundOperations) { foundBehaviours.Add(foundOperation); } foreach (var foundModel in foundModels) { foundBehaviours.Add(foundModel); } foreach (var foundContainer in foundContainers) { foundBehaviours.Add(foundContainer); } exported.hiddenComponents = new HiddenComponentData[foundBehaviours.Count]; var index = 0; foreach (var foundBehaviour in foundBehaviours) { Undo.RegisterCompleteObjectUndo(foundBehaviour, "Hide component"); exported.hiddenComponents[index] = new HiddenComponentData { behaviour = foundBehaviour }; index++; } for (var i = 0; i < exported.hiddenComponents.Length; i++) { exported.hiddenComponents[i].hideFlags = exported.hiddenComponents[i].behaviour.hideFlags; exported.hiddenComponents[i].enabled = exported.hiddenComponents[i].behaviour.enabled; } for (var i = 0; i < exported.hiddenComponents.Length; i++) { exported.hiddenComponents[i].behaviour.hideFlags = exported.hiddenComponents[i].behaviour.hideFlags | ComponentHideFlags; exported.hiddenComponents[i].behaviour.enabled = false; } EditorSceneManager.MarkSceneDirty(currentScene); Undo.CollapseUndoOperations(groupIndex); groupIndex = 0; exported.disarm = false; } finally { switch (exportType) { case ExportType.FBX: { UnityEngine.Object.DestroyImmediate(tempExportObject); break; } } if (groupIndex != 0) { Undo.CollapseUndoOperations(groupIndex); } } }
internal static GameObject PickModel(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out CSGModel model, out Material material) { model = null; material = null; var flagState = CSGGeneratedComponentManager.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 = CSGGeneratedComponentManager.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); }
internal static GameObject PickNodeOrGameObject(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out CSGModel model, out CSGNode 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 (CSGSceneQuery.FindFirstWorldIntersection(model, worldRayStart, worldRayEnd, filterLayerParameter0, layers, ignore, filter, out tempIntersection)) { var clickedBrush = tempIntersection.brush; node = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(clickedBrush.UserID); if (node) { if (ignore != null && ignore.Contains(node.gameObject)) { node = null; return(null); } intersection = tempIntersection; return(node.gameObject); } else { node = null; } } } if (ignore == null) { return(null); } ArrayUtility.Add(ref ignore, gameObject); goto TryNextSelection; } if (object.Equals(gameObject, null)) { return(null); } if (ignore != null && ignore.Contains(gameObject)) { return(null); } return(gameObject); }
public static bool FindUnityWorldIntersection(Vector2 screenPos, out GameObject foundObject) { var sceneView = SceneView.currentDrawingSceneView; // ? SceneView.currentDrawingSceneView : SceneView.lastActiveSceneView; var camera = sceneView ? sceneView.camera : Camera.current; foundObject = null; if (!camera) { return(false); } var wireframeShown = CSGSettings.IsWireframeShown(sceneView); var worldRay = HandleUtility.GUIPointToWorldRay(screenPos); var worldRayStart = worldRay.origin; var worldRayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane)); var worldRayEnd = worldRayStart + worldRayVector; CSGModel intersectionModel = null; LegacyBrushIntersection[] intersections; if (FindMultiWorldIntersection(worldRayStart, worldRayEnd, out intersections, ignoreInvisibleSurfaces: !wireframeShown)) { var visibleLayers = Tools.visibleLayers; for (int i = 0; i < intersections.Length; i++) { if (((1 << intersections[i].gameObject.layer) & visibleLayers) == 0) { continue; } intersectionModel = intersections[i].model; break; } } GameObject[] modelMeshes = null; HideFlags[] hideFlags = null; if (intersectionModel != null) { modelMeshes = CSGModelManager.GetModelMeshes(intersectionModel); if (modelMeshes != null) { hideFlags = new HideFlags[modelMeshes.Length]; for (var i = 0; i < modelMeshes.Length; i++) { hideFlags[i] = modelMeshes[i].hideFlags; modelMeshes[i].hideFlags = HideFlags.None; } } } var gameObject = HandleUtility.PickGameObject(screenPos, false); if (modelMeshes != null) { for (var i = 0; i < modelMeshes.Length; i++) { var modelMesh = modelMeshes[i]; if (!modelMesh) { continue; } if (gameObject == modelMesh) { gameObject = null; } modelMesh.hideFlags = hideFlags[i]; } } if (!gameObject || gameObject.GetComponent <Canvas>() || gameObject.GetComponent <CSGModel>() || gameObject.GetComponent <CSGBrush>() || gameObject.GetComponent <CSGOperation>() || gameObject.GetComponent <GeneratedMeshInstance>() || gameObject.GetComponent <GeneratedMeshes>()) { return(false); } foundObject = gameObject; return(true); }
public PlaneIntersection(CSGTreeBrushIntersection brushIntersection, CSGNode node, CSGModel model) { this.point = brushIntersection.surfaceIntersection.worldIntersection; this.plane = brushIntersection.surfaceIntersection.worldPlane; this.node = node; this.model = model; }
public static bool FindUnityWorldIntersection(Camera camera, Vector2 screenPos, out GameObject foundObject, bool ignoreInvisibleSurfaces = true) { foundObject = null; if (!camera) { return(false); } var wireframeShown = CSGSettings.IsWireframeShown(camera); var worldRay = HandleUtility.GUIPointToWorldRay(screenPos); var worldRayStart = worldRay.origin; var worldRayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane)); var worldRayEnd = worldRayStart + worldRayVector; CSGModel intersectionModel = null; LegacyBrushIntersection[] intersections; if (FindMultiWorldIntersection(worldRayStart, worldRayEnd, out intersections, ignoreInvisibleSurfaces: ignoreInvisibleSurfaces && !wireframeShown)) { var visibleLayers = Tools.visibleLayers; for (int i = 0; i < intersections.Length; i++) { if (((1 << intersections[i].gameObject.layer) & visibleLayers) == 0) { continue; } intersectionModel = intersections[i].model; break; } } /* * GameObject[] modelMeshes = null; * HideFlags[] hideFlags = null; * if (intersectionModel != null) * { * modelMeshes = CSGModelManager.GetModelMeshes(intersectionModel); * if (modelMeshes != null) * { * hideFlags = new HideFlags[modelMeshes.Length]; * for (var i = 0; i < modelMeshes.Length; i++) * { * hideFlags[i] = modelMeshes[i].hideFlags; * modelMeshes[i].hideFlags = HideFlags.None; * } * } * } */ CSGModel foundModel; GameObject gameObject = null; var flagState = BeginPicking(null); try { gameObject = HandleUtility.PickGameObject(screenPos, false, null); } finally { foundModel = EndPicking(flagState, gameObject); } if (foundModel == intersectionModel && intersectionModel) { return(false); } /* * var gameObject = HandleUtility.PickGameObject(screenPos, false); * * if (modelMeshes != null) * { * for (var i = 0; i < modelMeshes.Length; i++) * { * var modelMesh = modelMeshes[i]; * if (!modelMesh) * continue; * * if (gameObject == modelMesh) * gameObject = null; * * modelMesh.hideFlags = hideFlags[i]; * } * } */ if (!gameObject || gameObject.GetComponent <Canvas>() || gameObject.GetComponent <CSGModel>() || gameObject.GetComponent <CSGBrush>() || gameObject.GetComponent <CSGOperation>() || gameObject.GetComponent <GeneratedMeshInstance>() || gameObject.GetComponent <GeneratedMeshes>()) { return(false); } foundObject = gameObject; return(true); }
public static bool FindClickWorldIntersection(Vector2 screenPos, out GameObject foundObject) { var sceneView = SceneView.currentDrawingSceneView;// ? SceneView.currentDrawingSceneView : SceneView.lastActiveSceneView; var camera = sceneView ? sceneView.camera : Camera.current; foundObject = null; if (!camera) { return(false); } var worldRay = HandleUtility.GUIPointToWorldRay(screenPos); var worldRayStart = worldRay.origin; var worldRayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane)); var worldRayEnd = worldRayStart + worldRayVector; CSGModel intersectionModel = null; if (_prevSceenPos == screenPos && _prevSceneView == sceneView && _deepClickIntersections != null) { var prevIntersection = (_deepIndex > 0 && _deepIndex < _deepClickIntersections.Length) ? _deepClickIntersections[_deepIndex] : null; if (_deepClickIntersections.Length > 1) { var visibleLayers = Tools.visibleLayers; for (var i = _deepClickIntersections.Length - 1; i >= 0; i--) { if (((1 << _deepClickIntersections[i].gameObject.layer) & visibleLayers) == 0) { continue; } if (_deepClickIntersections[i].brush) { continue; } ArrayUtility.RemoveAt(ref _deepClickIntersections, i); if (i <= _deepIndex) { _deepIndex--; } } } if (_deepClickIntersections.Length <= 1) { ResetDeepClick(); } else { _deepIndex = (_deepIndex + 1) % _deepClickIntersections.Length; var currentIntersection = (_deepIndex > 0 && _deepIndex < _deepClickIntersections.Length) ? _deepClickIntersections[_deepIndex] : null; if (currentIntersection != prevIntersection && currentIntersection != null) { foundObject = currentIntersection.gameObject; _prevSceenPos = screenPos; _prevSceneView = sceneView; intersectionModel = currentIntersection.model; } else { ResetDeepClick(); } } } if (_prevSceenPos != screenPos) { var wireframeShown = CSGSettings.IsWireframeShown(sceneView); if (FindMultiWorldIntersection(worldRayStart, worldRayEnd, out _deepClickIntersections, ignoreInvisibleSurfaces: !wireframeShown, ignoreUnrenderables: !wireframeShown)) { var visibleLayers = Tools.visibleLayers; for (int i = 0; i < _deepClickIntersections.Length; i++) { if (((1 << _deepClickIntersections[i].gameObject.layer) & visibleLayers) == 0) { continue; } _deepIndex = 0; var intersection = _deepClickIntersections[i]; foundObject = intersection.gameObject; _prevSceenPos = screenPos; _prevSceneView = sceneView; intersectionModel = intersection.model; break; } } else { ResetDeepClick(); } } GameObject[] modelMeshes = null; if (intersectionModel != null) { modelMeshes = CSGModelManager.GetModelMeshes(intersectionModel); } HideFlags[] hideFlags = null; if (modelMeshes != null) { hideFlags = new HideFlags[modelMeshes.Length]; for (var i = 0; i < modelMeshes.Length; i++) { hideFlags[i] = modelMeshes[i].hideFlags; if (modelMeshes[i].hideFlags != HideFlags.None) { modelMeshes[i].hideFlags = HideFlags.None; } } } var gameObject = HandleUtility.PickGameObject(screenPos, true); if (modelMeshes != null) { for (var i = 0; i < modelMeshes.Length; i++) { var modelMesh = modelMeshes[i]; if (!modelMesh) { continue; } if (gameObject == modelMesh) { gameObject = null; } if (modelMesh.hideFlags != hideFlags[i]) { modelMesh.hideFlags = hideFlags[i]; } } } if (!gameObject || gameObject.GetComponent <CSGModel>() || gameObject.GetComponent <CSGBrush>() || gameObject.GetComponent <CSGOperation>() || gameObject.GetComponent <GeneratedMeshInstance>() || gameObject.GetComponent <GeneratedMeshes>()) { return(foundObject != null); } foundObject = gameObject; return(true); }
public static ShapeExtrusionState Do(Rect dragArea, out Curve2D shape, out float height, out CSGModel 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, 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 < 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); } }
static bool FindWorldIntersection(CSGModel model, Vector3 worldRayStart, Vector3 worldRayEnd, out LegacyBrushIntersection[] intersections, bool ignoreInvisibleSurfaces = true, bool ignoreUnrenderables = true, CSGBrush[] ignoreBrushes = null) { intersections = null; if (InternalCSGModelManager.External == null || InternalCSGModelManager.External.RayCastIntoModelMulti == null) { return(false); } var foundIntersections = new Dictionary <CSGNode, LegacyBrushIntersection>(); var visibleLayers = Tools.visibleLayers; ignoreInvisibleSurfaces = ignoreInvisibleSurfaces && !CSGSettings.ShowCulledSurfaces; if (!ModelTraits.IsModelSelectable(model)) { return(false); } if (ignoreUnrenderables && !ModelTraits.WillModelRender(model) && !Selection.Contains(model.gameObject.GetInstanceID())) { return(false); } LegacyBrushIntersection[] modelIntersections; if (!InternalCSGModelManager.External.RayCastIntoModelMulti(model, worldRayStart, worldRayEnd, ignoreInvisibleSurfaces, out modelIntersections, ignoreBrushes: ignoreBrushes)) { return(false); } for (var i = 0; i < modelIntersections.Length; i++) { var intersection = modelIntersections[i]; var brush = intersection.gameObject.GetComponent <CSGBrush>(); if (BrushTraits.IsSurfaceUnselectable(brush, intersection.surfaceIndex, brush.ChildData.Model.IsTrigger, ignoreSurfaceFlags: !ignoreInvisibleSurfaces)) { continue; } var currentNode = GetTopMostGroupForNode(brush); LegacyBrushIntersection other; if (foundIntersections.TryGetValue(currentNode, out other) && other.distance <= intersection.distance) { continue; } intersection.brush = brush; intersection.model = model; foundIntersections[currentNode] = modelIntersections[i]; } if (foundIntersections.Count == 0) { return(false); } var sortedIntersections = foundIntersections.Values.ToArray(); Array.Sort(sortedIntersections, (x, y) => (int)Mathf.Sign(x.distance - y.distance)); intersections = sortedIntersections; return(true); }
/// <summary> /// Imports the specified map into the SabreCSG model. /// </summary> /// <param name="model">The model to import into.</param> /// <param name="map">The map to be imported.</param> /// <param name="scale">The scale modifier.</param> public static void Import(CSGModel model, T3dMap map, int scale = 64) { try { model.BeginUpdate(); List <T3dActor> brushes = map.Brushes; Brush[] sabreBrushes = new Brush[brushes.Count]; // iterate through all brush actors. for (int k = 0; k < brushes.Count; k++) { // get the underlying brush data. T3dActor tactor = brushes[k]; T3dBrush tbrush = tactor.Brush; #if UNITY_EDITOR UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Unreal Gold Map", "Converting Unreal Brushes To SabreCSG Brushes (" + (k + 1) + " / " + brushes.Count + ")...", k / (float)brushes.Count); #endif // iterate through the brush polygons. Polygon[] polygons = new Polygon[tbrush.Polygons.Count]; for (int i = 0; i < tbrush.Polygons.Count; i++) { T3dPolygon tpolygon = tbrush.Polygons[i]; // find the material in the unity project automatically. Material material = FindMaterial(tpolygon.Texture); Vertex[] vertices = new Vertex[tpolygon.Vertices.Count]; for (int j = 0; j < tpolygon.Vertices.Count; j++) { // main-scale // scale around pivot point. Vector3 vertexPosition = ToVector3(tpolygon.Vertices[j]); Vector3 pivot = ToVector3(tactor.PrePivot); Vector3 difference = vertexPosition - pivot; vertexPosition = difference.Multiply(ToVector3Raw(tactor.MainScale)) + pivot; // post-scale vertices[j] = new Vertex(vertexPosition.Multiply(ToVector3Raw(tactor.PostScale)) / (float)scale, ToVector3(tpolygon.Normal), GenerateUV(tpolygon, j, material)); } // detect the polygon flags. bool userExcludeFromFinal = false; if ((tpolygon.Flags & T3dPolygonFlags.Invisible) > 0) { userExcludeFromFinal = true; } polygons[i] = new Polygon(vertices, material, false, userExcludeFromFinal); } // position and rotate the brushes around their pivot point. Transform transform = model.CreateCustomBrush(polygons).transform; transform.position = (ToVector3(tactor.Location) / (float)scale) - (ToVector3(tactor.PrePivot) / (float)scale); Vector3 axis; float angle; T3dRotatorToQuaternion(tactor.Rotation).ToAngleAxis(out angle, out axis); transform.RotateAround(transform.position + (ToVector3(tactor.PrePivot) / (float)scale), axis, angle); PrimitiveBrush brush = transform.GetComponent <PrimitiveBrush>(); sabreBrushes[k] = brush; object value; // detect the brush mode (additive, subtractive). if (tactor.Properties.TryGetValue("CsgOper", out value)) { brush.Mode = (string)value == "CSG_Add" ? CSGMode.Add : CSGMode.Subtract; } // detect special brush flags. if (tactor.Properties.TryGetValue("PolyFlags", out value)) { T3dBrushFlags flags = (T3dBrushFlags)value; if ((flags & T3dBrushFlags.Invisible) > 0) { brush.IsVisible = false; } if ((flags & T3dBrushFlags.NonSolid) > 0) { brush.HasCollision = false; } if ((flags & T3dBrushFlags.SemiSolid) > 0) { brush.IsNoCSG = true; } } // detect single polygons. if (polygons.Length == 1) { brush.IsNoCSG = true; } } // add all new brushes to a group. string title = "Unreal Gold Map"; if (map.Title != "") { title += " '" + map.Title + "'"; } if (map.Author != "") { title += " (" + map.Author + ")"; } GroupBrush groupBrush = new GameObject(title).AddComponent <GroupBrush>(); groupBrush.transform.SetParent(model.transform); for (int i = 0; i < sabreBrushes.Length; i++) { sabreBrushes[i].transform.SetParent(groupBrush.transform); } #if UNITY_EDITOR UnityEditor.EditorUtility.ClearProgressBar(); #endif } catch (Exception) { throw; } finally { model.EndUpdate(); } }
public static BoxExtrusionState Do(Rect dragArea, out Bounds bounds, out float height, out CSGModel modelBeneathCursor, out Matrix4x4 transformation, BoxExtrusionFlags flags, Axis axis, float?snappingSteps = null) { try { if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan) { 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; } }
public static void Do(int id, Rect dragArea, ref List <Vector3> points, out Matrix4x4 transformation, out CSGModel 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 (Tools.current == Tool.View || Tools.current == Tool.None || evt.alt) { 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)); 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 (Tools.current == Tool.View || Tools.current == Tool.None || evt.alt) { 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 CSGModel modelBeneathCursor, UnitySceneExtensions.SceneHandles.CapFunction capFunction) { var id = GUIUtility.GetControlID(s_PointDrawingHash, FocusType.Keyboard); PointDrawing.Do(id, dragArea, ref points, out transformation, out modelBeneathCursor, capFunction); }
private const float inchesInMeters = 0.03125f; // 1/32 /// <summary> /// Imports the specified world into the SabreCSG model. /// </summary> /// <param name="model">The model to import into.</param> /// <param name="world">The world to be imported.</param> /// <param name="scale">The scale modifier.</param> public static void Import(CSGModel model, VmfWorld world) { try { model.BeginUpdate(); // group all the brushes together. GroupBrush groupBrush = new GameObject("Source Engine Map").AddComponent <GroupBrush>(); groupBrush.transform.SetParent(model.transform); // iterate through all world solids. for (int i = 0; i < world.Solids.Count; i++) { #if UNITY_EDITOR UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Source Engine Map", "Converting Hammer Solids To SabreCSG 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; } // build a very large cube brush. var go = model.CreateBrush(PrimitiveBrushType.Cube, Vector3.zero); var pr = go.GetComponent <PrimitiveBrush>(); BrushUtility.Resize(pr, new Vector3(8192, 8192, 8192)); // clip all the sides out of the brush. for (int j = solid.Sides.Count; j-- > 0;) { VmfSolidSide side = solid.Sides[j]; Plane clip = new Plane(pr.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * inchesInMeters)); ClipUtility.ApplyClipPlane(pr, clip, false); // find the polygons associated with the clipping plane. // the normal is unique and can never occur twice as that wouldn't allow the solid to be convex. var polygons = pr.GetPolygons().Where(p => p.Plane.normal == clip.normal); foreach (var polygon in polygons) { // detect excluded polygons. if (IsExcludedMaterial(side.Material)) { polygon.UserExcludeFromFinal = true; } // detect collision-only brushes. if (IsInvisibleMaterial(side.Material)) { pr.IsVisible = false; } // try finding the material in the project. polygon.Material = FindMaterial(side.Material); // calculate the texture coordinates. int w = 256; int h = 256; if (polygon.Material != null && polygon.Material.mainTexture != null) { w = polygon.Material.mainTexture.width; h = polygon.Material.mainTexture.height; } CalculateTextureCoordinates(pr, polygon, w, h, side.UAxis, side.VAxis); } } // add the brush to the group. pr.transform.SetParent(groupBrush.transform); } // iterate through all entities. for (int e = 0; e < world.Entities.Count; e++) { #if UNITY_EDITOR UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Source Engine Map", "Converting Hammer Entities To SabreCSG Brushes (" + (e + 1) + " / " + world.Entities.Count + ")...", e / (float)world.Entities.Count); #endif VmfEntity entity = world.Entities[e]; // skip entities that sabrecsg 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; } // build a very large cube brush. var go = model.CreateBrush(PrimitiveBrushType.Cube, Vector3.zero); var pr = go.GetComponent <PrimitiveBrush>(); BrushUtility.Resize(pr, new Vector3(8192, 8192, 8192)); // clip all the sides out of the brush. for (int j = solid.Sides.Count; j-- > 0;) { VmfSolidSide side = solid.Sides[j]; Plane clip = new Plane(pr.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * inchesInMeters)); ClipUtility.ApplyClipPlane(pr, clip, false); // find the polygons associated with the clipping plane. // the normal is unique and can never occur twice as that wouldn't allow the solid to be convex. var polygons = pr.GetPolygons().Where(p => p.Plane.normal == clip.normal); foreach (var polygon in polygons) { // detect excluded polygons. if (IsExcludedMaterial(side.Material)) { polygon.UserExcludeFromFinal = true; } // detect collision-only brushes. if (IsInvisibleMaterial(side.Material)) { pr.IsVisible = false; } // try finding the material in the project. polygon.Material = FindMaterial(side.Material); // calculate the texture coordinates. int w = 256; int h = 256; if (polygon.Material != null && polygon.Material.mainTexture != null) { w = polygon.Material.mainTexture.width; h = polygon.Material.mainTexture.height; } CalculateTextureCoordinates(pr, polygon, w, h, side.UAxis, side.VAxis); } } // 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; } // add the brush to the group. pr.transform.SetParent(groupBrush.transform); } } #if UNITY_EDITOR UnityEditor.EditorUtility.ClearProgressBar(); #endif } catch (Exception) { throw; } finally { model.EndUpdate(); } }