Exemple #1
0
    public override void OnInspectorGUI()
    {
        VolumeGrass _target = (VolumeGrass)target;

        GUILayout.Space(10);
        GUILayout.Label("Mode", EditorStyles.boldLabel);
        int        _state = GUILayout.Toolbar(_target.state, _target.stateStrings);
        MeshFilter filter = _target.gameObject.GetComponent(typeof(MeshFilter)) as MeshFilter;

        if ((_target.state == 0) && (_state == 1))
        {
            // build mesh
            if (!_target.BuildMesh())
            {
                EditorUtility.DisplayDialog("Error...", "Can't build mesh   ", "Proceed", "");
                return;                 // nie można zbudowac mesha (np. za mało wierzchołków)
            }
        }
        else if ((_target.state == 1) && (_state == 0))
        {
            if (filter && filter.sharedMesh)
            {
                filter.sharedMesh = null;
                MeshFilter filter_sidewalls = null;
                Transform  tr = _target.transform.Find("sidewalls");
                if (tr != null)
                {
                    filter_sidewalls = tr.gameObject.GetComponent(typeof(MeshFilter)) as MeshFilter;
                }
                if (filter_sidewalls && filter_sidewalls.sharedMesh)
                {
                    filter_sidewalls.sharedMesh = null;
                }
            }
            _target.state = _state;
            EditorUtility.SetDirty(_target);
            return;
        }
        _target.state = _state;

        if (_target.state == 1)
        {
            GUILayout.Space(15);
            GUILayout.Label("Grass height/coverage modification", EditorStyles.boldLabel);
            GUILayout.BeginHorizontal();
            bool prev_paint_height = _target.paint_height;
            GUILayout.Label("Modify volume height on vertices", EditorStyles.label);
            _target.paint_height = EditorGUILayout.Toggle(_target.paint_height);
            if (prev_paint_height != _target.paint_height)
            {
                EditorUtility.SetDirty(_target);
            }
            GUILayout.EndHorizontal();
            if (_target.paint_height)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Label("Area size", EditorStyles.label);
                _target.paint_size = EditorGUILayout.Slider(_target.paint_size, 0.5f, 50);
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
                GUILayout.Label("Area smoothness", EditorStyles.label);
                _target.paint_smoothness = EditorGUILayout.Slider(_target.paint_smoothness, 0, 1);
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
                GUILayout.Label("Opacity", EditorStyles.label);
                _target.paint_opacity = EditorGUILayout.Slider(_target.paint_opacity, 0, 1);
                GUILayout.EndHorizontal();
            }
        }

        GUILayout.Space(15);

        GUILayout.Label("General Settings", EditorStyles.boldLabel);
        GUILayout.BeginHorizontal();
        GUILayout.Label("Show node numbers", EditorStyles.label);
        bool tmp_showNodeNumbers = EditorGUILayout.Toggle(_target.showNodeNumbers);

        if (_target.showNodeNumbers != tmp_showNodeNumbers)
        {
            _target.showNodeNumbers = tmp_showNodeNumbers;
            EditorUtility.SetDirty(_target);
        }
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Show tesselation points in build mode", EditorStyles.label);
        bool new_flag = EditorGUILayout.Toggle(_target.show_tesselation_points);

        if (_target.show_tesselation_points != new_flag)
        {
            _target.show_tesselation_points = new_flag;
            if ((!new_flag) && (_target.which_active == 3))
            {
                _target.active_idx = -1;
            }
            EditorUtility.SetDirty(_target);
        }
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Default subnodes", EditorStyles.label);
        _target.bezier_subdivisions = EditorGUILayout.IntSlider(_target.bezier_subdivisions, 1, 50);
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Snap to ground when dragging node", EditorStyles.label);
        _target.snap_on_move = EditorGUILayout.Toggle(_target.snap_on_move);
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Snap to ground every node at once", EditorStyles.label);
        _target.snap_always = EditorGUILayout.Toggle(_target.snap_always);
        GUILayout.EndHorizontal();
        GUILayout.Space(2);
        GUILayout.BeginHorizontal();
        GUILayout.Label("Ground collision layer mask", EditorStyles.label);
        _target.ground_layerMask.value = EditorGUILayout.LayerField(_target.ground_layerMask.value);
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Disable(hide) on incompatible hardware", EditorStyles.label);
        _target.hide_on_old_hardware = EditorGUILayout.Toggle(_target.hide_on_old_hardware);
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Force ALT (slower) shader in editor", EditorStyles.label);
        bool prev_useOGL = _target.useOGL;

        _target.useOGL = EditorGUILayout.Toggle(_target.useOGL);
        if (_target.useOGL != prev_useOGL)
        {
            _target.checkOGL();
        }
        GUILayout.EndHorizontal();

        GUILayout.Space(15);
        GUILayout.Label("Build Settings", EditorStyles.boldLabel);
        GUILayout.BeginHorizontal();
        GUILayout.Label("Slices on blades texture", EditorStyles.label);
        float prev_slices_num = _target.slices_num;

        _target.slices_num = EditorGUILayout.IntSlider(_target.slices_num, 1, 64);
        if (_target.slices_num != prev_slices_num)
        {
            _target.setupLODAndShader(_target.act_lod, true);
        }
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Slice planes per world unit", EditorStyles.label);
        float UV_ratio       = 1.0f / (_target.mesh_height * _target.slices_num);
        float prev_plane_num = _target.plane_num;

        _target.plane_num = EditorGUILayout.Slider(_target.plane_num * UV_ratio, 0.3f, 80f) / UV_ratio;
        if (_target.plane_num != prev_plane_num)
        {
            _target.setupLODAndShader(_target.act_lod, true);
        }
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Grass height in world units", EditorStyles.label);
        _target.mesh_height = EditorGUILayout.Slider(_target.mesh_height, 0.02f, 3f);
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Additional mesh height offset", EditorStyles.label);
        _target.add_height_offset = EditorGUILayout.Slider(_target.add_height_offset, -2f, 2f);
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Subnode optimization threshold angle", EditorStyles.label);
        _target.colinear_treshold = EditorGUILayout.Slider(_target.colinear_treshold, 91f, 180f);
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        GUILayout.Label("Adjust to ground", EditorStyles.label);
        _target.snap_on_build = EditorGUILayout.Toggle(_target.snap_on_build);
        GUILayout.EndHorizontal();
        if (_target.snap_on_build)
        {
            GUILayout.BeginHorizontal();
            GUILayout.Label("Max height error", EditorStyles.label);
            _target.max_y_error[_target.act_lod] = EditorGUILayout.Slider(_target.max_y_error[_target.act_lod], 0.01f, 1);
            GUILayout.EndHorizontal();
            _target.min_edge_length[_target.act_lod] = EditorGUILayout.Slider("Min edge length", _target.min_edge_length[_target.act_lod], 0.01f, 5);
            GUILayout.BeginHorizontal();
            GUILayout.Label("UV map grid resolution", EditorStyles.label);
            _target.mapping_grid_size = EditorGUILayout.IntSlider(_target.mapping_grid_size, 10, 300);
            GUILayout.EndHorizontal();
            bool prev_custom_UV_bounds = _target.custom_UV_bounds;
            GUILayout.BeginHorizontal();
            GUILayout.Label("Custom UV map grid bounds", EditorStyles.label);
            _target.custom_UV_bounds = EditorGUILayout.Toggle(_target.custom_UV_bounds);
            GUILayout.EndHorizontal();
            if (prev_custom_UV_bounds != _target.custom_UV_bounds)
            {
                if (_target.custom_UV_bounds)
                {
                    _target.getUVBounds();
                    _target.AdjustCustomUVBounds();
                }
                EditorUtility.SetDirty(_target);
            }
            if (_target.custom_UV_bounds)
            {
                Vector4 old_bounds = new Vector4(_target.custom_minx, _target.custom_maxx, _target.custom_minz, _target.custom_maxz);
                Vector4 new_bounds = EditorGUILayout.Vector4Field("UV bounds rect (X=xMin, Y=xMax, Z=zMin, W=zMax)", old_bounds);
                if (Vector4.Distance(old_bounds, new_bounds) > 0)
                {
                    if (new_bounds.x > _target.minx)
                    {
                        new_bounds.x = _target.minx;
                    }
                    if (new_bounds.y < _target.maxx)
                    {
                        new_bounds.y = _target.maxx;
                    }
                    if (new_bounds.z > _target.minz)
                    {
                        new_bounds.z = _target.minz;
                    }
                    if (new_bounds.w < _target.maxz)
                    {
                        new_bounds.w = _target.maxz;
                    }
                    _target.custom_minx = new_bounds.x;
                    _target.custom_maxx = new_bounds.y;
                    _target.custom_minz = new_bounds.z;
                    _target.custom_maxz = new_bounds.w;
                    _target.reinitUV    = true;
                    EditorUtility.SetDirty(_target);
                }
            }
            GUILayout.BeginHorizontal();
            GUILayout.Label("UV2 range (lightmap 0..u, 0..v)", EditorStyles.label);
            _target.UV2range.x = EditorGUILayout.Slider(_target.UV2range.x, 0.1f, 1f);
            _target.UV2range.y = EditorGUILayout.Slider(_target.UV2range.y, 0.1f, 1f);
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
            GUILayout.Label("Border transitions on build", EditorStyles.label);
            _target.auto_border_transitions = EditorGUILayout.Toggle(_target.auto_border_transitions);
            GUILayout.EndHorizontal();
            bool prev_fullBackGeometry = _target.fullBackGeometry;
            GUILayout.BeginHorizontal();
            GUILayout.Label("Silhouettes backcut", EditorStyles.label);
            _target.fullBackGeometry = EditorGUILayout.Toggle(_target.fullBackGeometry);
            GUILayout.EndHorizontal();
            if (!prev_fullBackGeometry && _target.fullBackGeometry)
            {
                EditorUtility.DisplayDialog("Info", "This feature can improve grass silhouette on _very_ wavy terrain, but requires full grass geometry (instead of sidewalls only) to be rendered into depth buffer. Takes effect on play.", "Proceed", "");
            }
        }
        GUILayout.Space(12);
        if ((filter == null) || (filter.sharedMesh == null))
        {
            GUILayout.Label("  Current LOD mesh ", EditorStyles.miniLabel);
        }
        else
        {
            GUILayout.Label("  Current LOD mesh (" + filter.sharedMesh.vertices.Length + " verts, " + (filter.sharedMesh.triangles.Length / 3) + " tris)", EditorStyles.miniLabel);
        }
        if (_target.state == 1)
        {
            GUILayout.BeginHorizontal();
            GUILayout.Label("  Used when distance < than ", EditorStyles.miniLabel);
            _target.LOD_distances[_target.act_lod] = EditorGUILayout.IntField(_target.LOD_distances[_target.act_lod]);
            GUILayout.EndHorizontal();
        }
        for (int i = 0; i < 4; i++)
        {
            if (_target.LODs[i] == null)
            {
                _target.lodStrings[i] = _target.lodStrings_empty[i];
            }
            else
            {
                _target.lodStrings[i] = _target.lodStrings_occupied[i];
            }
        }
        int act_lod = GUILayout.Toolbar(_target.act_lod, _target.lodStrings);

        if (_target.act_lod != act_lod)
        {
            if (_target.state == 1)
            {
                _target.setupLODAndShader(act_lod, true);
            }
            _target.act_lod = act_lod;
        }
        if (_target.state == 1)
        {
            GUILayout.BeginHorizontal();
            string lb;
            if (_target.LODs[_target.act_lod] != null)
            {
                lb = "Rebuild LOD";
            }
            else
            {
                lb = "Build LOD";
            }
            if (GUILayout.Button(lb, GUILayout.Width(85), GUILayout.Height(20)))
            {
                if (!_target.BuildMesh())
                {
                    EditorUtility.DisplayDialog("Error...", "Can't build mesh   ", "Proceed", "");
                }
            }
            if (_target.LODs[_target.act_lod] != null)
            {
                if (GUILayout.Button("Delete LOD", GUILayout.Width(85), GUILayout.Height(20)))
                {
                    if ((filter != null) && (filter.sharedMesh != null))
                    {
                        filter.sharedMesh = null;
                        DestroyImmediate(_target.LODs[_target.act_lod]);
                        _target.LODs[_target.act_lod] = null;
                        if (_target.LODs_sidewalls[_target.act_lod] != null)
                        {
                            Transform tr = _target.transform.Find("sidewalls");
                            if (tr != null)
                            {
                                tr.parent = null;
                                DestroyImmediate(tr);
                            }
                            DestroyImmediate(_target.LODs_sidewalls[_target.act_lod]);
                            _target.LODs_sidewalls[_target.act_lod] = null;
                        }
                    }
                }
            }
            if (_target.snap_on_build && (_target.LODs[_target.act_lod] != null))
            {
                if (GUILayout.Button("Refine UV at slopes", GUILayout.Height(20)))
                {
                    if ((filter != null) && (filter.sharedMesh != null))
                    {
                        Mesh      msh      = filter.sharedMesh;
                        Vector3[] vertices = msh.vertices;
                        Vector2[] uvs      = msh.uv;
                        Vector4[] tangents = msh.tangents;
                        Color[]   colors   = msh.colors;
                        _target.iterateUVs(_target.mapping_grid_size >> 2, vertices, uvs, tangents, colors);
                        msh.uv       = uvs;
                        msh.tangents = tangents;
                    }
                }
            }
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
            bool prev_checkerMatFlag = _target.checkerMatFlag;
            GUILayout.Label("Show units checker (useful when refining)", EditorStyles.label);
            _target.checkerMatFlag = EditorGUILayout.Toggle(_target.checkerMatFlag);
            if (_target.checkerMatFlag && (!prev_checkerMatFlag))
            {
                _target.showChecker();
            }
            else if ((!_target.checkerMatFlag) && prev_checkerMatFlag)
            {
                _target.hideChecker();
            }
            GUILayout.EndHorizontal();
        }
        if (_target.active_idx >= 0)
        {
            GUILayout.Space(15);
            if (_target.which_active == 3)
            {
                // tesselation points
                GUILayout.Label("Tesselation Point Properties", EditorStyles.boldLabel);
                Vector3 vec;
                if (_target.localGlobalState == 0)
                {
                    // local
                    vec = EditorGUILayout.Vector3Field("Position", _target.tesselation_points[_target.active_idx]);
                }
                else
                {
                    // global
                    vec = _target.T_wl(EditorGUILayout.Vector3Field("Position", _target.T_lw(_target.tesselation_points[_target.active_idx])));
                }
                if (_target.ConstrainPoints(vec))
                {
                    EditorUtility.SetDirty(_target);
                }
                GUILayout.BeginHorizontal();
                _target.localGlobalState = GUILayout.Toolbar(_target.localGlobalState, _target.localGlobalStrings);
                if (GUILayout.Button("Delete Point", GUILayout.Width(100), GUILayout.Height(20)))
                {
                    Undo.RegisterUndo(new Object[2] {
                        _target, _target.transform
                    }, "grass edit");
                    _target.DeleteActiveControlPoint();
                    EditorUtility.SetDirty(_target);
                }
                GUILayout.EndHorizontal();
            }
            else
            {
                // nodes
                GUILayout.Label("Node Properties", EditorStyles.boldLabel);
                if (_target.state == 0)
                {
                    Vector3 vec;
                    if (_target.localGlobalState == 0)
                    {
                        // local
                        if (_target.which_active == 0)
                        {
                            vec = EditorGUILayout.Vector3Field("Position", _target.control_points[_target.active_idx]);
                        }
                        else if (_target.which_active == 1)
                        {
                            vec = EditorGUILayout.Vector3Field("Position", _target.bezier_pointsA[_target.active_idx]);
                        }
                        else
                        {
                            vec = EditorGUILayout.Vector3Field("Position", _target.bezier_pointsB[_target.active_idx]);
                        }
                    }
                    else
                    {
                        // global
                        if (_target.which_active == 0)
                        {
                            vec = _target.T_wl(EditorGUILayout.Vector3Field("Position", _target.T_lw(_target.control_points[_target.active_idx])));
                        }
                        else if (_target.which_active == 1)
                        {
                            vec = _target.T_wl(EditorGUILayout.Vector3Field("Position", _target.T_lw(_target.bezier_pointsA[_target.active_idx])));
                        }
                        else
                        {
                            vec = _target.T_wl(EditorGUILayout.Vector3Field("Position", _target.T_lw(_target.bezier_pointsB[_target.active_idx])));
                        }
                    }
                    if (_target.ConstrainPoints(vec))
                    {
                        EditorUtility.SetDirty(_target);
                    }
                    GUILayout.BeginHorizontal();
                    _target.localGlobalState = GUILayout.Toolbar(_target.localGlobalState, _target.localGlobalStrings);
                    if (GUILayout.Button("Delete Node", GUILayout.Width(100), GUILayout.Height(20)))
                    {
                        Undo.RegisterUndo(new Object[2] {
                            _target, _target.transform
                        }, "grass edit");
                        _target.DeleteActiveControlPoint();
                        EditorUtility.SetDirty(_target);
                    }
                    GUILayout.EndHorizontal();
                }
                int subs = EditorGUILayout.IntSlider("Subnodes count", (int)_target.subdivisions[_target.active_idx], 1, 50);
                if (subs != _target.subdivisions[_target.active_idx])
                {
                    _target.subdivisions[_target.active_idx] = subs;
                    EditorUtility.SetDirty(_target);
                }
                GUILayout.BeginHorizontal();
                GUILayout.Label("Optimize collinear subnodes", EditorStyles.label);
                _target.optimize_subnodes[_target.active_idx] = EditorGUILayout.Toggle(_target.optimize_subnodes[_target.active_idx]);
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
                GUILayout.Label("Build sidewall", EditorStyles.label);
                _target.side_walls[_target.active_idx] = EditorGUILayout.Toggle(_target.side_walls[_target.active_idx]);
                GUILayout.EndHorizontal();
            }
        }

        GUILayout.Space(15);
    }