From 4b3df24a77bc449710ecc647c76d82e63c49c0bf Mon Sep 17 00:00:00 2001 From: Kacper Drobny Date: Sat, 8 Dec 2018 17:09:56 +0100 Subject: [PATCH] More changes in panel logic (#37) * refactoring of minipanel * Yet another refactoring of panels --- OpenDiablo2.Common/Interfaces/UI/IButton.cs | 5 + OpenDiablo2.Common/Interfaces/UI/IGameHUD.cs | 16 ++ .../Interfaces/UI/IMiniPanel.cs | 7 +- OpenDiablo2.Common/OpenDiablo2.Common.csproj | 1 + OpenDiablo2.Core/AutofacModule.cs | 1 + OpenDiablo2.Core/OpenDiablo2.Core.csproj | 1 + OpenDiablo2.Core/UI/Button.cs | 6 - OpenDiablo2.Core/UI/GameHUD.cs | 181 ++++++++++++++++++ OpenDiablo2.Core/UI/MiniPanel.cs | 108 +++-------- OpenDiablo2.Scenes/Game.cs | 74 +------ 10 files changed, 249 insertions(+), 151 deletions(-) create mode 100644 OpenDiablo2.Common/Interfaces/UI/IGameHUD.cs create mode 100644 OpenDiablo2.Core/UI/GameHUD.cs diff --git a/OpenDiablo2.Common/Interfaces/UI/IButton.cs b/OpenDiablo2.Common/Interfaces/UI/IButton.cs index 4b4196b5..aafe5551 100644 --- a/OpenDiablo2.Common/Interfaces/UI/IButton.cs +++ b/OpenDiablo2.Common/Interfaces/UI/IButton.cs @@ -46,6 +46,11 @@ namespace OpenDiablo2.Common.Interfaces /// OnToggleDelegate OnToggle { get; set; } + /// + /// Toggle the button. Only valid for toggle buttons. + /// + bool Toggle(); + string Text { get; set; } /// diff --git a/OpenDiablo2.Common/Interfaces/UI/IGameHUD.cs b/OpenDiablo2.Common/Interfaces/UI/IGameHUD.cs new file mode 100644 index 00000000..d9dbe362 --- /dev/null +++ b/OpenDiablo2.Common/Interfaces/UI/IGameHUD.cs @@ -0,0 +1,16 @@ +namespace OpenDiablo2.Common.Interfaces +{ + public interface IGameHUD + { + bool IsRunningEnabled { get; } + bool IsLeftPanelVisible { get; } + bool IsRightPanelVisible { get; } + + bool IsMouseOver(); + void OpenPanel(IPanel panel); + void OpenPanels(IPanel leftPanel, IPanel rightPanel); + + void Render(); + void Update(); + } +} \ No newline at end of file diff --git a/OpenDiablo2.Common/Interfaces/UI/IMiniPanel.cs b/OpenDiablo2.Common/Interfaces/UI/IMiniPanel.cs index 85a9177c..77e5af11 100644 --- a/OpenDiablo2.Common/Interfaces/UI/IMiniPanel.cs +++ b/OpenDiablo2.Common/Interfaces/UI/IMiniPanel.cs @@ -2,11 +2,14 @@ namespace OpenDiablo2.Common.Interfaces { + public delegate void PanelSelectedEvent(IPanel panel); + public interface IMiniPanel : IDisposable { - bool IsLeftPanelVisible { get; } - bool IsRightPanelVisible { get; } + event PanelSelectedEvent PanelSelected; + bool IsMouseOver(); + void UpdatePanelLocation(); void OnMenuToggle(bool isToggled); void Render(); void Update(); diff --git a/OpenDiablo2.Common/OpenDiablo2.Common.csproj b/OpenDiablo2.Common/OpenDiablo2.Common.csproj index 2de7b29e..d2a7303a 100644 --- a/OpenDiablo2.Common/OpenDiablo2.Common.csproj +++ b/OpenDiablo2.Common/OpenDiablo2.Common.csproj @@ -87,6 +87,7 @@ + diff --git a/OpenDiablo2.Core/AutofacModule.cs b/OpenDiablo2.Core/AutofacModule.cs index 21eb87a8..39599e65 100644 --- a/OpenDiablo2.Core/AutofacModule.cs +++ b/OpenDiablo2.Core/AutofacModule.cs @@ -22,6 +22,7 @@ namespace OpenDiablo2.Core builder.RegisterType().AsImplementedInterfaces().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().InstancePerDependency(); builder.RegisterType().As().InstancePerDependency(); builder.RegisterType().As().InstancePerDependency(); builder.RegisterType().AsImplementedInterfaces().InstancePerDependency(); diff --git a/OpenDiablo2.Core/OpenDiablo2.Core.csproj b/OpenDiablo2.Core/OpenDiablo2.Core.csproj index bd57b144..8fe9ff22 100644 --- a/OpenDiablo2.Core/OpenDiablo2.Core.csproj +++ b/OpenDiablo2.Core/OpenDiablo2.Core.csproj @@ -68,6 +68,7 @@ + diff --git a/OpenDiablo2.Core/UI/Button.cs b/OpenDiablo2.Core/UI/Button.cs index 2d39d2eb..a36a1edd 100644 --- a/OpenDiablo2.Core/UI/Button.cs +++ b/OpenDiablo2.Core/UI/Button.cs @@ -2,16 +2,10 @@ using OpenDiablo2.Common.Interfaces; using OpenDiablo2.Common.Models; using System; -using System.Collections.Generic; using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace OpenDiablo2.Core.UI { - - public sealed class Button : IButton { private readonly IMouseInfoProvider mouseInfoProvider; diff --git a/OpenDiablo2.Core/UI/GameHUD.cs b/OpenDiablo2.Core/UI/GameHUD.cs new file mode 100644 index 00000000..5eee4e93 --- /dev/null +++ b/OpenDiablo2.Core/UI/GameHUD.cs @@ -0,0 +1,181 @@ +using OpenDiablo2.Common; +using OpenDiablo2.Common.Enums; +using OpenDiablo2.Common.Interfaces; +using System; +using System.Diagnostics; +using System.Drawing; + +namespace OpenDiablo2.Core.UI +{ + public class GameHUD : IGameHUD + { + private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private readonly IRenderWindow renderWindow; + private readonly IGameState gameState; + private readonly IMouseInfoProvider mouseInfoProvider; + private readonly IMiniPanel minipanel; + + private readonly IButton runButton, menuButton; + private readonly ISprite panelSprite, healthManaSprite, gameGlobeOverlapSprite; + private readonly IPanelFrame leftPanelFrame, rightPanelFrame; + + public GameHUD( + IRenderWindow renderWindow, + IGameState gameState, + IMouseInfoProvider mouseInfoProvider, + Func createMiniPanel, + Func createButton, + Func createPanelFrame) + { + this.renderWindow = renderWindow; + this.gameState = gameState; + this.mouseInfoProvider = mouseInfoProvider; + minipanel = createMiniPanel(); + minipanel.PanelSelected += OpenPanel; + + leftPanelFrame = createPanelFrame(ePanelFrameType.Left); + rightPanelFrame = createPanelFrame(ePanelFrameType.Right); + + runButton = createButton(eButtonType.Run); + runButton.Location = new Point(256, 570); + runButton.OnToggle = OnRunToggle; + + menuButton = createButton(eButtonType.Menu); + menuButton.Location = new Point(393, 561); + menuButton.OnToggle = minipanel.OnMenuToggle; + menuButton.Toggle(); + + panelSprite = renderWindow.LoadSprite(ResourcePaths.GamePanels, Palettes.Act1); + healthManaSprite = renderWindow.LoadSprite(ResourcePaths.HealthMana, Palettes.Act1); + gameGlobeOverlapSprite = renderWindow.LoadSprite(ResourcePaths.GameGlobeOverlap, Palettes.Act1); + } + + public IPanel LeftPanel { get; private set; } + public IPanel RightPanel { get; private set; } + public bool ArePanelsBounded { get; private set; } = false; + + public bool IsLeftPanelVisible => LeftPanel != null; + public bool IsRightPanelVisible => RightPanel != null; + public bool IsRunningEnabled => runButton.Toggled; + + public void OpenPanel(IPanel panel) + { + switch (panel.FrameType) + { + case ePanelFrameType.Left: + LeftPanel = LeftPanel == panel ? null : panel; + UpdateCameraOffset(); + if (ArePanelsBounded) + RightPanel = null; + ArePanelsBounded = false; + break; + + case ePanelFrameType.Right: + RightPanel = RightPanel == panel ? null : panel; + UpdateCameraOffset(); + if (ArePanelsBounded) + LeftPanel = null; + ArePanelsBounded = false; + break; + + case ePanelFrameType.Center: + // todo; write logic for "center" panels + break; + + default: + Debug.Fail("Unknown frame type"); + break; + } + } + + // used when panels are bounded with each other (shops/chest) + public void OpenPanels(IPanel leftPanel, IPanel rightPanel) + { + if (leftPanel.FrameType != ePanelFrameType.Left || rightPanel.FrameType != ePanelFrameType.Right) + throw new ArgumentException("wrong panel position."); + + LeftPanel = leftPanel; + RightPanel = rightPanel; + UpdateCameraOffset(); + ArePanelsBounded = true; + } + + public bool IsMouseOver() + { + return mouseInfoProvider.MouseY >= 550 + || minipanel.IsMouseOver() + || IsRightPanelVisible && mouseInfoProvider.MouseX >= 400 + || IsLeftPanelVisible && mouseInfoProvider.MouseX < 400; + } + + public void Render() + { + if (IsLeftPanelVisible) + { + LeftPanel.Render(); + leftPanelFrame.Render(); + } + + if (IsRightPanelVisible) + { + RightPanel.Render(); + rightPanelFrame.Render(); + } + + if (!IsLeftPanelVisible || !IsRightPanelVisible) + minipanel.Render(); + + // Render the background bottom bar + renderWindow.Draw(panelSprite, 0, new Point(0, 600)); + renderWindow.Draw(panelSprite, 1, new Point(166, 600)); + renderWindow.Draw(panelSprite, 2, new Point(294, 600)); + renderWindow.Draw(panelSprite, 3, new Point(422, 600)); + renderWindow.Draw(panelSprite, 4, new Point(550, 600)); + renderWindow.Draw(panelSprite, 5, new Point(685, 600)); + + // Render the health bar + renderWindow.Draw(healthManaSprite, 0, new Point(30, 587)); + renderWindow.Draw(gameGlobeOverlapSprite, 0, new Point(28, 595)); + + // Render the mana bar + renderWindow.Draw(healthManaSprite, 1, new Point(692, 588)); + renderWindow.Draw(gameGlobeOverlapSprite, 1, new Point(693, 591)); + + runButton.Render(); + menuButton.Render(); + } + + public void Update() + { + runButton.Update(); + menuButton.Update(); + + if (IsLeftPanelVisible) + { + LeftPanel.Update(); + leftPanelFrame.Update(); + } + + if (IsRightPanelVisible) + { + RightPanel.Update(); + rightPanelFrame.Update(); + } + + if(!IsLeftPanelVisible || !IsRightPanelVisible) + minipanel.Update(); + } + + private void UpdateCameraOffset() + { + gameState.CameraOffset = (IsRightPanelVisible ? -200 : 0) + (IsLeftPanelVisible ? 200 : 0); + minipanel.UpdatePanelLocation(); + } + + private void OnRunToggle(bool isToggled) + { + log.Debug("Run Toggle: " + isToggled); + } + } +} diff --git a/OpenDiablo2.Core/UI/MiniPanel.cs b/OpenDiablo2.Core/UI/MiniPanel.cs index ee914005..d4e9df9c 100644 --- a/OpenDiablo2.Core/UI/MiniPanel.cs +++ b/OpenDiablo2.Core/UI/MiniPanel.cs @@ -1,11 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Linq; -using OpenDiablo2.Common; +using OpenDiablo2.Common; using OpenDiablo2.Common.Enums; using OpenDiablo2.Common.Interfaces; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; namespace OpenDiablo2.Core.UI { @@ -15,29 +14,26 @@ namespace OpenDiablo2.Core.UI eButtonType.MinipanelSkill, eButtonType.MinipanelAutomap, eButtonType.MinipanelMessage, eButtonType.MinipanelQuest, eButtonType.MinipanelMenu }; private readonly IRenderWindow renderWindow; + private readonly IMouseInfoProvider mouseInfoProvider; private readonly IGameState gameState; private readonly ISprite sprite; private readonly IReadOnlyList buttons; private readonly IEnumerable panels; - private readonly IPanelFrame leftPanelFrame; - private readonly IPanelFrame rightPanelFrame; private bool isPanelVisible; - public IPanel LeftPanel { get; private set; } - public IPanel RightPanel { get; private set; } - public bool IsLeftPanelVisible => LeftPanel != null; - public bool IsRightPanelVisible => RightPanel != null; + public event PanelSelectedEvent PanelSelected; - public MiniPanel(IRenderWindow renderWindow, IGameState gameState, - IEnumerable panels, Func createButton, - Func createPanelFrame) + public MiniPanel(IRenderWindow renderWindow, + IGameState gameState, + IMouseInfoProvider mouseInfoProvider, + IEnumerable panels, + Func createButton) { this.renderWindow = renderWindow; + this.mouseInfoProvider = mouseInfoProvider; this.gameState = gameState; this.panels = panels; - leftPanelFrame = createPanelFrame(ePanelFrameType.Left); - rightPanelFrame = createPanelFrame(ePanelFrameType.Right); sprite = renderWindow.LoadSprite(ResourcePaths.MinipanelSmall, Palettes.Units); @@ -48,53 +44,29 @@ namespace OpenDiablo2.Core.UI { var panel = panels.SingleOrDefault(o => o.PanelType == x); if (panel == null) return; - TogglePanel(panel); + PanelSelected?.Invoke(panel); }; return newBtn; }).ToList().AsReadOnly(); UpdatePanelLocation(); - OnMenuToggle(true); } public void OnMenuToggle(bool isToggled) => isPanelVisible = isToggled; - public void Update() + public bool IsMouseOver() { - if (IsLeftPanelVisible) - { - LeftPanel.Update(); - leftPanelFrame.Update(); - } + int xDiff = mouseInfoProvider.MouseX - sprite.Location.X; + int yDiff = mouseInfoProvider.MouseY - sprite.Location.Y + sprite.LocalFrameSize.Height; - if (IsRightPanelVisible) - { - RightPanel.Update(); - rightPanelFrame.Update(); - } - - if (!isPanelVisible || (IsLeftPanelVisible && IsRightPanelVisible)) - return; - - foreach (var button in buttons) - button.Update(); + return isPanelVisible + && xDiff >= 0 && xDiff <= sprite.LocalFrameSize.Width + && yDiff >= 0 && yDiff <= sprite.LocalFrameSize.Height; } public void Render() { - if (IsLeftPanelVisible) - { - LeftPanel.Render(); - leftPanelFrame.Render(); - } - - if (IsRightPanelVisible) - { - RightPanel.Render(); - rightPanelFrame.Render(); - } - - if (!isPanelVisible || (IsLeftPanelVisible && IsRightPanelVisible)) + if (!isPanelVisible) return; renderWindow.Draw(sprite); @@ -103,6 +75,15 @@ namespace OpenDiablo2.Core.UI button.Render(); } + public void Update() + { + if (!isPanelVisible) + return; + + foreach (var button in buttons) + button.Update(); + } + public void Dispose() { foreach (var button in buttons) @@ -111,34 +92,7 @@ namespace OpenDiablo2.Core.UI sprite.Dispose(); } - private void TogglePanel(IPanel panel) - { - switch (panel.FrameType) - { - case ePanelFrameType.Left: - LeftPanel = LeftPanel == panel ? null : panel; - break; - case ePanelFrameType.Right: - RightPanel = RightPanel == panel ? null : panel; - break; - case ePanelFrameType.Center: - // todo; stack center panels - break; - default: - Debug.Fail("Unknown frame type"); - break; - } - - UpdateCameraOffset(); - } - - private void UpdateCameraOffset() - { - gameState.CameraOffset = (IsRightPanelVisible ? -200 : 0) + (IsLeftPanelVisible ? 200 : 0); - UpdatePanelLocation(); - } - - private void UpdatePanelLocation() + public void UpdatePanelLocation() { sprite.Location = new Point((800 - sprite.LocalFrameSize.Width + (int)(gameState.CameraOffset * 1.3f)) / 2, 526 + sprite.LocalFrameSize.Height); diff --git a/OpenDiablo2.Scenes/Game.cs b/OpenDiablo2.Scenes/Game.cs index 0cf5eb6f..2472a59b 100644 --- a/OpenDiablo2.Scenes/Game.cs +++ b/OpenDiablo2.Scenes/Game.cs @@ -18,6 +18,7 @@ namespace OpenDiablo2.Scenes private readonly IGameState gameState; private readonly ISessionManager sessionManager; private readonly IKeyboardInfoProvider keyboardInfoProvider; + private readonly IGameHUD gameHUD; //private ISprite[] testSprite; @@ -39,8 +40,7 @@ namespace OpenDiablo2.Scenes IKeyboardInfoProvider keyboardInfoProvider, IItemManager itemManager, ISessionManager sessionManager, - Func createButton, - Func createMiniPanel + IGameHUD gameHUD ) { this.renderWindow = renderWindow; @@ -49,31 +49,11 @@ namespace OpenDiablo2.Scenes this.mouseInfoProvider = mouseInfoProvider; this.keyboardInfoProvider = keyboardInfoProvider; this.sessionManager = sessionManager; - - - panelSprite = renderWindow.LoadSprite(ResourcePaths.GamePanels, Palettes.Act1); - healthManaSprite = renderWindow.LoadSprite(ResourcePaths.HealthMana, Palettes.Act1); - gameGlobeOverlapSprite = renderWindow.LoadSprite(ResourcePaths.GameGlobeOverlap, Palettes.Act1); - - minipanel = createMiniPanel(); - - runButton = createButton(eButtonType.Run); - runButton.Location = new Point(256, 570); - runButton.OnToggle = OnRunToggle; - - // move to minipanel? - menuButton = createButton(eButtonType.Menu); - menuButton.Location = new Point(393, 561); - menuButton.OnToggle = minipanel.OnMenuToggle; + this.gameHUD = gameHUD; //var item = itemManager.getItem("hdm"); } - private void OnRunToggle(bool isToggled) - { - log.Debug("Run Toggle: " + isToggled); - } - public void Render() { // TODO: Maybe show some sort of connecting/loading message? @@ -81,63 +61,25 @@ namespace OpenDiablo2.Scenes return; mapEngine.Render(); - DrawPanel(); - - } - - private void DrawPanel() - { - minipanel.Render(); - - // Render the background bottom bar - renderWindow.Draw(panelSprite, 0, new Point(0, 600)); - renderWindow.Draw(panelSprite, 1, new Point(166, 600)); - renderWindow.Draw(panelSprite, 2, new Point(294, 600)); - renderWindow.Draw(panelSprite, 3, new Point(422, 600)); - renderWindow.Draw(panelSprite, 4, new Point(550, 600)); - renderWindow.Draw(panelSprite, 5, new Point(685, 600)); - - // Render the health bar - renderWindow.Draw(healthManaSprite, 0, new Point(30, 587)); - renderWindow.Draw(gameGlobeOverlapSprite, 0, new Point(28, 595)); - - // Render the mana bar - renderWindow.Draw(healthManaSprite, 1, new Point(692, 588)); - renderWindow.Draw(gameGlobeOverlapSprite, 1, new Point(693, 591)); - - - - runButton.Render(); - menuButton.Render(); + gameHUD.Render(); } public void Update(long ms) { var seconds = ms / 1000f; - minipanel.Update(); - - runButton.Update(); - menuButton.Update(); - HandleMovement(); mapEngine.Update(ms); + gameHUD.Update(); } private void HandleMovement() { - if (mouseInfoProvider.MouseY > 530) // 550 is what it should be, but the minipanel check needs to happent oo + // todo; if clicked on hud, then we don't move. But when clicked on map and move cursor over hud, then it's fine + if (gameHUD.IsMouseOver()) return; - if (minipanel.IsRightPanelVisible && mouseInfoProvider.MouseX >= 400) - return; - - if (minipanel.IsLeftPanelVisible && mouseInfoProvider.MouseX < 400) - return; - - - // TODO: Filter movement for inventory panel var mx = (mouseInfoProvider.MouseX - 400) - gameState.CameraOffset; var my = (mouseInfoProvider.MouseY - 300); @@ -153,7 +95,7 @@ namespace OpenDiablo2.Scenes if (mouseInfoProvider.LeftMouseDown && (lastMovementType == eMovementType.Stopped || lastDirection != actualDirection)) { lastDirection = actualDirection; - lastMovementType = runButton.Toggled ? eMovementType.Running : eMovementType.Walking; + lastMovementType = gameHUD.IsRunningEnabled ? eMovementType.Running : eMovementType.Walking; sessionManager.MoveRequest(actualDirection, lastMovementType); } else if (!mouseInfoProvider.LeftMouseDown && lastMovementType != eMovementType.Stopped)