1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-16 04:25:23 +00:00

More changes in panel logic (#37)

* refactoring of minipanel

* Yet another refactoring of panels
This commit is contained in:
Kacper Drobny 2018-12-08 17:09:56 +01:00 committed by Diego M
parent 98bb55a8ea
commit 4b3df24a77
10 changed files with 249 additions and 151 deletions

View File

@ -46,6 +46,11 @@ namespace OpenDiablo2.Common.Interfaces
/// </summary>
OnToggleDelegate OnToggle { get; set; }
/// <summary>
/// Toggle the button. Only valid for toggle buttons.
/// </summary>
bool Toggle();
string Text { get; set; }
/// <summary>

View File

@ -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();
}
}

View File

@ -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();

View File

@ -87,6 +87,7 @@
<Compile Include="Interfaces\MessageBus\IMessageFrame.cs" />
<Compile Include="Interfaces\MessageBus\ISessionManager.cs" />
<Compile Include="Interfaces\MessageBus\ISessionServer.cs" />
<Compile Include="Interfaces\UI\IGameHUD.cs" />
<Compile Include="Interfaces\UI\IPanel.cs" />
<Compile Include="Models\AnimationData.cs" />
<Compile Include="Models\BitMuncher.cs" />

View File

@ -22,6 +22,7 @@ namespace OpenDiablo2.Core
builder.RegisterType<GameEngine>().AsImplementedInterfaces().SingleInstance();
builder.RegisterType<GameState>().As<IGameState>().SingleInstance();
builder.RegisterType<MapEngine>().As<IMapEngine>().SingleInstance();
builder.RegisterType<GameHUD>().As<IGameHUD>().InstancePerDependency();
builder.RegisterType<MiniPanel>().As<IMiniPanel>().InstancePerDependency();
builder.RegisterType<PanelFrame>().As<IPanelFrame>().InstancePerDependency();
builder.RegisterType<CharacterPanel>().AsImplementedInterfaces().InstancePerDependency();

View File

@ -68,6 +68,7 @@
<Compile Include="ResourceManager.cs" />
<Compile Include="TextDictionary.cs" />
<Compile Include="UI\Button.cs" />
<Compile Include="UI\GameHUD.cs" />
<Compile Include="UI\ItemContainer.cs" />
<Compile Include="UI\PanelFrame.cs" />
<Compile Include="UI\InventoryPanel.cs" />

View File

@ -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;

View File

@ -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<IMiniPanel> createMiniPanel,
Func<eButtonType, IButton> createButton,
Func<ePanelFrameType, IPanelFrame> 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);
}
}
}

View File

@ -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<IButton> buttons;
private readonly IEnumerable<IPanel> 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<IPanel> panels, Func<eButtonType, IButton> createButton,
Func<ePanelFrameType, IPanelFrame> createPanelFrame)
public MiniPanel(IRenderWindow renderWindow,
IGameState gameState,
IMouseInfoProvider mouseInfoProvider,
IEnumerable<IPanel> panels,
Func<eButtonType, IButton> 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);

View File

@ -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<eButtonType, IButton> createButton,
Func<IMiniPanel> 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)