Example #1
0
    /// execute the current DialogPiece <br/> stops at Text and Choice pieces
    private void ExecuteDialog()
    {
        Dictionary <int, bool> jumped = new Dictionary <int, bool>();

again:

        if (dialogIndex >= currentDialog.Length)
        {
            // no more dialog
            inDialog = false;
            gameObject.SetActive(false);

            if (onDialogComplete != null)
            {
                onDialogComplete();
            }

            //erase all active sprites
            foreach (GameObject image in currentDialogSprites.Values)
            {
                GameObject.Destroy(image);
            }
            currentDialogSprites.Clear();

            return;
        }

        DialogPiece p = currentDialog[dialogIndex];

        if (p.type == DialogPieceType.Text)
        {
            TextDialogPiece piece = p as TextDialogPiece;

            speaking    = true;
            currentLine = piece.text;
            letterIndex = 0;
            letterTimer = 0;

            dialogText.text = "";

            continueArrow.SetActive(false);

            if (piece.charName != "")
            {
                nameBox.SetActive(true);
                nameText.text = piece.charName;

                if (currentDialogSprites.TryGetValue(piece.charName.ToLower(), out GameObject image))
                {
                    if (activeSprite)
                    {
                        activeSprite.GetComponent <Image>().CrossFadeAlpha(transparentSpriteAlpha, spriteFadeDuration, true);
                    }

                    if (!String.IsNullOrEmpty(piece.expression))
                    {
                        SetImageSprite(image, GetCharacterSprite(piece.charName, piece.expression, piece.line));
                    }

                    image.GetComponent <Image>().CrossFadeAlpha(1, spriteFadeDuration, true);
                    activeSprite = image;
                }
                else
                {
                    if (!String.IsNullOrEmpty(piece.expression))
                    {
                        throw new DialogException(piece.line, "character '" + piece.charName + "' doesn't have a sprite");
                    }
                }
            }
            else
            {
                nameBox.SetActive(false);
            }
        }
        else if (p.type == DialogPieceType.Choice)
        {
            ChoiceDialogPiece piece = p as ChoiceDialogPiece;

            foreach (Transform oldBtn in choiceContainer.transform)
            {
                GameObject.Destroy(oldBtn.gameObject);
            }

            float totalHeight = 0;

            for (int i = 0; i < piece.choices.Count; i++)
            {
                ChoiceTextPositionPair pair = piece.choices[i];
                Transform newButton         = Instantiate(choiceButtonPrefab, choiceContainer).transform;
                newButton.localPosition = new Vector3(0, -i * (choiceButtonHeight + choiceButtonMargin), 0);

                newButton.GetChild(0).GetComponent <Text>().text = pair.text;

                newButton.GetComponent <DialogOptionButton>().onClick.AddListener(delegate
                {
                    continueArrow.transform.localScale = new Vector3(1, 1, 1);
                    choiceBox.SetActive(false);

                    inChoice    = false;
                    dialogIndex = pair.position;
                    ExecuteDialog();
                });

                totalHeight += choiceButtonHeight + (i < piece.choices.Count - 1 ? choiceButtonMargin : 0);
            }

            choiceContainer.transform.localPosition = new Vector3(0, totalHeight / 2, 0);

            inChoice = true;

            continueArrow.transform.localScale = new Vector3(1, -1, 1);

            choiceBox.SetActive(true);
        }
        else if (p.type == DialogPieceType.Jump)
        {
            JumpDialogPiece piece = p as JumpDialogPiece;

            if (jumped.ContainsKey(piece.jumpTo))
            {
                throw new DialogException(piece.line, "infinite jump loop");
            }

            jumped.Add(piece.jumpTo, true);
            dialogIndex = piece.jumpTo;

            goto again;
        }
        else if (p.type == DialogPieceType.Sprite)
        {
            SpriteDialogPiece piece = p as SpriteDialogPiece;

            if (piece.filename != "" && !dialogSpriteFilenames.ContainsKey(piece.character.ToLower()))
            {
                dialogSpriteFilenames.Add(piece.character.ToLower(), piece.filename);
            }

            Sprite sprite = GetCharacterSprite(piece.character, piece.expression, piece.line);

            if (activeSprite)
            {
                activeSprite.GetComponent <Image>().CrossFadeAlpha(transparentSpriteAlpha, spriteFadeDuration, true);
            }

            GameObject image;
            if (!currentDialogSprites.ContainsKey(piece.character))
            {
                //create the object if it doesn't exist
                image = new GameObject(piece.character + " sprite");
                Image newImage = image.AddComponent <Image>();
                currentDialogSprites.Add(piece.character, image);
                RectTransform rect = image.GetComponent <RectTransform>();
                rect.SetParent(this.transform);
                rect.SetSiblingIndex(0);

                newImage.canvasRenderer.SetAlpha(0);
            }
            else
            {
                image = currentDialogSprites[piece.character];
            }

            activeSprite = image;

            image.GetComponent <Image>().CrossFadeAlpha(1, spriteFadeDuration, true);
            image.transform.localPosition = SpritePositions[piece.position].localPosition;
            SetImageSprite(image, sprite);

            dialogIndex++;
            goto again;
        }
    }
