コード例 #1
0
        public virtual void DrawGPUInstancerPrototypeBillboardSettings(GPUInstancerPrototype selectedPrototype,
                                                                       GPUInstancerShaderBindings shaderBindings, GPUInstancerBillboardAtlasBindings billboardAtlasBindings)
        {
            if (selectedPrototype.isBillboardDisabled || (selectedPrototype is GPUInstancerDetailPrototype && !((GPUInstancerDetailPrototype)selectedPrototype).usePrototypeMesh))
            {
                if (selectedPrototype.useGeneratedBillboard)
                {
                    selectedPrototype.useGeneratedBillboard = false;
                }
                if (selectedPrototype.billboard != null)
                {
                    selectedPrototype.billboard = null;
                }
                return;
            }

            if (Event.current.type == EventType.Repaint && !selectedPrototype.checkedForBillboardExtentions)
            {
                selectedPrototype.checkedForBillboardExtentions = true;
                if (CheckForBillboardExtentions(selectedPrototype, billboardAtlasBindings))
                {
                    return;
                }
            }

            EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);

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

            selectedPrototype.useGeneratedBillboard = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useGeneratedBillboard, selectedPrototype.useGeneratedBillboard);
            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useGeneratedBillboard);

            if (selectedPrototype.useGeneratedBillboard && selectedPrototype.billboard == null)
            {
                selectedPrototype.billboard = new GPUInstancerBillboard();
            }
            else if (!selectedPrototype.useGeneratedBillboard && selectedPrototype.billboard != null)
            {
                if (selectedPrototype.billboard.albedoAtlasTexture != null)
                {
                    billboardAtlasBindings.DeleteBillboardTextures(selectedPrototype);
                }
                if (!selectedPrototype.billboard.useCustomBillboard)
                {
                    selectedPrototype.billboard = null;
                }
            }

            if (selectedPrototype.useGeneratedBillboard)
            {
                if (selectedPrototype.treeType != GPUInstancerTreeType.SpeedTree && selectedPrototype.treeType != GPUInstancerTreeType.TreeCreatorTree && selectedPrototype.treeType != GPUInstancerTreeType.SoftOcclusionTree &&
                    !selectedPrototype.billboard.useCustomBillboard)
                {
                    EditorGUILayout.HelpBox(GPUInstancerEditorConstants.HELPTEXT_unsupportedBillboardWarning, MessageType.Warning);
                }

                bool previousUseCustomBillboard = selectedPrototype.billboard.useCustomBillboard;
                selectedPrototype.billboard.useCustomBillboard = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useCustomBillboard, selectedPrototype.billboard.useCustomBillboard);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useCustomBillboard);

                if (selectedPrototype.billboard.useCustomBillboard)
                {
                    selectedPrototype.billboard.customBillboardMesh = (Mesh)EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_customBillboardMesh,
                                                                                                        selectedPrototype.billboard.customBillboardMesh, typeof(Mesh), false);
                    selectedPrototype.billboard.customBillboardMaterial = (Material)EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_customBillboardMaterial,
                                                                                                                selectedPrototype.billboard.customBillboardMaterial, typeof(Material), false);
                    selectedPrototype.billboard.isBillboardShadowCasting = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isBillboardShadowCasting,
                                                                                                  selectedPrototype.billboard.isBillboardShadowCasting);

                    if (!previousUseCustomBillboard && selectedPrototype.billboard.albedoAtlasTexture != null)
                    {
                        billboardAtlasBindings.DeleteBillboardTextures(selectedPrototype);
                    }


                    if (shaderBindings != null && selectedPrototype.billboard.customBillboardMaterial != null)
                    {
                        if (!shaderBindings.IsShadersInstancedVersionExists(selectedPrototype.billboard.customBillboardMaterial.shader.name))
                        {
                            Shader instancedShader = GPUInstancerUtility.CreateInstancedShader(selectedPrototype.billboard.customBillboardMaterial.shader, shaderBindings);
                            if (instancedShader != null)
                            {
                                shaderBindings.AddShaderInstance(selectedPrototype.billboard.customBillboardMaterial.shader.name, instancedShader);
                            }
                        }
                    }
                }
                else
                {
                    if (selectedPrototype.billboard.customBillboardInLODGroup)
                    {
                        selectedPrototype.billboard.customBillboardInLODGroup = false;
                    }

                    selectedPrototype.billboard.billboardQuality = (BillboardQuality)EditorGUILayout.Popup(GPUInstancerEditorConstants.TEXT_billboardQuality,
                                                                                                           (int)selectedPrototype.billboard.billboardQuality, GPUInstancerEditorConstants.TEXT_BillboardQualityOptions);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardQuality);

                    switch (selectedPrototype.billboard.billboardQuality)
                    {
                    case BillboardQuality.Low:
                        selectedPrototype.billboard.atlasResolution = 1024;
                        break;

                    case BillboardQuality.Mid:
                        selectedPrototype.billboard.atlasResolution = 2048;
                        break;

                    case BillboardQuality.High:
                        selectedPrototype.billboard.atlasResolution = 4096;
                        break;

                    case BillboardQuality.VeryHigh:
                        selectedPrototype.billboard.atlasResolution = 8192;
                        break;
                    }

                    selectedPrototype.billboard.frameCount = EditorGUILayout.IntSlider(GPUInstancerEditorConstants.TEXT_billboardFrameCount, selectedPrototype.billboard.frameCount, 8, 32);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardFrameCount);
                    selectedPrototype.billboard.frameCount = Mathf.NextPowerOfTwo(selectedPrototype.billboard.frameCount);

                    selectedPrototype.billboard.billboardBrightness = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_billboardBrightness, selectedPrototype.billboard.billboardBrightness, 0.0f, 1.0f);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardBrightness);

                    selectedPrototype.billboard.isOverridingOriginalCutoff = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_overrideOriginalCutoff, selectedPrototype.billboard.isOverridingOriginalCutoff);
                    if (selectedPrototype.billboard.isOverridingOriginalCutoff)
                    {
                        selectedPrototype.billboard.cutoffOverride = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_overrideCutoffAmount, selectedPrototype.billboard.cutoffOverride, 0.01f, 1.0f);
                    }
                    else
                    {
                        selectedPrototype.billboard.cutoffOverride = -1f;
                    }
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_overrideOriginalCutoff);
                }

                if (!selectedPrototype.billboard.customBillboardInLODGroup)
                {
                    bool hasLODGroup        = selectedPrototype.prefabObject.GetComponent <LODGroup>() != null;
                    bool speedTreeBillboard = selectedPrototype.treeType == GPUInstancerTreeType.SpeedTree && hasLODGroup &&
                                              selectedPrototype.prefabObject.GetComponentInChildren <BillboardRenderer>() != null;
                    if (hasLODGroup && !speedTreeBillboard)
                    {
                        selectedPrototype.billboard.replaceLODCullWithBillboard = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_replaceLODCull, selectedPrototype.billboard.replaceLODCullWithBillboard);
                        DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_replaceLODCull);
                    }
                    if ((!hasLODGroup || !selectedPrototype.billboard.replaceLODCullWithBillboard) && !speedTreeBillboard)
                    {
                        selectedPrototype.billboard.billboardDistance = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_generatedBillboardDistance, selectedPrototype.billboard.billboardDistance, 0.01f, 1f);
                        DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_generatedBillboardDistance);
                    }
                }

                if (!selectedPrototype.billboard.useCustomBillboard)
                {
                    selectedPrototype.billboard.billboardFaceCamPos = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_billboardFaceCamPos, selectedPrototype.billboard.billboardFaceCamPos);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_billboardFaceCamPos);

                    if (selectedPrototype.billboard.albedoAtlasTexture == null)
                    {
                        GPUInstancerUtility.AssignBillboardBinding(selectedPrototype, billboardAtlasBindings);
                    }

                    EditorGUI.BeginDisabledGroup(true);
                    EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_billboardAlbedo, selectedPrototype.billboard.albedoAtlasTexture, typeof(GameObject), false);
                    EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_billboardNormal, selectedPrototype.billboard.normalAtlasTexture, typeof(GameObject), false);
                    EditorGUI.EndDisabledGroup();
                }

                GUILayout.Space(10);

                EditorGUILayout.BeginHorizontal();

                if (!selectedPrototype.billboard.useCustomBillboard)
                {
                    GPUInstancerEditorConstants.DrawColoredButton(selectedPrototype.billboard.albedoAtlasTexture == null ?
                                                                  GPUInstancerEditorConstants.Contents.generateBillboard : GPUInstancerEditorConstants.Contents.regenerateBillboard,
                                                                  GPUInstancerEditorConstants.Colors.green, Color.white, FontStyle.Bold, Rect.zero,
                                                                  () =>
                    {
                        GPUInstancerUtility.GeneratePrototypeBillboard(selectedPrototype, billboardAtlasBindings, selectedPrototype.billboard.albedoAtlasTexture != null);
                    });
                }

                if ((!selectedPrototype.billboard.useCustomBillboard && selectedPrototype.billboard.albedoAtlasTexture != null) ||
                    (selectedPrototype.billboard.useCustomBillboard &&
                     selectedPrototype.billboard.customBillboardMesh != null &&
                     selectedPrototype.billboard.customBillboardMaterial != null))
                {
                    GPUInstancerEditorConstants.DrawColoredButton(GPUInstancerEditorConstants.Contents.showBillboard, GPUInstancerEditorConstants.Colors.lightBlue, Color.white, FontStyle.Bold, Rect.zero,
                                                                  () =>
                    {
                        GPUInstancerUtility.ShowBillboardQuad(selectedPrototype, Vector3.zero);
                    });
                }

                EditorGUILayout.EndHorizontal();

                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_regenerateBillboard);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_showBillboard);
            }

            if (selectedPrototype.useGeneratedBillboard && selectedPrototype.billboard != null && selectedPrototype.billboard.useCustomBillboard && GPUInstancerDefines.billboardExtentions != null && GPUInstancerDefines.billboardExtentions.Count > 0)
            {
                GUILayout.Space(10);

                EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);

                GPUInstancerEditorConstants.DrawCustomLabel("External Billboard Generators", GPUInstancerEditorConstants.Styles.boldLabel);

                GUILayout.Space(5);

                foreach (Extention.GPUInstancerBillboardExtention billboardExtention in GPUInstancerDefines.billboardExtentions)
                {
                    try
                    {
                        EditorGUILayout.BeginHorizontal();
                        GUILayout.Label(billboardExtention.GetTitle(), GPUInstancerEditorConstants.Styles.label);

                        GPUInstancerEditorConstants.DrawColoredButton(new GUIContent(billboardExtention.GetButtonText()), GPUInstancerEditorConstants.Colors.green, Color.white, FontStyle.Bold, Rect.zero,
                                                                      () =>
                        {
                            _redirectObject = billboardExtention.GenerateBillboard(selectedPrototype.prefabObject);
                            selectedPrototype.checkedForBillboardExtentions = false;
                        });
                        EditorGUILayout.EndHorizontal();

                        GUILayout.Space(5);
                    }
                    catch (System.Exception e)
                    {
                        EditorUtility.ClearProgressBar();
                        Debug.LogError("Error generating billboard: " + e.Message + " StackTrace:" + e.StackTrace);
                    }
                }

                EditorGUILayout.EndVertical();
            }

            EditorGUILayout.EndVertical();
        }
