/// <summary> /// Returns terrain names of terrains that intersect with the given bounds object /// </summary> /// <param name="bounds">A bounds object to check against the terrains. Needs to be in absolute world space position, mind the current origin offset!</param> /// <returns></returns> public static string[] GetTerrainsIntersectingBounds(BoundsDouble bounds) { //Reduce the bounds size a bit to prevent selecting terrains that are perfectly aligned with the bounds border //-this leads to too many terrains being logged as affected by an operation otherwise. Bounds intersectingBounds = new BoundsDouble(); intersectingBounds.center = bounds.center; intersectingBounds.size = bounds.size - new Vector3Double(0.001f, 0.001f, 0.001f); if (GaiaUtils.HasDynamicLoadedTerrains()) { GaiaSessionManager sessionManager = GaiaSessionManager.GetSessionManager(); if (sessionManager == null) { Debug.LogError("Trying to get terrains that intersect with bounds, but there is no session manager in scene."); return(null); } return(TerrainLoaderManager.TerrainScenes.Where(x => x.m_bounds.Intersects(intersectingBounds)).Select(x => x.GetTerrainName()).ToArray()); } else { List <string> affectedTerrainNames = new List <string>(); foreach (Terrain t in Terrain.activeTerrains) { if (intersectingBounds.Intersects(TerrainHelper.GetWorldSpaceBounds(t))) { affectedTerrainNames.Add(t.name); } } return(affectedTerrainNames.ToArray()); } }
void OnDrawGizmosSelected() { #if UNITY_EDITOR if (Selection.activeObject == gameObject) { if (m_showBoundingBox) { Gizmos.color = Color.red; Gizmos.DrawWireCube(transform.position, new Vector3(m_settings.m_range * 2f, m_settings.m_range * 2f, m_settings.m_range * 2f)); } //Water if (m_showSeaLevelPlane && PWS_WaterSystem.Instance == null) { BoundsDouble bounds = new BoundsDouble(); if (TerrainHelper.GetTerrainBounds(ref bounds) == true) { bounds.center = new Vector3Double(bounds.center.x, SessionManager.GetSeaLevel(), bounds.center.z); bounds.size = new Vector3Double(bounds.size.x, 0.05f, bounds.size.z); Gizmos.color = new Color(Color.blue.r, Color.blue.g, Color.blue.b, Color.blue.a / 4f); Gizmos.DrawCube(bounds.center, bounds.size); } } } #endif }
// public static void ShowWorldBiomeMasksSpawner() // { // Terrain worldMapTerrain = TerrainHelper.GetWorldMapTerrain(); // if (worldMapTerrain == null) // { // Debug.LogError("No world map created yet! Please create a world map first before opening the Biome Masks setup!"); // return; // } // GaiaSessionManager gsm = GaiaSessionManager.GetSessionManager(false); // //Get the Gaia Settings // GaiaSettings settings = GaiaUtils.GetGaiaSettings(); // //Create or find the stamper // GameObject spawnerObj = GameObject.Find(GaiaConstants.worldBiomeMasks); // if (spawnerObj == null) // { // spawnerObj = new GameObject(GaiaConstants.worldBiomeMasks); // GameObject worldMapObj = GaiaUtils.GetOrCreateWorldDesigner(); // spawnerObj.transform.parent = worldMapObj.transform; // Spawner spawner = spawnerObj.AddComponent<WorldBiomeMasks>(); // //Existing settings for world mask biomes in session? -> Take those! // if (gsm.m_session.m_worldBiomeMaskSettings != null) // { // spawner.LoadSettings(gsm.m_session.m_worldBiomeMaskSettings); // } // else // { // //No session settings? Use default setup from Gaia settings then // if (settings != null) // { // if (settings.m_defaultBiomeMaskSettings != null) // { // spawner.LoadSettings(settings.m_defaultBiomeMaskSettings); // } // } // } // spawner.m_settings.m_isWorldmapSpawner = true; // spawner.m_settings.m_worldmapSpawnerType = WorldmapSpawnerType.WorldBiomeMasks; // spawner.m_worldMapTerrain = worldMapTerrain; // spawner.FitToTerrain(); // spawner.UpdateMinMaxHeight(); // gsm.m_session.m_worldBiomeMaskSettings = spawner.m_settings; // } // else // { // Spawner spawner = spawnerObj.GetComponent<Spawner>(); // spawner.m_settings.m_isWorldmapSpawner = true; // spawner.m_worldMapTerrain = worldMapTerrain; // spawner.FitToTerrain(); // spawner.UpdateMinMaxHeight(); // gsm.m_session.m_worldBiomeMaskSettings = spawner.m_settings; // } // gsm.SwitchToWorldMap(); //#if UNITY_EDITOR // Selection.activeGameObject = spawnerObj; //#endif // } public static GameObject GetOrCreateWorldMapStamper() { //Create or find the stamper GameObject stamperObj = GameObject.Find(GaiaConstants.worldMapStamper); if (stamperObj == null) { stamperObj = new GameObject(GaiaConstants.worldMapStamper); GameObject worldMapObj = GaiaUtils.GetOrCreateWorldDesigner(); stamperObj.transform.parent = worldMapObj.transform; Stamper stamper = stamperObj.AddComponent <Stamper>(); stamper.m_settings = ScriptableObject.CreateInstance <StamperSettings>(); stamper.m_settings.m_isWorldmapStamper = true; stamper.m_recordUndo = false; stamper.UpdateMinMaxHeight(); //stamper.m_seaLevel = m_settings.m_currentDefaults.m_seaLevel; stamper.FitToTerrain(); } else { Stamper stamper = stamperObj.GetComponent <Stamper>(); stamper.m_settings.m_isWorldmapStamper = true; stamper.m_recordUndo = false; stamper.UpdateMinMaxHeight(); //stamper.m_seaLevel = m_settings.m_currentDefaults.m_seaLevel; stamper.FitToTerrain(); } Terrain worldMapTerrain = TerrainHelper.GetWorldMapTerrain(); if (worldMapTerrain != null) { stamperObj.transform.position = worldMapTerrain.transform.position + worldMapTerrain.terrainData.size / 2f; } return(stamperObj); }
public void OnWorldMapCreate() { m_worldMapTerrain = TerrainHelper.GetWorldMapTerrain(); GaiaSettings gaiaSettings = GaiaUtils.GetGaiaSettings(); GaiaDefaults currentDefaults = gaiaSettings.m_currentDefaults; TerrainLoaderManager.Instance.TerrainSceneStorage.m_hasWorldMap = true; float worldheightmapRes = m_worldMapTerrain.terrainData.heightmapResolution / m_worldMapTerrain.terrainData.size.x; BoundsDouble bounds = new BoundsDouble(); TerrainHelper.GetTerrainBounds(ref bounds); if (bounds.size.x > 0) { TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize = (float)m_currentWorldCreationSettings.m_tileSize / (float)bounds.size.x; TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMapRelativeHeightmapPixels = (((float)bounds.size.x / m_localTileSize) * m_localHeightmapRes / m_localHeightmapRes); } else { //no bounds size means no real terrains (yet) - set these parameters according to the current settings/defaults then TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize = (float)m_currentWorldCreationSettings.m_tileSize / (gaiaSettings.m_tilesX * currentDefaults.m_terrainSize); TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMapRelativeHeightmapPixels = ((gaiaSettings.m_tilesX * currentDefaults.m_terrainSize) / currentDefaults.m_terrainSize) * currentDefaults.m_heightmapResolution / currentDefaults.m_heightmapResolution; } SyncLocalMapToWorldMap(); ShowWorldMapStampSpawner(); GaiaSessionManager.OnWorldCreated -= OnWorldMapCreate; }
public void UpdateCulling(GaiaSettings gaiaSettings) { if (!GaiaUtils.CheckIfSceneProfileExists()) { return; } if (GaiaGlobal.Instance.m_mainCamera == null) { GaiaGlobal.Instance.m_mainCamera = GaiaUtils.GetCamera(); } float farClipPlane = 2000f; if (GaiaGlobal.Instance.m_mainCamera != null) { farClipPlane = GaiaGlobal.Instance.m_mainCamera.farClipPlane; } if (GaiaGlobal.Instance.SceneProfile.m_sunLight == null) { GaiaGlobal.Instance.SceneProfile.m_sunLight = GaiaUtils.GetMainDirectionalLight(); } Terrain terrain = TerrainHelper.GetActiveTerrain(); //Objects m_layerDistances = new float[32]; for (int i = 0; i < m_layerDistances.Length; i++) { string layerName = LayerMask.LayerToName(i); switch (layerName) { case "Default": case "Water": case "PW_VFX": m_layerDistances[i] = 0f; break; case "PW_Object_Small": m_layerDistances[i] = GaiaUtils.CalculateCameraCullingLayerValue(terrain, gaiaSettings.m_currentEnvironment, 5f); break; case "PW_Object_Medium": m_layerDistances[i] = GaiaUtils.CalculateCameraCullingLayerValue(terrain, gaiaSettings.m_currentEnvironment, 3f); break; case "PW_Object_Large": m_layerDistances[i] = GaiaUtils.CalculateCameraCullingLayerValue(terrain, gaiaSettings.m_currentEnvironment); break; default: m_layerDistances[i] = 0f; break; } } }
public override void OnInspectorGUI() { DrawDefaultInspector(); //Set up the box style if (m_boxStyle == null) { m_boxStyle = new GUIStyle(GUI.skin.box); m_boxStyle.normal.textColor = GUI.skin.label.normal.textColor; m_boxStyle.fontStyle = FontStyle.Bold; m_boxStyle.alignment = TextAnchor.UpperLeft; } GUILayout.Space(10f); //Terraform section GUILayout.BeginVertical("Terrain Controller", m_boxStyle); GUILayout.Space(20); GUILayout.BeginHorizontal(); var helper = Selection.activeGameObject.GetComponent <TerrainHelper>(); if (GUILayout.Button("Flatten")) { TerrainHelper.Flatten(); } if (GUILayout.Button("Smooth")) { helper.Smooth(); } if (GUILayout.Button("Stitch")) { TerrainHelper.Stitch(); } if (GUILayout.Button("Clear Trees")) { //TerrainHelper.ClearTrees(); } if (GUILayout.Button("Clear Details")) { //TerrainHelper.ClearDetails(); } GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.EndVertical(); GUILayout.Space(5f); }
/// <summary> /// Get the terrain that matches this location, otherwise return null /// </summary> /// <param name="locationWU">Location to check in world units</param> /// <returns>Terrain here or null</returns> public static Terrain GetTerrain(Vector3 locationWU, bool selectWorldMapTerrains = false) { Terrain terrain; Vector3 terrainMin = new Vector3(); Vector3 terrainMax = new Vector3(); //First check active terrain - most likely already selected terrain = Terrain.activeTerrain; if (terrain != null && terrain.terrainData != null && (selectWorldMapTerrains == TerrainHelper.IsWorldMapTerrain(terrain))) { terrainMin = terrain.GetPosition(); terrainMax = terrainMin + terrain.terrainData.size; if (locationWU.x >= terrainMin.x && locationWU.x <= terrainMax.x) { if (locationWU.z >= terrainMin.z && locationWU.z <= terrainMax.z) { return(terrain); } } } //Then check rest of terrains Terrain closestTerrain = null; float closestDistance = float.MaxValue; for (int idx = 0; idx < Terrain.activeTerrains.Length; idx++) { terrain = Terrain.activeTerrains[idx]; if (terrain.terrainData == null || (selectWorldMapTerrains != TerrainHelper.IsWorldMapTerrain(terrain))) { continue; } terrainMin = terrain.GetPosition(); terrainMax = terrainMin + terrain.terrainData.size; if (locationWU.x >= terrainMin.x && locationWU.x <= terrainMax.x) { if (locationWU.z >= terrainMin.z && locationWU.z <= terrainMax.z) { return(terrain); } } if (closestTerrain == null || Vector3.Distance(terrain.transform.position, locationWU) < closestDistance) { closestTerrain = terrain; } } return(closestTerrain); }
private void CopyWorldMapToLocalMap(BoundsDouble bounds, Terrain t) { //make sure we have a world map terrain first if (m_worldMapTerrain == null) { m_worldMapTerrain = TerrainHelper.GetWorldMapTerrain(); } if (m_worldMapTerrain == null) { Debug.LogError("Can't export world map to local terrains - world map terrain is missing!"); return; } RenderTexture chunkContent = RenderTexture.GetTemporary(t.terrainData.heightmapTexture.descriptor); //FilterMode oldFilterMode = m_worldMapTerrain.terrainData.heightmapTexture.filterMode; //m_worldMapTerrain.terrainData.heightmapTexture.filterMode = FilterMode.Trilinear; //t.terrainData.heightmapTexture.filterMode = FilterMode.Trilinear; //chunkContent.filterMode = FilterMode.Trilinear; int maxTilesX = Mathf.RoundToInt((float)bounds.size.x / t.terrainData.size.x); int maxTilesZ = Mathf.RoundToInt((float)bounds.size.z / t.terrainData.size.z); int currentTileX = Mathf.RoundToInt((t.transform.position.x - (float)bounds.min.x) / t.terrainData.size.x); int currentTileZ = Mathf.RoundToInt((t.transform.position.z - (float)bounds.min.z) / t.terrainData.size.z); float res = (t.terrainData.heightmapResolution) / ((float)bounds.size.x / t.terrainData.bounds.size.x * (t.terrainData.heightmapResolution - 1)); Bounds worldSpaceBounds = t.terrainData.bounds; worldSpaceBounds.center = new Vector3(worldSpaceBounds.center.x + t.transform.position.x, worldSpaceBounds.center.y + t.transform.position.y, worldSpaceBounds.center.z + t.transform.position.z); float xPos = ((float)currentTileX * t.terrainData.heightmapResolution) / (maxTilesX * t.terrainData.heightmapResolution); float zPos = ((float)currentTileZ * t.terrainData.heightmapResolution) / (maxTilesZ * t.terrainData.heightmapResolution); Vector2 pos = new Vector2(xPos, zPos); Graphics.Blit(m_worldMapTerrain.terrainData.heightmapTexture, chunkContent, new Vector2(res, res), pos); //m_worldMapTerrain.terrainData.heightmapTexture.filterMode = oldFilterMode; RenderTexture previousRT = RenderTexture.active; RenderTexture.active = chunkContent; t.terrainData.CopyActiveRenderTextureToHeightmap(new RectInt(0, 0, t.terrainData.heightmapResolution, t.terrainData.heightmapResolution), new Vector2Int(0, 0), t.drawInstanced ? TerrainHeightmapSyncControl.None : TerrainHeightmapSyncControl.HeightOnly); RenderTexture.active = previousRT; t.terrainData.SyncHeightmap(); t.editorRenderFlags = TerrainRenderFlags.All; RenderTexture.ReleaseTemporary(chunkContent); chunkContent = null; }
private Vector3 GetLocalStamperPosition() { BoundsDouble b = new BoundsDouble(); TerrainHelper.GetTerrainBounds(ref b); Transform worldmapTransform = transform.parent.parent; Terrain worldMapTerrain = worldmapTransform.GetComponent <Terrain>(); float relativeX = (transform.position.x - worldmapTransform.position.x) / worldMapTerrain.terrainData.size.x; float relativeZ = (transform.position.z - worldmapTransform.position.z) / worldMapTerrain.terrainData.size.z; float relativeY = transform.position.y / TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize; //TODO: Check if double precision required float newX = (float)b.min.x + (float)b.size.x * relativeX; float newZ = (float)b.min.z + (float)b.size.z * relativeZ; return(new Vector3(newX, relativeY, newZ)); }
public void BakeAllTreeCollisions(string spawnRuleGUID, float radius) { SpawnRule sr = CollisionMask.m_allTreeSpawnRules.FirstOrDefault(x => x.GUID == spawnRuleGUID); if (sr == null) { return; } foreach (Terrain t in Terrain.activeTerrains) { int treePrototypeID = TerrainHelper.GetTreePrototypeIDFromSpawnRule(sr, t); if (treePrototypeID != -1) { BakeTerrainTreeCollisions(t, treePrototypeID, spawnRuleGUID, radius); } } }
/// <summary> /// Position and fit the spawner to the terrain /// </summary> public void FitToAllTerrains() { Terrain currentTerrain = GetCurrentTerrain(); if (currentTerrain == null) { Debug.LogError("Could not fit to terrain - no active terrain present"); return; } BoundsDouble b = new Bounds(); if (TerrainHelper.GetTerrainBounds(ref b)) { transform.position = b.center; m_settings.m_range = (float)b.extents.x; } }
public Terrain GetCurrentTerrain() { Terrain currentTerrain = Gaia.TerrainHelper.GetTerrain(transform.position, false); //Check if the stamper is over a terrain currently //if not, we will draw a preview based on the last active terrain we were over //if that is null either we can't draw a stamp preview if (currentTerrain) { //Update last active terrain with current if (m_lastActiveTerrain != currentTerrain) { //if the current terrain is a new terrain, we should refresh the min max values in case this terrain has never been calculated before SessionManager.GetWorldMinMax(ref m_minWorldHeight, ref m_maxWorldHeight); } m_lastActiveTerrain = currentTerrain; } //if not, we check if there is any terrain within the bounds of the biome spawner if (currentTerrain == null) { float width = m_settings.m_range * 2f; Bounds stamperBounds = new Bounds(transform.position, new Vector3(width, width, width)); foreach (Terrain t in Terrain.activeTerrains) { //only look at this terrain if it matches the selected world map mode if (!TerrainHelper.IsWorldMapTerrain(t) && t.terrainData != null) { Bounds worldSpaceBounds = t.terrainData.bounds; worldSpaceBounds.center = new Vector3(worldSpaceBounds.center.x + t.transform.position.x, worldSpaceBounds.center.y + t.transform.position.y, worldSpaceBounds.center.z + t.transform.position.z); if (worldSpaceBounds.Intersects(stamperBounds)) { currentTerrain = t; break; } } } } return(currentTerrain); }
public void SyncLocalMapToWorldMap() { BoundsDouble bounds = new BoundsDouble(); TerrainHelper.GetTerrainBounds(ref bounds); if (GaiaUtils.HasDynamicLoadedTerrains()) { Action <Terrain> act = (t) => CopyLocalMapToWorldMap(bounds, t); GaiaUtils.CallFunctionOnDynamicLoadedTerrains(act, false); } else { foreach (Terrain t in Terrain.activeTerrains) { if (t != m_worldMapTerrain) { CopyLocalMapToWorldMap(bounds, t); } } } }
public static void FinalizePlayerObjectRuntime(GameObject playerObj) { GaiaSessionManager session = GaiaSessionManager.GetSessionManager(); if (session != null) { if (session.m_session != null) { if (playerObj.transform.position.y < session.m_session.m_seaLevel) { playerObj.transform.position = new Vector3(playerObj.transform.position.x, session.m_session.m_seaLevel + 5f, playerObj.transform.position.z); } } } #if GAIA_PRO_PRESENT //Add the simple terrain culling script, useful in any case if (GaiaUtils.CheckIfSceneProfileExists()) { GaiaGlobal.Instance.SceneProfile.m_terrainCullingEnabled = true; } #endif bool dynamicLoadedTerrains = GaiaUtils.HasDynamicLoadedTerrains(); if (dynamicLoadedTerrains) { #if GAIA_PRO_PRESENT Terrain terrain = TerrainHelper.GetActiveTerrain(); TerrainLoader loader = playerObj.GetComponent <TerrainLoader>(); if (loader == null) { loader = playerObj.AddComponent <TerrainLoader>(); } loader.LoadMode = LoadMode.RuntimeAlways; float size = terrain.terrainData.size.x * 1.25f * 2f; loader.m_loadingBoundsRegular = new BoundsDouble(playerObj.transform.position, new Vector3(size, size, size)); loader.m_loadingBoundsImpostor = new BoundsDouble(playerObj.transform.position, new Vector3(size * 3f, size * 3f, size * 3f)); #endif } }
/// <summary> /// Gets the world map terrain from the scene /// </summary> /// <returns>The world map terrain</returns> public static Terrain GetWorldMapTerrain() { foreach (Terrain t in Terrain.activeTerrains) { if (TerrainHelper.IsWorldMapTerrain(t)) { return(t); } } //still no world map terrain? might be a deactivated GameObject, check those as well GameObject worldMapGO = GaiaUtils.FindObjectDeactivated(GaiaConstants.worldMapTerrainPrefix + "_", false); if (worldMapGO != null) { Terrain t = worldMapGO.GetComponent <Terrain>(); if (t != null) { return(t); } } return(null); }
public void SyncLocationFromStamperSettings() { BoundsDouble b = new BoundsDouble(); TerrainHelper.GetTerrainBounds(ref b); Transform worldmapTransform = transform.parent.parent; Terrain worldMapTerrain = worldmapTransform.GetComponent <Terrain>(); //TODO: review if this needs to be in double precision Vector3Double origin = TerrainLoaderManager.Instance.GetOrigin(); float relativeX = (float)(m_connectedStamperSettings.m_x - b.min.x + origin.x / TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize) / (float)b.size.x; float relativeY = (float)m_connectedStamperSettings.m_y * TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize; float relativeZ = (float)(m_connectedStamperSettings.m_z - b.min.z + origin.z / TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize) / (float)b.size.z; //float relativeX = (float)(m_connectedStamperSettings.m_x - b.min.x) / (float)b.size.x; //float relativeY = (float) m_connectedStamperSettings.m_y * SessionManager.m_session.m_worldMaprelativeSize; //float relativeZ = (float)(m_connectedStamperSettings.m_z - b.min.z) / (float)b.size.z; float newX = worldmapTransform.position.x + worldMapTerrain.terrainData.size.x * relativeX; float newZ = worldmapTransform.position.z + worldMapTerrain.terrainData.size.z * relativeZ; transform.position = new Vector3(newX, relativeY, newZ); }
/// <summary> /// Syncs the heightmap of the world map to the local terrain tiles, preserving correct height scale, heightmap resolution, etc. /// </summary> /// <param name="validLocalTerrainNames">A list of local terrain tile names that are valid to change for the sync operation. If the list is null, all tiles will be assumed valid.</param> public void SyncWorldMapToLocalMap(List <string> validLocalTerrainNames = null) { BoundsDouble bounds = new BoundsDouble(); TerrainHelper.GetTerrainBounds(ref bounds); if (GaiaUtils.HasDynamicLoadedTerrains()) { Action <Terrain> act = (t) => CopyWorldMapToLocalMap(bounds, t); GaiaUtils.CallFunctionOnDynamicLoadedTerrains(act, false, validLocalTerrainNames); } else { foreach (Terrain t in Terrain.activeTerrains) { if (t != m_worldMapTerrain) { if (validLocalTerrainNames == null || validLocalTerrainNames.Contains(t.name)) { CopyWorldMapToLocalMap(bounds, t); } } } } }
//void OnEnable() //{ // if (m_gaiaSettings == null) // { // m_gaiaSettings = GaiaUtils.GetGaiaSettings(); // } //} /// <summary> /// Position and fit the spawner to the terrain /// </summary> public void FitToTerrain(Terrain t = null) { if (t == null) { t = Gaia.TerrainHelper.GetTerrain(transform.position, false); if (t == null) { t = Terrain.activeTerrain; } if (t == null) { Debug.LogWarning("Could not fit to terrain - no terrain present"); return; } } Bounds b = new Bounds(); if (TerrainHelper.GetTerrainBounds(t, ref b)) { transform.position = new Vector3(b.center.x, t.transform.position.y, b.center.z); m_settings.m_range = b.extents.x; } }
public RenderTexture BakeTerrainWorldBiomeMask(Terrain terrain, string worldBiomeMaskGUID) { if (m_gaiaSessionManager == null) { m_gaiaSessionManager = GaiaSessionManager.GetSessionManager(false); } if (m_worldMapTerrain == null) { m_worldMapTerrain = TerrainHelper.GetWorldMapTerrain(); } if (m_worldMapTerrain == null) { Debug.LogWarning("Found no world map terrain for baking a world biome mask."); return(null); } if (String.IsNullOrEmpty(worldBiomeMaskGUID)) { return(null); } if (m_gaiaSessionManager.m_session == null) { Debug.LogWarning("Found no session for baking a world biome mask."); return(null); } if (m_gaiaSessionManager.m_session.m_worldBiomeMaskSettings == null) { Debug.LogWarning("Found no world designer settings in the session for baking a world biome mask."); return(null); } //we need to apply the mask stack for this biome mask on the world map to get the result, then copy the appropiate rectangle for the queried terrain into the cache & return it. bool worldMapActiveState = m_worldMapTerrain.gameObject.activeInHierarchy; m_worldMapTerrain.gameObject.SetActive(true); GameObject emptyGO = new GameObject(); emptyGO.transform.position = new Vector3(m_worldMapTerrain.transform.position.x + m_worldMapTerrain.terrainData.size.x / 2f, m_worldMapTerrain.transform.position.y, m_worldMapTerrain.transform.position.z + +m_worldMapTerrain.terrainData.size.z / 2f); GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(m_worldMapTerrain, emptyGO.transform, m_worldMapTerrain.terrainData.size.x); operation.m_isWorldMapOperation = true; operation.GetHeightmap(); operation.GetNormalmap(); operation.CollectTerrainBakedMasks(); RenderTextureDescriptor rtDescriptor = operation.RTbakedMask.descriptor; RenderTexture inputTexture = RenderTexture.GetTemporary(rtDescriptor); RenderTexture currentRT = RenderTexture.active; RenderTexture.active = inputTexture; GL.Clear(true, true, Color.white); RenderTexture.active = currentRT; RenderTexture ruleOutputTexture = RenderTexture.GetTemporary(rtDescriptor); ImageMask[] maskStack = m_gaiaSessionManager.m_session.m_worldBiomeMaskSettings.m_spawnerRules.Find(x => x.GUID == worldBiomeMaskGUID).m_imageMasks; //Calculate Target position &/ resolution BoundsDouble bounds = new BoundsDouble(); TerrainHelper.GetTerrainBounds(ref bounds); bounds.center -= TerrainLoaderManager.Instance.GetOrigin(); RenderTexture chunkContent = new RenderTexture(terrain.terrainData.heightmapTexture.descriptor); int maxTilesX = Mathf.RoundToInt((float)bounds.size.x / terrain.terrainData.size.x); int maxTilesZ = Mathf.RoundToInt((float)bounds.size.z / terrain.terrainData.size.z); int currentTileX = Mathf.RoundToInt((terrain.transform.position.x - (float)bounds.min.x) / terrain.terrainData.size.x); int currentTileZ = Mathf.RoundToInt((terrain.transform.position.z - (float)bounds.min.z) / terrain.terrainData.size.z); float res = (terrain.terrainData.heightmapResolution) / ((float)bounds.size.x / terrain.terrainData.bounds.size.x * (terrain.terrainData.heightmapResolution - 1)); Bounds worldSpaceBounds = terrain.terrainData.bounds; worldSpaceBounds.center = new Vector3(worldSpaceBounds.center.x + terrain.transform.position.x, worldSpaceBounds.center.y + terrain.transform.position.y, worldSpaceBounds.center.z + terrain.transform.position.z); float xPos = ((float)currentTileX * terrain.terrainData.heightmapResolution) / (maxTilesX * terrain.terrainData.heightmapResolution); float zPos = ((float)currentTileZ * terrain.terrainData.heightmapResolution) / (maxTilesZ * terrain.terrainData.heightmapResolution); Vector2 pos = new Vector2(xPos, zPos); //If we have a mask stack, we need to process it if (maskStack != null && maskStack.Length > 0) { //We start from a white texture, so we need the first mask action in the stack to always be "Multiply", otherwise there will be no result. maskStack[0].m_blendMode = ImageMaskBlendMode.Multiply; float maxWorldHeight = 0f; float minWorldHeight = 0f; m_gaiaSessionManager.GetWorldMinMax(ref minWorldHeight, ref maxWorldHeight, true); //Iterate through all image masks and set up the current paint context in case the shader uses heightmap data foreach (ImageMask mask in maskStack) { mask.m_multiTerrainOperation = operation; mask.m_seaLevel = m_gaiaSessionManager.GetSeaLevel(true); mask.m_maxWorldHeight = maxWorldHeight; mask.m_minWorldHeight = minWorldHeight; } Graphics.Blit(ImageProcessing.ApplyMaskStack(inputTexture, ruleOutputTexture, maskStack, ImageMaskInfluence.Local), ruleOutputTexture); } else { //no mask stack -> just blit the white input texture over as the output Graphics.Blit(inputTexture, ruleOutputTexture); } operation.CloseOperation(); DestroyImmediate(emptyGO); RenderTexture.ReleaseTemporary(inputTexture); m_worldMapTerrain.gameObject.SetActive(worldMapActiveState); //copy the rule output into the right size for the requested terrain chunk Graphics.Blit(ruleOutputTexture, chunkContent, new Vector2(res, res), pos); string filename = GetWorldBiomeMaskFilename(terrain, worldBiomeMaskGUID); SaveBakedMaskInCache(chunkContent, terrain, filename); RenderTexture.ReleaseTemporary(ruleOutputTexture); return(chunkContent); }
public override void OnInspectorGUI() { //Get our spawner m_spawnerGroup = (SpawnerGroup)target; //Set up the box style if (m_boxStyle == null) { m_boxStyle = new GUIStyle(GUI.skin.box); m_boxStyle.normal.textColor = GUI.skin.label.normal.textColor; m_boxStyle.fontStyle = FontStyle.Bold; m_boxStyle.alignment = TextAnchor.UpperLeft; } //Setup the wrap style if (m_wrapStyle == null) { m_wrapStyle = new GUIStyle(GUI.skin.label); m_wrapStyle.wordWrap = true; } //Fix up names if necessary m_spawnerGroup.FixNames(); //Create a nice text intro GUILayout.BeginVertical("Spawner Group", m_boxStyle); GUILayout.Space(20); EditorGUILayout.LabelField("A Spawner Group allows you to chain a set of spawners together. The command buttons you run will be run on all sub spawners. It may take a little while so be patient.", m_wrapStyle); GUILayout.EndVertical(); //Disable if spawning if (m_spawnerGroup.m_updateCoroutine != null) { GUI.enabled = false; } DrawDefaultInspector(); GUILayout.BeginVertical("Terrain Helper", m_boxStyle); GUILayout.Space(20); GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Flatten"))) { if (EditorUtility.DisplayDialog("Flatten Terrain tiles ?", "Are you sure you want to flatten all terrain tiles - this can not be undone ?", "Yes", "No")) { TerrainHelper.Flatten(); } } if (GUILayout.Button(GetLabel("Smooth"))) { if (EditorUtility.DisplayDialog("Smooth Terrain tiles ?", "Are you sure you want to smooth all terrain tiles - this can not be undone ?", "Yes", "No")) { TerrainHelper.Smooth(1); } } if (GUILayout.Button(GetLabel("Clear Trees"))) { if (EditorUtility.DisplayDialog("Clear Terrain trees ?", "Are you sure you want to clear all terrain trees - this can not be undone ?", "Yes", "No")) { //outdated //TerrainHelper.ClearTrees(); } } if (GUILayout.Button(GetLabel("Clear Details"))) { if (EditorUtility.DisplayDialog("Clear Terrain details ?", "Are you sure you want to clear all terrain details - this can not be undone ?", "Yes", "No")) { //outdated //TerrainHelper.ClearDetails(); } } GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.EndVertical(); //Re-enable GUI.enabled = true; //Display progress if (m_spawnerGroup.m_updateCoroutine != null) { GUILayout.BeginVertical("Spawner Controller", m_boxStyle); GUILayout.Space(20); GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Cancel"))) { m_spawnerGroup.CancelSpawn(); } GUILayout.EndHorizontal(); GUILayout.Space(5); GUILayout.EndVertical(); //Draw the various progress bars for (int idx = 0; idx < m_spawnerGroup.m_spawners.Count; idx++) { //Display progress if (m_spawnerGroup.m_spawners[idx].m_spawner.m_spawnProgress > 0f && m_spawnerGroup.m_spawners[idx].m_spawner.m_spawnProgress < 1f) { ProgressBar(string.Format("{0} ({1:0.0}%)", m_spawnerGroup.m_spawners[idx].m_name, m_spawnerGroup.m_spawners[idx].m_spawner.m_spawnProgress * 100f), m_spawnerGroup.m_spawners[idx].m_spawner.m_spawnProgress); } } } else { GUILayout.BeginVertical("Spawner Controller", m_boxStyle); GUILayout.Space(20); GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Reset"))) { m_spawnerGroup.ResetSpawner(); } if (GUILayout.Button(GetLabel("Spawn"))) { //Check that they have a single selected terrain if (Gaia.TerrainHelper.GetActiveTerrainCount() != 1) { EditorUtility.DisplayDialog("OOPS!", "You must have only one active terrain in order to use a Spawner Group. Please either add a terrain, or deactivate all but one terrain.", "OK"); } else { m_spawnerGroup.RunSpawnerIteration(); StartEditorUpdates(); } } GUILayout.EndHorizontal(); GUILayout.Space(5f); GUILayout.EndVertical(); } }
private bool CheckPoint(Texture2D maskTexture, Vector3 position, float min, float max) { try { if (maskTexture == null) { return(false); } if (!maskTexture.isReadable) { Debug.LogError("Texture is not marked as readable. Please set is readable on the texture import settings on texture " + maskTexture.name); } Terrain terrain = TerrainHelper.GetTerrain(position); if (terrain != null) { float scalerX = (float)(position.x - terrain.transform.position.x) / (float)terrain.terrainData.size.x; float scalerZ = (float)(position.z - terrain.transform.position.z) / (float)terrain.terrainData.size.z; Color value = Color.white; value = maskTexture.GetPixel(Mathf.RoundToInt(scalerX * maskTexture.width), Mathf.RoundToInt(scalerZ * maskTexture.height)); switch (ReflectionMaskerData.m_channelSelection) { case ReflectionMaskerChannelSelection.R: if (value.r >= min && value.r <= max) { return(false); } break; case ReflectionMaskerChannelSelection.G: if (value.g >= min && value.g <= max) { return(false); } break; case ReflectionMaskerChannelSelection.B: if (value.b >= min && value.b <= max) { return(false); } break; case ReflectionMaskerChannelSelection.A: if (value.a >= min && value.a <= max) { return(false); } break; case ReflectionMaskerChannelSelection.RGBA: if (value.r >= min && value.r <= max) { return(false); } if (value.g >= min && value.g <= max) { return(false); } if (value.b >= min && value.b <= max) { return(false); } if (value.a >= min && value.a <= max) { return(false); } break; } } return(true); } catch (Exception e) { Debug.LogError("Issues happened when trying to check the point " + e.Message + " Happened here " + e.StackTrace); return(true); } }
/// <summary> /// Get the bounds of the terrain at this location or fail with a null /// </summary> /// <param name="locationWU">Location to check and get terrain for</param> /// <returns>Bounds of selected terrain or null if invalid for some reason</returns> public static bool GetTerrainBounds(ref BoundsDouble bounds, bool activeTerrainsOnly = false) { //Terrain terrain = GetTerrain(locationWU); //if (terrain == null) //{ // return false; //} //bounds.center = terrain.transform.position; //bounds.size = terrain.terrainData.size; //bounds.center += bounds.extents; Vector3Double accumulatedCenter = new Vector3Double(); //Do we use dynamic loaded terrains in the scene? if (GaiaUtils.HasDynamicLoadedTerrains() && !activeTerrainsOnly) { #if GAIA_PRO_PRESENT //we do have dynamic terrains -> calculate the bounds according to the terrain scene data in the session GaiaSessionManager gsm = GaiaSessionManager.GetSessionManager(false); foreach (TerrainScene t in TerrainLoaderManager.TerrainScenes) { accumulatedCenter += t.m_bounds.center; } bounds.center = accumulatedCenter / TerrainLoaderManager.TerrainScenes.Count; foreach (TerrainScene t in TerrainLoaderManager.TerrainScenes) { bounds.Encapsulate(t.m_bounds); } #endif } else { //no placeholder -> calculate bounds according to the active terrains in the scene if (Terrain.activeTerrains.Length > 0) { foreach (Terrain t in Terrain.activeTerrains) { if (!TerrainHelper.IsWorldMapTerrain(t)) { if (t.terrainData != null) { accumulatedCenter += new Vector3Double(t.transform.position) + new Vector3Double(t.terrainData.bounds.extents); } else { Debug.LogWarning("Terrain " + t.name + " in the scene is missing the terrain data object!"); } } } bounds.center = accumulatedCenter / Terrain.activeTerrains.Length; foreach (Terrain t in Terrain.activeTerrains) { if (!TerrainHelper.IsWorldMapTerrain(t)) { if (t.terrainData != null) { Bounds newBounds = new Bounds(); newBounds.center = t.transform.position; newBounds.size = t.terrainData.size; newBounds.center += t.terrainData.bounds.extents; bounds.Encapsulate(newBounds); } } } } else { bounds = new BoundsDouble(Vector3Double.zero, Vector3Double.zero); //No active terrains? There might be mesh terrains we can use then GameObject meshTerrainExportObject = GaiaUtils.GetTerrainExportObject(false); if (meshTerrainExportObject != null) { foreach (Transform t in meshTerrainExportObject.transform) { MeshRenderer mr = t.GetComponent <MeshRenderer>(); if (mr != null) { bounds.Encapsulate(mr.bounds); } } } } } return(true); }
public void CreateWorldMapTerrain() { //Remove old world map terrain, if any Terrain oldWMTerrain = TerrainHelper.GetWorldMapTerrain(); if (oldWMTerrain != null) { #if UNITY_EDITOR if (EditorUtility.DisplayDialog("Delete old world map?", "You are about to create a new world map in this scene. This will delete the existing world map and the stamp tokens on it. This will only affect the small world map terrain, the actual full scene terrain tiles will not be removed. Continue?", "Continue", "Cancel")) { DestroyImmediate(oldWMTerrain.gameObject); } else { return; } #else Destroy(oldWMTerrain.gameObject); #endif } GaiaSettings gaiaSettings = GaiaUtils.GetGaiaSettings(); GaiaDefaults currentDefaults = gaiaSettings.m_currentDefaults; GaiaSessionManager gsm = GaiaSessionManager.GetSessionManager(); //Collect some info from the existing world, if any. //We need the average height from the terrains to create the height of the worldmap accordingly in scale double averageHeight = currentDefaults.m_terrainHeight; //We need the heightmap resolution and terrain size stored in the session //To properly scale between world map and local map even when one of the two is not loaded at the moment int count = 0; foreach (Terrain t in Terrain.activeTerrains) { averageHeight += t.terrainData.size.y; if (!TerrainHelper.IsWorldMapTerrain(t)) { m_localHeightmapRes = t.terrainData.heightmapResolution; m_localTileSize = t.terrainData.size.x; } count++; } //} //only calculate an average if there is at least one placeholder or terrain if (count > 0) { averageHeight /= count; } BoundsDouble bounds = new BoundsDouble(); TerrainHelper.GetTerrainBounds(ref bounds); //Collect the new world settings for world creation WorldCreationSettings worldCreationSettings = ScriptableObject.CreateInstance <WorldCreationSettings>(); worldCreationSettings.m_xTiles = 1; worldCreationSettings.m_zTiles = 1; worldCreationSettings.m_tileSize = (count > 0) ? Mathd.RoundToInt(bounds.size.x) : gaiaSettings.m_tilesX * currentDefaults.m_terrainSize; worldCreationSettings.m_tileHeight = currentDefaults.m_terrainHeight; worldCreationSettings.m_createInScene = false; worldCreationSettings.m_autoUnloadScenes = false; worldCreationSettings.m_applyFloatingPointFix = false; worldCreationSettings.m_applyFloatingPointFix = false; worldCreationSettings.m_centerOffset = Vector3.zero; //(count > 0) ? new Vector2Double(bounds.center.x + bounds.extents.x + worldCreationSettings.m_tileSize, bounds.center.z) : Vector2Double.zero; worldCreationSettings.m_isWorldMap = true; //clone defaults so we can inject our custom heightmap resolution for the worldmap GaiaDefaults clonedDefaults = Instantiate(currentDefaults); clonedDefaults.m_heightmapResolution = (int)m_heightmapResolution; worldCreationSettings.m_gaiaDefaults = clonedDefaults; m_currentWorldCreationSettings = worldCreationSettings; GaiaSessionManager.OnWorldCreated -= OnWorldMapCreate; GaiaSessionManager.OnWorldCreated += OnWorldMapCreate; GaiaSessionManager.CreateWorld(worldCreationSettings); }
public static void ShowWorldMapStampSpawner() { Terrain worldMapTerrain = TerrainHelper.GetWorldMapTerrain(); if (worldMapTerrain == null) { Debug.LogError("No world map created yet! Please create a world map first before opening the random terrain generator"); return; } GaiaSessionManager gsm = GaiaSessionManager.GetSessionManager(false); //Get the Gaia Settings GaiaSettings settings = GaiaUtils.GetGaiaSettings(); //Create or find the stamper GameObject spawnerObj = GaiaUtils.GetOrCreateWorldDesigner(); Spawner spawner = spawnerObj.GetComponent <WorldDesigner>(); if (spawner == null) { spawner = spawnerObj.AddComponent <WorldDesigner>(); if (settings != null) { if (settings.m_defaultStampSpawnSettings != null) { spawner.LoadSettings(settings.m_defaultStampSpawnSettings); } } spawner.m_settings.m_isWorldmapSpawner = true; spawner.m_worldMapTerrain = worldMapTerrain; //set up the export settings with the current Gaia Settings / defaults spawner.m_worldCreationSettings.m_targeSizePreset = settings.m_targeSizePreset; spawner.m_worldCreationSettings.m_xTiles = settings.m_tilesX; spawner.m_worldCreationSettings.m_zTiles = settings.m_tilesZ; spawner.m_worldTileSize = GaiaUtils.IntToEnvironmentSize(settings.m_currentDefaults.m_terrainSize); spawner.m_worldCreationSettings.m_tileSize = settings.m_currentDefaults.m_terrainSize; spawner.m_worldCreationSettings.m_tileHeight = settings.m_currentDefaults.m_terrainHeight; spawner.m_worldCreationSettings.m_createInScene = settings.m_createTerrainScenes; spawner.m_worldCreationSettings.m_autoUnloadScenes = settings.m_unloadTerrainScenes; spawner.m_worldCreationSettings.m_applyFloatingPointFix = settings.m_floatingPointFix; spawner.m_worldCreationSettings.m_qualityPreset = settings.m_currentEnvironment; if (spawner.m_worldCreationSettings.m_gaiaDefaults == null) { spawner.m_worldCreationSettings.m_gaiaDefaults = settings.m_currentDefaults; } spawner.StoreWorldSize(); //spawner.StoreHeightmapResolution(); //Check if we do have an existing terrain already, if yes, we would want to re-use it for the world map -> terrain export if (GaiaUtils.HasTerrains()) { spawner.m_useExistingTerrainForWorldMapExport = true; } else { //No terrains yet - set up the terrain tiles in the session according to the current world creation settings //so that the stamp previews will come out right. TerrainLoaderManager.Instance.TerrainSceneStorage.m_terrainTilesX = settings.m_tilesX; TerrainLoaderManager.Instance.TerrainSceneStorage.m_terrainTilesZ = settings.m_tilesZ; } spawner.FitToTerrain(); spawner.UpdateMinMaxHeight(); } else { spawner.m_settings.m_isWorldmapSpawner = true; spawner.m_worldMapTerrain = worldMapTerrain; spawner.FitToTerrain(); spawner.UpdateMinMaxHeight(); } gsm.m_session.m_worldBiomeMaskSettings = spawner.m_settings; TerrainLoaderManager.Instance.SwitchToWorldMap(); #if UNITY_EDITOR Selection.activeGameObject = spawnerObj; #endif }
public override void OnInspectorGUI() { //Get our resource m_manager = (GaiaSessionManager)target; //Set up the box style if (m_boxStyle == null) { m_boxStyle = new GUIStyle(GUI.skin.box); m_boxStyle.normal.textColor = GUI.skin.label.normal.textColor; m_boxStyle.fontStyle = FontStyle.Bold; m_boxStyle.alignment = TextAnchor.UpperLeft; } //Setup the wrap style if (m_wrapStyle == null) { m_wrapStyle = new GUIStyle(GUI.skin.label); m_wrapStyle.wordWrap = true; } //Set up the description wrap style if (m_descWrapStyle == null) { m_descWrapStyle = new GUIStyle(GUI.skin.textArea); m_descWrapStyle.wordWrap = true; } //Scroll m_scrollPosition = GUILayout.BeginScrollView(m_scrollPosition, false, false); //Create a nice text intro GUILayout.BeginVertical("Gaia Session Manager", m_boxStyle); GUILayout.Space(20); EditorGUILayout.LabelField("Track and control session creation and playback.", m_wrapStyle); GUILayout.Space(4); EditorGUILayout.BeginHorizontal(); m_manager.m_session = (GaiaSession)EditorGUILayout.ObjectField(GetLabel("Session"), m_manager.m_session, typeof(GaiaSession), false); if (GUILayout.Button(GetLabel("New"), GUILayout.Width(45))) { m_manager.CreateSession(); } EditorGUILayout.EndHorizontal(); GUILayout.EndVertical(); if (m_manager.m_session == null) { GUILayout.EndScrollView(); return; } //Track changes EditorGUI.BeginChangeCheck(); //Make some space GUILayout.Space(4); //Wrap it up in a box GUILayout.BeginVertical(m_boxStyle); GUILayout.BeginVertical("Summary:", m_boxStyle); GUILayout.Space(20); //Display the basic details EditorGUILayout.LabelField("Name"); if (m_manager.IsLocked()) { GUI.enabled = false; } string name = EditorGUILayout.TextArea(m_manager.m_session.m_name, m_descWrapStyle, GUILayout.MinHeight(15)); GUI.enabled = true; EditorGUILayout.LabelField("Description"); if (m_manager.IsLocked()) { GUI.enabled = false; } string description = EditorGUILayout.TextArea(m_manager.m_session.m_description, m_descWrapStyle, GUILayout.MinHeight(45)); Texture2D previewImage = m_manager.GetPreviewImage(); if (!m_manager.IsLocked()) { previewImage = (Texture2D)EditorGUILayout.ObjectField(GetLabel("Preview Image"), m_manager.m_session.m_previewImage, typeof(Texture2D), false, GUILayout.MaxHeight(15f)); } //Detect change in session and handle changes to preview image float width, height; if (m_manager.m_session.GetInstanceID() != m_lastSessionID) { m_lastPreviewImgName = ""; m_lastSessionID = m_manager.m_session.GetInstanceID(); if (m_manager.HasPreviewImage()) { previewImage = m_manager.GetPreviewImage(); m_lastPreviewImgName = previewImage.name; } } else //Process changes to preview image { if (previewImage == null) { if (m_manager.IsLocked()) //Undo change if locked { if (m_manager.HasPreviewImage()) { previewImage = m_manager.GetPreviewImage(); m_lastPreviewImgName = previewImage.name; Debug.LogWarning("You can not change the image on a locked session"); } } else { if (m_manager.HasPreviewImage()) { m_manager.RemovePreviewImage(); m_lastPreviewImgName = ""; } } } else { //Handle changes to preview image if (previewImage.name != m_lastPreviewImgName) { if (m_manager.IsLocked()) //Revert { if (m_manager.HasPreviewImage()) { previewImage = m_manager.GetPreviewImage(); m_lastPreviewImgName = previewImage.name; Debug.LogWarning("You can not change the image on a locked session"); } else { previewImage = null; m_lastPreviewImgName = ""; } } else { //Make it readable Gaia.Utils.MakeTextureReadable(previewImage); //Make a new texture from it Texture2D newTexture = new Texture2D(previewImage.width, previewImage.height, TextureFormat.ARGB32, false); newTexture.name = m_manager.m_session.m_name; newTexture.SetPixels(previewImage.GetPixels(0)); newTexture.Apply(); //Resize and scale it width = 320; height = previewImage.height * (width / previewImage.width); Gaia.ScaleTexture.Bilinear(newTexture, (int)width, (int)height); //Compress it //newTexture.Compress(true); //And store its content m_manager.AddPreviewImage(newTexture); //Assign back to the texture for the scene previewImage = newTexture; m_lastPreviewImgName = previewImage.name; } } } } GUI.enabled = true; //In response to locked above if (previewImage != null) { //Get aspect ratio and available space and display the image width = Screen.width - 43f; height = previewImage.height * (width / previewImage.width); GUILayout.Label(previewImage, GUILayout.MaxWidth(width), GUILayout.MaxHeight(height)); } EditorGUILayout.LabelField("Created", m_manager.m_session.m_dateCreated); EditorGUILayout.LabelField("Dimensions", string.Format("w{0} d{1} h{2}", m_manager.m_session.m_terrainWidth, m_manager.m_session.m_terrainDepth, m_manager.m_session.m_terrainHeight)); if (m_manager.IsLocked()) { GUI.enabled = false; } m_manager.m_session.m_seaLevel = EditorGUILayout.Slider(GetLabel("Sea Level"), m_manager.m_session.m_seaLevel, 0f, m_manager.m_session.m_terrainDepth); GUI.enabled = true; //In response to locked above bool locked = EditorGUILayout.Toggle(GetLabel("Locked"), m_manager.m_session.m_isLocked); GUILayout.EndVertical(); //Iterate through the operations GUILayout.BeginVertical("Operations:", m_boxStyle); GUILayout.Space(20); if (m_manager.m_session.m_operations.Count == 0) { GUILayout.Space(5); GUILayout.Label("No operations yet..."); GUILayout.Space(5); } else { GaiaOperation op; EditorGUI.indentLevel++; for (int opIdx = 0; opIdx < m_manager.m_session.m_operations.Count; opIdx++) { op = m_manager.m_session.m_operations[opIdx]; if (op.m_isActive) { op.m_isFoldedOut = EditorGUILayout.Foldout(op.m_isFoldedOut, op.m_description, true); } else { op.m_isFoldedOut = EditorGUILayout.Foldout(op.m_isFoldedOut, op.m_description + " [inactive]", true); } if (op.m_isFoldedOut) { EditorGUI.indentLevel++; EditorGUILayout.LabelField("Description", op.m_description, m_wrapStyle); EditorGUILayout.LabelField("Created", op.m_operationDateTime); if (m_manager.m_session.m_isLocked) { GUI.enabled = false; } op.m_isActive = EditorGUILayout.Toggle(GetLabel("Active"), op.m_isActive); GUI.enabled = true; int dataLength = 0; for (int idx = 0; idx < op.m_operationDataJson.GetLength(0); idx++) { dataLength += op.m_operationDataJson[idx].Length; } EditorGUILayout.LabelField("Data", dataLength.ToString() + " bytes"); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (m_manager.m_session.m_isLocked) { GUI.enabled = false; } if (GUILayout.Button(GetLabel("Delete"))) { if (EditorUtility.DisplayDialog("Delete Operation ?", "Are you sure you want to delete this operation ?", "Yes", "No")) { m_manager.RemoveOperation(opIdx); } } GUI.enabled = true; if (GUILayout.Button(GetLabel("Apply"))) { m_manager.Apply(opIdx); } if (GUILayout.Button(GetLabel("Play"))) { m_manager.PlayOperation(opIdx); } GUILayout.EndHorizontal(); EditorGUI.indentLevel--; } //EditorGUILayout.Space(); } EditorGUI.indentLevel--; } GUILayout.EndVertical(); //Create a nice text intro if (!m_manager.m_session.m_isLocked) { GUILayout.BeginVertical(m_boxStyle); m_manager.m_genShowRandomGenerator = EditorGUILayout.BeginToggleGroup(GetLabel(" Random Terrain Generator"), m_manager.m_genShowRandomGenerator); if (m_manager.m_genShowRandomGenerator) { m_manager.m_genNumStampsToGenerate = EditorGUILayout.IntSlider(GetLabel("Stamps"), m_manager.m_genNumStampsToGenerate, 1, 20); m_manager.m_genScaleWidth = EditorGUILayout.Slider(GetLabel("Width Scale"), m_manager.m_genScaleWidth, 0.5f, 100f); m_manager.m_genScaleHeight = EditorGUILayout.Slider(GetLabel("Height Scale"), m_manager.m_genScaleHeight, 0.5f, 100f); m_manager.m_genBorderStyle = (Gaia.GaiaConstants.GeneratorBorderStyle)EditorGUILayout.EnumPopup(GetLabel("Border Style"), m_manager.m_genBorderStyle); m_manager.m_genChanceOfHills = EditorGUILayout.Slider(GetLabel("Hill Chance"), m_manager.m_genChanceOfHills, 0f, 1f); m_manager.m_genChanceOfIslands = EditorGUILayout.Slider(GetLabel("Island Chance"), m_manager.m_genChanceOfIslands, 0f, 1f); m_manager.m_genChanceOfLakes = EditorGUILayout.Slider(GetLabel("Lake Chance"), m_manager.m_genChanceOfLakes, 0f, 1f); m_manager.m_genChanceOfMesas = EditorGUILayout.Slider(GetLabel("Mesa Chance"), m_manager.m_genChanceOfMesas, 0f, 1f); m_manager.m_genChanceOfMountains = EditorGUILayout.Slider(GetLabel("Mountain Chance"), m_manager.m_genChanceOfMountains, 0f, 1f); m_manager.m_genChanceOfPlains = EditorGUILayout.Slider(GetLabel("Plains Chance"), m_manager.m_genChanceOfPlains, 0f, 1f); m_manager.m_genChanceOfRivers = EditorGUILayout.Slider(GetLabel("River Chance"), m_manager.m_genChanceOfRivers, 0f, 1f); m_manager.m_genChanceOfValleys = EditorGUILayout.Slider(GetLabel("Valley Chance"), m_manager.m_genChanceOfValleys, 0f, 1f); m_manager.m_genChanceOfVillages = EditorGUILayout.Slider(GetLabel("Village Chance"), m_manager.m_genChanceOfVillages, 0f, 1f); m_manager.m_genChanceOfWaterfalls = EditorGUILayout.Slider(GetLabel("Waterfall Chance"), m_manager.m_genChanceOfWaterfalls, 0f, 1f); GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Reset Session"))) { if (EditorUtility.DisplayDialog("Reset Session ?", "Are you sure you want to reset your session - this can not be undone ?", "Yes", "No")) { m_manager.ResetSession(); } } if (GUILayout.Button(GetLabel("Add Stamps"))) { m_manager.RandomiseStamps(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndToggleGroup(); GUILayout.EndVertical(); } //Create a nice text intro GUILayout.BeginVertical(m_boxStyle); m_manager.m_genShowTerrainHelper = EditorGUILayout.BeginToggleGroup(GetLabel(" Terrain Helper"), m_manager.m_genShowTerrainHelper); if (m_manager.m_genShowTerrainHelper) { GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Flatten Terrain"))) { if (EditorUtility.DisplayDialog("Flatten Terrain?", "Are you sure you want to flatten your terrain - this can not be undone ?", "Yes", "No")) { GaiaWorldManager wm = new GaiaWorldManager(Terrain.activeTerrains); wm.FlattenWorld(); } } if (GUILayout.Button(GetLabel("Smooth Terrain"))) { if (EditorUtility.DisplayDialog("Smooth Terrain?", "Are you sure you want to smooth your terrain - this can not be undone ?", "Yes", "No")) { GaiaWorldManager wm = new GaiaWorldManager(Terrain.activeTerrains); wm.SmoothWorld(); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button(GetLabel("Clear Trees"))) { if (EditorUtility.DisplayDialog("Clear Trees?", "Are you sure you want to clear your trees - this can not be undone ?", "Yes", "No")) { TerrainHelper.ClearTrees(); } } if (GUILayout.Button(GetLabel("Clear Details"))) { if (EditorUtility.DisplayDialog("Clear Details?", "Are you sure you want to clear your details / grass - this can not be undone ?", "Yes", "No")) { TerrainHelper.ClearDetails(); } } GUILayout.EndHorizontal(); } EditorGUILayout.EndToggleGroup(); GUILayout.EndVertical(); //Check for changes, make undo record, make changes and let editor know we are dirty if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_manager, "Made changes"); m_manager.m_session.m_name = name; m_manager.m_session.m_description = description; m_manager.m_session.m_isLocked = locked; m_manager.m_session.m_previewImage = previewImage; EditorUtility.SetDirty(m_manager.m_session); EditorUtility.SetDirty(m_manager); } GUILayout.BeginVertical("Session Controller", m_boxStyle); GUILayout.Space(20); GUILayout.BeginHorizontal(); if (m_manager.m_updateSessionCoroutine == null && m_manager.m_updateOperationCoroutine == null) { if (GUILayout.Button(GetLabel("Play Session"))) { if (EditorUtility.DisplayDialog("Playback Session ?", "Are you sure you want to playback your session - this can not be undone ?", "Yes", "No")) { m_manager.PlaySession(); } } if (GUILayout.Button(GetLabel("Export Resources"))) { m_manager.ExportSessionResources(); } } else { if (GUILayout.Button(GetLabel("Cancel"))) { m_manager.CancelPlayback(); } } GUILayout.EndHorizontal(); GUILayout.Space(5); //Debug.Log(m_manager.m_lastUpdateDateTime); //Draw the various spawner progress bars if (m_manager.m_currentStamper != null) { if (m_manager.m_currentStamper.IsStamping()) { ProgressBar(string.Format("{0}:{1} ({2:0.0}%)", m_manager.m_currentStamper.gameObject.name, m_manager.m_currentStamper.m_stampPreviewImage.name, m_manager.m_currentStamper.m_stampProgress * 100f), m_manager.m_currentStamper.m_stampProgress); } } if (m_manager.m_currentSpawner != null) { if (m_manager.m_currentSpawner.IsSpawning()) { ProgressBar(string.Format("{0} ({1:0.0}%)", m_manager.m_currentSpawner.gameObject.name, m_manager.m_currentSpawner.m_spawnProgress * 100f), m_manager.m_currentSpawner.m_spawnProgress); } } GUILayout.EndVertical(); GUILayout.EndVertical(); //End scroll GUILayout.EndScrollView(); }
public void LoadStorageData() { #if UNITY_EDITOR //Try to get the terrain scene storage file from the last used GUID first if (!String.IsNullOrEmpty(m_lastUsedGUID)) { m_terrainSceneStorage = (TerrainSceneStorage)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(m_lastUsedGUID), typeof(TerrainSceneStorage)); } //No guid / storage object? Then we need to create one in the current session directory if (m_terrainSceneStorage == null) { GaiaSessionManager gsm = GaiaSessionManager.GetSessionManager(); if (gsm != null && gsm.m_session != null) { string path = GaiaDirectories.GetScenePath(gsm.m_session) + "/TerrainScenes.asset"; if (File.Exists(path)) { m_terrainSceneStorage = (TerrainSceneStorage)AssetDatabase.LoadAssetAtPath(path, typeof(TerrainSceneStorage)); } else { m_terrainSceneStorage = ScriptableObject.CreateInstance <TerrainSceneStorage>(); if (TerrainHelper.GetWorldMapTerrain() != null) { m_terrainSceneStorage.m_hasWorldMap = true; } AssetDatabase.CreateAsset(m_terrainSceneStorage, path); AssetDatabase.ImportAsset(path); } } else { m_terrainSceneStorage = ScriptableObject.CreateInstance <TerrainSceneStorage>(); } } //Check if there are scene files existing already and if they are in the storage data - if not, we should pick them up accordingly string directory = GaiaDirectories.GetTerrainScenePathForStorageFile(m_terrainSceneStorage); var dirInfo = new DirectoryInfo(directory); bool madeChanges = false; if (dirInfo != null) { FileInfo[] allFiles = dirInfo.GetFiles(); foreach (FileInfo fileInfo in allFiles) { if (fileInfo.Extension == ".unity") { string path = GaiaDirectories.GetPathStartingAtAssetsFolder(fileInfo.FullName); if (!m_terrainSceneStorage.m_terrainScenes.Exists(x => x.GetTerrainName() == x.GetTerrainName(path))) { string firstSegment = fileInfo.Name.Split('-')[0]; int xCoord = -99; int zCoord = -99; bool successX, successZ; try { successX = Int32.TryParse(firstSegment.Substring(firstSegment.IndexOf('_') + 1, firstSegment.LastIndexOf('_') - (firstSegment.IndexOf('_') + 1)), out xCoord); successZ = Int32.TryParse(firstSegment.Substring(firstSegment.LastIndexOf('_') + 1, firstSegment.Length - 1 - firstSegment.LastIndexOf('_')), out zCoord); } catch (Exception ex) { if (ex.Message == "123") { } successX = false; successZ = false; } if (successX && successZ) { //double centerX = (xCoord - (m_terrainSceneStorage.m_terrainTilesX / 2f)) * m_terrainSceneStorage.m_terrainTilesSize + (m_terrainSceneStorage.m_terrainTilesSize /2f); //double centerZ = (zCoord - (m_terrainSceneStorage.m_terrainTilesZ / 2f)) * m_terrainSceneStorage.m_terrainTilesSize + (m_terrainSceneStorage.m_terrainTilesSize / 2f); Vector2 offset = new Vector2(-m_terrainSceneStorage.m_terrainTilesSize * m_terrainSceneStorage.m_terrainTilesX * 0.5f, -m_terrainSceneStorage.m_terrainTilesSize * m_terrainSceneStorage.m_terrainTilesZ * 0.5f); Vector3Double position = new Vector3(m_terrainSceneStorage.m_terrainTilesSize * xCoord + offset.x, 0, m_terrainSceneStorage.m_terrainTilesSize * zCoord + offset.y); Vector3Double center = new Vector3Double(position + new Vector3Double(m_terrainSceneStorage.m_terrainTilesSize / 2f, 0f, m_terrainSceneStorage.m_terrainTilesSize / 2f)); BoundsDouble bounds = new BoundsDouble(center, new Vector3Double(m_terrainSceneStorage.m_terrainTilesSize, m_terrainSceneStorage.m_terrainTilesSize * 4, m_terrainSceneStorage.m_terrainTilesSize)); //Use forward slashes in the path - The Unity scene management classes expect it that way path = path.Replace("\\", "/"); TerrainScene terrainScene = new TerrainScene() { m_scenePath = path, m_pos = position, m_bounds = bounds, m_useFloatingPointFix = m_terrainSceneStorage.m_useFloatingPointFix }; if (File.Exists(path.Replace("Terrain", GaiaConstants.ImpostorTerrainName))) { terrainScene.m_impostorScenePath = path.Replace("Terrain", GaiaConstants.ImpostorTerrainName); } if (File.Exists(path.Replace("Terrain", "Collider"))) { terrainScene.m_colliderScenePath = path.Replace("Terrain", "Collider"); } if (File.Exists(path.Replace("Terrain", "Backup"))) { terrainScene.m_backupScenePath = path.Replace("Terrain", "Backup"); } m_terrainSceneStorage.m_terrainScenes.Add(terrainScene); madeChanges = true; } } } } if (madeChanges) { EditorUtility.SetDirty(m_terrainSceneStorage); AssetDatabase.SaveAssets(); } } m_lastUsedGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_terrainSceneStorage)); RefreshTerrainsWithCurrentData(); RefreshSceneViewLoadingRange(); ////Go over the currently open scene and close the ones that do not seem to have a reference on them //for (int i = EditorSceneManager.loadedSceneCount-1; i >= 0; i--) //{ // Scene scene = EditorSceneManager.GetSceneAt(i); // if (EditorSceneManager.GetActiveScene().Equals(scene)) // { // continue; // } // TerrainScene terrainScene = m_terrainSceneStorage.m_terrainScenes.Find(x => x.m_scenePath == scene.path || x.m_impostorScenePath == scene.path || x.m_colliderScenePath == scene.path); // if (terrainScene != null) // { // terrainScene.UpdateWithCurrentData(); // } // else // { // EditorSceneManager.UnloadSceneAsync(scene); // } //} #endif }
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); }
/// <summary> /// Draw gizmos /// </summary> void OnDrawGizmos() { if (m_resources == null) { return; } if (m_spawner == null) { return; } if (m_terrainHeightMap == null) { return; } //Lets visualise fitness float x, y = transform.position.y, z; float xStart = transform.position.x - m_range; float xEnd = transform.position.x + m_range; float zStart = transform.position.z - m_range; float zEnd = transform.position.z + m_range; float ballsize = Mathf.Clamp(m_resolution * 0.25f, 0.5f, 5f); m_spawner.m_settings.m_spawnRange = m_range; m_spawner.m_spawnerBounds = new Bounds(transform.position, new Vector3(m_range * 2f, m_range * 20f, m_range * 2f)); SpawnInfo spawnInfo = new SpawnInfo(); Vector3 location = new Vector3(); float fitness = 0f; //Create caches if ((DateTime.Now - m_lastCacheUpdateDate).TotalSeconds > 5) { m_lastCacheUpdateDate = DateTime.Now; m_spawner.DeleteSpawnCaches(); m_spawner.CreateSpawnCaches(m_selectedResourceType, m_selectedResourceIdx); //Also update the location so make moving it easier Terrain terrain = TerrainHelper.GetTerrain(transform.position); if (terrain != null) { transform.position = new Vector3(transform.position.x, terrain.SampleHeight(transform.position) + 5f, transform.position.z); } } //Set up the texture layer array in spawn info spawnInfo.m_textureStrengths = new float[Terrain.activeTerrain.terrainData.alphamapLayers]; //Now visualise fitness for (x = xStart; x < xEnd; x += m_resolution) { for (z = zStart; z < zEnd; z += m_resolution) { location.Set(x, y, z); if (m_spawner.CheckLocation(location, ref spawnInfo)) { fitness = GetFitness(ref spawnInfo); if (fitness < m_minimumFitness) { continue; } Gizmos.color = Color.Lerp(m_unfitColour, m_fitColour, fitness); Gizmos.DrawSphere(spawnInfo.m_hitLocationWU, ballsize); } } } //Now draw water //Water if (m_resources != null) { BoundsDouble bounds = new BoundsDouble(); if (TerrainHelper.GetTerrainBounds(ref bounds) == true) { bounds.center = new Vector3Double(bounds.center.x, GaiaSessionManager.GetSessionManager().GetSeaLevel(), bounds.center.z); bounds.size = new Vector3Double(bounds.size.x, 0.05f, bounds.size.z); Gizmos.color = new Color(Color.blue.r, Color.blue.g, Color.blue.b, Color.blue.a / 4f); Gizmos.DrawCube(bounds.center, bounds.size); } } }