コード例 #1
0
        private void UpdateMeshPreview()
        {
            MeshHideAsset source = target as MeshHideAsset;

            if (source.asset == null)
            {
                _meshPreview = null;
                return;
            }

            if (_meshPreview == null)
            {
                _meshPreview = new Mesh();
            }

            UpdateMeshData(source.triangleFlags);

            _meshPreview.Clear();
            _meshPreview.vertices     = _meshData.vertices;
            _meshPreview.subMeshCount = _meshData.subMeshCount;

            for (int i = 0; i < _meshData.subMeshCount; i++)
            {
                _meshPreview.SetTriangles(_meshData.submeshes[i].triangles, i);
            }

            ResetPreviewCamera();
        }
コード例 #2
0
        void OnEnable()
        {
            MeshHideAsset source = target as MeshHideAsset;

            if (source.asset == null)
            {
                return;
            }

            if (_material == null)
            {
                _material = AssetDatabase.GetBuiltinExtraResource <Material>("Default-Diffuse.mat");
            }

            if (_meshPreview == null)
            {
                UpdateMeshPreview();
            }

            if (_previewRenderUtility == null)
            {
                _previewRenderUtility = new PreviewRenderUtility();
                ResetPreviewCamera();
            }
        }
コード例 #3
0
        private void UpdateMeshPreview()
        {
            MeshHideAsset source = target as MeshHideAsset;

            if (source.asset == null)
            {
                _meshPreview = null;
                return;
            }

            if (_meshPreview == null)
            {
                _meshPreview = new Mesh();
#if UMA_32BITBUFFERS
                _meshPreview.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#endif
            }

            UpdateMeshData(source.triangleFlags);

            _meshPreview.Clear();
            _meshPreview.vertices     = _meshData.vertices;
            _meshPreview.subMeshCount = _meshData.subMeshCount;

            for (int i = 0; i < _meshData.subMeshCount; i++)
            {
                _meshPreview.SetTriangles(_meshData.submeshes[i].triangles, i);
            }

            ResetPreviewCamera();
        }
コード例 #4
0
        private bool UpdateSourceAsset(SlotDataAsset newObj)
        {
            MeshHideAsset source = target as MeshHideAsset;
            bool          update = false;

            if (source.asset != null)
            {
                if (EditorUtility.DisplayDialog("Warning", "Setting a new source slot will clear the existing data on this asset!", "OK", "Cancel"))
                {
                    update = true;
                }
            }
            else
            {
                update = true;
            }

            if (update)
            {
                source.AssetSlotName = newObj.slotName;
                source.Initialize();
                UpdateMeshPreview();
                AssetDatabase.SaveAssets();
                EditorUtility.SetDirty(target);
                return(true);
            }
            return(false);
        }
コード例 #5
0
        public override bool HasPreviewGUI()
        {
            MeshHideAsset source = target as MeshHideAsset;

            if (source.asset == null)
            {
                return(false);
            }

            return(true);
        }
コード例 #6
0
        public void UpdateMeshData(BitArray[] triangleFlags)
        {
            if (triangleFlags == null)
            {
                Debug.LogWarning("UpdateMeshData: triangleFlags are null!");
                return;
            }

            if (_meshData == null)
            {
                _meshData = new UMAMeshData();
            }

            MeshHideAsset source = target as MeshHideAsset;

            UMAMeshData sourceData = source.asset.meshData;

            _meshData.submeshes    = new SubMeshTriangles[sourceData.subMeshCount];
            _meshData.subMeshCount = sourceData.subMeshCount;

            bool has_normals = (sourceData.normals != null && sourceData.normals.Length != 0);

            _meshData.vertices = new Vector3[sourceData.vertexCount];
            sourceData.vertices.CopyTo(_meshData.vertices, 0);

            if (has_normals)
            {
                _meshData.normals = new Vector3[sourceData.vertexCount];
                sourceData.normals.CopyTo(_meshData.normals, 0);
            }

            for (int i = 0; i < sourceData.subMeshCount; i++)
            {
                List <int> newTriangles = new List <int>();
                for (int j = 0; j < triangleFlags[i].Count; j++)
                {
                    if (!triangleFlags[i][j])
                    {
                        newTriangles.Add(sourceData.submeshes[i].triangles[(j * 3) + 0]);
                        newTriangles.Add(sourceData.submeshes[i].triangles[(j * 3) + 1]);
                        newTriangles.Add(sourceData.submeshes[i].triangles[(j * 3) + 2]);
                    }
                }
                _meshData.submeshes[i]           = new SubMeshTriangles();
                _meshData.submeshes[i].triangles = new int[newTriangles.Count];
                newTriangles.CopyTo(_meshData.submeshes[i].triangles);
            }
        }
