示例#1
0
            void ActivateNode(NarrativeNode _node)
            {
                currentNode = _node;
                ActionProcess action = new ActionProcess(this, currentNode);

                processMgr.Launch(action);
            }
示例#2
0
            IEnumerator ActivateNodeRoutine(NarrativeNode _node)
            {
                _node.Activate();

                yield return(StartCoroutine(waitingRoutine(_node.Duration)));

                List <NarrativeNode> nexts = _node.Next();

                yield return(StartCoroutine(ActivateNodeNextsRoutine(nexts)));
            }
示例#3
0
            public override Node Create(Vector2 pos)
            {
                NarrativeNode node = CreateInstance <NarrativeNode> ();

                node.rect = new Rect(pos.x, pos.y, 300, 120);
                node.name = ID;

                node.CreateInput("Previous Node", CONNECT_FORWARD_STR, NodeSide.Left, 30);
                node.CreateOutput("Next Node", CONNECT_FORWARD_STR, NodeSide.Right, 30);

                return(node);
            }
示例#4
0
 public ActionProcess(ActionManager _parent, NarrativeNode _node)
 {
     parent      = _parent;
     currentNode = _node;
 }
示例#5
0
 void ActivateNode(NarrativeNode _node)
 {
     currentNode = _node;
     StartCoroutine(ActivateNodeRoutine(_node));
 }
