Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        /// <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);
        }
Example #4
0
        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));
        }