// Copyright (c) Wojciech Figat. All rights reserved. using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using FlaxEditor.CustomEditors; using FlaxEditor.CustomEditors.Editors; using FlaxEditor.GUI.ContextMenu; using FlaxEngine; using FlaxEngine.GUI; namespace FlaxEditor.Surface { class AttributesEditor : ContextMenuBase { private CustomEditorPresenter _presenter; private Proxy _proxy; private byte[] _oldData; private class Proxy { [Collection(OverrideEditorTypeName = "FlaxEditor.Surface.AttributesEditor+ValuesEditor", Spacing = 10)] [EditorDisplay(null, EditorDisplayAttribute.InlineStyle)] public Attribute[] Value; } public sealed class ValuesEditor : ObjectSwitcherEditor { private OptionType[] _options; /// protected override OptionType[] Options => _options; /// public override void Initialize(LayoutElementsContainer layout) { var options = (IList)Presenter.Panel.Tag; _options = new OptionType[options.Count]; for (int i = 0; i < options.Count; i++) { var type = options[i]; _options[i] = new OptionType(Utilities.Utils.GetPropertyNameUI(type.Name), type, Creator); } base.Initialize(layout); } /// protected override void Deinitialize() { base.Deinitialize(); _options = null; } private object Creator(Type type) { var ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Utils.GetEmptyArray(), null); return ctor.Invoke(Utils.GetEmptyArray()); } } /// /// The action fired when parameters editing finishes and value gets accepted to be set. /// public Action Edited; /// /// Initializes a new instance of the class. /// /// The attributes list to edit. /// The allowed attribute types to use. public AttributesEditor(Attribute[] attributes, IList attributeTypes) { // Context menu dimensions const float width = 375.0f; const float height = 370.0f; Size = new Float2(width, height); // Title var title = new Label(2, 2, width - 4, 23.0f) { Font = new FontReference(Style.Current.FontLarge), Text = "Edit attributes", Parent = this }; // Ok and Cancel Buttons float buttonsWidth = (width - 12.0f) * 0.5f; float buttonsHeight = 20.0f; var okButton = new Button(4.0f, Bottom - 4.0f - buttonsHeight, buttonsWidth, buttonsHeight) { Text = "Ok", Parent = this }; okButton.Clicked += OnOkButtonClicked; var cancelButton = new Button(okButton.Right + 4.0f, okButton.Y, buttonsWidth, buttonsHeight) { Text = "Cancel", Parent = this }; cancelButton.Clicked += Hide; // Actual panel used to display attributes var panel1 = new Panel(ScrollBars.Vertical) { Bounds = new Rectangle(0, title.Bottom + 4.0f, width, height - buttonsHeight - title.Height - 14.0f), Parent = this }; var editor = new CustomEditorPresenter(null); editor.Panel.AnchorPreset = AnchorPresets.HorizontalStretchTop; editor.Panel.IsScrollable = true; editor.Panel.Parent = panel1; editor.Panel.Tag = attributeTypes; _presenter = editor; // Cache 'previous' state to check if attributes were edited after operation _oldData = SurfaceMeta.GetAttributesData(attributes); _proxy = new Proxy { Value = attributes, }; editor.Select(_proxy); _presenter.Modified += OnPresenterModified; OnPresenterModified(); } private void OnPresenterModified() { if (_proxy.Value.Length == 0) { var label = _presenter.Label("No attributes.\nPress the \"+\" button to add a new one and then select an attribute type using the \"Type\" dropdown.", TextAlignment.Center); label.Label.Wrapping = TextWrapping.WrapWords; label.Control.Height = 35f; label.Label.Margin = new Margin(10f); label.Label.TextColor = label.Label.TextColorHighlighted = Style.Current.ForegroundGrey; } } private void OnOkButtonClicked() { var newValue = ((Proxy)_presenter.Selection[0]).Value; newValue = newValue.Where(v => v != null).ToArray(); var newData = SurfaceMeta.GetAttributesData(newValue); if (!_oldData.SequenceEqual(newData)) Edited?.Invoke(newValue); Hide(); } /// protected override void OnShow() { Focus(); base.OnShow(); } /// public override void Hide() { if (!Visible) return; Focus(null); base.Hide(); } /// public override bool OnKeyDown(KeyboardKeys key) { if (key == KeyboardKeys.Escape) { Hide(); return true; } return base.OnKeyDown(key); } /// public override void OnDestroy() { _presenter = null; _oldData = null; _proxy = null; Edited = null; _presenter.Modified -= OnPresenterModified; base.OnDestroy(); } } }