///---------------------------------------------------------------------------------------------- ///Add a listener to several messages public void Register(object target, params string[] messages) { if (target == null) { return; } for (var i = 0; i < messages.Length; i++) { var method = target.GetType().GetMethod(messages[i], METHOD_FLAGS); if (method == null) { Logger.LogError(string.Format("Type '{0}' does not implement a method named '{1}', for the registered event to use.", target.GetType().FriendlyName(), messages[i]), "Events", target); continue; } List <object> targetObjects = null; if (!listeners.TryGetValue(messages[i], out targetObjects)) { targetObjects = new List <object>(); listeners[messages[i]] = targetObjects; } if (!targetObjects.Contains(target)) { targetObjects.Add(target); } } }
///<summary>Duplicate the connection providing a new source and target</summary> public Connection Duplicate(Node newSource, Node newTarget) { if (newSource == null || newTarget == null) { Logger.LogError("Can't Duplicate a Connection without providing NewSource and NewTarget Nodes"); return(null); } //deep clone var newConnection = JSONSerializer.Clone <Connection>(this); UndoUtility.RecordObject(newSource.graph, "Duplicate Connection"); newConnection._UID = null; newConnection.sourceNode = newSource; newConnection.targetNode = newTarget; newSource.outConnections.Add(newConnection); newTarget.inConnections.Add(newConnection); if (newSource.graph != null) { foreach (var task in Graph.GetTasksInElement(newConnection)) { task.Validate(newSource.graph); } } //-- newConnection.OnValidate(newSource.outConnections.Count - 1, newTarget.inConnections.Count - 1); UndoUtility.SetDirty(newSource.graph); return(newConnection); }
///Resolves and gets an actor based on the key name public IDialogueActor GetActorReferenceByName(string paramName) { //Check for INSTIGATOR selection if (paramName == INSTIGATOR_NAME) { //return it directly if it implements IDialogueActor if (agent is IDialogueActor) { return((IDialogueActor)agent); } //Otherwise use the default actor and set name and transform from agent if (agent != null) { return(new ProxyDialogueActor(agent.gameObject.name, agent.transform)); } return(new ProxyDialogueActor("Null Instigator", null)); } //Check for non INSTIGATOR selection. If there IS an actor reference return it var refData = actorParameters.Find(r => r.name == paramName); if (refData != null && refData.actor != null) { return(refData.actor); } //Otherwise use the default actor and set the name to the key and null transform Logger.Log(string.Format("An actor entry '{0}' on DialogueTree has no reference. A dummy Actor will be used with the entry Key for name", paramName), "Dialogue Tree", this); return(new ProxyDialogueActor(paramName, null)); }
///<summary>Create a new Connection. Use this for constructor</summary> public static Connection Create(Node source, Node target, int sourceIndex = -1, int targetIndex = -1) { if (source == null || target == null) { Logger.LogError("Can't Create a Connection without providing Source and Target Nodes"); return(null); } if (source is MissingNode) { Logger.LogError("Creating new Connections from a 'MissingNode' is not allowed. Please resolve the MissingNode node first"); return(null); } var newConnection = (Connection)System.Activator.CreateInstance(source.outConnectionType); UndoUtility.RecordObject(source.graph, "Create Connection"); var resultSourceIndex = newConnection.SetSourceNode(source, sourceIndex); var resultTargetIndex = newConnection.SetTargetNode(target, targetIndex); newConnection.OnValidate(resultSourceIndex, resultTargetIndex); newConnection.OnCreate(resultSourceIndex, resultTargetIndex); UndoUtility.SetDirty(source.graph); return(newConnection); }
//Create and set a UnityObject variable node on drop protected override void OnDropAccepted(Object o, Vector2 mousePos) { if (o == null) { return; } if (UnityEditor.EditorUtility.IsPersistent(this) && !UnityEditor.EditorUtility.IsPersistent(o)) { Logger.Log("This Graph is an asset. The dragged object is a scene reference. The reference will not persist!", LogTag.EDITOR); } var targetType = o.GetType(); var menu = new UnityEditor.GenericMenu(); menu = AppendDragAndDropObjectMenu(menu, o, "", mousePos); menu.AddSeparator("/"); menu = this.AppendTypeReflectionNodesMenu(menu, targetType, "", mousePos, null, o); if (o is GameObject) { foreach (var component in (o as GameObject).GetComponents <Component>().Where(c => c.hideFlags == 0)) { var cType = component.GetType(); menu = AppendDragAndDropObjectMenu(menu, component, cType.Name + "/", mousePos); menu = this.AppendTypeReflectionNodesMenu(menu, cType, "", mousePos, null, component); } } menu.ShowAsBrowser("Add Node For Drag & Drop Instance"); Event.current.Use(); }
//... protected override void OnValidate() { base.OnValidate(); #if UNITY_EDITOR if (UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage() != null) { return; } #endif if (Application.isPlaying || IsPrefabAsset()) { return; } if (!_allGlobals.Contains(this)) { _allGlobals.Add(this); } if (string.IsNullOrEmpty(_identifier)) { _identifier = gameObject.name; } var existing = Find(identifier); if (existing != this && existing != null) { Logger.LogError(string.Format("Another blackboard with the same identifier name '{0}' exists. Please rename either.", identifier), LogTag.BLACKBOARD, this); } }
protected override void RegisterPorts() { var returnPort = AddValueInput <object>("Value"); AddFlowInput(" ", (f) => { #if UNITY_EDITOR if (f.Return == null) { Fail("The 'Return' node should be called as part of a Custom Function node."); return; } var returnValue = returnPort.value; var returnType = returnValue != null? returnValue.GetType() : null; if (f.ReturnType != null && !f.ReturnType.RTIsAssignableFrom(returnType)) { Fail(string.Format("Return Value is not of expected type '{0}'.", f.ReturnType.FriendlyName())); return; } if (f.ReturnType == null && returnValue != null) { Logger.LogWarning("Function Returns a value, but no value is required", null, this); } #endif f.Return(returnPort.value); }); }
//... protected void OnEnable() { if (IsPrefabAsset()) { return; } if (string.IsNullOrEmpty(_identifier)) { _identifier = gameObject.name; } if (Application.isPlaying) { if (Find(identifier) != null) { Logger.Log(string.Format("There exist more than one Global Blackboards with same identifier name '{0}'. The old one will now be destroyed.", identifier), LogTag.BLACKBOARD, this); if (_singletonMode == SingletonMode.DestroyComponentOnly) { Destroy(this); } if (_singletonMode == SingletonMode.DestroyEntireGameObject) { Destroy(this.gameObject); } return; } if (_dontDestroyOnLoad) { DontDestroyOnLoad(this.gameObject); } } if (!_allGlobals.Contains(this)) { _allGlobals.Add(this); } }
protected override void RegisterPorts() { var 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; } 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); }); }
void OnEnable() { current = this; var canvasIcon = (Texture)Resources.Load("CanvasIcon"); titleContent = new GUIContent("Canvas", canvasIcon); willRepaint = true; fullDrawPass = true; wantsMouseMove = true; guiSkin = (GUISkin)Resources.Load(EditorGUIUtility.isProSkin? "NodeCanvasSkin" : "NodeCanvasSkinLight"); minSize = new Vector2(700, 300); #if UNITY_2017_2_OR_NEWER EditorApplication.playModeStateChanged -= PlayModeChange; EditorApplication.playModeStateChanged += PlayModeChange; #else EditorApplication.playmodeStateChanged -= PlayModeChange; EditorApplication.playmodeStateChanged += PlayModeChange; #endif Selection.selectionChanged -= OnSelectionChange; Selection.selectionChanged += OnSelectionChange; Logger.RemoveListener(OnLogMessageReceived); Logger.AddListener(OnLogMessageReceived); }
protected override void OnGraphPaused() { Logger.Log(string.Format("Dialogue Paused '{0}'", this.name), "Dialogue Tree", this); if (OnDialoguePaused != null) { OnDialoguePaused(this); } }
void OnCustomEvent(string eventName, IEventData data) { if (eventName.Equals(this.eventName.value, System.StringComparison.OrdinalIgnoreCase)) { Logger.Log(string.Format("Event Received from ({0}): '{1}'", agent.gameObject.name, name), LogTag.EVENT, this); YieldReturn(true); } }
///---------------------------------------------------------------------------------------------- //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); }
//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); }
///Set the target IDialogueActor for the provided key parameter name public void SetActorReference(string paramName, IDialogueActor actor) { var param = actorParameters.Find(p => p.name == paramName); if (param == null) { Logger.LogError(string.Format("There is no defined Actor key name '{0}'", paramName), "Dialogue Tree", this); return; } param.actor = actor; }
///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"); } }
protected override void OnGraphUnpaused() { currentNode = currentNode != null ? currentNode : (DTNode)primeNode; EnterNode(currentNode); Logger.Log(string.Format("Dialogue Resumed '{0}'", this.name), "Dialogue Tree", this); if (OnDialogueStarted != null) { OnDialogueStarted(this); } }
void OnCustomEvent(string eventName, ParadoxNotion.IEventData msg) { if (eventName.Equals(this.eventName.value, System.StringComparison.OrdinalIgnoreCase)) { var senderGraph = Graph.GetElementGraph(msg.sender); this.sender = senderGraph != null ? senderGraph.agent as GraphOwner : null; this.receiver = ResolveReceiver(msg.receiver); Logger.Log(string.Format("Event Received from ({0}): '{1}'", receiver.name, eventName), LogTag.EVENT, this); onReceived.Call(new Flow()); } }
///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); }
void IUpdatable.Update() { if (send) { send = false; var sw = new Stopwatch(); sw.Start(); o.Call(new Flow()); sw.Stop(); Logger.Log(string.Format("Debug Event Elapsed Time: {0} ms.", sw.ElapsedMilliseconds), LogTag.EDITOR, this); } }
void OnCustomEvent(string eventName, ParadoxNotion.IEventData msg) { if (eventName.Equals(this.eventName.value, System.StringComparison.OrdinalIgnoreCase)) { var receivedValue = msg.valueBoxed; if (ObjectUtils.AnyEquals(receivedValue, value.value)) { Logger.Log(string.Format("Event Received from ({0}): '{1}'", agent.gameObject.name, eventName), LogTag.EVENT, this); YieldReturn(true); } } }
protected override void OnGraphStoped() { currentDialogue = previousDialogue; previousDialogue = null; currentNode = null; Logger.Log(string.Format("Dialogue Finished '{0}'", this.name), "Dialogue Tree", this); if (OnDialogueFinished != null) { OnDialogueFinished(this); } }
void OnDisable() { current = null; welcomeShown = false; Graph.currentSelection = null; #if UNITY_2017_2_OR_NEWER EditorApplication.playModeStateChanged -= PlayModeChange; #else EditorApplication.playmodeStateChanged -= PlayModeChange; #endif Selection.selectionChanged -= OnSelectionChange; Logger.RemoveListener(OnLogMessageReceived); }
///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); }
///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; } }
///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); }
///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); }
///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); }
///Called after the node has GatherPorts to gather the references and validate the binding connection public void GatherAndValidateTargetPort() { _targetPort = null; //refetch if (targetPort != null) { //all good if (targetPort.type == bindingType) { targetPortID = targetPort.ID; targetPort.connections++; return; } //replace binder connection type if possible if (targetPort is ValueInput && sourcePort is ValueOutput) { if (TypeConverter.HasConvertion(sourcePort.type, targetPort.type)) { graph.RemoveConnection(this); Create(sourcePort, targetPort); targetPortID = targetPort.ID; targetPort.connections++; return; } //the cast is invalid Logger.LogError(string.Format("Input Port with ID '{0}' cast is invalid.", targetPortID), LogTag.VALIDATION, targetNode); targetPort.FlagInvalidCast(); targetPortID = targetPort.ID; targetPort.connections++; return; } } //the id is missing... Logger.LogError(string.Format("Input Port with ID '{0}' is missing on node {1}", targetPortID, targetNode.name), LogTag.VALIDATION, targetNode); var target = targetNode as FlowNode; Port missingPort = null; if (bindingType == typeof(Flow)) { missingPort = target.AddFlowInput(targetPortID, targetPortID, (f) => { throw new System.Exception("Port is missing"); }); } else { missingPort = target.AddValueInput(targetPortID, targetPortID, typeof(object)); } missingPort.FlagMissing(); missingPort.connections++; }