コード例 #1
0
        public static void CheckFileList(IList <string> paths, List <string> allowedExtensions)
        {
            if (paths.Count == 0)
            {
                MerinoDebug.Log(LoggingLevel.Warning, "No files provided.");
                return;
            }

            var invalid = new List <string>();

            foreach (var path in paths)
            {
                // Does this file exist?
                var exists = System.IO.File.Exists(path);

                // Does this file have the right extension?
                var hasAllowedExtension = allowedExtensions.FindIndex(item => path.EndsWith(item)) != -1;

                if (!exists || !hasAllowedExtension)
                {
                    invalid.Add(string.Format("\"{0}\"", path));
                }
            }

            if (invalid.Count != 0)
            {
                var message = string.Format("The file{0} {1} {2}.",
                                            invalid.Count == 1 ? "" : "s",
                                            string.Join(", ", invalid.ToArray()),
                                            invalid.Count == 1 ? "is not valid" : "are not valid"
                                            );

                MerinoDebug.Log(LoggingLevel.Error, message);
            }
        }
コード例 #2
0
        IEnumerator RunDialogue(string startNode = "Start")
        {
            // Get lines, options and commands from the Dialogue object, one at a time.
            foreach (Yarn.Dialogue.RunnerResult step in dialogue.Run(startNode))
            {
                CurrentNode = dialogue.currentNode;
                if (step is Yarn.Dialogue.LineResult)
                {
                    // Wait for line to finish displaying
                    var lineResult = step as Yarn.Dialogue.LineResult;
                    yield return(this.StartCoroutine(RunLine(lineResult.line)));
                }
                else if (step is Yarn.Dialogue.OptionSetResult)
                {
                    // Wait for user to finish picking an option
                    var optionSetResult = step as Yarn.Dialogue.OptionSetResult;
                    RunOptions(optionSetResult.options, optionSetResult.setSelectedOptionDelegate);
                    yield return(new WaitWhile(() => inputOption < 0));
                }
                else if (step is Yarn.Dialogue.CommandResult)
                {
                    // Wait for command to finish running
                    var commandResult = step as Yarn.Dialogue.CommandResult;
                    yield return(this.StartCoroutine(RunCommand(commandResult.command)));
                }
            }

            MerinoDebug.Log(LoggingLevel.Info, "Reached the end of the dialogue.");
            CurrentNode = null;

            // No more results! The dialogue is done.
            yield return(new WaitUntil(() => MerinoPrefs.stopOnDialogueEnd));

            StopPlaytest_Internal();
        }
コード例 #3
0
ファイル: MerinoData.cs プロジェクト: koloquials/capstone
		public static TextAsset GetDefaultData()
		{
			var defaultData = Resources.Load<TextAsset>(MerinoPrefs.newFileTemplatePath);
			if (defaultData == null)
			{
				MerinoDebug.Log(LoggingLevel.Warning, "Merino couldn't find the new file template at Resources/" + MerinoPrefs.newFileTemplatePath + ". Double-check the file exists there, or you can override this path in EditorPrefs.");
				return null;
			}
			return defaultData;
		}
コード例 #4
0
ファイル: MerinoCore.cs プロジェクト: koloquials/capstone
        // strip forbidden characters from node titles
        public static string CleanNodeTitle(string newName)
        {
            // v0.6, added regex to disallow forbidden characters in node titles
            string newNameClean = Regex.Replace(newName, forbiddenCharactersInNodeTitles_regex, "");

            if (newName.Length != newNameClean.Length)
            {
                // GUI.Label( GUILayoutUtility.GetLastRect(), new GUIContent("Yarn node titles cannot use <>[]{}|:#$ or whitespace", helpIcon), EditorStyles.helpBox );
                MerinoDebug.Log(LoggingLevel.Verbose, "Merino stripped forbidden characters <>[]{}|:#$ (and whitespace) from your node title.\n" + newName + " ... " + newNameClean);
                return(newNameClean);
            }
            return(newName);
        }
