diff --git a/OpenRA.Mods.Common/Traits/ScriptTags.cs b/OpenRA.Mods.Common/Traits/ScriptTags.cs index 36651a1cda..3e46521142 100644 --- a/OpenRA.Mods.Common/Traits/ScriptTags.cs +++ b/OpenRA.Mods.Common/Traits/ScriptTags.cs @@ -10,14 +10,41 @@ #endregion using System.Collections.Generic; +using System.Linq; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Allows this actor to be 'tagged' with arbitrary strings. Tags must be unique or they will be rejected.")] - public class ScriptTagsInfo : TraitInfo + public class ScriptTagsInfo : TraitInfo, IEditorActorOptions { + [Desc("Display order for the script tags text field in the map editor")] + public readonly int EditorScriptTagsDisplayOrder = 5; + public override object Create(ActorInitializer init) { return new ScriptTags(init, this); } + + IEnumerable IEditorActorOptions.ActorOptions(ActorInfo ai, World world) + { + yield return new EditorActorTextField("Tags", EditorScriptTagsDisplayOrder, + actor => + { + var init = actor.GetInitOrDefault(this); + if (init != null) + return string.Join(", ", init.Value); + + return ""; + }, + (actor, value) => + { + var tags = string.IsNullOrWhiteSpace(value) + ? [] : + value.Split(',').Select(t => t.Trim()).Where(t => !string.IsNullOrWhiteSpace(t)).ToArray(); + if (tags.Length == 0) + actor.RemoveInit(this); + else + actor.ReplaceInit(new ScriptTagsInit(tags), this); + }); + } } public class ScriptTags diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index 70f5a7b1bb..ad50b5f247 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -710,6 +710,21 @@ namespace OpenRA.Mods.Common.Traits } } + public class EditorActorTextField : EditorActorOption + { + public readonly Func GetValue; + public readonly Action OnChange; + + public EditorActorTextField(string name, int displayOrder, + Func getValue, + Action onChange) + : base(name, displayOrder) + { + GetValue = getValue; + OnChange = onChange; + } + } + [RequireExplicitImplementation] public interface INotifyEditorPlacementInfo : ITraitInfoInterface { diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorEditLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorEditLogic.cs index 54f9018486..a5a8a57184 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorEditLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/ActorEditLogic.cs @@ -51,6 +51,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly Widget checkboxOptionTemplate; readonly Widget sliderOptionTemplate; readonly Widget dropdownOptionTemplate; + readonly Widget textFieldOptionTemplate; ActorIDStatus actorIDStatus = ActorIDStatus.Normal; ActorIDStatus nextActorIDStatus = ActorIDStatus.Normal; @@ -85,6 +86,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic checkboxOptionTemplate = initContainer.Get("CHECKBOX_OPTION_TEMPLATE"); sliderOptionTemplate = initContainer.Get("SLIDER_OPTION_TEMPLATE"); dropdownOptionTemplate = initContainer.Get("DROPDOWN_OPTION_TEMPLATE"); + textFieldOptionTemplate = initContainer.Get("TEXTFIELD_OPTION_TEMPLATE"); initContainer.RemoveChildren(); var deleteButton = actorEditPanel.Get("DELETE_BUTTON"); @@ -320,6 +322,31 @@ namespace OpenRA.Mods.Common.Widgets.Logic initContainer.AddChild(dropdownContainer); } + else if (o is EditorActorTextField tfo) + { + var textFieldContainer = textFieldOptionTemplate.Clone(); + textFieldContainer.Bounds.Y = initContainer.Bounds.Height; + initContainer.Bounds.Height += textFieldContainer.Bounds.Height; + textFieldContainer.Get("LABEL").GetText = () => tfo.Name; + + var editorActionHandle = new EditorActorOptionActionHandle(tfo.OnChange, tfo.GetValue(SelectedActor)); + editActorPreview.Add(editorActionHandle); + + var textField = textFieldContainer.Get("OPTION"); + textField.Text = tfo.GetValue(SelectedActor); + + textField.OnTextEdited = () => + { + tfo.OnChange(SelectedActor, textField.Text); + editorActionHandle.OnChange(textField.Text); + }; + + textField.OnEscKey = _ => { textField.YieldKeyboardFocus(); return true; }; + textField.OnEnterKey = _ => { textField.YieldKeyboardFocus(); return true; }; + typableFields.Add(textField); + + initContainer.AddChild(textFieldContainer); + } } buttonContainer.Bounds.Y += initContainer.Bounds.Height - oldInitHeight; diff --git a/mods/cnc/chrome/editor.yaml b/mods/cnc/chrome/editor.yaml index 5317c6be23..ec40696bb2 100644 --- a/mods/cnc/chrome/editor.yaml +++ b/mods/cnc/chrome/editor.yaml @@ -651,6 +651,20 @@ Container@EDITOR_WORLD_ROOT: Width: 213 Height: 25 Font: Bold + Container@TEXTFIELD_OPTION_TEMPLATE: + Width: PARENT_WIDTH + Height: 27 + Children: + Label@LABEL: + Y: 1 + Width: 55 + Height: 25 + Align: Right + TextField@OPTION: + X: 69 + Y: 1 + Width: 213 + Height: 25 Container@BUTTON_CONTAINER: Y: 70 Children: diff --git a/mods/common/chrome/editor.yaml b/mods/common/chrome/editor.yaml index aae22c0457..978be69d06 100644 --- a/mods/common/chrome/editor.yaml +++ b/mods/common/chrome/editor.yaml @@ -618,6 +618,20 @@ Container@EDITOR_WORLD_ROOT: Width: 213 Height: 25 Font: Bold + Container@TEXTFIELD_OPTION_TEMPLATE: + Width: PARENT_WIDTH + Height: 27 + Children: + Label@LABEL: + Y: 1 + Width: 55 + Height: 25 + Align: Right + TextField@OPTION: + X: 69 + Y: 1 + Width: 213 + Height: 25 Container@BUTTON_CONTAINER: Y: 75 Children: