예제 #1
0
        ///----------------------------------------------------------------------------------------------

        //avoid connecting from same source
        protected override bool CanConnectFromSource(Node sourceNode)
        {
            if (this.IsChildOf(sourceNode))
            {
                Logger.LogWarning("States are already connected together. Consider using multiple conditions on an existing transition instead", "Editor", this);
                return(false);
            }
            return(true);
        }
예제 #2
0
 //avoid connecting to same target
 protected override bool CanConnectToTarget(Node targetNode)
 {
     if (this.IsParentOf(targetNode))
     {
         Logger.LogWarning("States are already connected together. Consider using multiple conditions on an existing transition instead", "Editor", this);
         return(false);
     }
     return(true);
 }
예제 #3
0
 ///Raise the OnMultipleChoiceRequest event
 public static void RequestMultipleChoices(MultipleChoiceRequestInfo info)
 {
     if (OnMultipleChoiceRequest != null)
     {
         OnMultipleChoiceRequest(info);
     }
     else
     {
         Logger.LogWarning("Multiple Choice Request event has no subscribers. Make sure to add the default '@DialogueGUI' prefab or create your own GUI.", "Dialogue Tree");
     }
 }
예제 #4
0
 ///Invokes the function and callbacks when a Return node is hit.
 public void InvokeAsync(Flow f, FlowHandler Callback, params object[] args)
 {
     if (isInvoking)
     {
         Logger.LogWarning("Invoking a custom function which is already running is currently not supported.", "Execution", this);
         return;
     }
     this.args  = args;
     isInvoking = true;
     f.PushReturnData((o) => { this.returnValue = o; isInvoking = false; Callback(f); }, returns.type);
     onInvoke.Call(f);
 }
예제 #5
0
 ///Set all target IDialogueActors at once by provided dictionary
 public void SetActorReferences(Dictionary <string, IDialogueActor> actors)
 {
     foreach (var pair in actors)
     {
         var param = actorParameters.Find(p => p.name == pair.Key);
         if (param == null)
         {
             Logger.LogWarning(string.Format("There is no defined Actor key name '{0}'. Seting actor skiped", pair.Key), "Dialogue Tree", this);
             continue;
         }
         param.actor = pair.Value;
     }
 }
예제 #6
0
        ///Trigger a state to enter by it's name. Returns the state found and entered if any
        public FSMState TriggerState(string stateName, TransitionCallMode callMode)
        {
            var state = GetStateWithName(stateName);

            if (state != null)
            {
                EnterState(state, callMode);
                return(state);
            }

            Logger.LogWarning("No State with name '" + stateName + "' found on FSM '" + name + "'", LogTag.EXECUTION, this);
            return(null);
        }
예제 #7
0
        ///the connection context menu
        GenericMenu GetConnectionMenu()
        {
            var menu = new GenericMenu();

            menu.AddItem(new GUIContent(infoExpanded? "Collapse Info" : "Expand Info"), false, () => { infoExpanded = !infoExpanded; });
            menu.AddItem(new GUIContent(isActive? "Disable" : "Enable"), false, () => { isActive = !isActive; });

            var assignable = this as ITaskAssignable;

            if (assignable != null)
            {
                if (assignable.task != null)
                {
                    menu.AddItem(new GUIContent("Copy Assigned Condition"), false, () => { CopyBuffer.Set <Task>(assignable.task); });
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Copy Assigned Condition"));
                }

                if (CopyBuffer.Has <Task>())
                {
                    menu.AddItem(new GUIContent(string.Format("Paste Assigned Condition ({0})", CopyBuffer.Peek <Task>().name)), false, () =>
                    {
                        if (assignable.task == CopyBuffer.Peek <Task>())
                        {
                            return;
                        }

                        if (assignable.task != null)
                        {
                            if (!EditorUtility.DisplayDialog("Paste Condition", string.Format("Connection already has a Condition assigned '{0}'. Replace assigned condition with pasted condition '{1}'?", assignable.task.name, CopyBuffer.Peek <Task>().name), "YES", "NO"))
                            {
                                return;
                            }
                        }

                        try { assignable.task = CopyBuffer.Get <Task>().Duplicate(graph); }
                        catch { Logger.LogWarning("Can't paste Condition here. Incombatible Types.", "Editor", this); }
                    });
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Paste Assigned Condition"));
                }
            }

            menu.AddSeparator("/");
            menu.AddItem(new GUIContent("Delete"), false, () => { graph.RemoveConnection(this); });
            return(menu);
        }