コード例 #7
0
        public void ResetPreviewCamera()
        {
            if (_previewRenderUtility == null)
            {
                return;
            }

            MeshHideAsset source = target as MeshHideAsset;

            _drag = Vector2.zero;
            if (source.asset.meshData.rootBoneHash == UMAUtils.StringToHash("Global"))
            {
                _drag.y = -90;
            }

            _previewRenderUtility.m_Camera.transform.position = new Vector3(0, 0, -6);
            _previewRenderUtility.m_Camera.transform.rotation = Quaternion.identity;
        }
コード例 #8
0
        void OnEnable()
        {
            MeshHideAsset source = target as MeshHideAsset;

            if (thisDynamicRaceLibrary == null)
            {
                UMAContext context = UMAContext.FindInstance();
                if (context != null)
                {
                    thisDynamicRaceLibrary = context.raceLibrary as DynamicRaceLibrary;
                }
            }

            SetRaceLists();

            if (source.asset == null)
            {
                return;
            }

            if (_material == null)
            {
                _material = AssetDatabase.GetBuiltinExtraResource <Material>("Default-Diffuse.mat");
            }

            if (_meshPreview == null)
            {
                UpdateMeshPreview();
            }

            if (_previewRenderUtility == null)
            {
                _previewRenderUtility = new PreviewRenderUtility();
                ResetPreviewCamera();
            }
        }
コード例 #9
0
        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            MeshHideAsset source            = target as MeshHideAsset;
            bool          beginSceneEditing = false;

            //DrawDefaultInspector();
            var obj = EditorGUILayout.ObjectField("SlotDataAsset", source.asset, typeof(SlotDataAsset), false);

            if (obj != null && obj != source.asset)
            {
                source.asset = obj as SlotDataAsset;
                source.Initialize();
                UpdateMeshPreview();
                AssetDatabase.SaveAssets();
                EditorUtility.SetDirty(target);
            }

            //If we had a slotData added and we set it to none, then lets clear everything.
            if (obj == null && source.asset != null)
            {
                source.asset = null;
                source.Initialize();
                AssetDatabase.SaveAssets();
                EditorUtility.SetDirty(target);
            }

            if (source.asset == null)
            {
                EditorGUILayout.HelpBox("No SlotDataAsset set! Begin by adding a SlotDataAsset to the object field above.", MessageType.Error);
            }

            GUILayout.Space(20);
            if (source.TriangleCount > 0)
            {
                EditorGUILayout.LabelField("Triangle Indices Count: " + source.TriangleCount);
                EditorGUILayout.LabelField("Submesh Count: " + source.SubmeshCount);
                EditorGUILayout.LabelField("Hidden Triangle Count: " + source.HiddenCount);
            }
            else
            {
                EditorGUILayout.LabelField("No triangle array found");
            }

            GUILayout.Space(20);
            if (!GeometrySelectorWindow.IsOpen)
            {
                EditorGUI.BeginDisabledGroup(source.asset == null);
                if (GUILayout.Button("Begin Editing", GUILayout.MinHeight(50)))
                {
                    if (source.asset != null)
                    {
                        beginSceneEditing = true;
                    }
                }
                EditorGUI.EndDisabledGroup();
                GUILayout.Space(20);
                GUILayout.Label("Editing will be done in an empty scene.");
                GUILayout.Label("You will be prompted to save the scene");
                GUILayout.Label("if there are any unsaved changes.");
            }
            serializedObject.ApplyModifiedProperties();

            if (beginSceneEditing)
            {
                // This has to happen outside the inspector
                EditorApplication.delayCall += CreateSceneEditObject;
            }
        }
