public static void ReplaceObjectsInModel(CSGModel model, HashSet <Mesh> oldMeshes, HashSet <Mesh> newMeshes, bool skipAssetDatabaseUpdate = false) { if (!model) { return; } if (!CSGPrefabUtility.IsPrefab(model)) { return; } if (!skipAssetDatabaseUpdate) { AssetDatabase.StartAssetEditing(); // We might be modifying a prefab, in which case we need to store a mesh inside it } try { var asset = CSGPrefabUtility.GetPrefabAsset(model.gameObject); var assetPath = AssetDatabase.GetAssetPath(asset); if (string.IsNullOrEmpty(assetPath)) { return; } #if UNITY_2018_3_OR_NEWER foreach (var oldMesh in oldMeshes) { if (CanRemoveObjectFromAsset(assetPath, oldMesh, ignoreWhenPartOfOtherAsset: true)) { AssetDatabase.RemoveObjectFromAsset(oldMesh); } } #endif foreach (var _newMesh in newMeshes) { var newMesh = _newMesh; if (IsObjectPartOfAnotherAsset(assetPath, newMesh)) { // Copy the mesh newMesh = newMesh.Clone(); } if (CanAddObjectToAsset(assetPath, newMesh)) { AssetDatabase.AddObjectToAsset(newMesh, asset); } } } finally { if (!skipAssetDatabaseUpdate) { AssetDatabase.StopAssetEditing(); } } }
public static bool NeedsRigidBody(CSGModel model) { var collidable = (model.Settings & ModelSettingsFlags.NoCollider) != ModelSettingsFlags.NoCollider; var isTrigger = collidable && (model.Settings & ModelSettingsFlags.IsTrigger) == ModelSettingsFlags.IsTrigger; var ownerStaticFlags = GameObjectUtility.GetStaticEditorFlags(model.gameObject); var batchingstatic = (ownerStaticFlags & StaticEditorFlags.BatchingStatic) == StaticEditorFlags.BatchingStatic; return((batchingstatic || collidable) && !isTrigger); }
public static bool IsDefaultModel(CSGModel model) { if ((model.hideFlags & MeshInstanceManager.ComponentHideFlags) == MeshInstanceManager.ComponentHideFlags || (model.hideFlags & HideFlags.DontSave) == HideFlags.DontSave || (model.hideFlags & HideFlags.DontSaveInEditor) == HideFlags.DontSaveInEditor) { return(true); } return(false); }
public static bool IsModelSelectable(CSGModel model) { if (!model || !model.isActiveAndEnabled) { return(false); } if (((1 << model.gameObject.layer) & Tools.visibleLayers) == 0) { return(false); } return(true); }
static void SetCSGOperationHierarchy(CSGOperation op, CSGOperation parentOp, CSGModel parentModel) { SetNodeParent(op.ChildData, op.ParentData, parentOp, parentModel); /* * if (!operationCache.ChildData.Model) * return; * * External.SetOperationHierarchy(op.operationNodeID, * operationCache.ChildData.modelNodeID, * operationCache.ChildData.parentNodeID);*/ }
static void SetCSGBrushHierarchy(CSGBrush brush, CSGOperation parentOp, CSGModel parentModel) { SetNodeParent(brush.ChildData, brush.hierarchyItem, parentOp, parentModel); /* * if (!brushCache.childData.Model) * return; * * External.SetBrushHierarchy(brush.brushNodeID, * brushCache.childData.modelNodeID, * brushCache.childData.parentNodeID);*/ }
public static bool NeedsStaticRigidBody(CSGModel model) { if (!IsModelEditable(model)) { return(false); } var ownerStaticFlags = GameObjectUtility.GetStaticEditorFlags(model.gameObject); var batchingstatic = (ownerStaticFlags & StaticEditorFlags.BatchingStatic) == StaticEditorFlags.BatchingStatic; return(batchingstatic); }
public static bool NeedsRigidBody(CSGModel model) { if (!IsModelEditable(model)) { return(false); } var collidable = model.HaveCollider; var isTrigger = collidable && model.IsTrigger; var ownerStaticFlags = GameObjectUtility.GetStaticEditorFlags(model.gameObject); var batchingstatic = (ownerStaticFlags & StaticEditorFlags.BatchingStatic) == StaticEditorFlags.BatchingStatic; return((batchingstatic || collidable) && !isTrigger); }
public virtual void Reset() { editMode = EditMode.CreatePlane; brushPosition = MathConstants.zeroVector3; parentGameObject = null; parentModel = null; operationGameObject = null; parentTransform = null; generatedGameObjects = null; generatedBrushes = null; undoGroupIndex = -1; forceCurrentCSGOperationType = invalidCSGOperationType; currentCSGOperationType = invalidCSGOperationType; }
public static bool WillModelRender(CSGModel model) { #if UNITY_2018_3_OR_NEWER var currentPrefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage(); if (currentPrefabStage != null) { var prefabRoot = currentPrefabStage.prefabContentsRoot; if (prefabRoot.scene != model.gameObject.scene) { return(false); } } #endif // Is our model valid ...? if (!model || !model.isActiveAndEnabled) { return(false); } // Does our model have a meshRenderer? if (model.IsRenderable) { // If so, is it shadow-only? // if (model.ShadowsOnly) // { // .. and do we need to show shadow-only surfaces? // return CSGSettings.ShowCastShadowsSurfaces; // } // Otherwise, it is always rendering (with the exception of manually hidden surfaces) return(true); } // Is it a trigger and are we showing triggers? if (model.IsTrigger && CSGSettings.ShowTriggerSurfaces) { return(true); } // Check if it's a collider and are we showing colliders? if (model.HaveCollider && CSGSettings.ShowColliderSurfaces) { return(true); } // Otherwise see if we're showing surfaces culled by the CSG process ... return(CSGSettings.ShowCulledSurfaces); }
public virtual void Init() { prevSelection = new List <UnityEngine.Object>(Selection.objects).ToArray(); Reset(); shapeIsValid = true; isFinished = false; originalGridRotation = RealtimeCSG.CSGGrid.ForcedGridRotation; originalGridCenter = RealtimeCSG.CSGGrid.ForcedGridCenter; originalForceGrid = RealtimeCSG.CSGGrid.ForceGrid; geometryModel = null; }
public static bool IsPrefab(CSGModel model) { if (!model) { return(false); } var parent = CSGPrefabUtility.GetPrefabAsset(model.gameObject); if (parent) { return(true); } return(false); }
public static void ReplaceObjectInModel(CSGModel model, UnityEngine.Object oldObj, UnityEngine.Object newObj, bool skipAssetDatabaseUpdate = false) { if (!model || oldObj == newObj) { return; } if (!CSGPrefabUtility.IsPrefab(model)) { return; } if (!skipAssetDatabaseUpdate) { AssetDatabase.StartAssetEditing(); // We might be modifying a prefab, in which case we need to store a mesh inside it } try { var asset = CSGPrefabUtility.GetPrefabAsset(model.gameObject); var assetPath = AssetDatabase.GetAssetPath(asset); #if UNITY_2018_3_OR_NEWER if (oldObj) { if (CanRemoveObjectFromAsset(assetPath, oldObj)) { AssetDatabase.RemoveObjectFromAsset(oldObj); } } #endif if (newObj) { if (CanAddObjectToAsset(assetPath, newObj)) { AssetDatabase.AddObjectToAsset(newObj, asset); } } } finally { if (!skipAssetDatabaseUpdate) { AssetDatabase.StopAssetEditing(); } } }
public static bool WillModelRender(CSGModel model) { // Is our model valid ...? if (!IsModelEditable(model)) { return(false); } #if UNITY_2018_3_OR_NEWER if (CSGPrefabUtility.AreInPrefabMode()) { if (!CSGPrefabUtility.IsEditedInPrefabMode(model)) { return(false); } } #endif // Does our model have a meshRenderer? if (model.IsRenderable) { // If so, is it shadow-only? // if (model.ShadowsOnly) // { // .. and do we need to show shadow-only surfaces? // return CSGSettings.ShowCastShadowsSurfaces; // } // Otherwise, it is always rendering (with the exception of manually hidden surfaces) return(true); } // Is it a trigger and are we showing triggers? if (model.IsTrigger && CSGSettings.ShowTriggerSurfaces) { return(true); } // Check if it's a collider and are we showing colliders? if (model.HaveCollider && CSGSettings.ShowColliderSurfaces) { return(true); } // Otherwise see if we're showing surfaces culled by the CSG process ... return(CSGSettings.ShowCulledSurfaces); }
public static bool IsModelEditable(CSGModel model) { if (!model) { return(false); } #if UNITY_2018_3_OR_NEWER && UNITY_EDITOR if (CSGPrefabUtility.AreInPrefabMode()) { // Nested prefabs do not play nice with editing in scene, so it's best to edit them in prefab mode themselves // We only allow editing of nested prefabs when in prefab mode return(CSGPrefabUtility.IsEditedInPrefabMode(model)); } #endif return(model.isActiveAndEnabled); }
private static bool TryGetMeshInstance(GeneratedMeshes meshContainer, CSGModel model, ModelSettingsFlags modelSettings, GeneratedMeshDescription meshDescription, RenderSurfaceType renderSurfaceType, out GeneratedMeshInstance meshInstance) { var startGetMeshInstanceTime = EditorApplication.timeSinceStartup; meshInstance = MeshInstanceManager.GetMeshInstance(meshContainer, meshDescription, modelSettings, renderSurfaceType); getMeshInstanceTime += EditorApplication.timeSinceStartup - startGetMeshInstanceTime; if (meshInstance && meshDescription == meshInstance.MeshDescription && meshInstance.SharedMesh && meshInstance.IsValid()) { return(true); } meshInstance = null; return(true); }
private static bool UpdateMesh(CSGModel model, GeneratedMeshDescription meshDescription, RenderSurfaceType renderSurfaceType, ref GeneratedMeshContents outputGeneratedMeshContents, ref bool outputHasGeneratedNormals, ref Mesh sharedMesh) { // create our arrays on the C# side with the correct size GeneratedMeshContents generatedMesh; var startGetModelMeshesTime = EditorApplication.timeSinceStartup; { generatedMesh = External.GetModelMesh(model.modelNodeID, meshDescription); if (generatedMesh == null) { return(false); } } getModelMeshesTime += EditorApplication.timeSinceStartup - startGetModelMeshesTime; UpdateMesh(generatedMesh, meshDescription, renderSurfaceType, ref outputHasGeneratedNormals, ref sharedMesh); /* #if UNITY_2018_3_OR_NEWER * var modelGameObject = model.gameObject; * var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage(modelGameObject); * if (prefabStage != null && string.IsNullOrEmpty(AssetDatabase.GetAssetPath(sharedMesh))) * { * var prefabAssetPath = prefabStage.prefabAssetPath; * if (!string.IsNullOrEmpty(prefabAssetPath)) * AssetDatabase.AddObjectToAsset(sharedMesh, prefabAssetPath); * UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(modelGameObject.scene); * } #endif */ outputGeneratedMeshContents = generatedMesh; return(true); }
public static bool IsEditedInPrefabMode(CSGModel model) { #if UNITY_2018_3_OR_NEWER && UNITY_EDITOR if (!model) { return(false); } if (!AreInPrefabMode()) { return(false); } var currentStageHandle = StageUtility.GetCurrentStageHandle(); if (currentStageHandle.Contains(model.gameObject)) { return(true); } #endif return(false); }
public static void AddObjectToModel(CSGModel model, UnityEngine.Object obj) { if (!model || !obj) { return; } if (!CSGPrefabUtility.IsPrefab(model)) { return; } var asset = CSGPrefabUtility.GetPrefabAsset(model.gameObject); var assetPath = AssetDatabase.GetAssetPath(asset); if (!CanAddObjectToAsset(assetPath, obj)) { return; } AssetDatabase.AddObjectToAsset(obj, asset); }
static void FindParentModel(Transform opTransform, out CSGModel parentModel) { if (!opTransform) { parentModel = null; return; } var iterator = opTransform.parent; while (iterator) { var currentNodeObj = iterator.GetComponent(TypeConstants.CSGModelType); if (currentNodeObj) { parentModel = currentNodeObj as CSGModel; return; } iterator = iterator.parent; } parentModel = GetDefaultCSGModelForObject(opTransform); }
public static void RemoveObjectFromModel(CSGModel model, UnityEngine.Object obj) { #if UNITY_2018_3_OR_NEWER if (!model || !obj) { return; } if (!CSGPrefabUtility.IsPrefab(model)) { return; } var asset = CSGPrefabUtility.GetPrefabAsset(model.gameObject); var assetPath = AssetDatabase.GetAssetPath(asset); if (!CanRemoveObjectFromAsset(assetPath, obj)) { return; } AssetDatabase.RemoveObjectFromAsset(obj); #endif }
public static RenderSurfaceType GetModelSurfaceType(CSGModel model) { if (model.IsRenderable) // if it's renderable then it's already being rendered using a MeshRenderer { // except if it's a shadow only surface, it has a MeshRenderer, but is not usually visible ... // if (model.ShadowsOnly) // return RenderSurfaceType.ShadowOnly; return(RenderSurfaceType.Normal); } if (model.IsTrigger) { return(RenderSurfaceType.Trigger); } if (model.HaveCollider) { return(RenderSurfaceType.Collider); } return(RenderSurfaceType.Culled); }
public static bool WillModelRender(CSGModel model) { // Is our model valid ...? if (!model || !model.isActiveAndEnabled) { return(false); } // Does our model have a meshRenderer? if (model.IsRenderable) { // If so, is it shadow-only? if (model.ShadowsOnly) { // .. and do we need to show shadow-only surfaces? return(CSGSettings.ShowCastShadowsSurfaces); } // Otherwise, it is always rendering (with the exception of manually hidden surfaces) return(true); } // Is it a trigger and are we showing triggers? if (model.IsTrigger && CSGSettings.ShowTriggerSurfaces) { return(true); } // Check if it's a collider and are we showing colliders? if (model.HaveCollider && CSGSettings.ShowColliderSurfaces) { return(true); } // Otherwise see if we're showing surfaces culled by the CSG process ... return(CSGSettings.ShowCulledSurfaces); }
internal override bool CreateControlMeshForBrushIndex(CSGModel parentModel, CSGBrush brush, ShapePolygon polygon, Matrix4x4 localToWorld, float height, out ControlMesh newControlMesh, out Shape newShape) { var direction = haveForcedDirection ? forcedDirection : buildPlane.normal; if (!ShapePolygonUtility.GenerateControlMeshFromVertices(polygon, localToWorld, GeometryUtility.RotatePointIntoPlaneSpace(buildPlane, direction), height, new TexGen(), false, true, out newControlMesh, out newShape)) { return false; } brush.Shape = newShape; brush.ControlMesh = newControlMesh; InternalCSGModelManager.ValidateBrush(brush, true); ControlMeshUtility.RebuildShape(brush); return true; }
public static GameObject[] GetModelMeshes(CSGModel model) { var meshContainer = model.generatedMeshes; var meshInstances = MeshInstanceManager.GetAllModelMeshInstances(meshContainer); if (meshInstances == null) { return(new GameObject[0]); } var gameObjects = new List <GameObject>(); for (var i = 0; i < meshInstances.Length; i++) { if (!meshInstances[i] || meshInstances[i].RenderSurfaceType != RenderSurfaceType.Normal) { continue; } gameObjects.Add(meshInstances[i].gameObject); } return(gameObjects.ToArray()); }
private bool GenerateSphere(float radius, int splits, CSGModel parentModel, CSGBrush brush, out ControlMesh controlMesh, out Shape shape) { if (prevSplits != splits || prevIsHemisphere != IsHemiSphere || splitControlMesh == null || splitShape == null) { splitControlMesh = null; splitShape = null; BrushFactory.CreateCubeControlMesh(out splitControlMesh, out splitShape, Vector3.one); var axi = new Vector3[] { MathConstants.upVector3, MathConstants.leftVector3, MathConstants.forwardVector3 }; List<int> intersectedEdges = new List<int>(); float step = 1.0f / (float)(splits + 1); float offset; for (int i = 0; i < axi.Length; i++) { var normal = axi[i]; offset = 0.5f - step; while (offset > 0.0f) { ControlMeshUtility.CutMesh(splitControlMesh, splitShape, new CSGPlane(-normal, -offset), ref intersectedEdges); if (i != 0 || !IsHemiSphere) { ControlMeshUtility.CutMesh(splitControlMesh, splitShape, new CSGPlane(normal, -offset), ref intersectedEdges); } offset -= step; } if (i != 0 || !IsHemiSphere) { if ((splits & 1) == 1) ControlMeshUtility.CutMesh(splitControlMesh, splitShape, new CSGPlane(normal, 0), ref intersectedEdges); } } if (IsHemiSphere) { var cuttingPlane = new CSGPlane(MathConstants.upVector3, 0); intersectedEdges.Clear(); if (ControlMeshUtility.CutMesh(splitControlMesh, splitShape, cuttingPlane, ref intersectedEdges)) { var edge_loop = ControlMeshUtility.FindEdgeLoop(splitControlMesh, ref intersectedEdges); if (edge_loop != null) { if (ControlMeshUtility.SplitEdgeLoop(splitControlMesh, splitShape, edge_loop)) { Shape foundShape; ControlMesh foundControlMesh; ControlMeshUtility.FindAndDetachSeparatePiece(splitControlMesh, splitShape, cuttingPlane, out foundControlMesh, out foundShape); } } } } // Spherize the cube for (int i = 0; i < splitControlMesh.Vertices.Length; i++) { Vector3 v = splitControlMesh.Vertices[i] * 2.0f; float x2 = v.x * v.x; float y2 = v.y * v.y; float z2 = v.z * v.z; Vector3 s; s.x = v.x * Mathf.Sqrt(1f - (y2 * 0.5f) - (z2 * 0.5f) + ((y2 * z2) / 3.0f)); s.y = v.y * Mathf.Sqrt(1f - (z2 * 0.5f) - (x2 * 0.5f) + ((z2 * x2) / 3.0f)); s.z = v.z * Mathf.Sqrt(1f - (x2 * 0.5f) - (y2 * 0.5f) + ((x2 * y2) / 3.0f)); splitControlMesh.Vertices[i] = s;//(splitControlMesh.Vertices[i] * 0.75f) + (splitControlMesh.Vertices[i].normalized * 0.25f); } if (!ControlMeshUtility.Triangulate(null, splitControlMesh, splitShape)) { Debug.LogWarning("!ControlMeshUtility.IsConvex"); controlMesh = null; shape = null; return false; } ControlMeshUtility.FixTexGens(splitControlMesh, splitShape); if (!ControlMeshUtility.IsConvex(splitControlMesh, splitShape)) { Debug.LogWarning("!ControlMeshUtility.IsConvex"); controlMesh = null; shape = null; return false; } ControlMeshUtility.UpdateTangents(splitControlMesh, splitShape); prevSplits = splits; prevIsHemisphere = IsHemiSphere; } if (splitControlMesh == null || splitShape == null || !splitControlMesh.Valid) { Debug.LogWarning("splitControlMesh == null || splitShape == null || !splitControlMesh.IsValid"); controlMesh = null; shape = null; return false; } controlMesh = splitControlMesh.Clone(); shape = splitShape.Clone(); /* 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); } */ for (int i = 0; i < controlMesh.Vertices.Length; i++) { var vertex = controlMesh.Vertices[i]; vertex *= radius; controlMesh.Vertices[i] = vertex; } for (int i = 0; i < shape.Surfaces.Length; i++) { var plane = shape.Surfaces[i].Plane; plane.d *= radius; shape.Surfaces[i].Plane = plane; } bool smoothShading = SphereSmoothShading; if (!sphereSmoothingGroup.HasValue && smoothShading) { sphereSmoothingGroup = SurfaceUtility.FindUnusedSmoothingGroupIndex(); } for (int i = 0; i < shape.TexGenFlags.Length; i++) { shape.TexGens[i].SmoothingGroup = smoothShading ? sphereSmoothingGroup.Value : 0; } var defaultTexGen = new TexGen(); defaultTexGen.Scale = MathConstants.oneVector3; //defaultTexGen.Color = Color.white; var fakeSurface = new Surface(); fakeSurface.TexGenIndex = 0; var defaultMaterial = CSGSettings.DefaultMaterial; for (var s = 0; s < shape.Surfaces.Length; s++) { var texGenIndex = shape.Surfaces[s].TexGenIndex; var axis = GeometryUtility.SnapToClosestAxis(shape.Surfaces[s].Plane.normal); var rotation = Quaternion.FromToRotation(axis, MathConstants.backVector3); var matrix = Matrix4x4.TRS(MathConstants.zeroVector3, rotation, MathConstants.oneVector3); SurfaceUtility.AlignTextureSpaces(matrix, false, ref shape.TexGens[texGenIndex], ref shape.TexGenFlags[texGenIndex], ref shape.Surfaces[s]); shape.TexGens[texGenIndex].RenderMaterial = defaultMaterial; } return true; }
internal abstract bool CreateControlMeshForBrushIndex(CSGModel parentModel, CSGBrush brush, ShapePolygon polygon, Matrix4x4 localToWorld, float height, out ControlMesh newControlMesh, out Shape newShape);
protected bool GenerateBrushObjects(int brushObjectCount, bool inGridSpace = true) { Undo.IncrementCurrentGroup(); undoGroupIndex = Undo.GetCurrentGroup(); var lastUsedModel = SelectionUtility.LastUsedModel; if (!ModelTraits.IsModelEditable(lastUsedModel)) { lastUsedModel = null; } var lastUsedModelTransform = !lastUsedModel ? null : lastUsedModel.transform; if (!lastUsedModelTransform || !lastUsedModel.isActiveAndEnabled) { if (prevSelection != null && prevSelection.Length > 0) { for (int i = 0; i < prevSelection.Length; i++) { UnityEngine.Object obj = prevSelection[i]; CSGBrush brush = obj as CSGBrush; MonoBehaviour mono = obj as MonoBehaviour; GameObject go = obj as GameObject; if (!brush) { if (mono) { brush = mono.GetComponentInChildren <CSGBrush>(); } if (go) { brush = go.GetComponentInChildren <CSGBrush>(); } } if (!brush) { continue; } if ((brush.gameObject.hideFlags & (HideFlags.HideInHierarchy | HideFlags.NotEditable | HideFlags.DontSaveInBuild)) != 0) { continue; } if (brush.ChildData == null || brush.ChildData.ModelTransform == null) { continue; } var model = brush.ChildData.Model; if (!model || !model.isActiveAndEnabled) { continue; } lastUsedModelTransform = brush.ChildData.ModelTransform; break; } } } if (generatedBrushes != null && generatedBrushes.Length > 0) { for (int i = generatedBrushes.Length - 1; i >= 0; i--) { if (generatedBrushes[i]) { continue; } ArrayUtility.RemoveAt(ref generatedBrushes, i); } for (int i = generatedGameObjects.Length - 1; i >= 0; i--) { if (generatedGameObjects[i]) { var brush = generatedGameObjects[i].GetComponentInChildren <CSGBrush>(); if (brush && ArrayUtility.Contains(generatedBrushes, brush)) { continue; } } ArrayUtility.RemoveAt(ref generatedGameObjects, i); } } if (generatedGameObjects == null || generatedGameObjects.Length != brushObjectCount) { if (generatedBrushes != null && generatedBrushes.Length > 0) { for (int i = 0; i < generatedBrushes.Length; i++) { InternalCSGModelManager.OnDestroyed(generatedBrushes[i]); GameObject.DestroyImmediate(generatedBrushes[i]); } } if (generatedGameObjects != null && generatedGameObjects.Length > 0) { for (int i = 0; i < generatedGameObjects.Length; i++) { GameObject.DestroyImmediate(generatedGameObjects[i]); } } if (parentGameObject != null) { GameObject.DestroyImmediate(parentGameObject); } //DebugEditorWindow.PrintDebugInfo(); if (lastUsedModelTransform == null) { parentGameObject = OperationsUtility.CreateGameObject(lastUsedModelTransform, "Model", true); InternalCSGModelManager.CreateCSGModel(parentGameObject); parentModel = parentGameObject.GetComponent <CSGModel>(); Undo.RegisterCreatedObjectUndo(parentGameObject, "Created model"); if (brushObjectCount > 1) { operationGameObject = OperationsUtility.CreateGameObject(parentGameObject.transform, "Operation", true); var transform = operationGameObject.transform; SetBrushTransformation(transform); var operation = operationGameObject.AddComponent <CSGOperation>(); if (CurrentCSGOperationType != invalidCSGOperationType) { operation.OperationType = CurrentCSGOperationType; } operation.HandleAsOne = true; Undo.RegisterCreatedObjectUndo(operationGameObject, "Created operation"); parentTransform = operationGameObject.transform; } else { parentTransform = parentGameObject.transform; } } else if (brushObjectCount > 1) { parentModel = lastUsedModelTransform.GetComponent <CSGModel>(); parentGameObject = OperationsUtility.CreateGameObject(lastUsedModelTransform, "Brushes", true); var transform = parentGameObject.transform; SetBrushTransformation(transform); operationGameObject = parentGameObject; var operation = operationGameObject.AddComponent <CSGOperation>(); if (CurrentCSGOperationType != invalidCSGOperationType) { operation.OperationType = CurrentCSGOperationType; } operation.HandleAsOne = true; parentTransform = operationGameObject.transform; Undo.RegisterCreatedObjectUndo(parentGameObject, "Created brush"); } else { parentGameObject = null; operationGameObject = null; parentTransform = lastUsedModelTransform; parentModel = lastUsedModelTransform.GetComponent <CSGModel>(); } generatedGameObjects = new GameObject[brushObjectCount]; generatedBrushes = new CSGBrush[brushObjectCount]; for (int p = 0; p < brushObjectCount; p++) { string name; if (brushObjectCount == 1) { name = "Brush"; } else { name = "Brush (" + p + ")"; } var gameObject = OperationsUtility.CreateGameObject(parentTransform, name, false); gameObject.SetActive(false); var brushComponent = gameObject.AddComponent <CSGBrush>(); if (operationGameObject == null) { if (CurrentCSGOperationType != invalidCSGOperationType) { brushComponent.OperationType = CurrentCSGOperationType; } operationGameObject = gameObject; var transform = gameObject.transform; SetBrushTransformation(transform); } generatedBrushes[p] = brushComponent; generatedBrushes[p].ControlMesh = new ControlMesh(); generatedBrushes[p].Shape = new Shape(); Undo.RegisterCreatedObjectUndo(gameObject, "Created brush"); generatedGameObjects[p] = gameObject; } //InternalCSGModelManager.Refresh(forceHierarchyUpdate: true); // brushes not registered at this point!?? //DebugEditorWindow.PrintDebugInfo(); //Selection.objects = generatedGameObjects; } else { UpdateBrushPosition(); } return(generatedBrushes != null && generatedBrushes.Length > 0 && generatedBrushes.Length == brushObjectCount); }
static public void OnInspectorGUI(Editor editor, UnityEngine.Object[] targets) { TooltipUtility.InitToolTip(editor); try { var models = new CSGModel[targets.Length]; for (int i = targets.Length - 1; i >= 0; i--) { models[i] = targets[i] as CSGModel; if (!models[i]) { ArrayUtility.RemoveAt(ref models, i); } } CSG_GUIStyleUtility.InitStyles(); ShowRealtimeCSGDisabledMessage(); if (models.Length > 0 && models.Length == targets.Length) { CSGModelComponentInspectorGUI.OnInspectorGUI(targets); return; } var filteredSelection = EditModeManager.FilteredSelection; var targetNodes = filteredSelection.NodeTargets; var targetModels = filteredSelection.ModelTargets; var targetBrushes = filteredSelection.BrushTargets; var targetOperations = filteredSelection.OperationTargets; if (targetNodes == null) { return; } bool?isPrefab = false; PrefabInstantiateBehaviour?prefabBehaviour = PrefabInstantiateBehaviour.Reference; PrefabSourceAlignment? prefabSourceAlignment = PrefabSourceAlignment.AlignedTop; PrefabDestinationAlignment?prefabDestinationAlignment = PrefabDestinationAlignment.AlignToSurface; if (targetNodes.Length > 0) { var gameObject = targetNodes[0].gameObject; isPrefab = CSGPrefabUtility.IsPrefabAsset(gameObject); prefabBehaviour = targetNodes[0].PrefabBehaviour; prefabSourceAlignment = targetNodes[0].PrefabSourceAlignment; prefabDestinationAlignment = targetNodes[0].PrefabDestinationAlignment; for (int i = 1; i < targetNodes.Length; i++) { gameObject = targetNodes[i].gameObject; var currentIsPrefab = CSGPrefabUtility.IsPrefabAsset(gameObject); var currentPrefabBehaviour = targetNodes[i].PrefabBehaviour; var currentPrefabSourceAlignment = targetNodes[i].PrefabSourceAlignment; var currentPrefabDestinationAlignment = targetNodes[i].PrefabDestinationAlignment; if (isPrefab.HasValue && isPrefab.Value != currentIsPrefab) { isPrefab = null; } if (prefabBehaviour.HasValue && prefabBehaviour.Value != currentPrefabBehaviour) { prefabBehaviour = null; } if (prefabSourceAlignment.HasValue && prefabSourceAlignment.Value != currentPrefabSourceAlignment) { prefabSourceAlignment = null; } if (prefabDestinationAlignment.HasValue && prefabDestinationAlignment.Value != currentPrefabDestinationAlignment) { prefabDestinationAlignment = null; } } } GUILayout.BeginVertical(GUI.skin.box); { if (isPrefab.HasValue && isPrefab.Value) { EditorGUILayout.LabelField(PrefabLabelContent); } else { EditorGUILayout.LabelField(RaySnappingLabelContent); TooltipUtility.SetToolTip(RaySnappingBehaviourTooltip); } EditorGUI.indentLevel++; { if (isPrefab.HasValue && isPrefab.Value) { EditorGUI.showMixedValue = !prefabBehaviour.HasValue; var prefabBehavour = prefabBehaviour.HasValue ? prefabBehaviour.Value : PrefabInstantiateBehaviour.Reference; EditorGUI.BeginChangeCheck(); { prefabBehavour = (PrefabInstantiateBehaviour)EditorGUILayout.EnumPopup(PrefabInstantiateBehaviourContent, prefabBehavour); TooltipUtility.SetToolTip(PrefabInstantiateBehaviourTooltip); } if (EditorGUI.EndChangeCheck()) { Undo.RecordObjects(targetNodes, "Changed CSG operation of nodes"); for (int i = 0; i < targetNodes.Length; i++) { targetNodes[i].PrefabBehaviour = prefabBehavour; } } EditorGUI.showMixedValue = false; } EditorGUI.showMixedValue = !prefabDestinationAlignment.HasValue; var destinationAlignment = prefabDestinationAlignment.HasValue ? prefabDestinationAlignment.Value : PrefabDestinationAlignment.AlignToSurface; EditorGUI.BeginChangeCheck(); { destinationAlignment = (PrefabDestinationAlignment)EditorGUILayout.EnumPopup(DestinationAlignmentContent, destinationAlignment); TooltipUtility.SetToolTip(DestinationAlignmentTooltip); } if (EditorGUI.EndChangeCheck()) { Undo.RecordObjects(targetNodes, "Changed CSG operation of nodes"); for (int i = 0; i < targetNodes.Length; i++) { targetNodes[i].PrefabDestinationAlignment = destinationAlignment; } } EditorGUI.showMixedValue = false; EditorGUI.showMixedValue = !prefabSourceAlignment.HasValue; var sourceAlignment = prefabSourceAlignment.HasValue ? prefabSourceAlignment.Value : PrefabSourceAlignment.AlignedFront; EditorGUI.BeginChangeCheck(); { sourceAlignment = (PrefabSourceAlignment)EditorGUILayout.EnumPopup(SourceAlignmentContent, sourceAlignment); TooltipUtility.SetToolTip(SourceAlignmentTooltip); } if (EditorGUI.EndChangeCheck()) { Undo.RecordObjects(targetNodes, "Changed CSG operation of nodes"); for (int i = 0; i < targetNodes.Length; i++) { targetNodes[i].PrefabSourceAlignment = sourceAlignment; } } EditorGUI.showMixedValue = false; } EditorGUI.indentLevel--; } GUILayout.EndVertical(); GUILayout.Space(10); if (targetModels.Length == 0) { int invalidOperationType = 999; bool? handleAsOne = null; bool selMixedValues = false; CSGOperationType operationType = (CSGOperationType)invalidOperationType; bool opMixedValues = false; if (targetBrushes.Length > 0) { operationType = targetBrushes[0].OperationType; } for (int b = 1; b < targetBrushes.Length; b++) { var brush = targetBrushes[b]; if (operationType != brush.OperationType) { opMixedValues = true; } } foreach (var operation in targetOperations) { if (operationType == (CSGOperationType)invalidOperationType) { operationType = operation.OperationType; } else if (operationType != operation.OperationType) { opMixedValues = true; } if (!handleAsOne.HasValue) { handleAsOne = operation.HandleAsOne; } else if (handleAsOne.Value != operation.HandleAsOne) { selMixedValues = true; } } GUILayout.BeginVertical(GUI.skin.box); { bool passThroughValue = false; if (targetBrushes.Length == 0 && targetOperations.Length > 0) // only operations { bool?passThrough = targetOperations[0].PassThrough; for (int i = 1; i < targetOperations.Length; i++) { if (passThrough.HasValue && passThrough.Value != targetOperations[i].PassThrough) { passThrough = null; break; } } opMixedValues = !passThrough.HasValue || passThrough.Value; var ptMixedValues = !passThrough.HasValue; passThroughValue = passThrough.HasValue ? passThrough.Value : false; if (CSG_EditorGUIUtility.PassThroughButton(passThroughValue, ptMixedValues)) { Undo.RecordObjects(targetNodes, "Changed CSG operation of nodes"); foreach (var operation in targetOperations) { operation.PassThrough = true; } InternalCSGModelManager.CheckForChanges(); EditorApplication.RepaintHierarchyWindow(); } if (passThroughValue) { operationType = (CSGOperationType)255; } } EditorGUI.BeginChangeCheck(); { operationType = CSG_EditorGUIUtility.ChooseOperation(operationType, opMixedValues); } if (EditorGUI.EndChangeCheck()) { Undo.RecordObjects(targetNodes, "Changed CSG operation of nodes"); foreach (var brush in targetBrushes) { brush.OperationType = operationType; } foreach (var operation in targetOperations) { operation.PassThrough = false; operation.OperationType = operationType; } InternalCSGModelManager.CheckForChanges(); EditorApplication.RepaintHierarchyWindow(); } } GUILayout.EndVertical(); if (targetOperations.Length == 0 && targetModels.Length == 0) { GUILayout.Space(10); if (targetBrushes.Length == 1) { GUILayout.BeginVertical(GUI.skin.box); { EditorGUI.indentLevel++; OpenSurfaces = EditorGUILayout.Foldout(OpenSurfaces, SurfacesContent); EditorGUI.indentLevel--; if (OpenSurfaces) { var targetShape = targetBrushes[0].Shape; var texGens = targetShape.TexGens; var texGenFlagArray = targetShape.TexGenFlags; for (int t = 0; t < texGens.Length; t++) { GUILayout.Space(2); var texGenFlags = texGenFlagArray[t]; var material = targetShape.TexGens[t].RenderMaterial; var physicsMat = targetShape.TexGens[t].PhysicsMaterial; EditorGUI.BeginChangeCheck(); { GUILayout.BeginHorizontal(); { GUILayout.Space(4); material = CSG_EditorGUIUtility.MaterialImage(material); GUILayout.Space(2); GUILayout.BeginVertical(); { //EditorGUI.BeginDisabledGroup(texGenFlags != TexGenFlags.None); { material = EditorGUILayout.ObjectField(material, typeof(Material), true) as Material; } //EditorGUI.EndDisabledGroup(); physicsMat = EditorGUILayout.ObjectField(physicsMat, typeof(PhysicMaterial), true) as PhysicMaterial; texGenFlags = EditModeCommonGUI.OnSurfaceFlagButtons(texGenFlags); } GUILayout.EndVertical(); GUILayout.Space(4); } GUILayout.EndHorizontal(); } if (EditorGUI.EndChangeCheck()) { var selectedBrushSurfaces = new [] { new SelectedBrushSurface(targetBrushes[0], t) }; using (new UndoGroup(selectedBrushSurfaces, "discarding surface")) { texGenFlagArray[t] = texGenFlags; targetShape.TexGens[t].RenderMaterial = material; targetShape.TexGens[t].PhysicsMaterial = physicsMat; } } GUILayout.Space(4); } } } GUILayout.EndVertical(); } } if (handleAsOne.HasValue) { EditorGUI.BeginChangeCheck(); { EditorGUI.showMixedValue = selMixedValues; handleAsOne = EditorGUILayout.Toggle(HandleAsOneLabel, handleAsOne.Value); } if (EditorGUI.EndChangeCheck()) { Undo.RecordObjects(targetNodes, "Changed CSG operation 'Handle as one object'"); foreach (var operation in targetOperations) { operation.HandleAsOne = handleAsOne.Value; } EditorApplication.RepaintHierarchyWindow(); } } } #if false if (targetNodes.Length == 1) { var node = targetNodes[0]; var brush = node as CSGBrush; if (brush != null) { var brush_cache = CSGSceneManager.GetBrushCache(brush); if (brush_cache == null || brush_cache.childData == null || brush_cache.childData.modelTransform == null) { EditorGUILayout.LabelField("brush-cache: null"); } else { EditorGUILayout.LabelField("node-id: " + brush.brushNodeID); } } var operation = node as CSGOperation; if (operation != null) { var operation_cache = CSGSceneManager.GetOperationCache(operation); if (operation_cache == null || operation_cache.childData == null || operation_cache.childData.modelTransform == null) { EditorGUILayout.LabelField("operation-cache: null"); } else { EditorGUILayout.LabelField("operation-id: " + operation.operationNodeID); } } var model = node as CSGModel; if (model != null) { var model_cache = CSGSceneManager.GetModelCache(model); if (model_cache == null || model_cache.meshContainer == null) { EditorGUILayout.LabelField("model-cache: null"); } else { EditorGUILayout.LabelField("model-id: " + model.modelNodeID); } } } #endif } finally { TooltipUtility.DrawToolTip(getLastRect: true, goUp: true); } }
static void SetNodeParent(ChildNodeData childData, HierarchyItem hierarchyItem, CSGOperation parentOp, CSGModel parentModel) { var oldParentData = childData.OwnerParentData; childData.Parent = parentOp; childData.Model = parentModel; var newParentData = GetParentData(childData); if (oldParentData != newParentData) { if (oldParentData != null) { oldParentData.RemoveNode(hierarchyItem); } if (newParentData != null) { newParentData.AddNode(hierarchyItem); } childData.OwnerParentData = newParentData; childData.ModelTransform = (!childData.Model) ? null : childData.Model.transform; } }