/// <summary>
            /// Computes positions for this Tile and caches
            /// them.
            /// </summary>
            public void ComputePositions()
            {
                Positions = new PositionsContainer[Pool._placer.ObjectsToPlace.Count];
                UnityEngine.Terrain t = Tile.MeshManager.ActiveTerrain;
                float amp             = TerraConfig.Instance.Generator.Amplitude;

                for (int i = 0; i < Positions.Length; i++)
                {
                    ObjectDetailNode objectPlacementData = Pool._placer.ObjectsToPlace[i];
                    Vector2[]        samples             = objectPlacementData.SamplePositions(Tile.Random);
                    List <Vector3>   worldPositions      = new List <Vector3>((int)(Positions.Length * 0.66f));

                    for (var j = 0; j < samples.Length; j++)
                    {
                        Vector2 pos    = samples[j];
                        float   height = t.terrainData.GetInterpolatedHeight(pos.x, pos.y);
                        float   angle  = Vector3.Angle(Vector3.up, t.terrainData.GetInterpolatedNormal(pos.x, pos.y)) / 90;
                        Vector2 world  = MathUtil.NormalToWorld(Tile.GridPosition, pos);

                        if (objectPlacementData.ShouldPlaceAt(world.x, world.y, height / amp, angle))
                        {
                            worldPositions.Add(new Vector3(world.x, height, world.y));
                        }
                    }

                    Positions[i] = new PositionsContainer(worldPositions.ToArray(), objectPlacementData);
                }
            }
            /// <summary>
            /// Gets the container that holds the passed
            /// ObjectPlacementType
            /// </summary>
            /// <param name="objectPlacementData">type to search for</param>
            /// <returns>ObjectContainer, null if no matches were found</returns>
            ObjectContainer GetContainerForType(ObjectDetailNode objectPlacementData)
            {
                foreach (ObjectContainer c in Pool._containers)
                {
                    if (c.ObjectPlacementData.Equals(objectPlacementData))
                    {
                        return(c);
                    }
                }

                return(null);
            }
        public static void Show(ObjectDetailNodeEditor objectNode)
        {
            EditorGUI.BeginChangeCheck();

            ObjectDetailNode obj = objectNode.ObjectDetailNode;

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

            Show(obj, () => {
                //Translate
                obj.ShowTranslateFoldout = EditorGUILayout.Foldout(obj.ShowTranslateFoldout, "Translate");
                if (obj.ShowTranslateFoldout)
                {
                    obj.TranslationAmount = EditorGUILayout.Vector3Field("Translate", obj.TranslationAmount);

                    EditorGUILayout.BeginHorizontal();
                    obj.IsRandomTranslate = EditorGUILayout.Toggle("Random", obj.IsRandomTranslate);
                    if (GUILayout.Button("?", GUILayout.Width(25)))
                    {
                        const string msg = "Optionally randomly translate the placed object. " +
                                           "Max and min extents for the random number generator can " +
                                           "be set.";
                        EditorUtility.DisplayDialog("Help - Random Translate", msg, "Close");
                    }
                    EditorGUILayout.EndHorizontal();

                    if (obj.IsRandomTranslate)
                    {
                        EditorGUI.indentLevel = 1;

                        obj.RandomTranslateExtents.Min = EditorGUILayout.Vector3Field("Min", obj.RandomTranslateExtents.Min);
                        obj.RandomTranslateExtents.Max = EditorGUILayout.Vector3Field("Max", obj.RandomTranslateExtents.Max);

                        FitMinMax(ref obj.RandomTranslateExtents.Min, ref obj.RandomTranslateExtents.Max);
                        EditorGUI.indentLevel = 0;
                    }
                }

                //Rotate
                obj.ShowRotateFoldout = EditorGUILayout.Foldout(obj.ShowRotateFoldout, "Rotate");
                if (obj.ShowRotateFoldout)
                {
                    obj.RotationAmount = EditorGUILayout.Vector3Field("Rotation", obj.RotationAmount);

                    EditorGUILayout.BeginHorizontal();
                    obj.IsRandomRotation = EditorGUILayout.Toggle("Random", obj.IsRandomRotation);
                    if (GUILayout.Button("?", GUILayout.Width(25)))
                    {
                        const string msg = "Optionally randomly rotate the placed object. " +
                                           "Max and min extents for the random number generator can " +
                                           "be set.";
                        EditorUtility.DisplayDialog("Help - Random Rotate", msg, "Close");
                    }
                    EditorGUILayout.EndHorizontal();

                    if (obj.IsRandomRotation)
                    {
                        EditorGUI.indentLevel = 1;

                        obj.RandomRotationExtents.Min = EditorGUILayout.Vector3Field("Min", obj.RandomRotationExtents.Min);
                        obj.RandomRotationExtents.Max = EditorGUILayout.Vector3Field("Max", obj.RandomRotationExtents.Max);

                        FitMinMax(ref obj.RandomRotationExtents.Min, ref obj.RandomRotationExtents.Max);
                        EditorGUI.indentLevel = 0;
                    }
                }

                //Scale
                obj.ShowScaleFoldout = EditorGUILayout.Foldout(obj.ShowScaleFoldout, "Scale");
                if (obj.ShowScaleFoldout)
                {
                    obj.ScaleAmount = EditorGUILayout.Vector3Field("Scale", obj.ScaleAmount);

                    EditorGUILayout.BeginHorizontal();
                    obj.IsRandomScale = EditorGUILayout.Toggle("Random", obj.IsRandomScale);
                    if (GUILayout.Button("?", GUILayout.Width(25)))
                    {
                        const string msg = "Optionally randomly scale the placed object. " +
                                           "Max and min extents for the random number generator can " +
                                           "be set.";
                        EditorUtility.DisplayDialog("Help - Random Scale", msg, "Close");
                    }
                    EditorGUILayout.EndHorizontal();

                    if (obj.IsRandomScale)
                    {
                        obj.IsUniformScale = EditorGUILayout.Toggle("Scale Uniformly", obj.IsUniformScale);

                        EditorGUI.indentLevel = 1;

                        if (obj.IsUniformScale)
                        {
                            obj.UniformScaleMin = EditorGUILayout.FloatField("Min", obj.UniformScaleMin);
                            obj.UniformScaleMax = EditorGUILayout.FloatField("Max", obj.UniformScaleMax);
                        }
                        else
                        {
                            obj.RandomScaleExtents.Min = EditorGUILayout.Vector3Field("Min", obj.RandomScaleExtents.Min);
                            obj.RandomScaleExtents.Max = EditorGUILayout.Vector3Field("Max", obj.RandomScaleExtents.Max);

                            FitMinMax(ref obj.RandomScaleExtents.Min, ref obj.RandomScaleExtents.Max);
                        }
                        EditorGUI.indentLevel = 0;
                    }
                }
            });

            if (EditorGUI.EndChangeCheck())
            {
                objectNode.serializedObject.ApplyModifiedProperties();
            }
        }
 public PositionsContainer(Vector3[] positions, ObjectDetailNode objectPlacementData)
 {
     Positions           = positions;
     ObjectPlacementData = objectPlacementData;
 }
 public ObjectContainer(ObjectDetailNode objectPlacementData)
 {
     ObjectPlacementData = objectPlacementData;
 }