OldBlueWater/BlueWater/Assets/Doozy/Runtime/UIManager/ScriptableObjects/Internal/PrefabLinkDatabase.cs

294 lines
12 KiB
C#

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System;
using System.Collections.Generic;
using System.Linq;
using Doozy.Runtime.Common;
using Doozy.Runtime.Common.Extensions;
using Doozy.Runtime.Common.ScriptableObjects;
using UnityEngine;
namespace Doozy.Runtime.UIManager.ScriptableObjects.Internal
{
[Serializable]
public abstract class PrefabLinkDatabase<Tdatabase, TprefabLink> : SingletonRuntimeScriptableObject<Tdatabase> where Tdatabase : SingletonRuntimeScriptableObject<Tdatabase> where TprefabLink : PrefabLink
{
[SerializeField] private List<TprefabLink> Database = new List<TprefabLink>();
public List<TprefabLink> database => Database;
public abstract string defaultLinkName { get; }
public abstract string databaseName { get; }
/// <summary>
/// Get all the registered links names in the database.
/// First name will always be the default name 'None'.
/// </summary>
/// <returns> List of links names </returns>
public List<string> GetAllNames()
{
var names = new List<string>() { defaultLinkName };
// Validate();
// Sort();
names.AddRange(Database.Select(link => link.prefabName.RemoveWhitespaces().RemoveAllSpecialCharacters()));
return names;
}
/// <summary> Check it the database contains the given link </summary>
/// <param name="link"> Link to check </param>
/// <returns> TRUE if the database contains the given link, FALSE otherwise </returns>
public bool Contains(TprefabLink link) =>
Database.RemoveNulls().Contains(link);
/// <summary> Check if the database contains a link with the given prefabName </summary>
/// <param name="prefabName"> Name of the prefab </param>
/// <returns> TRUE if the database contains a link with the given prefabName, FALSE otherwise </returns>
public bool Contains(string prefabName) =>
Database.RemoveNulls().Any(x => x.prefabName.Equals(prefabName));
/// <summary> Check if the database contains a link with the given prefab reference </summary>
/// <param name="prefab"> Reference to the prefab </param>
/// <returns> TRUE if the database contains a link with the given prefab reference, FALSE otherwise </returns>
public bool Contains(GameObject prefab) =>
Database.RemoveNulls().Any(x => x.prefab == prefab);
/// <summary> Add a new link to the database with the given prefab and prefabName </summary>
/// <param name="link"> Link to add to the database </param>
/// <returns> TRUE if the database was updated, FALSE if the database already contains a link with the given prefabName </returns>
public bool Add(TprefabLink link)
{
if (link == null) return false;
link.Validate();
if (Contains(link)) return false;
if (!link.hasPrefab)
{
// Debug.Log($"Cannot add a link with a null prefab reference to the {databaseName} database.");
Remove(link);
return false;
}
if (!link.hasPrefabName)
{
// Debug.Log($"Cannot add a link with a null or empty prefabName to the {databaseName} database.");
Remove(link);
return false;
}
if (Contains(link.prefab))
{
Debug.Log($"{databaseName} database already contains a link with the given prefab reference. Link not added.");
return false;
}
if (Contains(link.prefabName))
{
Debug.Log($"{databaseName} database already contains a link with the given '{link.prefabName}' prefabName. Link not added.");
return false;
}
Database.Add(link);
Save();
return true;
}
/// <summary> Remove a link from the database </summary>
/// <param name="link"> Link to remove from the database </param>
/// <returns> TRUE if the link was removed, FALSE if the link was not found in the database </returns>
public bool Remove(TprefabLink link)
{
if (link == null) return false;
if (!Contains(link)) return false;
Database.Remove(link);
#if UNITY_EDITOR
{
UnityEditor.AssetDatabase.MoveAssetToTrash(UnityEditor.AssetDatabase.GetAssetPath(link));
Save();
}
#endif
return true;
}
/// <summary> Remove a link from the database with the given prefabName </summary>
/// <param name="prefabName"> Name of the prefab </param>
/// <returns> TRUE if the database was updated, FALSE if the database does not contain a link with the given prefabName </returns>
public bool Remove(string prefabName)
{
prefabName = prefabName.RemoveWhitespaces().RemoveAllSpecialCharacters();
if (string.IsNullOrEmpty(prefabName)) return false;
TprefabLink link = null;
foreach (TprefabLink item in Database)
{
if (!item.prefabName.Equals(prefabName)) continue;
link = item;
break;
}
if (link == null) return false;
Database.Remove(link);
#if UNITY_EDITOR
{
UnityEditor.AssetDatabase.MoveAssetToTrash(UnityEditor.AssetDatabase.GetAssetPath(link));
Save();
}
#endif
return true;
}
/// <summary> Remove a link from the database with the given prefab reference </summary>
/// <param name="prefab"> Reference to the prefab </param>
/// <returns> TRUE if the database was updated, FALSE if the database does not contain a link with the given prefab reference </returns>
public bool Remove(GameObject prefab)
{
if (prefab == null) return false;
if (!Contains(prefab)) return false;
TprefabLink link = null;
foreach (TprefabLink item in Database)
{
if (item.prefab != prefab) continue;
link = item;
break;
}
if (link == null) return false;
Database.Remove(link);
#if UNITY_EDITOR
{
UnityEditor.AssetDatabase.MoveAssetToTrash(UnityEditor.AssetDatabase.GetAssetPath(link));
Save();
}
#endif
return true;
}
/// <summary> Remove the given link from the database and then delete the asset file from the project </summary>
/// <param name="link"> Link to delete </param>
/// <returns> TRUE if the operation was successful, FALSE otherwise </returns>
public bool Delete(TprefabLink link)
{
if (link == null) return false;
if (!Contains(link)) return false;
Database.Remove(link);
#if UNITY_EDITOR
{
UnityEditor.AssetDatabase.MoveAssetToTrash(UnityEditor.AssetDatabase.GetAssetPath(link));
Save();
}
#endif
return true;
}
/// <summary>
/// Get the prefab reference of a link with the given prefabName.
/// If the prefabName is not found, it will return null.
/// <param name="tooltipName"> Name of the tooltip prefab </param>
/// </summary>
public GameObject GetPrefab(string tooltipName)
{
if (tooltipName.IsNullOrEmpty()) return null;
if (tooltipName.Equals(defaultLinkName)) return null;
tooltipName = tooltipName.RemoveWhitespaces().RemoveAllSpecialCharacters();
foreach (TprefabLink t in Database)
if (t.prefabName.Equals(tooltipName))
return t.prefab;
return null;
}
/// <summary> Refresh the database </summary>
/// <param name="saveAssets"> Write all unsaved asset changes to disk? </param>
/// <param name="refreshAssetDatabase"> Scan and load all modified assets? </param>
public void RefreshDatabase(bool saveAssets = true, bool refreshAssetDatabase = false)
{
#if UNITY_EDITOR
{
string title = $"{databaseName} - Refreshing Database";
UnityEditor.EditorUtility.DisplayProgressBar(title, "Initializing...", 0f);
Database.Clear();
UnityEditor.EditorUtility.DisplayProgressBar(title, $"Searching for {typeof(TprefabLink).Name} files...", 0.1f);
//FIND the GUIDs for all ScriptableObjects of the given type
string[] guids = UnityEditor.AssetDatabase.FindAssets($"t:{typeof(TprefabLink).Name}");
//PROCESS ALL FOUND ASSETS (validate & add)
int foundCount = guids.Length;
for (int i = 0; i < foundCount; i++)
{
string guid = guids[i];
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
UnityEditor.EditorUtility.DisplayProgressBar(title, $"{assetPath}", 0.2f + 0.6f * ((i + 1f) / foundCount));
Add(UnityEditor.AssetDatabase.LoadAssetAtPath<TprefabLink>(assetPath));
}
UnityEditor.EditorUtility.DisplayProgressBar(title, "Validate and Sort...", 0.8f);
Validate();
//MARK DATABASE as DIRTY
UnityEditor.EditorUtility.SetDirty(instance);
UnityEditor.EditorUtility.DisplayProgressBar(title, "Saving...", 1f);
if (saveAssets) Save();
if (refreshAssetDatabase) UnityEditor.AssetDatabase.Refresh();
UnityEditor.EditorUtility.ClearProgressBar();
}
#endif
}
/// <summary> Validate the database by removing invalid items </summary>
public Tdatabase Validate()
{
// Debug.Log($"Validating {databaseName}...");
bool save = false;
for (int i = Database.Count - 1; i >= 0; i--)
{
TprefabLink link = Database[i];
if
(
link != null && //link is not null
link.prefab != null && //link prefab is not null
!link.prefabName.IsNullOrEmpty()) //link prefab name is not null or empty
{
link.Validate(); //validate the link
continue; //continue to the next link
}
Database.RemoveAt(i);
save = true;
}
Sort();
if (save) Save();
return instance;
}
/// <summary> Sort the database by prefabName. </summary>
public Tdatabase Sort()
{
Database.Sort((x, y) => string.Compare(x.prefabName, y.prefabName, StringComparison.Ordinal));
return instance;
}
public Tdatabase Save()
{
#if UNITY_EDITOR
{
UnityEditor.EditorUtility.SetDirty(instance);
UnityEditor.AssetDatabase.SaveAssetIfDirty(instance);
}
#endif
return instance;
}
public Tdatabase SaveAndRefresh()
{
#if UNITY_EDITOR
{
Save();
UnityEditor.AssetDatabase.Refresh();
}
#endif
return instance;
}
}
}