[TASK] Initial commit with basic product setup

This commit is contained in:
2019-08-18 13:50:14 +02:00
commit 01a66a8e1f
2548 changed files with 167528 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
using System;
using UnityEditor;
using UnityEngine;
namespace Mapbox.Editor.NodeEditor
{
public class Connection
{
public ConnectionPoint inPoint;
public ConnectionPoint outPoint;
public Action<Connection> OnClickRemoveConnection;
private Vector2 _outVector;
public Connection(ConnectionPoint inPoint, ConnectionPoint outPoint)
{
this.inPoint = inPoint;
this.outPoint = outPoint;
}
public void Draw()
{
_outVector = new Vector2(outPoint.node.rect.xMax, outPoint.rect.center.y);
Handles.DrawBezier(
inPoint.left,
_outVector,
inPoint.left + Vector2.left * 50f,
outPoint.rect.center - Vector2.left * 50f,
outPoint.isActive ? Color.white : Color.gray,
null,
2f
);
//if (Handles.Button((inPoint.rect.center + outPoint.rect.center) * 0.5f, Quaternion.identity, 4, 8, Handles.RectangleCap))
//{
//}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8d8dac7dcfe2eb94e89cf9a897eadf22
timeCreated: 1501854762
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,164 @@
using System;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using Mapbox.Unity.Map;
namespace Mapbox.Editor.NodeEditor
{
public enum ConnectionPointType { In, Out }
public class ConnectionPoint
{
public Vector2 left;
public Vector2 right;
public Rect rect;
public Rect labelRect;
public Rect inLabelRect;
public Rect toggleRect;
public ConnectionPointType type;
public Node node;
public GUIStyle style;
private VectorSubLayerProperties _activeProp;
public bool isActive;
private string _outLabel;
private string _inLabel;
public string inLabel
{
get { return _inLabel; }
set
{
if (_inLabel != value)
labelGui = new GUIContent(value.ToString());
_inLabel = value;
}
}
private GUIContent labelGui;
private float _deltaY;
private GUIStyle _labelStyle = new GUIStyle()
{
fontSize = 10,
normal = new GUIStyleState() { textColor = Color.white },
alignment = TextAnchor.MiddleRight
};
private GUIStyle _inLabelStyle = new GUIStyle()
{
fontSize = 10,
normal = new GUIStyleState() { textColor = Color.white },
alignment = TextAnchor.MiddleRight
};
private static Texture2D activeOutImage;
private static Texture2D inactiveOutImage;
public ConnectionPoint(Node node, string inname, string name, float deltay, ConnectionPointType type, GUIStyle style, VectorSubLayerProperties activeProp = null)
{
isActive = true;
if (activeOutImage == null)
{
activeOutImage = EditorGUIUtility.Load("builtin skins/darkskin/images/node3.png") as Texture2D;
inactiveOutImage = EditorGUIUtility.Load("builtin skins/darkskin/images/node6.png") as Texture2D;
}
if (!string.IsNullOrEmpty(name))
{
this._outLabel = Regex.Replace(name, "(\\B[A-Z])", " $1");
}
else
{
this._outLabel = "";
}
inLabel = inname;
this.node = node;
this.type = type;
this.style = style;
_deltaY = deltay;
rect = new Rect(0, 0, 10f + (string.IsNullOrEmpty(inLabel) ? 0 : 100), 20f);
left = new Vector2(rect.x, rect.y + (rect.height / 2));
labelRect = new Rect(node.rect.xMin, node.rect.y + _deltaY - 15f, node.rect.width - 20, 25);
inLabelRect = new Rect(rect.x + 4, rect.y - 1, rect.width, rect.height);
_activeProp = activeProp;
}
public void Draw()
{
if (_activeProp != null)
isActive = _activeProp.coreOptions.isActive;
rect.y = node.rect.y + _deltaY - rect.height * 0.5f;
labelRect.x = node.rect.xMin + (isActive ? -20 : 0);
labelRect.y = node.rect.y + _deltaY - 15f;
labelRect.width = node.rect.width - 20;
inLabelRect.x = rect.x + 4;
inLabelRect.y = rect.y - 1;
toggleRect.x = node.rect.xMin - 30 + node.rect.width;
toggleRect.width = 20;
toggleRect.y = labelRect.y + 5;
toggleRect.height = 20;
switch (type)
{
case ConnectionPointType.In:
rect.x = node.rect.x - rect.width + 8f;
break;
case ConnectionPointType.Out:
rect.x = node.rect.x + node.rect.width - 8f;
break;
}
if (!string.IsNullOrEmpty(_outLabel))
{
GUI.Label(labelRect, _outLabel, _labelStyle);
}
if (!string.IsNullOrEmpty(inLabel))
{
var v = _inLabelStyle.CalcSize(labelGui);
inLabelRect.x = node.rect.x - v.x - 13;
inLabelRect.width = v.x + 13;
rect.x = node.rect.x - v.x - 5;
rect.width = v.x + 15;
}
left.x = rect.x;
left.y = rect.y + (rect.height / 2);
if (_activeProp != null)
{
rect.x -= 30;
rect.width = 45;
rect.y -= 1;
rect.height = 21;
if (_activeProp.coreOptions.isActive)
{
GUI.DrawTexture(rect, activeOutImage);
}
else
{
GUI.DrawTexture(rect, inactiveOutImage);
}
}
else
{
if (GUI.Button(rect, "", style))
{
}
}
if (_activeProp != null)
{
_activeProp.coreOptions.isActive = EditorGUI.Toggle(toggleRect, _activeProp.coreOptions.isActive);
//_activeProp.serializedObject.ApplyModifiedProperties();
}
GUI.Label(inLabelRect, inLabel, _inLabelStyle);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 667c708eac26a1c4aa960535705ebab3
timeCreated: 1501854778
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,434 @@
//https://github.com/Seneral/Node_Editor_Framework
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Reflection;
namespace Mapbox.Editor.NodeEditor
{
public static class GUIScaleUtility
{
// General
private static bool compabilityMode;
private static bool initiated;
// cache the reflected methods
private static FieldInfo currentGUILayoutCache;
private static FieldInfo currentTopLevelGroup;
// Delegates to the reflected methods
private static Func<Rect> GetTopRectDelegate;
private static Func<Rect> topmostRectDelegate;
// Delegate accessors
public static Rect getTopRect
{
get { return (Rect) GetTopRectDelegate.Invoke(); }
}
public static Rect getTopRectScreenSpace
{
get { return (Rect) topmostRectDelegate.Invoke(); }
}
// Rect stack for manipulating groups
public static List<Rect> currentRectStack { get; private set; }
private static List<List<Rect>> rectStackGroups;
// Matrices stack
private static List<Matrix4x4> GUIMatrices;
private static List<bool> adjustedGUILayout;
#region Init
public static void CheckInit()
{
if (!initiated)
Init();
}
public static void Init()
{
// As we can call Begin/Ends inside another, we need to save their states hierarchial in Lists (not Stack, as we need to iterate over them!):
currentRectStack = new List<Rect>();
rectStackGroups = new List<List<Rect>>();
GUIMatrices = new List<Matrix4x4>();
adjustedGUILayout = new List<bool>();
// Fetch rect acessors using Reflection
Assembly UnityEngine = Assembly.GetAssembly(typeof(UnityEngine.GUI));
Type GUIClipType = UnityEngine.GetType("UnityEngine.GUIClip", true);
PropertyInfo topmostRect = GUIClipType.GetProperty("topmostRect", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
MethodInfo GetTopmostRect = topmostRect != null ? (topmostRect.GetGetMethod(false) ?? topmostRect.GetGetMethod(true)) : null;
MethodInfo GetTopRect = GUIClipType.GetMethod("GetTopRect", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
MethodInfo ClipRect = GUIClipType.GetMethod("Clip", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] {typeof(Rect)}, new ParameterModifier[] { });
if (GUIClipType == null || topmostRect == null || GetTopRect == null || ClipRect == null)
{
Debug.LogWarning("GUIScaleUtility cannot run on this system! Compability mode enabled. For you that means you're not able to use the Node Editor inside more than one group:( Please PM me (Seneral @UnityForums) so I can figure out what causes this! Thanks!");
Debug.LogWarning((GUIClipType == null ? "GUIClipType is Null, " : "") + (topmostRect == null ? "topmostRect is Null, " : "") + (GetTopRect == null ? "GetTopRect is Null, " : "") + (ClipRect == null ? "ClipRect is Null, " : ""));
compabilityMode = true;
initiated = true;
return;
}
// Create simple acessor delegates
GetTopRectDelegate = (Func<Rect>) Delegate.CreateDelegate(typeof(Func<Rect>), GetTopRect);
topmostRectDelegate = (Func<Rect>) Delegate.CreateDelegate(typeof(Func<Rect>), GetTopmostRect);
if (GetTopRectDelegate == null || topmostRectDelegate == null)
{
Debug.LogWarning("GUIScaleUtility cannot run on this system! Compability mode enabled. For you that means you're not able to use the Node Editor inside more than one group:( Please PM me (Seneral @UnityForums) so I can figure out what causes this! Thanks!");
Debug.LogWarning((GUIClipType == null ? "GUIClipType is Null, " : "") + (topmostRect == null ? "topmostRect is Null, " : "") + (GetTopRect == null ? "GetTopRect is Null, " : "") + (ClipRect == null ? "ClipRect is Null, " : ""));
compabilityMode = true;
initiated = true;
return;
}
// Sometimes, strange errors pop up (related to Mac?), which we try to catch and enable a compability Mode no supporting zooming in groups
/*try
{
topmostRectDelegate.Invoke ();
}
catch (Exception e)
{
Debug.LogWarning ("GUIScaleUtility cannot run on this system! Compability mode enabled. For you that means you're not able to use the Node Editor inside more than one group:( Please PM me (Seneral @UnityForums) so I can figure out what causes this! Thanks!");
Debug.Log (e.Message);
compabilityMode = true;
}*/
initiated = true;
}
#endregion
#region Scale Area
public static Vector2 getCurrentScale
{
get { return new Vector2(1 / GUI.matrix.GetColumn(0).magnitude, 1 / GUI.matrix.GetColumn(1).magnitude); }
}
/// <summary>
/// Begins a scaled local area.
/// Returns vector to offset GUI controls with to account for zooming to the pivot.
/// Using adjustGUILayout does that automatically for GUILayout rects. Theoretically can be nested!
/// </summary>
public static Vector2 BeginScale(ref Rect rect, Vector2 zoomPivot, float zoom, bool adjustGUILayout)
{
Rect screenRect;
if (compabilityMode)
{
// In compability mode, we will assume only one top group and do everything manually, not using reflected calls (-> practically blind)
GUI.EndGroup();
screenRect = rect;
#if UNITY_EDITOR
if (!Application.isPlaying)
screenRect.y += 23;
#endif
}
else
{
// If it's supported, we take the completely generic way using reflected calls
GUIScaleUtility.BeginNoClip();
screenRect = GUIScaleUtility.GUIToScaledSpace(rect);
}
rect = Scale(screenRect, screenRect.position + zoomPivot, new Vector2(zoom, zoom));
// Now continue drawing using the new clipping group
GUI.BeginGroup(rect);
rect.position = Vector2.zero; // Adjust because we entered the new group
// Because I currently found no way to actually scale to a custom pivot rather than (0, 0),
// we'll make use of a cheat and just offset it accordingly to let it appear as if it would scroll to the center
// Note, due to that, controls not adjusted are still scaled to (0, 0)
Vector2 zoomPosAdjust = rect.center - screenRect.size / 2 + zoomPivot;
// For GUILayout, we can make this adjustment here if desired
adjustedGUILayout.Add(adjustGUILayout);
if (adjustGUILayout)
{
GUILayout.BeginHorizontal();
GUILayout.Space(rect.center.x - screenRect.size.x + zoomPivot.x);
GUILayout.BeginVertical();
GUILayout.Space(rect.center.y - screenRect.size.y + zoomPivot.y);
}
// Take a matrix backup to restore back later on
GUIMatrices.Add(GUI.matrix);
// Scale GUI.matrix. After that we have the correct clipping group again.
GUIUtility.ScaleAroundPivot(new Vector2(1 / zoom, 1 / zoom), zoomPosAdjust);
return zoomPosAdjust;
}
/// <summary>
/// Ends a scale region previously opened with BeginScale
/// </summary>
public static void EndScale()
{
// Set last matrix and clipping group
if (GUIMatrices.Count == 0 || adjustedGUILayout.Count == 0)
throw new UnityException("GUIScaleUtility: You are ending more scale regions than you are beginning!");
GUI.matrix = GUIMatrices[GUIMatrices.Count - 1];
GUIMatrices.RemoveAt(GUIMatrices.Count - 1);
// End GUILayout zoomPosAdjustment
if (adjustedGUILayout[adjustedGUILayout.Count - 1])
{
GUILayout.EndVertical();
GUILayout.EndHorizontal();
}
adjustedGUILayout.RemoveAt(adjustedGUILayout.Count - 1);
// End the scaled group
GUI.EndGroup();
if (compabilityMode)
{
// In compability mode, we don't know the previous group rect, but as we cannot use top groups there either way, we restore the screen group
if (!Application.isPlaying) // We're in an editor window
GUI.BeginClip(new Rect(0, 23, Screen.width, Screen.height - 23));
else
GUI.BeginClip(new Rect(0, 0, Screen.width, Screen.height));
}
else
{
// Else, restore the clips (groups)
GUIScaleUtility.RestoreClips();
}
}
#endregion
#region Clips Hierarchy
/// <summary>
/// Begins a field without groups. They should be restored using RestoreClips. Can be nested!
/// </summary>
public static void BeginNoClip()
{
// Record and close all clips one by one, from bottom to top, until we hit the 'origin'
List<Rect> rectStackGroup = new List<Rect>();
Rect topMostClip = getTopRect;
while (topMostClip != new Rect(-10000, -10000, 40000, 40000))
{
rectStackGroup.Add(topMostClip);
GUI.EndClip();
topMostClip = getTopRect;
}
// Store the clips appropriately
rectStackGroup.Reverse();
rectStackGroups.Add(rectStackGroup);
currentRectStack.AddRange(rectStackGroup);
}
/// <summary>
/// Begins a field without the last count groups. They should be restored using RestoreClips. Can be nested!
/// </summary>
public static void MoveClipsUp(int count)
{
// Record and close all clips one by one, from bottom to top, until reached the count or hit the 'origin'
List<Rect> rectStackGroup = new List<Rect>();
Rect topMostClip = getTopRect;
while (topMostClip != new Rect(-10000, -10000, 40000, 40000) && count > 0)
{
rectStackGroup.Add(topMostClip);
GUI.EndClip();
topMostClip = getTopRect;
count--;
}
// Store the clips appropriately
rectStackGroup.Reverse();
rectStackGroups.Add(rectStackGroup);
currentRectStack.AddRange(rectStackGroup);
}
/// <summary>
/// Restores the clips removed in BeginNoClip or MoveClipsUp
/// </summary>
public static void RestoreClips()
{
if (rectStackGroups.Count == 0)
{
Debug.LogError("GUIClipHierarchy: BeginNoClip/MoveClipsUp - RestoreClips count not balanced!");
return;
}
// Read and restore clips one by one, from top to bottom
List<Rect> rectStackGroup = rectStackGroups[rectStackGroups.Count - 1];
for (int clipCnt = 0; clipCnt < rectStackGroup.Count; clipCnt++)
{
GUI.BeginClip(rectStackGroup[clipCnt]);
currentRectStack.RemoveAt(currentRectStack.Count - 1);
}
rectStackGroups.RemoveAt(rectStackGroups.Count - 1);
}
#endregion
#region Layout & Matrix Ignores
/// <summary>
/// Ignores the current GUILayout cache and begins a new one. Cannot be nested!
/// </summary>
public static void BeginNewLayout()
{
if (compabilityMode)
return;
// Will mimic a new layout by creating a new group at (0, 0). Will be restored though after ending the new Layout
Rect topMostClip = getTopRect;
if (topMostClip != new Rect(-10000, -10000, 40000, 40000))
GUILayout.BeginArea(new Rect(0, 0, topMostClip.width, topMostClip.height));
else
GUILayout.BeginArea(new Rect(0, 0, Screen.width, Screen.height));
}
/// <summary>
/// Ends the last GUILayout cache
/// </summary>
public static void EndNewLayout()
{
if (!compabilityMode)
GUILayout.EndArea();
}
/// <summary>
/// Begins an area without GUIMatrix transformations. Can be nested!
/// </summary>
public static void BeginIgnoreMatrix()
{
// Store and clean current matrix
GUIMatrices.Add(GUI.matrix);
GUI.matrix = Matrix4x4.identity;
}
/// <summary>
/// Restores last matrix ignored with BeginIgnoreMatrix
/// </summary>
public static void EndIgnoreMatrix()
{
if (GUIMatrices.Count == 0)
throw new UnityException("GUIScaleutility: You are ending more ignoreMatrices than you are beginning!");
// Read and assign previous matrix
GUI.matrix = GUIMatrices[GUIMatrices.Count - 1];
GUIMatrices.RemoveAt(GUIMatrices.Count - 1);
}
#endregion
#region Space Transformations
/// <summary>
/// Scales the position around the pivot with scale
/// </summary>
public static Vector2 Scale(Vector2 pos, Vector2 pivot, Vector2 scale)
{
return Vector2.Scale(pos - pivot, scale) + pivot;
}
/// <summary>
/// Scales the rect around the pivot with scale
/// </summary>
public static Rect Scale(Rect rect, Vector2 pivot, Vector2 scale)
{
rect.position = Vector2.Scale(rect.position - pivot, scale) + pivot;
rect.size = Vector2.Scale(rect.size, scale);
return rect;
}
/// <summary>
/// Transforms the position from the space aquired with BeginNoClip or MoveClipsUp to it's previous space
/// </summary>
public static Vector2 ScaledToGUISpace(Vector2 scaledPosition)
{
if (rectStackGroups == null || rectStackGroups.Count == 0)
return scaledPosition;
// Iterate through the clips and substract positions
List<Rect> rectStackGroup = rectStackGroups[rectStackGroups.Count - 1];
for (int clipCnt = 0; clipCnt < rectStackGroup.Count; clipCnt++)
scaledPosition -= rectStackGroup[clipCnt].position;
return scaledPosition;
}
/// <summary>
/// Transforms the rect from the space aquired with BeginNoClip or MoveClipsUp to it's previous space.
/// DOES NOT scale the rect, only offsets it!
/// </summary>
public static Rect ScaledToGUISpace(Rect scaledRect)
{
if (rectStackGroups == null || rectStackGroups.Count == 0)
return scaledRect;
scaledRect.position = ScaledToGUISpace(scaledRect.position);
return scaledRect;
}
/// <summary>
/// Transforms the position to the new space aquired with BeginNoClip or MoveClipsUp
/// It's way faster to call GUIToScreenSpace before modifying the space though!
/// </summary>
public static Vector2 GUIToScaledSpace(Vector2 guiPosition)
{
if (rectStackGroups == null || rectStackGroups.Count == 0)
return guiPosition;
// Iterate through the clips and add positions ontop
List<Rect> rectStackGroup = rectStackGroups[rectStackGroups.Count - 1];
for (int clipCnt = 0; clipCnt < rectStackGroup.Count; clipCnt++)
guiPosition += rectStackGroup[clipCnt].position;
return guiPosition;
}
/// <summary>
/// Transforms the rect to the new space aquired with BeginNoClip or MoveClipsUp.
/// DOES NOT scale the rect, only offsets it!
/// It's way faster to call GUIToScreenSpace before modifying the space though!
/// </summary>
public static Rect GUIToScaledSpace(Rect guiRect)
{
if (rectStackGroups == null || rectStackGroups.Count == 0)
return guiRect;
guiRect.position = GUIToScaledSpace(guiRect.position);
return guiRect;
}
/// <summary>
/// Transforms the position to screen space.
/// You can use GUIToScaledSpace when you want to transform an old rect to the new space aquired with BeginNoClip or MoveClipsUp (slower, try to call this function before any of these two)!
/// ATTENTION: This does not work well when any of the top groups is negative, means extends to the top or left of the screen. You may consider to use GUIToScaledSpace then, if possible!
/// </summary>
public static Vector2 GUIToScreenSpace(Vector2 guiPosition)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
return guiPosition + getTopRectScreenSpace.position - new Vector2(0, 22);
#endif
return guiPosition + getTopRectScreenSpace.position;
}
/// <summary>
/// Transforms the rect to screen space.
/// You can use GUIToScaledSpace when you want to transform an old rect to the new space aquired with BeginNoClip or MoveClipsUp (slower, try to call this function before any of these two)!
/// ATTENTION: This does not work well when any of the top groups is negative, means extends to the top or left of the screen. You may consider to use GUIToScaledSpace then, if possible!
/// </summary>
public static Rect GUIToScreenSpace(Rect guiRect)
{
guiRect.position += getTopRectScreenSpace.position;
#if UNITY_EDITOR
if (!Application.isPlaying)
guiRect.y -= 22;
#endif
return guiRect;
}
#endregion
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0569e7bedb842a84489760d9f273f442
timeCreated: 1502064204
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,481 @@
using System;
using UnityEditor;
using UnityEngine;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Reflection;
using System.Collections;
using Mapbox.Unity.MeshGeneration.Modifiers;
using System.Linq;
using Mapbox.Unity.MeshGeneration.Interfaces;
using Mapbox.Unity.Map;
using Mapbox.Unity.Utilities;
namespace Mapbox.Editor.NodeEditor
{
public class Node
{
private bool _expanded = true;
private bool _isRoot = false;
private Vector2 _panDelta;
//private Vector2 _topLeft = new Vector2(50, 50);
private Vector2 _padding = new Vector2(50, 100);
private float _propTopTest = 0f;
public List<Connection> Connections;
public List<ConnectionPoint> ConnectionPoints;
public List<Node> Children;
public object ScriptableObject;
public Rect spaceRect;
public Rect rect;
public Rect buttonRect;
public string title;
public string subtitle;
public bool isDragged;
public bool isSelected;
public ConnectionPoint inPoint;
public Action<Node> OnRemoveNode;
private GUIStyle _titleStyle = new GUIStyle()
{
fontSize = 14,
fontStyle = FontStyle.Bold,
normal = new GUIStyleState() { textColor = Color.white }
};
private GUIStyle _subtitleStyle = new GUIStyle()
{
fontSize = 10,
fontStyle = FontStyle.Italic,
normal = new GUIStyleState() { textColor = Color.white }
};
private float _headerHeight = 70;
private float _propertyHeight = 25;
private int _propCount = 0;
private float _inbuff;
//Vector2 position, float width, float height
public Node(object so = null)
{
_propTopTest = 0f;
_propCount = 0;
Children = new List<Node>();
Connections = new List<Connection>();
ConnectionPoints = new List<ConnectionPoint>();
ScriptableObject = so;
if (ScriptableObject != null)
{
if (ScriptableObject is ModifierBase)
{
title = Regex.Replace(((ModifierBase)ScriptableObject).name, "(\\B[A-Z])", " $1");
subtitle = Regex.Replace(ScriptableObject.GetType().Name, "(\\B[A-Z])", " $1");
}
else
{
//title = Regex.Replace(ScriptableObject., "(\\B[A-Z])", " $1");
title = Regex.Replace(ScriptableObject.GetType().Name, "(\\B[A-Z])", " $1");
}
}
var inlabel = "";
if (ScriptableObject is VectorSubLayerProperties)
inlabel = (ScriptableObject as VectorSubLayerProperties).coreOptions.sublayerName;
if (ScriptableObject is PrefabItemOptions)
inlabel = (ScriptableObject as PrefabItemOptions).coreOptions.sublayerName;
inPoint = new ConnectionPoint(this, inlabel, "", 20, ConnectionPointType.In, NodeBasedEditor.inPointStyle);
}
public float Draw(Vector2 position, float width, float height)
{
if (!string.IsNullOrEmpty(title))
width = title.Length * 10;
var boxHeight = _headerHeight + _propCount * _propertyHeight;
if (ScriptableObject is ModifierBase)
boxHeight = 52;
_inbuff = (string.IsNullOrEmpty(inPoint.inLabel) ? 0 : 100);
spaceRect = new Rect(position.x + _inbuff, position.y, width, boxHeight);
rect = new Rect(position.x + _inbuff, position.y, width, boxHeight);
buttonRect = new Rect(rect.xMax - 25, rect.yMin + 10, 20, 20);
_propTopTest = 0;
if (_expanded)
{
foreach (var c in Children)
{
var h = c.Draw(new Vector2(spaceRect.xMax + _padding.x, spaceRect.yMin + _propTopTest), 100, 0);
_propTopTest += h;
spaceRect.height += h;
}
}
var so = ScriptableObject as VectorSubLayerProperties;
if (so != null)
{
inPoint.inLabel = so.coreOptions.sublayerName;
inPoint.Draw();
}
else
{
if (!_isRoot)
inPoint.Draw();
}
var prefabItemObj = ScriptableObject as PrefabItemOptions;
if (prefabItemObj != null)
{
inPoint.inLabel = prefabItemObj.coreOptions.sublayerName;
inPoint.Draw();
}
else
{
if (!_isRoot)
inPoint.Draw();
}
spaceRect.height = Math.Max(height, Math.Max(spaceRect.height, boxHeight));
if (Children.Count > 0)
{
spaceRect.height -= Math.Min(_propTopTest, boxHeight);
}
if (isSelected)
{
GUILayout.BeginArea(rect, NodeBasedEditor.selectedNodeStyle);
}
else
{
if (ScriptableObject is ModifierBase)
GUILayout.BeginArea(rect, NodeBasedEditor.leafNodeStyle);
else
GUILayout.BeginArea(rect, NodeBasedEditor.nodeStyle);
}
GUILayout.Label(title, _titleStyle);
GUILayout.Label(subtitle, _subtitleStyle);
GUILayout.EndArea();
foreach (var p in ConnectionPoints)
{
p.Draw();
}
DrawConnections();
if (Children.Count > 0)
{
if (_expanded)
{
if (GUI.Button(buttonRect, "", (GUIStyle)"flow overlay foldout"))
{
_expanded = !_expanded;
}
}
else
{
if (GUI.Button(buttonRect, "", (GUIStyle)"IN FoldoutStatic"))
{
_expanded = !_expanded;
}
}
}
return spaceRect.height;
}
public bool ProcessEvents(Event e)
{
switch (e.type)
{
case EventType.MouseDown:
if (e.button == 0)
{
if (rect.Contains(e.mousePosition))
{
if (!isDragged)
{
if (ScriptableObject is ModifierBase)
{
Selection.objects = new UnityEngine.Object[1] { (ModifierBase)ScriptableObject };
}
if (ScriptableObject is AbstractMap)
{
Selection.objects = new UnityEngine.Object[1] { ((AbstractMap)ScriptableObject).gameObject };
}
}
isDragged = true;
GUI.changed = true;
isSelected = true;
//nodeStyle = selectedNodeStyle;
}
else
{
GUI.changed = true;
isSelected = false;
//nodeStyle = defaultNodeStyle;
}
}
if (e.button == 1 && isSelected && rect.Contains(e.mousePosition))
{
ProcessContextMenu();
e.Use();
}
break;
case EventType.MouseUp:
isDragged = false;
break;
//case EventType.MouseDrag:
// if (e.button == 0 && isDragged)
// {
// rect.position += e.delta;
// e.Use();
// return true;
// }
// break;
}
return false;
}
private void ProcessContextMenu()
{
//GenericMenu genericMenu = new GenericMenu();
//genericMenu.AddItem(new GUIContent("Remove node"), false, OnClickRemoveNode);
//genericMenu.ShowAsContext();
}
private void OnClickRemoveNode()
{
if (OnRemoveNode != null)
{
OnRemoveNode(this);
}
}
private void DrawConnections()
{
if (Connections != null)
{
for (int i = 0; i < Connections.Count; i++)
{
Connections[i].Draw();
}
}
}
public void Dive(object obj, bool showModifiers = true, int depth = 0)
{
if (obj == null)
return;
_isRoot = depth == 0;
if (ScriptableObject is ModifierStackBase)
_expanded = showModifiers;
foreach (FieldInfo fi in obj.GetType().GetFields().Where(prop => prop.IsDefined(typeof(NodeEditorElementAttribute), false)))
{
//field SO
#if ENABLE_WINMD_SUPPORT
if (typeof(ILayer).GetTypeInfo().IsAssignableFrom(fi.FieldType.GetTypeInfo()))
#else
if (typeof(ILayer).IsAssignableFrom(fi.FieldType))
#endif
{
var val = fi.GetValue(obj) as ILayer;
if (val != null)
{
var name = (fi.GetCustomAttributes(typeof(NodeEditorElementAttribute), true)[0] as NodeEditorElementAttribute).Name;
var conp = new ConnectionPoint(this, "", name, _headerHeight + _propertyHeight * _propCount, ConnectionPointType.Out, NodeBasedEditor.outPointStyle);
ConnectionPoints.Add(conp);
var newNode = new Node(val);
Children.Add(newNode);
newNode.Connections.Add(new Connection(newNode.inPoint, conp));
newNode.Dive(val, showModifiers, depth + 1);
_propCount++;
}
}
//field list<SO>
Type type = fi.FieldType;
if (type.IsGenericType && type.GetGenericTypeDefinition()
== typeof(List<>))
{
if (typeof(LayerProperties).IsAssignableFrom(type.GetGenericArguments()[0]))
{
if (typeof(VectorSubLayerProperties).IsAssignableFrom(type.GetGenericArguments()[0]))
{
var val = fi.GetValue(obj);
if (val is List<VectorSubLayerProperties>)
{
foreach (VectorSubLayerProperties listitem in val as IEnumerable)
{
//var prop = new SerializedObject(listitem);
var cc = new ConnectionPoint(this, "", listitem.coreOptions.sublayerName, _headerHeight + _propertyHeight * _propCount, ConnectionPointType.Out, NodeBasedEditor.outPointStyle, listitem);
ConnectionPoints.Add(cc);
_propCount++;
var newNode = new Node(listitem);
Children.Add(newNode);
newNode.Connections.Add(new Connection(newNode.inPoint, cc));
newNode.Dive(listitem, showModifiers, depth + 1);
}
}
else if (val is List<PrefabItemOptions>)
{
foreach (PrefabItemOptions listitem in val as IEnumerable)
{
//var prop = new SerializedObject(listitem);
var cc = new ConnectionPoint(this, "", listitem.coreOptions.sublayerName, _headerHeight + _propertyHeight * _propCount, ConnectionPointType.Out, NodeBasedEditor.outPointStyle, listitem);
ConnectionPoints.Add(cc);
_propCount++;
var newNode = new Node(listitem);
Children.Add(newNode);
newNode.Connections.Add(new Connection(newNode.inPoint, cc));
newNode.Dive(listitem, showModifiers, depth + 1);
}
}
}
else
{
var name = (fi.GetCustomAttributes(typeof(NodeEditorElementAttribute), true)[0] as NodeEditorElementAttribute).Name;
var conp = new ConnectionPoint(this, "", name, _headerHeight + _propertyHeight * _propCount, ConnectionPointType.Out, NodeBasedEditor.outPointStyle);
ConnectionPoints.Add(conp);
var val = fi.GetValue(obj);
if (val is IEnumerable)
{
foreach (ScriptableObject listitem in val as IEnumerable)
{
var newNode = new Node(listitem);
Children.Add(newNode);
newNode.Connections.Add(new Connection(newNode.inPoint, conp));
newNode.Dive(listitem, showModifiers, depth + 1);
}
_propCount++;
}
}
}
else
{
var name = (fi.GetCustomAttributes(typeof(NodeEditorElementAttribute), true)[0] as NodeEditorElementAttribute).Name;
var conp = new ConnectionPoint(this, "", name, _headerHeight + _propertyHeight * _propCount, ConnectionPointType.Out, NodeBasedEditor.outPointStyle);
ConnectionPoints.Add(conp);
var val = fi.GetValue(obj);
if (val is IEnumerable)
{
foreach (ModifierBase listitem in val as IEnumerable)
{
var newNode = new Node(listitem);
Children.Add(newNode);
newNode.Connections.Add(new Connection(newNode.inPoint, conp));
newNode.Dive(listitem, showModifiers, depth + 1);
}
_propCount++;
}
}
}
if (typeof(ScriptableObject).IsAssignableFrom(fi.FieldType))
{
var val = fi.GetValue(obj) as ModifierBase;
if (val != null)
{
var name = (fi.GetCustomAttributes(typeof(NodeEditorElementAttribute), true)[0] as NodeEditorElementAttribute).Name;
var conp = new ConnectionPoint(this, "", name, _headerHeight + _propertyHeight * _propCount, ConnectionPointType.Out, NodeBasedEditor.outPointStyle);
ConnectionPoints.Add(conp);
var newNode = new Node(val);
Children.Add(newNode);
newNode.Connections.Add(new Connection(newNode.inPoint, conp));
newNode.Dive(val, showModifiers, depth + 1);
_propCount++;
}
}
}
foreach (PropertyInfo pi in obj.GetType().GetProperties().Where(prop => prop.IsDefined(typeof(NodeEditorElementAttribute), false)))
{
//property SO
if (typeof(LayerProperties).IsAssignableFrom(pi.PropertyType))
{
var val = pi.GetValue(obj, null) as LayerProperties;
if (val != null)
{
var name = (pi.GetCustomAttributes(typeof(NodeEditorElementAttribute), true)[0] as NodeEditorElementAttribute).Name;
var conp = new ConnectionPoint(this, "", name, _headerHeight + _propertyHeight * _propCount, ConnectionPointType.Out, NodeBasedEditor.outPointStyle);
ConnectionPoints.Add(conp);
var newNode = new Node(val);
Children.Add(newNode);
newNode.Connections.Add(new Connection(newNode.inPoint, conp));
newNode.Dive(val, showModifiers, depth + 1);
_propCount++;
}
}
if (typeof(ILayer).IsAssignableFrom(pi.PropertyType))
{
var val = pi.GetValue(obj, null) as ILayer;
if (val != null)
{
var name = (pi.GetCustomAttributes(typeof(NodeEditorElementAttribute), true)[0] as NodeEditorElementAttribute).Name;
var conp = new ConnectionPoint(this, "", name, _headerHeight + _propertyHeight * _propCount, ConnectionPointType.Out, NodeBasedEditor.outPointStyle);
ConnectionPoints.Add(conp);
var newNode = new Node(val);
Children.Add(newNode);
newNode.Connections.Add(new Connection(newNode.inPoint, conp));
newNode.Dive(val, showModifiers, depth + 1);
_propCount++;
}
}
//property list<SO>
Type type = pi.PropertyType;
if (type.IsGenericType && type.GetGenericTypeDefinition()
== typeof(List<>))
{
if (typeof(LayerProperties).IsAssignableFrom(type.GetGenericArguments()[0]))
{
var val = pi.GetValue(obj, null);
var name = (pi.GetCustomAttributes(typeof(NodeEditorElementAttribute), true)[0] as NodeEditorElementAttribute).Name;
var conp = new ConnectionPoint(this, "", name, _headerHeight + _propertyHeight * _propCount, ConnectionPointType.Out, NodeBasedEditor.outPointStyle);
ConnectionPoints.Add(conp);
if (val is IEnumerable)
{
foreach (LayerProperties listitem in val as IEnumerable)
{
var newNode = new Node(listitem);
Children.Add(newNode);
newNode.Connections.Add(new Connection(newNode.inPoint, conp));
newNode.Dive(listitem, showModifiers, depth + 1);
}
_propCount++;
}
}
}
}
}
public void ProcessNodeEvents(Event e)
{
bool guiChanged = ProcessEvents(e);
foreach (var item in Children)
{
item.ProcessNodeEvents(e);
}
if (guiChanged)
{
GUI.changed = true;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 679a0efa08a678448a906413bfebad0b
timeCreated: 1501854745
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,328 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using Mapbox.Unity.Map;
using System.Reflection;
using System;
using System.Linq;
using System.Collections;
namespace Mapbox.Editor.NodeEditor
{
public class NodeBasedEditor : EditorWindow
{
[NonSerialized]
private Vector2 _panDelta;
[NonSerialized]
private float _nodeHeight = 50;
[NonSerialized]
private Vector2 _topLeft = new Vector2(50, 50);
//[NonSerialized]
//private Vector2 _padding = new Vector2(50, 100);
//private List<Node> nodes;
//private List<Connection> connections;
private int _activeMap = 0;
private List<Node> _maps;
//private Node _rootNode;
public static GUIStyle nodeStyle;
public static GUIStyle leafNodeStyle;
public static GUIStyle optionStyle;
public static GUIStyle selectedNodeStyle;
public static GUIStyle inPointStyle;
public static GUIStyle outPointStyle;
private static Texture2D _magnifierTexture;
public static Texture2D magnifierTexture
{
get
{
if (_magnifierTexture == null)
{
_magnifierTexture = EditorGUIUtility.FindTexture("d_ViewToolZoom");
}
return _magnifierTexture;
}
}
private GUIStyle _optionLabel;
//private ConnectionPoint selectedInPoint;
//private ConnectionPoint selectedOutPoint;
private Vector2 offset;
private Vector2 drag;
private float zoomScale = 1;
private Vector2 zoomOrigin = new Vector2(0, 20);
private Rect _canvasWindowRect { get { return new Rect(0, 20, position.width, position.height - 20); } }
private Rect _optionsRect { get { return new Rect(position.width - 250, 20, 250, 60); } }
private bool _showOptions = false;
private Vector2 _clickedPosition;
[MenuItem("Mapbox/Map Editor")]
private static void OpenWindow()
{
NodeBasedEditor window = GetWindow<NodeBasedEditor>();
window.titleContent = new GUIContent("Map Editor");
}
private void OnEnable()
{
GUIScaleUtility.CheckInit();
//MagnifierTexture = EditorGUIUtility.FindTexture("d_ViewToolZoom");
var textOffset = new RectOffset(12, 0, 10, 0);
nodeStyle = new GUIStyle();
nodeStyle.normal.background = EditorGUIUtility.Load("builtin skins/darkskin/images/node1.png") as Texture2D;
nodeStyle.border = new RectOffset(12, 12, 12, 12);
nodeStyle.richText = true;
nodeStyle.padding = textOffset;
selectedNodeStyle = new GUIStyle();
selectedNodeStyle.normal.background = EditorGUIUtility.Load("builtin skins/darkskin/images/node1 on.png") as Texture2D;
selectedNodeStyle.border = new RectOffset(12, 12, 12, 12);
selectedNodeStyle.richText = true;
selectedNodeStyle.padding = textOffset;
leafNodeStyle = new GUIStyle();
leafNodeStyle.normal.background = EditorGUIUtility.Load("builtin skins/darkskin/images/node2.png") as Texture2D;
leafNodeStyle.border = new RectOffset(12, 12, 12, 12);
leafNodeStyle.richText = true;
leafNodeStyle.padding = textOffset;
inPointStyle = new GUIStyle();
inPointStyle.normal.background = EditorGUIUtility.Load("builtin skins/darkskin/images/btn left.png") as Texture2D;
inPointStyle.active.background = EditorGUIUtility.Load("builtin skins/darkskin/images/btn left on.png") as Texture2D;
inPointStyle.border = new RectOffset(4, 4, 12, 12);
outPointStyle = new GUIStyle();
outPointStyle.normal.background = EditorGUIUtility.Load("builtin skins/darkskin/images/btn right.png") as Texture2D;
outPointStyle.active.background = EditorGUIUtility.Load("builtin skins/darkskin/images/btn right on.png") as Texture2D;
outPointStyle.border = new RectOffset(4, 4, 12, 12);
Parse();
}
private void Parse(bool showModifiers = true)
{
if (_maps == null)
_maps = new List<Node>();
else
_maps.Clear();
var abstractMaps = FindObjectsOfType<AbstractMap>();
//foreach (var abstractMap in abstractMaps)
//{
// foreach (FieldInfo fi in abstractMap.GetType().GetFields().Where(x => x.IsDefined(typeof(NodeEditorElementAttribute), true)))
// {
// var val = fi.GetValue(abstractMap) as ScriptableObject;
// if (typeof(ScriptableObject).IsAssignableFrom(fi.FieldType) && val != null)
// {
// var map = abstractMap.MapVisualizer;
// var mapNode = new Node(map as ScriptableObject);
// mapNode.title = map.name;
// mapNode.subtitle = "Map Visualizer";
// _maps.Add(mapNode);
// mapNode.Dive(map, showModifiers);
// }
// }
//}
foreach (var abstractMap in abstractMaps)
{
if (abstractMap != null)
{
var map = abstractMap;
var mapNode = new Node(map);
//{
// title = "Map",
// subtitle = "Map Visualizer"
//};
_maps.Add(mapNode);
mapNode.Dive(map, showModifiers);
}
}
}
private void OnGUI()
{
if (optionStyle == null)
{
optionStyle = (GUIStyle)"ObjectPickerPreviewBackground";
optionStyle.padding = new RectOffset(10, 10, 10, 10);
}
DrawGrid(20, 0.2f, Color.gray);
DrawGrid(100, 0.4f, Color.gray);
OnGUIToolBar();
var test = _canvasWindowRect;
var sc = GUIScaleUtility.BeginScale(ref test, zoomOrigin, zoomScale, false);
if (_activeMap < _maps.Count)
{
DrawNodes(sc);
ProcessNodeEvents(Event.current);
ProcessEvents(Event.current);
if (GUI.changed) Repaint();
}
GUIScaleUtility.EndScale();
if (_showOptions)
{
GUILayout.BeginArea(_optionsRect, optionStyle);
GUILayout.BeginHorizontal();
if (GUILayout.Button("Hide Modifiers", (GUIStyle)"ButtonLeft", GUILayout.Width(115)))
{
Parse(false);
}
if (GUILayout.Button("Show Modifiers", (GUIStyle)"ButtonRight", GUILayout.Width(115)))
{
Parse(true);
}
GUILayout.EndHorizontal();
if (GUILayout.Button("Reset Zoom", EditorStyles.miniButton, GUILayout.Width(230)))
{
zoomScale = 1;
}
GUILayout.EndArea();
}
}
void OnGUIToolBar()
{
GUILayout.BeginHorizontal(EditorStyles.toolbar);
if (GUILayout.Button("Map Visualizers", EditorStyles.toolbarDropDown))
{
GenericMenu toolsMenu = new GenericMenu();
var i = 0;
foreach (var item in _maps)
{
toolsMenu.AddItem(new GUIContent(item.title), false, ChangeMap, i);
i++;
}
// Offset menu from right of editor window
toolsMenu.DropDown(new Rect(0, 0, 0, 16));
EditorGUIUtility.ExitGUI();
}
if (GUILayout.Button("Refresh", EditorStyles.toolbarButton, GUILayout.Width(100)))
{
Parse();
}
GUILayout.FlexibleSpace();
if (GUILayout.Button("Options", EditorStyles.toolbarButton, GUILayout.Width(100)))
{
_showOptions = !_showOptions;
}
GUILayout.EndHorizontal();
}
private void ChangeMap(object i)
{
_activeMap = (int)i;
}
void OnFocus()
{
Parse();
}
private void DrawGrid(float gridSpacing, float gridOpacity, Color gridColor)
{
int widthDivs = Mathf.CeilToInt(position.width / gridSpacing);
int heightDivs = Mathf.CeilToInt(position.height / gridSpacing);
Handles.BeginGUI();
Handles.color = new Color(gridColor.r, gridColor.g, gridColor.b, gridOpacity);
offset += drag * 0.5f;
Vector3 newOffset = new Vector3(offset.x % gridSpacing, offset.y % gridSpacing, 0);
for (int i = 0; i < widthDivs; i++)
{
Handles.DrawLine(new Vector3(gridSpacing * i, -gridSpacing, 0) + newOffset, new Vector3(gridSpacing * i, position.height, 0f) + newOffset);
}
for (int j = 0; j < heightDivs; j++)
{
Handles.DrawLine(new Vector3(-gridSpacing, gridSpacing * j, 0) + newOffset, new Vector3(position.width, gridSpacing * j, 0f) + newOffset);
}
Handles.color = Color.white;
Handles.EndGUI();
}
private void DrawNodes(Vector2 sc)
{
_maps[_activeMap].Draw(_topLeft + _panDelta + sc, 100, _nodeHeight);
GUI.changed = true;
}
private void ProcessEvents(Event e)
{
drag = Vector2.zero;
switch (e.type)
{
case EventType.MouseDown:
if (e.button == 0)
{
_clickedPosition = e.mousePosition;
ClearConnectionSelection();
}
break;
case EventType.MouseDrag:
if (e.button == 0)
{
if (_canvasWindowRect.Contains(_clickedPosition))
{
_panDelta += e.delta;
}
}
break;
case EventType.ScrollWheel:
{
Vector2 delta = Event.current.delta;
Vector2 zoomedMousePos = (e.mousePosition - _canvasWindowRect.min) / zoomScale + zoomOrigin;
float oldZoomScale = zoomScale;
float zoomDelta = -delta.y / 150.0f;
zoomScale -= zoomDelta;
zoomScale = Mathf.Clamp(zoomScale, 0.5f, 2.0f);
zoomOrigin += (zoomedMousePos - zoomOrigin) - (oldZoomScale / zoomScale) * (zoomedMousePos - zoomOrigin);
Event.current.Use();
}
break;
case EventType.MouseUp:
if (e.button == 0)
{
_clickedPosition = new Vector2(Mathf.Infinity, Mathf.Infinity);
}
break;
}
}
private void ProcessNodeEvents(Event e)
{
_maps[_activeMap].ProcessNodeEvents(e);
}
private void ClearConnectionSelection()
{
//selectedInPoint = null;
//selectedOutPoint = null;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 26556c3e20124f847973c22be86cf80a
timeCreated: 1501854727
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: