BITFALL/Assets/GSpawn - Level Designer/Scripts/Core/ProfileDb.cs

247 lines
8.2 KiB
C#

#if UNITY_EDITOR
using UnityEngine;
using System.Collections.Generic;
using UnityEditor;
namespace GSpawn
{
public abstract class ProfileDb<TProfile> : ScriptableObject
where TProfile : Profile
{
public delegate void ActiveProfileChangedHandler (TProfile newActiveProfile);
public delegate void ProfileRenamedHandler (TProfile profile);
public event ActiveProfileChangedHandler activeProfileChanged;
public event ProfileRenamedHandler profileRenamed;
private static readonly string _defaultProfileName = "Default";
[SerializeField]
private List<TProfile> _profiles = new List<TProfile>();
[SerializeField]
private TProfile _activeProfile;
public int numProfiles { get { return _profiles.Count; } }
public TProfile defaultProfile
{
get
{
// Note: We can't do this in OnEnabled because it causes
// issues when importing into another project (i.e. it
// overrides the existing default profile).
initializeIfNecessary();
return _profiles[0];
}
}
public TProfile activeProfile
{
get
{
if (_activeProfile == null)
{
UndoEx.saveEnabledState();
UndoEx.enabled = false;
_activeProfile = defaultProfile;
EditorUtility.SetDirty(this);
UndoEx.restoreEnabledState();
}
return (TProfile)_activeProfile;
}
}
public bool isDefaultProfileActive { get { return defaultProfile == activeProfile; } }
public abstract string folderPath { get; }
public static string defaultProfileName { get { return _defaultProfileName; } }
public void onPostProcessAllAssets()
{
// Note: Make sure all profiles are loaded. Don't do this in OnEnable. See the defaultProfile property.
loadProfiles(folderPath);
createDefaultProfile();
EditorUtility.SetDirty(this);
}
public void initializeIfNecessary()
{
if (_profiles.Count == 0)
{
loadProfiles(folderPath);
createDefaultProfile();
}
}
public void setActiveProfile(string profileName, bool allowUndoRedo)
{
initializeIfNecessary();
if (string.IsNullOrEmpty(profileName)) return;
var newActiveProfile = findProfile(profileName);
if (newActiveProfile != null && newActiveProfile != _activeProfile)
{
if (allowUndoRedo) UndoEx.record(this);
_activeProfile = newActiveProfile;
EditorUtility.SetDirty(this);
onActiveProfileChanged();
if (activeProfileChanged != null) activeProfileChanged((TProfile)_activeProfile);
}
}
public TProfile createProfile(string profileName)
{
if (string.IsNullOrEmpty(profileName)) return null;
// Note: Avoid calling getProfileNames. It will cause a stack overflow
// because of 'initializeIfNecessary'.
var names = new List<string>();
foreach (var p in _profiles)
names.Add(p.profileName);
profileName = UniqueNameGen.generate(profileName, names);
TProfile profile = CreateInstance<TProfile>();
profile.profileName = profileName;
_profiles.Add(profile);
AssetDbEx.saveScriptableObject(profile, folderPath + "/" + profile.profileName + ".asset");
EditorUtility.SetDirty(this);
return profile;
}
public void deleteProfile(TProfile profile)
{
if (profile == defaultProfile) return;
if (containsProfile(profile))
{
//UndoEx.record(this);
bool refreshActiveProfile = profile == _activeProfile;
_profiles.Remove(profile);
//UndoEx.destroyObjectImmediate(profile);
DestroyImmediate(profile, true);
if (refreshActiveProfile) setActiveProfile(defaultProfile.profileName, true);
EditorUtility.SetDirty(this);
}
}
public void renameProfile(TProfile profile, string newName)
{
if (!string.IsNullOrEmpty(newName) && containsProfile(profile) && profile.profileName != newName)
{
var names = new List<string>();
getProfileNames(names, profile.profileName);
newName = UniqueNameGen.generate(newName, names);
// Note: Rename the asset first in order to avoid warning message.
AssetDatabase.RenameAsset(AssetDatabase.GetAssetPath(profile), newName);
profile.profileName = newName;
if (profileRenamed != null) profileRenamed(profile);
EditorUtility.SetDirty(this);
}
}
public bool containsProfile(TProfile profile)
{
return _profiles.Contains(profile);
}
public bool containsProfile(string name)
{
if (string.IsNullOrEmpty(name)) return false;
return _profiles.Find(item => { return item.profileName == name; }) != null;
}
public void getProfileNames(List<string> profileNames, string ignoredName)
{
initializeIfNecessary();
profileNames.Clear();
foreach (var profile in _profiles)
{
if (profile.profileName != ignoredName)
profileNames.Add(profile.profileName);
}
}
public void getProfiles(List<TProfile> profiles)
{
initializeIfNecessary();
profiles.Clear();
profiles.AddRange(_profiles);
}
public TProfile findProfile(string profileName)
{
initializeIfNecessary();
return _profiles.Find(item => item.profileName == profileName);
}
public TProfile getProfile(int index)
{
initializeIfNecessary();
return _profiles[index];
}
public int indexOf(TProfile profile)
{
initializeIfNecessary();
return _profiles.IndexOf(profile);
}
protected virtual void onActiveProfileChanged () {}
protected virtual void onEnabled () {}
protected virtual void onDisabled () {}
protected virtual void onDestroy () {}
private void loadProfiles(string folderPath)
{
if (_profiles.Count == 0)
{
var profiles = AssetDbEx.loadAssetsInFolder<TProfile>(folderPath);
foreach (var profile in profiles)
{
if (!containsProfile(profile))
_profiles.Add(profile);
}
EditorUtility.SetDirty(this);
}
}
private void createDefaultProfile()
{
if (!containsProfile(_defaultProfileName))
{
createProfile(_defaultProfileName);
EditorUtility.SetDirty(this);
}
}
private void OnEnable()
{
// Note: Doesn't work when exporting to a different project.
//loadProfiles(folderPath);
//createDefaultProfile();
//if (_activeProfile == null) _activeProfile = defaultProfile;
//EditorUtility.SetDirty(this);
onEnabled();
}
private void OnDisable()
{
onDisabled();
}
private void OnDestroy()
{
onDestroy();
foreach (var profile in _profiles)
DestroyImmediate(profile, true);
}
}
}
#endif