コード例 #5
0
ファイル: MerinoData.cs プロジェクト: koloquials/capstone
		public static TextAsset LoadYarnFileAtFullPath(string path, bool isRelativePath=false)
		{
			var newFile = AssetDatabase.LoadAssetAtPath<TextAsset>( isRelativePath ? path : "Assets" + path.Substring(Application.dataPath.Length) );
			if (MerinoData.CurrentFiles.Contains(newFile) == false)
			{
				MerinoData.CurrentFiles.Add(newFile);
			}
			else
			{
				MerinoDebug.Log(LoggingLevel.Warning, "Merino: file at " + path + " is already loaded!");
			}

			return newFile;
		}
コード例 #6
0
        private void InitIfNeeded()
        {
            // create the main Dialogue runner, and pass our variableStorage to it
            varStorage = new MerinoVariableStorage();
            dialogue   = new Yarn.Dialogue(varStorage);

            // setup the logging system.
            dialogue.LogDebugMessage = message => MerinoDebug.Log(LoggingLevel.Verbose, message);
            dialogue.LogErrorMessage = PlaytestErrorLog;

            // icons
            if (errorIcon == null)
            {
                errorIcon = EditorGUIUtility.Load("icons/d_console.erroricon.sml.png") as Texture;
            }
        }
コード例 #7
0
        /// <summary>
        /// Logs errors from the playtest engine and Yarn Loader.
        /// </summary>
        public void PlaytestErrorLog(string message)
        {
            string fileName   = "unknown";
            string nodeName   = "unknown";
            int    lineNumber = -1;

            // detect file name
            if (message.Contains("file"))
            {
                fileName = message.Split(new string[] { "file" }, StringSplitOptions.None)[1].Split(new string[] { " ", ":" }, StringSplitOptions.None)[1];
            }

            // detect node name
            if (message.Contains("node"))
            {
                nodeName = message.Split(new string[] { "node" }, StringSplitOptions.None)[1].Split(new string[] { " ", ":" }, StringSplitOptions.None)[1];

                // detect line numbers, if any, by grabbing the first digit after nodeName
                string numberLog = "";
                for (int index = message.IndexOf(nodeName); index < message.Length; index++)
                {
                    if (Char.IsDigit(message[index]))
                    {
                        numberLog += message[index];
                    }
                    else if (numberLog.Length > 0)                      // did we hit a non-number, after already hitting numbers? then stop
                    {
                        break;
                    }
                }

                int.TryParse(numberLog, out lineNumber);
            }

            var nodeRef = MerinoData.TreeElements.Find(x => x.name == nodeName);

            // v0.6, resolved: "todo: replace "<input>" in parsing errors with the name of the file instead."
            // if filename is default "<input>" then guess filename via cached parentID data in TreeElements
            if (fileName == "<input>" && nodeRef != null)
            {
                fileName = MerinoData.GetFileParent(nodeRef.id).name;
            }

            MerinoEditorWindow.errorLog.Add(new MerinoEditorWindow.MerinoErrorLine(message, fileName, nodeRef != null ? nodeRef.id : -1, Mathf.Max(0, lineNumber)));
            MerinoDebug.Log(LoggingLevel.Error, message);
        }
コード例 #8
0
        public static void ConvertNodesInFile(ConvertFormatOptions options, string file, string fileExtension, ConvertNodesToText convert)
        {
            //	var d = new Dialogue(null);

            var text = File.ReadAllText(file);

            IEnumerable <YarnSpinnerLoader.NodeInfo> nodes;

            try {
                nodes = YarnSpinnerLoader.GetNodesFromText(text, YarnSpinnerLoader.GetFormatFromFileName(file));
            } catch (FormatException e) {
                MerinoDebug.Log(LoggingLevel.Error, e.Message);
                return;
            }

            var serialisedText = convert(nodes);

            var destinationDirectory = options.outputDirectory;

            if (destinationDirectory == null)
            {
                destinationDirectory = Path.GetDirectoryName(file);
            }

            var fileName = Path.GetFileName(file);

            // ChangeExtension thinks that the file "Foo.yarn.txt" has the extension "txt", so
            // to simplify things, just lop that extension off right away if it's there
            fileName = fileName.Replace(".yarn.txt", "");

            // change the filename's extension
            fileName = Path.ChangeExtension(fileName, fileExtension);

            // figure out where we're writing this file
            var destinationFilePath = Path.Combine(destinationDirectory, fileName);

            File.WriteAllText(destinationFilePath, serialisedText);

            if (options.verbose)
            {
                MerinoDebug.Log(LoggingLevel.Verbose, "Wrote " + destinationFilePath);
            }
        }