コード例 #2
0
        public static bool CheckForBillboardExtentions(GPUInstancerPrototype selectedPrototype, GPUInstancerBillboardAtlasBindings billboardAtlasBindings)
        {
            bool hasExtentionBillboard = false;

            if (GPUInstancerDefines.billboardExtentions != null && GPUInstancerDefines.billboardExtentions.Count > 0)
            {
                foreach (Extention.GPUInstancerBillboardExtention billboardExtention in GPUInstancerDefines.billboardExtentions)
                {
                    try
                    {
                        if (billboardExtention.IsBillboardAdded(selectedPrototype.prefabObject))
                        {
                            Mesh     generatedMesh     = billboardExtention.GetBillboardMesh(selectedPrototype.prefabObject);
                            Material generatedMaterial = billboardExtention.GetBillboardMaterial(selectedPrototype.prefabObject);
                            bool     isInLODGroup      = billboardExtention.IsInLODGroup(selectedPrototype.prefabObject);
                            if (generatedMesh != null && generatedMaterial != null)
                            {
                                if (selectedPrototype.billboard == null)
                                {
                                    selectedPrototype.billboard = new GPUInstancerBillboard();
                                }

                                selectedPrototype.useGeneratedBillboard               = true;
                                selectedPrototype.billboard.useCustomBillboard        = true;
                                selectedPrototype.billboard.customBillboardInLODGroup = isInLODGroup;
                                selectedPrototype.billboard.customBillboardMesh       = generatedMesh;
                                selectedPrototype.billboard.customBillboardMaterial   = generatedMaterial;

                                hasExtentionBillboard = true;
                                break;
                            }
                        }
                    }
                    catch (System.Exception e)
                    {
                        EditorUtility.ClearProgressBar();
                        Debug.LogError("Error generating billboard: " + e.Message + " StackTrace:" + e.StackTrace);
                    }
                }
            }
            return(hasExtentionBillboard);
        }
