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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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