Example #2
0
    /// parses a dialog script into an array of DialogPieces
    public static DialogPiece[] ParseDialog(string dialogText, char newLine = '\n')
    {
        string[] lines = dialogText.Split(newLine);

        List <DialogPiece> pieces = new List <DialogPiece>();

        Dictionary <string, int> labels = new Dictionary <string, int>();

        // stores references to labels that haven't been defined yet, and what should happen when they're defined
        Dictionary <string, List <LabelReference> > labelReferences = new Dictionary <string, List <LabelReference> >();

        void LabelRef(string label, int line, Action <int> action)
        {
            //if the label is already defined, execute the action immediately
            //otherwise, store it in references for later
            if (labels.TryGetValue(label, out int position))
            {
                action(position);
            }
            else
            {
                if (!labelReferences.ContainsKey(label))
                {
                    labelReferences.Add(label, new List <LabelReference>());
                }
                labelReferences[label].Add(new LabelReference(line, action));
            }
        }

        for (int i = 0; i < lines.Length; i++)
        {
            string l = lines[i].Trim();

            //ignore empty lines
            if (String.IsNullOrWhiteSpace(l))
            {
                continue;
            }

            if (l[0] == '@')
            {
                //label

                string labelName = l.Substring(1);
                if (labels.ContainsKey(labelName))
                {
                    throw new DialogParseException(i, "label '" + labelName + "' is defined more than once");
                }

                int position = pieces.Count;

                if (labelReferences.TryGetValue(labelName, out List <LabelReference> references))
                {
                    foreach (LabelReference labelRef in references)
                    {
                        labelRef.action(position);
                    }

                    labelReferences.Remove(labelName);
                }

                labels[labelName] = position;
            }
            else if (l[0] == '?')
            {
                //choice

                string[] options;

                if (l == "?")
                {
                    List <string> opList = new List <string>();
                    while (true)
                    {
                        i++;
                        string op = lines[i].Trim();
                        if (op == String.Empty)
                        {
                            continue;
                        }
                        opList.Add(op[op.Length - 1] == ',' ? op.Substring(0, op.Length - 1) : op);
                        if (op[op.Length - 1] != ',')
                        {
                            break;
                        }
                    }
                    options = opList.ToArray();
                }
                else
                {
                    options = l.Substring(1).Split(',');
                }

                List <ChoiceTextPositionPair> choices = new List <ChoiceTextPositionPair>();

                for (int o = 0; o < options.Length; o++)
                {
                    string option = options[o].Trim();

                    string text  = option.Substring(0, option.IndexOf(':')).Trim();
                    string label = option.Substring(option.IndexOf(':') + 1).Trim();

                    if (label == "next")
                    {
                        choices.Add(new ChoiceTextPositionPair(text, pieces.Count + 1));
                    }
                    else
                    {
                        LabelRef(label, i, position => choices.Add(new ChoiceTextPositionPair(text, position)));
                    }
                }

                ChoiceDialogPiece thePiece = new ChoiceDialogPiece(i, choices);

                pieces.Add(thePiece);
            }
            else if (l[0] == '>')
            {
                //jump

                string labelName = l.Substring(1).Trim();

                JumpDialogPiece thePiece = new JumpDialogPiece(i, 0);

                LabelRef(labelName, i, position => thePiece.jumpTo = position);

                pieces.Add(thePiece);
            }
            else if (l[0] == '!')
            {
                //misc command

                string command = l.Substring(1, l.IndexOf(' ') - 1);

                string rest = l.Substring(command.Length + 2).Trim();

                if (command == "sprite")
                {
                    int colon = rest.IndexOf(':');
                    int comma = rest.IndexOf(',');
                    //comma = comma == -1 ? rest.Length : comma;
                    string character = rest.Substring(0, colon).Trim().ToLower();
                    string alias     = "";
                    if (character.Contains("-"))
                    {
                        int hyphen = character.IndexOf('-');

                        alias     = character.Substring(hyphen + 1);
                        character = character.Substring(0, hyphen);
                    }

                    string position   = rest.Substr(colon + 1, comma == -1 ? rest.Length : comma).Trim().ToLower();
                    string expression = comma == -1 ? "" : rest.Substring(comma + 1).Trim().ToLower();

                    pieces.Add(new SpriteDialogPiece(i, character, position, expression, alias));
                }
            }
            else
            {
                //normal dialog

                if (!l.Contains(":"))
                {
                    throw new DialogParseException(i, "invalid line syntax");
                }

                int    colon      = l.IndexOf(':');
                string charName   = l.Substring(0, colon);
                string expression = "";
                int    paren      = charName.IndexOf('(');
                if (paren != -1)
                {
                    expression = charName.Substr(paren + 1, charName.IndexOf(')'));
                    charName   = charName.Substring(0, paren).Trim();
                }

                string messageText = l.Substring(colon + 1).Trim();

                pieces.Add(new TextDialogPiece(i, charName, messageText, expression));
            }
        }

        //if there are any references still left, it means their labels don't exist
        foreach (var kvp in labelReferences)
        {
            throw new DialogParseException(kvp.Value[0].line, "undefined label '" + kvp.Key + "'");
        }

        return(pieces.ToArray());
    }