コード例 #10
0
        private void CreateSceneEditObject()
        {
            MeshHideAsset source = target as MeshHideAsset;

            if (source.asset == null)
            {
                return;
            }

            if (GeometrySelectorWindow.IsOpen)
            {
                return;
            }

            if (GeometrySelectorExists())
            {
                GameObject.DestroyImmediate(GameObject.Find("GeometrySelector").gameObject);
            }

            int saveChoice = EditorUtility.DisplayDialogComplex("Open Mesh Hide Editor", "Opening the Mesh Hide Editor will close all scenes and create a new blank scene. Any current scene changes will be lost unless saved.", "Save and Continue", "Continue without saving", "Cancel");

            switch (saveChoice)
            {
            case 0:     // Save and continue
            {
                if (!EditorSceneManager.SaveOpenScenes())
                {
                    return;
                }
                break;
            }

            case 1:     // don't save and continue
                break;

            case 2:     // cancel
                return;
            }

            SceneView sceneView = SceneView.lastActiveSceneView;

            if (sceneView == null)
            {
                EditorUtility.DisplayDialog("Error", "A Scene View must be open and active", "OK");
                return;
            }

            SceneView.lastActiveSceneView.Focus();

            List <GeometrySelector.SceneInfo> currentscenes = new List <GeometrySelector.SceneInfo>();

            for (int i = 0; i < EditorSceneManager.sceneCount; i++)
            {
                Scene sc = EditorSceneManager.GetSceneAt(i);
                GeometrySelector.SceneInfo si = new GeometrySelector.SceneInfo();
                si.path = sc.path;
                si.name = sc.name;
                if (i == 0)
                {
                    // first scene should clear the temp scene.
                    si.mode = OpenSceneMode.Single;
                }
                else
                {
                    si.mode = sc.isLoaded ? OpenSceneMode.Additive : OpenSceneMode.AdditiveWithoutLoading;
                }
                currentscenes.Add(si);
            }

            Scene s = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single);

            EditorSceneManager.SetActiveScene(s);
            GameObject       obj      = EditorUtility.CreateGameObjectWithHideFlags("GeometrySelector", HideFlags.DontSaveInEditor);
            GeometrySelector geometry = obj.AddComponent <GeometrySelector>();

            if (geometry != null)
            {
                Selection.activeGameObject = obj;
                SceneView.lastActiveSceneView.FrameSelected(true);

                geometry.meshAsset     = source;
                geometry.restoreScenes = currentscenes;
                geometry.InitializeFromMeshData(source.asset.meshData);

                //temporary, only works on submesh 0
                geometry.selectedTriangles = new BitArray(source.triangleFlags[0]);

                geometry.UpdateSelectionMesh();
                SceneView.FrameLastActiveSceneView();
                SceneView.lastActiveSceneView.FrameSelected();
            }
        }
