230 lines
9.1 KiB
C#
230 lines
9.1 KiB
C#
using NodeCanvas.Framework;
|
|
using ParadoxNotion;
|
|
using UnityEngine;
|
|
|
|
namespace NodeCanvas.StateMachines
|
|
{
|
|
|
|
|
|
///<summary> Super base class for FSM nodes that live within an FSM Graph.</summary>
|
|
public abstract class FSMNode : Node
|
|
{
|
|
|
|
public override bool allowAsPrime { get { return false; } }
|
|
public override bool canSelfConnect { get { return false; } }
|
|
public override int maxInConnections { get { return -1; } }
|
|
public override int maxOutConnections { get { return -1; } }
|
|
sealed public override System.Type outConnectionType { get { return typeof(FSMConnection); } }
|
|
sealed public override Alignment2x2 commentsAlignment { get { return Alignment2x2.Bottom; } }
|
|
sealed public override Alignment2x2 iconAlignment { get { return Alignment2x2.Bottom; } }
|
|
|
|
///<summary>The FSM this state belongs to</summary>
|
|
public FSM FSM { get { return (FSM)graph; } }
|
|
|
|
|
|
///----------------------------------------------------------------------------------------------
|
|
///---------------------------------------UNITY EDITOR-------------------------------------------
|
|
#if UNITY_EDITOR
|
|
|
|
private static GUIPort clickedPort { get; set; }
|
|
private static int dragDropMisses { get; set; }
|
|
|
|
class GUIPort
|
|
{
|
|
public FSMNode parent { get; private set; }
|
|
public Vector2 pos { get; private set; }
|
|
public GUIPort(FSMNode parent, Vector2 pos) {
|
|
this.parent = parent;
|
|
this.pos = pos;
|
|
}
|
|
}
|
|
|
|
//Draw the ports and connections
|
|
sealed protected override void DrawNodeConnections(Rect drawCanvas, bool fullDrawPass, Vector2 canvasMousePos, float zoomFactor) {
|
|
|
|
var e = Event.current;
|
|
|
|
//Receive connections first
|
|
if ( clickedPort != null && e.type == EventType.MouseUp && e.button == 0 ) {
|
|
|
|
if ( rect.Contains(e.mousePosition) ) {
|
|
graph.ConnectNodes(clickedPort.parent, this);
|
|
clickedPort = null;
|
|
e.Use();
|
|
|
|
} else {
|
|
|
|
dragDropMisses++;
|
|
|
|
if ( dragDropMisses == graph.allNodes.Count && clickedPort != null ) {
|
|
var source = clickedPort.parent;
|
|
var pos = Event.current.mousePosition;
|
|
var menu = new UnityEditor.GenericMenu();
|
|
clickedPort = null;
|
|
|
|
menu.AddItem(new GUIContent("Add Action State"), false, () =>
|
|
{
|
|
var newState = graph.AddNode<ActionState>(pos);
|
|
graph.ConnectNodes(source, newState);
|
|
});
|
|
|
|
//PostGUI cause of zoom factors
|
|
Editor.GraphEditorUtility.PostGUI += () => { menu.ShowAsContext(); };
|
|
Event.current.Use();
|
|
e.Use();
|
|
}
|
|
}
|
|
}
|
|
|
|
var portRectLeft = new Rect(0, 0, 20, 20);
|
|
var portRectRight = new Rect(0, 0, 20, 20);
|
|
var portRectBottom = new Rect(0, 0, 20, 20);
|
|
|
|
portRectLeft.center = new Vector2(rect.x - 11, rect.center.y);
|
|
portRectRight.center = new Vector2(rect.xMax + 11, rect.center.y);
|
|
portRectBottom.center = new Vector2(rect.center.x, rect.yMax + 11);
|
|
|
|
if ( maxOutConnections != 0 ) {
|
|
if ( fullDrawPass || drawCanvas.Overlaps(rect) ) {
|
|
UnityEditor.EditorGUIUtility.AddCursorRect(portRectLeft, UnityEditor.MouseCursor.ArrowPlus);
|
|
UnityEditor.EditorGUIUtility.AddCursorRect(portRectRight, UnityEditor.MouseCursor.ArrowPlus);
|
|
UnityEditor.EditorGUIUtility.AddCursorRect(portRectBottom, UnityEditor.MouseCursor.ArrowPlus);
|
|
|
|
GUI.color = new Color(1, 1, 1, 0.3f);
|
|
GUI.DrawTexture(portRectLeft, Editor.StyleSheet.arrowLeft);
|
|
GUI.DrawTexture(portRectRight, Editor.StyleSheet.arrowRight);
|
|
if ( maxInConnections == 0 ) {
|
|
GUI.DrawTexture(portRectBottom, Editor.StyleSheet.arrowBottom);
|
|
}
|
|
GUI.color = Color.white;
|
|
|
|
if ( Editor.GraphEditorUtility.allowClick && e.type == EventType.MouseDown && e.button == 0 ) {
|
|
|
|
if ( portRectLeft.Contains(e.mousePosition) ) {
|
|
clickedPort = new GUIPort(this, portRectLeft.center);
|
|
dragDropMisses = 0;
|
|
e.Use();
|
|
}
|
|
|
|
if ( portRectRight.Contains(e.mousePosition) ) {
|
|
clickedPort = new GUIPort(this, portRectRight.center);
|
|
dragDropMisses = 0;
|
|
e.Use();
|
|
}
|
|
|
|
if ( maxInConnections == 0 && portRectBottom.Contains(e.mousePosition) ) {
|
|
clickedPort = new GUIPort(this, portRectBottom.center);
|
|
dragDropMisses = 0;
|
|
e.Use();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//draw new linking
|
|
if ( clickedPort != null && clickedPort.parent == this ) {
|
|
UnityEditor.Handles.DrawBezier(clickedPort.pos, e.mousePosition, clickedPort.pos, e.mousePosition, new Color(0.5f, 0.5f, 0.8f, 0.8f), Editor.StyleSheet.bezierTexture, 2);
|
|
}
|
|
|
|
//draw out connections
|
|
for ( var i = 0; i < outConnections.Count; i++ ) {
|
|
|
|
var connection = outConnections[i] as FSMConnection;
|
|
var targetState = connection.targetNode as FSMNode;
|
|
if ( targetState == null ) { //In case of MissingNode type
|
|
continue;
|
|
}
|
|
|
|
var targetPos = targetState.GetConnectedInPortPosition(connection);
|
|
var sourcePos = Vector2.zero;
|
|
|
|
if ( rect.center.x <= targetPos.x ) {
|
|
sourcePos = portRectRight.center;
|
|
}
|
|
|
|
if ( rect.center.x > targetPos.x ) {
|
|
sourcePos = portRectLeft.center;
|
|
}
|
|
|
|
if ( maxInConnections == 0 && rect.center.y < targetPos.y - 50 && Mathf.Abs(rect.center.x - targetPos.x) < 200 ) {
|
|
sourcePos = portRectBottom.center;
|
|
}
|
|
|
|
var boundRect = RectUtils.GetBoundRect(sourcePos, targetPos);
|
|
if ( fullDrawPass || drawCanvas.Overlaps(boundRect) ) {
|
|
connection.DrawConnectionGUI(sourcePos, targetPos);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//...
|
|
Vector2 GetConnectedInPortPosition(Connection connection) {
|
|
|
|
var sourcePos = connection.sourceNode.rect.center;
|
|
var thisPos = rect.center;
|
|
|
|
var style = 0;
|
|
|
|
if ( style == 0 ) {
|
|
if ( sourcePos.x <= thisPos.x ) {
|
|
if ( sourcePos.y <= thisPos.y ) {
|
|
return new Vector2(rect.center.x - 15, rect.yMin - ( this == graph.primeNode ? 20 : 0 ));
|
|
} else {
|
|
return new Vector2(rect.center.x - 15, rect.yMax + 2);
|
|
}
|
|
}
|
|
|
|
if ( sourcePos.x > thisPos.x ) {
|
|
if ( sourcePos.y <= thisPos.y ) {
|
|
return new Vector2(rect.center.x + 15, rect.yMin - ( this == graph.primeNode ? 20 : 0 ));
|
|
} else {
|
|
return new Vector2(rect.center.x + 15, rect.yMax + 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
// //Another idea
|
|
// if (style == 1){
|
|
// if (sourcePos.x <= thisPos.x){
|
|
// if (sourcePos.y >= thisPos.y){
|
|
// return new Vector2(rect.xMin - 3, rect.yMax - 10);
|
|
// } else {
|
|
// return new Vector2(rect.xMin - 3, rect.yMin + 10);
|
|
// }
|
|
// }
|
|
// if (sourcePos.x > thisPos.x){
|
|
// if (sourcePos.y >= thisPos.y){
|
|
// return new Vector2(rect.center.x, rect.yMax + 2);
|
|
// } else {
|
|
// return new Vector2(rect.center.x, rect.yMin - (this == graph.primeNode? 20 : 0 ));
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// //YET Another idea
|
|
// if (style >= 2){
|
|
// if (sourcePos.x <= thisPos.x){
|
|
// if (sourcePos.y >= thisPos.y){
|
|
// return new Vector2(rect.xMin - 3, rect.yMax - 10);
|
|
// } else {
|
|
// return new Vector2(rect.xMin - 3, rect.yMin + 10);
|
|
// }
|
|
// }
|
|
// if (sourcePos.x > thisPos.x){
|
|
// if (sourcePos.y >= thisPos.y){
|
|
// return new Vector2(rect.xMax + 3, rect.yMax - 10);
|
|
// } else {
|
|
// return new Vector2(rect.xMax + 3, rect.yMin + 10);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
return thisPos;
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
} |