Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
21 changes: 21 additions & 0 deletions src/clock/mumeclock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,13 @@ void MumeClock::parseMumeTime(const QString &mumeTime, const int64_t secsSinceEp
qWarning() << "Calculated week day does not match MUME";
}
m_mumeStartEpoch = newStartEpoch;

// Check if season changed and emit signal
const auto currentSeason = capturedMoment.toSeason();
if (currentSeason != m_lastSeasonEmitted && currentSeason != MumeSeasonEnum::UNKNOWN) {
m_lastSeasonEmitted = currentSeason;
emit sig_seasonChanged(currentSeason);
}
}

void MumeClock::onUserGmcp(const GmcpMessage &msg)
Expand Down Expand Up @@ -319,6 +326,13 @@ void MumeClock::parseWeather(const MumeTimeEnum time, int64_t secsSinceEpoch)
if (time != MumeTimeEnum::UNKNOWN || m_precision >= MumeClockPrecisionEnum::HOUR) {
m_precision = MumeClockPrecisionEnum::MINUTE;
}

// Check if season changed and emit signal
const auto currentSeason = moment.toSeason();
if (currentSeason != m_lastSeasonEmitted && currentSeason != MumeSeasonEnum::UNKNOWN) {
m_lastSeasonEmitted = currentSeason;
emit sig_seasonChanged(currentSeason);
}
}

void MumeClock::parseClockTime(const QString &clockTime)
Expand Down Expand Up @@ -357,6 +371,13 @@ void MumeClock::parseClockTime(const QString &clockTime, const int64_t secsSince
log("Synchronized with clock in room (" + QString::number(newStartEpoch - m_mumeStartEpoch)
+ " seconds from previous)");
m_mumeStartEpoch = newStartEpoch;

// Check if season changed and emit signal
const auto currentSeason = moment.toSeason();
if (currentSeason != m_lastSeasonEmitted && currentSeason != MumeSeasonEnum::UNKNOWN) {
m_lastSeasonEmitted = currentSeason;
emit sig_seasonChanged(currentSeason);
}
}

void MumeClock::parseMSSP(const MsspTime &msspTime)
Expand Down
2 changes: 2 additions & 0 deletions src/clock/mumeclock.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,11 @@ class NODISCARD_QOBJECT MumeClock final : public QObject

private:
void onUserGmcp(const GmcpMessage &msg);
MumeSeasonEnum m_lastSeasonEmitted = MumeSeasonEnum::UNKNOWN;

signals:
void sig_log(const QString &, const QString &);
void sig_seasonChanged(MumeSeasonEnum newSeason);

public slots:
void parseMumeTime(const QString &mumeTime);
Expand Down
479 changes: 478 additions & 1 deletion src/configuration/configuration.cpp

Large diffs are not rendered by default.

162 changes: 160 additions & 2 deletions src/configuration/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@

#undef TRANSPARENT // Bad dog, Microsoft; bad dog!!!

// Forward declaration for InfomarkClassEnum
enum class InfomarkClassEnum : uint8_t;

#define SUBGROUP() \
friend class Configuration; \
void read(const QSettings &conf); \
Expand Down Expand Up @@ -79,6 +82,7 @@ class NODISCARD Configuration final
char prefixChar = char_consts::C_UNDERSCORE;
bool encodeEmoji = true;
bool decodeEmoji = true;
bool enableYellFallbackParsing = true; // Parse yells from game text when GMCP unavailable

private:
SUBGROUP();
Expand Down Expand Up @@ -143,6 +147,10 @@ class NODISCARD Configuration final
bool trilinearFiltering = false;
bool softwareOpenGL = false;
QString resourcesDirectory;
TextureSetEnum textureSet = TextureSetEnum::MODERN;
bool enableSeasonalTextures = true;
float layerTransparency = 1.0f; // 0.0 = only focused layer, 1.0 = maximum transparency
bool enableRadialTransparency = true; // Enable radial transparency zones on upper layers

// not saved yet:
bool drawCharBeacons = true;
Expand All @@ -159,12 +167,21 @@ class NODISCARD Configuration final
NamedConfig<bool> autoTilt{"MMAPPER_AUTO_TILT", true};
NamedConfig<bool> printPerfStats{"MMAPPER_GL_PERFSTATS", IS_DEBUG_BUILD};

