From 2b0db40c17ae69910c8c54faffb17c8ecaa7f971 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Thu, 12 Oct 2023 01:22:59 -0400 Subject: [PATCH] Add basic replacement functionality- replacing adds multiple copies on child actors, however. --- .../Dedicated/MissingScriptEditor.cs | 157 +++++++++++++++++- 1 file changed, 155 insertions(+), 2 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/MissingScriptEditor.cs b/Source/Editor/CustomEditors/Dedicated/MissingScriptEditor.cs index a6c4e6623..0af811074 100644 --- a/Source/Editor/CustomEditors/Dedicated/MissingScriptEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/MissingScriptEditor.cs @@ -1,6 +1,13 @@ -using FlaxEditor.CustomEditors.Editors; +using FlaxEditor.Actions; +using FlaxEditor.CustomEditors.Editors; +using FlaxEditor.CustomEditors.GUI; +using FlaxEditor.GUI; +using FlaxEditor.GUI.ContextMenu; +using FlaxEditor.Scripting; using FlaxEngine; using FlaxEngine.GUI; +using System; +using System.Collections.Generic; namespace FlaxEditor.CustomEditors.Dedicated; @@ -10,6 +17,11 @@ namespace FlaxEditor.CustomEditors.Dedicated; [CustomEditor(typeof(MissingScript)), DefaultEditor] public class MissingScriptEditor : GenericEditor { + DropPanel _dropPanel; + Button _replaceScriptButton; + CheckBox _shouldReplaceAllCheckbox; + CustomEditor _propertiesEditor; + /// public override void Initialize(LayoutElementsContainer layout) { @@ -18,9 +30,150 @@ public class MissingScriptEditor : GenericEditor base.Initialize(layout); return; } + _dropPanel = dropPanel; + _dropPanel.HeaderTextColor = Color.OrangeRed; - dropPanel.HeaderTextColor = Color.OrangeRed; + Panel replaceScriptPanel = new Panel + { + Parent = _dropPanel, + Height = 64, + }; + + _replaceScriptButton = new Button + { + Text = "Replace Script", + AnchorPreset = AnchorPresets.TopCenter, + Width = 240, + Height = 24, + X = -120, + Y = 0, + Parent = replaceScriptPanel, + }; + _replaceScriptButton.Clicked += OnReplaceScriptButtonClicked; + + Label replaceAllLabel = new Label + { + Text = "Replace All of Same Type", + AnchorPreset = AnchorPresets.BottomCenter, + Y = -34, + Parent = replaceScriptPanel, + }; + replaceAllLabel.X -= FlaxEngine.GUI.Style.Current.FontSmall.MeasureText(replaceAllLabel.Text).X; + + _shouldReplaceAllCheckbox = new CheckBox + { + TooltipText = "Wether or not to apply this script change to all scripts missing the same type.", + AnchorPreset = AnchorPresets.BottomCenter, + Y = -34, + Parent = replaceScriptPanel, + }; + + float centerDifference = (_shouldReplaceAllCheckbox.Right - replaceAllLabel.Left) / 2; + replaceAllLabel.X += centerDifference; + _shouldReplaceAllCheckbox.X += centerDifference; base.Initialize(layout); } + + private List FindActorsWithMatchingMissingScript(Actor parent = null) + { + List missingScripts = new List(); + if (parent != null) + { + for (int child = 0; child < parent.ChildrenCount; child++) + { + Actor actor = parent.Children[child]; + for (int scriptIndex = 0; scriptIndex < actor.ScriptsCount; scriptIndex++) + { + Script actorScript = actor.Scripts[scriptIndex]; + if (actorScript is not MissingScript missingActorScript) + { + continue; + } + + MissingScript currentMissing = Values[0] as MissingScript; + if (missingActorScript.MissingTypeName != currentMissing.MissingTypeName) + { + continue; + } + + Debug.Log("Found correct missing script."); + + // Matching MissingScript. + missingScripts.Add(missingActorScript); + } + + missingScripts.AddRange(FindActorsWithMatchingMissingScript(actor)); + } + } else + { + foreach (Actor actor in Level.GetActors()) + { + missingScripts.AddRange(FindActorsWithMatchingMissingScript(actor)); + } + } + + return missingScripts; + } + + private void ReplaceScript(ScriptType script, bool replaceAllInScene) + { + var actions = new List(4); + + List missingScripts = new List(); + if (!replaceAllInScene) + { + missingScripts.Add(Values[0] as MissingScript); + } else + { + missingScripts.AddRange(FindActorsWithMatchingMissingScript()); + } + + foreach (MissingScript missingScript in missingScripts) + { + actions.Add(AddRemoveScript.Add(missingScript.Actor, script)); + actions.Add(AddRemoveScript.Remove(missingScript)); + } + + if (actions.Count == 0) + { + Editor.LogWarning("Failed to replace scripts!"); + return; + } + + var multiAction = new MultiUndoAction(actions); + multiAction.Do(); + var presenter = ParentEditor.Presenter; + if (presenter != null) + { + presenter.Undo.AddAction(multiAction); + presenter.Control.Focus(); + } + } + + private void OnReplaceScriptButtonClicked() + { + var scripts = Editor.Instance.CodeEditing.Scripts.Get(); + if (scripts.Count == 0) + { + // No scripts + var cm1 = new ContextMenu(); + cm1.AddButton("No scripts in project"); + cm1.Show(_dropPanel, _replaceScriptButton.BottomLeft); + return; + } + + // Show context menu with list of scripts to add + var cm = new ItemsListContextMenu(180); + for (int i = 0; i < scripts.Count; i++) + { + cm.AddItem(new TypeSearchPopup.TypeItemView(scripts[i])); + } + // Get the parent (actor properties editor) of the parent (Scripts Editor) of our editor. + _propertiesEditor = ParentEditor.ParentEditor; + + cm.ItemClicked += item => ReplaceScript((ScriptType)item.Tag, _shouldReplaceAllCheckbox.Checked); + cm.SortItems(); + cm.Show(_dropPanel, _replaceScriptButton.BottomLeft - new Float2((cm.Width - _replaceScriptButton.Width) / 2, 0)); + } }