diff --git a/3rdparty/discord/rpc/lib/discord-rpc.dll b/3rdparty/discord/rpc/lib/discord-rpc.dll deleted file mode 100644 index 4254cfa2786..00000000000 Binary files a/3rdparty/discord/rpc/lib/discord-rpc.dll and /dev/null differ diff --git a/3rdparty/discord/rpc/lib/discord-rpc32.dll b/3rdparty/discord/rpc/lib/discord-rpc32.dll new file mode 100644 index 00000000000..88c7d0cefe4 Binary files /dev/null and b/3rdparty/discord/rpc/lib/discord-rpc32.dll differ diff --git a/3rdparty/discord/rpc/lib/discord-rpc64.dll b/3rdparty/discord/rpc/lib/discord-rpc64.dll new file mode 100644 index 00000000000..8493c549004 Binary files /dev/null and b/3rdparty/discord/rpc/lib/discord-rpc64.dll differ diff --git a/CI/copy-non-qt-win-dependencies.ps1 b/CI/copy-non-qt-win-dependencies.ps1 index fe8d9ed3b85..f28bd2ec7e5 100644 --- a/CI/copy-non-qt-win-dependencies.ps1 +++ b/CI/copy-non-qt-win-dependencies.ps1 @@ -11,4 +11,4 @@ COPY ..\*.dic . COPY ..\*.aff . XCOPY /S /I /Q /Y $Env:MINGW_BASE_DIR\lib\lua\5.1 . XCOPY /S /I /Q /Y ..\..\3rdparty\lcf lcf -COPY ..\..\3rdparty\discord\rpc\lib\discord-rpc.dll discord-rpc.dll +COPY ..\..\3rdparty\discord\rpc\lib\discord-rpc32.dll discord-rpc32.dll diff --git a/src/Host.cpp b/src/Host.cpp index 075dea05ca7..c887d5101c7 100644 --- a/src/Host.cpp +++ b/src/Host.cpp @@ -331,6 +331,11 @@ Host::Host(int port, const QString& hostname, const QString& login, const QStrin // DISABLED: - Prevent "None" option for user dictionary - changed to true and not changed anywhere else , mEnableUserDictionary(true) , mUseSharedDictionary(false) +, mPlayerRoomStyle(0) +, mPlayerRoomOuterColor(Qt::red) +, mPlayerRoomInnerColor(Qt::white) +, mPlayerRoomOuterDiameterPercentage(120) +, mPlayerRoomInnerDiameterPercentage(70) { // mLogStatus = mudlet::self()->mAutolog; mLuaInterface.reset(new LuaInterface(this)); @@ -2398,3 +2403,31 @@ void Host::updateAnsi16ColorsInTable() { mLuaInterpreter.updateAnsi16ColorsInTable(); } + +void Host::setPlayerRoomStyleDetails(const quint8 styleCode, const quint8 outerDiameter, const quint8 innerDiameter, const QColor& outerColor, const QColor& innerColor) +{ + QMutexLocker locker(& mLock); + // Now we have the exclusive lock on this class's protected members + + mPlayerRoomStyle = styleCode; + mPlayerRoomOuterDiameterPercentage = outerDiameter; + mPlayerRoomInnerDiameterPercentage = innerDiameter; + mPlayerRoomOuterColor = outerColor; + mPlayerRoomInnerColor = innerColor; + // We have made the change to the protected aspects of this class so can unlock the mutex locker and proceed: + locker.unlock(); +} + +void Host::getPlayerRoomStyleDetails(quint8& styleCode, quint8& outerDiameter, quint8& innerDiameter, QColor& primaryColor, QColor& secondaryColor) +{ + QMutexLocker locker(& mLock); + // Now we have the exclusive lock on this class's protected members + + styleCode = mPlayerRoomStyle; + outerDiameter = mPlayerRoomOuterDiameterPercentage; + innerDiameter = mPlayerRoomInnerDiameterPercentage; + primaryColor = mPlayerRoomOuterColor; + secondaryColor = mPlayerRoomInnerColor; + // We have accessed the protected aspects of this class so can unlock the mutex locker and proceed: + locker.unlock(); +} diff --git a/src/Host.h b/src/Host.h index 29b64f28f19..97cd36233fe 100644 --- a/src/Host.h +++ b/src/Host.h @@ -321,6 +321,9 @@ class Host : public QObject void updateProxySettings(QNetworkAccessManager* manager); std::unique_ptr& getConnectionProxy(); void updateAnsi16ColorsInTable(); + // Store/retrieve all the settings in one call: + void setPlayerRoomStyleDetails(const quint8 styleCode, const quint8 outerDiameter = 120, const quint8 innerDiameter = 70, const QColor& outerColor = QColor(), const QColor& innerColor = QColor()); + void getPlayerRoomStyleDetails(quint8& styleCode, quint8& outerDiameter, quint8& innerDiameter, QColor& outerColor, QColor& innerColor); cTelnet mTelnet; QPointer mpConsole; @@ -656,6 +659,28 @@ private slots: // looked up directly by that class: bool mEnableUserDictionary; bool mUseSharedDictionary; + + // These hold values that are needed in the TMap clas which are saved with + // the profile - but which cannot be kept there as that class is not + // necessarily instantiated when the profile is read. + // Base color(s) for the player room in the mappers: + // Mode selected: + // 0 is closest to original style with adjustable outer diameter + // 1 is Fixed red color ring with adjustable outer/inner diameter + // 2 is fixed blue/yellow colors ring with adjustable outer/inner diameter + // 3 is adjustable outer(primary)/inner(secondary) colors ring with adjustable outer/inner diameter + quint8 mPlayerRoomStyle; + QColor mPlayerRoomOuterColor; + QColor mPlayerRoomInnerColor; + // Percentage of the room size (actually width) for the outer diameter of + // the circular marking, integer percentage clamped in the preferences + // between 200 and 50 - default 120: + quint8 mPlayerRoomOuterDiameterPercentage; + // Percentage of the outer size for the inner diameter of the circular + // marking, integer percentage clamped in the preferences between 83 and 0, + // with a default of 70. NOT USED FOR "Original" style marking (the 0'th + // one): + quint8 mPlayerRoomInnerDiameterPercentage; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Host::DiscordOptionFlags) diff --git a/src/T2DMap.cpp b/src/T2DMap.cpp index 4e3dcefd937..8fbec675e69 100644 --- a/src/T2DMap.cpp +++ b/src/T2DMap.cpp @@ -679,12 +679,502 @@ bool T2DMap::sizeFontToFitTextInRect( QFont & font, const QRectF & boundaryRect, return true; } +// Helper that refactors out code to start a speedwalk: +void T2DMap::initiateSpeeWalk(const int speedWalkStartRoomId, const int speedWalkTargetRoomId) +{ + mTarget = speedWalkTargetRoomId; + if (mpMap->mpRoomDB->getRoom(speedWalkTargetRoomId)) { + mpMap->mTargetID = speedWalkTargetRoomId; + if (mpMap->findPath(speedWalkStartRoomId, speedWalkTargetRoomId)) { + mpHost->startSpeedWalk(); + } else { + mpHost->mpConsole->printSystemMessage(tr("Mapper: Cannot find a path from %1 to %2 using known exits.\n") + .arg(QString::number(speedWalkStartRoomId), + QString::number(speedWalkTargetRoomId))); + } + } +} + +// This has been refactored to a separate function out of the paintEven() code +// because we need to use it in two places - one for every room that is not the +// player's room and then, AFTER all those have been drawn, once for the +// player's room if it is visible. This is so it is drawn LAST (and any effects, +// or extra markings for it do not get overwritten by the drawing of the other +// rooms)... +inline void T2DMap::drawRoom(QPainter& painter, QFont& roomVNumFont, QPen& pen, TRoom* pRoom, const bool isGridMode, const bool areRoomIdsLegible, const int speedWalkStartRoomId, const float rx, const float ry, const bool picked) +{ + const int currentRoomId = pRoom->getId(); + pRoom->rendered = false; + QRectF roomRectangle; + if (isGridMode) { + roomRectangle = QRectF(rx - mRoomWidth / 2.0, ry - mRoomHeight / 2.0, mRoomWidth, mRoomHeight); + } else { + roomRectangle = QRectF(rx - (mRoomWidth * rSize) / 2.0, ry - (mRoomHeight * rSize) / 2.0, mRoomWidth * rSize, mRoomHeight * rSize); + } + // We should be using the full area for testing for clicks even though + // we only show a smaller one if the user has dialed down the room size + // on NON-grid mode areas: + const QRectF roomClickTestRectangle(QRectF(static_cast(rx) - (static_cast(mRoomWidth) / 2.0), + static_cast(ry) - (static_cast(mRoomHeight) / 2.0), + static_cast(mRoomWidth), static_cast(mRoomHeight))); + + QColor roomColor; + int roomEnvironment = pRoom->environment; + if (mpMap->envColors.contains(roomEnvironment)) { + roomEnvironment = mpMap->envColors[roomEnvironment]; + } else { + if (!mpMap->customEnvColors.contains(roomEnvironment)) { + roomEnvironment = 1; + } + } + // clang-format off + switch (roomEnvironment) { + case 1: roomColor = mpHost->mRed_2; break; + case 2: roomColor = mpHost->mGreen_2; break; + case 3: roomColor = mpHost->mYellow_2; break; + case 4: roomColor = mpHost->mBlue_2; break; + case 5: roomColor = mpHost->mMagenta_2; break; + case 6: roomColor = mpHost->mCyan_2; break; + case 7: roomColor = mpHost->mWhite_2; break; + case 8: roomColor = mpHost->mBlack_2; break; + case 9: roomColor = mpHost->mLightRed_2; break; + case 10: roomColor = mpHost->mLightGreen_2; break; + case 11: roomColor = mpHost->mLightYellow_2; break; + case 12: roomColor = mpHost->mLightBlue_2; break; + case 13: roomColor = mpHost->mLightMagenta_2; break; + case 14: roomColor = mpHost->mLightCyan_2; break; + case 15: roomColor = mpHost->mLightWhite_2; break; + case 16: roomColor = mpHost->mLightBlack_2; break; + // clang-format on + default: //user defined room color + if (mpMap->customEnvColors.contains(roomEnvironment)) { + roomColor = mpMap->customEnvColors[roomEnvironment]; + } else { + if (16 < roomEnvironment && roomEnvironment < 232) { + quint8 base = roomEnvironment - 16; + quint8 r = base / 36; + quint8 g = (base - (r * 36)) / 6; + quint8 b = (base - (r * 36)) - (g * 6); + + r *= 51; + g *= 51; + b *= 51; + roomColor = QColor(r, g, b, 255); + } else if (231 < roomEnvironment && roomEnvironment < 256) { + quint8 k = ((roomEnvironment - 232) * 10) + 8; + roomColor = QColor(k, k, k, 255); + } + } + } + + if (((mPick || picked) && roomClickTestRectangle.contains(mPHighlight)) + || mMultiSelectionSet.contains(currentRoomId)) { + + // This room is in the selection: + // TODO: replace this flood fill of the room with an orange rectangle with something a bit more subtle: + painter.fillRect(roomRectangle, QColor(255, 155, 55)); + mPick = false; + if (mStartSpeedWalk) { + mStartSpeedWalk = false; + // This draws a red circle around the room that was choosen as + // the target for the speedwalk, but it is only shown for one + // paintEvent call and it is not obvious that it is useful, note + // that this is the code for a room being clicked on that is + // within the area - there is a separate block of code further down + // in this method that handles clicking on the out of area exit so + // that a speed walk is done to the room in the OTHER area: + float roomRadius = 0.4 * mRoomWidth; + QPointF roomCenter = QPointF(rx, ry); + QRadialGradient gradient(roomCenter, roomRadius); + gradient.setColorAt(0.95, QColor(255, 0, 0, 150)); + gradient.setColorAt(0.80, QColor(150, 100, 100, 150)); + gradient.setColorAt(0.799, QColor(150, 100, 100, 100)); + gradient.setColorAt(0.7, QColor(255, 0, 0, 200)); + gradient.setColorAt(0, Qt::white); + QPen transparentPen(Qt::transparent); + QPainterPath diameterPath; + painter.setBrush(gradient); + painter.setPen(transparentPen); + diameterPath.addEllipse(roomCenter, roomRadius, roomRadius); + painter.drawPath(diameterPath); + + initiateSpeeWalk(speedWalkStartRoomId, currentRoomId); + } + + } else { + // Room is NOT selected + if (mBubbleMode) { + float roomRadius = 0.5 * rSize * mRoomWidth; + QPointF roomCenter = QPointF(rx, ry); + // CHECK: The use of a gradient fill to a white center on round + // rooms might look nice in some sitations but not in all: + QRadialGradient gradient(roomCenter, roomRadius); + gradient.setColorAt(0.85, roomColor); + gradient.setColorAt(0, Qt::white); + QPen transparentPen(Qt::transparent); + QPainterPath diameterPath; + painter.setBrush(gradient); + painter.setPen(transparentPen); + diameterPath.addEllipse(roomCenter, roomRadius, roomRadius); + painter.drawPath(diameterPath); + } else { + painter.fillRect(roomRectangle, roomColor); + } + + // Do we need to draw the room symbol: + if (!(mShowRoomID && areRoomIdsLegible) && !pRoom->mSymbol.isEmpty()) { + QString pixmapKey; + if (roomColor.lightness() > 127) { + pixmapKey = QStringLiteral("B_%1").arg(pRoom->mSymbol); + } else { + pixmapKey = QStringLiteral("W_%1").arg(pRoom->mSymbol); + } + if (!mSymbolPixmapCache.contains(pixmapKey)) { + addSymbolToPixmapCache(pixmapKey, isGridMode); + } + + painter.save(); + painter.setBackgroundMode(Qt::TransparentMode); + + QPixmap* pix = mSymbolPixmapCache.object(pixmapKey); + if (!pix) { + qWarning("T2DMap::paintEvent() Alert: mSymbolPixmapCache failure, too many items to cache all of them for: \"%s\"", pRoom->mSymbol.toUtf8().constData()); + } else { + /* + * For the non-scaling QPainter::drawPixmap() used now we + * have to position the generated pixmap containing the + * particular symbol for this room to Y when it would + * position it at X - this should be faster than the previous + * scaling QPainter::drawPixmap() as that would scale the + * pixmap to fit the Room Rectangle! + * + * |<------->| roomRectangle.width() + * roomRectangle.topLeft-->X---------+ + * | Room | + * | Y---+ | + * | |Pix| | + * | +---+ | + * |Rectangle| + * +---------+ + * |<->|<--symbolRect.width() + * x-offset---->|<>|<-- (roomRectangle.width() - symbolRect.width())/2.0 + * similarly for the y-offset + */ + + painter.drawPixmap( + QPoint(qRound(roomRectangle.left() + ((roomRectangle.width() - pix->width()) / 2.0)), qRound(roomRectangle.top() + ((roomRectangle.height() - pix->height()) / 2.0))), + *pix); + } + + painter.restore(); + } + + // Do we need to draw the custom (user specified) highlight + if (pRoom->highlight) { + float roomRadius = (pRoom->highlightRadius * mRoomWidth) / 2.0; + QPointF roomCenter = QPointF(rx, ry); + QRadialGradient gradient(roomCenter, roomRadius); + gradient.setColorAt(0.85, pRoom->highlightColor); + gradient.setColorAt(0, pRoom->highlightColor2); + QPen transparentPen(Qt::transparent); + QPainterPath diameterPath; + painter.setBrush(gradient); + painter.setPen(transparentPen); + diameterPath.addEllipse(roomCenter, roomRadius, roomRadius); + painter.drawPath(diameterPath); + } + + // Do we need to draw the room Id number: + if (mShowRoomID && areRoomIdsLegible) { + painter.save(); + QColor roomIdColor; + if (roomColor.lightness() > 127) { + roomIdColor = QColor(Qt::black); + } else { + roomIdColor = QColor(Qt::white); + } + painter.setPen(QPen(roomIdColor)); + painter.setFont(roomVNumFont); + painter.drawText(roomRectangle, Qt::AlignCenter, QString::number(currentRoomId)); + painter.restore(); + } + + } + + // Change these from const to static to tweak them whilst running in a debugger...! + const float allInsideTipOffsetFactor = 1 / 20.0f; + const float upDownXOrYFactor = 1 / 3.1f; + const float inOuterXFactor = 1 / 4.5f; + const float inUpDownYFactor = 1 / 7.0f; + const float outOuterXFactor = 1 / 2.2f; + const float outUpDownYFactor = 1 / 5.5f; + const float outInterXFactor = 1 / 3.5f; + const float outerRealDoorPenThicknessFactor = 0.050f; + const float outerStubDoorPenThicknessFactor = 0.025f; + const float innerRealDoorPenThicknessFactor = 0.025f; + const float innerStubDoorPenThicknessFactor = 0.0125f; + + QColor lc; + if (roomColor.lightness() > 127) { + lc = QColor(Qt::black); + } else { + lc = QColor(Qt::white); + } + pen = painter.pen(); + pen.setColor(lc); + pen.setCosmetic(mMapperUseAntiAlias); + pen.setCapStyle(Qt::RoundCap); + pen.setJoinStyle(Qt::RoundJoin); + QPen innerPen = pen; + painter.save(); + + QBrush innerBrush = painter.brush(); + innerBrush.setStyle(Qt::NoBrush); + if (pRoom->getUp() > 0 || pRoom->exitStubs.contains(DIR_UP)) { + QPolygonF poly_up; + poly_up.append(QPointF(rx, ry + (mRoomHeight * rSize * allInsideTipOffsetFactor))); + poly_up.append(QPointF(rx - (mRoomWidth * rSize * upDownXOrYFactor), ry + (mRoomHeight * rSize * upDownXOrYFactor))); + poly_up.append(QPointF(rx + (mRoomWidth * rSize * upDownXOrYFactor), ry + (mRoomHeight * rSize * upDownXOrYFactor))); + bool isDoor = true; + QBrush brush = painter.brush(); + switch (pRoom->doors.value(key_up)) { + case 1: //open door + brush.setColor(QColor(10, 155, 10)); + innerPen.setColor(QColor(10, 155, 10)); + break; + case 2: //closed door + brush.setColor(QColor(155, 155, 10)); + innerPen.setColor(QColor(155, 155, 10)); + break; + case 3: + brush.setColor(QColor(155, 10, 10)); + innerPen.setColor(QColor(155, 10, 10)); + break; + default: + brush.setColor(lc); + isDoor = false; + } + if (pRoom->getUp() > 0) { + pen.setWidthF(mRoomWidth * rSize * outerRealDoorPenThicknessFactor); + innerPen.setWidthF(mRoomWidth * rSize * innerRealDoorPenThicknessFactor); + brush.setStyle(Qt::Dense4Pattern); + } else { + pen.setWidthF(mRoomWidth * rSize * outerStubDoorPenThicknessFactor); + innerPen.setWidthF(mRoomWidth * rSize * innerStubDoorPenThicknessFactor); + brush.setStyle(Qt::DiagCrossPattern); + } + painter.setPen(pen); + painter.setBrush(brush); + painter.drawPolygon(poly_up); + if (isDoor) { + // Draw a narrower triangle on top of the existing one if there + // is a door - to help emphasis the coloured door if the brush + // from the main one is not obvious given the main room colour. + painter.setPen(innerPen); + painter.setBrush(innerBrush); + painter.drawPolygon(poly_up); + } + } + + if (pRoom->getDown() > 0 || pRoom->exitStubs.contains(DIR_DOWN)) { + QPolygonF poly_down; + poly_down.append(QPointF(rx, ry - (mRoomHeight * rSize * allInsideTipOffsetFactor))); + poly_down.append(QPointF(rx - (mRoomWidth * rSize * upDownXOrYFactor), ry - (mRoomHeight * rSize * upDownXOrYFactor))); + poly_down.append(QPointF(rx + (mRoomWidth * rSize * upDownXOrYFactor), ry - (mRoomHeight * rSize * upDownXOrYFactor))); + bool isDoor = true; + QBrush brush = painter.brush(); + switch (pRoom->doors.value(key_down)) { + case 1: //open door + brush.setColor(QColor(10, 155, 10)); + innerPen.setColor(QColor(10, 155, 10)); + break; + case 2: //closed door + brush.setColor(QColor(155, 155, 10)); + innerPen.setColor(QColor(155, 155, 10)); + break; + case 3: + brush.setColor(QColor(155, 10, 10)); + innerPen.setColor(QColor(155, 10, 10)); + break; + default: + brush.setColor(lc); + isDoor = false; + } + if (pRoom->getDown() > 0) { + pen.setWidthF(mRoomWidth * rSize * outerRealDoorPenThicknessFactor); + innerPen.setWidthF(mRoomWidth * rSize * innerRealDoorPenThicknessFactor); + brush.setStyle(Qt::Dense4Pattern); + } else { + pen.setWidthF(mRoomWidth * rSize * outerStubDoorPenThicknessFactor); + innerPen.setWidthF(mRoomWidth * rSize * innerStubDoorPenThicknessFactor); + brush.setStyle(Qt::DiagCrossPattern); + } + painter.setPen(pen); + painter.setBrush(brush); + painter.drawPolygon(poly_down); + if (isDoor) { + painter.setPen(innerPen); + painter.setBrush(innerBrush); + painter.drawPolygon(poly_down); + } + } + + if (pRoom->getIn() > 0 || pRoom->exitStubs.contains(DIR_IN)) { + QPolygonF poly_in_left; + QPolygonF poly_in_right; + poly_in_left.append(QPointF(rx - (mRoomWidth * rSize * allInsideTipOffsetFactor), ry)); + poly_in_left.append(QPointF(rx - (mRoomWidth * rSize * inOuterXFactor), ry + (mRoomHeight * rSize * inUpDownYFactor))); + poly_in_left.append(QPointF(rx - (mRoomWidth * rSize * inOuterXFactor), ry - (mRoomHeight * rSize * inUpDownYFactor))); + poly_in_right.append(QPointF(rx + (mRoomWidth * rSize * allInsideTipOffsetFactor), ry)); + poly_in_right.append(QPointF(rx + (mRoomWidth * rSize * inOuterXFactor), ry + (mRoomHeight * rSize * inUpDownYFactor))); + poly_in_right.append(QPointF(rx + (mRoomWidth * rSize * inOuterXFactor), ry - (mRoomHeight * rSize * inUpDownYFactor))); + bool isDoor = true; + QBrush brush = painter.brush(); + switch (pRoom->doors.value(key_in)) { + case 1: //open door + brush.setColor(QColor(10, 155, 10)); + innerPen.setColor(QColor(10, 155, 10)); + break; + case 2: //closed door + brush.setColor(QColor(155, 155, 10)); + innerPen.setColor(QColor(155, 155, 10)); + break; + case 3: + brush.setColor(QColor(155, 10, 10)); + innerPen.setColor(QColor(155, 10, 10)); + break; + default: + brush.setColor(lc); + isDoor = false; + } + if (pRoom->getIn() > 0) { + pen.setWidthF(mRoomWidth * rSize * outerRealDoorPenThicknessFactor); + innerPen.setWidthF(mRoomWidth * rSize * innerRealDoorPenThicknessFactor); + brush.setStyle(Qt::Dense4Pattern); + } else { + pen.setWidthF(mRoomWidth * rSize * outerStubDoorPenThicknessFactor); + innerPen.setWidthF(mRoomWidth * rSize * innerStubDoorPenThicknessFactor); + brush.setStyle(Qt::DiagCrossPattern); + } + painter.setBrush(brush); + painter.setPen(pen); + painter.drawPolygon(poly_in_left); + painter.drawPolygon(poly_in_right); + if (isDoor) { + painter.setPen(innerPen); + painter.setBrush(innerBrush); + painter.drawPolygon(poly_in_left); + painter.drawPolygon(poly_in_right); + } + } + + if (pRoom->getOut() > 0 || pRoom->exitStubs.contains(DIR_OUT)) { + QPolygonF poly_out_left; + QPolygonF poly_out_right; + poly_out_left.append(QPointF(rx - (mRoomWidth * rSize * outOuterXFactor), ry)); + poly_out_left.append(QPointF(rx - (mRoomWidth * rSize * outInterXFactor), ry + (mRoomHeight * rSize * outUpDownYFactor))); + poly_out_left.append(QPointF(rx - (mRoomWidth * rSize * outInterXFactor), ry - (mRoomHeight * rSize * outUpDownYFactor))); + poly_out_right.append(QPointF(rx + (mRoomWidth * rSize * outOuterXFactor), ry)); + poly_out_right.append(QPointF(rx + (mRoomWidth * rSize * outInterXFactor), ry + (mRoomHeight * rSize * outUpDownYFactor))); + poly_out_right.append(QPointF(rx + (mRoomWidth * rSize * outInterXFactor), ry - (mRoomHeight * rSize * outUpDownYFactor))); + bool isDoor = true; + QBrush brush = painter.brush(); + switch (pRoom->doors.value(key_out)) { + case 1: //open door + brush.setColor(QColor(10, 155, 10)); + innerPen.setColor(QColor(10, 155, 10)); + break; + case 2: //closed door + brush.setColor(QColor(155, 155, 10)); + innerPen.setColor(QColor(155, 155, 10)); + break; + case 3: + brush.setColor(QColor(155, 10, 10)); + innerPen.setColor(QColor(155, 10, 10)); + break; + default: + brush.setColor(lc); + isDoor = false; + } + if (pRoom->getOut() > 0) { + pen.setWidthF(mRoomWidth * rSize * outerRealDoorPenThicknessFactor); + innerPen.setWidthF(mRoomWidth * rSize * innerRealDoorPenThicknessFactor); + brush.setStyle(Qt::Dense4Pattern); + } else { + pen.setWidthF(mRoomWidth * rSize * outerStubDoorPenThicknessFactor); + innerPen.setWidthF(mRoomWidth * rSize * innerStubDoorPenThicknessFactor); + brush.setStyle(Qt::DiagCrossPattern); + } + painter.setBrush(brush); + painter.setPen(pen); + painter.drawPolygon(poly_out_left); + painter.drawPolygon(poly_out_right); + if (isDoor) { + painter.setPen(innerPen); + painter.setBrush(innerBrush); + painter.drawPolygon(poly_out_left); + painter.drawPolygon(poly_out_right); + } + } + + painter.restore(); + if (!isGridMode) { + QMapIterator it(mAreaExitsList); + while (it.hasNext()) { + it.next(); + QPoint P = it.value(); + int rx = P.x(); + int ry = P.y(); + + QRectF dr = QRectF(rx, ry, mRoomWidth * rSize, mRoomHeight * rSize); + + // clang-format off + if (((mPick || picked) + && mPHighlight.x() >= (dr.x() - mRoomWidth / 3.0) + && mPHighlight.x() <= (dr.x() + mRoomWidth / 3.0) + && mPHighlight.y() >= (dr.y() - mRoomHeight / 3.0) + && mPHighlight.y() <= (dr.y() + mRoomHeight / 3.0)) + && mStartSpeedWalk) { + + // clang-format on + mStartSpeedWalk = false; + // This draws a red circle around the out of area exit that + // was choosen as the target for the speedwalk, but it is + // only shown for one paintEvent call and it is not obvious + // that it is useful, note that there is similar code for a + // room being clicked on that is WITHIN the area, that is + // above this point in the source code: + float roomRadius = (0.8 * mRoomWidth) / 2.0; + QPointF roomCenter = QPointF(rx, ry); + QRadialGradient gradient(roomCenter, roomRadius); + gradient.setColorAt(0.95, QColor(255, 0, 0, 150)); + gradient.setColorAt(0.80, QColor(150, 100, 100, 150)); + gradient.setColorAt(0.799, QColor(150, 100, 100, 100)); + gradient.setColorAt(0.7, QColor(255, 0, 0, 200)); + gradient.setColorAt(0, Qt::white); + QPen transparentPen(Qt::transparent); + QPainterPath myPath; + painter.setBrush(gradient); + painter.setPen(transparentPen); + myPath.addEllipse(roomCenter, roomRadius, roomRadius); + painter.drawPath(myPath); + + mPick = false; + initiateSpeeWalk(speedWalkStartRoomId, it.key()); + } + } + } +} + +// Revised to use a QCache to hold QPixmap * to generated images for room symbols void T2DMap::paintEvent(QPaintEvent* e) { if (!mpMap) { return; } - bool __Pick = mPick; + // As it happens this local is never changed in this method so it can be + // made const: + const bool __Pick = mPick; QElapsedTimer renderTimer; renderTimer.start(); @@ -731,7 +1221,8 @@ void T2DMap::paintEvent(QPaintEvent* e) QList exitList; QList oneWayExits; - TRoom* pPlayerRoom = mpMap->mpRoomDB->getRoom(mpMap->mRoomIdHash.value(mpMap->mProfileName)); + int playerRoomId = mpMap->mRoomIdHash.value(mpMap->mProfileName); + TRoom* pPlayerRoom = mpMap->mpRoomDB->getRoom(playerRoomId); if (!pPlayerRoom) { painter.save(); painter.fillRect(0, 0, width(), height(), Qt::transparent); @@ -745,7 +1236,7 @@ void T2DMap::paintEvent(QPaintEvent* e) int ox; int oy; - if (mRoomID != mpMap->mRoomIdHash.value(mpMap->mProfileName) && mShiftMode) { + if (mRoomID != playerRoomId && mShiftMode) { mShiftMode = false; } TArea* playerArea; @@ -761,7 +1252,7 @@ void T2DMap::paintEvent(QPaintEvent* e) if (!mpMap->mpRoomDB->getArea(playerAreaID)) { return; } - mRoomID = mpMap->mRoomIdHash.value(mpMap->mProfileName); + mRoomID = playerRoomId; playerRoom = mpMap->mpRoomDB->getRoom(mRoomID); if (!playerRoom) { return; @@ -824,10 +1315,6 @@ void T2DMap::paintEvent(QPaintEvent* e) isFontBigEnoughToShowRoomVnum = sizeFontToFitTextInRect(roomVNumFont, roomTestRect, QStringLiteral("8").repeated(mMaxRoomIdDigits), roomVnumMargin); } - // This could be the coordinates of the center of the window? - int px = qRound((mRoomWidth * xspan) / 2.0); - int py = qRound((mRoomHeight * yspan) / 2.0); - TArea* pArea = playerArea; int zLevel = mOz; @@ -902,6 +1389,9 @@ void T2DMap::paintEvent(QPaintEvent* e) painter.fillRect(mMultiRect, QColor(190, 190, 190, 60)); } + QPointF playerRoomOnWidgetCoordinates; + bool isPlayerRoomVisible = false; + // Draw the rooms: QSetIterator itRoom(pArea->getAreaRooms()); while (itRoom.hasNext()) { int currentAreaRoom = itRoom.next(); @@ -909,522 +1399,61 @@ void T2DMap::paintEvent(QPaintEvent* e) if (!room) { continue; } - float rx = room->x * mRoomWidth + mRX; - float ry = room->y * -1 * mRoomHeight + mRY; - int rz = room->z; - if (rz != zLevel) { + if (room->z != zLevel) { continue; } + + float rx = room->x * mRoomWidth + static_cast(mRX); + float ry = room->y * -1 * mRoomHeight + static_cast(mRY); if (rx < 0 || ry < 0 || rx > widgetWidth || ry > widgetHeight) { continue; } - room->rendered = false; - QRectF roomRectangle; - if (pArea->gridMode) { - roomRectangle = QRectF(rx - mRoomWidth / 2.0, ry - mRoomHeight / 2.0, mRoomWidth, mRoomHeight); - } else { - roomRectangle = QRectF(rx - (mRoomWidth * rSize) / 2.0, ry - (mRoomHeight * rSize) / 2.0, mRoomWidth * rSize, mRoomHeight * rSize); - } - // We should be using the full area for testing for clicks even though - // we only show a smaller one if the user has dialed down the room size - // on NON-grid mode areas: - const QRectF roomClickTestRectangle(QRectF(static_cast(rx) - (static_cast(mRoomWidth) / 2.0), - static_cast(ry) - (static_cast(mRoomHeight) / 2.0), - static_cast(mRoomWidth), static_cast(mRoomHeight))); - - QColor roomColor; - int roomEnvironment = room->environment; - if (mpMap->envColors.contains(roomEnvironment)) { - roomEnvironment = mpMap->envColors[roomEnvironment]; + if (playerRoomId == currentAreaRoom) { + // We defer drawing THIS (the player's room) until the end + isPlayerRoomVisible = true; + playerRoomOnWidgetCoordinates = QPointF(static_cast(rx), static_cast(ry)); } else { - if (!mpMap->customEnvColors.contains(roomEnvironment)) { - roomColor = QColor(0, 164, 204, 255); - } - } - switch (roomEnvironment) { - case 1: - roomColor = mpHost->mRed_2; - break; - case 2: - roomColor = mpHost->mGreen_2; - break; - case 3: - roomColor = mpHost->mYellow_2; - break; - case 4: - roomColor = mpHost->mBlue_2; - break; - case 5: - roomColor = mpHost->mMagenta_2; - break; - case 6: - roomColor = mpHost->mCyan_2; - break; - case 7: - roomColor = mpHost->mWhite_2; - break; - case 8: - roomColor = mpHost->mBlack_2; - break; - case 9: - roomColor = mpHost->mLightRed_2; - break; - case 10: - roomColor = mpHost->mLightGreen_2; - break; - case 11: - roomColor = mpHost->mLightYellow_2; - break; - case 12: - roomColor = mpHost->mLightBlue_2; - break; - case 13: - roomColor = mpHost->mLightMagenta_2; - break; - case 14: - roomColor = mpHost->mLightCyan_2; - break; - case 15: - roomColor = mpHost->mLightWhite_2; - break; - case 16: - roomColor = mpHost->mLightBlack_2; - break; - default: //user defined room color - if (mpMap->customEnvColors.contains(roomEnvironment)) { - roomColor = mpMap->customEnvColors[roomEnvironment]; - } else { - if (16 < roomEnvironment && roomEnvironment < 232) { - quint8 base = roomEnvironment - 16; - quint8 r = base / 36; - quint8 g = (base - (r * 36)) / 6; - quint8 b = (base - (r * 36)) - (g * 6); - - r *= 51; - g *= 51; - b *= 51; - roomColor = QColor(r, g, b, 255); - } else if (231 < roomEnvironment && roomEnvironment < 256) { - quint8 k = ((roomEnvironment - 232) * 10) + 8; - roomColor = QColor(k, k, k, 255); - } - } + // Not the player's room: + drawRoom(painter, roomVNumFont, pen, room, pArea->gridMode, isFontBigEnoughToShowRoomVnum, playerRoomId, rx, ry, __Pick); } + } // End of while loop for each room in area - if (((mPick || __Pick) && roomClickTestRectangle.contains(mPHighlight)) - || mMultiSelectionSet.contains(currentAreaRoom)) { - - painter.fillRect(roomRectangle, QColor(255, 155, 55)); - mPick = false; - if (mStartSpeedWalk) { - mStartSpeedWalk = false; - float roomRadius = 0.4 * mRoomWidth; - QPointF roomCenter = QPointF(rx, ry); - QRadialGradient gradient(roomCenter, roomRadius); - gradient.setColorAt(0.95, QColor(255, 0, 0, 150)); - gradient.setColorAt(0.80, QColor(150, 100, 100, 150)); - gradient.setColorAt(0.799, QColor(150, 100, 100, 100)); - gradient.setColorAt(0.7, QColor(255, 0, 0, 200)); - gradient.setColorAt(0, Qt::white); - QPen transparentPen(Qt::transparent); - QPainterPath diameterPath; - painter.setBrush(gradient); - painter.setPen(transparentPen); - diameterPath.addEllipse(roomCenter, roomRadius, roomRadius); - painter.drawPath(diameterPath); - - - mTarget = currentAreaRoom; - if (mpMap->mpRoomDB->getRoom(mTarget)) { - mpMap->mTargetID = mTarget; - if (mpMap->findPath(mpMap->mRoomIdHash.value(mpMap->mProfileName), mpMap->mTargetID)) { - mpHost->startSpeedWalk(); - } else { - QString msg = tr("Mapper: Cannot find a path to this room using known exits.\n"); - mpHost->mpConsole->printSystemMessage(msg); - } - } - } - } else { - if (mBubbleMode) { - float roomRadius = 0.5 * rSize * mRoomWidth; - QPointF roomCenter = QPointF(rx, ry); - QRadialGradient gradient(roomCenter, roomRadius); - gradient.setColorAt(0.85, roomColor); - gradient.setColorAt(0, Qt::white); - QPen transparentPen(Qt::transparent); - QPainterPath diameterPath; - painter.setBrush(gradient); - painter.setPen(transparentPen); - diameterPath.addEllipse(roomCenter, roomRadius, roomRadius); - painter.drawPath(diameterPath); - } else { - painter.fillRect(roomRectangle, roomColor); - } - - if (!(mShowRoomID && isFontBigEnoughToShowRoomVnum) && !room->mSymbol.isEmpty()) { - QString pixmapKey; - if (roomColor.lightness() > 127) { - pixmapKey = QStringLiteral("B_%1").arg(room->mSymbol); - } else { - pixmapKey = QStringLiteral("W_%1").arg(room->mSymbol); - } - if (!mSymbolPixmapCache.contains(pixmapKey)) { - addSymbolToPixmapCache(pixmapKey, pArea->gridMode); - } - - painter.save(); - painter.setBackgroundMode(Qt::TransparentMode); - - QPixmap* pix = mSymbolPixmapCache.object(pixmapKey); - if (!pix) { - qWarning("T2DMap::paintEvent() Alert: mSymbolPixmapCache failure, too many items to cache all of them for: \"%s\"", room->mSymbol.toUtf8().constData()); - } else { - /* - * For the non-scaling QPainter::drawPixmap() used now we - * have to position the generated pixmap containing the - * particular symbol for this room to Y when it would - * position it at X - this should be faster than the previous - * scaling QPainter::drawPixmap() as that would scale the - * pixmap to fit the Room Rectangle! - * - * |<------->| roomRectangle.width() - * roomRectangle.topLeft-->X---------+ - * | Room | - * | Y---+ | - * | |Pix| | - * | +---+ | - * |Rectangle| - * +---------+ - * |<->|<--symbolRect.width() - * x-offset---->|<>|<-- (roomRectangle.width() - symbolRect.width())/2.0 - * similarly for the y-offset - */ - - painter.drawPixmap( - QPoint(qRound(roomRectangle.left() + ((roomRectangle.width() - pix->width()) / 2.0)), qRound(roomRectangle.top() + ((roomRectangle.height() - pix->height()) / 2.0))), - *pix); - } - - painter.restore(); - } - - if (room->highlight) { - float roomRadius = (room->highlightRadius * mRoomWidth) / 2.0; - QPointF roomCenter = QPointF(rx, ry); - QRadialGradient gradient(roomCenter, roomRadius); - gradient.setColorAt(0.85, room->highlightColor); - gradient.setColorAt(0, room->highlightColor2); - QPen transparentPen(Qt::transparent); - QPainterPath diameterPath; - painter.setBrush(gradient); - painter.setPen(transparentPen); - diameterPath.addEllipse(roomCenter, roomRadius, roomRadius); - painter.drawPath(diameterPath); - } - - if (mShowRoomID && isFontBigEnoughToShowRoomVnum) { - painter.save(); - QColor roomIdColor; - if (roomColor.lightness() > 127) { - roomIdColor = QColor(Qt::black); - } else { - roomIdColor = QColor(Qt::white); - } - painter.setPen(QPen(roomIdColor)); - painter.setFont(roomVNumFont); - painter.drawText(roomRectangle, Qt::AlignCenter, QString::number(currentAreaRoom)); - painter.restore(); - } - - if (mShiftMode && currentAreaRoom == mpMap->mRoomIdHash.value(mpMap->mProfileName)) { - float roomRadius = (1.2 * mRoomWidth) / 2; - QPointF roomCenter = QPointF(rx, ry); - QRadialGradient gradient(roomCenter, roomRadius); - gradient.setColorAt(0.95, QColor(255, 0, 0, 150)); - gradient.setColorAt(0.80, QColor(150, 100, 100, 150)); - gradient.setColorAt(0.799, QColor(150, 100, 100, 100)); - gradient.setColorAt(0.7, QColor(255, 0, 0, 200)); - gradient.setColorAt(0, Qt::white); - QPen transparentPen(Qt::transparent); - QPainterPath myPath; - painter.setBrush(gradient); - painter.setPen(transparentPen); - myPath.addEllipse(roomCenter, roomRadius, roomRadius); - painter.drawPath(myPath); - } - } - - // Change these from const to static to tweak them whilst running in a debugger...! - const float allInsideTipOffsetFactor = 1 / 20.0f; - const float upDownXOrYFactor = 1 / 3.1f; - const float inOuterXFactor = 1 / 4.5f; - const float inUpDownYFactor = 1 / 7.0f; - const float outOuterXFactor = 1 / 2.2f; - const float outUpDownYFactor = 1 / 5.5f; - const float outInterXFactor = 1 / 3.5f; - const float outerRealDoorPenThicknessFactor = 0.050f; - const float outerStubDoorPenThicknessFactor = 0.025f; - const float innerRealDoorPenThicknessFactor = 0.025f; - const float innerStubDoorPenThicknessFactor = 0.0125f; - - QColor lc; - if (roomColor.lightness() > 127) { - lc = QColor(Qt::black); - } else { - lc = QColor(Qt::white); - } - pen = painter.pen(); - pen.setColor(lc); - pen.setCosmetic(mMapperUseAntiAlias); - pen.setCapStyle(Qt::RoundCap); - pen.setJoinStyle(Qt::RoundJoin); - QPen innerPen = pen; + if (isPlayerRoomVisible) { + drawRoom(painter, roomVNumFont, pen, playerRoom, pArea->gridMode, isFontBigEnoughToShowRoomVnum, playerRoomId, static_cast(playerRoomOnWidgetCoordinates.x()), static_cast(playerRoomOnWidgetCoordinates.y()), __Pick); painter.save(); + QPen transparentPen(Qt::transparent); + QPainterPath myPath; + double roomRadius = (mpMap->mPlayerRoomOuterDiameterPercentage / 200.0) * static_cast(mRoomWidth); + QRadialGradient gradient(playerRoomOnWidgetCoordinates, roomRadius); + if (mpHost->mMapStrongHighlight) { + // Never set, no means to except via XMLImport, as dlgMapper class's + // slot_toggleStrongHighlight is not wired up to anything + QRectF dr = QRectF(playerRoomOnWidgetCoordinates.x() - (static_cast(mRoomWidth) * rSize) / 2.0, + playerRoomOnWidgetCoordinates.y() - (static_cast(mRoomHeight) * rSize) / 2.0, + static_cast(mRoomWidth) * rSize, static_cast(mRoomHeight) * rSize); + painter.fillRect(dr, QColor(255, 0, 0, 150)); - QBrush innerBrush = painter.brush(); - innerBrush.setStyle(Qt::NoBrush); - if (room->getUp() > 0 || room->exitStubs.contains(DIR_UP)) { - QPolygonF poly_up; - poly_up.append(QPointF(rx, ry + (mRoomHeight * rSize * allInsideTipOffsetFactor))); - poly_up.append(QPointF(rx - (mRoomWidth * rSize * upDownXOrYFactor), ry + (mRoomHeight * rSize * upDownXOrYFactor))); - poly_up.append(QPointF(rx + (mRoomWidth * rSize * upDownXOrYFactor), ry + (mRoomHeight * rSize * upDownXOrYFactor))); - bool isDoor = true; - QBrush brush = painter.brush(); - switch (room->doors.value(key_up)) { - case 1: //open door - brush.setColor(QColor(10, 155, 10)); - innerPen.setColor(QColor(10, 155, 10)); - break; - case 2: //closed door - brush.setColor(QColor(155, 155, 10)); - innerPen.setColor(QColor(155, 155, 10)); - break; - case 3: - brush.setColor(QColor(155, 10, 10)); - innerPen.setColor(QColor(155, 10, 10)); - break; - default: - brush.setColor(lc); - isDoor = false; - } - if (room->getUp() > 0) { - pen.setWidthF(mRoomWidth * rSize * outerRealDoorPenThicknessFactor); - innerPen.setWidthF(mRoomWidth * rSize * innerRealDoorPenThicknessFactor); - brush.setStyle(Qt::Dense4Pattern); - } else { - pen.setWidthF(mRoomWidth * rSize * outerStubDoorPenThicknessFactor); - innerPen.setWidthF(mRoomWidth * rSize * innerStubDoorPenThicknessFactor); - brush.setStyle(Qt::DiagCrossPattern); - } - painter.setPen(pen); - painter.setBrush(brush); - painter.drawPolygon(poly_up); - if (isDoor) { - // Draw a narrower triangle on top of the existing one if there - // is a door - to help emphasis the coloured door if the brush - // from the main one is not obvious given the main room colour. - painter.setPen(innerPen); - painter.setBrush(innerBrush); - painter.drawPolygon(poly_up); - } - } - - if (room->getDown() > 0 || room->exitStubs.contains(DIR_DOWN)) { - QPolygonF poly_down; - poly_down.append(QPointF(rx, ry - (mRoomHeight * rSize * allInsideTipOffsetFactor))); - poly_down.append(QPointF(rx - (mRoomWidth * rSize * upDownXOrYFactor), ry - (mRoomHeight * rSize * upDownXOrYFactor))); - poly_down.append(QPointF(rx + (mRoomWidth * rSize * upDownXOrYFactor), ry - (mRoomHeight * rSize * upDownXOrYFactor))); - bool isDoor = true; - QBrush brush = painter.brush(); - switch (room->doors.value(key_down)) { - case 1: //open door - brush.setColor(QColor(10, 155, 10)); - innerPen.setColor(QColor(10, 155, 10)); - break; - case 2: //closed door - brush.setColor(QColor(155, 155, 10)); - innerPen.setColor(QColor(155, 155, 10)); - break; - case 3: - brush.setColor(QColor(155, 10, 10)); - innerPen.setColor(QColor(155, 10, 10)); - break; - default: - brush.setColor(lc); - isDoor = false; - } - if (room->getDown() > 0) { - pen.setWidthF(mRoomWidth * rSize * outerRealDoorPenThicknessFactor); - innerPen.setWidthF(mRoomWidth * rSize * innerRealDoorPenThicknessFactor); - brush.setStyle(Qt::Dense4Pattern); - } else { - pen.setWidthF(mRoomWidth * rSize * outerStubDoorPenThicknessFactor); - innerPen.setWidthF(mRoomWidth * rSize * innerStubDoorPenThicknessFactor); - brush.setStyle(Qt::DiagCrossPattern); - } - painter.setPen(pen); - painter.setBrush(brush); - painter.drawPolygon(poly_down); - if (isDoor) { - painter.setPen(innerPen); - painter.setBrush(innerBrush); - painter.drawPolygon(poly_down); - } - } - - if (room->getIn() > 0 || room->exitStubs.contains(DIR_IN)) { - QPolygonF poly_in_left; - QPolygonF poly_in_right; - poly_in_left.append(QPointF(rx - (mRoomWidth * rSize * allInsideTipOffsetFactor), ry)); - poly_in_left.append(QPointF(rx - (mRoomWidth * rSize * inOuterXFactor), ry + (mRoomHeight * rSize * inUpDownYFactor))); - poly_in_left.append(QPointF(rx - (mRoomWidth * rSize * inOuterXFactor), ry - (mRoomHeight * rSize * inUpDownYFactor))); - poly_in_right.append(QPointF(rx + (mRoomWidth * rSize * allInsideTipOffsetFactor), ry)); - poly_in_right.append(QPointF(rx + (mRoomWidth * rSize * inOuterXFactor), ry + (mRoomHeight * rSize * inUpDownYFactor))); - poly_in_right.append(QPointF(rx + (mRoomWidth * rSize * inOuterXFactor), ry - (mRoomHeight * rSize * inUpDownYFactor))); - bool isDoor = true; - QBrush brush = painter.brush(); - switch (room->doors.value(key_in)) { - case 1: //open door - brush.setColor(QColor(10, 155, 10)); - innerPen.setColor(QColor(10, 155, 10)); - break; - case 2: //closed door - brush.setColor(QColor(155, 155, 10)); - innerPen.setColor(QColor(155, 155, 10)); - break; - case 3: - brush.setColor(QColor(155, 10, 10)); - innerPen.setColor(QColor(155, 10, 10)); - break; - default: - brush.setColor(lc); - isDoor = false; - } - if (room->getIn() > 0) { - pen.setWidthF(mRoomWidth * rSize * outerRealDoorPenThicknessFactor); - innerPen.setWidthF(mRoomWidth * rSize * innerRealDoorPenThicknessFactor); - brush.setStyle(Qt::Dense4Pattern); - } else { - pen.setWidthF(mRoomWidth * rSize * outerStubDoorPenThicknessFactor); - innerPen.setWidthF(mRoomWidth * rSize * innerStubDoorPenThicknessFactor); - brush.setStyle(Qt::DiagCrossPattern); - } - painter.setBrush(brush); - painter.setPen(pen); - painter.drawPolygon(poly_in_left); - painter.drawPolygon(poly_in_right); - if (isDoor) { - painter.setPen(innerPen); - painter.setBrush(innerBrush); - painter.drawPolygon(poly_in_left); - painter.drawPolygon(poly_in_right); - } - } - - if (room->getOut() > 0 || room->exitStubs.contains(DIR_OUT)) { - QPolygonF poly_out_left; - QPolygonF poly_out_right; - poly_out_left.append(QPointF(rx - (mRoomWidth * rSize * outOuterXFactor), ry)); - poly_out_left.append(QPointF(rx - (mRoomWidth * rSize * outInterXFactor), ry + (mRoomHeight * rSize * outUpDownYFactor))); - poly_out_left.append(QPointF(rx - (mRoomWidth * rSize * outInterXFactor), ry - (mRoomHeight * rSize * outUpDownYFactor))); - poly_out_right.append(QPointF(rx + (mRoomWidth * rSize * outOuterXFactor), ry)); - poly_out_right.append(QPointF(rx + (mRoomWidth * rSize * outInterXFactor), ry + (mRoomHeight * rSize * outUpDownYFactor))); - poly_out_right.append(QPointF(rx + (mRoomWidth * rSize * outInterXFactor), ry - (mRoomHeight * rSize * outUpDownYFactor))); - bool isDoor = true; - QBrush brush = painter.brush(); - switch (room->doors.value(key_out)) { - case 1: //open door - brush.setColor(QColor(10, 155, 10)); - innerPen.setColor(QColor(10, 155, 10)); - break; - case 2: //closed door - brush.setColor(QColor(155, 155, 10)); - innerPen.setColor(QColor(155, 155, 10)); - break; - case 3: - brush.setColor(QColor(155, 10, 10)); - innerPen.setColor(QColor(155, 10, 10)); - break; - default: - brush.setColor(lc); - isDoor = false; - } - if (room->getOut() > 0) { - pen.setWidthF(mRoomWidth * rSize * outerRealDoorPenThicknessFactor); - innerPen.setWidthF(mRoomWidth * rSize * innerRealDoorPenThicknessFactor); - brush.setStyle(Qt::Dense4Pattern); - } else { - pen.setWidthF(mRoomWidth * rSize * outerStubDoorPenThicknessFactor); - innerPen.setWidthF(mRoomWidth * rSize * innerStubDoorPenThicknessFactor); - brush.setStyle(Qt::DiagCrossPattern); - } - painter.setBrush(brush); - painter.setPen(pen); - painter.drawPolygon(poly_out_left); - painter.drawPolygon(poly_out_right); - if (isDoor) { - painter.setPen(innerPen); - painter.setBrush(innerBrush); - painter.drawPolygon(poly_out_left); - painter.drawPolygon(poly_out_right); - } + gradient.setColorAt(0.95, QColor(255, 0, 0, 150)); + gradient.setColorAt(0.80, QColor(150, 100, 100, 150)); + gradient.setColorAt(0.799, QColor(150, 100, 100, 100)); + gradient.setColorAt(0.7, QColor(255, 0, 0, 200)); + gradient.setColorAt(0, Qt::white); + painter.setBrush(gradient); + painter.setPen(transparentPen); + myPath.addEllipse(playerRoomOnWidgetCoordinates, roomRadius, roomRadius); + } else { + gradient.setStops(mPlayerRoomColorGradentStops); + painter.setBrush(gradient); + painter.setPen(transparentPen); + myPath.addEllipse(playerRoomOnWidgetCoordinates, roomRadius, roomRadius); } - + painter.drawPath(myPath); painter.restore(); - if (!pArea->gridMode) { - QMapIterator it(mAreaExitsList); - while (it.hasNext()) { - it.next(); - QPoint P = it.value(); - int rx = P.x(); - int ry = P.y(); - - QRectF dr = QRectF(rx, ry, mRoomWidth * rSize, mRoomHeight * rSize); - - // clang-format off - if (((mPick || __Pick) - && mPHighlight.x() >= (dr.x() - mRoomWidth / 3.0) - && mPHighlight.x() <= (dr.x() + mRoomWidth / 3.0) - && mPHighlight.y() >= (dr.y() - mRoomHeight / 3.0) - && mPHighlight.y() <= (dr.y() + mRoomHeight / 3.0)) - && mStartSpeedWalk) { - - // clang-format on - mStartSpeedWalk = false; - float roomRadius = (0.8 * mRoomWidth) / 2.0; - QPointF roomCenter = QPointF(rx, ry); - QRadialGradient gradient(roomCenter, roomRadius); - gradient.setColorAt(0.95, QColor(255, 0, 0, 150)); - gradient.setColorAt(0.80, QColor(150, 100, 100, 150)); - gradient.setColorAt(0.799, QColor(150, 100, 100, 100)); - gradient.setColorAt(0.7, QColor(255, 0, 0, 200)); - gradient.setColorAt(0, Qt::white); - QPen transparentPen(Qt::transparent); - QPainterPath myPath; - painter.setBrush(gradient); - painter.setPen(transparentPen); - myPath.addEllipse(roomCenter, roomRadius, roomRadius); - painter.drawPath(myPath); - - mPick = false; - mTarget = it.key(); - if (mpMap->mpRoomDB->getRoom(mTarget)) { - mpMap->mTargetID = mTarget; - if (mpMap->findPath(mpMap->mRoomIdHash.value(mpMap->mProfileName), mpMap->mTargetID)) { - mpMap->mpHost->startSpeedWalk(); - } else { - QString msg = tr("Mapper: Cannot find a path to this room using known exits.\n"); - mpHost->mpConsole->printSystemMessage(msg); - } - } - } - } - } } + // Draw Labels above the map if (mpMap->mapLabels.contains(mAreaID)) { QMapIterator it(mpMap->mapLabels[mAreaID]); while (it.hasNext()) { @@ -1472,6 +1501,7 @@ void T2DMap::paintEvent(QPaintEvent* e) } } + // Draw an indication of the central room of a multi-room selection. // Similar code was used to indicate target of custom exit line selected for // editing but this could not be done there because gridmode areas don't hit // that bit of code and later rooms would overwrite the target... @@ -1510,46 +1540,6 @@ void T2DMap::paintEvent(QPaintEvent* e) infoColor = QColor(Qt::white); } - // Draw central red circle: - if (!mShiftMode) { - painter.save(); - QPen transparentPen(Qt::transparent); - QPainterPath myPath; - if (mpHost->mMapStrongHighlight) { - // Never set, no means to except via XMLImport, as dlgMapper class's - // slot_toggleStrongHighlight is not wired up to anything - QRectF dr = QRectF(px - (mRoomWidth * rSize) / 2.0, py - (mRoomHeight * rSize) / 2.0, mRoomWidth * rSize, mRoomHeight * rSize); - painter.fillRect(dr, QColor(255, 0, 0, 150)); - - float roomRadius = 0.95 * mRoomWidth; - QPointF roomCenter = QPointF(px, py); - QRadialGradient gradient(roomCenter, roomRadius); - gradient.setColorAt(0.95, QColor(255, 0, 0, 150)); - gradient.setColorAt(0.80, QColor(150, 100, 100, 150)); - gradient.setColorAt(0.799, QColor(150, 100, 100, 100)); - gradient.setColorAt(0.7, QColor(255, 0, 0, 200)); - gradient.setColorAt(0, Qt::white); - painter.setBrush(gradient); - painter.setPen(transparentPen); - myPath.addEllipse(roomCenter, roomRadius, roomRadius); - } else { - float roomRadius = 0.95 * mRoomWidth; - QPointF roomCenter = QPointF(px, py); - QRadialGradient gradient(roomCenter, roomRadius); - gradient.setColorAt(0.95, QColor(255, 0, 0, 150)); - gradient.setColorAt(0.80, QColor(150, 100, 100, 150)); - gradient.setColorAt(0.799, QColor(150, 100, 100, 100)); - gradient.setColorAt(0.3, QColor(150, 150, 150, 100)); - gradient.setColorAt(0.1, QColor(255, 255, 255, 100)); - gradient.setColorAt(0, Qt::white); - painter.setBrush(gradient); - painter.setPen(transparentPen); - myPath.addEllipse(roomCenter, roomRadius, roomRadius); - } - painter.drawPath(myPath); - painter.restore(); - } - if (mShowInfo) { paintMapInfo(renderTimer, painter, playerAreaID == mAreaID, infoColor); } @@ -1581,7 +1571,7 @@ void T2DMap::paintEvent(QPaintEvent* e) mpMap->mpMapper->showArea->setFont(_f); - if (mHelpMsg.size() > 0) { + if (!mHelpMsg.isEmpty()) { painter.setPen(QColor(255, 155, 50)); QFont _f = painter.font(); QFont _f2 = _f; @@ -2375,7 +2365,7 @@ void T2DMap::createLabel(QRectF labelRectangle) textOrImageDialog.setStandardButtons(QMessageBox::Cancel); textOrImageDialog.exec(); if (textOrImageDialog.clickedButton() == textButton) { - QString title = tr("Enter label text.","2D Mapper create label dialog title/text"); + QString title = tr("Enter label text.", "2D Mapper create label dialog title/text"); font = QFontDialog::getFont(nullptr); text = QInputDialog::getText(nullptr, title, title); if (text.length() < 1) { @@ -2411,7 +2401,7 @@ void T2DMap::createLabel(QRectF labelRectangle) QPixmap pixmap(fabs(labelRectangle.width()), fabs(labelRectangle.height())); QRect drawRectangle = labelRectangle.normalized().toRect(); drawRectangle.moveTo(0, 0); - //pixmap.fill(QColor(0,255,0,0)); + //pixmap.fill(QColor(0, 255, 0, 0)); QPainter labelPainter(&pixmap); QPen labelPen; labelPainter.setFont(font); @@ -5136,3 +5126,84 @@ void T2DMap::resizeMultiSelectionWidget() mMultiSelectionListWidget.resize(newWidth, height()); } } + +void T2DMap::setPlayerRoomStyle(const int type) +{ + if (!mpMap) { + return; + } + + // From Qt 5.6 does not deallocate any memory previously used: + mPlayerRoomColorGradentStops.clear(); + // Indicate the LARGEST size we will need + mPlayerRoomColorGradentStops.reserve(5); + + double factor = mpMap->mPlayerRoomInnerDiameterPercentage / 100.0; + bool solid = (mpMap->mPlayerRoomInnerDiameterPercentage == 0); + switch (type) { + case 1: // Simple(?) shaded red ring: + if (solid) { + mPlayerRoomColorGradentStops.resize(3); + mPlayerRoomColorGradentStops[0] = QGradientStop(0.000, QColor(255, 0, 0, 255)); + mPlayerRoomColorGradentStops[1] = QGradientStop(0.990, QColor(255, 0, 0, 255)); + mPlayerRoomColorGradentStops[2] = QGradientStop(1.000, QColor(255, 0, 0, 0)); + } else { + mPlayerRoomColorGradentStops.resize(5); + mPlayerRoomColorGradentStops[0] = QGradientStop(0.000, QColor(255, 0, 0, 0)); + mPlayerRoomColorGradentStops[1] = QGradientStop(factor * 0.950, QColor(255, 0, 0, 0)); + mPlayerRoomColorGradentStops[2] = QGradientStop(factor * 1.050, QColor(255, 0, 0, 255)); + mPlayerRoomColorGradentStops[3] = QGradientStop(1.000 - (factor * 0.100), QColor(255, 0, 0, 255)); + mPlayerRoomColorGradentStops[4] = QGradientStop(1.000, QColor(255, 0, 0, 0)); + } + break; + // End of case 1: + + case 2: // Shaded bicolor (blue-yellow - so it ALWAYS contrasts with underlying room color) Ring: + if (solid) { + mPlayerRoomColorGradentStops.resize(3); + mPlayerRoomColorGradentStops[0] = QGradientStop(0.000, QColor(255, 255, 0, 255)); + mPlayerRoomColorGradentStops[1] = QGradientStop(0.990, QColor(0, 0, 255, 255)); + mPlayerRoomColorGradentStops[2] = QGradientStop(1.000, QColor(0, 0, 255, 0)); + } else { + mPlayerRoomColorGradentStops.resize(5); + mPlayerRoomColorGradentStops[0] = QGradientStop(0.000, QColor(255, 255, 0, 0)); + mPlayerRoomColorGradentStops[1] = QGradientStop(factor * 0.950, QColor(255, 255, 0, 0)); + mPlayerRoomColorGradentStops[2] = QGradientStop(factor * 1.050, QColor(255, 255, 0, 255)); + mPlayerRoomColorGradentStops[3] = QGradientStop(1.000 - (factor * 0.100), QColor(0, 0, 255, 255)); + mPlayerRoomColorGradentStops[4] = QGradientStop(1.000, QColor(0, 0, 255, 0)); + } + break; + // End of case 2: + + case 3: { // User set ring: + if (solid) { + mPlayerRoomColorGradentStops.resize(3); + mPlayerRoomColorGradentStops[0] = QGradientStop(0.000, mpMap->mPlayerRoomInnerColor); + mPlayerRoomColorGradentStops[1] = QGradientStop(0.990, mpMap->mPlayerRoomOuterColor); + QColor transparentColor(mpMap->mPlayerRoomOuterColor); + transparentColor.setAlpha(0); + mPlayerRoomColorGradentStops[2] = QGradientStop(1.000, transparentColor); + } else { + mPlayerRoomColorGradentStops.resize(5); + QColor transparentColor(mpMap->mPlayerRoomInnerColor); + transparentColor.setAlpha(0); + mPlayerRoomColorGradentStops[0] = QGradientStop(1.000, transparentColor); + mPlayerRoomColorGradentStops[1] = QGradientStop(factor * 0.950, transparentColor); + mPlayerRoomColorGradentStops[2] = QGradientStop(factor * 1.050, mpMap->mPlayerRoomInnerColor); + mPlayerRoomColorGradentStops[3] = QGradientStop(1.000 - (factor * 0.100), mpMap->mPlayerRoomOuterColor); + transparentColor = mpMap->mPlayerRoomOuterColor; + transparentColor.setAlpha(0); + mPlayerRoomColorGradentStops[4] = QGradientStop(1.000, transparentColor); + } + break; + } // End of case 3: + + default: // Sort of emulates the original code: + mPlayerRoomColorGradentStops.resize(5); + mPlayerRoomColorGradentStops[0] = QGradientStop(0, Qt::white); + mPlayerRoomColorGradentStops[1] = QGradientStop(0.7, QColor(255, 0, 0, 200)); + mPlayerRoomColorGradentStops[2] = QGradientStop(0.799, QColor(150, 100, 100, 100)); + mPlayerRoomColorGradentStops[3] = QGradientStop(0.80, QColor(150, 100, 100, 150)); + mPlayerRoomColorGradentStops[4] = QGradientStop(0.95, QColor(255, 0, 0, 150)); + } // End of switch () +} diff --git a/src/T2DMap.h b/src/T2DMap.h index 5f834ba9ab8..10e042c925d 100644 --- a/src/T2DMap.h +++ b/src/T2DMap.h @@ -24,24 +24,25 @@ ***************************************************************************/ -#include "TArea.h" #include "pre_guard.h" -#include #include #include -#include #include #include #include #include +#include #include #include "post_guard.h" class Host; +class TArea; class TMap; +class TRoom; class QCheckBox; class QComboBox; +class QElapsedTimer; class QListWidgetItem; class QPushButton; class QTreeWidgetItem; @@ -161,6 +162,7 @@ class T2DMap : public QWidget bool mSizeLabel; bool isCenterViewCall; QString mHelpMsg; + void setPlayerRoomStyle(const int style); public slots: void slot_roomSelectionChanged(); @@ -213,8 +215,10 @@ public slots: std::pair getMousePosition(); bool checkButtonIsForGivenDirection(const QPushButton*, const QString&, const int&); bool sizeFontToFitTextInRect(QFont&, const QRectF&, const QString&, const quint8 percentageMargin = 10); + void drawRoom(QPainter&, QFont&, QPen&, TRoom*, const bool isGridMode, const bool areRoomIdsLegible, const int, const float, const float, const bool); void paintMapInfo(const QElapsedTimer& renderTimer, QPainter& painter, const bool showingCurrentArea, QColor& infoColor); void paintAreaExits(QPainter& painter, QPen& pen, QList& exitList, QList& oneWayExits, const TArea* pArea, int zLevel, float exitWidth); + void initiateSpeeWalk(const int speedWalkStartRoomId, const int speedWalkTargetRoomId); bool mDialogLock; @@ -232,8 +236,8 @@ public slots: // slot_movePosition(), etc.} - previously have // used -1 but is now reset to 0 if it is not valid. int mMultiSelectionHighlightRoomId; - bool mIsSelectionSorting; + bool mIsSelectionSorting; bool mIsSelectionSortByNames; // Used to keep track of if sorting the multiple @@ -242,11 +246,14 @@ public slots: bool mIsSelectionUsingNames; QCache mSymbolPixmapCache; ushort mSymbolFontSize; - QFont mMapSymbolFont; QPointer mpCreateRoomAction; // in the players current area, how many digits does the biggest room number have? quint8 mMaxRoomIdDigits; + + // Holds the QRadialGradient details to use for the player room: + QGradientStops mPlayerRoomColorGradentStops; + private slots: void slot_createRoom(); }; diff --git a/src/TMap.h b/src/TMap.h index 067669d6301..6f6d4f8626a 100644 --- a/src/TMap.h +++ b/src/TMap.h @@ -155,6 +155,7 @@ class TMap : public QObject void setMmpMapLocation(const QString &location); QString getMmpMapLocation() const; + TRoomDB* mpRoomDB; QMap envColors; QPointer mpHost; @@ -236,7 +237,20 @@ class TMap : public QObject // location of an MMP map provided by the game QString mMmpMapLocation; - + // Base color(s) for the player room in the mappers: + QColor mPlayerRoomOuterColor; + QColor mPlayerRoomInnerColor; + // Mode selected - 0 is closest to original style: + quint8 mPlayerRoomStyle; + // Percentage of the room size (actually width) for the outer diameter of + // the circular marking, integer percentage clamped in the preferences + // between 200 and 50 - default 120: + quint8 mPlayerRoomOuterDiameterPercentage; + // Percentage of the outer size for the inner diameter of the circular + // marking, integer percentage clamped in the preferences between 83 and 0, + // with a default of 70. NOT USED FOR "Original" style marking (the 0'th + // one): + quint8 mPlayerRoomInnerDiameterPercentage; public slots: // Moved and revised from dlgMapper: diff --git a/src/XMLexport.cpp b/src/XMLexport.cpp index ac71e08260a..b85412d969e 100644 --- a/src/XMLexport.cpp +++ b/src/XMLexport.cpp @@ -369,6 +369,9 @@ void XMLexport::writeHost(Host* pHost, pugi::xml_node mudletPackage) auto hostPackage = mudletPackage.append_child("HostPackage"); auto host = hostPackage.append_child("Host"); + // Some of the data items being stored are simple numbers or other texts + // that can be expressed solely with the Latin1 character encoding so that + // can be used compared to the more complex Utf8 one needed otherwise: host.append_attribute("autoClearCommandLineAfterSend") = pHost->mAutoClearCommandLineAfterSend ? "yes" : "no"; host.append_attribute("printCommand") = pHost->mPrintCommand ? "yes" : "no"; host.append_attribute("USE_IRE_DRIVER_BUGFIX") = pHost->mUSE_IRE_DRIVER_BUGFIX ? "yes" : "no"; @@ -436,6 +439,17 @@ void XMLexport::writeHost(Host* pHost, pugi::xml_node mudletPackage) host.append_attribute("mRequiredDiscordUserDiscriminator") = pHost->mRequiredDiscordUserDiscriminator.toUtf8().constData(); host.append_attribute("mSGRCodeHasColSpaceId") = pHost->getHaveColorSpaceId() ? "yes" : "no"; host.append_attribute("mServerMayRedefineColors") = pHost->getMayRedefineColors() ? "yes" : "no"; + quint8 styleCode = 0; + quint8 outerDiameterPercentage = 0; + quint8 innerDiameterPercentage = 0; + QColor outerColor; + QColor innerColor; + pHost->getPlayerRoomStyleDetails(styleCode, outerDiameterPercentage, innerDiameterPercentage, outerColor, innerColor); + host.append_attribute("playerRoomPrimaryColor") = outerColor.name(QColor::HexArgb).toLatin1().constData(); + host.append_attribute("playerRoomSecondaryColor") = innerColor.name(QColor::HexArgb).toLatin1().constData(); + host.append_attribute("playerRoomStyle") = QString::number(styleCode).toLatin1().constData(); + host.append_attribute("playerRoomOuterDiameter") = QString::number(outerDiameterPercentage).toLatin1().constData(); + host.append_attribute("playerRoomInnerDiameter") = QString::number(innerDiameterPercentage).toLatin1().constData(); QString ignore; QSetIterator it(pHost->mDoubleClickIgnore); diff --git a/src/XMLimport.cpp b/src/XMLimport.cpp index a34ff5afd97..5254f88e431 100644 --- a/src/XMLimport.cpp +++ b/src/XMLimport.cpp @@ -873,6 +873,32 @@ void XMLimport::readHostPackage(Host* pHost) pHost->setMayRedefineColors(false); } + if (attributes().hasAttribute(QLatin1String("playerRoomStyle"))) { + quint8 styleCode = 0; + quint8 outerDiameterPercentage = 0; + quint8 innerDiameterPercentage = 0; + QColor outerColor; + QColor innerColor; + // Retrieve current (possibly default) settings: + pHost->getPlayerRoomStyleDetails(styleCode, outerDiameterPercentage, innerDiameterPercentage, outerColor, innerColor); + // Gather values from file: + styleCode = static_cast(qBound(0, attributes().value(QLatin1String("playerRoomStyle")).toInt(), 255)); + outerDiameterPercentage = static_cast(qBound(0, attributes().value(QLatin1String("playerRoomOuterDiameter")).toInt(), 255)); + innerDiameterPercentage = static_cast(qBound(0, attributes().value(QLatin1String("playerRoomInnerDiameter")).toInt(), 255)); + outerColor.setNamedColor(attributes().value(QLatin1String("playerRoomPrimaryColor")).toString()); + innerColor.setNamedColor(attributes().value(QLatin1String("playerRoomSecondaryColor")).toString()); + // Store all the settings in the Host instance: + pHost->setPlayerRoomStyleDetails(styleCode, outerDiameterPercentage, innerDiameterPercentage, outerColor, innerColor); + if (pHost->mpMap) { + // And the TMap instance: + pHost->mpMap->mPlayerRoomStyle = styleCode; + pHost->mpMap->mPlayerRoomOuterDiameterPercentage = outerDiameterPercentage; + pHost->mpMap->mPlayerRoomInnerDiameterPercentage = innerDiameterPercentage; + pHost->mpMap->mPlayerRoomOuterColor = outerColor; + pHost->mpMap->mPlayerRoomInnerColor = innerColor; + } + } + pHost->mFORCE_MXP_NEGOTIATION_OFF = (attributes().value("mFORCE_MXP_NEGOTIATION_OFF") == "yes"); pHost->mEnableTextAnalyzer = (attributes().value("enableTextAnalyzer") == "yes"); pHost->mRoomSize = attributes().value("mRoomSize").toString().toDouble(); diff --git a/src/discord.cpp b/src/discord.cpp index 5bcb2cadf58..311e65e009f 100644 --- a/src/discord.cpp +++ b/src/discord.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (C) 2018 by Vadim Peretokin - vperetokin@gmail.com * - * Copyright (C) 2018 by Stephen Lyons - slysven@virginmedia.com * + * Copyright (C) 2018-2019 by Stephen Lyons - slysven@virginmedia.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -27,6 +27,9 @@ #include #include "post_guard.h" +// Uncomment this to provide some additional qDebug() output: +// #define DEBUG_DISCORD 1 + QReadWriteLock Discord::smReadWriteLock; QString Discord::smUserName; @@ -57,9 +60,18 @@ Discord::Discord(QObject* parent) {"starmourn", {"starmourn.com"}}, {"stickmud", {"stickmud.com"}}} { +#if defined(Q_OS_WIN64) + // Only defined on 64 bit Windows + mpLibrary.reset(new QLibrary(QStringLiteral("discord-rpc64"))); +#elif defined(Q_OS_WIN32) + // Defined on both 32 and 64 bit Windows + mpLibrary.reset(new QLibrary(QStringLiteral("discord-rpc32"))); +#else + // All other OSes mpLibrary.reset(new QLibrary(QStringLiteral("discord-rpc"))); +#endif - using Discord_InitializePrototype = void (*)(const char*, DiscordEventHandlers*, int); + using Discord_InitializePrototype = void (*)(const char*, DiscordEventHandlers*, int, const char*); using Discord_UpdatePresencePrototype = void (*)(const DiscordRichPresence*); using Discord_RunCallbacksPrototype = void (*)(); using Discord_ShutdownPrototype = void (*)(); @@ -69,11 +81,14 @@ Discord::Discord(QObject* parent) Discord_RunCallbacks = reinterpret_cast(mpLibrary->resolve("Discord_RunCallbacks")); Discord_Shutdown = reinterpret_cast(mpLibrary->resolve("Discord_Shutdown")); - if (!Discord_Initialize || !Discord_UpdatePresence || !Discord_RunCallbacks || !Discord_Shutdown) { + if (!mpLibrary->isLoaded() || !Discord_Initialize || !Discord_UpdatePresence || !Discord_RunCallbacks || !Discord_Shutdown) { qDebug() << "Could not find Discord library - searched in:"; for (auto& libraryPath : qApp->libraryPaths()) { qDebug() << " " << libraryPath; } + if (auto msg = mpLibrary->errorString(); !msg.isEmpty()) { + qDebug().noquote().nospace() << " additionally there is an error message: \"" << msg << "\"."; + } return; } @@ -90,7 +105,7 @@ Discord::Discord(QObject* parent) mpHandlers->joinRequest = handleDiscordJoinRequest; // Initialise the default Mudlet presence - Discord_Initialize(mHostApplicationIDs.value(nullptr).toUtf8().constData(), mpHandlers, 0); + Discord_Initialize(mHostApplicationIDs.value(nullptr).toUtf8().constData(), mpHandlers, 0, nullptr); // mudlet instance is not available in this constructor as it's still being initialised, so postpone the connection QTimer::singleShot(0, [this]() { @@ -256,6 +271,9 @@ void Discord::handleDiscordReady(const DiscordUser* request) Discord::smAvatar = QString::fromUtf8(request->avatar); Discord::smReadWriteLock.unlock(); +#if defined(DEBUG_DISCORD) + qDebug().noquote().nospace() << "Discord Ready callback received - for UserName: \"" << smUserName << "\", ID: \"" << smUserId << "#" << smDiscriminator << "\"."; +#endif // don't call UpdatePresence from here - freezes Mudlet deep in the Discord API // when profile autostart is enabled } @@ -310,6 +328,9 @@ void Discord::UpdatePresence() if (!pHost) { localDiscordPresence tempPresence; tempPresence.setLargeImageKey(QStringLiteral("mudlet")); +#if defined(DEBUG_DISCORD) + qDebug().nospace().noquote() << "Discord::UpdatePresence() INFO - no current active Host instance, sending update using built-in Mudlet ApplicationID:\n" << tempPresence; +#endif DiscordRichPresence convertedPresence(tempPresence.convert()); Discord_UpdatePresence(&convertedPresence); @@ -319,6 +340,9 @@ void Discord::UpdatePresence() if (!pHost->discordUserIdMatch(Discord::smUserName, Discord::smDiscriminator)) { // Oh dear - the current Discord User does not match the required user // details (if set) - must abort +#if defined(DEBUG_DISCORD) + qDebug().nospace().noquote() << "Discord::UpdatePresence() INFO - Discord UserName/Discriminator does not match, not sending this update!"; +#endif return; } @@ -355,9 +379,12 @@ void Discord::UpdatePresence() if (mCurrentApplicationId != applicationID) { // It has changed - must shutdown and reopen the library instance with // the alternate application id: +#if defined(DEBUG_DISCORD) + qDebug().nospace().noquote() << "Discord::UpdatePresence() INFO - mCurrentApplicationId (\"" << mCurrentApplicationId << "\") does not match the one for this Host instance (\"" << applicationID << "\"), restarting RPC library with the latter."; +#endif Discord_Shutdown(); - Discord_Initialize(applicationID.toUtf8().constData(), mpHandlers, 0); + Discord_Initialize(applicationID.toUtf8().constData(), mpHandlers, 0, nullptr); mCurrentApplicationId = applicationID; } @@ -422,6 +449,9 @@ void Discord::UpdatePresence() pDiscordPresence->setStartTimeStamp(0); } +#if defined(DEBUG_DISCORD) + qDebug().nospace().noquote() << "Discord::UpdatePresence() INFO - sending update:\n" << *pDiscordPresence; +#endif // Convert our stored presence into the format that the RPC library wants: DiscordRichPresence convertedPresence(pDiscordPresence->convert()); Discord_UpdatePresence(&convertedPresence); diff --git a/src/discord.h b/src/discord.h index e3f1082c61e..cc1ba3aa0b1 100644 --- a/src/discord.h +++ b/src/discord.h @@ -220,10 +220,17 @@ class Discord : public QObject DiscordEventHandlers* mpHandlers; // These are function pointers to functions located in the Discord RPC library: - std::function Discord_Initialize; + std::function Discord_Initialize; std::function Discord_UpdatePresence; std::function Discord_RunCallbacks; std::function Discord_Shutdown; + // Not used: + // std::function(void)> Discord_ClearPresence; +#if defined(DISCORD_DISABLE_IO_THREAD) + // std::function Discord_UpdateConnection; +#endif + // std::function Discord_Respond; + // std::function Discord_UpdateHandlers; bool mLoaded; diff --git a/src/dlgMapper.cpp b/src/dlgMapper.cpp index 38131be39b3..6dde3d93508 100644 --- a/src/dlgMapper.cpp +++ b/src/dlgMapper.cpp @@ -28,9 +28,6 @@ #include "TConsole.h" #include "TMap.h" #include "TRoomDB.h" -#if defined(INCLUDE_3DMAPPER) -#include "glwidget.h" -#endif #include "pre_guard.h" #include @@ -66,6 +63,10 @@ dlgMapper::dlgMapper( QWidget * parent, Host * pH, TMap * pM ) mp2dMap->mpMap = pM; mp2dMap->mpHost = pH; + // Have to do this here rather than in the T2DMap constructor because that + // classes mpMap pointer is not initialised in its constructor. + // Set up default player room markings: + mp2dMap->setPlayerRoomStyle(mpMap->mPlayerRoomStyle); QMapIterator it(mpMap->mpRoomDB->getAreaNamesMap()); //sort them alphabetically (case sensitive) QMap areaNames; @@ -113,7 +114,7 @@ dlgMapper::dlgMapper( QWidget * parent, Host * pH, TMap * pM ) connect(increaseTop, &QAbstractButton::pressed, glWidget, &GLWidget::increaseTop); connect(increaseBottom, &QAbstractButton::pressed, glWidget, &GLWidget::increaseBottom); connect(reduceTop, &QAbstractButton::pressed, glWidget, &GLWidget::reduceTop); - connect(reduceBottom, &QAbstractButton::pressed, glWidget, &GLWidget::reduceBottom); + connect(reduceBottom, &QAbstractButton::pressed, glWidget, &GLWidget::reduceBottom); connect(shiftZup, &QAbstractButton::pressed, glWidget, &GLWidget::shiftZup); connect(shiftZdown, &QAbstractButton::pressed, glWidget, &GLWidget::shiftZdown); connect(shiftLeft, &QAbstractButton::pressed, glWidget, &GLWidget::shiftLeft); diff --git a/src/dlgMapper.h b/src/dlgMapper.h index e37b18c386d..71e9eeed11d 100644 --- a/src/dlgMapper.h +++ b/src/dlgMapper.h @@ -33,6 +33,9 @@ class Host; class TMap; +#if defined(INCLUDE_3DMAPPER) +class GLWidget; +#endif class dlgMapper : public QWidget, public Ui::mapper diff --git a/src/dlgProfilePreferences.cpp b/src/dlgProfilePreferences.cpp index e842fc18da2..3c31a5ebcf1 100644 --- a/src/dlgProfilePreferences.cpp +++ b/src/dlgProfilePreferences.cpp @@ -851,6 +851,23 @@ void dlgProfilePreferences::initWithHost(Host* pHost) connect(pushButton_showGlyphUsage, &QAbstractButton::clicked, this, &dlgProfilePreferences::slot_showMapGlyphUsage, Qt::UniqueConnection); connect(fontComboBox_mapSymbols, &QFontComboBox::currentFontChanged, this, &dlgProfilePreferences::slot_setMapSymbolFont, Qt::UniqueConnection); connect(checkBox_isOnlyMapSymbolFontToBeUsed, &QAbstractButton::clicked, this, &dlgProfilePreferences::slot_setMapSymbolFontStrategy, Qt::UniqueConnection); + + widget_playerRoomStyle->show(); + comboBox_playerRoomStyle->setCurrentIndex(pHost->mpMap->mPlayerRoomStyle); + // Custom colours only available in style '3' (of '0' to '3'): + pushButton_playerRoomPrimaryColor->setEnabled(pHost->mpMap->mPlayerRoomStyle == 3); + pushButton_playerRoomSecondaryColor->setEnabled(pHost->mpMap->mPlayerRoomStyle == 3); + spinBox_playerRoomOuterDiameter->setValue(pHost->mpMap->mPlayerRoomOuterDiameterPercentage); + spinBox_playerRoomInnerDiameter->setValue(pHost->mpMap->mPlayerRoomInnerDiameterPercentage); + // Adjustable inner diameter not available for style '0' (original): + spinBox_playerRoomInnerDiameter->setEnabled(pHost->mpMap->mPlayerRoomStyle != 0); + setButtonColor(pushButton_playerRoomPrimaryColor, pHost->mpMap->mPlayerRoomOuterColor); + setButtonColor(pushButton_playerRoomSecondaryColor, pHost->mpMap->mPlayerRoomInnerColor); + connect(comboBox_playerRoomStyle, qOverload(&QComboBox::currentIndexChanged), this, &dlgProfilePreferences::slot_changePlayerRoomStyle); + connect(pushButton_playerRoomPrimaryColor, &QAbstractButton::clicked, this, &dlgProfilePreferences::slot_setPlayerRoomPrimaryColor); + connect(pushButton_playerRoomSecondaryColor, &QAbstractButton::clicked, this, &dlgProfilePreferences::slot_setPlayerRoomSecondaryColor); + connect(spinBox_playerRoomOuterDiameter, qOverload(&QSpinBox::valueChanged), this, &dlgProfilePreferences::slot_setPlayerRoomOuterDiameter); + connect(spinBox_playerRoomInnerDiameter, qOverload(&QSpinBox::valueChanged), this, &dlgProfilePreferences::slot_setPlayerRoomInnerDiameter); } else { label_mapSymbolsFont->setEnabled(false); fontComboBox_mapSymbols->setEnabled(false); @@ -858,6 +875,7 @@ void dlgProfilePreferences::initWithHost(Host* pHost) pushButton_showGlyphUsage->setEnabled(false); checkBox_showDefaultArea->hide(); + widget_playerRoomStyle->hide(); } comboBox_encoding->addItem(QLatin1String("ASCII")); @@ -1119,6 +1137,13 @@ void dlgProfilePreferences::disconnectHostRelatedControls() disconnect(pushButton_resetLogDir, &QAbstractButton::clicked, nullptr, nullptr); disconnect(comboBox_logFileNameFormat, qOverload(&QComboBox::currentIndexChanged), nullptr, nullptr); disconnect(mIsToLogInHtml, &QAbstractButton::clicked, nullptr, nullptr); + + widget_playerRoomStyle->hide(); + disconnect(comboBox_playerRoomStyle, qOverload(&QComboBox::currentIndexChanged), nullptr, nullptr); + disconnect(pushButton_playerRoomPrimaryColor, &QAbstractButton::clicked, nullptr, nullptr); + disconnect(pushButton_playerRoomSecondaryColor, &QAbstractButton::clicked, nullptr, nullptr); + disconnect(spinBox_playerRoomOuterDiameter, qOverload(&QSpinBox::valueChanged), nullptr, nullptr); + disconnect(spinBox_playerRoomInnerDiameter, qOverload(&QSpinBox::valueChanged), nullptr, nullptr); } void dlgProfilePreferences::clearHostDetails() @@ -1399,7 +1424,7 @@ void dlgProfilePreferences::setTab(QString tab) { foreach (QWidget* child, tabWidget->findChildren()) { - if (child->objectName().contains(tab,Qt::CaseInsensitive)) + if (child->objectName().contains(tab, Qt::CaseInsensitive)) { tabWidget->setCurrentIndex(tabWidget->indexOf(child)); return; @@ -1512,7 +1537,9 @@ void dlgProfilePreferences::setColor(QPushButton* b, QColor& c) pHost->updateAnsi16ColorsInTable(); } - // Also set a contrasting foreground color so text will always be visible + // Also set a contrasting foreground color so text will always be + // visible - if the button is disabled the colors will be somewhat + // "greyed-out": setButtonColor(b, color); } } @@ -2558,6 +2585,23 @@ void dlgProfilePreferences::slot_save_and_exit() pHost->setHaveColorSpaceId(checkBox_expectCSpaceIdInColonLessMColorCode->isChecked()); pHost->setMayRedefineColors(checkBox_allowServerToRedefineColors->isChecked()); + + if (widget_playerRoomStyle->isVisible()) { + // Although the controls have been interactively modifying the + // TMap cached values for these, they were not being committed to + // the master values in the Host instance - but now we should write + // those - whilst we can get the first three (quint8) values + // directly from controls on this form/dialogue, the last two + // (QColors) are easiest to retrieve from the TMap instance as the + // colours are not directly stored here (as for some styles they + // show a partly "grey-ed out" colour as they are disabled for those + // styles): + pHost->setPlayerRoomStyleDetails(static_cast(comboBox_playerRoomStyle->currentIndex()), + static_cast(spinBox_playerRoomOuterDiameter->value()), + static_cast(spinBox_playerRoomInnerDiameter->value()), + pHost->mpMap->mPlayerRoomOuterColor, + pHost->mpMap->mPlayerRoomInnerColor); + } } #if defined(INCLUDE_UPDATER) @@ -3434,8 +3478,78 @@ void dlgProfilePreferences::slot_changeLogFileAsHtml(const bool isHtml) void dlgProfilePreferences::setButtonColor(QPushButton* button, const QColor& color) { - button->setStyleSheet(QStringLiteral("QPushButton{color: %1; background-color: %2;}").arg(color.lightness() > 127 ? QStringLiteral("black") : QStringLiteral("white"), - color.name())); + if (color.isValid()) { + if (button->isEnabled()) { + if (button == pushButton_playerRoomPrimaryColor || button == pushButton_playerRoomSecondaryColor) { + + // These two buttons show a color that may have transparency; so, + // instead of colouring the background, we include a generated + // black/white checkerboard pattern overlaid with the colour which + // when its alpha is not a 100% opaque will (partly) show the + // checkerboard. + + // Ensure the icon has a 3:1 aspect ratio: + if (auto iconWidth{button->iconSize().width()}, iconHeight{button->iconSize().height()}; iconWidth != iconHeight * 3) { + button->setIconSize(QSize(iconHeight * 3, iconHeight)); + } + + // Create a black/white checker background and overlay + QPixmap labelBackground(1 + (button->iconSize().height() * 3), 1 + (button->iconSize().height())); + labelBackground.fill(Qt::black); + QPainter painter(&labelBackground); + painter.drawImage(QRect(0, 0, labelBackground.width(), labelBackground.height()), + QImage(QStringLiteral(":/icons/black_white_transparent_check_1x3_ratio.png")) + .scaled(labelBackground.width(), labelBackground.height(), Qt::KeepAspectRatioByExpanding)); + painter.fillRect(0, 0, labelBackground.width(), labelBackground.height(), color); + painter.end(); + button->setIcon(QIcon(labelBackground)); + } else { + button->setStyleSheet(QStringLiteral("QPushButton {color: %1; background-color: %2; }") + .arg(color.lightness() > 127 ? QLatin1String("black") : QLatin1String("white"), + color.name())); + } + return; + } + + QColor disabledColor = QColor::fromHsl(color.hslHue(), color.hslSaturation()/4, color.lightness(), color.alpha()); + if (button == pushButton_playerRoomPrimaryColor || button == pushButton_playerRoomSecondaryColor) { + + // These two buttons show a color that may have transparency; so, + // instead of colouring the background, we include a generated + // black/white checkerboard pattern overlaid with the colour which + // when its alpha is not a 100% opaque will (partly) show the + // checkerboard. + + // Ensure the icon has a 3:1 aspect ratio: + if (auto iconWidth{button->iconSize().width()}, iconHeight{button->iconSize().height()}; iconWidth != iconHeight * 3) { + button->setIconSize(QSize(iconHeight * 3, iconHeight)); + } + + QPixmap iconBackground(1 + (button->iconSize().height() * 3), 1 + (button->iconSize().height())); + iconBackground.fill(Qt::black); + QPainter painter(&iconBackground); + painter.drawImage(QRect(0, 0, iconBackground.width(), iconBackground.height()), + QImage(QStringLiteral(":/icons/black_white_transparent_check_1x3_ratio.png")) + .scaled(iconBackground.width(), iconBackground.height(), Qt::KeepAspectRatioByExpanding)); + painter.fillRect(0, 0, iconBackground.width(), iconBackground.height(), disabledColor); + painter.end(); + // Because the button is disabled we have to explictly force our + // icon to be used for that state otherwise the built-in icon engine + // will assume our image is for the normal state and grey it out + // completely by automagic means instead of making use of the + // partial (desaturating) effect that we want to use: + QIcon icon; + icon.addPixmap(iconBackground, QIcon::Disabled, QIcon::Off); + button->setIcon(icon); + } else { + button->setStyleSheet(QStringLiteral("QPushButton {color: %1; background-color: %2; }") + .arg(QLatin1String("darkGray"), disabledColor.name())); + } + return; + } + + button->setIcon(QIcon()); + button->setStyleSheet(QString()); } // These next eight slots are so that if there are multiple profile preferences @@ -3593,3 +3707,137 @@ void dlgProfilePreferences::slot_guiLanguageChanged(const QString& language) // setupUi(...) call in the constructor} would be needed in every class with // persistent UI texts - this is not trivial and has been deemed NWIH...! } + +void dlgProfilePreferences::slot_changePlayerRoomStyle(const int index) +{ + Host* pHost = mpHost; + if (!pHost || !pHost->mpMap) { + return; + } + + int style = index; + switch (index) { + case 1: // Red ring + pushButton_playerRoomPrimaryColor->setEnabled(false); + pushButton_playerRoomSecondaryColor->setEnabled(false); + spinBox_playerRoomInnerDiameter->setEnabled(true); + break; + + case 2: // Blue-yellow ring + pushButton_playerRoomPrimaryColor->setEnabled(false); + pushButton_playerRoomSecondaryColor->setEnabled(false); + spinBox_playerRoomInnerDiameter->setEnabled(true); + break; + + case 3: // Custom ring + pushButton_playerRoomPrimaryColor->setEnabled(true); + pushButton_playerRoomSecondaryColor->setEnabled(true); + spinBox_playerRoomInnerDiameter->setEnabled(true); + break; + + default: + style = 0; + [[fallthrough]]; + case 0: // "Original" + pushButton_playerRoomPrimaryColor->setEnabled(false); + pushButton_playerRoomSecondaryColor->setEnabled(false); + spinBox_playerRoomInnerDiameter->setEnabled(false); + } + setButtonColor(pushButton_playerRoomPrimaryColor, pHost->mpMap->mPlayerRoomOuterColor); + setButtonColor(pushButton_playerRoomSecondaryColor, pHost->mpMap->mPlayerRoomInnerColor); + pHost->mpMap->mPlayerRoomStyle = static_cast(style); + if (!pHost->mpMap->mpMapper || !pHost->mpMap->mpMapper->mp2dMap) { + return; + } + pHost->mpMap->mpMapper->mp2dMap->setPlayerRoomStyle(style); + // And update the displayed map: + pHost->mpMap->mpMapper->mp2dMap->update(); +} + +void dlgProfilePreferences::slot_setPlayerRoomPrimaryColor() +{ + Host* pHost = mpHost; + if (!pHost || !mpHost->mpMap || !mpHost->mpMap->mpMapper || !mpHost->mpMap->mpMapper->mp2dMap) { + return; + } + + setPlayerRoomColor(pushButton_playerRoomPrimaryColor, mpHost->mpMap->mPlayerRoomOuterColor); + if (comboBox_playerRoomStyle->currentIndex() != 3) { + return; + } + + // The current setting IS for the custom color - so use it straight away: + mpHost->mpMap->mpMapper->mp2dMap->setPlayerRoomStyle(3); + // And update the displayed map: + mpHost->mpMap->mpMapper->mp2dMap->update(); +} + +void dlgProfilePreferences::slot_setPlayerRoomSecondaryColor() +{ + Host* pHost = mpHost; + if (!pHost || !mpHost->mpMap || !mpHost->mpMap->mpMapper || !mpHost->mpMap->mpMapper->mp2dMap) { + return; + } + + setPlayerRoomColor(pushButton_playerRoomSecondaryColor, mpHost->mpMap->mPlayerRoomInnerColor); + if (comboBox_playerRoomStyle->currentIndex() != 3) { + return; + } + + // The current setting IS for the custom color - so use it straight away: + mpHost->mpMap->mpMapper->mp2dMap->setPlayerRoomStyle(3); + // And update the displayed map: + mpHost->mpMap->mpMapper->mp2dMap->update(); +} + +void dlgProfilePreferences::slot_setPlayerRoomOuterDiameter(const int value) +{ + Host* pHost = mpHost; + if (!pHost || !mpHost->mpMap || !mpHost->mpMap->mpMapper || !mpHost->mpMap->mpMapper->mp2dMap) { + return; + } + + if (value < 256 && mpHost->mpMap->mPlayerRoomOuterDiameterPercentage != value) { + mpHost->mpMap->mPlayerRoomOuterDiameterPercentage = static_cast(value); + mpHost->mPlayerRoomOuterDiameterPercentage = static_cast(value); + // And update the displayed map: + mpHost->mpMap->mpMapper->mp2dMap->update(); + } +} + +void dlgProfilePreferences::slot_setPlayerRoomInnerDiameter(const int value) +{ + Host* pHost = mpHost; + if (!pHost || !mpHost->mpMap || !mpHost->mpMap->mpMapper || !mpHost->mpMap->mpMapper->mp2dMap) { + return; + } + + if (value < 256 && mpHost->mpMap->mPlayerRoomInnerDiameterPercentage != value) { + mpHost->mpMap->mPlayerRoomInnerDiameterPercentage = static_cast(value); + mpHost->mPlayerRoomInnerDiameterPercentage = static_cast(value); + // Redefine the QGradientStops + mpHost->mpMap->mpMapper->mp2dMap->setPlayerRoomStyle(qBound(0, comboBox_playerRoomStyle->currentIndex(), 3)); + // And update the displayed map: + mpHost->mpMap->mpMapper->mp2dMap->update(); + } +} + +void dlgProfilePreferences::setPlayerRoomColor(QPushButton* b, QColor& c) +{ + Host* pHost = mpHost; + if (!pHost) { + return; + } + + auto color = QColorDialog::getColor(c, this, (b == pushButton_playerRoomPrimaryColor + ? tr("Set outer color of player room mark.") + : tr("Set inner color of player room mark.")), + QColorDialog::ShowAlphaChannel); + if (color.isValid()) { + c = color; + + // Also sets a contrasting foreground color so text will always be + // visible and adjusts the saturation of a disabled button: + setButtonColor(b, color); + } +} diff --git a/src/dlgProfilePreferences.h b/src/dlgProfilePreferences.h index 8194a1d1c74..cce38603d1d 100644 --- a/src/dlgProfilePreferences.h +++ b/src/dlgProfilePreferences.h @@ -149,13 +149,19 @@ private slots: void slot_changeMenuBarVisibility(const mudlet::controlsVisibility); void slot_changeToolBarVisibility(const mudlet::controlsVisibility); void slot_changeShowIconsOnMenus(const Qt::CheckState); - void slot_changeGuiLanguage(const QString &language); - void slot_passwords_location_changed(int index); + void slot_changeGuiLanguage(const QString&); + void slot_passwords_location_changed(int); + void slot_changePlayerRoomStyle(const int); + void slot_setPlayerRoomPrimaryColor(); + void slot_setPlayerRoomSecondaryColor(); + void slot_setPlayerRoomOuterDiameter(const int); + void slot_setPlayerRoomInnerDiameter(const int); private: void setColors(); void setColors2(); void setColor(QPushButton*, QColor&); + void setPlayerRoomColor(QPushButton*, QColor&); void setButtonColor(QPushButton*, const QColor&); void loadEditorTab(); void populateThemesList(); @@ -174,6 +180,7 @@ private slots: void generateMapGlyphDisplay(); void generateDiscordTooltips(); void hidePasswordMigrationLabel(); + void setupPasswordsMigration(); int mFontSize; QPointer mpHost; @@ -190,7 +197,6 @@ private slots: // Host::mEnableUserDictionary: - although, following review THAT has been // disallowed... bool mUseSharedDictionary; - void setupPasswordsMigration(); }; #endif // MUDLET_DLGPROFILEPREFERENCES_H diff --git a/src/icons/black_white_transparent_check_1x3_ratio.png b/src/icons/black_white_transparent_check_1x3_ratio.png new file mode 100644 index 00000000000..7b2bd7fc051 Binary files /dev/null and b/src/icons/black_white_transparent_check_1x3_ratio.png differ diff --git a/src/mudlet.cpp b/src/mudlet.cpp index 23ea6d7fe11..05014d84d7a 100644 --- a/src/mudlet.cpp +++ b/src/mudlet.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -3405,41 +3406,50 @@ void mudlet::createMapper(bool loadDefaultMap) if (!pHost) { return; } - if (pHost->mpMap->mpMapper) { + auto pMap = pHost->mpMap.data(); + if (pMap->mpMapper) { bool visStatus = pHost->mpMap->mpMapper->isVisible(); - if (pHost->mpMap->mpMapper->parentWidget()->inherits("QDockWidget")) { - pHost->mpMap->mpMapper->parentWidget()->setVisible(!visStatus); + if (pMap->mpMapper->parentWidget()->inherits("QDockWidget")) { + pMap->mpMapper->parentWidget()->setVisible(!visStatus); } - pHost->mpMap->mpMapper->setVisible(!visStatus); + pMap->mpMapper->setVisible(!visStatus); return; } auto hostName(pHost->getName()); pHost->mpDockableMapWidget = new QDockWidget(tr("Map - %1").arg(hostName)); pHost->mpDockableMapWidget->setObjectName(QStringLiteral("dockMap_%1").arg(hostName)); - pHost->mpMap->mpMapper = new dlgMapper(pHost->mpDockableMapWidget, pHost, pHost->mpMap.data()); //FIXME: mpHost definieren + // Arrange for TMap member values to be copied from the Host masters so they + // are in place when the 2D mapper is created: + pHost->getPlayerRoomStyleDetails(pMap->mPlayerRoomStyle, + pMap->mPlayerRoomOuterDiameterPercentage, + pMap->mPlayerRoomInnerDiameterPercentage, + pMap->mPlayerRoomOuterColor, + pMap->mPlayerRoomInnerColor); + + pMap->mpMapper = new dlgMapper(pHost->mpDockableMapWidget, pHost, pMap); //FIXME: mpHost definieren #if defined(INCLUDE_3DMAPPER) - pHost->mpMap->mpM = pHost->mpMap->mpMapper->glWidget; + pMap->mpM = pMap->mpMapper->glWidget; #endif - pHost->mpDockableMapWidget->setWidget(pHost->mpMap->mpMapper); + pHost->mpDockableMapWidget->setWidget(pMap->mpMapper); - if (loadDefaultMap && pHost->mpMap->mpRoomDB->getRoomIDList().isEmpty()) { + if (loadDefaultMap && pMap->mpRoomDB->getRoomIDList().isEmpty()) { qDebug() << "mudlet::slot_mapper() - restore map case 3."; - pHost->mpMap->pushErrorMessagesToFile(tr("Pre-Map loading(3) report"), true); + pMap->pushErrorMessagesToFile(tr("Pre-Map loading(3) report"), true); QDateTime now(QDateTime::currentDateTime()); - if (pHost->mpMap->restore(QString())) { - pHost->mpMap->audit(); - pHost->mpMap->mpMapper->mp2dMap->init(); - pHost->mpMap->mpMapper->updateAreaComboBox(); - pHost->mpMap->mpMapper->resetAreaComboBoxToPlayerRoomArea(); - pHost->mpMap->mpMapper->show(); + if (pMap->restore(QString())) { + pMap->audit(); + pMap->mpMapper->mp2dMap->init(); + pMap->mpMapper->updateAreaComboBox(); + pMap->mpMapper->resetAreaComboBoxToPlayerRoomArea(); + pMap->mpMapper->show(); } - pHost->mpMap->pushErrorMessagesToFile(tr("Loading map(3) at %1 report").arg(now.toString(Qt::ISODate)), true); + pMap->pushErrorMessagesToFile(tr("Loading map(3) at %1 report").arg(now.toString(Qt::ISODate)), true); } else { - if (pHost->mpMap->mpMapper) { - pHost->mpMap->mpMapper->show(); + if (pMap->mpMapper) { + pMap->mpMapper->show(); } } addDockWidget(Qt::RightDockWidgetArea, pHost->mpDockableMapWidget); diff --git a/src/mudlet.qrc b/src/mudlet.qrc index 291f4a78a87..ab1a267e754 100644 --- a/src/mudlet.qrc +++ b/src/mudlet.qrc @@ -29,6 +29,7 @@ icons/avalon.png icons/badge.png icons/batmud_mud.png + icons/black_white_transparent_check_1x3_ratio.png icons/bookmarks.png icons/chronometer.png icons/clessidra.jpg @@ -66,6 +67,11 @@ icons/edit-web-search.png icons/errors.png icons/export.png + icons/face-plain.png + icons/face-sad.png + icons/face-smile.png + icons/face-surprise.png + icons/face-uncertain.png icons/filter-grey-locked.png icons/filter-grey.png icons/filter-locked.png @@ -185,10 +191,5 @@ ui/package_manager.ui ui/package_manager_unpack.ui ui/set_room_area.ui - icons/face-plain.png - icons/face-sad.png - icons/face-smile.png - icons/face-surprise.png - icons/face-uncertain.png diff --git a/src/ui/profile_preferences.ui b/src/ui/profile_preferences.ui index 203eb2d420c..6ff163460c1 100644 --- a/src/ui/profile_preferences.ui +++ b/src/ui/profile_preferences.ui @@ -2099,6 +2099,131 @@ + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 2D map player room marker style: + + + + + + + false + + + Outer ring color + + + + + + + false + + + Inner ring color + + + + + + + 0 + + + QComboBox::AdjustToMinimumContentsLengthWithIcon + + + + Original + + + + + Red ring + + + + + Blue/Yellow ring + + + + + Custom ring + + + + + + + + <p>Percentage ratio (<i>the default is 120%</i>) of the marker symbol to the space available for the room.</p> + + + Qt::AlignCenter + + + % + + + Outer diameter: + + + 50 + + + 200 + + + 120 + + + + + + + false + + + <p>Percentage ratio of the inner diameter of the marker symbol to the outer one (<i>the default is 70%</i>).</p> + + + Qt::AlignCenter + + + % + + + Inner diameter: + + + 83 + + + 70 + + + + + +