コード例 #9
0
 public static void SaveDataToFiles()
 {
     if (MerinoData.CurrentFiles.Count > 0)
     {
         foreach (var file in MerinoData.CurrentFiles)
         {
             if (MerinoData.FileToNodeID.ContainsKey(file))
             {
                 File.WriteAllText(AssetDatabase.GetAssetPath(file), SaveFileNodesAsString(MerinoData.FileToNodeID[file]));
                 EditorUtility.SetDirty(file);
                 LastSaveTime = EditorApplication.timeSinceStartup;
             }
             else
             {
                 MerinoDebug.Log(LoggingLevel.Warning, file.name + " has not been mapped to a NodeID and cannot be saved, reload the file and try again.");
             }
         }
     }
 }
コード例 #10
0
        /// <summary>
        /// Logs errors from the playtest engine and Yarn Loader.
        /// </summary>
        public void PlaytestErrorLog(string message)
        {
            string fileName   = "unknown";
            string nodeName   = "unknown";
            int    lineNumber = -1;

            // detect file name
            if (message.Contains("file"))
            {
                fileName = message.Split(new string[] { "file" }, StringSplitOptions.None)[1].Split(new string[] { " ", ":" }, StringSplitOptions.None)[1];
            }

            // detect node name
            if (message.Contains("node"))
            {
                nodeName = message.Split(new string[] { "node" }, StringSplitOptions.None)[1].Split(new string[] { " ", ":" }, StringSplitOptions.None)[1];

                // detect line numbers, if any, by grabbing the first digit after nodeName
                string numberLog = "";
                for (int index = message.IndexOf(nodeName); index < message.Length; index++)
                {
                    if (Char.IsDigit(message[index]))
                    {
                        numberLog += message[index];
                    }
                    else if (numberLog.Length > 0)                      // did we hit a non-number, after already hitting numbers? then stop
                    {
                        break;
                    }
                }

                int.TryParse(numberLog, out lineNumber);
            }

            // also output to Unity console
            var nodeRef = MerinoData.TreeElements.Find(x => x.name == nodeName);

            MerinoEditorWindow.errorLog.Add(new MerinoEditorWindow.MerinoErrorLine(message, fileName, nodeRef != null ? nodeRef.id : -1, Mathf.Max(0, lineNumber)));
            MerinoDebug.Log(LoggingLevel.Error, message);
        }
コード例 #11
0
ファイル: MerinoCore.cs プロジェクト: koloquials/capstone
        public static void SaveDataToFiles()
        {
            if (MerinoData.CurrentFiles.Count > 0)
            {
                for (int i = 0; i < MerinoData.CurrentFiles.Count; i++)
                {
                    TextAsset file = MerinoData.CurrentFiles[i];
                    if (MerinoData.FileToNodeID.ContainsKey(file))
                    {
                        if (file == null)
                        {
                            var missingDataID = MerinoData.FileToNodeID[file];
                            MerinoData.DirtyFiles.Remove(file);                             // wait how does this work? it's null, but the pointer isn't?
                            MerinoData.CurrentFiles.RemoveAt(i);
                            i--;
                            var missingFileName = MerinoData.GetNode(missingDataID) != null?MerinoData.GetNode(missingDataID).name : "<cannot recover filename>";

                            if (EditorUtility.DisplayDialog("Can't save file " + missingFileName, "The file has been deleted, moved outside of the project's assets folder, or otherwise hidden. Merino can't find it.", "Save backup of current data as new file", "Do nothing"))
                            {
                                MerinoEditorWindow.GetEditorWindow().CreateNewYarnFile("YarnBackupOfFile", SaveAllNodesAsString(missingDataID));
                            }
                            continue;
                        }
                        else
                        {
                            File.WriteAllText(AssetDatabase.GetAssetPath(file), SaveFileNodesAsString(MerinoData.FileToNodeID[file]));
                            EditorUtility.SetDirty(file);
                            LastSaveTime = EditorApplication.timeSinceStartup;
                        }
                    }
                    else
                    {
                        MerinoDebug.Log(LoggingLevel.Warning, file.name + " has not been mapped to a NodeID and cannot be saved, reload the file and try again.");
                    }
                }
                EditorUtility.SetDirty(MerinoData.Instance);
            }
        }
