Merge pull request #4 from taoria/working-in-process

Working in process
main
taoria 3 years ago committed by GitHub
commit e181648e94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Sample/Editor/HelloEditor.asset
  2. 2
      Sample/Editor/HelloEditor.asset.meta
  3. 22
      Sample/Editor/HelloEditor.cs
  4. 14
      Sample/Editor/HelloEditor.cs.meta
  5. 11
      Sample/Editor/HelloGraph.cs
  6. 2
      Sample/Editor/HelloGraph.cs.meta
  7. 9
      Sample/Editor/HelloGraphView.cs
  8. 5
      Sample/Editor/HelloGraphView.cs.meta
  9. 10
      Sample/Editor/HelloWorld.cs
  10. 4
      Sample/Editor/HelloWorldGraph.cs
  11. 23
      Sample/New HelloGraph.asset
  12. 8
      Sample/New HelloGraph.asset.meta
  13. 13
      TNode/Attribute/NodeAttribute.cs
  14. 3
      TNode/Attribute/NodeAttribute.cs.meta
  15. 127
      TNode/Editor/BaseViews/DataGraphView.cs
  16. 2
      TNode/Editor/BaseViews/NodeView.cs
  17. 4
      TNode/Editor/BaseViews/SimpleGraphSubWindow.cs
  18. 5
      TNode/Editor/Cache/NodeEditorExtensions.cs
  19. 29
      TNode/Editor/GraphEditor.cs
  20. 2
      TNode/Editor/GraphEditorData.cs
  21. 34
      TNode/Editor/Inspector/DefaultInspectorItemFactory.cs
  22. 3
      TNode/Editor/Inspector/DefaultInspectorItemFactory.cs.meta
  23. 9
      TNode/Editor/Inspector/INodeDataBinding.cs
  24. 8
      TNode/Editor/Inspector/INodeDataBindingBase.cs
  25. 3
      TNode/Editor/Inspector/INodeDataBindingBase.cs.meta
  26. 3
      TNode/Editor/Inspector/InspectorImplementation.meta
  27. 16
      TNode/Editor/Inspector/InspectorImplementation/DefaultInspectorItem.cs
  28. 3
      TNode/Editor/Inspector/InspectorImplementation/DefaultInspectorItem.cs.meta
  29. 38
      TNode/Editor/Inspector/InspectorItem.cs
  30. 16
      TNode/Editor/Inspector/MonoScriptInspector.cs
  31. 3
      TNode/Editor/Inspector/MonoScriptInspector.cs.meta
  32. 29
      TNode/Editor/Inspector/NodeInspector.cs
  33. 8
      TNode/Editor/Inspector/TinyInspector.cs
  34. 13
      TNode/Editor/Inspector/TinyInspectorItem.cs
  35. 0
      TNode/Editor/Inspector/TinyInspectorItem.cs.meta
  36. 3
      TNode/Editor/Resources/NodeInsepctor.uxml
  37. 10
      TNode/Editor/Resources/NodeInsepctor.uxml.meta
  38. 1
      TNode/Editor/Resources/ScriptTemplates/NewGraph.cs.txt
  39. 4
      TNode/Editor/Resources/ScriptTemplates/NewGraphEditor.cs.txt
  40. 9
      TNode/Editor/Resources/ScriptTemplates/NewGraphView.cs.txt
  41. 3
      TNode/Editor/Resources/ScriptTemplates/NewGraphView.cs.txt.meta
  42. 18
      TNode/Editor/SearchWindowProvider.cs
  43. 3
      TNode/Editor/SearchWindowProvider.cs.meta
  44. 26
      TNode/Editor/Tools/GraphEditorCreator/GraphEditorCreator.cs
  45. 2
      TNode/Editor/Tools/GraphEditorCreator/GraphEditorCreator.uxml
  46. 18
      TNode/Editor/Tools/GraphEditorCreator/SourceGeneratorForGraphEditor.cs
  47. 2
      TNode/Models/NodeLink.cs

@ -10,7 +10,7 @@ MonoBehaviour:
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: cde084f079a7426daa86ed86cb80ed1b, type: 3}
m_Name: HelloWorld
m_Name: HelloEditor
m_EditorClassIdentifier:
nodeData:
rid: -2

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: ad64ccb31efdc9c4082380856cd58efc
guid: 0ecaf7effd4cb5545b03d4f552942c80
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000

