public bool endDialogue(bool unloadDialogueAsset = false) { // Reset all flags, counters and references: reset(); currentNode = null; bindingCore = null; if (dialogue == null) { Debug.LogError("[DialogueController] Error! Dialogue is null yet you are still trying to end it."); return(false); } // Execute end binding right away: executeBinding(ref dialogue.endBinding); // End the dialogue and unload asset as required: if (unloadDialogueAsset) { Dialogue prevDialogue = dialogue; dialogue = null; Object.Destroy(prevDialogue); Resources.UnloadAsset(prevDialogue); } // Notify the dialogue trigger of the end of a new dialogue: if (trigger != null) { trigger.notifyDialogueEvent(DialogueEvent.End); } return(true); }
public bool startDialogue(IDialogueTrigger inTrigger, IBindingCore inBindingCore) { // NOTE: Returns false if the conditions for none of the root nodes were met! if (dialogue == null) { return(false); } if (inBindingCore == null) { Debug.LogWarning("[DialogueController] Error! Null binding core may result in dialogue bindings not being resolved!"); } trigger = inTrigger; bindingCore = inBindingCore; // Reset all flags, counters and references: reset(); // Execute start binding right away: executeBinding(ref dialogue.startBinding); DialogueRoot root = DialogueRoot.Blank; getRootNode(ref root); bool started = selectNode(root.node); // Notify the dialogue trigger of the start of a new dialogue: if (started && trigger != null) { trigger.notifyDialogueEvent(DialogueEvent.Start); } return(started); }
/// <summary> /// Call to execute a binding. This will first verify the binding, then resolve its path and /// finally try to execute the binding by either assigning the value of a field, by setting /// a property or by calling a method on the target designated by the binding's path. /// </summary> /// <returns>A result containing an error code and success feedback.</returns> /// <param name="binding">The binding you wish to take effect.</param> /// <param name="core">The binding core object relative to which the path should be resolved.</param> public BindingResult executeBinding(ref Binding binding, IBindingCore core) { // Check the binding's parameter set: if (!verifyBinding(ref binding)) { // Tell the author of this binding request that the operation was aborted: binding.responseCode = BindingResponse.Error; Debug.LogError("[BindingExecutor] Error! The binding '" + binding.ToString() + "' is invalid!"); return(new BindingResult(BindingError.InvalidBinding)); } // NOTE: All methods callable via binding must match the 'UtmlBindingListener' delegate! // Try and find some dependency via reflection using the hierarchy given by the path: BindingResult result = resolveBindingPath(ref binding, core); if (result.error != BindingError.Success) { // Tell the author of this binding request that an error occurred: binding.responseCode = BindingResponse.Error; // Invalid or unknown binding, abort event call: Debug.LogError("[BindingExecutor] Error! Path resolution for binding '" + binding.path + "' failed!"); } return(result); }
private BindingResult resolveBindingPath(ref Binding binding, IBindingCore core) { if (core == null) { Debug.LogError("[BindingExecutor] Error! Unable to resolve path from null binding core!"); return(new BindingResult(BindingError.NullReference)); } // NOTE: When calling this, it is assumed that the binding was verified beforehand. // NOTE2: This method resolves the path, finds the event call method, then checks parameters. StringBuilder pathBuffer = new StringBuilder(pathBufferBlankString); // Reset path buffer: for (int j = 0; j < pathBuffer.Length; ++j) { pathBuffer[j] = pathBufferFillChar; } /* NOTE3: Was I trying to use a char array because strings are immutable and heap allocations are slow? Yep. * For the most part, I'm trying to resolve the path on stack only, with very few runtime allocations. * Had to use a string builder instead, because C# can't just use pointer style strings like in C++. */ // Get the path from binding for easier access: string path = binding.path; // Declare some 'navigation' and reference variables: int bufferIndex = 0; MemberType memberType = MemberType.None; object current = core; System.Type currentType = core.GetType(); try { // Iterate through the path characters and evaluate parts of it as you get to them: for (int i = 0; i < path.Length; ++i) { char c = path[i]; // A new path segment commences, evaluate the previous section: if (c == '/') { string fBufferString = pathBuffer.ToString().Substring(0, bufferIndex); FieldInfo fInfo = currentType.GetField(fBufferString, bindingFieldFlags); if (fInfo == null) { // No matching field was found, abort query: Debug.LogError("[BindingExecutor] Error! Field '" + fBufferString + "' not found in type '" + currentType.Name + "'! Aborting path resolution!"); return(new BindingResult(BindingError.NotFound)); } // Get the object instance referenced by the field's value and determine its type: current = fInfo.GetValue(current); if (current == null) { Debug.LogError("Error! For some obnoxious reason, '" + fInfo.Name + "' was null on object."); return(new BindingResult(BindingError.NullReference)); } currentType = current.GetType(); // Reset path buffer and index: for (int j = 0; j < pathBuffer.Length; ++j) { pathBuffer[j] = pathBufferFillChar; } bufferIndex = 0; } // The method name at the end of a path is designated by the ':' prefix: else if (c == pathMethodChar) { memberType = MemberType.Method; } else if (c == pathFieldChar) { memberType = MemberType.Field; } else if (c != '\0') { // Write path characters into buffer one after the other: pathBuffer[bufferIndex++] = c; } if (c == '\0' || i == path.Length - 1) { // Check if a method or type name was found/declared within the preceeding path: switch (memberType) { case MemberType.Method: return(useBindingMethod(current, pathBuffer, bufferIndex, ref binding)); case MemberType.Field: return(useBindingField(current, pathBuffer, bufferIndex, ref binding)); default: Debug.LogError("[BindingExecutor] Error! No member declaration found in path '" + path + "'! Are you missing a '" + pathMethodChar + "' or '" + pathFieldChar + "' prefix?"); break; } return(new BindingResult(BindingError.InvalidBinding)); } } } // Catch any exceptions in the process: catch (System.Exception ex) { Debug.LogError("[BindingExecutor] ERROR! An exception was caught while resolving binding path '" + path + "'!\nException message: '" + ex.Message + "'\nAborting path resolution!"); } return(new BindingResult(BindingError.Failure)); }