Пример #1
0
        private void GenerateMapMagicTerrainSettings()
        {
            if (terrainSettings)
            {
                return;
            }

            terrainSettings      = ScriptableObject.CreateInstance <GPUInstancerTerrainSettings>();
            terrainSettings.name = "GPUI_MapMagic_" + mapMagicInstance.gens.name + "_" + mapMagicInstance.gens.GetInstanceID();
            terrainSettings.maxDetailDistance      = mapMagicInstance.detailDistance;
            terrainSettings.maxTreeDistance        = mapMagicInstance.treeDistance;
            terrainSettings.detailDensity          = mapMagicInstance.detailDensity;
            terrainSettings.healthyDryNoiseTexture = Resources.Load <Texture2D>(GPUInstancerConstants.NOISE_TEXTURES_PATH + GPUInstancerConstants.DEFAULT_HEALTHY_DRY_NOISE);
            terrainSettings.windWaveNormalTexture  = Resources.Load <Texture2D>(GPUInstancerConstants.NOISE_TEXTURES_PATH + GPUInstancerConstants.DEFAULT_WIND_WAVE_NOISE);

#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                string assetPath = GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_TERRAIN_PATH + terrainSettings.name + ".asset";

                if (!System.IO.Directory.Exists(GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_TERRAIN_PATH))
                {
                    System.IO.Directory.CreateDirectory(GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_TERRAIN_PATH);
                }

                AssetDatabase.CreateAsset(terrainSettings, assetPath);

                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            }
#endif
        }
Пример #2
0
        private GPUInstancerTerrainSettings GenerateTerrainSettings(Terrain terrain, GameObject gameObject)
        {
#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                string[] guids = AssetDatabase.FindAssets("t:GPUInstancerTerrainSettings");
                for (int i = 0; i < guids.Length; i++)
                {
                    GPUInstancerTerrainSettings ts = AssetDatabase.LoadAssetAtPath <GPUInstancerTerrainSettings>(AssetDatabase.GUIDToAssetPath(guids[i]));
                    if (ts != null && ts.terrainDataInstanceID == terrain.terrainData.GetInstanceID())
                    {
                        prototypeList.Clear();
                        if (this is GPUInstancerDetailManager)
                        {
                            GPUInstancerUtility.SetPrototypeListFromAssets(ts, prototypeList, typeof(GPUInstancerDetailPrototype));
                        }
                        return(ts);
                    }
                }
            }
#endif

            GPUInstancerTerrainSettings terrainSettings = ScriptableObject.CreateInstance <GPUInstancerTerrainSettings>();
            terrainSettings.name = (string.IsNullOrEmpty(terrain.terrainData.name) ? terrain.gameObject.name : terrain.terrainData.name) + "_" + terrain.terrainData.GetInstanceID();
            terrainSettings.terrainDataInstanceID  = terrain.terrainData.GetInstanceID();
            terrainSettings.maxDetailDistance      = terrain.detailObjectDistance;
            terrainSettings.maxTreeDistance        = terrain.treeDistance;
            terrainSettings.detailDensity          = terrain.detailObjectDensity;
            terrainSettings.healthyDryNoiseTexture = Resources.Load <Texture2D>(GPUInstancerConstants.NOISE_TEXTURES_PATH + GPUInstancerConstants.DEFAULT_HEALTHY_DRY_NOISE);
            terrainSettings.windWaveNormalTexture  = Resources.Load <Texture2D>(GPUInstancerConstants.NOISE_TEXTURES_PATH + GPUInstancerConstants.DEFAULT_WIND_WAVE_NOISE);

#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                string assetPath = GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_TERRAIN_PATH + terrainSettings.name + ".asset";

                if (!System.IO.Directory.Exists(GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_TERRAIN_PATH))
                {
                    System.IO.Directory.CreateDirectory(GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_TERRAIN_PATH);
                }

                AssetDatabase.CreateAsset(terrainSettings, assetPath);

                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            }
#endif
            return(terrainSettings);
        }
Пример #3
0
        public virtual void SetupManagerWithTerrain(Terrain terrain)
        {
#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                Undo.RecordObject(this, "Changed GPUInstancer Terrain Data for " + gameObject);
                if (_terrain != null && _terrain.GetComponent <GPUInstancerTerrainProxy>() != null)
                {
                    Undo.RecordObject(_terrain.gameObject, "Removed GPUInstancerTerrainProxy component");
                    DestroyImmediate(_terrain.GetComponent <GPUInstancerTerrainProxy>());
                }
            }