コード例 #11
0
        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            MeshHideAsset source            = target as MeshHideAsset;
            bool          beginSceneEditing = false;

            //DrawDefaultInspector();
            SlotDataAsset obj = EditorGUILayout.ObjectField("SlotDataAsset", source.asset, typeof(SlotDataAsset), false) as SlotDataAsset;

            if (obj != source.asset)
            {
                source.asset = obj as SlotDataAsset;
                if (_autoInitialize)
                {
                    UpdateSourceAsset(obj);
                }
            }
            EditorGUILayout.LabelField("Slot Name", source.AssetSlotName.ToString());
            if (source.HasReference)
            {
                EditorGUILayout.HelpBox("Warning: This Mesh Hide Asset contains a reference. It should be freed so the referenced asset is not included in the build.", MessageType.Warning);
                if (GUILayout.Button("Free Reference"))
                {
                    source.FreeReference();
                    EditorUtility.SetDirty(source);
                    AssetDatabase.SaveAssets();
                }
            }

            _autoInitialize = EditorGUILayout.Toggle(new GUIContent("AutoInitialize (recommended)", "Checking this will auto initialize the MeshHideAsset when a slot is added (recommended).  " +
                                                                    "For users that are rebuilding slots that don't change the geometry, the slot reference will be lost but can be reset without losing the existing MeshHide information by unchecking this."), _autoInitialize);

            if (source.asset == null)
            {
                EditorGUILayout.HelpBox("No SlotDataAsset set! Begin by adding a SlotDataAsset to the object field above.", MessageType.Error);
            }


            //Race Selector here
            GUILayout.Space(20);
            selectedRaceIndex = EditorGUILayout.Popup("Select Base Slot by Race", selectedRaceIndex, foundRaceNames.ToArray());
            if (selectedRaceIndex <= 0)
            {
                EditorGUILayout.HelpBox("Quick selection of base slots by race. This is not needed to create a mesh hide asset, any slot can be used.", MessageType.Info);
            }
            else
            {
                UMAData.UMARecipe baseRecipe = new UMAData.UMARecipe();
                foundRaces[selectedRaceIndex].baseRaceRecipe.Load(baseRecipe, UMAContextBase.Instance);

                foreach (SlotData sd in baseRecipe.slotDataList)
                {
                    if (sd != null && sd.asset != null)
                    {
                        if (GUILayout.Button(string.Format("{0} ({1})", sd.asset.name, sd.slotName)))
                        {
                            if (UpdateSourceAsset(sd.asset))
                            {
                                selectedRaceIndex = 0;
                            }
                        }
                    }
                }
            }

            GUILayout.Space(20);
            if (source.TriangleCount > 0)
            {
                EditorGUILayout.LabelField("Triangle Indices Count: " + source.TriangleCount);
                EditorGUILayout.LabelField("Submesh Count: " + source.SubmeshCount);
                EditorGUILayout.LabelField("Hidden Triangle Count: " + source.HiddenCount);
            }
            else
            {
                EditorGUILayout.LabelField("No triangle array found");
            }

            GUILayout.Space(20);
            if (!GeometrySelectorWindow.IsOpen)
            {
                EditorGUI.BeginDisabledGroup(source.asset == null);
                if (GUILayout.Button("Begin Editing", GUILayout.MinHeight(50)))
                {
                    if (source.asset != null)
                    {
                        beginSceneEditing = true;
                    }
                }
                EditorGUI.EndDisabledGroup();
                GUILayout.Space(20);
                GUILayout.Label("Editing will be done in an empty scene.");
                GUILayout.Label("You will be prompted to save the scene");
                GUILayout.Label("if there are any unsaved changes.");
            }
            serializedObject.ApplyModifiedProperties();

            if (beginSceneEditing)
            {
                // This has to happen outside the inspector
                EditorApplication.delayCall += CreateSceneEditObject;
            }
        }