예제 #8
0
 ///Invokes the function and return it's return value
 public object Invoke(Flow f, params object[] args)
 {
     if (isInvoking)
     {
         Logger.LogWarning("Invoking a custom function which is already running is currently not supported.", "Execution", this);
         return(null);
     }
     this.args  = args;
     isInvoking = true;
     f.PushReturnData((o) => { this.returnValue = o; }, returns.type);
     isInvoking = false;
     onInvoke.Call(f);
     return(returnValue);
 }
예제 #9
0
        ///Enter a state providing the state itself
        public bool EnterState(FSMState newState, TransitionCallMode callMode)
        {
            if (!isRunning)
            {
                Logger.LogWarning("Tried to EnterState on an FSM that was not running", LogTag.EXECUTION, this);
                return(false);
            }

            if (newState == null)
            {
                Logger.LogWarning("Tried to Enter Null State", LogTag.EXECUTION, this);
                return(false);
            }

            if (currentState != null)
            {
                if (onStateExit != null)
                {
                    onStateExit(currentState);
                }
                currentState.Reset(false);
                if (callMode == TransitionCallMode.Stacked)
                {
                    stateStack.Push(currentState);
                    if (stateStack.Count > 5)
                    {
                        Logger.LogWarning("State stack exceeds 5. Ensure that you are not cycling stack calls", LogTag.EXECUTION, this);
                    }
                }
            }

            if (callMode == TransitionCallMode.Clean)
            {
                stateStack.Clear();
            }

            previousState = currentState;
            currentState  = newState;

            if (onStateTransition != null)
            {
                onStateTransition(currentState);
            }
            if (onStateEnter != null)
            {
                onStateEnter(currentState);
            }
            currentState.Execute(agent, blackboard);
            return(true);
        }
        ///Invokes the function and callbacks when a Return node is hit.
        public void InvokeAsync(Flow f, FlowHandler flowCallback, params object[] args)
        {
            if (isInvoking)
            {
                Logger.LogWarning("Invoking a Custom Function which is already running.", "Execution", this);
            }
            this.args  = args;
            isInvoking = true;
            FlowReturn returnCallback = (o) => { this.returnValue = o; isInvoking = false; flowCallback(f); };
            var        invocationFlow = new Flow();

            invocationFlow.SetReturnData(returnCallback, returns.type);
            onInvoke.Call(invocationFlow);
        }
예제 #11
0
 ///----------------------------------------------------------------------------------------------
 protected override void OnNodeInspectorGUI()
 {
     if (GUILayout.Button("Call"))
     {
         if (Application.isPlaying)
         {
             //we do this only for the debugging to show, cause it doesn if we fire the port in here (OnGUI) but it works fine otherwise
             send = true;
         }
         else
         {
             Logger.LogWarning("Debug Flow Signal Event will only work in PlayMode", LogTag.EDITOR, this);
         }
     }
 }
예제 #12
0
        protected override void RegisterPorts()
        {
            if (useReturnValue)
            {
                returnPort = AddValueInput <object>("Value");
            }
            AddFlowInput(" ", (f) =>
            {
                var returnData = f.PopReturnData();
                if (returnData.returnCall == null)
                {
                    Fail("The 'Return' node should be called as part of a Custom Function node.");
                    return;
                }

                if (useReturnValue)
                {
                    var returnValue = returnPort.value;
                    if (returnData.returnType == null)
                    {
                        if (returnValue != null)
                        {
                            Logger.LogWarning("Function Returns a value, but no value is required", null, this);
                        }
                        returnData.returnCall(returnValue);
                        return;
                    }

                    var returnType = returnValue != null? returnValue.GetType() : null;
                    if ((returnType == null && returnData.returnType.RTIsValueType()) || (returnType != null && !returnData.returnType.RTIsAssignableFrom(returnType)))
                    {
                        Fail(string.Format("Return Value is not of expected type '{0}'.", returnData.returnType.FriendlyName()));
                        return;
                    }

                    returnData.returnCall(returnValue);
                }
                else
                {
                    returnData.returnCall(null);
                }
            });
        }
