public static TerrainLayer GetLayerFromPrototype(ResourceProtoTexture proto) { foreach (Terrain t in Terrain.activeTerrains) { foreach (TerrainLayer layer in t.terrainData.terrainLayers) { if (proto != null && layer != null) { if (proto.m_texture != null && layer.diffuseTexture != null) { if (PWCommon4.Utils.IsSameTexture(proto.m_texture, layer.diffuseTexture, false) == true) { return(layer); } } } } } return(null); }
/// <summary> /// Extract and save the resources file /// </summary> /// <param name="writer"></param> /// <param name="source"></param> private void SaveResources(StreamWriter writer, GaiaResource source) { if (writer == null) { Debug.LogError("Can not write resources, writer not supplied."); return; } if (source == null) { Debug.LogError("Can not write resources, resources not supplied."); return; } //Create extraction path string path = "Assets/GaiaExtensions/"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } path += m_extensionName + "/"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } path += Path.GetFileName(AssetDatabase.GetAssetPath(source.GetInstanceID())); GaiaResource resources = ScriptableObject.CreateInstance <Gaia.GaiaResource>(); AssetDatabase.CreateAsset(resources, path); resources.m_beachHeight = source.m_beachHeight; resources.m_name = source.m_name; resources.m_resourcesID = source.m_resourcesID; resources.m_seaLevel = source.m_seaLevel; resources.m_terrainHeight = source.m_terrainHeight; //Iterate through the prototypes SpawnCritera srcCrit, newCrit; ResourceProtoTexture srcTex, newTex; resources.m_texturePrototypes = new ResourceProtoTexture[source.m_texturePrototypes.GetLength(0)]; for (int resIdx = 0; resIdx < source.m_texturePrototypes.GetLength(0); resIdx++) { srcTex = source.m_texturePrototypes[resIdx]; newTex = new ResourceProtoTexture(); newTex.m_metalic = srcTex.m_metalic; newTex.m_name = srcTex.m_name; newTex.m_normal = srcTex.m_normal; newTex.m_offsetX = srcTex.m_offsetX; newTex.m_offsetY = srcTex.m_offsetY; newTex.m_sizeX = srcTex.m_sizeX; newTex.m_sizeY = srcTex.m_sizeY; newTex.m_smoothness = srcTex.m_smoothness; newTex.m_texture = srcTex.m_texture; newTex.m_spawnCriteria = new SpawnCritera[srcTex.m_spawnCriteria.GetLength(0)]; for (int critIdx = 0; critIdx < srcTex.m_spawnCriteria.GetLength(0); critIdx++) { srcCrit = srcTex.m_spawnCriteria[critIdx]; newCrit = new SpawnCritera(); newCrit.m_checkHeight = srcCrit.m_checkHeight; newCrit.m_checkProximity = srcCrit.m_checkProximity; newCrit.m_checkSlope = srcCrit.m_checkSlope; newCrit.m_checkTexture = srcCrit.m_checkTexture; newCrit.m_checkType = srcCrit.m_checkType; newCrit.m_heightFitness = srcCrit.m_heightFitness; newCrit.m_isActive = srcCrit.m_isActive; newCrit.m_matchingTextures = srcCrit.m_matchingTextures; newCrit.m_maxHeight = srcCrit.m_maxHeight; newTex.m_spawnCriteria[critIdx] = newCrit; } resources.m_texturePrototypes[resIdx] = newTex; } }
/// <summary> /// Takes a spawner preset list and assembles arrays with the new prototypes in them. If a reference Terrain is passed in, the arrays will contain the existing prototypes on the terrain + only the additional stuff from the preset list, no duplicates. /// </summary> /// <param name="spawnerPresetList"></param> /// <param name="terrainLayers"></param> /// <param name="terrainDetails"></param> /// <param name="terrainTrees"></param> /// <param name="referenceTerrain"></param> public static void GetPrototypes(List <BiomeSpawnerListEntry> spawnerPresetList, ref TerrainLayer[] terrainLayers, ref DetailPrototype[] terrainDetails, ref TreePrototype[] terrainTrees, Terrain referenceTerrain = null) { //Early out when no spawner preset list if (spawnerPresetList == null || spawnerPresetList.Count == 0) { return; } //collect the splat prototypes in a GaiaSplatPrototype List first, then build a terrain layer array from that later List <GaiaSplatPrototype> presetSplatPrototypes = new List <GaiaSplatPrototype>(); List <DetailPrototype> presetTerrainDetails = new List <DetailPrototype>(); List <TreePrototype> presetTerrainTrees = new List <TreePrototype>(); //if there is a reference terrain, start by pre-filling those lists with the prototypes from the terrain if (referenceTerrain != null) { foreach (TerrainLayer layer in referenceTerrain.terrainData.terrainLayers) { presetSplatPrototypes.Add(new GaiaSplatPrototype(layer)); } foreach (DetailPrototype detailPrototype in referenceTerrain.terrainData.detailPrototypes) { presetTerrainDetails.Add(detailPrototype); } foreach (TreePrototype treePrototype in referenceTerrain.terrainData.treePrototypes) { presetTerrainTrees.Add(treePrototype); } } foreach (BiomeSpawnerListEntry preset in spawnerPresetList.Where(x => x.m_autoAssignPrototypes == true)) { if (preset == null) { //Skip entries missing information continue; } if (preset.m_spawnerSettings == null) { continue; } if (preset.m_spawnerSettings.m_resources == null) { continue; } GaiaResource resources = preset.m_spawnerSettings.m_resources; foreach (SpawnRule sr in preset.m_spawnerSettings.m_spawnerRules) { //skip if resource is not maintained properly (=null) if (sr.ResourceIsNull(preset.m_spawnerSettings)) { Debug.Log("Spawn Rule " + sr.m_name + " in " + preset.m_spawnerSettings.name + " has missing resources maintained. This rule might not work properly when spawning later."); continue; } switch (sr.m_resourceType) { case GaiaConstants.SpawnerResourceType.TerrainTexture: ResourceProtoTexture protoTexture = resources.m_texturePrototypes[sr.m_resourceIdx]; if (protoTexture != null) { GaiaSplatPrototype newSplat = new GaiaSplatPrototype(); newSplat.normalMap = protoTexture.m_normal; newSplat.normalScale = protoTexture.m_normalScale; newSplat.smoothness = protoTexture.m_smoothness; newSplat.metallic = protoTexture.m_metallic; newSplat.diffuseRemapMin = protoTexture.m_diffuseRemapMin; newSplat.diffuseRemapMax = protoTexture.m_diffuseRemapMax; newSplat.maskMapRemapMin = protoTexture.m_maskMapRemapMin; newSplat.maskMapRemapMax = protoTexture.m_maskMapRemapMax; newSplat.specularColor = protoTexture.m_specularColor; newSplat.tileOffset = new Vector2(protoTexture.m_offsetX, protoTexture.m_offsetY); newSplat.tileSize = new Vector2(protoTexture.m_sizeX, protoTexture.m_sizeY); newSplat.texture = protoTexture.m_texture; newSplat.maskMap = protoTexture.m_maskmap; //Only add as a new prototype if not a fully equal prototype already exists in the list if (!presetSplatPrototypes.Exists(x => x.texture == newSplat.texture && x.normalMap == newSplat.normalMap && x.tileOffset == newSplat.tileOffset && x.tileSize == newSplat.tileSize )) { presetSplatPrototypes.Add(newSplat); } } break; case GaiaConstants.SpawnerResourceType.TerrainDetail: ResourceProtoDetail protoDetail = resources.m_detailPrototypes[sr.m_resourceIdx]; if (protoDetail != null) { DetailPrototype newTerrainDetail = new DetailPrototype(); newTerrainDetail.renderMode = protoDetail.m_renderMode; newTerrainDetail.prototypeTexture = protoDetail.m_detailTexture; newTerrainDetail.prototype = protoDetail.m_detailProtoype; newTerrainDetail.dryColor = protoDetail.m_dryColour; newTerrainDetail.healthyColor = protoDetail.m_healthyColour; newTerrainDetail.maxHeight = protoDetail.m_maxHeight; newTerrainDetail.maxWidth = protoDetail.m_maxWidth; newTerrainDetail.minHeight = protoDetail.m_minHeight; newTerrainDetail.minWidth = protoDetail.m_minWidth; newTerrainDetail.noiseSpread = protoDetail.m_noiseSpread; if ((protoDetail.m_renderMode == DetailRenderMode.Grass && protoDetail.m_detailProtoype == null) || protoDetail.m_renderMode == DetailRenderMode.GrassBillboard) { if (!presetTerrainDetails.Exists(x => x.prototypeTexture == newTerrainDetail.prototypeTexture && x.prototype == newTerrainDetail.prototype && x.dryColor == newTerrainDetail.dryColor && x.healthyColor == newTerrainDetail.healthyColor && x.maxHeight == newTerrainDetail.maxHeight && x.maxWidth == newTerrainDetail.maxWidth && x.minHeight == newTerrainDetail.minHeight && x.minWidth == newTerrainDetail.minWidth && x.noiseSpread == newTerrainDetail.noiseSpread )) { presetTerrainDetails.Add(newTerrainDetail); } } else { if (!presetTerrainDetails.Exists(x => x.prototype == newTerrainDetail.prototype && x.prototype == newTerrainDetail.prototype && x.dryColor == newTerrainDetail.dryColor && x.healthyColor == newTerrainDetail.healthyColor && x.maxHeight == newTerrainDetail.maxHeight && x.maxWidth == newTerrainDetail.maxWidth && x.minHeight == newTerrainDetail.minHeight && x.minWidth == newTerrainDetail.minWidth && x.noiseSpread == newTerrainDetail.noiseSpread )) { presetTerrainDetails.Add(newTerrainDetail); } } } break; case GaiaConstants.SpawnerResourceType.TerrainTree: ResourceProtoTree protoTree = resources.m_treePrototypes[sr.m_resourceIdx]; if (protoTree != null) { TreePrototype newTree = new TreePrototype(); newTree.bendFactor = protoTree.m_bendFactor; newTree.prefab = protoTree.m_desktopPrefab; if (!presetTerrainTrees.Exists(x => x.bendFactor == newTree.bendFactor && x.prefab == newTree.prefab)) { presetTerrainTrees.Add(newTree); } } break; } } } //now look at the existing terrain layers on the terrain again, and add only the additional new Splat Prototypes as new layers - all the other ones must exist on the terrains already List <GaiaSplatPrototype> additionalSplatPrototypes = new List <GaiaSplatPrototype>(); List <DetailPrototype> additionalTerrainDetails = new List <DetailPrototype>(); List <TreePrototype> additionalTerrainTrees = new List <TreePrototype>(); //Do we have a refernece terrain? The only the splat prototypes with a higher index then what is currently present on the terrain already are relevant if (referenceTerrain != null) { for (int i = referenceTerrain.terrainData.terrainLayers.Length; i <= presetSplatPrototypes.Count - 1; i++) { additionalSplatPrototypes.Add(presetSplatPrototypes[i]); } for (int i = referenceTerrain.terrainData.detailPrototypes.Length; i <= presetTerrainDetails.Count - 1; i++) { additionalTerrainDetails.Add(presetTerrainDetails[i]); } for (int i = referenceTerrain.terrainData.treePrototypes.Length; i <= presetTerrainTrees.Count - 1; i++) { additionalTerrainTrees.Add(presetTerrainTrees[i]); } } else { //no reference terrain - we take preset prototypes collected before additionalSplatPrototypes = presetSplatPrototypes; additionalTerrainDetails = presetTerrainDetails; additionalTerrainTrees = presetTerrainTrees; } //convert Gaia Splat Prototypes into actual terrain layer files string layername = string.Format("Gaia_-{0:yyyyMMdd-HHmmss}", DateTime.Now); TerrainLayer[] additionalTerrainLayers = GaiaSplatPrototype.CreateTerrainLayers(layername, additionalSplatPrototypes.ToArray()); if (referenceTerrain != null) { //got a reference terrain? return the existing prototypes so they are not altered and attach the truly new ones terrainLayers = referenceTerrain.terrainData.terrainLayers; terrainLayers = terrainLayers.Concat(additionalTerrainLayers).ToArray(); terrainDetails = referenceTerrain.terrainData.detailPrototypes; terrainDetails = terrainDetails.Concat(additionalTerrainDetails.ToArray()).ToArray(); terrainTrees = referenceTerrain.terrainData.treePrototypes; terrainTrees = terrainTrees.Concat(additionalTerrainTrees.ToArray()).ToArray(); } else { //no reference terrain, just return all the new stuff directly terrainLayers = additionalTerrainLayers; terrainDetails = additionalTerrainDetails.ToArray(); terrainTrees = additionalTerrainTrees.ToArray(); } }
public Spawner CreateSpawner(bool autoAddResources = false, Transform targetTransform = null) { //Find or create gaia GameObject gaiaObj = GaiaUtils.GetGaiaGameObject(); GameObject spawnerObj = new GameObject(this.name); spawnerObj.AddComponent <Spawner>(); if (targetTransform != null) { spawnerObj.transform.parent = targetTransform; } else { spawnerObj.transform.parent = gaiaObj.transform; } Spawner spawner = spawnerObj.GetComponent <Spawner>(); spawner.LoadSettings(this); //spawner.m_settings.m_resources = (GaiaResource)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(this.m_resourcesGUID), typeof(GaiaResource)); if (autoAddResources) { TerrainLayer[] terrainLayers = new TerrainLayer[0]; DetailPrototype[] terrainDetails = new DetailPrototype[0]; TreePrototype[] terrainTrees = new TreePrototype[0]; GaiaDefaults.GetPrototypes(new List <BiomeSpawnerListEntry>() { new BiomeSpawnerListEntry() { m_spawnerSettings = this, m_autoAssignPrototypes = true } }, ref terrainLayers, ref terrainDetails, ref terrainTrees, Terrain.activeTerrain); foreach (Terrain t in Terrain.activeTerrains) { GaiaDefaults.ApplyPrototypesToTerrain(t, terrainLayers, terrainDetails, terrainTrees); } } //We need to check the texture prototypes in this spawner against the already created terrain layers for this session //- otherwise the spawner will not know about those in subsequent spawns and might create unneccessary additional layers //Get a list of all exisiting Terrain Layers for this session string path = GaiaDirectories.GetTerrainLayerPath(); #if UNITY_EDITOR AssetDatabase.ImportAsset(path); if (Directory.Exists(path)) { string[] allLayerGuids = AssetDatabase.FindAssets("t:TerrainLayer", new string[1] { path }); List <TerrainLayer> existingTerrainLayers = new List <TerrainLayer>(); foreach (string guid in allLayerGuids) { try { TerrainLayer layer = (TerrainLayer)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid), typeof(TerrainLayer)); if (layer != null) { existingTerrainLayers.Add(layer); } } catch (Exception ex) { if (ex.Message == "") { } } } foreach (SpawnRule sr in spawner.m_settings.m_spawnerRules) { if (sr.m_resourceType == SpawnerResourceType.TerrainTexture) { ResourceProtoTexture protoTexture = spawner.m_settings.m_resources.m_texturePrototypes[sr.m_resourceIdx]; //if a terrainLayer with these properties exist we can assume it fits to the given spawn rule TerrainLayer terrainLayer = existingTerrainLayers.FirstOrDefault(x => x.diffuseTexture == protoTexture.m_texture && x.normalMapTexture == protoTexture.m_normal && x.tileOffset == new Vector2(protoTexture.m_offsetX, protoTexture.m_offsetY) && x.tileSize == new Vector2(protoTexture.m_sizeX, protoTexture.m_sizeY) ); if (terrainLayer != null) { protoTexture.m_LayerGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(terrainLayer)); } } } } #endif foreach (SpawnRule rule in spawner.m_settings.m_spawnerRules) { rule.m_spawnedInstances = 0; } if (Terrain.activeTerrains.Where(x => !TerrainHelper.IsWorldMapTerrain(x)).Count() > 0) { spawner.FitToAllTerrains(); } //else //{ // spawner.FitToTerrain(); //} return(spawner); }