Ejemplo n.º 1
0
    void HandleLodChunks()
    {
        if (terrainChunks != null)
        {
            ReleaseIndirectArgsBuffers();
        }

        if (renderType == GrassRenderType.Mesh)
        {
            terrainChunks = MeshChunker.Chunk(grassMesh, chunksX, chunksY, chunksZ, grassPerTri, drawMat.GetFloat("bladeHeight"));
        }
        else
        {
            terrainChunks = MeshChunker.ChunkTerrain(terrainObject, chunksX, chunksZ, grassPerTri, terrainExpansion, drawMat.GetFloat("bladeHeight"));
            if (!terrainNormalMap)
            {
                terrainNormalMap = TextureCreator.GetTerrainNormalMap(terrainObject, gfComputeShader, normalKernel, highQualityHeightmap);
                terrainMapOffset = 1f / terrainNormalMap.width * 0.5f;
            }

            if (discardEmptyChunks)
            {
                DiscardUnusedChunks();
            }
        }


        CheckIndirectInstancingArgs();
    }
    void DrawPaintGUI()
    {
        DrawMapsInspector();

        EditorGUI.BeginChangeCheck();

        mapPaintingEnabled = EditorGUILayout.ToggleLeft(GetContent(() => grassFlow.enableMapPainting), grassFlow.enableMapPainting);

        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(grassFlow, "GrassFlow Change Variable");

            grassFlow.enableMapPainting = mapPaintingEnabled;

            Undo.FlushUndoRecordObjects();
        }

        if (!grassFlow.enableMapPainting)
        {
            return;
        }

        EditorGUI.BeginChangeCheck();

        bool _saveBeforeStroke = EditorGUILayout.ToggleLeft(new GUIContent("Save On Stroke", "Saves the maps before each stroke so that the stroke can be reverted to the save before the stroke."), saveBeforeStroke);

        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(this, "GrassFlow Change Variable");

            saveBeforeStroke = _saveBeforeStroke;

            Undo.FlushUndoRecordObjects();
        }

        if (GUILayout.Button(new GUIContent("Revert Changes", "Works kind of like a limited undo functionality, discarding changes to detail maps since they were last saved. " +
                                            "The maps are saved whenever the project assets are saved e.g. on Ctrl+S. Revert hotkey: Shift-R")))
        {
            grassFlow.RevertDetailMaps();
        }

        if (grassFlow.renderType == GrassFlowRenderer.GrassRenderType.Mesh)
        {
            GUILayout.Space(12);

            if (GUILayout.Button(new GUIContent("Bake Density to Mesh", "Creates a new mesh based on the density information in the parameter map. " +
                                                "You can use this mesh to more efficiently only render grass on certain parts of your mesh. Does NOT automatically apply the resulting mesh.")))
            {
                string fileName = EditorUtility.SaveFilePanelInProject("Choose Save Location", "GrassflowDensityMesh", "asset", "");
                if (string.IsNullOrEmpty(fileName))
                {
                    return;
                }

                SaveData();
                Mesh bakedMesh = MeshChunker.BakeDensityToMesh(grassFlow.grassMesh, grassFlow.paramMap);

                AssetDatabase.CreateAsset(bakedMesh, fileName);
                AssetDatabase.SaveAssets();
            }
        }


        EditorGUILayout.Space();
        EditorGUILayout.LabelField("", new GUIStyle(GUI.skin.horizontalScrollbarThumb)
        {
            fixedHeight = 2
        }, GUILayout.Height(3));
        EditorGUILayout.Space();

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        EditorGUI.BeginChangeCheck();
        int newToolIndex = GUILayout.Toolbar(selectedPaintToolIndex, toolIcons, GUILayout.Height(iconSize - 15), GUILayout.Width(iconSize * toolIcons.Length));

        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(this, "GrassFlow Change Paint Tool");
            selectedPaintToolIndex = newToolIndex;
            paintToolType          = (PaintToolType)selectedPaintToolIndex;
            Undo.FlushUndoRecordObjects();
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.BeginVertical(EditorStyles.helpBox);
        GUILayout.Label(toolInfos[selectedPaintToolIndex].text);
        GUILayout.Label(toolInfos[selectedPaintToolIndex].tooltip, EditorStyles.wordWrappedMiniLabel);
        GUILayout.EndVertical();

        if (brushList.ShowGUI())
        {
            Undo.RecordObject(this, "GrassFlow Change Brush");
            selectedBrushIndex = brushList.selectedIndex;
            GrassFlowRenderer.SetPaintBrushTexture(brushList.GetActiveBrush().texture);
            Undo.FlushUndoRecordObjects();
        }

        EditorGUILayout.Space();
        EditorGUILayout.LabelField("Settings", bold);

        Undo.RecordObject(this, "GrassFlow Change Variable");

        if (paintToolType == PaintToolType.Color)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Brush Color", GUILayout.Width(100));
            paintBrushColor = EditorGUILayout.ColorField(new GUIContent(), paintBrushColor, true, true, true, new ColorPickerHDRConfig(0, 10, 0, 10));
            EditorGUILayout.EndHorizontal();
        }
        else
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(new GUIContent("Clamp Range",
                                                      "Min and max range for parameters while painting. This can be used to essentially paint a set value instead of being additive or subtractive."), GUILayout.Width(100));
            clampRange = EditorGUILayout.Vector2Field("", clampRange, GUILayout.Width(100));
            GUILayout.Space(5);
            EditorGUILayout.MinMaxSlider("", ref clampRange.x, ref clampRange.y, 0, 1, GUILayout.MinWidth(20));
            EditorGUILayout.EndHorizontal();
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Brush Size", GUILayout.Width(100));
        paintBrushSize = EditorGUILayout.FloatField("", paintBrushSize, GUILayout.Width(100));
        GUILayout.Space(5);
        paintBrushSize = GUILayout.HorizontalSlider(paintBrushSize, 0f, 1f);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Brush Strength", GUILayout.Width(100));
        paintBrushStrength = EditorGUILayout.FloatField("", paintBrushStrength, GUILayout.Width(100));
        GUILayout.Space(5);
        paintBrushStrength = GUILayout.HorizontalSlider(paintBrushStrength, 0f, 1f);
        EditorGUILayout.EndHorizontal();

        LayerMask rayCastMask = EditorGUILayout.MaskField(new GUIContent("Raycast Layer Mask", "This mask is used when raycasting the terrain/mesh for painting. " +
                                                                         "You can use this to only paint on the layer your terrain is on and paint through blocking objects, or vice versa."),
                                                          InternalEditorUtility.LayerMaskToConcatenatedLayersMask(paintRaycastMask), InternalEditorUtility.layers);

        paintRaycastMask = InternalEditorUtility.ConcatenatedLayersMaskToLayerMask(rayCastMask);

        continuousPaint = EditorGUILayout.ToggleLeft(new GUIContent("Paint Continuously",
                                                                    "If off the mouse needs to be moved to paint, otherwise it will paint continously while the mouse is down."), continuousPaint);

        useDeltaTimePaint = EditorGUILayout.ToggleLeft(new GUIContent("Use Delta Time Paint",
                                                                      "If on the brush strength is multiplied by delta time to make painting strength framerate independent. " +
                                                                      "It's useful to turn this off if you want to use brushes more like stamps and use strength of 1 and apply the full brush to the grass with a single click."), useDeltaTimePaint);


        if (grassFlow.renderType == GrassFlowRenderer.GrassRenderType.Terrain)
        {
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("", new GUIStyle(GUI.skin.horizontalScrollbarThumb)
            {
                fixedHeight = 2
            }, GUILayout.Height(3));
            EditorGUILayout.Space();

            EditorGUILayout.LabelField("Splat Maps", bold);

            if (grassFlow.terrainObject)
            {
                int numSplatLayers = grassFlow.terrainObject.terrainData.alphamapLayers;

                if (numSplatLayers > 0)
                {
                    EditorGUI.BeginChangeCheck();

                    int   _splatMapLayerIdx  = Mathf.Clamp(splatMapLayerIdx, 0, numSplatLayers);
                    float _splatMapTolerance = splatMapTolerance;

                    int[]        splatInts = new int[numSplatLayers];
                    GUIContent[] splatStrs = new GUIContent[numSplatLayers];

                    for (int i = 0; i < splatInts.Length; i++)
                    {
                        splatInts[i] = i;
                        splatStrs[i] = new GUIContent((i + 1).ToString() + " : " + grassFlow.terrainObject.terrainData.splatPrototypes[i].texture.name);
                    }

                    _splatMapLayerIdx = EditorGUILayout.IntPopup(new GUIContent("Splat Layer",
                                                                                "The index of the splat texture layer you want to use to mask where grass appears."),
                                                                 _splatMapLayerIdx, splatStrs, splatInts);

                    _splatMapTolerance = EditorGUILayout.Slider(new GUIContent("Tolerance",
                                                                               "Controls opacity tolerance when applying splat map layers."), splatMapTolerance, 0f, 1f);

                    if (EditorGUI.EndChangeCheck())
                    {
                        Undo.RecordObject(this, "GrassFlow Change Paint Tool");

                        splatMapLayerIdx  = _splatMapLayerIdx;
                        splatMapTolerance = _splatMapTolerance;

                        Undo.FlushUndoRecordObjects();
                    }


                    EditorGUILayout.BeginHorizontal();
                    if (GUILayout.Button(new GUIContent("Apply Additive", "Adds grass based on the selected layer, but does not remove any existing grass.")))
                    {
                        grassFlow.ApplySplatTex(grassFlow.terrainObject, splatMapLayerIdx, 0, splatMapTolerance);
                    }

                    if (GUILayout.Button(new GUIContent("Apply Subtractive", "Removes grass based on the selected layer, but does not affect grass outside of the splat map.")))
                    {
                        grassFlow.ApplySplatTex(grassFlow.terrainObject, splatMapLayerIdx, 1, 1f - splatMapTolerance);
                    }

                    if (GUILayout.Button(new GUIContent("Apply Replace", "Adds grass based on the selected layer, removing and overwriting existing grass.")))
                    {
                        grassFlow.ApplySplatTex(grassFlow.terrainObject, splatMapLayerIdx, 2, splatMapTolerance);
                    }
                    EditorGUILayout.EndHorizontal();
                }
                else
                {
                    GUILayout.BeginVertical(EditorStyles.helpBox);
                    GUILayout.Label("No splat layers on the terrain.");
                    GUILayout.EndVertical();
                }

                //grassFlow.terrainObject.terrainData.alphamapTextures[]
            }
            else
            {
                GUILayout.BeginVertical(EditorStyles.helpBox);
                GUILayout.Label("Please assign terrain object in settings.");
                GUILayout.EndVertical();
            }
        }
    }