예제 #13
0
        ///A IDictionary editor
        public static IDictionary DictionaryEditor(GUIContent content, IDictionary dict, Type dictType, InspectedFieldInfo info)
        {
            var keyType   = dictType.RTGetGenericArguments()[0];
            var valueType = dictType.RTGetGenericArguments()[1];

            if (object.Equals(dict, null))
            {
                GUILayout.Label("Null Dictionary");
                return(dict);
            }

            if (!CachedFoldout(dictType, content))
            {
                return(dict);
            }

            GUILayout.BeginVertical();

            var keys   = dict.Keys.Cast <object>().ToList();
            var values = dict.Values.Cast <object>().ToList();

            if (GUILayout.Button("Add Element"))
            {
                if (!typeof(UnityObject).IsAssignableFrom(keyType))
                {
                    object newKey = null;
                    if (keyType == typeof(string))
                    {
                        newKey = string.Empty;
                    }
                    else
                    {
                        newKey = Activator.CreateInstance(keyType);
                    }

                    if (dict.Contains(newKey))
                    {
                        Logger.LogWarning(string.Format("Key '{0}' already exists in Dictionary", newKey.ToString()), "Editor");
                        return(dict);
                    }

                    keys.Add(newKey);
                }
                else
                {
                    Logger.LogWarning("Can't add a 'null' Dictionary Key", "Editor");
                    return(dict);
                }

                values.Add(valueType.IsValueType ? Activator.CreateInstance(valueType) : null);
            }

            //clear before reconstruct
            dict.Clear();

            for (var i = 0; i < keys.Count; i++)
            {
                GUILayout.BeginHorizontal("box");
                GUILayout.Box("", GUILayout.Width(6), GUILayout.Height(35));

                GUILayout.BeginVertical();
                keys[i]   = ReflectedFieldInspector("K:", keys[i], keyType, info);
                values[i] = ReflectedFieldInspector("V:", values[i], valueType, info);
                GUILayout.EndVertical();

                if (GUILayout.Button("X", GUILayout.Width(18), GUILayout.Height(34)))
                {
                    keys.RemoveAt(i);
                    values.RemoveAt(i);
                }

                GUILayout.EndHorizontal();

                try { dict.Add(keys[i], values[i]); }
                catch { Logger.Log("Dictionary Key removed due to duplicate found", "Editor"); }
            }

            Separator();

            GUILayout.EndVertical();
            return(dict);
        }
        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))
                {
                    foreach (FSMConnection connection in inConnections)
                    {
                        if (connection.sourceNode == clickedPort.parent)
                        {
                            Logger.LogWarning("State is already connected to target state. Consider using multiple conditions on an existing transition instead", "Editor", this);
                            clickedPort = null;
                            e.Use();
                            return;
                        }
                    }

                    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 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
                        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))
                {
                    EditorGUIUtility.AddCursorRect(portRectLeft, MouseCursor.ArrowPlus);
                    EditorGUIUtility.AddCursorRect(portRectRight, MouseCursor.ArrowPlus);
                    EditorGUIUtility.AddCursorRect(portRectBottom, MouseCursor.ArrowPlus);

                    GUI.color = new Color(1, 1, 1, 0.3f);
                    GUI.Box(portRectLeft, string.Empty, CanvasStyles.arrowLeft);
                    GUI.Box(portRectRight, string.Empty, CanvasStyles.arrowRight);
                    if (maxInConnections == 0)
                    {
                        GUI.Box(portRectBottom, string.Empty, CanvasStyles.arrowBottom);
                    }
                    GUI.color = Color.white;

                    if (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();
                        }
                    }
                }
            }

            if (clickedPort != null && clickedPort.parent == this)
            {
                Handles.DrawBezier(clickedPort.pos, e.mousePosition, clickedPort.pos, e.mousePosition, new Color(0.5f, 0.5f, 0.8f, 0.8f), null, 2);
            }

            for (var i = 0; i < outConnections.Count; i++)
            {
                var connection  = outConnections[i] as FSMConnection;
                var targetState = connection.targetNode as FSMState;
                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);
                }
            }
        }