diff --git a/Editor/AGS.Editor/Components/FileCommandsComponent.cs b/Editor/AGS.Editor/Components/FileCommandsComponent.cs index b3442b49eab..e2915f67483 100644 --- a/Editor/AGS.Editor/Components/FileCommandsComponent.cs +++ b/Editor/AGS.Editor/Components/FileCommandsComponent.cs @@ -18,6 +18,7 @@ class FileCommandsComponent : BaseComponent private const string MAKE_TEMPLATE_COMMAND = "CreateTemplate"; private const string AUTO_NUMBER_SPEECH_COMMAND = "AutoNumberSpeech"; private const string CREATE_VOICE_ACTING_SCRIPT_COMMAND = "CreateVoiceActingScript"; + private const string EXPORT_GLOBAL_MESSAGES_TO_SCRIPT_COMMAND = "ExportGlobalMessagesToScript"; private const string REMOVE_GLOBAL_MESSAGES_COMMAND = "RemoveGlobalMessages"; private const string RECREATE_SPRITEFILE_COMMAND = "RecreateSpriteFile"; private const string SHOW_PREFERENCES_COMMAND = "ShowPreferences"; @@ -58,7 +59,10 @@ public FileCommandsComponent(GUIController guiController, AGSEditor agsEditor) commands.Commands.Add(new MenuCommand(MAKE_TEMPLATE_COMMAND, "&Make template from this game...", "MenuIconMakeTemplate")); commands.Commands.Add(new MenuCommand(AUTO_NUMBER_SPEECH_COMMAND, "&Auto-number speech lines...", "MenuIconAutoNumber")); commands.Commands.Add(new MenuCommand(CREATE_VOICE_ACTING_SCRIPT_COMMAND, "Create &voice acting script...", "MenuIconVoiceActingScript")); - commands.Commands.Add(new MenuCommand(REMOVE_GLOBAL_MESSAGES_COMMAND, "&Remove Global Messages")); + // TODO: I do not see any way to schedule sub-menus in this system!? + // but if it's supported, maybe put these 2 global messages commands int a submenu + commands.Commands.Add(new MenuCommand(EXPORT_GLOBAL_MESSAGES_TO_SCRIPT_COMMAND, "Export Global Messages to script")); + commands.Commands.Add(new MenuCommand(REMOVE_GLOBAL_MESSAGES_COMMAND, "Remove Global Messages")); commands.Commands.Add(new MenuCommand(RECREATE_SPRITEFILE_COMMAND, "Restore all sprites from sources")); _guiController.AddMenuItems(this, commands); @@ -147,6 +151,13 @@ public override void CommandClick(string controlID) { _guiController.ShowCreateVoiceActingScriptWizard(); } + else if (controlID == EXPORT_GLOBAL_MESSAGES_TO_SCRIPT_COMMAND) + { + if (_guiController.ShowQuestion("This will move any remaining AGS 2.x Global Messages from this game's internal data to the generated script module. This will let you see these texts again and do with them whatever you prefer. But this will also make script commands like DisplayMessage no longer work, and you will have to replace them with contemporary commands for displaying these texts. Are you sure you want to do this?") == DialogResult.Yes) + { + ExportGlobalMessagesToScript(); + } + } else if (controlID == REMOVE_GLOBAL_MESSAGES_COMMAND) { if (_guiController.ShowQuestion("This will remove all traces of AGS 2.x Global Messages from this game. Do not proceed if you are still using any of the Global Messages that you created with a previous version of AGS. Are you sure you want to do this?") == DialogResult.Yes) @@ -188,9 +199,45 @@ public override void RefreshDataFromGame() } } + _guiController.SetMenuItemEnabled(this, EXPORT_GLOBAL_MESSAGES_TO_SCRIPT_COMMAND, globalMessagesExist); _guiController.SetMenuItemEnabled(this, REMOVE_GLOBAL_MESSAGES_COMMAND, globalMessagesExist); } + private void ExportGlobalMessagesToScript() + { + int validMessages = 0; + for (int i = 0; i < _agsEditor.CurrentGame.GlobalMessages.Length; i++) + { + if (!string.IsNullOrEmpty(_agsEditor.CurrentGame.GlobalMessages[i])) + validMessages++; + } + + if (validMessages > 0) + { + string scriptName = _agsEditor.Tasks.GenerateScriptWithGlobalMessages("_GlobalMessages"); + if (scriptName == null) + { + _guiController.ShowMessage("Global Messages were not moved, operation cancelled", MessageBoxIcon.Exclamation); + return; + } + + for (int i = 0; i < _agsEditor.CurrentGame.GlobalMessages.Length; i++) + { + _agsEditor.CurrentGame.GlobalMessages[i] = string.Empty; + } + + _guiController.ShowMessage( + string.Format("{0} Global Messages were moved to a String array in {1}.", + validMessages, scriptName), + MessageBoxIcon.Information); + } + else + { + _guiController.ShowMessage("No valid Global Messages were found, nothing to move.", MessageBoxIcon.Information); + } + RefreshDataFromGame(); // update menu state + } + private void RemoveGlobalMessagesFromGame() { int messagesRemoved = 0; @@ -204,7 +251,7 @@ private void RemoveGlobalMessagesFromGame() } _guiController.ShowMessage(messagesRemoved.ToString() + " Global Messages were removed.", MessageBoxIcon.Information); - _guiController.SetMenuItemEnabled(this, REMOVE_GLOBAL_MESSAGES_COMMAND, false); + RefreshDataFromGame(); // update menu state } private int CountSprites(SpriteFolder folder) diff --git a/Editor/AGS.Editor/Components/ScriptsComponent.cs b/Editor/AGS.Editor/Components/ScriptsComponent.cs index a4132991b22..151b7394560 100644 --- a/Editor/AGS.Editor/Components/ScriptsComponent.cs +++ b/Editor/AGS.Editor/Components/ScriptsComponent.cs @@ -129,17 +129,9 @@ protected override void ItemCommandClick(string controlID) } else if (controlID == MENU_COMMAND_NEW) { - string newFileName = FindFirstAvailableFileName("NewScript"); - Script newScript = new Script(newFileName + ".asc", "// new module script\r\n", false); - Script newHeader = new Script(newFileName + ".ash", "// new module header\r\n", true); - newScript.Modified = true; - newScript.SaveToDisk(); - newHeader.Modified = true; - newHeader.SaveToDisk(); - ScriptAndHeader scripts = new ScriptAndHeader(newHeader, newScript); + var scripts = AddNewScript("NewScript", "// new module header\r\n", "// new module script\r\n"); AddSingleItem(scripts); - _agsEditor.CurrentGame.FilesAddedOrRemoved = true; - _guiController.ProjectTree.BeginLabelEdit(this, ITEM_COMMAND_PREFIX + newScript.NameForLabelEdit); + _guiController.ProjectTree.BeginLabelEdit(this, ITEM_COMMAND_PREFIX + scripts.Script.NameForLabelEdit); } else if (controlID == COMMAND_OPEN_GLOBAL_HEADER) { @@ -157,6 +149,35 @@ protected override void ItemCommandClick(string controlID) } } + /// + /// Adds a new script module (header/script pair) item to the project, + /// finds the first available name based on requested one, + /// assigns header and body text. Returns added Script object. + /// + public ScriptAndHeader AddNewScript(string scriptName, string headerText, string scriptText, bool insertOnTop) + { + var scripts = AddNewScript(scriptName, headerText, scriptText); + if (insertOnTop) + _agsEditor.CurrentGame.RootScriptFolder.Items.Insert(0, scripts); + else + _agsEditor.CurrentGame.RootScriptFolder.Items.Add(scripts); + RePopulateTreeView(); + return scripts; + } + + private ScriptAndHeader AddNewScript(string scriptName, string headerText, string scriptText) + { + string newFileName = FindFirstAvailableFileName(scriptName); + Script newScript = new Script(newFileName + ".asc", scriptText, false); + Script newHeader = new Script(newFileName + ".ash", headerText, true); + newScript.Modified = true; + newScript.SaveToDisk(); + newHeader.Modified = true; + newHeader.SaveToDisk(); + _agsEditor.CurrentGame.FilesAddedOrRemoved = true; + return new ScriptAndHeader(newHeader, newScript); + } + protected override void DeleteResourcesUsedByItem(ScriptAndHeader item) { DeleteScript(item); diff --git a/Editor/AGS.Editor/Tasks.cs b/Editor/AGS.Editor/Tasks.cs index 030bd982c02..4ced87324ec 100644 --- a/Editor/AGS.Editor/Tasks.cs +++ b/Editor/AGS.Editor/Tasks.cs @@ -971,5 +971,51 @@ public void ResizeAllGUIs(System.Drawing.Size oldResolution, System.Drawing.Size } } } + + /// + /// Creates a new script module on top of the list, and generates array of Strings, + /// filling it with the GlobalMessages. If a script of same name exists, tries to + /// find next available name. Returns the resulting script name on success, or + /// null if something went wrong. + /// + public string GenerateScriptWithGlobalMessages(string scriptName) + { + // TODO: make an interface and use FindComponentThatImplementsInterface? + var scriptComponent = Factory.ComponentController.FindComponent(); + if (scriptComponent == null) + return null; + + var game = AGSEditor.Instance.CurrentGame; + var items = game.GlobalMessages; + + // Generate header + StringBuilder sb = new StringBuilder(); + sb.Append("// AUTOGENERATED SCRIPT, but is safe to remove if you are not using it.\r\n"); + sb.Append("// GlobalMessages migrated from AGS 2.x game data\r\n"); + sb.Append("import String GlobalMessages[500];\r\n"); + sb.Append("// Gets global message by a classic message number (where they begin at 500th index)\r\n"); + sb.Append("import String GetMessageByNumber(int message_number);\r\n"); + string headerText = sb.ToString(); + sb.Clear(); + + // Generate script + sb.Append("// AUTOGENERATED SCRIPT, but is safe to remove if you are not using it.\r\n"); + sb.Append("// GlobalMessages migrated from AGS 2.x game data\r\n"); + sb.Append("String GlobalMessages[500];\r\nexport GlobalMessages;\r\n"); + sb.Append("String GetMessageByNumber(int message_number){\r\n"); + sb.Append(" return GlobalMessages[message_number - 500];\r\n"); + sb.Append("}\r\n"); + sb.Append("function game_start(){\r\n"); + sb.Append(" // Initialize global messages\r\n"); + for (int i = 0; i < Math.Min(500, items.Length); ++i) + sb.AppendFormat(" GlobalMessages[{0}] = \"{1}\";\r\n", i, items[i]); + sb.Append("}\r\n"); + string scriptText = sb.ToString(); + + var scripts = scriptComponent.AddNewScript(scriptName, headerText, scriptText, true); + if (scripts == null) + return null; + return scripts.Name; + } } } diff --git a/Editor/AGS.Types/Scripts.cs b/Editor/AGS.Types/Scripts.cs index d7b72a7b5ac..1d21f009428 100644 --- a/Editor/AGS.Types/Scripts.cs +++ b/Editor/AGS.Types/Scripts.cs @@ -67,7 +67,8 @@ private void AddAt(Script newScript, int index) { // Header found, script does not exist and trying to add a script, so add it as its pair. // Note that ScriptAndHeader is immutable so we remove the existing one and add a new one - _scripts.AddAt(new ScriptAndHeader(scriptAndHeaderExisting.Header, newScript), indexExisting); _scripts.Remove(scriptAndHeaderExisting); + _scripts.AddAt(new ScriptAndHeader(scriptAndHeaderExisting.Header, newScript), indexExisting); + _scripts.Remove(scriptAndHeaderExisting); } else if (scriptAndHeaderExisting.Header == null && scriptAndHeaderExisting.Script != null