/// <summary>
 /// Returns the index of the landscape texture.  -1 if not found
 /// </summary>
 /// <returns>The texture index. -1 if not found</returns>
 /// <param name="textureType">Texture type.</param>
 int GetTextureIndex(SimpleCityLandscapeTextureType textureType)
 {
     for (int i = 0; i < textures.Length; i++)
     {
         if (textures[i].textureType == textureType)
         {
             return(i);
         }
     }
     return(-1);  // Doesn't exist
 }
        void UpdateBaseTexture(SimpleCityDungeonModel model, float[,,] map)
        {
            if (terrain == null)
            {
                return;
            }
            int fillIndex = GetTextureIndex(SimpleCityLandscapeTextureType.Fill);

            if (fillIndex < 0)
            {
                return;
            }

            var data = terrain.terrainData;


            // Fill up the entire space with the fill texture
            for (var y = 0; y < data.alphamapHeight; y++)
            {
                for (var x = 0; x < data.alphamapWidth; x++)
                {
                    for (int t = 0; t < textures.Length; t++)
                    {
                        var ratio = (t == fillIndex) ? 1 : 0;
                        map[y, x, t] = ratio;
                    }
                }
            }

            var activeTextureTypes = new SimpleCityLandscapeTextureType[] {
                SimpleCityLandscapeTextureType.Park,
                SimpleCityLandscapeTextureType.Road,
                SimpleCityLandscapeTextureType.CityWallPadding,
            };

            var activeCellTypes = new SimpleCityCellType[] {
                SimpleCityCellType.Park,
                SimpleCityCellType.Road,
                SimpleCityCellType.CityWallPadding,
            };

            var dataMaps = new List <float[, ]>();

            for (int i = 0; i < activeTextureTypes.Length; i++)
            {
                dataMaps.Add(new float[map.GetLength(0), map.GetLength(1)]);
            }

            var gridSize2D = model.Config.CellSize;
            var gridSize   = new Vector3(gridSize2D.x, 0, gridSize2D.y);
            var cells      = new List <SimpleCityCell>();

            foreach (var cell in model.Cells)
            {
                cells.Add(cell);
            }
            cells.AddRange(model.WallPaddingCells);

            foreach (var cell in cells)
            {
                var locationGrid = cell.Position;
                var location = locationGrid * gridSize - gridSize / 2.0f;
                var size = gridSize;
                int gx1, gy1, gx2, gy2;
                LandscapeDataRasterizer.WorldToTerrainTextureCoord(terrain, location.x, location.z, out gx1, out gy1);
                LandscapeDataRasterizer.WorldToTerrainTextureCoord(terrain, location.x + size.x, location.z + size.z, out gx2, out gy2);
                for (int i = 0; i < activeTextureTypes.Length; i++)
                {
                    //SimpleCityLandscapeTextureType activeTexType = activeTextureTypes[i];
                    SimpleCityCellType activeCellType = activeCellTypes[i];
                    //int textureIndex = GetTextureIndex(activeTexType);
                    var dataMap = dataMaps[i];

                    for (var gx = gx1; gx <= gx2; gx++)
                    {
                        for (var gy = gy1; gy <= gy2; gy++)
                        {
                            dataMap[gy, gx] = (cell.CellType == activeCellType) ? 1 : 0;
                        }
                    }
                }
            }

            // Blur the layout data
            var filter = new BlurFilter(roadBlurDistance);

            for (int i = 0; i < dataMaps.Count; i++)
            {
                dataMaps[i] = filter.ApplyFilter(dataMaps[i]);
            }

            for (int i = 0; i < dataMaps.Count; i++)
            {
                var dataMap      = dataMaps[i];
                int textureIndex = GetTextureIndex(activeTextureTypes[i]);
                if (textureIndex < 0)
                {
                    continue;
                }
                for (var y = 0; y < data.alphamapHeight; y++)
                {
                    for (var x = 0; x < data.alphamapWidth; x++)
                    {
                        map[y, x, textureIndex] = dataMap[y, x];
                        if (textureIndex != fillIndex)
                        {
                            map[y, x, fillIndex] -= dataMap[y, x];
                            map[y, x, fillIndex]  = Mathf.Clamp01(map[y, x, fillIndex]);
                        }
                    }
                }
            }

            // Normalize
            for (var y = 0; y < data.alphamapHeight; y++)
            {
                for (var x = 0; x < data.alphamapWidth; x++)
                {
                    // Apply the curves
                    for (int t = 0; t < textures.Length; t++)
                    {
                        var curve = textures[t].curve;
                        if (curve != null && curve.keys.Length > 0)
                        {
                            map[y, x, t] = curve.Evaluate(map[y, x, t]);
                        }
                    }

                    float sum = 0;
                    for (int t = 0; t < textures.Length; t++)
                    {
                        sum += map[y, x, t];
                    }

                    for (int t = 0; t < textures.Length; t++)
                    {
                        map[y, x, t] /= sum;
                    }
                }
            }

            for (int layer = 0; layer < data.detailPrototypes.Length; layer++)
            {
                var foliageMap = data.GetDetailLayer(0, 0, data.detailWidth, data.detailHeight, layer);

                for (int x = 0; x < data.detailWidth; x++)
                {
                    float nx      = x / (float)(data.detailWidth - 1);
                    int   sampleX = Mathf.RoundToInt(nx * (data.alphamapWidth - 1));
                    for (int y = 0; y < data.detailHeight; y++)
                    {
                        float ny      = y / (float)(data.detailHeight - 1);
                        int   sampleY = Mathf.RoundToInt(ny * (data.alphamapHeight - 1));

                        float influence = 0;
                        foreach (var foliageTheme in foliage)
                        {
                            var textureIndex = GetTextureIndex(foliageTheme.textureType);
                            if (textureIndex < 0)
                            {
                                continue;
                            }
                            foreach (var entry in foliageTheme.foliageEntries)
                            {
                                if (entry.grassIndex == layer)
                                {
                                    float mapData = map[sampleY, sampleX, textureIndex];
                                    if (foliageTheme.curve != null && foliageTheme.curve.length > 0)
                                    {
                                        mapData = foliageTheme.curve.Evaluate(mapData);
                                    }
                                    float alpha = mapData * entry.density * foliageTheme.density;
                                    influence += alpha;
                                }
                            }
                        }

                        int   value = Mathf.FloorToInt(influence);
                        float frac  = influence - value;
                        if (Random.value < frac)
                        {
                            value++;
                        }
                        foliageMap[y, x] = value;
                    }
                }

                data.SetDetailLayer(0, 0, layer, foliageMap);
            }

            /*
             * // Update foliage
             * foreach (var foliageTheme in foliage)
             * {
             *  var textureIndex = GetTextureIndex(foliageTheme.textureType);
             *  if (textureIndex < 0) continue;
             *  foreach (var entry in foliageTheme.foliageEntries)
             *  {
             *      int layer = entry.grassIndex;
             *      var foliageMap = data.GetDetailLayer(0, 0, data.detailWidth, data.detailHeight, layer);
             *      for (int x = 0; x < data.detailWidth; x++)
             *      {
             *          float nx = x / (float)(data.detailWidth - 1);
             *          int sampleX = Mathf.RoundToInt(nx * (data.alphamapWidth - 1));
             *          for (int y = 0; y < data.detailHeight; y++)
             *          {
             *              float ny = y / (float)(data.detailHeight - 1);
             *              int sampleY = Mathf.RoundToInt(ny * (data.alphamapHeight - 1));
             *
             *              float alpha = map[sampleY, sampleX, textureIndex] * entry.density * foliageTheme.density;
             *              int value = Mathf.FloorToInt(alpha);
             *              float frac = alpha - value;
             *              if (Random.value < frac) value++;
             *              foliageMap[y, x] = value;
             *          }
             *      }
             *
             *      data.SetDetailLayer(0, 0, layer, foliageMap);
             *  }
             * }
             */
        }