コード例 #3
0
        public virtual void DrawGPUInstancerPrototypeBox(GPUInstancerPrototype selectedPrototype, bool isFrustumCulling, bool isOcclusionCulling,
                                                         GPUInstancerShaderBindings shaderBindings, GPUInstancerBillboardAtlasBindings billboardAtlasBindings)
        {
            if (selectedPrototype == null)
            {
                return;
            }

            EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);
            // title
            Rect foldoutRect = GUILayoutUtility.GetRect(0, 20, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(false));

            foldoutRect.x   += 12;
            showPrototypeBox = EditorGUI.Foldout(foldoutRect, showPrototypeBox, selectedPrototype.ToString(), true, GPUInstancerEditorConstants.Styles.foldout);

            if (!showPrototypeBox)
            {
                EditorGUILayout.EndVertical();
                return;
            }

            if (!string.IsNullOrEmpty(selectedPrototype.warningText))
            {
                EditorGUILayout.HelpBox(selectedPrototype.warningText, MessageType.Error);
                if (selectedPrototype.warningText.StartsWith("Can not create instanced version for shader"))
                {
                    GPUInstancerEditorConstants.DrawColoredButton(new GUIContent("Go to Unity Archive"),
                                                                  GPUInstancerEditorConstants.Colors.lightred, Color.white, FontStyle.Bold, Rect.zero,
                                                                  () =>
                    {
                        Application.OpenURL("https://unity3d.com/get-unity/download/archive");
                    });
                    GUILayout.Space(10);
                }
            }

            EditorGUI.BeginDisabledGroup(true);
            EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_prefabObject, selectedPrototype.prefabObject, typeof(GameObject), false);
            EditorGUILayout.ObjectField(GPUInstancerEditorConstants.TEXT_prototypeSO, selectedPrototype, typeof(GPUInstancerPrototype), false);
            EditorGUI.EndDisabledGroup();

            EditorGUI.BeginChangeCheck();

            #region Shadows
            EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);
            GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_shadows, GPUInstancerEditorConstants.Styles.boldLabel);

            EditorGUI.BeginDisabledGroup(Application.isPlaying);
            selectedPrototype.isShadowCasting = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isShadowCasting, selectedPrototype.isShadowCasting);
            DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isShadowCasting);
            EditorGUI.EndDisabledGroup();
            if (selectedPrototype.isShadowCasting)
            {
                if (selectedPrototype is GPUInstancerPrefabPrototype)
                {
                    EditorGUI.BeginDisabledGroup(Application.isPlaying);
                    selectedPrototype.useOriginalShaderForShadow = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useOriginalShaderForShadow, selectedPrototype.useOriginalShaderForShadow);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useOriginalShaderForShadow);
                    EditorGUI.EndDisabledGroup();
                }

                if (!(selectedPrototype is GPUInstancerDetailPrototype))
                {
                    selectedPrototype.useCustomShadowDistance = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useCustomShadowDistance, selectedPrototype.useCustomShadowDistance);
                    if (selectedPrototype.useCustomShadowDistance)
                    {
                        selectedPrototype.shadowDistance = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_shadowDistance, selectedPrototype.shadowDistance, 0.0f, QualitySettings.shadowDistance);
                    }
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useCustomShadowDistance);
                    if (selectedPrototype.prefabObject != null && selectedPrototype.prefabObject.GetComponent <LODGroup>() != null)
                    {
                        LODGroup          lodGroup    = selectedPrototype.prefabObject.GetComponent <LODGroup>();
                        List <GUIContent> optionsList = GPUInstancerEditorConstants.Contents.LODs.GetRange(0, lodGroup.lodCount);
                        optionsList.Add(GPUInstancerEditorConstants.Contents.LODs[8]);
                        GUIContent[] options = optionsList.ToArray();
                        int          index   = 0;
                        for (int i = 0; i < lodGroup.lodCount; i++)
                        {
                            index = i * 4;
                            if (i >= 4)
                            {
                                index = (i - 4) * 4 + 1;
                            }
                            selectedPrototype.shadowLODMap[index] = EditorGUILayout.Popup(GPUInstancerEditorConstants.Contents.shadowLODs[i], selectedPrototype.shadowLODMap[index],
                                                                                          options);
                        }
                    }

                    selectedPrototype.cullShadows = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_cullShadows, selectedPrototype.cullShadows);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_cullShadows);
                }
            }

            EditorGUILayout.EndVertical();
            #endregion Shadows

            #region Culling
            EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);
            GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_culling, GPUInstancerEditorConstants.Styles.boldLabel);

            selectedPrototype.maxDistance = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_maxDistance, selectedPrototype.maxDistance, 0.0f, GetMaxDistance(selectedPrototype));
            DrawHelpText(selectedPrototype is GPUInstancerDetailPrototype ? GPUInstancerEditorConstants.HELPTEXT_maxDistanceDetail : GPUInstancerEditorConstants.HELPTEXT_maxDistance);
            if (isFrustumCulling)
            {
                selectedPrototype.isFrustumCulling = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isFrustumCulling, selectedPrototype.isFrustumCulling);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isFrustumCulling);
                selectedPrototype.frustumOffset = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_frustumOffset, selectedPrototype.frustumOffset, 0.0f, 0.5f);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_frustumOffset);
            }

            if (isOcclusionCulling)
            {
                selectedPrototype.isOcclusionCulling = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isOcclusionCulling, selectedPrototype.isOcclusionCulling);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isOcclusionCulling);
            }

            if (isFrustumCulling || isOcclusionCulling)
            {
                selectedPrototype.minCullingDistance = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_minCullingDistance, selectedPrototype.minCullingDistance, 0, 100);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_minCullingDistance);
            }

            EditorGUILayout.EndVertical();
            #endregion Culling

            #region LOD
            if (selectedPrototype.prefabObject != null && (selectedPrototype.prefabObject.GetComponent <LODGroup>() != null || selectedPrototype.useGeneratedBillboard))
            {
                EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box);
                GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_LOD, GPUInstancerEditorConstants.Styles.boldLabel);

                EditorGUI.BeginDisabledGroup(Application.isPlaying);
                selectedPrototype.isLODCrossFade = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isLODCrossFade, selectedPrototype.isLODCrossFade);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isLODCrossFade);

                if (selectedPrototype.isLODCrossFade)
                {
                    selectedPrototype.isLODCrossFadeAnimate = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_isLODCrossFadeAnimate, selectedPrototype.isLODCrossFadeAnimate);
                    DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_isLODCrossFadeAnimate);

                    if (!selectedPrototype.isLODCrossFadeAnimate)
                    {
                        selectedPrototype.lodFadeTransitionWidth = EditorGUILayout.Slider(GPUInstancerEditorConstants.TEXT_lodFadeTransitionWidth, selectedPrototype.lodFadeTransitionWidth, 0.0f, 1.0f);
                        DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_lodFadeTransitionWidth);
                    }
                }

                selectedPrototype.lodBiasAdjustment = EditorGUILayout.FloatField(GPUInstancerEditorConstants.TEXT_lodBiasAdjustment, selectedPrototype.lodBiasAdjustment);
                DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_lodBiasAdjustment);
                EditorGUI.EndDisabledGroup();

                EditorGUILayout.EndVertical();
            }
            #endregion LOD

            EditorGUI.BeginDisabledGroup(Application.isPlaying);
            DrawGPUInstancerPrototypeInfo(selectedPrototype);

            DrawGPUInstancerPrototypeBillboardSettings(selectedPrototype, shaderBindings, billboardAtlasBindings);

            DrawGPUInstancerPrototypeActions();
            DrawGPUInstancerPrototypeAdvancedActions();

            if (EditorGUI.EndChangeCheck() && selectedPrototype != null)
            {
                EditorUtility.SetDirty(selectedPrototype);
            }
            EditorGUI.EndDisabledGroup();
            EditorGUILayout.EndVertical();
        }