public void OnSelectionChanged(ResourceTileSelection selection) { List<int> ids = new List<int>(selection.resource_tile_ids); if (tileIds.Count == ids.Count) { return; } if (ids.Count <= 0) { FloodFill(); } else { if (tileIds.Count < ids.Count) { tileIds = ids; } TerrainManager.Status status; ResourceTileLite[] tiles = TerrainManager.GetResourceTileCacheGroup(out status,tileIds.ToArray()); if (status == TerrainManager.Status.Succeeded) { Region region = new Region(tiles); region.ToTerrainRegion(out region); PaintRegion(region); } } tileIds = ids; }
/// <summary> /// Sets the terrain from resourceTiles. /// </summary> /// <param name='resourceTiles'> /// Microtiles. /// </param> /// <param name='mode'> /// Mode. /// </param> public void SetTerrainFromResourceTiles(ResourceTile[] resourceTiles, SetTerrainMode mode) { if (resourceTiles.Length <= 0) { // return; // if this case actually gets hit I want to know what is causing it. throw new System.ArgumentException("Please find out why the resourceTile array was empty and tell Adam."); } // if the view is not entirely terrain, clear it and move it to the center of the view if (!m_isTerrainFixedInPlace && !CameraRig.use.isViewFrustumEntirelyTerrain ) { ClearTerrain(SetTerrainMode.NoFlush); MoveTerrainToCenterOfView(); } // determine region of update to minimize calls to Terrain APIs Region region = new Region(resourceTiles); // clear structures in the region ClearBuildingsInRegion(region); // convert to terrain-space region region.ToTerrainRegion( out region ); // get current properties for the region float[,] heights = terrainData.GetHeights(region.left, region.bottom, region.width, region.height); float[,,] splats = terrainData.GetAlphamaps(region.left, region.bottom, region.width, region.height); int[][,] details = new int[terrainData.detailPrototypes.Length][,]; for (int i=0; i<details.Length; i++) { details[i] = terrainData.GetDetailLayer(region.left, region.bottom, region.width, region.height, i); } // update values as needed int xOffset = (int)terrain.transform.position.x + region.left; int zOffset = (int)terrain.transform.position.z + region.bottom; Building b = null; foreach (ResourceTile tile in resourceTiles) { // get coordinates in the space of the chunk int x = tile.x - xOffset; int z = tile.z - zOffset; // skip any resourceTiles that are out of bounds, as when e.g., server returns a bigger cached chunk than we need if (x<0 || x>heights.GetUpperBound(1) || z<0 || z>heights.GetUpperBound(0) ) { continue; } // // cache stuff that is not collapsed into other representations // resourceTileCache[region.bottom+z,region.left+x] = new ResourceTileLite(tile); // set heights GroundTextureType ground = tile.groundTextureType; heights[z,x] = (ground==GroundTextureType.Water)?0f:terrainData.size.y; // set ground texture for (int i=0; i<=splats.GetUpperBound(2); ++i) { splats[z,x,i] = 0f; } splats[z,x,(int)ground] = 1f; // get the raw number of trees of each type int[] treeCounts = tile.GetTreeCountsByGraphicType(); // remap tree counts to the range for detail values for (int i=0; i<treeCounts.Length; ++i) { treeCounts[i] = (int)(detailResolutionPerPatch*Mathf.Min(treeCounts[i]*ResourceTile.oneOverMaxNumberOfTreesPerAcre, 1f)); } // set details for (int i=0; i<treeCounts.Length; ++i) { details[i][z,x] = treeCounts[i]; } // add structures if (tile.hasOutpost && !m_outpostInstances.ContainsKey(tile.id)) { m_outpostInstances.Add( tile.id, Instantiate(m_outpostPrefab, tile.GetCenterPoint(), Quaternion.identity) as ResearchOutpost ); } else if (!tile.hasOutpost && m_outpostInstances.ContainsKey(tile.id)) { Destroy(m_outpostInstances[tile.id].gameObject); m_outpostInstances.Remove(tile.id); } b = buildHousingAction.GetBuildingWithCapacity(tile.housingCapacity); if (b==null) { continue; } Building building = Instantiate(b, tile.GetCenterPoint(), Quaternion.identity) as Building; building.gameObject.transform.parent = m_objectGrouper.transform; m_buildingInstances.Add(building.gameObject); } // cache stuff that is not collapsed into other representations // NOTE: must do afterward for now, since it relies on e.g. research outpost locations; can go back once server sets permissions foreach (ResourceTile tile in resourceTiles) { // get coordinates in the space of the chunk int x = tile.x - xOffset; int z = tile.z - zOffset; // skip any resourceTiles that are out of bounds, as when e.g., server returns a bigger cached chunk than we need if (x<0 || x>heights.GetUpperBound(1) || z<0 || z>heights.GetUpperBound(0) ) { continue; } resourceTileCache[region.bottom+z,region.left+x] = new ResourceTileLite(tile); } // apply results terrainData.SetHeights(region.left, region.bottom, heights); terrainData.SetAlphamaps(region.left, region.bottom, splats); for (int i=0; i<details.Length; i++) { terrainData.SetDetailLayer(region.left, region.bottom, i, details[i]); } // set the cleared flag if (region.width>0 && region.height>0) { m_isTerrainDataCleared = false; } // flush if requested if (mode == SetTerrainMode.Flush) { terrain.Flush(); } // broadcast that tiles have finished loading MessengerAM.Send(new MessageLoadedNewTiles(region)); Messenger<Region>.Broadcast(kLoadedNewTiles,region); }
/// <summary> /// Clears the trees in region. /// </summary> /// <param name='region'> /// Region in world space specifying resource tiles to clear. /// </param> /// <param name='mode'> /// Mode. /// </param> private void ClearTreesInRegion(Region region, SetTerrainMode mode) { // set all details to 0 in the region region.ToTerrainRegion( out region ); int[,] details = new int[region.right-region.left+1, region.top-region.bottom+1]; for (int i=0; i<terrainData.detailPrototypes.Length; i++) terrainData.SetDetailLayer(region.left, region.bottom, i, details); // flush if requested if (mode == SetTerrainMode.Flush) { terrain.Flush(); } }