Browse Source

improved hints and added icons

pull/4116/head
Felipe Wannmacher 4 years ago committed by Anders Jenbo
parent
commit
6a6fd404dc
  1. 3
      CMake/Assets.cmake
  2. BIN
      Packaging/resources/assets/data/hintbox.pcx
  3. BIN
      Packaging/resources/assets/data/hintboxbackground.pcx
  4. BIN
      Packaging/resources/assets/data/hinticons.pcx
  5. 4
      Source/control.cpp
  6. 189
      Source/controls/modifier_hints.cpp
  7. 2
      Source/controls/modifier_hints.h

3
CMake/Assets.cmake

@ -49,6 +49,9 @@ set(devilutionx_assets
data/dirtybucp.pcx
data/healthbox.pcx
data/health.pcx
data/hintbox.pcx
data/hintboxbackground.pcx
data/hinticons.pcx
data/panel8buc.pcx
data/panel8bucp.pcx
data/monstertags.pcx

BIN
Packaging/resources/assets/data/hintbox.pcx

Binary file not shown.

BIN
Packaging/resources/assets/data/hintboxbackground.pcx

Binary file not shown.

BIN
Packaging/resources/assets/data/hinticons.pcx

Binary file not shown.

4
Source/control.cpp

@ -14,6 +14,7 @@
#include "DiabloUI/art.h"
#include "DiabloUI/art_draw.h"
#include "automap.h"
#include "controls/modifier_hints.h"
#include "controls/plrctrls.h"
#include "cursor.h"
#include "engine/cel_sprite.hpp"
@ -565,6 +566,8 @@ void InitControlPan()
initialDropGoldIndex = 0;
CalculatePanelAreas();
InitModifierHints();
}
void DrawCtrlPan(const Surface &out)
@ -830,6 +833,7 @@ void FreeControlPan()
pGBoxBuff = std::nullopt;
FreeMainPanel();
FreeCharPanel();
FreeModifierHints();
}
void DrawInfoBox(const Surface &out)

189
Source/controls/modifier_hints.cpp