@ -0,0 +1,22 @@
using TNode.Editor;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
namespace Sample.Editor{
public class HelloEditor : GraphEditor<HelloGraph>{
[OnOpenAsset]
public static bool OnOpenAsset(int instanceID, int line){
var graph = EditorUtility.InstanceIDToObject(instanceID) as HelloGraph;
if (graph != null)
{
var wnd = GetWindow<HelloEditor>();
wnd.titleContent = new GUIContent("HelloGraph Editor");
wnd.CreateGUI();
wnd._graphView.Data = graph;
return true;
}
return false;
}
}
}

@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: a5c15a07ff247a247a73d6991b540e27
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- m_ViewDataDictionary: {instanceID: 0}
- mVisualTreeAsset: {fileID: 9197481963319205126, guid: b67f6dcbe2361b649ad2b7845207321b, type: 3}
- nodeEditorData: {fileID: 11400000, guid: 0ecaf7effd4cb5545b03d4f552942c80, type: 2}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,11 @@
using System;
using TNode.Models;
using UnityEngine;
namespace Sample.Editor{
[CreateAssetMenu(fileName = "New HelloGraph", menuName = "TNode/HelloGraph")]
[Serializable]
public class HelloGraph : GraphData{
}
}

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 8b641f4bc28454e4aa2c5ddc629b07c2
guid: 9eda9b79596ecc746bb59fa8939c6ac3
MonoImporter:
externalObjects: {}
serializedVersion: 2

@ -0,0 +1,9 @@
using TNode.Attribute;
using TNode.Editor.BaseViews;
namespace Sample.Editor{
[NodeComponent]
public class HelloGraphView : DataGraphView<HelloGraph>{
}
}

@ -1,10 +1,9 @@
fileFormatVersion: 2
guid: 7b39119946f2f83458e3c2bafb200552
guid: 8ec139b86ff8c10488c233a10e6106f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- nodeEditorData: {fileID: 11400000, guid: ad64ccb31efdc9c4082380856cd58efc, type: 2}
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

@ -1,10 +0,0 @@
using TNode.Editor;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;
public class HelloWorld : GraphEditor<HelloWorldGraph>{
}

@ -1,4 +0,0 @@
using TNode.Models;
public class HelloWorldGraph : GraphData{
}

