For the tool tips shown if you let the mouse pointer hover over any of the cells in the paperdoll (inventory subset showing worn and wielded items), remove the trailing period and add a leading space and a trailing space. Improves readability.
309 lines
11 KiB
C++
309 lines
11 KiB
C++
// Copyright (c) Warwick Allison, 1999.
|
|
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
|
|
// NetHack may be freely redistributed. See license for details.
|
|
|
|
// qt_inv.cpp -- inventory usage window
|
|
//
|
|
// Essentially a "paper doll" style display. [grep fodder]
|
|
//
|
|
// This is at the top center of the main window
|
|
|
|
extern "C" {
|
|
#include "hack.h"
|
|
}
|
|
|
|
#include "qt_pre.h"
|
|
#include <QtGui/QtGui>
|
|
#if QT_VERSION >= 0x050000
|
|
#include <QtWidgets/QtWidgets>
|
|
#endif
|
|
#include "qt_post.h"
|
|
#include "qt_inv.h"
|
|
#include "qt_glyph.h"
|
|
#include "qt_main.h"
|
|
#include "qt_set.h"
|
|
|
|
namespace nethack_qt_ {
|
|
|
|
static struct obj *
|
|
find_tool(int tooltyp)
|
|
{
|
|
struct obj *o;
|
|
|
|
for (o = g.invent; o; o = o->nobj) {
|
|
if ((tooltyp == LEASH && o->otyp == LEASH && o->leashmon)
|
|
// OIL_LAMP is used for candles, lamps, lantern, candelabrum too
|
|
|| (tooltyp == OIL_LAMP && o->lamplit))
|
|
break;
|
|
}
|
|
return o;
|
|
}
|
|
|
|
NetHackQtInvUsageWindow::NetHackQtInvUsageWindow(QWidget* parent) :
|
|
QWidget(parent)
|
|
{
|
|
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
// needed to enable tool tips
|
|
setMouseTracking(true);
|
|
|
|
// paperdoll is 6x3 but the indices are column oriented: 0..2x0..5
|
|
for (int x = 0; x <= 2; ++x)
|
|
for (int y = 0; y <= 5; ++y)
|
|
tips[x][y] = NULL;
|
|
}
|
|
|
|
NetHackQtInvUsageWindow::~NetHackQtInvUsageWindow()
|
|
{
|
|
for (int x = 0; x <= 2; ++x)
|
|
for (int y = 0; y <= 5; ++y)
|
|
if (tips[x][y])
|
|
free((void *) tips[x][y]), tips[x][y] = NULL;
|
|
}
|
|
|
|
void NetHackQtInvUsageWindow::drawWorn(QPainter &painter, obj *nhobj,
|
|
int x, int y, // cell index, not pixels
|
|
const char *alttip, int flags)
|
|
{
|
|
short int glyph;
|
|
int border;
|
|
char tipstr[1 + BUFSZ + 1]; // extra room for leading and trailing space
|
|
bool rev = (flags == dollReverse),
|
|
canbe = (flags != dollUnused);
|
|
|
|
if (nhobj) {
|
|
border = BORDER_DEFAULT;
|
|
#ifdef ENHANCED_PAPERDOLL
|
|
// color margin around cell containing item whose BUC state is known
|
|
if (Role_if('P') && !Blind)
|
|
nhobj->bknown = 1;
|
|
if (nhobj->bknown)
|
|
border = nhobj->cursed ? BORDER_CURSED
|
|
: !nhobj->blessed ? BORDER_UNCURSED
|
|
: BORDER_BLESSED;
|
|
|
|
// set up a tool tip describing the item that will be displayed here
|
|
Sprintf(tipstr, " %s ", // extra spaces for enhanced readability
|
|
// xprname: invlet, space, dash, space, object description
|
|
xprname(nhobj, (char *) NULL, nhobj->invlet, FALSE, 0L, 0L));
|
|
// tips are managed with nethack's alloc(); we don't track allocation
|
|
// amount; allocated buffers get reused when big enough (usual case
|
|
// since paperdoll updates occur more often than equipment changes)
|
|
if (tips[x][y] && strlen(tipstr) > strlen(tips[x][y]))
|
|
free((void *) tips[x][y]), tips[x][y] = NULL;
|
|
|
|
if (tips[x][y])
|
|
Strcpy(tips[x][y], tipstr); // guaranteed to fit
|
|
else
|
|
tips[x][y] = dupstr(tipstr);
|
|
#endif
|
|
glyph = obj_to_glyph(nhobj, rn2_on_display_rng);
|
|
} else {
|
|
border = NO_BORDER;
|
|
#ifdef ENHANCED_PAPERDOLL
|
|
// caller usually passes an alternate tool tip for empty cells
|
|
size_t altlen = alttip ? 1U + strlen(alttip) + 1U : 0U;
|
|
if (tips[x][y] && (!alttip || altlen > strlen(tips[x][y])))
|
|
free((void *) tips[x][y]), tips[x][y] = NULL;
|
|
|
|
if (alttip) {
|
|
Sprintf(tipstr, " %s ", alttip);
|
|
if (tips[x][y])
|
|
Strcpy(tips[x][y], tipstr); // guaranteed to fit
|
|
else
|
|
tips[x][y] = dupstr(tipstr);
|
|
}
|
|
#else
|
|
nhUse(alttip);
|
|
#endif
|
|
// an empty slot is shown as floor tile unless it's always empty
|
|
glyph = canbe ? cmap_to_glyph(S_room) : GLYPH_UNEXPLORED;
|
|
}
|
|
qt_settings->glyphs().drawBorderedCell(painter, glyph, x, y, border, rev);
|
|
}
|
|
|
|
// called to update the paper doll inventory subset
|
|
void NetHackQtInvUsageWindow::paintEvent(QPaintEvent*)
|
|
{
|
|
// Paper doll is a 6 row by 3 column grid of worn and wielded
|
|
// equipment showing the map tiles that the inventory objects
|
|
// would be displayed as if they were on the floor.
|
|
//
|
|
// 0 1 2 two- dual
|
|
// [ old ] normal hander wielding legend
|
|
// 0 [x H b] b H q b H q b H q b eyewear H helmet q quiver
|
|
// 1 [S " w] S " w W " W X " w S shield " amulet w weapon
|
|
// 2 [G C G] G C x G C x G C . G gloves C cloak x alt-weap
|
|
// 3 [= A =] = A = = A = = A = = left rg A suit = right ring
|
|
// 4 [. U .] l U L l U L l U L l leash U shirt L light
|
|
// 5 [. F .] . F . . F . . F . . blank F boots . blank
|
|
// W wielded two-handed weapon
|
|
// X wielded secondary weapon
|
|
//
|
|
// 3.7: use a different legend for the layout:
|
|
// show gloves in only one slot;
|
|
// move alternate weapon to former right hand glove slot;
|
|
// move blindfold to former alternate weapon slot;
|
|
// add quiver to former blindfold slot;
|
|
// show secondary weapon in shield slot when two-weapon is active;
|
|
// show two-handed primary weapon in both shield and uwep slots;
|
|
// show lit lamp/lantern/candle/candelabrum on lower right side;
|
|
// show leash-in-use on lower left side
|
|
//
|
|
// Actually indexed by grid[column][row].
|
|
|
|
#ifdef ENHANCED_PAPERDOLL
|
|
if (iflags.wc_ascii_map)
|
|
qt_settings->doll_is_shown = false;
|
|
if (!qt_settings->doll_is_shown)
|
|
return;
|
|
// set glyphs() for the paper doll; might be different size than map's
|
|
qt_settings->glyphs().setSize(qt_settings->dollWidth,
|
|
qt_settings->dollHeight);
|
|
|
|
/* for drawWorn()'s use of obj->invlet */
|
|
if (!flags.invlet_constant)
|
|
reassign();
|
|
#endif
|
|
|
|
QPainter painter;
|
|
painter.begin(this);
|
|
|
|
// String argument is for a tool tip when the object in question is Null.
|
|
//
|
|
// left column
|
|
drawWorn(painter, ublindf, 0, 0, "no eyewear"); // bf|towel|lenses
|
|
/* shield slot varies depending upon weapon usage;
|
|
no alt tool tip is needed for first two cases because object will
|
|
never be Null when the corresponding tests pass */
|
|
if (u.twoweap)
|
|
drawWorn(painter, uswapwep, 0, 1, NULL); // secondary weapon, in use
|
|
else if (uwep && bimanual(uwep)) // show two-handed uwep twice
|
|
drawWorn(painter, uwep, 0, 1, NULL, dollReverse); // uwep on left
|
|
else
|
|
drawWorn(painter, uarms, 0, 1, "no shield");
|
|
drawWorn(painter, uarmg, 0, 2, "no gloves");
|
|
drawWorn(painter, uleft, 0, 3, "no left ring");
|
|
/* light source and leash aren't unique and don't have pointers defined */
|
|
drawWorn(painter, find_tool(LEASH), 0, 4, "no leashes in use");
|
|
drawWorn(painter, NULL, 0, 5, NULL, dollUnused); // always blank
|
|
|
|
// middle column; no unused slots
|
|
drawWorn(painter, uarmh, 1, 0, "no helmet");
|
|
drawWorn(painter, uamul, 1, 1, "no amulet");
|
|
drawWorn(painter, uarmc, 1, 2, "no cloak");
|
|
drawWorn(painter, uarm, 1, 3, "no suit");
|
|
drawWorn(painter, uarmu, 1, 4, "no shirt");
|
|
drawWorn(painter, uarmf, 1, 5, "no boots");
|
|
|
|
// right column
|
|
drawWorn(painter, uquiver, 2, 0, "nothing readied for firing"); // quiver
|
|
drawWorn(painter, uwep, 2, 1, "no weapon");
|
|
/* uswapwep slot varies depending upon dual-wielding state;
|
|
shown in shield slot when actively wielded, so uswapwep slot is empty
|
|
then and an alternate tool tip is used to explain that emptiness */
|
|
if (!u.twoweap)
|
|
drawWorn(painter, uswapwep, 2, 2, "no alternate weapon");
|
|
else
|
|
drawWorn(painter, NULL, 2, 2, "secondary weapon is wielded");
|
|
drawWorn(painter, uright, 2, 3, "no right ring");
|
|
/* OIL_LAMP matches lit candles, lamps, lantern, and candelabrum
|
|
(and might also duplicate Sunsword when it is wielded--hence lit--
|
|
depending upon whether another light source precedes it in invent) */
|
|
drawWorn(painter, find_tool(OIL_LAMP), 2, 4, "no active light sources");
|
|
drawWorn(painter, NULL, 2, 5, NULL, dollUnused); // always blank
|
|
|
|
painter.end();
|
|
|
|
#ifdef ENHANCED_PAPERDOLL
|
|
// reset glyphs() to the ones being used for the map
|
|
qt_settings->glyphs().setSize(qt_settings->tileWidth,
|
|
qt_settings->tileHeight);
|
|
#endif
|
|
}
|
|
|
|
QSize NetHackQtInvUsageWindow::sizeHint(void) const
|
|
{
|
|
if (qt_settings) {
|
|
int w = 0, h = 1; // one pixel margin at top
|
|
// 1+X+1: one pixel border surrounding each tile in the paper doll,
|
|
// so +1 left and +1 right, also +1 above and +1 below
|
|
#ifdef ENHANCED_PAPERDOLL
|
|
if (iflags.wc_ascii_map)
|
|
qt_settings->doll_is_shown = false;
|
|
if (qt_settings->doll_is_shown) {
|
|
w += (1 + qt_settings->dollWidth + 1) * 3;
|
|
h += (1 + qt_settings->dollHeight + 1) * 6;
|
|
}
|
|
#else
|
|
if (iflags.wc_tiled_map) {
|
|
w += (1 + qt_settings->glyphs().width() + 1) * 3;
|
|
h += (1 + qt_settings->glyphs().height() + 1) * 6;
|
|
}
|
|
#endif
|
|
return QSize(w, h);
|
|
} else {
|
|
return QWidget::sizeHint();
|
|
}
|
|
}
|
|
|
|
// ENHANCED_PAPERDOLL - called when a tool tip is triggered by hovering mouse
|
|
bool NetHackQtInvUsageWindow::tooltip_event(QHelpEvent *tipevent)
|
|
{
|
|
#ifdef ENHANCED_PAPERDOLL
|
|
if (iflags.wc_ascii_map)
|
|
qt_settings->doll_is_shown = false;
|
|
if (!qt_settings->doll_is_shown) {
|
|
tipevent->ignore();
|
|
return false;
|
|
}
|
|
int wd = qt_settings->dollWidth,
|
|
ht = qt_settings->dollHeight;
|
|
|
|
// inverse of drawBorderedCell();
|
|
int yoffset = 1, // tiny extra margin at top
|
|
ex = tipevent->pos().x(),
|
|
ey = tipevent->pos().y() - yoffset,
|
|
// KISS: treat 1-pixel margin around cells as part of enclosed cell
|
|
cellx = ex / (wd + 2),
|
|
celly = ey / (ht + 2);
|
|
|
|
const char *tip = (cellx >= 0 && cellx <= 2 && celly >= 0 && celly <= 5)
|
|
? tips[cellx][celly] : NULL;
|
|
if (tip && *tip) {
|
|
QToolTip::showText(tipevent->globalPos(), QString(tip));
|
|
} else {
|
|
QToolTip::hideText();
|
|
tipevent->ignore();
|
|
}
|
|
#else
|
|
nhUse(tipevent);
|
|
#endif /* ENHANCED_PAPERDOLL */
|
|
return true;
|
|
}
|
|
|
|
// ENHANCED_PAPERDOLL - event handler is necessary to support tool tips
|
|
bool NetHackQtInvUsageWindow::event(QEvent *event)
|
|
{
|
|
#ifdef ENHANCED_PAPERDOLL
|
|
if (event->type() == QEvent::ToolTip) {
|
|
QHelpEvent *tipevent = static_cast <QHelpEvent *> (event);
|
|
return tooltip_event(tipevent);
|
|
}
|
|
#endif
|
|
// with this routine intercepting events, we need to pass along
|
|
// paint and mouse-press events to have them handled
|
|
return QWidget::event(event);
|
|
|
|
}
|
|
|
|
// ENHANCED_PAPERDOLL - clicking on the PaperDoll runs #seeall ('*')
|
|
void NetHackQtInvUsageWindow::mousePressEvent(QMouseEvent *event UNUSED)
|
|
{
|
|
#ifdef ENHANCED_PAPERDOLL
|
|
QWidget *main = NetHackQtBind::mainWidget();
|
|
(static_cast <NetHackQtMainWindow *> (main))->FuncAsCommand(doprinuse);
|
|
#endif
|
|
}
|
|
|
|
} // namespace nethack_qt_
|