@ -2,6 +2,7 @@
#include <cstddef>
#include "DiabloUI/art_draw.h"
#include "DiabloUI/ui_flags.hpp"
#include "control.h"
#include "controls/controller.h"
@ -18,15 +19,6 @@ extern std::optional<CelSprite> pSBkIconCels;
namespace {
int SpaceWidth()
{
static const int Result = GetLineWidth(" ");
return Result;
}
/** The number of spaces between left and right hints. */
constexpr int MidSpaces = 5;
/** Vertical distance between text lines. */
constexpr int LineHeight = 25;
@ -45,121 +37,95 @@ constexpr int IconSizeTextMarginRight = 3;
/** Spell icon text top margin. */
constexpr int IconSizeTextMarginTop = 2;
constexpr int HintBoxSize = 39;
constexpr int HintBoxMargin = 5;
Art hintBox;
Art hintBoxBackground;
Art hintIcons;
enum HintIcon : uint8_t {
IconChar,
IconInv,
IconQuests,
IconSpells,
IconMap,
IconMenu,
IconNull
};
struct CircleMenuHint {
CircleMenuHint(bool isDpad, const char *top, const char *right, const char *bottom, const char *left)
: isDpad(isDpad)
, top(top)
, topW(GetLineWidth(top))
CircleMenuHint(HintIcon top, HintIcon right, HintIcon bottom, HintIcon left)
: top(top)
, right(right)
, rightW(GetLineWidth(right))
, bottom(bottom)
, bottomW(GetLineWidth(bottom))
, left(left)
, leftW(GetLineWidth(left))
, xMid(leftW + SpaceWidth() * MidSpaces / 2)
{
}
[[nodiscard]] int Width() const
{
return 2 * xMid;
}
bool isDpad;
const char *top;
int topW;
const char *right;
int rightW;
const char *bottom;
int bottomW;
const char *left;
int leftW;
int xMid;
HintIcon top;
HintIcon right;
HintIcon bottom;
HintIcon left;
};
bool IsTopActive(const CircleMenuHint &hint)
{
if (hint.isDpad)
return IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_UP);
return IsControllerButtonPressed(ControllerButton_BUTTON_Y);
}
bool IsRightActive(const CircleMenuHint &hint)
{
if (hint.isDpad)
return IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_RIGHT);
return IsControllerButtonPressed(ControllerButton_BUTTON_B);
}
bool IsBottomActive(const CircleMenuHint &hint)
{
if (hint.isDpad)
return IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_DOWN);
return IsControllerButtonPressed(ControllerButton_BUTTON_A);
}
bool IsLeftActive(const CircleMenuHint &hint)
{
if (hint.isDpad)
return IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_LEFT);
return IsControllerButtonPressed(ControllerButton_BUTTON_X);
}
UiFlags CircleMenuHintTextColor(bool active)
{
return active ? UiFlags::ColorBlue : UiFlags::ColorWhitegold;
}
UiFlags CircleSpellMenuHintTextColor(bool active)
{
return active ? UiFlags::ColorBlue : UiFlags::ColorWhite;
}
/**
* @brief Draws hint text for a four button layout with the top/left edge of the bounding box at the position given by origin.
* @param out The output buffer to draw on.
* @param hint Struct describing the text to draw and the dimensions of the layout.
* @param hint Struct describing the icon to draw.
* @param origin Top left corner of the layout (relative to the output buffer).
*/
void DrawCircleMenuHint(const Surface &out, const CircleMenuHint &hint, const Point &origin)
{
DrawString(out, hint.top, origin + Displacement { hint.xMid - hint.topW / 2, 0 }, CircleMenuHintTextColor(IsTopActive(hint)));
const Displacement backgroundDisplacement = { (HintBoxSize - IconSize) / 2 + 1, (HintBoxSize - IconSize) / 2 - 1 };
Point hintBoxPositions[4] = {
origin + Displacement { 0, LineHeight - HintBoxSize },
origin + Displacement { HintBoxSize + HintBoxMargin, LineHeight - HintBoxSize * 2 - HintBoxMargin },
origin + Displacement { HintBoxSize + HintBoxMargin, LineHeight + HintBoxMargin },
origin + Displacement { HintBoxSize * 2 + HintBoxMargin * 2, LineHeight - HintBoxSize }
};
Point iconPositions[4] = {
hintBoxPositions[0] + backgroundDisplacement,
hintBoxPositions[1] + backgroundDisplacement,
hintBoxPositions[2] + backgroundDisplacement,
hintBoxPositions[3] + backgroundDisplacement,
};
uint8_t iconIndices[4] { hint.left, hint.top, hint.bottom, hint.right };
DrawString(out, hint.left, origin + Displacement { 0, LineHeight }, CircleMenuHintTextColor(IsLeftActive(hint)));
DrawString(out, hint.right, origin + Displacement { hint.leftW + MidSpaces * SpaceWidth(), LineHeight }, CircleMenuHintTextColor(IsRightActive(hint)));
for (int slot = 0; slot < 4; ++slot) {
if (iconIndices[slot] == HintIcon::IconNull)
continue;
DrawString(out, hint.bottom, origin + Displacement { hint.xMid - hint.bottomW / 2, LineHeight * 2 }, CircleMenuHintTextColor(IsBottomActive(hint)));
DrawArt(out, iconPositions[slot], &hintBoxBackground);
DrawArt(out, iconPositions[slot], &hintIcons, iconIndices[slot], 37, 38);
DrawArt(out, hintBoxPositions[slot], &hintBox);
}
}
/**
* @brief Draws hint text for a four button layout with the top/left edge of the bounding box at the position given by origin plus the icon for the spell mapped to that entry.
* @param out The output buffer to draw on.
* @param hint Struct describing the text to draw and the dimensions of the layout.
* @param origin Top left corner of the layout (relative to the output buffer).
*/
void DrawSpellsCircleMenuHint(const Surface &out, const CircleMenuHint &hint, const Point &origin)
void DrawSpellsCircleMenuHint(const Surface &out, const Point &origin)
{
const auto &myPlayer = Players[MyPlayerId];
Point positions[4] = {
origin + Displacement { 0, LineHeight },
origin + Displacement { IconSize, LineHeight - IconSize },
origin + Displacement { IconSize, LineHeight + IconSize },
origin + Displacement { IconSize * 2, LineHeight }
const Displacement spellIconDisplacement = { (HintBoxSize - IconSize) / 2 + 1, HintBoxSize - (HintBoxSize - IconSize) / 2 - 1 };
Point hintBoxPositions[4] = {
origin + Displacement { 0, LineHeight - HintBoxSize },
origin + Displacement { HintBoxSize + HintBoxMargin, LineHeight - HintBoxSize * 2 - HintBoxMargin },
origin + Displacement { HintBoxSize + HintBoxMargin, LineHeight + HintBoxMargin },
origin + Displacement { HintBoxSize * 2 + HintBoxMargin * 2, LineHeight - HintBoxSize }
};
Point textPositions[4] = {
positions[0] + Displacement { IconSize - hint.leftW - IconSizeTextMarginRight, IconSizeTextMarginTop - IconSize },
positions[1] + Displacement { IconSize - hint.topW - IconSizeTextMarginRight, IconSizeTextMarginTop - IconSize },
positions[2] + Displacement { IconSize - hint.bottomW - IconSizeTextMarginRight, IconSizeTextMarginTop - IconSize },
positions[3] + Displacement { IconSize - hint.rightW - IconSizeTextMarginRight, IconSizeTextMarginTop - IconSize }
Point spellIconPositions[4] = {
hintBoxPositions[0] + spellIconDisplacement,
hintBoxPositions[1] + spellIconDisplacement,
hintBoxPositions[2] + spellIconDisplacement,
hintBoxPositions[3] + spellIconDisplacement,
};
const char *texts[4] = { hint.left, hint.top, hint.bottom, hint.right };
bool isActive[4] = { IsLeftActive(hint), IsTopActive(hint), IsBottomActive(hint), IsRightActive(hint) };
uint64_t spells = myPlayer._pAblSpells | myPlayer._pMemSpells | myPlayer._pScrlSpells | myPlayer._pISpells;
spell_id splId;
spell_type splType;
Point textPosition;
for (int slot = 0; slot < 4; ++slot) {
splId = myPlayer._pSplHotKey[slot];
@ -172,11 +138,8 @@ void DrawSpellsCircleMenuHint(const Surface &out, const CircleMenuHint &hint, co
}
SetSpellTrans(splType);
DrawSpellCel(out, positions[slot], *pSBkIconCels, SpellITbl[splId]);
textPosition = textPositions[slot];
// Drop shadow
DrawString(out, texts[slot], textPosition + Displacement { -1, 1 }, UiFlags::ColorBlack);
DrawString(out, texts[slot], textPosition, CircleSpellMenuHintTextColor(isActive[slot]));
DrawSpellCel(out, spellIconPositions[slot], *pSBkIconCels, SpellITbl[splId]);
DrawArt(out, hintBoxPositions[slot], &hintBox);
}
}
@ -184,10 +147,10 @@ void DrawStartModifierMenu(const Surface &out)
{
if (!start_modifier_active)
return;
static const CircleMenuHint DPad(/*isDpad=*/true, /*top=*/_("Menu"), /*right=*/_("Inv"), /*bottom=*/_("Map"), /*left=*/_("Char"));
static const CircleMenuHint Buttons(/*isDpad=*/false, /*top=*/"", /*right=*/"", /*bottom=*/_("Spells"), /*left=*/_("Quests"));
static const CircleMenuHint DPad(/*top=*/HintIcon::IconMenu, /*right=*/HintIcon::IconInv, /*bottom=*/HintIcon::IconMap, /*left=*/HintIcon::IconChar);
static const CircleMenuHint Buttons(/*top=*/HintIcon::IconNull, /*right=*/HintIcon::IconNull, /*bottom=*/HintIcon::IconSpells, /*left=*/HintIcon::IconQuests);
DrawCircleMenuHint(out, DPad, { PANEL_LEFT + CircleMarginX, PANEL_TOP - CircleTop });
DrawCircleMenuHint(out, Buttons, { PANEL_LEFT + PANEL_WIDTH - Buttons.Width() - CircleMarginX, PANEL_TOP - CircleTop });
DrawCircleMenuHint(out, Buttons, { PANEL_LEFT + PANEL_WIDTH - HintBoxSize * 3 - CircleMarginX - HintBoxMargin * 2, PANEL_TOP - CircleTop });
}
void DrawSelectModifierMenu(const Surface &out)
@ -196,15 +159,33 @@ void DrawSelectModifierMenu(const Surface &out)
return;
if (sgOptions.Controller.bDpadHotkeys) {
static const CircleMenuHint DPad(/*isDpad=*/true, /*top=*/"F6", /*right=*/"F8", /*bottom=*/"F7", /*left=*/"F5");
DrawSpellsCircleMenuHint(out, DPad, { PANEL_LEFT + CircleMarginX, PANEL_TOP - CircleTop });
DrawSpellsCircleMenuHint(out, { PANEL_LEFT + CircleMarginX, PANEL_TOP - CircleTop });
}
static const CircleMenuHint Spells(/*isDpad=*/false, "F6", "F8", "F7", "F5");
DrawSpellsCircleMenuHint(out, Spells, { PANEL_LEFT + PANEL_WIDTH - IconSize * 3 - CircleMarginX, PANEL_TOP - CircleTop });
DrawSpellsCircleMenuHint(out, { PANEL_LEFT + PANEL_WIDTH - HintBoxSize * 3 - CircleMarginX - HintBoxMargin * 2, PANEL_TOP - CircleTop });
}
} // namespace
void InitModifierHints()
{
LoadMaskedArt("data\\hintbox.pcx", &hintBox, 1, 1);
LoadMaskedArt("data\\hintboxbackground.pcx", &hintBoxBackground, 1, 1);
LoadMaskedArt("data\\hinticons.pcx", &hintIcons, 6, 1);
if (hintBox.surface == nullptr || hintBoxBackground.surface == nullptr) {
app_fatal("%s", _("Failed to load UI resources.\n"
"\n"
"Make sure devilutionx.mpq is in the game folder and that it is up to date."));
}
}
void FreeModifierHints()
{
hintBox.Unload();
hintBoxBackground.Unload();
hintIcons.Unload();
}
void DrawControllerModifierHints(const Surface &out)
{
DrawStartModifierMenu(out);

2
Source/controls/modifier_hints.h

@ -5,5 +5,7 @@
namespace devilution {
void DrawControllerModifierHints(const Surface &out);
void InitModifierHints();
void FreeModifierHints();
} // namespace devilution

Loading…
Cancel
Save