// Background image settings
bool useBackgroundImage = false;
QString backgroundImagePath;
int backgroundFitMode = 0; // BackgroundFitModeEnum::FIT
float backgroundOpacity = 1.0f;
float backgroundFocusedScale = 1.0f; // Scale factor for FOCUSED mode (0.1 to 10.0)
float backgroundFocusedOffsetX = 0.0f; // X offset for FOCUSED mode (-1000 to 1000)
float backgroundFocusedOffsetY = 0.0f; // Y offset for FOCUSED mode (-1000 to 1000)

// 5..90 degrees
FixedPoint<1> fov{50, 900, 765};
// 0..90 degrees
FixedPoint<1> verticalAngle{0, 900, 450};
// -45..45 degrees
FixedPoint<1> horizontalAngle{-450, 450, 0};
// -180..180 degrees (full rotation)
FixedPoint<1> horizontalAngle{-1800, 1800, 0};
// 1..10 rooms
FixedPoint<1> layerHeight{10, 100, 15};

Expand All @@ -175,10 +192,147 @@ class NODISCARD Configuration final
Advanced();
} advanced;

struct NODISCARD VisibilityFilter final
{
NamedConfig<bool> generic{"VISIBLE_MARKER_GENERIC", true};
NamedConfig<bool> herb{"VISIBLE_MARKER_HERB", true};
NamedConfig<bool> river{"VISIBLE_MARKER_RIVER", true};
NamedConfig<bool> place{"VISIBLE_MARKER_PLACE", true};
NamedConfig<bool> mob{"VISIBLE_MARKER_MOB", true};
NamedConfig<bool> comment{"VISIBLE_MARKER_COMMENT", true};
NamedConfig<bool> road{"VISIBLE_MARKER_ROAD", true};
NamedConfig<bool> object{"VISIBLE_MARKER_OBJECT", true};
NamedConfig<bool> action{"VISIBLE_MARKER_ACTION", true};
NamedConfig<bool> locality{"VISIBLE_MARKER_LOCALITY", true};
NamedConfig<bool> connections{"VISIBLE_CONNECTIONS", true};

public:
NODISCARD bool isVisible(InfomarkClassEnum markerClass) const;
void setVisible(InfomarkClassEnum markerClass, bool visible);
NODISCARD bool isConnectionsVisible() const { return connections.get(); }
void setConnectionsVisible(bool visible) { connections.set(visible); }
void showAll();
void hideAll();
void registerChangeCallback(const ChangeMonitor::Lifetime &lifetime,
const ChangeMonitor::Function &callback);

VisibilityFilter();
} visibilityFilter;

private:
SUBGROUP();
} canvas;

