You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

447 lines
12 KiB
C#

/******************************************************************************/
/*
Project - MudBun
Publisher - Long Bunny Labs
http://LongBunnyLabs.com
Author - Ming-Lun "Allen" Chou
http://AllenChou.net
*/
/******************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace MudBun
{
public class ProjectPrefs : ScriptableObject
{
private static readonly string InstancePath = "Assets/MudBun/ProjectPrefs.asset";
[Serializable]
public class Record
{
public enum TypeEnum
{
Bool,
Int,
Float,
String,
Set,
}
public string Key = "";
public TypeEnum Type = TypeEnum.Bool;
public string Value = "";
public void Sort()
{
if (Type != TypeEnum.Set)
return;
var set = StringToSet(Value);
set = set.OrderBy(x => x).ToArray();
Value = SetToString(set);
}
}
[SerializeField] private List<Record> m_records = new List<Record>();
public List<Record> Records => m_records;
[SerializeField] private string m_version = "";
public string Version => m_version;
internal static void Init()
{
// poke
var instance = Instance;
//Debug.Log("MudBun: Project prefs version " + MudBun.Version);
}
private static ProjectPrefs Instance
{
get
{
var instance = AssetDatabase.LoadAssetAtPath<ProjectPrefs>(InstancePath);
if (instance != null
&& instance.m_version != MudBun.Version)
{
#if !MUDBUN_DEV
Debug.Log($"MudBun: Detected previous different version ({instance.m_version}); resettings compatibility records.");
//Debug.Log($"MudBun: New project prefs created for version {MudBun.Version}.");
CompatibilityManager.Reset();
#endif
instance.m_version = MudBun.Version;
}
if (instance == null)
{
instance = CreateInstance<ProjectPrefs>();
instance.m_version = MudBun.Version;
AssetDatabase.CreateAsset(instance, InstancePath);
AssetDatabase.Refresh();
instance = AssetDatabase.LoadAssetAtPath<ProjectPrefs>(InstancePath);
Assert.Unequal(instance, null);
}
return instance;
}
}
private static string[] StringToSet(string value)
{
return value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
}
private static string SetToString(string[] set)
{
return string.Join(";", set);
}
private static string AddToSetString(string setStr, string value)
{
var set = StringToSet(setStr);
if (set.Contains(value))
return setStr;
set = set.Append(value).ToArray();
return SetToString(set);
}
private static string RemoveFromSetString(string setStr, string value)
{
var set = StringToSet(setStr);
set = set.Where(x => x != value).ToArray();
return SetToString(set);
}
public static bool GetRecord(string key, out Record record)
{
var list = Instance.Records.FindAll(x => x.Key.Equals(key));
if (list == null || list.Count == 0)
{
record = null;
return false;
}
record = list.First();
return true;
}
public static void SetRecord(string key, Record record)
{
if (GetRecord(key, out Record existingRecord))
{
if (existingRecord.Type == record.Type
&& existingRecord.Value.Equals(record.Value))
return;
existingRecord.Type = record.Type;
existingRecord.Value = record.Value;
}
else
{
record.Key = key;
Instance.Records.Add(record);
}
EditorUtility.SetDirty(Instance);
AssetDatabase.SaveAssets();
}
public static bool HasKey(string key)
{
return Instance.Records.Any(x => x.Key.Equals(key));
}
public static void DeleteKey(string key)
{
Instance.Records.RemoveAll(x => x.Key.Equals(key));
}
public static bool GetBool(string key, bool defaultValue)
{
if (!GetRecord(key, out Record record))
return defaultValue;
Assert.Equal(record.Type, Record.TypeEnum.Bool);
if (!bool.TryParse(record.Value, out bool result))
{
Debug.LogWarning($"MudBun ProjectPrefs: Cannot parse string \"{record.Value}\" into bool for project preference \"{record.Key}\".");
return defaultValue;
}
return result;
}
public static void SetBool(string key, bool value)
{
SetRecord(key, new Record() { Type = Record.TypeEnum.Bool, Value = value.ToString() });
}
public static int GetInt(string key, int defaultValue)
{
if (!GetRecord(key, out Record record))
return defaultValue;
Assert.Equal(record.Type, Record.TypeEnum.Int);
if (!int.TryParse(record.Value, out int result))
{
Debug.LogWarning($"MudBun ProjectPrefs: Cannot parse string \"{record.Value}\" into int for project preference \"{record.Key}\".");
return defaultValue;
}
return result;
}
public static void SetInt(string key, int value)
{
SetRecord(key, new Record() { Type = Record.TypeEnum.Int, Value = value.ToString() });
}
public static float GetFloat(string key, float defaultValue)
{
if (!GetRecord(key, out Record record))
return defaultValue;
Assert.Equal(record.Type, Record.TypeEnum.Float);
if (!float.TryParse(record.Value, out float result))
{
Debug.LogWarning($"MudBun ProjectPrefs: Cannot parse string \"{record.Value}\" into float for project preference \"{record.Key}\".");
return defaultValue;
}
return result;
}
public static void SetFloat(string key, float value)
{
SetRecord(key, new Record() { Type = Record.TypeEnum.Float, Value = value.ToString() });
}
public static string GetString(string key, string defaultValue)
{
if (!GetRecord(key, out Record record))
return defaultValue;
Assert.Equal(record.Type, Record.TypeEnum.String);
return record.Value;
}
public static void SetString(string key, string value)
{
SetRecord(key, new Record() { Type = Record.TypeEnum.String, Value = value });
}
public static string[] GetSet(string key, string[] defaultValue)
{
if (!GetRecord(key, out Record record))
return defaultValue;
Assert.Equal(record.Type, Record.TypeEnum.Set);
return record.Value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
}
public static bool SetContains(string key, string value)
{
var set = GetSet(key, null);
if (set == null)
return false;
return set.Contains(value);
}
public static void AddToSet(string key, string value)
{
if (!GetRecord(key, out Record record))
{
SetRecord(key, new Record() { Type = Record.TypeEnum.Set, Value = value });
return;
}
Assert.Equal(record.Type, Record.TypeEnum.Set);
record.Value = AddToSetString(record.Value, value);
}
public static void RemoveFromSet(string key, string value)
{
if (!GetRecord(key, out Record record))
return;
Assert.Equal(record.Type, Record.TypeEnum.Set);
record.Value = RemoveFromSetString(record.Value, value);
}
}
[CustomEditor(typeof(ProjectPrefs))]
public class ProjectPrefsEditor : MudEditorBase
{
private static readonly int TypeWidth = 80;
private static readonly int SmallButtonWidth = 24;
private static readonly int SortButtonWidth = 80;
private static readonly float SaveDelay = 2.0f;
private float m_lastDirtyTime = -1.0f;
private void MarkDirty()
{
EditorUtility.SetDirty(serializedObject.targetObject);
m_lastDirtyTime = Time.realtimeSinceStartup;
}
private void Save()
{
AssetDatabase.SaveAssets();
m_lastDirtyTime = -1.0f;
}
private void TrySave()
{
if (m_lastDirtyTime < 0.0f)
return;
if (Time.realtimeSinceStartup - m_lastDirtyTime < SaveDelay)
return;
Save();
}
private void OnEnable()
{
EditorApplication.update += TrySave;
}
private void OnDisable()
{
EditorApplication.update -= TrySave;
Save();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
var prefs = (ProjectPrefs) serializedObject.targetObject;
var records = prefs.Records;
if (records == null)
return;
Undo.RecordObject(prefs, "Modify ProjectPrefs");
EditorGUI.BeginChangeCheck();
ProjectPrefs.Record recordToMoveUp = null;
ProjectPrefs.Record recordToMoveDown = null;
ProjectPrefs.Record recordToDelete = null;
foreach (var record in records)
{
EditorGUILayout.BeginHorizontal();
record.Key = EditorGUILayout.TextField(record.Key);
if (GUILayout.Button("↑", GUILayout.Width(SmallButtonWidth)))
recordToMoveUp = record;
if (GUILayout.Button("↓", GUILayout.Width(SmallButtonWidth)))
recordToMoveDown = record;
if (GUILayout.Button("-", GUILayout.Width(SmallButtonWidth)))
recordToDelete = record;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginHorizontal();
record.Type = (ProjectPrefs.Record.TypeEnum) Convert.ToInt32(EditorGUILayout.EnumPopup(record.Type, GUILayout.MinWidth(TypeWidth), GUILayout.MaxWidth(TypeWidth)));
switch (record.Type)
{
case ProjectPrefs.Record.TypeEnum.Bool:
bool boolValue;
if (!bool.TryParse(record.Value, out boolValue))
boolValue = false;
record.Value = EditorGUILayout.Toggle(boolValue).ToString();
break;
case ProjectPrefs.Record.TypeEnum.Int:
int intValue;
if (!int.TryParse(record.Value, out intValue))
intValue = 0;
record.Value = EditorGUILayout.IntField(intValue).ToString();
break;
case ProjectPrefs.Record.TypeEnum.Float:
float floatValue;
if (!float.TryParse(record.Value, out floatValue))
floatValue = 0.0f;
record.Value = EditorGUILayout.FloatField(floatValue).ToString();
break;
case ProjectPrefs.Record.TypeEnum.Set:
case ProjectPrefs.Record.TypeEnum.String:
record.Value = EditorGUILayout.TextField(record.Value);
break;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
}
if (recordToMoveUp != null)
{
int i = records.FindIndex(x => x == recordToMoveUp);
if (i > 0)
{
var recordToSwap = records[i - 1];
records[i - 1] = recordToMoveUp;
records[i] = recordToSwap;
}
}
if (recordToMoveDown != null)
{
int i = records.FindIndex(x => x == recordToMoveDown);
if (i >= 0 && i < records.Count - 1)
{
var recordToSwap = records[i + 1];
records[i + 1] = recordToMoveDown;
records[i] = recordToSwap;
}
}
if (recordToDelete != null)
records.Remove(recordToDelete);
GUILayout.Label($"Version: {prefs.Version}");
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Sort", GUILayout.Width(SortButtonWidth)))
{
records.Sort((a, b) => a.Key.CompareTo(b.Key));
records.ForEach(x => x.Sort());
}
if (GUILayout.Button("+", GUILayout.Width(SmallButtonWidth)))
{
string newRecordKey = "NewRecord";
while (records.Any(x => x.Key.Equals(newRecordKey)))
newRecordKey += "+";
records.Add(new ProjectPrefs.Record() { Key = newRecordKey });
}
EditorGUILayout.EndHorizontal();
serializedObject.Update();
if (EditorGUI.EndChangeCheck())
{
MarkDirty();
}
}
}
}