private static void UpdateModelFlags(ChiselModel model) { if (!IsDefaultModel(model)) { return; } const HideFlags DefaultGameObjectHideFlags = HideFlags.NotEditable; const HideFlags DefaultTransformHideFlags = HideFlags.NotEditable; // | HideFlags.HideInInspector; var gameObject = model.gameObject; var transform = model.transform; if (gameObject.hideFlags != DefaultGameObjectHideFlags) { gameObject.hideFlags = DefaultGameObjectHideFlags; } if (transform.hideFlags != DefaultTransformHideFlags) { transform.hideFlags = DefaultTransformHideFlags; } if (transform.parent != null) { transform.SetParent(null, false); transform.localPosition = Vector3.zero; transform.localRotation = Quaternion.identity; transform.localScale = Vector3.one; } }
private static void UpdateModelFlags(ChiselModel model) { if (!IsDefaultModel(model)) { return; } const HideFlags DefaultGameObjectHideFlags = HideFlags.NotEditable; const HideFlags DefaultTransformHideFlags = HideFlags.NotEditable; // | HideFlags.HideInInspector; var gameObject = model.gameObject; var transform = model.transform; if (gameObject.hideFlags != DefaultGameObjectHideFlags) { gameObject.hideFlags = DefaultGameObjectHideFlags; } if (transform.hideFlags != DefaultTransformHideFlags) { transform.hideFlags = DefaultTransformHideFlags; } if (transform.parent != null) { transform.SetParent(null, false); ChiselObjectUtility.ResetTransform(transform); } }
public static void UpdateColliders(ChiselModel model, ChiselColliderObjects[] colliders) { if (colliders == null) { return; } var colliderSettings = model.ColliderSettings; for (int i = 0; i < colliders.Length; i++) { var meshCollider = colliders[i].meshCollider; if (meshCollider.cookingOptions != colliderSettings.cookingOptions) { meshCollider.cookingOptions = colliderSettings.cookingOptions; } if (meshCollider.convex != colliderSettings.convex) { meshCollider.convex = colliderSettings.convex; } if (meshCollider.isTrigger != colliderSettings.isTrigger) { meshCollider.isTrigger = colliderSettings.isTrigger; } } }
public static bool NeedUVGeneration(ChiselModel model) { haveUVsToUpdate = false; #if UNITY_EDITOR if (!model) { return(false); } var staticFlags = UnityEditor.GameObjectUtility.GetStaticEditorFlags(model.gameObject); if ((staticFlags & UnityEditor.StaticEditorFlags.LightmapStatic) != UnityEditor.StaticEditorFlags.LightmapStatic) { return(false); } for (int i = 0; i < model.generatedMeshes.Length; i++) { var generatedMesh = model.generatedMeshes[i]; // Avoid light mapping multiple times, when the same mesh is used on multiple MeshRenderers if (!ChiselSharedUnityMeshManager.HasLightmapUVs(generatedMesh.sharedMesh)) { return(true); } } #endif return(false); }
internal static void UpdateModelMeshDescriptions(ChiselModel model) { if (!ChiselModelGeneratedObjects.IsValid(model.generated)) { if (model.generated != null) { model.generated.Destroy(); } model.generated = ChiselModelGeneratedObjects.Create(model); } var tree = model.Node; if (!tree.Valid) { return; } var meshTypes = ChiselMeshQueryManager.GetMeshQuery(model); var meshDescriptions = tree.GetMeshDescriptions(meshTypes, model.VertexChannelMask); // Check if the tree creates *any* meshes if (meshDescriptions == null || meshDescriptions.Length == 0) { //componentGenerator.RemoveAllGeneratedComponents(model); PostUpdateModel?.Invoke(model); return; } // Sort all meshDescriptions so that meshes that can be merged are next to each other Array.Sort(meshDescriptions, kMeshDescriptionSorterDelegate); model.generated.Update(model, meshDescriptions); }
public void Unregister(ChiselModel model) { DestroyAllRegisteredGeneratedComponentsInModel(model); RemoveContainerGameObject(model); models.Remove(model); }
private void RemoveContainerGameObjectWithUndo(ChiselModel model) { if (model.generated != null) { model.generated.DestroyWithUndo(); } }
public static void UpdateModel(ChiselModel model) { if (PreUpdateModel != null) { PreUpdateModel(model); } UpdateModelMeshDescriptions(model); // Re-use existing UnityEngine.Mesh if they exist sharedUnityMeshes.ReuseExistingMeshes(model); // Find all meshes whose refCounts are 0 sharedUnityMeshes.FindAllUnusedUnityMeshes(); // Generate new UnityEngine.Mesh instances and fill them with data from the CSG algorithm (if necessary) // note: reuses garbage collected meshes when possible sharedUnityMeshes.CreateNewMeshes(model); // Generate (or re-use) components and set them up properly componentGenerator.Rebuild(model); if (PostUpdateModel != null) { PostUpdateModel(model); } // Destroy all meshes whose refCounts are 0 sharedUnityMeshes.DestroyNonRecycledUnusedUnityMeshes(); }
//*/ public static void UpdateProperties(ChiselModel model, ChiselColliderObjects[] colliders) { var colliderSettings = model.ColliderSettings; for (int i = 0; i < colliders.Length; i++) { var meshCollider = colliders[i].meshCollider; if (!meshCollider) { continue; } // If the cookingOptions are not the default values it would force a full slow rebake later, // even if we already did a Bake in a job //if (meshCollider.cookingOptions != colliderSettings.cookingOptions) // meshCollider.cookingOptions = colliderSettings.cookingOptions; if (meshCollider.convex != colliderSettings.convex) { meshCollider.convex = colliderSettings.convex; } if (meshCollider.isTrigger != colliderSettings.isTrigger) { meshCollider.isTrigger = colliderSettings.isTrigger; } var sharedMesh = colliders[i].sharedMesh; var expectedEnabled = sharedMesh.vertexCount > 0; if (meshCollider.enabled != expectedEnabled) { meshCollider.enabled = expectedEnabled; } } }
private GameObject CreateComponentGameObject(ChiselModel model, string name, params Type[] components) { var modelScene = model.gameObject.scene; var oldActiveScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); if (modelScene != oldActiveScene) { UnityEngine.SceneManagement.SceneManager.SetActiveScene(modelScene); } try { var container = model.GeneratedDataContainer; var gameObject = new GameObject(name, components); var transform = gameObject.GetComponent <Transform>(); transform.SetParent(container.transform, false); transform.localPosition = Vector3.zero; transform.localRotation = Quaternion.identity; transform.localScale = Vector3.one; return(gameObject); } finally { if (modelScene != oldActiveScene) { UnityEngine.SceneManagement.SceneManager.SetActiveScene(oldActiveScene); } } }
void UpdateSettings(ChiselModel model, GameObjectState state, bool meshIsModified) { #if UNITY_EDITOR Profiler.BeginSample("CheckIfFullMeshNeedsToBeHidden"); // If we need to render partial meshes (where some brushes are hidden) then we should show the full mesh ChiselGeneratedComponentManager.CheckIfFullMeshNeedsToBeHidden(model, this); Profiler.EndSample(); if (meshIsModified) { // Setting the sharedMesh to ensure the meshFilter knows it needs to be updated Profiler.BeginSample("OverrideMesh"); meshFilter.sharedMesh = meshFilter.sharedMesh; Profiler.EndSample(); Profiler.BeginSample("SetDirty"); UnityEditor.EditorUtility.SetDirty(meshFilter); UnityEditor.EditorUtility.SetDirty(model); Profiler.EndSample(); Profiler.BeginSample("SetHasLightmapUVs"); ChiselGeneratedComponentManager.SetHasLightmapUVs(sharedMesh, false); Profiler.EndSample(); Profiler.BeginSample("ClearLightmapData"); ChiselGeneratedComponentManager.ClearLightmapData(state, this); Profiler.EndSample(); } #endif }
private void RemoveContainerGameObject(ChiselModel model) { if (model.generated != null) { model.generated.Destroy(); model.generated = null; } }
internal static bool IsDefaultModel(ChiselModel model) { if (!model) { return(false); } return(model.IsDefaultModel); }
public void AddUnityMeshes(ChiselModel model) { for (int i = 0; i < model.generatedMeshes.Length; i++) { var generatedMesh = model.generatedMeshes[i]; generatedMesh.sharedMesh = ReturnOrRegisterUnityMeshAndIncreaseRefCount(generatedMesh.meshKey, generatedMesh.sharedMesh); } }
internal void DestroyAllRegisteredGeneratedComponentsInModel(ChiselModel model) { GameObject modelGameObject = null; if (model) { modelGameObject = model.gameObject; } __uniqueGameObjects.Clear(); foreach (var components in model.generatedRenderComponents.Values) { foreach (var component in components) { if (component == null) { continue; } if (component.gameObject) { var gameObject = component.gameObject; if (gameObject != modelGameObject) { __uniqueGameObjects.Add(gameObject); } } } } foreach (var components in model.generatedMeshColliders.Values) { foreach (var component in components) { if (component == null) { continue; } if (component.gameObject) { var gameObject = component.gameObject; if (gameObject != modelGameObject) { __uniqueGameObjects.Add(gameObject); } } } } foreach (var gameObject in __uniqueGameObjects) { ChiselObjectUtility.SafeDestroy(gameObject); } __uniqueGameObjects.Clear(); model.generatedRenderComponents.Clear(); model.generatedMeshColliders.Clear(); model.generatedComponents.Clear(); }
public void RemoveUnityMeshes(ChiselModel model) { for (int i = 0; i < model.generatedMeshes.Length; i++) { var generatedMesh = model.generatedMeshes[i]; DecreaseRefCount(generatedMesh.meshKey); generatedMesh.sharedMesh = null; } }
public static void CheckIfFullMeshNeedsToBeHidden(ChiselModel model, ChiselRenderObjects renderable) { var shouldHideMesh = (model.generated.visibilityState != VisibilityState.AllVisible && model.generated.visibilityState != VisibilityState.Unknown); if (renderable.meshRenderer.forceRenderingOff != shouldHideMesh) { renderable.meshRenderer.forceRenderingOff = shouldHideMesh; } }
static List <ChiselGeneratedModelMesh> __allocateGeneratedMeshesTable = new List <ChiselGeneratedModelMesh>(); // static to avoid allocations internal static void UpdateModelMeshDescriptions(ChiselModel model) { var tree = model.Node; if (!tree.Valid) { return; } var meshTypes = ChiselMeshQueryManager.GetMeshQuery(model); var meshDescriptions = tree.GetMeshDescriptions(meshTypes, model.VertexChannelMask); // Make sure we remove all old generated meshes sharedUnityMeshes.DecreaseMeshRefCount(model); // Check if the tree creates *any* meshes if (meshDescriptions == null) { model.generatedMeshes = __emptyGeneratedMeshesTable; componentGenerator.RemoveAllGeneratedComponents(model); if (PostUpdateModel != null) { PostUpdateModel(model); } return; } __allocateGeneratedMeshesTable.Clear(); for (int d = 0; d < meshDescriptions.Length; d++) { var meshDescription = meshDescriptions[d]; // Make sure the meshDescription actually holds a mesh if (meshDescription.vertexCount == 0 || meshDescription.indexCount == 0) { continue; } // Make sure the mesh is valid if (meshDescription.vertexCount >= MaxVertexCount) { Debug.LogError("Mesh has too many vertices (" + meshDescription.vertexCount + " > " + MaxVertexCount + ")"); continue; } // Add the generated mesh to the list __allocateGeneratedMeshesTable.Add(new ChiselGeneratedModelMesh { meshDescription = meshDescription, meshKey = new GeneratedMeshKey(meshDescription) }); } // TODO: compare with existing generated meshes, only rebuild stuff for things that have actually changed model.generatedMeshes = __allocateGeneratedMeshesTable.ToArray(); }
static readonly List <GeneratedMeshContents> __foundContents = new List <GeneratedMeshContents>(); // static to avoid allocations public void Update(ChiselModel model, GameObjectState state, GeneratedMeshDescription[] meshDescriptions, int startIndex, int endIndex) { bool meshIsModified = false; // Retrieve the generatedMeshes and its materials, combine them into a single Unity Mesh/Material array try { for (int i = startIndex; i < endIndex; i++) { ref var meshDescription = ref meshDescriptions[i]; var generatedMeshContents = model.Node.GetGeneratedMesh(meshDescription); if (generatedMeshContents == null) { continue; } if (generatedMeshContents.indices.Length == 0) { generatedMeshContents.Dispose(); continue; } var renderMaterial = ChiselBrushMaterialManager.GetRenderMaterialByInstanceID(meshDescription.surfaceParameter); __foundContents.Add(generatedMeshContents); __foundMaterials.Add(renderMaterial); } triangleBrushes.Clear(); if (__foundContents.Count == 0) { if (sharedMesh.vertexCount > 0) { sharedMesh.Clear(keepVertexLayout: true); } } else { sharedMesh.CopyFrom(__foundContents, triangleBrushes); #if UNITY_EDITOR ChiselGeneratedComponentManager.SetHasLightmapUVs(sharedMesh, false); #endif } if (renderMaterials != null && renderMaterials.Length == __foundMaterials.Count) { __foundMaterials.CopyTo(renderMaterials); } else { renderMaterials = __foundMaterials.ToArray(); } if (meshFilter.sharedMesh != sharedMesh) { meshFilter.sharedMesh = sharedMesh; meshIsModified = true; } meshRenderer.sharedMaterials = renderMaterials; meshRenderer.enabled = sharedMesh.vertexCount > 0; }
internal static void SetActiveModel() { var model = GetSelectedModel(); if (!model) { return; } ChiselModelManager.ActiveModel = model; }
public void Register(ChiselModel model) { // Destroy leftover components in model lookups DestroyAllRegisteredGeneratedComponentsInModel(model); // Rebuild component lookup tables used by generatedMeshes BuildGeneratedComponentLookupTables(model); models.Add(model); }
public void Unregister(ChiselModel model) { // If we removed our model component, we should remove the containers if (!model && model.hierarchyItem.GameObject) { RemoveContainerGameObjectWithUndo(model); } models.Remove(model); }
public void ReuseExistingMeshes(ChiselModel model) { for (int i = 0; i < model.generatedMeshes.Length; i++) { var generatedMesh = model.generatedMeshes[i]; // See if we already know a mesh that has the same description generatedMesh.sharedMesh = ReturnUnityMeshAndIncreaseRefCountIfExists(generatedMesh.meshKey); generatedMesh.needsUpdate = !generatedMesh.sharedMesh; } }
void UpdateSettings(ChiselModel model, GameObjectState state, bool meshIsModified) { #if UNITY_EDITOR // If we need to render partial meshes (where some brushes are hidden) then we should show the full mesh ChiselGeneratedComponentManager.CheckIfFullMeshNeedsToBeHidden(model, this); if (meshIsModified) { ChiselGeneratedComponentManager.ClearLightmapData(state, this); } #endif }
public static GameObjectState Create(ChiselModel model) { var modelGameObject = model.gameObject; return(new GameObjectState { layer = modelGameObject.layer, #if UNITY_EDITOR staticFlags = UnityEditor.GameObjectUtility.GetStaticEditorFlags(modelGameObject) #endif }); }
void UpdateComponentFlags(ChiselModel model, ModelState modelState, Component component, GameObject componentGameObject, Transform componentTransform, string componentName, bool notEditable) { const HideFlags GameObjectHideFlags = HideFlags.NotEditable; const HideFlags TransformHideFlags = HideFlags.NotEditable;// | HideFlags.HideInInspector; if (componentGameObject.name != componentName) { componentGameObject.name = componentName; } // TODO: make components turn off this flag when its gameObject is directly selected? HideFlags ComponentHideFlags = HideFlags.HideInHierarchy | (notEditable ? HideFlags.NotEditable : HideFlags.None); // Avoids MeshCollider showing wireframe // Some components could theoretically just be put on the model itself, so we don't modify any flags then if (componentGameObject == modelState.modelGameObject) { return; } // Make sure we're always a child of the current data container if (componentTransform.parent != modelState.containerTransform) { componentTransform.SetParent(modelState.containerTransform, false); componentTransform.localPosition = Vector3.zero; componentTransform.localRotation = Quaternion.identity; componentTransform.localScale = Vector3.one; } if (componentGameObject.layer != modelState.layer) { componentGameObject.layer = modelState.layer; } if (componentGameObject.hideFlags != GameObjectHideFlags) { componentGameObject.hideFlags = GameObjectHideFlags; } if (componentTransform.hideFlags != TransformHideFlags) { componentTransform.hideFlags = TransformHideFlags; } if (component.hideFlags != ComponentHideFlags) { component.hideFlags = ComponentHideFlags; } #if UNITY_EDITOR var prevStaticFlags = UnityEditor.GameObjectUtility.GetStaticEditorFlags(componentGameObject); if (prevStaticFlags != modelState.staticFlags) { UnityEditor.GameObjectUtility.SetStaticEditorFlags(componentGameObject, modelState.staticFlags); } #endif }
private ChiselColliderComponents CreateColliderComponents(ChiselModel model, GeneratedMeshDescription meshDescription) { var gameObject = CreateComponentGameObject(model, GeneratedMeshColliderName, typeof(MeshCollider)); var colliderComponents = new ChiselColliderComponents { meshCollider = gameObject.GetComponent <MeshCollider>(), gameObject = gameObject, transform = gameObject.transform }; return(colliderComponents); }
public static void UpdateProperties(ChiselModel model, MeshRenderer[] meshRenderers) { if (meshRenderers == null || meshRenderers.Length == 0) { return; } var renderSettings = model.RenderSettings; Profiler.BeginSample("serializedObject"); #if UNITY_EDITOR if (renderSettings.serializedObjectFieldsDirty) { renderSettings.serializedObjectFieldsDirty = false; // These SerializedObject settings can *only* be modified in the inspector, // so we should only be calling this on creation / // when something in inspector changed. // Warning: calling new UnityEditor.SerializedObject with an empty array crashes Unity using (var serializedObject = new UnityEditor.SerializedObject(meshRenderers)) { serializedObject.SetPropertyValue("m_ImportantGI", renderSettings.ImportantGI); serializedObject.SetPropertyValue("m_PreserveUVs", renderSettings.OptimizeUVs); serializedObject.SetPropertyValue("m_IgnoreNormalsForChartDetection", renderSettings.IgnoreNormalsForChartDetection); serializedObject.SetPropertyValue("m_AutoUVMaxDistance", renderSettings.AutoUVMaxDistance); serializedObject.SetPropertyValue("m_AutoUVMaxAngle", renderSettings.AutoUVMaxAngle); serializedObject.SetPropertyValue("m_MinimumChartSize", renderSettings.MinimumChartSize); } } Profiler.EndSample(); #endif Profiler.BeginSample("meshRenderers"); for (int i = 0; i < meshRenderers.Length; i++) { var meshRenderer = meshRenderers[i]; var isRenderable = meshRenderer.shadowCastingMode != ShadowCastingMode.ShadowsOnly; meshRenderer.lightProbeProxyVolumeOverride = !isRenderable ? null : renderSettings.lightProbeProxyVolumeOverride; meshRenderer.probeAnchor = !isRenderable ? null : renderSettings.probeAnchor; meshRenderer.motionVectorGenerationMode = !isRenderable ? MotionVectorGenerationMode.ForceNoMotion : renderSettings.motionVectorGenerationMode; meshRenderer.reflectionProbeUsage = !isRenderable ? ReflectionProbeUsage.Off : renderSettings.reflectionProbeUsage; meshRenderer.lightProbeUsage = !isRenderable ? LightProbeUsage.Off : renderSettings.lightProbeUsage; meshRenderer.allowOcclusionWhenDynamic = renderSettings.allowOcclusionWhenDynamic; meshRenderer.renderingLayerMask = renderSettings.renderingLayerMask; #if UNITY_EDITOR meshRenderer.stitchLightmapSeams = isRenderable && renderSettings.stitchLightmapSeams; meshRenderer.scaleInLightmap = !isRenderable ? 0.0f : renderSettings.scaleInLightmap; meshRenderer.receiveGI = renderSettings.receiveGI; #endif } Profiler.EndSample(); }
public ChiselModel GetOrCreateDefaultModel() { if (!DefaultModel) { DefaultModel = null; if (Scene.IsValid() && Scene.isLoaded) { DefaultModel = ChiselGeneratedComponentManager.CreateDefaultModel(this); } } return(DefaultModel); }
private void RemoveContainerGameObject(ChiselModel model) { if (model.GeneratedDataTransform) { model.GeneratedDataContainer.hideFlags = HideFlags.None; model.GeneratedDataTransform.hideFlags = HideFlags.None; CSGNodeHierarchyManager.ignoreNextChildrenChanged = true; ChiselObjectUtility.SafeDestroy(model.GeneratedDataContainer); CSGNodeHierarchyManager.ignoreNextChildrenChanged = false; model.GeneratedDataContainer = null; model.GeneratedDataTransform = null; } }