public static void Show(TreeNodeEditor treeNode)
        {
            EditorGUI.BeginChangeCheck();

            TreeDetailNode treeDetail = treeNode.TreeDetailNode;

            treeDetail.Prefab = (GameObject)
                                EditorGUILayout.ObjectField(new GUIContent("Tree"), treeDetail.Prefab, typeof(GameObject), false);

            Show(treeDetail, () => {
                treeDetail.RandomRotation = EditorGUILayout.Toggle("Random Rotation", treeDetail.RandomRotation);
                treeDetail.BendFactor     = EditorGUILayout.FloatField("Bend Factor", treeDetail.BendFactor);
            });

            if (EditorGUI.EndChangeCheck())
            {
                treeNode.serializedObject.ApplyModifiedProperties();
            }
        }
        /// <summary>
        /// Adds trees according to the <see cref="_biomeMap"/> in
        /// this <see cref="Tile"/>
        /// </summary>
        public IEnumerator AddTrees()
        {
            if (_biomeMap == null)
            {
                yield break;
            }

            //Collect prototypes from tree nodes
            TreeDetailNode[] allTreeNodes = _painter.Biomes
                                            .SelectMany(biome => biome.GetTreeInputs())
                                            .ToArray();
            List <TreePrototype> prototypes = new List <TreePrototype>(allTreeNodes.Length);

            foreach (TreeDetailNode treeNode in allTreeNodes)
            {
                prototypes.Add((TreePrototype)treeNode.GetDetailPrototype());
            }

            int            coroutineRes = TerraConfig.Instance.Generator.CoroutineRes;
            int            iterations   = 0;
            GenerationData conf         = TerraConfig.Instance.Generator;

            _terrain.terrainData.treePrototypes = prototypes.ToArray();
            _terrain.terrainData.RefreshPrototypes();
            _terrain.treeDistance            = conf.TreeDistance;
            _terrain.treeBillboardDistance   = conf.BillboardStart;
            _terrain.treeMaximumFullLODCount = conf.MaxMeshTrees;

            BiomeNode[] biomeNodes     = _painter.Biomes;
            int         prototypeIndex = 0;

            for (int i = 0; i < biomeNodes.Length; i++)
            {
                //Collect all trees for this biome
                BiomeNode        biome     = biomeNodes[i];
                TreeDetailNode[] treeNodes = biome.GetTreeInputs();

                if (treeNodes.Length == 0)   //A biome may contain no trees
                {
                    continue;
                }

                foreach (TreeDetailNode treeNode in treeNodes)
                {
                    //Get map of normalized "tree positions"
                    Vector2[] samples = null;
                    if (!TerraConfig.Instance.IsEditor)
                    {
                        bool           isDone = false;
                        TreeDetailNode node   = treeNode;
                        TerraConfig.Instance.Worker.Enqueue(() => samples = node.SamplePositions(_tile.Random), () => isDone = true);

                        while (!isDone)
                        {
                            yield return(null);
                        }
                    }
                    else
                    {
                        samples = treeNode.SamplePositions(_tile.Random);
                    }

                    foreach (Vector2 sample in samples)
                    {
                        int selectedBiome = _sampler.GetBiomeAtInterpolatedCoords(_biomeMap, sample.x, sample.y);

                        if (iterations > coroutineRes)
                        {
                            iterations = 0;
                            yield return(null);
                        }
                        if (selectedBiome != i)
                        {
                            continue; //Not in this biome, skip
                        }

                        //Check whether a tree can be placed here
                        float   amp    = TerraConfig.Instance.Generator.Amplitude;
                        float   height = _terrain.terrainData.GetInterpolatedHeight(sample.x, sample.y) / amp;
                        float   angle  = Vector3.Angle(Vector3.up, _terrain.terrainData.GetInterpolatedNormal(sample.x, sample.y)) / 90;
                        Vector2 world  = MathUtil.NormalToWorld(_tile.GridPosition, sample);

                        if (treeNode.ShouldPlaceAt(world.x, world.y, height, angle))
                        {
                            //Add tree to terrain
                            Vector3 treeLoc = new Vector3(sample.x, height, sample.y);

                            //Tree sample set index matches the tree prototype index (j)
                            TreeInstance tree = treeNode.GetTreeInstance(treeLoc, prototypeIndex, _tile.Random);
                            _terrain.AddTreeInstance(tree);
                        }
                    }

                    prototypeIndex++;
                }
            }
        }