#endif

            _terrain = terrain;

            if (terrain != null)
            {
                if (terrainSettings != null)
                {
                    string guid = GPUInstancerUtility.GetAssetGUID(terrain.terrainData);
                    if (!string.IsNullOrEmpty(guid) && guid == terrainSettings.terrainDataGUID)
                    {
                        return;
                    }
                    else
                    {
                        prototypeList.Clear();
                        //RemoveTerrainSettings(terrainSettings);
                        terrainSettings = null;
                    }
                }
                terrainSettings = GenerateTerrainSettings(terrain, gameObject);
                GeneratePrototypes(false);
                if (!Application.isPlaying)
                {
                    AddProxyToTerrain();
                }
            }
            else
            {
                prototypeList.Clear();
                //RemoveTerrainSettings(terrainSettings);
                terrainSettings = null;
            }
        }
Пример #4
0
        private static void RemoveTerrainSettings(GPUInstancerTerrainSettings terrainSettings)
        {
#if UNITY_EDITOR
            AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(terrainSettings));
#endif
        }
Пример #5
0
        private GPUInstancerTerrainSettings GenerateTerrainSettings(Terrain terrain, GameObject gameObject)
        {
#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                string[] guids = AssetDatabase.FindAssets("t:GPUInstancerTerrainSettings");
                string   guid  = GPUInstancerUtility.GetAssetGUID(terrain.terrainData);
                for (int i = 0; i < guids.Length; i++)
                {
                    GPUInstancerTerrainSettings ts = AssetDatabase.LoadAssetAtPath <GPUInstancerTerrainSettings>(AssetDatabase.GUIDToAssetPath(guids[i]));
                    if (ts != null && !string.IsNullOrEmpty(guid) && ts.terrainDataGUID == guid)
                    {
                        prototypeList.Clear();
                        if (this is GPUInstancerDetailManager)
                        {
                            List <GPUInstancerPrototype> detailPrototypeList = new List <GPUInstancerPrototype>();
                            GPUInstancerUtility.SetPrototypeListFromAssets(ts, detailPrototypeList, typeof(GPUInstancerDetailPrototype));
                            for (int p = 0; p < detailPrototypeList.Count; p++)
                            {
                                foreach (GPUInstancerDetailPrototype detailPrototype in detailPrototypeList)
                                {
                                    if (detailPrototype.prototypeIndex == p)
                                    {
                                        prototypeList.Add(detailPrototype);
                                        break;
                                    }
                                }
                            }
                        }
                        if (this is GPUInstancerTreeManager)
                        {
                            List <GPUInstancerPrototype> treePrototypeList = new List <GPUInstancerPrototype>();
                            GPUInstancerUtility.SetPrototypeListFromAssets(ts, treePrototypeList, typeof(GPUInstancerTreePrototype));
                            for (int p = 0; p < treePrototypeList.Count; p++)
                            {
                                foreach (GPUInstancerTreePrototype treePrototype in treePrototypeList)
                                {
                                    if (treePrototype.prototypeIndex == p)
                                    {
                                        prototypeList.Add(treePrototype);
                                        break;
                                    }
                                }
                            }
                        }
                        return(ts);
                    }
                }
            }
#endif

            GPUInstancerTerrainSettings terrainSettings = ScriptableObject.CreateInstance <GPUInstancerTerrainSettings>();
            terrainSettings.name                   = (string.IsNullOrEmpty(terrain.terrainData.name) ? terrain.gameObject.name : terrain.terrainData.name) + "_" + terrain.terrainData.GetInstanceID();
            terrainSettings.terrainDataGUID        = GPUInstancerUtility.GetAssetGUID(terrain.terrainData);
            terrainSettings.maxDetailDistance      = terrain.detailObjectDistance;
            terrainSettings.maxTreeDistance        = terrain.treeDistance;
            terrainSettings.detailDensity          = terrain.detailObjectDensity;
            terrainSettings.healthyDryNoiseTexture = Resources.Load <Texture2D>(GPUInstancerConstants.NOISE_TEXTURES_PATH + GPUInstancerConstants.DEFAULT_HEALTHY_DRY_NOISE);
            terrainSettings.windWaveNormalTexture  = Resources.Load <Texture2D>(GPUInstancerConstants.NOISE_TEXTURES_PATH + GPUInstancerConstants.DEFAULT_WIND_WAVE_NOISE);

