private ChiselRenderComponents CreateRenderComponents(ChiselModel model, GeneratedMeshDescription meshDescription)
        {
            var gameObject       = CreateComponentGameObject(model, GeneratedMeshRendererName, typeof(MeshFilter), typeof(MeshRenderer));
            var renderComponents = new ChiselRenderComponents
            {
                meshFilter   = gameObject.GetComponent <MeshFilter>(),
                meshRenderer = gameObject.GetComponent <MeshRenderer>(),
                gameObject   = gameObject,
                transform    = gameObject.transform
            };

            return(renderComponents);
        }
        // NOTE: assumes that if a renderComponents are passed to this, they are -valid-
        //		 do any checking outside of this method, and make sure everything that
        //		 needs to be cleaned up, IS cleaned up
        private bool UpdateOrCreateRenderComponents(ChiselModel model, ModelState modelState, GeneratedMeshDescription meshDescription, ref ChiselRenderComponents renderComponents)
        {
            bool updated = false;

            if (renderComponents == null)
            {
                renderComponents = CreateRenderComponents(model, meshDescription);
                updated          = true;
            }

            UpdateRenderComponents(model, modelState, meshDescription, renderComponents);
            UpdateComponentFlags(model, modelState, renderComponents.meshRenderer, renderComponents.gameObject, renderComponents.transform, GeneratedMeshRendererName, notEditable: true);
            if (!renderComponents.meshRenderer.enabled)
            {
                renderComponents.meshRenderer.enabled = true;
            }
            return(updated);
        }
        private void UpdateRenderComponents(ChiselModel model, ModelState modelState, GeneratedMeshDescription meshDescription, ChiselRenderComponents renderComponents)
        {
            var meshRenderer = renderComponents.meshRenderer;

#if UNITY_EDITOR
            updateMeshRenderers.Add(meshRenderer);
#endif

            var query = meshDescription.meshQuery.LayerQuery;
            meshRenderer.receiveShadows = ((query & LayerUsageFlags.ReceiveShadows) == LayerUsageFlags.ReceiveShadows);
            switch (query & (LayerUsageFlags.Renderable | LayerUsageFlags.CastShadows))
            {
            case LayerUsageFlags.None:                              meshRenderer.enabled = false; break;

            case LayerUsageFlags.Renderable:                meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;                   meshRenderer.enabled = true; break;

            case LayerUsageFlags.CastShadows:               meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;   meshRenderer.enabled = true; break;

            case LayerUsageFlags.RenderCastShadows: meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;                    meshRenderer.enabled = true; break;
            }
#if UNITY_EDITOR
            UnityEditor.EditorUtility.SetSelectedRenderState(meshRenderer, UnityEditor.EditorSelectedRenderState.Hidden);
#endif
        }
        private static void GenerateLightmapUVsForInstance(ChiselModel model, ChiselRenderComponents renderComponents, Mesh generatedMesh)
        {
            // Avoid light mapping multiple times, when the same mesh is used on multiple MeshRenderers
            if (ChiselSharedUnityMeshManager.HasLightmapUVs(generatedMesh))
            {
                return;
            }

            if (renderComponents == null ||
                !renderComponents.meshFilter ||
                !renderComponents.meshRenderer)
            {
                return;
            }

            var uvSettings = model.UVGenerationSettings;
            var param      = new UnityEditor.UnwrapParam();

            UnityEditor.UnwrapParam.SetDefaults(out param);
            param.angleError = Mathf.Clamp(uvSettings.angleError, SerializableUnwrapParam.minAngleError, SerializableUnwrapParam.maxAngleError);
            param.areaError  = Mathf.Clamp(uvSettings.areaError, SerializableUnwrapParam.minAreaError, SerializableUnwrapParam.maxAreaError);
            param.hardAngle  = Mathf.Clamp(uvSettings.hardAngle, SerializableUnwrapParam.minHardAngle, SerializableUnwrapParam.maxHardAngle);
            param.packMargin = Mathf.Clamp(uvSettings.packMarginPixels, SerializableUnwrapParam.minPackMargin, SerializableUnwrapParam.maxPackMargin) / 256.0f;

            var oldVertices = generatedMesh.vertices;

            if (oldVertices.Length == 0)
            {
                return;
            }

            // TODO: can we avoid creating a temporary Mesh? if not; make sure CSGSharedUnityMeshManager is handled correctly

            var oldUV        = generatedMesh.uv;
            var oldNormals   = generatedMesh.normals;
            var oldTangents  = generatedMesh.tangents;
            var oldTriangles = generatedMesh.triangles;

            var tempMesh = new Mesh
            {
                vertices  = oldVertices,
                normals   = oldNormals,
                uv        = oldUV,
                tangents  = oldTangents,
                triangles = oldTriangles
            };

            var lightmapGenerationTime = UnityEditor.EditorApplication.timeSinceStartup;

            UnityEditor.Unwrapping.GenerateSecondaryUVSet(tempMesh, param);
            lightmapGenerationTime = UnityEditor.EditorApplication.timeSinceStartup - lightmapGenerationTime;

            // TODO: make a nicer text here
            Debug.Log("Generating lightmap UVs (by Unity) for the mesh '" + generatedMesh.name + "' of the Model named \"" + model.name + "\"\n" +
                      "\tUV generation in " + (lightmapGenerationTime * 1000) + " ms\n", model);

            // Modify the original mesh, since it is shared
            generatedMesh.uv2 = tempMesh.uv2;   // static lightmaps
            generatedMesh.uv3 = tempMesh.uv3;   // real-time lightmaps
            ChiselSharedUnityMeshManager.SetHasLightmapUVs(generatedMesh, true);

            renderComponents.meshFilter.sharedMesh = null;
            renderComponents.meshFilter.sharedMesh = generatedMesh;
            UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(model.gameObject.scene);
        }