Initial commit
This commit is contained in:
1 parent
ee9615239e
commit
16feac691f
4093 files changed
+1030491
No files matched your search
@@ -0,0 +1,77 @@
|
||||
// Copyright © 2018 Procedural Worlds Pty Limited. All Rights Reserved.
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using static Gaia.GaiaConstants;
|
||||
using UnityEditor;
|
||||
|
||||
/*
|
||||
* Scriptable Object containing settings for a Spawner
|
||||
*/
|
||||
public enum NoiseTypeName { Billow, Perlin, Ridge, Value}
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary> Contains settings for the initial creation of the Base Terrain during random terrain generation</summary>
|
||||
[System.Serializable]
|
||||
public class BaseTerrainSettings : ScriptableObject, ISerializationCallbackReceiver
|
||||
{
|
||||
|
||||
#region Public Variables
|
||||
|
||||
/// <summary>
|
||||
/// If the baseTerrain should be displayed as a preview in the random terrain generator or not.
|
||||
/// </summary>
|
||||
public bool m_drawPreview = true;
|
||||
|
||||
public float m_heightScale = 8f;
|
||||
public float m_baseLevel = 0f;
|
||||
public float m_heightVariance = 0.5f;
|
||||
public GeneratorBorderStyle m_borderStyle;
|
||||
public NoiseTypeName m_shapeNoiseStyle = NoiseTypeName.Perlin;
|
||||
public float m_shapeSize = 8f;
|
||||
public float m_shapeStrength = 0.35f;
|
||||
public float m_shapeSteepness = 0.4f;
|
||||
public float m_shapeGranularity = 2f;
|
||||
|
||||
|
||||
public NoiseTypeName m_mountainNoiseStyle = NoiseTypeName.Billow;
|
||||
public float m_mountainSize = 6.5f;
|
||||
public float m_mountainStrength = 0.15f;
|
||||
public float m_mountainSteepness = 0.1f;
|
||||
public float m_mountainGranularity = 2f;
|
||||
|
||||
|
||||
public NoiseTypeName m_valleyNoiseStyle = NoiseTypeName.Perlin;
|
||||
public float m_valleySize = 5f;
|
||||
public float m_valleyStrength = 0.1f;
|
||||
public float m_valleySteepness = 0.2f;
|
||||
public float m_valleyGranularity = 1f;
|
||||
|
||||
public Vector3 m_shapeOffset;
|
||||
public Vector3 m_mountainOffset;
|
||||
public Vector3 m_valleyOffset;
|
||||
public float m_smoothness = 1f;
|
||||
public bool m_shapeFoldedOut;
|
||||
public bool m_mountainsFoldedOut;
|
||||
public bool m_valleysFoldedOut;
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
#region Serialization
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b113ae1283ed08b4ba3f2be14bcb5163
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 0861027633dd71c4485845e27852793c, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,663 @@
|
||||
using ProceduralWorlds.WaterSystem;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
#if UNITY_POST_PROCESSING_STACK_V2
|
||||
using UnityEngine.Rendering.PostProcessing;
|
||||
#endif
|
||||
using static Gaia.GaiaConstants;
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// A generic spawning system.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class BiomeController : MonoBehaviour
|
||||
{
|
||||
|
||||
[SerializeField]
|
||||
private BiomeControllerSettings settings;
|
||||
/// <summary>
|
||||
/// The current biome controller settings
|
||||
/// </summary>
|
||||
public BiomeControllerSettings m_settings
|
||||
{
|
||||
get
|
||||
{
|
||||
if (settings == null && gameObject!=null)
|
||||
{
|
||||
settings = ScriptableObject.CreateInstance<BiomeControllerSettings>();
|
||||
settings.name = gameObject.name;
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
set
|
||||
{
|
||||
settings = value;
|
||||
}
|
||||
|
||||
}
|
||||
public bool m_autoSpawnersToggleAll = false;
|
||||
public List<AutoSpawner> m_autoSpawners = new List<AutoSpawner>();
|
||||
#if UNITY_POST_PROCESSING_STACK_V2
|
||||
public PostProcessProfile m_postProcessProfile;
|
||||
public BiomePostProcessingVolumeSpawnMode m_ppVSpawnMode = BiomePostProcessingVolumeSpawnMode.Add;
|
||||
#endif
|
||||
public bool m_autoSpawnRequested;
|
||||
public bool m_drawPreview;
|
||||
public bool m_biomePreviewDirty;
|
||||
private Terrain m_lastActiveTerrain;
|
||||
private float m_minWorldHeight;
|
||||
private float m_maxWorldHeight;
|
||||
private RenderTexture m_cachedPreviewRT;
|
||||
|
||||
private GaiaSettings m_gaiaSettings;
|
||||
private GaiaSettings GaiaSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_gaiaSettings == null)
|
||||
{
|
||||
m_gaiaSettings = GaiaUtils.GetGaiaSettings();
|
||||
}
|
||||
return m_gaiaSettings;
|
||||
}
|
||||
}
|
||||
|
||||
public AutoSpawnerArea m_autoSpawnerArea = AutoSpawnerArea.Local;
|
||||
public bool m_showSeaLevelPlane = true;
|
||||
public bool m_showSeaLevelinPreview = true;
|
||||
public bool m_showBoundingBox = true;
|
||||
public string m_oldName;
|
||||
public bool m_changesMadeSinceLastSave;
|
||||
public bool m_biomeWasSpawned;
|
||||
|
||||
public bool m_highlightLoadingSettings;
|
||||
public long m_highlightLoadingSettingsStartedTimeStamp;
|
||||
|
||||
#if GAIA_PRO_PRESENT
|
||||
private TerrainLoader m_terrainLoader;
|
||||
public LoadMode m_loadTerrainMode = LoadMode.Disabled;
|
||||
public int m_impostorLoadingRange;
|
||||
public TerrainLoader TerrainLoader
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_terrainLoader == null)
|
||||
{
|
||||
if (this != null)
|
||||
{
|
||||
m_terrainLoader = gameObject.GetComponent<TerrainLoader>();
|
||||
|
||||
if (m_terrainLoader == null)
|
||||
{
|
||||
m_terrainLoader = gameObject.AddComponent<TerrainLoader>();
|
||||
m_terrainLoader.hideFlags = HideFlags.HideInInspector;
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_terrainLoader;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private GaiaSessionManager m_sessionManager;
|
||||
private GaiaSessionManager SessionManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_sessionManager == null)
|
||||
{
|
||||
m_sessionManager = GaiaSessionManager.GetSessionManager(false);
|
||||
}
|
||||
return m_sessionManager;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds child game objects that contain a spawner component to the list of spawners
|
||||
/// </summary>
|
||||
public void UpdateSpawnerList()
|
||||
{
|
||||
for (int i =0; i<transform.childCount; i++)
|
||||
{
|
||||
Transform t = transform.GetChild(i);
|
||||
Spawner spawner = t.GetComponent<Spawner>();
|
||||
if (spawner != null)
|
||||
{
|
||||
if (m_autoSpawners.Find(x => x.spawner == spawner) == null)
|
||||
{
|
||||
m_autoSpawners.Insert(i, new AutoSpawner() { isActive = true, spawner = spawner });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void HighlightLoadingSettings()
|
||||
{
|
||||
m_highlightLoadingSettings = true;
|
||||
m_highlightLoadingSettingsStartedTimeStamp = GaiaUtils.GetUnixTimestamp();
|
||||
}
|
||||
|
||||
|
||||
public void UpdateAutoLoadRange()
|
||||
{
|
||||
#if GAIA_PRO_PRESENT
|
||||
if (m_loadTerrainMode != LoadMode.Disabled)
|
||||
{
|
||||
float width = m_settings.m_range * 2f;
|
||||
//reduce the loading width a bit => this is to prevent loading in terrains when the spawner bounds end exactly at the border of
|
||||
//surrounding terrains, this loads in a lot of extra terrains which are not required for the spawn
|
||||
width -= 0.5f;
|
||||
Vector3 center = transform.position;
|
||||
TerrainLoader.m_loadingBoundsRegular.center = center;
|
||||
TerrainLoader.m_loadingBoundsRegular.size = new Vector3(width, width, width);
|
||||
TerrainLoader.m_loadingBoundsImpostor.center = center;
|
||||
if (m_impostorLoadingRange > 0)
|
||||
{
|
||||
TerrainLoader.m_loadingBoundsImpostor.size = new Vector3(width + m_impostorLoadingRange, width + m_impostorLoadingRange, width + m_impostorLoadingRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
TerrainLoader.m_loadingBoundsImpostor.size = Vector3.zero;
|
||||
}
|
||||
|
||||
}
|
||||
TerrainLoader.LoadMode = m_loadTerrainMode;
|
||||
#endif
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
m_settings.ClearImageMaskTextures();
|
||||
}
|
||||
|
||||
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 void LoadSettings(BiomeControllerSettings settingsToLoad)
|
||||
{
|
||||
m_settings.ClearImageMaskTextures();
|
||||
//set position according to the stored settings
|
||||
transform.position = new Vector3(settingsToLoad.m_x, settingsToLoad.m_y, settingsToLoad.m_z);
|
||||
|
||||
//Set existing settings = null to force a new scriptable object
|
||||
m_settings = null;
|
||||
m_settings = Instantiate(settingsToLoad);
|
||||
|
||||
//Try to look up all collision layer masks by their name where possible - layer orders could be different from when the biome controller was saved.
|
||||
foreach (ImageMask imageMask in m_settings.m_imageMasks.Where(x => x.m_operation == ImageMaskOperation.CollisionMask))
|
||||
{
|
||||
imageMask.TryRefreshCollisionMask();
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadFromPreset(BiomePreset presetToLoad)
|
||||
{
|
||||
try
|
||||
{
|
||||
presetToLoad.RefreshSpawnerListEntries();
|
||||
m_autoSpawners.Clear();
|
||||
//Remove all child spawners
|
||||
for (int i = transform.childCount - 1; i >= 0; i--)
|
||||
{
|
||||
DestroyImmediate(transform.GetChild(i).gameObject);
|
||||
}
|
||||
|
||||
//Track created spawners
|
||||
List<Spawner> createdSpawners = new List<Spawner>();
|
||||
int totalCount = presetToLoad.m_spawnerPresetList.Count();
|
||||
int currentCount = 0;
|
||||
foreach (BiomeSpawnerListEntry spawnerListEntry in presetToLoad.m_spawnerPresetList)
|
||||
{
|
||||
createdSpawners.Add(spawnerListEntry.m_spawnerSettings.CreateSpawner(false, transform));
|
||||
//GaiaUtils.DisplayProgressBarNoEditor("Creating Tools", "Creating Biome " + this.name, ++currentStep / totalSteps);
|
||||
if (ProgressBar.Show(ProgressBarPriority.CreateBiomeTools, "Loading Biome Preset", "Creating Tools", ++currentCount, totalCount, false, true))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (createdSpawners.Count > 0)
|
||||
{
|
||||
m_settings.m_range = createdSpawners[0].m_settings.m_spawnRange;
|
||||
}
|
||||
|
||||
foreach (Spawner spawner in createdSpawners)
|
||||
{
|
||||
m_autoSpawners.Add(new AutoSpawner() { isActive = true, status = AutoSpawnerStatus.Initial, spawner = spawner });
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError("Error while loading biome preset settings, Message: " + ex.Message + ", Stack Trace: " + ex.StackTrace);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ProgressBar.Clear(ProgressBarPriority.CreateBiomeTools);
|
||||
}
|
||||
}
|
||||
|
||||
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 UpdateMinMaxHeight()
|
||||
{
|
||||
SessionManager.GetWorldMinMax(ref m_minWorldHeight, ref m_maxWorldHeight, false);
|
||||
float seaLevel = SessionManager.GetSeaLevel(false);
|
||||
//Iterate through all image masks and set up the current min max height
|
||||
//This is fairly important to display the height-dependent mask settings correctly
|
||||
foreach (ImageMask mask in m_settings.m_imageMasks)
|
||||
{
|
||||
mask.m_maxWorldHeight = m_maxWorldHeight;
|
||||
mask.m_minWorldHeight = m_minWorldHeight;
|
||||
mask.m_seaLevel = seaLevel;
|
||||
}
|
||||
ImageMask.CheckMaskStackForInvalidTextureRules("Biome Controller", this.name, m_settings.m_imageMasks);
|
||||
}
|
||||
|
||||
public void DrawBiomePreview()
|
||||
{
|
||||
if (m_drawPreview)
|
||||
{
|
||||
|
||||
//Set up a multi-terrain operation once, all rules can then draw from the data collected here
|
||||
Terrain currentTerrain = GetCurrentTerrain();
|
||||
if (currentTerrain == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(currentTerrain, transform, m_settings.m_range * 2f);
|
||||
operation.GetHeightmap();
|
||||
|
||||
|
||||
//only re-generate all textures etc. if settings have changed and the preview is dirty, otherwise we can just use the cached textures
|
||||
if (m_biomePreviewDirty == true)
|
||||
{
|
||||
//Get additional op data (required for certain image masks)
|
||||
operation.GetNormalmap();
|
||||
operation.CollectTerrainBakedMasks();
|
||||
|
||||
//Clear texture cache first
|
||||
if (m_cachedPreviewRT != null)
|
||||
{
|
||||
m_cachedPreviewRT.Release();
|
||||
DestroyImmediate(m_cachedPreviewRT);
|
||||
}
|
||||
|
||||
m_cachedPreviewRT = new RenderTexture(operation.RTheightmap);
|
||||
RenderTexture currentRT = RenderTexture.active;
|
||||
RenderTexture.active = m_cachedPreviewRT;
|
||||
GL.Clear(true, true, Color.black);
|
||||
RenderTexture.active = currentRT;
|
||||
|
||||
Graphics.Blit(ApplyBrush(operation), m_cachedPreviewRT);
|
||||
RenderTexture.active = currentRT;
|
||||
//Everything processed, preview not dirty anymore
|
||||
m_biomePreviewDirty = false;
|
||||
}
|
||||
|
||||
//Now draw the preview according to the cached textures
|
||||
Material material = GaiaMultiTerrainOperation.GetDefaultGaiaSpawnerPreviewMaterial();
|
||||
material.SetInt("_zTestMode", (int)UnityEngine.Rendering.CompareFunction.Always);
|
||||
|
||||
//assign the first color texture in the material
|
||||
material.SetTexture("_colorTexture0", m_cachedPreviewRT);
|
||||
|
||||
//remove all other potential color textures, there can be caching issues if other visualisers were used in the meantime
|
||||
|
||||
for (int colorIndex = 1; colorIndex < GaiaConstants.maxPreviewedTextures; colorIndex++)
|
||||
{
|
||||
material.SetTexture("_colorTexture" + colorIndex, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//set the color
|
||||
material.SetColor("_previewColor0", m_settings.m_visualisationColor);
|
||||
|
||||
Color seaLevelColor = GaiaSettings.m_stamperSeaLevelTintColor;
|
||||
if (!m_showSeaLevelinPreview)
|
||||
{
|
||||
seaLevelColor.a = 0f;
|
||||
}
|
||||
material.SetColor("_seaLevelTintColor", seaLevelColor);
|
||||
material.SetFloat("_seaLevel", SessionManager.m_session.m_seaLevel);
|
||||
operation.Visualize(MultiTerrainOperationType.Heightmap, operation.RTheightmap, material, 1);
|
||||
|
||||
//Clean up
|
||||
operation.CloseOperation();
|
||||
//Clean up temp textures
|
||||
GaiaUtils.ReleaseAllTempRenderTextures();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private RenderTexture ApplyBrush(GaiaMultiTerrainOperation operation, MultiTerrainOperationType opType = MultiTerrainOperationType.Heightmap)
|
||||
{
|
||||
Terrain currentTerrain = GetCurrentTerrain();
|
||||
|
||||
RenderTextureDescriptor rtDescriptor = operation.RTheightmap.descriptor;
|
||||
|
||||
switch (opType)
|
||||
{
|
||||
case MultiTerrainOperationType.Heightmap:
|
||||
rtDescriptor = operation.RTheightmap.descriptor;
|
||||
break;
|
||||
case MultiTerrainOperationType.Texture:
|
||||
rtDescriptor = operation.RTtextureSplatmap.descriptor;
|
||||
break;
|
||||
case MultiTerrainOperationType.TerrainDetail:
|
||||
rtDescriptor = operation.RTdetailmap.descriptor;
|
||||
break;
|
||||
case MultiTerrainOperationType.Tree:
|
||||
rtDescriptor = operation.RTterrainTree.descriptor;
|
||||
break;
|
||||
case MultiTerrainOperationType.GameObject:
|
||||
rtDescriptor = operation.RTgameObject.descriptor;
|
||||
break;
|
||||
default:
|
||||
rtDescriptor = operation.RTheightmap.descriptor;
|
||||
break;
|
||||
}
|
||||
|
||||
//Random write needs to be enabled for certain mask types to function!
|
||||
rtDescriptor.enableRandomWrite = true;
|
||||
|
||||
RenderTexture inputTexture = RenderTexture.GetTemporary(rtDescriptor);
|
||||
|
||||
RenderTexture currentRT = RenderTexture.active;
|
||||
RenderTexture.active = inputTexture;
|
||||
GL.Clear(true, true, Color.white);
|
||||
RenderTexture.active = currentRT;
|
||||
|
||||
//Iterate through all image masks and set up the current paint context in case the shader uses heightmap data
|
||||
foreach (ImageMask mask in m_settings.m_imageMasks)
|
||||
{
|
||||
mask.m_multiTerrainOperation = operation;
|
||||
mask.m_seaLevel = SessionManager.GetSeaLevel();
|
||||
mask.m_maxWorldHeight = m_maxWorldHeight;
|
||||
mask.m_minWorldHeight = m_minWorldHeight;
|
||||
}
|
||||
|
||||
//Get the combined masks for the biome
|
||||
RenderTexture biomeOutputTexture = RenderTexture.GetTemporary(rtDescriptor);
|
||||
Graphics.Blit(ImageProcessing.ApplyMaskStack(inputTexture, biomeOutputTexture, m_settings.m_imageMasks, ImageMaskInfluence.Local), biomeOutputTexture);
|
||||
ReleaseRenderTexture(inputTexture);
|
||||
inputTexture = null;
|
||||
return biomeOutputTexture;
|
||||
}
|
||||
|
||||
|
||||
private void ReleaseRenderTexture(RenderTexture texture)
|
||||
{
|
||||
if (texture != null)
|
||||
{
|
||||
RenderTexture.ReleaseTemporary(texture);
|
||||
texture = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveForeignTrees(List<SpawnerSettings> biomeSpawnerSettings, List<string> validTerrainNames = null)
|
||||
{
|
||||
ProgressBar.Show(ProgressBarPriority.BiomeRemoval, "Removing Foreign Trees", "Removing...");
|
||||
//Collect the "allowed" tree prefabs in a list, any tree that is not in this list will be affected by the removal operation
|
||||
List<GameObject> domesticTreePrefabs = new List<GameObject>();
|
||||
//List<TreePrototype> treeProtosToRemove = new List<TreePrototype>();
|
||||
Terrain currentTerrain = GetCurrentTerrain();
|
||||
foreach (SpawnerSettings spawnerSettings in biomeSpawnerSettings)
|
||||
{
|
||||
foreach (SpawnRule sr in spawnerSettings.m_spawnerRules)
|
||||
{
|
||||
if (sr.m_resourceType == GaiaConstants.SpawnerResourceType.TerrainTree)
|
||||
{
|
||||
domesticTreePrefabs.Add(spawnerSettings.m_resources.m_treePrototypes[sr.m_resourceIdx].m_desktopPrefab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(currentTerrain, transform, m_settings.m_range * 2f, false, validTerrainNames);
|
||||
operation.GetHeightmap();
|
||||
operation.GetNormalmap();
|
||||
operation.CollectTerrainDetails();
|
||||
operation.CollectTerrainTrees();
|
||||
operation.CollectTerrainGameObjects();
|
||||
operation.CollectTerrainBakedMasks();
|
||||
|
||||
operation.RemoveForeignTrees(ApplyBrush(operation,MultiTerrainOperationType.Tree), domesticTreePrefabs, m_settings.m_removeForeignTreesStrength);
|
||||
ProgressBar.Clear(ProgressBarPriority.BiomeRemoval);
|
||||
operation.CloseOperation();
|
||||
}
|
||||
|
||||
public void RemoveForeignGameObjects(List<SpawnerSettings> biomeSpawnerSettings, List<string> validTerrainNames=null)
|
||||
{
|
||||
ProgressBar.Show(ProgressBarPriority.BiomeRemoval, "Removing Foreign GameObjects", "Removing...");
|
||||
List<ResourceProtoGameObjectInstance> knownProtoInstances = new List<ResourceProtoGameObjectInstance>();
|
||||
List<ResourceProtoGameObjectInstance> GoProtoInstancesToRemove = new List<ResourceProtoGameObjectInstance>();
|
||||
Terrain currentTerrain = GetCurrentTerrain();
|
||||
foreach (SpawnerSettings spawnerSettings in biomeSpawnerSettings)
|
||||
{
|
||||
foreach (SpawnRule sr in spawnerSettings.m_spawnerRules)
|
||||
{
|
||||
if (sr.m_resourceType == GaiaConstants.SpawnerResourceType.GameObject)
|
||||
{
|
||||
foreach (ResourceProtoGameObjectInstance instance in spawnerSettings.m_resources.m_gameObjectPrototypes[sr.m_resourceIdx].m_instances)
|
||||
{
|
||||
knownProtoInstances.Add(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(currentTerrain, transform, m_settings.m_range * 2f, false, validTerrainNames);
|
||||
operation.GetHeightmap();
|
||||
operation.GetNormalmap();
|
||||
operation.CollectTerrainDetails();
|
||||
operation.CollectTerrainTrees();
|
||||
operation.CollectTerrainGameObjects();
|
||||
operation.CollectTerrainBakedMasks();
|
||||
|
||||
int protoIndex = 0;
|
||||
var allSpawners = Resources.FindObjectsOfTypeAll<Spawner>();
|
||||
foreach (Spawner spawner in allSpawners)
|
||||
{
|
||||
//During the removal we have to put the spawn settings in remove mode
|
||||
SpawnMode originalMode = spawner.m_settings.m_spawnMode;
|
||||
spawner.m_settings.m_spawnMode = SpawnMode.Remove;
|
||||
|
||||
ProgressBar.Show(ProgressBarPriority.BiomeRemoval, "Removing Foreign GameObjects", "Removing Game Objects...", protoIndex , allSpawners.Length);
|
||||
foreach (SpawnRule sr in spawner.m_settings.m_spawnerRules)
|
||||
{
|
||||
|
||||
|
||||
if (sr.m_resourceType == GaiaConstants.SpawnerResourceType.GameObject)
|
||||
{
|
||||
ResourceProtoGameObject protoGO = spawner.m_settings.m_resources.m_gameObjectPrototypes[sr.m_resourceIdx];
|
||||
foreach (ResourceProtoGameObjectInstance instance in protoGO.m_instances)
|
||||
{
|
||||
if (!knownProtoInstances.Contains(instance))
|
||||
{
|
||||
operation.SetTerrainGameObjects(ApplyBrush(operation, MultiTerrainOperationType.GameObject), protoGO, sr, spawner.m_settings, 0, ref sr.m_spawnedInstances, m_settings.m_removeForeignGameObjectStrength,false);
|
||||
//no need to look at other instances if this one triggered the removal already
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spawner.m_settings.m_spawnMode = originalMode;
|
||||
protoIndex++;
|
||||
}
|
||||
operation.CloseOperation();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
//need to dirty the scene when we remove game objects
|
||||
EditorSceneManager.MarkSceneDirty(gameObject.scene);
|
||||
#endif
|
||||
ProgressBar.Clear(ProgressBarPriority.BiomeRemoval);
|
||||
}
|
||||
|
||||
public void RemoveForeignTerrainDetails(List<SpawnerSettings> biomeSpawnerSettings, List<string> validTerrainNames = null)
|
||||
{
|
||||
ProgressBar.Show(ProgressBarPriority.BiomeRemoval, "Removing Foreign Terrain Details", "Removing...");
|
||||
List<ResourceProtoDetail> knownTerrainDetails = new List<ResourceProtoDetail>();
|
||||
Terrain currentTerrain = GetCurrentTerrain();
|
||||
foreach (SpawnerSettings spawnerSettings in biomeSpawnerSettings)
|
||||
{
|
||||
foreach (SpawnRule sr in spawnerSettings.m_spawnerRules)
|
||||
{
|
||||
if (sr.m_resourceType == GaiaConstants.SpawnerResourceType.TerrainDetail)
|
||||
{
|
||||
knownTerrainDetails.Add(spawnerSettings.m_resources.m_detailPrototypes[sr.m_resourceIdx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(currentTerrain, transform, m_settings.m_range * 2f, false, validTerrainNames);
|
||||
operation.GetHeightmap();
|
||||
operation.GetNormalmap();
|
||||
operation.CollectTerrainDetails();
|
||||
operation.CollectTerrainTrees();
|
||||
operation.CollectTerrainGameObjects();
|
||||
operation.CollectTerrainBakedMasks();
|
||||
|
||||
ProgressBar.Show(ProgressBarPriority.BiomeRemoval, "Removing Foreign Terrain Details", "Removing Terrain Details...");
|
||||
operation.RemoveForeignTerrainDetails(ApplyBrush(operation, MultiTerrainOperationType.TerrainDetail), knownTerrainDetails, m_settings.m_removeForeignTerrainDetailsStrength);
|
||||
|
||||
operation.CloseOperation();
|
||||
ProgressBar.Clear(ProgressBarPriority.BiomeRemoval);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd63de8b80658e841978e0280130ee66
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,115 @@
|
||||
// Copyright © 2018 Procedural Worlds Pty Limited. All Rights Reserved.
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using static Gaia.GaiaConstants;
|
||||
using UnityEditor;
|
||||
|
||||
/*
|
||||
* Scriptable Object containing settings for a Biome Controller
|
||||
*/
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
[System.Serializable]
|
||||
public class BiomeControllerSettings : ScriptableObject, ISerializationCallbackReceiver
|
||||
{
|
||||
|
||||
#region Public Variables
|
||||
///// <summary>
|
||||
///// Biome x location
|
||||
///// </summary>
|
||||
public float m_x = 0f;
|
||||
|
||||
///// <summary>
|
||||
///// Biome y location
|
||||
///// </summary>
|
||||
public float m_y = 50f;
|
||||
|
||||
///// <summary>
|
||||
///// Biome z location
|
||||
///// </summary>
|
||||
public float m_z = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Range of the biome controller when spawning locally
|
||||
/// </summary>
|
||||
public float m_range = 1024;
|
||||
|
||||
public float m_postProcessBlenddDistance;
|
||||
|
||||
public Color m_visualisationColor = GaiaConstants.spawnerInitColor;
|
||||
|
||||
public bool m_removeForeignGameObjects;
|
||||
public float m_removeForeignGameObjectStrength = 0.2f;
|
||||
public bool m_removeForeignTrees;
|
||||
public float m_removeForeignTreesStrength = 0.2f;
|
||||
public bool m_removeForeignTerrainDetails;
|
||||
public float m_removeForeignTerrainDetailsStrength = 0.2f;
|
||||
|
||||
[SerializeField]
|
||||
private ImageMask[] imageMasks = new ImageMask[0];
|
||||
public string m_lastSavePath;
|
||||
|
||||
//Clear flags
|
||||
public bool m_clearSpawnsToggleTrees;
|
||||
public bool m_clearSpawnsToggleDetails;
|
||||
public bool m_clearSpawnsToggleGOs;
|
||||
public bool m_clearSpawnsToggleSpawnExtensions;
|
||||
public bool m_clearSpawnsToggleProbes;
|
||||
public ClearSpawnFor m_clearSpawnsFor;
|
||||
public ClearSpawnFromBiomes m_clearSpawnsFrom;
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Removes References to Texture2Ds in Image masks. The image mask will still remember the GUID of that texture to load it when needed.
|
||||
/// Call this when you are "done" with the biome controller settings to free up memory caused by these references.
|
||||
/// </summary>
|
||||
public void ClearImageMaskTextures()
|
||||
{
|
||||
foreach (ImageMask im in m_imageMasks)
|
||||
{
|
||||
im.FreeTextureReferences();
|
||||
}
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Using a property to make sure the image mask list is always initialized
|
||||
//<summary>All image filters that are being applied in this spawning process</summary>
|
||||
|
||||
public ImageMask[] m_imageMasks {
|
||||
get
|
||||
{
|
||||
if (imageMasks == null)
|
||||
{
|
||||
imageMasks = new ImageMask[0];
|
||||
}
|
||||
return imageMasks;
|
||||
}
|
||||
set
|
||||
{
|
||||
imageMasks = value;
|
||||
}
|
||||
}
|
||||
|
||||
//public float m_powerOf;
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
#region Serialization
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d4b6d2ca1100d734aaa40e6410ad3214
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 0861027633dd71c4485845e27852793c, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,225 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
#if UNITY_POST_PROCESSING_STACK_V2
|
||||
using UnityEngine.Rendering.PostProcessing;
|
||||
#endif
|
||||
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
[System.Serializable]
|
||||
public class BiomeSpawnerListEntry : IComparable
|
||||
{
|
||||
public bool m_autoAssignPrototypes;
|
||||
public SpawnerSettings m_spawnerSettings;
|
||||
public bool m_isActiveInStamper;
|
||||
public bool m_isActiveInBiome;
|
||||
|
||||
public int CompareTo(object other)
|
||||
{
|
||||
if (other.GetType() != typeof(BiomeSpawnerListEntry))
|
||||
throw new NotImplementedException();
|
||||
|
||||
return (m_spawnerSettings.name.CompareTo(((BiomeSpawnerListEntry)other).m_spawnerSettings.name));
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class AdvancedTabBiomeListEntry : IComparable
|
||||
{
|
||||
public bool m_autoAssignPrototypes;
|
||||
public BiomePreset m_biomePreset;
|
||||
|
||||
public int CompareTo(object other)
|
||||
{
|
||||
if (other.GetType() != typeof(AdvancedTabBiomeListEntry))
|
||||
throw new NotImplementedException();
|
||||
|
||||
return (m_biomePreset.m_orderNumber.CompareTo(((AdvancedTabBiomeListEntry)other).m_biomePreset.m_orderNumber));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Just a simple association from Spawner Preset to an incremental int ID - used in the the Gaia Manager Window to have a simple dropdown of possible presets + an empty "Custom" selection
|
||||
/// </summary>
|
||||
public struct BiomePresetDropdownEntry : IComparable
|
||||
{
|
||||
public BiomePreset biomePreset;
|
||||
public string name;
|
||||
public int ID;
|
||||
|
||||
public int CompareTo(object other)
|
||||
{
|
||||
if (other.GetType() != typeof(BiomePresetDropdownEntry))
|
||||
throw new NotImplementedException();
|
||||
|
||||
return biomePreset.m_orderNumber.CompareTo(((BiomePresetDropdownEntry)other).biomePreset.m_orderNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Contains a list of spawner settings that are designed to be created together with a new terrain.</summary>
|
||||
[CreateAssetMenu(menuName = "Procedural Worlds/Gaia/Biome Preset")]
|
||||
[System.Serializable]
|
||||
public class BiomePreset : ScriptableObject
|
||||
{
|
||||
public int m_orderNumber = 0;
|
||||
public List<BiomeSpawnerListEntry> m_spawnerPresetList = new List<BiomeSpawnerListEntry>();
|
||||
|
||||
#if UNITY_POST_PROCESSING_STACK_V2
|
||||
[System.NonSerialized]
|
||||
private PostProcessProfile m_postProcessProfile = null;
|
||||
|
||||
//This construct ensures we only serialize the GUID of the PP profile, but not the profile itself
|
||||
//The GUID will "survive" when PP is not installed in a project, while the PP profile object would not
|
||||
public PostProcessProfile postProcessProfile
|
||||
{
|
||||
|
||||
get
|
||||
{
|
||||
if (m_postProcessProfile == null && m_postProcessingProfileGUID != null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
m_postProcessProfile = (PostProcessProfile)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(m_postProcessingProfileGUID), typeof(PostProcessProfile));
|
||||
#endif
|
||||
}
|
||||
return m_postProcessProfile;
|
||||
}
|
||||
set
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
m_postProcessingProfileGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(value));
|
||||
m_postProcessProfile = value;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
//need this serialized to remember the GUID even when PP is not installed in the project
|
||||
[SerializeField]
|
||||
private string m_postProcessingProfileGUID = "";
|
||||
[SerializeField]
|
||||
private GaiaSceneCullingProfile m_gaiaSceneCullingProfile;
|
||||
public GaiaSceneCullingProfile GaiaSceneCullingProfile
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_gaiaSceneCullingProfile == null)
|
||||
{
|
||||
m_gaiaSceneCullingProfile = (GaiaSceneCullingProfile)GaiaUtils.GetAsset(GaiaConstants.defaultSceneCullingProfile, typeof(GaiaSceneCullingProfile));
|
||||
}
|
||||
return m_gaiaSceneCullingProfile;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_gaiaSceneCullingProfile = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshSpawnerListEntries()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
//walk through the references spawner settings files, and if they have a "last saved path" reload them again in this preset to make sure the reference in there is correct.
|
||||
foreach (BiomeSpawnerListEntry bsle in m_spawnerPresetList)
|
||||
{
|
||||
if (bsle.m_spawnerSettings != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(bsle.m_spawnerSettings.m_lastGUIDSaved))
|
||||
{
|
||||
SpawnerSettings spawnerSettings = (SpawnerSettings)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(bsle.m_spawnerSettings.m_lastGUIDSaved), typeof(SpawnerSettings));
|
||||
if (spawnerSettings != null)
|
||||
{
|
||||
bsle.m_spawnerSettings = spawnerSettings;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public BiomeController CreateBiome(bool autoAssignPrototypes)
|
||||
{
|
||||
int totalSteps = m_spawnerPresetList.Count;
|
||||
int currentStep = 0;
|
||||
|
||||
#if !UNITY_POST_PROCESSING_STACK_V2
|
||||
//Workaround to disable warnings for "unused" field m_postProcessingProfileGUID
|
||||
//This is just a "harmless" piece of code to make the compiler think the field is in use
|
||||
if (m_postProcessingProfileGUID == "")
|
||||
{
|
||||
currentStep = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
GaiaSessionManager sessionManager = GaiaSessionManager.GetSessionManager();
|
||||
Transform gaiaTransform = GaiaUtils.GetGaiaGameObject().transform;
|
||||
GameObject newGO = new GameObject();
|
||||
newGO.name = this.name + " Biome";
|
||||
newGO.transform.parent = gaiaTransform;
|
||||
|
||||
BiomeController biomeController = newGO.AddComponent<BiomeController>();
|
||||
|
||||
RefreshSpawnerListEntries();
|
||||
|
||||
//Track created spawners
|
||||
List<Spawner> createdSpawners = new List<Spawner>();
|
||||
foreach (BiomeSpawnerListEntry spawnerListEntry in m_spawnerPresetList)
|
||||
{
|
||||
if (spawnerListEntry != null)
|
||||
{
|
||||
if (spawnerListEntry.m_spawnerSettings != null)
|
||||
{
|
||||
createdSpawners.Add(spawnerListEntry.m_spawnerSettings.CreateSpawner(false, biomeController.transform));
|
||||
//GaiaUtils.DisplayProgressBarNoEditor("Creating Tools", "Creating Biome " + this.name, ++currentStep / totalSteps);
|
||||
if (ProgressBar.Show(ProgressBarPriority.CreateBiomeTools, "Creating Biome", "Creating Tools", ++currentStep, totalSteps, false, true))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (createdSpawners.Count > 0)
|
||||
{
|
||||
biomeController.m_settings.m_range = createdSpawners[0].m_settings.m_spawnRange;
|
||||
}
|
||||
|
||||
for (int i = 0; i < createdSpawners.Count; i++)
|
||||
{
|
||||
Spawner spawner = createdSpawners[i];
|
||||
biomeController.m_autoSpawners.Add(new AutoSpawner() { isActive = m_spawnerPresetList[i].m_isActiveInBiome, status = AutoSpawnerStatus.Initial, spawner = spawner });
|
||||
}
|
||||
if (autoAssignPrototypes)
|
||||
{
|
||||
//prepare resource prototype arrays once, so the same prototypes can be added to all the tiles.
|
||||
TerrainLayer[] terrainLayers = new TerrainLayer[0];
|
||||
DetailPrototype[] terrainDetails = new DetailPrototype[0];
|
||||
TreePrototype[] terrainTrees = new TreePrototype[0];
|
||||
GaiaDefaults.GetPrototypes(m_spawnerPresetList.Where(x => x.m_autoAssignPrototypes == true).ToList(), ref terrainLayers, ref terrainDetails, ref terrainTrees, Terrain.activeTerrain);
|
||||
|
||||
foreach (Terrain t in Terrain.activeTerrains)
|
||||
{
|
||||
GaiaDefaults.ApplyPrototypesToTerrain(t, terrainLayers, terrainDetails, terrainTrees);
|
||||
}
|
||||
}
|
||||
|
||||
if (GaiaUtils.CheckIfSceneProfileExists())
|
||||
{
|
||||
GaiaGlobal.Instance.SceneProfile.CullingProfile = GaiaSceneCullingProfile;
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_POST_PROCESSING_STACK_V2
|
||||
biomeController.m_postProcessProfile = postProcessProfile;
|
||||
#endif
|
||||
ProgressBar.Clear(ProgressBarPriority.CreateBiomeTools);
|
||||
|
||||
return biomeController;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8bf996bd940696a4b814912e16c3d5ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: c124d01b3e9d009458e77af1a6efe7c1, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e85f920f42e737b459e0298c54646269
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+1206
File diff suppressed because it is too large.
Load diff
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90d11c9154f1cea46bc91709ce3da22f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,91 @@
|
||||
using PWCommon4;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
//This class is not a full editor class by itself, but used to collect reusable methods
|
||||
//for editing Biomes in a reorderable list.
|
||||
public class BiomeListEditor : PWEditor, IPWEditor
|
||||
{
|
||||
|
||||
public static float OnElementHeight()
|
||||
{
|
||||
return EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
public static void DrawListHeader(Rect rect, bool currentFoldOutState, List<AdvancedTabBiomeListEntry> biomesList, EditorUtils editorUtils, string headerKey)
|
||||
{
|
||||
int oldIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
//rect.xMin += 0f;
|
||||
EditorGUI.LabelField(rect, editorUtils.GetContent(headerKey));
|
||||
//bool newFoldOutState = EditorGUI.Foldout(rect, currentFoldOutState, PropertyCount("SpawnerAdded", spawnerList, editorUtils), true);
|
||||
EditorGUI.indentLevel = oldIndent;
|
||||
//return newFoldOutState;
|
||||
}
|
||||
|
||||
public static void DrawListElement_AdvancedTab(Rect rect, AdvancedTabBiomeListEntry listEntry, EditorUtils m_editorUtils)
|
||||
{
|
||||
int oldIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
|
||||
Rect labelRect = rect;
|
||||
//260 is the total width of the controls at the end of each row
|
||||
labelRect.width = rect.width -280;
|
||||
labelRect.height = EditorGUIUtility.singleLineHeight;
|
||||
|
||||
EditorGUI.LabelField(labelRect, listEntry.m_biomePreset.name);
|
||||
|
||||
EditorGUIUtility.AddCursorRect(labelRect, MouseCursor.Zoom);
|
||||
if (labelRect.Contains(Event.current.mousePosition) && Event.current.clickCount>0)
|
||||
{
|
||||
Selection.activeObject = listEntry.m_biomePreset;
|
||||
EditorGUIUtility.PingObject(Selection.activeObject);
|
||||
}
|
||||
|
||||
labelRect.x = rect.width - 230;
|
||||
labelRect.width = 110f;
|
||||
|
||||
EditorGUI.LabelField(labelRect, m_editorUtils.GetContent("SpawnerListAutoAssignPrototypes"));
|
||||
|
||||
labelRect.x = rect.width - 130f;
|
||||
labelRect.width = 20f;
|
||||
|
||||
listEntry.m_autoAssignPrototypes = EditorGUI.Toggle(labelRect, listEntry.m_autoAssignPrototypes);
|
||||
|
||||
labelRect.x = rect.width - 80f;
|
||||
labelRect.width = 100f;
|
||||
if (GUI.Button(labelRect, m_editorUtils.GetContent("AdvancedTabAddBiome")))
|
||||
{
|
||||
BiomeController newBiome = listEntry.m_biomePreset.CreateBiome(listEntry.m_autoAssignPrototypes);
|
||||
Selection.activeGameObject = newBiome.gameObject;
|
||||
}
|
||||
|
||||
|
||||
EditorGUI.indentLevel = oldIndent;
|
||||
}
|
||||
|
||||
public static void DrawListElement(Rect rect, BiomeSpawnerListEntry listEntry, EditorUtils m_editorUtils)
|
||||
{
|
||||
int oldIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
listEntry.m_spawnerSettings = (SpawnerSettings)EditorGUI.ObjectField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), listEntry.m_spawnerSettings, typeof(SpawnerSettings), false);
|
||||
EditorGUI.indentLevel = oldIndent;
|
||||
}
|
||||
|
||||
public static GUIContent PropertyCount(string key, List<BiomeSpawnerListEntry> list, EditorUtils editorUtils)
|
||||
{
|
||||
GUIContent content = editorUtils.GetContent(key);
|
||||
content.text += " [" + list.Count + "]";
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 765621075a226334394984725e5c273e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,157 @@
|
||||
using Gaia.Internal;
|
||||
using PWCommon4;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
#if UNITY_POST_PROCESSING_STACK_V2
|
||||
using UnityEngine.Rendering.PostProcessing;
|
||||
#endif
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Editor for Biome Preset settings, only offers a text & a button to create the spawner in the scene
|
||||
/// If the user wants to edit or create new spawner settings, they can do so by saving a spawner settings file from a spawner directly.
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(BiomePreset))]
|
||||
public class BiomePresetEditor : PWEditor
|
||||
{
|
||||
private EditorUtils m_editorUtils;
|
||||
private BiomePreset m_biomePreset;
|
||||
private UnityEditorInternal.ReorderableList m_spawnerPresetList;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
m_biomePreset = (BiomePreset)target;
|
||||
//Init editor utils
|
||||
if (m_editorUtils == null)
|
||||
{
|
||||
// Get editor utils for this
|
||||
m_editorUtils = PWApp.GetEditorUtils(this);
|
||||
}
|
||||
m_biomePreset.RefreshSpawnerListEntries();
|
||||
CreateSpawnerPresetList();
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
m_editorUtils.Initialize(); // Do not remove this!
|
||||
m_biomePreset = (BiomePreset)target;
|
||||
serializedObject.Update();
|
||||
|
||||
m_editorUtils.Panel("BiomeSettings", DrawBiomeSettings,true);
|
||||
|
||||
if (GUILayout.Button(m_editorUtils.GetContent("AddToScene")))
|
||||
{
|
||||
BiomeController newBiome = m_biomePreset.CreateBiome(true);
|
||||
Selection.activeGameObject = newBiome.gameObject;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void DrawBiomeSettings(bool helpEnabled)
|
||||
{
|
||||
m_biomePreset.m_orderNumber = m_editorUtils.IntField("OrderNumber", m_biomePreset.m_orderNumber, helpEnabled);
|
||||
Rect listRect = EditorGUILayout.GetControlRect(true, m_spawnerPresetList.GetHeight());
|
||||
m_spawnerPresetList.DoList(listRect);
|
||||
m_editorUtils.InlineHelp("SpawnerAdded", helpEnabled);
|
||||
|
||||
|
||||
if (m_biomePreset.m_spawnerPresetList.Count == 0)
|
||||
{
|
||||
GUILayout.Space(EditorGUIUtility.singleLineHeight);
|
||||
EditorGUILayout.HelpBox(m_editorUtils.GetTextValue("NoSpawnersYet"), MessageType.Warning);
|
||||
GUILayout.Space(10);
|
||||
if (m_editorUtils.Button("CreateFirstSpawner"))
|
||||
{
|
||||
GameObject spawnerObj = new GameObject("New Spawner");
|
||||
Spawner spawner = spawnerObj.AddComponent<Spawner>();
|
||||
spawner.m_createdfromBiomePreset = true;
|
||||
Selection.activeGameObject = spawnerObj;
|
||||
}
|
||||
GUILayout.Space(20);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Space(10);
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
if (m_editorUtils.Button("CreateAdditionalSpawner",GUILayout.MaxWidth(200)))
|
||||
{
|
||||
GameObject spawnerObj = new GameObject("New Spawner");
|
||||
Spawner spawner = spawnerObj.AddComponent<Spawner>();
|
||||
spawner.m_createdfromBiomePreset = true;
|
||||
Selection.activeGameObject = spawnerObj;
|
||||
}
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
GUILayout.Space(EditorGUIUtility.singleLineHeight);
|
||||
m_biomePreset.GaiaSceneCullingProfile = (GaiaSceneCullingProfile)m_editorUtils.ObjectField("GaiaSceneCullingProfile", m_biomePreset.GaiaSceneCullingProfile, typeof(GaiaSceneCullingProfile), false, helpEnabled);
|
||||
|
||||
#if UNITY_POST_PROCESSING_STACK_V2
|
||||
GUILayout.Space(EditorGUIUtility.singleLineHeight);
|
||||
m_biomePreset.postProcessProfile = (PostProcessProfile)m_editorUtils.ObjectField("PostProcessingProfile", m_biomePreset.postProcessProfile, typeof(PostProcessProfile), false, helpEnabled);
|
||||
#endif
|
||||
GUILayout.Space(EditorGUIUtility.singleLineHeight);
|
||||
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
EditorUtility.SetDirty(m_biomePreset);
|
||||
}
|
||||
|
||||
#region Spawner Preset List
|
||||
|
||||
void CreateSpawnerPresetList()
|
||||
{
|
||||
m_spawnerPresetList = new UnityEditorInternal.ReorderableList(m_biomePreset.m_spawnerPresetList, typeof(BiomeSpawnerListEntry), true, true, true, true);
|
||||
m_spawnerPresetList.elementHeightCallback = OnElementHeightSpawnerPresetListEntry;
|
||||
m_spawnerPresetList.drawElementCallback = DrawSpawnerPresetListElement;
|
||||
m_spawnerPresetList.drawHeaderCallback = DrawSpawnerPresetListHeader;
|
||||
m_spawnerPresetList.onAddCallback = OnAddSpawnerPresetListEntry;
|
||||
m_spawnerPresetList.onRemoveCallback = OnRemoveSpawnerPresetListEntry;
|
||||
m_spawnerPresetList.onReorderCallback = OnReorderSpawnerPresetList;
|
||||
}
|
||||
|
||||
private void OnReorderSpawnerPresetList(ReorderableList list)
|
||||
{
|
||||
//Do nothing, changing the order does not immediately affect anything in this window
|
||||
}
|
||||
|
||||
private void OnRemoveSpawnerPresetListEntry(ReorderableList list)
|
||||
{
|
||||
m_biomePreset.m_spawnerPresetList = SpawnerPresetListEditor.OnRemoveListEntry(m_biomePreset.m_spawnerPresetList, m_spawnerPresetList.index);
|
||||
list.list = m_biomePreset.m_spawnerPresetList;
|
||||
}
|
||||
|
||||
private void OnAddSpawnerPresetListEntry(ReorderableList list)
|
||||
{
|
||||
m_biomePreset.m_spawnerPresetList = SpawnerPresetListEditor.OnAddListEntry(m_biomePreset.m_spawnerPresetList);
|
||||
list.list = m_biomePreset.m_spawnerPresetList;
|
||||
}
|
||||
|
||||
private void DrawSpawnerPresetListHeader(Rect rect)
|
||||
{
|
||||
SpawnerPresetListEditor.DrawListHeader(rect, true, m_biomePreset.m_spawnerPresetList, m_editorUtils, "SpawnerAdded");
|
||||
}
|
||||
|
||||
private void DrawSpawnerPresetListElement(Rect rect, int index, bool isActive, bool isFocused)
|
||||
{
|
||||
SpawnerPresetListEditor.DrawListElement(rect, m_biomePreset.m_spawnerPresetList[index], m_editorUtils);
|
||||
}
|
||||
|
||||
private float OnElementHeightSpawnerPresetListEntry(int index)
|
||||
{
|
||||
return SpawnerPresetListEditor.OnElementHeight();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 052ba5ee911edda4892967f51a6b2f6d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
using Gaia.Internal;
|
||||
using PWCommon4;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Editor for Spawner settings, only offers a text & a button to create the spawner in the scene
|
||||
/// If the user wants to edit or create new spawner settings, they can do so by saving a spawner settings file from a spawner directly.
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(SpawnerSettings))]
|
||||
public class SpawnerSettingsEditor : PWEditor
|
||||
{
|
||||
private EditorUtils m_editorUtils;
|
||||
private SpawnerSettings m_spawnerSettings;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
//Init editor utils
|
||||
if (m_editorUtils == null)
|
||||
{
|
||||
// Get editor utils for this
|
||||
m_editorUtils = PWApp.GetEditorUtils(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
m_editorUtils.Initialize(); // Do not remove this!
|
||||
m_spawnerSettings = (SpawnerSettings)target;
|
||||
|
||||
string message = m_editorUtils.GetTextValue("Intro"); ;
|
||||
EditorGUILayout.HelpBox(message, MessageType.Info, true);
|
||||
|
||||
if (GUILayout.Button(m_editorUtils.GetContent("AddToScene")))
|
||||
{
|
||||
m_spawnerSettings.CreateSpawner();
|
||||
}
|
||||
|
||||
GUILayout.Label(m_editorUtils.GetContent("SpawnRulePreview"), m_editorUtils.Styles.heading);
|
||||
|
||||
GaiaResource resource = m_spawnerSettings.m_resources;// (GaiaResource)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(m_spawnerSettings.m_resourcesGUID), typeof(GaiaResource));
|
||||
|
||||
foreach (SpawnRule rule in m_spawnerSettings.m_spawnerRules)
|
||||
{
|
||||
m_editorUtils.LabelField("Name", new GUIContent(rule.m_name));
|
||||
m_editorUtils.LabelField("Type", new GUIContent(rule.m_resourceType.ToString()));
|
||||
|
||||
|
||||
Texture2D resourceTexture = SpawnerEditor.GetSpawnRulePreviewTexture(rule, resource);
|
||||
|
||||
if (resourceTexture != null)
|
||||
{
|
||||
m_editorUtils.Image(resourceTexture, 100, 100);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2798f8dfa33d28345a94494e544a0809
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
using PWCommon4;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
//This class is not a full editor class by itself, but used to collect reusable methods
|
||||
//for editing Spawner Settings in a reorderable list.
|
||||
public class SpawnerPresetListEditor : PWEditor, IPWEditor
|
||||
{
|
||||
|
||||
public static float OnElementHeight()
|
||||
{
|
||||
return EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
public static List<BiomeSpawnerListEntry> OnRemoveListEntry(List<BiomeSpawnerListEntry> oldList, int index)
|
||||
{
|
||||
//if (index < 0 || index >= oldList.Length)
|
||||
// return null;
|
||||
//SpawnerPresetListEntry toRemove = oldList[index];
|
||||
//SpawnerPresetListEntry[] newList = new SpawnerPresetListEntry[oldList.Length - 1];
|
||||
//for (int i = 0; i < newList.Length; ++i)
|
||||
//{
|
||||
// if (i < index)
|
||||
// {
|
||||
// newList[i] = oldList[i];
|
||||
// }
|
||||
// else if (i >= index)
|
||||
// {
|
||||
// newList[i] = oldList[i + 1];
|
||||
// }
|
||||
//}
|
||||
oldList.RemoveAt(index);
|
||||
return oldList;
|
||||
}
|
||||
|
||||
public static List<BiomeSpawnerListEntry> OnAddListEntry(List<BiomeSpawnerListEntry> oldList)
|
||||
{
|
||||
oldList.Add(new BiomeSpawnerListEntry() { m_autoAssignPrototypes = true });
|
||||
return oldList;
|
||||
}
|
||||
|
||||
public static void DrawListHeader(Rect rect, bool currentFoldOutState, List<BiomeSpawnerListEntry> spawnerList, EditorUtils editorUtils, string headerKey)
|
||||
{
|
||||
int oldIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
//rect.xMin += 0f;
|
||||
EditorGUI.LabelField(rect, editorUtils.GetContent(headerKey));
|
||||
//bool newFoldOutState = EditorGUI.Foldout(rect, currentFoldOutState, PropertyCount("SpawnerAdded", spawnerList, editorUtils), true);
|
||||
EditorGUI.indentLevel = oldIndent;
|
||||
//return newFoldOutState;
|
||||
}
|
||||
|
||||
public static void DrawList(ReorderableList list, EditorUtils editorUtils)
|
||||
{
|
||||
Rect maskRect;
|
||||
//if (listExpanded)
|
||||
//{
|
||||
maskRect = EditorGUILayout.GetControlRect(true, list.GetHeight());
|
||||
list.DoList(maskRect);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// int oldIndent = EditorGUI.indentLevel;
|
||||
// EditorGUI.indentLevel = 1;
|
||||
// listExpanded = EditorGUILayout.Foldout(listExpanded, PropertyCount("SpawnerAdded", (List<SpawnerPresetListEntry>)list.list, editorUtils), true);
|
||||
// maskRect = GUILayoutUtility.GetLastRect();
|
||||
// EditorGUI.indentLevel = oldIndent;
|
||||
//}
|
||||
|
||||
//editorUtils.Panel("MaskBaking", DrawMaskBaking, false);
|
||||
}
|
||||
|
||||
//public static void DrawListElement_GaiaManager(Rect rect, BiomeSpawnerListEntry listEntry, EditorUtils m_editorUtils, EditorWindow window = null)
|
||||
//{
|
||||
// int oldIndent = EditorGUI.indentLevel;
|
||||
// Rect controlRect = new Rect(rect);
|
||||
// controlRect.width = 40;
|
||||
// controlRect.height = EditorGUIUtility.singleLineHeight;
|
||||
// EditorGUI.indentLevel = 0;
|
||||
// EditorGUI.LabelField(controlRect, m_editorUtils.GetContent("SpawnerListActive"));
|
||||
// controlRect.x = rect.x + 40;
|
||||
// controlRect.width = 10;
|
||||
// listEntry.m_isActiveInStamper = EditorGUI.Toggle(controlRect, listEntry.m_isActiveInStamper);
|
||||
// controlRect.width = 40;
|
||||
// EditorGUI.LabelField(controlRect, m_editorUtils.GetContent("BiomeActive"));
|
||||
// controlRect.x = rect.x + 40;
|
||||
// controlRect.width = 10;
|
||||
// listEntry.m_isActiveInBiome = EditorGUI.Toggle(controlRect, listEntry.m_isActiveInBiome);
|
||||
// controlRect.x = rect.x + 60;
|
||||
// controlRect.width = 70;
|
||||
// controlRect.height = EditorGUIUtility.singleLineHeight;
|
||||
// EditorGUI.LabelField(controlRect, m_editorUtils.GetContent("SpawnerListAutoAssignPrototypes"));
|
||||
// controlRect.x = rect.x + 125;
|
||||
// controlRect.width = 10;
|
||||
// listEntry.m_autoAssignPrototypes = EditorGUI.Toggle(controlRect, listEntry.m_autoAssignPrototypes);
|
||||
// controlRect.width = 26;
|
||||
// controlRect.x = rect.x + rect.width - 30;
|
||||
// int controlID = EditorGUIUtility.GetControlID(FocusType.Passive);
|
||||
// if (GUI.Button(controlRect, " "))
|
||||
// {
|
||||
// EditorGUIUtility.ShowObjectPicker<SpawnerSettings>(listEntry.m_spawnerSettings, false, "l:GaiaManagerSpawner", controlID);
|
||||
// }
|
||||
// controlRect.width = rect.width - 160;
|
||||
// controlRect.x = rect.x + 150;
|
||||
// listEntry.m_spawnerSettings = (SpawnerSettings)EditorGUI.ObjectField(controlRect, listEntry.m_spawnerSettings, typeof(SpawnerSettings), false);
|
||||
|
||||
// string commandName = Event.current.commandName;
|
||||
// if (commandName == "ObjectSelectorUpdated")
|
||||
// {
|
||||
// if (controlID == EditorGUIUtility.GetObjectPickerControlID())
|
||||
// {
|
||||
// listEntry.m_spawnerSettings = (SpawnerSettings)EditorGUIUtility.GetObjectPickerObject();
|
||||
// if (window != null)
|
||||
// {
|
||||
// window.Repaint();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else if (commandName == "ObjectSelectorClosed")
|
||||
// {
|
||||
// if (controlID == EditorGUIUtility.GetObjectPickerControlID())
|
||||
// {
|
||||
// listEntry.m_spawnerSettings = (SpawnerSettings)EditorGUIUtility.GetObjectPickerObject();
|
||||
// }
|
||||
// }
|
||||
|
||||
// EditorGUI.indentLevel = oldIndent;
|
||||
//}
|
||||
|
||||
public static void DrawListElement(Rect rect, BiomeSpawnerListEntry listEntry, EditorUtils m_editorUtils, EditorWindow window = null)
|
||||
{
|
||||
int oldIndent = EditorGUI.indentLevel;
|
||||
Rect controlRect = new Rect(rect);
|
||||
EditorGUI.indentLevel = 0;
|
||||
controlRect.height = EditorGUIUtility.singleLineHeight;
|
||||
controlRect.width = 12;
|
||||
EditorGUI.LabelField(controlRect, m_editorUtils.GetContent("StamperActive"));
|
||||
controlRect.x = rect.x + 12;
|
||||
controlRect.width = 20;
|
||||
listEntry.m_isActiveInStamper = EditorGUI.Toggle(controlRect, listEntry.m_isActiveInStamper);
|
||||
controlRect.x = controlRect.x + 20;
|
||||
controlRect.width = 12;
|
||||
EditorGUI.LabelField(controlRect, m_editorUtils.GetContent("BiomeActive"));
|
||||
controlRect.x = controlRect.x + 12;
|
||||
controlRect.width = 15;
|
||||
listEntry.m_isActiveInBiome = EditorGUI.Toggle(controlRect, listEntry.m_isActiveInBiome);
|
||||
controlRect.x = controlRect.x + 20;
|
||||
controlRect.width = 12;
|
||||
EditorGUI.LabelField(controlRect, m_editorUtils.GetContent("AutoAssignPrototypes"));
|
||||
controlRect.x = controlRect.x + 12;
|
||||
controlRect.width = 15;
|
||||
listEntry.m_autoAssignPrototypes = EditorGUI.Toggle(controlRect, listEntry.m_autoAssignPrototypes);
|
||||
controlRect.x = rect.x + 10;
|
||||
controlRect.width = 20;
|
||||
controlRect.x = rect.x + rect.width - 20;
|
||||
int controlID = EditorGUIUtility.GetControlID(FocusType.Passive);
|
||||
if (GUI.Button(controlRect, " "))
|
||||
{
|
||||
EditorGUIUtility.ShowObjectPicker<SpawnerSettings>(listEntry.m_spawnerSettings, false, "l:" + GaiaConstants.gaiaManagerSpawnerLabel, controlID);
|
||||
}
|
||||
controlRect.width = rect.width - 100;
|
||||
controlRect.x = rect.x + 100;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
listEntry.m_spawnerSettings = (SpawnerSettings)EditorGUI.ObjectField(controlRect, listEntry.m_spawnerSettings, typeof(SpawnerSettings), false);
|
||||
|
||||
string commandName = Event.current.commandName;
|
||||
if (commandName == "ObjectSelectorUpdated")
|
||||
{
|
||||
if (controlID == EditorGUIUtility.GetObjectPickerControlID())
|
||||
{
|
||||
//Triggers when the custom picker object was updated
|
||||
listEntry.m_spawnerSettings = (SpawnerSettings)EditorGUIUtility.GetObjectPickerObject();
|
||||
listEntry.m_spawnerSettings.RefreshGUID();
|
||||
if (window != null)
|
||||
{
|
||||
window.Repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (commandName == "ObjectSelectorClosed")
|
||||
{
|
||||
if (controlID == EditorGUIUtility.GetObjectPickerControlID())
|
||||
{
|
||||
//Triggers when the custom picker object was closed
|
||||
listEntry.m_spawnerSettings = (SpawnerSettings)EditorGUIUtility.GetObjectPickerObject();
|
||||
listEntry.m_spawnerSettings.RefreshGUID();
|
||||
}
|
||||
}
|
||||
if(EditorGUI.EndChangeCheck())
|
||||
{
|
||||
//Triggers when the user drags and drops a spawner settings file into the slot
|
||||
listEntry.m_spawnerSettings.RefreshGUID();
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel = oldIndent;
|
||||
}
|
||||
|
||||
public static void DrawListElement_AdvancedTab(Rect rect, BiomeSpawnerListEntry listEntry, EditorUtils m_editorUtils)
|
||||
{
|
||||
int oldIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
Rect labelRect = rect;
|
||||
//260 is the total width of the controls at the end of each row
|
||||
labelRect.width = rect.width - 280;
|
||||
labelRect.height = EditorGUIUtility.singleLineHeight;
|
||||
|
||||
EditorGUI.LabelField(labelRect, listEntry.m_spawnerSettings.name);
|
||||
|
||||
EditorGUIUtility.AddCursorRect(labelRect, MouseCursor.Zoom);
|
||||
if (labelRect.Contains(Event.current.mousePosition) && Event.current.clickCount > 0)
|
||||
{
|
||||
Selection.activeObject = listEntry.m_spawnerSettings;
|
||||
EditorGUIUtility.PingObject(Selection.activeObject);
|
||||
}
|
||||
|
||||
labelRect.x = rect.width - 230;
|
||||
labelRect.width = 110f;
|
||||
|
||||
EditorGUI.LabelField(labelRect, m_editorUtils.GetContent("SpawnerListAutoAssignPrototypes"));
|
||||
|
||||
labelRect.x = rect.width - 130f;
|
||||
labelRect.width = 20f;
|
||||
|
||||
listEntry.m_autoAssignPrototypes = EditorGUI.Toggle(labelRect, listEntry.m_autoAssignPrototypes);
|
||||
|
||||
labelRect.x = rect.width - 80f;
|
||||
labelRect.width = 100f;
|
||||
if (GUI.Button(labelRect, m_editorUtils.GetContent("AdvancedTabAddSpawner")))
|
||||
{
|
||||
Spawner newSpawner = listEntry.m_spawnerSettings.CreateSpawner(listEntry.m_autoAssignPrototypes);
|
||||
Selection.activeGameObject = newSpawner.gameObject;
|
||||
}
|
||||
|
||||
|
||||
EditorGUI.indentLevel = oldIndent;
|
||||
}
|
||||
|
||||
public static void DrawListElementInStamper(Rect rect, BiomeSpawnerListEntry listEntry, EditorUtils m_editorUtils)
|
||||
{
|
||||
int oldIndent = EditorGUI.indentLevel;
|
||||
Rect controlRect = new Rect(rect);
|
||||
controlRect.width = 40;
|
||||
controlRect.height = EditorGUIUtility.singleLineHeight;
|
||||
EditorGUI.indentLevel = 0;
|
||||
EditorGUI.LabelField(controlRect, "Active");
|
||||
controlRect.x = rect.x + 40;
|
||||
controlRect.width = 10;
|
||||
listEntry.m_isActiveInStamper = EditorGUI.Toggle(controlRect, listEntry.m_isActiveInStamper);
|
||||
controlRect.width = rect.width - 70;
|
||||
controlRect.x = rect.x + 70;
|
||||
listEntry.m_spawnerSettings = (SpawnerSettings)EditorGUI.ObjectField(controlRect, listEntry.m_spawnerSettings, typeof(SpawnerSettings), false);
|
||||
EditorGUI.indentLevel = oldIndent;
|
||||
}
|
||||
|
||||
public static void DrawListElementInBiome(Rect rect, BiomeSpawnerListEntry listEntry, EditorUtils m_editorUtils)
|
||||
{
|
||||
int oldIndent = EditorGUI.indentLevel;
|
||||
Rect controlRect = new Rect(rect);
|
||||
controlRect.width = 40;
|
||||
controlRect.height = EditorGUIUtility.singleLineHeight;
|
||||
EditorGUI.indentLevel = 0;
|
||||
EditorGUI.LabelField(controlRect, "Active");
|
||||
controlRect.x = rect.x + 40;
|
||||
controlRect.width = 10;
|
||||
listEntry.m_isActiveInBiome = EditorGUI.Toggle(controlRect, listEntry.m_isActiveInBiome);
|
||||
controlRect.width = rect.width - 70;
|
||||
controlRect.x = rect.x + 70;
|
||||
listEntry.m_spawnerSettings = (SpawnerSettings)EditorGUI.ObjectField(controlRect, listEntry.m_spawnerSettings, typeof(SpawnerSettings), false);
|
||||
EditorGUI.indentLevel = oldIndent;
|
||||
}
|
||||
|
||||
public static GUIContent PropertyCount(string key, List<BiomeSpawnerListEntry> list, EditorUtils editorUtils)
|
||||
{
|
||||
GUIContent content = editorUtils.GetContent(key);
|
||||
content.text += " [" + list.Count + "]";
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 968fa80c60c6a5a42ab7114ff230ec0f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// This class only exists to change the displayed name from "Spawner" to "World Biome Masks" on the component.
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(WorldBiomeMasks))]
|
||||
public class WorldBiomeMasksEditor : SpawnerEditor
|
||||
{
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf26408c3c4cf35408a18408f266a499
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// This class only exists to change the displayed name from "Spawner" to "World Generator" on the component.
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(WorldDesigner))]
|
||||
public class WorldDesignerEditor : SpawnerEditor
|
||||
{
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44f7726ac5af60c4a970bcdf7f860674
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,4 @@
|
||||
/// <summary>
|
||||
/// This file is being replaced with WorldDesignerEditor.cs and is just left here for upwards compatibility to "disable" this file in earlier Gaia installations
|
||||
/// </summary>
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 054d1dcb815a71148a42b4b1b71733e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this interface to implement a Gaia Spawn extension that can be run by a spawner to execute your own code whenever the spawner finds a fit location.
|
||||
/// </summary>
|
||||
public interface ISpawnExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// The name to identify the Extension
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this extension impacts Terrain heights.
|
||||
/// If it does, Gaia will trigger the necessary terrain updates after running this extension so things like the terrain collider are updated according to your changes.
|
||||
/// </summary>
|
||||
bool AffectsHeights { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this extension impacts Terrain textures.
|
||||
/// If it does, Gaia will trigger the necessary splatmap updates after running this extension
|
||||
/// /// </summary>
|
||||
bool AffectsTextures { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the extension - To avoid some actions to happen at every instance of this
|
||||
/// Extension spawning. All the spawner settings from the UI can be accessed via spawner.m_settings.
|
||||
/// Resource Information is in spawner.m_settings.m_resources
|
||||
/// </summary>
|
||||
/// <param name="spawner">The Gaia spawner that is running this extension.</param>
|
||||
void Init(Spawner spawner);
|
||||
|
||||
/// <summary>
|
||||
/// This is the core function that will be called when spawning.
|
||||
/// </summary>
|
||||
/// <param name="spawner">The Gaia spawner that is spawning this. All the spawner settings from the UI can be accessed via spawner.m_settings.</param>
|
||||
/// <param name="target">The target transform for Game Object spawns</param>
|
||||
/// <param name="ruleIndex">The index of the spawn rule this extension is running in.</param>
|
||||
/// <param name="instanceIndex">The index of the instance inside the rule.</param>
|
||||
/// <param name="spawnInfo">Class containing details of the spawn.</param>
|
||||
void Spawn(Spawner spawner, Transform target, int ruleIndex, int instanceIndex, SpawnExtensionInfo spawnInfo);
|
||||
|
||||
/// <summary>
|
||||
/// This is the function that the spawner calls when trying to remove the content produced by this spawn extension.
|
||||
/// </summary>
|
||||
void Delete();
|
||||
|
||||
/// <summary>
|
||||
/// This will be called when the Spawn Extension is finished spawning. Do all cleanup operations in here.
|
||||
/// </summary>
|
||||
void Close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ab02451e182ba84e93e2b960fe3c00f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,298 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
[Serializable]
|
||||
public class SpawnCritera
|
||||
{
|
||||
[Tooltip("Criteria name")]
|
||||
public string m_name;
|
||||
|
||||
[Tooltip("CHECK TYPE - a single point on the terrain or area based. The size of the area checks is based on the Bounds Radius in the DNA. Area based checks are good for larger structures but substantially slower so use with care.")]
|
||||
public Gaia.GaiaConstants.SpawnerLocationCheckType m_checkType = GaiaConstants.SpawnerLocationCheckType.PointCheck;
|
||||
|
||||
[Tooltip("When selected, the criteria will only be valid if the terrain was clear of any other objects at this location. A location is determined to be ‘virgin’ when raycast collision test hits clear terrain. To detect other objects at this location they must have colliders. You can use an invisible collider and this test to stop any resources that require virgin terrain from spawning at that location.")]
|
||||
public bool m_virginTerrain = true;
|
||||
|
||||
[Tooltip("Whether or not this location will be checked for height.")]
|
||||
public bool m_checkHeight = true;
|
||||
[Tooltip("The minimum valid height relative to sea level. Only tested when Check Height is checked.")]
|
||||
public float m_minHeight = 0f;
|
||||
[Tooltip("The maximum valid height relative to sea level. Only tested when Check Height is checked.")]
|
||||
public float m_maxHeight = 1000f;
|
||||
[Tooltip("The fitness curve - evaluated between the minimum and the maximum height when Check Height is checked. 0 is low fitness and unlikely to spawn, 1 is high fitness and likely to spawn.")]
|
||||
public AnimationCurve m_heightFitness = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 0.0f));
|
||||
|
||||
[Tooltip("Whether or not this location will be checked for slope.")]
|
||||
public bool m_checkSlope = true;
|
||||
[Tooltip("The minimum valid slope. Only tested when Check Slope is checked.")]
|
||||
public float m_minSlope = 0f;
|
||||
[Tooltip("The maximum valid slope. Only tested when Check Slope is checked.")]
|
||||
public float m_maxSlope = 90;
|
||||
[Tooltip("The fitness curve - evaluated between the minimum and the maximum slope when Check Slope is checked. 0 is low fitness and unlikely to spawn, 1 is high fitness and likely to spawn.")]
|
||||
public AnimationCurve m_slopeFitness = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 0.0f));
|
||||
|
||||
[Tooltip("Whether or not to check proximity to other tags near this location.")]
|
||||
public bool m_checkProximity = false;
|
||||
[Tooltip("The tag that will be checked in proximity to this location e.g. House")]
|
||||
public string m_proximityTag = "";
|
||||
[Tooltip("The minimum valid proximity. Only tested when Check Proximity is checked.")]
|
||||
public float m_minProximity = 0f;
|
||||
[Tooltip("The maximum valid proximity. Only tested when Check Proximity is checked.")]
|
||||
public float m_maxProximity = 100f;
|
||||
[Tooltip("The fitness curve - evaluated between the minimum and the maximum proximity when Check Proximity is checked. 0 is low fitness and unlikely to spawn, 1 is high fitness and likely to spawn.")]
|
||||
public AnimationCurve m_proximityFitness = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(0.3f, 0.2f), new Keyframe(1f, 0.0f));
|
||||
|
||||
[Tooltip("Check textures at this location.")]
|
||||
public bool m_checkTexture = false;
|
||||
[Tooltip("Texture slots from your terrain (first valid slot is 0). Will select for presence that texture. Use exclamation mark in front of slot to select for absence of that texture. For example 3 selects for presence of texture 3, !3 checks for absence of texture 3. Fitness is based on the strength of the texture at that location in range 0..1. Only tested when Check Texture is checked.")]
|
||||
public string m_matchingTextures = "!3";
|
||||
|
||||
[Tooltip("Whether or not this spawn criteria is active. It will be ignored if not active.")]
|
||||
public bool m_isActive = true;
|
||||
|
||||
/// <summary>
|
||||
/// One off initialisation thing to speed processing
|
||||
/// </summary>
|
||||
private bool m_isInitialised = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise the criteria
|
||||
/// </summary>
|
||||
public void Initialise(Spawner spawner)
|
||||
{
|
||||
|
||||
//Check the values in the texture fitness
|
||||
string newTextureFilter = "";
|
||||
int maxTexture = 4;
|
||||
char maxTextureChar = maxTexture.ToString()[0];
|
||||
if (Terrain.activeTerrain != null)
|
||||
{
|
||||
maxTexture = Terrain.activeTerrain.terrainData.alphamapLayers;
|
||||
maxTextureChar = maxTexture.ToString()[0];
|
||||
}
|
||||
for (int idx = 0; idx < m_matchingTextures.Length; idx++)
|
||||
{
|
||||
if ((m_matchingTextures[idx] >= '0' && m_matchingTextures[idx] <= maxTextureChar) || m_matchingTextures[idx] == '!')
|
||||
{
|
||||
newTextureFilter += m_matchingTextures[idx];
|
||||
}
|
||||
}
|
||||
m_matchingTextures = newTextureFilter;
|
||||
|
||||
m_isInitialised = true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the fitness of the supplied slope
|
||||
/// </summary>
|
||||
/// <param name="slope">The slope to be checked</param>
|
||||
/// <returns>Fitness at that slope - if fitness not applicable it returns 1f</returns>
|
||||
public float GetSlopeFitness(float slope)
|
||||
{
|
||||
float fitness = 1f;
|
||||
if (m_checkSlope)
|
||||
{
|
||||
if (slope < m_minSlope || slope > m_maxSlope)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
fitness = m_maxSlope - m_minSlope;
|
||||
if (fitness > 0f)
|
||||
{
|
||||
fitness = (slope - m_minSlope) / fitness;
|
||||
fitness = m_slopeFitness.Evaluate(fitness);
|
||||
}
|
||||
else
|
||||
{
|
||||
fitness = 0f;
|
||||
}
|
||||
}
|
||||
return fitness;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the fitness of the supplied height
|
||||
/// </summary>
|
||||
/// <param name="height">The height to be checked</param>
|
||||
/// <returns>Fitness at that height - if fitness not applicable it returns 1f</returns>
|
||||
public float GetHeightFitness(float height, float sealLevel)
|
||||
{
|
||||
float fitness = 1f;
|
||||
if (m_checkHeight)
|
||||
{
|
||||
height -= sealLevel;
|
||||
if (height < m_minHeight || height > m_maxHeight)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
fitness = m_maxHeight - m_minHeight;
|
||||
if (fitness > 0f)
|
||||
{
|
||||
fitness = (height - m_minHeight) / fitness;
|
||||
fitness = m_heightFitness.Evaluate(fitness);
|
||||
}
|
||||
else
|
||||
{
|
||||
fitness = 0f;
|
||||
}
|
||||
}
|
||||
return fitness;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the fitness of the supplied proximity
|
||||
/// </summary>
|
||||
/// <param name="proximity">The proximity to be checked</param>
|
||||
/// <returns>Fitness at that proximity - if fitness not applicable it returns 1f</returns>
|
||||
public float GetProximityFitness(float proximity)
|
||||
{
|
||||
float fitness = 1f;
|
||||
if (m_checkProximity)
|
||||
{
|
||||
if (proximity < m_minProximity || proximity > m_maxProximity)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
fitness = m_maxProximity - m_minProximity;
|
||||
if (fitness > 0f)
|
||||
{
|
||||
fitness = (proximity - m_minProximity) / fitness;
|
||||
fitness = m_proximityFitness.Evaluate(fitness);
|
||||
}
|
||||
else
|
||||
{
|
||||
fitness = 0f;
|
||||
}
|
||||
}
|
||||
return fitness;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the fitness of the supplied textures
|
||||
/// </summary>
|
||||
/// <param name="textures">The textures to be checked</param>
|
||||
/// <returns>Fitness of these textures - if fitness not applicable it returns 1f</returns>
|
||||
public float GetTextureFitness(float[] textures)
|
||||
{
|
||||
bool negate = false;
|
||||
float fitness = 1f;
|
||||
float textureFitness;
|
||||
if (m_checkTexture)
|
||||
{
|
||||
fitness = float.MaxValue;
|
||||
for (int checkIdx = 0; checkIdx < m_matchingTextures.Length; checkIdx++)
|
||||
{
|
||||
if (m_matchingTextures[checkIdx] == '!')
|
||||
{
|
||||
negate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (negate)
|
||||
{
|
||||
textureFitness = 1f - textures[(int)Char.GetNumericValue(m_matchingTextures[checkIdx])];
|
||||
negate = false;
|
||||
if (fitness == float.MaxValue || (textureFitness < fitness))
|
||||
{
|
||||
fitness = textureFitness;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textureFitness = textures[(int)Char.GetNumericValue(m_matchingTextures[checkIdx])];
|
||||
if (fitness == float.MaxValue || (textureFitness > fitness))
|
||||
{
|
||||
fitness = textureFitness;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fitness;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return fitness of the spawninfo object - not ideal as it forces closer coupling
|
||||
/// </summary>
|
||||
/// <param name="spawnInfo">Spawn infor object</param>
|
||||
/// <returns>Fitness at that location 0..1</returns>
|
||||
public float GetFitness(ref SpawnInfo spawnInfo)
|
||||
{
|
||||
|
||||
|
||||
|
||||
//Make sure we are initialised
|
||||
if (!m_isInitialised)
|
||||
{
|
||||
Initialise(spawnInfo.m_spawner);
|
||||
}
|
||||
|
||||
//Check for active or not
|
||||
if (!m_isActive)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
//Check for virgin (clear terrain)
|
||||
if (m_virginTerrain == true)
|
||||
{
|
||||
if (spawnInfo.m_wasVirginTerrain != true)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
//Set default fitness
|
||||
float fitness = 1f;
|
||||
|
||||
//Check height
|
||||
if (m_checkHeight)
|
||||
{
|
||||
fitness = Mathf.Min(fitness, GetHeightFitness(spawnInfo.m_terrainHeightWU, GaiaSessionManager.GetSessionManager().GetSeaLevel()));
|
||||
}
|
||||
|
||||
//Check slope
|
||||
if (m_checkSlope && fitness > 0f)
|
||||
{
|
||||
if (m_checkType == GaiaConstants.SpawnerLocationCheckType.PointCheck)
|
||||
{
|
||||
fitness = Mathf.Min(fitness, GetSlopeFitness(spawnInfo.m_terrainSlopeWU));
|
||||
}
|
||||
else
|
||||
{
|
||||
//fitness = Mathf.Min(fitness, GetSlopeFitness(spawnInfo.m_areaHitSlopeWU));
|
||||
fitness = Mathf.Min(fitness, GetSlopeFitness(spawnInfo.m_areaAvgSlopeWU));
|
||||
}
|
||||
}
|
||||
|
||||
//Check textures
|
||||
if (m_checkTexture && fitness > 0f)
|
||||
{
|
||||
fitness = Mathf.Min(fitness, GetTextureFitness(spawnInfo.m_textureStrengths));
|
||||
}
|
||||
|
||||
//Check proximity
|
||||
if (m_checkProximity && fitness > 0f)
|
||||
{
|
||||
Rect area = new Rect(spawnInfo.m_hitLocationWU.x - m_maxProximity, spawnInfo.m_hitLocationWU.z - m_maxProximity, m_maxProximity * 2f, m_maxProximity * 2f);
|
||||
GameObject closestObject = null; //spawnInfo.m_spawner.GetClosestObject(m_proximityTag, area);
|
||||
if (closestObject != null)
|
||||
{
|
||||
fitness = Mathf.Min(fitness, GetProximityFitness(Vector3.Distance(closestObject.transform.position, spawnInfo.m_hitLocationWU)));
|
||||
}
|
||||
else
|
||||
{
|
||||
fitness = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
//Exit with final fitness
|
||||
return fitness;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d50a21bc0bd2a8c4a8482f4ae0e9cd52
|
||||
timeCreated: 1431843657
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
public class SpawnExtensionInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The location where the Spawn Extension is triggered in world space.
|
||||
/// </summary>
|
||||
public Vector3 m_position;
|
||||
/// <summary>
|
||||
/// The (suggested) rotation for this location - it is up to the extension to implement or ignore this
|
||||
/// </summary>
|
||||
public Quaternion m_rotation;
|
||||
/// <summary>
|
||||
/// The (suggested) scale for this location - it is up to the extension to implement or ignore this
|
||||
/// </summary>
|
||||
public Vector3 m_scale;
|
||||
/// <summary>
|
||||
/// The scalar fitness value for this location. 0 = no fitness, 1 = full fitness.
|
||||
/// </summary>
|
||||
public float m_fitness;
|
||||
/// <summary>
|
||||
/// The current terrain the Spawn Extension was triggered on. Use this together with the location to query information from the terrain, e.g. slope, etc.
|
||||
/// </summary>
|
||||
public Terrain m_currentTerrain;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f1209ce786148848ac155a78d648783
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb336402aa5f4e04e89a387abedb2681
|
||||
folderAsset: yes
|
||||
timeCreated: 1452153018
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple Spawn Extension for demo / debug purposes. Just writes some info to the console when being executed.
|
||||
/// </summary>
|
||||
public class DebugSpawnExtension : MonoBehaviour, ISpawnExtension
|
||||
{
|
||||
public string Name { get { return "DebugSpawnExtension"; } }
|
||||
|
||||
public bool AffectsHeights => false;
|
||||
|
||||
public bool AffectsTextures => false;
|
||||
|
||||
public GameObject testPrefab;
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Debug.Log("Spawn Extension is closing down.");
|
||||
}
|
||||
|
||||
public void Init(Spawner spawner)
|
||||
{
|
||||
Debug.Log("Spawn Extension starting up.");
|
||||
}
|
||||
|
||||
public void Spawn(Spawner spawner, Transform target, int ruleIndex, int instanceIndex, SpawnExtensionInfo spawnExtensionInfo)
|
||||
{
|
||||
Debug.Log("Spawn Extension spawning.");
|
||||
if (testPrefab != null)
|
||||
{
|
||||
GameObject newGO = GameObject.Instantiate(testPrefab, spawnExtensionInfo.m_position, spawnExtensionInfo.m_rotation);
|
||||
newGO.transform.localScale = spawnExtensionInfo.m_scale;
|
||||
newGO.transform.parent = target;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
Debug.Log("Spawn Extenison deleting.");
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 419cf668855b7724cb1db262f35227a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple Spawn Extension for demo / debug purposes. Just writes some info to the console when being executed.
|
||||
/// </summary>
|
||||
public class GeNaSpawnExtension : MonoBehaviour, ISpawnExtension
|
||||
{
|
||||
public string Name { get { return "GeNaSpawnExtension"; } }
|
||||
|
||||
public bool AffectsHeights => false;
|
||||
|
||||
public bool AffectsTextures => false;
|
||||
|
||||
public GameObject m_genaSpawnerPrefab;
|
||||
private GeNa.Spawner m_genaSpawnerInstance;
|
||||
|
||||
public void Close()
|
||||
{
|
||||
//Debug.Log("Spawn Extension is closing down.");
|
||||
if (m_genaSpawnerInstance != null)
|
||||
{
|
||||
DestroyImmediate(m_genaSpawnerInstance.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void Init(Spawner spawner)
|
||||
{
|
||||
//Debug.Log("Spawn Extension starting up.");
|
||||
if (m_genaSpawnerPrefab == null)
|
||||
{
|
||||
Debug.LogWarning("GeNa Spawn Extension '" + Name + "' does not have a GeNa Spawner Prefab assigned.");
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject newGO = Instantiate(m_genaSpawnerPrefab);
|
||||
m_genaSpawnerInstance = newGO.GetComponent<GeNa.Spawner>();
|
||||
|
||||
if (m_genaSpawnerInstance == null)
|
||||
{
|
||||
Debug.LogWarning("Could not find a GeNa Spawner component on the prefab for GeNa Spawn Extension '" + Name + "'. Does this prefab use a GeNa Spawner component on the top level?");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void Spawn(Spawner spawner, Transform target, int ruleIndex, int instanceIndex, SpawnExtensionInfo spawnExtensionInfo)
|
||||
{
|
||||
//Debug.Log("Spawn Extension spawning.");
|
||||
if (m_genaSpawnerInstance != null)
|
||||
{
|
||||
|
||||
float scalarX = (spawnExtensionInfo.m_position.x - spawnExtensionInfo.m_currentTerrain.transform.position.x) / spawnExtensionInfo.m_currentTerrain.terrainData.size.x;
|
||||
float scalarZ = (spawnExtensionInfo.m_position.z - spawnExtensionInfo.m_currentTerrain.transform.position.z) / spawnExtensionInfo.m_currentTerrain.terrainData.size.z;
|
||||
Vector3 normal = spawnExtensionInfo.m_currentTerrain.terrainData.GetInterpolatedNormal(scalarX,scalarZ);
|
||||
m_genaSpawnerInstance.Initialise(target,"Gaia Spawn Extension Spawn",false);
|
||||
m_genaSpawnerInstance.m_parentName = target.name;
|
||||
m_genaSpawnerInstance.Spawn(spawnExtensionInfo.m_position, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa421c7b24a3d0b4a97bd7a94ccd7c29
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is used to get information about a location on the terrain. Used heavily by the spawning system.
|
||||
/// </summary>
|
||||
public class SpawnInfo
|
||||
{
|
||||
public Spawner m_spawner; //The spawner that populated this
|
||||
public bool m_outOfBounds = true; //Was this out of bounds or not
|
||||
public bool m_wasVirginTerrain; //If virgin terrain was hit at this location - hitting a terrain tree is counted as false
|
||||
public float m_spawnRotationY; //The rotation chosen for the spawn
|
||||
public float m_hitDistanceWU; //The distance from the centre of the spawner to this location in unity world units
|
||||
public Vector3 m_hitLocationWU; //The location of the hit in unity world units
|
||||
public Vector3 m_hitLocationNU; //The location on the hit in normalised units, with respect to the terrain it was located in
|
||||
public Vector3 m_hitNormal; //The normal of the hit
|
||||
public Transform m_hitObject; //The object that was hit
|
||||
public Terrain m_hitTerrain; //The terrain that this happened on
|
||||
public float m_terrainHeightWU; //The terrain height at this location in world units
|
||||
public float m_terrainSlopeWU; //The terrian slope at this location in 0 (flat) .. 90 (vertical) degrees
|
||||
public Vector3 m_terrainNormalWU; //The terrain normal at the hit location
|
||||
public float m_fitness; //The fitness that was calculated for this location
|
||||
public float[] m_textureStrengths; //The texture strenghts in the terrain at this location
|
||||
public Vector3[] m_areaHitsWU; //Will be filled in when doing area based hits
|
||||
public float m_areaHitSlopeWU; //Will be calculated when doing area based hits
|
||||
public float m_areaMinSlopeWU; //Minimum slope detected, calculates when doing area based hits
|
||||
public float m_areaAvgSlopeWU; //Average of slopes detected, calculates when doing area based hits
|
||||
public float m_areaMaxSlopeWU; //Maximum slope detected, calculates when doing area based hits
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91704e2acfee3c647894bb10cffff10f
|
||||
timeCreated: 1433552825
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb9c66a27acb6114e9205771eb2f2fa5
|
||||
timeCreated: 1433046587
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
public class SpawnRuleExtension : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise the extension
|
||||
/// </summary>
|
||||
public virtual void Initialise()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this extension impacts textures
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual bool AffectsTextures()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this extension impacts details
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual bool AffectsDetails()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Call this to update fitness of the location spawnInfo passed in
|
||||
/// </summary>
|
||||
/// <param name="spawnInfo">Use this to get details about the location and update the fitness</param>
|
||||
/// <returns>Return the fitness of the location</returns>
|
||||
public virtual float GetFitness(float fitness, ref SpawnInfo spawnInfo)
|
||||
{
|
||||
return fitness;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this extension should override the spawn itself
|
||||
/// </summary>
|
||||
/// <param name="spawnInfo"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool OverridesSpawn(SpawnRule spawnRule, ref SpawnInfo spawnInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Spawn an instance at the location provided.
|
||||
/// </summary>
|
||||
/// <param name="location"></param>
|
||||
/// <returns></returns>
|
||||
public virtual void Spawn(SpawnRule spawnRule, ref SpawnInfo spawnInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to do any post spawn goodness
|
||||
/// </summary>
|
||||
public virtual void PostSpawn(SpawnRule spawnRule, ref SpawnInfo spawnInfo)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 057f9a6e39df59746a9bda58a3957337
|
||||
timeCreated: 1452149421
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9df16ee49ef1a2246ba1007a065388a1
|
||||
timeCreated: 1433039847
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,230 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// Allow grouped spawners and spawner control
|
||||
/// </summary>
|
||||
[ExecuteInEditMode]
|
||||
public class SpawnerGroup : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Spawner instances
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SpawnerInstance
|
||||
{
|
||||
public string m_name; //The name of the spawner
|
||||
public Spawner m_spawner; //The spawner instance we are managing
|
||||
public int m_interationsPerSpawn = 1; //The number of spawner iterations to call per spawn
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The spawner instances
|
||||
/// </summary>
|
||||
public List<SpawnerInstance> m_spawners = new List<SpawnerInstance>();
|
||||
|
||||
/// <summary>
|
||||
/// The spawner group instances
|
||||
/// </summary>
|
||||
[HideInInspector]
|
||||
public List<SpawnerGroup> m_spawnerGroups = new List<SpawnerGroup>();
|
||||
|
||||
/// <summary>
|
||||
/// Use for co-routine simulation
|
||||
/// </summary>
|
||||
public IEnumerator m_updateCoroutine;
|
||||
|
||||
/// <summary>
|
||||
/// Used to signal a cancelled spawn
|
||||
/// </summary>
|
||||
private bool m_cancelSpawn = false;
|
||||
|
||||
/// <summary>
|
||||
/// Used to force an editor update so we can see progress
|
||||
/// </summary>
|
||||
[HideInInspector]
|
||||
public int m_progress = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Called by unity in editor when this is enabled - unity initialisation is quite opaque!
|
||||
/// </summary>
|
||||
void OnEnable()
|
||||
{
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start editor updates
|
||||
/// </summary>
|
||||
public void StartEditorUpdates()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.update += EditorUpdate;
|
||||
#endif
|
||||
}
|
||||
|
||||
//Stop editor updates
|
||||
public void StopEditorUpdates()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.update -= EditorUpdate;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is executed only in the editor - using it to simulate co-routine execution and update execution
|
||||
/// </summary>
|
||||
void EditorUpdate()
|
||||
{
|
||||
if (m_updateCoroutine == null)
|
||||
{
|
||||
StopEditorUpdates();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_updateCoroutine.MoveNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Run a spawner iteration
|
||||
/// </summary>
|
||||
public void RunSpawnerIteration()
|
||||
{
|
||||
m_cancelSpawn = false;
|
||||
m_progress = 0;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
m_updateCoroutine = RunSpawnerIterationCoRoutine();
|
||||
StartEditorUpdates();
|
||||
}
|
||||
else
|
||||
{
|
||||
StartCoroutine(RunSpawnerIterationCoRoutine());
|
||||
}
|
||||
#else
|
||||
StartCoroutine(RunSpawnerIterationCoRoutine());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Run a spawner iteration as a coroutine
|
||||
/// </summary>
|
||||
public IEnumerator RunSpawnerIterationCoRoutine()
|
||||
{
|
||||
SpawnerInstance si;
|
||||
for (int idx = 0; idx < m_spawners.Count; idx++)
|
||||
{
|
||||
si = m_spawners[idx];
|
||||
if (si != null && si.m_spawner != null)
|
||||
{
|
||||
for (int iter=0; iter < si.m_interationsPerSpawn; iter++)
|
||||
{
|
||||
if (!m_cancelSpawn)
|
||||
{
|
||||
//si.m_spawner.m_showDebug = true;
|
||||
//si.m_spawner.RunSpawnerIteration(true,0,0);
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
while (si.m_spawner.m_spawnComplete != true)
|
||||
{
|
||||
m_progress++; //Forces an editor update
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
m_progress++;
|
||||
#if UNITY_EDITOR
|
||||
SceneView.RepaintAll();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_progress = 0;
|
||||
m_updateCoroutine = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancel the spawn
|
||||
/// </summary>
|
||||
public void CancelSpawn()
|
||||
{
|
||||
//This
|
||||
m_cancelSpawn = true;
|
||||
for (int idx = 0; idx < m_spawners.Count; idx++)
|
||||
{
|
||||
m_spawners[idx].m_spawner.CancelSpawn();
|
||||
}
|
||||
|
||||
//Groups
|
||||
for (int idx = 0; idx < m_spawnerGroups.Count; idx++)
|
||||
{
|
||||
m_spawnerGroups[idx].CancelSpawn();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the names from the prefabs - return true if something changed
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool FixNames()
|
||||
{
|
||||
bool changed = false;
|
||||
SpawnerInstance si;
|
||||
for (int idx = 0; idx < m_spawners.Count; idx++)
|
||||
{
|
||||
si = m_spawners[idx];
|
||||
if (si != null && si.m_spawner != null)
|
||||
{
|
||||
if (si.m_name != si.m_spawner.name)
|
||||
{
|
||||
si.m_name = si.m_spawner.name;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the spawners
|
||||
/// </summary>
|
||||
public void ResetSpawner()
|
||||
{
|
||||
//This
|
||||
SpawnerInstance si;
|
||||
for (int idx = 0; idx < m_spawners.Count; idx++)
|
||||
{
|
||||
si = m_spawners[idx];
|
||||
if (si != null && si.m_spawner != null)
|
||||
{
|
||||
si.m_spawner.ResetSpawner();
|
||||
}
|
||||
}
|
||||
|
||||
//Groups
|
||||
SpawnerGroup sg;
|
||||
for (int idx = 0; idx < m_spawnerGroups.Count; idx++)
|
||||
{
|
||||
sg = m_spawnerGroups[idx];
|
||||
if (sg != null)
|
||||
{
|
||||
sg.ResetSpawner();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 146d2bfb353ceca4c96b842cf19f57ea
|
||||
timeCreated: 1437940894
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,338 @@
|
||||
// Copyright © 2018 Procedural Worlds Pty Limited. All Rights Reserved.
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using static Gaia.GaiaConstants;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
/*
|
||||
* Scriptable Object containing settings for a Spawner
|
||||
*/
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary> Contains information about a Sequence of clips to play and how </summary>
|
||||
[CreateAssetMenu(menuName = "Procedural Worlds/Gaia/Spawner Settings")]
|
||||
[System.Serializable]
|
||||
public class SpawnerSettings : ScriptableObject, ISerializationCallbackReceiver
|
||||
{
|
||||
|
||||
#region Public Variables
|
||||
|
||||
/// <summary>
|
||||
/// The resources associated with the spawner
|
||||
/// </summary>
|
||||
public GaiaResource m_resources = new GaiaResource();
|
||||
|
||||
///// <summary>
|
||||
///// Spanwer x location - done this way to expose in the editor as a simple slider
|
||||
///// </summary>
|
||||
public float m_x = 0f;
|
||||
|
||||
///// <summary>
|
||||
///// Spawner y location - done this way to expose in the editor as a simple slider
|
||||
///// </summary>
|
||||
public float m_y = 50f;
|
||||
|
||||
///// <summary>
|
||||
///// Spawner z location - done this way to expose in the editor as a simple slider
|
||||
///// </summary>
|
||||
public float m_z = 0f;
|
||||
|
||||
///// <summary>
|
||||
///// Spawner width - this is the horizontal scaling factor - applied to both x & z
|
||||
///// </summary>
|
||||
public float m_width = 10f;
|
||||
|
||||
///// <summary>
|
||||
///// Spawner height - this is the vertical scaling factor
|
||||
///// </summary>
|
||||
public float m_height = 10f;
|
||||
|
||||
///// <summary>
|
||||
///// Spawner rotation
|
||||
///// </summary>
|
||||
public float m_rotation = 0f;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Is this spawner intended to be used on world map terrains?
|
||||
/// </summary>
|
||||
public bool m_isWorldmapSpawner = false;
|
||||
|
||||
/// <summary>
|
||||
/// Range of the spawn area
|
||||
/// </summary>
|
||||
public float m_spawnRange = 500f;
|
||||
|
||||
/// <summary>
|
||||
/// Should the random seed be generated anew for each spawn?
|
||||
/// </summary>
|
||||
public bool m_generateRandomSeed = true;
|
||||
|
||||
/// <summary>
|
||||
/// Seed value for the random number generator
|
||||
/// </summary>
|
||||
public int m_randomSeed = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The spawn Density which controls the global object density for all spawners. This value is managed in the session
|
||||
/// for the scene, but also needs to be stored in the spawner settings for correct session playback.
|
||||
/// </summary>
|
||||
public float m_spawnDensity = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// The path this resources file came from
|
||||
/// </summary>
|
||||
public string m_resourcesPath;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The GUID of the last used resources file; Used while saving and loading to save / load the resource file reference
|
||||
/// </summary>
|
||||
//public string m_resourcesGUID;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The prefabs that can be spawned and their settings
|
||||
/// </summary>
|
||||
public List<SpawnRule> m_spawnerRules = new List<SpawnRule>();
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to show gizmos
|
||||
/// </summary>
|
||||
public bool m_showGizmos = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to show debug messages
|
||||
/// </summary>
|
||||
public bool m_showDebug = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to show the terrain helper
|
||||
/// </summary>
|
||||
public bool m_showTerrainHelper = true;
|
||||
|
||||
|
||||
public SpawnMode m_spawnMode = SpawnMode.Replace;
|
||||
|
||||
[SerializeField]
|
||||
private ImageMask[] imageMasks = new ImageMask[0];
|
||||
|
||||
/// <summary>
|
||||
/// Toggle for trees in the spawn clear controls
|
||||
/// </summary>
|
||||
public bool m_clearSpawnsToggleTrees = false;
|
||||
|
||||
/// <summary>
|
||||
/// Toggle for terrain details in the spawn clear controls
|
||||
/// </summary>
|
||||
public bool m_clearSpawnsToggleDetails = false;
|
||||
|
||||
/// <summary>
|
||||
/// Toggle for game objects in the spawn clear controls
|
||||
/// </summary>
|
||||
public bool m_clearSpawnsToggleGOs = false;
|
||||
|
||||
/// <summary>
|
||||
/// Toggle for spawn extensions in the spawn clear controls
|
||||
/// </summary>
|
||||
public bool m_clearSpawnsToggleSpawnExtensions = false;
|
||||
|
||||
/// <summary>
|
||||
/// Toggle for probes in the spawn clear controls
|
||||
/// </summary>
|
||||
public bool m_clearSpawnsToggleProbes = false;
|
||||
|
||||
/// <summary>
|
||||
/// Setting to determine which terrains should be affected by a clearing action
|
||||
/// </summary>
|
||||
public ClearSpawnFor m_clearSpawnsFor = ClearSpawnFor.AllTerrains;
|
||||
|
||||
/// <summary>
|
||||
/// Setting to determine which prototypes should be deleted in a clearing action
|
||||
/// </summary>
|
||||
public ClearSpawnFrom m_clearSpawnsFrom = ClearSpawnFrom.AnySource;
|
||||
|
||||
/// <summary>
|
||||
/// The last GUID of the settings file used to save these settings.
|
||||
/// </summary>
|
||||
public string m_lastGUIDSaved = "";
|
||||
|
||||
|
||||
|
||||
//Using a property to make sure the image mask list is always initialized
|
||||
//<summary>All image filters that are being applied in this spawning process</summary>
|
||||
|
||||
public ImageMask[] m_imageMasks
|
||||
{
|
||||
get
|
||||
{
|
||||
if (imageMasks == null)
|
||||
{
|
||||
imageMasks = new ImageMask[0];
|
||||
}
|
||||
return imageMasks;
|
||||
}
|
||||
set
|
||||
{
|
||||
imageMasks = value;
|
||||
}
|
||||
}
|
||||
|
||||
//public float m_powerOf;
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
#region Unity Events
|
||||
private void Awake()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region Serialization
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Removes References to Texture2Ds in Image masks. The image mask will still remember the GUID of that texture to load it when needed.
|
||||
/// Call this when you are "done" with the spawner settings to free up memory caused by these references.
|
||||
/// </summary>
|
||||
public void ClearImageMaskTextures()
|
||||
{
|
||||
foreach (ImageMask im in m_imageMasks)
|
||||
{
|
||||
im.FreeTextureReferences();
|
||||
}
|
||||
foreach (SpawnRule sr in m_spawnerRules)
|
||||
{
|
||||
foreach (ImageMask im in sr.m_imageMasks)
|
||||
{
|
||||
im.FreeTextureReferences();
|
||||
}
|
||||
}
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
|
||||
public void RefreshGUID()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
string currentGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(this));
|
||||
if (!m_lastGUIDSaved.Equals(currentGUID))
|
||||
{
|
||||
m_lastGUIDSaved = currentGUID;
|
||||
EditorUtility.SetDirty(this);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1d61257710f55f478816040e1d1dfc9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 0861027633dd71c4485845e27852793c, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,132 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// A class to manage tree instances on unity terrain
|
||||
/// </summary>
|
||||
public class TreeManager
|
||||
{
|
||||
#pragma warning disable 414
|
||||
private List<TreePrototype> m_terrainTrees = new List<TreePrototype>();
|
||||
private Quadtree<int> m_terrainTreeLocations = new Quadtree<int>(new Rect(0,0, 10f, 10f));
|
||||
#pragma warning restore 414
|
||||
|
||||
/// <summary>
|
||||
/// Load the trees in from the terrain
|
||||
/// </summary>
|
||||
public void LoadTreesFromTerrain()
|
||||
{
|
||||
//Destroy previous contents
|
||||
m_terrainTrees = null;
|
||||
m_terrainTreeLocations = null;
|
||||
|
||||
//Work out the bounds of the environment
|
||||
float minY = float.NaN;
|
||||
float minX = float.NaN;
|
||||
float maxX = float.NaN;
|
||||
float minZ = float.NaN;
|
||||
float maxZ = float.NaN;
|
||||
Terrain sampleTerrain = null;
|
||||
foreach (Terrain terrain in Terrain.activeTerrains)
|
||||
{
|
||||
if (float.IsNaN(minY))
|
||||
{
|
||||
sampleTerrain = terrain;
|
||||
minY = terrain.transform.position.y;
|
||||
minX = terrain.transform.position.x;
|
||||
minZ = terrain.transform.position.z;
|
||||
maxX = minX + terrain.terrainData.size.x;
|
||||
maxZ = minZ + terrain.terrainData.size.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (terrain.transform.position.x < minX)
|
||||
{
|
||||
minX = terrain.transform.position.x;
|
||||
}
|
||||
if (terrain.transform.position.z < minZ)
|
||||
{
|
||||
minZ = terrain.transform.position.z;
|
||||
}
|
||||
if ((terrain.transform.position.x + terrain.terrainData.size.x) > maxX)
|
||||
{
|
||||
maxX = terrain.transform.position.x + terrain.terrainData.size.x;
|
||||
}
|
||||
if ((terrain.transform.position.z + terrain.terrainData.size.z) > maxZ)
|
||||
{
|
||||
maxZ = terrain.transform.position.z + terrain.terrainData.size.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sampleTerrain != null)
|
||||
{
|
||||
Rect terrainBounds = new Rect(minX, minZ, maxX - minX, maxZ - minZ);
|
||||
|
||||
m_terrainTreeLocations = new Quadtree<int>(terrainBounds, 32);
|
||||
m_terrainTrees = new List<TreePrototype>(sampleTerrain.terrainData.treePrototypes);
|
||||
|
||||
foreach (Terrain terrain in Terrain.activeTerrains)
|
||||
{
|
||||
float terrainOffsetX = terrain.transform.position.x;
|
||||
float terrainOffsetZ = terrain.transform.position.z;
|
||||
float terrainWidth = terrain.terrainData.size.x;
|
||||
float terrainDepth = terrain.terrainData.size.z;
|
||||
TreeInstance[] terrainTreeInstances = terrain.terrainData.treeInstances;
|
||||
for (int treeIdx = 0; treeIdx < terrainTreeInstances.Length; treeIdx++)
|
||||
{
|
||||
TreeInstance treeInstance = terrainTreeInstances[treeIdx];
|
||||
m_terrainTreeLocations.Insert(terrainOffsetX + (treeInstance.position.x * terrainWidth), terrainOffsetZ + (treeInstance.position.z * terrainDepth), terrainTreeInstances[treeIdx].prototypeIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a tree instance into storage - must be called after the initial load call
|
||||
/// </summary>
|
||||
/// <param name="position"></param>
|
||||
/// <param name="prototypeIdx"></param>
|
||||
public void AddTree(Vector3 position, int prototypeIdx)
|
||||
{
|
||||
if (m_terrainTreeLocations == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_terrainTreeLocations.Insert(position.x, position.z, prototypeIdx);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of trees within range of the location provided
|
||||
/// </summary>
|
||||
/// <param name="position">Location to check</param>
|
||||
/// <param name="range">Range around location to check</param>
|
||||
/// <returns>Number of trees within range</returns>
|
||||
public int Count(Vector3 position, float range)
|
||||
{
|
||||
if (m_terrainTreeLocations == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Rect query = new Rect(position.x - range, position.z - range, range * 2f, range * 2f);
|
||||
return m_terrainTreeLocations.Find(query).Count();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of trees being managed
|
||||
/// </summary>
|
||||
/// <returns>Number of trees being managed</returns>
|
||||
public int Count()
|
||||
{
|
||||
if (m_terrainTreeLocations == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return m_terrainTreeLocations.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9698914ca25555449450f7e6a17197a
|
||||
timeCreated: 1471419699
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// This class only exists to change the displayed name from "Spawner" to "World Biome Masks" on the component.
|
||||
/// </summary>
|
||||
public class WorldBiomeMasks : Spawner
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f157bdee0e49e464bac16f64f56f4530
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gaia
|
||||
{
|
||||
/// <summary>
|
||||
/// This class only exists to change the displayed name from "Spawner" to "World Generator" on the component.
|
||||
/// </summary>
|
||||
public class WorldDesigner : Spawner
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e6fe132ece01fb4aa7f13b4c2e4e27a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
/// <summary>
|
||||
/// This file is being replaced with WorldDesigner.cs and is just left here for upwards compatibility to "disable" this file in earlier Gaia installations
|
||||
/// </summary>
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a955c961b4c87854ea6019284c0fc205
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user