コード例 #12
0
        public override void OnInspectorGUI()
        {
            EditorGUILayout.LabelField("Mesh Selector Utilities", EditorStyles.largeLabel, GUILayout.MaxHeight(25));
            scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUIStyle.none);
            GUILayout.Space(20);

            EditorGUILayout.BeginHorizontal();
            bool newNormals = EditorGUILayout.Toggle("Visualize Normals", _Source.visualizeNormals);

            if (newNormals != _Source.visualizeNormals)
            {
                _Source.visualizeNormals = newNormals;
                SceneView.RepaintAll();
            }
            Color32 newNormalColor = EditorGUILayout.ColorField(_Source.normalsColor);

            if (!newNormalColor.Equals(_Source.normalsColor))
            {
                _Source.normalsColor = newNormalColor;
                SceneView.RepaintAll();
            }
            EditorGUILayout.EndHorizontal();
            float newNormalLength = EditorGUILayout.Slider("Normals Length", _Source.normalsLength, 0.01f, 1.5f);

            if (newNormalLength != _Source.normalsLength)
            {
                _Source.normalsLength = newNormalLength;
                SceneView.RepaintAll();
            }

            GUILayout.Space(20);
            EditorGUILayout.LabelField(new GUIContent("Occlusion Slot (Optional)", "Use this mesh to attempt to automatically detect occluded triangles"));
            EditorGUILayout.BeginHorizontal();
            SlotDataAsset newOccluderSlotData = (SlotDataAsset)EditorGUILayout.ObjectField(_OccluderSlotData, typeof(SlotDataAsset), false);
            MeshHideAsset newOccluderMeshHide = (MeshHideAsset)EditorGUILayout.ObjectField(_OccluderMeshHide, typeof(MeshHideAsset), false);

            if (GUILayout.Button("Clear", GUILayout.MaxWidth(60)))
            {
                _OccluderSlotData     = null;
                newOccluderSlotData   = null;
                _OccluderMeshHide     = null;
                newOccluderMeshHide   = null;
                _Source.occlusionMesh = null;
                SceneView.RepaintAll();
            }
            if (newOccluderSlotData != _OccluderSlotData)
            {
                _OccluderSlotData   = newOccluderSlotData;
                _OccluderMeshHide   = null;
                newOccluderMeshHide = null;
                if (_OccluderSlotData != null)
                {
                    _Source.UpdateOcclusionMesh(_OccluderSlotData.meshData, _occluderOffset, _occluderPosition, _occluderRotation, _occluderScale);
                }
                else
                {
                    _Source.occlusionMesh = null;
                }
                SceneView.RepaintAll();
            }
            if (newOccluderMeshHide != _OccluderMeshHide)
            {
                if (newOccluderMeshHide == _Source.meshAsset)
                {
                    EditorUtility.DisplayDialog("Error", "Can not select the same MeshHideAsset currently being edited!", "OK");
                }
                else
                {
                    _OccluderMeshHide   = newOccluderMeshHide;
                    _OccluderSlotData   = null;
                    newOccluderSlotData = null;
                    if (_OccluderMeshHide != null && _OccluderMeshHide != _Source.meshAsset)
                    {
                        _Source.UpdateOcclusionMesh(_OccluderMeshHide, _occluderOffset, _occluderPosition, _occluderRotation, _occluderScale);
                    }
                    else
                    {
                        _Source.occlusionMesh = null;
                    }
                    SceneView.RepaintAll();
                }
            }
            EditorGUILayout.EndHorizontal();

            EditorGUI.BeginDisabledGroup(_Source.occlusionMesh == null);
            bool changed = false;

            Color32 newOcclusionColor = EditorGUILayout.ColorField("Occlusion Mesh Color", _Source.occlusionColor);

            if (!newOcclusionColor.Equals(_Source.occlusionColor))
            {
                _Source.occlusionColor = newOcclusionColor;
                SceneView.RepaintAll();
            }
            bool newWireframe = EditorGUILayout.Toggle("Occlusion Mesh Wireframe", _Source.occlusionWireframe);

            if (newWireframe != _Source.occlusionWireframe)
            {
                _Source.occlusionWireframe = newWireframe;
                SceneView.RepaintAll();
            }

            float newOffset = EditorGUILayout.Slider(new GUIContent("Normal Offset", "Distance along the normal to offset each vertex of the occlusion mesh"), _occluderOffset, -0.1f, 0.25f);

            if (!Mathf.Approximately(newOffset, _occluderOffset))
            {
                _occluderOffset = newOffset;
                changed         = true;
            }

            Vector3 newPosition = EditorGUILayout.Vector3Field(new GUIContent("Position", "Offset the position of the occluder"), _occluderPosition);

            if (newPosition != _occluderPosition)
            {
                _occluderPosition = newPosition;
                changed           = true;
            }

            Vector3 newRotation = EditorGUILayout.Vector3Field(new GUIContent("Rotation", "Offset the rotation (degrees) of the occluder"), _occluderRotation);

            if (newRotation != _occluderRotation)
            {
                _occluderRotation = newRotation;
                changed           = true;
            }

            Vector3 newScale = EditorGUILayout.Vector3Field(new GUIContent("Scale", "Offset the scale of the occluder"), _occluderScale);

            if (newScale != _occluderScale)
            {
                _occluderScale = newScale;
                changed        = true;
            }

            bothDirections = EditorGUILayout.Toggle(new GUIContent("RayCast Both Directions",
                                                                   "Determines whether to raycast only outward along the normal from the source mesh or in both directions.  Both directions can be helpful if the occlusion slot is close to the surface of the source mesh or even slightly under it."),
                                                    bothDirections);

            if (changed)
            {
                if (_OccluderSlotData)
                {
                    _Source.UpdateOcclusionMesh(_OccluderSlotData.meshData, _occluderOffset, _occluderPosition, _occluderRotation, _occluderScale);
                }
                if (_OccluderMeshHide)
                {
                    _Source.UpdateOcclusionMesh(_OccluderMeshHide, _occluderOffset, _occluderPosition, _occluderRotation, _occluderScale);
                }
            }

            if (GUILayout.Button(new GUIContent("Raycast Hidden Faces", "Warning! This will clear the current selection.")))
            {
                RaycastHide(bothDirections);
            }
            EditorGUI.EndDisabledGroup();

            GUILayout.Space(20);
            textureMap = EditorGUILayout.ObjectField("Set From Texture Map", textureMap, typeof(Texture2D), false) as Texture2D;
            if (GUILayout.Button("Calculate occlusion from texture."))
            {
                if (_Source != null)
                {
                    if (textureMap == null)
                    {
                        EditorUtility.DisplayDialog("Warning", "A readable texture must be selected before processing.", "OK");
                    }
                    else
                    {
                        _Source.UpdateFromTexture(textureMap);
                    }
                }
            }

            GUILayout.Space(20);
            if (GUILayout.Button(new GUIContent("View UV Layout", "Brings up a window displaying the uv layout of the currently selected object and export to texture options.")))
            {
                GeometryUVEditorWindow.Init(_Source);
            }
            GUILayout.EndScrollView();
        }
