#if UNITY_2018_3_OR_NEWER
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
#if UNITY_2019_1_OR_NEWER
using UnityEngine.UIElements;
#elif UNITY_2018_3_OR_NEWER
using UnityEditor.Experimental.UIElements;
using UnityEngine.Experimental.UIElements;
using UnityEngine.Experimental.UIElements.StyleEnums;
#endif
namespace UnityAtoms.Editor
{
///
/// Editor class for the `Generator`. Use it via the top window bar at _Tools / Unity Atoms / Generator_. Only availble in `UNITY_2019_1_OR_NEWER`.
///
public class GeneratorEditor : EditorWindow
{
///
/// Create the editor window.
///
[MenuItem("Tools/Unity Atoms/Generator")]
static void Init()
{
var window = GetWindow(false, "Unity Atoms - Generator");
window.position = new Rect(Screen.width / 2, Screen.height / 2, 440, 540);
window.Show();
}
private string _valueType = "";
private bool _isValueTypeEquatable = true;
private string _valueTypeNamespace = "";
private string _subUnityAtomsNamespace = "";
private List _atomTypesToGenerate = new List(AtomTypes.ALL_ATOM_TYPES);
private Dictionary _typeVEDict = new Dictionary();
private VisualElement _typesToGenerateInfoRow;
///
/// Add provided `AtomType` to the list of Atom types to be generated.
///
/// The `AtomType` to be added.
private void AddAtomTypeToGenerate(AtomType atomType)
{
_atomTypesToGenerate.Add(atomType);
foreach (KeyValuePair> entry in AtomTypes.DEPENDENCY_GRAPH)
{
if (!_typeVEDict.ContainsKey(entry.Key)) continue;
if (entry.Value.All((atom) => _atomTypesToGenerate.Contains(atom)))
{
_typeVEDict[entry.Key].SetEnabled(true);
}
}
_typesToGenerateInfoRow.Query().First().text = "";
}
///
/// Remove provided `AtomType` from the list of Atom types to be generated.
///
/// The `AtomType` to be removed.
private List RemoveAtomTypeToGenerate(AtomType atomType)
{
_atomTypesToGenerate.Remove(atomType);
List disabledDeps = new List();
foreach (KeyValuePair> entry in AtomTypes.DEPENDENCY_GRAPH)
{
if (!_typeVEDict.ContainsKey(entry.Key)) continue;
if (_atomTypesToGenerate.Contains(entry.Key) && entry.Value.Any((atom) => !_atomTypesToGenerate.Contains(atom)))
{
_typeVEDict[entry.Key].SetEnabled(false);
var toggle = _typeVEDict[entry.Key].Query().First();
toggle.SetValueWithoutNotify(false);
toggle.MarkDirtyRepaint();
disabledDeps.Add(entry.Key);
disabledDeps = disabledDeps.Concat(RemoveAtomTypeToGenerate(entry.Key)).ToList();
}
}
return disabledDeps;
}
///
/// Set and display warning text in the editor.
///
/// `AtomType` to generate the warning for.
/// List of disabled deps.
private void SetWarningText(AtomType atomType, List disabledDeps = null)
{
if (disabledDeps != null && disabledDeps.Count > 0)
{
string warningText = $"{String.Join(", ", disabledDeps.Select((a) => a.DisplayName))} depend(s) on {atomType.DisplayName}.";
_typesToGenerateInfoRow.Query().First().text = warningText;
}
else
{
_typesToGenerateInfoRow.Query().First().text = "";
}
}
private static string _baseWritePath = Runtime.IsUnityAtomsRepo
? "../Packages/BaseAtoms" : "Assets/Atoms";
///
/// Called when editor is enabled.
///
private void OnEnable()
{
#if UNITY_2019_1_OR_NEWER
var root = this.rootVisualElement;
#elif UNITY_2018_3_OR_NEWER
var root = this.GetRootVisualContainer();
#endif
var pathRow = new VisualElement() { style = { flexDirection = FlexDirection.Row } };
pathRow.Add(new Label() { text = "Relative Write Path", style = { width = 180, marginRight = 8 } });
var textfield = new TextField() { value = _baseWritePath, style = { flexGrow = 1 } };
textfield.RegisterCallback>(evt => _baseWritePath = evt.newValue);
pathRow.Add(textfield);
root.Add(pathRow);
var typeNameRow = new VisualElement() { style = { flexDirection = FlexDirection.Row } };
typeNameRow.Add(new Label() { text = "Type", style = { width = 180, marginRight = 8 } });
textfield = new TextField() { value = _valueType, style = { flexGrow = 1 } };
textfield.RegisterCallback>(evt => _valueType = evt.newValue);
typeNameRow.Add(textfield);
root.Add(typeNameRow);
var equatableRow = new VisualElement() { style = { flexDirection = FlexDirection.Row } };
equatableRow.Add(new Label() { text = "Is Type Equatable?", style = { width = 180, marginRight = 8 } });
var equatableToggle = new Toggle() { value = _isValueTypeEquatable, style = { flexGrow = 1 } };
equatableToggle.RegisterCallback>(evt => _isValueTypeEquatable = evt.newValue);
equatableRow.Add(equatableToggle);
root.Add(equatableRow);
var typeNamespaceRow = new VisualElement() { style = { flexDirection = FlexDirection.Row } };
typeNamespaceRow.Add(new Label() { text = "Type Namespace", style = { width = 180, marginRight = 8 } });
textfield = new TextField() { value = _valueTypeNamespace, style = { flexGrow = 1 } };
textfield.RegisterCallback>(evt => _valueTypeNamespace = evt.newValue);
typeNamespaceRow.Add(textfield);
root.Add(typeNamespaceRow);
var subUnityAtomsNamespaceRow = new VisualElement() { style = { flexDirection = FlexDirection.Row } };
subUnityAtomsNamespaceRow.Add(new Label() { text = "Sub Unity Atoms Namespace", style = { width = 180, marginRight = 8 } });
textfield = new TextField() { value = _subUnityAtomsNamespace, style = { flexGrow = 1 } };
textfield.RegisterCallback>(evt => _subUnityAtomsNamespace = evt.newValue);
subUnityAtomsNamespaceRow.Add(textfield);
root.Add(subUnityAtomsNamespaceRow);
root.Add(CreateDivider());
var typesToGenerateLabelRow = new VisualElement() { style = { flexDirection = FlexDirection.Row } };
typesToGenerateLabelRow.Add(new Label() { text = "Type(s) to Generate" });
root.Add(typesToGenerateLabelRow);
foreach (var atomType in AtomTypes.ALL_ATOM_TYPES)
{
_typeVEDict.Add(atomType, CreateAtomTypeToGenerateToggleRow(atomType));
root.Add(_typeVEDict[atomType]);
}
root.Add(CreateDivider());
_typesToGenerateInfoRow = new VisualElement() { style = { flexDirection = FlexDirection.Column } };
_typesToGenerateInfoRow.Add(new Label() { style = { color = Color.yellow, height = 12 } });
_typesToGenerateInfoRow.RegisterCallback((e) => { _typesToGenerateInfoRow.Query().First().text = ""; });
root.Add(_typesToGenerateInfoRow);
root.Add(CreateDivider());
var buttonRow = new VisualElement()
{
style = { flexDirection = FlexDirection.Row }
};
var button1 = new Button(Close)
{
text = "Close",
style = { flexGrow = 1 }
};
buttonRow.Add(button1);
var button2 = new Button(() =>
{
var templates = Generator.GetTemplatePaths();
var templateConditions = Generator.CreateTemplateConditions(_isValueTypeEquatable, _valueTypeNamespace, _subUnityAtomsNamespace, _valueType);
var templateVariables = Generator.CreateTemplateVariablesMap(_valueType, _valueTypeNamespace, _subUnityAtomsNamespace);
var capitalizedValueType = _valueType.Replace('.', '_').Capitalize();
_atomTypesToGenerate.ForEach((atomType) =>
{
templateVariables["VALUE_TYPE_NAME"] = atomType.IsValuePair ? $"{capitalizedValueType}Pair" : capitalizedValueType;
var valueType = atomType.IsValuePair ? $"{capitalizedValueType}Pair" : _valueType;
templateVariables["VALUE_TYPE"] = valueType;
Generator.Generate(new AtomReceipe(atomType, valueType), _baseWritePath, templates, templateConditions, templateVariables);
});
AssetDatabase.Refresh();
})
{
text = "Generate",
style = { flexGrow = 1 }
};
buttonRow.Add(button2);
root.Add(buttonRow);
}
///
/// Helper method to create a divider.
///
/// The divider (`VisualElement`) created.
private VisualElement CreateDivider()
{
return new VisualElement()
{
style = { flexDirection = FlexDirection.Row, marginBottom = 2, marginTop = 2, marginLeft = 2, marginRight = 2, height = 1 }
};
}
///
/// Helper to create toogle row for a specific `AtomType`.
///
/// The provided `AtomType`.
/// A new toggle row (`VisualElement`).
private VisualElement CreateAtomTypeToGenerateToggleRow(AtomType atomType)
{
var row = new VisualElement() { style = { flexDirection = FlexDirection.Row } };
row.Add(new Label() { text = atomType.DisplayName, style = { width = 220, marginRight = 8 } });
var toggle = new Toggle() { value = _atomTypesToGenerate.Contains(atomType) };
toggle.RegisterCallback>(evt =>
{
if (evt.newValue)
{
AddAtomTypeToGenerate(atomType);
}
else
{
var disabledDeps = RemoveAtomTypeToGenerate(atomType);
SetWarningText(atomType, disabledDeps);
}
});
row.Add(toggle);
return row;
}
}
}
#endif