diff --git a/Intersect.Client.Core/Interface/Game/Bag/BagItem.cs b/Intersect.Client.Core/Interface/Game/Bag/BagItem.cs index 57bb708ab8..70592aec0f 100644 --- a/Intersect.Client.Core/Interface/Game/Bag/BagItem.cs +++ b/Intersect.Client.Core/Interface/Game/Bag/BagItem.cs @@ -11,7 +11,6 @@ using Intersect.Client.Interface.Game.Inventory; using Intersect.Client.Localization; using Intersect.Client.Networking; -using Intersect.Collections.Slotting; using Intersect.Configuration; using Intersect.Framework.Core; using Intersect.Framework.Core.GameObjects.Items; diff --git a/Intersect.Client.Core/Interface/Game/MenuContainer.cs b/Intersect.Client.Core/Interface/Game/MenuContainer.cs index 32e9a74f1b..217b45441b 100644 --- a/Intersect.Client.Core/Interface/Game/MenuContainer.cs +++ b/Intersect.Client.Core/Interface/Game/MenuContainer.cs @@ -391,7 +391,7 @@ public void ToggleSimplifiedEscapeMenu() public void ToggleSpellsWindow() { - if (_spellsWindow.IsVisible()) + if (_spellsWindow.IsVisibleInTree) { _spellsWindow.Hide(); } @@ -425,7 +425,7 @@ public bool HasWindowsOpen() _friendsWindow.IsVisible || _inventoryWindow.IsVisibleInTree || _questsWindow.IsVisible() || - _spellsWindow.IsVisible() || + _spellsWindow.IsVisibleInTree || _partyWindow.IsVisible() || _guildWindow.IsVisibleInTree; return windowsOpen; diff --git a/Intersect.Client.Core/Interface/Game/Spells/SpellItem.cs b/Intersect.Client.Core/Interface/Game/Spells/SpellItem.cs index bb5fab5323..a142e7bad4 100644 --- a/Intersect.Client.Core/Interface/Game/Spells/SpellItem.cs +++ b/Intersect.Client.Core/Interface/Game/Spells/SpellItem.cs @@ -1,10 +1,15 @@ +using Intersect.Client.Core; +using Intersect.Client.Framework.Content; +using Intersect.Client.Framework.File_Management; using Intersect.Client.Framework.GenericClasses; +using Intersect.Client.Framework.Gwen; using Intersect.Client.Framework.Gwen.Control; using Intersect.Client.Framework.Gwen.Control.EventArguments; using Intersect.Client.Framework.Gwen.Input; using Intersect.Client.Framework.Input; using Intersect.Client.General; using Intersect.Client.Interface.Game.DescriptionWindows; +using Intersect.Client.Localization; using Intersect.Configuration; using Intersect.Framework.Core; using Intersect.GameObjects; @@ -12,236 +17,270 @@ namespace Intersect.Client.Interface.Game.Spells; - -public partial class SpellItem +public partial class SpellItem : SlotItem { + // Controls + private readonly Label _cooldownLabel; + private readonly SpellsWindow _spellWindow; + private Draggable? _dragIcon; + private SpellDescriptionWindow? _descriptionWindow; - public ImagePanel Container; - + // Drag Handling public bool IsDragging; + private bool _canDrag; + private long _clickTime; + private bool _mouseOver; + private int _mouseX = -1; + private int _mouseY = -1; + + // Context Menu Handling + private readonly MenuItem _useSpellMenuItem; + private readonly MenuItem _forgetSpellMenuItem; + + public SpellItem(SpellsWindow spellWindow, Base parent, int index, ContextMenu contextMenu) + : base(parent, nameof(SpellItem), index, contextMenu) + { + _spellWindow = spellWindow; + TextureFilename = "spellitem.png"; - private bool mCanDrag; - - private long mClickTime; - - private Label mCooldownLabel; + _iconImage.HoverEnter += _iconImage_HoverEnter; + _iconImage.HoverLeave += _iconImage_HoverLeave; + _iconImage.Clicked += _iconImage_Clicked; + _iconImage.DoubleClicked += _iconImage_DoubleClicked; - private Guid mCurrentSpellId; + _cooldownLabel = new Label(this, "CooldownLabel") + { + IsVisibleInParent = false, + FontName = "sourcesansproblack", + FontSize = 8, + TextColor = new Color(0, 255, 255, 255), + Alignment = [Alignments.Center], + BackgroundTemplateName = "quantity.png", + Padding = new Padding(2), + }; - private SpellDescriptionWindow mDescWindow; + LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer.GetResolutionString()); - private Draggable mDragIcon; + _contextMenu.ClearChildren(); + _useSpellMenuItem = _contextMenu.AddItem(Strings.SpellContextMenu.Cast.ToString()); + _useSpellMenuItem.Clicked += _useSpellMenuItem_Clicked; + _forgetSpellMenuItem = _contextMenu.AddItem(Strings.SpellContextMenu.Forget.ToString()); + _forgetSpellMenuItem.Clicked += _forgetSpellMenuItem_Clicked; + _contextMenu.LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer.GetResolutionString()); + } - private bool mIconCd; + #region Context Menu - private bool mMouseOver; + public void OpenContextMenu() + { + // Clear out the old options. + _contextMenu.ClearChildren(); - private int mMouseX = -1; + if (Globals.Me?.Spells is not { Length: > 0 } spellSlots) + { + return; + } - private int mMouseY = -1; + // No point showing a menu for blank space. + if (!SpellDescriptor.TryGet(spellSlots[SlotIndex].Id, out var spell)) + { + return; + } - //Drag/Drop References - private SpellsWindow mSpellWindow; + // Add our use spell option. + _contextMenu.AddChild(_useSpellMenuItem); + _useSpellMenuItem.SetText(Strings.SpellContextMenu.Cast.ToString(spell.Name)); - private string mTexLoaded = string.Empty; + // If this spell is not bound, allow users to forget it! + if (!spell.Bound) + { + _contextMenu.AddChild(_forgetSpellMenuItem); + _forgetSpellMenuItem.SetText(Strings.SpellContextMenu.Forget.ToString(spell.Name)); + } - private int mYindex; + _contextMenu.SizeToChildren(); + _contextMenu.Open(Pos.None); + } - public ImagePanel Pnl; + private void _useSpellMenuItem_Clicked(Base sender, MouseButtonState arguments) + { + Globals.Me?.TryUseSpell(SlotIndex); + } - public SpellItem(SpellsWindow spellWindow, int index) + private void _forgetSpellMenuItem_Clicked(Base sender, MouseButtonState arguments) { - mSpellWindow = spellWindow; - mYindex = index; + Globals.Me?.TryForgetSpell(SlotIndex); } - public void Setup() + #endregion + + #region Mouse Events + + private void _iconImage_HoverEnter(Base? sender, EventArgs? arguments) { - Pnl = new ImagePanel(Container, "SpellIcon"); - Pnl.HoverEnter += pnl_HoverEnter; - Pnl.HoverLeave += pnl_HoverLeave; - Pnl.Clicked += pnl_Clicked; - Pnl.DoubleClicked += Pnl_DoubleClicked; - mCooldownLabel = new Label(Pnl, "SpellCooldownLabel"); - mCooldownLabel.IsHidden = true; - mCooldownLabel.TextColor = new Color(0, 255, 255, 255); + if (InputHandler.MouseFocus != null) + { + return; + } + + _mouseOver = true; + _canDrag = true; + + if (Globals.InputManager.IsMouseButtonDown(MouseButton.Left)) + { + _canDrag = false; + return; + } + + if (_descriptionWindow != null) + { + _descriptionWindow.Dispose(); + _descriptionWindow = null; + } + + if (Globals.Me?.Spells is not { Length: > 0 } spellSlots) + { + return; + } + + _descriptionWindow = new SpellDescriptionWindow(spellSlots[SlotIndex].Id, _spellWindow.X, _spellWindow.Y); } - private void Pnl_DoubleClicked(Base sender, MouseButtonState arguments) + private void _iconImage_HoverLeave(Base sender, EventArgs arguments) { - Globals.Me.TryUseSpell(mYindex); + _mouseOver = false; + _mouseX = -1; + _mouseY = -1; + + if (_descriptionWindow != null) + { + _descriptionWindow.Dispose(); + _descriptionWindow = null; + } } - void pnl_Clicked(Base sender, MouseButtonState arguments) + private void _iconImage_Clicked(Base sender, MouseButtonState arguments) { switch (arguments.MouseButton) { case MouseButton.Left: - mClickTime = Timing.Global.MillisecondsUtc + 500; + _clickTime = Timing.Global.MillisecondsUtc + 500; break; case MouseButton.Right: if (ClientConfiguration.Instance.EnableContextMenus) { - mSpellWindow.OpenContextMenu(mYindex); + OpenContextMenu(); } else { - Globals.Me?.TryForgetSpell(mYindex); + Globals.Me?.TryForgetSpell(SlotIndex); } break; } - } - void pnl_HoverLeave(Base sender, EventArgs arguments) + private void _iconImage_DoubleClicked(Base sender, MouseButtonState arguments) { - mMouseOver = false; - mMouseX = -1; - mMouseY = -1; - if (mDescWindow != null) - { - mDescWindow.Dispose(); - mDescWindow = null; - } + Globals.Me?.TryUseSpell(SlotIndex); } - void pnl_HoverEnter(Base sender, EventArgs arguments) + #endregion + + public override void Update() { - if (InputHandler.MouseFocus != null) + if (Globals.Me == default) { return; } - mMouseOver = true; - mCanDrag = true; - if (Globals.InputManager.IsMouseButtonDown(MouseButton.Left)) + if (Globals.Me?.Spells is not { Length: > 0 } spellSlots) { - mCanDrag = false; - return; } - if (mDescWindow != null) + if (!SpellDescriptor.TryGet(spellSlots[SlotIndex].Id, out var spell)) { - mDescWindow.Dispose(); - mDescWindow = null; + _iconImage.Hide(); + _iconImage.Texture = null; + _cooldownLabel.Hide(); + return; } - mDescWindow = new SpellDescriptionWindow(Globals.Me.Spells[mYindex].Id, mSpellWindow.X, mSpellWindow.Y); - } - - public FloatRect RenderBounds() - { - var rect = new FloatRect() + _cooldownLabel.IsVisibleInParent = !IsDragging && Globals.Me.IsSpellOnCooldown(SlotIndex); + if (_cooldownLabel.IsVisibleInParent) { - X = Pnl.ToCanvas(new Point(0, 0)).X, - Y = Pnl.ToCanvas(new Point(0, 0)).Y, - Width = Pnl.Width, - Height = Pnl.Height - }; - - return rect; - } + var itemCooldownRemaining = Globals.Me.GetSpellRemainingCooldown(SlotIndex); + _cooldownLabel.Text = TimeSpan.FromMilliseconds(itemCooldownRemaining).WithSuffix("0.0"); + _iconImage.RenderColor.A = 100; + } + else + { + _iconImage.RenderColor.A = 255; + } - public void Update() - { - var spell = SpellDescriptor.Get(Globals.Me.Spells[mYindex].Id); - if (!IsDragging && - (mTexLoaded != "" && spell == null || - spell != null && mTexLoaded != spell.Icon || - mCurrentSpellId != Globals.Me.Spells[mYindex].Id || - mIconCd != - Globals.Me.GetSpellCooldown(Globals.Me.Spells[mYindex].Id) > Timing.Global.Milliseconds || - Globals.Me.GetSpellCooldown(Globals.Me.Spells[mYindex].Id) > Timing.Global.Milliseconds)) + if (Path.GetFileName(_iconImage.Texture?.Name) != spell.Icon) { - mCooldownLabel.IsHidden = true; - if (spell != null) + var spellIconTexture = Globals.ContentManager?.GetTexture(TextureType.Spell, spell.Icon); + if (spellIconTexture != null) { - var spellTex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Spell, spell.Icon); - if (spellTex != null) - { - Pnl.Texture = spellTex; - if (Globals.Me.GetSpellCooldown(Globals.Me.Spells[mYindex].Id) > - Timing.Global.Milliseconds) - { - Pnl.RenderColor = new Color(100, 255, 255, 255); - } - else - { - Pnl.RenderColor = new Color(255, 255, 255, 255); - } - } - else - { - if (Pnl.Texture != null) - { - Pnl.Texture = null; - } - } - - mTexLoaded = spell.Icon; - mCurrentSpellId = Globals.Me.Spells[mYindex].Id; - mIconCd = Globals.Me.IsSpellOnCooldown(mYindex); - - if (mIconCd) - { - mCooldownLabel.IsHidden = false; - var remaining = Globals.Me.GetSpellRemainingCooldown(mYindex); - mCooldownLabel.Text = TimeSpan.FromMilliseconds(remaining).WithSuffix(); - } + _iconImage.Texture = spellIconTexture; + _iconImage.RenderColor.A = (byte)(_cooldownLabel.IsVisibleInParent ? 100 : 255); + _iconImage.IsVisibleInParent = true; } else { - if (Pnl.Texture != null) + if (_iconImage.Texture != null) { - Pnl.Texture = null; + _iconImage.Texture = null; + _iconImage.IsVisibleInParent = false; } - - mTexLoaded = string.Empty; } + + _descriptionWindow?.Dispose(); + _descriptionWindow = null; + _iconImage_HoverEnter(null, null); } if (!IsDragging) { - if (mMouseOver) + if (_mouseOver) { if (!Globals.InputManager.IsMouseButtonDown(MouseButton.Left)) { - mCanDrag = true; - mMouseX = -1; - mMouseY = -1; - if (Timing.Global.MillisecondsUtc < mClickTime) + _canDrag = true; + _mouseX = -1; + _mouseY = -1; + if (Timing.Global.MillisecondsUtc < _clickTime) { - mClickTime = 0; + _clickTime = 0; } } else { - if (mCanDrag && Draggable.Active == null) + if (_canDrag && Draggable.Active == null) { - if (mMouseX == -1 || mMouseY == -1) + if (_mouseX == -1 || _mouseY == -1) { - mMouseX = InputHandler.MousePosition.X - Pnl.ToCanvas(new Point(0, 0)).X; - mMouseY = InputHandler.MousePosition.Y - Pnl.ToCanvas(new Point(0, 0)).Y; + _mouseX = InputHandler.MousePosition.X - _iconImage.ToCanvas(new Point(0, 0)).X; + _mouseY = InputHandler.MousePosition.Y - _iconImage.ToCanvas(new Point(0, 0)).Y; } else { - var xdiff = mMouseX - - (InputHandler.MousePosition.X - Pnl.ToCanvas(new Point(0, 0)).X); + var xdiff = _mouseX - + (InputHandler.MousePosition.X - _iconImage.ToCanvas(new Point(0, 0)).X); - var ydiff = mMouseY - - (InputHandler.MousePosition.Y - Pnl.ToCanvas(new Point(0, 0)).Y); + var ydiff = _mouseY - + (InputHandler.MousePosition.Y - _iconImage.ToCanvas(new Point(0, 0)).Y); if (Math.Sqrt(Math.Pow(xdiff, 2) + Math.Pow(ydiff, 2)) > 5) { IsDragging = true; - mDragIcon = new Draggable( - Pnl.ToCanvas(new Point(0, 0)).X + mMouseX, - Pnl.ToCanvas(new Point(0, 0)).X + mMouseY, Pnl.Texture, Pnl.RenderColor + _iconImage.IsVisibleInParent = false; + _dragIcon = new Draggable( + _iconImage.ToCanvas(new Point(0, 0)).X + _mouseX, + _iconImage.ToCanvas(new Point(0, 0)).X + _mouseY, _iconImage.Texture, _iconImage.RenderColor ); - - mTexLoaded = string.Empty; } } } @@ -250,15 +289,17 @@ public void Update() } else { - if (mDragIcon.Update()) + if (_dragIcon?.Update() == true) { //Drug the item and now we stopped IsDragging = false; + _iconImage.IsVisibleInParent = true; + var dragRect = new FloatRect( - mDragIcon.X - (Container.Padding.Left + Container.Padding.Right) / 2, - mDragIcon.Y - (Container.Padding.Top + Container.Padding.Bottom) / 2, - (Container.Padding.Left + Container.Padding.Right) / 2 + Pnl.Width, - (Container.Padding.Top + Container.Padding.Bottom) / 2 + Pnl.Height + _dragIcon.X - (Padding.Left + Padding.Right) / 2f, + _dragIcon.Y - (Padding.Top + Padding.Bottom) / 2f, + (Padding.Left + Padding.Right) / 2f + _iconImage.Width, + (Padding.Top + Padding.Bottom) / 2f + _iconImage.Height ); float bestIntersect = 0; @@ -266,20 +307,25 @@ public void Update() //So we picked up an item and then dropped it. Lets see where we dropped it to. //Check spell first. - if (mSpellWindow.RenderBounds().IntersectsWith(dragRect)) + if (_spellWindow.RenderBounds().IntersectsWith(dragRect)) { for (var i = 0; i < Options.Instance.Player.MaxSpells; i++) { - if (i < mSpellWindow.Items.Count && - mSpellWindow.Items[i].RenderBounds().IntersectsWith(dragRect)) + if (_spellWindow.Items[i] is not SpellItem spellSlot) { - if (FloatRect.Intersect(mSpellWindow.Items[i].RenderBounds(), dragRect).Width * - FloatRect.Intersect(mSpellWindow.Items[i].RenderBounds(), dragRect).Height > + continue; + } + + if (i < _spellWindow.Items.Count && + spellSlot.RenderBounds().IntersectsWith(dragRect)) + { + if (FloatRect.Intersect(spellSlot.RenderBounds(), dragRect).Width * + FloatRect.Intersect(spellSlot.RenderBounds(), dragRect).Height > bestIntersect) { bestIntersect = - FloatRect.Intersect(mSpellWindow.Items[i].RenderBounds(), dragRect).Width * - FloatRect.Intersect(mSpellWindow.Items[i].RenderBounds(), dragRect).Height; + FloatRect.Intersect(spellSlot.RenderBounds(), dragRect).Width * + FloatRect.Intersect(spellSlot.RenderBounds(), dragRect).Height; bestIntersectIndex = i; } @@ -288,9 +334,9 @@ public void Update() if (bestIntersectIndex > -1) { - if (mYindex != bestIntersectIndex && !Globals.Me.IsCasting) + if (SlotIndex != bestIntersectIndex && !Globals.Me.IsCasting) { - Globals.Me.SwapSpells(bestIntersectIndex, mYindex); + Globals.Me.SwapSpells(bestIntersectIndex, SlotIndex); } } } @@ -321,13 +367,25 @@ public void Update() if (bestIntersectIndex > -1) { - Globals.Me.AddToHotbar((byte) bestIntersectIndex, 1, mYindex); + Globals.Me.AddToHotbar((byte) bestIntersectIndex, 1, SlotIndex); } } - mDragIcon.Dispose(); + _dragIcon.Dispose(); } } } + public FloatRect RenderBounds() + { + var rect = new FloatRect() + { + X = _iconImage.ToCanvas(new Point(0, 0)).X, + Y = _iconImage.ToCanvas(new Point(0, 0)).Y, + Width = _iconImage.Width, + Height = _iconImage.Height + }; + + return rect; + } } diff --git a/Intersect.Client.Core/Interface/Game/Spells/SpellsWindow.cs b/Intersect.Client.Core/Interface/Game/Spells/SpellsWindow.cs index 6af3dd98e9..a0c9500dcb 100644 --- a/Intersect.Client.Core/Interface/Game/Spells/SpellsWindow.cs +++ b/Intersect.Client.Core/Interface/Game/Spells/SpellsWindow.cs @@ -1,191 +1,94 @@ -using Intersect.Client.Core; +using Intersect.Client.Core; using Intersect.Client.Framework.File_Management; using Intersect.Client.Framework.GenericClasses; +using Intersect.Client.Framework.Gwen; using Intersect.Client.Framework.Gwen.Control; -using Intersect.Client.General; using Intersect.Client.Localization; -using Intersect.GameObjects; +using Intersect.Client.Utilities; namespace Intersect.Client.Interface.Game.Spells; - -public partial class SpellsWindow +public partial class SpellsWindow : Window { + public List Items { get; set; } = []; + private readonly ScrollControl _slotContainer; + private readonly ContextMenu _contextMenu; - //Spell List - public List Items = new List(); - - //Initialized - private bool mInitializedSpells; - - //Item/Spell Rendering - private ScrollControl mItemContainer; - - //Controls - private WindowControl mSpellWindow; - - //Location - public int X; - - public int Y; - - // Context menu - private Framework.Gwen.Control.Menu mContextMenu; - - private MenuItem mUseSpellContextItem; - - private MenuItem mForgetSpellContextItem; - - //Init - public SpellsWindow(Canvas gameCanvas) + public SpellsWindow(Canvas gameCanvas) : base(gameCanvas, Strings.Spells.Title, false, nameof(SpellsWindow)) { - mSpellWindow = new WindowControl(gameCanvas, Strings.Spells.Title, false, "SpellsWindow"); - mSpellWindow.DisableResizing(); + DisableResizing(); - mItemContainer = new ScrollControl(mSpellWindow, "SpellsContainer"); - mItemContainer.EnableScroll(false, true); - mSpellWindow.LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer.GetResolutionString()); + Alignment = [Alignments.Bottom, Alignments.Right]; + MinimumSize = new Point(x: 225, y: 327); + Margin = new Margin(0, 0, 15, 60); + IsVisibleInTree = false; + IsResizable = false; + IsClosable = true; - // Generate our context menu with basic options. - mContextMenu = new Framework.Gwen.Control.Menu(gameCanvas, "SpellContextMenu"); - mContextMenu.IsHidden = true; - mContextMenu.IconMarginDisabled = true; - //TODO: Is this a memory leak? - mContextMenu.ClearChildren(); - mUseSpellContextItem = mContextMenu.AddItem(Strings.SpellContextMenu.Cast); - mUseSpellContextItem.Clicked += MUseSpellContextItem_Clicked; - mForgetSpellContextItem = mContextMenu.AddItem(Strings.SpellContextMenu.Forget); - mForgetSpellContextItem.Clicked += MForgetSpellContextItem_Clicked; - mContextMenu.LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer.GetResolutionString()); - } - - public void OpenContextMenu(int slot) - { - // Clear out the old options. - mContextMenu.RemoveChild(mUseSpellContextItem, false); - mContextMenu.RemoveChild(mForgetSpellContextItem, false); - mContextMenu.ClearChildren(); - - var spell = SpellDescriptor.Get(Globals.Me.Spells[slot].Id); - - // No point showing a menu for blank space. - if (spell == null) + _slotContainer = new ScrollControl(this, "SpellsContainer") { - return; - } - - // Add our use spell option. - mContextMenu.AddChild(mUseSpellContextItem); - mUseSpellContextItem.SetText(Strings.SpellContextMenu.Cast.ToString(spell.Name)); + Dock = Pos.Fill, + OverflowX = OverflowBehavior.Auto, + OverflowY = OverflowBehavior.Scroll, + }; - // If this spell is not bound, allow users to forget it! - if (!spell.Bound) + _contextMenu = new ContextMenu(gameCanvas, "SpellContextMenu") { - mContextMenu.AddChild(mForgetSpellContextItem); - mForgetSpellContextItem.SetText(Strings.SpellContextMenu.Forget.ToString(spell.Name)); - } - - // Set our spell slot as userdata for future reference. - mContextMenu.UserData = slot; - - mContextMenu.SizeToChildren(); - mContextMenu.Open(Framework.Gwen.Pos.None); - } - - private void MForgetSpellContextItem_Clicked(Base sender, Framework.Gwen.Control.EventArguments.MouseButtonState arguments) - { - var slot = (int)sender.Parent.UserData; - Globals.Me.TryForgetSpell(slot); + IsVisibleInParent = false, + IconMarginDisabled = true, + ItemFont = GameContentManager.Current.GetFont(name: "sourcesansproblack"), + ItemFontSize = 10, + }; } - private void MUseSpellContextItem_Clicked(Base sender, Framework.Gwen.Control.EventArguments.MouseButtonState arguments) + protected override void EnsureInitialized() { - var slot = (int)sender.Parent.UserData; - Globals.Me.TryUseSpell(slot); + LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer.GetResolutionString()); + InitItemContainer(); } - //Methods public void Update() { - if (!mInitializedSpells) - { - InitItemContainer(); - mInitializedSpells = true; - } - - if (mSpellWindow.IsHidden == true) + if (!IsVisibleInTree) { return; } - X = mSpellWindow.X; - Y = mSpellWindow.Y; - for (var i = 0; i < Options.Instance.Player.MaxSpells; i++) + var slotCount = Math.Min(Items.Count, Options.Instance.Player.MaxSpells); + for (var slotIndex = 0; slotIndex < slotCount; slotIndex++) { - var spell = SpellDescriptor.Get(Globals.Me.Spells[i].Id); - Items[i].Pnl.IsHidden = spell == null || Items[i].IsDragging; - if (spell != null) - { - Items[i].Update(); - } + Items[slotIndex].Update(); } } private void InitItemContainer() { - for (var i = 0; i < Options.Instance.Player.MaxSpells; i++) + for (var slotIndex = 0; slotIndex < Options.Instance.Player.MaxSpells; slotIndex++) { - Items.Add(new SpellItem(this, i)); - Items[i].Container = new ImagePanel(mItemContainer, "Spell"); - Items[i].Setup(); - - Items[i].Container.LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer.GetResolutionString()); - - var xPadding = Items[i].Container.Margin.Left + Items[i].Container.Margin.Right; - var yPadding = Items[i].Container.Margin.Top + Items[i].Container.Margin.Bottom; - Items[i] - .Container.SetPosition( - i % - (mItemContainer.Width / (Items[i].Container.Width + xPadding)) * - (Items[i].Container.Width + xPadding) + - xPadding, - i / - (mItemContainer.Width / (Items[i].Container.Width + xPadding)) * - (Items[i].Container.Height + yPadding) + - yPadding - ); + Items.Add(new SpellItem(this, _slotContainer, slotIndex, _contextMenu)); } - } - public void Show() - { - mSpellWindow.IsHidden = false; + PopulateSlotContainer.Populate(_slotContainer, Items); } - public bool IsVisible() + public override void Hide() { - return !mSpellWindow.IsHidden; - } - - public void Hide() - { - mContextMenu?.Close(); - mSpellWindow.IsHidden = true; + _contextMenu?.Close(); + base.Hide(); } public FloatRect RenderBounds() { var rect = new FloatRect() { - X = mSpellWindow.ToCanvas(new Point(0, 0)).X - - (Items[0].Container.Padding.Left + Items[0].Container.Padding.Right) / 2, - Y = mSpellWindow.ToCanvas(new Point(0, 0)).Y - - (Items[0].Container.Padding.Top + Items[0].Container.Padding.Bottom) / 2, - Width = mSpellWindow.Width + Items[0].Container.Padding.Left + Items[0].Container.Padding.Right, - Height = mSpellWindow.Height + Items[0].Container.Padding.Top + Items[0].Container.Padding.Bottom + X = ToCanvas(new Point(0, 0)).X - + (Items[0].Padding.Left + Items[0].Padding.Right) / 2, + Y = ToCanvas(new Point(0, 0)).Y - + (Items[0].Padding.Top + Items[0].Padding.Bottom) / 2, + Width = Width + Items[0].Padding.Left + Items[0].Padding.Right, + Height = Height + Items[0].Padding.Top + Items[0].Padding.Bottom }; return rect; } - }