#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                string assetPath = GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_TERRAIN_PATH + terrainSettings.name + ".asset";

                // If there is already a file with the same name, change file name
                int counter = 2;
                while (System.IO.File.Exists(assetPath))
                {
                    assetPath = GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_TERRAIN_PATH + terrainSettings.name + "_" + counter + ".asset";
                    counter++;
                }

                if (!System.IO.Directory.Exists(GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_TERRAIN_PATH))
                {
                    System.IO.Directory.CreateDirectory(GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_TERRAIN_PATH);
                }

                AssetDatabase.CreateAsset(terrainSettings, assetPath);

                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            }
#endif
            return(terrainSettings);
        }
        public static void DrawGPUInstancerPrototypeInfo(GPUInstancerPrototype selectedPrototype, UnityAction <string> DrawHelpText, UnityEngine.Object component, UnityAction OnEditorDataChanged,
                                                         GPUInstancerShaderBindings shaderBindings, GPUInstancerEditorSimulator simulator, GPUInstancerTerrainSettings terrainSettings, int detailLayer)
        {
            GPUInstancerDetailPrototype prototype = (GPUInstancerDetailPrototype)selectedPrototype;

            EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);
            GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_detailProperties, GPUInstancerEditorConstants.Styles.boldLabel);

            EditorGUI.BeginChangeCheck();

            prototype.detailDensity = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_detailDensity, prototype.detailDensity, 0.0f, terrainSettings.detailDensity);
            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_detailDensity);
            prototype.detailScale = EditorGUILayout.Vector4Field(GPUInstancerEditorConstants.TEXT_detailScale, prototype.detailScale);
            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_detailScale);

            prototype.noiseSpread = EditorGUILayout.FloatField(GPUInstancerEditorConstants.TEXT_noiseSpread, prototype.noiseSpread);
            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_noiseSpread);

            prototype.useCustomHealthyDryNoiseTexture = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useCustomHealthyDryNoiseTexture, prototype.useCustomHealthyDryNoiseTexture);
            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useCustomHealthyDryNoiseTexture);
            if (prototype.useCustomHealthyDryNoiseTexture)
            {
                prototype.healthyDryNoiseTexture = (Texture2D)EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_healthyDryNoiseTexture, prototype.healthyDryNoiseTexture, typeof(Texture2D), false);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_healthyDryNoiseTexture);
            }

            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObject(component, "Editor data changed.");
                if (OnEditorDataChanged != null)
                {
                    OnEditorDataChanged();
                }
                EditorUtility.SetDirty(prototype);
            }

            EditorGUI.BeginChangeCheck();
            if (!prototype.usePrototypeMesh)
            {
                prototype.useCustomMaterialForTextureDetail = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useCustomMaterialForTextureDetail, prototype.useCustomMaterialForTextureDetail);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useCustomMaterialForTextureDetail);
                if (prototype.useCustomMaterialForTextureDetail)
                {
                    prototype.textureDetailCustomMaterial = (Material)EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_textureDetailCustomMaterial, prototype.textureDetailCustomMaterial, typeof(Material), false);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_textureDetailCustomMaterial);
                    prototype.isBillboard = false;
                }
                else
                {
                    prototype.textureDetailCustomMaterial = null;
                }
            }

            EditorGUILayout.EndVertical();

            if (!prototype.usePrototypeMesh && !prototype.isBillboard)
            {
                EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);
                GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_crossQuads, GPUInstancerEditorConstants.Styles.boldLabel);

                prototype.useCrossQuads = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_crossQuads, prototype.useCrossQuads);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_crossQuads);

                if (prototype.useCrossQuads)
                {
                    prototype.quadCount = EditorGUILayout.IntSlider(GPUInstancerEditorConstants.TEXT_quadCount, prototype.quadCount, 2, 4);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_quadCount);

                    if (!prototype.useCustomMaterialForTextureDetail)
                    {
                        prototype.billboardDistance = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_billboardDistance, prototype.billboardDistance, 0.5f, 1f);
                        DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardDistance);
                        prototype.billboardDistanceDebug = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_billboardDistanceDebug, prototype.billboardDistanceDebug);
                        DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardDistanceDebug);
                        if (prototype.billboardDistanceDebug)
                        {
                            prototype.billboardDistanceDebugColor = EditorGUILayout.ColorField(GPUInstancerEditorConstants.TEXT_billboardDistanceDebugColor, prototype.billboardDistanceDebugColor);
                            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardDistanceDebugColor);
                        }
                        prototype.billboardFaceCamPos = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_CQBillboardFaceCamPos, prototype.billboardFaceCamPos);
                        DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_CQBillboardFaceCamPos);
                    }
                }
                else
                {
                    prototype.quadCount = 1;
                }

                EditorGUILayout.EndVertical();
            }
            else
            {
                prototype.useCrossQuads = false;
            }

            if (EditorGUI.EndChangeCheck())
            {
                if (!prototype.usePrototypeMesh && prototype.useCustomMaterialForTextureDetail && prototype.textureDetailCustomMaterial != null)
                {
                    if (!shaderBindings.IsShadersInstancedVersionExists(prototype.textureDetailCustomMaterial.shader.name))
                    {
                        Shader instancedShader;
                        if (GPUInstancerUtility.IsShaderInstanced(prototype.textureDetailCustomMaterial.shader))
                        {
                            instancedShader = prototype.textureDetailCustomMaterial.shader;
                        }
                        else
                        {
                            instancedShader = GPUInstancerUtility.CreateInstancedShader(prototype.textureDetailCustomMaterial.shader, shaderBindings);
                        }

                        if (instancedShader != null)
                        {
                            shaderBindings.AddShaderInstance(prototype.textureDetailCustomMaterial.shader.name, instancedShader);
                        }
                        else
                        {
                            Debug.LogWarning("Can not create instanced version for shader: " + prototype.textureDetailCustomMaterial.shader.name + ". Standard Shader will be used instead.");
                        }
                    }
                }
                EditorUtility.SetDirty(prototype);
            }

            if (!prototype.usePrototypeMesh && !prototype.useCustomMaterialForTextureDetail)
            {
                EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);
                GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_foliageShaderProperties, GPUInstancerEditorConstants.Styles.boldLabel);

                EditorGUI.BeginChangeCheck();
                prototype.isBillboard = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isBillboard, prototype.isBillboard);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isBillboard);

                if (prototype.isBillboard)
                {
                    prototype.billboardFaceCamPos = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_billboardFaceCamPos, prototype.billboardFaceCamPos);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardFaceCamPos);
                }

                if (EditorGUI.EndChangeCheck())
                {
                    EditorUtility.SetDirty(prototype);
                    if (simulator != null && simulator.simulateAtEditor && !simulator.initializingInstances)
                    {
                        GPUInstancerUtility.UpdateDetailInstanceRuntimeDataList(simulator.gpuiManager.runtimeDataList, terrainSettings, false, detailLayer);
                    }
                }

                EditorGUI.BeginChangeCheck();

                prototype.detailHealthyColor = EditorGUILayout.ColorField(GPUInstancerEditorConstants.TEXT_detailHealthyColor, prototype.detailHealthyColor);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_detailHealthyColor);
                prototype.detailDryColor = EditorGUILayout.ColorField(GPUInstancerEditorConstants.TEXT_detailDryColor, prototype.detailDryColor);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_detailDryColor);

                if (EditorGUI.EndChangeCheck())
                {
                    Undo.RecordObject(component, "Editor data changed.");
                    if (OnEditorDataChanged != null)
                    {
                        OnEditorDataChanged();
                    }
                    if (simulator != null && simulator.simulateAtEditor && !simulator.initializingInstances)
                    {
                        GPUInstancerUtility.UpdateDetailInstanceRuntimeDataList(simulator.gpuiManager.runtimeDataList, terrainSettings, false, detailLayer);
                    }
                    EditorUtility.SetDirty(prototype);
                }

                EditorGUI.BeginChangeCheck();

                prototype.ambientOcclusion = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_ambientOcclusion, prototype.ambientOcclusion, 0f, 1f);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_ambientOcclusion);
                prototype.gradientPower = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_gradientPower, prototype.gradientPower, 0f, 1f);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_gradientPower);

                GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_windSettings, GPUInstancerEditorConstants.Styles.boldLabel);

                prototype.windIdleSway = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_windIdleSway, prototype.windIdleSway, 0f, 1f);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windIdleSway);
                prototype.windWavesOn = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_windWavesOn, prototype.windWavesOn);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windWavesOn);
                if (prototype.windWavesOn)
                {
                    prototype.windWaveTintColor = EditorGUILayout.ColorField(GPUInstancerEditorConstants.TEXT_windWaveTintColor, prototype.windWaveTintColor);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windWaveTintColor);
                    prototype.windWaveSize = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_windWaveSize, prototype.windWaveSize, 0f, 1f);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windWaveSize);
                    prototype.windWaveTint = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_windWaveTint, prototype.windWaveTint, 0f, 1f);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windWaveTint);
                    prototype.windWaveSway = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_windWaveSway, prototype.windWaveSway, 0f, 1f);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_windWaveSway);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    EditorUtility.SetDirty(prototype);
                    if (simulator != null && simulator.simulateAtEditor && !simulator.initializingInstances)
                    {
                        GPUInstancerUtility.UpdateDetailInstanceRuntimeDataList(simulator.gpuiManager.runtimeDataList, terrainSettings, false, detailLayer);
                    }
                }
                EditorGUILayout.EndVertical();
            }
        }
        public static void DrawGPUInstancerPrototypeInfo(GPUInstancerPrototype selectedPrototype, UnityAction <string> DrawHelpText, Object component, UnityAction OnEditorDataChanged,
                                                         GPUInstancerShaderBindings shaderBindings, GPUInstancerEditorSimulator simulator, GPUInstancerTerrainSettings terrainSettings)
        {
            GPUInstancerTreePrototype treePrototype = (GPUInstancerTreePrototype)selectedPrototype;

            EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);
            GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_treeSettings, GPUInstancerEditorConstants.Styles.boldLabel);

            treePrototype.isApplyRotation = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useRandomTreeTotation, treePrototype.isApplyRotation);
            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useRandomTreeTotation);

            EditorGUILayout.EndVertical();
        }
        public static bool DrawGPUInstancerPrototypeInfo(List <GPUInstancerPrototype> selectedPrototypeList, UnityAction <string> DrawHelpText, Object component, UnityAction OnEditorDataChanged,
                                                         GPUInstancerEditorSimulator simulator, GPUInstancerTerrainSettings terrainSettings)
        {
            GPUInstancerTreePrototype prototype0 = (GPUInstancerTreePrototype)selectedPrototypeList[0];

            #region Determine Multiple Values
            bool hasChanged                = false;
            bool isApplyRotationMixed      = false;
            bool isApplyRotation           = prototype0.isApplyRotation;
            bool isApplyPrefabScaleMixed   = false;
            bool isApplyPrefabScale        = prototype0.isApplyPrefabScale;
            bool isApplyTerrainHeightMixed = false;
            bool isApplyTerrainHeight      = prototype0.isApplyTerrainHeight;
            for (int i = 1; i < selectedPrototypeList.Count; i++)
            {
                GPUInstancerTreePrototype prototypeI = (GPUInstancerTreePrototype)selectedPrototypeList[i];
                if (!isApplyRotationMixed && isApplyRotation != prototypeI.isApplyRotation)
                {
                    isApplyRotationMixed = true;
                }
                if (!isApplyPrefabScaleMixed && isApplyPrefabScale != prototypeI.isApplyPrefabScale)
                {
                    isApplyPrefabScaleMixed = true;
                }
                if (!isApplyTerrainHeightMixed && isApplyTerrainHeight != prototypeI.isApplyTerrainHeight)
                {
                    isApplyTerrainHeightMixed = true;
                }
            }
            #endregion Determine Multiple Values

            EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);
            GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_treeSettings, GPUInstancerEditorConstants.Styles.boldLabel);

            hasChanged |= MultiToggle(selectedPrototypeList, GPUInstancerEditorConstants.TEXT_useRandomTreeRotation, isApplyRotation, isApplyRotationMixed, (p, v) => ((GPUInstancerTreePrototype)p).isApplyRotation = v);
            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useRandomTreeRotation);

            hasChanged |= MultiToggle(selectedPrototypeList, GPUInstancerEditorConstants.TEXT_useTerrainHeight, isApplyTerrainHeight, isApplyTerrainHeightMixed, (p, v) => ((GPUInstancerTreePrototype)p).isApplyTerrainHeight = v);
            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useTerrainHeight);

            hasChanged |= MultiToggle(selectedPrototypeList, GPUInstancerEditorConstants.TEXT_usePrefabScale, isApplyPrefabScale, isApplyPrefabScaleMixed, (p, v) => ((GPUInstancerTreePrototype)p).isApplyPrefabScale = v);
            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_usePrefabScale);

            EditorGUILayout.EndVertical();

            return(hasChanged);
        }