void SceneGUICallback(SceneView sceneView)
    {
        if (mapPaintingEnabled && mainTabIndex == 1)
        {
            Event e = Event.current;

            HandleHotkeys(e);

            RaycastHit hit;
            Ray        ray = HandleUtility.GUIPointToWorldRay(e.mousePosition);

            Physics.Raycast(ray, out hit, float.PositiveInfinity, paintRaycastMask);

            bool hitTerrain = hit.transform == grassFlow.terrainTransform;

            if (e.type == EventType.MouseDown || e.type == EventType.MouseUp)
            {
                if (e.button == 0 && !Event.current.alt)
                {
                    Selection.activeObject = grassFlow;
                }
            }

            if (!hitTerrain)
            {
                DisablePaintHighlight();
                if (!shouldPaint)
                {
                    return;
                }
            }

            if (grassFlow.drawMat)
            {
                grassFlow.drawMat.SetTexture("paintHighlightBrushTex", brushList.GetActiveBrush().texture);
                grassFlow.drawMat.SetColor("paintHightlightColor", paintBrushColor);

                if (shouldPaint)
                {
                    if (paintToolType == PaintToolType.Color)
                    {
                        grassFlow.drawMat.SetVector("paintHighlightBrushParams", Vector4.zero);
                    }
                    else
                    {
                        grassFlow.drawMat.SetVector("paintHighlightBrushParams", new Vector4(hit.textureCoord.x, hit.textureCoord.y, paintBrushSize * 0.05f, 0.5f));
                    }
                }
                else
                {
                    grassFlow.drawMat.SetVector("paintHighlightBrushParams", new Vector4(hit.textureCoord.x, hit.textureCoord.y, paintBrushSize * 0.05f, 1f));
                }
            }

            int   id       = GUIUtility.GetControlID(grassEditorHash, FocusType.Passive);
            float brushDir = e.shift ? -1f : 1f;

            switch (e.GetTypeForControl(id))
            {
            case EventType.Layout:
                HandleUtility.AddDefaultControl(id);

                if (continuousPaint && shouldPaint)
                {
                    PaintSwitch(hit.textureCoord, brushDir);
                }

                break;

            case EventType.MouseMove:
                HandleUtility.Repaint();
                break;

            case EventType.MouseDown:
            case EventType.MouseDrag: {
                // Don't do anything at all if someone else owns the hotControl. Fixes case 677541.
                if (EditorGUIUtility.hotControl != 0 && EditorGUIUtility.hotControl != id)
                {
                    return;
                }

                // Don't do anything on MouseDrag if we don't own the hotControl.
                if (e.GetTypeForControl(id) == EventType.MouseDrag && EditorGUIUtility.hotControl != id)
                {
                    return;
                }

                // If user is ALT-dragging, we want to return to main routine
                if (Event.current.alt)
                {
                    return;
                }

                // Allow painting with LMB only
                if (e.button != 0)
                {
                    return;
                }

                if (HandleUtility.nearestControl != id)
                {
                    return;
                }

                if (e.type == EventType.MouseDown)
                {
                    EditorGUIUtility.hotControl = id;
                    shouldPaint = true;
                    if (saveBeforeStroke)
                    {
                        SaveData(false);
                    }
                    GrassFlowRenderer.SetPaintBrushTexture(brushList.GetActiveBrush().texture);
                }


                if (!continuousPaint)
                {
                    PaintSwitch(hit.textureCoord, brushDir);
                }

                e.Use();
            }
            break;

            case EventType.MouseUp: {
                if (GUIUtility.hotControl != id)
                {
                    return;
                }

                shouldPaint = false;
                MarkDirtyMaps();
                if (saveBeforeStroke)
                {
                    AssetDatabase.Refresh();
                }

                // Release hot control
                GUIUtility.hotControl = 0;
            }
            break;
            }
        }
        else
        {
            DisablePaintHighlight();
        }
    }
Exemplo n.º 2
0
 private void Start()
 {
     GrassFlowRenderer.SetPaintBrushTexture(flatTex);
 }
    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();
            }
        }
    }