summaryrefslogtreecommitdiff
path: root/src/gui/widgets
AgeCommit message (Collapse)AuthorFilesLines
6 daysGUI: Added Desktop skinHEADmasterThorbjørn Lindeijer1-10/+6
Replaces the default login wallpaper. The wallpaper can still be set either through branding or in the client data. This also fixes the scaling of the Manasource logo when using the Mana theme. Closes #99
2025-07-15Render font outlines using TTF_SetFontOutlineThorbjørn Lindeijer8-88/+75
Rather than rendering the same texture 4 additional times, render a specific outline version of the text. While reducing the number of times the text is drawn, it does increase font texture use. Result is a generally prettier outline due to rendering it properly at sharp corners of the characters. The shadow for outlined text is now also thicker, as appropriate. As part of this change, the `TextRenderer` class was merged into the `Graphics` and `TrueTypeFont` classes. There seemed to be little point in having a separate function for this, apart from needing more static casts to `Graphics*`. Also fixed an issue where the font style was not being restored after adjusting the font scale, when using an older SDL_ttf than 2.0.18. Closes #87
2025-07-15Theme: Introduced HIGHLIGHT_TEXT colorThorbjørn Lindeijer3-3/+12
For customizing the text color used with HIGHLIGHT color as background.
2025-07-15Theme: Use TEXT color when rendering item amountsThorbjørn Lindeijer1-1/+1
Rather than hardcoded black.
2025-07-14Various small cleanupsThorbjørn Lindeijer1-1/+0
* Fixed doxygen comment on KeyFunction struct * Use SDL_BUTTON_LMASK instead of SDL_BUTTON(1) * Removed unused include
2025-07-11Make the screenshot file name a clickable linkThorbjørn Lindeijer1-0/+19
Some security checks are done because players might also write "screenshot:" in the chat to create file:// URLs and `SDL_OpenURL` can be used to open many things. So we disallow ".." and require a ".png" extension.
2025-07-11Cleaned up ImageRect a littleThorbjørn Lindeijer2-64/+25
* Use `std::unique_ptr`, so we can get rid of the custom move constructor and destructor. * Move and rename the `ImagePosition` enum to `WindowAlignment`, which fits better with what this enum is actually used for.
2025-07-08Jewelry: Adjusted color of highlighted tabThorbjørn Lindeijer1-3/+12
Seems this color just wasn't copied over correctly due to being on a different palette originally. Also made Tab::draw use the correct outline color. Addresses part of #98.
2025-07-06Add support for custom text colors for progress bars in GUI themeAndrew Hall1-1/+6
Since there was already specific support for theming different progress bars with a custom color gradient, it was relatively straight-forward to extend this to support custom text formats. Thanks to @Meway for having an initial go at this feature! Closes #111
2025-07-04Added logging priorities and use SDLs logging facilitiesThorbjørn Lindeijer3-5/+5
By using SDL logging, we can rely on SDL to filter the log messages by their priority before they get sent to our custom output function. For example, we now no longer get entries for created and destroyed Window instances by default, since these have only "debug" priority whereas the default priority for the "app" category is "info". We can also get log messages raised by SDL itself in our log now. Log levels can be controlled per category through the "SDL_LOGGING" environment variable. Many existing log messages have been assigned a category based on their existing prefix.
2025-07-02Added Quests windowThorbjørn Lindeijer3-2/+14
This window gives an overview over completed and currently active quests. A persistent checkbox toggles whether completed quests are shown. Item links are supported in quest texts. New window icon by meway. Completed quest icon for Mana theme copied from ManaPlus. The Quests window has no shortcut for now.
2025-05-25Fixed tooltip visibility logic for shortcut and inventory windowsThorbjørn Lindeijer3-25/+39
* When hovering an empty box in the shortcut window, the tooltip of a previously hovered non-empty box would stay visible. * When hovering to the right of a row of inventory items, the tooltip for the left-most item on the next row would be displayed. Also added some padding to shift the text and item icon a little in the shortcut window when using the Jewelry theme.
2025-04-28GUI: Use theme icons for offline/online player indicatorsThorbjørn Lindeijer2-34/+24
Instead of loading images directly, which is less flexible. In Jewelry theme, these icons are embedded in the window.png image.
2025-04-26GUI: Added support for explicit outline color per palette entryThorbjørn Lindeijer6-41/+116
This enables customized outlines for each text color as well as adding outlines for specific palettes, as done by the Jewelry theme. Merged PARTY_CHAT_TAB and PARTY_SOCIAL_TAB into just PARTY_TAB since we should probably be using the same color there anyway. Split off WHISPER_TAB as separate color from WHISPER.
2025-04-25GUI: Added support for multiple color palettes to ThemeThorbjørn Lindeijer19-226/+161
Each Skin can point to a different palette, which can be used to tweak text colors where necessary. For now there is no generic solution for this, instead a number of locations have been adjusted to take the palette into account: * ChatWindow sets its palette on the BrowserBox used in its tabs. * Popup sets its palette on child widgets when they are added (covering BrowserBox, Label and TextBox). * ItemPopup now uses its palette when looking up colors. The BrowserBox now retrieves its numbered text colors from the theme. Also added OLDCHAT, AWAYCHAT and GLOBAL theme colors, with ##g, ##o and ##a to choose these colors respectively. Fixed ImageRect move constructor. TextPreview class was cleaned up from unused functionality. Being name colors are no longer different between the name shown on the being and the name shown in the SpeechDialog.
2025-04-25Introduced theme dropdown in interface setupThorbjørn Lindeijer3-20/+13
* Added Theme dropdown to Interface setup * Added CARET theme color * Fixed issue with logging errors in `check` function in `theme.cpp` * Fixed XML::Children::Iterator to iterate only element nodes * Changed default theme to "jewelry" Changing the theme (or font size) shows a dialog that points out a restart is required to apply these changes. This is necessary at the moment because many things, like default or minimum window sizes, are only calculated once.
2025-04-25GUI: Added support for hiding the scroll area buttonsThorbjørn Lindeijer2-9/+138
And made the Jewelry theme hide those buttons.
2025-04-25GUI: Added support for fixed-size scrollarea markersThorbjørn Lindeijer2-7/+338
Due to getVerticalMarkerDimension and getHorizontalMarkerDimension not being virtual, this unfortunately required copying a lot of code from Guichan to make sure it calls our versions of these functions. Also addressed a small issue where gcn::ScrollArea::checkPolicies was not taking the frame size of the content into account.
2025-04-25Jewelry: Fixed sticky button positionThorbjørn Lindeijer1-18/+18
Used "spacing" to store the additional space between the sticky button and the edge of the window (or the close button). Adjusted Popup and ToolWindow skins by one pixel to make the sticky button align the same way as for the Window skin.
2025-04-25GUI: Allow theme to skin item slots and equipment boxesThorbjørn Lindeijer8-57/+60
* Added EquipmentBox and ItemSlot skin types. * Allowed rectangles drawn by the theme to be not filled. * Added width/height attributes to skin element since we needed a way to specify the size of the item slots and equipment boxes.
2025-04-25GUI: Allow customizing the SkinType used by a WindowThorbjørn Lindeijer2-9/+23
Now different windows can use different skin types. This also introduces a new ToolWindow skin type, which is generally a window without title bar nor close button. Customized windows are: * Chat -> Popup skin * MiniMap -> Popup skin * ShortcutWindow (items and emotes) -> ToolWindow skin Even though the MiniMap now appears as a Popup, it does have a title, so appropriate attributes have been added to this skin type.
2025-04-02Use a consistent naming style for enum class valuesThorbjørn Lindeijer2-10/+10
Sometimes I've used CamelCase and sometimes SNAKE_CASE for these values. Since "enum class" values are always prefixed with the enum name, which uses CamelCase, I find it more fitting to use it for the values as well. Also fixes compilation on Windows where 'ERROR' was conflicting with a define.
2025-04-02General code cleanupsThorbjørn Lindeijer2-36/+18
* Removed some unused includes and forward declarations. * Use std::unique_ptr to automate cleanup. * Use TextRenderer::renderText in BrowserBox to avoid code duplication. * Removed unused STATE_NORMAL from StateFlags. * Small layout fix in ServerDialog. * Reduced rewrapping delay in BrowserBox to 33ms and disabled it entirely when there are no more than 1000 lines to rewrap. The rewrapping is usually fast enough.
2025-04-02Fixed minimum width of the Social windowThorbjørn Lindeijer2-2/+17
Needs to allow space for all three buttons, especially since they are no longer clipped to the window.
2025-04-01GUI: Made CheckBox, RadioButton and Slider more customizableThorbjørn Lindeijer5-49/+63
Added handling of padding and text format and added new "spacing" skin variable which is used for the space between the label and the control in case of CheckBox and RadioButton. Small tweaks to UI layout in various places.
2025-03-31GUI: Support customizing widget text format through themeThorbjørn Lindeijer6-39/+138
The following widgets now support setting the font, text color, outline color and shadow color through the theme: * Button * Tab * Window (title) * ProgressBar The text format can be specified differently per skin state.
2025-03-31GUI: De-hardcode the window title offsetsThorbjørn Lindeijer2-9/+14
2025-03-31GUI: Apply clipping only where necessaryThorbjørn Lindeijer5-31/+40
Clipping has been disabled globally by taking it out of Graphics::pushClipArea. Now its name is a little confusing, but it can't just be changed since it is part of Guichan. Widgets that do need to clip their children use the new Graphics::pushClipRect, which pushes a clipping rectangle without affecting the local coordinates. These are: * ScrollArea * TextField * TabbedArea (scrolling tabs) * MiniMap While it might count as a small optimization, I'm actually disabling clipping because it is not always desired. For example it gets in the way of rendering the complete ResizeGrip in the Jewelry theme because that's a child widget.
2025-03-24Expanded GUI theming capabilitiesThorbjørn Lindeijer26-288/+433
* Moved previously hardcoded values for frame size, padding and title bar height to the Skin. * Added support for rendering colored rectangles (used for scroll bar background). * Scroll bar width is now determined by its skin. * Added separate skins for horizontal and vertical scroll bars and horizontal and vertical scroll markers and added a skin for the shortcut box. * Added support for hovered state on window close button.
2025-03-24Define the GUI theme in XMLThorbjørn Lindeijer14-164/+181
Now all images used by the various UI widgets are defined in a `theme.xml`, removing hardcoded requirements on the size of images, borders and sub-images and their locations. The `colors.xml` file was merged into this new file as well. The `<img>` element defines either a plain image, or a 9-scale that is automatically rendered at the size of the widget when any of the `left`, `right`, `top` or `bottom` attributes are given. The `x`, `y`, `width` and `height` attributes determine the sub-rectangle within the image referenced by `src`. `x` and `y` default to 0 and `width` and `height` default to the imge size. The `<state>` element defines in which state its images are used by setting its `selected`, `disabled`, `hovered` or `focused` attributes to either `true` or `false`. Only the first matching state is rendered. The `Text` and `SpeechBubble` classes now use the same skin to draw the bubble, as well as using a newly introduced `BUBBLE_TEXT` color from the theme palette.
2025-03-17Have ImageRect automatically initialize and clean upThorbjørn Lindeijer2-4/+0
2025-03-14Moved widget drawing code into ThemeThorbjørn Lindeijer29-1244/+172
This is cleaner overall since now each widget type no longer needs to keep track of its own instances and updating of the GUI alpha. It also introduces a single point from where the GUI theme support can be enhanced. Theme is no longer a singleton, though for now there is a single instance owned by the Gui singleton. Widgets adjusted to delegate their painting to the Theme: * Button * Tab * TextField * CheckBox * RadioButton * Slider * DropDown * ProgressBar * ScrollArea * ResizeGrip * PlayerBox (by subclassing ScrollArea) The Window and Popup widgets already use the theme through the Skin class. They can actually use a different skin per instance, though this feature is only used by the SpeechBubble.
2025-03-11Implemented replacement of key names in NPC dialogThorbjørn Lindeijer2-0/+42
Now when NPCs text includes "###MoveUp;", it will get replaced by "Up", or whatever key is currently bound to that action. For compatibility reasons the key name can optionally have a "key" prefix, for example "###keyMoveUp;". Closes #73
2025-03-07Reuse gcn::ScrollArea::drawThorbjørn Lindeijer2-27/+7
Code appeared duplicated just because we don't draw the background, but this could be done by overriding drawBackground instead.
2025-03-07Introduced spriteOffsetY setting to replace half tile hackThorbjørn Lindeijer1-3/+2
For historical reasons, sprites get a 16 pixel offset by default, which is used to position them correctly on their tile. When pixel-based movement was added, actors are now positioned on the middle of a tile and the built-in offset was removed. Servers that use sprites that do not rely on this offset can now set the spriteOffsetY option to 0.
2025-02-28Fixed unresponsive UI when switching server/char with Away dialog openThorbjørn Lindeijer2-7/+8
The UI became unresponsive as a result of not actually deleting the OkDialog. The dialog is now managed by the AwayListener, which now schedules Away dialog for deletion when necessary, using a DeathListener to clear the reference to the dialog. The WindowContainer now uses an std::set instead of std::list to keep track of widgets scheduled for deletion, to avoid crashing when a widget is scheduled for deletion multiple times.
2025-02-26Plugged a few more memory leaksThorbjørn Lindeijer4-20/+9
* DebugWindow and SkillDialog were not deleting their tabs nor their tab widgets. * TabbedArea was not deleting its arrow buttons. * Button was deleting its TextPopup on deletion of the last Button instance, which was wrong because it was also being deleted by the WindowContainer. Also removed some misplaced event forwarding to the TextPopup. TabbedArea is tricky because it does not automatically delete added tabs or their widgets. Tab instances are only deleted when they were added by name. Issues found by Valgrind memory analyzer.
2025-02-26Use ResourceRef for all resource typesThorbjørn Lindeijer29-169/+124
All ResourceManager functions that load resources now return respective ResourceRef values, which helps to make sure resources are properly cleaned up. The Sound class was cleaned up and now also allows SoundEffect resources to be unloaded. The Animation class now keeps its ImageSet loaded only as long as necessary. Previously, SimpleAnimation and ParticleEmitter would keep the ImageSet loaded indefinitely by never decreasing its reference count. Reduced duplicated animation loading code between SimpleAnimation and ParticleEmitter.
2025-02-21Removed ImageSpriteThorbjørn Lindeijer1-2/+0
The only use of ImageSprite was for FloorItem instances, which now just draw the item icon in FloorItem::draw. This leaves only one Sprite subclass, AnimatedSprite, which means we can remove the entire virtual Sprite interface.
2025-02-21Replaced ImageSprite in Emote by plain ImageThorbjørn Lindeijer1-5/+12
Emotes just need an image to be represented in the UI, so we don't need to use ImageSprite.
2025-02-17Further ResourceManager and PhysFS cleanupsThorbjørn Lindeijer2-16/+31
* Wrapped remaining PhysFS API calls and set PHYSFS_DEPRECATED to suppress deprecation warnings for PHYSFS_getUserDir, since no alternative is available for now. * Removed support for decompressing .gz files, since it has been unused for years and doesn't seem useful when updates are anyway served in an archive. * Use SDL_LoadFile and SDL_LoadFile_RW convenience functions (raises minimum SDL version to 2.0.10). * Removed ResourceManager::copyFile, since it was unused and will likely stay unused. * Removed ResourceManager::loadTextFile. Instead, split up the string in BrowserBox::addRows without making additional copies.
2025-01-21Replaced include guards with #pragma onceThorbjørn Lindeijer46-186/+46
Thanks to https://github.com/cgmb/guardonce and a follow-up replace to remove duplicated newlines at end of file: find src -type f -name '*.h' -exec \ sed --in-place -e :a -e '/^\n*$/{$d;N;};/\n$/ba' {} \; Source: https://unix.stackexchange.com/questions/81685/how-to-remove-multiple-newlines-at-eof Fixes compile on macOS, which appears to have been due to the EVENT_H include guard.
2025-01-21Fixed ConfigOptionChanged eventsThorbjørn Lindeijer1-1/+1
With the statically typed config we no longer get an event for each changed config value. Where relevant, this is now done through `setConfigValue`. The `Event` now uses a `std::any`, which for `ConfigOptionChanged` events is set to the changed `Config` member. This allows for a type-safe check on which config value was changed.
2025-01-20Made client config statically typedThorbjørn Lindeijer21-86/+73
This makes accessing the config values much faster, since it no longer needs to do a lookup nor string conversion, which means we could remove some needless copying of the values. Overall it makes it easier to find out where settings are used and it puts the defaults along with the declaration. Options with default values are no longer saved to the config file. This does not include unrecognized options, which are kept around to provide some compatibility with older clients. While most basic options have kept the same name, more complicated settings like window geometry, shortcuts, outfits, etc. now have their own XML elements. Older clients will ignore these and erase them when saving the configuration.
2024-10-29Optimise PlayerRelationsManager::clearThorbjørn Lindeijer1-5/+4
Previous implementation was O(n^2), doing lots of work (saving file and updating UI) for each removed player.
2024-10-26Fixed FPS limit being enabled by defaultThorbjørn Lindeijer2-2/+2
There were some inconsistencies between the values set up in `Client::initConfiguration` and those in `getConfigDefaults`. These duplicates have now been removed. For some of these settings the code getting the values had to be adjusted to use getBoolValue, to actually rely on the provided default instead of one provided as a parameter.
2024-10-18Added small grabbable margin to Shortcuts windowThorbjørn Lindeijer3-43/+19
The Shortcuts window could no longer be moved since adding support for resizing windows at the top edge. Now there is again a bit of space where the window can be grabbed. Included some related cleanups.
2024-10-18General code cleanupsThorbjørn Lindeijer1-3/+2
2024-10-08Do a single logic update each frameThorbjørn Lindeijer1-1/+1
The logic update now uses Time::deltaTimeMs() where needed to make it framerate-independent. This means there will no longer be multiple logic calls per frame (as was usually the case with logic ticking at 100 fps whereas the game would generally run at 60 fps). At the same time, the game can be more precise at higher framerates and should now run smoother at 144 Hz, for example. Previously the game would sometimes skip logic ticks at that rate. This change affects: * Updating of animations * Being movement speed * More moving of manual time variables to Timer Notoriously, the particle system still does 100 ticks/second.
2024-10-08Added convenient and efficient Timer classThorbjørn Lindeijer2-5/+7
The Timer is efficient because it does not depend on incrementing a counter to keep track of time, nor does it call SDL_GetTicks every time its state is checked (this happens once per frame instead). Along with global functions Time::absoluteTimeMs() and Time::deltaTimeMs(), this replaces previous globals tick_time, cur_time and get_elapsed_time(). For now, there is still a fixed 100 times per second logic call rate, but the new Time::deltaTimeMs() function should allow getting rid of this.