From 88f5c353cbbac11b6be24408ddd88938fe792757 Mon Sep 17 00:00:00 2001 From: Kevin Eady <8634912+KevinEady@users.noreply.github.com> Date: Thu, 12 Aug 2021 19:32:38 +0200 Subject: [PATCH 01/10] Add GumpStudio submodule --- .gitmodules | 3 +++ GumpStudio | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 GumpStudio diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..d91a18dd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "GumpStudio"] + path = GumpStudio + url = https://github.com/KevinEady/GumpStudio.git diff --git a/GumpStudio b/GumpStudio new file mode 160000 index 00000000..44dc30a2 --- /dev/null +++ b/GumpStudio @@ -0,0 +1 @@ +Subproject commit 44dc30a2e4c3b0378d6c09746b83e318586d0563 From ffe8ff67ea67fa8c13c249c4c20f9e440f5e9ac1 Mon Sep 17 00:00:00 2001 From: Kevin Eady <8634912+KevinEady@users.noreply.github.com> Date: Thu, 12 Aug 2021 20:08:28 +0200 Subject: [PATCH 02/10] update submodule --- GumpStudio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GumpStudio b/GumpStudio index 44dc30a2..5d2f7fa5 160000 --- a/GumpStudio +++ b/GumpStudio @@ -1 +1 @@ -Subproject commit 44dc30a2e4c3b0378d6c09746b83e318586d0563 +Subproject commit 5d2f7fa5d6dbb77a7aa77cd9cce44c88378a4577 From e7f9547b93f69ccd6ed5d94289aff9f2054e534a Mon Sep 17 00:00:00 2001 From: Kevin Eady <8634912+KevinEady@users.noreply.github.com> Date: Thu, 12 Aug 2021 21:21:01 +0200 Subject: [PATCH 03/10] Fix building --- .gitignore | 9 + POLExportPlugin/Class1.cs | 1450 +++++++++++++------------- POLExportPlugin/GumpStudio.csproj | 105 ++ POLExportPlugin/GumpStudioCore.dll | Bin 361472 -> 0 bytes POLExportPlugin/POLGumpExport.csproj | 20 +- POLExportPlugin/POLGumpExport.sln | 27 +- 6 files changed, 880 insertions(+), 731 deletions(-) create mode 100644 POLExportPlugin/GumpStudio.csproj delete mode 100644 POLExportPlugin/GumpStudioCore.dll diff --git a/.gitignore b/.gitignore index e70a3a9d..13f7162e 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,12 @@ runecl.exe scripts/eCompile_commands.txt scripts/ecompile.cfg.example scripts/modules/* + +# Output folders + +bin +obj + +# IDE Folders + +.vs diff --git a/POLExportPlugin/Class1.cs b/POLExportPlugin/Class1.cs index 7b82a11e..ddf24b80 100644 --- a/POLExportPlugin/Class1.cs +++ b/POLExportPlugin/Class1.cs @@ -1,724 +1,726 @@ -/* Copyright (c) 2004-2006 Francesco Furiani & Mark Chandler - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software - * is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR - * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Modified by Fernando Rozenblit in 2008 to create POL Scripts. - * - * Rewrote some parts of Class1.cs for a better reading / updating - * - * TODO: Add distro pkg support - */ - -/* - * Modified by David Gardner on 2018-12-05 to add additional functionality. - * - * - Added TextEntryLimited for both the barebones style and distro pkg style - * - Added support for gumppictiled for the distro pkg style - * - Fixed an invalid placeholder warning in: Gump_WriteGumpPic(ImageElement elem) - * - Modified the html gump element for distro pkg style output to place the boolean values of showbackground - * and scroll bar regardless of whether they are true or false, probably a personal preference. - */ - - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Windows.Forms; -using GumpStudio; -using GumpStudio.Elements; -using GumpStudio.Plugins; -using Ultima; - -namespace POLGumpExport -{ - public class POLExporter : BasePlugin - { - protected DesignerForm m_Designer; - protected MenuItem mnu_FileExportPOLExport; - protected MenuItem mnu_MenuItem; - protected POLExportForm frm_POLExportForm; - - private bool bGetDefaultText = false; - - public override string Name - { - get - { - return this.GetPluginInfo().PluginName; - } - } - - public override PluginInfo GetPluginInfo() - { - PluginInfo pluginInfo = new PluginInfo(); - pluginInfo.AuthorEmail = "rozenblit@gmail.com"; - pluginInfo.AuthorName = "Fernando Rozenblit"; - pluginInfo.Description = "Exports the Gump into a POL script. Based on Sphere Exporter by Francesco Furiani & Mark Chandler."; - pluginInfo.PluginName = "POLGumpExporter"; - pluginInfo.Version = "1.1"; - return pluginInfo; - } - - public override void Load(DesignerForm frmDesigner) - { - this.m_Designer = frmDesigner; - this.mnu_FileExportPOLExport = new MenuItem("POL"); - this.mnu_FileExportPOLExport.Click += new EventHandler(this.mnu_FileExportPOLExport_Click); - if ( !this.m_Designer.mnuFileExport.Enabled ) - { - this.m_Designer.mnuFileExport.Enabled = true; - } - this.m_Designer.mnuFileExport.MenuItems.Add(this.mnu_FileExportPOLExport); - base.Load(frmDesigner); - } - - private void mnu_FileExportPOLExport_Click(object sender, EventArgs e) - { - frm_POLExportForm = new POLExportForm(this); - frm_POLExportForm.ShowDialog(); - } - - public StringWriter GetPOLScript(bool bUsedistro) - { - return GetPOLScript(bUsedistro, true, true, true); - } - - public StringWriter GetPOLScript(bool bUseDistro, bool bShowComment, bool bShowNames, bool bDefaultTexts) - { - if (bUseDistro) return CreateDistroScript(bShowComment, bShowNames, bDefaultTexts); - else return CreateBareScript(); - } - - private string GetCommentString(BaseElement be_elem, bool bShowComments, bool bShowNames) - { - if (be_elem == null) - return ""; - - string elem_comment = ""; - string elem_name = ""; - string comment = ""; - - if (be_elem.Comment != null) - elem_comment = be_elem.Comment; - - if (bShowNames) { - if (be_elem.Name != null) - elem_name = be_elem.Name; - - comment = be_elem.Name + ((elem_comment != String.Empty && bShowComments) ? ": " : ""); - } - if (bShowComments) - comment += elem_comment; - - return "// " + comment; - } - - private string GetGumpName() - { - string gump_name = frm_POLExportForm.GumpName; - string default_name = "gump"; - string[] words = null; - - if (gump_name != null) - if (gump_name != String.Empty) - words = gump_name.Split(new char[]{' '},StringSplitOptions.RemoveEmptyEntries); - - if (words == null) - return default_name; - - if (words.Length > 0) - return words[0]; - - return default_name; - } - - private StringWriter CreateDistroScript(bool bShowComment, bool bShowNames, bool bDefaultTexts) - { - StringWriter sw_Script = new StringWriter(); - List GumpCommands = new List(); - - bGetDefaultText = bDefaultTexts; // define if plugin will set default text for empty elems - - string gump_name = GetGumpName(); - - GumpCommands.Add(DistroGump_GFCreateGump(gump_name, m_Designer.GumpProperties.Location)); - GumpCommands.Add(""); - if (!m_Designer.GumpProperties.Moveable) - GumpCommands.Add(String.Format("GFMovable( {0}, 0 );", gump_name)); - - if (!m_Designer.GumpProperties.Closeable) - GumpCommands.Add(String.Format("GFClosable( {0}, 0 );", gump_name)); - - if (!m_Designer.GumpProperties.Disposeable) - GumpCommands.Add(String.Format("GFDisposable( {0}, 0 );", gump_name)); - - - if (m_Designer.Stacks.Count > 0) - { - int radiogroup = -1; - int pageindex = 0; - // ================= - - foreach (GroupElement ge_Elements in m_Designer.Stacks) - { - if (pageindex > 0) - GumpCommands.Add(""); - - GumpCommands.Add(DistroGump_GFPage(gump_name, ref pageindex)); // "page pageid" - if (ge_Elements == null) - continue; - - foreach (BaseElement be_Element in ge_Elements.GetElementsRecursive()) - { - if (be_Element == null) - continue; - - if (bShowComment || bShowNames) - { - string comment = GetCommentString(be_Element, bShowComment, bShowNames); - if (comment != String.Empty) - { - GumpCommands.Add(""); - GumpCommands.Add(comment); - } - } - - Type ElementType = be_Element.GetType(); - - if (ElementType == typeof(HTMLElement)) - { - HTMLElement elem = be_Element as HTMLElement; - if (elem.TextType == HTMLElementType.HTML) - GumpCommands.Add(DistroGump_GFHTMLArea(gump_name, elem)); - else - GumpCommands.Add(DistroGump_GFAddHTMLLocalized(gump_name, elem)); - } - else if (ElementType == typeof(TextEntryElement)) - { - TextEntryElement elem = be_Element as TextEntryElement; - GumpCommands.Add(DistroGump_GFTextEntry(gump_name, elem)); - } - else if (ElementType == typeof(LabelElement)) - { - LabelElement elem = be_Element as LabelElement; - GumpCommands.Add(DistroGump_GFTextLine(gump_name, elem)); - } - - else if (ElementType == typeof(AlphaElement)) - { - AlphaElement elem = be_Element as AlphaElement; - GumpCommands.Add(DistroGump_GFAddAlphaRegion(gump_name, elem)); - } - else if (ElementType == typeof(BackgroundElement)) - { - BackgroundElement elem = be_Element as BackgroundElement; - GumpCommands.Add(DistroGump_GFResizePic(gump_name, elem)); - } - else if (ElementType == typeof(ImageElement)) - { - ImageElement elem = be_Element as ImageElement; - GumpCommands.Add(DistroGump_GFGumpPic(gump_name, elem)); - } - else if (ElementType == typeof(ItemElement)) - { - ItemElement elem = be_Element as ItemElement; - GumpCommands.Add(DistroGump_GFTilePic(gump_name, elem)); - } - else if (ElementType == typeof(TiledElement)) - { - TiledElement elem = be_Element as TiledElement; - GumpCommands.Add(DistroGump_GFPicTiled(gump_name, elem)); - } - - else if (ElementType == typeof(ButtonElement)) - { - ButtonElement elem = be_Element as ButtonElement; - GumpCommands.Add(DistroGump_GFAddButton(gump_name, elem)); - } - - else if (ElementType == typeof(CheckboxElement)) - { - CheckboxElement elem = be_Element as CheckboxElement; - GumpCommands.Add(DistroGump_GFCheckBox(gump_name, elem)); - } - else if (ElementType == typeof(RadioElement)) - { - RadioElement elem = be_Element as RadioElement; - if (elem.Group != radiogroup) - { - GumpCommands.Add(String.Format("GFSetRadioGroup( {0}, {1} );", gump_name, elem.Group)); - radiogroup = elem.Group; - } - GumpCommands.Add(DistroGump_GFRadioButton(gump_name, elem)); - } - } - } - } - - - sw_Script.WriteLine("// Created {0}, with Gump Studio.", DateTime.Now); - sw_Script.WriteLine("// Exported with {0} ver {1} for gump pkg", this.GetPluginInfo().PluginName, this.GetPluginInfo().Version); - sw_Script.WriteLine(); - sw_Script.WriteLine("use uo;"); - sw_Script.WriteLine("use os;"); - sw_Script.WriteLine(); - sw_Script.WriteLine("include \":gumps:gumps\";"); - sw_Script.WriteLine(); - sw_Script.WriteLine("program gump_{0}( who )", gump_name); - sw_Script.WriteLine(); - - foreach (string cmd in GumpCommands) - { - sw_Script.WriteLine("\t"+cmd); - } - sw_Script.WriteLine(); - sw_Script.WriteLine("\tGFSendGump( who, {0} );", gump_name); - sw_Script.WriteLine(); - sw_Script.WriteLine("endprogram"); - - - return sw_Script; - } - - #region Distro pkg commands - private string DistroGump_GFRadioButton(string gump_name, RadioElement elem) - { - return String.Format("GFRadioButton( {0}, {1}, {2}, {3}, {4}, {5}, {6} );", gump_name, elem.X, elem.Y, elem.UnCheckedID, elem.CheckedID, BoolToString(elem.Checked), elem.Value); - } - - private string DistroGump_GFCheckBox(string gump_name, CheckboxElement elem) - { - return String.Format("GFCheckBox( {0}, {1}, {2}, {3}, {4}, {5}, {6} );", gump_name, elem.X, elem.Y, elem.UnCheckedID, elem.CheckedID, BoolToString(elem.Checked), elem.Group); - } - - private string DistroGump_GFAddButton(string gump_name, ButtonElement elem) - { - string btn_type = ""; - if (elem.ButtonType == ButtonTypeEnum.Page) - btn_type = "GF_PAGE_BTN"; - else - btn_type = "GF_CLOSE_BTN"; - - return String.Format("GFAddButton( {0}, {1}, {2}, {3}, {4}, {5}, {6} );", gump_name, elem.X, elem.Y, elem.NormalID, elem.PressedID, btn_type, elem.Param); - } - - private string DistroGump_GFTilePic(string gump_name, ItemElement elem) - { - string hue = (elem.Hue != null) ? elem.Hue.Index.ToString() : "0"; - return String.Format("GFTilePic( {0}, {1}, {2}, {3}, {4} );", gump_name, elem.X, elem.Y, elem.ItemID, hue); - } - - private string DistroGump_GFPicTiled(string gump_name, TiledElement elem) - { - return String.Format("GFPicTiled( {0}, {1}, {2}, {3}, {4}, {5} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, elem.GumpID); - } - - private string DistroGump_GFGumpPic(string gump_name, ImageElement elem) - { - string hue = (elem.Hue != null) ? elem.Hue.Index.ToString() : "0"; - return String.Format("GFGumpPic( {0}, {1}, {2}, {3}, {4} );", gump_name, elem.X, elem.Y, elem.GumpID, hue); - } - - private string DistroGump_GFResizePic(string gump_name, BackgroundElement elem) - { - return String.Format("GFResizePic( {0}, {1}, {2}, {3}, {4}, {5} );", gump_name, elem.X, elem.Y, elem.GumpID, elem.Width, elem.Height); - } - - private string DistroGump_GFAddAlphaRegion(string gump_name, AlphaElement elem) - { - return String.Format("GFAddAlphaRegion( {0}, {1}, {2}, {3}, {4} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height); - } - - private string DistroGump_GFTextLine(string gump_name, LabelElement elem) - { - string hue = (elem.Hue != null) ? elem.Hue.Index.ToString() : "0"; - - string text = (bGetDefaultText) ? "TextLine" : ""; - if (elem.Text != null) - if (elem.Text != String.Empty) - text = elem.Text; - - return String.Format("GFTextLine( {0}, {1}, {2}, {3}, \"{4}\" );", gump_name, elem.X, elem.Y, hue, text); - } - - private string DistroGump_GFTextEntry(string gump_name, TextEntryElement elem) - { - string text = (bGetDefaultText) ? "TextEntry" : ""; - if (elem.InitialText != null) - if (elem.InitialText != String.Empty) - text = elem.InitialText; - - string hue = (elem.Hue != null) ? elem.Hue.Index.ToString() : "0"; - if (elem.MaxLength > 0) - return String.Format("GFTextEntry( {0}, {1}, {2}, {3}, {4}, {5}, \"{6}\", {7}, {8} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, hue, text, elem.ID, elem.MaxLength); - else - return String.Format("GFTextEntry( {0}, {1}, {2}, {3}, {4}, {5}, \"{6}\", {7} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, hue, text, elem.ID); - - } - - private string DistroGump_GFAddHTMLLocalized(string gump_name, HTMLElement elem) - { - //TODO: What about allowing Hue to be placed in HTML when using cliloc? - if (elem.ShowScrollbar || elem.ShowBackground) - return String.Format("GFAddHTMLLocalized( {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, elem.CliLocID, BoolToString(elem.ShowBackground), BoolToString(elem.ShowScrollbar)); - else - return String.Format("GFAddHTMLLocalized( {0}, {1}, {2}, {3}, {4}, {5}, 0, 0 );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, elem.CliLocID); - } - - private string DistroGump_GFHTMLArea(string gump_name, HTMLElement elem) - { - string text = (bGetDefaultText) ? "HtmlElement" : ""; - - if (elem.HTML != null) - if (elem.HTML != String.Empty) - text = elem.HTML; - - if (elem.ShowScrollbar || elem.ShowBackground) - return String.Format("GFHTMLArea( {0}, {1}, {2}, {3}, {4}, \"{5}\", {6}, {7} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, text, BoolToString(elem.ShowBackground), BoolToString(elem.ShowScrollbar)); - else - return String.Format("GFHTMLArea( {0}, {1}, {2}, {3}, {4}, \"{5}\", 0, 0 );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, text); - } - - private string DistroGump_GFPage(string gump_name, ref int pageindex) - { - return String.Format("GFPage( {0}, {1} );", gump_name, pageindex++); - } - - string DistroGump_GFCreateGump(string gump_name, System.Drawing.Point loc) - { - if (loc.X != 0 || loc.Y != 0) - return String.Format("var {0} := GFCreateGump( {1}, {2} );", gump_name, loc.X, loc.Y); - else - return String.Format("var {0} := GFCreateGump( 0, 0 );", gump_name); - - } - #endregion - - private StringWriter CreateBareScript() - { - StringWriter sw_Script = new StringWriter(); - //ArrayList al_Buttons = new ArrayList(); - //ArrayList al_Texts = new ArrayList(); - - List GumpCommands = new List(); - List GumpTexts = new List(); - - - sw_Script.WriteLine("// Created {0}, with Gump Studio.", DateTime.Now); - sw_Script.WriteLine("// Exported with {0} ver {1}.", this.GetPluginInfo().PluginName, this.GetPluginInfo().Version); - sw_Script.WriteLine(""); - - if (!m_Designer.GumpProperties.Moveable) - GumpCommands.Add("NoMove"); - - if (!m_Designer.GumpProperties.Closeable) - GumpCommands.Add("NoClose"); - - if (!m_Designer.GumpProperties.Disposeable) - GumpCommands.Add("NoDispose"); - - if (m_Designer.Stacks.Count > 0) - { - int radiogroup = -1; - int pageindex = 0; - // ================= - - foreach (GroupElement ge_Elements in m_Designer.Stacks) - { - GumpCommands.Add(Gump_WritePage(ref pageindex)); // "page pageid" - if (ge_Elements == null) - continue; - - foreach (BaseElement be_Element in ge_Elements.GetElementsRecursive()) - { - if (be_Element == null) - continue; - - Type ElementType = be_Element.GetType(); - - if (ElementType == typeof(HTMLElement)) - { - HTMLElement elem = be_Element as HTMLElement; - if (elem.TextType == HTMLElementType.HTML) - { - string cmd = Gump_WriteHTMLGump(elem, ref GumpTexts); - GumpCommands.Add(cmd); - } - else - { - string cmd = Gump_WriteXMFHtmlGump(elem); - GumpCommands.Add(cmd); - } - } - else if (ElementType == typeof(TextEntryElement)) - { - TextEntryElement elem = be_Element as TextEntryElement; - string cmd = Gump_WriteTextEntry(elem, ref GumpTexts); - GumpCommands.Add(cmd); - } - else if (ElementType == typeof(LabelElement)) - { - LabelElement elem = be_Element as LabelElement; - string cmd = Gump_WriteText(elem, ref GumpTexts); - GumpCommands.Add(cmd); - } - - else if (ElementType == typeof(AlphaElement)) - { - AlphaElement elem = be_Element as AlphaElement; - string cmd = Gump_WriteCheckerTrans(elem); - GumpCommands.Add(cmd); - } - else if (ElementType == typeof(BackgroundElement)) - { - BackgroundElement elem = be_Element as BackgroundElement; - string cmd = Gump_WriteResizePic(elem); - GumpCommands.Add(cmd); - } - else if (ElementType == typeof(ImageElement)) - { - ImageElement elem = be_Element as ImageElement; - string cmd = Gump_WriteGumpPic(elem); - GumpCommands.Add(cmd); - } - else if (ElementType == typeof(ItemElement)) - { - ItemElement elem = be_Element as ItemElement; - string cmd = Gump_WriteTilePic(elem); - GumpCommands.Add(cmd); - } - else if (ElementType == typeof(TiledElement)) - { - TiledElement elem = be_Element as TiledElement; - string cmd = Gump_WriteGumpPicTiled(elem); - GumpCommands.Add(cmd); - } - - else if (ElementType == typeof(ButtonElement)) - { - ButtonElement elem = be_Element as ButtonElement; - string cmd = Gump_WriteButton(elem); - GumpCommands.Add(cmd); - } - - else if (ElementType == typeof(CheckboxElement)) - { - CheckboxElement elem = be_Element as CheckboxElement; - string cmd = Gump_WriteCheckBox(elem); - GumpCommands.Add(cmd); - } - else if (ElementType == typeof(RadioElement)) - { - RadioElement elem = be_Element as RadioElement; - if (elem.Group != radiogroup) - { - GumpCommands.Add("group " + elem.Group); - radiogroup = elem.Group; - } - string cmd = Gump_WriteRadioBox(elem); - GumpCommands.Add(cmd); - } - } - } - } - sw_Script.WriteLine(""); - sw_Script.WriteLine("use uo;"); - sw_Script.WriteLine("use os;"); - sw_Script.WriteLine(""); - sw_Script.WriteLine("program gump_{0}( who )", frm_POLExportForm.GumpName); - sw_Script.WriteLine(""); - - sw_Script.WriteLine("\tvar gump := array {"); - - int i = 1; - foreach (string tmpCmd in GumpCommands) - { - sw_Script.Write("\t\t\"{0}\"", tmpCmd); - - if (i == GumpCommands.Count) - sw_Script.WriteLine(""); - else - sw_Script.WriteLine(",", tmpCmd); - i++; - } - sw_Script.WriteLine("\t};"); - - sw_Script.WriteLine("\tvar data := array {"); - - i = 1; - foreach (string tmpSe in GumpTexts) - { - sw_Script.Write("\t\t\"{0}\"", tmpSe); - if (i == GumpTexts.Count) - sw_Script.WriteLine(""); - else - sw_Script.WriteLine(","); - i++; - } - sw_Script.WriteLine("\t};"); - sw_Script.WriteLine(""); - sw_Script.WriteLine("\tSendDialogGump( who, gump, data{0} );", Gump_Location(m_Designer.GumpProperties.Location)); - sw_Script.WriteLine(""); - sw_Script.WriteLine("endprogram"); - return sw_Script; - } - - #region Bare Gump Commands - private string Gump_WriteRadioBox(RadioElement elem) - { - return String.Format("radio {0} {1} {2} {3} {4} {5}", elem.X, elem.Y, elem.UnCheckedID, elem.CheckedID, BoolToString(elem.Checked), elem.Value); - } - - private string Gump_WriteButton(ButtonElement elem) - { - bool quit = true; - string page_id = "0"; - string ret_value = elem.Param.ToString(); - - if (elem.ButtonType == ButtonTypeEnum.Page) - { - quit = false; - page_id = elem.Param.ToString(); - ret_value = "0"; - } - - return string.Format("button {0} {1} {2} {3} {4} {5} {6}", elem.X, elem.Y, elem.NormalID, elem.PressedID, BoolToString(quit), page_id, ret_value); - } - - private string Gump_WriteCheckBox(CheckboxElement elem) - { - return string.Format("checkbox {0} {1} {2} {3} {4} {5}", elem.X, elem.Y, elem.UnCheckedID, elem.CheckedID, BoolToString(elem.Checked), elem.Group); - } - - private string Gump_WriteGumpPicTiled(TiledElement elem) - { - return string.Format("gumppictiled {0} {1} {2} {3} {4}", elem.X, elem.Y, elem.Width, elem.Height, elem.GumpID); - } - - private string Gump_WriteTilePic(ItemElement elem) - { - if (IsHued(elem.Hue.Index.ToString())) - return string.Format("tilepichue {0} {1} {2} {3}", elem.X, elem.Y, elem.ItemID, elem.Hue.Index); - else - return String.Format("tilepic {0} {1} {2}", elem.X, elem.Y, elem.ItemID); - } - - private string Gump_WriteGumpPic(ImageElement elem) - { - if (IsHued(elem.Hue.Index.ToString())) - { - return String.Format("gumppic {0} {1} {2} {3}", elem.X, elem.Y, elem.GumpID, elem.Hue.Index); - } - else return String.Format("gumppic {0} {1} {2}", elem.X, elem.Y, elem.GumpID); - } - - private string Gump_WriteResizePic(BackgroundElement elem) - { - return String.Format("resizepic {0} {1} {2} {3} {4}", elem.X, elem.Y, elem.GumpID, elem.Width, elem.Height); - } - - private string Gump_WriteCheckerTrans(AlphaElement elem) - { - return String.Format("checkertrans {0} {1} {2} {3}", elem.X, elem.Y, elem.Width, elem.Height); - } - - private string Gump_WriteText(LabelElement elem, ref List texts) - { - int textid = texts.Count; - - string text = String.Concat("Text id.", textid); - - if (elem.Text != null) - { - text = (elem.Text == String.Empty) ? text : elem.Text; - } - - texts.Add(text); - - return String.Format("text {0} {1} {2} {3}", elem.X, elem.Y, elem.Hue.Index, textid); - } - - string Gump_WritePage(ref int pageid) - { - return String.Format("page {0}", pageid++); - } - - string Gump_WriteHTMLGump(HTMLElement elem, ref List texts) { - int textid = texts.Count; - - string text = String.Concat("HtmlGump id.", textid); - - if (elem.HTML != null) { - text = (elem.HTML == String.Empty) ? text : elem.HTML; - } - - texts.Add(text); - - return String.Format("htmlgump {0} {1} {2} {3} {4} {5} {6}", elem.X, elem.Y, elem.Width, elem.Height, textid, BoolToString(elem.ShowBackground), BoolToString(elem.ShowScrollbar)); - } - - string Gump_WriteXMFHtmlGump(HTMLElement elem) - { - return String.Format("xmfhtmlgump {0} {1} {2} {3} {4} {5} {6}", elem.X, elem.Y, elem.Width, elem.Height, elem.CliLocID, BoolToString(elem.ShowBackground), BoolToString(elem.ShowScrollbar)); - } - - private string Gump_WriteTextEntry(TextEntryElement elem, ref List texts) - { - int textid = texts.Count; - - string text = String.Concat("TextEntry id.", textid); - - if (elem.InitialText != null) - { - text = (elem.InitialText == String.Empty) ? text : elem.InitialText; - } - - texts.Add(text); - if (elem.MaxLength > 0) - return String.Format("textentrylimited {0} {1} {2} {3} {4} {5} {6} {7}", elem.X, elem.Y, elem.Width, elem.Height, elem.Hue.Index, elem.ID, textid, elem.MaxLength); - else - return String.Format("textentry {0} {1} {2} {3} {4} {5} {6}", elem.X, elem.Y, elem.Width, elem.Height, elem.Hue.Index, elem.ID, textid); - - } - #endregion - - #region Helper commands - string Gump_Location(System.Drawing.Point loc) - { - if (loc.X == 0 && loc.Y == 0) - return ""; - - return String.Format(", {0}, {1}", loc.X, loc.Y); - } - - string BoolToString(bool check) - { - return (check) ? "1" : "0"; - } - - bool IsHued(string hue) - { - if (hue == null) - return false; - if (hue == string.Empty) - return false; - if (hue == "0") - return false; - return true; - } - #endregion - } -} +/* Copyright (c) 2004-2006 Francesco Furiani & Mark Chandler + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software + * is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Modified by Fernando Rozenblit in 2008 to create POL Scripts. + * + * Rewrote some parts of Class1.cs for a better reading / updating + * + * TODO: Add distro pkg support + */ + +/* + * Modified by David Gardner on 2018-12-05 to add additional functionality. + * + * - Added TextEntryLimited for both the barebones style and distro pkg style + * - Added support for gumppictiled for the distro pkg style + * - Fixed an invalid placeholder warning in: Gump_WriteGumpPic(ImageElement elem) + * - Modified the html gump element for distro pkg style output to place the boolean values of showbackground + * and scroll bar regardless of whether they are true or false, probably a personal preference. + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Windows.Forms; +using GumpStudio; +using GumpStudio.Elements; +using GumpStudio.Plugins; +using Ultima; + +namespace POLGumpExport +{ + public class POLExporter : BasePlugin + { + private MenuItem _MenuFileExport; + protected POLExportForm frm_POLExportForm; + + private bool bGetDefaultText = false; + + public override PluginInfo Info { get; } = new PluginInfo("POLGumpExporter", "1.2", "POLServer team", "team@polserver.com", "Exports the Gump into a POL script. Based on Sphere Exporter by Francesco Furiani & Mark Chandler."); + private readonly Settings _Config = new Settings(); + public override BaseConfig Config => _Config; + + [Serializable] + public class Settings : BaseConfig + { + public override string Name => "POLGumpExporter"; + } + + protected override void OnLoaded() + { + base.OnLoaded(); + + Designer.MenuFileExport.Enabled = true; + + if (_MenuFileExport == null) + { + _MenuFileExport = new MenuItem(Info.Name, mnu_FileExportPOLExport_Click); + } + + Designer.MenuFileExport.MenuItems.Add(_MenuFileExport); + } + + protected override void OnUnloaded() + { + base.OnUnloaded(); + + Designer.MenuFileExport.MenuItems.Remove(_MenuFileExport); + + if (Designer.MenuFileExport.MenuItems.Count == 0) + { + Designer.MenuFileExport.Enabled = false; + } + } + + private void mnu_FileExportPOLExport_Click(object sender, EventArgs e) + { + frm_POLExportForm = new POLExportForm(this); + frm_POLExportForm.ShowDialog(); + } + + public StringWriter GetPOLScript(bool bUsedistro) + { + return GetPOLScript(bUsedistro, true, true, true); + } + + public StringWriter GetPOLScript(bool bUseDistro, bool bShowComment, bool bShowNames, bool bDefaultTexts) + { + if (bUseDistro) return CreateDistroScript(bShowComment, bShowNames, bDefaultTexts); + else return CreateBareScript(); + } + + private string GetCommentString(BaseElement be_elem, bool bShowComments, bool bShowNames) + { + if (be_elem == null) + return ""; + + string elem_comment = ""; + string elem_name = ""; + string comment = ""; + + if (be_elem.Comment != null) + elem_comment = be_elem.Comment; + + if (bShowNames) { + if (be_elem.Name != null) + elem_name = be_elem.Name; + + comment = be_elem.Name + ((elem_comment != String.Empty && bShowComments) ? ": " : ""); + } + if (bShowComments) + comment += elem_comment; + + return "// " + comment; + } + + private string GetGumpName() + { + string gump_name = frm_POLExportForm.GumpName; + string default_name = "gump"; + string[] words = null; + + if (gump_name != null) + if (gump_name != String.Empty) + words = gump_name.Split(new char[]{' '},StringSplitOptions.RemoveEmptyEntries); + + if (words == null) + return default_name; + + if (words.Length > 0) + return words[0]; + + return default_name; + } + + private StringWriter CreateDistroScript(bool bShowComment, bool bShowNames, bool bDefaultTexts) + { + StringWriter sw_Script = new StringWriter(); + List GumpCommands = new List(); + + bGetDefaultText = bDefaultTexts; // define if plugin will set default text for empty elems + + string gump_name = GetGumpName(); + + GumpCommands.Add(DistroGump_GFCreateGump(gump_name, Designer.GumpProperties.Location)); + GumpCommands.Add(""); + if (!Designer.GumpProperties.Moveable) + GumpCommands.Add(String.Format("GFMovable( {0}, 0 );", gump_name)); + + if (!Designer.GumpProperties.Closeable) + GumpCommands.Add(String.Format("GFClosable( {0}, 0 );", gump_name)); + + if (!Designer.GumpProperties.Disposeable) + GumpCommands.Add(String.Format("GFDisposable( {0}, 0 );", gump_name)); + + + if (Designer.Stacks.Count > 0) + { + int radiogroup = -1; + int pageindex = 0; + // ================= + + foreach (GroupElement ge_Elements in Designer.Stacks) + { + if (pageindex > 0) + GumpCommands.Add(""); + + GumpCommands.Add(DistroGump_GFPage(gump_name, ref pageindex)); // "page pageid" + if (ge_Elements == null) + continue; + + foreach (BaseElement be_Element in ge_Elements.GetElementsRecursive()) + { + if (be_Element == null) + continue; + + if (bShowComment || bShowNames) + { + string comment = GetCommentString(be_Element, bShowComment, bShowNames); + if (comment != String.Empty) + { + GumpCommands.Add(""); + GumpCommands.Add(comment); + } + } + + Type ElementType = be_Element.GetType(); + + if (ElementType == typeof(HTMLElement)) + { + HTMLElement elem = be_Element as HTMLElement; + if (elem.TextType == HTMLElementType.HTML) + GumpCommands.Add(DistroGump_GFHTMLArea(gump_name, elem)); + else + GumpCommands.Add(DistroGump_GFAddHTMLLocalized(gump_name, elem)); + } + else if (ElementType == typeof(TextEntryElement)) + { + TextEntryElement elem = be_Element as TextEntryElement; + GumpCommands.Add(DistroGump_GFTextEntry(gump_name, elem)); + } + else if (ElementType == typeof(LabelElement)) + { + LabelElement elem = be_Element as LabelElement; + GumpCommands.Add(DistroGump_GFTextLine(gump_name, elem)); + } + + else if (ElementType == typeof(AlphaElement)) + { + AlphaElement elem = be_Element as AlphaElement; + GumpCommands.Add(DistroGump_GFAddAlphaRegion(gump_name, elem)); + } + else if (ElementType == typeof(BackgroundElement)) + { + BackgroundElement elem = be_Element as BackgroundElement; + GumpCommands.Add(DistroGump_GFResizePic(gump_name, elem)); + } + else if (ElementType == typeof(ImageElement)) + { + ImageElement elem = be_Element as ImageElement; + GumpCommands.Add(DistroGump_GFGumpPic(gump_name, elem)); + } + else if (ElementType == typeof(ItemElement)) + { + ItemElement elem = be_Element as ItemElement; + GumpCommands.Add(DistroGump_GFTilePic(gump_name, elem)); + } + else if (ElementType == typeof(TiledElement)) + { + TiledElement elem = be_Element as TiledElement; + GumpCommands.Add(DistroGump_GFPicTiled(gump_name, elem)); + } + + else if (ElementType == typeof(ButtonElement)) + { + ButtonElement elem = be_Element as ButtonElement; + GumpCommands.Add(DistroGump_GFAddButton(gump_name, elem)); + } + + else if (ElementType == typeof(CheckboxElement)) + { + CheckboxElement elem = be_Element as CheckboxElement; + GumpCommands.Add(DistroGump_GFCheckBox(gump_name, elem)); + } + else if (ElementType == typeof(RadioElement)) + { + RadioElement elem = be_Element as RadioElement; + if (elem.Group != radiogroup) + { + GumpCommands.Add(String.Format("GFSetRadioGroup( {0}, {1} );", gump_name, elem.Group)); + radiogroup = elem.Group; + } + GumpCommands.Add(DistroGump_GFRadioButton(gump_name, elem)); + } + } + } + } + + + sw_Script.WriteLine("// Created {0}, with Gump Studio.", DateTime.Now); + sw_Script.WriteLine("// Exported with {0} ver {1} for gump pkg", Info.Name, Info.Version); + sw_Script.WriteLine(); + sw_Script.WriteLine("use uo;"); + sw_Script.WriteLine("use os;"); + sw_Script.WriteLine(); + sw_Script.WriteLine("include \":gumps:gumps\";"); + sw_Script.WriteLine(); + sw_Script.WriteLine("program gump_{0}( who )", gump_name); + sw_Script.WriteLine(); + + foreach (string cmd in GumpCommands) + { + sw_Script.WriteLine("\t"+cmd); + } + sw_Script.WriteLine(); + sw_Script.WriteLine("\tGFSendGump( who, {0} );", gump_name); + sw_Script.WriteLine(); + sw_Script.WriteLine("endprogram"); + + + return sw_Script; + } + + #region Distro pkg commands + private string DistroGump_GFRadioButton(string gump_name, RadioElement elem) + { + return String.Format("GFRadioButton( {0}, {1}, {2}, {3}, {4}, {5}, {6} );", gump_name, elem.X, elem.Y, elem.UnCheckedID, elem.CheckedID, BoolToString(elem.Checked), elem.Value); + } + + private string DistroGump_GFCheckBox(string gump_name, CheckboxElement elem) + { + return String.Format("GFCheckBox( {0}, {1}, {2}, {3}, {4}, {5}, {6} );", gump_name, elem.X, elem.Y, elem.UnCheckedID, elem.CheckedID, BoolToString(elem.Checked), elem.Group); + } + + private string DistroGump_GFAddButton(string gump_name, ButtonElement elem) + { + string btn_type = ""; + if (elem.ButtonType == ButtonTypeEnum.Page) + btn_type = "GF_PAGE_BTN"; + else + btn_type = "GF_CLOSE_BTN"; + + return String.Format("GFAddButton( {0}, {1}, {2}, {3}, {4}, {5}, {6} );", gump_name, elem.X, elem.Y, elem.NormalID, elem.PressedID, btn_type, elem.Param); + } + + private string DistroGump_GFTilePic(string gump_name, ItemElement elem) + { + string hue = (elem.Hue != null) ? elem.Hue.Index.ToString() : "0"; + return String.Format("GFTilePic( {0}, {1}, {2}, {3}, {4} );", gump_name, elem.X, elem.Y, elem.ItemID, hue); + } + + private string DistroGump_GFPicTiled(string gump_name, TiledElement elem) + { + return String.Format("GFPicTiled( {0}, {1}, {2}, {3}, {4}, {5} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, elem.GumpID); + } + + private string DistroGump_GFGumpPic(string gump_name, ImageElement elem) + { + string hue = (elem.Hue != null) ? elem.Hue.Index.ToString() : "0"; + return String.Format("GFGumpPic( {0}, {1}, {2}, {3}, {4} );", gump_name, elem.X, elem.Y, elem.GumpID, hue); + } + + private string DistroGump_GFResizePic(string gump_name, BackgroundElement elem) + { + return String.Format("GFResizePic( {0}, {1}, {2}, {3}, {4}, {5} );", gump_name, elem.X, elem.Y, elem.GumpID, elem.Width, elem.Height); + } + + private string DistroGump_GFAddAlphaRegion(string gump_name, AlphaElement elem) + { + return String.Format("GFAddAlphaRegion( {0}, {1}, {2}, {3}, {4} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height); + } + + private string DistroGump_GFTextLine(string gump_name, LabelElement elem) + { + string hue = (elem.Hue != null) ? elem.Hue.Index.ToString() : "0"; + + string text = (bGetDefaultText) ? "TextLine" : ""; + if (elem.Text != null) + if (elem.Text != String.Empty) + text = elem.Text; + + return String.Format("GFTextLine( {0}, {1}, {2}, {3}, \"{4}\" );", gump_name, elem.X, elem.Y, hue, text); + } + + private string DistroGump_GFTextEntry(string gump_name, TextEntryElement elem) + { + string text = (bGetDefaultText) ? "TextEntry" : ""; + if (elem.InitialText != null) + if (elem.InitialText != String.Empty) + text = elem.InitialText; + + string hue = (elem.Hue != null) ? elem.Hue.Index.ToString() : "0"; + if (elem.MaxLength > 0) + return String.Format("GFTextEntry( {0}, {1}, {2}, {3}, {4}, {5}, \"{6}\", {7}, {8} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, hue, text, elem.ID, elem.MaxLength); + else + return String.Format("GFTextEntry( {0}, {1}, {2}, {3}, {4}, {5}, \"{6}\", {7} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, hue, text, elem.ID); + + } + + private string DistroGump_GFAddHTMLLocalized(string gump_name, HTMLElement elem) + { + //TODO: What about allowing Hue to be placed in HTML when using cliloc? + if (elem.ShowScrollbar || elem.ShowBackground) + return String.Format("GFAddHTMLLocalized( {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, elem.CliLocID, BoolToString(elem.ShowBackground), BoolToString(elem.ShowScrollbar)); + else + return String.Format("GFAddHTMLLocalized( {0}, {1}, {2}, {3}, {4}, {5}, 0, 0 );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, elem.CliLocID); + } + + private string DistroGump_GFHTMLArea(string gump_name, HTMLElement elem) + { + string text = (bGetDefaultText) ? "HtmlElement" : ""; + + if (elem.HTML != null) + if (elem.HTML != String.Empty) + text = elem.HTML; + + if (elem.ShowScrollbar || elem.ShowBackground) + return String.Format("GFHTMLArea( {0}, {1}, {2}, {3}, {4}, \"{5}\", {6}, {7} );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, text, BoolToString(elem.ShowBackground), BoolToString(elem.ShowScrollbar)); + else + return String.Format("GFHTMLArea( {0}, {1}, {2}, {3}, {4}, \"{5}\", 0, 0 );", gump_name, elem.X, elem.Y, elem.Width, elem.Height, text); + } + + private string DistroGump_GFPage(string gump_name, ref int pageindex) + { + return String.Format("GFPage( {0}, {1} );", gump_name, pageindex++); + } + + string DistroGump_GFCreateGump(string gump_name, System.Drawing.Point loc) + { + if (loc.X != 0 || loc.Y != 0) + return String.Format("var {0} := GFCreateGump( {1}, {2} );", gump_name, loc.X, loc.Y); + else + return String.Format("var {0} := GFCreateGump( 0, 0 );", gump_name); + + } + #endregion + + private StringWriter CreateBareScript() + { + StringWriter sw_Script = new StringWriter(); + //ArrayList al_Buttons = new ArrayList(); + //ArrayList al_Texts = new ArrayList(); + + List GumpCommands = new List(); + List GumpTexts = new List(); + + + sw_Script.WriteLine("// Created {0}, with Gump Studio.", DateTime.Now); + sw_Script.WriteLine("// Exported with {0} ver {1}.", Info.Name, Info.Version); + sw_Script.WriteLine(""); + + if (!Designer.GumpProperties.Moveable) + GumpCommands.Add("NoMove"); + + if (!Designer.GumpProperties.Closeable) + GumpCommands.Add("NoClose"); + + if (!Designer.GumpProperties.Disposeable) + GumpCommands.Add("NoDispose"); + + if (Designer.Stacks.Count > 0) + { + int radiogroup = -1; + int pageindex = 0; + // ================= + + foreach (GroupElement ge_Elements in Designer.Stacks) + { + GumpCommands.Add(Gump_WritePage(ref pageindex)); // "page pageid" + if (ge_Elements == null) + continue; + + foreach (BaseElement be_Element in ge_Elements.GetElementsRecursive()) + { + if (be_Element == null) + continue; + + Type ElementType = be_Element.GetType(); + + if (ElementType == typeof(HTMLElement)) + { + HTMLElement elem = be_Element as HTMLElement; + if (elem.TextType == HTMLElementType.HTML) + { + string cmd = Gump_WriteHTMLGump(elem, ref GumpTexts); + GumpCommands.Add(cmd); + } + else + { + string cmd = Gump_WriteXMFHtmlGump(elem); + GumpCommands.Add(cmd); + } + } + else if (ElementType == typeof(TextEntryElement)) + { + TextEntryElement elem = be_Element as TextEntryElement; + string cmd = Gump_WriteTextEntry(elem, ref GumpTexts); + GumpCommands.Add(cmd); + } + else if (ElementType == typeof(LabelElement)) + { + LabelElement elem = be_Element as LabelElement; + string cmd = Gump_WriteText(elem, ref GumpTexts); + GumpCommands.Add(cmd); + } + + else if (ElementType == typeof(AlphaElement)) + { + AlphaElement elem = be_Element as AlphaElement; + string cmd = Gump_WriteCheckerTrans(elem); + GumpCommands.Add(cmd); + } + else if (ElementType == typeof(BackgroundElement)) + { + BackgroundElement elem = be_Element as BackgroundElement; + string cmd = Gump_WriteResizePic(elem); + GumpCommands.Add(cmd); + } + else if (ElementType == typeof(ImageElement)) + { + ImageElement elem = be_Element as ImageElement; + string cmd = Gump_WriteGumpPic(elem); + GumpCommands.Add(cmd); + } + else if (ElementType == typeof(ItemElement)) + { + ItemElement elem = be_Element as ItemElement; + string cmd = Gump_WriteTilePic(elem); + GumpCommands.Add(cmd); + } + else if (ElementType == typeof(TiledElement)) + { + TiledElement elem = be_Element as TiledElement; + string cmd = Gump_WriteGumpPicTiled(elem); + GumpCommands.Add(cmd); + } + + else if (ElementType == typeof(ButtonElement)) + { + ButtonElement elem = be_Element as ButtonElement; + string cmd = Gump_WriteButton(elem); + GumpCommands.Add(cmd); + } + + else if (ElementType == typeof(CheckboxElement)) + { + CheckboxElement elem = be_Element as CheckboxElement; + string cmd = Gump_WriteCheckBox(elem); + GumpCommands.Add(cmd); + } + else if (ElementType == typeof(RadioElement)) + { + RadioElement elem = be_Element as RadioElement; + if (elem.Group != radiogroup) + { + GumpCommands.Add("group " + elem.Group); + radiogroup = elem.Group; + } + string cmd = Gump_WriteRadioBox(elem); + GumpCommands.Add(cmd); + } + } + } + } + sw_Script.WriteLine(""); + sw_Script.WriteLine("use uo;"); + sw_Script.WriteLine("use os;"); + sw_Script.WriteLine(""); + sw_Script.WriteLine("program gump_{0}( who )", frm_POLExportForm.GumpName); + sw_Script.WriteLine(""); + + sw_Script.WriteLine("\tvar gump := array {"); + + int i = 1; + foreach (string tmpCmd in GumpCommands) + { + sw_Script.Write("\t\t\"{0}\"", tmpCmd); + + if (i == GumpCommands.Count) + sw_Script.WriteLine(""); + else + sw_Script.WriteLine(",", tmpCmd); + i++; + } + sw_Script.WriteLine("\t};"); + + sw_Script.WriteLine("\tvar data := array {"); + + i = 1; + foreach (string tmpSe in GumpTexts) + { + sw_Script.Write("\t\t\"{0}\"", tmpSe); + if (i == GumpTexts.Count) + sw_Script.WriteLine(""); + else + sw_Script.WriteLine(","); + i++; + } + sw_Script.WriteLine("\t};"); + sw_Script.WriteLine(""); + sw_Script.WriteLine("\tSendDialogGump( who, gump, data{0} );", Gump_Location(Designer.GumpProperties.Location)); + sw_Script.WriteLine(""); + sw_Script.WriteLine("endprogram"); + return sw_Script; + } + + #region Bare Gump Commands + private string Gump_WriteRadioBox(RadioElement elem) + { + return String.Format("radio {0} {1} {2} {3} {4} {5}", elem.X, elem.Y, elem.UnCheckedID, elem.CheckedID, BoolToString(elem.Checked), elem.Value); + } + + private string Gump_WriteButton(ButtonElement elem) + { + bool quit = true; + string page_id = "0"; + string ret_value = elem.Param.ToString(); + + if (elem.ButtonType == ButtonTypeEnum.Page) + { + quit = false; + page_id = elem.Param.ToString(); + ret_value = "0"; + } + + return string.Format("button {0} {1} {2} {3} {4} {5} {6}", elem.X, elem.Y, elem.NormalID, elem.PressedID, BoolToString(quit), page_id, ret_value); + } + + private string Gump_WriteCheckBox(CheckboxElement elem) + { + return string.Format("checkbox {0} {1} {2} {3} {4} {5}", elem.X, elem.Y, elem.UnCheckedID, elem.CheckedID, BoolToString(elem.Checked), elem.Group); + } + + private string Gump_WriteGumpPicTiled(TiledElement elem) + { + return string.Format("gumppictiled {0} {1} {2} {3} {4}", elem.X, elem.Y, elem.Width, elem.Height, elem.GumpID); + } + + private string Gump_WriteTilePic(ItemElement elem) + { + if (IsHued(elem.Hue.Index.ToString())) + return string.Format("tilepichue {0} {1} {2} {3}", elem.X, elem.Y, elem.ItemID, elem.Hue.Index); + else + return String.Format("tilepic {0} {1} {2}", elem.X, elem.Y, elem.ItemID); + } + + private string Gump_WriteGumpPic(ImageElement elem) + { + if (IsHued(elem.Hue.Index.ToString())) + { + return String.Format("gumppic {0} {1} {2} {3}", elem.X, elem.Y, elem.GumpID, elem.Hue.Index); + } + else return String.Format("gumppic {0} {1} {2}", elem.X, elem.Y, elem.GumpID); + } + + private string Gump_WriteResizePic(BackgroundElement elem) + { + return String.Format("resizepic {0} {1} {2} {3} {4}", elem.X, elem.Y, elem.GumpID, elem.Width, elem.Height); + } + + private string Gump_WriteCheckerTrans(AlphaElement elem) + { + return String.Format("checkertrans {0} {1} {2} {3}", elem.X, elem.Y, elem.Width, elem.Height); + } + + private string Gump_WriteText(LabelElement elem, ref List texts) + { + int textid = texts.Count; + + string text = String.Concat("Text id.", textid); + + if (elem.Text != null) + { + text = (elem.Text == String.Empty) ? text : elem.Text; + } + + texts.Add(text); + + return String.Format("text {0} {1} {2} {3}", elem.X, elem.Y, elem.Hue.Index, textid); + } + + string Gump_WritePage(ref int pageid) + { + return String.Format("page {0}", pageid++); + } + + string Gump_WriteHTMLGump(HTMLElement elem, ref List texts) { + int textid = texts.Count; + + string text = String.Concat("HtmlGump id.", textid); + + if (elem.HTML != null) { + text = (elem.HTML == String.Empty) ? text : elem.HTML; + } + + texts.Add(text); + + return String.Format("htmlgump {0} {1} {2} {3} {4} {5} {6}", elem.X, elem.Y, elem.Width, elem.Height, textid, BoolToString(elem.ShowBackground), BoolToString(elem.ShowScrollbar)); + } + + string Gump_WriteXMFHtmlGump(HTMLElement elem) + { + return String.Format("xmfhtmlgump {0} {1} {2} {3} {4} {5} {6}", elem.X, elem.Y, elem.Width, elem.Height, elem.CliLocID, BoolToString(elem.ShowBackground), BoolToString(elem.ShowScrollbar)); + } + + private string Gump_WriteTextEntry(TextEntryElement elem, ref List texts) + { + int textid = texts.Count; + + string text = String.Concat("TextEntry id.", textid); + + if (elem.InitialText != null) + { + text = (elem.InitialText == String.Empty) ? text : elem.InitialText; + } + + texts.Add(text); + if (elem.MaxLength > 0) + return String.Format("textentrylimited {0} {1} {2} {3} {4} {5} {6} {7}", elem.X, elem.Y, elem.Width, elem.Height, elem.Hue.Index, elem.ID, textid, elem.MaxLength); + else + return String.Format("textentry {0} {1} {2} {3} {4} {5} {6}", elem.X, elem.Y, elem.Width, elem.Height, elem.Hue.Index, elem.ID, textid); + + } + #endregion + + #region Helper commands + string Gump_Location(System.Drawing.Point loc) + { + if (loc.X == 0 && loc.Y == 0) + return ""; + + return String.Format(", {0}, {1}", loc.X, loc.Y); + } + + string BoolToString(bool check) + { + return (check) ? "1" : "0"; + } + + bool IsHued(string hue) + { + if (hue == null) + return false; + if (hue == string.Empty) + return false; + if (hue == "0") + return false; + return true; + } + #endregion + } +} diff --git a/POLExportPlugin/GumpStudio.csproj b/POLExportPlugin/GumpStudio.csproj new file mode 100644 index 00000000..5823b3c6 --- /dev/null +++ b/POLExportPlugin/GumpStudio.csproj @@ -0,0 +1,105 @@ + + + WinExe + net48 + GumpStudio + true + Gump Studio.NET + Bradley Uffner + Gump Studio.NET + Gump Studio + January 2008 + 1.9.2 + 1.9.2 + 1.9.2 + Resources\Icon.ico + false + false + ..\Build\ + false + GumpStudio.GumpDesignerMain + true + + + AnyCPU + true + + + true + AnyCPU + DEBUG;TRACE + + + + + Resources\UOFont.dll + + + + + + + + True + True + GumpArtBrowser.resx + + + True + True + Resources.resx + + + UserControl + + + UserControl + + + Form + + + Form + + + Form + + + Form + + + Form + + + Form + + + Form + + + Form + + + Form + + + + + TextTemplatingFileGenerator + README.cs + + + + + + + + PublicResXFileCodeGenerator + GumpArtBrowser.Designer.cs + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + \ No newline at end of file diff --git a/POLExportPlugin/GumpStudioCore.dll b/POLExportPlugin/GumpStudioCore.dll deleted file mode 100644 index e68dce6c0441787c299b09d688227677441146f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 361472 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