struct NODISCARD Hotkeys final
{
// File operations
NamedConfig<QString> fileOpen{"HOTKEY_FILE_OPEN", "Ctrl+O"};
NamedConfig<QString> fileSave{"HOTKEY_FILE_SAVE", "Ctrl+S"};
NamedConfig<QString> fileReload{"HOTKEY_FILE_RELOAD", "Ctrl+R"};
NamedConfig<QString> fileQuit{"HOTKEY_FILE_QUIT", "Ctrl+Q"};

// Edit operations
NamedConfig<QString> editUndo{"HOTKEY_EDIT_UNDO", "Ctrl+Z"};
NamedConfig<QString> editRedo{"HOTKEY_EDIT_REDO", "Ctrl+Y"};
NamedConfig<QString> editPreferences{"HOTKEY_EDIT_PREFERENCES", "Ctrl+P"};
NamedConfig<QString> editPreferencesAlt{"HOTKEY_EDIT_PREFERENCES_ALT", "Esc"};
NamedConfig<QString> editFindRooms{"HOTKEY_EDIT_FIND_ROOMS", "Ctrl+F"};
NamedConfig<QString> editRoom{"HOTKEY_EDIT_ROOM", "Ctrl+E"};

// View operations
NamedConfig<QString> viewZoomIn{"HOTKEY_VIEW_ZOOM_IN", ""};
NamedConfig<QString> viewZoomOut{"HOTKEY_VIEW_ZOOM_OUT", ""};
NamedConfig<QString> viewZoomReset{"HOTKEY_VIEW_ZOOM_RESET", "Ctrl+0"};
NamedConfig<QString> viewLayerUp{"HOTKEY_VIEW_LAYER_UP", ""};
NamedConfig<QString> viewLayerDown{"HOTKEY_VIEW_LAYER_DOWN", ""};
NamedConfig<QString> viewLayerReset{"HOTKEY_VIEW_LAYER_RESET", ""};

// View toggles
NamedConfig<QString> viewRadialTransparency{"HOTKEY_VIEW_RADIAL_TRANSPARENCY", ""};
NamedConfig<QString> viewStatusBar{"HOTKEY_VIEW_STATUS_BAR", ""};
NamedConfig<QString> viewScrollBars{"HOTKEY_VIEW_SCROLL_BARS", ""};
NamedConfig<QString> viewMenuBar{"HOTKEY_VIEW_MENU_BAR", ""};
NamedConfig<QString> viewAlwaysOnTop{"HOTKEY_VIEW_ALWAYS_ON_TOP", ""};

// Side panels
NamedConfig<QString> panelLog{"HOTKEY_PANEL_LOG", "Ctrl+L"};
NamedConfig<QString> panelClient{"HOTKEY_PANEL_CLIENT", ""};
NamedConfig<QString> panelGroup{"HOTKEY_PANEL_GROUP", ""};
NamedConfig<QString> panelRoom{"HOTKEY_PANEL_ROOM", ""};
NamedConfig<QString> panelAdventure{"HOTKEY_PANEL_ADVENTURE", ""};
NamedConfig<QString> panelDescription{"HOTKEY_PANEL_DESCRIPTION", ""};
NamedConfig<QString> panelComms{"HOTKEY_PANEL_COMMS", ""};

// Mouse modes
NamedConfig<QString> modeMoveMap{"HOTKEY_MODE_MOVE_MAP", ""};
NamedConfig<QString> modeRaypick{"HOTKEY_MODE_RAYPICK", ""};
NamedConfig<QString> modeSelectRooms{"HOTKEY_MODE_SELECT_ROOMS", ""};
NamedConfig<QString> modeSelectMarkers{"HOTKEY_MODE_SELECT_MARKERS", ""};
NamedConfig<QString> modeSelectConnection{"HOTKEY_MODE_SELECT_CONNECTION", ""};
NamedConfig<QString> modeCreateMarker{"HOTKEY_MODE_CREATE_MARKER", ""};
NamedConfig<QString> modeCreateRoom{"HOTKEY_MODE_CREATE_ROOM", ""};
NamedConfig<QString> modeCreateConnection{"HOTKEY_MODE_CREATE_CONNECTION", ""};
NamedConfig<QString> modeCreateOnewayConnection{"HOTKEY_MODE_CREATE_ONEWAY_CONNECTION", ""};

// Room operations
NamedConfig<QString> roomCreate{"HOTKEY_ROOM_CREATE", ""};
NamedConfig<QString> roomMoveUp{"HOTKEY_ROOM_MOVE_UP", ""};
NamedConfig<QString> roomMoveDown{"HOTKEY_ROOM_MOVE_DOWN", ""};
NamedConfig<QString> roomMergeUp{"HOTKEY_ROOM_MERGE_UP", ""};
NamedConfig<QString> roomMergeDown{"HOTKEY_ROOM_MERGE_DOWN", ""};
NamedConfig<QString> roomDelete{"HOTKEY_ROOM_DELETE", "Del"};
NamedConfig<QString> roomConnectNeighbors{"HOTKEY_ROOM_CONNECT_NEIGHBORS", ""};
NamedConfig<QString> roomMoveToSelected{"HOTKEY_ROOM_MOVE_TO_SELECTED", ""};
NamedConfig<QString> roomUpdateSelected{"HOTKEY_ROOM_UPDATE_SELECTED", ""};

private:
SUBGROUP();
} hotkeys;