示例#6
0
        public NarrativeList Parse(string inputStr)
        {
            CurrentNarrativeList = new NarrativeList();

            // Automatically add external block statements enclosing whole thing if not present.
            if (!inputStr.StartsWith($"{OPENBRACKET}{NodeType.Begin}"))
            {
                inputStr = $"{OPENBRACKET}{NodeType.Begin} ALL_CONTENT{CLOSEBRACKET}" + inputStr + $"{OPENBRACKET}{NodeType.End} ALL_CONTENT{CLOSEBRACKET}";
            }

            // Trim initial open bracket ("split" on open bracket symbol, discard meaningless empty first element, keep only what comes after).
            //inputStr.TrimStart(OnOpenBracket);

            int seqCounter = 0;

            while (true)
            {
                if (String.IsNullOrEmpty(inputStr))
                {
                    break;
                }

                var currentStr = inputStr.Before(OnOpenBracket); // Should have the form "TypeOrTagName Tag: option, option, option]text|text
                inputStr = inputStr.After(OnOpenBracket);        // Should have the form above, plus zero or more "[(same again)" on the end.

                if (currentStr == "")
                {
                    continue;
                }

                // Parse out the speech string (always present, if sometimes empty)
                var speechString = currentStr.After(OnCloseBracket);
                currentStr = currentStr.Before(OnCloseBracket);

                PreviousNode = CurrentNode;

                var firstWord = currentStr.Before(OnSpaceOrColon);
                if (Enum.TryParse <NodeType>(firstWord, out NodeType nodeWord) && nodeWord != NodeType.Tag) // First word is the name of a node type.
                {
                    if (nodeWord.IsOneOf(NodeConsts.ConditionOpeners))                                      // To wit, "Begin", "Check", "Cue", or "Ice".
                    {
                        var nodeTag = currentStr.Split(OnSpaceOrColon)[1].ToLower();                        // Second word - likely of more than two! - is therefore the tag.

                        if (NestedTagStructure.Any(ncond => ncond.Tag == nodeTag))
                        {
                            throw new Exception($"Error parsing input string - tag {nodeTag} already exists and cannot be reused.");
                        }

                        // Specific implementations for each type of condition node
                        NarrativeConditionNode curNode;
                        if (nodeWord == NodeType.Begin)
                        {
                            curNode = new NarrativeLabelNode();
                        }
                        else if (nodeWord == NodeType.Check)
                        {
                            var argument       = currentStr.After(OnColon).Trim();
                            var varName        = argument.Before(OnSpace); // Or should this be the part that's on colon, instead?  TBD.
                            var conditionValue = argument.After(OnSpace);

                            curNode = new NarrativeCheckConditionNode()
                            {
                                CheckedVariable  = varName,
                                CheckedCondition = conditionValue
                            };
                        }
                        else if (nodeWord == NodeType.Cue)
                        {
                            var argument  = currentStr.After(OnColon).Trim();
                            var argAsGest = (Gest)Enum.Parse(typeof(Gest), argument, ignoreCase: true);

                            curNode = new NarrativeCueConditionNode()
                            {
                                TargetGesture = argAsGest
                            };
                        }
                        else if (nodeWord == NodeType.Ice)
                        {
                            curNode = new NarrativeIceConditionNode();

                            var argumentStr = currentStr.After(OnColon).Trim();
                            var arguments   = argumentStr.Split(',').Select(s => s.Trim());

                            foreach (var argument in arguments)
                            {
                                if (argument == "")
                                {
                                    continue;
                                }

                                var target = argument.Before(OnSpace);
                                var amount = argument.After(OnSpace);

                                // Which variable are they assigning?
                                var targetIndex = NarrativeIceConditionNode.ArgumentNames.ToList().IndexOf(target);
                                if (targetIndex == -1)
                                {
                                    throw new Exception($"Cannot parse argument '{target}' - target must be one of {NarrativeIceConditionNode.ArgumentNames.Join()}");
                                }

                                // What are they assigning it to be?  Is it a range (min-max), or a single value (the mean)?
                                double firstAmount;
                                double?secondAmount;
                                try
                                {
                                    if (amount.Contains("-"))
                                    {
                                        firstAmount = double.Parse(amount.Split('-')[0]);
                                        var amountMax = double.Parse(amount.Split('-')[1]);
                                        secondAmount = amountMax - firstAmount;
                                    }
                                    else
                                    {
                                        firstAmount  = double.Parse(amount);
                                        secondAmount = null;
                                    }
                                }
                                catch (Exception)
                                {
                                    throw new Exception($"Cannot parse amount '{amount}' - specify either a single value, or a range as 'min-max'.");
                                }

                                // Having parsed that assignment, make it so.
                                (curNode as NarrativeIceConditionNode).AssignArgument(targetIndex, firstAmount, secondAmount);
                            }
                        }
                        else
                        {
                            throw new Exception();  // Should be impossible to hit this but flow control demands that it exist.
                        }
                        // In any of these cases, the current inmost-nested condition set is now this one, and the Tag has been set.
                        curNode.Tag = nodeTag;
                        NestedTagStructure.Push(curNode);
                        CurrentNode = curNode;
                    }
                    else if (nodeWord == NodeType.End)
                    {
                        var nodeTag = currentStr.After(OnSpaceOrColon).ToLower(); // Second word is therefore the tag.

                        if (NestedTagStructure.Peek().Tag != nodeTag)
                        {
                            throw new Exception($"Failure to parse input string - tag {nodeTag} is being closed out of sequence.");
                        }
                        NestedTagStructure.Pop();

                        CurrentNode = new NarrativeEndNode()
                        {
                            Tag = nodeTag
                        };
                    }
                    else if (nodeWord == NodeType.Wait)
                    {
                        TimeSpan waitTime;
                        var      secondWord = currentStr.After(OnSpaceOrColon).ToLower();
                        if (double.TryParse(secondWord, out double value))
                        {
                            waitTime = TimeSpan.FromMilliseconds(value);
                        }
                        else
                        {
                            int      numBeats;
                            TimeSpan oneBeat = TimeSpan.FromMilliseconds(400);
                            if (secondWord == "one")
                            {
                                numBeats = 1;
                            }
                            else if (secondWord == "two")
                            {
                                numBeats = 2;
                            }
                            else if (secondWord == "three")
                            {
                                numBeats = 3;
                            }
                            else if (secondWord == "four")
                            {
                                numBeats = 4;
                            }
                            else
                            {
                                throw new Exception($"Do not understand 'Wait {secondWord}' - use milliseconds instead.");
                            }
                            waitTime = oneBeat.MultipliedBy(numBeats);
                        }

                        CurrentNode = new NarrativeWaitNode()
                        {
                            DelayLength = waitTime
                        };
                    }
                    else if (nodeWord == NodeType.Retry)
                    {
                        var nodeTag = currentStr.After(OnSpaceOrColon).ToLower(); // Second word is therefore the tag.

                        CurrentNode = new NarrativeRetryNode()
                        {
                            Tag = nodeTag
                        };
                    }
                    else if (nodeWord == NodeType.TransitionBy)
                    {
                        var nodeTag = currentStr.After(OnSpaceOrColon).Replace("by ", "").ToLower(); // Second/third word is therefore the tag.

                        CurrentNode = new NarrativeTransitionNode()
                        {
                            Tag = nodeTag
                        };
                    }
                    else if (nodeWord == NodeType.Set)
                    {
                        var argument      = currentStr.After(OnSpace);
                        var variableName  = argument.Before(OnSpaceOrColon);
                        var variableValue = argument.After(OnSpaceOrColon);

                        CurrentNode = new NarrativeSetNode()
                        {
                            Variable = variableName, Value = variableValue
                        };
                    }
                    else if (nodeWord == NodeType.Disconnect)
                    {
                        CurrentNode = new NarrativeDisconnectNode();
                    }
                    else if (nodeWord == NodeType.Then)
                    {
                        CurrentNode = new NarrativeNode(); // Absolute plainest type possible, not worth deriving.  Basically ends up describing a brief pause and/or simply provides logical structure to the author.
                    }

                    // For all of these, the Type of node is simply the node word.  (Type is really only relevant for the Tag type, below.)
                    CurrentNode.Type = nodeWord;
                }
                else if (NestedTagStructure.Peek().Tag == firstWord.ToLower()) // First word is the name of our current most-deeply-nested condition; that's acceptable too.
                {
                    var targetValue = currentStr.After(OnColon).Trim().ToLower();

                    CurrentNode = new NarrativeTagNode()
                    {
                        Type = NodeType.Tag, Tag = firstWord.ToLower(), Value = targetValue
                    };

                    NestedTagStructure.Peek().Alternatives.Add(targetValue, CurrentNode);
                }
                else
                {
                    throw new Exception($"Unable to parse '{currentStr}'!");
                }

                // True for all of these is that the position in the sequence is a cumulative counter, they belong in the narrative list, and their speech string is the bit we parsed out way back at the top.
                CurrentNode.SeqID = seqCounter++;
                CurrentNarrativeList.Add(CurrentNode);
                CurrentNode.SpeechString = speechString;
            }

            // Go through and assign NextNode based on sequence position, with Tag alterna-nodes redirecting to their associated End node, and a nameless Disconnect node as the final one's NextNode.
            foreach (var node in CurrentNarrativeList)
            {
                if (node == CurrentNarrativeList.Last())
                {
                    node.NextNode = new NarrativeDisconnectNode();
                }
                else
                {
                    var naturalNextNode = CurrentNarrativeList[node.SeqID + 1];
                    if (naturalNextNode.Type != NodeType.Tag)
                    {
                        node.NextNode = naturalNextNode;
                    }
                    else
                    {
                        var nodesTag = ((NarrativeTagNode)naturalNextNode).Tag;
                        node.NextNode = CurrentNarrativeList.First(n => n is NarrativeEndNode nEnd && nEnd.Tag == nodesTag);
                    }
                }
            }

            return(CurrentNarrativeList);
        }
    //[UnityEditor.MenuItem("CONTEXT/ReadSceneNames/Update Scene Names")]
    private static void UpdateNames(UnityEditor.MenuCommand command)
    {
        NarrativeNode context = (NarrativeNode)command.context;

        context.scenes = ReadNames();
    }
示例#8
0
 void OnEnable()
 {
     t              = (NarrativeNode)target;
     GetTarget      = new SerializedObject(t);
     transitionList = GetTarget.FindProperty("transitionStates");
 }