コード例 #13
0
ファイル: UMASimpleLOD.cs プロジェクト: argallegos/UMA-test
        private bool ProcessRecipe(int currentLevel)
        {
            bool changedSlots = false;

            if (_umaData.umaRecipe.slotDataList == null)
            {
                return(false);
            }

            for (int i = 0; i < _umaData.umaRecipe.slotDataList.Length; i++)
            {
                var slot = _umaData.umaRecipe.slotDataList[i];
                if (slot != null)
                {
                    var slotName = slot.slotName;
                    var lodIndex = slotName.IndexOf("_LOD");
                    if (lodIndex >= 0)
                    {
                        slotName = slotName.Substring(0, lodIndex);
                    }
                    if (currentLevel - lodOffset >= 0 && swapSlots)
                    {
                        slotName = string.Format("{0}_LOD{1}", slotName, currentLevel - lodOffset);
                    }

                    bool slotFound = false;
                    for (int k = (currentLevel - lodOffset); k >= 0; k--)
                    {
                        if (slotName != slot.slotName && UMAContext.Instance.HasSlot(slotName))
                        {
                            _umaData.umaRecipe.slotDataList[i] = UMAContext.Instance.InstantiateSlot(slotName, slot.GetOverlayList());
                            slotFound    = true;
                            changedSlots = true;
                            break;
                        }
                    }
                    //If slot still not found when searching down lods, then let's trying searching up lods
                    if (!slotFound)
                    {
                        for (int k = (currentLevel - lodOffset) + 1; k <= maxLOD; k++)
                        {
                            if (slotName != slot.slotName && UMAContext.Instance.HasSlot(slotName))
                            {
                                _umaData.umaRecipe.slotDataList[i] = UMAContext.Instance.InstantiateSlot(slotName, slot.GetOverlayList());
                                slotFound    = true;
                                changedSlots = true;
                                break;
                            }
                        }
                    }
                }
            }

            //Reprocess mesh hide assets
            //Eventually, make this a function in DCA (UpdateMeshHideMasks) and replace correspond code in DCA.LoadCharacter too
            if (_avatar != null && changedSlots)
            {
                foreach (SlotData sd in _umaData.umaRecipe.slotDataList)
                {
                    if (_avatar.MeshHideDictionary.ContainsKey(sd.asset))
                    {   //If this slotDataAsset is found in the MeshHideDictionary then we need to supply the SlotData with the bitArray.
                        sd.meshHideMask = MeshHideAsset.GenerateMask(_avatar.MeshHideDictionary[sd.asset]);
                    }
                }
            }
#if UNITY_EDITOR
            UnityEditor.EditorUtility.SetDirty(_umaData);
#endif
            return(changedSlots);
        }
