Files
KopMap/Assets/NatureManufacture Assets/WorldStreamer/Scritps/Editor/StreamerEditor.cs
2025-09-02 18:55:19 +08:00

462 lines
20 KiB
C#

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor.SceneManagement;
namespace WorldStreamer2
{
[CustomEditor(typeof(Streamer))]
class StreamerEditor : Editor
{
//[MenuItem("GameObject/Create Other/Create World Streamer", false, 10)]
[MenuItem("GameObject/NM/World Streamer", false, 10)]
static public void CreateWorldStreamer()
{
GameObject gameObject = new GameObject("WorldStreamer");
gameObject.tag = Streamer.STREAMERTAG;
gameObject.AddComponent<Streamer>();
}
public override bool RequiresConstantRepaint()
{
return true;
}
bool checkedScenes = false;
bool scenesToAddCheck = false;
Editor _editor;
public override void OnInspectorGUI()
{
Streamer streamer = (Streamer)target;
EditorGUI.BeginChangeCheck();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Streaming Info", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUI.indentLevel++;
EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(360));
if (Application.isPlaying == false && Streamer.loadingManager != null)
{
Streamer.loadingManager = null;
}
if (Streamer.loadingManager != null)
{
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Scenes To Load", GUILayout.MaxWidth(120));
EditorGUILayout.LabelField(Streamer.loadingManager.ScenesToLoadCount.ToString(), GUILayout.MaxWidth(100));
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Scenes To Unload", GUILayout.MaxWidth(120));
EditorGUILayout.LabelField(Streamer.loadingManager.ScenesToUnloadCount.ToString(), GUILayout.MaxWidth(100));
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Async Operations");
EditorGUILayout.LabelField(Streamer.loadingManager.AsyncOperationsCount.ToString(), GUILayout.MaxWidth(100));
EditorGUILayout.EndVertical();
}
else
{
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Scenes To Load", GUILayout.MaxWidth(120));
EditorGUILayout.LabelField("0", GUILayout.MaxWidth(50));
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Scenes To Unload", GUILayout.MaxWidth(120));
EditorGUILayout.LabelField("0", GUILayout.MaxWidth(100));
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Asyncs Operation", GUILayout.MaxWidth(120));
EditorGUILayout.LabelField("0", GUILayout.MaxWidth(100));
EditorGUILayout.EndVertical();
}
EditorGUILayout.EndHorizontal();
EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
// DrawDefaultInspector();
EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.Space();
EditorGUI.indentLevel++;
//public float
streamer.positionCheckTime = EditorGUILayout.FloatField(new GUIContent("Position Check Time", "Frequancy in seconds in which you want to check if grid element is close /far enough to load/unload."),
streamer.positionCheckTime);
//public float
streamer.destroyTileDelay = EditorGUILayout.FloatField(new GUIContent("Destroy Tile Delay", "Time in seconds after which grid element will be unloaded."), streamer.destroyTileDelay);
////public int
//streamer.maxParallelSceneLoading = EditorGUILayout.IntField(new GUIContent("Max Parallel Scene Loading", "Amount of max grid elements that you want to start loading in one frame."), streamer.maxParallelSceneLoading);
// public int
streamer.sceneLoadWaitFrames = EditorGUILayout.IntField(new GUIContent("Scene Load Wait Frames", "Number of empty frames between loading actions."), streamer.sceneLoadWaitFrames);
EditorGUILayout.Space();
streamer.looping = EditorGUILayout.Toggle(
new GUIContent("Looping", "Enable looping system, each layer is streamed independently, so if you want to synchronize them, they should have the same XYZ size. More info at manual."),
streamer.looping);
if (streamer.looping)
{
EditorGUI.indentLevel++;
streamer.overideRangeLimit = EditorGUILayout.Toggle(new GUIContent("Overide single instance scene loading", "Override scene split range limit with loading scenes multiple times."),
streamer.overideRangeLimit);
streamer.overideScenesLimits = EditorGUILayout.Toggle(new GUIContent("Sync scene collection limits", "Override scene collection split limit."), streamer.overideScenesLimits);
streamer.xLimitsOverrideIs = EditorGUILayout.Toggle(new GUIContent("Override X limits", "Override scene collection split limit on x axis."), streamer.xLimitsOverrideIs);
if (streamer.xLimitsOverrideIs)
{
EditorGUI.indentLevel++;
streamer.xLimitsOverride = EditorGUILayout.Vector2IntField(new GUIContent("Override X limits", "Override scene collection split limit on x axis."), streamer.xLimitsOverride);
EditorGUI.indentLevel--;
}
streamer.yLimitsOverrideIs = EditorGUILayout.Toggle(new GUIContent("Override Y limits", "Override scene collection split limit on y axis."), streamer.yLimitsOverrideIs);
if (streamer.yLimitsOverrideIs)
{
EditorGUI.indentLevel++;
streamer.yLimitsOverride = EditorGUILayout.Vector2IntField(new GUIContent("Override Y limits", "Override scene collection split limit on y axis."), streamer.yLimitsOverride);
EditorGUI.indentLevel--;
}
streamer.zLimitsOverrideIs = EditorGUILayout.Toggle(new GUIContent("Override Z limits", "Override scene collection split limit on z axis."), streamer.zLimitsOverrideIs);
if (streamer.zLimitsOverrideIs)
{
EditorGUI.indentLevel++;
streamer.zLimitsOverride = EditorGUILayout.Vector2IntField(new GUIContent("Override Z limits", "Override scene collection split limit on z axis."), streamer.zLimitsOverride);
EditorGUI.indentLevel--;
}
}
EditorGUILayout.Space();
streamer.terrainNeighbours =
(TerrainNeighbours)EditorGUILayout.ObjectField(
new GUIContent("Terrain Neighbours",
"If you want to fix small holes from LODs system at unity terrain borders, drag and drop object here from scene hierarchy that contains our \"Terrain Neighbours\" script."),
streamer.terrainNeighbours, typeof(TerrainNeighbours), true);
EditorGUILayout.Space();
EditorGUI.indentLevel--;
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
//EditorGUI.indentLevel--;
EditorGUILayout.LabelField("Player Settings", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.Space();
streamer.player = (Transform)EditorGUILayout.ObjectField(new GUIContent("Player", "Drag and drop here, an object that system have to follow during streaming process."), streamer.player, typeof(Transform),
true);
streamer.spawnedPlayer = EditorGUILayout.Toggle(new GUIContent("Spawned Player", "Streamer will wait for player spawn and fill it automatically"), streamer.spawnedPlayer);
if (streamer.player != null && EditorUtility.IsPersistent(streamer.player))
{
streamer.player = null;
}
if (streamer.spawnedPlayer)
{
string newTag = EditorGUILayout.TagField(new GUIContent("Player Tag", "Streamer will search for player by tag."), streamer.playerTag);
if (streamer.playerTag != newTag)
{
streamer.playerTag = newTag;
EditorUtility.SetDirty(streamer);
}
}
EditorGUILayout.Space();
EditorGUILayout.EndVertical();
EditorGUI.indentLevel--;
EditorGUILayout.Space();
if (EditorGUI.EndChangeCheck())
{
Undo.RegisterCompleteObjectUndo(target, "UI change streamer");
}
SerializedProperty list = serializedObject.FindProperty("sceneCollectionManagers");
//EditorGUILayout.PropertyField(list);
//EditorGUI.indentLevel++;
GUIStyle foldoutStyle = new GUIStyle(EditorStyles.foldout);
foldoutStyle.fontStyle = FontStyle.Bold;
list.isExpanded = EditorGUILayout.Foldout(list.isExpanded, new GUIContent("Scene Collection Managers"), foldoutStyle);
if (list.isExpanded)
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.Space();
EditorGUILayout.PropertyField(list.FindPropertyRelative("Array.size"));
EditorGUILayout.Space();
EditorGUI.indentLevel++;
for (int i = 0; i < list.arraySize; i++)
{
SerializedProperty scriptable = list.GetArrayElementAtIndex(i);
if (scriptable != null)
{
Color old = GUI.color;
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.BeginHorizontal();
if (scriptable.objectReferenceValue != null)
{
if (i < streamer.sceneCollectionManagers.Count)
scriptable.isExpanded = EditorGUILayout.Foldout(scriptable.isExpanded,
scriptable.objectReferenceValue.name + " (" + (streamer.sceneCollectionManagers[i].active ? "active" : "inactive") + ")", true, foldoutStyle);
else
{
scriptable.isExpanded = EditorGUILayout.Foldout(scriptable.isExpanded, scriptable.objectReferenceValue.name, true, EditorStyles.boldLabel);
if (streamer.sceneCollectionManagers.Count > i && streamer.sceneCollectionManagers[i] != null && !streamer.sceneCollectionManagers[i].active)
GUI.color = Color.gray;
}
}
EditorGUILayout.PropertyField(scriptable, new GUIContent(""));
EditorGUILayout.EndHorizontal();
if (scriptable.isExpanded && scriptable.objectReferenceValue != null)
{
//EditorGUI.indentLevel++;
Editor.CreateCachedEditor(scriptable.objectReferenceValue, null, ref _editor);
if (_editor != null)
{
EditorGUI.BeginChangeCheck();
//_editor.DrawDefaultInspector();
_editor.OnInspectorGUI();
if (EditorGUI.EndChangeCheck())
{
Undo.RegisterCompleteObjectUndo(streamer.sceneCollectionManagers[i], "UI change streamer collection");
Undo.FlushUndoRecordObjects();
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}
}
//EditorGUI.indentLevel--;
EditorGUILayout.Space();
}
if (streamer.sceneCollectionManagers != null && i < streamer.sceneCollectionManagers.Count)
{
SceneCollectionManager currentCollection = streamer.sceneCollectionManagers[i];
if (currentCollection != null)
{
if (currentCollection.deloadingRange.x < currentCollection.loadingRange.x || currentCollection.deloadingRange.y < currentCollection.loadingRange.y ||
currentCollection.deloadingRange.z < currentCollection.loadingRange.z)
{
EditorGUILayout.HelpBox("Scene collection " + currentCollection.name + " deloading range must >= loading range", MessageType.Error, true);
}
if (streamer.looping && !streamer.overideRangeLimit)
{
if (Mathf.Abs(currentCollection.xLimitsx - currentCollection.xLimitsy) < currentCollection.deloadingRange.x * 2 ||
Mathf.Abs(currentCollection.yLimitsx - currentCollection.yLimitsy) < currentCollection.deloadingRange.y * 2 ||
Mathf.Abs(currentCollection.zLimitsx - currentCollection.zLimitsy) < currentCollection.deloadingRange.z * 2)
{
EditorGUILayout.HelpBox("Scene collection " + currentCollection.name + " deloading range * 2 must > scene collection limits for looping to work correctly", MessageType.Warning,
true);
}
}
}
}
EditorGUILayout.EndVertical();
GUI.color = old;
EditorGUILayout.Space();
}
}
EditorGUILayout.Space();
EditorGUILayout.EndVertical();
EditorGUI.indentLevel--;
}
serializedObject.ApplyModifiedProperties();
EditorGUILayout.Space();
//if (_editor == null)
//{
// _editor =
// Editor.CreateEditor(myTarget.sceneCollectionManagers[0]);
//}
//_editor.DrawDefaultInspector();
serializedObject.ApplyModifiedProperties();
if (streamer.sceneCollectionManagers == null || streamer.sceneCollectionManagers.Count == 0)
{
EditorGUILayout.HelpBox("No scene collection manager", MessageType.Info, true);
}
else
{
List<string> scenesToAdd = new List<string>();
foreach (var sceneCollectionManager in streamer.sceneCollectionManagers)
{
if (sceneCollectionManager != null)
{
SceneCollectionManager currentCollection = sceneCollectionManager;
if (!Directory.Exists(currentCollection.path))
{
EditorGUILayout.HelpBox("Scene collection path doesn't exist.", MessageType.Error, true);
return;
}
if (!checkedScenes)
{
checkedScenes = true;
List<EditorBuildSettingsScene> scenesList = new List<EditorBuildSettingsScene>();
scenesList.AddRange(EditorBuildSettings.scenes);
scenesToAdd.AddRange(currentCollection.names);
foreach (var item in scenesList)
{
if (scenesToAdd.Contains(item.path.Replace(currentCollection.path, "")) && item.enabled)
{
scenesToAdd.Remove(item.path.Replace(currentCollection.path, ""));
}
}
if (scenesToAdd.Count > 0)
{
scenesToAddCheck = true;
}
}
}
}
if (scenesToAddCheck)
EditorGUILayout.HelpBox("Add scenes from scene collection to build settings.", MessageType.Error, true);
if (GUILayout.Button("Add scenes to build settings"))
{
AddScenesToBuild(streamer);
scenesToAddCheck = false;
}
}
//Check tag exist
//Open tag manager
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
SerializedProperty tagsProp = tagManager.FindProperty("tags");
// First check if it is not already present
bool found = false;
for (int i = 0; i < tagsProp.arraySize; i++)
{
SerializedProperty t = tagsProp.GetArrayElementAtIndex(i);
if (t.stringValue.Equals(Streamer.STREAMERTAG))
{
found = true;
break;
}
}
if (!found)
{
EditorGUILayout.HelpBox("No tag " + Streamer.STREAMERTAG + " in unity.", MessageType.Error, true);
if (GUILayout.Button("Add tag to unity"))
{
found = false;
for (int i = 0; i < tagsProp.arraySize; i++)
{
SerializedProperty t = tagsProp.GetArrayElementAtIndex(i);
if (t.stringValue.Equals(Streamer.STREAMERTAG))
{
found = true;
break;
}
}
if (!found)
{
tagsProp.InsertArrayElementAtIndex(0);
SerializedProperty n = tagsProp.GetArrayElementAtIndex(0);
n.stringValue = Streamer.STREAMERTAG;
tagManager.ApplyModifiedProperties();
}
streamer.tag = Streamer.STREAMERTAG;
}
}
if (streamer.tag != Streamer.STREAMERTAG)
{
EditorGUILayout.HelpBox("Streamer must have " + Streamer.STREAMERTAG + " Tag.", MessageType.Error, true);
if (GUILayout.Button("Change tag"))
{
streamer.tag = Streamer.STREAMERTAG;
}
}
}
/// <summary>
/// Adds the scenes to build.
/// </summary>
void AddScenesToBuild(Streamer myTarget)
{
List<EditorBuildSettingsScene> scenesList = new List<EditorBuildSettingsScene>();
scenesList.AddRange(EditorBuildSettings.scenes);
foreach (var sceneCollectionManager in myTarget.sceneCollectionManagers)
{
List<string> scenesToAdd = new List<string>();
scenesToAdd.AddRange(sceneCollectionManager.names);
foreach (var item in scenesList)
{
if (scenesToAdd.Contains(item.path.Replace(sceneCollectionManager.path, "")))
{
scenesToAdd.Remove(item.path.Replace(sceneCollectionManager.path, ""));
item.enabled = true;
}
}
foreach (var item in scenesToAdd)
{
scenesList.Add(new EditorBuildSettingsScene(sceneCollectionManager.path + item, true));
}
}
EditorBuildSettings.scenes = scenesList.ToArray();
}
}
}