@ -0,0 +1,23 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9eda9b79596ecc746bb59fa8939c6ac3, type: 3}
m_Name: New HelloGraph
m_EditorClassIdentifier:
nodes: []
nodeLinks: []
entryNode:
rid: -2
references:
version: 2
RefIds:
- rid: -2
type: {class: , ns: , asm: }

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: edfa4bd023c6a7641aec2257a5e1248e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,13 @@
using JetBrains.Annotations;
using TNode.Models;
namespace TNode.Attribute{
[MeansImplicitUse]
[BaseTypeRequired(typeof(NodeData))]
public class NodeAttribute:System.Attribute{
public NodeAttribute(GraphData graphData){
}
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2311dd22c61449b7aa44b37085623fc4
timeCreated: 1656298063

@ -1,13 +1,110 @@
using TNode.Cache;
using System;
using System.Collections.Generic;
using TNode.BaseViews;
using TNode.Cache;
using TNode.Models;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;
namespace TNode.BaseViews{
namespace TNode.Editor.BaseViews{
/*
public class DialogueGraphView : DataGraphView<DialogueGraph>{
public Action<DialogueNodeView> onNodeAdded;
public Action<DialogueNodeView> onNodeSelected;
public Action<DialogueNodeView> onNodeRemoved;
public Action<DialogueNodeView> onNodeUnselected;
// public DialogueGraphView(DialogueGraph graph):base(){
// this.Data = graph;
//
// //Set background to a bit of darker
//
//
// //Register a data context change callback
//
// }
public override void OnGraphViewCreate(){
AddNode(GenerateEntryPoint());
RegisterCallback<ContextualMenuPopulateEvent>(evt => {
var pos = evt.mousePosition;
evt.menu.AppendAction("Add NodeAttribute", (dropMenuAction) => {
DialogueNodeView nodeView = new DialogueNodeView{
GUID = Guid.NewGuid().ToString(),
title = "New NodeAttribute"
};
// make it a 200x100 box
nodeView.SetPosition(new Rect(pos.x - 100, pos.y - 50, 200, 100));
AddNode(nodeView);
}, DropdownMenuAction.AlwaysEnabled);
});
this.OnDataChanged += OnOnDataChanged;
}
private void OnOnDataChanged(object sender, DataChangedEventArgs<DialogueGraph> e){
//clean all nodes from the graphview
foreach (var graphViewNode in nodes){
RemoveElement(graphViewNode);
}
foreach (var edge in edges){
RemoveElement(edge);
}
//add all nodes from the new graph
foreach (var node in e.NewData.nodes){
//AddNode(node);
}
}
public void AddNode(DialogueNodeData dialogueNodeData){
var res = InstantiateFromDialogueNodeData(dialogueNodeData);
AddNode(res);
}
public void AddNode(DialogueNodeView nodeView){
AddElement(nodeView);
onNodeAdded?.Invoke(nodeView);
//Register nodeView selection callback
nodeView.RegisterCallback<MouseDownEvent>(evt => {
if (evt.clickCount == 1){
onNodeSelected?.Invoke(nodeView);
}
});
nodeView.OnUnselect += () => { onNodeUnselected?.Invoke(nodeView); };
}
public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter) => this.ports.ToList()
.Where(x => x != startPort &&
x.direction != startPort.direction).ToList();
public DialogueNodeView GenerateEntryPoint(){
var entryPoint = new DialogueNodeView{
title = "Entry Point",
GUID = Guid.NewGuid().ToString(),
EntryPoint = true
};
//Add output port to the nodeView
entryPoint.AddPort(Orientation.Horizontal, Direction.Output, "Next");
//Set nodeView position to top center side of screen
entryPoint.SetPosition(new Rect(this.layout.width / 2 - 100, 0, 200, 200));
return entryPoint;
}
protected DialogueNodeView InstantiateFromDialogueNodeData(DialogueNodeData dialogueNodeData){
var node = new DialogueNodeView();
node.title = dialogueNodeData.nodeName;
node.GUID = Guid.NewGuid().ToString();
//TODO:after completing the separation of the node data and the node editor data,this should be switch to the node editor data
//node.SetPosition(dialogueNodeData.rect);
this.AddNode(node);
return node;
}
}
*/
public abstract class DataGraphView<T>:GraphView where T:GraphData{
private T _data;
private SearchWindowProvider _searchWindowProvider;
public T Data{
get{ return _data; }
set{
@ -33,7 +130,7 @@ namespace TNode.BaseViews{
//Get the node type
var nodeType = dataNode.GetType();
//Get the derived type of Node View from the node type
//Get the derived type of NodeAttribute View from the node type
var nodeViewType = typeof(NodeView<>).MakeGenericType(nodeType);
//Fetch the node view from the node view type
@ -61,9 +158,23 @@ namespace TNode.BaseViews{
public event DataChangedEventHandler OnDataChanged;
public delegate void DataChangedEventHandler(object sender, DataChangedEventArgs<T> e);
private void ConstructDefaultBehaviour(){
//Register a right click context menu
//ConstructContextualMenuOption();
}
public void ConstructViewContextualMenu(EventCallback<ContextualMenuPopulateEvent> callback){
RegisterCallback<ContextualMenuPopulateEvent>(callback);
}
private void OnInit(){
ConstructDefaultBehaviour();
OnGraphViewCreate();
}
public virtual void OnGraphViewCreate(){
}
@ -73,6 +184,14 @@ namespace TNode.BaseViews{
~DataGraphView(){
OnGraphViewDestroy();
}
//rewrite function of the derived class in the comment on the top of this script file in this class
// public abstract override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter);
//
// public void AddNode(NodeData nodeData){
//
// }
}
public class DataChangedEventArgs<T>{

@ -4,7 +4,7 @@ using UnityEditor.Experimental.GraphView;
namespace TNode.BaseViews{
//A Node monitor some type of node in the graph
//A NodeAttribute monitor some type of node in the graph
public abstract class NodeView<T> : Node where T:NodeData,new(){
protected T _data;

@ -6,13 +6,13 @@ namespace TNode.BaseViews{
public class SimpleGraphSubWindow:GraphElement{
private readonly Dragger _dragger = new Dragger();
private void ConstructWindowBasicSetting(){
protected void ConstructWindowBasicSetting(){
RegisterCallback<WheelEvent>(evt => { evt.StopPropagation(); });
focusable = false;
capabilities |= Capabilities.Movable | Capabilities.Resizable;
this.AddManipulator(_dragger);
}
private void BuildWindow(VisualTreeAsset visualTreeAsset){
protected void BuildWindow(VisualTreeAsset visualTreeAsset){
if(visualTreeAsset != null){
visualTreeAsset.CloneTree(this);
}

@ -2,6 +2,7 @@
using System.Collections.Generic;
using TNode.Attribute;
using TNode.BaseViews;
using TNode.Editor.BaseViews;
using UnityEngine;
namespace TNode.Cache{
@ -45,5 +46,9 @@ namespace TNode.Cache{
var instance = Activator.CreateInstance(implementedType);
return instance;
}
public static bool HasSpecificType<T>() where T : class{
var implementedType = NodeEditorSingleton.Instance.FromGenericToSpecific[typeof(T)] as T;
return (T)implementedType!=null;
}
}
}

@ -1,9 +1,11 @@
using Codice.CM.Common;
using TNode.BaseViews;
using TNode.Cache;
using TNode.Editor.BaseViews;
using TNode.Editor.Model;
using TNode.Models;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UIElements;
@ -28,20 +30,35 @@ namespace TNode.Editor{
// Instantiate UXML
VisualElement labelFromUXML = mVisualTreeAsset.Instantiate();
root.Add(labelFromUXML);
BuildGraphView();
DefineGraphEditorActions();
OnCreate();
}
private void BuildGraphView(){
_graphView = NodeEditorExtensions.CreateInstance<DataGraphView<T>>();
rootVisualElement.Add(_graphView);
_graphView.StretchToParentSize();
_graphView.ConstructViewContextualMenu(evt => {
//Current issue is that the search window don't show up at the exact position of the mouse click by dma.eventInfo.mousePosition
//So I have to manually set the position of the search window to fit the mouse click position by add an offset driven by Editor's position
//Maybe a better way exists to fix this issue
Vector2 editorPosition = this.position.position;
evt.menu.AppendAction("Create Node", dma => {
var dmaPos = dma.eventInfo.mousePosition+editorPosition;
SearchWindowContext searchWindowContext = new SearchWindowContext(dmaPos,200,200);
SearchWindow.Open(searchWindowContext, ScriptableObject.CreateInstance<SearchWindowProvider>());
});
});
}
private void ConstructSearchWindow(){
//Register a search window
}
private void DefineGraphEditorActions(){

@ -4,7 +4,7 @@ using UnityEngine;
namespace TNode.Editor{
[CreateAssetMenu(fileName = "Node Editor Config", menuName = "TNode/Node Editor Config")]
[CreateAssetMenu(fileName = "NodeAttribute Editor Config", menuName = "TNode/NodeAttribute Editor Config")]
public class GraphEditorData:ScriptableObject{
public List<NodeEditorData> nodesData;

@ -0,0 +1,34 @@
using System;
using TNode.Cache;
using TNode.Editor.Inspector.InspectorImplementation;
using UnityEditor;
using UnityEngine.UIElements;
namespace TNode.Editor.Inspector{
public class DefaultInspectorItemFactory{
public InspectorItem<T> Create<T>(){
//Check type of T
var hasSpecificType = NodeEditorExtensions.HasSpecificType<InspectorItem<T>>();
if (hasSpecificType){
return NodeEditorExtensions.CreateInstance<InspectorItem<T>>();
}
else{
return DefaultInspectorItem<T>();
}
}
public static InspectorItem<T> DefaultInspectorItem<T>(){
DefaultInspectorItem<T> item = new DefaultInspectorItem<T>();
if (typeof(string) == typeof(T)){
item.foldOut.Add(new TextField(){
name = "StringTextField"
});
}
return item;
}
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 83b9e37f79cf4a18b265e3e22e7e3ced
timeCreated: 1656142463

@ -2,7 +2,7 @@
using UnityEngine;
namespace TNode.Editor.Inspector{
public interface INodeDataBinding<out T>{
public interface INodeDataBinding<out T>:INodeDataBindingBase{
protected T GetValue(){
var fieldInfo = typeof(T).GetField(BindingPath, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
@ -15,8 +15,11 @@ namespace TNode.Editor.Inspector{
}
return default;
}
public string BindingPath{ get; set; }
public NodeData BindingNodeData{ get; set; }
public T Value => GetValue();
public void OnBindingDataUpdate(){
}
}
}

@ -0,0 +1,8 @@
using TNode.Models;
namespace TNode.Editor.Inspector{
public interface INodeDataBindingBase{
public string BindingPath{ get; set; }
public NodeData BindingNodeData{ get; set; }
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2445523267fc49d3a17639a5c3ee47c7
timeCreated: 1656210915

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4cdebd0430794d32918ba8c63d71d0cc
timeCreated: 1656142311

@ -0,0 +1,16 @@
using UnityEngine.UIElements;
namespace TNode.Editor.Inspector.InspectorImplementation{
public class DefaultInspectorItem<T>:InspectorItem<T>{
public readonly Foldout foldOut;
public DefaultInspectorItem(){
foldOut = new Foldout{
text = ""
};
this.Add(foldOut);
OnValueChanged += () => {
foldOut.text = this.BindingPath;
};
}
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6b4f88e6c094449280ba5e38cb508287
timeCreated: 1656143219

@ -4,7 +4,41 @@ using UnityEngine.UIElements;
namespace TNode.Editor.Inspector{
public abstract class InspectorItem<T>:VisualElement,INodeDataBinding<T>{
public string BindingPath{ get; set; }
public NodeData BindingNodeData{ get; set; }
private NodeData _bindingNodeData;
private string _bindingFieldName;
protected event System.Action OnValueChanged;
public string BindingPath{
get => _bindingFieldName;
set{
_bindingFieldName = value;
if(_bindingFieldName!=null&&_bindingNodeData!=null){
OnValueChanged?.Invoke();
}
}
}
public NodeData BindingNodeData{
get => _bindingNodeData;
set{
_bindingNodeData = value;
if(_bindingFieldName!=null&&_bindingNodeData!=null){
OnValueChanged?.Invoke();
}
}
}
public InspectorItem(){
OnValueChanged+= OnValueChangedHandler;
}
private void OnValueChangedHandler(){
}
~InspectorItem(){
OnValueChanged-= OnValueChangedHandler;
}
}
}

@ -0,0 +1,16 @@
using UnityEditor;
using UnityEditor.AssetImporters;
using UnityEngine;
namespace TNode.Editor.Inspector{
// [CustomEditor(typeof(MonoImporter))]
// public class MonoScriptInspector:AssetImporterEditor{
// public override void OnInspectorGUI(){
// base.OnInspectorGUI();
// if(GUILayout.Button("Open")){
// EditorUtility.OpenWithDefaultApp(AssetDatabase.GetAssetPath(target));
// }
// }
// }
//
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 192a51f6578144c5bbddb5cf77685c71
timeCreated: 1656214219

@ -1,7 +1,10 @@
using TNode.BaseViews;
using System.Reflection;
using TNode.BaseViews;
using TNode.Models;
using UnityEngine;
using UnityEngine.UIElements;
namespace TNode.Editor.BaseViews{
namespace TNode.Editor.Inspector{
public class NodeInspector:SimpleGraphSubWindow{
private NodeData _data;
@ -18,8 +21,30 @@ namespace TNode.Editor.BaseViews{
RefreshInspector();
}
}
public NodeInspector(){
var visualTreeAsset = Resources.Load<VisualTreeAsset>("NodeInspector");
ConstructWindowBasicSetting();
BuildWindow(visualTreeAsset);
}
private void RefreshInspector(){
//iterate field of data and get name of every fields,create a new inspector item of appropriate type and add it to the inspector for each field
foreach (var field in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public)){
var bindingPath = field.Name;
var type = field.FieldType;
DefaultInspectorItemFactory defaultInspectorItemFactory = new DefaultInspectorItemFactory();
//Invoke generic function Create<> of default inspector item factory to create an inspector item of appropriate type by reflection
MethodInfo methodInfo = defaultInspectorItemFactory.GetType().GetMethod("Create", BindingFlags.Instance | BindingFlags.Public);
if (methodInfo != null){
var genericMethod = methodInfo.MakeGenericMethod(type);
var createdInspector = genericMethod.Invoke(defaultInspectorItemFactory,null) as VisualElement;
Add(createdInspector);
if (createdInspector is INodeDataBindingBase castedInspector){
castedInspector.BindingNodeData = _data;
castedInspector.BindingPath = bindingPath;
}
}
}
}

@ -1,8 +0,0 @@
namespace TNode.Editor.Inspector{
/// <summary>
/// Tiny Inspector item is a simple inspector inside a node view
/// </summary>
public class TinyInspector{
}
}

@ -0,0 +1,13 @@
using TNode.Models;
using UnityEngine.UIElements;
namespace TNode.Editor.Inspector{
/// <summary>
/// Tiny Inspector item is a simple inspector item inside a node view ,it monitor node data
///
/// </summary>
public class TinyInspectorItem<T>:VisualElement,INodeDataBinding<T>{
public string BindingPath{ get; set; }
public NodeData BindingNodeData{ get; set; }
}
}

@ -0,0 +1,3 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:VisualElement name="InspectorBody" style="height: 458px; background-color: rgba(36, 36, 36, 255);" />
</ui:UXML>

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 79c615f2df8f4cf45b71df7812d06674
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

@ -1,6 +1,7 @@
using TNode.Models;
using UnityEngine;
using UnityEditor;
using System;
[CreateAssetMenu(fileName = "New $GraphClassName$", menuName = "TNode/$GraphClassName$")]
[Serializable]
public class $GraphClassName$ : GraphData{

@ -4,14 +4,14 @@ using UnityEditor.Callbacks;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;
using System;
public class $EditorClassName$ : GraphEditor<$GraphClassName$>{
[OnOpenAsset]
public static bool OnOpenAsset(int instanceID, int line){
var graph = EditorUtility.InstanceIDToObject(instanceID) as $GraphClassName$;
if (graph != null)
{
$GraphClassName$ wnd = GetWindow<$EditorClassName$>();
var wnd = GetWindow<$EditorClassName$>();
wnd.titleContent = new GUIContent("$GraphClassName$ Editor");
wnd.CreateGUI();
wnd._graphView.Data = graph;

@ -0,0 +1,9 @@
using TNode.Models;
using TNode.Attribute;
using TNode.Editor.BaseViews;
[NodeComponent]
public class $GraphViewClassName$ : DataGraphView<$GraphClassName$>{
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bc741e48f31d4668bd3351eea8a5eaf1
timeCreated: 1656217566

@ -0,0 +1,18 @@
using System.Collections.Generic;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
namespace TNode.Editor{
public class SearchWindowProvider:ScriptableObject,ISearchWindowProvider{
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context){
var list = new List<SearchTreeEntry>();
list.Add(new SearchTreeGroupEntry(new GUIContent("Add New Node"), 0));
list.Add(new SearchTreeGroupEntry(new GUIContent("Add Placemat"), 0));
return list;
}
public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context){
return false;
}
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1daac5c2c1794f36933cdbc922840769
timeCreated: 1656314210

@ -59,6 +59,8 @@ namespace TNode.Editor.Tools.GraphEditorCreator{
_graphClassNameTextField.RegisterCallback<ChangeEvent<string>>((evt) => {
CheckIfTextValid();
});
CheckIfTextValid();
}
@ -107,6 +109,7 @@ namespace TNode.Editor.Tools.GraphEditorCreator{
//Query the name of the graph editor
string editorName =_editorClassNameTextField.text;
string graphName = _graphClassNameTextField.text;
string graphViewName = graphName+"View";
if (editorName == "")
{
editorName = "NewGraphEditor";
@ -117,35 +120,32 @@ namespace TNode.Editor.Tools.GraphEditorCreator{
var source = sourceGeneratorForGraphEditor.GenerateGraphEditor(editorName,graphName);
var sourceGraph = sourceGeneratorForGraphEditor.GenerateGraph(graphName);
var sourceGraphView = sourceGeneratorForGraphEditor.GenerateGraphView(graphViewName,graphName);
string editorPath = Path.Combine(path, editorName + ".cs");
string graphPath = Path.Combine(path, graphName + ".cs");
string graphViewPath = Path.Combine(path, graphViewName + ".cs");
File.WriteAllText(editorPath, source);
File.WriteAllText(graphPath, sourceGraph);
File.WriteAllText(graphViewPath, sourceGraphView);
//Refresh the AssetDatabase to import the new file
AssetDatabase.Refresh();
//Wait for the new file to be imported
while (!AssetDatabase.LoadAssetAtPath<MonoScript>(editorPath))
{
EditorUtility.DisplayProgressBar("Generating Graph Editor", "Please wait while the new graph editor is being imported", 0.5f);
EditorApplication.update();
}
//Create an Node Editor Data Instance for the new graph editor
//Create an NodeAttribute Editor Data Instance for the new graph editor
NodeEditorData nodeEditorData = ScriptableObject.CreateInstance<NodeEditorData>();
nodeEditorData.name = editorName;
EditorUtility.SetDirty(nodeEditorData);
//Save it at the same folder as the new graph editor
string nodeEditorDataPath = Path.Combine(path, editorName + ".asset");
AssetDatabase.CreateAsset(nodeEditorData, nodeEditorDataPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
//Wait for the new file to be imported
while (!AssetDatabase.LoadAssetAtPath<NodeEditorData>(nodeEditorDataPath))
{
@ -153,18 +153,12 @@ namespace TNode.Editor.Tools.GraphEditorCreator{
EditorApplication.update();
}
var script = AssetDatabase.LoadAssetAtPath<MonoScript>(editorPath);
//Set the mono importer to the current graph editor script
MonoImporter monoImporter = AssetImporter.GetAtPath(editorPath) as MonoImporter;
if (monoImporter != null)
monoImporter.SetDefaultReferences(new string[]{"nodeEditorData"}, new Object[]{nodeEditorData});
//Refresh the asset ann close it
//Mark it dirty

@ -6,7 +6,7 @@
<ui:Label tabindex="-1" text=".cs" display-tooltip-when-elided="true" style="-unity-text-align: middle-left;" />
</ui:VisualElement>
<ui:VisualElement name="GraphName" style="flex-direction: row;">
<ui:TextField picking-mode="Ignore" label="Your Editor Class Name" value="filler text" text="filler text" name="GraphClassNameTextField" style="width: 306px;" />
<ui:TextField picking-mode="Ignore" label="Your Graph Class Name" value="filler text" text="filler text" name="GraphClassNameTextField" style="width: 306px;" />
<ui:Label tabindex="-1" text=".cs" display-tooltip-when-elided="true" style="-unity-text-align: middle-left;" />
</ui:VisualElement>
<ui:Button tabindex="-1" text="Create Editor" display-tooltip-when-elided="true" name="CreateButton" />

@ -22,7 +22,9 @@ namespace TNode.Editor.Tools.GraphEditorCreator{
}
var source = template.text.Replace("$EditorClassName$",editorClassName).Replace("$GraphClassName$",graphClassName);
return source;
}
}
//what's the shortcut to navigate the files
public string GenerateGraph(string graphClassName,string templateName="NewGraph.cs"){
TextAsset template = Resources.Load<TextAsset>("ScriptTemplates/"+templateName);
//Check if graph class name is valid
@ -33,5 +35,19 @@ namespace TNode.Editor.Tools.GraphEditorCreator{
var source = template.text.Replace("$GraphClassName$",graphClassName);
return source;
}
public string GenerateGraphView(string graphViewClassName,string graphClassName,string templateName="NewGraphView.cs"){
TextAsset template = Resources.Load<TextAsset>("ScriptTemplates/"+templateName);
//Check if graph class name is valid
var regex = new System.Text.RegularExpressions.Regex("^[a-zA-Z0-9_]+$");
if(!Regex.IsMatch(graphClassName)){
Debug.LogError("The graph class name is invalid. It must be a valid C# identifier.");
}
if(!Regex.IsMatch(graphViewClassName)){
Debug.LogError("The graph view name is invalid. It must be a valid C# identifier.");
}
var source = template.text.Replace("$GraphClassName$",graphClassName).Replace("$GraphViewClassName$",graphViewClassName);
return source;
}
}
}

@ -2,7 +2,7 @@
using Dialogue;
namespace TNode.Models{
//Node links are stored in output side of the two node port.
//NodeAttribute links are stored in output side of the two node port.
[Serializable]
public class NodeLink{
// public DialogueNodePortData From{ get; }

Loading…
Cancel
Save