コード例 #14
0
        private void CreateSceneEditObject()
        {
            bool          focusObject = true;
            MeshHideAsset source      = target as MeshHideAsset;

            if (source.asset == null)
            {
                return;
            }

            if (GeometrySelectorWindow.IsOpen)
            {
                return;
            }

            if (GeometrySelectorExists())
            {
                GameObject.DestroyImmediate(GameObject.Find("GeometrySelector").gameObject);
            }

            bool hasDirtyScenes = false;

            for (int i = 0; i < EditorSceneManager.sceneCount; i++)
            {
                Scene sc = EditorSceneManager.GetSceneAt(i);
                if (sc.isDirty)
                {
                    hasDirtyScenes = true;
                }
            }
            if (hasDirtyScenes)
            {
                int saveChoice = EditorUtility.DisplayDialogComplex("Modified scenes detected", "Opening the Mesh Hide Editor will close all scenes and create a new blank scene. Any current scene changes will be lost unless saved.", "Save and Continue", "Continue without saving", "Cancel");

                switch (saveChoice)
                {
                case 0:                         // Save and continue
                {
                    if (!EditorSceneManager.SaveOpenScenes())
                    {
                        return;
                    }
                    break;
                }

                case 1:                         // don't save and continue
                    break;

                case 2:                         // cancel
                    return;
                }
            }

            SceneView sceneView = SceneView.lastActiveSceneView;

            if (sceneView == null)
            {
                EditorUtility.DisplayDialog("Error", "A Scene View must be open and active", "OK");
                return;
            }

            SceneView.lastActiveSceneView.Focus();

            List <GeometrySelector.SceneInfo> currentscenes = new List <GeometrySelector.SceneInfo>();

            for (int i = 0; i < EditorSceneManager.sceneCount; i++)
            {
                Scene sc = EditorSceneManager.GetSceneAt(i);
                GeometrySelector.SceneInfo si = new GeometrySelector.SceneInfo();
                si.path = sc.path;
                si.name = sc.name;
                if (i == 0)
                {
                    // first scene should clear the temp scene.
                    si.mode = OpenSceneMode.Single;
                }
                else
                {
                    si.mode = sc.isLoaded ? OpenSceneMode.Additive : OpenSceneMode.AdditiveWithoutLoading;
                }
                currentscenes.Add(si);
            }

#if UNITY_2019_1_OR_NEWER
            Scene s = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
#else
            Scene s = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single);
#endif
            EditorSceneManager.SetActiveScene(s);
            GameObject       obj      = EditorUtility.CreateGameObjectWithHideFlags("GeometrySelector", HideFlags.DontSaveInEditor);
            GeometrySelector geometry = obj.AddComponent <GeometrySelector>();

            // Restore the camera position.
            string CamKey = source.name + "_MHA_Cam";
            if (EditorPrefs.HasKey(CamKey))
            {
                string   xform = EditorPrefs.GetString(CamKey);
                CamSaver cs    = CamSaver.FromString(xform);
                sceneView.camera.transform.position      = cs.position;
                sceneView.camera.transform.localRotation = cs.rotation;
                focusObject = false;
            }

            if (geometry != null)
            {
                Selection.activeGameObject = obj;
                if (focusObject)
                {
                    SceneView.lastActiveSceneView.FrameSelected(true);
                }

                // sceneView.camera.transform;
                geometry.meshAsset        = source;
                geometry.restoreScenes    = currentscenes;
                geometry.currentSceneView = sceneView;

#if UNITY_2019_1_OR_NEWER
                geometry.SceneviewLightingState = sceneView.sceneLighting;
                sceneView.sceneLighting         = false;
#else
                geometry.SceneviewLightingState = sceneView.m_SceneLighting;
                sceneView.m_SceneLighting       = false;
#endif
                geometry.InitializeFromMeshData(source.asset.meshData);


                geometry.selectedTriangles = new BitArray(source.triangleFlags[source.asset.subMeshIndex]);

                geometry.UpdateSelectionMesh();
                if (focusObject)
                {
                    SceneView.FrameLastActiveSceneView();
                    SceneView.lastActiveSceneView.FrameSelected();
                }
            }
        }