コード例 #12
0
ファイル: MerinoCore.cs プロジェクト: koloquials/capstone
        // ensure unique node titles, very important for YarnSpinner
        private static void ValidateNodeTitles(List <MerinoTreeElement> nodes = null)
        {
            if (!MerinoPrefs.validateNodeTitles)
            {
                return;
            }

            if (nodes == null)             // if null, then let's just use all currently loaded nodes
            {
                nodes = MerinoData.TreeElements;
            }

            // make sure we're not doing this to any folder or file nodes, ONLY YARN NODES
            nodes = nodes.Where(x => x.leafType == MerinoTreeElement.LeafType.Node).ToList();

            // validate data: ensure unique node names
            var  nodeTitles     = new Dictionary <int, string>();      // index, newTitle
            var  duplicateCount = new Dictionary <string, int>();      // increment counter for each duplicate name, and use for rename suffix
            bool foundDuplicate = false;

            for (int i = 0; i < nodes.Count; i++)
            {
                // if there's a node already with that name, then append unique suffix
                if (nodeTitles.Values.Contains(nodes[i].name))
                {
                    // count duplicates
                    if (!duplicateCount.ContainsKey(nodes[i].name))
                    {
                        duplicateCount.Add(nodes[i].name, 2);
                    }

                    // when we make a new name, we have to ensure it's unique...
                    if (nodeTitles.ContainsKey(nodes[i].id) == false)
                    {
                        nodeTitles.Add(nodes[i].id, nodes[i].name);
                    }

                    nodeTitles[nodes[i].id] = nodes[i].name + "_" + duplicateCount[nodes[i].name]++;
                    foundDuplicate          = true;
                }                 // but if there's not already a node with that name, we should still make a note of it
                else if (nodeTitles.ContainsKey(nodes[i].id) == false)
                {
                    nodeTitles.Add(nodes[i].id, nodes[i].name);
                }
            }

            if (foundDuplicate)
            {
                string renamedNodes = "Merino found nodes with duplicate names (which aren't allowed for Yarn) and renamed them. This might break node links, you can undo it. The following nodes were renamed: ";
                Undo.RecordObject(MerinoData.Instance, "Merino: AutoRename");

                foreach (var kvp in nodeTitles)
                {
                    if (MerinoData.TreeElements[kvp.Key].name != kvp.Value)
                    {
                        renamedNodes += string.Format("\n* {0} > {1}", MerinoData.TreeElements[kvp.Key].name, kvp.Value);
                        MerinoData.TreeElements[kvp.Key].name = kvp.Value;
                    }
                }
                EditorUtility.SetDirty(MerinoData.Instance);
                MerinoDebug.Log(LoggingLevel.Warning, renamedNodes);
                //todo: repaint MerinoEditorWindow tree view so names get updated

                // this is bad, but we're gonna do some recursion here, just to make extra sure there's STILL no duplicates...
                ValidateNodeTitles(MerinoData.TreeElements);
            }
            else if (MerinoPrefs.useAutosave)
            {
                SaveDataToFiles();
            }
        }