using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace WorldStreamer2
{
///
/// Contains information about scenes in collection
///
[Serializable]
public class SceneCollectionManager : ScriptableObject
{
///
/// Is scene collection active and loading
///
public bool active = true;
///
/// Loading priority
///
public int priority = 1;
[Tooltip("Amount of max grid elements that you want to start loading in one frame.")]
///
/// The max parallel scene loading.
///
public int maxParallelSceneLoading = 1;
//[Header("Ranges")]
[Tooltip("Distance in grid elements that you want hold loaded.")]
///
/// The loading range of new tiles.
///
public Vector3Int loadingRange = new Vector3Int(3, 3, 3);
[Tooltip("Enables ring streaming.")]
///
/// The use loading minimum range.
///
public bool useLoadingRangeMin = false;
[Tooltip("Area that you want to cutout from loading range.")]
///
/// The loading minimum range.
///
public Vector3Int loadingRangeMin = new Vector3Int(2, 2, 2);
[Tooltip("Enables ccene collection elements to unload when scene loaded.")]
///
/// Use scene collection to unload when loaded
///
public bool useUnloadRangeConnect = false;
[Tooltip("Scene collection elements to unload when scene loaded.")]
///
/// Scene collection to unload when loaded
///
public SceneCollectionManager unloadRangeConnect; //sync with other layer
[HideInInspector] [Tooltip("Scene collection elements to unload when scene loaded.")]
///
/// Scene collection to unload when loaded
///
public SceneCollectionManager unloadRangeConnectParent;
[Tooltip("Distance in grid elements after which you want to unload assets.")]
///
/// The deloading range of tiles.
///
public Vector3Int deloadingRange = new Vector3Int(3, 3, 3);
[Header("Settings")]
///
/// The strem object name prefix.
///
public string prefixName = "stream";
///
/// The scene name prefix.
///
public string prefixScene = "Scene";
///
/// The path of scenes.
///
public string path = "Assets/WorldStreamer/SplitScenes/";
[Space(5)]
///
/// The names of the scenes in collection.
///
public string[] names;
[Space(5)]
///
/// The is split by x.
///
public bool xSplitIs = true;
///
/// The is split by y.
///
public bool ySplitIs = false;
///
/// The is split by z.
///
public bool zSplitIs = true;
[Space(5)]
///
/// The size of the tile in x.
///
public int xSize = 500;
///
/// The size of the tile in y.
///
public int ySize = 500;
///
/// The size of the tile in z.
///
public int zSize = 500;
[Space(5)]
///
/// The x axis limits.
///
public int xLimitsx = int.MaxValue;
///
/// The x axis limits.
///
public int xLimitsy = int.MinValue;
///
/// The y axis limits.
///
public int yLimitsx = int.MaxValue;
///
/// The y axis limits.
///
public int yLimitsy = int.MinValue;
///
/// The z axis limits.
///
public int zLimitsx = int.MaxValue;
///
/// The z axis limits.
///
public int zLimitsy = int.MinValue;
//For in scene use
///
/// The x axis limits.
///
[HideInInspector] public int xLimitsScenex = int.MaxValue;
///
/// The x axis limits.
///
[HideInInspector] public int xLimitsSceney = int.MinValue;
///
/// The y axis limits.
///
[HideInInspector] public int yLimitsScenex = int.MaxValue;
///
/// The y axis limits.
///
[HideInInspector] public int yLimitsSceney = int.MinValue;
///
/// The z axis limits.
///
[HideInInspector] public int zLimitsScenex = int.MaxValue;
///
/// The z axis limits.
///
[HideInInspector] public int zLimitsSceney = int.MinValue;
[Space(5)]
///
/// The collapsed for scene collection editor.
///
[HideInInspector]
public bool
collapsed = true;
///
/// The layer number for scene collection editor.
///
[HideInInspector] public int
layerNumber = 0;
[Space(5)]
///
/// The color.
///
public Color color = Color.red;
public bool showDebug = false;
///
/// The scenes array.
///
public Dictionary scenesArray;
[HideInInspector] public int xLoadingLimity;
[HideInInspector] public int xLoadingLimitx;
[HideInInspector] public int xLoadingRange;
[HideInInspector] public int yLoadingLimity;
[HideInInspector] public int yLoadingLimitx;
[HideInInspector] public int yLoadingRange;
[HideInInspector] public int zLoadingLimity;
[HideInInspector] public int zLoadingLimitx;
[HideInInspector] public int zLoadingRange;
///
/// The x position.
///
[HideInInspector] public int xPos = 0;
///
/// The y position.
///
[HideInInspector] public int yPos = 0;
///
/// The z position.
///
[HideInInspector] public int zPos = 0;
///
/// The currently scene loading.
///
[HideInInspector] public int currentlySceneLoading = 0;
///
/// The loaded scenes.
///
//[HideInInspector]
public List loadedScenes = new List();
#if UNITY_EDITOR
[MenuItem("Assets/Create/Scene Collection Manager")]
public static void Create()
{
Selection.activeObject = Create("Assets/", "SceneCollectionManager.asset");
}
public static SceneCollectionManager Create(string path, string assetName)
{
if (string.IsNullOrEmpty(path))
return null;
SceneCollectionManager asset = ScriptableObject.CreateInstance();
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
if (path[path.Length - 1] != '/' && path[path.Length - 1] != '\\')
path += "/";
string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path + assetName);
AssetDatabase.CreateAsset(asset, assetPathAndName);
AssetDatabase.SaveAssets();
EditorUtility.FocusProjectWindow();
return asset;
}
#endif
public void GetSceneCollectionWolrdLimits(out Vector2Int xLimits, out Vector2Int yLimits, out Vector2Int zLimits)
{
xLimits = new Vector2Int(xLimitsx * xSize, (xLimitsy + 1) * xSize);
yLimits = new Vector2Int(yLimitsx * ySize, (yLimitsy + 1) * ySize);
zLimits = new Vector2Int(zLimitsx * zSize, (zLimitsy + 1) * zSize);
}
public void ResetPosition()
{
xPos = int.MinValue;
yPos = int.MinValue;
zPos = int.MinValue;
}
public bool CheckPosition(Vector3 pos)
{
int xPosCurrent = (xSize != 0) ? (int) (Mathf.FloorToInt(pos.x / xSize)) : 0;
int yPosCurrent = (ySize != 0) ? (int) (Mathf.FloorToInt(pos.y / ySize)) : 0;
int zPosCurrent = (zSize != 0) ? (int) (Mathf.FloorToInt(pos.z / zSize)) : 0;
if (xPosCurrent != xPos || yPosCurrent != yPos || zPosCurrent != zPos)
{
xPos = xPosCurrent;
yPos = yPosCurrent;
zPos = zPosCurrent;
return true;
}
return false;
}
public Vector3Int GetTilePosition(Vector3 pos)
{
int xPosCurrent = (xSize != 0) ? (int) (Mathf.FloorToInt(pos.x / xSize)) : 0;
int yPosCurrent = (ySize != 0) ? (int) (Mathf.FloorToInt(pos.y / ySize)) : 0;
int zPosCurrent = (zSize != 0) ? (int) (Mathf.FloorToInt(pos.z / zSize)) : 0;
return new Vector3Int(xPosCurrent, yPosCurrent, zPosCurrent);
}
public void CalculateLoadingLimits(bool looping, bool overideRangeLimit)
{
CalculateLoadingLimits(looping, overideRangeLimit, false, Vector2Int.zero, Vector2Int.zero, Vector2Int.zero);
}
public void CalculateLoadingLimits(bool looping, bool overideRangeLimit, bool overideScenesLimits, Vector2Int xLimits, Vector2Int yLimits, Vector2Int zLimits)
{
loadedScenes.Clear();
currentlySceneLoading = 0;
//Application.backgroundLoadingPriority = ThreadPriority.High;
// Debug.Log(Application.backgroundLoadingPriority);
xLoadingLimity = xLimitsy;
xLoadingLimitx = xLimitsx;
xLoadingRange = xLoadingLimity - xLoadingLimitx + 1;
yLoadingLimity = yLimitsy;
yLoadingLimitx = yLimitsx;
yLoadingRange = yLoadingLimity - yLoadingLimitx + 1;
zLoadingLimity = zLimitsy;
zLoadingLimitx = zLimitsx;
zLoadingRange = zLoadingLimity - zLoadingLimitx + 1;
if (overideScenesLimits)
{
if (xSize != 0)
{
xLoadingLimity = xLimits.y / xSize - 1;
xLoadingLimitx = xLimits.x / xSize;
xLoadingRange = xLoadingLimity - xLoadingLimitx + 1;
}
if (ySize != 0)
{
yLoadingLimity = yLimits.y / ySize - 1;
yLoadingLimitx = yLimits.x / ySize;
yLoadingRange = yLoadingLimity - yLoadingLimitx + 1;
}
if (zSize != 0)
{
zLoadingLimity = zLimits.y / zSize - 1;
zLoadingLimitx = zLimits.x / zSize;
zLoadingRange = zLoadingLimity - zLoadingLimitx + 1;
}
}
//Debug.Log(xLoadingLimitx + " " + xLoadingLimity + " " + xLoadingRange + " " + deloadingRange.x);
if (looping && overideRangeLimit)
{
if ((xLoadingLimitx != 0 || xLoadingLimity != 0) && deloadingRange.x != 0)
{
//int xLimitChange = Mathf.CeilToInt((Mathf.Ceil((deloadingRange.x * 2) / xLoadingRange)) * 0.5f);
int xLimitChange = Mathf.CeilToInt((Mathf.Ceil((deloadingRange.x * 2) / (float) xLoadingRange) - 0.5f) * 0.5f);
xLoadingLimitx -= xLimitChange * xLoadingRange;
xLoadingLimity += xLimitChange * xLoadingRange;
xLoadingRange = xLoadingLimity - xLoadingLimitx + 1;
}
if ((yLoadingLimitx != 0 || yLoadingLimity != 0) && deloadingRange.y != 0)
{
int yLimitChange = Mathf.CeilToInt((Mathf.Ceil((deloadingRange.y * 2) / (float) yLoadingRange) - 0.5f) * 0.5f);
//int yLimitChange = Mathf.CeilToInt((Mathf.Ceil((deloadingRange.y * 2) / yLoadingRange)) * 0.5f);
yLoadingLimitx -= yLimitChange * yLoadingRange;
yLoadingLimity += yLimitChange * yLoadingRange;
yLoadingRange = yLoadingLimity - yLoadingLimitx + 1;
}
if ((zLoadingLimitx != 0 || zLoadingLimity != 0) && deloadingRange.z != 0)
{
int zLimitChange = Mathf.CeilToInt((Mathf.Ceil((deloadingRange.z * 2) / (float) zLoadingRange) - 0.5f) * 0.5f);
//int zLimitChange = Mathf.CeilToInt((Mathf.Ceil((deloadingRange.z * 2) / zLoadingRange)) * 0.5f);
zLoadingLimitx -= zLimitChange * zLoadingRange;
zLoadingLimity += zLimitChange * zLoadingRange;
zLoadingRange = zLoadingLimity - zLoadingLimitx + 1;
}
}
xLimitsScenex = xLimitsx;
xLimitsSceney = xLimitsy;
yLimitsScenex = yLimitsx;
yLimitsSceney = yLimitsy;
zLimitsScenex = zLimitsx;
zLimitsSceney = zLimitsy;
//Debug.Log(xLoadingLimitx + " " + xLoadingLimity + " " + xLoadingRange);
}
public void PrepareScenesArray(bool overideRangeLimit)
{
PrepareScenesArray(overideRangeLimit, false, Vector2Int.zero, Vector2Int.zero, Vector2Int.zero);
}
public void PrepareScenesArray(bool overideRangeLimit, bool overideScenesLimits, Vector2Int xLimits, Vector2Int yLimits, Vector2Int zLimits)
{
scenesArray = new Dictionary(new Vector3IntArrayComparer());
foreach (var sceneName in names)
{
int posX = 0;
int posY = 0;
int posZ = 0;
Streamer.SceneNameToPos(this, sceneName, out posX, out posY, out posZ);
SceneSplit sceneSplit = new SceneSplit();
sceneSplit.posX = posX;
sceneSplit.posY = posY;
sceneSplit.posZ = posZ;
sceneSplit.basePosX = posX;
sceneSplit.basePosY = posY;
sceneSplit.basePosZ = posZ;
sceneSplit.sceneName = sceneName.Replace(".unity", "");
sceneSplit.sceneCollectionManager = this;
sceneSplit.loadingFinished = false;
//Debug.Log(new Vector3Int(posX, posY, posZ));
scenesArray.Add(new Vector3Int(posX, posY, posZ), sceneSplit);
}
int tempxLimity = xLimitsy;
int tempxLimitx = xLimitsx;
int tempxRange = tempxLimity - tempxLimitx + 1;
int tempyLimity = yLimitsy;
int tempyLimitx = yLimitsx;
int tempyRange = tempyLimity - tempyLimitx + 1;
int tempzLimity = zLimitsy;
int tempzLimitx = zLimitsx;
int tempzRange = tempzLimity - tempzLimitx + 1;
if (overideScenesLimits)
{
if (xSize != 0)
{
tempxLimity = xLimits.y / xSize - 1;
tempxLimitx = xLimits.x / xSize;
tempxRange = tempxLimity - tempxLimitx + 1;
}
if (ySize != 0)
{
tempyLimity = yLimits.y / ySize - 1;
tempyLimitx = yLimits.x / ySize;
tempyRange = tempyLimity - tempyLimitx + 1;
}
if (zSize != 0)
{
tempzLimity = zLimits.y / zSize - 1;
tempzLimitx = zLimits.x / zSize;
tempzRange = tempzLimity - tempzLimitx + 1;
}
}
//Debug.Log(name + " " + tempxLimitx + " " + tempxLimity + " " + tempzLimitx + " " + tempzLimity + " " + xLimits.x + " " + xLimits.y);
//Debug.Log(name + " " + xLoadingLimitx + " " + xLoadingLimity);
if (overideRangeLimit)
{
for (int x = xLoadingLimitx; x <= xLoadingLimity; x++)
{
for (int y = yLoadingLimitx; y <= yLoadingLimity; y++)
{
for (int z = zLoadingLimitx; z <= zLoadingLimity; z++)
{
Vector3Int sceneID = new Vector3Int(x, y, z);
int xFinal = Streamer.mod((x + Mathf.Abs(tempxLimitx)), tempxRange) + tempxLimitx;
int yFinal = Streamer.mod((y + Mathf.Abs(tempyLimitx)), tempyRange) + tempyLimitx;
int zFinal = Streamer.mod((z + Mathf.Abs(tempzLimitx)), tempzRange) + tempzLimitx;
// Debug.Log(sceneID);
if (!scenesArray.ContainsKey(sceneID))
{
//Debug.Log(x + " " + tempxLimitx + " " + tempxRange);
sceneID = new Vector3Int(xFinal, yFinal, zFinal);
// Debug.Log(sceneID);
if (!scenesArray.ContainsKey(sceneID))
{
//Debug.Log("no scene");
continue;
}
SceneSplit split = scenesArray[sceneID];
SceneSplit sceneSplit = new SceneSplit();
sceneSplit.posX = x;
sceneSplit.posY = y;
sceneSplit.posZ = z;
sceneSplit.basePosX = split.basePosX;
sceneSplit.basePosY = split.basePosY;
sceneSplit.basePosZ = split.basePosZ;
sceneSplit.sceneName = split.sceneName;
sceneSplit.sceneCollectionManager = this;
sceneSplit.loadingFinished = false;
//Debug.Log(split.sceneName);
scenesArray.Add(new Vector3Int(x, y, z), sceneSplit);
}
}
}
}
}
}
///
/// Converts scene name into vector int position
///
/// Scene name.
public static Vector3Int SceneNameToVectorIntPos(SceneCollectionManager sceneCollectionManager, string sceneName)
{
int posX = 0;
int posY = 0;
int posZ = 0;
string[] values = sceneName.Replace(sceneCollectionManager.prefixScene, "").Replace(".unity", "").Split(new char[]
{
'_'
}, System.StringSplitOptions.RemoveEmptyEntries);
foreach (var item in values)
{
if (item[0] == 'x')
{
posX = int.Parse(item.Replace("x", ""));
}
if (item[0] == 'y')
{
posY = int.Parse(item.Replace("y", ""));
}
if (item[0] == 'z')
{
posZ = int.Parse(item.Replace("z", ""));
}
}
return new Vector3Int(posX, posY, posZ);
}
}
}