struct NODISCARD CommsSettings final
{
// Colors for each communication type
NamedConfig<QColor> tellColor{"COMMS_TELL_COLOR", QColor(Qt::cyan)};
NamedConfig<QColor> whisperColor{"COMMS_WHISPER_COLOR", QColor(135, 206, 250)}; // Light sky blue
NamedConfig<QColor> groupColor{"COMMS_GROUP_COLOR", QColor(Qt::green)};
NamedConfig<QColor> askColor{"COMMS_ASK_COLOR", QColor(Qt::yellow)};
NamedConfig<QColor> sayColor{"COMMS_SAY_COLOR", QColor(Qt::white)};
NamedConfig<QColor> emoteColor{"COMMS_EMOTE_COLOR", QColor(Qt::magenta)};
NamedConfig<QColor> socialColor{"COMMS_SOCIAL_COLOR", QColor(255, 182, 193)}; // Light pink
NamedConfig<QColor> yellColor{"COMMS_YELL_COLOR", QColor(Qt::red)};
NamedConfig<QColor> narrateColor{"COMMS_NARRATE_COLOR", QColor(255, 165, 0)}; // Orange
NamedConfig<QColor> prayColor{"COMMS_PRAY_COLOR", QColor(173, 216, 230)}; // Light blue
NamedConfig<QColor> shoutColor{"COMMS_SHOUT_COLOR", QColor(139, 0, 0)}; // Dark red
NamedConfig<QColor> singColor{"COMMS_SING_COLOR", QColor(144, 238, 144)}; // Light green
NamedConfig<QColor> backgroundColor{"COMMS_BG_COLOR", QColor(Qt::black)};

// Talker colors (based on GMCP Comm.Channel talker-type)
NamedConfig<QColor> talkerYouColor{"COMMS_TALKER_YOU_COLOR", QColor(255, 215, 0)}; // Gold
NamedConfig<QColor> talkerPlayerColor{"COMMS_TALKER_PLAYER_COLOR", QColor(Qt::white)};
NamedConfig<QColor> talkerNpcColor{"COMMS_TALKER_NPC_COLOR", QColor(192, 192, 192)}; // Silver/Gray
NamedConfig<QColor> talkerAllyColor{"COMMS_TALKER_ALLY_COLOR", QColor(0, 255, 0)}; // Bright green
NamedConfig<QColor> talkerNeutralColor{"COMMS_TALKER_NEUTRAL_COLOR", QColor(255, 255, 0)}; // Yellow
NamedConfig<QColor> talkerEnemyColor{"COMMS_TALKER_ENEMY_COLOR", QColor(255, 0, 0)}; // Red

// Font styling options
NamedConfig<bool> yellAllCaps{"COMMS_YELL_ALL_CAPS", true};
NamedConfig<bool> whisperItalic{"COMMS_WHISPER_ITALIC", true};
NamedConfig<bool> emoteItalic{"COMMS_EMOTE_ITALIC", true};

// Display options
NamedConfig<bool> showTimestamps{"COMMS_SHOW_TIMESTAMPS", false};
NamedConfig<bool> saveLogOnExit{"COMMS_SAVE_LOG_ON_EXIT", false};
NamedConfig<QString> logDirectory{"COMMS_LOG_DIR", ""};

// Tab muting (acts as a filter)
NamedConfig<bool> muteDirectTab{"COMMS_MUTE_DIRECT", false};
NamedConfig<bool> muteLocalTab{"COMMS_MUTE_LOCAL", false};
NamedConfig<bool> muteGlobalTab{"COMMS_MUTE_GLOBAL", false};

private:
SUBGROUP();
} comms;

#define XFOREACH_NAMED_COLOR_OPTIONS(X) \
X(BACKGROUND, BACKGROUND_NAME) \
X(CONNECTION_NORMAL, CONNECTION_NORMAL_NAME) \
Expand Down Expand Up @@ -300,6 +454,10 @@ class NODISCARD Configuration final
{
int64_t startEpoch = 0;
bool display = false;
NamedConfig<bool> gmcpBroadcast{"GMCP_BROADCAST_CLOCK", true}; // Enable GMCP clock broadcasting
NamedConfig<int> gmcpBroadcastInterval{"GMCP_BROADCAST_INTERVAL", 2500}; // Update interval in milliseconds (default: 2.5 seconds = 1 MUME minute)

MumeClockSettings();

private:
SUBGROUP();
Expand Down
Loading