diff --git a/.clang-format b/.clang-format index 71628c23e..335adde5d 100644 --- a/.clang-format +++ b/.clang-format @@ -66,7 +66,7 @@ CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 -Cpp11BracedListStyle: false +Cpp11BracedListStyle: true DeriveLineEnding: true DerivePointerAlignment: false DisableFormat: false @@ -119,7 +119,7 @@ SpaceAfterCStyleCast: false SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: true +SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements diff --git a/CHANGELOG.md b/CHANGELOG.md index 874b6d05f..9a1016480 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ * Added a menu option to change the application exit key combination * Added the GLM (OpenGL Mathematics) library as a Git subtree +* Replaced all built-in matrix and vector data types and functions with GLM library equivalents +* Replaced some additional math functions and moved the remaining built-in functions to a math utility namespace +* Added a function to generate MD5 hashes +* Changed two clang-format rules related to braced lists and reformatted the codebase +* Changed the language standard from C++14 to C++17 ### Bug fixes @@ -293,6 +298,4 @@ Many bugs have been fixed, and numerous features that were only partially implem * On macOS Big Sur (and possibly other OS versions) when connecting a DualShock 4 controller either via Bluetooth or using a USB cable, two separate controller devices are registered in parallel. This is a bug in either macOS or the DualShock driver and it makes it seem as if ES-DE is registering double button presses when actually two separate controller devices are generating identical input. A workaround if using Bluetooth mode is to plug in the USB cable just after connecting the controller, wait a second or two and then remove the cable again. This will remove the cabled device, leaving only the Bluetooth device active. Another workaround is to enable the setting "Only accept input from first controller" in the ES-DE input device settings. The reason why this bug may not be visible in some other games and applications is that ES-DE enables and auto-configures all connected controllers. -* Some screen tearing can be seen in the upper part of the screen when using the slide transitions with certain graphics drivers and resolutions. This problem will hopefully be resolved in ES-DE v1.2 when moving to the GLM library. - * On Windows when using high DPI displays, if not running ES-DE on the primary monitor and the display where it runs does not have the same scaling percentage as the primary monitor, then the ES-DE resolution will not be properly set. The application will still work and if running in fullscreen mode it may not even be noticeable. This issue is caused by a bug in SDL where the primary display scaling is always used for calculating the display bounds and as such it needs to be fixed in that library. If using the same scaling percentage across all monitors, or if not using high DPI monitors at all, then this issue will not occur. diff --git a/CMakeLists.txt b/CMakeLists.txt index a7fda450d..9d6d7065d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,11 +122,11 @@ endif() # Set up compiler and linker flags for debug, profiling or release builds. if(CMAKE_BUILD_TYPE MATCHES Debug) - # Enable the C++14 standard and disable optimizations as it's a debug build. + # Enable the C++17 standard and disable optimizations as it's a debug build. if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++14 /Od /DEBUG:FULL") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17 /Od /DEBUG:FULL") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O0") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -O0") endif() # If using Clang, then add additional debug data needed by GDB. @@ -139,18 +139,18 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) elseif(CMAKE_BUILD_TYPE MATCHES Profiling) # For the profiling build, we enable optimizations and supply the required profiler flags. if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++14 /O2 /DEBUG:FULL") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17 /O2 /DEBUG:FULL") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O2 -pg -g") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O2 -pg -g") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -O2 -pg") endif() else() - # Enable the C++14 standard and enable optimizations as it's a release build. + # Enable the C++17 standard and enable optimizations as it's a release build. # This will also disable all assert() macros. Strip the binary too. if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG /std:c++14 /O2 /DEBUG:NONE") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG /std:c++17 /O2 /DEBUG:NONE") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O2 -DNDEBUG") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O2 -DNDEBUG") if(APPLE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -O2") else() @@ -196,6 +196,10 @@ if(DEFINED libCEC_FOUND) add_definitions(-DHAVE_LIBCEC) endif() +# GLM library options. +add_definitions(-DGLM_FORCE_CXX17) +add_definitions(-DGLM_FORCE_XYZW_ONLY) + # For Unix systems, assign the installation prefix. If it's not explicitly set, # we use /usr on Linux, /usr/pkg on NetBSD and /usr/local on FreeBSD and OpenBSD. if(NOT WIN32 AND NOT APPLE) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 45795265d..b2407e56c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,7 +33,7 @@ This plan is under constant review so expect it to change from time to time. Sti * Improved full-screen support, removing the temporary full-screen hacks * On-screen keyboard * Support for the Raspberry Pi 4 with OpenGL ES 2.0 and GLSL shaders (Raspberry Pi OS) -* Add GLM library dependency for matrix and vector operations, start to decommission the built-in functions +* Add GLM library dependency for matrix and vector operations, decommission the built-in functions * Add to more Linux repositories, BSD ports collections etc. * Flatpak and Snap releases on Linux @@ -90,6 +90,7 @@ But as clang-format won't change the actual code content or fix all code style c * As a general rule, use C++ syntax instead of C syntax, for example `static_cast(someFloatVariable)` instead of `(int)someFloatVariable` * Always declare one variable per line, never combine multiple declarations of the same type * Name member variables starting with an `m` such as `mMyMemberVariable` and name static variables starting with an `s` such as `sMyStaticVariable` +* Use braced initializations when possible, e.g. `float myFloat{1.5f}` as this is generally the safest way to do it * Short function definitions can be placed in either the .h or .cpp file depending on the situation * Avoid overoptimizations, especially if it sacrifices readability, makes the code hard to expand on or is error prone * Try to be coherent with the existing codebase regarding names, structure etc., it should not be obvious what person wrote which parts diff --git a/INSTALL-DEV.md b/INSTALL-DEV.md index 041fb5670..d6de8da65 100644 --- a/INSTALL-DEV.md +++ b/INSTALL-DEV.md @@ -1,4 +1,4 @@ -# EmulationStation Desktop Edition (ES-DE) - Building and advanced configuration (development version) +# EmulationStation Desktop Edition (ES-DE) v1.2 (development version) - Building and advanced configuration **Note:** This is a quite technical document intended for those that are interested in compiling ES-DE from source code, or would like to customize the configuration. If you just want to start using the software, check out [USERGUIDE-DEV.md](USERGUIDE-DEV.md) instead. diff --git a/INSTALL.md b/INSTALL.md index 59b72a6af..918b62cad 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,4 +1,4 @@ -# EmulationStation Desktop Edition (ES-DE) - Building and advanced configuration +# EmulationStation Desktop Edition (ES-DE) v1.1 - Building and advanced configuration **Note:** This is a quite technical document intended for those that are interested in compiling ES-DE from source code, or would like to customize the configuration. If you just want to start using the software, check out [USERGUIDE.md](USERGUIDE.md) instead. diff --git a/THEMES-DEV.md b/THEMES-DEV.md new file mode 100644 index 000000000..79af9725c --- /dev/null +++ b/THEMES-DEV.md @@ -0,0 +1,956 @@ +# EmulationStation Desktop Edition (ES-DE) v1.2 (development version) - Themes + +**Note:** If creating theme sets specifically for ES-DE, please add `-DE` to the theme name, as in `rbsimple-DE`. Because the ES-DE theme support has already deviated somehow from the RetroPie EmulationStation fork and will continue to deviate further in the future, the theme set will likely not be backwards compatible. It would be confusing and annoying for a user that downloads and attempts to use an ES-DE theme set in another EmulationStation fork only to get crashes, error messages or corrupted graphics. At least the -DE extension is a visual indicator that it's an ES-DE specific theme set. + +Also note that this document is only relevant for the current ES-DE development version, if you would like to see the documentation for the latest stable release, refer to [THEMES.md](THEMES.md) instead. + +ES-DE allows each system to have its own "theme." A theme is a collection **views** that define some **elements**, each with their own **properties**. + +The first place ES-DE will check for a theme is in the system's `` folder, for a theme.xml file: +* `[SYSTEM_PATH]/theme.xml` + +If that file doesn't exist, ES-DE will try to find the theme in the current **theme set**. Theme sets are just a collection of individual system themes arranged in the "themes" folder under some name. A theme set can provide a default theme that will be used if there is no matching system theme. Here's an example: + +``` +... + themes/ + my_theme_set/ + snes/ + theme.xml + my_cool_background.jpg + + nes/ + theme.xml + my_other_super_cool_background.jpg + + common_resources/ + my_font.ttf + + theme.xml (Default theme) + another_theme_set/ + snes/ + theme.xml + some_resource.svg +``` + +The theme set system makes it easy for users to try different themes and allows distributions to include multiple theme options. Users can change the currently active theme set in the "UI Settings" menu. The option is only visible if at least one theme set exists. + +There are two places ES-DE can load theme sets from: +* `[HOME]/.emulationstation/themes/[CURRENT_THEME_SET]/[SYSTEM_THEME]/theme.xml` +* `[INSTALLATION PATH]/themes/[CURRENT_THEME_SET]/[SYSTEM_THEME]/theme.xml` + +An example installation path would be: \ +`/usr/share/emulationstation/themes/[CURRENT_THEME_SET]/[SYSTEM_THEME]/theme.xml` + +`[SYSTEM_THEME]` is the `` tag for the system, as defined in `es_systems.cfg`. If the `` tag is not set, ES-DE will use the system's ``. + +If both files happen to exist, ES-DE will pick the first one (the one located in the home directory). + +Again, the `[CURRENT_THEME_SET]` value is set in the "UI Settings" menu. If it has not been set yet or the previously selected theme set is missing, the first available theme set will be used as the default. + +# Simple Example + +Here is a very simple theme that changes the description text's color: + +```xml + + + 7 + + + 00FF00 + + + 0.5 0.5 + 0.5 0.5 + 0.8 0.8 + ./my_art/my_awesome_image.jpg + + + +``` + +# How it works + +Everything must be inside a `` tag. + +**The `` tag *must* be specified**. This is the version of the theming system the theme was designed for. +The current version is 7. + +A *view* can be thought of as a particular "screen" within EmulationStation. Views are defined like this: + +```xml + + ... define elements here ... + +``` + + + +An *element* is a particular visual element, such as an image or a piece of text. You can either modify an element that already exists for a particular view (as is done in the "description" example), like this: + +```xml + + ... define properties here ... + +``` + +Or, you can create your own elements by adding `extra="true"` (as is done in the "my_image" example) like this: + +```xml + + ... define properties here ... + +``` + +"Extra" elements will be drawn in the order they are defined (so define backgrounds first!). When they get drawn relative to the pre-existing elements depends on the view. Make sure "extra" element names do not clash with existing element names! An easy way to protect against this is to just start all your extra element names with some prefix like "e_". + + + +*Properties* control how a particular *element* looks - for example, its position, size, image path, etc. The type of the property determines what kinds of values you can use. You can read about the types below in the "Reference" section. Properties are defined like this: + +```xml + ValueHere +``` + + +# Advanced Features + +It is recommended that if you are writing a theme you launch EmulationStation with the `--debug` and `--windowed` switches. This way you can read error messages without having to check the log file. You can also reload the current gamelist view and system view with `Ctrl-R` if `--debug` is specified. + +### The `` tag + +You can include theme files within theme files, similar to `#include` in C (though the internal mechanism is different, the effect is the same). Example: + +`~/.emulationstation/all_themes.xml`: +```xml + + + 7 + + + ./all_themes/myfont.ttf + 00FF00 + + + +``` + +`~/.emulationstation/snes/theme.xml`: +```xml + + + 7 + ./../all_themes.xml + + + FF0000 + + + +``` + +Is equivalent to this `snes/theme.xml`: +```xml + + + 7 + + + ./all_themes/myfont.ttf + FF0000 + + + +``` + +Notice that properties that were not specified got merged (``) and the `snes/theme.xml` could overwrite the included files' values (``). Also notice the included file still needed the `` tag. + + +### Theming multiple views simultaneously + +Sometimes you want to apply the same properties to the same elements across multiple views. The `name` attribute actually works as a list (delimited by any characters of `\t\r\n ,` - that is, whitespace and commas). So, for example, to easily apply the same header to the basic, grid, and system views: + +```xml + + + 7 + + + ./snes_art/snes_header.png + + + + + ./snes_art/snes_header_detailed.png + + + +``` + +This is equivalent to: +```xml + + + 7 + + + ./snes_art/snes_header.png + + + + + ./snes_art/snes_header_detailed.png + + + + + ./snes_art/snes_header.png + + + + + ./snes_art/snes_header.png + + + ... and any other view that might try to look up "logo" ... + +``` + + +### Theming multiple elements simultaneously + +You can theme multiple elements *of the same type* simultaneously. The `name` attribute actually works as a list (delimited by any characters of `\t\r\n ,` - that is, whitespace and commas), just like it does for views, as long as the elements have the same type. This is useful if you want to, say, apply the same color to all the metadata labels: + +```xml + + + 7 + + + + 48474D + + + +``` + +Which is equivalent to: +```xml + + + 7 + + + 48474D + + + 48474D + + + 48474D + + + 48474D + + + 48474D + + + 48474D + + + 48474D + + + 48474D + + + +``` + +Just remember, *this only works if the elements have the same type!* + +### Element rendering order with z-index + +You can now change the order in which elements are rendered by setting `zIndex` values. Default values correspond to the default rendering order while allowing elements to easily be shifted without having to set `zIndex` values for every element. Elements will be rendered in order from smallest z-index to largest. + + +#### Navigation sounds + +The navigation sounds are configured globally per theme set, so it needs to be defined as a feature and with the view set to the special 'all' category. +It's recommended to put these elements in a separate file and include it from the main theme file (e.g. `./navigationsounds.xml`). +There are seven different navigation sounds that can be configured. The names as well as the element structure should be self-explanatory based +on the example below. +Starting EmulationStation with the --debug flag will provide feedback on whether any navigation sound elements were read from the theme set. If no navigation sound is provided by the theme, ES-DE will use the bundled navigation sound file as a fallback. This is done per sound, so the theme could provide for example one or two custom sound files while using the bundled ES-DE sounds for the other samples. + +Example debug output: +``` +Jul 12 11:28:58 Debug: NavigationSounds::loadThemeNavigationSounds(): Theme set includes navigation sound support, loading custom sounds +Jul 12 11:28:58 Debug: Sound::getFromTheme(): Looking for tag +Jul 12 11:28:58 Debug: Sound::getFromTheme(): Tag found, ready to load theme sound file +Jul 12 11:28:58 Debug: Sound::getFromTheme(): Looking for tag +Jul 12 11:28:58 Debug: Sound::getFromTheme(): Tag not found, using fallback sound file +``` + +Example `navigationsounds.xml`, to be included from the main theme file: + +```xml + + + 7 + + + + ./core/sounds/systembrowse.wav + + + ./core/sounds/quicksysselect.wav + + + ./core/sounds/select.wav + + + ./core/sounds/back.wav + + + ./core/sounds/scroll.wav + + + ./core/sounds/favorite.wav + + + ./core/sounds/launch.wav + + + + +``` + +#### Defaults + +##### system +* Extra Elements `extra="true"` - 10 +* `carousel name="systemcarousel"` - 40 +* `text name="systemInfo"` - 50 + +##### basic, detailed, grid, video +* `image name="background"` - 0 +* Extra Elements `extra="true"` - 10 +* `textlist name="gamelist"` - 20 +* `imagegrid name="gamegrid"` - 20 +* Media + * `image name="md_image"` - 30 + * `video name="md_video"` - 30 + * `image name="md_marquee"` - 35 +* Metadata - 40 + * Labels + * `text name="md_lbl_rating"` + * `text name="md_lbl_releasedate"` + * `text name="md_lbl_developer"` + * `text name="md_lbl_publisher"` + * `text name="md_lbl_genre"` + * `text name="md_lbl_players"` + * `text name="md_lbl_lastplayed"` + * `text name="md_lbl_playcount"` + * Values + * `rating name="md_rating"` + * `datetime name="md_releasedate"` + * `text name="md_developer"` + * `text name="md_publisher"` + * `text name="md_genre"` + * `text name="md_players"` + * `datetime name="md_lastplayed"` + * `text name="md_playcount"` + * `text name="md_description"` + * `text name="md_name"` +* System Logo/Text - 50 + * `text name="logoText"` + * `image name="logo"` +* Gamelist information - 50 + * `text name="gamelistInfo"` + +### Theme variables + +Theme variables can be used to simplify theme construction. There are 2 types of variables available. +* System Variables +* Theme Defined Variables + +#### System Variables + +System variables are system specific and are derived from the values in es_systems.cfg. +* `system.name` +* `system.fullName` +* `system.theme` + +#### Theme Defined Variables +Variables can also be defined in the theme. +``` + + 8b0000 + +``` + +#### Usage in themes +Variables can be used to specify the value of a theme property: +``` +${themeColor} +``` + +or to specify only a portion of the value of a theme property: + +``` +${themeColor}c0 +./art/logo/${system.theme}.svg +```` + + +# Reference + +## Views, their elements, and themeable properties: + +#### basic +* `helpsystem name="help"` - ALL + - The help system style for this view. +* `image name="background"` - ALL + - This is a background image that exists for convenience. It goes from (0, 0) to (1, 1). +* `text name="logoText"` - ALL + - Displays the name of the system. Only present if no "logo" image is specified. Displayed at the top of the screen, centered by default. +* `image name="logo"` - ALL + - A header image. If a non-empty `path` is specified, `text name="logoText"` will be hidden and this image will be, by default, displayed roughly in its place. +* `textlist name="gamelist"` - ALL + - The gamelist. `primaryColor` is for games, `secondaryColor` is for folders. Centered by default. + +--- + +#### detailed +* `helpsystem name="help"` - ALL + - The help system style for this view. +* `image name="background"` - ALL + - This is a background image that exists for convenience. It goes from (0, 0) to (1, 1). +* `text name="logoText"` - ALL + - Displays the name of the system. Only present if no "logo" image is specified. Displayed at the top of the screen, centered by default. +* `image name="logo"` - ALL + - A header image. If a non-empty `path` is specified, `text name="logoText"` will be hidden and this image will be, by default, displayed roughly in its place. +* `textlist name="gamelist"` - ALL + - The gamelist. `primaryColor` is for games, `secondaryColor` is for folders. Left aligned by default. +* `text name="gamelistInfo"` - ALL + - Displays the game count (all games as well as favorites), any applied filters, and a folder icon if a folder has been entered. If this text is left aligned, the folder icon will be placed to the right of the other information, and if it's right aligned, the folder icon will be placed to the left. Left aligned by default. + +* Metadata + * Labels + * `text name="md_lbl_rating"` - ALL + * `text name="md_lbl_releasedate"` - ALL + * `text name="md_lbl_developer"` - ALL + * `text name="md_lbl_publisher"` - ALL + * `text name="md_lbl_genre"` - ALL + * `text name="md_lbl_players"` - ALL + * `text name="md_lbl_lastplayed"` - ALL + * `text name="md_lbl_playcount"` - ALL + + * Values + * All values will follow to the right of their labels if a position isn't specified. + + * `image name="md_image"` - POSITION | SIZE | Z_INDEX + - Path is the "image" metadata for the currently selected game. + * `rating name="md_rating"` - ALL + - The "rating" metadata. + * `datetime name="md_releasedate"` - ALL + - The "releasedate" metadata. + * `text name="md_developer"` - ALL + - The "developer" metadata. + * `text name="md_publisher"` - ALL + - The "publisher" metadata. + * `text name="md_genre"` - ALL + - The "genre" metadata. + * `text name="md_players"` - ALL + - The "players" metadata (number of players the game supports). + * `datetime name="md_lastplayed"` - ALL + - The "lastplayed" metadata. Displayed as a string representing the time relative to "now" (e.g. "3 hours ago"). + * `text name="md_playcount"` - ALL + - The "playcount" metadata (number of times the game has been played). + * `text name="md_description"` - POSITION | SIZE | FONT_PATH | FONT_SIZE | COLOR | Z_INDEX + - Text is the "desc" metadata. If no `pos`/`size` is specified, will move and resize to fit under the lowest label and reach to the bottom of the screen. + * `text name="md_name"` - ALL + - The "name" metadata (the game name). Unlike the others metadata fields, the name is positioned offscreen by default + +#### video +* `helpsystem name="help"` - ALL + - The help system style for this view. +* `image name="background"` - ALL + - This is a background image that exists for convenience. It goes from (0, 0) to (1, 1). +* `text name="logoText"` - ALL + - Displays the name of the system. Only present if no "logo" image is specified. Displayed at the top of the screen, centered by default. +* `image name="logo"` - ALL + - A header image. If a non-empty `path` is specified, `text name="logoText"` will be hidden and this image will be, by default, displayed roughly in its place. +* `textlist name="gamelist"` - ALL + - The gamelist. `primaryColor` is for games, `secondaryColor` is for folders. Left aligned by default. +* `text name="gamelistInfo"` - ALL + - Displays the game count (all games as well as favorites), any applied filters, and a folder icon if a folder has been entered. If this text is left aligned, the folder icon will be placed to the right of the other information, and if it's right aligned, the folder icon will be placed to the left. Left aligned by default. + +* Metadata + * Labels + * `text name="md_lbl_rating"` - ALL + * `text name="md_lbl_releasedate"` - ALL + * `text name="md_lbl_developer"` - ALL + * `text name="md_lbl_publisher"` - ALL + * `text name="md_lbl_genre"` - ALL + * `text name="md_lbl_players"` - ALL + * `text name="md_lbl_lastplayed"` - ALL + * `text name="md_lbl_playcount"` - ALL + + * Values + * All values will follow to the right of their labels if a position isn't specified. + + * `image name="md_image"` - POSITION | SIZE | Z_INDEX + - Path is the "image" metadata for the currently selected game. + * `image name="md_marquee"` - POSITION | SIZE | Z_INDEX + - Path is the "marquee" metadata for the currently selected game. + * `video name="md_video"` - POSITION | SIZE | Z_INDEX + - Path is the "video" metadata for the currently selected game. + * `rating name="md_rating"` - ALL + - The "rating" metadata. + * `datetime name="md_releasedate"` - ALL + - The "releasedate" metadata. + * `text name="md_developer"` - ALL + - The "developer" metadata. + * `text name="md_publisher"` - ALL + - The "publisher" metadata. + * `text name="md_genre"` - ALL + - The "genre" metadata. + * `text name="md_players"` - ALL + - The "players" metadata (number of players the game supports). + * `datetime name="md_lastplayed"` - ALL + - The "lastplayed" metadata. Displayed as a string representing the time relative to "now" (e.g. "3 hours ago"). + * `text name="md_playcount"` - ALL + - The "playcount" metadata (number of times the game has been played). + * `text name="md_description"` - POSITION | SIZE | FONT_PATH | FONT_SIZE | COLOR | Z_INDEX + - Text is the "desc" metadata. If no `pos`/`size` is specified, will move and resize to fit under the lowest label and reach to the bottom of the screen. + * `text name="md_name"` - ALL + - The "name" metadata (the game name). Unlike the others metadata fields, the name is positioned offscreen by default + +--- + +#### grid +* `helpsystem name="help"` - ALL + - The help system style for this view. +* `image name="background"` - ALL + - This is a background image that exists for convenience. It goes from (0, 0) to (1, 1). +* `text name="logoText"` - ALL + - Displays the name of the system. Only present if no "logo" image is specified. Displayed at the top of the screen, centered by default. +* `image name="logo"` - ALL + - A header image. If a non-empty `path` is specified, `text name="logoText"` will be hidden and this image will be, by default, displayed roughly in its place. +* `imagegrid name="gamegrid"` - ALL + - The gamegrid. The number of tile displayed is controlled by its size, margin and the default tile max size. +* `gridtile name="default"` - ALL + - Note that many of the default gridtile parameters change the selected gridtile parameters if they are not explicitly set by the theme. For example, changing the background image of the default gridtile also change the background image of the selected gridtile. Refer to the gridtile documentation for more informations. +* `gridtile name="selected"` - ALL + - See default gridtile description right above. +* `text name="gamelistInfo"` - ALL + - Displays the game count (all games as well as favorites), any applied filters, and a folder icon if a folder has been entered. If this text is left aligned, the folder icon will be placed to the right of the other information, and if it's right aligned, the folder icon will be placed to the left. Left aligned by default. + +* Metadata + * Labels + * `text name="md_lbl_rating"` - ALL + * `text name="md_lbl_releasedate"` - ALL + * `text name="md_lbl_developer"` - ALL + * `text name="md_lbl_publisher"` - ALL + * `text name="md_lbl_genre"` - ALL + * `text name="md_lbl_players"` - ALL + * `text name="md_lbl_lastplayed"` - ALL + * `text name="md_lbl_playcount"` - ALL + + * Values + * All values will follow to the right of their labels if a position isn't specified. + + * `rating name="md_rating"` - ALL + - The "rating" metadata. + * `datetime name="md_releasedate"` - ALL + - The "releasedate" metadata. + * `text name="md_developer"` - ALL + - The "developer" metadata. + * `text name="md_publisher"` - ALL + - The "publisher" metadata. + * `text name="md_genre"` - ALL + - The "genre" metadata. + * `text name="md_players"` - ALL + - The "players" metadata (number of players the game supports). + * `datetime name="md_lastplayed"` - ALL + - The "lastplayed" metadata. Displayed as a string representing the time relative to "now" (e.g. "3 hours ago"). + * `text name="md_playcount"` - ALL + - The "playcount" metadata (number of times the game has been played). + * `text name="md_description"` - POSITION | SIZE | FONT_PATH | FONT_SIZE | COLOR | Z_INDEX + - Text is the "desc" metadata. If no `pos`/`size` is specified, will move and resize to fit under the lowest label and reach to the bottom of the screen. + * `text name="md_name"` - ALL + - The "name" metadata (the game name). Unlike the others metadata fields, the name is positioned offscreen by default + +--- + +#### system +* `helpsystem name="help"` - ALL + - The help system style for this view. +* `carousel name="systemcarousel"` -ALL + - The system logo carousel +* `image name="logo"` - PATH | COLOR + - A logo image, to be displayed in the system logo carousel. +* `text name="logoText"` - FONT_PATH | COLOR | FORCE_UPPERCASE | LINE_SPACING | TEXT + - A logo text, to be displayed system name in the system logo carousel when no logo is available. +* `text name="systemInfo"` - ALL + - Displays details of the system currently selected in the carousel. +* You can use extra elements (elements with `extra="true"`) to add your own backgrounds, etc. They will be displayed behind the carousel, and scroll relative to the carousel. + + +## Types of properties: + +* NORMALIZED_PAIR - two decimals, in the range [0..1], delimited by a space. For example, `0.25 0.5`. Most commonly used for position (x and y coordinates) and size (width and height). +* NORMALIZED_RECT - four decimals, in the range [0..1], delimited by a space. For example, `0.25 0.5 0.10 0.30`. Most commonly used for padding to store top, left, bottom and right coordinates. +* PATH - a path. If the first character is a `~`, it will be expanded into the environment variable for the home path (`$HOME` for Linux or `%HOMEPATH%` for Windows) unless overridden using the --home command line option. If the first character is a `.`, it will be expanded to the theme file's directory, allowing you to specify resources relative to the theme file, like so: `./../general_art/myfont.ttf`. +* BOOLEAN - `true`/`1` or `false`/`0`. +* COLOR - a hexidecimal RGB or RGBA color (6 or 8 digits). If 6 digits, will assume the alpha channel is `FF` (not transparent). +* FLOAT - a decimal. +* STRING - a string of text. + + +## Types of elements and their properties: + +Common to almost all elements is a `pos` and `size` property of the NORMALIZED_PAIR type. They are normalized in terms of their "parent" object's size; 99% of the time, this is just the size of the screen. In this case, `0 0` would correspond to the top left corner, and `1 1` the bottom right corner (a positive Y value points further down). `pos` almost always refers to the top left corner of your element. You *can* use numbers outside of the [0..1] range if you want to place an element partially or completely off-screen. + +The order you define properties in does not matter. +Remember, you do *not* need to specify every property! +*Note that a view may choose to only make only certain properties on a particular element themeable!* + +#### image + +Can be created as an extra. + +* `pos` - type: NORMALIZED_PAIR. +* `size` - type: NORMALIZED_PAIR. + - If only one axis is specified (and the other is zero), the other will be automatically calculated in accordance with the image's aspect ratio. +* `maxSize` - type: NORMALIZED_PAIR. + - The image will be resized as large as possible so that it fits within this size and maintains its aspect ratio. Use this instead of `size` when you don't know what kind of image you're using so it doesn't get grossly oversized on one axis (e.g. with a game's image metadata). +* `origin` - type: NORMALIZED_PAIR. + - Where on the image `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the image exactly in the middle of the screen. If the "POSITION" and "SIZE" attributes are themeable, "ORIGIN" is implied. +* `rotation` - type: FLOAT. + - angle in degrees that the image should be rotated. Positive values will rotate clockwise, negative values will rotate counterclockwise. +* `rotationOrigin` - type: NORMALIZED_PAIR. + - Point around which the image will be rotated. Defaults to `0.5 0.5`. +* `path` - type: PATH. + - Path to the image file. Most common extensions are supported (including .jpg, .png, and unanimated .gif). +* `default` - type: PATH. + - Path to default image file. Default image will be displayed when selected game does not have an image. +* `tile` - type: BOOLEAN. + - If true, the image will be tiled instead of stretched to fit its size. Useful for backgrounds. +* `color` - type: COLOR. + - Multiply each pixel's color by this color. For example, an all-white image with `FF0000` would become completely red. You can also control the transparency of an image with `FFFFFFAA` - keeping all the pixels their normal color and only affecting the alpha channel. +* `visible` - type: BOOLEAN. + - If true, component will be rendered, otherwise rendering will be skipped. Can be used to hide elements from a particular view. +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. + +#### imagegrid + +* `pos` - type: NORMALIZED_PAIR. +* `size` - type: NORMALIZED_PAIR. + - The size of the grid. Take care the selected tile can go out of the grid size, so don't position the grid too close to another element or the screen border. +* `margin` - type: NORMALIZED_PAIR. Margin between tiles. +* `padding` - type: NORMALIZED_RECT. + - NEW : Padding for displaying tiles. +* `autoLayout` - type: NORMALIZED_PAIR. + - NEW : Number of column and rows in the grid (integer values). +* `autoLayoutSelectedZoom` - type: FLOAT. + - NEW : Zoom factor to apply when a tile is selected. +* `gameImage` - type: PATH. + - The default image used for games which doesn't have an image. +* `folderImage` - type: PATH. + - The default image used for folders which doesn't have an image. +* `imageSource` - type: STRING. + - Selects the image to display. `thumbnail` by default, can also be set to `image`, `miximage`, `screenshot`, `cover`, `marquee` or `3dbox`. If selecting `image`, the media type `miximage` will be tried first, with fallback to `screenshot` and then `cover`. +* `scrollDirection` - type: STRING. + - `vertical` by default, can also be set to `horizontal`. Not that in `horizontal` mod, the tiles are ordered from top to bottom, then from left to right. +* `centerSelection` - type: BOOLEAN. + - `false` by default, when `true` the selected tile will be locked to the center of the grid. +* `scrollLoop` - type: BOOLEAN. + - `false` by default, when `true` the grid will seamlessly loop around when scrolling reaches the end of the list. Only works when `centerSelection` is `true`. +* `animate` - type : BOOLEAN. + - `true` by default, when `false` the grid scrolling will not be animated. +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. + +#### gridtile + +* `size` - type: NORMALIZED_PAIR. + - The size of the default gridtile is used to calculate how many tiles can fit in the imagegrid. If not explicitly set, the size of the selected gridtile is equal the size of the default gridtile * 1.2 +* `padding` - type: NORMALIZED_PAIR. + - The padding around the gridtile content. Default `16 16`. If not explicitly set, the selected tile padding will be equal to the default tile padding. +* `imageColor` - type: COLOR. + - The default tile image color and selected tile image color have no influence on each others. +* `backgroundImage` - type: PATH. + - If not explicitly set, the selected tile background image will be the same as the default tile background image. +* `backgroundCornerSize` - type: NORMALIZED_PAIR. + - The corner size of the ninepatch used for the tile background. Default is `16 16`. +* `backgroundColor` - type: COLOR. + - A shortcut to define both the center color and edge color at the same time. The default tile background color and selected tile background color have no influence on each others. +* `backgroundCenterColor` - type: COLOR. + - Set the color of the center part of the ninepatch. The default tile background center color and selected tile background center color have no influence on each others. +* `backgroundEdgeColor` - type: COLOR. + - Set the color of the edge parts of the ninepatch. The default tile background edge color and selected tile background edge color have no influence on each others. + +#### video + +* `pos` - type: NORMALIZED_PAIR. +* `size` - type: NORMALIZED_PAIR. + - If only one axis is specified (and the other is zero), the other will be automatically calculated in accordance with the video's aspect ratio. +* `maxSize` - type: NORMALIZED_PAIR. + - The video will be resized as large as possible so that it fits within this size and maintains its aspect ratio. Use this instead of `size` when you don't know what kind of video you're using so it doesn't get grossly oversized on one axis (e.g. with a game's video metadata). +* `origin` - type: NORMALIZED_PAIR. + - Where on the image `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the image exactly in the middle of the screen. If the "POSITION" and "SIZE" attributes are themeable, "ORIGIN" is implied. +* `rotation` - type: FLOAT. + - angle in degrees that the text should be rotated. Positive values will rotate clockwise, negative values will rotate counterclockwise. +* `rotationOrigin` - type: NORMALIZED_PAIR. + - Point around which the text will be rotated. Defaults to `0.5 0.5`. +* `delay` - type: FLOAT. Default is false. + - Delay in seconds before video will start playing. +* `default` - type: PATH. + - Path to default video file. Default video will be played when selected game does not have a video. +* `showSnapshotNoVideo` - type: BOOLEAN + - If true, image will be shown when selected game does not have a video and no `default` video is configured. +* `showSnapshotDelay` - type: BOOLEAN + - If true, playing of video will be delayed for `delayed` seconds, when game is selected. +* `visible` - type: BOOLEAN. + - If true, component will be rendered, otherwise rendering will be skipped. Can be used to hide elements from a particular view. +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. + +#### text + +Can be created as an extra. + +* `pos` - type: NORMALIZED_PAIR. +* `size` - type: NORMALIZED_PAIR. + - Possible combinations: + - `0 0` - automatically size so text fits on one line (expanding horizontally). + - `w 0` - automatically wrap text so it doesn't go beyond `w` (expanding vertically). + - `w h` - works like a "text box." If `h` is non-zero and `h` <= `fontSize` (implying it should be a single line of text), text that goes beyond `w` will be truncated with an elipses (...). +* `origin` - type: NORMALIZED_PAIR. + - Where on the component `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the component exactly in the middle of the screen. If the "POSITION" and "SIZE" attributes are themeable, "ORIGIN" is implied. +* `rotation` - type: FLOAT. + - angle in degrees that the text should be rotated. Positive values will rotate clockwise, negative values will rotate counterclockwise. +* `rotationOrigin` - type: NORMALIZED_PAIR. + - Point around which the text will be rotated. Defaults to `0.5 0.5`. +* `text` - type: STRING. +* `color` - type: COLOR. +* `backgroundColor` - type: COLOR; +* `fontPath` - type: PATH. + - Path to a truetype font (.ttf). +* `fontSize` - type: FLOAT. + - Size of the font as a percentage of screen height (e.g. for a value of `0.1`, the text's height would be 10% of the screen height). +* `alignment` - type: STRING. + - Valid values are "left", "center", or "right". Controls alignment on the X axis. "center" will also align vertically. +* `forceUppercase` - type: BOOLEAN. Draw text in uppercase. +* `lineSpacing` - type: FLOAT. Controls the space between lines (as a multiple of font height). Default is 1.5. +* `visible` - type: BOOLEAN. + - If true, component will be rendered, otherwise rendering will be skipped. Can be used to hide elements from a particular view. +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. + +#### textlist + +* `pos` - type: NORMALIZED_PAIR. +* `size` - type: NORMALIZED_PAIR. +* `origin` - type: NORMALIZED_PAIR. + - Where on the component `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the component exactly in the middle of the screen. If the "POSITION" and "SIZE" attributes are themeable, "ORIGIN" is implied. +* `selectorColor` - type: COLOR. + - Color of the "selector bar." +* `selectorImagePath` - type: PATH. + - Path to image to render in place of "selector bar." +* `selectorImageTile` - type: BOOLEAN. + - If true, the selector image will be tiled instead of stretched to fit its size. +* `selectorHeight` - type: FLOAT. + - Height of the "selector bar". +* `selectorOffsetY` - type: FLOAT. + - Allows moving of the "selector bar" up or down from its computed position. Useful for fine tuning the position of the "selector bar" relative to the text. +* `selectedColor` - type: COLOR. + - Color of the highlighted entry text. +* `primaryColor` - type: COLOR. + - Primary color; what this means depends on the text list. For example, for game lists, it is the color of a game. +* `secondaryColor` - type: COLOR. + - Secondary color; what this means depends on the text list. For example, for game lists, it is the color of a folder. +* `fontPath` - type: PATH. +* `fontSize` - type: FLOAT. +* `alignment` - type: STRING. + - Valid values are "left", "center", or "right". Controls alignment on the X axis. +* `horizontalMargin` - type: FLOAT. + - Horizontal offset for text from the alignment point. If `alignment` is "left", offsets the text to the right. If `alignment` is "right", offsets text to the left. No effect if `alignment` is "center". Given as a percentage of the element's parent's width (same unit as `size`'s X value). +* `forceUppercase` - type: BOOLEAN. Draw text in uppercase. +* `lineSpacing` - type: FLOAT. Controls the space between lines (as a multiple of font height). Default is 1.5. +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. + +#### ninepatch + +* `pos` - type: NORMALIZED_PAIR. +* `size` - type: NORMALIZED_PAIR. +* `path` - type: PATH. +* `visible` - type: BOOLEAN. + - If true, component will be rendered, otherwise rendering will be skipped. Can be used to hide elements from a particular view. +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. + +EmulationStation borrows the concept of "nine patches" from Android (or "9-Slices"). Currently the implementation is very simple and hard-coded to only use 48x48px images (16x16px for each "patch"). Check the `data/resources` directory for some examples (button.png, frame.png). + +#### rating + +* `pos` - type: NORMALIZED_PAIR. +* `size` - type: NORMALIZED_PAIR. + - Only one value is actually used. The other value should be zero. (e.g. specify width OR height, but not both. This is done to maintain the aspect ratio.) +* `origin` - type: NORMALIZED_PAIR. + - Where on the component `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the component exactly in the middle of the screen. If the "POSITION" and "SIZE" attributes are themeable, "ORIGIN" is implied. +* `rotation` - type: FLOAT. + - angle in degrees that the rating should be rotated. Positive values will rotate clockwise, negative values will rotate counterclockwise. +* `rotationOrigin` - type: NORMALIZED_PAIR. + - Point around which the rating will be rotated. Defaults to `0.5 0.5`. +* `filledPath` - type: PATH. + - Path to the "filled star" image. Image must be square (width equals height). +* `unfilledPath` - type: PATH. + - Path to the "unfilled star" image. Image must be square (width equals height). +* `color` - type: COLOR. + - Multiply each pixel's color by this color. For example, an all-white image with `FF0000` would become completely red. You can also control the transparency of an image with `FFFFFFAA` - keeping all the pixels their normal color and only affecting the alpha channel. +* `visible` - type: BOOLEAN. + - If true, component will be rendered, otherwise rendering will be skipped. Can be used to hide elements from a particular view. +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. + +#### datetime +* `pos` - type: NORMALIZED_PAIR. +* `size` - type: NORMALIZED_PAIR. + - Possible combinations: + - `0 0` - automatically size so text fits on one line (expanding horizontally). + - `w 0` - automatically wrap text so it doesn't go beyond `w` (expanding vertically). + - `w h` - works like a "text box." If `h` is non-zero and `h` <= `fontSize` (implying it should be a single line of text), text that goes beyond `w` will be truncated with an elipses (...). +* `origin` - type: NORMALIZED_PAIR. + - Where on the component `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the component exactly in the middle of the screen. If the "POSITION" and "SIZE" attributes are themeable, "ORIGIN" is implied. +* `rotation` - type: FLOAT. + - angle in degrees that the text should be rotated. Positive values will rotate clockwise, negative values will rotate counterclockwise. +* `rotationOrigin` - type: NORMALIZED_PAIR. + - Point around which the text will be rotated. Defaults to `0.5 0.5`. +* `color` - type: COLOR. +* `backgroundColor` - type: COLOR; +* `fontPath` - type: PATH. + - Path to a truetype font (.ttf). +* `fontSize` - type: FLOAT. + - Size of the font as a percentage of screen height (e.g. for a value of `0.1`, the text's height would be 10% of the screen height). +* `alignment` - type: STRING. + - Valid values are "left", "center", or "right". Controls alignment on the X axis. "center" will also align vertically. +* `forceUppercase` - type: BOOLEAN. Draw text in uppercase. +* `lineSpacing` - type: FLOAT. Controls the space between lines (as a multiple of font height). Default is 1.5. +* `visible` - type: BOOLEAN. + - If true, component will be rendered, otherwise rendering will be skipped. Can be used to hide elements from a particular view. +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. +* `displayRelative` - type: BOOLEAN. Renders the datetime as a a relative string (ex: 'x days ago') +* `format` - type: STRING. Specifies format for rendering datetime. + - %Y: The year, including the century (1900) + - %m: The month number [01,12] + - %d: The day of the month [01,31] + - %H: The hour (24-hour clock) [00,23] + - %M: The minute [00,59] + - %S: The second [00,59] + +#### helpsystem + +* `pos` - type: NORMALIZED_PAIR. Default is "0.012 0.9515" +* `origin` - type: NORMALIZED_PAIR. + - Where on the component `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place + the component exactly in the middle of the screen. +* `textColor` - type: COLOR. Default is 777777FF. +* `textColorDimmed` - type: COLOR. Default is 777777FF. +* `iconColor` - type: COLOR. Default is 777777FF. +* `iconColorDimmed` - type: COLOR. Default is 777777FF. +* `fontPath` - type: PATH. +* `fontSize` - type: FLOAT. +* `entrySpacing` - type: FLOAT. Default is 16.0. + - Spacing in pixels between the help system components. +* `iconTextSpacing` - type: FLOAT. Default is 8.0. + - Spacing in pixels within a help system component between it's icon and text. +* `textStyle` - type: STRING. Default is `uppercase`. + - The style of the text. Options: `uppercase`, `lowercase`, `camelcase`. +* `customButtonIcon` - type: PATH. + - A button icon override. Specify the button type in the attribute `button`. The available buttons are: + `dpad_updown`, + `dpad_leftright`, + `dpad_all`, + `thumbstick_click`, + `button_l`, + `button_r`, + `button_lr`, + `button_a_SNES`, + `button_b_SNES`, + `button_x_SNES`, + `button_y_SNES`, + `button_back_SNES`, + `button_start_SNES`, + `button_a_PS`, + `button_b_PS`, + `button_x_PS`, + `button_y_PS`, + `button_back_PS4`, + `button_start_PS4`, + `button_back_PS5`, + `button_start_PS5`, + `button_a_XBOX`, + `button_b_XBOX`, + `button_x_XBOX`, + `button_y_XBOX`, + `button_back_XBOX`, + `button_start_XBOX`, + `button_back_XBOX360`, + `button_start_XBOX360`. + +#### carousel + +* `type` - type: STRING. + - Sets the scoll direction of the carousel. + - Accepted values are "horizontal", "vertical", "horizontal_wheel" or "vertical_wheel". + - Default is "horizontal". +* `size` - type: NORMALIZED_PAIR. Default is "1 0.2325" +* `pos` - type: NORMALIZED_PAIR. Default is "0 0.38375". +* `origin` - type: NORMALIZED_PAIR. + - Where on the carousel `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the carousel exactly in the middle of the screen. If the "POSITION" and "SIZE" attributes are themeable, "ORIGIN" is implied. +* `color` - type: COLOR. + - Controls the color of the carousel background. + - Default is FFFFFFD8 +* `logoSize` - type: NORMALIZED_PAIR. Default is "0.25 0.155" +* `logoScale` - type: FLOAT. + - Selected logo is increased in size by this scale + - Default is 1.2 +* `logoRotation` - type: FLOAT. + - Angle in degrees that the logos should be rotated. Value should be positive. + - Default is 7.5 + - This property only applies when `type` is "horizontal_wheel" or "vertical_wheel". +* `logoRotationOrigin` - type: NORMALIZED_PAIR. + - Point around which the logos will be rotated. Defaults to `-5 0.5`. + - This property only applies when `type` is "horizontal_wheel" or "vertical_wheel". +* `logoAlignment` - type: STRING. + - Sets the alignment of the logos relative to the carousel. + - Accepted values are "top", "bottom" or "center" when `type` is "horizontal" or "horizontal_wheel". + - Accepted values are "left", "right" or "center" when `type` is "vertical" or "vertical_wheel". + - Default is "center" +* `maxLogoCount` - type: FLOAT. + - Sets the number of logos to display in the carousel. + - Default is 3 +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. + +The help system is a special element that displays a context-sensitive list of actions the user can take at any time. You should try and keep the position constant throughout every screen. Keep in mind the "default" settings (including position) are used whenever the user opens a menu. + + +To see some examples of EmulationStation themes, the following resources are recommended: + +https://aloshi.com/emulationstation#themes + +https://github.com/RetroPie + +https://gitlab.com/recalbox/recalbox-themes + +https://wiki.batocera.org/themes diff --git a/THEMES.md b/THEMES.md index cc2fc3888..32d86757b 100644 --- a/THEMES.md +++ b/THEMES.md @@ -1,4 +1,4 @@ -# EmulationStation Desktop Edition (ES-DE) - Themes +# EmulationStation Desktop Edition (ES-DE) v1.1 - Themes **Note:** If creating theme sets specifically for ES-DE, please add `-DE` to the theme name, as in `rbsimple-DE`. Because the ES-DE theme support has already deviated somehow from the RetroPie EmulationStation fork and will continue to deviate further in the future, the theme set will likely not be backwards compatible. It would be confusing and annoying for a user that downloads and attempts to use an ES-DE theme set in another EmulationStation fork only to get crashes, error messages or corrupted graphics. At least the -DE extension is a visual indicator that it's an ES-DE specific theme set. @@ -71,20 +71,18 @@ Here is a very simple theme that changes the description text's color: Everything must be inside a `` tag. -**The `` tag *must* be specified**. This is the version of the theming system the theme was designed for. The current version is 6. +**The `` tag *must* be specified**. This is the version of the theming system the theme was designed for. +The current version is 6. - - -A *view* can be thought of as a particular "screen" within EmulationStation. Views are defined like this: +A *view* can be thought of as a particular "screen" within EmulationStation. Views are defined like this: ```xml + ... define elements here ... ``` - - An *element* is a particular visual element, such as an image or a piece of text. You can either modify an element that already exists for a particular view (as is done in the "description" example), like this: ```xml @@ -122,6 +120,7 @@ You can include theme files within theme files, similar to `#include` in C (thou `~/.emulationstation/all_themes.xml`: ```xml + 6 @@ -135,6 +134,7 @@ You can include theme files within theme files, similar to `#include` in C (thou `~/.emulationstation/snes/theme.xml`: ```xml + 6 ./../all_themes.xml @@ -148,6 +148,7 @@ You can include theme files within theme files, similar to `#include` in C (thou Is equivalent to this `snes/theme.xml`: ```xml + 6 @@ -167,6 +168,7 @@ Notice that properties that were not specified got merged (``) and the Sometimes you want to apply the same properties to the same elements across multiple views. The `name` attribute actually works as a list (delimited by any characters of `\t\r\n ,` - that is, whitespace and commas). So, for example, to easily apply the same header to the basic, grid, and system views: ```xml + 6 @@ -184,6 +186,7 @@ Sometimes you want to apply the same properties to the same elements across mult This is equivalent to: ```xml + 6 @@ -216,6 +219,7 @@ This is equivalent to: You can theme multiple elements *of the same type* simultaneously. The `name` attribute actually works as a list (delimited by any characters of `\t\r\n ,` - that is, whitespace and commas), just like it does for views, as long as the elements have the same type. This is useful if you want to, say, apply the same color to all the metadata labels: ```xml + 6 @@ -230,6 +234,7 @@ You can theme multiple elements *of the same type* simultaneously. The `name` a Which is equivalent to: ```xml + 6 @@ -288,6 +293,7 @@ Jul 12 11:28:58 Debug: Sound::getFromTheme(): Tag not found, using fallback sou Example `navigationsounds.xml`, to be included from the main theme file: ```xml + 6 @@ -849,11 +855,12 @@ EmulationStation borrows the concept of "nine patches" from Android (or "9-Slice #### helpsystem -* `pos` - type: NORMALIZED_PAIR. Default is "0.012 0.9515" +* `pos` - type: NORMALIZED_PAIR. Default is "0.012 0.9515" * `origin` - type: NORMALIZED_PAIR. - - Where on the component `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the component exactly in the middle of the screen. -* `textColor` - type: COLOR. Default is 777777FF. -* `iconColor` - type: COLOR. Default is 777777FF. + - Where on the component `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place + the component exactly in the middle of the screen. +* `textColor` - type: COLOR. Default is 777777FF. +* `iconColor` - type: COLOR. Default is 777777FF. * `fontPath` - type: PATH. * `fontSize` - type: FLOAT. diff --git a/USERGUIDE-DEV.md b/USERGUIDE-DEV.md index ea57304fd..a59b65160 100644 --- a/USERGUIDE-DEV.md +++ b/USERGUIDE-DEV.md @@ -1,4 +1,4 @@ -# EmulationStation Desktop Edition (ES-DE) - User guide (development version) +# EmulationStation Desktop Edition (ES-DE) v1.2 (development version) - User guide This document is intended as a quick start guide and as a reference for the application settings and general functionality. For details on how to build ES-DE from source code and to perform more advanced configuration, please refer to [INSTALL-DEV.md](INSTALL-DEV.md). @@ -26,6 +26,7 @@ For additional details, read on below. There are also installation videos available at the ES-DE YouTube channel:\ [https://www.youtube.com/channel/UCosLuC9yIMQPKFBJXgDpvVQ](https://www.youtube.com/channel/UCosLuC9yIMQPKFBJXgDpvVQ) + ## Installation and first startup To install ES-DE, just download the package or installer from [https://es-de.org](https://es-de.org) and follow the brief instructions below. @@ -78,7 +79,7 @@ On Unix this means /home/\/.emulationstation/, on macOS /Users/\/.emulationstation/, on macOS /Users/\mStartPath = ""; std::vector exts; mCollectionEnvData->mSearchExtensions = exts; - mCollectionEnvData->mLaunchCommand = ""; + std::vector> commands; + mCollectionEnvData->mLaunchCommands = commands; std::vector allPlatformIds; allPlatformIds.push_back(PlatformIds::PLATFORM_IGNORE); mCollectionEnvData->mPlatformIds = allPlatformIds; @@ -791,7 +792,7 @@ FileData* CollectionSystemsManager::updateCollectionFolderMetadata(SystemData* s if (gameCount > 1) { std::random_device randDev; // Mersenne Twister pseudorandom number generator. - std::mt19937 engine { randDev() }; + std::mt19937 engine{randDev()}; unsigned int target; for (unsigned int i = 0; i < 3; i++) { diff --git a/es-app/src/FileData.cpp b/es-app/src/FileData.cpp index 834cbaae3..b0e16298f 100644 --- a/es-app/src/FileData.cpp +++ b/es-app/src/FileData.cpp @@ -212,7 +212,7 @@ const std::string FileData::getMediaDirectory() const std::string FileData::getMediafilePath(std::string subdirectory, std::string mediatype) const { - const std::vector extList = { ".png", ".jpg" }; + const std::vector extList = {".png", ".jpg"}; std::string subFolders; // Extract possible subfolders from the path. @@ -287,7 +287,7 @@ const std::string FileData::getThumbnailPath() const const std::string FileData::getVideoPath() const { - const std::vector extList = { ".avi", ".mkv", ".mov", ".mp4", ".wmv" }; + const std::vector extList = {".avi", ".mkv", ".mov", ".mp4", ".wmv"}; std::string subFolders; // Extract possible subfolders from the path. @@ -756,7 +756,22 @@ void FileData::launchGame(Window* window) command = metadata.get("launchcommand"); } else { - command = mEnvData->mLaunchCommand; + std::string alternativeEmulator = getSystem()->getAlternativeEmulator(); + for (auto launchCommand : mEnvData->mLaunchCommands) { + if (launchCommand.second == alternativeEmulator) { + command = launchCommand.first; + break; + } + } + if (!alternativeEmulator.empty() && command.empty()) { + LOG(LogWarning) << "The alternative emulator configured for system \"" + << getSystem()->getName() + << "\" is invalid, falling back to the default command \"" + << getSystem()->getSystemEnvData()->mLaunchCommands.front().first << "\""; + } + + if (command.empty()) + command = mEnvData->mLaunchCommands.front().first; } std::string commandRaw = command; @@ -1158,7 +1173,7 @@ std::string FileData::findEmulatorPath(std::string& command) HKEY registryKey; LSTATUS keyStatus = -1; LSTATUS pathStatus = -1; - char registryPath[1024] {}; + char registryPath[1024]{}; DWORD pathSize = 1024; // First look in HKEY_CURRENT_USER. diff --git a/es-app/src/FileFilterIndex.cpp b/es-app/src/FileFilterIndex.cpp index 0f83b7990..cb8afb7e3 100644 --- a/es-app/src/FileFilterIndex.cpp +++ b/es-app/src/FileFilterIndex.cpp @@ -11,7 +11,6 @@ #include "FileData.h" #include "Log.h" #include "Settings.h" -#include "math/Misc.h" #include "utils/StringUtil.h" #include "views/UIModeController.h" @@ -37,15 +36,15 @@ FileFilterIndex::FileFilterIndex() // clang-format off FilterDataDecl filterDecls[] = { //type //allKeys //filteredBy //filteredKeys //primaryKey //hasSecondaryKey //secondaryKey //menuLabel - { FAVORITES_FILTER, &mFavoritesIndexAllKeys, &mFilterByFavorites, &mFavoritesIndexFilteredKeys, "favorite", false, "", "FAVORITES" }, - { GENRE_FILTER, &mGenreIndexAllKeys, &mFilterByGenre, &mGenreIndexFilteredKeys, "genre", true, "genre", "GENRE" }, - { PLAYER_FILTER, &mPlayersIndexAllKeys, &mFilterByPlayers, &mPlayersIndexFilteredKeys, "players", false, "", "PLAYERS" }, - { PUBDEV_FILTER, &mPubDevIndexAllKeys, &mFilterByPubDev, &mPubDevIndexFilteredKeys, "developer", true, "publisher", "PUBLISHER / DEVELOPER" }, - { RATINGS_FILTER, &mRatingsIndexAllKeys, &mFilterByRatings, &mRatingsIndexFilteredKeys, "rating", false, "", "RATING" }, - { KIDGAME_FILTER, &mKidGameIndexAllKeys, &mFilterByKidGame, &mKidGameIndexFilteredKeys, "kidgame", false, "", "KIDGAME" }, - { COMPLETED_FILTER, &mCompletedIndexAllKeys, &mFilterByCompleted, &mCompletedIndexFilteredKeys, "completed", false, "", "COMPLETED" }, - { BROKEN_FILTER, &mBrokenIndexAllKeys, &mFilterByBroken, &mBrokenIndexFilteredKeys, "broken", false, "", "BROKEN" }, - { HIDDEN_FILTER, &mHiddenIndexAllKeys, &mFilterByHidden, &mHiddenIndexFilteredKeys, "hidden", false, "", "HIDDEN" } + {FAVORITES_FILTER, &mFavoritesIndexAllKeys, &mFilterByFavorites, &mFavoritesIndexFilteredKeys, "favorite", false, "", "FAVORITES"}, + {GENRE_FILTER, &mGenreIndexAllKeys, &mFilterByGenre, &mGenreIndexFilteredKeys, "genre", true, "genre", "GENRE"}, + {PLAYER_FILTER, &mPlayersIndexAllKeys, &mFilterByPlayers, &mPlayersIndexFilteredKeys, "players", false, "", "PLAYERS"}, + {PUBDEV_FILTER, &mPubDevIndexAllKeys, &mFilterByPubDev, &mPubDevIndexFilteredKeys, "developer", true, "publisher", "PUBLISHER / DEVELOPER"}, + {RATINGS_FILTER, &mRatingsIndexAllKeys, &mFilterByRatings, &mRatingsIndexFilteredKeys, "rating", false, "", "RATING"}, + {KIDGAME_FILTER, &mKidGameIndexAllKeys, &mFilterByKidGame, &mKidGameIndexFilteredKeys, "kidgame", false, "", "KIDGAME"}, + {COMPLETED_FILTER, &mCompletedIndexAllKeys, &mFilterByCompleted, &mCompletedIndexFilteredKeys, "completed", false, "", "COMPLETED"}, + {BROKEN_FILTER, &mBrokenIndexAllKeys, &mFilterByBroken, &mBrokenIndexFilteredKeys, "broken", false, "", "BROKEN"}, + {HIDDEN_FILTER, &mHiddenIndexAllKeys, &mFilterByHidden, &mHiddenIndexFilteredKeys, "hidden", false, "", "HIDDEN"} }; // clang-format on @@ -67,15 +66,15 @@ void FileFilterIndex::importIndex(FileFilterIndex* indexToImport) }; IndexImportStructure indexStructDecls[] = { - { &mFavoritesIndexAllKeys, &(indexToImport->mFavoritesIndexAllKeys) }, - { &mGenreIndexAllKeys, &(indexToImport->mGenreIndexAllKeys) }, - { &mPlayersIndexAllKeys, &(indexToImport->mPlayersIndexAllKeys) }, - { &mPubDevIndexAllKeys, &(indexToImport->mPubDevIndexAllKeys) }, - { &mRatingsIndexAllKeys, &(indexToImport->mRatingsIndexAllKeys) }, - { &mKidGameIndexAllKeys, &(indexToImport->mKidGameIndexAllKeys) }, - { &mCompletedIndexAllKeys, &(indexToImport->mCompletedIndexAllKeys) }, - { &mBrokenIndexAllKeys, &(indexToImport->mBrokenIndexAllKeys) }, - { &mHiddenIndexAllKeys, &(indexToImport->mHiddenIndexAllKeys) }, + {&mFavoritesIndexAllKeys, &(indexToImport->mFavoritesIndexAllKeys)}, + {&mGenreIndexAllKeys, &(indexToImport->mGenreIndexAllKeys)}, + {&mPlayersIndexAllKeys, &(indexToImport->mPlayersIndexAllKeys)}, + {&mPubDevIndexAllKeys, &(indexToImport->mPubDevIndexAllKeys)}, + {&mRatingsIndexAllKeys, &(indexToImport->mRatingsIndexAllKeys)}, + {&mKidGameIndexAllKeys, &(indexToImport->mKidGameIndexAllKeys)}, + {&mCompletedIndexAllKeys, &(indexToImport->mCompletedIndexAllKeys)}, + {&mBrokenIndexAllKeys, &(indexToImport->mBrokenIndexAllKeys)}, + {&mHiddenIndexAllKeys, &(indexToImport->mHiddenIndexAllKeys)}, }; std::vector indexImportDecl = std::vector( @@ -304,7 +303,7 @@ void FileFilterIndex::setKidModeFilters() { if (UIModeController::getInstance()->isUIModeKid()) { mFilterByKidGame = true; - std::vector val = { "TRUE" }; + std::vector val = {"TRUE"}; setFilter(KIDGAME_FILTER, &val); } } @@ -419,14 +418,13 @@ bool FileFilterIndex::isFiltered() bool FileFilterIndex::isKeyBeingFilteredBy(std::string key, FilterIndexType type) { - const FilterIndexType filterTypes[9] = { FAVORITES_FILTER, GENRE_FILTER, PLAYER_FILTER, - PUBDEV_FILTER, RATINGS_FILTER, KIDGAME_FILTER, - COMPLETED_FILTER, BROKEN_FILTER, HIDDEN_FILTER }; + const FilterIndexType filterTypes[9] = {FAVORITES_FILTER, GENRE_FILTER, PLAYER_FILTER, + PUBDEV_FILTER, RATINGS_FILTER, KIDGAME_FILTER, + COMPLETED_FILTER, BROKEN_FILTER, HIDDEN_FILTER}; std::vector filterKeysList[9] = { mFavoritesIndexFilteredKeys, mGenreIndexFilteredKeys, mPlayersIndexFilteredKeys, mPubDevIndexFilteredKeys, mRatingsIndexFilteredKeys, mKidGameIndexFilteredKeys, - mCompletedIndexFilteredKeys, mBrokenIndexFilteredKeys, mHiddenIndexFilteredKeys - }; + mCompletedIndexFilteredKeys, mBrokenIndexFilteredKeys, mHiddenIndexFilteredKeys}; for (int i = 0; i < 9; i++) { if (filterTypes[i] == type) { diff --git a/es-app/src/FileSorts.cpp b/es-app/src/FileSorts.cpp index 8c84f3d78..84479b8f3 100644 --- a/es-app/src/FileSorts.cpp +++ b/es-app/src/FileSorts.cpp @@ -45,8 +45,7 @@ namespace FileSorts FileData::SortType(&compareTimesPlayedDescending, "times played, descending"), FileData::SortType(&compareSystem, "system, ascending"), - FileData::SortType(&compareSystemDescending, "system, descending") - }; + FileData::SortType(&compareSystemDescending, "system, descending")}; const std::vector SortTypes(typesArr, typesArr + diff --git a/es-app/src/Gamelist.cpp b/es-app/src/Gamelist.cpp index 31ac2b9e8..ac71f8d80 100644 --- a/es-app/src/Gamelist.cpp +++ b/es-app/src/Gamelist.cpp @@ -117,11 +117,35 @@ void parseGamelist(SystemData* system) return; } + pugi::xml_node alternativeEmulator = doc.child("alternativeEmulator"); + if (alternativeEmulator) { + std::string label = alternativeEmulator.child("label").text().get(); + if (label != "") { + bool validLabel = false; + for (auto command : system->getSystemEnvData()->mLaunchCommands) { + if (command.second == label) + validLabel = true; + } + if (validLabel) { + system->setAlternativeEmulator(label); + LOG(LogDebug) << "Gamelist::parseGamelist(): System \"" << system->getName() + << "\" has a valid alternativeEmulator entry: \"" << label << "\""; + } + else { + system->setAlternativeEmulator(""); + LOG(LogWarning) << "System \"" << system->getName() + << "\" has an invalid alternativeEmulator entry that does " + "not match any command tag in es_systems.xml: \"" + << label << "\""; + } + } + } + std::string relativeTo = system->getStartPath(); bool showHiddenFiles = Settings::getInstance()->getBool("ShowHiddenFiles"); - std::vector tagList = { "game", "folder" }; - FileType typeList[2] = { GAME, FOLDER }; + std::vector tagList = {"game", "folder"}; + FileType typeList[2] = {GAME, FOLDER}; for (int i = 0; i < 2; i++) { std::string tag = tagList[i]; FileType type = typeList[i]; @@ -221,7 +245,7 @@ void addFileDataNode(pugi::xml_node& parent, } } -void updateGamelist(SystemData* system) +void updateGamelist(SystemData* system, bool updateAlternativeEmulator) { // We do this by reading the XML again, adding changes and then writing them back, // because there might be information missing in our systemdata which we would otherwise @@ -256,8 +280,39 @@ void updateGamelist(SystemData* system) LOG(LogError) << "Couldn't find node in gamelist \"" << xmlReadPath << "\""; return; } + if (updateAlternativeEmulator) { + pugi::xml_node alternativeEmulator = doc.child("alternativeEmulator"); + + if (system->getAlternativeEmulator() != "") { + if (!alternativeEmulator) { + doc.prepend_child("alternativeEmulator"); + alternativeEmulator = doc.child("alternativeEmulator"); + } + + pugi::xml_node label = alternativeEmulator.child("label"); + + if (label && system->getAlternativeEmulator() != + alternativeEmulator.child("label").text().get()) { + alternativeEmulator.remove_child(label); + alternativeEmulator.prepend_child("label").text().set( + system->getAlternativeEmulator().c_str()); + } + else if (!label) { + alternativeEmulator.prepend_child("label").text().set( + system->getAlternativeEmulator().c_str()); + } + } + else if (alternativeEmulator) { + doc.remove_child("alternativeEmulator"); + } + } } else { + if (updateAlternativeEmulator && system->getAlternativeEmulator() != "") { + pugi::xml_node alternativeEmulator = doc.prepend_child("alternativeEmulator"); + alternativeEmulator.prepend_child("label").text().set( + system->getAlternativeEmulator().c_str()); + } // Set up an empty gamelist to append to. root = doc.append_child("gameList"); } @@ -312,15 +367,31 @@ void updateGamelist(SystemData* system) } // Now write the file. - if (numUpdated > 0) { + if (numUpdated > 0 || updateAlternativeEmulator) { // Make sure the folders leading up to this path exist (or the write will fail). std::string xmlWritePath(system->getGamelistPath(true)); Utils::FileSystem::createDirectory(Utils::FileSystem::getParent(xmlWritePath)); - LOG(LogDebug) << "Gamelist::updateGamelist(): Added/updated " << numUpdated - << (numUpdated == 1 ? " entity in \"" : " entities in \"") << xmlReadPath - << "\""; - + if (updateAlternativeEmulator) { + if (system->getAlternativeEmulator() == "") { + LOG(LogDebug) << "Gamelist::updateGamelist(): Removed the " + "alternativeEmulator tag for system \"" + << system->getName() << "\" as the default emulator \"" + << system->getSystemEnvData()->mLaunchCommands.front().second + << "\" was selected"; + } + else { + LOG(LogDebug) << "Gamelist::updateGamelist(): " + "Added/updated the alternativeEmulator tag for system \"" + << system->getName() << "\" to \"" + << system->getAlternativeEmulator() << "\""; + } + } + if (numUpdated > 0) { + LOG(LogDebug) << "Gamelist::updateGamelist(): Added/updated " << numUpdated + << (numUpdated == 1 ? " entity in \"" : " entities in \"") + << xmlWritePath << "\""; + } #if defined(_WIN64) if (!doc.save_file(Utils::String::stringToWideString(xmlWritePath).c_str())) { #else diff --git a/es-app/src/Gamelist.h b/es-app/src/Gamelist.h index a8f91a027..46c8dd10c 100644 --- a/es-app/src/Gamelist.h +++ b/es-app/src/Gamelist.h @@ -15,6 +15,6 @@ class SystemData; void parseGamelist(SystemData* system); // Writes currently loaded metadata for a SystemData to gamelist.xml. -void updateGamelist(SystemData* system); +void updateGamelist(SystemData* system, bool updateAlternativeEmulator = false); #endif // ES_APP_GAME_LIST_H diff --git a/es-app/src/MediaViewer.cpp b/es-app/src/MediaViewer.cpp index d62630ff2..f79caacf3 100644 --- a/es-app/src/MediaViewer.cpp +++ b/es-app/src/MediaViewer.cpp @@ -83,19 +83,19 @@ void MediaViewer::update(int deltaTime) void MediaViewer::render() { - Transform4x4f transform = Transform4x4f::Identity(); - Renderer::setMatrix(transform); + glm::mat4 trans{Renderer::getIdentity()}; + Renderer::setMatrix(trans); // Render a black background below the game media. Renderer::drawRect(0.0f, 0.0f, static_cast(Renderer::getScreenWidth()), static_cast(Renderer::getScreenHeight()), 0x000000FF, 0x000000FF); if (mVideo && !mDisplayingImage) { - mVideo->render(transform); + mVideo->render(trans); #if defined(USE_OPENGL_21) Renderer::shaderParameters videoParameters; - unsigned int shaders = 0; + unsigned int shaders{0}; if (Settings::getInstance()->getBool("MediaViewerVideoScanlines")) shaders = Renderer::SHADER_SCANLINES; if (Settings::getInstance()->getBool("MediaViewerVideoBlur")) { @@ -121,8 +121,8 @@ void MediaViewer::render() Renderer::shaderPostprocessing(shaders, videoParameters); #endif } - else if (mImage && mImage->hasImage() && mImage->getSize() != 0) { - mImage->render(transform); + else if (mImage && mImage->hasImage() && mImage->getSize() != glm::vec2{}) { + mImage->render(trans); #if defined(USE_OPENGL_21) if (mCurrentImageIndex == mScreenShotIndex && diff --git a/es-app/src/MiximageGenerator.cpp b/es-app/src/MiximageGenerator.cpp index 12e2f6f4a..1d52a78a4 100644 --- a/es-app/src/MiximageGenerator.cpp +++ b/es-app/src/MiximageGenerator.cpp @@ -12,7 +12,6 @@ #include "Log.h" #include "Settings.h" #include "SystemData.h" -#include "math/Misc.h" #include "utils/StringUtil.h" #include @@ -472,7 +471,7 @@ bool MiximageGenerator::generateImage() frameImageAlpha.draw_image(xPosMarquee, yPosMarquee, marqueeImageAlpha); // Set a frame color based on an average of the screenshot contents. - unsigned char frameColor[] = { 0, 0, 0, 0 }; + unsigned char frameColor[] = {0, 0, 0, 0}; sampleFrameColor(screenshotImage, frameColor); // Upper / lower frame. @@ -564,11 +563,11 @@ void MiximageGenerator::calculateMarqueeSize(const unsigned int& targetWidth, // an approximately equivalent amount of space on the miximage. float widthRatio = static_cast(width) / static_cast(height); - widthModifier = Math::clamp(widthModifier + widthRatio / 6.5f, 0.0f, 1.0f); + widthModifier = glm::clamp(widthModifier + widthRatio / 6.5f, 0.0f, 1.0f); // Hack to increase the size slightly for wider and shorter images. if (widthRatio >= 4) - widthModifier += Math::clamp(widthRatio / 40.0f, 0.0f, 0.3f); + widthModifier += glm::clamp(widthRatio / 40.0f, 0.0f, 0.3f); adjustedTargetWidth = static_cast(static_cast(targetWidth) * widthModifier); @@ -620,9 +619,9 @@ void MiximageGenerator::sampleFrameColor(CImg& screenshotImage, } } - unsigned char redC = Math::clamp(static_cast(redLine / 255), 0, 255); - unsigned char greenC = Math::clamp(static_cast(greenLine / 255), 0, 255); - unsigned char blueC = Math::clamp(static_cast(blueLine / 255), 0, 255); + unsigned char redC = glm::clamp(static_cast(redLine / 255), 0, 255); + unsigned char greenC = glm::clamp(static_cast(greenLine / 255), 0, 255); + unsigned char blueC = glm::clamp(static_cast(blueLine / 255), 0, 255); // Convert to the HSL color space to be able to modify saturation and lightness. CImg colorHSL = CImg<>(1, 1, 1, 3).fill(redC, greenC, blueC).RGBtoHSL(); @@ -635,8 +634,8 @@ void MiximageGenerator::sampleFrameColor(CImg& screenshotImage, // makes the end result look better than the raw average pixel value. Also clamp // the lightness to a low value so we don't get a frame that is nearly pitch black // if the screenshot mostly contains blacks or dark colors. - colorHSL(0, 0, 0, 1) = Math::clamp(saturation * 0.9f, 0.0f, 1.0f); - colorHSL(0, 0, 0, 2) = Math::clamp(lightness * 1.25f, 0.10f, 1.0f); + colorHSL(0, 0, 0, 1) = glm::clamp(saturation * 0.9f, 0.0f, 1.0f); + colorHSL(0, 0, 0, 2) = glm::clamp(lightness * 1.25f, 0.10f, 1.0f); const CImg colorRGB = colorHSL.HSLtoRGB(); diff --git a/es-app/src/SystemData.cpp b/es-app/src/SystemData.cpp index 6f95bf97a..630db6fb8 100644 --- a/es-app/src/SystemData.cpp +++ b/es-app/src/SystemData.cpp @@ -417,13 +417,27 @@ bool SystemData::loadConfig() std::string name; std::string fullname; std::string path; - std::string cmd; std::string themeFolder; name = system.child("name").text().get(); fullname = system.child("fullname").text().get(); path = system.child("path").text().get(); + auto nameFindFunc = [&] { + for (auto system : sSystemVector) { + if (system->mName == name) { + LOG(LogWarning) << "A system with the name \"" << name + << "\" has already been loaded, skipping duplicate entry"; + return true; + } + } + return false; + }; + + // If the name is matching a system that has already been loaded, then skip the entry. + if (nameFindFunc()) + continue; + // If there is a %ROMPATH% variable set for the system, expand it. By doing this // it's possible to use either absolute ROM paths in es_systems.xml or to utilize // the ROM path configured as ROMDirectory in es_settings.xml. If it's set to "" @@ -461,7 +475,41 @@ bool SystemData::loadConfig() // Convert extensions list from a string into a vector of strings. std::vector extensions = readList(system.child("extension").text().get()); - cmd = system.child("command").text().get(); + // Load all launch command tags for the system and if there are multiple tags, then + // the label attribute needs to be set on all entries as it's a requirement for the + // alternative emulator logic. + std::vector> commands; + for (pugi::xml_node entry = system.child("command"); entry; + entry = entry.next_sibling("command")) { + if (!entry.attribute("label")) { + if (commands.size() == 1) { + // The first command tag had a label but the second one doesn't. + LOG(LogError) + << "Missing mandatory label attribute for alternative emulator " + "entry, only the default command tag will be processed for system \"" + << name << "\""; + break; + } + else if (commands.size() > 1) { + // At least two command tags had a label but this one doesn't. + LOG(LogError) + << "Missing mandatory label attribute for alternative emulator " + "entry, no additional command tags will be processed for system \"" + << name << "\""; + break; + } + } + else if (!commands.empty() && commands.back().second == "") { + // There are more than one command tags and the first tag did not have a label. + LOG(LogError) + << "Missing mandatory label attribute for alternative emulator " + "entry, only the default command tag will be processed for system \"" + << name << "\""; + break; + } + commands.push_back( + std::make_pair(entry.text().get(), entry.attribute("label").as_string())); + } // Platform ID list const std::string platformList = @@ -504,7 +552,7 @@ bool SystemData::loadConfig() << "A system in the es_systems.xml file has no name defined, skipping entry"; continue; } - else if (fullname.empty() || path.empty() || extensions.empty() || cmd.empty()) { + else if (fullname.empty() || path.empty() || extensions.empty() || commands.empty()) { LOG(LogError) << "System \"" << name << "\" is missing the fullname, path, " "extension, or command tag, skipping entry"; @@ -526,7 +574,7 @@ bool SystemData::loadConfig() SystemEnvironmentData* envData = new SystemEnvironmentData; envData->mStartPath = path; envData->mSearchExtensions = extensions; - envData->mLaunchCommand = cmd; + envData->mLaunchCommands = commands; envData->mPlatformIds = platformIds; SystemData* newSys = new SystemData(name, fullname, envData, themeFolder); @@ -679,7 +727,7 @@ bool SystemData::createSystemDirectories() std::string fullname; std::string path; std::string extensions; - std::string command; + std::vector commands; std::string platform; std::string themeFolder; const std::string systemInfoFileName = "/systeminfo.txt"; @@ -690,7 +738,10 @@ bool SystemData::createSystemDirectories() fullname = system.child("fullname").text().get(); path = system.child("path").text().get(); extensions = system.child("extension").text().get(); - command = system.child("command").text().get(); + for (pugi::xml_node entry = system.child("command"); entry; + entry = entry.next_sibling("command")) { + commands.push_back(entry.text().get()); + } platform = Utils::String::toLower(system.child("platform").text().get()); themeFolder = system.child("theme").text().as_string(name.c_str()); @@ -757,7 +808,16 @@ bool SystemData::createSystemDirectories() systemInfoFile << "Supported file extensions:" << std::endl; systemInfoFile << extensions << std::endl << std::endl; systemInfoFile << "Launch command:" << std::endl; - systemInfoFile << command << std::endl << std::endl; + systemInfoFile << commands.front() << std::endl << std::endl; + // Alternative emulator configuration entries. + if (commands.size() > 1) { + systemInfoFile << (commands.size() == 2 ? "Alternative launch command:" : + "Alternative launch commands:") + << std::endl; + for (auto it = commands.cbegin() + 1; it != commands.cend(); it++) + systemInfoFile << (*it) << std::endl; + systemInfoFile << std::endl; + } systemInfoFile << "Platform (for scraping):" << std::endl; systemInfoFile << platform << std::endl << std::endl; systemInfoFile << "Theme folder:" << std::endl; @@ -919,7 +979,7 @@ SystemData* SystemData::getRandomSystem(const SystemData* currentSystem) // Get a random number in range. std::random_device randDev; // Mersenne Twister pseudorandom number generator. - std::mt19937 engine { randDev() }; + std::mt19937 engine{randDev()}; std::uniform_int_distribution uniform_dist(0, total - 1); int target = uniform_dist(engine); @@ -998,7 +1058,7 @@ FileData* SystemData::getRandomGame(const FileData* currentGame) // Get a random number in range. std::random_device randDev; // Mersenne Twister pseudorandom number generator. - std::mt19937 engine { randDev() }; + std::mt19937 engine{randDev()}; std::uniform_int_distribution uniform_dist(0, total - 1); target = uniform_dist(engine); } while (currentGame && gameList.at(target) == currentGame); diff --git a/es-app/src/SystemData.h b/es-app/src/SystemData.h index 28a44721a..5927c2385 100644 --- a/es-app/src/SystemData.h +++ b/es-app/src/SystemData.h @@ -27,7 +27,7 @@ class ThemeData; struct SystemEnvironmentData { std::string mStartPath; std::vector mSearchExtensions; - std::string mLaunchCommand; + std::vector> mLaunchCommands; std::vector mPlatformIds; }; @@ -97,6 +97,9 @@ public: bool getScrapeFlag() { return mScrapeFlag; } void setScrapeFlag(bool scrapeflag) { mScrapeFlag = scrapeflag; } + std::string getAlternativeEmulator() { return mAlternativeEmulator; } + void setAlternativeEmulator(const std::string& command) { mAlternativeEmulator = command; } + static void deleteSystems(); // Loads the systems configuration file at getConfigPath() and creates the systems. static bool loadConfig(); @@ -153,6 +156,7 @@ private: std::string mName; std::string mFullName; SystemEnvironmentData* mEnvData; + std::string mAlternativeEmulator; std::string mThemeFolder; std::shared_ptr mTheme; diff --git a/es-app/src/SystemScreensaver.cpp b/es-app/src/SystemScreensaver.cpp index e74b161d9..8d7fe8c64 100644 --- a/es-app/src/SystemScreensaver.cpp +++ b/es-app/src/SystemScreensaver.cpp @@ -248,19 +248,19 @@ void SystemScreensaver::renderScreensaver() if (mVideoScreensaver && screensaverType == "video") { // Render a black background below the video. - Renderer::setMatrix(Transform4x4f::Identity()); + Renderer::setMatrix(Renderer::getIdentity()); Renderer::drawRect(0.0f, 0.0f, static_cast(Renderer::getScreenWidth()), static_cast(Renderer::getScreenHeight()), 0x000000FF, 0x000000FF); // Only render the video if the state requires it. if (static_cast(mState) >= STATE_FADE_IN_VIDEO) { - Transform4x4f transform = Transform4x4f::Identity(); - mVideoScreensaver->render(transform); + glm::mat4 trans{Renderer::getIdentity()}; + mVideoScreensaver->render(trans); } } else if (mImageScreensaver && screensaverType == "slideshow") { // Render a black background below the image. - Renderer::setMatrix(Transform4x4f::Identity()); + Renderer::setMatrix(Renderer::getIdentity()); Renderer::drawRect(0.0f, 0.0f, static_cast(Renderer::getScreenWidth()), static_cast(Renderer::getScreenHeight()), 0x000000FF, 0x000000FF); @@ -268,15 +268,14 @@ void SystemScreensaver::renderScreensaver() if (static_cast(mState) >= STATE_FADE_IN_VIDEO) { if (mImageScreensaver->hasImage()) { mImageScreensaver->setOpacity(255 - static_cast(mOpacity * 255)); - - Transform4x4f transform = Transform4x4f::Identity(); - mImageScreensaver->render(transform); + glm::mat4 trans{Renderer::getIdentity()}; + mImageScreensaver->render(trans); } } } if (isScreensaverActive()) { - Renderer::setMatrix(Transform4x4f::Identity()); + Renderer::setMatrix(Renderer::getIdentity()); if (Settings::getInstance()->getString("ScreensaverType") == "slideshow") { if (mHasMediaFiles) { #if defined(USE_OPENGL_21) @@ -292,13 +291,13 @@ void SystemScreensaver::renderScreensaver() 0x00000000 | mRectangleFadeIn, 0x00000000 | mRectangleFadeIn); } mRectangleFadeIn = - Math::clamp(mRectangleFadeIn + 6 + mRectangleFadeIn / 20, 0, 170); + glm::clamp(mRectangleFadeIn + 6 + mRectangleFadeIn / 20, 0, 170); mGameOverlay.get()->setColor(0xFFFFFF00 | mTextFadeIn); if (mTextFadeIn > 50) mGameOverlayFont.at(0)->renderTextCache(mGameOverlay.get()); if (mTextFadeIn < 255) - mTextFadeIn = Math::clamp(mTextFadeIn + 2 + mTextFadeIn / 6, 0, 255); + mTextFadeIn = glm::clamp(mTextFadeIn + 2 + mTextFadeIn / 6, 0, 255); } } else { @@ -345,13 +344,13 @@ void SystemScreensaver::renderScreensaver() 0x00000000 | mRectangleFadeIn, 0x00000000 | mRectangleFadeIn); } mRectangleFadeIn = - Math::clamp(mRectangleFadeIn + 6 + mRectangleFadeIn / 20, 0, 170); + glm::clamp(mRectangleFadeIn + 6 + mRectangleFadeIn / 20, 0, 170); mGameOverlay.get()->setColor(0xFFFFFF00 | mTextFadeIn); if (mTextFadeIn > 50) mGameOverlayFont.at(0)->renderTextCache(mGameOverlay.get()); if (mTextFadeIn < 255) - mTextFadeIn = Math::clamp(mTextFadeIn + 2 + mTextFadeIn / 6, 0, 255); + mTextFadeIn = glm::clamp(mTextFadeIn + 2 + mTextFadeIn / 6, 0, 255); } } else { @@ -365,11 +364,11 @@ void SystemScreensaver::renderScreensaver() dimParameters.fragmentDimValue = mDimValue; Renderer::shaderPostprocessing(Renderer::SHADER_DIM, dimParameters); if (mDimValue > 0.4) - mDimValue = Math::clamp(mDimValue - 0.021f, 0.4f, 1.0f); + mDimValue = glm::clamp(mDimValue - 0.021f, 0.4f, 1.0f); dimParameters.fragmentSaturation = mSaturationAmount; Renderer::shaderPostprocessing(Renderer::SHADER_DESATURATE, dimParameters); if (mSaturationAmount > 0.0) - mSaturationAmount = Math::clamp(mSaturationAmount - 0.035f, 0.0f, 1.0f); + mSaturationAmount = glm::clamp(mSaturationAmount - 0.035f, 0.0f, 1.0f); #else Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0x000000A0, 0x000000A0); @@ -381,7 +380,7 @@ void SystemScreensaver::renderScreensaver() blackParameters.fragmentDimValue = mDimValue; Renderer::shaderPostprocessing(Renderer::SHADER_DIM, blackParameters); if (mDimValue > 0.0) - mDimValue = Math::clamp(mDimValue - 0.045f, 0.0f, 1.0f); + mDimValue = glm::clamp(mDimValue - 0.045f, 0.0f, 1.0f); #else Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0x000000FF, 0x000000FF); @@ -515,7 +514,7 @@ void SystemScreensaver::pickRandomImage(std::string& path) // Get a random number in range. std::random_device randDev; // Mersenne Twister pseudorandom number generator. - std::mt19937 engine { randDev() }; + std::mt19937 engine{randDev()}; std::uniform_int_distribution uniform_dist(0, static_cast(mImageFiles.size()) - 1); index = uniform_dist(engine); @@ -549,7 +548,7 @@ void SystemScreensaver::pickRandomVideo(std::string& path) // Get a random number in range. std::random_device randDev; // Mersenne Twister pseudorandom number generator. - std::mt19937 engine { randDev() }; + std::mt19937 engine{randDev()}; std::uniform_int_distribution uniform_dist(0, static_cast(mVideoFiles.size()) - 1); index = uniform_dist(engine); @@ -577,7 +576,7 @@ void SystemScreensaver::pickRandomCustomImage(std::string& path) // Get a random number in range. std::random_device randDev; // Mersenne Twister pseudorandom number generator. - std::mt19937 engine { randDev() }; + std::mt19937 engine{randDev()}; std::uniform_int_distribution uniform_dist( 0, static_cast(mImageCustomFiles.size()) - 1); index = uniform_dist(engine); @@ -609,18 +608,18 @@ void SystemScreensaver::generateOverlayInfo() mGameOverlayFont.at(0)->buildTextCache(overlayText, posX, posY, 0xFFFFFFFF)); float textSizeX; - float textSizeY = mGameOverlayFont[0].get()->sizeText(overlayText).y(); + float textSizeY = mGameOverlayFont[0].get()->sizeText(overlayText).y; // There is a weird issue with sizeText() where the X size value is returned // as too large if there are two rows in a string and the second row is longer // than the first row. Possibly it's the newline character that is somehow // injected in the size calculation. Regardless, this workaround is working // fine for the time being. - if (mGameOverlayFont[0].get()->sizeText(gameName).x() > - mGameOverlayFont[0].get()->sizeText(systemName).x()) - textSizeX = mGameOverlayFont[0].get()->sizeText(gameName).x(); + if (mGameOverlayFont[0].get()->sizeText(gameName).x > + mGameOverlayFont[0].get()->sizeText(systemName).x) + textSizeX = mGameOverlayFont[0].get()->sizeText(gameName).x; else - textSizeX = mGameOverlayFont[0].get()->sizeText(systemName).x(); + textSizeX = mGameOverlayFont[0].get()->sizeText(systemName).x; float marginX = Renderer::getWindowWidth() * 0.01f; diff --git a/es-app/src/VolumeControl.cpp b/es-app/src/VolumeControl.cpp index 4019b7754..18fd01b0d 100644 --- a/es-app/src/VolumeControl.cpp +++ b/es-app/src/VolumeControl.cpp @@ -9,7 +9,7 @@ #include "VolumeControl.h" #include "Log.h" -#include "math/Misc.h" +#include "utils/MathUtil.h" #if defined(_WIN64) #include @@ -212,13 +212,13 @@ int VolumeControl::getVolume() const } #endif - volume = Math::clamp(volume, 0, 100); + volume = glm::clamp(volume, 0, 100); return volume; } void VolumeControl::setVolume(int volume) { - volume = Math::clamp(volume, 0, 100); + volume = glm::clamp(volume, 0, 100); #if defined(__linux__) if (mixerElem != nullptr) { diff --git a/es-app/src/animations/MoveCameraAnimation.h b/es-app/src/animations/MoveCameraAnimation.h deleted file mode 100644 index 82fd76152..000000000 --- a/es-app/src/animations/MoveCameraAnimation.h +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// MoveCameraAnimation.h -// -// Animation to play when moving the camera, used by the slide transition style. -// - -#ifndef ES_APP_ANIMATIONS_MOVE_CAMERA_ANIMATION_H -#define ES_APP_ANIMATIONS_MOVE_CAMERA_ANIMATION_H - -#include "animations/Animation.h" - -class MoveCameraAnimation : public Animation -{ -public: - MoveCameraAnimation(Transform4x4f& camera, const Vector3f& target) - : mCameraStart(camera) - , mTarget(target) - , cameraOut(camera) - { - } - - int getDuration() const override { return 400; } - - void apply(float t) override - { - // Cubic ease out. - t -= 1; - cameraOut.translation() = - -Vector3f().lerp(-mCameraStart.translation(), mTarget, t * t * t + 1); - } - -private: - Transform4x4f mCameraStart; - Vector3f mTarget; - - Transform4x4f& cameraOut; -}; - -#endif // ES_APP_ANIMATIONS_MOVE_CAMERA_ANIMATION_H diff --git a/es-app/src/guis/GuiAlternativeEmulators.cpp b/es-app/src/guis/GuiAlternativeEmulators.cpp new file mode 100644 index 000000000..ca5bb888e --- /dev/null +++ b/es-app/src/guis/GuiAlternativeEmulators.cpp @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: MIT +// +// EmulationStation Desktop Edition +// GuiAlternativeEmulators.cpp +// +// User interface to select between alternative emulators per system +// based on configuration entries in es_systems.xml. +// + +#include "guis/GuiAlternativeEmulators.h" + +#include "Gamelist.h" +#include "SystemData.h" +#include "views/ViewController.h" + +GuiAlternativeEmulators::GuiAlternativeEmulators(Window* window) + : GuiComponent{window} + , mMenu{window, "ALTERNATIVE EMULATORS"} + , mHasSystems(false) +{ + addChild(&mMenu); + mMenu.addButton("BACK", "back", [this] { delete this; }); + + // Horizontal sizes for the system and label entries. + float systemSizeX = mMenu.getSize().x / 3.27f; + float labelSizeX = mMenu.getSize().x / 1.53; + + for (auto it = SystemData::sSystemVector.cbegin(); // Line break. + it != SystemData::sSystemVector.cend(); it++) { + + // Only include systems that have at least two command entries, unless the system + // has an invalid entry. + if ((*it)->getAlternativeEmulator() != "" && + (*it)->getSystemEnvData()->mLaunchCommands.size() < 2) + continue; + + ComponentListRow row; + + // This transparent bracket is only added to generate a left margin. + auto bracket = std::make_shared(mWindow); + bracket->setImage(":/graphics/arrow.svg"); + bracket->setOpacity(0); + bracket->setSize(bracket->getSize() / 3.0f); + row.addElement(bracket, false); + + std::string name = (*it)->getName(); + std::shared_ptr systemText = + std::make_shared(mWindow, name, Font::get(FONT_SIZE_MEDIUM), 0x777777FF); + + systemText->setSize(systemSizeX, systemText->getSize().y); + row.addElement(systemText, false); + + std::string configuredLabel = (*it)->getAlternativeEmulator(); + std::string label; + + if (configuredLabel == "") { + label = (*it)->getSystemEnvData()->mLaunchCommands.front().second; + } + else { + for (auto command : (*it)->getSystemEnvData()->mLaunchCommands) { + if (command.second == configuredLabel) { + label = command.second; + break; + } + } + } + + bool invalidEntry = false; + + if (label.empty()) { + label = ""; + invalidEntry = true; + } + + std::shared_ptr labelText; + + if (label == (*it)->getSystemEnvData()->mLaunchCommands.front().second) { + labelText = std::make_shared( + mWindow, label, Font::get(FONT_SIZE_MEDIUM, FONT_PATH_LIGHT), 0x777777FF, + ALIGN_RIGHT); + } + else { + // Mark any non-default value with bold and add a gear symbol as well. + labelText = std::make_shared( + mWindow, label + (!invalidEntry ? " " + ViewController::GEAR_CHAR : ""), + Font::get(FONT_SIZE_MEDIUM, FONT_PATH_BOLD), 0x777777FF, ALIGN_RIGHT); + } + + // Mark invalid entries with red color. + if (invalidEntry) + labelText->setColor(TEXTCOLOR_SCRAPERMARKED); + + mCommandRows[name] = labelText; + labelText->setSize(labelSizeX, labelText->getSize().y); + + row.addElement(labelText, false); + row.makeAcceptInputHandler([this, it] { selectorWindow(*it); }); + + mMenu.addRow(row); + mHasSystems = true; + } + + // Add a dummy row if no enabled systems have any alternative emulators defined in + // es_systems.xml. + if (!mHasSystems) { + ComponentListRow row; + std::shared_ptr systemText = + std::make_shared(mWindow, "", + Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_CENTER); + row.addElement(systemText, true); + mMenu.addRow(row); + } + + float width = + static_cast(std::min(static_cast(Renderer::getScreenHeight() * 1.05f), + static_cast(Renderer::getScreenWidth() * 0.90f))); + + setSize(mMenu.getSize()); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, Renderer::getScreenHeight() * 0.13f); + + mMenu.setSize(width, Renderer::getScreenHeight() * 0.76f); +} + +void GuiAlternativeEmulators::updateMenu(const std::string& systemName, + const std::string& label, + bool defaultEmulator) +{ + // If another label was selected, then update the menu accordingly. + if (defaultEmulator) { + mCommandRows[systemName].get()->setFont(Font::get(FONT_SIZE_MEDIUM, FONT_PATH_LIGHT)); + mCommandRows[systemName].get()->setValue(label); + } + else { + // Mark any non-default value with bold and add a gear symbol as well. + mCommandRows[systemName].get()->setFont(Font::get(FONT_SIZE_MEDIUM, FONT_PATH_BOLD)); + mCommandRows[systemName].get()->setValue(label + " " + ViewController::GEAR_CHAR); + } + + mCommandRows[systemName].get()->setColor(DEFAULT_TEXTCOLOR); +} + +void GuiAlternativeEmulators::selectorWindow(SystemData* system) +{ + auto s = new GuiSettings(mWindow, system->getFullName()); + + std::string selectedLabel = system->getAlternativeEmulator(); + std::string label; + + for (auto entry : system->getSystemEnvData()->mLaunchCommands) { + ComponentListRow row; + + if (entry.second == "") + label = ""; + else + label = entry.second; + + std::shared_ptr labelText = std::make_shared( + mWindow, label, Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_CENTER); + + row.addElement(labelText, true); + row.makeAcceptInputHandler([this, s, system, labelText, entry, selectedLabel] { + if (entry.second != selectedLabel) { + if (entry.second == system->getSystemEnvData()->mLaunchCommands.front().second) + system->setAlternativeEmulator(""); + else + system->setAlternativeEmulator(entry.second); + updateGamelist(system, true); + updateMenu( + system->getName(), labelText->getValue(), + (entry.second == system->getSystemEnvData()->mLaunchCommands.front().second)); + } + delete s; + }); + + // This transparent bracket is only added to generate the correct help prompts. + auto bracket = std::make_shared(mWindow); + bracket->setImage(":/graphics/arrow.svg"); + bracket->setOpacity(0); + bracket->setSize(bracket->getSize() / 3.0f); + row.addElement(bracket, false); + + // Select the row that corresponds to the selected label. + if (selectedLabel == label) + s->addRow(row, true); + else + s->addRow(row, false); + } + + // Adjust the width depending on the aspect ratio of the screen, to make the screen look + // somewhat coherent regardless of screen type. The 1.778 aspect ratio value is the 16:9 + // reference. + float aspectValue = 1.778f / Renderer::getScreenAspectRatio(); + + float maxWidthModifier = glm::clamp(0.70f * aspectValue, 0.50f, 0.92f); + float maxWidth = static_cast(Renderer::getScreenWidth()) * maxWidthModifier; + + s->setMenuSize(glm::vec2{maxWidth, s->getMenuSize().y}); + + auto menuSize = s->getMenuSize(); + auto menuPos = s->getMenuPosition(); + + s->setMenuPosition(glm::vec3{(s->getSize().x - menuSize.x) / 2.0f, + (s->getSize().y - menuSize.y) / 3.0f, menuPos.z}); + mWindow->pushGui(s); +} + +bool GuiAlternativeEmulators::input(InputConfig* config, Input input) +{ + if (input.value != 0 && (config->isMappedTo("b", input) || config->isMappedTo("back", input))) { + delete this; + return true; + } + + return mMenu.input(config, input); +} + +std::vector GuiAlternativeEmulators::getHelpPrompts() +{ + std::vector prompts = mMenu.getHelpPrompts(); + prompts.push_back(HelpPrompt("b", "back")); + if (mHasSystems) + prompts.push_back(HelpPrompt("a", "select")); + return prompts; +} + +HelpStyle GuiAlternativeEmulators::getHelpStyle() +{ + HelpStyle style = HelpStyle(); + style.applyTheme(ViewController::get()->getState().getSystem()->getTheme(), "system"); + return style; +} diff --git a/es-app/src/guis/GuiAlternativeEmulators.h b/es-app/src/guis/GuiAlternativeEmulators.h new file mode 100644 index 000000000..f243939e1 --- /dev/null +++ b/es-app/src/guis/GuiAlternativeEmulators.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +// +// EmulationStation Desktop Edition +// GuiAlternativeEmulators.h +// +// User interface to select between alternative emulators per system +// based on configuration entries in es_systems.xml. +// + +#ifndef ES_APP_GUIS_GUI_ALTERNATIVE_EMULATORS_H +#define ES_APP_GUIS_GUI_ALTERNATIVE_EMULATORS_H + +#include "GuiComponent.h" +#include "guis/GuiSettings.h" + +template class OptionListComponent; + +class GuiAlternativeEmulators : public GuiComponent +{ +public: + GuiAlternativeEmulators(Window* window); + +private: + void updateMenu(const std::string& systemName, const std::string& label, bool defaultEmulator); + void selectorWindow(SystemData* system); + + virtual bool input(InputConfig* config, Input input) override; + virtual std::vector getHelpPrompts() override; + HelpStyle getHelpStyle() override; + + MenuComponent mMenu; + bool mHasSystems; + + std::map> mCommandRows; + std::shared_ptr> mCommandSelection; +}; + +#endif // ES_APP_GUIS_GUI_ALTERNATIVE_EMULATORS_H diff --git a/es-app/src/guis/GuiCollectionSystemsOptions.cpp b/es-app/src/guis/GuiCollectionSystemsOptions.cpp index 86e8404d7..73c77b2fa 100644 --- a/es-app/src/guis/GuiCollectionSystemsOptions.cpp +++ b/es-app/src/guis/GuiCollectionSystemsOptions.cpp @@ -158,7 +158,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st auto bracketThemeCollection = std::make_shared(mWindow); bracketThemeCollection->setImage(":/graphics/arrow.svg"); bracketThemeCollection->setResize( - Vector2f(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight())); + glm::vec2{0.0f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()}); row.addElement(themeCollection, true); row.addElement(bracketThemeCollection, false); row.makeAcceptInputHandler([this, unusedFolders] { @@ -195,7 +195,8 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st Font::get(FONT_SIZE_MEDIUM), 0x777777FF); auto bracketNewCollection = std::make_shared(mWindow); bracketNewCollection->setImage(":/graphics/arrow.svg"); - bracketNewCollection->setResize(Vector2f(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight())); + bracketNewCollection->setResize( + glm::vec2{0.0f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()}); row.addElement(newCollection, true); row.addElement(bracketNewCollection, false); auto createCollectionCall = [this](const std::string& newVal) { @@ -219,7 +220,8 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st mWindow, "DELETE CUSTOM COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF); auto bracketDeleteCollection = std::make_shared(mWindow); bracketDeleteCollection->setImage(":/graphics/arrow.svg"); - bracketDeleteCollection->setResize(Vector2f(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight())); + bracketDeleteCollection->setResize( + glm::vec2{0.0f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()}); row.addElement(deleteCollection, true); row.addElement(bracketDeleteCollection, false); row.makeAcceptInputHandler([this, customSystems] { diff --git a/es-app/src/guis/GuiGameScraper.cpp b/es-app/src/guis/GuiGameScraper.cpp index 98b74fd02..9c2a2e59d 100644 --- a/es-app/src/guis/GuiGameScraper.cpp +++ b/es-app/src/guis/GuiGameScraper.cpp @@ -22,7 +22,7 @@ GuiGameScraper::GuiGameScraper(Window* window, ScraperSearchParams params, std::function doneFunc) : GuiComponent(window) - , mGrid(window, Vector2i(1, 7)) + , mGrid(window, glm::ivec2{1, 7}) , mBox(window, ":/graphics/frame.svg") , mSearchParams(params) , mClose(false) @@ -52,20 +52,20 @@ GuiGameScraper::GuiGameScraper(Window* window, scrapeName + ((mSearchParams.game->getType() == FOLDER) ? " " + ViewController::FOLDER_CHAR : ""), Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_CENTER); - mGrid.setEntry(mGameName, Vector2i(0, 1), false, true); + mGrid.setEntry(mGameName, glm::ivec2{0, 1}, false, true); // Row 2 is a spacer. mSystemName = std::make_shared( mWindow, Utils::String::toUpper(mSearchParams.system->getFullName()), Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_CENTER); - mGrid.setEntry(mSystemName, Vector2i(0, 3), false, true); + mGrid.setEntry(mSystemName, glm::ivec2{0, 3}, false, true); // Row 4 is a spacer. // GuiScraperSearch. mSearch = std::make_shared(window, GuiScraperSearch::NEVER_AUTO_ACCEPT, 1); - mGrid.setEntry(mSearch, Vector2i(0, 5), true); + mGrid.setEntry(mSearch, glm::ivec2{0, 5}, true); // Buttons std::vector> buttons; @@ -92,7 +92,7 @@ GuiGameScraper::GuiGameScraper(Window* window, })); mButtonGrid = makeButtonGrid(mWindow, buttons); - mGrid.setEntry(mButtonGrid, Vector2i(0, 6), true, false); + mGrid.setEntry(mButtonGrid, glm::ivec2{0, 6}, true, false); mSearch->setAcceptCallback([this, doneFunc](const ScraperSearchResult& result) { doneFunc(result); @@ -103,11 +103,11 @@ GuiGameScraper::GuiGameScraper(Window* window, // Limit the width of the GUI on ultrawide monitors. The 1.778 aspect ratio value is // the 16:9 reference. float aspectValue = 1.778f / Renderer::getScreenAspectRatio(); - float width = Math::clamp(0.95f * aspectValue, 0.70f, 0.95f) * Renderer::getScreenWidth(); + float width = glm::clamp(0.95f * aspectValue, 0.70f, 0.95f) * Renderer::getScreenWidth(); setSize(width, Renderer::getScreenHeight() * 0.747f); - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, - (Renderer::getScreenHeight() - mSize.y()) / 2.0f); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, + (Renderer::getScreenHeight() - mSize.y) / 2.0f); mGrid.resetCursor(); mSearch->search(params); // Start the search. @@ -115,16 +115,14 @@ GuiGameScraper::GuiGameScraper(Window* window, void GuiGameScraper::onSizeChanged() { - mBox.fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mBox.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); mGrid.setRowHeightPerc(0, 0.04f, false); - mGrid.setRowHeightPerc(1, mGameName->getFont()->getLetterHeight() / mSize.y(), - false); // Game name. + mGrid.setRowHeightPerc(1, mGameName->getFont()->getLetterHeight() / mSize.y, false); mGrid.setRowHeightPerc(2, 0.04f, false); - mGrid.setRowHeightPerc(3, mSystemName->getFont()->getLetterHeight() / mSize.y(), - false); // System name. + mGrid.setRowHeightPerc(3, mSystemName->getFont()->getLetterHeight() / mSize.y, false); mGrid.setRowHeightPerc(4, 0.04f, false); - mGrid.setRowHeightPerc(6, mButtonGrid->getSize().y() / mSize.y(), false); // Buttons. + mGrid.setRowHeightPerc(6, mButtonGrid->getSize().y / mSize.y, false); mGrid.setSize(mSize); } diff --git a/es-app/src/guis/GuiGamelistFilter.cpp b/es-app/src/guis/GuiGamelistFilter.cpp index 2c48660cf..61a7361c2 100644 --- a/es-app/src/guis/GuiGamelistFilter.cpp +++ b/es-app/src/guis/GuiGamelistFilter.cpp @@ -50,7 +50,7 @@ void GuiGamelistFilter::initializeMenu() mMenu.addButton("BACK", "back", std::bind(&GuiGamelistFilter::applyFilters, this)); - mMenu.setPosition((Renderer::getScreenWidth() - mMenu.getSize().x()) / 2.0f, + mMenu.setPosition((Renderer::getScreenWidth() - mMenu.getSize().x) / 2.0f, Renderer::getScreenHeight() * 0.13f); // Save the initial filter values to be able to check later if any changes were made. @@ -101,12 +101,12 @@ void GuiGamelistFilter::addFiltersToMenu() row.addElement(mTextFilterField, true); auto spacer = std::make_shared(mWindow); - spacer->setSize(Renderer::getScreenWidth() * 0.005f, 0); + spacer->setSize(Renderer::getScreenWidth() * 0.005f, 0.0f); row.addElement(spacer, false); auto bracket = std::make_shared(mWindow); bracket->setImage(":/graphics/arrow.svg"); - bracket->setResize(Vector2f(0, lbl->getFont()->getLetterHeight())); + bracket->setResize(glm::vec2{0.0f, lbl->getFont()->getLetterHeight()}); row.addElement(bracket, false); mTextFilterField->setValue(mFilterIndex->getTextFilter()); diff --git a/es-app/src/guis/GuiGamelistOptions.cpp b/es-app/src/guis/GuiGamelistOptions.cpp index 0db9424a3..9c6a5f87e 100644 --- a/es-app/src/guis/GuiGamelistOptions.cpp +++ b/es-app/src/guis/GuiGamelistOptions.cpp @@ -240,8 +240,7 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system) // Center the menu. setSize(static_cast(Renderer::getScreenWidth()), static_cast(Renderer::getScreenHeight())); - mMenu.setPosition((mSize.x() - mMenu.getSize().x()) / 2.0f, - (mSize.y() - mMenu.getSize().y()) / 2.0f); + mMenu.setPosition((mSize.x - mMenu.getSize().x) / 2.0f, (mSize.y - mMenu.getSize().y) / 2.0f); } GuiGamelistOptions::~GuiGamelistOptions() diff --git a/es-app/src/guis/GuiInfoPopup.cpp b/es-app/src/guis/GuiInfoPopup.cpp index c7ab4e9e4..2491c7e49 100644 --- a/es-app/src/guis/GuiInfoPopup.cpp +++ b/es-app/src/guis/GuiInfoPopup.cpp @@ -33,36 +33,36 @@ GuiInfoPopup::GuiInfoPopup(Window* window, std::string message, int duration) mSize = s->getSize(); // Confirm that the size isn't larger than the screen width, otherwise cap it. - if (mSize.x() > maxWidth) { - s->setSize(maxWidth, mSize[1]); - mSize[0] = maxWidth; + if (mSize.x > maxWidth) { + s->setSize(maxWidth, mSize.y); + mSize.x = maxWidth; } - if (mSize.y() > maxHeight) { - s->setSize(mSize[0], maxHeight); - mSize[1] = maxHeight; + if (mSize.y > maxHeight) { + s->setSize(mSize.x, maxHeight); + mSize.y = maxHeight; } // Add a padding to the box. int paddingX = static_cast(Renderer::getScreenWidth() * 0.03f); int paddingY = static_cast(Renderer::getScreenHeight() * 0.02f); - mSize[0] = mSize.x() + paddingX; - mSize[1] = mSize.y() + paddingY; + mSize.x = mSize.x + paddingX; + mSize.y = mSize.y + paddingY; - float posX = Renderer::getScreenWidth() * 0.5f - mSize.x() * 0.5f; + float posX = Renderer::getScreenWidth() * 0.5f - mSize.x * 0.5f; float posY = Renderer::getScreenHeight() * 0.02f; setPosition(posX, posY, 0); mFrame->setImagePath(":/graphics/frame.svg"); - mFrame->fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mFrame->fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); addChild(mFrame); // We only initialize the actual time when we first start to render. mStartTime = 0; - mGrid = new ComponentGrid(window, Vector2i(1, 3)); + mGrid = new ComponentGrid(window, glm::ivec2{1, 3}); mGrid->setSize(mSize); - mGrid->setEntry(s, Vector2i(0, 1), false, true); + mGrid->setEntry(s, glm::ivec2{0, 1}, false, true); addChild(mGrid); } @@ -72,10 +72,10 @@ GuiInfoPopup::~GuiInfoPopup() delete mFrame; } -void GuiInfoPopup::render(const Transform4x4f& /*parentTrans*/) +void GuiInfoPopup::render(const glm::mat4& /*parentTrans*/) { - // We use Identity() as we want to render on a specific window position, not on the view. - Transform4x4f trans = getTransform() * Transform4x4f::Identity(); + // We use getIdentity() as we want to render on a specific window position, not on the view. + glm::mat4 trans{getTransform() * Renderer::getIdentity()}; if (mRunning && updateState()) { // If we're still supposed to be rendering it. Renderer::setMatrix(trans); diff --git a/es-app/src/guis/GuiInfoPopup.h b/es-app/src/guis/GuiInfoPopup.h index 8de60ee3a..61b720ce4 100644 --- a/es-app/src/guis/GuiInfoPopup.h +++ b/es-app/src/guis/GuiInfoPopup.h @@ -21,7 +21,7 @@ public: GuiInfoPopup(Window* window, std::string message, int duration); ~GuiInfoPopup(); - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void stop() override { mRunning = false; } private: diff --git a/es-app/src/guis/GuiLaunchScreen.cpp b/es-app/src/guis/GuiLaunchScreen.cpp index b20977841..3dbf7089e 100644 --- a/es-app/src/guis/GuiLaunchScreen.cpp +++ b/es-app/src/guis/GuiLaunchScreen.cpp @@ -12,7 +12,6 @@ #include "SystemData.h" #include "components/ComponentGrid.h" #include "components/TextComponent.h" -#include "math/Misc.h" #include "utils/StringUtil.h" GuiLaunchScreen::GuiLaunchScreen(Window* window) @@ -34,7 +33,7 @@ GuiLaunchScreen::~GuiLaunchScreen() void GuiLaunchScreen::displayLaunchScreen(FileData* game) { - mGrid = new ComponentGrid(mWindow, Vector2i(3, 8)); + mGrid = new ComponentGrid(mWindow, glm::ivec2{3, 8}); addChild(mGrid); mImagePath = game->getMarqueePath(); @@ -51,8 +50,8 @@ void GuiLaunchScreen::displayLaunchScreen(FileData* game) const float gameNameFontSize = 0.073f; // Spacer row. - mGrid->setEntry(std::make_shared(mWindow), Vector2i(1, 0), false, false, - Vector2i(1, 1)); + mGrid->setEntry(std::make_shared(mWindow), glm::ivec2{1, 0}, false, false, + glm::ivec2{1, 1}); // Title. mTitle = std::make_shared( @@ -60,19 +59,19 @@ void GuiLaunchScreen::displayLaunchScreen(FileData* game) Font::get(static_cast( titleFontSize * std::min(Renderer::getScreenHeight(), Renderer::getScreenWidth()))), 0x666666FF, ALIGN_CENTER); - mGrid->setEntry(mTitle, Vector2i(1, 1), false, true, Vector2i(1, 1)); + mGrid->setEntry(mTitle, glm::ivec2{1, 1}, false, true, glm::ivec2{1, 1}); // Spacer row. - mGrid->setEntry(std::make_shared(mWindow), Vector2i(1, 2), false, false, - Vector2i(1, 1)); + mGrid->setEntry(std::make_shared(mWindow), glm::ivec2{1, 2}, false, false, + glm::ivec2{1, 1}); // Row for the marquee. - mGrid->setEntry(std::make_shared(mWindow), Vector2i(1, 3), false, false, - Vector2i(1, 1)); + mGrid->setEntry(std::make_shared(mWindow), glm::ivec2{1, 3}, false, false, + glm::ivec2{1, 1}); // Spacer row. - mGrid->setEntry(std::make_shared(mWindow), Vector2i(1, 4), false, false, - Vector2i(1, 1)); + mGrid->setEntry(std::make_shared(mWindow), glm::ivec2{1, 4}, false, false, + glm::ivec2{1, 1}); // Game name. mGameName = std::make_shared( @@ -80,32 +79,32 @@ void GuiLaunchScreen::displayLaunchScreen(FileData* game) Font::get(static_cast( gameNameFontSize * std::min(Renderer::getScreenHeight(), Renderer::getScreenWidth()))), 0x444444FF, ALIGN_CENTER); - mGrid->setEntry(mGameName, Vector2i(1, 5), false, true, Vector2i(1, 1)); + mGrid->setEntry(mGameName, glm::ivec2{1, 5}, false, true, glm::ivec2{1, 1}); // System name. mSystemName = std::make_shared( mWindow, "SYSTEM NAME", Font::get(FONT_SIZE_MEDIUM), 0x666666FF, ALIGN_CENTER); - mGrid->setEntry(mSystemName, Vector2i(1, 6), false, true, Vector2i(1, 1)); + mGrid->setEntry(mSystemName, glm::ivec2{1, 6}, false, true, glm::ivec2{1, 1}); // Spacer row. - mGrid->setEntry(std::make_shared(mWindow), Vector2i(1, 7), false, false, - Vector2i(1, 1)); + mGrid->setEntry(std::make_shared(mWindow), glm::ivec2{1, 7}, false, false, + glm::ivec2{1, 1}); // Left spacer. - mGrid->setEntry(std::make_shared(mWindow), Vector2i(0, 0), false, false, - Vector2i(1, 8)); + mGrid->setEntry(std::make_shared(mWindow), glm::ivec2{0, 0}, false, false, + glm::ivec2{1, 8}); // Right spacer. - mGrid->setEntry(std::make_shared(mWindow), Vector2i(2, 0), false, false, - Vector2i(1, 8)); + mGrid->setEntry(std::make_shared(mWindow), glm::ivec2{2, 0}, false, false, + glm::ivec2{1, 8}); // Adjust the width depending on the aspect ratio of the screen, to make the screen look // somewhat coherent regardless of screen type. The 1.778 aspect ratio value is the 16:9 // reference. float aspectValue = 1.778f / Renderer::getScreenAspectRatio(); - float maxWidthModifier = Math::clamp(0.78f * aspectValue, 0.78f, 0.90f); - float minWidthModifier = Math::clamp(0.50f * aspectValue, 0.50f, 0.65f); + float maxWidthModifier = glm::clamp(0.78f * aspectValue, 0.78f, 0.90f); + float minWidthModifier = glm::clamp(0.50f * aspectValue, 0.50f, 0.65f); float maxWidth = static_cast(Renderer::getScreenWidth()) * maxWidthModifier; float minWidth = static_cast(Renderer::getScreenWidth()) * minWidthModifier; @@ -114,12 +113,12 @@ void GuiLaunchScreen::displayLaunchScreen(FileData* game) Font::get(static_cast(gameNameFontSize * std::min(Renderer::getScreenHeight(), Renderer::getScreenWidth()))) ->sizeText(Utils::String::toUpper(game->getName())) - .x(); + .x; // Add a bit of width to compensate for the left and right spacers. fontWidth += static_cast(Renderer::getScreenWidth()) * 0.05f; - float width = Math::clamp(fontWidth, minWidth, maxWidth); + float width = glm::clamp(fontWidth, minWidth, maxWidth); if (mImagePath != "") setSize(width, static_cast(Renderer::getScreenHeight()) * 0.60f); @@ -131,15 +130,15 @@ void GuiLaunchScreen::displayLaunchScreen(FileData* game) mGrid->setRowHeightPerc(0, 0.09f, false); else mGrid->setRowHeightPerc(0, 0.15f, false); - mGrid->setRowHeightPerc(1, mTitle->getFont()->getLetterHeight() * 1.70f / mSize.y(), false); + mGrid->setRowHeightPerc(1, mTitle->getFont()->getLetterHeight() * 1.70f / mSize.y, false); mGrid->setRowHeightPerc(2, 0.05f, false); if (mImagePath != "") mGrid->setRowHeightPerc(3, 0.35f, false); else mGrid->setRowHeightPerc(3, 0.01f, false); mGrid->setRowHeightPerc(4, 0.05f, false); - mGrid->setRowHeightPerc(5, mGameName->getFont()->getHeight() * 0.80f / mSize.y(), false); - mGrid->setRowHeightPerc(6, mSystemName->getFont()->getHeight() * 0.90f / mSize.y(), false); + mGrid->setRowHeightPerc(5, mGameName->getFont()->getHeight() * 0.80f / mSize.y, false); + mGrid->setRowHeightPerc(6, mSystemName->getFont()->getHeight() * 0.90f / mSize.y, false); // Set left and right spacers column widths. mGrid->setColWidthPerc(0, 0.025f); @@ -153,7 +152,7 @@ void GuiLaunchScreen::displayLaunchScreen(FileData* game) for (int i = 0; i < 7; i++) totalRowHeight += mGrid->getRowHeight(i); - setSize(mSize.x(), totalRowHeight); + setSize(mSize.x, totalRowHeight); mGameName->setText(Utils::String::toUpper(game->getName())); mSystemName->setText(Utils::String::toUpper(game->getSystem()->getFullName())); @@ -163,29 +162,29 @@ void GuiLaunchScreen::displayLaunchScreen(FileData* game) // width so that the sizes look somewhat consistent regardless of the aspect ratio // of the images. if (mImagePath != "") { - mMarquee->setImage(game->getMarqueePath(), false); + mMarquee->setImage(game->getMarqueePath(), false, true); mMarquee->cropTransparentPadding(static_cast(Renderer::getScreenWidth()) * (0.25f * (1.778f / Renderer::getScreenAspectRatio())), mGrid->getRowHeight(3)); mMarquee->setOrigin(0.5f, 0.5f); - Vector3f currentPos = mMarquee->getPosition(); - Vector2f currentSize = mMarquee->getSize(); + glm::vec3 currentPos{mMarquee->getPosition()}; + glm::vec2 currentSize{mMarquee->getSize()}; // Position the image in the middle of row four. - currentPos.x() = mSize.x() / 2.0f; - currentPos.y() = mGrid->getRowHeight(0) + mGrid->getRowHeight(1) + mGrid->getRowHeight(2) + - mGrid->getRowHeight(3) / 2.0f; + currentPos.x = mSize.x / 2.0f; + currentPos.y = mGrid->getRowHeight(0) + mGrid->getRowHeight(1) + mGrid->getRowHeight(2) + + mGrid->getRowHeight(3) / 2.0f; mMarquee->setPosition(currentPos); } - setOrigin({ 0.5f, 0.5f }); + setOrigin({0.5f, 0.5f}); // Center on the X axis and keep slightly off-center on the Y axis. setPosition(static_cast(Renderer::getScreenWidth()) / 2.0f, static_cast(Renderer::getScreenHeight()) / 2.25f); - mBackground.fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); mBackground.setEdgeColor(0xEEEEEEFF); } @@ -219,7 +218,7 @@ void GuiLaunchScreen::update(int deltaTime) if (Settings::getInstance()->getString("MenuOpeningEffect") == "none") mScaleUp = 1.0f; else if (mScaleUp < 1.0f) - mScaleUp = Math::clamp(mScaleUp + 0.07f, 0.0f, 1.0f); + mScaleUp = glm::clamp(mScaleUp + 0.07f, 0.0f, 1.0f); } void GuiLaunchScreen::render() @@ -228,7 +227,7 @@ void GuiLaunchScreen::render() if (mScaleUp < 1.0f) setScale(mScaleUp); - Transform4x4f trans = Transform4x4f::Identity() * getTransform(); + glm::mat4 trans{Renderer::getIdentity() * getTransform()}; Renderer::setMatrix(trans); GuiComponent::renderChildren(trans); diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 3cd80dc9f..e77910616 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -20,6 +20,7 @@ #include "components/OptionListComponent.h" #include "components/SliderComponent.h" #include "components/SwitchComponent.h" +#include "guis/GuiAlternativeEmulators.h" #include "guis/GuiCollectionSystemsOptions.h" #include "guis/GuiComplexTextEditPopup.h" #include "guis/GuiDetectDevice.h" @@ -75,8 +76,7 @@ GuiMenu::GuiMenu(Window* window) addChild(&mMenu); addVersionInfo(); setSize(mMenu.getSize()); - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, - Renderer::getScreenHeight() * 0.13f); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, Renderer::getScreenHeight() * 0.13f); } GuiMenu::~GuiMenu() @@ -87,7 +87,11 @@ GuiMenu::~GuiMenu() ViewController::get()->stopScrolling(); } -void GuiMenu::openScraperOptions() { mWindow->pushGui(new GuiScraperMenu(mWindow, "SCRAPER")); } +void GuiMenu::openScraperOptions() +{ + // Open the scraper menu. + mWindow->pushGui(new GuiScraperMenu(mWindow, "SCRAPER")); +} void GuiMenu::openUIOptions() { @@ -97,17 +101,16 @@ void GuiMenu::openUIOptions() auto startup_system = std::make_shared>( mWindow, getHelpStyle(), "GAMELIST ON STARTUP", false); startup_system->add("NONE", "", Settings::getInstance()->getString("StartupSystem") == ""); - float dotsSize = Font::get(FONT_SIZE_MEDIUM)->sizeText("...").x(); + float dotsSize = Font::get(FONT_SIZE_MEDIUM)->sizeText("...").x; for (auto it = SystemData::sSystemVector.cbegin(); it != SystemData::sSystemVector.cend(); it++) { if ((*it)->getName() != "retropie") { // If required, abbreviate the system name so it doesn't overlap the setting name. std::string abbreviatedString = - Font::get(FONT_SIZE_MEDIUM) - ->getTextMaxWidth((*it)->getFullName(), mSize.x() * 0.47f); - float sizeDifference = Font::get(FONT_SIZE_MEDIUM)->sizeText((*it)->getFullName()).x() - - Font::get(FONT_SIZE_MEDIUM)->sizeText(abbreviatedString).x(); - if (sizeDifference > 0) { + Font::get(FONT_SIZE_MEDIUM)->getTextMaxWidth((*it)->getFullName(), mSize.x * 0.47f); + float sizeDifference = Font::get(FONT_SIZE_MEDIUM)->sizeText((*it)->getFullName()).x - + Font::get(FONT_SIZE_MEDIUM)->sizeText(abbreviatedString).x; + if (sizeDifference > 0.0f) { // It doesn't make sense to abbreviate if the number of pixels removed by // the abbreviation is less or equal to the size of the three dots that // would be appended to the string. @@ -374,6 +377,28 @@ void GuiMenu::openUIOptions() } }); + // Media viewer. + ComponentListRow media_viewer_row; + media_viewer_row.elements.clear(); + media_viewer_row.addElement(std::make_shared(mWindow, "MEDIA VIEWER SETTINGS", + Font::get(FONT_SIZE_MEDIUM), + 0x777777FF), + true); + media_viewer_row.addElement(makeArrow(mWindow), false); + media_viewer_row.makeAcceptInputHandler(std::bind(&GuiMenu::openMediaViewerOptions, this)); + s->addRow(media_viewer_row); + + // Screensaver. + ComponentListRow screensaver_row; + screensaver_row.elements.clear(); + screensaver_row.addElement(std::make_shared(mWindow, "SCREENSAVER SETTINGS", + Font::get(FONT_SIZE_MEDIUM), + 0x777777FF), + true); + screensaver_row.addElement(makeArrow(mWindow), false); + screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this)); + s->addRow(screensaver_row); + #if defined(USE_OPENGL_21) // Blur background when the menu is open. auto menu_blur_background = std::make_shared(mWindow); @@ -556,28 +581,6 @@ void GuiMenu::openUIOptions() } }); - // Media viewer. - ComponentListRow media_viewer_row; - media_viewer_row.elements.clear(); - media_viewer_row.addElement(std::make_shared(mWindow, "MEDIA VIEWER SETTINGS", - Font::get(FONT_SIZE_MEDIUM), - 0x777777FF), - true); - media_viewer_row.addElement(makeArrow(mWindow), false); - media_viewer_row.makeAcceptInputHandler(std::bind(&GuiMenu::openMediaViewerOptions, this)); - s->addRow(media_viewer_row); - - // Screensaver. - ComponentListRow screensaver_row; - screensaver_row.elements.clear(); - screensaver_row.addElement(std::make_shared(mWindow, "SCREENSAVER SETTINGS", - Font::get(FONT_SIZE_MEDIUM), - 0x777777FF), - true); - screensaver_row.addElement(makeArrow(mWindow), false); - screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this)); - s->addRow(screensaver_row); - mWindow->pushGui(s); } @@ -770,6 +773,49 @@ void GuiMenu::openOtherOptions() { auto s = new GuiSettings(mWindow, "OTHER SETTINGS"); + // Alternative emulators GUI. + ComponentListRow alternativeEmulatorsRow; + alternativeEmulatorsRow.elements.clear(); + alternativeEmulatorsRow.addElement( + std::make_shared(mWindow, "ALTERNATIVE EMULATORS", + Font::get(FONT_SIZE_MEDIUM), 0x777777FF), + true); + alternativeEmulatorsRow.addElement(makeArrow(mWindow), false); + alternativeEmulatorsRow.makeAcceptInputHandler( + std::bind([this] { mWindow->pushGui(new GuiAlternativeEmulators(mWindow)); })); + s->addRow(alternativeEmulatorsRow); + + // Game media directory. + ComponentListRow rowMediaDir; + auto media_directory = std::make_shared(mWindow, "GAME MEDIA DIRECTORY", + Font::get(FONT_SIZE_MEDIUM), 0x777777FF); + auto bracketMediaDirectory = std::make_shared(mWindow); + bracketMediaDirectory->setImage(":/graphics/arrow.svg"); + bracketMediaDirectory->setResize( + glm::vec2{0.0f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()}); + rowMediaDir.addElement(media_directory, true); + rowMediaDir.addElement(bracketMediaDirectory, false); + std::string titleMediaDir = "ENTER GAME MEDIA DIRECTORY"; + std::string mediaDirectoryStaticText = "Default directory:"; + std::string defaultDirectoryText = "~/.emulationstation/downloaded_media/"; + std::string initValueMediaDir = Settings::getInstance()->getString("MediaDirectory"); + bool multiLineMediaDir = false; + auto updateValMediaDir = [this](const std::string& newVal) { + Settings::getInstance()->setString("MediaDirectory", newVal); + Settings::getInstance()->saveFile(); + ViewController::get()->reloadAll(); + mWindow->invalidateCachedBackground(); + }; + rowMediaDir.makeAcceptInputHandler([this, titleMediaDir, mediaDirectoryStaticText, + defaultDirectoryText, initValueMediaDir, updateValMediaDir, + multiLineMediaDir] { + mWindow->pushGui(new GuiComplexTextEditPopup( + mWindow, getHelpStyle(), titleMediaDir, mediaDirectoryStaticText, defaultDirectoryText, + Settings::getInstance()->getString("MediaDirectory"), updateValMediaDir, + multiLineMediaDir, "SAVE", "SAVE CHANGES?")); + }); + s->addRow(rowMediaDir); + // Maximum VRAM. auto max_vram = std::make_shared(mWindow, 80.f, 1024.f, 8.f, "MiB"); max_vram->setValue(static_cast(Settings::getInstance()->getInt("MaxVRAM"))); @@ -893,36 +939,6 @@ void GuiMenu::openOtherOptions() } }); - // Game media directory. - ComponentListRow rowMediaDir; - auto media_directory = std::make_shared(mWindow, "GAME MEDIA DIRECTORY", - Font::get(FONT_SIZE_MEDIUM), 0x777777FF); - auto bracketMediaDirectory = std::make_shared(mWindow); - bracketMediaDirectory->setImage(":/graphics/arrow.svg"); - bracketMediaDirectory->setResize(Vector2f(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight())); - rowMediaDir.addElement(media_directory, true); - rowMediaDir.addElement(bracketMediaDirectory, false); - std::string titleMediaDir = "ENTER GAME MEDIA DIRECTORY"; - std::string mediaDirectoryStaticText = "Default directory:"; - std::string defaultDirectoryText = "~/.emulationstation/downloaded_media/"; - std::string initValueMediaDir = Settings::getInstance()->getString("MediaDirectory"); - bool multiLineMediaDir = false; - auto updateValMediaDir = [this](const std::string& newVal) { - Settings::getInstance()->setString("MediaDirectory", newVal); - Settings::getInstance()->saveFile(); - ViewController::get()->reloadAll(); - mWindow->invalidateCachedBackground(); - }; - rowMediaDir.makeAcceptInputHandler([this, titleMediaDir, mediaDirectoryStaticText, - defaultDirectoryText, initValueMediaDir, updateValMediaDir, - multiLineMediaDir] { - mWindow->pushGui(new GuiComplexTextEditPopup( - mWindow, getHelpStyle(), titleMediaDir, mediaDirectoryStaticText, defaultDirectoryText, - Settings::getInstance()->getString("MediaDirectory"), updateValMediaDir, - multiLineMediaDir, "SAVE", "SAVE CHANGES?")); - }); - s->addRow(rowMediaDir); - #if defined(_WIN64) // Hide taskbar during the ES program session. auto hide_taskbar = std::make_shared(mWindow); @@ -1259,8 +1275,8 @@ void GuiMenu::openCollectionSystemOptions() void GuiMenu::onSizeChanged() { - mVersion.setSize(mSize.x(), 0); - mVersion.setPosition(0, mSize.y() - mVersion.getSize().y()); + mVersion.setSize(mSize.x, 0.0f); + mVersion.setPosition(0.0f, mSize.y - mVersion.getSize().y); } void GuiMenu::addEntry(const std::string& name, diff --git a/es-app/src/guis/GuiMetaDataEd.cpp b/es-app/src/guis/GuiMetaDataEd.cpp index bce30d558..3ce434094 100644 --- a/es-app/src/guis/GuiMetaDataEd.cpp +++ b/es-app/src/guis/GuiMetaDataEd.cpp @@ -42,7 +42,7 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, : GuiComponent(window) , mScraperParams(scraperParams) , mBackground(window, ":/graphics/frame.svg") - , mGrid(window, Vector2i(1, 3)) + , mGrid(window, glm::ivec2{1, 3}) , mMetaDataDecl(mdd) , mMetaData(md) , mSavedCallback(saveCallback) @@ -53,7 +53,7 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, addChild(&mBackground); addChild(&mGrid); - mHeaderGrid = std::make_shared(mWindow, Vector2i(1, 5)); + mHeaderGrid = std::make_shared(mWindow, glm::ivec2{1, 5}); mTitle = std::make_shared(mWindow, "EDIT METADATA", Font::get(FONT_SIZE_LARGE), 0x555555FF, ALIGN_CENTER); @@ -78,15 +78,15 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, folderPath + Utils::FileSystem::getFileName(scraperParams.game->getPath()) + " [" + Utils::String::toUpper(scraperParams.system->getName()) + "]" + (scraperParams.game->getType() == FOLDER ? " " + ViewController::FOLDER_CHAR : ""), - Font::get(FONT_SIZE_SMALL), 0x777777FF, ALIGN_CENTER, Vector3f(0.0f, 0.0f, 0.0f), - Vector2f(0.0f, 0.0f), 0x00000000, 0.05f); - mHeaderGrid->setEntry(mTitle, Vector2i(0, 1), false, true); - mHeaderGrid->setEntry(mSubtitle, Vector2i(0, 3), false, true); + Font::get(FONT_SIZE_SMALL), 0x777777FF, ALIGN_CENTER, glm::vec3{}, glm::vec2{}, 0x00000000, + 0.05f); + mHeaderGrid->setEntry(mTitle, glm::ivec2{0, 1}, false, true); + mHeaderGrid->setEntry(mSubtitle, glm::ivec2{0, 3}, false, true); - mGrid.setEntry(mHeaderGrid, Vector2i(0, 0), false, true); + mGrid.setEntry(mHeaderGrid, glm::ivec2{0, 0}, false, true); mList = std::make_shared(mWindow); - mGrid.setEntry(mList, Vector2i(0, 1), true, true); + mGrid.setEntry(mList, glm::ivec2{0, 1}, true, true); // Populate list. for (auto iter = mdd.cbegin(); iter != mdd.cend(); iter++) { @@ -123,8 +123,8 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, case MD_BOOL: { ed = std::make_shared(window); // Make the switches slightly smaller. - auto switchSize = ed->getSize() * 0.9f; - ed->setResize(switchSize.x(), switchSize.y()); + glm::vec2 switchSize{ed->getSize() * 0.9f}; + ed->setResize(switchSize.x, switchSize.y); ed->setOrigin(-0.05f, -0.09f); ed->setChangedColor(ICONCOLOR_USERMARKED); @@ -138,8 +138,8 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, ed = std::make_shared(window, true); ed->setChangedColor(ICONCOLOR_USERMARKED); - const float height = lbl->getSize().y() * 0.71f; - ed->setSize(0, height); + const float height = lbl->getSize().y * 0.71f; + ed->setSize(0.0f, height); row.addElement(ed, false, true); auto ratingSpacer = std::make_shared(mWindow); @@ -182,7 +182,7 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, auto bracket = std::make_shared(mWindow); bracket->setImage(":/graphics/arrow.svg"); - bracket->setResize(Vector2f(0, lbl->getFont()->getLetterHeight())); + bracket->setResize(glm::vec2{0.0f, lbl->getFont()->getLetterHeight()}); row.addElement(bracket, false); bool multiLine = false; @@ -198,8 +198,28 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, }; std::string staticTextString = "Default value from es_systems.xml:"; - std::string defaultLaunchCommand = - scraperParams.system->getSystemEnvData()->mLaunchCommand; + std::string defaultLaunchCommand; + + std::string alternativeEmulator = scraperParams.system->getAlternativeEmulator(); + for (auto launchCommand : + scraperParams.system->getSystemEnvData()->mLaunchCommands) { + if (launchCommand.second == alternativeEmulator) { + defaultLaunchCommand = launchCommand.first; + break; + } + } + if (!alternativeEmulator.empty() && defaultLaunchCommand.empty()) { + LOG(LogWarning) + << "The alternative emulator defined for system \"" + << scraperParams.system->getName() + << "\" is invalid, falling back to the default command \"" + << scraperParams.system->getSystemEnvData()->mLaunchCommands.front().first + << "\""; + } + + if (defaultLaunchCommand.empty()) + defaultLaunchCommand = + scraperParams.system->getSystemEnvData()->mLaunchCommands.front().first; row.makeAcceptInputHandler([this, title, staticTextString, defaultLaunchCommand, ed, updateVal, multiLine] { @@ -223,7 +243,7 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, auto bracket = std::make_shared(mWindow); bracket->setImage(":/graphics/arrow.svg"); - bracket->setResize(Vector2f(0, lbl->getFont()->getLetterHeight())); + bracket->setResize(glm::vec2{0.0f, lbl->getFont()->getLetterHeight()}); row.addElement(bracket, false); bool multiLine = iter->type == MD_MULTILINE_STRING; @@ -346,15 +366,15 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, } mButtons = makeButtonGrid(mWindow, buttons); - mGrid.setEntry(mButtons, Vector2i(0, 2), true, false); + mGrid.setEntry(mButtons, glm::ivec2{0, 2}, true, false); // Resize + center. float width = static_cast(std::min(static_cast(Renderer::getScreenHeight() * 1.05f), static_cast(Renderer::getScreenWidth() * 0.90f))); setSize(width, Renderer::getScreenHeight() * 0.83f); - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, - (Renderer::getScreenHeight() - mSize.y()) / 2.0f); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, + (Renderer::getScreenHeight() - mSize.y) / 2.0f); } void GuiMetaDataEd::onSizeChanged() @@ -363,19 +383,19 @@ void GuiMetaDataEd::onSizeChanged() const float titleHeight = mTitle->getFont()->getLetterHeight(); const float subtitleHeight = mSubtitle->getFont()->getLetterHeight(); - const float titleSubtitleSpacing = mSize.y() * 0.03f; + const float titleSubtitleSpacing = mSize.y * 0.03f; mGrid.setRowHeightPerc( - 0, (titleHeight + titleSubtitleSpacing + subtitleHeight + TITLE_VERT_PADDING) / mSize.y()); - mGrid.setRowHeightPerc(2, mButtons->getSize().y() / mSize.y()); + 0, (titleHeight + titleSubtitleSpacing + subtitleHeight + TITLE_VERT_PADDING) / mSize.y); + mGrid.setRowHeightPerc(2, mButtons->getSize().y / mSize.y); // Snap list size to the row height to prevent a fraction of a row from being displayed. - float listHeight = 0; - float listSize = mList->getSize().y(); + float listHeight = 0.0f; + float listSize = mList->getSize().y; int i = 0; while (i < mList->size()) { // Add the separator height to the row height so that it also gets properly rendered. - float rowHeight = mList->getRowHeight(i) + (1 * Renderer::getScreenHeightModifier()); + float rowHeight = mList->getRowHeight(i) + Renderer::getScreenHeightModifier(); if (listHeight + rowHeight < listSize) listHeight += rowHeight; else @@ -385,19 +405,19 @@ void GuiMetaDataEd::onSizeChanged() // Adjust the size of the list and window. float heightAdjustment = listSize - listHeight; - mList->setSize(mList->getSize().x(), listHeight); - Vector2f newWindowSize = mSize; - newWindowSize.y() -= heightAdjustment; - mBackground.fitTo(newWindowSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mList->setSize(mList->getSize().x, listHeight); + glm::vec2 newWindowSize{mSize}; + newWindowSize.y -= heightAdjustment; + mBackground.fitTo(newWindowSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); // Move the buttons up as well to make the layout align correctly after the resize. - Vector3f newButtonPos = mButtons->getPosition(); - newButtonPos.y() -= heightAdjustment; + glm::vec3 newButtonPos{mButtons->getPosition()}; + newButtonPos.y -= heightAdjustment; mButtons->setPosition(newButtonPos); - mHeaderGrid->setRowHeightPerc(1, titleHeight / mHeaderGrid->getSize().y()); - mHeaderGrid->setRowHeightPerc(2, titleSubtitleSpacing / mHeaderGrid->getSize().y()); - mHeaderGrid->setRowHeightPerc(3, subtitleHeight / mHeaderGrid->getSize().y()); + mHeaderGrid->setRowHeightPerc(1, titleHeight / mHeaderGrid->getSize().y); + mHeaderGrid->setRowHeightPerc(2, titleSubtitleSpacing / mHeaderGrid->getSize().y); + mHeaderGrid->setRowHeightPerc(3, subtitleHeight / mHeaderGrid->getSize().y); } void GuiMetaDataEd::save() diff --git a/es-app/src/guis/GuiOfflineGenerator.cpp b/es-app/src/guis/GuiOfflineGenerator.cpp index 8b6f3c506..4bd6f84b8 100644 --- a/es-app/src/guis/GuiOfflineGenerator.cpp +++ b/es-app/src/guis/GuiOfflineGenerator.cpp @@ -16,7 +16,7 @@ GuiOfflineGenerator::GuiOfflineGenerator(Window* window, const std::queue& gameQueue) : GuiComponent(window) , mBackground(window, ":/graphics/frame.svg") - , mGrid(window, Vector2i(6, 13)) + , mGrid(window, glm::ivec2{6, 13}) , mGameQueue(gameQueue) { addChild(&mBackground); @@ -38,100 +38,100 @@ GuiOfflineGenerator::GuiOfflineGenerator(Window* window, const std::queue(mWindow, "MIXIMAGE OFFLINE GENERATOR", Font::get(FONT_SIZE_LARGE), 0x555555FF, ALIGN_CENTER); - mGrid.setEntry(mTitle, Vector2i(0, 0), false, true, Vector2i(6, 1)); + mGrid.setEntry(mTitle, glm::ivec2{0, 0}, false, true, glm::ivec2{6, 1}); mStatus = std::make_shared(mWindow, "NOT STARTED", Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_CENTER); - mGrid.setEntry(mStatus, Vector2i(0, 1), false, true, Vector2i(6, 1)); + mGrid.setEntry(mStatus, glm::ivec2{0, 1}, false, true, glm::ivec2{6, 1}); mGameCounter = std::make_shared( mWindow, std::to_string(mGamesProcessed) + " OF " + std::to_string(mTotalGames) + (mTotalGames == 1 ? " GAME " : " GAMES ") + "PROCESSED", Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_CENTER); - mGrid.setEntry(mGameCounter, Vector2i(0, 2), false, true, Vector2i(6, 1)); + mGrid.setEntry(mGameCounter, glm::ivec2{0, 2}, false, true, glm::ivec2{6, 1}); // Spacer row with top border. - mGrid.setEntry(std::make_shared(mWindow), Vector2i(0, 3), false, false, - Vector2i(6, 1), GridFlags::BORDER_TOP); + mGrid.setEntry(std::make_shared(mWindow), glm::ivec2{0, 3}, false, false, + glm::ivec2{6, 1}, GridFlags::BORDER_TOP); // Left spacer. - mGrid.setEntry(std::make_shared(mWindow), Vector2i(0, 4), false, false, - Vector2i(1, 7)); + mGrid.setEntry(std::make_shared(mWindow), glm::ivec2{0, 4}, false, false, + glm::ivec2{1, 7}); // Generated label. mGeneratedLbl = std::make_shared( mWindow, "Generated:", Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mGeneratedLbl, Vector2i(1, 4), false, true, Vector2i(1, 1)); + mGrid.setEntry(mGeneratedLbl, glm::ivec2{1, 4}, false, true, glm::ivec2{1, 1}); // Generated value/counter. mGeneratedVal = std::make_shared(mWindow, std::to_string(mGamesProcessed), Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mGeneratedVal, Vector2i(2, 4), false, true, Vector2i(1, 1)); + mGrid.setEntry(mGeneratedVal, glm::ivec2{2, 4}, false, true, glm::ivec2{1, 1}); // Overwritten label. mOverwrittenLbl = std::make_shared( mWindow, "Overwritten:", Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mOverwrittenLbl, Vector2i(1, 5), false, true, Vector2i(1, 1)); + mGrid.setEntry(mOverwrittenLbl, glm::ivec2{1, 5}, false, true, glm::ivec2{1, 1}); // Overwritten value/counter. mOverwrittenVal = std::make_shared(mWindow, std::to_string(mImagesOverwritten), Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mOverwrittenVal, Vector2i(2, 5), false, true, Vector2i(1, 1)); + mGrid.setEntry(mOverwrittenVal, glm::ivec2{2, 5}, false, true, glm::ivec2{1, 1}); // Skipping label. mSkippedLbl = std::make_shared( mWindow, "Skipped (existing):", Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mSkippedLbl, Vector2i(1, 6), false, true, Vector2i(1, 1)); + mGrid.setEntry(mSkippedLbl, glm::ivec2{1, 6}, false, true, glm::ivec2{1, 1}); // Skipping value/counter. mSkippedVal = std::make_shared( mWindow, std::to_string(mGamesSkipped), Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mSkippedVal, Vector2i(2, 6), false, true, Vector2i(1, 1)); + mGrid.setEntry(mSkippedVal, glm::ivec2{2, 6}, false, true, glm::ivec2{1, 1}); // Failed label. mFailedLbl = std::make_shared(mWindow, "Failed:", Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mFailedLbl, Vector2i(1, 7), false, true, Vector2i(1, 1)); + mGrid.setEntry(mFailedLbl, glm::ivec2{1, 7}, false, true, glm::ivec2{1, 1}); // Failed value/counter. mFailedVal = std::make_shared( mWindow, std::to_string(mGamesFailed), Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mFailedVal, Vector2i(2, 7), false, true, Vector2i(1, 1)); + mGrid.setEntry(mFailedVal, glm::ivec2{2, 7}, false, true, glm::ivec2{1, 1}); // Processing label. mProcessingLbl = std::make_shared( mWindow, "Processing: ", Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mProcessingLbl, Vector2i(3, 4), false, true, Vector2i(1, 1)); + mGrid.setEntry(mProcessingLbl, glm::ivec2{3, 4}, false, true, glm::ivec2{1, 1}); // Processing value. mProcessingVal = std::make_shared(mWindow, "", Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mProcessingVal, Vector2i(4, 4), false, true, Vector2i(1, 1)); + mGrid.setEntry(mProcessingVal, glm::ivec2{4, 4}, false, true, glm::ivec2{1, 1}); // Spacer row. - mGrid.setEntry(std::make_shared(mWindow), Vector2i(1, 8), false, false, - Vector2i(4, 1)); + mGrid.setEntry(std::make_shared(mWindow), glm::ivec2{1, 8}, false, false, + glm::ivec2{4, 1}); // Last error message label. mLastErrorLbl = std::make_shared( mWindow, "Last error message:", Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mLastErrorLbl, Vector2i(1, 9), false, true, Vector2i(4, 1)); + mGrid.setEntry(mLastErrorLbl, glm::ivec2{1, 9}, false, true, glm::ivec2{4, 1}); // Last error message value. mLastErrorVal = std::make_shared(mWindow, "", Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_LEFT); - mGrid.setEntry(mLastErrorVal, Vector2i(1, 10), false, true, Vector2i(4, 1)); + mGrid.setEntry(mLastErrorVal, glm::ivec2{1, 10}, false, true, glm::ivec2{4, 1}); // Right spacer. - mGrid.setEntry(std::make_shared(mWindow), Vector2i(5, 4), false, false, - Vector2i(1, 7)); + mGrid.setEntry(std::make_shared(mWindow), glm::ivec2{5, 4}, false, false, + glm::ivec2{1, 7}); // Spacer row with bottom border. - mGrid.setEntry(std::make_shared(mWindow), Vector2i(0, 11), false, false, - Vector2i(6, 1), GridFlags::BORDER_BOTTOM); + mGrid.setEntry(std::make_shared(mWindow), glm::ivec2{0, 11}, false, false, + glm::ivec2{6, 1}, GridFlags::BORDER_BOTTOM); // Buttons. std::vector> buttons; @@ -177,7 +177,7 @@ GuiOfflineGenerator::GuiOfflineGenerator(Window* window, const std::queuegetFont()->getLetterHeight() * 1.9725f / mSize.y(), false); - mGrid.setRowHeightPerc(1, (mStatus->getFont()->getLetterHeight() + 2.0f) / mSize.y(), false); - mGrid.setRowHeightPerc(2, mGameCounter->getFont()->getHeight() * 1.75f / mSize.y(), false); - mGrid.setRowHeightPerc(3, (mStatus->getFont()->getLetterHeight() + 3.0f) / mSize.y(), false); + mGrid.setRowHeightPerc(0, mTitle->getFont()->getLetterHeight() * 1.9725f / mSize.y, false); + mGrid.setRowHeightPerc(1, (mStatus->getFont()->getLetterHeight() + 2.0f) / mSize.y, false); + mGrid.setRowHeightPerc(2, mGameCounter->getFont()->getHeight() * 1.75f / mSize.y, false); + mGrid.setRowHeightPerc(3, (mStatus->getFont()->getLetterHeight() + 3.0f) / mSize.y, false); mGrid.setRowHeightPerc(4, 0.07f, false); mGrid.setRowHeightPerc(5, 0.07f, false); mGrid.setRowHeightPerc(6, 0.07f, false); @@ -217,7 +217,7 @@ void GuiOfflineGenerator::onSizeChanged() mGrid.setRowHeightPerc(8, 0.02f, false); mGrid.setRowHeightPerc(9, 0.07f, false); mGrid.setRowHeightPerc(10, 0.07f, false); - mGrid.setRowHeightPerc(12, mButtonGrid->getSize().y() / mSize.y(), false); + mGrid.setRowHeightPerc(12, mButtonGrid->getSize().y / mSize.y, false); // Set column widths. mGrid.setColWidthPerc(0, 0.03f); diff --git a/es-app/src/guis/GuiScraperMenu.cpp b/es-app/src/guis/GuiScraperMenu.cpp index 4040c0e50..b85698e59 100644 --- a/es-app/src/guis/GuiScraperMenu.cpp +++ b/es-app/src/guis/GuiScraperMenu.cpp @@ -140,8 +140,7 @@ GuiScraperMenu::GuiScraperMenu(Window* window, std::string title) setSize(mMenu.getSize()); - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, - Renderer::getScreenHeight() * 0.13f); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, Renderer::getScreenHeight() * 0.13f); } GuiScraperMenu::~GuiScraperMenu() diff --git a/es-app/src/guis/GuiScraperMulti.cpp b/es-app/src/guis/GuiScraperMulti.cpp index 222bf926e..441c23353 100644 --- a/es-app/src/guis/GuiScraperMulti.cpp +++ b/es-app/src/guis/GuiScraperMulti.cpp @@ -28,7 +28,7 @@ GuiScraperMulti::GuiScraperMulti(Window* window, bool approveResults) : GuiComponent(window) , mBackground(window, ":/graphics/frame.svg") - , mGrid(window, Vector2i(1, 5)) + , mGrid(window, glm::ivec2{1, 5}) , mSearchQueue(searches) , mApproveResults(approveResults) { @@ -47,15 +47,15 @@ GuiScraperMulti::GuiScraperMulti(Window* window, // Set up grid. mTitle = std::make_shared(mWindow, "SCRAPING IN PROGRESS", Font::get(FONT_SIZE_LARGE), 0x555555FF, ALIGN_CENTER); - mGrid.setEntry(mTitle, Vector2i(0, 0), false, true); + mGrid.setEntry(mTitle, glm::ivec2{0, 0}, false, true); mSystem = std::make_shared(mWindow, "SYSTEM", Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_CENTER); - mGrid.setEntry(mSystem, Vector2i(0, 1), false, true); + mGrid.setEntry(mSystem, glm::ivec2{0, 1}, false, true); mSubtitle = std::make_shared( mWindow, "subtitle text", Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_CENTER); - mGrid.setEntry(mSubtitle, Vector2i(0, 2), false, true); + mGrid.setEntry(mSubtitle, glm::ivec2{0, 2}, false, true); if (mApproveResults && !Settings::getInstance()->getBool("ScraperSemiautomatic")) mSearchComp = std::make_shared( @@ -70,7 +70,7 @@ GuiScraperMulti::GuiScraperMulti(Window* window, std::bind(&GuiScraperMulti::acceptResult, this, std::placeholders::_1)); mSearchComp->setSkipCallback(std::bind(&GuiScraperMulti::skip, this)); mSearchComp->setCancelCallback(std::bind(&GuiScraperMulti::finish, this)); - mGrid.setEntry(mSearchComp, Vector2i(0, 3), + mGrid.setEntry(mSearchComp, glm::ivec2{0, 3}, mSearchComp->getSearchType() != GuiScraperSearch::ALWAYS_ACCEPT_FIRST_RESULT, true); @@ -102,16 +102,16 @@ GuiScraperMulti::GuiScraperMulti(Window* window, std::bind(&GuiScraperMulti::finish, this))); mButtonGrid = makeButtonGrid(mWindow, buttons); - mGrid.setEntry(mButtonGrid, Vector2i(0, 4), true, false); + mGrid.setEntry(mButtonGrid, glm::ivec2{0, 4}, true, false); // Limit the width of the GUI on ultrawide monitors. The 1.778 aspect ratio value is // the 16:9 reference. float aspectValue = 1.778f / Renderer::getScreenAspectRatio(); - float width = Math::clamp(0.95f * aspectValue, 0.70f, 0.95f) * Renderer::getScreenWidth(); + float width = glm::clamp(0.95f * aspectValue, 0.70f, 0.95f) * Renderer::getScreenWidth(); setSize(width, Renderer::getScreenHeight() * 0.849f); - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, - (Renderer::getScreenHeight() - mSize.y()) / 2.0f); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, + (Renderer::getScreenHeight() - mSize.y) / 2.0f); doNextSearch(); } @@ -130,12 +130,12 @@ GuiScraperMulti::~GuiScraperMulti() void GuiScraperMulti::onSizeChanged() { - mBackground.fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); - mGrid.setRowHeightPerc(0, mTitle->getFont()->getLetterHeight() * 1.9725f / mSize.y(), false); - mGrid.setRowHeightPerc(1, (mSystem->getFont()->getLetterHeight() + 2.0f) / mSize.y(), false); - mGrid.setRowHeightPerc(2, mSubtitle->getFont()->getHeight() * 1.75f / mSize.y(), false); - mGrid.setRowHeightPerc(4, mButtonGrid->getSize().y() / mSize.y(), false); + mGrid.setRowHeightPerc(0, mTitle->getFont()->getLetterHeight() * 1.9725f / mSize.y, false); + mGrid.setRowHeightPerc(1, (mSystem->getFont()->getLetterHeight() + 2.0f) / mSize.y, false); + mGrid.setRowHeightPerc(2, mSubtitle->getFont()->getHeight() * 1.75f / mSize.y, false); + mGrid.setRowHeightPerc(4, mButtonGrid->getSize().y / mSize.y, false); mGrid.setSize(mSize); } diff --git a/es-app/src/guis/GuiScraperSearch.cpp b/es-app/src/guis/GuiScraperSearch.cpp index 04c8dc48a..e12edd803 100644 --- a/es-app/src/guis/GuiScraperSearch.cpp +++ b/es-app/src/guis/GuiScraperSearch.cpp @@ -38,7 +38,7 @@ GuiScraperSearch::GuiScraperSearch(Window* window, SearchType type, unsigned int scrapeCount) : GuiComponent(window) - , mGrid(window, Vector2i(4, 3)) + , mGrid(window, glm::ivec2{4, 3}) , mBusyAnim(window) , mSearchType(type) , mScrapeCount(scrapeCount) @@ -54,8 +54,8 @@ GuiScraperSearch::GuiScraperSearch(Window* window, SearchType type, unsigned int mRetryCount = 0; // Left spacer (empty component, needed for borders). - mGrid.setEntry(std::make_shared(mWindow), Vector2i(0, 0), false, false, - Vector2i(1, 3), GridFlags::BORDER_TOP | GridFlags::BORDER_BOTTOM); + mGrid.setEntry(std::make_shared(mWindow), glm::ivec2{0, 0}, false, false, + glm::ivec2{1, 3}, GridFlags::BORDER_TOP | GridFlags::BORDER_BOTTOM); // Selected result name. mResultName = std::make_shared(mWindow, "Result name", @@ -63,7 +63,7 @@ GuiScraperSearch::GuiScraperSearch(Window* window, SearchType type, unsigned int // Selected result thumbnail. mResultThumbnail = std::make_shared(mWindow); - mGrid.setEntry(mResultThumbnail, Vector2i(1, 1), false, false, Vector2i(1, 1)); + mGrid.setEntry(mResultThumbnail, glm::ivec2{1, 1}, false, false, glm::ivec2{1, 1}); // Selected result description and container. mDescContainer = std::make_shared(mWindow); @@ -87,18 +87,14 @@ GuiScraperSearch::GuiScraperSearch(Window* window, SearchType type, unsigned int mMD_ReleaseDate = std::make_shared(mWindow); mMD_ReleaseDate->setColor(mdColor); mMD_ReleaseDate->setUppercase(true); - mMD_Developer = - std::make_shared(mWindow, "", font, mdColor, ALIGN_LEFT, Vector3f::Zero(), - Vector2f::Zero(), 0x00000000, 0.02f); - mMD_Publisher = - std::make_shared(mWindow, "", font, mdColor, ALIGN_LEFT, Vector3f::Zero(), - Vector2f::Zero(), 0x00000000, 0.02f); - mMD_Genre = - std::make_shared(mWindow, "", font, mdColor, ALIGN_LEFT, Vector3f::Zero(), - Vector2f::Zero(), 0x00000000, 0.02f); - mMD_Players = - std::make_shared(mWindow, "", font, mdColor, ALIGN_LEFT, Vector3f::Zero(), - Vector2f::Zero(), 0x00000000, 0.02f); + mMD_Developer = std::make_shared(mWindow, "", font, mdColor, ALIGN_LEFT, + glm::vec3{}, glm::vec2{}, 0x00000000, 0.02f); + mMD_Publisher = std::make_shared(mWindow, "", font, mdColor, ALIGN_LEFT, + glm::vec3{}, glm::vec2{}, 0x00000000, 0.02f); + mMD_Genre = std::make_shared(mWindow, "", font, mdColor, ALIGN_LEFT, glm::vec3{}, + glm::vec2{}, 0x00000000, 0.02f); + mMD_Players = std::make_shared(mWindow, "", font, mdColor, ALIGN_LEFT, + glm::vec3{}, glm::vec2{}, 0x00000000, 0.02f); mMD_Filler = std::make_shared(mWindow, "", font, mdColor); if (Settings::getInstance()->getString("Scraper") != "thegamesdb") @@ -127,15 +123,15 @@ GuiScraperSearch::GuiScraperSearch(Window* window, SearchType type, unsigned int std::make_shared(mWindow, "", font, mdLblColor), mMD_Filler)); mMD_Grid = std::make_shared( - mWindow, Vector2i(2, static_cast(mMD_Pairs.size() * 2 - 1))); + mWindow, glm::ivec2{2, static_cast(mMD_Pairs.size() * 2 - 1)}); unsigned int i = 0; for (auto it = mMD_Pairs.cbegin(); it != mMD_Pairs.cend(); it++) { - mMD_Grid->setEntry(it->first, Vector2i(0, i), false, true); - mMD_Grid->setEntry(it->second, Vector2i(1, i), false, it->resize); + mMD_Grid->setEntry(it->first, glm::ivec2{0, i}, false, true); + mMD_Grid->setEntry(it->second, glm::ivec2{1, i}, false, it->resize); i += 2; } - mGrid.setEntry(mMD_Grid, Vector2i(2, 1), false, false); + mGrid.setEntry(mMD_Grid, glm::ivec2{2, 1}, false, false); // Result list. mResultList = std::make_shared(mWindow); @@ -184,7 +180,7 @@ void GuiScraperSearch::onSizeChanged() { mGrid.setSize(mSize); - if (mSize.x() == 0 || mSize.y() == 0) + if (mSize.x == 0 || mSize.y == 0) return; // Column widths. @@ -203,7 +199,7 @@ void GuiScraperSearch::onSizeChanged() // Row heights. if (mSearchType == ALWAYS_ACCEPT_FIRST_RESULT) // Show name. mGrid.setRowHeightPerc(0, (mResultName->getFont()->getHeight() * 1.6f) / - mGrid.getSize().y()); // Result name. + mGrid.getSize().y); // Result name. else mGrid.setRowHeightPerc(0, 0.0825f); // Hide name but do padding. @@ -230,11 +226,11 @@ void GuiScraperSearch::onSizeChanged() mResultDesc->getFont()->getHeight() * 6.0f); // Make description text wrap at edge of container. - mResultDesc->setSize(mDescContainer->getSize().x(), 0); + mResultDesc->setSize(mDescContainer->getSize().x, 0.0f); // Set the width of mResultName to the cell width so that text abbreviation will work correctly. - Vector2f resultNameSize = mResultName->getSize(); - mResultName->setSize(mGrid.getColWidth(3), resultNameSize.y()); + glm::vec2 resultNameSize{mResultName->getSize()}; + mResultName->setSize(mGrid.getColWidth(3), resultNameSize.y); mGrid.onSizeChanged(); mBusyAnim.setSize(mSize); @@ -243,8 +239,8 @@ void GuiScraperSearch::onSizeChanged() void GuiScraperSearch::resizeMetadata() { mMD_Grid->setSize(mGrid.getColWidth(2), mGrid.getRowHeight(1)); - if (mMD_Grid->getSize().y() > mMD_Pairs.size()) { - const int fontHeight = static_cast(mMD_Grid->getSize().y() / mMD_Pairs.size() * 0.8f); + if (mMD_Grid->getSize().y > mMD_Pairs.size()) { + const int fontHeight = static_cast(mMD_Grid->getSize().y / mMD_Pairs.size() * 0.8f); auto fontLbl = Font::get(fontHeight, FONT_PATH_REGULAR); auto fontComp = Font::get(fontHeight, FONT_PATH_LIGHT); @@ -253,15 +249,14 @@ void GuiScraperSearch::resizeMetadata() for (auto it = mMD_Pairs.cbegin(); it != mMD_Pairs.cend(); it++) { it->first->setFont(fontLbl); it->first->setSize(0, 0); - if (it->first->getSize().x() > maxLblWidth) - maxLblWidth = - it->first->getSize().x() + (16.0f * Renderer::getScreenWidthModifier()); + if (it->first->getSize().x > maxLblWidth) + maxLblWidth = it->first->getSize().x + (16.0f * Renderer::getScreenWidthModifier()); } for (unsigned int i = 0; i < mMD_Pairs.size(); i++) mMD_Grid->setRowHeightPerc( i * 2, (fontLbl->getLetterHeight() + (2.0f * Renderer::getScreenHeightModifier())) / - mMD_Grid->getSize().y()); + mMD_Grid->getSize().y); // Update component fonts. mMD_ReleaseDate->setFont(fontComp); @@ -270,7 +265,7 @@ void GuiScraperSearch::resizeMetadata() mMD_Genre->setFont(fontComp); mMD_Players->setFont(fontComp); - mMD_Grid->setColWidthPerc(0, maxLblWidth / mMD_Grid->getSize().x()); + mMD_Grid->setColWidthPerc(0, maxLblWidth / mMD_Grid->getSize().x); if (mScrapeRatings) { // Rating is manually sized. @@ -293,33 +288,33 @@ void GuiScraperSearch::updateViewStyle() // Add them back depending on search type. if (mSearchType == ALWAYS_ACCEPT_FIRST_RESULT) { // Show name. - mGrid.setEntry(mResultName, Vector2i(1, 0), false, false, Vector2i(2, 1), + mGrid.setEntry(mResultName, glm::ivec2{1, 0}, false, false, glm::ivec2{2, 1}, GridFlags::BORDER_TOP); // Need a border on the bottom left. - mGrid.setEntry(std::make_shared(mWindow), Vector2i(0, 2), false, false, - Vector2i(3, 1), GridFlags::BORDER_BOTTOM); + mGrid.setEntry(std::make_shared(mWindow), glm::ivec2{0, 2}, false, false, + glm::ivec2{3, 1}, GridFlags::BORDER_BOTTOM); // Show description on the right. - mGrid.setEntry(mDescContainer, Vector2i(3, 0), false, false, Vector2i(1, 3), + mGrid.setEntry(mDescContainer, glm::ivec2{3, 0}, false, false, glm::ivec2{1, 3}, GridFlags::BORDER_TOP | GridFlags::BORDER_BOTTOM); // Make description text wrap at edge of container. - mResultDesc->setSize(mDescContainer->getSize().x(), 0.0f); + mResultDesc->setSize(mDescContainer->getSize().x, 0.0f); } else { // Fake row where name would be. - mGrid.setEntry(std::make_shared(mWindow), Vector2i(1, 0), false, true, - Vector2i(2, 1), GridFlags::BORDER_TOP); + mGrid.setEntry(std::make_shared(mWindow), glm::ivec2{1, 0}, false, true, + glm::ivec2{2, 1}, GridFlags::BORDER_TOP); // Show result list on the right. - mGrid.setEntry(mResultList, Vector2i(3, 0), true, true, Vector2i(1, 3), + mGrid.setEntry(mResultList, glm::ivec2{3, 0}, true, true, glm::ivec2{1, 3}, GridFlags::BORDER_LEFT | GridFlags::BORDER_TOP | GridFlags::BORDER_BOTTOM); // Show description under image/info. - mGrid.setEntry(mDescContainer, Vector2i(1, 2), false, false, Vector2i(2, 1), + mGrid.setEntry(mDescContainer, glm::ivec2{1, 2}, false, false, glm::ivec2{2, 1}, GridFlags::BORDER_BOTTOM); // Make description text wrap at edge of container. - mResultDesc->setSize(mDescContainer->getSize().x(), 0); + mResultDesc->setSize(mDescContainer->getSize().x, 0); } } @@ -565,12 +560,12 @@ bool GuiScraperSearch::input(InputConfig* config, Input input) return GuiComponent::input(config, input); } -void GuiScraperSearch::render(const Transform4x4f& parentTrans) +void GuiScraperSearch::render(const glm::mat4& parentTrans) { - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; renderChildren(trans); - Renderer::drawRect(0.0f, 0.0f, mSize.x(), mSize.y(), 0x00000009, 0x00000009); + Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x00000009, 0x00000009); if (mBlockAccept) { Renderer::setMatrix(trans); diff --git a/es-app/src/guis/GuiScraperSearch.h b/es-app/src/guis/GuiScraperSearch.h index d2f813ea3..9b05ed7cc 100644 --- a/es-app/src/guis/GuiScraperSearch.h +++ b/es-app/src/guis/GuiScraperSearch.h @@ -75,7 +75,7 @@ public: bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; std::vector getHelpPrompts() override; HelpStyle getHelpStyle() override; void onSizeChanged() override; diff --git a/es-app/src/guis/GuiSettings.cpp b/es-app/src/guis/GuiSettings.cpp index 3f65efd8c..b5827febb 100644 --- a/es-app/src/guis/GuiSettings.cpp +++ b/es-app/src/guis/GuiSettings.cpp @@ -41,8 +41,7 @@ GuiSettings::GuiSettings(Window* window, std::string title) setSize(static_cast(Renderer::getScreenWidth()), static_cast(Renderer::getScreenHeight())); - mMenu.setPosition((mSize.x() - mMenu.getSize().x()) / 2.0f, - Renderer::getScreenHeight() * 0.13f); + mMenu.setPosition((mSize.x - mMenu.getSize().x) / 2.0f, Renderer::getScreenHeight() * 0.13f); } GuiSettings::~GuiSettings() @@ -171,7 +170,7 @@ void GuiSettings::addEditableTextComponent(const std::string label, auto bracket = std::make_shared(mWindow); bracket->setImage(":/graphics/arrow.svg"); - bracket->setResize(Vector2f(0, lbl->getFont()->getLetterHeight())); + bracket->setResize(glm::vec2{0.0f, lbl->getFont()->getLetterHeight()}); row.addElement(bracket, false); // OK callback (apply new value to ed). diff --git a/es-app/src/guis/GuiSettings.h b/es-app/src/guis/GuiSettings.h index 0010d5689..d768a96b3 100644 --- a/es-app/src/guis/GuiSettings.h +++ b/es-app/src/guis/GuiSettings.h @@ -22,7 +22,10 @@ public: virtual ~GuiSettings(); void save(); - void addRow(const ComponentListRow& row) { mMenu.addRow(row); } + void addRow(const ComponentListRow& row, bool setCursorHere = false) + { + mMenu.addRow(row, setCursorHere); + } void addWithLabel(const std::string& label, const std::shared_ptr& comp) { mMenu.addWithLabel(label, comp); @@ -34,6 +37,11 @@ public: bool isPassword = false); void addSaveFunc(const std::function& func) { mSaveFuncs.push_back(func); } + glm::vec2 getMenuSize() { return mMenu.getSize(); } + void setMenuSize(glm::vec2 size) { mMenu.setSize(size); } + glm::vec3 getMenuPosition() { return mMenu.getPosition(); } + void setMenuPosition(glm::vec3 position) { mMenu.setPosition(position); } + void setNeedsSaving(bool state = true) { mNeedsSaving = state; } void setNeedsReloadHelpPrompts() { mNeedsReloadHelpPrompts = true; } void setNeedsCollectionsUpdate() { mNeedsCollectionsUpdate = true; } diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index fe243b8ae..d597706f9 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -572,7 +572,7 @@ int main(int argc, char* argv[]) bool splashScreen = Settings::getInstance()->getBool("SplashScreen"); bool splashScreenProgress = Settings::getInstance()->getBool("SplashScreenProgress"); - SDL_Event event {}; + SDL_Event event{}; if (!window.init()) { LOG(LogError) << "Window failed to initialize"; @@ -613,6 +613,16 @@ int main(int argc, char* argv[]) } } + // Check if any of the enabled systems has an invalid alternative emulator entry, + // which means that a label is present in the gamelist.xml file which is not matching + // any command tag in es_systems.xml. + for (auto system : SystemData::sSystemVector) { + if (system->getAlternativeEmulator() == "") { + ViewController::get()->invalidAlternativeEmulatorDialog(); + break; + } + } + // Don't generate controller events while we're loading. SDL_GameControllerEventState(SDL_DISABLE); diff --git a/es-app/src/scrapers/GamesDBJSONScraper.cpp b/es-app/src/scrapers/GamesDBJSONScraper.cpp index 7ca45b709..69f9052ed 100644 --- a/es-app/src/scrapers/GamesDBJSONScraper.cpp +++ b/es-app/src/scrapers/GamesDBJSONScraper.cpp @@ -7,6 +7,10 @@ // Called from Scraper. // +#if defined(_MSC_VER) // MSVC compiler. +#define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING +#endif + #include "scrapers/GamesDBJSONScraper.h" #include "scrapers/GamesDBJSONScraperResources.h" @@ -33,90 +37,90 @@ namespace TheGamesDBJSONRequestResources resources; } -const std::map gamesdb_new_platformid_map { - { THREEDO, "25" }, - { COMMODORE_AMIGA, "4911" }, - { COMMODORE_AMIGA_CD32, "4947" }, - { AMSTRAD_CPC, "4914" }, - { APPLE_II, "4942" }, - { ARCADE, "23" }, - { ATARI_800, "4943" }, - { ATARI_2600, "22" }, - { ATARI_5200, "26" }, - { ATARI_7800, "27" }, - { ATARI_JAGUAR, "28" }, - { ATARI_JAGUAR_CD, "29" }, - { ATARI_LYNX, "4924" }, - { ATARI_ST, "4937" }, - { ATARI_XE, "30" }, - { CAVESTORY, "1" }, - { COLECOVISION, "31" }, - { COMMODORE_64, "40" }, - { DAPHNE, "23" }, - { INTELLIVISION, "32" }, - { APPLE_MACINTOSH, "37" }, - { MICROSOFT_XBOX, "14" }, - { MICROSOFT_XBOX_360, "15" }, - { MOONLIGHT, "1" }, - { MSX, "4929" }, - { MSX2, "4929" }, - { MSX_TURBO_R, "4929" }, - { SNK_NEO_GEO, "24" }, - { SNK_NEO_GEO_CD, "24" }, - { SNK_NEO_GEO_POCKET, "4922" }, - { SNK_NEO_GEO_POCKET_COLOR, "4923" }, - { NINTENDO_3DS, "4912" }, - { NINTENDO_64, "3" }, - { NINTENDO_DS, "8" }, - { NINTENDO_FAMICOM, "7" }, - { NINTENDO_FAMICOM_DISK_SYSTEM, "4936" }, - { NINTENDO_ENTERTAINMENT_SYSTEM, "7" }, - { NINTENDO_GAME_BOY, "4" }, - { NINTENDO_GAME_BOY_ADVANCE, "5" }, - { NINTENDO_GAME_BOY_COLOR, "41" }, - { NINTENDO_GAMECUBE, "2" }, - { NINTENDO_WII, "9" }, - { NINTENDO_WII_U, "38" }, - { NINTENDO_VIRTUAL_BOY, "4918" }, - { NINTENDO_GAME_AND_WATCH, "4950" }, - { NINTENDO_POKEMON_MINI, "4957" }, - { NINTENDO_SATELLAVIEW, "6" }, - { NINTENDO_SWITCH, "4971" }, - { BANDAI_SUFAMI_TURBO, "6" }, - { DOS, "1" }, - { PC, "1" }, - { VALVE_STEAM, "1" }, - { NEC_PCFX, "4930" }, - { SEGA_32X, "33" }, - { SEGA_CD, "21" }, - { SEGA_DREAMCAST, "16" }, - { SEGA_GAME_GEAR, "20" }, - { SEGA_GENESIS, "18" }, - { SEGA_MASTER_SYSTEM, "35" }, - { SEGA_MEGA_DRIVE, "36" }, - { SEGA_SATURN, "17" }, - { SEGA_SG1000, "4949" }, - { SONY_PLAYSTATION, "10" }, - { SONY_PLAYSTATION_2, "11" }, - { SONY_PLAYSTATION_3, "12" }, - { SONY_PLAYSTATION_4, "4919" }, - { SONY_PLAYSTATION_VITA, "39" }, - { SONY_PLAYSTATION_PORTABLE, "13" }, - { SUPER_NINTENDO, "6" }, - { SHARP_X1, "4977" }, - { SHARP_X68000, "4931" }, - { NEC_SUPERGRAFX, "34" }, - { NEC_PC_8800, "4933" }, - { NEC_PC_9800, "4934" }, - { NEC_PC_ENGINE, "34" }, - { NEC_PC_ENGINE_CD, "4955" }, - { BANDAI_WONDERSWAN, "4925" }, - { BANDAI_WONDERSWAN_COLOR, "4926" }, - { SINCLAIR_ZX_SPECTRUM, "4913" }, - { VIDEOPAC_ODYSSEY2, "4927" }, - { VECTREX, "4939" }, - { TANDY_COLOR_COMPUTER, "4941" }, - { TANDY_TRS80, "4941" }, +const std::map gamesdb_new_platformid_map{ + {THREEDO, "25"}, + {COMMODORE_AMIGA, "4911"}, + {COMMODORE_AMIGA_CD32, "4947"}, + {AMSTRAD_CPC, "4914"}, + {APPLE_II, "4942"}, + {ARCADE, "23"}, + {ATARI_800, "4943"}, + {ATARI_2600, "22"}, + {ATARI_5200, "26"}, + {ATARI_7800, "27"}, + {ATARI_JAGUAR, "28"}, + {ATARI_JAGUAR_CD, "29"}, + {ATARI_LYNX, "4924"}, + {ATARI_ST, "4937"}, + {ATARI_XE, "30"}, + {CAVESTORY, "1"}, + {COLECOVISION, "31"}, + {COMMODORE_64, "40"}, + {DAPHNE, "23"}, + {INTELLIVISION, "32"}, + {APPLE_MACINTOSH, "37"}, + {MICROSOFT_XBOX, "14"}, + {MICROSOFT_XBOX_360, "15"}, + {MOONLIGHT, "1"}, + {MSX, "4929"}, + {MSX2, "4929"}, + {MSX_TURBO_R, "4929"}, + {SNK_NEO_GEO, "24"}, + {SNK_NEO_GEO_CD, "24"}, + {SNK_NEO_GEO_POCKET, "4922"}, + {SNK_NEO_GEO_POCKET_COLOR, "4923"}, + {NINTENDO_3DS, "4912"}, + {NINTENDO_64, "3"}, + {NINTENDO_DS, "8"}, + {NINTENDO_FAMICOM, "7"}, + {NINTENDO_FAMICOM_DISK_SYSTEM, "4936"}, + {NINTENDO_ENTERTAINMENT_SYSTEM, "7"}, + {NINTENDO_GAME_BOY, "4"}, + {NINTENDO_GAME_BOY_ADVANCE, "5"}, + {NINTENDO_GAME_BOY_COLOR, "41"}, + {NINTENDO_GAMECUBE, "2"}, + {NINTENDO_WII, "9"}, + {NINTENDO_WII_U, "38"}, + {NINTENDO_VIRTUAL_BOY, "4918"}, + {NINTENDO_GAME_AND_WATCH, "4950"}, + {NINTENDO_POKEMON_MINI, "4957"}, + {NINTENDO_SATELLAVIEW, "6"}, + {NINTENDO_SWITCH, "4971"}, + {BANDAI_SUFAMI_TURBO, "6"}, + {DOS, "1"}, + {PC, "1"}, + {VALVE_STEAM, "1"}, + {NEC_PCFX, "4930"}, + {SEGA_32X, "33"}, + {SEGA_CD, "21"}, + {SEGA_DREAMCAST, "16"}, + {SEGA_GAME_GEAR, "20"}, + {SEGA_GENESIS, "18"}, + {SEGA_MASTER_SYSTEM, "35"}, + {SEGA_MEGA_DRIVE, "36"}, + {SEGA_SATURN, "17"}, + {SEGA_SG1000, "4949"}, + {SONY_PLAYSTATION, "10"}, + {SONY_PLAYSTATION_2, "11"}, + {SONY_PLAYSTATION_3, "12"}, + {SONY_PLAYSTATION_4, "4919"}, + {SONY_PLAYSTATION_VITA, "39"}, + {SONY_PLAYSTATION_PORTABLE, "13"}, + {SUPER_NINTENDO, "6"}, + {SHARP_X1, "4977"}, + {SHARP_X68000, "4931"}, + {NEC_SUPERGRAFX, "34"}, + {NEC_PC_8800, "4933"}, + {NEC_PC_9800, "4934"}, + {NEC_PC_ENGINE, "34"}, + {NEC_PC_ENGINE_CD, "4955"}, + {BANDAI_WONDERSWAN, "4925"}, + {BANDAI_WONDERSWAN_COLOR, "4926"}, + {SINCLAIR_ZX_SPECTRUM, "4913"}, + {VIDEOPAC_ODYSSEY2, "4927"}, + {VECTREX, "4939"}, + {TANDY_COLOR_COMPUTER, "4941"}, + {TANDY_TRS80, "4941"}, }; void thegamesdb_generate_json_scraper_requests( diff --git a/es-app/src/scrapers/GamesDBJSONScraperResources.cpp b/es-app/src/scrapers/GamesDBJSONScraperResources.cpp index aa806d6e2..64929712d 100644 --- a/es-app/src/scrapers/GamesDBJSONScraperResources.cpp +++ b/es-app/src/scrapers/GamesDBJSONScraperResources.cpp @@ -12,6 +12,10 @@ // gamesdb_publishers.json // +#if defined(_MSC_VER) // MSVC compiler. +#define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING +#endif + #include "scrapers/GamesDBJSONScraperResources.h" #include "Log.h" diff --git a/es-app/src/scrapers/Scraper.cpp b/es-app/src/scrapers/Scraper.cpp index 234fd8a6a..c768843a8 100644 --- a/es-app/src/scrapers/Scraper.cpp +++ b/es-app/src/scrapers/Scraper.cpp @@ -26,10 +26,9 @@ #include #include -const std::map scraper_request_funcs { - { "thegamesdb", &thegamesdb_generate_json_scraper_requests }, - { "screenscraper", &screenscraper_generate_scraper_requests } -}; +const std::map scraper_request_funcs{ + {"thegamesdb", &thegamesdb_generate_json_scraper_requests}, + {"screenscraper", &screenscraper_generate_scraper_requests}}; std::unique_ptr startScraperSearch(const ScraperSearchParams& params) { diff --git a/es-app/src/scrapers/ScreenScraper.cpp b/es-app/src/scrapers/ScreenScraper.cpp index 7135960a2..afdb9ea00 100644 --- a/es-app/src/scrapers/ScreenScraper.cpp +++ b/es-app/src/scrapers/ScreenScraper.cpp @@ -14,7 +14,6 @@ #include "PlatformId.h" #include "Settings.h" #include "SystemData.h" -#include "math/Misc.h" #include "utils/StringUtil.h" #include "utils/TimeUtil.h" @@ -26,109 +25,108 @@ using namespace PlatformIds; // List of systems and their IDs from: // https://www.screenscraper.fr/api/systemesListe.php?devid=xxx&devpassword=yyy&softname=zzz&output=XML -const std::map screenscraper_platformid_map { - { THREEDO, 29 }, - { COMMODORE_AMIGA, 64 }, - { COMMODORE_AMIGA_CD32, 130 }, - { AMSTRAD_CPC, 65 }, - { AMSTRAD_GX4000, 87 }, - { APPLE_II, 86 }, - { APPLE_IIGS, 217 }, - { ARCADE, 75 }, - { ATARI_800, 43 }, - { ATARI_2600, 26 }, - { ATARI_5200, 40 }, - { ATARI_7800, 41 }, - { ATARI_JAGUAR, 27 }, - { ATARI_JAGUAR_CD, 171 }, - { ATARI_LYNX, 28 }, - { ATARI_ST, 42 }, - { ATARI_XE, 43 }, - { ATOMISWAVE, 53 }, - { BBC_MICRO, 37 }, - { CAVESTORY, 135 }, - { COLECOVISION, 48 }, - { COMMODORE_64, 66 }, - { COMMODORE_CDTV, 129 }, - { DAPHNE, 49 }, - { INTELLIVISION, 115 }, - { GAMEENGINE_LUTRO, 206 }, - { APPLE_MACINTOSH, 146 }, - { MICROSOFT_XBOX, 32 }, - { MICROSOFT_XBOX_360, 33 }, - { MOONLIGHT, 138 }, - { MSX, 113 }, - { MSX2, 116 }, - { MSX_TURBO_R, 118 }, - { SNK_NEO_GEO, 142 }, - { SNK_NEO_GEO_CD, 142 }, - { SNK_NEO_GEO_POCKET, 25 }, - { SNK_NEO_GEO_POCKET_COLOR, 82 }, - { NINTENDO_3DS, 17 }, - { NINTENDO_64, 14 }, - { NINTENDO_DS, 15 }, - { NINTENDO_FAMICOM, 3 }, - { NINTENDO_FAMICOM_DISK_SYSTEM, 106 }, - { NINTENDO_ENTERTAINMENT_SYSTEM, 3 }, - { FAIRCHILD_CHANNELF, 80 }, - { NINTENDO_GAME_BOY, 9 }, - { NINTENDO_GAME_BOY_ADVANCE, 12 }, - { NINTENDO_GAME_BOY_COLOR, 10 }, - { NINTENDO_GAMECUBE, 13 }, - { NINTENDO_WII, 16 }, - { NINTENDO_WII_U, 18 }, - { NINTENDO_VIRTUAL_BOY, 11 }, - { NINTENDO_GAME_AND_WATCH, 52 }, - { NINTENDO_POKEMON_MINI, 211 }, - { NINTENDO_SATELLAVIEW, 107 }, - { NINTENDO_SWITCH, 225 }, - { BANDAI_SUFAMI_TURBO, 108 }, - { DOS, 135 }, - { PC, 135 }, - { VALVE_STEAM, 135 }, - { NEC_PCFX, 72 }, - { GAMEENGINE_OPENBOR, 214 }, - { TANGERINE_ORIC, 131 }, - { GAMEENGINE_SCUMMVM, 123 }, - { SEGA_32X, 19 }, - { SEGA_CD, 20 }, - { SEGA_DREAMCAST, 23 }, - { SEGA_GAME_GEAR, 21 }, - { SEGA_GENESIS, 1 }, - { SEGA_MASTER_SYSTEM, 2 }, - { SEGA_MEGA_DRIVE, 1 }, - { SEGA_SATURN, 22 }, - { SEGA_SG1000, 109 }, - { SHARP_X1, 220 }, - { SHARP_X68000, 79 }, - { GAMEENGINE_SOLARUS, 223 }, - { SONY_PLAYSTATION, 57 }, - { SONY_PLAYSTATION_2, 58 }, - { SONY_PLAYSTATION_3, 59 }, - { SONY_PLAYSTATION_VITA, 62 }, - { SONY_PLAYSTATION_PORTABLE, 61 }, - { SAMCOUPE, 213 }, - { SUPER_NINTENDO, 4 }, - { NEC_SUPERGRAFX, 105 }, - { GAMEENGINE_TIC80, 222 }, - { NEC_PC_8800, 221 }, - { NEC_PC_9800, 208 }, - { NEC_PC_ENGINE, 31 }, - { NEC_PC_ENGINE_CD, 114 }, - { BANDAI_WONDERSWAN, 45 }, - { BANDAI_WONDERSWAN_COLOR, 46 }, - { SINCLAIR_ZX_SPECTRUM, 76 }, - { SINCLAIR_ZX81_SINCLAR, 77 }, - { VIDEOPAC_ODYSSEY2, 104 }, - { VECTREX, 102 }, - { TANDY_TRS80, 144 }, - { TANDY_COLOR_COMPUTER, 144 }, - { SEGA_NAOMI, 56 }, - { THOMSON_MOTO, 141 }, - { UZEBOX, 216 }, - { SPECTRAVIDEO, 218 }, - { PALM_OS, 219 } -}; +const std::map screenscraper_platformid_map{ + {THREEDO, 29}, + {COMMODORE_AMIGA, 64}, + {COMMODORE_AMIGA_CD32, 130}, + {AMSTRAD_CPC, 65}, + {AMSTRAD_GX4000, 87}, + {APPLE_II, 86}, + {APPLE_IIGS, 217}, + {ARCADE, 75}, + {ATARI_800, 43}, + {ATARI_2600, 26}, + {ATARI_5200, 40}, + {ATARI_7800, 41}, + {ATARI_JAGUAR, 27}, + {ATARI_JAGUAR_CD, 171}, + {ATARI_LYNX, 28}, + {ATARI_ST, 42}, + {ATARI_XE, 43}, + {ATOMISWAVE, 53}, + {BBC_MICRO, 37}, + {CAVESTORY, 135}, + {COLECOVISION, 48}, + {COMMODORE_64, 66}, + {COMMODORE_CDTV, 129}, + {DAPHNE, 49}, + {INTELLIVISION, 115}, + {GAMEENGINE_LUTRO, 206}, + {APPLE_MACINTOSH, 146}, + {MICROSOFT_XBOX, 32}, + {MICROSOFT_XBOX_360, 33}, + {MOONLIGHT, 138}, + {MSX, 113}, + {MSX2, 116}, + {MSX_TURBO_R, 118}, + {SNK_NEO_GEO, 142}, + {SNK_NEO_GEO_CD, 142}, + {SNK_NEO_GEO_POCKET, 25}, + {SNK_NEO_GEO_POCKET_COLOR, 82}, + {NINTENDO_3DS, 17}, + {NINTENDO_64, 14}, + {NINTENDO_DS, 15}, + {NINTENDO_FAMICOM, 3}, + {NINTENDO_FAMICOM_DISK_SYSTEM, 106}, + {NINTENDO_ENTERTAINMENT_SYSTEM, 3}, + {FAIRCHILD_CHANNELF, 80}, + {NINTENDO_GAME_BOY, 9}, + {NINTENDO_GAME_BOY_ADVANCE, 12}, + {NINTENDO_GAME_BOY_COLOR, 10}, + {NINTENDO_GAMECUBE, 13}, + {NINTENDO_WII, 16}, + {NINTENDO_WII_U, 18}, + {NINTENDO_VIRTUAL_BOY, 11}, + {NINTENDO_GAME_AND_WATCH, 52}, + {NINTENDO_POKEMON_MINI, 211}, + {NINTENDO_SATELLAVIEW, 107}, + {NINTENDO_SWITCH, 225}, + {BANDAI_SUFAMI_TURBO, 108}, + {DOS, 135}, + {PC, 135}, + {VALVE_STEAM, 135}, + {NEC_PCFX, 72}, + {GAMEENGINE_OPENBOR, 214}, + {TANGERINE_ORIC, 131}, + {GAMEENGINE_SCUMMVM, 123}, + {SEGA_32X, 19}, + {SEGA_CD, 20}, + {SEGA_DREAMCAST, 23}, + {SEGA_GAME_GEAR, 21}, + {SEGA_GENESIS, 1}, + {SEGA_MASTER_SYSTEM, 2}, + {SEGA_MEGA_DRIVE, 1}, + {SEGA_SATURN, 22}, + {SEGA_SG1000, 109}, + {SHARP_X1, 220}, + {SHARP_X68000, 79}, + {GAMEENGINE_SOLARUS, 223}, + {SONY_PLAYSTATION, 57}, + {SONY_PLAYSTATION_2, 58}, + {SONY_PLAYSTATION_3, 59}, + {SONY_PLAYSTATION_VITA, 62}, + {SONY_PLAYSTATION_PORTABLE, 61}, + {SAMCOUPE, 213}, + {SUPER_NINTENDO, 4}, + {NEC_SUPERGRAFX, 105}, + {GAMEENGINE_TIC80, 222}, + {NEC_PC_8800, 221}, + {NEC_PC_9800, 208}, + {NEC_PC_ENGINE, 31}, + {NEC_PC_ENGINE_CD, 114}, + {BANDAI_WONDERSWAN, 45}, + {BANDAI_WONDERSWAN_COLOR, 46}, + {SINCLAIR_ZX_SPECTRUM, 76}, + {SINCLAIR_ZX81_SINCLAR, 77}, + {VIDEOPAC_ODYSSEY2, 104}, + {VECTREX, 102}, + {TANDY_TRS80, 144}, + {TANDY_COLOR_COMPUTER, 144}, + {SEGA_NAOMI, 56}, + {THOMSON_MOTO, 141}, + {UZEBOX, 216}, + {SPECTRAVIDEO, 218}, + {PALM_OS, 219}}; // Helper XML parsing method, finding a node-by-name recursively. pugi::xml_node find_node_by_name_re(const pugi::xml_node& node, @@ -333,11 +331,10 @@ void ScreenScraperRequest::processGame(const pugi::xml_document& xmldoc, Utils::String::toLower(Settings::getInstance()->getString("ScraperLanguage")); // Name fallback: US, WOR(LD). (Xpath: Data/jeu[0]/noms/nom[*]). - result.mdl.set("name", - find_child_by_attribute_list(game.child("noms"), "nom", "region", - { region, "wor", "us", "ss", "eu", "jp" }) - .text() - .get()); + result.mdl.set("name", find_child_by_attribute_list(game.child("noms"), "nom", "region", + {region, "wor", "us", "ss", "eu", "jp"}) + .text() + .get()); LOG(LogDebug) << "ScreenScraperRequest::processGame(): Name: " << result.mdl.get("name"); // Validate rating. @@ -360,7 +357,7 @@ void ScreenScraperRequest::processGame(const pugi::xml_document& xmldoc, // Description fallback language: EN, WOR(LD). std::string description = find_child_by_attribute_list(game.child("synopsis"), "synopsis", - "langue", { language, "en", "wor" }) + "langue", {language, "en", "wor"}) .text() .get(); @@ -373,7 +370,7 @@ void ScreenScraperRequest::processGame(const pugi::xml_document& xmldoc, // Get the date proper. The API returns multiple 'date' children nodes to the 'dates' // main child of 'jeu'. Date fallback: WOR(LD), US, SS, JP, EU. std::string _date = find_child_by_attribute_list(game.child("dates"), "date", "region", - { region, "wor", "us", "ss", "jp", "eu" }) + {region, "wor", "us", "ss", "jp", "eu"}) .text() .get(); @@ -411,10 +408,10 @@ void ScreenScraperRequest::processGame(const pugi::xml_document& xmldoc, } // Genre fallback language: EN. (Xpath: Data/jeu[0]/genres/genre[*]). - std::string genre = find_child_by_attribute_list(game.child("genres"), "genre", "langue", - { language, "en" }) - .text() - .get(); + std::string genre = + find_child_by_attribute_list(game.child("genres"), "genre", "langue", {language, "en"}) + .text() + .get(); if (!genre.empty()) { result.mdl.set("genre", genre); LOG(LogDebug) << "ScreenScraperRequest::processGame(): Genre: " @@ -482,8 +479,7 @@ void ScreenScraperRequest::processMedia(ScraperSearchResult& result, } else { // Region fallback: WOR(LD), US, CUS(TOM?), JP, EU. - for (auto _region : - std::vector { region, "wor", "us", "cus", "jp", "eu" }) { + for (auto _region : std::vector{region, "wor", "us", "cus", "jp", "eu"}) { if (art) break; diff --git a/es-app/src/scrapers/ScreenScraper.h b/es-app/src/scrapers/ScreenScraper.h index 97295587b..3e07bf61b 100644 --- a/es-app/src/scrapers/ScreenScraper.h +++ b/es-app/src/scrapers/ScreenScraper.h @@ -46,10 +46,10 @@ public: std::string getGameSearchUrl(const std::string gameName) const; // Access to the API. - const std::string API_DEV_U = { 15, 21, 39, 22, 42, 40 }; - const std::string API_DEV_P = { 32, 70, 46, 54, 12, 5, 13, 120, 50, 66, 25 }; - const std::string API_DEV_KEY = { 67, 112, 72, 120, 121, 77, 119, 74, 84, 56, - 75, 122, 78, 98, 69, 86, 56, 120, 120, 49 }; + const std::string API_DEV_U = {15, 21, 39, 22, 42, 40}; + const std::string API_DEV_P = {32, 70, 46, 54, 12, 5, 13, 120, 50, 66, 25}; + const std::string API_DEV_KEY = {67, 112, 72, 120, 121, 77, 119, 74, 84, 56, + 75, 122, 78, 98, 69, 86, 56, 120, 120, 49}; const std::string API_URL_BASE = "https://www.screenscraper.fr/api2"; const std::string API_SOFT_NAME = "EmulationStation-DE " + static_cast(PROGRAM_VERSION_STRING); diff --git a/es-app/src/views/SystemView.cpp b/es-app/src/views/SystemView.cpp index 1e78c6777..0a4ecd850 100644 --- a/es-app/src/views/SystemView.cpp +++ b/es-app/src/views/SystemView.cpp @@ -23,8 +23,8 @@ #endif // Buffer values for scrolling velocity (left, stopped, right). -const int logoBuffersLeft[] = { -5, -2, -1 }; -const int logoBuffersRight[] = { 1, 2, 5 }; +const int logoBuffersLeft[] = {-5, -2, -1}; +const int logoBuffersRight[] = {1, 2, 5}; SystemView::SystemView(Window* window) : IList(window, LIST_SCROLL_STYLE_SLOW, LIST_ALWAYS_LOOP) @@ -123,8 +123,8 @@ void SystemView::populate() e.data.logo->setOrigin(0.5, 0.5); } - Vector2f denormalized = mCarousel.logoSize * e.data.logo->getOrigin(); - e.data.logo->setPosition(denormalized.x(), denormalized.y(), 0.0); + glm::vec2 denormalized{mCarousel.logoSize * e.data.logo->getOrigin()}; + e.data.logo->setPosition(denormalized.x, denormalized.y, 0.0f); // Make background extras. e.data.backgroundExtras = ThemeData::makeExtras((*it)->getTheme(), "system", mWindow); @@ -315,7 +315,7 @@ void SystemView::onCursorChanged(const CursorState& /*state*/) anim = new LambdaAnimation( [this, startExtrasFade, startPos, endPos, posMax](float t) { t -= 1; - float f = Math::lerp(startPos, endPos, t * t * t + 1); + float f = glm::mix(startPos, endPos, t * t * t + 1); if (f < 0) f += posMax; if (f >= posMax) @@ -325,11 +325,13 @@ void SystemView::onCursorChanged(const CursorState& /*state*/) t += 1; if (t < 0.3f) - this->mExtrasFadeOpacity = Math::lerp(0.0f, 1.0f, t / 0.2f + startExtrasFade); + this->mExtrasFadeOpacity = + glm::mix(0.0f, 1.0f, glm::clamp(t / 0.2f + startExtrasFade, 0.0f, 1.0f)); else if (t < 0.7f) this->mExtrasFadeOpacity = 1.0f; else - this->mExtrasFadeOpacity = Math::lerp(1.0f, 0.0f, (t - 0.6f) / 0.3f); + this->mExtrasFadeOpacity = + glm::mix(1.0f, 0.0f, glm::clamp((t - 0.6f) / 0.3f, 0.0f, 1.0f)); if (t > 0.5f) this->mExtrasCamOffset = endPos; @@ -345,7 +347,7 @@ void SystemView::onCursorChanged(const CursorState& /*state*/) anim = new LambdaAnimation( [this, startPos, endPos, posMax](float t) { t -= 1; - float f = Math::lerp(startPos, endPos, t * t * t + 1); + float f = glm::mix(startPos, endPos, t * t * t + 1); if (f < 0) f += posMax; if (f >= posMax) @@ -381,7 +383,7 @@ void SystemView::onCursorChanged(const CursorState& /*state*/) anim = new LambdaAnimation( [this, startPos, endPos, posMax](float t) { t -= 1; - float f = Math::lerp(startPos, endPos, t * t * t + 1); + float f = glm::mix(startPos, endPos, t * t * t + 1); if (f < 0) f += posMax; if (f >= posMax) @@ -396,12 +398,12 @@ void SystemView::onCursorChanged(const CursorState& /*state*/) setAnimation(anim, 0, nullptr, false, 0); } -void SystemView::render(const Transform4x4f& parentTrans) +void SystemView::render(const glm::mat4& parentTrans) { if (size() == 0) return; // Nothing to render. - Transform4x4f trans = getTransform() * parentTrans; + glm::mat4 trans{getTransform() * parentTrans}; renderExtras(trans, INT16_MIN, INT16_MAX); @@ -430,7 +432,7 @@ std::vector SystemView::getHelpPrompts() if (!UIModeController::getInstance()->isUIModeKid() && Settings::getInstance()->getBool("ScreensaverControls")) - prompts.push_back(HelpPrompt("back", "toggle screensaver")); + prompts.push_back(HelpPrompt("back", "screensaver")); return prompts; } @@ -449,7 +451,6 @@ void SystemView::onThemeChanged(const std::shared_ptr& /*theme*/) populate(); } -// Get the ThemeElements that make up the SystemView. void SystemView::getViewElements(const std::shared_ptr& theme) { LOG(LogDebug) << "SystemView::getViewElements()"; @@ -473,83 +474,78 @@ void SystemView::getViewElements(const std::shared_ptr& theme) mViewNeedsReload = false; } -// Render system carousel. -void SystemView::renderCarousel(const Transform4x4f& trans) +void SystemView::renderCarousel(const glm::mat4& trans) { // Background box behind logos. - Transform4x4f carouselTrans = trans; - carouselTrans.translate(Vector3f(mCarousel.pos.x(), mCarousel.pos.y(), 0.0)); - carouselTrans.translate(Vector3f(mCarousel.origin.x() * mCarousel.size.x() * -1.0f, - mCarousel.origin.y() * mCarousel.size.y() * -1.0f, 0.0f)); + glm::mat4 carouselTrans{trans}; + carouselTrans = + glm::translate(carouselTrans, glm::vec3{mCarousel.pos.x, mCarousel.pos.y, 0.0f}); + carouselTrans = glm::translate(carouselTrans, + glm::vec3{mCarousel.origin.x * mCarousel.size.x * -1.0f, + mCarousel.origin.y * mCarousel.size.y * -1.0f, 0.0f}); - Vector2f clipPos(carouselTrans.translation().x(), carouselTrans.translation().y()); + glm::vec2 clipPos{carouselTrans[3].x, carouselTrans[3].y}; Renderer::pushClipRect( - Vector2i(static_cast(clipPos.x()), static_cast(clipPos.y())), - Vector2i(static_cast(mCarousel.size.x()), static_cast(mCarousel.size.y()))); + glm::ivec2{static_cast(clipPos.x), static_cast(clipPos.y)}, + glm::ivec2{static_cast(mCarousel.size.x), static_cast(mCarousel.size.y)}); Renderer::setMatrix(carouselTrans); - Renderer::drawRect(0.0f, 0.0f, mCarousel.size.x(), mCarousel.size.y(), mCarousel.color, + Renderer::drawRect(0.0f, 0.0f, mCarousel.size.x, mCarousel.size.y, mCarousel.color, mCarousel.colorEnd, mCarousel.colorGradientHorizontal); // Draw logos. // Note: logoSpacing will also include the size of the logo itself. - Vector2f logoSpacing(0.0f, 0.0f); + glm::vec2 logoSpacing{}; float xOff = 0.0f; float yOff = 0.0f; switch (mCarousel.type) { case VERTICAL_WHEEL: { - yOff = (mCarousel.size.y() - mCarousel.logoSize.y()) / 2.0f - - (mCamOffset * logoSpacing[1]); + yOff = (mCarousel.size.y - mCarousel.logoSize.y) / 2.0f - (mCamOffset * logoSpacing.y); if (mCarousel.logoAlignment == ALIGN_LEFT) - xOff = mCarousel.logoSize.x() / 10.0f; + xOff = mCarousel.logoSize.x / 10.0f; else if (mCarousel.logoAlignment == ALIGN_RIGHT) - xOff = mCarousel.size.x() - (mCarousel.logoSize.x() * 1.1f); + xOff = mCarousel.size.x - (mCarousel.logoSize.x * 1.1f); else - xOff = (mCarousel.size.x() - mCarousel.logoSize.x()) / 2.0f; + xOff = (mCarousel.size.x - mCarousel.logoSize.x) / 2.0f; break; } case VERTICAL: { - logoSpacing[1] = - ((mCarousel.size.y() - (mCarousel.logoSize.y() * mCarousel.maxLogoCount)) / - (mCarousel.maxLogoCount)) + - mCarousel.logoSize.y(); - yOff = (mCarousel.size.y() - mCarousel.logoSize.y()) / 2.0f - - (mCamOffset * logoSpacing[1]); + logoSpacing.y = ((mCarousel.size.y - (mCarousel.logoSize.y * mCarousel.maxLogoCount)) / + (mCarousel.maxLogoCount)) + + mCarousel.logoSize.y; + yOff = (mCarousel.size.y - mCarousel.logoSize.y) / 2.0f - (mCamOffset * logoSpacing.y); if (mCarousel.logoAlignment == ALIGN_LEFT) - xOff = mCarousel.logoSize.x() / 10.0f; + xOff = mCarousel.logoSize.x / 10.0f; else if (mCarousel.logoAlignment == ALIGN_RIGHT) - xOff = mCarousel.size.x() - (mCarousel.logoSize.x() * 1.1f); + xOff = mCarousel.size.x - (mCarousel.logoSize.x * 1.1f); else - xOff = (mCarousel.size.x() - mCarousel.logoSize.x()) / 2.0f; + xOff = (mCarousel.size.x - mCarousel.logoSize.x) / 2.0f; break; } case HORIZONTAL_WHEEL: { - xOff = (mCarousel.size.x() - mCarousel.logoSize.x()) / 2.0f - - (mCamOffset * logoSpacing[1]); + xOff = (mCarousel.size.x - mCarousel.logoSize.x) / 2.0f - (mCamOffset * logoSpacing.y); if (mCarousel.logoAlignment == ALIGN_TOP) - yOff = mCarousel.logoSize.y() / 10.0f; + yOff = mCarousel.logoSize.y / 10.0f; else if (mCarousel.logoAlignment == ALIGN_BOTTOM) - yOff = mCarousel.size.y() - (mCarousel.logoSize.y() * 1.1f); + yOff = mCarousel.size.y - (mCarousel.logoSize.y * 1.1f); else - yOff = (mCarousel.size.y() - mCarousel.logoSize.y()) / 2.0f; + yOff = (mCarousel.size.y - mCarousel.logoSize.y) / 2.0f; break; } case HORIZONTAL: { } default: { - logoSpacing[0] = - ((mCarousel.size.x() - (mCarousel.logoSize.x() * mCarousel.maxLogoCount)) / - (mCarousel.maxLogoCount)) + - mCarousel.logoSize.x(); - xOff = (mCarousel.size.x() - mCarousel.logoSize.x()) / 2.0f - - (mCamOffset * logoSpacing[0]); + logoSpacing.x = ((mCarousel.size.x - (mCarousel.logoSize.x * mCarousel.maxLogoCount)) / + (mCarousel.maxLogoCount)) + + mCarousel.logoSize.x; + xOff = (mCarousel.size.x - mCarousel.logoSize.x) / 2.0f - (mCamOffset * logoSpacing.x); if (mCarousel.logoAlignment == ALIGN_TOP) - yOff = mCarousel.logoSize.y() / 10.0f; + yOff = mCarousel.logoSize.y / 10.0f; else if (mCarousel.logoAlignment == ALIGN_BOTTOM) - yOff = mCarousel.size.y() - (mCarousel.logoSize.y() * 1.1f); + yOff = mCarousel.size.y - (mCarousel.logoSize.y * 1.1f); else - yOff = (mCarousel.size.y() - mCarousel.logoSize.y()) / 2.0f; + yOff = (mCarousel.size.y - mCarousel.logoSize.y) / 2.0f; break; } } @@ -575,8 +571,9 @@ void SystemView::renderCarousel(const Transform4x4f& trans) while (index >= static_cast(mEntries.size())) index -= static_cast(mEntries.size()); - Transform4x4f logoTrans = carouselTrans; - logoTrans.translate(Vector3f(i * logoSpacing[0] + xOff, i * logoSpacing[1] + yOff, 0)); + glm::mat4 logoTrans{carouselTrans}; + logoTrans = glm::translate( + logoTrans, glm::vec3{i * logoSpacing.x + xOff, i * logoSpacing.y + yOff, 0.0f}); float distance = i - mCamOffset; @@ -600,16 +597,15 @@ void SystemView::renderCarousel(const Transform4x4f& trans) Renderer::popClipRect(); } -// Draw background extras. -void SystemView::renderExtras(const Transform4x4f& trans, float lower, float upper) +void SystemView::renderExtras(const glm::mat4& trans, float lower, float upper) { int extrasCenter = static_cast(mExtrasCamOffset); // Adding texture loading buffers depending on scrolling speed and status. - int bufferIndex = getScrollingVelocity() + 1; + int bufferIndex{getScrollingVelocity() + 1}; - Renderer::pushClipRect(Vector2i::Zero(), - Vector2i(static_cast(mSize.x()), static_cast(mSize.y()))); + Renderer::pushClipRect(glm::ivec2{}, + glm::ivec2{static_cast(mSize.x), static_cast(mSize.y)}); for (int i = extrasCenter + logoBuffersLeft[bufferIndex]; i <= extrasCenter + logoBuffersRight[bufferIndex]; i++) { @@ -621,16 +617,17 @@ void SystemView::renderExtras(const Transform4x4f& trans, float lower, float upp // Only render selected system when not showing. if (mShowing || index == mCursor) { - Transform4x4f extrasTrans = trans; + glm::mat4 extrasTrans{trans}; if (mCarousel.type == HORIZONTAL || mCarousel.type == HORIZONTAL_WHEEL) - extrasTrans.translate(Vector3f((i - mExtrasCamOffset) * mSize.x(), 0, 0)); + extrasTrans = glm::translate( + extrasTrans, glm::vec3{(i - mExtrasCamOffset) * mSize.x, 0.0f, 0.0f}); else - extrasTrans.translate(Vector3f(0, (i - mExtrasCamOffset) * mSize.y(), 0)); + extrasTrans = glm::translate( + extrasTrans, glm::vec3{0.0f, (i - mExtrasCamOffset) * mSize.y, 0.0f}); Renderer::pushClipRect( - Vector2i(static_cast(extrasTrans.translation()[0]), - static_cast(extrasTrans.translation()[1])), - Vector2i(static_cast(mSize.x()), static_cast(mSize.y()))); + glm::ivec2{static_cast(extrasTrans[3].x), static_cast(extrasTrans[3].y)}, + glm::ivec2{static_cast(mSize.x), static_cast(mSize.y)}); SystemViewData data = mEntries.at(index).data; for (unsigned int j = 0; j < data.backgroundExtras.size(); j++) { GuiComponent* extra = data.backgroundExtras[j]; @@ -644,46 +641,45 @@ void SystemView::renderExtras(const Transform4x4f& trans, float lower, float upp Renderer::popClipRect(); } -void SystemView::renderFade(const Transform4x4f& trans) +void SystemView::renderFade(const glm::mat4& trans) { unsigned int fadeColor = 0x00000000 | static_cast(mExtrasFadeOpacity * 255.0f); Renderer::setMatrix(trans); - Renderer::drawRect(0.0f, 0.0f, mSize.x(), mSize.y(), fadeColor, fadeColor); + Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, fadeColor, fadeColor); } -// Populate the system carousel with the legacy values. void SystemView::getDefaultElements(void) { // Carousel. mCarousel.type = HORIZONTAL; mCarousel.logoAlignment = ALIGN_CENTER; - mCarousel.size.x() = mSize.x(); - mCarousel.size.y() = floorf(0.2325f * mSize.y()); - mCarousel.pos.x() = 0.0f; - mCarousel.pos.y() = floorf(0.5f * (mSize.y() - mCarousel.size.y())); - mCarousel.origin.x() = 0.0f; - mCarousel.origin.y() = 0.0f; + mCarousel.size.x = mSize.x; + mCarousel.size.y = floorf(0.2325f * mSize.y); + mCarousel.pos.x = 0.0f; + mCarousel.pos.y = floorf(0.5f * (mSize.y - mCarousel.size.y)); + mCarousel.origin.x = 0.0f; + mCarousel.origin.y = 0.0f; mCarousel.color = 0xFFFFFFD8; mCarousel.colorEnd = 0xFFFFFFD8; mCarousel.colorGradientHorizontal = true; mCarousel.logoScale = 1.2f; mCarousel.logoRotation = 7.5f; - mCarousel.logoRotationOrigin.x() = -5.0f; - mCarousel.logoRotationOrigin.y() = 0.5f; - mCarousel.logoSize.x() = 0.25f * mSize.x(); - mCarousel.logoSize.y() = 0.155f * mSize.y(); + mCarousel.logoRotationOrigin.x = -5.0f; + mCarousel.logoRotationOrigin.y = 0.5f; + mCarousel.logoSize.x = 0.25f * mSize.x; + mCarousel.logoSize.y = 0.155f * mSize.y; mCarousel.maxLogoCount = 3; mCarousel.zIndex = 40.0f; // System info bar. - mSystemInfo.setSize(mSize.x(), mSystemInfo.getFont()->getLetterHeight() * 2.2f); - mSystemInfo.setPosition(0, mCarousel.pos.y() + mCarousel.size.y()); + mSystemInfo.setSize(mSize.x, mSystemInfo.getFont()->getLetterHeight() * 2.2f); + mSystemInfo.setPosition(0.0f, mCarousel.pos.y + mCarousel.size.y); mSystemInfo.setBackgroundColor(0xDDDDDDD8); mSystemInfo.setRenderBackground(true); - mSystemInfo.setFont(Font::get(static_cast(0.035f * mSize.y()), Font::getDefaultPath())); + mSystemInfo.setFont(Font::get(static_cast(0.035f * mSize.y), Font::getDefaultPath())); mSystemInfo.setColor(0x000000FF); - mSystemInfo.setZIndex(50); - mSystemInfo.setDefaultZIndex(50); + mSystemInfo.setZIndex(50.0f); + mSystemInfo.setDefaultZIndex(50.0f); } void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem) @@ -699,11 +695,11 @@ void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem) mCarousel.type = HORIZONTAL; } if (elem->has("size")) - mCarousel.size = elem->get("size") * mSize; + mCarousel.size = elem->get("size") * mSize; if (elem->has("pos")) - mCarousel.pos = elem->get("pos") * mSize; + mCarousel.pos = elem->get("pos") * mSize; if (elem->has("origin")) - mCarousel.origin = elem->get("origin"); + mCarousel.origin = elem->get("origin"); if (elem->has("color")) { mCarousel.color = elem->get("color"); mCarousel.colorEnd = mCarousel.color; @@ -716,7 +712,7 @@ void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem) if (elem->has("logoScale")) mCarousel.logoScale = elem->get("logoScale"); if (elem->has("logoSize")) - mCarousel.logoSize = elem->get("logoSize") * mSize; + mCarousel.logoSize = elem->get("logoSize") * mSize; if (elem->has("maxLogoCount")) mCarousel.maxLogoCount = static_cast(std::round(elem->get("maxLogoCount"))); if (elem->has("zIndex")) @@ -724,7 +720,7 @@ void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem) if (elem->has("logoRotation")) mCarousel.logoRotation = elem->get("logoRotation"); if (elem->has("logoRotationOrigin")) - mCarousel.logoRotationOrigin = elem->get("logoRotationOrigin"); + mCarousel.logoRotationOrigin = elem->get("logoRotationOrigin"); if (elem->has("logoAlignment")) { if (!(elem->get("logoAlignment").compare("left"))) mCarousel.logoAlignment = ALIGN_LEFT; diff --git a/es-app/src/views/SystemView.h b/es-app/src/views/SystemView.h index 8d30c42c4..6e590c971 100644 --- a/es-app/src/views/SystemView.h +++ b/es-app/src/views/SystemView.h @@ -34,18 +34,18 @@ struct SystemViewData { struct SystemViewCarousel { CarouselType type; - Vector2f pos; - Vector2f size; - Vector2f origin; + glm::vec2 pos; + glm::vec2 size; + glm::vec2 origin; float logoScale; float logoRotation; - Vector2f logoRotationOrigin; + glm::vec2 logoRotationOrigin; Alignment logoAlignment; unsigned int color; unsigned int colorEnd; bool colorGradientHorizontal; int maxLogoCount; // Number of logos shown on the carousel. - Vector2f logoSize; + glm::vec2 logoSize; float zIndex; }; @@ -62,7 +62,7 @@ public: bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void onThemeChanged(const std::shared_ptr& theme); @@ -81,13 +81,17 @@ protected: private: void populate(); void updateGameCount(); + // Get the ThemeElements that make up the SystemView. void getViewElements(const std::shared_ptr& theme); + // Populate the system carousel with the legacy values. void getDefaultElements(void); void getCarouselFromTheme(const ThemeData::ThemeElement* elem); - void renderCarousel(const Transform4x4f& parentTrans); - void renderExtras(const Transform4x4f& parentTrans, float lower, float upper); - void renderFade(const Transform4x4f& trans); + // Render system carousel. + void renderCarousel(const glm::mat4& parentTrans); + // Draw background extras. + void renderExtras(const glm::mat4& parentTrans, float lower, float upper); + void renderFade(const glm::mat4& trans); SystemViewCarousel mCarousel; TextComponent mSystemInfo; diff --git a/es-app/src/views/UIModeController.h b/es-app/src/views/UIModeController.h index f16c4257d..5fbc83721 100644 --- a/es-app/src/views/UIModeController.h +++ b/es-app/src/views/UIModeController.h @@ -58,9 +58,7 @@ private: int mPassKeyCounter; // These are Xbox button names, so they may be different in pracise on non-Xbox controllers. - const std::vector mInputVals = { - "up", "down", "left", "right", "a", "b", "x", "y" - }; + const std::vector mInputVals = {"up", "down", "left", "right", "a", "b", "x", "y"}; }; #endif // ES_APP_VIEWS_UI_MODE_CONTROLLER_H diff --git a/es-app/src/views/ViewController.cpp b/es-app/src/views/ViewController.cpp index 03865faaf..577554d3c 100644 --- a/es-app/src/views/ViewController.cpp +++ b/es-app/src/views/ViewController.cpp @@ -41,12 +41,14 @@ const std::string ViewController::FOLDER_CHAR = Utils::String::wideStringToStrin const std::string ViewController::TICKMARK_CHAR = Utils::String::wideStringToString(L"\uF14A"); const std::string ViewController::CONTROLLER_CHAR = Utils::String::wideStringToString(L"\uF11b"); const std::string ViewController::FILTER_CHAR = Utils::String::wideStringToString(L"\uF0b0"); +const std::string ViewController::GEAR_CHAR = Utils::String::wideStringToString(L"\uF013"); #else const std::string ViewController::FAVORITE_CHAR = "\uF005"; const std::string ViewController::FOLDER_CHAR = "\uF07C"; const std::string ViewController::TICKMARK_CHAR = "\uF14A"; const std::string ViewController::CONTROLLER_CHAR = "\uF11b"; const std::string ViewController::FILTER_CHAR = "\uF0b0"; +const std::string ViewController::GEAR_CHAR = "\uF013"; #endif ViewController* ViewController::get() @@ -66,7 +68,7 @@ ViewController::ViewController(Window* window) , mCurrentView(nullptr) , mPreviousView(nullptr) , mSkipView(nullptr) - , mCamera(Transform4x4f::Identity()) + , mCamera(Renderer::getIdentity()) , mSystemViewTransition(false) , mWrappedViews(false) , mFadeOpacity(0) @@ -193,6 +195,17 @@ void ViewController::noGamesDialog() mWindow->pushGui(mNoGamesMessageBox); } +void ViewController::invalidAlternativeEmulatorDialog() +{ + mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(), + "AT LEAST ONE OF YOUR SYSTEMS HAS AN\n" + "INVALID ALTERNATIVE EMULATOR CONFIGURED\n" + "WITH NO MATCHING ENTRY IN THE SYSTEMS\n" + "CONFIGURATION FILE, PLEASE REVIEW YOUR\n" + "SETUP USING THE 'ALTERNATIVE EMULATORS'\n" + "ENTRY UNDER THE 'OTHER SETTINGS' MENU")); +} + void ViewController::goToStart() { // If the system view does not exist, then create it. We do this here as it would @@ -234,8 +247,8 @@ void ViewController::ReloadAndGoToStart() bool ViewController::isCameraMoving() { if (mCurrentView) { - if (mCamera.r3().x() - -mCurrentView->getPosition().x() != 0 || - mCamera.r3().y() - -mCurrentView->getPosition().y() != 0) + if (mCamera[3].x - -mCurrentView->getPosition().x != 0.0f || + mCamera[3].y - -mCurrentView->getPosition().y != 0.0f) return true; } return false; @@ -245,8 +258,8 @@ void ViewController::cancelViewTransitions() { if (Settings::getInstance()->getString("TransitionStyle") == "slide") { if (isCameraMoving()) { - mCamera.r3().x() = -mCurrentView->getPosition().x(); - mCamera.r3().y() = -mCurrentView->getPosition().y(); + mCamera[3].x = -mCurrentView->getPosition().x; + mCamera[3].y = -mCurrentView->getPosition().y; stopAllAnimations(); } // mSkipView is used when skipping through the gamelists in quick succession. @@ -285,8 +298,8 @@ int ViewController::getSystemId(SystemData* system) void ViewController::restoreViewPosition() { if (mPreviousView) { - Vector3f restorePosition = mPreviousView->getPosition(); - restorePosition.x() = mWrapPreviousPositionX; + glm::vec3 restorePosition{mPreviousView->getPosition()}; + restorePosition.x = mWrapPreviousPositionX; mPreviousView->setPosition(restorePosition); mWrapPreviousPositionX = 0; mWrappedViews = false; @@ -320,7 +333,7 @@ void ViewController::goToSystemView(SystemData* system, bool playTransition) auto systemList = getSystemListView(); systemList->setPosition(getSystemId(system) * static_cast(Renderer::getScreenWidth()), - systemList->getPosition().y()); + systemList->getPosition().y); systemList->goToSystem(system, false); mCurrentView = systemList; @@ -328,21 +341,21 @@ void ViewController::goToSystemView(SystemData* system, bool playTransition) // Application startup animation. if (applicationStartup) { - mCamera.translation() = -mCurrentView->getPosition(); + mCamera = glm::translate(mCamera, -mCurrentView->getPosition()); if (Settings::getInstance()->getString("TransitionStyle") == "slide") { if (getSystemListView()->getCarouselType() == CarouselType::HORIZONTAL || getSystemListView()->getCarouselType() == CarouselType::HORIZONTAL_WHEEL) - mCamera.translation().y() += Renderer::getScreenHeight(); + mCamera[3].y += static_cast(Renderer::getScreenHeight()); else - mCamera.translation().x() -= Renderer::getScreenWidth(); + mCamera[3].x -= static_cast(Renderer::getScreenWidth()); updateHelpPrompts(); } else if (Settings::getInstance()->getString("TransitionStyle") == "fade") { if (getSystemListView()->getCarouselType() == CarouselType::HORIZONTAL || getSystemListView()->getCarouselType() == CarouselType::HORIZONTAL_WHEEL) - mCamera.translation().y() += Renderer::getScreenHeight(); + mCamera[3].y += static_cast(Renderer::getScreenHeight()); else - mCamera.translation().x() += Renderer::getScreenWidth(); + mCamera[3].x += static_cast(Renderer::getScreenWidth()); } else { updateHelpPrompts(); @@ -444,13 +457,13 @@ void ViewController::goToGameList(SystemData* system) if (mState.viewing == SYSTEM_SELECT) { // Move the system list. auto sysList = getSystemListView(); - float offsetX = sysList->getPosition().x(); + float offsetX = sysList->getPosition().x; int sysId = getSystemId(system); sysList->setPosition(sysId * static_cast(Renderer::getScreenWidth()), - sysList->getPosition().y()); - offsetX = sysList->getPosition().x() - offsetX; - mCamera.translation().x() -= offsetX; + sysList->getPosition().y); + offsetX = sysList->getPosition().x - offsetX; + mCamera[3].x -= offsetX; } // If we are wrapping around, either from the first to last system, or the other way @@ -458,30 +471,30 @@ void ViewController::goToGameList(SystemData* system) // movements will be correct. This is accomplished by simply offsetting the X position // with the position of the first or last system plus the screen width. if (wrapFirstToLast) { - Vector3f currentPosition = mCurrentView->getPosition(); - mWrapPreviousPositionX = currentPosition.x(); - float offsetX = getGameListView(system)->getPosition().x(); + glm::vec3 currentPosition{mCurrentView->getPosition()}; + mWrapPreviousPositionX = currentPosition.x; + float offsetX{getGameListView(system)->getPosition().x}; // This is needed to move the camera in the correct direction if there are only two systems. if (SystemData::sSystemVector.size() == 2 && mNextSystem) offsetX -= Renderer::getScreenWidth(); else offsetX += Renderer::getScreenWidth(); - currentPosition.x() = offsetX; + currentPosition.x = offsetX; mCurrentView->setPosition(currentPosition); - mCamera.translation().x() -= offsetX; + mCamera[3].x -= offsetX; mWrappedViews = true; } else if (wrapLastToFirst) { - Vector3f currentPosition = mCurrentView->getPosition(); - mWrapPreviousPositionX = currentPosition.x(); - float offsetX = getGameListView(system)->getPosition().x(); + glm::vec3 currentPosition{mCurrentView->getPosition()}; + mWrapPreviousPositionX = currentPosition.x; + float offsetX{getGameListView(system)->getPosition().x}; if (SystemData::sSystemVector.size() == 2 && !mNextSystem) offsetX += Renderer::getScreenWidth(); else offsetX -= Renderer::getScreenWidth(); - currentPosition.x() = offsetX; + currentPosition.x = offsetX; mCurrentView->setPosition(currentPosition); - mCamera.translation().x() = -offsetX; + mCamera[3].x = -offsetX; mWrappedViews = true; } @@ -489,13 +502,13 @@ void ViewController::goToGameList(SystemData* system) // Application startup animation, if starting in a gamelist rather than in the system view. if (mState.viewing == NOTHING) { - mCamera.translation() = -mCurrentView->getPosition(); + mCamera = glm::translate(mCamera, -mCurrentView->getPosition()); if (Settings::getInstance()->getString("TransitionStyle") == "slide") { - mCamera.translation().y() -= Renderer::getScreenHeight(); + mCamera[3].y -= static_cast(Renderer::getScreenHeight()); updateHelpPrompts(); } else if (Settings::getInstance()->getString("TransitionStyle") == "fade") { - mCamera.translation().y() += Renderer::getScreenHeight() * 2; + mCamera[3].y += static_cast(Renderer::getScreenHeight() * 2); } else { updateHelpPrompts(); @@ -528,21 +541,23 @@ void ViewController::playViewTransition(bool instant) { mCancelledTransition = false; - Vector3f target(Vector3f::Zero()); + glm::vec3 target{}; if (mCurrentView) target = mCurrentView->getPosition(); // No need to animate, we're not going anywhere (probably due to goToNextGamelist() // or goToPrevGamelist() being called when there's only 1 system). - if (target == -mCamera.translation() && !isAnimationPlaying(0)) + if (target == static_cast(-mCamera[3]) && !isAnimationPlaying(0)) return; - std::string transition_style = Settings::getInstance()->getString("TransitionStyle"); + std::string transition_style{Settings::getInstance()->getString("TransitionStyle")}; if (instant || transition_style == "instant") { setAnimation(new LambdaAnimation( [this, target](float /*t*/) { - this->mCamera.translation() = -target; + this->mCamera[3].x = -target.x; + this->mCamera[3].y = -target.y; + this->mCamera[3].z = -target.z; if (mPreviousView) mPreviousView->onHide(); }, @@ -559,7 +574,7 @@ void ViewController::playViewTransition(bool instant) // Without this, a (much shorter) fade transition would still play as // finishedCallback is calling this function. if (!mCancelledTransition) - mFadeOpacity = Math::lerp(0.0f, 1.0f, t); + mFadeOpacity = glm::mix(0.0f, 1.0f, t); }; auto fadeCallback = [this]() { @@ -571,14 +586,16 @@ void ViewController::playViewTransition(bool instant) const static int FADE_WAIT = 200; // Time to wait between in/out. setAnimation(new LambdaAnimation(fadeFunc, FADE_DURATION), 0, [this, fadeFunc, fadeCallback, target] { - this->mCamera.translation() = -target; + this->mCamera[3].x = -target.x; + this->mCamera[3].y = -target.y; + this->mCamera[3].z = -target.z; updateHelpPrompts(); setAnimation(new LambdaAnimation(fadeFunc, FADE_DURATION), FADE_WAIT, fadeCallback, true); }); // Fast-forward animation if we're partway faded. - if (target == -mCamera.translation()) { + if (target == static_cast(-mCamera[3])) { // Not changing screens, so cancel the first half entirely. advanceAnimation(0, FADE_DURATION); advanceAnimation(0, FADE_WAIT); @@ -848,16 +865,16 @@ void ViewController::update(int deltaTime) } } -void ViewController::render(const Transform4x4f& parentTrans) +void ViewController::render(const glm::mat4& parentTrans) { - Transform4x4f trans = mCamera * parentTrans; - Transform4x4f transInverse; - transInverse.invert(trans); + glm::mat4 trans{mCamera * parentTrans}; + glm::mat4 transInverse{glm::inverse(trans)}; // Camera position, position + size. - Vector3f viewStart = transInverse.translation(); - Vector3f viewEnd = transInverse * Vector3f(static_cast(Renderer::getScreenWidth()), - static_cast(Renderer::getScreenHeight(), 0)); + glm::vec3 viewStart{transInverse[3]}; + glm::vec3 viewEnd{std::fabs(trans[3].x) + static_cast(Renderer::getScreenWidth()), + std::fabs(trans[3].y) + static_cast(Renderer::getScreenHeight()), + 0.0f}; // Keep track of UI mode changes. UIModeController::getInstance()->monitorUIMode(); @@ -872,12 +889,12 @@ void ViewController::render(const Transform4x4f& parentTrans) // Same thing as for the system view, limit the rendering only to what needs to be drawn. if (it->second == mCurrentView || (it->second == mPreviousView && isCameraMoving())) { // Clipping. - Vector3f guiStart = it->second->getPosition(); - Vector3f guiEnd = it->second->getPosition() + - Vector3f(it->second->getSize().x(), it->second->getSize().y(), 0); + glm::vec3 guiStart{it->second->getPosition()}; + glm::vec3 guiEnd{it->second->getPosition() + + glm::vec3{it->second->getSize().x, it->second->getSize().y, 0.0f}}; - if (guiEnd.x() >= viewStart.x() && guiEnd.y() >= viewStart.y() && - guiStart.x() <= viewEnd.x() && guiStart.y() <= viewEnd.y()) + if (guiEnd.x >= viewStart.x && guiEnd.y >= viewStart.y && guiStart.x <= viewEnd.x && + guiStart.y <= viewEnd.y) it->second->render(trans); } } @@ -1000,7 +1017,7 @@ void ViewController::reloadAll() SystemData* system = mState.getSystem(); mSystemListView->goToSystem(system, false); mCurrentView = mSystemListView; - mCamera.r3().x() = 0; + mCamera[3].x = 0.0f; } else { goToSystemView(SystemData::sSystemVector.front(), false); diff --git a/es-app/src/views/ViewController.h b/es-app/src/views/ViewController.h index 17d5f78ee..243558947 100644 --- a/es-app/src/views/ViewController.h +++ b/es-app/src/views/ViewController.h @@ -38,6 +38,7 @@ public: // These functions are called from main(). void invalidSystemsFileDialog(); void noGamesDialog(); + void invalidAlternativeEmulatorDialog(); // Try to completely populate the GameListView map. // Caches things so there's no pauses during transitions. @@ -78,7 +79,7 @@ public: bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; enum ViewMode { NOTHING, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0). @@ -127,6 +128,7 @@ public: static const std::string TICKMARK_CHAR; static const std::string CONTROLLER_CHAR; static const std::string FILTER_CHAR; + static const std::string GEAR_CHAR; private: ViewController(Window* window); @@ -152,7 +154,7 @@ private: FileData* mGameToLaunch; State mState; - Transform4x4f mCamera; + glm::mat4 mCamera; bool mSystemViewTransition; bool mWrappedViews; float mWrapPreviousPositionX; diff --git a/es-app/src/views/gamelist/BasicGameListView.cpp b/es-app/src/views/gamelist/BasicGameListView.cpp index 85c5fe64f..f6d2a4002 100644 --- a/es-app/src/views/gamelist/BasicGameListView.cpp +++ b/es-app/src/views/gamelist/BasicGameListView.cpp @@ -19,9 +19,9 @@ BasicGameListView::BasicGameListView(Window* window, FileData* root) : ISimpleGameListView(window, root) , mList(window) { - mList.setSize(mSize.x(), mSize.y() * 0.8f); - mList.setPosition(0, mSize.y() * 0.2f); - mList.setDefaultZIndex(20); + mList.setSize(mSize.x, mSize.y * 0.8f); + mList.setPosition(0.0f, mSize.y * 0.2f); + mList.setDefaultZIndex(20.0f); addChild(&mList); populateList(root->getChildrenListToDisplay(), root); @@ -287,8 +287,6 @@ std::vector BasicGameListView::getHelpPrompts() SystemData::sSystemVector.size() > 1) prompts.push_back(HelpPrompt("left/right", "system")); - prompts.push_back(HelpPrompt("up/down", "choose")); - if (mRoot->getSystem()->getThemeFolder() == "custom-collections" && mCursorStack.empty() && ViewController::get()->getState().viewing == ViewController::GAME_LIST) prompts.push_back(HelpPrompt("a", "enter")); diff --git a/es-app/src/views/gamelist/DetailedGameListView.cpp b/es-app/src/views/gamelist/DetailedGameListView.cpp index 7d4ea3baa..00bb64fed 100644 --- a/es-app/src/views/gamelist/DetailedGameListView.cpp +++ b/es-app/src/views/gamelist/DetailedGameListView.cpp @@ -45,8 +45,8 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) { const float padding = 0.01f; - mList.setPosition(mSize.x() * (0.50f + padding), mList.getPosition().y()); - mList.setSize(mSize.x() * (0.50f - padding), mList.getSize().y()); + mList.setPosition(mSize.x * (0.50f + padding), mList.getPosition().y); + mList.setSize(mSize.x * (0.50f - padding), mList.getSize().y); mList.setAlignment(TextListComponent::ALIGN_LEFT); mList.setCursorChangedCallback([&](const CursorState& /*state*/) { updateInfoPanel(); }); @@ -54,8 +54,8 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) mThumbnail.setOrigin(0.5f, 0.5f); mThumbnail.setPosition(2.0f, 2.0f); mThumbnail.setVisible(false); - mThumbnail.setMaxSize(mSize.x() * (0.25f - 2 * padding), mSize.y() * 0.10f); - mThumbnail.setDefaultZIndex(25); + mThumbnail.setMaxSize(mSize.x * (0.25f - 2.0f * padding), mSize.y * 0.10f); + mThumbnail.setDefaultZIndex(25.0f); addChild(&mThumbnail); // Marquee. @@ -63,15 +63,15 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) // Default to off the screen. mMarquee.setPosition(2.0f, 2.0f); mMarquee.setVisible(false); - mMarquee.setMaxSize(mSize.x() * (0.5f - 2 * padding), mSize.y() * 0.18f); - mMarquee.setDefaultZIndex(35); + mMarquee.setMaxSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.18f); + mMarquee.setDefaultZIndex(35.0f); addChild(&mMarquee); // Image. mImage.setOrigin(0.5f, 0.5f); - mImage.setPosition(mSize.x() * 0.25f, mList.getPosition().y() + mSize.y() * 0.2125f); - mImage.setMaxSize(mSize.x() * (0.50f - 2 * padding), mSize.y() * 0.4f); - mImage.setDefaultZIndex(30); + mImage.setPosition(mSize.x * 0.25f, mList.getPosition().y + mSize.y * 0.2125f); + mImage.setMaxSize(mSize.x * (0.50f - 2.0f * padding), mSize.y * 0.4f); + mImage.setDefaultZIndex(30.0f); addChild(&mImage); // Metadata labels + values. @@ -101,27 +101,27 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) addChild(&mLblPlayCount); addChild(&mPlayCount); - mName.setPosition(mSize.x(), mSize.y()); - mName.setDefaultZIndex(40); + mName.setPosition(mSize.x, mSize.y); + mName.setDefaultZIndex(40.0f); mName.setColor(0xAAAAAAFF); mName.setFont(Font::get(FONT_SIZE_MEDIUM)); mName.setHorizontalAlignment(ALIGN_CENTER); addChild(&mName); - mDescContainer.setPosition(mSize.x() * padding, mSize.y() * 0.65f); - mDescContainer.setSize(mSize.x() * (0.50f - 2.0f * padding), - mSize.y() - mDescContainer.getPosition().y()); + mDescContainer.setPosition(mSize.x * padding, mSize.y * 0.65f); + mDescContainer.setSize(mSize.x * (0.50f - 2.0f * padding), + mSize.y - mDescContainer.getPosition().y); mDescContainer.setAutoScroll(true); - mDescContainer.setDefaultZIndex(40); + mDescContainer.setDefaultZIndex(40.0f); addChild(&mDescContainer); mDescription.setFont(Font::get(FONT_SIZE_SMALL)); - mDescription.setSize(mDescContainer.getSize().x(), 0); + mDescription.setSize(mDescContainer.getSize().x, 0.0f); mDescContainer.addChild(&mDescription); mGamelistInfo.setOrigin(0.5f, 0.5f); mGamelistInfo.setFont(Font::get(FONT_SIZE_SMALL)); - mGamelistInfo.setDefaultZIndex(50); + mGamelistInfo.setDefaultZIndex(50.0f); mGamelistInfo.setVisible(true); addChild(&mGamelistInfo); @@ -145,10 +145,9 @@ void DetailedGameListView::onThemeChanged(const std::shared_ptr& them initMDLabels(); std::vector labels = getMDLabels(); assert(labels.size() == 8); - std::vector lblElements = { "md_lbl_rating", "md_lbl_releasedate", - "md_lbl_developer", "md_lbl_publisher", - "md_lbl_genre", "md_lbl_players", - "md_lbl_lastplayed", "md_lbl_playcount" }; + std::vector lblElements = { + "md_lbl_rating", "md_lbl_releasedate", "md_lbl_developer", "md_lbl_publisher", + "md_lbl_genre", "md_lbl_players", "md_lbl_lastplayed", "md_lbl_playcount"}; for (unsigned int i = 0; i < labels.size(); i++) labels[i]->applyTheme(theme, getName(), lblElements[i], ALL); @@ -156,23 +155,23 @@ void DetailedGameListView::onThemeChanged(const std::shared_ptr& them initMDValues(); std::vector values = getMDValues(); assert(values.size() == 8); - std::vector valElements = { "md_rating", "md_releasedate", "md_developer", - "md_publisher", "md_genre", "md_players", - "md_lastplayed", "md_playcount" }; + std::vector valElements = {"md_rating", "md_releasedate", "md_developer", + "md_publisher", "md_genre", "md_players", + "md_lastplayed", "md_playcount"}; for (unsigned int i = 0; i < values.size(); i++) values[i]->applyTheme(theme, getName(), valElements[i], ALL ^ ThemeFlags::TEXT); mDescContainer.applyTheme(theme, getName(), "md_description", POSITION | ThemeFlags::SIZE | Z_INDEX | VISIBLE); - mDescription.setSize(mDescContainer.getSize().x(), 0); + mDescription.setSize(mDescContainer.getSize().x, 0.0f); mDescription.applyTheme( theme, getName(), "md_description", ALL ^ (POSITION | ThemeFlags::SIZE | ThemeFlags::ORIGIN | TEXT | ROTATION)); mGamelistInfo.applyTheme(theme, getName(), "gamelistInfo", ALL ^ ThemeFlags::TEXT); // If there is no position defined in the theme for gamelistInfo, then hide it. - if (mGamelistInfo.getPosition() == 0) + if (mGamelistInfo.getPosition() == glm::vec3{}) mGamelistInfo.setVisible(false); else mGamelistInfo.setVisible(true); @@ -187,26 +186,26 @@ void DetailedGameListView::initMDLabels() const unsigned int colCount = 2; const unsigned int rowCount = static_cast(components.size() / 2); - Vector3f start(mSize.x() * 0.01f, mSize.y() * 0.625f, 0.0f); + glm::vec3 start{mSize.x * 0.01f, mSize.y * 0.625f, 0.0f}; - const float colSize = (mSize.x() * 0.48f) / colCount; - const float rowPadding = 0.01f * mSize.y(); + const float colSize = (mSize.x * 0.48f) / colCount; + const float rowPadding = 0.01f * mSize.y; for (unsigned int i = 0; i < components.size(); i++) { const unsigned int row = i % rowCount; - Vector3f pos(0.0f, 0.0f, 0.0f); + glm::vec3 pos{}; if (row == 0) { - pos = start + Vector3f(colSize * (i / rowCount), 0, 0); + pos = start + glm::vec3{colSize * (i / rowCount), 0.0f, 0.0f}; } else { // Work from the last component. GuiComponent* lc = components[i - 1]; - pos = lc->getPosition() + Vector3f(0, lc->getSize().y() + rowPadding, 0); + pos = lc->getPosition() + glm::vec3{0.0f, lc->getSize().y + rowPadding, 0.0f}; } components[i]->setFont(Font::get(FONT_SIZE_SMALL)); components[i]->setPosition(pos); - components[i]->setDefaultZIndex(40); + components[i]->setDefaultZIndex(40.0f); } } @@ -227,23 +226,22 @@ void DetailedGameListView::initMDValues() float bottom = 0.0f; - const float colSize = (mSize.x() * 0.48f) / 2.0f; + const float colSize = (mSize.x * 0.48f) / 2.0f; for (unsigned int i = 0; i < labels.size(); i++) { - const float heightDiff = (labels[i]->getSize().y() - values[i]->getSize().y()) / 2.0f; + const float heightDiff = (labels[i]->getSize().y - values[i]->getSize().y) / 2.0f; values[i]->setPosition(labels[i]->getPosition() + - Vector3f(labels[i]->getSize().x(), heightDiff, 0)); - values[i]->setSize(colSize - labels[i]->getSize().x(), values[i]->getSize().y()); + glm::vec3{labels[i]->getSize().x, heightDiff, 0.0f}); + values[i]->setSize(colSize - labels[i]->getSize().x, values[i]->getSize().y); values[i]->setDefaultZIndex(40.0f); - float testBot = values[i]->getPosition().y() + values[i]->getSize().y(); + float testBot = values[i]->getPosition().y + values[i]->getSize().y; if (testBot > bottom) bottom = testBot; } - mDescContainer.setPosition(mDescContainer.getPosition().x(), bottom + mSize.y() * 0.01f); - mDescContainer.setSize(mDescContainer.getSize().x(), - mSize.y() - mDescContainer.getPosition().y()); + mDescContainer.setPosition(mDescContainer.getPosition().x, bottom + mSize.y * 0.01f); + mDescContainer.setSize(mDescContainer.getSize().x, mSize.y - mDescContainer.getPosition().y); } void DetailedGameListView::updateInfoPanel() @@ -333,7 +331,7 @@ void DetailedGameListView::updateInfoPanel() CollectionSystemsManager::get()->updateCollectionFolderMetadata(file->getSystem()); if (mRandomGame) { mThumbnail.setImage(mRandomGame->getThumbnailPath()); - mMarquee.setImage(mRandomGame->getMarqueePath()); + mMarquee.setImage(mRandomGame->getMarqueePath(), false, true); mImage.setImage(mRandomGame->getImagePath()); } else { @@ -344,7 +342,7 @@ void DetailedGameListView::updateInfoPanel() } else { mThumbnail.setImage(file->getThumbnailPath()); - mMarquee.setImage(file->getMarqueePath()); + mMarquee.setImage(file->getMarqueePath(), false, true); mImage.setImage(file->getImagePath()); } @@ -386,7 +384,7 @@ void DetailedGameListView::updateInfoPanel() // Fade in the game image. auto func = [this](float t) { mImage.setOpacity(static_cast( - Math::lerp(static_cast(FADE_IN_START_OPACITY), 1.0f, t) * 255)); + glm::mix(static_cast(FADE_IN_START_OPACITY), 1.0f, t) * 255)); }; mImage.setAnimation(new LambdaAnimation(func, FADE_IN_TIME), 0, nullptr, false); @@ -434,7 +432,7 @@ void DetailedGameListView::updateInfoPanel() if ((comp->isAnimationPlaying(0) && comp->isAnimationReversed(0) != fadingOut) || (!comp->isAnimationPlaying(0) && comp->getOpacity() != (fadingOut ? 0 : 255))) { auto func = [comp](float t) { - comp->setOpacity(static_cast(Math::lerp(0.0f, 1.0f, t) * 255)); + comp->setOpacity(static_cast(glm::mix(0.0f, 1.0f, t) * 255)); }; comp->setAnimation(new LambdaAnimation(func, 150), 0, nullptr, fadingOut); } diff --git a/es-app/src/views/gamelist/GridGameListView.cpp b/es-app/src/views/gamelist/GridGameListView.cpp index c30339ea0..ae7eae6ee 100644 --- a/es-app/src/views/gamelist/GridGameListView.cpp +++ b/es-app/src/views/gamelist/GridGameListView.cpp @@ -47,8 +47,8 @@ GridGameListView::GridGameListView(Window* window, FileData* root) { const float padding = 0.01f; - mGrid.setPosition(mSize.x() * 0.1f, mSize.y() * 0.1f); - mGrid.setDefaultZIndex(20); + mGrid.setPosition(mSize.x * 0.1f, mSize.y * 0.1f); + mGrid.setDefaultZIndex(20.0f); mGrid.setCursorChangedCallback([&](const CursorState& /*state*/) { updateInfoPanel(); }); addChild(&mGrid); @@ -81,41 +81,41 @@ GridGameListView::GridGameListView(Window* window, FileData* root) addChild(&mLblPlayCount); addChild(&mPlayCount); - mName.setPosition(mSize.x(), mSize.y()); - mName.setDefaultZIndex(40); + mName.setPosition(mSize.x, mSize.y); + mName.setDefaultZIndex(40.0f); mName.setColor(0xAAAAAAFF); mName.setFont(Font::get(FONT_SIZE_MEDIUM)); mName.setHorizontalAlignment(ALIGN_CENTER); addChild(&mName); - mDescContainer.setPosition(mSize.x() * padding, mSize.y() * 0.65f); - mDescContainer.setSize(mSize.x() * (0.50f - 2.0f * padding), - mSize.y() - mDescContainer.getPosition().y()); + mDescContainer.setPosition(mSize.x * padding, mSize.y * 0.65f); + mDescContainer.setSize(mSize.x * (0.50f - 2.0f * padding), + mSize.y - mDescContainer.getPosition().y); mDescContainer.setAutoScroll(true); - mDescContainer.setDefaultZIndex(40); + mDescContainer.setDefaultZIndex(40.0f); addChild(&mDescContainer); mDescription.setFont(Font::get(FONT_SIZE_SMALL)); - mDescription.setSize(mDescContainer.getSize().x(), 0); + mDescription.setSize(mDescContainer.getSize().x, 0.0f); mDescContainer.addChild(&mDescription); mMarquee.setOrigin(0.5f, 0.5f); - mMarquee.setPosition(mSize.x() * 0.25f, mSize.y() * 0.10f); - mMarquee.setMaxSize(mSize.x() * (0.5f - 2.0f * padding), mSize.y() * 0.18f); - mMarquee.setDefaultZIndex(35); + mMarquee.setPosition(mSize.x * 0.25f, mSize.y * 0.10f); + mMarquee.setMaxSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.18f); + mMarquee.setDefaultZIndex(35.0f); mMarquee.setVisible(false); addChild(&mMarquee); mImage.setOrigin(0.5f, 0.5f); mImage.setPosition(2.0f, 2.0f); - mImage.setMaxSize(mSize.x() * (0.50f - 2 * padding), mSize.y() * 0.4f); - mImage.setDefaultZIndex(10); + mImage.setMaxSize(mSize.x * (0.50f - 2.0f * padding), mSize.y * 0.4f); + mImage.setDefaultZIndex(10.0f); mImage.setVisible(false); addChild(&mImage); mGamelistInfo.setOrigin(0.5f, 0.5f); mGamelistInfo.setFont(Font::get(FONT_SIZE_SMALL)); - mGamelistInfo.setDefaultZIndex(50); + mGamelistInfo.setDefaultZIndex(50.0f); mGamelistInfo.setVisible(true); addChild(&mGamelistInfo); @@ -244,10 +244,9 @@ void GridGameListView::onThemeChanged(const std::shared_ptr& theme) initMDLabels(); std::vector labels = getMDLabels(); assert(labels.size() == 8); - std::vector lblElements = { "md_lbl_rating", "md_lbl_releasedate", - "md_lbl_developer", "md_lbl_publisher", - "md_lbl_genre", "md_lbl_players", - "md_lbl_lastplayed", "md_lbl_playcount" }; + std::vector lblElements = { + "md_lbl_rating", "md_lbl_releasedate", "md_lbl_developer", "md_lbl_publisher", + "md_lbl_genre", "md_lbl_players", "md_lbl_lastplayed", "md_lbl_playcount"}; for (unsigned int i = 0; i < labels.size(); i++) labels[i]->applyTheme(theme, getName(), lblElements[i], ALL); @@ -255,16 +254,16 @@ void GridGameListView::onThemeChanged(const std::shared_ptr& theme) initMDValues(); std::vector values = getMDValues(); assert(values.size() == 8); - std::vector valElements = { "md_rating", "md_releasedate", "md_developer", - "md_publisher", "md_genre", "md_players", - "md_lastplayed", "md_playcount" }; + std::vector valElements = {"md_rating", "md_releasedate", "md_developer", + "md_publisher", "md_genre", "md_players", + "md_lastplayed", "md_playcount"}; for (unsigned int i = 0; i < values.size(); i++) values[i]->applyTheme(theme, getName(), valElements[i], ALL ^ ThemeFlags::TEXT); mDescContainer.applyTheme(theme, getName(), "md_description", POSITION | ThemeFlags::SIZE | Z_INDEX | VISIBLE); - mDescription.setSize(mDescContainer.getSize().x(), 0); + mDescription.setSize(mDescContainer.getSize().x, 0.0f); mDescription.applyTheme( theme, getName(), "md_description", ALL ^ (POSITION | ThemeFlags::SIZE | ThemeFlags::ORIGIN | TEXT | ROTATION)); @@ -277,7 +276,7 @@ void GridGameListView::onThemeChanged(const std::shared_ptr& theme) mGamelistInfo.applyTheme(theme, getName(), "gamelistInfo", ALL ^ ThemeFlags::TEXT); // If there is no position defined in the theme for gamelistInfo, then hide it. - if (mGamelistInfo.getPosition() == 0) + if (mGamelistInfo.getPosition() == glm::vec3{}) mGamelistInfo.setVisible(false); else mGamelistInfo.setVisible(true); @@ -298,26 +297,26 @@ void GridGameListView::initMDLabels() const unsigned int colCount = 2; const unsigned int rowCount = static_cast(components.size() / 2); - Vector3f start(mSize.x() * 0.01f, mSize.y() * 0.625f, 0.0f); + glm::vec3 start{mSize.x * 0.01f, mSize.y * 0.625f, 0.0f}; - const float colSize = (mSize.x() * 0.48f) / colCount; - const float rowPadding = 0.01f * mSize.y(); + const float colSize = (mSize.x * 0.48f) / colCount; + const float rowPadding = 0.01f * mSize.y; for (unsigned int i = 0; i < components.size(); i++) { const unsigned int row = i % rowCount; - Vector3f pos(0.0f, 0.0f, 0.0f); + glm::vec3 pos{}; if (row == 0) { - pos = start + Vector3f(colSize * (i / rowCount), 0, 0); + pos = start + glm::vec3{colSize * (i / rowCount), 0.0f, 0.0f}; } else { // Work from the last component. GuiComponent* lc = components[i - 1]; - pos = lc->getPosition() + Vector3f(0, lc->getSize().y() + rowPadding, 0); + pos = lc->getPosition() + glm::vec3{0.0f, lc->getSize().y + rowPadding, 0.0f}; } components[i]->setFont(Font::get(FONT_SIZE_SMALL)); components[i]->setPosition(pos); - components[i]->setDefaultZIndex(40); + components[i]->setDefaultZIndex(40.0f); } } @@ -338,22 +337,21 @@ void GridGameListView::initMDValues() float bottom = 0.0f; - const float colSize = (mSize.x() * 0.48f) / 2.0f; + const float colSize = (mSize.x * 0.48f) / 2.0f; for (unsigned int i = 0; i < labels.size(); i++) { - const float heightDiff = (labels[i]->getSize().y() - values[i]->getSize().y()) / 2.0f; + const float heightDiff = (labels[i]->getSize().y - values[i]->getSize().y) / 2.0f; values[i]->setPosition(labels[i]->getPosition() + - Vector3f(labels[i]->getSize().x(), heightDiff, 0)); - values[i]->setSize(colSize - labels[i]->getSize().x(), values[i]->getSize().y()); - values[i]->setDefaultZIndex(40); + glm::vec3{labels[i]->getSize().x, heightDiff, 0.0f}); + values[i]->setSize(colSize - labels[i]->getSize().x, values[i]->getSize().y); + values[i]->setDefaultZIndex(40.0f); - float testBot = values[i]->getPosition().y() + values[i]->getSize().y(); + float testBot = values[i]->getPosition().y + values[i]->getSize().y; if (testBot > bottom) bottom = testBot; } - mDescContainer.setPosition(mDescContainer.getPosition().x(), bottom + mSize.y() * 0.01f); - mDescContainer.setSize(mDescContainer.getSize().x(), - mSize.y() - mDescContainer.getPosition().y()); + mDescContainer.setPosition(mDescContainer.getPosition().x, bottom + mSize.y * 0.01f); + mDescContainer.setSize(mDescContainer.getSize().x, mSize.y - mDescContainer.getPosition().y); } void GridGameListView::updateInfoPanel() @@ -406,7 +404,7 @@ void GridGameListView::updateInfoPanel() fadingOut = true; } else { - mMarquee.setImage(file->getMarqueePath()); + mMarquee.setImage(file->getMarqueePath(), false, true); // Populate the gamelistInfo field which shows an icon if a folder has been entered // as well as the game count for the entire system (total and favorites separately). @@ -446,7 +444,7 @@ void GridGameListView::updateInfoPanel() // Fade in the game image. auto func = [this](float t) { mImage.setOpacity(static_cast( - Math::lerp(static_cast(FADE_IN_START_OPACITY), 1.0f, t) * 255)); + glm::mix(static_cast(FADE_IN_START_OPACITY), 1.0f, t) * 255)); }; mImage.setAnimation(new LambdaAnimation(func, FADE_IN_TIME), 0, nullptr, false); @@ -494,7 +492,7 @@ void GridGameListView::updateInfoPanel() (!comp->isAnimationPlaying(0) && comp->getOpacity() != (fadingOut ? 0 : 255))) { auto func = [comp](float t) { // TEMPORARY - This does not seem to work, needs to be reviewed later. - // comp->setOpacity(static_cast(Math::lerp(0.0f, 1.0f, t) * 255)); + // comp->setOpacity(static_cast(glm::mix(0.0f, 1.0f, t) * 255)); }; comp->setAnimation(new LambdaAnimation(func, 150), 0, nullptr, fadingOut); } diff --git a/es-app/src/views/gamelist/IGameListView.cpp b/es-app/src/views/gamelist/IGameListView.cpp index 64df0456f..6412b7b9b 100644 --- a/es-app/src/views/gamelist/IGameListView.cpp +++ b/es-app/src/views/gamelist/IGameListView.cpp @@ -60,17 +60,17 @@ HelpStyle IGameListView::getHelpStyle() return style; } -void IGameListView::render(const Transform4x4f& parentTrans) +void IGameListView::render(const glm::mat4& parentTrans) { - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; - float scaleX = trans.r0().x(); - float scaleY = trans.r1().y(); + float scaleX = trans[0].x; + float scaleY = trans[1].y; - Vector2i pos(static_cast(std::round(trans.translation()[0])), - static_cast(std::round(trans.translation()[1]))); - Vector2i size(static_cast(std::round(mSize.x() * scaleX)), - static_cast(std::round(mSize.y() * scaleY))); + glm::ivec2 pos{static_cast(std::round(trans[3].x)), + static_cast(std::round(trans[3].y))}; + glm::ivec2 size{static_cast(std::round(mSize.x * scaleX)), + static_cast(std::round(mSize.y * scaleY))}; Renderer::pushClipRect(pos, size); renderChildren(trans); diff --git a/es-app/src/views/gamelist/IGameListView.h b/es-app/src/views/gamelist/IGameListView.h index b1c39ac5e..853aa925e 100644 --- a/es-app/src/views/gamelist/IGameListView.h +++ b/es-app/src/views/gamelist/IGameListView.h @@ -54,7 +54,7 @@ public: virtual HelpStyle getHelpStyle() override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; protected: FileData* mRoot; diff --git a/es-app/src/views/gamelist/ISimpleGameListView.cpp b/es-app/src/views/gamelist/ISimpleGameListView.cpp index db12519c3..f84013582 100644 --- a/es-app/src/views/gamelist/ISimpleGameListView.cpp +++ b/es-app/src/views/gamelist/ISimpleGameListView.cpp @@ -28,18 +28,18 @@ ISimpleGameListView::ISimpleGameListView(Window* window, FileData* root) , mRandomGame(nullptr) { mHeaderText.setText("Logo Text"); - mHeaderText.setSize(mSize.x(), 0); - mHeaderText.setPosition(0, 0); + mHeaderText.setSize(mSize.x, 0.0f); + mHeaderText.setPosition(0.0f, 0.0f); mHeaderText.setHorizontalAlignment(ALIGN_CENTER); - mHeaderText.setDefaultZIndex(50); + mHeaderText.setDefaultZIndex(50.0f); - mHeaderImage.setResize(0, mSize.y() * 0.185f); + mHeaderImage.setResize(0.0f, mSize.y * 0.185f); mHeaderImage.setOrigin(0.5f, 0.0f); - mHeaderImage.setPosition(mSize.x() / 2, 0); - mHeaderImage.setDefaultZIndex(50); + mHeaderImage.setPosition(mSize.x / 2.0f, 0.0f); + mHeaderImage.setDefaultZIndex(50.0f); - mBackground.setResize(mSize.x(), mSize.y()); - mBackground.setDefaultZIndex(0); + mBackground.setResize(mSize.x, mSize.y); + mBackground.setDefaultZIndex(0.0f); addChild(&mHeaderText); addChild(&mBackground); diff --git a/es-app/src/views/gamelist/VideoGameListView.cpp b/es-app/src/views/gamelist/VideoGameListView.cpp index a1ddd7278..669a3f868 100644 --- a/es-app/src/views/gamelist/VideoGameListView.cpp +++ b/es-app/src/views/gamelist/VideoGameListView.cpp @@ -64,8 +64,8 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) mVideo = new VideoFFmpegComponent(window); #endif - mList.setPosition(mSize.x() * (0.50f + padding), mList.getPosition().y()); - mList.setSize(mSize.x() * (0.50f - padding), mList.getSize().y()); + mList.setPosition(mSize.x * (0.50f + padding), mList.getPosition().y); + mList.setSize(mSize.x * (0.50f - padding), mList.getSize().y); mList.setAlignment(TextListComponent::ALIGN_LEFT); mList.setCursorChangedCallback([&](const CursorState& /*state*/) { updateInfoPanel(); }); @@ -73,22 +73,22 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) mThumbnail.setOrigin(0.5f, 0.5f); mThumbnail.setPosition(2.0f, 2.0f); mThumbnail.setVisible(false); - mThumbnail.setMaxSize(mSize.x() * (0.25f - 2.0f * padding), mSize.y() * 0.10f); - mThumbnail.setDefaultZIndex(35); + mThumbnail.setMaxSize(mSize.x * (0.25f - 2.0f * padding), mSize.y * 0.10f); + mThumbnail.setDefaultZIndex(35.0f); addChild(&mThumbnail); // Marquee. mMarquee.setOrigin(0.5f, 0.5f); - mMarquee.setPosition(mSize.x() * 0.25f, mSize.y() * 0.10f); - mMarquee.setMaxSize(mSize.x() * (0.5f - 2.0f * padding), mSize.y() * 0.18f); - mMarquee.setDefaultZIndex(35); + mMarquee.setPosition(mSize.x * 0.25f, mSize.y * 0.10f); + mMarquee.setMaxSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.18f); + mMarquee.setDefaultZIndex(35.0f); addChild(&mMarquee); // Video. mVideo->setOrigin(0.5f, 0.5f); - mVideo->setPosition(mSize.x() * 0.25f, mSize.y() * 0.4f); - mVideo->setSize(mSize.x() * (0.5f - 2.0f * padding), mSize.y() * 0.4f); - mVideo->setDefaultZIndex(30); + mVideo->setPosition(mSize.x * 0.25f, mSize.y * 0.4f); + mVideo->setSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.4f); + mVideo->setDefaultZIndex(30.0f); addChild(mVideo); // Metadata labels + values. @@ -118,27 +118,27 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) addChild(&mLblPlayCount); addChild(&mPlayCount); - mName.setPosition(mSize.x(), mSize.y()); - mName.setDefaultZIndex(40); + mName.setPosition(mSize.x, mSize.y); + mName.setDefaultZIndex(40.0f); mName.setColor(0xAAAAAAFF); mName.setFont(Font::get(FONT_SIZE_MEDIUM)); mName.setHorizontalAlignment(ALIGN_CENTER); addChild(&mName); - mDescContainer.setPosition(mSize.x() * padding, mSize.y() * 0.65f); - mDescContainer.setSize(mSize.x() * (0.50f - 2.0f * padding), - mSize.y() - mDescContainer.getPosition().y()); + mDescContainer.setPosition(mSize.x * padding, mSize.y * 0.65f); + mDescContainer.setSize(mSize.x * (0.50f - 2.0f * padding), + mSize.y - mDescContainer.getPosition().y); mDescContainer.setAutoScroll(true); - mDescContainer.setDefaultZIndex(40); + mDescContainer.setDefaultZIndex(40.0f); addChild(&mDescContainer); mDescription.setFont(Font::get(FONT_SIZE_SMALL)); - mDescription.setSize(mDescContainer.getSize().x(), 0); + mDescription.setSize(mDescContainer.getSize().x, 0.0f); mDescContainer.addChild(&mDescription); mGamelistInfo.setOrigin(0.5f, 0.5f); mGamelistInfo.setFont(Font::get(FONT_SIZE_SMALL)); - mGamelistInfo.setDefaultZIndex(50); + mGamelistInfo.setDefaultZIndex(50.0f); mGamelistInfo.setVisible(true); addChild(&mGamelistInfo); @@ -167,10 +167,9 @@ void VideoGameListView::onThemeChanged(const std::shared_ptr& theme) initMDLabels(); std::vector labels = getMDLabels(); assert(labels.size() == 8); - std::vector lblElements = { "md_lbl_rating", "md_lbl_releasedate", - "md_lbl_developer", "md_lbl_publisher", - "md_lbl_genre", "md_lbl_players", - "md_lbl_lastplayed", "md_lbl_playcount" }; + std::vector lblElements = { + "md_lbl_rating", "md_lbl_releasedate", "md_lbl_developer", "md_lbl_publisher", + "md_lbl_genre", "md_lbl_players", "md_lbl_lastplayed", "md_lbl_playcount"}; for (unsigned int i = 0; i < labels.size(); i++) labels[i]->applyTheme(theme, getName(), lblElements[i], ALL); @@ -178,23 +177,23 @@ void VideoGameListView::onThemeChanged(const std::shared_ptr& theme) initMDValues(); std::vector values = getMDValues(); assert(values.size() == 8); - std::vector valElements = { "md_rating", "md_releasedate", "md_developer", - "md_publisher", "md_genre", "md_players", - "md_lastplayed", "md_playcount" }; + std::vector valElements = {"md_rating", "md_releasedate", "md_developer", + "md_publisher", "md_genre", "md_players", + "md_lastplayed", "md_playcount"}; for (unsigned int i = 0; i < values.size(); i++) values[i]->applyTheme(theme, getName(), valElements[i], ALL ^ ThemeFlags::TEXT); mDescContainer.applyTheme(theme, getName(), "md_description", POSITION | ThemeFlags::SIZE | Z_INDEX | VISIBLE); - mDescription.setSize(mDescContainer.getSize().x(), 0); + mDescription.setSize(mDescContainer.getSize().x, 0.0f); mDescription.applyTheme( theme, getName(), "md_description", ALL ^ (POSITION | ThemeFlags::SIZE | ThemeFlags::ORIGIN | TEXT | ROTATION)); mGamelistInfo.applyTheme(theme, getName(), "gamelistInfo", ALL ^ ThemeFlags::TEXT); // If there is no position defined in the theme for gamelistInfo, then hide it. - if (mGamelistInfo.getPosition() == 0) + if (mGamelistInfo.getPosition() == glm::vec3{}) mGamelistInfo.setVisible(false); else mGamelistInfo.setVisible(true); @@ -209,26 +208,26 @@ void VideoGameListView::initMDLabels() const unsigned int colCount = 2; const unsigned int rowCount = static_cast(components.size() / 2); - Vector3f start(mSize.x() * 0.01f, mSize.y() * 0.625f, 0.0f); + glm::vec3 start{mSize.x * 0.01f, mSize.y * 0.625f, 0.0f}; - const float colSize = (mSize.x() * 0.48f) / colCount; - const float rowPadding = 0.01f * mSize.y(); + const float colSize = (mSize.x * 0.48f) / colCount; + const float rowPadding = 0.01f * mSize.y; for (unsigned int i = 0; i < components.size(); i++) { const unsigned int row = i % rowCount; - Vector3f pos(0.0f, 0.0f, 0.0f); + glm::vec3 pos{}; if (row == 0) { - pos = start + Vector3f(colSize * (i / rowCount), 0, 0); + pos = start + glm::vec3{colSize * (i / rowCount), 0.0f, 0.0f}; } else { // Work from the last component. GuiComponent* lc = components[i - 1]; - pos = lc->getPosition() + Vector3f(0, lc->getSize().y() + rowPadding, 0); + pos = lc->getPosition() + glm::vec3{0.0f, lc->getSize().y + rowPadding, 0.0f}; } components[i]->setFont(Font::get(FONT_SIZE_SMALL)); components[i]->setPosition(pos); - components[i]->setDefaultZIndex(40); + components[i]->setDefaultZIndex(40.0f); } } @@ -249,23 +248,22 @@ void VideoGameListView::initMDValues() float bottom = 0.0f; - const float colSize = (mSize.x() * 0.48f) / 2.0f; + const float colSize = (mSize.x * 0.48f) / 2.0f; for (unsigned int i = 0; i < labels.size(); i++) { - const float heightDiff = (labels[i]->getSize().y() - values[i]->getSize().y()) / 2.0f; + const float heightDiff = (labels[i]->getSize().y - values[i]->getSize().y) / 2.0f; values[i]->setPosition(labels[i]->getPosition() + - Vector3f(labels[i]->getSize().x(), heightDiff, 0)); - values[i]->setSize(colSize - labels[i]->getSize().x(), values[i]->getSize().y()); - values[i]->setDefaultZIndex(40); + glm::vec3{labels[i]->getSize().x, heightDiff, 0.0f}); + values[i]->setSize(colSize - labels[i]->getSize().x, values[i]->getSize().y); + values[i]->setDefaultZIndex(40.0f); - float testBot = values[i]->getPosition().y() + values[i]->getSize().y(); + float testBot = values[i]->getPosition().y + values[i]->getSize().y; if (testBot > bottom) bottom = testBot; } - mDescContainer.setPosition(mDescContainer.getPosition().x(), bottom + mSize.y() * 0.01f); - mDescContainer.setSize(mDescContainer.getSize().x(), - mSize.y() - mDescContainer.getPosition().y()); + mDescContainer.setPosition(mDescContainer.getPosition().x, bottom + mSize.y * 0.01f); + mDescContainer.setSize(mDescContainer.getSize().x, mSize.y - mDescContainer.getPosition().y); } void VideoGameListView::updateInfoPanel() @@ -356,7 +354,7 @@ void VideoGameListView::updateInfoPanel() CollectionSystemsManager::get()->updateCollectionFolderMetadata(file->getSystem()); if (mRandomGame) { mThumbnail.setImage(mRandomGame->getThumbnailPath()); - mMarquee.setImage(mRandomGame->getMarqueePath()); + mMarquee.setImage(mRandomGame->getMarqueePath(), false, true); mVideo->setImage(mRandomGame->getImagePath()); // Always stop the video before setting a new video as it will otherwise continue // to play if it has the same path (i.e. it is the same physical video file) as @@ -378,7 +376,7 @@ void VideoGameListView::updateInfoPanel() } else { mThumbnail.setImage(file->getThumbnailPath()); - mMarquee.setImage(file->getMarqueePath()); + mMarquee.setImage(file->getMarqueePath(), false, true); mVideo->setImage(file->getImagePath()); mVideo->onHide(); @@ -426,7 +424,7 @@ void VideoGameListView::updateInfoPanel() // Fade in the game image. auto func = [this](float t) { mVideo->setOpacity(static_cast( - Math::lerp(static_cast(FADE_IN_START_OPACITY), 1.0f, t) * 255)); + glm::mix(static_cast(FADE_IN_START_OPACITY), 1.0f, t) * 255)); }; mVideo->setAnimation(new LambdaAnimation(func, FADE_IN_TIME), 0, nullptr, false); @@ -474,7 +472,7 @@ void VideoGameListView::updateInfoPanel() if ((comp->isAnimationPlaying(0) && comp->isAnimationReversed(0) != fadingOut) || (!comp->isAnimationPlaying(0) && comp->getOpacity() != (fadingOut ? 0 : 255))) { auto func = [comp](float t) { - comp->setOpacity(static_cast(Math::lerp(0.0f, 1.0f, t) * 255)); + comp->setOpacity(static_cast(glm::mix(0.0f, 1.0f, t) * 255)); }; comp->setAnimation(new LambdaAnimation(func, 200), 0, nullptr, fadingOut); } diff --git a/es-core/CMakeLists.txt b/es-core/CMakeLists.txt index 422c27d35..c28cadc36 100644 --- a/es-core/CMakeLists.txt +++ b/es-core/CMakeLists.txt @@ -22,6 +22,7 @@ set(CORE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/animations/Animation.h ${CMAKE_CURRENT_SOURCE_DIR}/src/animations/AnimationController.h ${CMAKE_CURRENT_SOURCE_DIR}/src/animations/LambdaAnimation.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/animations/MoveCameraAnimation.h # GUI components ${CMAKE_CURRENT_SOURCE_DIR}/src/components/AnimatedImageComponent.h @@ -57,14 +58,6 @@ set(CORE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiMsgBox.h ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiTextEditPopup.h - # Math - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Misc.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Transform4x4f.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector2f.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector2i.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector3f.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector4f.h - # Renderers ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer.h ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Shader_GL21.h @@ -79,6 +72,7 @@ set(CORE_HEADERS # Utils ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/CImgUtil.h ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/FileSystemUtil.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/MathUtil.h ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/StringUtil.h ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/TimeUtil.h ) @@ -134,14 +128,6 @@ set(CORE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiMsgBox.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiTextEditPopup.cpp - # Math - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Misc.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Transform4x4f.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector2f.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector2i.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector3f.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector4f.cpp - # Renderer ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer_GL21.cpp @@ -158,6 +144,7 @@ set(CORE_SOURCES # Utils ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/CImgUtil.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/FileSystemUtil.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/MathUtil.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/StringUtil.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/TimeUtil.cpp ) diff --git a/es-core/src/GuiComponent.cpp b/es-core/src/GuiComponent.cpp index d3cf8e09e..d2e55030b 100644 --- a/es-core/src/GuiComponent.cpp +++ b/es-core/src/GuiComponent.cpp @@ -24,11 +24,11 @@ GuiComponent::GuiComponent(Window* window) , mColorShiftEnd(0) , mOpacity(255) , mSaturation(1.0f) - , mPosition(Vector3f::Zero()) - , mOrigin(Vector2f::Zero()) + , mPosition({}) + , mOrigin({}) , mRotationOrigin(0.5f, 0.5f) - , mSize(Vector2f::Zero()) - , mTransform(Transform4x4f::Identity()) + , mSize({}) + , mTransform(Renderer::getIdentity()) , mIsProcessing(false) , mVisible(true) , mEnabled(true) @@ -78,16 +78,16 @@ void GuiComponent::update(int deltaTime) updateChildren(deltaTime); } -void GuiComponent::render(const Transform4x4f& parentTrans) +void GuiComponent::render(const glm::mat4& parentTrans) { if (!isVisible()) return; - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; renderChildren(trans); } -void GuiComponent::renderChildren(const Transform4x4f& transform) const +void GuiComponent::renderChildren(const glm::mat4& transform) const { for (unsigned int i = 0; i < getChildCount(); i++) getChild(i)->render(transform); @@ -95,26 +95,26 @@ void GuiComponent::renderChildren(const Transform4x4f& transform) const void GuiComponent::setPosition(float x, float y, float z) { - mPosition = Vector3f(x, y, z); + mPosition = glm::vec3{x, y, z}; onPositionChanged(); } void GuiComponent::setOrigin(float x, float y) { - mOrigin = Vector2f(x, y); + mOrigin = glm::vec2{x, y}; onOriginChanged(); } void GuiComponent::setSize(float w, float h) { - mSize = Vector2f(w, h); + mSize = glm::vec2{w, h}; onSizeChanged(); } -Vector2f GuiComponent::getCenter() const +glm::vec2 GuiComponent::getCenter() const { - return Vector2f(mPosition.x() - (getSize().x() * mOrigin.x()) + getSize().x() / 2.0f, - mPosition.y() - (getSize().y() * mOrigin.y()) + getSize().y() / 2.0f); + return glm::vec2{mPosition.x - (getSize().x * mOrigin.x) + getSize().x / 2.0f, + mPosition.y - (getSize().y * mOrigin.y) + getSize().y / 2.0f}; } void GuiComponent::addChild(GuiComponent* cmp) @@ -171,33 +171,34 @@ void GuiComponent::setOpacity(unsigned char opacity) (*it)->setOpacity(opacity); } -const Transform4x4f& GuiComponent::getTransform() +const glm::mat4& GuiComponent::getTransform() { - mTransform = Transform4x4f::Identity(); - mTransform.translate(mPosition); + mTransform = Renderer::getIdentity(); + mTransform = glm::translate(mTransform, mPosition); if (mScale != 1.0f) - mTransform.scale(mScale); + mTransform = glm::scale(mTransform, glm::vec3{mScale}); if (mRotation != 0.0f) { // Calculate offset as difference between origin and rotation origin. - Vector2f rotationSize = getRotationSize(); - float xOff = (mOrigin.x() - mRotationOrigin.x()) * rotationSize.x(); - float yOff = (mOrigin.y() - mRotationOrigin.y()) * rotationSize.y(); + glm::vec2 rotationSize{getRotationSize()}; + float xOff{(mOrigin.x - mRotationOrigin.x) * rotationSize.x}; + float yOff{(mOrigin.y - mRotationOrigin.y) * rotationSize.y}; // Transform to offset point. if (xOff != 0.0f || yOff != 0.0f) - mTransform.translate(Vector3f(xOff * -1.0f, yOff * -1.0f, 0.0f)); + mTransform = glm::translate(mTransform, glm::vec3{xOff * -1.0f, yOff * -1.0f, 0.0f}); // Apply rotation transform. - mTransform.rotateZ(mRotation); + mTransform = glm::rotate(mTransform, mRotation, glm::vec3{0.0f, 0.0f, 1.0f}); // Transform back to original point. if (xOff != 0.0f || yOff != 0.0f) - mTransform.translate(Vector3f(xOff, yOff, 0.0f)); + mTransform = glm::translate(mTransform, glm::vec3{xOff, yOff, 0.0f}); } - mTransform.translate( - Vector3f(mOrigin.x() * mSize.x() * -1.0f, mOrigin.y() * mSize.y() * -1.0f, 0.0f)); + mTransform = glm::translate( + mTransform, glm::vec3{mOrigin.x * mSize.x * -1.0f, mOrigin.y * mSize.y * -1.0f, 0.0f}); + return mTransform; } @@ -301,9 +302,9 @@ void GuiComponent::applyTheme(const std::shared_ptr& theme, const std::string& element, unsigned int properties) { - Vector2f scale = getParent() ? getParent()->getSize() : - Vector2f(static_cast(Renderer::getScreenWidth()), - static_cast(Renderer::getScreenHeight())); + glm::vec2 scale{getParent() ? getParent()->getSize() : + glm::vec2{static_cast(Renderer::getScreenWidth()), + static_cast(Renderer::getScreenHeight())}}; const ThemeData::ThemeElement* elem = theme->getElement(view, element, ""); if (!elem) @@ -311,24 +312,24 @@ void GuiComponent::applyTheme(const std::shared_ptr& theme, using namespace ThemeFlags; if (properties & POSITION && elem->has("pos")) { - Vector2f denormalized = elem->get("pos") * scale; - setPosition(Vector3f(denormalized.x(), denormalized.y(), 0)); + glm::vec2 denormalized{elem->get("pos") * scale}; + setPosition(glm::vec3{denormalized.x, denormalized.y, 0.0f}); } if (properties & ThemeFlags::SIZE && elem->has("size")) - setSize(elem->get("size") * scale); + setSize(elem->get("size") * scale); // Position + size also implies origin. if ((properties & ORIGIN || (properties & POSITION && properties & ThemeFlags::SIZE)) && elem->has("origin")) { - setOrigin(elem->get("origin")); + setOrigin(elem->get("origin")); } if (properties & ThemeFlags::ROTATION) { if (elem->has("rotation")) setRotationDegrees(elem->get("rotation")); if (elem->has("rotationOrigin")) - setRotationOrigin(elem->get("rotationOrigin")); + setRotationOrigin(elem->get("rotationOrigin")); } if (properties & ThemeFlags::Z_INDEX && elem->has("zIndex")) diff --git a/es-core/src/GuiComponent.h b/es-core/src/GuiComponent.h index 83901040f..543ed901a 100644 --- a/es-core/src/GuiComponent.h +++ b/es-core/src/GuiComponent.h @@ -13,8 +13,6 @@ #include "HelpStyle.h" #include "InputConfig.h" #include "animations/AnimationController.h" -#include "math/Misc.h" -#include "math/Transform4x4f.h" #include #include @@ -45,8 +43,8 @@ public: virtual void textInput(const std::string& text); // Called when input is received. - // Return true if the input is consumed, false if - // it should continue to be passed to other children. + // Return true if the input is consumed, false if it should continue to be passed + // to other children. virtual bool input(InputConfig* config, Input input); // Called when time passes. @@ -56,49 +54,50 @@ public: virtual void update(int deltaTime); // Called when it's time to render. - // By default, just calls renderChildren(parentTrans * getTransform()). - // You probably want to override this like so: - // 1. Calculate the new transform that your control will draw at with - // Transform4x4f t = parentTrans * getTransform(). + // By default, just calls renderChildren(parentTrans * getTransform()) + // Normally the following steps are required: + // 1. Calculate the new transform that your component will draw at + // glm::mat4 trans{parentTrans * getTransform()}; // 2. Set the renderer to use that new transform as the model matrix - // Renderer::setMatrix(t); - // 3. Draw your component. - // 4. Tell your children to render, based on your component's transform - renderChildren(t). - virtual void render(const Transform4x4f& parentTrans); + // Renderer::setMatrix(trans); + // 3. Draw your component + // 4. Tell your children to render, based on your component's transform + // renderChildren(trans); + virtual void render(const glm::mat4& parentTrans); - Vector3f getPosition() const { return mPosition; } - void setPosition(const Vector3f& offset) { setPosition(offset.x(), offset.y(), offset.z()); } + glm::vec3 getPosition() const { return mPosition; } + void setPosition(const glm::vec3& offset) { setPosition(offset.x, offset.y, offset.z); } void setPosition(float x, float y, float z = 0.0f); virtual void onPositionChanged() {} - Vector2f getOrigin() const { return mOrigin; } + glm::vec2 getOrigin() const { return mOrigin; } // Sets the origin as a percentage of this image. // (e.g. (0, 0) is top left, (0.5, 0.5) is the center.) void setOrigin(float originX, float originY); - void setOrigin(Vector2f origin) { setOrigin(origin.x(), origin.y()); } + void setOrigin(glm::vec2 origin) { setOrigin(origin.x, origin.y); } virtual void onOriginChanged() {} - Vector2f getRotationOrigin() const { return mRotationOrigin; } + glm::vec2 getRotationOrigin() const { return mRotationOrigin; } // Sets the rotation origin as a percentage of this image. // (e.g. (0, 0) is top left, (0.5, 0.5) is the center.) void setRotationOrigin(float originX, float originY) { - mRotationOrigin = Vector2f(originX, originY); + mRotationOrigin = glm::vec2{originX, originY}; } - void setRotationOrigin(Vector2f origin) { setRotationOrigin(origin.x(), origin.y()); } + void setRotationOrigin(glm::vec2 origin) { setRotationOrigin(origin.x, origin.y); } - virtual Vector2f getSize() const { return mSize; } - void setSize(const Vector2f& size) { setSize(size.x(), size.y()); } + virtual glm::vec2 getSize() const { return mSize; } + void setSize(const glm::vec2& size) { setSize(size.x, size.y); } void setSize(float w, float h); virtual void setResize(float width, float height) {} virtual void onSizeChanged() {} - virtual Vector2f getRotationSize() const { return getSize(); } + virtual glm::vec2 getRotationSize() const { return getSize(); } float getRotation() const { return mRotation; } void setRotation(float rotation) { mRotation = rotation; } void setRotationDegrees(float rotation) { - setRotation(static_cast(ES_DEG_TO_RAD(rotation))); + setRotation(static_cast(glm::radians(rotation))); } float getScale() const { return mScale; } @@ -114,7 +113,7 @@ public: void setVisible(bool visible) { mVisible = visible; } // Returns the center point of the image (takes origin into account). - Vector2f getCenter() const; + glm::vec2 getCenter() const; void setParent(GuiComponent* parent) { mParent = parent; } GuiComponent* getParent() const { return mParent; } @@ -183,7 +182,7 @@ public: virtual std::shared_ptr getFont() const { return nullptr; } - const Transform4x4f& getTransform(); + const glm::mat4& getTransform(); virtual std::string getValue() const { return ""; } virtual void setValue(const std::string& value) {} @@ -231,7 +230,7 @@ public: const static unsigned char MAX_ANIMATIONS = 4; protected: - void renderChildren(const Transform4x4f& transform) const; + void renderChildren(const glm::mat4& transform) const; void updateSelf(int deltaTime); // Updates animations. void updateChildren(int deltaTime); // Updates animations. @@ -249,10 +248,10 @@ protected: GuiComponent* mParent; std::vector mChildren; - Vector3f mPosition; - Vector2f mOrigin; - Vector2f mRotationOrigin; - Vector2f mSize; + glm::vec3 mPosition; + glm::vec2 mOrigin; + glm::vec2 mRotationOrigin; + glm::vec2 mSize; float mRotation = 0.0; float mScale = 1.0; @@ -265,8 +264,8 @@ protected: bool mEnabled; private: - // Don't access this directly! Use getTransform()! - Transform4x4f mTransform; + // Don't access this directly, instead use getTransform(). + glm::mat4 mTransform; AnimationController* mAnimationMap[MAX_ANIMATIONS]; }; diff --git a/es-core/src/HelpStyle.cpp b/es-core/src/HelpStyle.cpp index b57d55e73..b351906f7 100644 --- a/es-core/src/HelpStyle.cpp +++ b/es-core/src/HelpStyle.cpp @@ -13,10 +13,16 @@ HelpStyle::HelpStyle() { - position = Vector2f(Renderer::getScreenWidth() * 0.012f, Renderer::getScreenHeight() * 0.9515f); - origin = Vector2f(0.0f, 0.0f); - iconColor = 0x777777FF; + position = + glm::vec2{Renderer::getScreenWidth() * 0.012f, Renderer::getScreenHeight() * 0.9515f}; + origin = glm::vec2{}; textColor = 0x777777FF; + textColorDimmed = 0x777777FF; + iconColor = 0x777777FF; + iconColorDimmed = 0x777777FF; + entrySpacing = 16.0f; + iconTextSpacing = 8.0f; + textStyle = "uppercase"; if (FONT_SIZE_SMALL != 0) font = Font::get(FONT_SIZE_SMALL); @@ -31,19 +37,102 @@ void HelpStyle::applyTheme(const std::shared_ptr& theme, const std::s return; if (elem->has("pos")) - position = - elem->get("pos") * Vector2f(static_cast(Renderer::getScreenWidth()), - static_cast(Renderer::getScreenHeight())); + position = elem->get("pos") * + glm::vec2{static_cast(Renderer::getScreenWidth()), + static_cast(Renderer::getScreenHeight())}; if (elem->has("origin")) - origin = elem->get("origin"); + origin = elem->get("origin"); if (elem->has("textColor")) textColor = elem->get("textColor"); + if (elem->has("textColorDimmed")) + textColorDimmed = elem->get("textColorDimmed"); + if (elem->has("iconColor")) iconColor = elem->get("iconColor"); + if (elem->has("iconColorDimmed")) + iconColorDimmed = elem->get("iconColorDimmed"); + if (elem->has("fontPath") || elem->has("fontSize")) font = Font::getFromTheme(elem, ThemeFlags::ALL, font); + + if (elem->has("entrySpacing")) + entrySpacing = elem->get("entrySpacing"); + + if (elem->has("iconTextSpacing")) + iconTextSpacing = elem->get("iconTextSpacing"); + + if (elem->has("textStyle")) + textStyle = elem->get("textStyle"); + + // Load custom button icons. + + // General. + if (elem->has("dpad_updown")) + mCustomButtons.dpad_updown = elem->get("dpad_updown"); + if (elem->has("dpad_leftright")) + mCustomButtons.dpad_leftright = elem->get("dpad_leftright"); + if (elem->has("dpad_all")) + mCustomButtons.dpad_all = elem->get("dpad_all"); + if (elem->has("thumbstick_click")) + mCustomButtons.thumbstick_click = elem->get("thumbstick_click"); + if (elem->has("button_l")) + mCustomButtons.button_l = elem->get("button_l"); + if (elem->has("button_r")) + mCustomButtons.button_r = elem->get("button_r"); + if (elem->has("button_lr")) + mCustomButtons.button_lr = elem->get("button_lr"); + + // SNES. + if (elem->has("button_a_SNES")) + mCustomButtons.button_a_SNES = elem->get("button_a_SNES"); + if (elem->has("button_b_SNES")) + mCustomButtons.button_b_SNES = elem->get("button_b_SNES"); + if (elem->has("button_x_SNES")) + mCustomButtons.button_x_SNES = elem->get("button_x_SNES"); + if (elem->has("button_y_SNES")) + mCustomButtons.button_y_SNES = elem->get("button_y_SNES"); + if (elem->has("button_start_SNES")) + mCustomButtons.button_start_SNES = elem->get("button_start_SNES"); + if (elem->has("button_back_SNES")) + mCustomButtons.button_back_SNES = elem->get("button_back_SNES"); + + // PS. + if (elem->has("button_a_PS")) + mCustomButtons.button_a_PS = elem->get("button_a_PS"); + if (elem->has("button_b_PS")) + mCustomButtons.button_b_PS = elem->get("button_b_PS"); + if (elem->has("button_x_PS")) + mCustomButtons.button_x_PS = elem->get("button_x_PS"); + if (elem->has("button_y_PS")) + mCustomButtons.button_y_PS = elem->get("button_y_PS"); + if (elem->has("button_start_PS4")) + mCustomButtons.button_start_PS4 = elem->get("button_start_PS4"); + if (elem->has("button_back_PS4")) + mCustomButtons.button_back_PS4 = elem->get("button_back_PS4"); + if (elem->has("button_start_PS5")) + mCustomButtons.button_start_PS5 = elem->get("button_start_PS5"); + if (elem->has("button_back_PS5")) + mCustomButtons.button_back_PS5 = elem->get("button_back_PS5"); + + // XBOX. + if (elem->has("button_a_XBOX")) + mCustomButtons.button_a_XBOX = elem->get("button_a_XBOX"); + if (elem->has("button_b_XBOX")) + mCustomButtons.button_b_XBOX = elem->get("button_b_XBOX"); + if (elem->has("button_x_XBOX")) + mCustomButtons.button_x_XBOX = elem->get("button_x_XBOX"); + if (elem->has("button_y_XBOX")) + mCustomButtons.button_y_XBOX = elem->get("button_y_XBOX"); + if (elem->has("button_start_XBOX")) + mCustomButtons.button_start_XBOX = elem->get("button_start_XBOX"); + if (elem->has("button_back_XBOX")) + mCustomButtons.button_back_XBOX = elem->get("button_back_XBOX"); + if (elem->has("button_start_XBOX360")) + mCustomButtons.button_start_XBOX360 = elem->get("button_start_XBOX360"); + if (elem->has("button_back_XBOX360")) + mCustomButtons.button_back_XBOX360 = elem->get("button_back_XBOX360"); } diff --git a/es-core/src/HelpStyle.h b/es-core/src/HelpStyle.h index b82b86e96..737123ad0 100644 --- a/es-core/src/HelpStyle.h +++ b/es-core/src/HelpStyle.h @@ -10,7 +10,7 @@ #ifndef ES_CORE_HELP_STYLE_H #define ES_CORE_HELP_STYLE_H -#include "math/Vector2f.h" +#include "utils/MathUtil.h" #include #include @@ -19,11 +19,58 @@ class Font; class ThemeData; struct HelpStyle { - Vector2f position; - Vector2f origin; - unsigned int iconColor; + glm::vec2 position; + glm::vec2 origin; unsigned int textColor; + unsigned int textColorDimmed; + unsigned int iconColor; + unsigned int iconColorDimmed; std::shared_ptr font; + float entrySpacing; + float iconTextSpacing; + std::string textStyle; + + struct CustomButtonIcons { + + // General. + std::string dpad_updown; + std::string dpad_leftright; + std::string dpad_all; + std::string thumbstick_click; + std::string button_l; + std::string button_r; + std::string button_lr; + + // SNES. + std::string button_a_SNES; + std::string button_b_SNES; + std::string button_x_SNES; + std::string button_y_SNES; + std::string button_start_SNES; + std::string button_back_SNES; + + // PS. + std::string button_a_PS; + std::string button_b_PS; + std::string button_x_PS; + std::string button_y_PS; + std::string button_start_PS4; + std::string button_back_PS4; + std::string button_start_PS5; + std::string button_back_PS5; + + // XBOX. + std::string button_a_XBOX; + std::string button_b_XBOX; + std::string button_x_XBOX; + std::string button_y_XBOX; + std::string button_start_XBOX; + std::string button_back_XBOX; + std::string button_start_XBOX360; + std::string button_back_XBOX360; + }; + + CustomButtonIcons mCustomButtons; HelpStyle(); // Default values. void applyTheme(const std::shared_ptr& theme, const std::string& view); diff --git a/es-core/src/Log.h b/es-core/src/Log.h index da45efd9f..9d98951a0 100644 --- a/es-core/src/Log.h +++ b/es-core/src/Log.h @@ -49,12 +49,11 @@ protected: std::ostringstream os; private: - std::map logLevelMap { // Log level indicators. - { LogError, "Error" }, - { LogWarning, "Warn" }, - { LogInfo, "Info" }, - { LogDebug, "Debug" } - }; + std::map logLevelMap{// Log level indicators. + {LogError, "Error"}, + {LogWarning, "Warn"}, + {LogInfo, "Info"}, + {LogDebug, "Debug"}}; static LogLevel reportingLevel; LogLevel messageLevel; diff --git a/es-core/src/MameNames.cpp b/es-core/src/MameNames.cpp index 30b1f4748..a3ff474e3 100644 --- a/es-core/src/MameNames.cpp +++ b/es-core/src/MameNames.cpp @@ -68,8 +68,8 @@ MameNames::MameNames() for (pugi::xml_node gameNode = doc.child("game"); gameNode; gameNode = gameNode.next_sibling("game")) { - NamePair namePair = { gameNode.child("mamename").text().get(), - gameNode.child("realname").text().get() }; + NamePair namePair = {gameNode.child("mamename").text().get(), + gameNode.child("realname").text().get()}; mNamePairs.push_back(namePair); } diff --git a/es-core/src/Platform.cpp b/es-core/src/Platform.cpp index e0a70729c..8319555ba 100644 --- a/es-core/src/Platform.cpp +++ b/es-core/src/Platform.cpp @@ -139,7 +139,7 @@ int launchGameUnix(const std::string& cmd_utf8, bool runInBackground) int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground, bool hideWindow) { #if defined(_WIN64) - STARTUPINFOW si {}; + STARTUPINFOW si{}; PROCESS_INFORMATION pi; si.cb = sizeof(si); diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index 1d1822a54..845fac177 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -97,161 +97,162 @@ void Settings::setDefaults() // // Scraper. - mStringMap["Scraper"] = { "screenscraper", "screenscraper" }; - mBoolMap["ScraperUseAccountScreenScraper"] = { false, false }; - mStringMap["ScraperUsernameScreenScraper"] = { "", "" }; - mStringMap["ScraperPasswordScreenScraper"] = { "", "" }; + mStringMap["Scraper"] = {"screenscraper", "screenscraper"}; + mBoolMap["ScraperUseAccountScreenScraper"] = {false, false}; + mStringMap["ScraperUsernameScreenScraper"] = {"", ""}; + mStringMap["ScraperPasswordScreenScraper"] = {"", ""}; - mBoolMap["ScrapeGameNames"] = { true, true }; - mBoolMap["ScrapeRatings"] = { true, true }; - mBoolMap["ScrapeMetadata"] = { true, true }; - mBoolMap["ScrapeVideos"] = { true, true }; - mBoolMap["ScrapeScreenshots"] = { true, true }; - mBoolMap["ScrapeCovers"] = { true, true }; - mBoolMap["ScrapeMarquees"] = { true, true }; - mBoolMap["Scrape3DBoxes"] = { true, true }; + mBoolMap["ScrapeGameNames"] = {true, true}; + mBoolMap["ScrapeRatings"] = {true, true}; + mBoolMap["ScrapeMetadata"] = {true, true}; + mBoolMap["ScrapeVideos"] = {true, true}; + mBoolMap["ScrapeScreenshots"] = {true, true}; + mBoolMap["ScrapeCovers"] = {true, true}; + mBoolMap["ScrapeMarquees"] = {true, true}; + mBoolMap["Scrape3DBoxes"] = {true, true}; - mStringMap["MiximageResolution"] = { "1280x960", "1280x960" }; - mStringMap["MiximageScreenshotScaling"] = { "sharp", "sharp" }; - mBoolMap["MiximageGenerate"] = { true, true }; - mBoolMap["MiximageOverwrite"] = { true, true }; - mBoolMap["MiximageRemoveLetterboxes"] = { true, true }; - mBoolMap["MiximageRemovePillarboxes"] = { true, true }; - mBoolMap["MiximageIncludeMarquee"] = { true, true }; - mBoolMap["MiximageIncludeBox"] = { true, true }; - mBoolMap["MiximageCoverFallback"] = { true, true }; + mStringMap["MiximageResolution"] = {"1280x960", "1280x960"}; + mStringMap["MiximageScreenshotScaling"] = {"sharp", "sharp"}; + mBoolMap["MiximageGenerate"] = {true, true}; + mBoolMap["MiximageOverwrite"] = {true, true}; + mBoolMap["MiximageRemoveLetterboxes"] = {true, true}; + mBoolMap["MiximageRemovePillarboxes"] = {true, true}; + mBoolMap["MiximageIncludeMarquee"] = {true, true}; + mBoolMap["MiximageIncludeBox"] = {true, true}; + mBoolMap["MiximageCoverFallback"] = {true, true}; - mStringMap["ScraperRegion"] = { "eu", "eu" }; - mStringMap["ScraperLanguage"] = { "en", "en" }; - mBoolMap["ScraperOverwriteData"] = { true, true }; - mBoolMap["ScraperHaltOnInvalidMedia"] = { true, true }; - mBoolMap["ScraperSearchMetadataName"] = { true, true }; - mBoolMap["ScraperInteractive"] = { true, true }; - mBoolMap["ScraperSemiautomatic"] = { true, true }; - mBoolMap["ScraperRespectExclusions"] = { true, true }; - mBoolMap["ScraperExcludeRecursively"] = { true, true }; - mBoolMap["ScraperIncludeFolders"] = { false, false }; - mBoolMap["ScraperRetryPeerVerification"] = { false, false }; + mStringMap["ScraperRegion"] = {"eu", "eu"}; + mStringMap["ScraperLanguage"] = {"en", "en"}; + mBoolMap["ScraperOverwriteData"] = {true, true}; + mBoolMap["ScraperHaltOnInvalidMedia"] = {true, true}; + mBoolMap["ScraperSearchMetadataName"] = {true, true}; + mBoolMap["ScraperInteractive"] = {true, true}; + mBoolMap["ScraperSemiautomatic"] = {true, true}; + mBoolMap["ScraperRespectExclusions"] = {true, true}; + mBoolMap["ScraperExcludeRecursively"] = {true, true}; + mBoolMap["ScraperIncludeFolders"] = {false, false}; + mBoolMap["ScraperRetryPeerVerification"] = {false, false}; // UI settings. - mStringMap["StartupSystem"] = { "", "" }; - mStringMap["GamelistViewStyle"] = { "automatic", "automatic" }; - mStringMap["TransitionStyle"] = { "slide", "slide" }; - mStringMap["ThemeSet"] = { "rbsimple-DE", "rbsimple-DE" }; - mStringMap["UIMode"] = { "full", "full" }; - mStringMap["DefaultSortOrder"] = { "filename, ascending", "filename, ascending" }; - mStringMap["MenuOpeningEffect"] = { "scale-up", "scale-up" }; - mStringMap["LaunchScreenDuration"] = { "normal", "normal" }; - mBoolMap["MenuBlurBackground"] = { true, true }; - mBoolMap["GamelistVideoPillarbox"] = { true, true }; - mBoolMap["GamelistVideoScanlines"] = { false, false }; - mBoolMap["FoldersOnTop"] = { true, true }; - mBoolMap["FavoritesFirst"] = { true, true }; - mBoolMap["FavoritesStar"] = { true, true }; - mBoolMap["SpecialCharsASCII"] = { false, false }; - mBoolMap["ListScrollOverlay"] = { false, false }; - mBoolMap["FavoritesAddButton"] = { true, true }; - mBoolMap["RandomAddButton"] = { false, false }; - mBoolMap["GamelistFilters"] = { true, true }; - mBoolMap["QuickSystemSelect"] = { true, true }; - mBoolMap["ShowHelpPrompts"] = { true, true }; - mBoolMap["PlayVideosImmediately"] = { false, false }; - mBoolMap["EnableMenuKidMode"] = { false, false }; + mStringMap["StartupSystem"] = {"", ""}; + mStringMap["GamelistViewStyle"] = {"automatic", "automatic"}; + mStringMap["TransitionStyle"] = {"slide", "slide"}; + mStringMap["ThemeSet"] = {"rbsimple-DE", "rbsimple-DE"}; + mStringMap["UIMode"] = {"full", "full"}; + mStringMap["DefaultSortOrder"] = {"filename, ascending", "filename, ascending"}; + mStringMap["MenuOpeningEffect"] = {"scale-up", "scale-up"}; + mStringMap["LaunchScreenDuration"] = {"normal", "normal"}; // UI settings -> media viewer settings. - mBoolMap["MediaViewerKeepVideoRunning"] = { true, true }; - mBoolMap["MediaViewerStretchVideos"] = { false, false }; - mBoolMap["MediaViewerVideoScanlines"] = { true, true }; - mBoolMap["MediaViewerVideoBlur"] = { false, false }; - mBoolMap["MediaViewerScreenshotScanlines"] = { true, true }; + mBoolMap["MediaViewerKeepVideoRunning"] = {true, true}; + mBoolMap["MediaViewerStretchVideos"] = {false, false}; + mBoolMap["MediaViewerVideoScanlines"] = {true, true}; + mBoolMap["MediaViewerVideoBlur"] = {false, false}; + mBoolMap["MediaViewerScreenshotScanlines"] = {true, true}; // UI settings -> screensaver settings. - mIntMap["ScreensaverTimer"] = { 5 * 60 * 1000, 5 * 60 * 1000 }; // 5 minutes. - mStringMap["ScreensaverType"] = { "video", "video" }; - mBoolMap["ScreensaverControls"] = { true, true }; + mIntMap["ScreensaverTimer"] = {5 * 60 * 1000, 5 * 60 * 1000}; // 5 minutes. + mStringMap["ScreensaverType"] = {"video", "video"}; + mBoolMap["ScreensaverControls"] = {true, true}; // UI settings -> screensaver settings -> slideshow screensaver settings. - mIntMap["ScreensaverSwapImageTimeout"] = { 10000, 10000 }; - mBoolMap["ScreensaverStretchImages"] = { false, false }; - mBoolMap["ScreensaverSlideshowGameInfo"] = { true, true }; - mBoolMap["ScreensaverSlideshowScanlines"] = { true, true }; - mBoolMap["ScreensaverSlideshowCustomImages"] = { false, false }; - mBoolMap["ScreensaverSlideshowRecurse"] = { false, false }; - mStringMap["ScreensaverSlideshowImageDir"] = { "~/.emulationstation/slideshow/custom_images", - "~/.emulationstation/slideshow/custom_images" }; + mIntMap["ScreensaverSwapImageTimeout"] = {10000, 10000}; + mBoolMap["ScreensaverStretchImages"] = {false, false}; + mBoolMap["ScreensaverSlideshowGameInfo"] = {true, true}; + mBoolMap["ScreensaverSlideshowScanlines"] = {true, true}; + mBoolMap["ScreensaverSlideshowCustomImages"] = {false, false}; + mBoolMap["ScreensaverSlideshowRecurse"] = {false, false}; + mStringMap["ScreensaverSlideshowImageDir"] = {"~/.emulationstation/slideshow/custom_images", + "~/.emulationstation/slideshow/custom_images"}; // UI settings -> screensaver settings -> video screensaver settings. - mIntMap["ScreensaverSwapVideoTimeout"] = { 0, 0 }; - mBoolMap["ScreensaverStretchVideos"] = { false, false }; - mBoolMap["ScreensaverVideoGameInfo"] = { true, true }; - mBoolMap["ScreensaverVideoScanlines"] = { true, true }; - mBoolMap["ScreensaverVideoBlur"] = { false, false }; + mIntMap["ScreensaverSwapVideoTimeout"] = {0, 0}; + mBoolMap["ScreensaverStretchVideos"] = {false, false}; + mBoolMap["ScreensaverVideoGameInfo"] = {true, true}; + mBoolMap["ScreensaverVideoScanlines"] = {true, true}; + mBoolMap["ScreensaverVideoBlur"] = {false, false}; + + mBoolMap["MenuBlurBackground"] = {true, true}; + mBoolMap["GamelistVideoPillarbox"] = {true, true}; + mBoolMap["GamelistVideoScanlines"] = {false, false}; + mBoolMap["FoldersOnTop"] = {true, true}; + mBoolMap["FavoritesFirst"] = {true, true}; + mBoolMap["FavoritesStar"] = {true, true}; + mBoolMap["SpecialCharsASCII"] = {false, false}; + mBoolMap["ListScrollOverlay"] = {false, false}; + mBoolMap["FavoritesAddButton"] = {true, true}; + mBoolMap["RandomAddButton"] = {false, false}; + mBoolMap["GamelistFilters"] = {true, true}; + mBoolMap["QuickSystemSelect"] = {true, true}; + mBoolMap["ShowHelpPrompts"] = {true, true}; + mBoolMap["PlayVideosImmediately"] = {false, false}; + mBoolMap["EnableMenuKidMode"] = {false, false}; // Sound settings. - mIntMap["SoundVolumeNavigation"] = { 80, 80 }; - mIntMap["SoundVolumeVideos"] = { 100, 100 }; - mBoolMap["GamelistVideoAudio"] = { true, true }; - mBoolMap["MediaViewerVideoAudio"] = { true, true }; - mBoolMap["ScreensaverVideoAudio"] = { false, false }; - mBoolMap["NavigationSounds"] = { true, true }; + mIntMap["SoundVolumeNavigation"] = {80, 80}; + mIntMap["SoundVolumeVideos"] = {100, 100}; + mBoolMap["GamelistVideoAudio"] = {true, true}; + mBoolMap["MediaViewerVideoAudio"] = {true, true}; + mBoolMap["ScreensaverVideoAudio"] = {false, false}; + mBoolMap["NavigationSounds"] = {true, true}; // Input device settings. - mStringMap["InputControllerType"] = { "xbox", "xbox" }; - mBoolMap["InputOnlyFirstController"] = { false, false }; + mStringMap["InputControllerType"] = {"xbox", "xbox"}; + mBoolMap["InputOnlyFirstController"] = {false, false}; // Game collection settings. - mStringMap["CollectionSystemsAuto"] = { "", "" }; - mStringMap["CollectionSystemsCustom"] = { "", "" }; - mBoolMap["FavFirstCustom"] = { false, false }; - mBoolMap["FavStarCustom"] = { false, false }; - mBoolMap["UseCustomCollectionsSystem"] = { true, true }; - mBoolMap["CollectionShowSystemInfo"] = { true, true }; + mStringMap["CollectionSystemsAuto"] = {"", ""}; + mStringMap["CollectionSystemsCustom"] = {"", ""}; + mBoolMap["FavFirstCustom"] = {false, false}; + mBoolMap["FavStarCustom"] = {false, false}; + mBoolMap["UseCustomCollectionsSystem"] = {true, true}; + mBoolMap["CollectionShowSystemInfo"] = {true, true}; -// Other settings. + // Other settings. + mStringMap["MediaDirectory"] = {"", ""}; #if defined(_RPI_) - mIntMap["MaxVRAM"] = { 80, 80 }; + mIntMap["MaxVRAM"] = {80, 80}; #else - mIntMap["MaxVRAM"] = { 256, 256 }; + mIntMap["MaxVRAM"] = {256, 256}; #endif - mIntMap["DisplayIndex"] = { 1, 1 }; + mIntMap["DisplayIndex"] = {1, 1}; #if defined(__unix__) - mStringMap["FullscreenMode"] = { "normal", "normal" }; + mStringMap["FullscreenMode"] = {"normal", "normal"}; #endif #if defined(BUILD_VLC_PLAYER) #if defined(_RPI_) // As the FFmpeg video player is not HW accelerated, use VLC as default on this weak device. - mStringMap["VideoPlayer"] = { "vlc", "vlc" }; + mStringMap["VideoPlayer"] = {"vlc", "vlc"}; #else - mStringMap["VideoPlayer"] = { "ffmpeg", "ffmpeg" }; + mStringMap["VideoPlayer"] = {"ffmpeg", "ffmpeg"}; #endif #endif - mStringMap["ExitButtonCombo"] = { "F4", "F4" }; - mStringMap["SaveGamelistsMode"] = { "always", "always" }; + mStringMap["ExitButtonCombo"] = {"F4", "F4"}; + mStringMap["SaveGamelistsMode"] = {"always", "always"}; #if defined(_WIN64) - mBoolMap["HideTaskbar"] = { false, false }; + mBoolMap["HideTaskbar"] = {false, false}; #endif - mBoolMap["RunInBackground"] = { false, false }; + mBoolMap["RunInBackground"] = {false, false}; #if defined(_WIN64) - mBoolMap["LaunchWorkaround"] = { true, true }; + mBoolMap["LaunchWorkaround"] = {true, true}; #endif - mStringMap["MediaDirectory"] = { "", "" }; #if !defined(_RPI_) - mBoolMap["VideoHardwareDecoding"] = { false, false }; + mBoolMap["VideoHardwareDecoding"] = {false, false}; #endif - mBoolMap["VideoUpscaleFrameRate"] = { false, false }; - mBoolMap["LaunchCommandOverride"] = { true, true }; - mBoolMap["ShowHiddenFiles"] = { true, true }; - mBoolMap["ShowHiddenGames"] = { true, true }; - mBoolMap["CustomEventScripts"] = { false, false }; - mBoolMap["ParseGamelistOnly"] = { false, false }; + mBoolMap["VideoUpscaleFrameRate"] = {false, false}; + mBoolMap["LaunchCommandOverride"] = {true, true}; + mBoolMap["ShowHiddenFiles"] = {true, true}; + mBoolMap["ShowHiddenGames"] = {true, true}; + mBoolMap["CustomEventScripts"] = {false, false}; + mBoolMap["ParseGamelistOnly"] = {false, false}; #if defined(__unix__) - mBoolMap["DisableComposition"] = { true, true }; + mBoolMap["DisableComposition"] = {true, true}; #endif - mBoolMap["DisplayGPUStatistics"] = { false, false }; + mBoolMap["DisplayGPUStatistics"] = {false, false}; // macOS requires root privileges to reboot and power off so it doesn't make much // sense to enable this setting and menu entry for that operating system. #if !defined(__APPLE__) - mBoolMap["ShowQuitMenu"] = { false, false }; + mBoolMap["ShowQuitMenu"] = {false, false}; #endif // @@ -259,45 +260,45 @@ void Settings::setDefaults() // // Options listed using --help - mBoolMap["Debug"] = { false, false }; - mBoolMap["ForceFull"] = { false, false }; - mBoolMap["ForceKid"] = { false, false }; - mBoolMap["ForceKiosk"] = { false, false }; - mBoolMap["IgnoreGamelist"] = { false, false }; - mBoolMap["SplashScreen"] = { true, true }; - mBoolMap["VSync"] = { true, true }; + mBoolMap["Debug"] = {false, false}; + mBoolMap["ForceFull"] = {false, false}; + mBoolMap["ForceKid"] = {false, false}; + mBoolMap["ForceKiosk"] = {false, false}; + mBoolMap["IgnoreGamelist"] = {false, false}; + mBoolMap["SplashScreen"] = {true, true}; + mBoolMap["VSync"] = {true, true}; #if !defined(_WIN64) - mBoolMap["Windowed"] = { false, false }; + mBoolMap["Windowed"] = {false, false}; #endif - mIntMap["WindowWidth"] = { 0, 0 }; - mIntMap["WindowHeight"] = { 0, 0 }; - mIntMap["ScreenWidth"] = { 0, 0 }; + mIntMap["WindowWidth"] = {0, 0}; + mIntMap["WindowHeight"] = {0, 0}; + mIntMap["ScreenWidth"] = {0, 0}; // Undocumented options. - mIntMap["ScreenHeight"] = { 0, 0 }; - mIntMap["ScreenOffsetX"] = { 0, 0 }; - mIntMap["ScreenOffsetY"] = { 0, 0 }; - mIntMap["ScreenRotate"] = { 0, 0 }; + mIntMap["ScreenHeight"] = {0, 0}; + mIntMap["ScreenOffsetX"] = {0, 0}; + mIntMap["ScreenOffsetY"] = {0, 0}; + mIntMap["ScreenRotate"] = {0, 0}; // // Settings that can be changed in es_settings.xml // but that are not configurable via the GUI. // - mBoolMap["DebugSkipInputLogging"] = { false, false }; - mStringMap["ROMDirectory"] = { "", "" }; - mStringMap["UIMode_passkey"] = { "uuddlrlrba", "uuddlrlrba" }; + mBoolMap["DebugSkipInputLogging"] = {false, false}; + mStringMap["ROMDirectory"] = {"", ""}; + mStringMap["UIMode_passkey"] = {"uuddlrlrba", "uuddlrlrba"}; // // Hardcoded or program-internal settings. // - mStringMap["ApplicationVersion"] = { "", "" }; - mBoolMap["DebugGrid"] = { false, false }; - mBoolMap["DebugText"] = { false, false }; - mBoolMap["DebugImage"] = { false, false }; - mBoolMap["SplashScreenProgress"] = { true, true }; - mIntMap["ScraperFilter"] = { 0, 0 }; + mStringMap["ApplicationVersion"] = {"", ""}; + mBoolMap["DebugGrid"] = {false, false}; + mBoolMap["DebugText"] = {false, false}; + mBoolMap["DebugImage"] = {false, false}; + mBoolMap["SplashScreenProgress"] = {true, true}; + mIntMap["ScraperFilter"] = {0, 0}; } template diff --git a/es-core/src/ThemeData.cpp b/es-core/src/ThemeData.cpp index 72dbe06b1..5de869eb5 100644 --- a/es-core/src/ThemeData.cpp +++ b/es-core/src/ThemeData.cpp @@ -21,181 +21,184 @@ #include #include -std::vector ThemeData::sSupportedViews { { "all" }, { "system" }, { "basic" }, - { "detailed" }, { "grid" }, { "video" } }; -std::vector ThemeData::sSupportedFeatures { - { "navigationsounds" }, { "video" }, { "carousel" }, { "z-index" }, { "visible" } -}; +std::vector ThemeData::sSupportedViews{{"all"}, {"system"}, {"basic"}, + {"detailed"}, {"grid"}, {"video"}}; +std::vector ThemeData::sSupportedFeatures{ + {"navigationsounds"}, {"video"}, {"carousel"}, {"z-index"}, {"visible"}}; -std::map> - ThemeData::sElementMap { - { "image", - { { "pos", NORMALIZED_PAIR }, - { "size", NORMALIZED_PAIR }, - { "maxSize", NORMALIZED_PAIR }, - { "origin", NORMALIZED_PAIR }, - { "rotation", FLOAT }, - { "rotationOrigin", NORMALIZED_PAIR }, - { "path", PATH }, - { "default", PATH }, - { "tile", BOOLEAN }, - { "color", COLOR }, - { "colorEnd", COLOR }, - { "gradientType", STRING }, - { "visible", BOOLEAN }, - { "zIndex", FLOAT } } }, - { "imagegrid", - { { "pos", NORMALIZED_PAIR }, - { "size", NORMALIZED_PAIR }, - { "margin", NORMALIZED_PAIR }, - { "padding", NORMALIZED_RECT }, - { "autoLayout", NORMALIZED_PAIR }, - { "autoLayoutSelectedZoom", FLOAT }, - { "gameImage", PATH }, - { "folderImage", PATH }, - { "imageSource", STRING }, - { "scrollDirection", STRING }, - { "centerSelection", BOOLEAN }, - { "scrollLoop", BOOLEAN }, - { "animate", BOOLEAN }, - { "zIndex", FLOAT } } }, - { "gridtile", - { { "size", NORMALIZED_PAIR }, - { "padding", NORMALIZED_PAIR }, - { "imageColor", COLOR }, - { "backgroundImage", PATH }, - { "backgroundCornerSize", NORMALIZED_PAIR }, - { "backgroundColor", COLOR }, - { "backgroundCenterColor", COLOR }, - { "backgroundEdgeColor", COLOR } } }, - { "text", - { { "pos", NORMALIZED_PAIR }, - { "size", NORMALIZED_PAIR }, - { "origin", NORMALIZED_PAIR }, - { "rotation", FLOAT }, - { "rotationOrigin", NORMALIZED_PAIR }, - { "text", STRING }, - { "backgroundColor", COLOR }, - { "fontPath", PATH }, - { "fontSize", FLOAT }, - { "color", COLOR }, - { "alignment", STRING }, - { "forceUppercase", BOOLEAN }, - { "lineSpacing", FLOAT }, - { "value", STRING }, - { "visible", BOOLEAN }, - { "zIndex", FLOAT } } }, - { "textlist", - { { "pos", NORMALIZED_PAIR }, - { "size", NORMALIZED_PAIR }, - { "origin", NORMALIZED_PAIR }, - { "selectorHeight", FLOAT }, - { "selectorOffsetY", FLOAT }, - { "selectorColor", COLOR }, - { "selectorColorEnd", COLOR }, - { "selectorGradientType", STRING }, - { "selectorImagePath", PATH }, - { "selectorImageTile", BOOLEAN }, - { "selectedColor", COLOR }, - { "primaryColor", COLOR }, - { "secondaryColor", COLOR }, - { "fontPath", PATH }, - { "fontSize", FLOAT }, - { "scrollSound", PATH }, // For backward compatibility with old themes. - { "alignment", STRING }, - { "horizontalMargin", FLOAT }, - { "forceUppercase", BOOLEAN }, - { "lineSpacing", FLOAT }, - { "zIndex", FLOAT } } }, - { "container", - { { "pos", NORMALIZED_PAIR }, - { "size", NORMALIZED_PAIR }, - { "origin", NORMALIZED_PAIR }, - { "visible", BOOLEAN }, - { "zIndex", FLOAT } } }, - { "ninepatch", - { { "pos", NORMALIZED_PAIR }, - { "size", NORMALIZED_PAIR }, - { "path", PATH }, - { "visible", BOOLEAN }, - { "zIndex", FLOAT } } }, - { "datetime", - { { "pos", NORMALIZED_PAIR }, - { "size", NORMALIZED_PAIR }, - { "origin", NORMALIZED_PAIR }, - { "rotation", FLOAT }, - { "rotationOrigin", NORMALIZED_PAIR }, - { "backgroundColor", COLOR }, - { "fontPath", PATH }, - { "fontSize", FLOAT }, - { "color", COLOR }, - { "alignment", STRING }, - { "forceUppercase", BOOLEAN }, - { "lineSpacing", FLOAT }, - { "value", STRING }, - { "format", STRING }, - { "displayRelative", BOOLEAN }, - { "visible", BOOLEAN }, - { "zIndex", FLOAT } } }, - { "rating", - { { "pos", NORMALIZED_PAIR }, - { "size", NORMALIZED_PAIR }, - { "origin", NORMALIZED_PAIR }, - { "rotation", FLOAT }, - { "rotationOrigin", NORMALIZED_PAIR }, - { "color", COLOR }, - { "filledPath", PATH }, - { "unfilledPath", PATH }, - { "visible", BOOLEAN }, - { "zIndex", FLOAT } } }, - { "sound", { { "path", PATH } } }, - { "helpsystem", - { { "pos", NORMALIZED_PAIR }, - { "origin", NORMALIZED_PAIR }, - { "textColor", COLOR }, - { "iconColor", COLOR }, - { "fontPath", PATH }, - { "fontSize", FLOAT } } }, - { "navigationsounds", - { { "systembrowseSound", PATH }, - { "quicksysselectSound", PATH }, - { "selectSound", PATH }, - { "backSound", PATH }, - { "scrollSound", PATH }, - { "favoriteSound", PATH }, - { "launchSound", PATH } } }, - { "video", - { { "pos", NORMALIZED_PAIR }, - { "size", NORMALIZED_PAIR }, - { "maxSize", NORMALIZED_PAIR }, - { "origin", NORMALIZED_PAIR }, - { "rotation", FLOAT }, - { "rotationOrigin", NORMALIZED_PAIR }, - { "default", PATH }, - { "delay", FLOAT }, - { "visible", BOOLEAN }, - { "zIndex", FLOAT }, - { "showSnapshotNoVideo", BOOLEAN }, - { "showSnapshotDelay", BOOLEAN } } }, - { "carousel", - { { "type", STRING }, - { "size", NORMALIZED_PAIR }, - { "pos", NORMALIZED_PAIR }, - { "origin", NORMALIZED_PAIR }, - { "color", COLOR }, - { "colorEnd", COLOR }, - { "gradientType", STRING }, - { "logoScale", FLOAT }, - { "logoRotation", FLOAT }, - { "logoRotationOrigin", NORMALIZED_PAIR }, - { "logoSize", NORMALIZED_PAIR }, - { "logoAlignment", STRING }, - { "maxLogoCount", FLOAT }, - { "zIndex", FLOAT } } } - }; +std::map> ThemeData::sElementMap{ + {"image", + {{"pos", NORMALIZED_PAIR}, + {"size", NORMALIZED_PAIR}, + {"maxSize", NORMALIZED_PAIR}, + {"origin", NORMALIZED_PAIR}, + {"rotation", FLOAT}, + {"rotationOrigin", NORMALIZED_PAIR}, + {"path", PATH}, + {"default", PATH}, + {"tile", BOOLEAN}, + {"color", COLOR}, + {"colorEnd", COLOR}, + {"gradientType", STRING}, + {"visible", BOOLEAN}, + {"zIndex", FLOAT}}}, + {"imagegrid", + {{"pos", NORMALIZED_PAIR}, + {"size", NORMALIZED_PAIR}, + {"margin", NORMALIZED_PAIR}, + {"padding", NORMALIZED_RECT}, + {"autoLayout", NORMALIZED_PAIR}, + {"autoLayoutSelectedZoom", FLOAT}, + {"gameImage", PATH}, + {"folderImage", PATH}, + {"imageSource", STRING}, + {"scrollDirection", STRING}, + {"centerSelection", BOOLEAN}, + {"scrollLoop", BOOLEAN}, + {"animate", BOOLEAN}, + {"zIndex", FLOAT}}}, + {"gridtile", + {{"size", NORMALIZED_PAIR}, + {"padding", NORMALIZED_PAIR}, + {"imageColor", COLOR}, + {"backgroundImage", PATH}, + {"backgroundCornerSize", NORMALIZED_PAIR}, + {"backgroundColor", COLOR}, + {"backgroundCenterColor", COLOR}, + {"backgroundEdgeColor", COLOR}}}, + {"text", + {{"pos", NORMALIZED_PAIR}, + {"size", NORMALIZED_PAIR}, + {"origin", NORMALIZED_PAIR}, + {"rotation", FLOAT}, + {"rotationOrigin", NORMALIZED_PAIR}, + {"text", STRING}, + {"backgroundColor", COLOR}, + {"fontPath", PATH}, + {"fontSize", FLOAT}, + {"color", COLOR}, + {"alignment", STRING}, + {"forceUppercase", BOOLEAN}, + {"lineSpacing", FLOAT}, + {"value", STRING}, + {"visible", BOOLEAN}, + {"zIndex", FLOAT}}}, + {"textlist", + {{"pos", NORMALIZED_PAIR}, + {"size", NORMALIZED_PAIR}, + {"origin", NORMALIZED_PAIR}, + {"selectorHeight", FLOAT}, + {"selectorOffsetY", FLOAT}, + {"selectorColor", COLOR}, + {"selectorColorEnd", COLOR}, + {"selectorGradientType", STRING}, + {"selectorImagePath", PATH}, + {"selectorImageTile", BOOLEAN}, + {"selectedColor", COLOR}, + {"primaryColor", COLOR}, + {"secondaryColor", COLOR}, + {"fontPath", PATH}, + {"fontSize", FLOAT}, + {"scrollSound", PATH}, // For backward compatibility with old themes. + {"alignment", STRING}, + {"horizontalMargin", FLOAT}, + {"forceUppercase", BOOLEAN}, + {"lineSpacing", FLOAT}, + {"zIndex", FLOAT}}}, + {"container", + {{"pos", NORMALIZED_PAIR}, + {"size", NORMALIZED_PAIR}, + {"origin", NORMALIZED_PAIR}, + {"visible", BOOLEAN}, + {"zIndex", FLOAT}}}, + {"ninepatch", + {{"pos", NORMALIZED_PAIR}, + {"size", NORMALIZED_PAIR}, + {"path", PATH}, + {"visible", BOOLEAN}, + {"zIndex", FLOAT}}}, + {"datetime", + {{"pos", NORMALIZED_PAIR}, + {"size", NORMALIZED_PAIR}, + {"origin", NORMALIZED_PAIR}, + {"rotation", FLOAT}, + {"rotationOrigin", NORMALIZED_PAIR}, + {"backgroundColor", COLOR}, + {"fontPath", PATH}, + {"fontSize", FLOAT}, + {"color", COLOR}, + {"alignment", STRING}, + {"forceUppercase", BOOLEAN}, + {"lineSpacing", FLOAT}, + {"value", STRING}, + {"format", STRING}, + {"displayRelative", BOOLEAN}, + {"visible", BOOLEAN}, + {"zIndex", FLOAT}}}, + {"rating", + {{"pos", NORMALIZED_PAIR}, + {"size", NORMALIZED_PAIR}, + {"origin", NORMALIZED_PAIR}, + {"rotation", FLOAT}, + {"rotationOrigin", NORMALIZED_PAIR}, + {"color", COLOR}, + {"filledPath", PATH}, + {"unfilledPath", PATH}, + {"visible", BOOLEAN}, + {"zIndex", FLOAT}}}, + {"sound", {{"path", PATH}}}, + {"helpsystem", + {{"pos", NORMALIZED_PAIR}, + {"origin", NORMALIZED_PAIR}, + {"textColor", COLOR}, + {"textColorDimmed", COLOR}, + {"iconColor", COLOR}, + {"iconColorDimmed", COLOR}, + {"fontPath", PATH}, + {"fontSize", FLOAT}, + {"entrySpacing", FLOAT}, + {"iconTextSpacing", FLOAT}, + {"textStyle", STRING}, + {"customButtonIcon", PATH}}}, + {"navigationsounds", + {{"systembrowseSound", PATH}, + {"quicksysselectSound", PATH}, + {"selectSound", PATH}, + {"backSound", PATH}, + {"scrollSound", PATH}, + {"favoriteSound", PATH}, + {"launchSound", PATH}}}, + {"video", + {{"pos", NORMALIZED_PAIR}, + {"size", NORMALIZED_PAIR}, + {"maxSize", NORMALIZED_PAIR}, + {"origin", NORMALIZED_PAIR}, + {"rotation", FLOAT}, + {"rotationOrigin", NORMALIZED_PAIR}, + {"default", PATH}, + {"delay", FLOAT}, + {"visible", BOOLEAN}, + {"zIndex", FLOAT}, + {"showSnapshotNoVideo", BOOLEAN}, + {"showSnapshotDelay", BOOLEAN}}}, + {"carousel", + {{"type", STRING}, + {"size", NORMALIZED_PAIR}, + {"pos", NORMALIZED_PAIR}, + {"origin", NORMALIZED_PAIR}, + {"color", COLOR}, + {"colorEnd", COLOR}, + {"gradientType", STRING}, + {"logoScale", FLOAT}, + {"logoRotation", FLOAT}, + {"logoRotationOrigin", NORMALIZED_PAIR}, + {"logoSize", NORMALIZED_PAIR}, + {"logoAlignment", STRING}, + {"maxLogoCount", FLOAT}, + {"zIndex", FLOAT}}}}; #define MINIMUM_THEME_FORMAT_VERSION 3 -#define CURRENT_THEME_FORMAT_VERSION 6 +#define CURRENT_THEME_FORMAT_VERSION 7 // Helper. unsigned int getHexColor(const std::string& str) @@ -450,20 +453,20 @@ void ThemeData::parseElement(const pugi::xml_node& root, switch (typeIt->second) { case NORMALIZED_RECT: { - Vector4f val; + glm::vec4 val; auto splits = Utils::String::delimitedStringToVector(str, " "); if (splits.size() == 2) { - val = Vector4f(static_cast(atof(splits.at(0).c_str())), - static_cast(atof(splits.at(1).c_str())), - static_cast(atof(splits.at(0).c_str())), - static_cast(atof(splits.at(1).c_str()))); + val = glm::vec4{static_cast(atof(splits.at(0).c_str())), + static_cast(atof(splits.at(1).c_str())), + static_cast(atof(splits.at(0).c_str())), + static_cast(atof(splits.at(1).c_str()))}; } else if (splits.size() == 4) { - val = Vector4f(static_cast(atof(splits.at(0).c_str())), - static_cast(atof(splits.at(1).c_str())), - static_cast(atof(splits.at(2).c_str())), - static_cast(atof(splits.at(3).c_str()))); + val = glm::vec4{static_cast(atof(splits.at(0).c_str())), + static_cast(atof(splits.at(1).c_str())), + static_cast(atof(splits.at(2).c_str())), + static_cast(atof(splits.at(3).c_str()))}; } element.properties[node.name()] = val; @@ -475,11 +478,11 @@ void ThemeData::parseElement(const pugi::xml_node& root, throw error << "invalid normalized pair (property \"" << node.name() << "\", value \"" << str.c_str() << "\")"; - std::string first = str.substr(0, divider); - std::string second = str.substr(divider, std::string::npos); + std::string first{str.substr(0, divider)}; + std::string second{str.substr(divider, std::string::npos)}; - Vector2f val(static_cast(atof(first.c_str())), - static_cast(atof(second.c_str()))); + glm::vec2 val{static_cast(atof(first.c_str())), + static_cast(atof(second.c_str()))}; element.properties[node.name()] = val; break; @@ -499,7 +502,20 @@ void ThemeData::parseElement(const pugi::xml_node& root, << ((node.text().get() != path) ? "which resolves to \"" + path + "\"" : ""); } - element.properties[node.name()] = path; + + // Special parsing instruction for customButtonIcon -> save node as it's button + // attribute to prevent nodes overwriting each other. + if (strcmp(node.name(), "customButtonIcon") == 0) { + const auto btn = node.attribute("button").as_string(""); + if (strcmp(btn, "") == 0) + LOG(LogError) + << " element requires the `button` property."; + else + element.properties[btn] = path; + } + else + element.properties[node.name()] = path; + break; } case COLOR: { @@ -602,7 +618,7 @@ std::vector ThemeData::makeExtras(const std::shared_ptrsetDefaultZIndex(10); + comp->setDefaultZIndex(10.0f); comp->applyTheme(theme, view, *it, ThemeFlags::ALL); comps.push_back(comp); } @@ -643,7 +659,7 @@ std::map ThemeData::getThemeSets() for (Utils::FileSystem::stringList::const_iterator it = dirContent.cbegin(); it != dirContent.cend(); it++) { if (Utils::FileSystem::isDirectory(*it)) { - ThemeSet set = { *it }; + ThemeSet set = {*it}; sets[set.getName()] = set; } } diff --git a/es-core/src/ThemeData.h b/es-core/src/ThemeData.h index d3e008b64..181c215a2 100644 --- a/es-core/src/ThemeData.h +++ b/es-core/src/ThemeData.h @@ -11,9 +11,8 @@ #ifndef ES_CORE_THEME_DATA_H #define ES_CORE_THEME_DATA_H -#include "math/Vector2f.h" -#include "math/Vector4f.h" #include "utils/FileSystemUtil.h" +#include "utils/MathUtil.h" #include #include @@ -103,20 +102,20 @@ public: std::string type; struct Property { - void operator=(const Vector4f& value) + void operator=(const glm::vec4& value) { r = value; - const Vector4f initVector = value; - v = Vector2f(initVector.x(), initVector.y()); + const glm::vec4 initVector{value}; + v = glm::vec2{initVector.x, initVector.y}; } - void operator=(const Vector2f& value) { v = value; } + void operator=(const glm::vec2& value) { v = value; } void operator=(const std::string& value) { s = value; } void operator=(const unsigned int& value) { i = value; } void operator=(const float& value) { f = value; } void operator=(const bool& value) { b = value; } - Vector4f r; - Vector2f v; + glm::vec4 r; + glm::vec2 v; std::string s; unsigned int i; float f; @@ -127,7 +126,7 @@ public: template const T get(const std::string& prop) const { - if (std::is_same::value) + if (std::is_same::value) return *(const T*)&properties.at(prop).v; else if (std::is_same::value) return *(const T*)&properties.at(prop).s; @@ -137,7 +136,7 @@ public: return *(const T*)&properties.at(prop).f; else if (std::is_same::value) return *(const T*)&properties.at(prop).b; - else if (std::is_same::value) + else if (std::is_same::value) return *(const T*)&properties.at(prop).r; return T(); } diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index e1820ecc6..8b021ed9b 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -45,7 +45,6 @@ Window::Window() , mCachedBackground(false) , mInvalidatedCachedBackground(false) , mVideoPlayerCount(0) - , mTopOpacity(0) , mTopScale(0.5) , mListScrollOpacity(0) , mChangedThemeSet(false) @@ -231,6 +230,20 @@ void Window::input(InputConfig* config, Input input) return; } + if (config->isMappedTo("a", input) && input.value != 0 && + Settings::getInstance()->getString("MenuOpeningEffect") == "scale-up" && mTopScale < 1.0f && + mGuiStack.size() == 2) { + // The user has entered a submenu when the initial menu screen has not finished scaling + // up. So scale it to full size so it won't be stuck at a smaller size when returning + // from the submenu. + mTopScale = 1.0f; + GuiComponent* menu = mGuiStack.back(); + glm::vec2 menuCenter{menu->getCenter()}; + menu->setOrigin(0.5f, 0.5f); + menu->setPosition(menuCenter.x, menuCenter.y, 0.0f); + menu->setScale(1.0f); + } + if (config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_g && SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug")) { // Toggle debug grid with Ctrl-G. @@ -346,14 +359,19 @@ void Window::update(int deltaTime) mScreensaver->update(deltaTime); } +bool Window::isBackgroundDimmed() +{ + return !mGuiStack.empty() && (mGuiStack.front() != mGuiStack.back() || mRenderLaunchScreen); +} + void Window::render() { - Transform4x4f transform = Transform4x4f::Identity(); + glm::mat4 trans{Renderer::getIdentity()}; mRenderedHelpPrompts = false; // Draw only bottom and top of GuiStack (if they are different). - if (mGuiStack.size()) { + if (!mGuiStack.empty()) { auto& bottom = mGuiStack.front(); auto& top = mGuiStack.back(); @@ -378,7 +396,7 @@ void Window::render() renderBottom = false; if (renderBottom) - bottom->render(transform); + bottom->render(trans); if (bottom != top || mRenderLaunchScreen) { #if defined(USE_OPENGL_21) @@ -395,7 +413,7 @@ void Window::render() unsigned char* processedTexture = new unsigned char[Renderer::getScreenWidth() * Renderer::getScreenHeight() * 4]; - // Defocus the background using multiple passes of gaussian blur, with the number + // De-focus the background using multiple passes of gaussian blur, with the number // of iterations relative to the screen resolution. Renderer::shaderParameters backgroundParameters; @@ -464,52 +482,51 @@ void Window::render() if (Settings::getInstance()->getString("MenuOpeningEffect") == "scale-up") { mBackgroundOverlay->setOpacity(mBackgroundOverlayOpacity); if (mBackgroundOverlayOpacity < 255) - mBackgroundOverlayOpacity = Math::clamp(mBackgroundOverlayOpacity + 30, 0, 255); + mBackgroundOverlayOpacity = glm::clamp(mBackgroundOverlayOpacity + 30, 0, 255); } #endif // USE_OPENGL_21 - mBackgroundOverlay->render(transform); + mBackgroundOverlay->render(trans); // Scale-up menu opening effect. if (Settings::getInstance()->getString("MenuOpeningEffect") == "scale-up") { if (mTopScale < 1.0f) { - mTopScale = Math::clamp(mTopScale + 0.07f, 0.0f, 1.0f); - Vector2f topCenter = top->getCenter(); - top->setOrigin({ 0.5f, 0.5f }); - top->setPosition({ topCenter.x(), topCenter.y(), 0.0f }); + mTopScale = glm::clamp(mTopScale + 0.07f, 0.0f, 1.0f); + glm::vec2 topCenter{top->getCenter()}; + top->setOrigin(0.5f, 0.5f); + top->setPosition(topCenter.x, topCenter.y, 0.0f); top->setScale(mTopScale); } } if (!mRenderLaunchScreen) - top->render(transform); + top->render(trans); } else { mCachedBackground = false; - mTopOpacity = 0; mTopScale = 0.5f; } } // Render the quick list scrolling overlay, which is triggered in IList. if (mListScrollOpacity != 0) { - Renderer::setMatrix(Transform4x4f::Identity()); + Renderer::setMatrix(Renderer::getIdentity()); Renderer::drawRect(0.0f, 0.0f, static_cast(Renderer::getScreenWidth()), static_cast(Renderer::getScreenHeight()), 0x00000000 | mListScrollOpacity, 0x00000000 | mListScrollOpacity); - Vector2f offset = mListScrollFont->sizeText(mListScrollText); - offset[0] = (Renderer::getScreenWidth() - offset.x()) * 0.5f; - offset[1] = (Renderer::getScreenHeight() - offset.y()) * 0.5f; + glm::vec2 offset{mListScrollFont->sizeText(mListScrollText)}; + offset.x = (Renderer::getScreenWidth() - offset.x) * 0.5f; + offset.y = (Renderer::getScreenHeight() - offset.y) * 0.5f; - TextCache* cache = mListScrollFont->buildTextCache(mListScrollText, offset.x(), offset.y(), + TextCache* cache = mListScrollFont->buildTextCache(mListScrollText, offset.x, offset.y, 0xFFFFFF00 | mListScrollOpacity); mListScrollFont->renderTextCache(cache); delete cache; } if (!mRenderedHelpPrompts) - mHelp->render(transform); + mHelp->render(trans); unsigned int screensaverTimer = static_cast(Settings::getInstance()->getInt("ScreensaverTimer")); @@ -531,7 +548,7 @@ void Window::render() renderScreensaver(); if (!mRenderScreensaver && mInfoPopup) - mInfoPopup->render(transform); + mInfoPopup->render(trans); if (mTimeSinceLastInput >= screensaverTimer && screensaverTimer != 0) { if (!isProcessing() && mAllowSleep && (!mScreensaver)) { @@ -550,14 +567,14 @@ void Window::render() mLaunchScreen->render(); if (Settings::getInstance()->getBool("DisplayGPUStatistics") && mFrameDataText) { - Renderer::setMatrix(Transform4x4f::Identity()); + Renderer::setMatrix(Renderer::getIdentity()); mDefaultFonts.at(1)->renderTextCache(mFrameDataText.get()); } } void Window::renderLoadingScreen(std::string text) { - Transform4x4f trans = Transform4x4f::Identity(); + glm::mat4 trans{Renderer::getIdentity()}; Renderer::setMatrix(trans); Renderer::drawRect(0.0f, 0.0f, static_cast(Renderer::getScreenWidth()), static_cast(Renderer::getScreenHeight()), 0x000000FF, 0x000000FF); @@ -565,16 +582,16 @@ void Window::renderLoadingScreen(std::string text) ImageComponent splash(this, true); splash.setResize(Renderer::getScreenWidth() * 0.6f, 0.0f); splash.setImage(":/graphics/splash.svg"); - splash.setPosition((Renderer::getScreenWidth() - splash.getSize().x()) / 2.0f, - (Renderer::getScreenHeight() - splash.getSize().y()) / 2.0f * 0.6f); + splash.setPosition((Renderer::getScreenWidth() - splash.getSize().x) / 2.0f, + (Renderer::getScreenHeight() - splash.getSize().y) / 2.0f * 0.6f); splash.render(trans); auto& font = mDefaultFonts.at(1); TextCache* cache = font->buildTextCache(text, 0.0f, 0.0f, 0x656565FF); - float x = std::round((Renderer::getScreenWidth() - cache->metrics.size.x()) / 2.0f); + float x = std::round((Renderer::getScreenWidth() - cache->metrics.size.x) / 2.0f); float y = std::round(Renderer::getScreenHeight() * 0.835f); - trans = trans.translate(Vector3f(x, y, 0.0f)); + trans = glm::translate(trans, glm::vec3{x, y, 0.0f}); Renderer::setMatrix(trans); font->renderTextCache(cache); delete cache; @@ -590,7 +607,7 @@ void Window::renderListScrollOverlay(unsigned char opacity, const std::string& t void Window::renderHelpPromptsEarly() { - mHelp->render(Transform4x4f::Identity()); + mHelp->render(Renderer::getIdentity()); mRenderedHelpPrompts = true; } @@ -633,17 +650,17 @@ void Window::setHelpPrompts(const std::vector& prompts, const HelpSt // Sort prompts so it goes [dpad_all] [dpad_u/d] [dpad_l/r] [a/b/x/y/l/r] [start/back]. std::sort(addPrompts.begin(), addPrompts.end(), [](const HelpPrompt& a, const HelpPrompt& b) -> bool { - static const std::vector map = { "up/down/left/right", - "up/down", - "left/right", - "a", - "b", - "x", - "y", - "l", - "r", - "start", - "back" }; + static const std::vector map = {"up/down/left/right", + "up/down", + "left/right", + "a", + "b", + "x", + "y", + "l", + "r", + "start", + "back"}; int i = 0; int aVal = 0; int bVal = 0; diff --git a/es-core/src/Window.h b/es-core/src/Window.h index 5201b2902..193053c43 100644 --- a/es-core/src/Window.h +++ b/es-core/src/Window.h @@ -26,7 +26,6 @@ class HelpComponent; class ImageComponent; class InputConfig; class TextCache; -class Transform4x4f; struct HelpStyle; class Window @@ -77,7 +76,7 @@ public: class InfoPopup { public: - virtual void render(const Transform4x4f& parentTrans) = 0; + virtual void render(const glm::mat4& parentTrans) = 0; virtual void stop() = 0; virtual ~InfoPopup() {} }; @@ -89,6 +88,7 @@ public: void removeGui(GuiComponent* gui); GuiComponent* peekGui(); int getGuiStackSize() { return static_cast(mGuiStack.size()); } + bool isBackgroundDimmed(); bool init(); void deinit(); @@ -191,7 +191,6 @@ private: int mVideoPlayerCount; std::mutex mVideoCountMutex; - unsigned char mTopOpacity; float mTopScale; bool mRenderedHelpPrompts; bool mChangedThemeSet; diff --git a/es-core/src/animations/MoveCameraAnimation.h b/es-core/src/animations/MoveCameraAnimation.h new file mode 100644 index 000000000..b84964ad4 --- /dev/null +++ b/es-core/src/animations/MoveCameraAnimation.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +// +// EmulationStation Desktop Edition +// MoveCameraAnimation.h +// +// Animation to play when moving the camera, used by the slide transition style. +// + +#ifndef ES_CORE_ANIMATIONS_MOVE_CAMERA_ANIMATION_H +#define ES_CORE_ANIMATIONS_MOVE_CAMERA_ANIMATION_H + +#include "animations/Animation.h" +#include "utils/MathUtil.h" + +class MoveCameraAnimation : public Animation +{ +public: + MoveCameraAnimation(glm::mat4& camera, const glm::vec3& target) + : mCameraStart(camera) + , mTarget(target) + , cameraPosition(camera) + { + } + + int getDuration() const override { return 400; } + + void apply(float t) override + { + t -= 1; + cameraPosition[3].x = -glm::mix(-mCameraStart[3].x, mTarget.x, t * t * t + 1); + cameraPosition[3].y = -glm::mix(-mCameraStart[3].y, mTarget.y, t * t * t + 1); + cameraPosition[3].z = -glm::mix(-mCameraStart[3].z, mTarget.z, t * t * t + 1); + } + +private: + glm::mat4 mCameraStart; + glm::mat4& cameraPosition; + glm::vec3 mTarget; +}; + +#endif // ES_CORE_ANIMATIONS_MOVE_CAMERA_ANIMATION_H diff --git a/es-core/src/components/AnimatedImageComponent.cpp b/es-core/src/components/AnimatedImageComponent.cpp index 64cbc2b81..7f97ace59 100644 --- a/es-core/src/components/AnimatedImageComponent.cpp +++ b/es-core/src/components/AnimatedImageComponent.cpp @@ -33,7 +33,7 @@ void AnimatedImageComponent::load(const AnimationDef* def) } auto img = std::unique_ptr(new ImageComponent(mWindow)); - img->setResize(mSize.x(), mSize.y()); + img->setResize(mSize.x, mSize.y); img->setImage(std::string(def->frames[i].path), false); mFrames.push_back(ImageFrame(std::move(img), def->frames[i].time)); @@ -55,7 +55,7 @@ void AnimatedImageComponent::reset() void AnimatedImageComponent::onSizeChanged() { for (auto it = mFrames.cbegin(); it != mFrames.cend(); it++) { - it->first->setResize(mSize.x(), mSize.y()); + it->first->setResize(mSize.x, mSize.y); } } @@ -86,7 +86,7 @@ void AnimatedImageComponent::update(int deltaTime) } } -void AnimatedImageComponent::render(const Transform4x4f& trans) +void AnimatedImageComponent::render(const glm::mat4& trans) { if (mFrames.size()) mFrames.at(mCurrentFrame).first->render(getTransform() * trans); diff --git a/es-core/src/components/AnimatedImageComponent.h b/es-core/src/components/AnimatedImageComponent.h index 09f604b29..7294de6bb 100644 --- a/es-core/src/components/AnimatedImageComponent.h +++ b/es-core/src/components/AnimatedImageComponent.h @@ -34,7 +34,7 @@ public: void reset(); // Set to frame 0. void update(int deltaTime) override; - void render(const Transform4x4f& trans) override; + void render(const glm::mat4& trans) override; void onSizeChanged() override; diff --git a/es-core/src/components/BusyComponent.cpp b/es-core/src/components/BusyComponent.cpp index c66a5ae99..4c66ac453 100644 --- a/es-core/src/components/BusyComponent.cpp +++ b/es-core/src/components/BusyComponent.cpp @@ -14,18 +14,18 @@ // Animation definition. AnimationFrame BUSY_ANIMATION_FRAMES[] = { - { ":/graphics/busy_0.svg", 300 }, - { ":/graphics/busy_1.svg", 300 }, - { ":/graphics/busy_2.svg", 300 }, - { ":/graphics/busy_3.svg", 300 }, + {":/graphics/busy_0.svg", 300}, + {":/graphics/busy_1.svg", 300}, + {":/graphics/busy_2.svg", 300}, + {":/graphics/busy_3.svg", 300}, }; -const AnimationDef BUSY_ANIMATION_DEF = { BUSY_ANIMATION_FRAMES, 4, true }; +const AnimationDef BUSY_ANIMATION_DEF = {BUSY_ANIMATION_FRAMES, 4, true}; BusyComponent::BusyComponent(Window* window) : GuiComponent(window) , mBackground(window, ":/graphics/frame.png") - , mGrid(window, Vector2i(5, 3)) + , mGrid(window, glm::ivec2{5, 3}) { mAnimation = std::make_shared(mWindow); mAnimation->load(&BUSY_ANIMATION_DEF); @@ -33,8 +33,8 @@ BusyComponent::BusyComponent(Window* window) 0x777777FF); // Col 0 = animation, col 1 = spacer, col 2 = text. - mGrid.setEntry(mAnimation, Vector2i(1, 1), false, true); - mGrid.setEntry(mText, Vector2i(3, 1), false, true); + mGrid.setEntry(mAnimation, glm::ivec2{1, 1}, false, true); + mGrid.setEntry(mText, glm::ivec2{3, 1}, false, true); addChild(&mBackground); addChild(&mGrid); @@ -44,25 +44,25 @@ void BusyComponent::onSizeChanged() { mGrid.setSize(mSize); - if (mSize.x() == 0 || mSize.y() == 0) + if (mSize.x == 0.0f || mSize.y == 0.0f) return; const float middleSpacerWidth = 0.01f * Renderer::getScreenWidth(); const float textHeight = mText->getFont()->getLetterHeight(); mText->setSize(0, textHeight); - const float textWidth = mText->getSize().x() + (4 * Renderer::getScreenWidthModifier()); + const float textWidth = mText->getSize().x + (4.0f * Renderer::getScreenWidthModifier()); - mGrid.setColWidthPerc(1, textHeight / mSize.x()); // Animation is square. - mGrid.setColWidthPerc(2, middleSpacerWidth / mSize.x()); - mGrid.setColWidthPerc(3, textWidth / mSize.x()); + mGrid.setColWidthPerc(1, textHeight / mSize.x); // Animation is square. + mGrid.setColWidthPerc(2, middleSpacerWidth / mSize.x); + mGrid.setColWidthPerc(3, textWidth / mSize.x); - mGrid.setRowHeightPerc(1, textHeight / mSize.y()); + mGrid.setRowHeightPerc(1, textHeight / mSize.y); - mBackground.setCornerSize({ 16.0f * Renderer::getScreenWidthModifier(), - 16.0f * Renderer::getScreenHeightModifier() }); - mBackground.fitTo(Vector2f(mGrid.getColWidth(1) + mGrid.getColWidth(2) + mGrid.getColWidth(3), - textHeight + (2.0f * Renderer::getScreenHeightModifier())), - mAnimation->getPosition(), Vector2f(0, 0)); + mBackground.setCornerSize( + {16.0f * Renderer::getScreenWidthModifier(), 16.0f * Renderer::getScreenHeightModifier()}); + mBackground.fitTo(glm::vec2{mGrid.getColWidth(1) + mGrid.getColWidth(2) + mGrid.getColWidth(3), + textHeight + (2.0f * Renderer::getScreenHeightModifier())}, + mAnimation->getPosition(), glm::vec2{}); } void BusyComponent::reset() diff --git a/es-core/src/components/ButtonComponent.cpp b/es-core/src/components/ButtonComponent.cpp index 06d7032d4..6ba641495 100644 --- a/es-core/src/components/ButtonComponent.cpp +++ b/es-core/src/components/ButtonComponent.cpp @@ -32,7 +32,7 @@ ButtonComponent::ButtonComponent(Window* window, void ButtonComponent::onSizeChanged() { // Fit to mBox. - mBox.fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mBox.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); } bool ButtonComponent::input(InputConfig* config, Input input) @@ -53,10 +53,10 @@ void ButtonComponent::setText(const std::string& text, const std::string& helpTe mTextCache = std::unique_ptr(mFont->buildTextCache(mText, 0, 0, getCurTextColor())); - float minWidth = mFont->sizeText("DELETE").x() + (12.0f * Renderer::getScreenWidthModifier()); - setSize(std::max(mTextCache->metrics.size.x() + (12.0f * Renderer::getScreenWidthModifier()), + float minWidth = mFont->sizeText("DELETE").x + (12.0f * Renderer::getScreenWidthModifier()); + setSize(std::max(mTextCache->metrics.size.x + (12.0f * Renderer::getScreenWidthModifier()), minWidth), - mTextCache->metrics.size.y()); + mTextCache->metrics.size.y); updateHelpPrompts(); } @@ -93,29 +93,29 @@ void ButtonComponent::updateImage() mBox.setImagePath(mFocused ? ":/graphics/button_filled.svg" : ":/graphics/button.svg"); } -void ButtonComponent::render(const Transform4x4f& parentTrans) +void ButtonComponent::render(const glm::mat4& parentTrans) { - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; mBox.render(trans); if (mTextCache) { - Vector3f centerOffset((mSize.x() - mTextCache->metrics.size.x()) / 2.0f, - (mSize.y() - mTextCache->metrics.size.y()) / 2.0f, 0); - trans = trans.translate(centerOffset); + glm::vec3 centerOffset{(mSize.x - mTextCache->metrics.size.x) / 2.0f, + (mSize.y - mTextCache->metrics.size.y) / 2.0f, 0.0f}; + trans = glm::translate(trans, centerOffset); if (Settings::getInstance()->getBool("DebugText")) { - Renderer::drawRect(centerOffset.x(), 0.0f, mTextCache->metrics.size.x(), mSize.y(), + Renderer::drawRect(centerOffset.x, 0.0f, mTextCache->metrics.size.x, mSize.y, 0x00000033, 0x00000033); - Renderer::drawRect(mBox.getPosition().x(), 0.0f, mBox.getSize().x(), mSize.y(), - 0x0000FF33, 0x0000FF33); + Renderer::drawRect(mBox.getPosition().x, 0.0f, mBox.getSize().x, mSize.y, 0x0000FF33, + 0x0000FF33); } Renderer::setMatrix(trans); mTextCache->setColor(getCurTextColor()); mFont->renderTextCache(mTextCache.get()); - trans = trans.translate(-centerOffset); + trans = glm::translate(trans, -centerOffset); } renderChildren(trans); diff --git a/es-core/src/components/ButtonComponent.h b/es-core/src/components/ButtonComponent.h index fd2c59171..75f3c4660 100644 --- a/es-core/src/components/ButtonComponent.h +++ b/es-core/src/components/ButtonComponent.h @@ -26,7 +26,7 @@ public: void setEnabled(bool state) override; bool input(InputConfig* config, Input input) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void setText(const std::string& text, const std::string& helpText); diff --git a/es-core/src/components/ComponentGrid.cpp b/es-core/src/components/ComponentGrid.cpp index d8bf872d3..496cda1fd 100644 --- a/es-core/src/components/ComponentGrid.cpp +++ b/es-core/src/components/ComponentGrid.cpp @@ -12,21 +12,21 @@ using namespace GridFlags; -ComponentGrid::ComponentGrid(Window* window, const Vector2i& gridDimensions) +ComponentGrid::ComponentGrid(Window* window, const glm::ivec2& gridDimensions) : GuiComponent(window) , mGridSize(gridDimensions) , mCursor(0, 0) { - assert(gridDimensions.x() > 0 && gridDimensions.y() > 0); + assert(gridDimensions.x > 0 && gridDimensions.y > 0); - mCells.reserve(gridDimensions.x() * gridDimensions.y()); + mCells.reserve(gridDimensions.x * gridDimensions.y); - mColWidths = new float[gridDimensions.x()]; - mRowHeights = new float[gridDimensions.y()]; + mColWidths = new float[gridDimensions.x]; + mRowHeights = new float[gridDimensions.y]; - for (int x = 0; x < gridDimensions.x(); x++) + for (int x = 0; x < gridDimensions.x; x++) mColWidths[x] = 0; - for (int y = 0; y < gridDimensions.y(); y++) + for (int y = 0; y < gridDimensions.y; y++) mRowHeights[y] = 0; } @@ -39,40 +39,40 @@ ComponentGrid::~ComponentGrid() float ComponentGrid::getColWidth(int col) { if (mColWidths[col] != 0) - return mColWidths[col] * mSize.x(); + return mColWidths[col] * mSize.x; // Calculate automatic width. float freeWidthPerc = 1; int between = 0; - for (int x = 0; x < mGridSize.x(); x++) { + for (int x = 0; x < mGridSize.x; x++) { freeWidthPerc -= mColWidths[x]; // If it's 0 it won't do anything. if (mColWidths[x] == 0) between++; } - return (freeWidthPerc * mSize.x()) / between; + return (freeWidthPerc * mSize.x) / static_cast(between); } float ComponentGrid::getRowHeight(int row) { if (mRowHeights[row] != 0) - return mRowHeights[row] * mSize.y(); + return mRowHeights[row] * mSize.y; // Calculate automatic height. float freeHeightPerc = 1; int between = 0; - for (int y = 0; y < mGridSize.y(); y++) { + for (int y = 0; y < mGridSize.y; y++) { freeHeightPerc -= mRowHeights[y]; // If it's 0 it won't do anything. if (mRowHeights[y] == 0) between++; } - return (freeHeightPerc * mSize.y()) / between; + return (freeHeightPerc * mSize.y) / static_cast(between); } void ComponentGrid::setColWidthPerc(int col, float width, bool update) { - assert(col >= 0 && col < mGridSize.x()); + assert(col >= 0 && col < mGridSize.x); mColWidths[col] = width; if (update) @@ -82,7 +82,7 @@ void ComponentGrid::setColWidthPerc(int col, float width, bool update) void ComponentGrid::setRowHeightPerc(int row, float height, bool update) { assert(height >= 0 && height <= 1); - assert(row >= 0 && row < mGridSize.y()); + assert(row >= 0 && row < mGridSize.y); mRowHeights[row] = height; if (update) @@ -90,14 +90,14 @@ void ComponentGrid::setRowHeightPerc(int row, float height, bool update) } void ComponentGrid::setEntry(const std::shared_ptr& comp, - const Vector2i& pos, + const glm::ivec2& pos, bool canFocus, bool resize, - const Vector2i& size, + const glm::ivec2& size, unsigned int border, GridFlags::UpdateType updateType) { - assert(pos.x() >= 0 && pos.x() < mGridSize.x() && pos.y() >= 0 && pos.y() < mGridSize.y()); + assert(pos.x >= 0 && pos.x < mGridSize.x && pos.y >= 0 && pos.y < mGridSize.y); assert(comp != nullptr); assert(comp->getParent() == nullptr); @@ -132,26 +132,25 @@ bool ComponentGrid::removeEntry(const std::shared_ptr& comp) void ComponentGrid::updateCellComponent(const GridEntry& cell) { // Size. - Vector2f size(0, 0); - for (int x = cell.pos.x(); x < cell.pos.x() + cell.dim.x(); x++) - size[0] += getColWidth(x); - for (int y = cell.pos.y(); y < cell.pos.y() + cell.dim.y(); y++) - size[1] += getRowHeight(y); + glm::vec2 size{0.0f}; + for (int x = cell.pos.x; x < cell.pos.x + cell.dim.x; x++) + size.x += getColWidth(x); + for (int y = cell.pos.y; y < cell.pos.y + cell.dim.y; y++) + size.y += getRowHeight(y); if (cell.resize) cell.component->setSize(size); - // Position. // Find top left corner. - Vector3f pos(0, 0, 0); - for (int x = 0; x < cell.pos.x(); x++) - pos[0] += getColWidth(x); - for (int y = 0; y < cell.pos.y(); y++) - pos[1] += getRowHeight(y); + glm::vec3 pos{}; + for (int x = 0; x < cell.pos.x; x++) + pos.x += getColWidth(x); + for (int y = 0; y < cell.pos.y; y++) + pos.y += getRowHeight(y); // Center component. - pos[0] = pos.x() + (size.x() - cell.component->getSize().x()) / 2; - pos[1] = pos.y() + (size.y() - cell.component->getSize().y()) / 2; + pos.x = pos.x + (size.x - cell.component->getSize().x) / 2.0f; + pos.y = pos.y + (size.y - cell.component->getSize().y) / 2.0f; cell.component->setPosition(pos); } @@ -162,58 +161,58 @@ void ComponentGrid::updateSeparators() bool drawAll = Settings::getInstance()->getBool("DebugGrid"); - Vector2f pos; - Vector2f size; + glm::vec2 pos; + glm::vec2 size; for (auto it = mCells.cbegin(); it != mCells.cend(); it++) { if (!it->border && !drawAll) continue; // Find component position + size. - pos = Vector2f(0, 0); - size = Vector2f(0, 0); - for (int x = 0; x < it->pos.x(); x++) + pos = glm::vec2{}; + size = glm::vec2{}; + for (int x = 0; x < it->pos.x; x++) pos[0] += getColWidth(x); - for (int y = 0; y < it->pos.y(); y++) + for (int y = 0; y < it->pos.y; y++) pos[1] += getRowHeight(y); - for (int x = it->pos.x(); x < it->pos.x() + it->dim.x(); x++) + for (int x = it->pos.x; x < it->pos.x + it->dim.x; x++) size[0] += getColWidth(x); - for (int y = it->pos.y(); y < it->pos.y() + it->dim.y(); y++) + for (int y = it->pos.y; y < it->pos.y + it->dim.y; y++) size[1] += getRowHeight(y); - if (size == 0) + if (size == glm::vec2{}) return; if (it->border & BORDER_TOP || drawAll) { std::vector coordVector; - coordVector.push_back(pos.x()); - coordVector.push_back(pos.y()); - coordVector.push_back(size.x()); + coordVector.push_back(pos.x); + coordVector.push_back(pos.y); + coordVector.push_back(size.x); coordVector.push_back(1.0f * Renderer::getScreenHeightModifier()); mSeparators.push_back(coordVector); } if (it->border & BORDER_BOTTOM || drawAll) { std::vector coordVector; - coordVector.push_back(pos.x()); - coordVector.push_back(pos.y() + size.y()); - coordVector.push_back(size.x()); + coordVector.push_back(pos.x); + coordVector.push_back(pos.y + size.y); + coordVector.push_back(size.x); coordVector.push_back(1.0f * Renderer::getScreenHeightModifier()); mSeparators.push_back(coordVector); } if (it->border & BORDER_LEFT || drawAll) { std::vector coordVector; - coordVector.push_back(pos.x()); - coordVector.push_back(pos.y()); + coordVector.push_back(pos.x); + coordVector.push_back(pos.y); coordVector.push_back(1.0f * Renderer::getScreenWidthModifier()); - coordVector.push_back(size.y()); + coordVector.push_back(size.y); mSeparators.push_back(coordVector); } if (it->border & BORDER_RIGHT || drawAll) { std::vector coordVector; - coordVector.push_back(pos.x() + size.x()); - coordVector.push_back(pos.y()); + coordVector.push_back(pos.x + size.x); + coordVector.push_back(pos.y); coordVector.push_back(1.0f * Renderer::getScreenWidthModifier()); - coordVector.push_back(size.y()); + coordVector.push_back(size.y); mSeparators.push_back(coordVector); } } @@ -229,13 +228,13 @@ void ComponentGrid::onSizeChanged() const ComponentGrid::GridEntry* ComponentGrid::getCellAt(int x, int y) const { - assert(x >= 0 && x < mGridSize.x() && y >= 0 && y < mGridSize.y()); + assert(x >= 0 && x < mGridSize.x && y >= 0 && y < mGridSize.y); for (auto it = mCells.cbegin(); it != mCells.cend(); it++) { - int xmin = it->pos.x(); - int xmax = xmin + it->dim.x(); - int ymin = it->pos.y(); - int ymax = ymin + it->dim.y(); + int xmin = it->pos.x; + int xmax = xmin + it->dim.x; + int ymin = it->pos.y; + int ymax = ymin + it->dim.y; if (x >= xmin && y >= ymin && x < xmax && y < ymax) return &(*it); @@ -254,16 +253,16 @@ bool ComponentGrid::input(InputConfig* config, Input input) return false; if (config->isMappedLike("down", input)) - return moveCursor(Vector2i(0, 1)); + return moveCursor(glm::ivec2{0, 1}); if (config->isMappedLike("up", input)) - return moveCursor(Vector2i(0, -1)); + return moveCursor(glm::ivec2{0, -1}); if (config->isMappedLike("left", input)) - return moveCursor(Vector2i(-1, 0)); + return moveCursor(glm::ivec2{-1, 0}); if (config->isMappedLike("right", input)) - return moveCursor(Vector2i(1, 0)); + return moveCursor(glm::ivec2{1, 0}); return false; } @@ -275,7 +274,7 @@ void ComponentGrid::resetCursor() for (auto it = mCells.cbegin(); it != mCells.cend(); it++) { if (it->canFocus) { - Vector2i origCursor = mCursor; + glm::ivec2 origCursor = mCursor; mCursor = it->pos; onCursorMoved(origCursor, mCursor); break; @@ -283,23 +282,22 @@ void ComponentGrid::resetCursor() } } -bool ComponentGrid::moveCursor(Vector2i dir) +bool ComponentGrid::moveCursor(glm::ivec2 dir) { - assert(dir.x() || dir.y()); + assert(dir.x || dir.y); - const Vector2i origCursor = mCursor; + const glm::ivec2 origCursor{mCursor}; const GridEntry* currentCursorEntry = getCellAt(mCursor); - Vector2i searchAxis(dir.x() == 0, dir.y() == 0); + glm::ivec2 searchAxis(dir.x == 0, dir.y == 0); - while (mCursor.x() >= 0 && mCursor.y() >= 0 && mCursor.x() < mGridSize.x() && - mCursor.y() < mGridSize.y()) { + while (mCursor.x >= 0 && mCursor.y >= 0 && mCursor.x < mGridSize.x && mCursor.y < mGridSize.y) { mCursor = mCursor + dir; - Vector2i curDirPos = mCursor; + glm::ivec2 curDirPos{mCursor}; const GridEntry* cursorEntry; // Spread out on search axis+ - while (mCursor.x() < mGridSize.x() && mCursor.y() < mGridSize.y() && mCursor.x() >= 0 && - mCursor.y() >= 0) { + while (mCursor.x < mGridSize.x && mCursor.y < mGridSize.y && mCursor.x >= 0 && + mCursor.y >= 0) { cursorEntry = getCellAt(mCursor); if (cursorEntry && cursorEntry->canFocus && cursorEntry != currentCursorEntry) { onCursorMoved(origCursor, mCursor); @@ -310,8 +308,8 @@ bool ComponentGrid::moveCursor(Vector2i dir) // Now again on search axis- mCursor = curDirPos; - while (mCursor.x() >= 0 && mCursor.y() >= 0 && mCursor.x() < mGridSize.x() && - mCursor.y() < mGridSize.y()) { + while (mCursor.x >= 0 && mCursor.y >= 0 && mCursor.x < mGridSize.x && + mCursor.y < mGridSize.y) { cursorEntry = getCellAt(mCursor); if (cursorEntry && cursorEntry->canFocus && cursorEntry != currentCursorEntry) { @@ -360,9 +358,9 @@ void ComponentGrid::update(int deltaTime) } } -void ComponentGrid::render(const Transform4x4f& parentTrans) +void ComponentGrid::render(const glm::mat4& parentTrans) { - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; renderChildren(trans); @@ -381,7 +379,7 @@ void ComponentGrid::textInput(const std::string& text) selectedEntry->component->textInput(text); } -void ComponentGrid::onCursorMoved(Vector2i from, Vector2i to) +void ComponentGrid::onCursorMoved(glm::ivec2 from, glm::ivec2 to) { const GridEntry* cell = getCellAt(from); if (cell) @@ -398,7 +396,7 @@ void ComponentGrid::setCursorTo(const std::shared_ptr& comp) { for (auto it = mCells.cbegin(); it != mCells.cend(); it++) { if (it->component == comp) { - Vector2i oldCursor = mCursor; + glm::ivec2 oldCursor{mCursor}; mCursor = it->pos; onCursorMoved(oldCursor, mCursor); return; @@ -416,8 +414,8 @@ std::vector ComponentGrid::getHelpPrompts() if (e) prompts = e->component->getHelpPrompts(); - bool canScrollVert = mGridSize.y() > 1; - bool canScrollHoriz = mGridSize.x() > 1; + bool canScrollVert = mGridSize.y > 1; + bool canScrollHoriz = mGridSize.x > 1; for (auto it = prompts.cbegin(); it != prompts.cend(); it++) { if (it->first == "up/down/left/right") { canScrollHoriz = false; diff --git a/es-core/src/components/ComponentGrid.h b/es-core/src/components/ComponentGrid.h index 9acd927e0..c52e8271a 100644 --- a/es-core/src/components/ComponentGrid.h +++ b/es-core/src/components/ComponentGrid.h @@ -10,7 +10,6 @@ #define ES_CORE_COMPONENTS_COMPONENT_GRID_H #include "GuiComponent.h" -#include "math/Vector2i.h" #include "renderers/Renderer.h" namespace GridFlags @@ -34,23 +33,23 @@ namespace GridFlags class ComponentGrid : public GuiComponent { public: - ComponentGrid(Window* window, const Vector2i& gridDimensions); + ComponentGrid(Window* window, const glm::ivec2& gridDimensions); virtual ~ComponentGrid(); bool removeEntry(const std::shared_ptr& comp); void setEntry(const std::shared_ptr& comp, - const Vector2i& pos, + const glm::ivec2& pos, bool canFocus, bool resize = true, - const Vector2i& size = Vector2i(1, 1), + const glm::ivec2& size = glm::ivec2{1, 1}, unsigned int border = GridFlags::BORDER_NONE, GridFlags::UpdateType updateType = GridFlags::UPDATE_ALWAYS); void textInput(const std::string& text) override; bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void onSizeChanged() override; void resetCursor(); @@ -65,7 +64,7 @@ public: // Dito. void setRowHeightPerc(int row, float height, bool update = true); - bool moveCursor(Vector2i dir); + bool moveCursor(glm::ivec2 dir); void setCursorTo(const std::shared_ptr& comp); std::shared_ptr getSelectedComponent() @@ -86,16 +85,16 @@ private: class GridEntry { public: - Vector2i pos; - Vector2i dim; + glm::ivec2 pos; + glm::ivec2 dim; std::shared_ptr component; bool canFocus; bool resize; GridFlags::UpdateType updateType; unsigned int border; - GridEntry(const Vector2i& p = Vector2i::Zero(), - const Vector2i& d = Vector2i::Zero(), + GridEntry(const glm::ivec2& p = glm::ivec2{}, + const glm::ivec2& d = glm::ivec2{}, const std::shared_ptr& cmp = nullptr, bool f = false, bool r = true, @@ -118,14 +117,14 @@ private: void updateCellComponent(const GridEntry& cell); void updateSeparators(); - void onCursorMoved(Vector2i from, Vector2i to); + void onCursorMoved(glm::ivec2 from, glm::ivec2 to); const GridEntry* getCellAt(int x, int y) const; - const GridEntry* getCellAt(const Vector2i& pos) const { return getCellAt(pos.x(), pos.y()); } + const GridEntry* getCellAt(const glm::ivec2& pos) const { return getCellAt(pos.x, pos.y); } std::vector> mSeparators; - Vector2i mGridSize; + glm::ivec2 mGridSize; std::vector mCells; - Vector2i mCursor; + glm::ivec2 mCursor; float* mRowHeights; float* mColWidths; diff --git a/es-core/src/components/ComponentList.cpp b/es-core/src/components/ComponentList.cpp index 9e1edfab3..135b3df7b 100644 --- a/es-core/src/components/ComponentList.cpp +++ b/es-core/src/components/ComponentList.cpp @@ -145,45 +145,47 @@ void ComponentList::updateCameraOffset() { // Move the camera to scroll. const float totalHeight = getTotalRowHeight(); - if (totalHeight > mSize.y()) { - float target = mSelectorBarOffset + getRowHeight(mEntries.at(mCursor).data) / 2.0f - - (mSize.y() / 2.0f); + if (totalHeight > mSize.y) { + float target = + mSelectorBarOffset + getRowHeight(mEntries.at(mCursor).data) / 2.0f - (mSize.y / 2.0f); // Clamp the camera to prevent a fraction of a row from being displayed. mCameraOffset = 0.0f; unsigned int i = 0; while (mCameraOffset < target && i < mEntries.size()) { mCameraOffset += getRowHeight(mEntries.at(i).data); - if (mCameraOffset > totalHeight - mSize.y()) + if (mCameraOffset > totalHeight - mSize.y) break; i++; } - if (mCameraOffset < 0) - mCameraOffset = 0; + if (mCameraOffset < 0.0f) + mCameraOffset = 0.0f; } else { - mCameraOffset = 0; + mCameraOffset = 0.0f; } } -void ComponentList::render(const Transform4x4f& parentTrans) +void ComponentList::render(const glm::mat4& parentTrans) { if (!size()) return; - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; // Clip everything to be inside our bounds. - Vector3f dim(mSize.x(), mSize.y(), 0.0f); - dim = trans * dim - trans.translation(); + glm::vec3 dim{mSize.x, mSize.y, 0.0f}; + dim.x = (trans[0].x * dim.x + trans[3].x) - trans[3].x; + dim.y = (trans[1].y * dim.y + trans[3].y) - trans[3].y; + Renderer::pushClipRect( - Vector2i(static_cast(std::round(trans.translation().x())), - static_cast(std::round(trans.translation().y()))), - Vector2i(static_cast(std::round(dim.x())), static_cast(std::round(dim.y())))); + glm::ivec2{static_cast(std::round(trans[3].x)), + static_cast(std::round(trans[3].y))}, + glm::ivec2{static_cast(std::round(dim.x)), static_cast(std::round(dim.y))}); // Scroll the camera. - trans.translate(Vector3f(0.0f, -std::round(mCameraOffset), 0.0f)); + trans = glm::translate(trans, glm::vec3{0.0f, -mCameraOffset, 0.0f}); // Draw our entries. std::vector drawAfterCursor; @@ -243,19 +245,14 @@ void ComponentList::render(const Transform4x4f& parentTrans) // Draw selector bar. if (mFocused) { - // Inversion: src * (1 - dst) + dst * 0 = where src = 1 - // Need a function that goes roughly 0x777777 -> 0xFFFFFF - // and 0xFFFFFF -> 0x777777 - // (1 - dst) + 0x77 - const float selectedRowHeight = getRowHeight(mEntries.at(mCursor).data); if (opacity == 1) { - Renderer::drawRect(0.0f, mSelectorBarOffset, mSize.x(), selectedRowHeight, 0xFFFFFFFF, + Renderer::drawRect(0.0f, mSelectorBarOffset, mSize.x, selectedRowHeight, 0xFFFFFFFF, 0xFFFFFFFF, false, opacity, trans, Renderer::Blend::ONE_MINUS_DST_COLOR, Renderer::Blend::ZERO); - Renderer::drawRect(0.0f, mSelectorBarOffset, mSize.x(), selectedRowHeight, 0x777777FF, + Renderer::drawRect(0.0f, mSelectorBarOffset, mSize.x, selectedRowHeight, 0x777777FF, 0x777777FF, false, opacity, trans, Renderer::Blend::ONE, Renderer::Blend::ONE); } @@ -271,12 +268,12 @@ void ComponentList::render(const Transform4x4f& parentTrans) // Draw separators. float y = 0; for (unsigned int i = 0; i < mEntries.size(); i++) { - Renderer::drawRect(0.0f, y, mSize.x(), 1.0f * Renderer::getScreenHeightModifier(), - 0xC6C7C6FF, 0xC6C7C6FF, false, opacity, trans); + Renderer::drawRect(0.0f, y, mSize.x, 1.0f * Renderer::getScreenHeightModifier(), 0xC6C7C6FF, + 0xC6C7C6FF, false, opacity, trans); y += getRowHeight(mEntries.at(i).data); } - Renderer::drawRect(0.0f, y, mSize.x(), 1.0f * Renderer::getScreenHeightModifier(), 0xC6C7C6FF, + Renderer::drawRect(0.0f, y, mSize.x, 1.0f * Renderer::getScreenHeightModifier(), 0xC6C7C6FF, 0xC6C7C6FF, false, opacity, trans); Renderer::popClipRect(); } @@ -286,11 +283,11 @@ float ComponentList::getRowHeight(const ComponentListRow& row) const // Returns the highest component height found in the row. float height = 0; for (unsigned int i = 0; i < row.elements.size(); i++) { - if (row.elements.at(i).component->getSize().y() > height) - height = row.elements.at(i).component->getSize().y(); + if (row.elements.at(i).component->getSize().y > height) + height = row.elements.at(i).component->getSize().y; } - return height; + return std::floor(height); } float ComponentList::getTotalRowHeight() const @@ -316,27 +313,27 @@ void ComponentList::updateElementPosition(const ComponentListRow& row) const auto comp = row.elements.at(i).component; // Center vertically. - comp->setPosition(x, (rowHeight - comp->getSize().y()) / 2.0f + yOffset); - x += comp->getSize().x(); + comp->setPosition(x, (rowHeight - comp->getSize().y) / 2.0f + yOffset); + x += comp->getSize().x; } } void ComponentList::updateElementSize(const ComponentListRow& row) { - float width = mSize.x() - mHorizontalPadding; + float width = mSize.x - mHorizontalPadding; std::vector> resizeVec; for (auto it = row.elements.cbegin(); it != row.elements.cend(); it++) { if (it->resize_width) resizeVec.push_back(it->component); else - width -= it->component->getSize().x(); + width -= it->component->getSize().x; } // Redistribute the "unused" width equally among the components with resize_width set to true. width = width / resizeVec.size(); for (auto it = resizeVec.cbegin(); it != resizeVec.cend(); it++) - (*it)->setSize(width, (*it)->getSize().y()); + (*it)->setSize(width, (*it)->getSize().y); } void ComponentList::textInput(const std::string& text) diff --git a/es-core/src/components/ComponentList.h b/es-core/src/components/ComponentList.h index 309e2007c..c5dc392c1 100644 --- a/es-core/src/components/ComponentList.h +++ b/es-core/src/components/ComponentList.h @@ -66,7 +66,7 @@ public: void textInput(const std::string& text) override; bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; virtual std::vector getHelpPrompts() override; void onSizeChanged() override; diff --git a/es-core/src/components/DateTimeComponent.cpp b/es-core/src/components/DateTimeComponent.cpp index c1e670fce..b66fc471f 100644 --- a/es-core/src/components/DateTimeComponent.cpp +++ b/es-core/src/components/DateTimeComponent.cpp @@ -27,8 +27,8 @@ DateTimeComponent::DateTimeComponent(Window* window, const std::shared_ptr& font, unsigned int color, Alignment align, - Vector3f pos, - Vector2f size, + glm::vec3 pos, + glm::vec2 size, unsigned int bgcolor) : TextComponent(window, text, font, color, align, pos, size, bgcolor) , mDisplayRelative(false) @@ -101,8 +101,9 @@ std::string DateTimeComponent::getDisplayString() const return Utils::Time::timeToString(mTime.getTime(), mFormat); } -void DateTimeComponent::render(const Transform4x4f& parentTrans) +void DateTimeComponent::render(const glm::mat4& parentTrans) { + // Render the component. TextComponent::render(parentTrans); } diff --git a/es-core/src/components/DateTimeComponent.h b/es-core/src/components/DateTimeComponent.h index 444484851..5b63b793b 100644 --- a/es-core/src/components/DateTimeComponent.h +++ b/es-core/src/components/DateTimeComponent.h @@ -26,11 +26,11 @@ public: const std::shared_ptr& font, unsigned int color = 0x000000FF, Alignment align = ALIGN_LEFT, - Vector3f pos = Vector3f::Zero(), - Vector2f size = Vector2f::Zero(), + glm::vec3 pos = {}, + glm::vec2 size = {}, unsigned int bgcolor = 0x00000000); - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void setValue(const std::string& val) override; std::string getValue() const override; diff --git a/es-core/src/components/DateTimeEditComponent.cpp b/es-core/src/components/DateTimeEditComponent.cpp index ef91ed5f4..5796f7621 100644 --- a/es-core/src/components/DateTimeEditComponent.cpp +++ b/es-core/src/components/DateTimeEditComponent.cpp @@ -154,9 +154,9 @@ void DateTimeEditComponent::update(int deltaTime) GuiComponent::update(deltaTime); } -void DateTimeEditComponent::render(const Transform4x4f& parentTrans) +void DateTimeEditComponent::render(const glm::mat4& parentTrans) { - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; if (mTextCache) { std::shared_ptr font = getFont(); @@ -164,28 +164,28 @@ void DateTimeEditComponent::render(const Transform4x4f& parentTrans) if (mAlignRight) { if (mTime != 0) - referenceSize = font->sizeText("ABCDEFG").x(); + referenceSize = font->sizeText("ABCDEFG").x; else - referenceSize = font->sizeText("ABCDEIJ").x(); + referenceSize = font->sizeText("ABCDEIJ").x; } // Vertically center. - Vector3f off(0, (mSize.y() - mTextCache->metrics.size.y()) / 2.0f, 0.0f); + glm::vec3 off{0.0f, (mSize.y - mTextCache->metrics.size.y) / 2.0f, 0.0f}; if (mAlignRight) - off.x() += referenceSize - mTextCache->metrics.size.x(); - trans.translate(off); + off.x += referenceSize - mTextCache->metrics.size.x; + trans = glm::translate(trans, off); Renderer::setMatrix(trans); if (Settings::getInstance()->getBool("DebugText")) { Renderer::setMatrix(trans); - if (mTextCache->metrics.size.x() > 0) { - Renderer::drawRect(0.0f, 0.0f - off.y(), mSize.x() - off.x(), mSize.y(), 0x0000FF33, + if (mTextCache->metrics.size.x > 0.0f) { + Renderer::drawRect(0.0f, 0.0f - off.y, mSize.x - off.x, mSize.y, 0x0000FF33, 0x0000FF33); } - Renderer::drawRect(0.0f, 0.0f, mTextCache->metrics.size.x(), - mTextCache->metrics.size.y(), 0x00000033, 0x00000033); + Renderer::drawRect(0.0f, 0.0f, mTextCache->metrics.size.x, mTextCache->metrics.size.y, + 0x00000033, 0x00000033); } mTextCache->setColor((mColor & 0xFFFFFF00) | getOpacity()); @@ -300,22 +300,22 @@ void DateTimeEditComponent::updateTextCache() return; // Year. - Vector2f start(0, 0); - Vector2f end = font->sizeText(dispString.substr(0, 4)); - Vector2f diff = end - start; - mCursorBoxes.push_back(Vector4f(start[0], start[1], diff[0], diff[1])); + glm::vec2 start{}; + glm::vec2 end{font->sizeText(dispString.substr(0, 4))}; + glm::vec2 diff{end - start}; + mCursorBoxes.push_back(glm::vec4{start[0], start[1], diff[0], diff[1]}); // Month. - start[0] = font->sizeText(dispString.substr(0, 5)).x(); + start[0] = font->sizeText(dispString.substr(0, 5)).x; end = font->sizeText(dispString.substr(0, 7)); diff = end - start; - mCursorBoxes.push_back(Vector4f(start[0], start[1], diff[0], diff[1])); + mCursorBoxes.push_back(glm::vec4{start[0], start[1], diff[0], diff[1]}); // Day. - start[0] = font->sizeText(dispString.substr(0, 8)).x(); + start[0] = font->sizeText(dispString.substr(0, 8)).x; end = font->sizeText(dispString.substr(0, 10)); diff = end - start; - mCursorBoxes.push_back(Vector4f(start[0], start[1], diff[0], diff[1])); + mCursorBoxes.push_back(glm::vec4{start[0], start[1], diff[0], diff[1]}); // The logic for handling time for 'mode = DISP_DATE_TIME' is missing, but // nobody will use it anyway so it's not worthwhile implementing. diff --git a/es-core/src/components/DateTimeEditComponent.h b/es-core/src/components/DateTimeEditComponent.h index 3273fe51b..a2c7ab58f 100644 --- a/es-core/src/components/DateTimeEditComponent.h +++ b/es-core/src/components/DateTimeEditComponent.h @@ -34,7 +34,7 @@ public: bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; unsigned int getColor() const override { return mColor; } - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void onSizeChanged() override; // Set how the point in time will be displayed: @@ -82,7 +82,7 @@ private: int mRelativeUpdateAccumulator; std::unique_ptr mTextCache; - std::vector mCursorBoxes; + std::vector mCursorBoxes; unsigned int mColor; Utils::Time::DateTime mOriginalValue; diff --git a/es-core/src/components/GridTileComponent.cpp b/es-core/src/components/GridTileComponent.cpp index af5a87136..dbe914da5 100644 --- a/es-core/src/components/GridTileComponent.cpp +++ b/es-core/src/components/GridTileComponent.cpp @@ -17,12 +17,12 @@ GridTileComponent::GridTileComponent(Window* window) , mBackground(window, ":/graphics/frame.png") { mDefaultProperties.mSize = getDefaultTileSize(); - mDefaultProperties.mPadding = Vector2f(16.0f * Renderer::getScreenWidthModifier(), - 16.0f * Renderer::getScreenHeightModifier()); + mDefaultProperties.mPadding = glm::vec2{16.0f * Renderer::getScreenWidthModifier(), + 16.0f * Renderer::getScreenHeightModifier()}; mDefaultProperties.mImageColor = 0xAAAAAABB; // Attempting to use frame.svg instead causes quite severe performance problems. mDefaultProperties.mBackgroundImage = ":/graphics/frame.png"; - mDefaultProperties.mBackgroundCornerSize = Vector2f(16.0f, 16.0f); + mDefaultProperties.mBackgroundCornerSize = glm::vec2{16.0f, 16.0f}; mDefaultProperties.mBackgroundCenterColor = 0xAAAAEEFF; mDefaultProperties.mBackgroundEdgeColor = 0xAAAAEEFF; @@ -50,9 +50,9 @@ GridTileComponent::GridTileComponent(Window* window) setVisible(true); } -void GridTileComponent::render(const Transform4x4f& parentTrans) +void GridTileComponent::render(const glm::mat4& parentTrans) { - Transform4x4f trans = getTransform() * parentTrans; + glm::mat4 trans{getTransform() * parentTrans}; if (mVisible) renderChildren(trans); @@ -76,14 +76,14 @@ void GridTileComponent::update(int deltaTime) void applyThemeToProperties(const ThemeData::ThemeElement* elem, GridTileProperties* properties) { - Vector2f screen = Vector2f(static_cast(Renderer::getScreenWidth()), - static_cast(Renderer::getScreenHeight())); + glm::vec2 screen{static_cast(Renderer::getScreenWidth()), + static_cast(Renderer::getScreenHeight())}; if (elem->has("size")) - properties->mSize = elem->get("size") * screen; + properties->mSize = elem->get("size") * screen; if (elem->has("padding")) - properties->mPadding = elem->get("padding"); + properties->mPadding = elem->get("padding"); if (elem->has("imageColor")) properties->mImageColor = elem->get("imageColor"); @@ -92,7 +92,7 @@ void applyThemeToProperties(const ThemeData::ThemeElement* elem, GridTilePropert properties->mBackgroundImage = elem->get("backgroundImage"); if (elem->has("backgroundCornerSize")) - properties->mBackgroundCornerSize = elem->get("backgroundCornerSize"); + properties->mBackgroundCornerSize = elem->get("backgroundCornerSize"); if (elem->has("backgroundColor")) { properties->mBackgroundCenterColor = elem->get("backgroundColor"); @@ -111,9 +111,6 @@ void GridTileComponent::applyTheme(const std::shared_ptr& theme, const std::string& /*element*/, unsigned int /*properties*/) { - Vector2f screen = Vector2f(static_cast(Renderer::getScreenWidth()), - static_cast(Renderer::getScreenHeight())); - // Apply theme to the default gridtile. const ThemeData::ThemeElement* elem = theme->getElement(view, "default", "gridtile"); if (elem) @@ -133,15 +130,15 @@ void GridTileComponent::applyTheme(const std::shared_ptr& theme, applyThemeToProperties(elem, &mSelectedProperties); } -Vector2f GridTileComponent::getDefaultTileSize() +glm::vec2 GridTileComponent::getDefaultTileSize() { - Vector2f screen = Vector2f(static_cast(Renderer::getScreenWidth()), - static_cast(Renderer::getScreenHeight())); + glm::vec2 screen{glm::vec2(static_cast(Renderer::getScreenWidth()), + static_cast(Renderer::getScreenHeight()))}; return screen * 0.22f; } -Vector2f GridTileComponent::getSelectedTileSize() const +glm::vec2 GridTileComponent::getSelectedTileSize() const { // Return the tile size. return mDefaultProperties.mSize * 1.2f; @@ -171,7 +168,7 @@ void GridTileComponent::setImage(const std::shared_ptr& texture void GridTileComponent::setSelected(bool selected, bool allowAnimation, - Vector3f* pPosition, + glm::vec3* pPosition, bool force) { if (mSelected == selected && !force) @@ -184,16 +181,16 @@ void GridTileComponent::setSelected(bool selected, cancelAnimation(3); this->setSelectedZoom(1); - mAnimPosition = Vector3f(0, 0, 0); + mAnimPosition = {}; resize(); } else { - mAnimPosition = Vector3f(pPosition->x(), pPosition->y(), pPosition->z()); + mAnimPosition = glm::vec3{pPosition->x, pPosition->y, pPosition->z}; auto func = [this](float t) { - t -= 1; // Cubic ease out. - float pct = Math::lerp(0, 1, t * t * t + 1); + t -= 1; + float pct = glm::mix(0.0f, 1.0f, t * t * t + 1.0f); this->setSelectedZoom(pct); }; @@ -202,7 +199,7 @@ void GridTileComponent::setSelected(bool selected, new LambdaAnimation(func, 250), 0, [this] { this->setSelectedZoom(1); - mAnimPosition = Vector3f(0, 0, 0); + mAnimPosition = {}; }, false, 3); } @@ -218,8 +215,8 @@ void GridTileComponent::setSelected(bool selected, this->setSelectedZoom(1); auto func = [this](float t) { - t -= 1.0f; // Cubic ease out. - float pct = Math::lerp(0, 1, t * t * t + 1.0f); + t -= 1.0f; + float pct = glm::mix(0.0f, 1.0f, t * t * t + 1.0f); this->setSelectedZoom(1.0f - pct); }; @@ -307,7 +304,7 @@ void GridTileComponent::calcCurrentProperties() } } -Vector3f GridTileComponent::getBackgroundPosition() +glm::vec3 GridTileComponent::getBackgroundPosition() { return mBackground.getPosition() + mPosition; } @@ -320,7 +317,7 @@ std::shared_ptr GridTileComponent::getTexture() return nullptr; }; -void GridTileComponent::forceSize(Vector2f size, float selectedZoom) +void GridTileComponent::forceSize(glm::vec2 size, float selectedZoom) { mDefaultProperties.mSize = size; mSelectedProperties.mSize = size * selectedZoom; diff --git a/es-core/src/components/GridTileComponent.h b/es-core/src/components/GridTileComponent.h index 6c0d600ee..edc583aaf 100644 --- a/es-core/src/components/GridTileComponent.h +++ b/es-core/src/components/GridTileComponent.h @@ -13,11 +13,11 @@ #include "NinePatchComponent.h" struct GridTileProperties { - Vector2f mSize; - Vector2f mPadding; + glm::vec2 mSize; + glm::vec2 mPadding; unsigned int mImageColor; std::string mBackgroundImage; - Vector2f mBackgroundCornerSize; + glm::vec2 mBackgroundCornerSize; unsigned int mBackgroundCenterColor; unsigned int mBackgroundEdgeColor; }; @@ -27,7 +27,7 @@ class GridTileComponent : public GuiComponent public: GridTileComponent(Window* window); - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; virtual void applyTheme(const std::shared_ptr& theme, const std::string& view, const std::string& element, @@ -35,8 +35,8 @@ public: // Made this a static function because the ImageGridComponent needs to know the default tile // max size to calculate the grid dimension before it instantiates the GridTileComponents. - static Vector2f getDefaultTileSize(); - Vector2f getSelectedTileSize() const; + static glm::vec2 getDefaultTileSize(); + glm::vec2 getSelectedTileSize() const; bool isSelected() const; void reset() { setImage(""); } @@ -45,13 +45,13 @@ public: void setImage(const std::shared_ptr& texture); void setSelected(bool selected, bool allowAnimation = true, - Vector3f* pPosition = nullptr, + glm::vec3* pPosition = nullptr, bool force = false); void setVisible(bool visible); - void forceSize(Vector2f size, float selectedZoom); + void forceSize(glm::vec2 size, float selectedZoom); - Vector3f getBackgroundPosition(); + glm::vec3 getBackgroundPosition(); virtual void update(int deltaTime) override; @@ -73,7 +73,7 @@ private: bool mSelected; bool mVisible; - Vector3f mAnimPosition; + glm::vec3 mAnimPosition; }; #endif // ES_CORE_COMPONENTS_GRID_TILE_COMPONENT_H diff --git a/es-core/src/components/HelpComponent.cpp b/es-core/src/components/HelpComponent.cpp index dd2c526a3..4a6bfb28b 100644 --- a/es-core/src/components/HelpComponent.cpp +++ b/es-core/src/components/HelpComponent.cpp @@ -10,16 +10,14 @@ #include "Log.h" #include "Settings.h" +#include "Window.h" #include "components/ComponentGrid.h" #include "components/ImageComponent.h" #include "components/TextComponent.h" #include "resources/TextureResource.h" #include "utils/StringUtil.h" -#define ICON_TEXT_SPACING 8 // Space between [icon] and [text] (px). -#define ENTRY_SPACING 16 // Space between [text] and next [icon] (px). - -static std::map sIconPathMap {}; +static std::map sIconPathMap{}; HelpComponent::HelpComponent(Window* window) : GuiComponent(window) @@ -31,58 +29,144 @@ void HelpComponent::assignIcons() { std::string controllerType = Settings::getInstance()->getString("InputControllerType"); + std::map sIconPathMapOld(sIconPathMap); sIconPathMap.clear(); // These graphics files are common between all controller types. - sIconPathMap["up/down"] = ":/help/dpad_updown.svg"; - sIconPathMap["left/right"] = ":/help/dpad_leftright.svg"; - sIconPathMap["up/down/left/right"] = ":/help/dpad_all.svg"; - sIconPathMap["thumbstickclick"] = ":/help/thumbstick_click.svg"; - sIconPathMap["l"] = ":/help/button_l.svg"; - sIconPathMap["r"] = ":/help/button_r.svg"; - sIconPathMap["lr"] = ":/help/button_lr.svg"; + sIconPathMap["up/down"] = mStyle.mCustomButtons.dpad_updown.empty() ? + ":/help/dpad_updown.svg" : + mStyle.mCustomButtons.dpad_updown; + sIconPathMap["left/right"] = mStyle.mCustomButtons.dpad_leftright.empty() ? + ":/help/dpad_leftright.svg" : + mStyle.mCustomButtons.dpad_leftright; + sIconPathMap["up/down/left/right"] = mStyle.mCustomButtons.dpad_all.empty() ? + ":/help/dpad_all.svg" : + mStyle.mCustomButtons.dpad_all; + sIconPathMap["thumbstickclick"] = mStyle.mCustomButtons.thumbstick_click.empty() ? + ":/help/thumbstick_click.svg" : + mStyle.mCustomButtons.thumbstick_click; + sIconPathMap["l"] = mStyle.mCustomButtons.button_l.empty() ? ":/help/button_l.svg" : + mStyle.mCustomButtons.button_l; + sIconPathMap["r"] = mStyle.mCustomButtons.button_r.empty() ? ":/help/button_r.svg" : + mStyle.mCustomButtons.button_r; + sIconPathMap["lr"] = mStyle.mCustomButtons.button_lr.empty() ? ":/help/button_lr.svg" : + mStyle.mCustomButtons.button_lr; // These graphics files are custom per controller type. if (controllerType == "snes") { - sIconPathMap["a"] = ":/help/button_a_SNES.svg"; - sIconPathMap["b"] = ":/help/button_b_SNES.svg"; - sIconPathMap["x"] = ":/help/button_x_SNES.svg"; - sIconPathMap["y"] = ":/help/button_y_SNES.svg"; - sIconPathMap["start"] = ":/help/button_start_SNES.svg"; - sIconPathMap["back"] = ":/help/button_back_SNES.svg"; + sIconPathMap["a"] = mStyle.mCustomButtons.button_a_SNES.empty() ? + ":/help/button_a_SNES.svg" : + mStyle.mCustomButtons.button_a_SNES; + sIconPathMap["b"] = mStyle.mCustomButtons.button_b_SNES.empty() ? + ":/help/button_b_SNES.svg" : + mStyle.mCustomButtons.button_b_SNES; + sIconPathMap["x"] = mStyle.mCustomButtons.button_x_SNES.empty() ? + ":/help/button_x_SNES.svg" : + mStyle.mCustomButtons.button_x_SNES; + sIconPathMap["y"] = mStyle.mCustomButtons.button_y_SNES.empty() ? + ":/help/button_y_SNES.svg" : + mStyle.mCustomButtons.button_y_SNES; + sIconPathMap["start"] = mStyle.mCustomButtons.button_start_SNES.empty() ? + ":/help/button_start_SNES.svg" : + mStyle.mCustomButtons.button_start_SNES; + sIconPathMap["back"] = mStyle.mCustomButtons.button_back_SNES.empty() ? + ":/help/button_back_SNES.svg" : + mStyle.mCustomButtons.button_back_SNES; } else if (controllerType == "ps4") { - sIconPathMap["a"] = ":/help/button_a_PS.svg"; - sIconPathMap["b"] = ":/help/button_b_PS.svg"; - sIconPathMap["x"] = ":/help/button_x_PS.svg"; - sIconPathMap["y"] = ":/help/button_y_PS.svg"; - sIconPathMap["start"] = ":/help/button_start_PS4.svg"; - sIconPathMap["back"] = ":/help/button_back_PS4.svg"; + sIconPathMap["a"] = mStyle.mCustomButtons.button_a_PS.empty() ? + ":/help/button_a_PS.svg" : + mStyle.mCustomButtons.button_a_PS; + sIconPathMap["b"] = mStyle.mCustomButtons.button_b_PS.empty() ? + ":/help/button_b_PS.svg" : + mStyle.mCustomButtons.button_b_PS; + sIconPathMap["x"] = mStyle.mCustomButtons.button_x_PS.empty() ? + ":/help/button_x_PS.svg" : + mStyle.mCustomButtons.button_x_PS; + sIconPathMap["y"] = mStyle.mCustomButtons.button_y_PS.empty() ? + ":/help/button_y_PS.svg" : + mStyle.mCustomButtons.button_y_PS; + sIconPathMap["start"] = mStyle.mCustomButtons.button_start_PS4.empty() ? + ":/help/button_start_PS4.svg" : + mStyle.mCustomButtons.button_start_PS4; + sIconPathMap["back"] = mStyle.mCustomButtons.button_back_PS4.empty() ? + ":/help/button_back_PS4.svg" : + mStyle.mCustomButtons.button_back_PS4; } else if (controllerType == "ps5") { - sIconPathMap["a"] = ":/help/button_a_PS.svg"; - sIconPathMap["b"] = ":/help/button_b_PS.svg"; - sIconPathMap["x"] = ":/help/button_x_PS.svg"; - sIconPathMap["y"] = ":/help/button_y_PS.svg"; - sIconPathMap["start"] = ":/help/button_start_PS5.svg"; - sIconPathMap["back"] = ":/help/button_back_PS5.svg"; + sIconPathMap["a"] = mStyle.mCustomButtons.button_a_PS.empty() ? + ":/help/button_a_PS.svg" : + mStyle.mCustomButtons.button_a_PS; + sIconPathMap["b"] = mStyle.mCustomButtons.button_b_PS.empty() ? + ":/help/button_b_PS.svg" : + mStyle.mCustomButtons.button_b_PS; + sIconPathMap["x"] = mStyle.mCustomButtons.button_x_PS.empty() ? + ":/help/button_x_PS.svg" : + mStyle.mCustomButtons.button_x_PS; + sIconPathMap["y"] = mStyle.mCustomButtons.button_y_PS.empty() ? + ":/help/button_y_PS.svg" : + mStyle.mCustomButtons.button_y_PS; + sIconPathMap["start"] = mStyle.mCustomButtons.button_start_PS5.empty() ? + ":/help/button_start_PS5.svg" : + mStyle.mCustomButtons.button_start_PS5; + sIconPathMap["back"] = mStyle.mCustomButtons.button_back_PS5.empty() ? + ":/help/button_back_PS5.svg" : + mStyle.mCustomButtons.button_back_PS5; } else if (controllerType == "xbox360") { - sIconPathMap["a"] = ":/help/button_a_XBOX.svg"; - sIconPathMap["b"] = ":/help/button_b_XBOX.svg"; - sIconPathMap["x"] = ":/help/button_x_XBOX.svg"; - sIconPathMap["y"] = ":/help/button_y_XBOX.svg"; - sIconPathMap["start"] = ":/help/button_start_XBOX360.svg"; - sIconPathMap["back"] = ":/help/button_back_XBOX360.svg"; + + sIconPathMap["a"] = mStyle.mCustomButtons.button_a_XBOX.empty() ? + ":/help/button_a_XBOX.svg" : + mStyle.mCustomButtons.button_a_XBOX; + sIconPathMap["b"] = mStyle.mCustomButtons.button_b_XBOX.empty() ? + ":/help/button_b_XBOX.svg" : + mStyle.mCustomButtons.button_b_XBOX; + sIconPathMap["x"] = mStyle.mCustomButtons.button_x_XBOX.empty() ? + ":/help/button_x_XBOX.svg" : + mStyle.mCustomButtons.button_x_XBOX; + sIconPathMap["y"] = mStyle.mCustomButtons.button_y_XBOX.empty() ? + ":/help/button_y_XBOX.svg" : + mStyle.mCustomButtons.button_y_XBOX; + sIconPathMap["start"] = mStyle.mCustomButtons.button_start_XBOX360.empty() ? + ":/help/button_start_XBOX360.svg" : + mStyle.mCustomButtons.button_start_XBOX360; + sIconPathMap["back"] = mStyle.mCustomButtons.button_back_XBOX360.empty() ? + ":/help/button_back_XBOX360.svg" : + mStyle.mCustomButtons.button_back_XBOX360; } else { // Xbox One and later. - sIconPathMap["a"] = ":/help/button_a_XBOX.svg"; - sIconPathMap["b"] = ":/help/button_b_XBOX.svg"; - sIconPathMap["x"] = ":/help/button_x_XBOX.svg"; - sIconPathMap["y"] = ":/help/button_y_XBOX.svg"; - sIconPathMap["start"] = ":/help/button_start_XBOX.svg"; - sIconPathMap["back"] = ":/help/button_back_XBOX.svg"; + sIconPathMap["a"] = mStyle.mCustomButtons.button_a_XBOX.empty() ? + ":/help/button_a_XBOX.svg" : + mStyle.mCustomButtons.button_a_XBOX; + sIconPathMap["b"] = mStyle.mCustomButtons.button_b_XBOX.empty() ? + ":/help/button_b_XBOX.svg" : + mStyle.mCustomButtons.button_b_XBOX; + sIconPathMap["x"] = mStyle.mCustomButtons.button_x_XBOX.empty() ? + ":/help/button_x_XBOX.svg" : + mStyle.mCustomButtons.button_x_XBOX; + sIconPathMap["y"] = mStyle.mCustomButtons.button_y_XBOX.empty() ? + ":/help/button_y_XBOX.svg" : + mStyle.mCustomButtons.button_y_XBOX; + sIconPathMap["start"] = mStyle.mCustomButtons.button_start_XBOX.empty() ? + ":/help/button_start_XBOX.svg" : + mStyle.mCustomButtons.button_start_XBOX; + sIconPathMap["back"] = mStyle.mCustomButtons.button_back_XBOX.empty() ? + ":/help/button_back_XBOX.svg" : + mStyle.mCustomButtons.button_back_XBOX; + } + + // Invalidate cache for icons that have changed. + auto it = sIconPathMap.begin(); + while (it != sIconPathMap.end()) { + if (sIconPathMapOld.find(it->first) != sIconPathMapOld.end()) { + if (sIconPathMapOld[it->first] != sIconPathMap[it->first]) { + if (mIconCache.find(it->first) != mIconCache.end()) { + mIconCache.erase(mIconCache.find(it->first)); + } + } + } + it++; } } @@ -102,6 +186,7 @@ void HelpComponent::setStyle(const HelpStyle& style) { mStyle = style; updateGrid(); + assignIcons(); } void HelpComponent::updateGrid() @@ -114,7 +199,7 @@ void HelpComponent::updateGrid() std::shared_ptr& font = mStyle.font; mGrid = std::make_shared(mWindow, - Vector2i(static_cast(mPrompts.size()) * 4, 1)); + glm::ivec2{static_cast(mPrompts.size()) * 4, 1}); // [icon] [spacer1] [text] [spacer2] @@ -124,35 +209,47 @@ void HelpComponent::updateGrid() float width = 0; const float height = std::round(font->getLetterHeight() * 1.25f); + // State variable indicating whether gui is dimmed. + bool isDimmed = mWindow->isBackgroundDimmed(); + for (auto it = mPrompts.cbegin(); it != mPrompts.cend(); it++) { auto icon = std::make_shared(mWindow); icon->setImage(getIconTexture(it->first.c_str())); - icon->setColorShift(mStyle.iconColor); + icon->setColorShift(isDimmed ? mStyle.iconColorDimmed : mStyle.iconColor); icon->setResize(0, height); icons.push_back(icon); - auto lbl = std::make_shared(mWindow, Utils::String::toUpper(it->second), - font, mStyle.textColor); + // Apply text style and color from the theme to the label and add it to the label list. + std::string lblInput = it->second; + if (mStyle.textStyle == "lowercase") + lblInput = Utils::String::toLower(lblInput); + else if (mStyle.textStyle == "camelcase") + lblInput = Utils::String::toCamelCase(lblInput); + else + lblInput = Utils::String::toUpper(lblInput); + auto lbl = std::make_shared( + mWindow, lblInput, font, isDimmed ? mStyle.textColorDimmed : mStyle.textColor); labels.push_back(lbl); - width += icon->getSize().x() + lbl->getSize().x() + - ((ICON_TEXT_SPACING + ENTRY_SPACING) * Renderer::getScreenWidthModifier()); + width += + icon->getSize().x + lbl->getSize().x + + ((mStyle.iconTextSpacing + mStyle.entrySpacing) * Renderer::getScreenWidthModifier()); } mGrid->setSize(width, height); for (unsigned int i = 0; i < icons.size(); i++) { const int col = i * 4; - mGrid->setColWidthPerc(col, icons.at(i)->getSize().x() / width); - mGrid->setColWidthPerc(col + 1, - (ICON_TEXT_SPACING * Renderer::getScreenWidthModifier()) / width); - mGrid->setColWidthPerc(col + 2, labels.at(i)->getSize().x() / width); + mGrid->setColWidthPerc(col, icons.at(i)->getSize().x / width); + mGrid->setColWidthPerc( + col + 1, (mStyle.iconTextSpacing * Renderer::getScreenWidthModifier()) / width); + mGrid->setColWidthPerc(col + 2, labels.at(i)->getSize().x / width); - mGrid->setEntry(icons.at(i), Vector2i(col, 0), false, false); - mGrid->setEntry(labels.at(i), Vector2i(col + 2, 0), false, false); + mGrid->setEntry(icons.at(i), glm::ivec2{col, 0}, false, false); + mGrid->setEntry(labels.at(i), glm::ivec2{col + 2, 0}, false, false); } - mGrid->setPosition(Vector3f(mStyle.position.x(), mStyle.position.y(), 0.0f)); + mGrid->setPosition({mStyle.position.x, mStyle.position.y, 0.0f}); mGrid->setOrigin(mStyle.origin); } @@ -167,6 +264,7 @@ std::shared_ptr HelpComponent::getIconTexture(const char* name) LOG(LogError) << "Unknown help icon \"" << name << "\""; return nullptr; } + if (!ResourceManager::getInstance()->fileExists(pathLookup->second)) { LOG(LogError) << "Couldn't load help icon \"" << name << "\" as the file \"" << pathLookup->second << "\" is missing"; @@ -187,9 +285,9 @@ void HelpComponent::setOpacity(unsigned char opacity) mGrid->getChild(i)->setOpacity(opacity); } -void HelpComponent::render(const Transform4x4f& parentTrans) +void HelpComponent::render(const glm::mat4& parentTrans) { - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; if (mGrid) mGrid->render(trans); diff --git a/es-core/src/components/HelpComponent.h b/es-core/src/components/HelpComponent.h index 19bd61aed..aa80eb170 100644 --- a/es-core/src/components/HelpComponent.h +++ b/es-core/src/components/HelpComponent.h @@ -26,7 +26,7 @@ public: void clearPrompts(); void setPrompts(const std::vector& prompts); - void render(const Transform4x4f& parent) override; + void render(const glm::mat4& parent) override; void setOpacity(unsigned char opacity) override; void setStyle(const HelpStyle& style); diff --git a/es-core/src/components/IList.h b/es-core/src/components/IList.h index 1c907a1b3..566c34137 100644 --- a/es-core/src/components/IList.h +++ b/es-core/src/components/IList.h @@ -37,9 +37,9 @@ struct ScrollTierList { // Default scroll tiers. // clang-format off const ScrollTier QUICK_SCROLL_TIERS[] = { - { 500, 500 }, - { 1200, 114 }, - { 0, 16 } + {500, 500}, + {1200, 114}, + {0, 16} }; const ScrollTierList LIST_SCROLL_STYLE_QUICK = { 3, @@ -47,8 +47,8 @@ const ScrollTierList LIST_SCROLL_STYLE_QUICK = { }; const ScrollTier SLOW_SCROLL_TIERS[] = { - { 500, 500 }, - { 0, 200 } + {500, 500}, + {0, 200} }; const ScrollTierList LIST_SCROLL_STYLE_SLOW = { @@ -282,7 +282,7 @@ protected: scroll(mScrollVelocity); } - void listRenderTitleOverlay(const Transform4x4f& /*trans*/) + void listRenderTitleOverlay(const glm::mat4& /*trans*/) { if (!Settings::getInstance()->getBool("ListScrollOverlay")) return; diff --git a/es-core/src/components/ImageComponent.cpp b/es-core/src/components/ImageComponent.cpp index 253d155b5..e292f180a 100644 --- a/es-core/src/components/ImageComponent.cpp +++ b/es-core/src/components/ImageComponent.cpp @@ -14,15 +14,15 @@ #include "resources/TextureResource.h" #include "utils/CImgUtil.h" -Vector2i ImageComponent::getTextureSize() const +glm::ivec2 ImageComponent::getTextureSize() const { if (mTexture) return mTexture->getSize(); else - return Vector2i::Zero(); + return glm::ivec2{}; } -Vector2f ImageComponent::getSize() const +glm::vec2 ImageComponent::getSize() const { return GuiComponent::getSize() * (mBottomRightCrop - mTopLeftCrop); } @@ -53,8 +53,8 @@ void ImageComponent::resize() if (!mTexture) return; - const Vector2f textureSize = mTexture->getSourceImageSize(); - if (textureSize == Vector2f::Zero()) + const glm::vec2 textureSize{mTexture->getSourceImageSize()}; + if (textureSize == glm::vec2{}) return; if (mTexture->isTiled()) { @@ -71,75 +71,74 @@ void ImageComponent::resize() if (mTargetIsMax) { mSize = textureSize; - Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y())); + glm::vec2 resizeScale{(mTargetSize.x / mSize.x), (mTargetSize.y / mSize.y)}; - if (resizeScale.x() < resizeScale.y()) { - // This will be mTargetSize.x(). We can't exceed it, nor be lower than it. - mSize[0] *= resizeScale.x(); + if (resizeScale.x < resizeScale.y) { + // This will be mTargetSize.x. We can't exceed it, nor be lower than it. + mSize.x *= resizeScale.x; // We need to make sure we're not creating an image larger than max size. - mSize[1] = std::min(floorf(mSize[1] *= resizeScale.x()), mTargetSize.y()); + mSize.y = std::min(floorf(mSize.y *= resizeScale.x), mTargetSize.y); } else { // This will be mTargetSize.y(). We can't exceed it. - mSize[1] = floorf(mSize[1] * resizeScale.y()); + mSize.y = floorf(mSize.y * resizeScale.y); // For SVG rasterization, always calculate width from rounded height (see comment // above). We need to make sure we're not creating an image larger than max size. - mSize[0] = - std::min((mSize[1] / textureSize.y()) * textureSize.x(), mTargetSize.x()); + mSize.x = std::min((mSize.y / textureSize.y) * textureSize.x, mTargetSize.x); } } else if (mTargetIsMin) { mSize = textureSize; - Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y())); + glm::vec2 resizeScale{(mTargetSize.x / mSize.x), (mTargetSize.y / mSize.y)}; - if (resizeScale.x() > resizeScale.y()) { - mSize[0] *= resizeScale.x(); - mSize[1] *= resizeScale.x(); + if (resizeScale.x > resizeScale.y) { + mSize.x *= resizeScale.x; + mSize.y *= resizeScale.x; - float cropPercent = (mSize.y() - mTargetSize.y()) / (mSize.y() * 2); - crop(0, cropPercent, 0, cropPercent); + float cropPercent = (mSize.y - mTargetSize.y) / (mSize.y * 2.0f); + crop(0.0f, cropPercent, 0.0f, cropPercent); } else { - mSize[0] *= resizeScale.y(); - mSize[1] *= resizeScale.y(); + mSize.x *= resizeScale.y; + mSize.y *= resizeScale.y; - float cropPercent = (mSize.x() - mTargetSize.x()) / (mSize.x() * 2); - crop(cropPercent, 0, cropPercent, 0); + float cropPercent = (mSize.x - mTargetSize.x) / (mSize.x * 2.0f); + crop(cropPercent, 0.0f, cropPercent, 0.0f); } // For SVG rasterization, always calculate width from rounded height (see comment // above). We need to make sure we're not creating an image smaller than min size. - mSize[1] = std::max(floorf(mSize[1]), mTargetSize.y()); - mSize[0] = std::max((mSize[1] / textureSize.y()) * textureSize.x(), mTargetSize.x()); + mSize.y = std::max(floorf(mSize.y), mTargetSize.y); + mSize.x = std::max((mSize.y / textureSize.y) * textureSize.x, mTargetSize.x); } else { // If both components are set, we just stretch. // If no components are set, we don't resize at all. - mSize = mTargetSize == Vector2f::Zero() ? textureSize : mTargetSize; + mSize = mTargetSize == glm::vec2{} ? textureSize : mTargetSize; // If only one component is set, we resize in a way that maintains aspect ratio. // For SVG rasterization, we always calculate width from rounded height (see // comment above). - if (!mTargetSize.x() && mTargetSize.y()) { - mSize[1] = floorf(mTargetSize.y()); - mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x(); + if (!mTargetSize.x && mTargetSize.y) { + mSize.y = floorf(mTargetSize.y); + mSize.x = (mSize.y / textureSize.y) * textureSize.x; } - else if (mTargetSize.x() && !mTargetSize.y()) { - mSize[1] = floorf((mTargetSize.x() / textureSize.x()) * textureSize.y()); - mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x(); + else if (mTargetSize.x && !mTargetSize.y) { + mSize.y = floorf((mTargetSize.x / textureSize.x) * textureSize.y); + mSize.x = (mSize.y / textureSize.y) * textureSize.x; } } } - mSize[0] = floorf(mSize.x()); - mSize[1] = floorf(mSize.y()); + mSize.x = floorf(mSize.x); + mSize.y = floorf(mSize.y); // mSize.y() should already be rounded. - mTexture->rasterizeAt(static_cast(mSize.x()), static_cast(mSize.y())); + mTexture->rasterizeAt(static_cast(mSize.x), static_cast(mSize.y)); onSizeChanged(); } -void ImageComponent::setImage(std::string path, bool tile) +void ImageComponent::setImage(std::string path, bool tile, bool linearMagnify) { // Always load bundled graphic resources statically, unless mForceLoad has been set. // This eliminates annoying texture pop-in problems that would otherwise occur. @@ -151,10 +150,11 @@ void ImageComponent::setImage(std::string path, bool tile) if (mDefaultPath.empty() || !ResourceManager::getInstance()->fileExists(mDefaultPath)) mTexture.reset(); else - mTexture = TextureResource::get(mDefaultPath, tile, mForceLoad, mDynamic); + mTexture = + TextureResource::get(mDefaultPath, tile, mForceLoad, mDynamic, linearMagnify); } else { - mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic); + mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, linearMagnify); } resize(); @@ -178,7 +178,7 @@ void ImageComponent::setImage(const std::shared_ptr& texture) void ImageComponent::setResize(float width, float height) { - mTargetSize = Vector2f(width, height); + mTargetSize = glm::vec2{width, height}; mTargetIsMax = false; mTargetIsMin = false; resize(); @@ -186,7 +186,7 @@ void ImageComponent::setResize(float width, float height) void ImageComponent::setMaxSize(float width, float height) { - mTargetSize = Vector2f(width, height); + mTargetSize = glm::vec2{width, height}; mTargetIsMax = true; mTargetIsMin = false; resize(); @@ -194,7 +194,7 @@ void ImageComponent::setMaxSize(float width, float height) void ImageComponent::setMinSize(float width, float height) { - mTargetSize = Vector2f(width, height); + mTargetSize = glm::vec2{width, height}; mTargetIsMax = false; mTargetIsMin = true; resize(); @@ -203,25 +203,25 @@ void ImageComponent::setMinSize(float width, float height) void ImageComponent::cropLeft(float percent) { assert(percent >= 0.0f && percent <= 1.0f); - mTopLeftCrop.x() = percent; + mTopLeftCrop.x = percent; } void ImageComponent::cropTop(float percent) { assert(percent >= 0.0f && percent <= 1.0f); - mTopLeftCrop.y() = percent; + mTopLeftCrop.y = percent; } void ImageComponent::cropRight(float percent) { assert(percent >= 0.0f && percent <= 1.0f); - mBottomRightCrop.x() = 1.0f - percent; + mBottomRightCrop.x = 1.0f - percent; } void ImageComponent::cropBot(float percent) { assert(percent >= 0.0f && percent <= 1.0f); - mBottomRightCrop.y() = 1.0f - percent; + mBottomRightCrop.y = 1.0f - percent; } void ImageComponent::crop(float left, float top, float right, float bot) @@ -235,12 +235,12 @@ void ImageComponent::crop(float left, float top, float right, float bot) void ImageComponent::uncrop() { // Remove any applied crop. - crop(0, 0, 0, 0); + crop(0.0f, 0.0f, 0.0f, 0.0f); } void ImageComponent::cropTransparentPadding(float maxSizeX, float maxSizeY) { - if (mSize == 0) + if (mSize == glm::vec2{}) return; std::vector imageRGBA = mTexture.get()->getRawRGBAData(); @@ -248,10 +248,10 @@ void ImageComponent::cropTransparentPadding(float maxSizeX, float maxSizeY) if (imageRGBA.size() == 0) return; - Vector2i imageSize = mTexture.get()->getSize(); - cimg_library::CImg imageCImg(imageSize.x(), imageSize.y(), 1, 4, 0); + glm::ivec2 imageSize{mTexture.get()->getSize()}; + cimg_library::CImg imageCImg(imageSize.x, imageSize.y, 1, 4, 0); - int paddingCoords[4] = {}; + int paddingCoords[4]{}; // We need to convert our RGBA data to the CImg internal format as CImg does not interleave // the pixels (as in RGBARGBARGBA). @@ -260,36 +260,36 @@ void ImageComponent::cropTransparentPadding(float maxSizeX, float maxSizeY) // This will give us the coordinates for the fully transparent areas. Utils::CImg::getTransparentPaddingCoords(imageCImg, paddingCoords); - Vector2f originalSize = mSize; + glm::vec2 originalSize{mSize}; - float cropLeft = static_cast(paddingCoords[0]) / static_cast(imageSize.x()); - float cropTop = static_cast(paddingCoords[1]) / static_cast(imageSize.y()); - float cropRight = static_cast(paddingCoords[2]) / static_cast(imageSize.x()); - float cropBottom = static_cast(paddingCoords[3]) / static_cast(imageSize.y()); + float cropLeft{static_cast(paddingCoords[0]) / static_cast(imageSize.x)}; + float cropTop{static_cast(paddingCoords[1]) / static_cast(imageSize.y)}; + float cropRight{static_cast(paddingCoords[2]) / static_cast(imageSize.x)}; + float cropBottom{static_cast(paddingCoords[3]) / static_cast(imageSize.y)}; crop(cropLeft, cropTop, cropRight, cropBottom); // Cropping the image obviously leads to a reduction in size, so we need to determine // how much to scale up after cropping to keep within the max size restrictions that // were passed as arguments. - mSize.x() -= mSize.x() * (cropLeft + cropRight); - mSize.y() -= mSize.y() * (cropTop + cropBottom); + mSize.x -= mSize.x * (cropLeft + cropRight); + mSize.y -= mSize.y * (cropTop + cropBottom); - float scaleFactor = originalSize.y() / mSize.y(); + float scaleFactor = originalSize.y / mSize.y; - if (scaleFactor * mSize.x() < maxSizeX) - scaleFactor = maxSizeX / mSize.x(); + if (scaleFactor * mSize.x < maxSizeX) + scaleFactor = maxSizeX / mSize.x; - if (scaleFactor * mSize.y() < maxSizeY) - scaleFactor = maxSizeY / mSize.y(); + if (scaleFactor * mSize.y < maxSizeY) + scaleFactor = maxSizeY / mSize.y; - if (scaleFactor * mSize.x() > maxSizeX) - scaleFactor = maxSizeX / mSize.x(); + if (scaleFactor * mSize.x > maxSizeX) + scaleFactor = maxSizeX / mSize.x; - if (scaleFactor * mSize.y() > maxSizeY) - scaleFactor = maxSizeY / mSize.y(); + if (scaleFactor * mSize.y > maxSizeY) + scaleFactor = maxSizeY / mSize.y; - setResize(mSize.x() * scaleFactor, mSize.y() * scaleFactor); + setResize(mSize.x * scaleFactor, mSize.y * scaleFactor); updateVertices(); } @@ -343,23 +343,23 @@ void ImageComponent::updateVertices() // We go through this mess to make sure everything is properly rounded. // If we just round vertices at the end, edge cases occur near sizes of 0.5. - const Vector2f topLeft = { 0, 0 }; - const Vector2f bottomRight = mSize; - const float px = mTexture->isTiled() ? mSize.x() / getTextureSize().x() : 1.0f; - const float py = mTexture->isTiled() ? mSize.y() / getTextureSize().y() : 1.0f; + const glm::vec2 topLeft{}; + const glm::vec2 bottomRight{mSize}; + const float px{mTexture->isTiled() ? mSize.x / getTextureSize().x : 1.0f}; + const float py{mTexture->isTiled() ? mSize.y / getTextureSize().y : 1.0f}; // clang-format off - mVertices[0] = { { topLeft.x(), topLeft.y() }, { mTopLeftCrop.x(), py - mTopLeftCrop.y() }, 0 }; - mVertices[1] = { { topLeft.x(), bottomRight.y() }, { mTopLeftCrop.x(), 1.0f - mBottomRightCrop.y() }, 0 }; - mVertices[2] = { { bottomRight.x(), topLeft.y() }, { mBottomRightCrop.x() * px, py - mTopLeftCrop.y() }, 0 }; - mVertices[3] = { { bottomRight.x(), bottomRight.y() }, { mBottomRightCrop.x() * px, 1.0f - mBottomRightCrop.y() }, 0 }; + mVertices[0] = {{topLeft.x, topLeft.y }, {mTopLeftCrop.x, py - mTopLeftCrop.y }, 0}; + mVertices[1] = {{topLeft.x, bottomRight.y}, {mTopLeftCrop.x, 1.0f - mBottomRightCrop.y}, 0}; + mVertices[2] = {{bottomRight.x, topLeft.y }, {mBottomRightCrop.x * px, py - mTopLeftCrop.y }, 0}; + mVertices[3] = {{bottomRight.x, bottomRight.y}, {mBottomRightCrop.x * px, 1.0f - mBottomRightCrop.y}, 0}; // clang-format on updateColors(); // Round vertices. for (int i = 0; i < 4; i++) - mVertices[i].pos.round(); + mVertices[i].pos = glm::round(mVertices[i].pos); if (mFlipX) { for (int i = 0; i < 4; i++) @@ -387,23 +387,23 @@ void ImageComponent::updateColors() mVertices[3].col = colorEnd; } -void ImageComponent::render(const Transform4x4f& parentTrans) +void ImageComponent::render(const glm::mat4& parentTrans) { if (!isVisible()) return; - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; Renderer::setMatrix(trans); if (mTexture && mOpacity > 0) { if (Settings::getInstance()->getBool("DebugImage")) { - Vector2f targetSizePos = (mTargetSize - mSize) * mOrigin * -1; - Renderer::drawRect(targetSizePos.x(), targetSizePos.y(), mTargetSize.x(), - mTargetSize.y(), 0xFF000033, 0xFF000033); - Renderer::drawRect(0.0f, 0.0f, mSize.x(), mSize.y(), 0xFF000033, 0xFF000033); + glm::vec2 targetSizePos{(mTargetSize - mSize) * mOrigin * glm::vec2{-1.0f}}; + Renderer::drawRect(targetSizePos.x, targetSizePos.y, mTargetSize.x, mTargetSize.y, + 0xFF000033, 0xFF000033); + Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033); } // An image with zero size would normally indicate a corrupt image file. - if (mTexture->isInitialized() && mTexture->getSize() != 0) { + if (mTexture->isInitialized() && mTexture->getSize() != glm::ivec2{}) { // Actually draw the image. // The bind() function returns false if the texture is not currently loaded. A blank // texture is bound in this case but we want to handle a fade so it doesn't just @@ -483,17 +483,17 @@ void ImageComponent::applyTheme(const std::shared_ptr& theme, if (!elem) return; - Vector2f scale = getParent() ? getParent()->getSize() : - Vector2f(static_cast(Renderer::getScreenWidth()), - static_cast(Renderer::getScreenHeight())); + glm::vec2 scale{getParent() ? getParent()->getSize() : + glm::vec2(static_cast(Renderer::getScreenWidth()), + static_cast(Renderer::getScreenHeight()))}; if (properties & ThemeFlags::SIZE) { if (elem->has("size")) - setResize(elem->get("size") * scale); + setResize(elem->get("size") * scale); else if (elem->has("maxSize")) - setMaxSize(elem->get("maxSize") * scale); + setMaxSize(elem->get("maxSize") * scale); else if (elem->has("minSize")) - setMinSize(elem->get("minSize") * scale); + setMinSize(elem->get("minSize") * scale); } if (elem->has("default")) diff --git a/es-core/src/components/ImageComponent.h b/es-core/src/components/ImageComponent.h index 68da21126..15f2c27f7 100644 --- a/es-core/src/components/ImageComponent.h +++ b/es-core/src/components/ImageComponent.h @@ -10,7 +10,6 @@ #define ES_CORE_COMPONENTS_IMAGE_COMPONENT_H #include "GuiComponent.h" -#include "math/Vector2i.h" #include "renderers/Renderer.h" class TextureResource; @@ -25,7 +24,7 @@ public: // Loads the image at the given filepath. Will tile if tile is true (retrieves texture // as tiling, creates vertices accordingly). - void setImage(std::string path, bool tile = false); + void setImage(std::string path, bool tile = false, bool linearMagnify = false); // Loads an image from memory. void setImage(const char* data, size_t length, bool tile = false); // Use an already existing texture. @@ -39,18 +38,18 @@ public: // Can be set before or after an image is loaded. // setMaxSize() and setResize() are mutually exclusive. void setResize(float width, float height) override; - void setResize(const Vector2f& size) { setResize(size.x(), size.y()); } + void setResize(const glm::vec2& size) { setResize(size.x, size.y); } // Resize the image to be as large as possible but fit within a box of this size. // Can be set before or after an image is loaded. // Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive. void setMaxSize(float width, float height); - void setMaxSize(const Vector2f& size) { setMaxSize(size.x(), size.y()); } + void setMaxSize(const glm::vec2& size) { setMaxSize(size.x, size.y); } void setMinSize(float width, float height); - void setMinSize(const Vector2f& size) { setMinSize(size.x(), size.y()); } + void setMinSize(const glm::vec2& size) { setMinSize(size.x, size.y); } - Vector2f getRotationSize() const override { return mRotateByTargetSize ? mTargetSize : mSize; } + glm::vec2 getRotationSize() const override { return mRotateByTargetSize ? mTargetSize : mSize; } // Applied AFTER image positioning and sizing. // cropTop(0.2) will crop 20% of the top of the image. @@ -83,14 +82,14 @@ public: // Returns the size of the current texture, or (0, 0) if none is loaded. // May be different than drawn size (use getSize() for that). - Vector2i getTextureSize() const; + glm::ivec2 getTextureSize() const; - Vector2f getSize() const override; + glm::vec2 getSize() const override; bool hasImage() { return static_cast(mTexture); } std::shared_ptr getTexture() { return mTexture; } - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; virtual void applyTheme(const std::shared_ptr& theme, const std::string& view, @@ -100,7 +99,7 @@ public: virtual std::vector getHelpPrompts() override; private: - Vector2f mTargetSize; + glm::vec2 mTargetSize; bool mFlipX, mFlipY, mTargetIsMax, mTargetIsMin; @@ -127,8 +126,8 @@ private: bool mDynamic; bool mRotateByTargetSize; - Vector2f mTopLeftCrop; - Vector2f mBottomRightCrop; + glm::vec2 mTopLeftCrop; + glm::vec2 mBottomRightCrop; }; #endif // ES_CORE_COMPONENTS_IMAGE_COMPONENT_H diff --git a/es-core/src/components/ImageGridComponent.h b/es-core/src/components/ImageGridComponent.h index b3ac4c393..9abbc8531 100644 --- a/es-core/src/components/ImageGridComponent.h +++ b/es-core/src/components/ImageGridComponent.h @@ -61,7 +61,7 @@ public: bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; virtual void applyTheme(const std::shared_ptr& theme, const std::string& view, const std::string& element, @@ -98,13 +98,13 @@ private: // Tiles. bool mLastRowPartial; - Vector2f mAutoLayout; + glm::vec2 mAutoLayout; float mAutoLayoutZoom; - Vector4f mPadding; - Vector2f mMargin; - Vector2f mTileSize; - Vector2i mGridDimension; + glm::vec4 mPadding; + glm::vec2 mMargin; + glm::vec2 mTileSize; + glm::ivec2 mGridDimension; std::shared_ptr mTheme; std::vector> mTiles; @@ -126,14 +126,14 @@ template ImageGridComponent::ImageGridComponent(Window* window) : IList(window) { - Vector2f screen = Vector2f(static_cast(Renderer::getScreenWidth()), - static_cast(Renderer::getScreenHeight())); + glm::vec2 screen{static_cast(Renderer::getScreenWidth()), + static_cast(Renderer::getScreenHeight())}; - mCamera = 0.0; - mCameraDirection = 1.0; + mCamera = 0.0f; + mCameraDirection = 1.0f; - mAutoLayout = Vector2f::Zero(); - mAutoLayoutZoom = 1.0; + mAutoLayout = glm::vec2{}; + mAutoLayoutZoom = 1.0f; mStartPosition = 0; @@ -144,7 +144,7 @@ ImageGridComponent::ImageGridComponent(Window* window) mSize = screen * 0.80f; mMargin = screen * 0.07f; - mPadding = Vector4f::Zero(); + mPadding = {}; mTileSize = GridTileComponent::getDefaultTileSize(); mAnimate = true; @@ -171,7 +171,7 @@ template bool ImageGridComponent::input(InputConfig* config, Inp if (input.value != 0) { int idx = isVertical() ? 0 : 1; - Vector2i dir = Vector2i::Zero(); + glm::ivec2 dir{}; if (config->isMappedLike("up", input)) dir[1 ^ idx] = -1; else if (config->isMappedLike("down", input)) @@ -181,11 +181,11 @@ template bool ImageGridComponent::input(InputConfig* config, Inp else if (config->isMappedLike("right", input)) dir[0 ^ idx] = 1; - if (dir != Vector2i::Zero()) { + if (dir != glm::ivec2{}) { if (isVertical()) - listInput(dir.x() + dir.y() * mGridDimension.x()); + listInput(dir.x + dir.y * mGridDimension.x); else - listInput(dir.x() + dir.y() * mGridDimension.y()); + listInput(dir.x + dir.y * mGridDimension.y); return true; } } @@ -208,17 +208,15 @@ template void ImageGridComponent::update(int deltaTime) (*it)->update(deltaTime); } -template void ImageGridComponent::render(const Transform4x4f& parentTrans) +template void ImageGridComponent::render(const glm::mat4& parentTrans) { - Transform4x4f trans = getTransform() * parentTrans; - Transform4x4f tileTrans = trans; + glm::mat4 trans{getTransform() * parentTrans}; + glm::mat4 tileTrans{trans}; - float offsetX = - isVertical() ? 0.0f : mCamera * mCameraDirection * (mTileSize.x() + mMargin.x()); - float offsetY = - isVertical() ? mCamera * mCameraDirection * (mTileSize.y() + mMargin.y()) : 0.0f; + float offsetX{isVertical() ? 0.0f : mCamera * mCameraDirection * (mTileSize.x + mMargin.x)}; + float offsetY{isVertical() ? mCamera * mCameraDirection * (mTileSize.y + mMargin.y) : 0.0f}; - tileTrans.translate(Vector3f(offsetX, offsetY, 0.0)); + tileTrans = glm::translate(tileTrans, glm::vec3{offsetX, offsetY, 0.0f}); if (mEntriesDirty) { updateTiles(); @@ -226,13 +224,13 @@ template void ImageGridComponent::render(const Transform4x4f& pa } // Create a clipRect to hide tiles used to buffer texture loading. - float scaleX = trans.r0().x(); - float scaleY = trans.r1().y(); + float scaleX = trans[0].x; + float scaleY = trans[1].y; - Vector2i pos(static_cast(std::round(trans.translation()[0])), - static_cast(std::round(trans.translation()[1]))); - Vector2i size(static_cast(std::round(mSize.x() * scaleX)), - static_cast(std::round(mSize.y() * scaleY))); + glm::ivec2 pos{static_cast(std::round(trans[3].x)), + static_cast(std::round(trans[3].y))}; + glm::ivec2 size{static_cast(std::round(mSize.x * scaleX)), + static_cast(std::round(mSize.y * scaleY))}; Renderer::pushClipRect(pos, size); @@ -271,20 +269,20 @@ void ImageGridComponent::applyTheme(const std::shared_ptr& theme, // Keep the theme pointer to apply it on the tiles later on. mTheme = theme; - Vector2f screen = Vector2f(static_cast(Renderer::getScreenWidth()), - static_cast(Renderer::getScreenHeight())); + glm::vec2 screen{static_cast(Renderer::getScreenWidth()), + static_cast(Renderer::getScreenHeight())}; const ThemeData::ThemeElement* elem = theme->getElement(view, element, "imagegrid"); if (elem) { if (elem->has("margin")) - mMargin = elem->get("margin") * screen; + mMargin = elem->get("margin") * screen; if (elem->has("padding")) - mPadding = elem->get("padding") * - Vector4f(screen.x(), screen.y(), screen.x(), screen.y()); + mPadding = + elem->get("padding") * glm::vec4{screen.x, screen.y, screen.x, screen.y}; if (elem->has("autoLayout")) - mAutoLayout = elem->get("autoLayout"); + mAutoLayout = elem->get("autoLayout"); if (elem->has("autoLayoutSelectedZoom")) mAutoLayoutZoom = elem->get("autoLayoutSelectedZoom"); @@ -369,7 +367,7 @@ void ImageGridComponent::applyTheme(const std::shared_ptr& theme, // grid dimension, and then (re)build the tiles. elem = theme->getElement(view, "default", "gridtile"); - mTileSize = elem && elem->has("size") ? elem->get("size") * screen : + mTileSize = elem && elem->has("size") ? elem->get("size") * screen : GridTileComponent::getDefaultTileSize(); // Apply size property which will trigger a call to onSizeChanged() which will build the tiles. @@ -401,8 +399,8 @@ template void ImageGridComponent::onCursorChanged(const CursorSt int oldStart = mStartPosition; - int dimScrollable = (isVertical() ? mGridDimension.y() : mGridDimension.x()) - 2 * EXTRAITEMS; - int dimOpposite = isVertical() ? mGridDimension.x() : mGridDimension.y(); + int dimScrollable = (isVertical() ? mGridDimension.y : mGridDimension.x) - 2 * EXTRAITEMS; + int dimOpposite = isVertical() ? mGridDimension.x : mGridDimension.y; int centralCol = static_cast((static_cast(dimScrollable) - 0.5f) / 2.0f); int maxCentralCol = dimScrollable / 2; @@ -449,7 +447,7 @@ template void ImageGridComponent::onCursorChanged(const CursorSt } } - Vector3f oldPos = Vector3f::Zero(); + glm::vec3 oldPos{}; if (oldTile != nullptr && oldTile != newTile) { oldPos = oldTile->getBackgroundPosition(); @@ -457,7 +455,7 @@ template void ImageGridComponent::onCursorChanged(const CursorSt } if (newTile != nullptr) - newTile->setSelected(true, true, oldPos == Vector3f::Zero() ? nullptr : &oldPos, true); + newTile->setSelected(true, true, oldPos == glm::vec3{} ? nullptr : &oldPos, true); } int firstVisibleCol = mStartPosition / dimOpposite; @@ -506,8 +504,8 @@ template void ImageGridComponent::onCursorChanged(const CursorSt if (!moveCamera) return; - t -= 1.0f; // Cubic ease out. - float pct = Math::lerp(0, 1.0f, t * t * t + 1.0f); + t -= 1.0f; + float pct = glm::mix(0.0f, 1.0f, t * t * t + 1.0f); t = startPos * (1.0f - pct) + endPos * pct; mCamera = t; }; @@ -530,35 +528,33 @@ template void ImageGridComponent::buildTiles() calcGridDimension(); if (mCenterSelection) { - int dimScrollable = - (isVertical() ? mGridDimension.y() : mGridDimension.x()) - 2 * EXTRAITEMS; + int dimScrollable = (isVertical() ? mGridDimension.y : mGridDimension.x) - 2 * EXTRAITEMS; mStartPosition -= static_cast(floorf(dimScrollable / 2.0f)); } - Vector2f tileDistance = mTileSize + mMargin; + glm::vec2 tileDistance{mTileSize + mMargin}; - if (mAutoLayout.x() != 0.0f && mAutoLayout.y() != 0.0f) { - auto x = - (mSize.x() - (mMargin.x() * (mAutoLayout.x() - 1.0f)) - mPadding.x() - mPadding.z()) / - static_cast(mAutoLayout.x()); - auto y = - (mSize.y() - (mMargin.y() * (mAutoLayout.y() - 1.0f)) - mPadding.y() - mPadding.w()) / - static_cast(mAutoLayout.y()); + if (mAutoLayout.x != 0.0f && mAutoLayout.y != 0.0f) { + auto x = (mSize.x - (mMargin.x * (mAutoLayout.x - 1.0f)) - mPadding.x - mPadding.z) / + static_cast(mAutoLayout.x); + auto y = (mSize.y - (mMargin.y * (mAutoLayout.y - 1.0f)) - mPadding.y - mPadding.w) / + static_cast(mAutoLayout.y); - mTileSize = Vector2f(x, y); + mTileSize = glm::vec2{x, y}; tileDistance = mTileSize + mMargin; } bool vert = isVertical(); - Vector2f startPosition = mTileSize / 2.0f; - startPosition += mPadding.v2(); + glm::vec2 startPosition{mTileSize / 2.0f}; + startPosition.x += mPadding.x; + startPosition.y += mPadding.y; int X; int Y; // Layout tile size and position. - for (int y = 0; y < (vert ? mGridDimension.y() : mGridDimension.x()); y++) { - for (int x = 0; x < (vert ? mGridDimension.x() : mGridDimension.y()); x++) { + for (int y = 0; y < (vert ? mGridDimension.y : mGridDimension.x); y++) { + for (int x = 0; x < (vert ? mGridDimension.x : mGridDimension.y); x++) { // Create tiles. auto tile = std::make_shared(mWindow); @@ -567,15 +563,15 @@ template void ImageGridComponent::buildTiles() X = vert ? x : y - EXTRAITEMS; Y = vert ? y - EXTRAITEMS : x; - tile->setPosition(X * tileDistance.x() + startPosition.x(), - Y * tileDistance.y() + startPosition.y()); + tile->setPosition(X * tileDistance.x + startPosition.x, + Y * tileDistance.y + startPosition.y); tile->setOrigin(0.5f, 0.5f); tile->setImage(""); if (mTheme) tile->applyTheme(mTheme, "grid", "gridtile", ThemeFlags::ALL); - if (mAutoLayout.x() != 0 && mAutoLayout.y() != 0) + if (mAutoLayout.x != 0 && mAutoLayout.y != 0.0f) tile->forceSize(mTileSize, mAutoLayoutZoom); mTiles.push_back(tile); @@ -617,7 +613,7 @@ void ImageGridComponent::updateTiles(bool ascending, int end = ascending ? static_cast(mTiles.size()) : -1; int img = mStartPosition + ti; - img -= EXTRAITEMS * (isVertical() ? mGridDimension.x() : mGridDimension.y()); + img -= EXTRAITEMS * (isVertical() ? mGridDimension.x : mGridDimension.y); // Update the tiles. while (ti != end) { @@ -677,7 +673,7 @@ void ImageGridComponent::updateTileAtPos(int tilePos, if (idx < 0 || idx >= mTiles.size()) idx = 0; - Vector3f pos = mTiles.at(idx)->getBackgroundPosition(); + glm::vec3 pos{mTiles.at(idx)->getBackgroundPosition()}; tile->setSelected(true, allowAnimation, &pos); } else { @@ -693,30 +689,30 @@ template void ImageGridComponent::calcGridDimension() { // grid_size = columns * tile_size + (columns - 1) * margin // <=> columns = (grid_size + margin) / (tile_size + margin) - Vector2f gridDimension = (mSize + mMargin) / (mTileSize + mMargin); + glm::vec2 gridDimension{(mSize + mMargin) / (mTileSize + mMargin)}; - if (mAutoLayout.x() != 0 && mAutoLayout.y() != 0) + if (mAutoLayout.x != 0.0f && mAutoLayout.y != 0.0f) gridDimension = mAutoLayout; - mLastRowPartial = floorf(gridDimension.y()) != gridDimension.y(); + mLastRowPartial = floorf(gridDimension.y) != gridDimension.y; // Ceil y dim so we can display partial last row. - mGridDimension = Vector2i(static_cast(gridDimension.x()), - static_cast(ceilf(gridDimension.y()))); + mGridDimension = glm::ivec2{static_cast(gridDimension.x), + static_cast(ceilf(gridDimension.y))}; // Grid dimension validation. - if (mGridDimension.x() < 1) { + if (mGridDimension.x < 1) { LOG(LogError) << "Theme defined grid X dimension below 1"; } - if (mGridDimension.y() < 1) { + if (mGridDimension.y < 1) { LOG(LogError) << "Theme defined grid Y dimension below 1"; } // Add extra tiles to both sides. if (isVertical()) - mGridDimension.y() += 2 * EXTRAITEMS; + mGridDimension.y += 2 * EXTRAITEMS; else - mGridDimension.x() += 2 * EXTRAITEMS; + mGridDimension.x += 2 * EXTRAITEMS; } template bool ImageGridComponent::isScrollLoop() @@ -724,8 +720,8 @@ template bool ImageGridComponent::isScrollLoop() if (!mScrollLoop) return false; if (isVertical()) - return (mGridDimension.x() * (mGridDimension.y() - 2 * EXTRAITEMS)) <= mEntries.size(); - return (mGridDimension.y() * (mGridDimension.x() - 2 * EXTRAITEMS)) <= mEntries.size(); + return (mGridDimension.x * (mGridDimension.y - 2 * EXTRAITEMS)) <= mEntries.size(); + return (mGridDimension.y * (mGridDimension.x - 2 * EXTRAITEMS)) <= mEntries.size(); } #endif // ES_CORE_COMPONENTS_IMAGE_GRID_COMPONENT_H diff --git a/es-core/src/components/MenuComponent.cpp b/es-core/src/components/MenuComponent.cpp index ce7258599..3d5b49e9d 100644 --- a/es-core/src/components/MenuComponent.cpp +++ b/es-core/src/components/MenuComponent.cpp @@ -21,7 +21,7 @@ MenuComponent::MenuComponent(Window* window, const std::shared_ptr& titleFont) : GuiComponent(window) , mBackground(window) - , mGrid(window, Vector2i(1, 3)) + , mGrid(window, glm::ivec2{1, 3}) , mNeedsSaving(false) { addChild(&mBackground); @@ -34,11 +34,11 @@ MenuComponent::MenuComponent(Window* window, mTitle->setHorizontalAlignment(ALIGN_CENTER); mTitle->setColor(0x555555FF); setTitle(title, titleFont); - mGrid.setEntry(mTitle, Vector2i(0, 0), false); + mGrid.setEntry(mTitle, glm::ivec2{}, false); // Set up list which will never change (externally, anyway). mList = std::make_shared(mWindow); - mGrid.setEntry(mList, Vector2i(0, 1), true); + mGrid.setEntry(mList, glm::ivec2{0, 1}, true); updateGrid(); updateSize(); @@ -74,7 +74,7 @@ void MenuComponent::setTitle(std::string title, const std::shared_ptr& fon float MenuComponent::getButtonGridHeight() const { - return (mButtonGrid ? mButtonGrid->getSize().y() : + return (mButtonGrid ? mButtonGrid->getSize().y : Font::get(FONT_SIZE_MEDIUM)->getHeight() + (BUTTON_GRID_VERT_PADDING * Renderer::getScreenHeightModifier())); } @@ -106,11 +106,11 @@ void MenuComponent::updateSize() void MenuComponent::onSizeChanged() { - mBackground.fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); // Update grid row/column sizes. - mGrid.setRowHeightPerc(0, TITLE_HEIGHT / mSize.y()); - mGrid.setRowHeightPerc(2, getButtonGridHeight() / mSize.y()); + mGrid.setRowHeightPerc(0, TITLE_HEIGHT / mSize.y); + mGrid.setRowHeightPerc(2, getButtonGridHeight() / mSize.y); mGrid.setSize(mSize); } @@ -134,7 +134,7 @@ void MenuComponent::updateGrid() if (mButtons.size()) { mButtonGrid = makeButtonGrid(mWindow, mButtons); - mGrid.setEntry(mButtonGrid, Vector2i(0, 2), true, false); + mGrid.setEntry(mButtonGrid, glm::ivec2{0, 2}, true, false); } } @@ -142,26 +142,27 @@ std::shared_ptr makeButtonGrid( Window* window, const std::vector>& buttons) { std::shared_ptr buttonGrid = - std::make_shared(window, Vector2i(static_cast(buttons.size()), 2)); + std::make_shared(window, glm::ivec2{static_cast(buttons.size()), 2}); // Initialize to padding. float buttonGridWidth = BUTTON_GRID_HORIZ_PADDING * Renderer::getScreenWidthModifier() * buttons.size(); for (int i = 0; i < static_cast(buttons.size()); i++) { - buttonGrid->setEntry(buttons.at(i), Vector2i(i, 0), true, false); - buttonGridWidth += buttons.at(i)->getSize().x(); + buttonGrid->setEntry(buttons.at(i), glm::ivec2{i, 0}, true, false); + buttonGridWidth += buttons.at(i)->getSize().x; } for (unsigned int i = 0; i < buttons.size(); i++) buttonGrid->setColWidthPerc( - i, (buttons.at(i)->getSize().x() + + i, (buttons.at(i)->getSize().x + BUTTON_GRID_HORIZ_PADDING * Renderer::getScreenWidthModifier()) / buttonGridWidth); buttonGrid->setSize(buttonGridWidth, - buttons.at(0)->getSize().y() + - (BUTTON_GRID_VERT_PADDING * Renderer::getScreenHeightModifier()) + 2); + buttons.at(0)->getSize().y + + (BUTTON_GRID_VERT_PADDING * Renderer::getScreenHeightModifier()) + + 2.0f); // Spacer row to deal with dropshadow to make buttons look centered. - buttonGrid->setRowHeightPerc(1, 2 / buttonGrid->getSize().y()); + buttonGrid->setRowHeightPerc(1, 2.0f / buttonGrid->getSize().y); return buttonGrid; } diff --git a/es-core/src/components/NinePatchComponent.cpp b/es-core/src/components/NinePatchComponent.cpp index f14915086..4de95d9f7 100644 --- a/es-core/src/components/NinePatchComponent.cpp +++ b/es-core/src/components/NinePatchComponent.cpp @@ -55,58 +55,58 @@ void NinePatchComponent::buildVertices() // (e.g. from 720p to 4K) will be within these boundaries though. float scaleFactor; if (Renderer::getScreenWidth() > Renderer::getScreenHeight()) - scaleFactor = Math::clamp(Renderer::getScreenHeightModifier(), 0.4f, 3.0f); + scaleFactor = glm::clamp(Renderer::getScreenHeightModifier(), 0.4f, 3.0f); else - scaleFactor = Math::clamp(Renderer::getScreenWidthModifier(), 0.4f, 3.0f); + scaleFactor = glm::clamp(Renderer::getScreenWidthModifier(), 0.4f, 3.0f); - mTexture = TextureResource::get(mPath, false, false, true, scaleFactor); + mTexture = TextureResource::get(mPath, false, false, true, true, scaleFactor); - if (mTexture->getSize() == Vector2i::Zero()) { + if (mTexture->getSize() == glm::ivec2{}) { mVertices = nullptr; LOG(LogWarning) << "NinePatchComponent has no texture"; return; } - Vector2f texSize; mVertices = new Renderer::Vertex[6 * 9]; - texSize = Vector2f(static_cast(mTexture->getSize().x()), - static_cast(mTexture->getSize().y())); + glm::vec2 texSize{static_cast(mTexture->getSize().x), + static_cast(mTexture->getSize().y)}; - // clang-format off - const float imgSizeX[3] = { mCornerSize.x(), mSize.x() - mCornerSize.x() * 2.0f, mCornerSize.x() }; - const float imgSizeY[3] = { mCornerSize.y(), mSize.y() - mCornerSize.y() * 2.0f, mCornerSize.y() }; - const float imgPosX[3] = { 0, imgSizeX[0], imgSizeX[0] + imgSizeX[1] }; - const float imgPosY[3] = { 0, imgSizeY[0], imgSizeY[0] + imgSizeY[1] }; + const float imgSizeX[3]{mCornerSize.x, mSize.x - mCornerSize.x * 2.0f, mCornerSize.x}; + const float imgSizeY[3]{mCornerSize.y, mSize.y - mCornerSize.y * 2.0f, mCornerSize.y}; + const float imgPosX[3]{0, imgSizeX[0], imgSizeX[0] + imgSizeX[1]}; + const float imgPosY[3]{0, imgSizeY[0], imgSizeY[0] + imgSizeY[1]}; // The "1 +" in posY and "-" in sizeY is to deal with texture coordinates having a bottom // left corner origin vs. verticies having a top left origin. - const float texSizeX[3] = { mCornerSize.x() / texSize.x(), (texSize.x() - mCornerSize.x() * 2.0f) / texSize.x(), mCornerSize.x() / texSize.x() }; - const float texSizeY[3] = { -mCornerSize.y() / texSize.y(), -(texSize.y() - mCornerSize.y() * 2.0f) / texSize.y(), -mCornerSize.y() / texSize.y() }; - const float texPosX[3] = { 0.0f, texSizeX[0], texSizeX[0] + texSizeX[1] }; - const float texPosY[3] = { 1.0f, 1.0f + texSizeY[0], 1.0f + texSizeY[0] + texSizeY[1] }; + // clang-format off + const float texSizeX[3]{mCornerSize.x / texSize.x, (texSize.x - mCornerSize.x * 2.0f) / texSize.x, mCornerSize.x / texSize.x}; + const float texSizeY[3]{-mCornerSize.y / texSize.y, -(texSize.y - mCornerSize.y * 2.0f) / texSize.y, -mCornerSize.y / texSize.y}; + + const float texPosX[3]{0.0f, texSizeX[0], texSizeX[0] + texSizeX[1]}; + const float texPosY[3]{1.0f, 1.0f + texSizeY[0], 1.0f + texSizeY[0] + texSizeY[1]}; // clang-format on int v = 0; for (int slice = 0; slice < 9; slice++) { - const int sliceX = slice % 3; - const int sliceY = slice / 3; - const Vector2f imgPos = Vector2f(imgPosX[sliceX], imgPosY[sliceY]); - const Vector2f imgSize = Vector2f(imgSizeX[sliceX], imgSizeY[sliceY]); - const Vector2f texPos = Vector2f(texPosX[sliceX], texPosY[sliceY]); - const Vector2f texSize = Vector2f(texSizeX[sliceX], texSizeY[sliceY]); + const int sliceX{slice % 3}; + const int sliceY{slice / 3}; + const glm::vec2 imgPos{imgPosX[sliceX], imgPosY[sliceY]}; + const glm::vec2 imgSize{imgSizeX[sliceX], imgSizeY[sliceY]}; + const glm::vec2 texPos{texPosX[sliceX], texPosY[sliceY]}; + const glm::vec2 texSize{texSizeX[sliceX], texSizeY[sliceY]}; // clang-format off - mVertices[v + 1] = { { imgPos.x() , imgPos.y() }, { texPos.x(), texPos.y() }, 0 }; - mVertices[v + 2] = { { imgPos.x() , imgPos.y() + imgSize.y() }, { texPos.x(), texPos.y() + texSize.y() }, 0 }; - mVertices[v + 3] = { { imgPos.x() + imgSize.x(), imgPos.y() }, { texPos.x() + texSize.x(), texPos.y() }, 0 }; - mVertices[v + 4] = { { imgPos.x() + imgSize.x(), imgPos.y() + imgSize.y() }, { texPos.x() + texSize.x(), texPos.y() + texSize.y() }, 0 }; + mVertices[v + 1] = {{imgPos.x , imgPos.y }, {texPos.x, texPos.y }, 0}; + mVertices[v + 2] = {{imgPos.x , imgPos.y + imgSize.y}, {texPos.x, texPos.y + texSize.y}, 0}; + mVertices[v + 3] = {{imgPos.x + imgSize.x, imgPos.y }, {texPos.x + texSize.x, texPos.y }, 0}; + mVertices[v + 4] = {{imgPos.x + imgSize.x, imgPos.y + imgSize.y}, {texPos.x + texSize.x, texPos.y + texSize.y}, 0}; // clang-format on // Round vertices. for (int i = 1; i < 5; i++) - mVertices[v + i].pos.round(); + mVertices[v + i].pos = glm::round(mVertices[v + i].pos); // Make duplicates of first and last vertex so this can be rendered as a triangle strip. mVertices[v + 0] = mVertices[v + 1]; @@ -118,12 +118,12 @@ void NinePatchComponent::buildVertices() updateColors(); } -void NinePatchComponent::render(const Transform4x4f& parentTrans) +void NinePatchComponent::render(const glm::mat4& parentTrans) { if (!isVisible()) return; - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; if (mTexture && mVertices != nullptr) { Renderer::setMatrix(trans); @@ -144,17 +144,15 @@ void NinePatchComponent::render(const Transform4x4f& parentTrans) renderChildren(trans); } -void NinePatchComponent::onSizeChanged() { buildVertices(); } - -void NinePatchComponent::fitTo(Vector2f size, Vector3f position, Vector2f padding) +void NinePatchComponent::fitTo(glm::vec2 size, glm::vec3 position, glm::vec2 padding) { size += padding; - position[0] -= padding.x() / 2.0f; - position[1] -= padding.y() / 2.0f; + position[0] -= padding.x / 2.0f; + position[1] -= padding.y / 2.0f; setSize(size + mCornerSize * 2.0f); - setPosition(position.x() + Math::lerp(-mCornerSize.x(), mCornerSize.x(), mOrigin.x()), - position.y() + Math::lerp(-mCornerSize.y(), mCornerSize.y(), mOrigin.y())); + setPosition(position.x + glm::mix(-mCornerSize.x, mCornerSize.x, mOrigin.x), + position.y + glm::mix(-mCornerSize.y, mCornerSize.y, mOrigin.y)); } void NinePatchComponent::setImagePath(const std::string& path) diff --git a/es-core/src/components/NinePatchComponent.h b/es-core/src/components/NinePatchComponent.h index 9c0191ded..a02009eb2 100644 --- a/es-core/src/components/NinePatchComponent.h +++ b/es-core/src/components/NinePatchComponent.h @@ -35,13 +35,10 @@ public: unsigned int centerColor = 0xFFFFFFFF); virtual ~NinePatchComponent(); - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; - void onSizeChanged() override; - - void fitTo(Vector2f size, - Vector3f position = Vector3f::Zero(), - Vector2f padding = Vector2f::Zero()); + void onSizeChanged() override { buildVertices(); } + void fitTo(glm::vec2 size, glm::vec3 position = {}, glm::vec2 padding = {}); void setImagePath(const std::string& path); // Apply a color shift to the "edge" parts of the ninepatch. @@ -54,8 +51,8 @@ public: const std::string& element, unsigned int properties) override; - const Vector2f& getCornerSize() const { return mCornerSize; } - void setCornerSize(const Vector2f& size) + const glm::vec2& getCornerSize() const { return mCornerSize; } + void setCornerSize(const glm::vec2& size) { mCornerSize = size; buildVertices(); @@ -68,7 +65,7 @@ private: Renderer::Vertex* mVertices; std::string mPath; - Vector2f mCornerSize; + glm::vec2 mCornerSize; unsigned int mEdgeColor; unsigned int mCenterColor; std::shared_ptr mTexture; diff --git a/es-core/src/components/OptionListComponent.h b/es-core/src/components/OptionListComponent.h index 223ec141f..fc21ce2f5 100644 --- a/es-core/src/components/OptionListComponent.h +++ b/es-core/src/components/OptionListComponent.h @@ -58,7 +58,7 @@ public: addChild(&mRightArrow); } - setSize(mLeftArrow.getSize().x() + mRightArrow.getSize().x(), font->getHeight()); + setSize(mLeftArrow.getSize().x + mRightArrow.getSize().x, font->getHeight()); } // Handles positioning/resizing of text and arrows. @@ -67,19 +67,19 @@ public: mLeftArrow.setResize(0, mText.getFont()->getLetterHeight()); mRightArrow.setResize(0, mText.getFont()->getLetterHeight()); - if (mSize.x() < (mLeftArrow.getSize().x() + mRightArrow.getSize().x())) { + if (mSize.x < (mLeftArrow.getSize().x + mRightArrow.getSize().x)) { LOG(LogWarning) << "OptionListComponent too narrow"; } - mText.setSize(mSize.x() - mLeftArrow.getSize().x() - mRightArrow.getSize().x(), + mText.setSize(mSize.x - mLeftArrow.getSize().x - mRightArrow.getSize().x, mText.getFont()->getHeight()); // Position. - mLeftArrow.setPosition(0, (mSize.y() - mLeftArrow.getSize().y()) / 2); - mText.setPosition(mLeftArrow.getPosition().x() + mLeftArrow.getSize().x(), - (mSize.y() - mText.getSize().y()) / 2); - mRightArrow.setPosition(mText.getPosition().x() + mText.getSize().x(), - (mSize.y() - mRightArrow.getSize().y()) / 2); + mLeftArrow.setPosition(0.0f, (mSize.y - mLeftArrow.getSize().y) / 2.0f); + mText.setPosition(mLeftArrow.getPosition().x + mLeftArrow.getSize().x, + (mSize.y - mText.getSize().y) / 2.0f); + mRightArrow.setPosition(mText.getPosition().x + mText.getSize().x, + (mSize.y - mRightArrow.getSize().y) / 2.0f); } bool input(InputConfig* config, Input input) override @@ -223,7 +223,11 @@ private: HelpStyle mHelpStyle; - void open() { mWindow->pushGui(new OptionListPopup(mWindow, getHelpStyle(), this, mName)); } + void open() + { + // Open the list popup. + mWindow->pushGui(new OptionListPopup(mWindow, getHelpStyle(), this, mName)); + } void onSelectedChanged() { @@ -232,10 +236,10 @@ private: std::stringstream ss; ss << getSelectedObjects().size() << " SELECTED"; mText.setText(ss.str()); - mText.setSize(0, mText.getSize().y()); - setSize(mText.getSize().x() + mRightArrow.getSize().x() + - 24 * Renderer::getScreenWidthModifier(), - mText.getSize().y()); + mText.setSize(0, mText.getSize().y); + setSize(mText.getSize().x + mRightArrow.getSize().x + + 24.0f * Renderer::getScreenWidthModifier(), + mText.getSize().y); if (mParent) // Hack since there's no "on child size changed" callback. mParent->onSizeChanged(); } @@ -244,11 +248,10 @@ private: for (auto it = mEntries.cbegin(); it != mEntries.cend(); it++) { if (it->selected) { mText.setText(Utils::String::toUpper(it->name)); - mText.setSize(0, mText.getSize().y()); - setSize(mText.getSize().x() + mLeftArrow.getSize().x() + - mRightArrow.getSize().x() + + mText.setSize(0.0f, mText.getSize().y); + setSize(mText.getSize().x + mLeftArrow.getSize().x + mRightArrow.getSize().x + 24.0f * Renderer::getScreenWidthModifier(), - mText.getSize().y()); + mText.getSize().y); if (mParent) // Hack since there's no "on child size changed" callback. mParent->onSizeChanged(); break; @@ -356,7 +359,7 @@ private: }); } - mMenu.setPosition((Renderer::getScreenWidth() - mMenu.getSize().x()) / 2.0f, + mMenu.setPosition((Renderer::getScreenWidth() - mMenu.getSize().x) / 2.0f, Renderer::getScreenHeight() * 0.13f); addChild(&mMenu); } diff --git a/es-core/src/components/RatingComponent.cpp b/es-core/src/components/RatingComponent.cpp index 6dfc32b3f..1751d0f46 100644 --- a/es-core/src/components/RatingComponent.cpp +++ b/es-core/src/components/RatingComponent.cpp @@ -25,7 +25,7 @@ RatingComponent::RatingComponent(Window* window, bool colorizeChanges) mFilledTexture = TextureResource::get(":/graphics/star_filled.svg", true); mUnfilledTexture = TextureResource::get(":/graphics/star_unfilled.svg", true); mValue = 0.5f; - mSize = Vector2f(64.0f * NUM_RATING_STARS, 64.0f); + mSize = glm::vec2{64.0f * NUM_RATING_STARS, 64.0f}; updateVertices(); updateColors(); } @@ -96,13 +96,13 @@ void RatingComponent::setColorShift(unsigned int color) void RatingComponent::onSizeChanged() { - if (mSize.y() == 0) - mSize[1] = mSize.x() / NUM_RATING_STARS; - else if (mSize.x() == 0) - mSize[0] = mSize.y() * NUM_RATING_STARS; + if (mSize.y == 0.0f) + mSize.y = mSize.x / NUM_RATING_STARS; + else if (mSize.x == 0.0f) + mSize.x = mSize.y * NUM_RATING_STARS; - if (mSize.y() > 0) { - size_t heightPx = static_cast(std::round(mSize.y())); + if (mSize.y > 0.0f) { + size_t heightPx = static_cast(std::round(mSize.y)); if (mFilledTexture) mFilledTexture->rasterizeAt(heightPx, heightPx); if (mUnfilledTexture) @@ -115,21 +115,21 @@ void RatingComponent::onSizeChanged() void RatingComponent::updateVertices() { const float numStars = NUM_RATING_STARS; - const float h = getSize().y(); // Ss the same as a single star's width. - const float w = getSize().y() * mValue * numStars; - const float fw = getSize().y() * numStars; + const float h = getSize().y; // Ss the same as a single star's width. + const float w = getSize().y * mValue * numStars; + const float fw = getSize().y * numStars; const unsigned int color = Renderer::convertRGBAToABGR(mColorShift); // clang-format off - mVertices[0] = { { 0.0f, 0.0f }, { 0.0f, 1.0f }, color }; - mVertices[1] = { { 0.0f, h }, { 0.0f, 0.0f }, color }; - mVertices[2] = { { w, 0.0f }, { mValue * numStars, 1.0f }, color }; - mVertices[3] = { { w, h }, { mValue * numStars, 0.0f }, color }; + mVertices[0] = {{0.0f, 0.0f}, {0.0f, 1.0f}, color}; + mVertices[1] = {{0.0f, h }, {0.0f, 0.0f}, color}; + mVertices[2] = {{w, 0.0f}, {mValue * numStars, 1.0f}, color}; + mVertices[3] = {{w, h }, {mValue * numStars, 0.0f}, color}; - mVertices[4] = { { 0.0f, 0.0f }, { 0.0f, 1.0f }, color }; - mVertices[5] = { { 0.0f, h }, { 0.0f, 0.0f }, color }; - mVertices[6] = { { fw, 0.0f }, { numStars, 1.0f }, color }; - mVertices[7] = { { fw, h }, { numStars, 0.0f }, color }; + mVertices[4] = {{0.0f, 0.0f}, {0.0f, 1.0f}, color}; + mVertices[5] = {{0.0f, h }, {0.0f, 0.0f}, color}; + mVertices[6] = {{fw, 0.0f}, {numStars, 1.0f}, color}; + mVertices[7] = {{fw, h }, {numStars, 0.0f}, color}; // clang-format on } @@ -141,18 +141,18 @@ void RatingComponent::updateColors() mVertices[i].col = color; } -void RatingComponent::render(const Transform4x4f& parentTrans) +void RatingComponent::render(const glm::mat4& parentTrans) { if (!isVisible() || mFilledTexture == nullptr || mUnfilledTexture == nullptr) return; - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; Renderer::setMatrix(trans); if (mOpacity > 0) { if (Settings::getInstance()->getBool("DebugImage")) { - Renderer::drawRect(0.0f, 0.0f, mSize.y() * NUM_RATING_STARS, mSize.y(), 0xFF000033, + Renderer::drawRect(0.0f, 0.0f, mSize.y * NUM_RATING_STARS, mSize.y, 0xFF000033, 0xFF000033); } diff --git a/es-core/src/components/RatingComponent.h b/es-core/src/components/RatingComponent.h index dfb2be65c..b533f14d2 100644 --- a/es-core/src/components/RatingComponent.h +++ b/es-core/src/components/RatingComponent.h @@ -27,7 +27,7 @@ public: void setValue(const std::string& value) override; bool input(InputConfig* config, Input input) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void onSizeChanged() override; @@ -48,8 +48,6 @@ public: virtual std::vector getHelpPrompts() override; private: - Vector2f mTargetSize; - void updateVertices(); void updateColors(); diff --git a/es-core/src/components/ScrollableContainer.cpp b/es-core/src/components/ScrollableContainer.cpp index d025ae89f..8a342a641 100644 --- a/es-core/src/components/ScrollableContainer.cpp +++ b/es-core/src/components/ScrollableContainer.cpp @@ -11,7 +11,6 @@ #include "Window.h" #include "animations/LambdaAnimation.h" -#include "math/Vector2i.h" #include "renderers/Renderer.h" #include "resources/Font.h" @@ -45,7 +44,7 @@ ScrollableContainer::ScrollableContainer(Window* window) void ScrollableContainer::setAutoScroll(bool autoScroll) { if (autoScroll) { - mScrollDir = Vector2f(0, 1); + mScrollDir = glm::vec2{0.0f, 1.0f}; mAutoScrollDelay = static_cast(mAutoScrollDelayConstant); mAutoScrollSpeed = mAutoScrollSpeedConstant; mAutoScrollSpeed = @@ -53,7 +52,7 @@ void ScrollableContainer::setAutoScroll(bool autoScroll) reset(); } else { - mScrollDir = Vector2f(0, 0); + mScrollDir = glm::vec2{}; mAutoScrollDelay = 0; mAutoScrollSpeed = 0; mAutoScrollAccumulator = 0; @@ -71,7 +70,7 @@ void ScrollableContainer::setScrollParameters(float autoScrollDelayConstant, void ScrollableContainer::reset() { - mScrollPos = Vector2f(0, 0); + mScrollPos = glm::vec2{}; mAutoScrollResetAccumulator = 0; mAutoScrollAccumulator = -mAutoScrollDelay + mAutoScrollSpeed; mAtEnd = false; @@ -82,16 +81,16 @@ void ScrollableContainer::update(int deltaTime) // Don't scroll if the media viewer or screensaver is active or if text scrolling is disabled; if (mWindow->isMediaViewerActive() || mWindow->isScreensaverActive() || !mWindow->getAllowTextScrolling()) { - if (mScrollPos != 0 && !mWindow->isLaunchScreenDisplayed()) + if (mScrollPos != glm::vec2{} && !mWindow->isLaunchScreenDisplayed()) reset(); return; } - const Vector2f contentSize = getContentSize(); + const glm::vec2 contentSize{getContentSize()}; int adjustedAutoScrollSpeed = mAutoScrollSpeed; // Adjust the scrolling speed based on the width of the container. - float widthModifier = contentSize.x() / static_cast(Renderer::getScreenWidth()); + float widthModifier = contentSize.x / static_cast(Renderer::getScreenWidth()); adjustedAutoScrollSpeed = static_cast(adjustedAutoScrollSpeed * widthModifier); // Also adjust the scrolling speed based on the size of the font. @@ -105,28 +104,28 @@ void ScrollableContainer::update(int deltaTime) if (adjustedAutoScrollSpeed != 0) { mAutoScrollAccumulator += deltaTime; while (mAutoScrollAccumulator >= adjustedAutoScrollSpeed) { - if (contentSize.y() > mSize.y()) + if (contentSize.y > mSize.y) mScrollPos += mScrollDir; mAutoScrollAccumulator -= adjustedAutoScrollSpeed; } } // Clip scrolling within bounds. - if (mScrollPos.x() < 0) - mScrollPos[0] = 0; - if (mScrollPos.y() < 0) - mScrollPos[1] = 0; + if (mScrollPos.x < 0.0f) + mScrollPos.x = 0.0f; + if (mScrollPos.y < 0.0f) + mScrollPos.y = 0.0f; - if (mScrollPos.x() + getSize().x() > contentSize.x()) { - mScrollPos[0] = contentSize.x() - getSize().x(); + if (mScrollPos.x + getSize().x > contentSize.x) { + mScrollPos.x = contentSize.x - getSize().x; mAtEnd = true; } - if (contentSize.y() < getSize().y()) { - mScrollPos[1] = 0; + if (contentSize.y < getSize().y) { + mScrollPos.y = 0.0f; } - else if (mScrollPos.y() + getSize().y() > contentSize.y()) { - mScrollPos[1] = contentSize.y() - getSize().y(); + else if (mScrollPos.y + getSize().y > contentSize.y) { + mScrollPos.y = contentSize.y - getSize().y; mAtEnd = true; } @@ -135,8 +134,8 @@ void ScrollableContainer::update(int deltaTime) if (mAutoScrollResetAccumulator >= static_cast(mAutoScrollResetDelayConstant)) { // Fade in the text as it resets to the start position. auto func = [this](float t) { - this->setOpacity(static_cast(Math::lerp(0.0f, 1.0f, t) * 255)); - mScrollPos = Vector2f(0, 0); + this->setOpacity(static_cast(glm::mix(0.0f, 1.0f, t) * 255)); + mScrollPos = glm::vec2{}; mAutoScrollResetAccumulator = 0; mAutoScrollAccumulator = -mAutoScrollDelay + mAutoScrollSpeed; mAtEnd = false; @@ -148,39 +147,41 @@ void ScrollableContainer::update(int deltaTime) GuiComponent::update(deltaTime); } -void ScrollableContainer::render(const Transform4x4f& parentTrans) +void ScrollableContainer::render(const glm::mat4& parentTrans) { if (!isVisible()) return; - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; - Vector2i clipPos(static_cast(trans.translation().x()), - static_cast(trans.translation().y())); + glm::ivec2 clipPos{static_cast(trans[3].x), static_cast(trans[3].y)}; - Vector3f dimScaled = trans * Vector3f(mSize.x(), mSize.y(), 0); - Vector2i clipDim(static_cast((dimScaled.x()) - trans.translation().x()), - static_cast((dimScaled.y()) - trans.translation().y())); + glm::vec3 dimScaled{}; + dimScaled.x = std::fabs(trans[3].x + mSize.x); + dimScaled.y = std::fabs(trans[3].y + mSize.y); + + glm::ivec2 clipDim{static_cast(dimScaled.x - trans[3].x), + static_cast(dimScaled.y - trans[3].y)}; Renderer::pushClipRect(clipPos, clipDim); - trans.translate(-Vector3f(mScrollPos.x(), mScrollPos.y(), 0)); + trans = glm::translate(trans, -glm::vec3{mScrollPos.x, mScrollPos.y, 0.0f}); Renderer::setMatrix(trans); GuiComponent::renderChildren(trans); Renderer::popClipRect(); } -Vector2f ScrollableContainer::getContentSize() +glm::vec2 ScrollableContainer::getContentSize() { - Vector2f max(0, 0); + glm::vec2 max{}; for (unsigned int i = 0; i < mChildren.size(); i++) { - Vector2f pos(mChildren.at(i)->getPosition()[0], mChildren.at(i)->getPosition()[1]); - Vector2f bottomRight = mChildren.at(i)->getSize() + pos; - if (bottomRight.x() > max.x()) - max.x() = bottomRight.x(); - if (bottomRight.y() > max.y()) - max.y() = bottomRight.y(); + glm::vec2 pos{mChildren.at(i)->getPosition().x, mChildren.at(i)->getPosition().y}; + glm::vec2 bottomRight{mChildren.at(i)->getSize() + pos}; + if (bottomRight.x > max.x) + max.x = bottomRight.x; + if (bottomRight.y > max.y) + max.y = bottomRight.y; if (!mFontSize) mFontSize = static_cast(mChildren.at(i)->getFont()->getSize()); } diff --git a/es-core/src/components/ScrollableContainer.h b/es-core/src/components/ScrollableContainer.h index 96d8b17f5..548d65b03 100644 --- a/es-core/src/components/ScrollableContainer.h +++ b/es-core/src/components/ScrollableContainer.h @@ -24,8 +24,8 @@ class ScrollableContainer : public GuiComponent public: ScrollableContainer(Window* window); - Vector2f getScrollPos() const { return mScrollPos; } - void setScrollPos(const Vector2f& pos) { mScrollPos = pos; } + glm::vec2 getScrollPos() const { return mScrollPos; } + void setScrollPos(const glm::vec2& pos) { mScrollPos = pos; } void setAutoScroll(bool autoScroll); void setScrollParameters(float autoScrollDelayConstant, @@ -34,13 +34,13 @@ public: void reset(); void update(int deltaTime) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; private: - Vector2f getContentSize(); + glm::vec2 getContentSize(); - Vector2f mScrollPos; - Vector2f mScrollDir; + glm::vec2 mScrollPos; + glm::vec2 mScrollDir; float mFontSize; float mSmallFontSize; diff --git a/es-core/src/components/SliderComponent.cpp b/es-core/src/components/SliderComponent.cpp index 247b9fc1e..35c84a26a 100644 --- a/es-core/src/components/SliderComponent.cpp +++ b/es-core/src/components/SliderComponent.cpp @@ -74,23 +74,23 @@ void SliderComponent::update(int deltaTime) GuiComponent::update(deltaTime); } -void SliderComponent::render(const Transform4x4f& parentTrans) +void SliderComponent::render(const glm::mat4& parentTrans) { - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; Renderer::setMatrix(trans); // Render suffix. if (mValueCache) mFont->renderTextCache(mValueCache.get()); - float width = - mSize.x() - mKnob.getSize().x() - - (mValueCache ? mValueCache->metrics.size.x() + (4.0f * Renderer::getScreenWidthModifier()) : - 0); + float width{mSize.x - mKnob.getSize().x - + (mValueCache ? + mValueCache->metrics.size.x + (4.0f * Renderer::getScreenWidthModifier()) : + 0.0f)}; // Render line. - const float lineWidth = 2.0f * Renderer::getScreenHeightModifier(); - Renderer::drawRect(mKnob.getSize().x() / 2.0f, mSize.y() / 2.0f - lineWidth / 2.0f, width, + const float lineWidth{2.0f * Renderer::getScreenHeightModifier()}; + Renderer::drawRect(mKnob.getSize().x / 2.0f, mSize.y / 2.0f - lineWidth / 2.0f, width, lineWidth, 0x777777FF, 0x777777FF); // Render knob. @@ -115,7 +115,7 @@ float SliderComponent::getValue() { return mValue; } void SliderComponent::onSizeChanged() { if (!mSuffix.empty()) - mFont = Font::get(static_cast(mSize.y()), FONT_PATH_LIGHT); + mFont = Font::get(static_cast(mSize.y), FONT_PATH_LIGHT); onValueChanged(); } @@ -139,21 +139,21 @@ void SliderComponent::onValueChanged() ss << mSuffix; const std::string max = ss.str(); - Vector2f textSize = mFont->sizeText(max); + glm::vec2 textSize = mFont->sizeText(max); mValueCache = std::shared_ptr(mFont->buildTextCache( - val, mSize.x() - textSize.x(), (mSize.y() - textSize.y()) / 2.0f, 0x777777FF)); - mValueCache->metrics.size[0] = textSize.x(); // Fudge the width. + val, mSize.x - textSize.x, (mSize.y - textSize.y) / 2.0f, 0x777777FF)); + mValueCache->metrics.size.x = textSize.x; // Fudge the width. } // Update knob position/size. - mKnob.setResize(0, mSize.y() * 0.7f); + mKnob.setResize(0, mSize.y * 0.7f); float lineLength = - mSize.x() - mKnob.getSize().x() - - (mValueCache ? mValueCache->metrics.size.x() + (4.0f * Renderer::getScreenWidthModifier()) : - 0); + mSize.x - mKnob.getSize().x - + (mValueCache ? mValueCache->metrics.size.x + (4.0f * Renderer::getScreenWidthModifier()) : + 0.0f); - mKnob.setPosition(((mValue - mMin / 2.0f) / mMax) * lineLength + mKnob.getSize().x() / 2.0f, - mSize.y() / 2.0f); + mKnob.setPosition(((mValue - mMin / 2.0f) / mMax) * lineLength + mKnob.getSize().x / 2.0f, + mSize.y / 2.0f); } std::vector SliderComponent::getHelpPrompts() diff --git a/es-core/src/components/SliderComponent.h b/es-core/src/components/SliderComponent.h index 3b9f7ec86..13b5d3153 100644 --- a/es-core/src/components/SliderComponent.h +++ b/es-core/src/components/SliderComponent.h @@ -29,7 +29,7 @@ public: bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void onSizeChanged() override; diff --git a/es-core/src/components/SwitchComponent.cpp b/es-core/src/components/SwitchComponent.cpp index 18d1010a4..23f64dd24 100644 --- a/es-core/src/components/SwitchComponent.cpp +++ b/es-core/src/components/SwitchComponent.cpp @@ -42,9 +42,9 @@ bool SwitchComponent::input(InputConfig* config, Input input) return false; } -void SwitchComponent::render(const Transform4x4f& parentTrans) +void SwitchComponent::render(const glm::mat4& parentTrans) { - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; mImage.render(trans); renderChildren(trans); } diff --git a/es-core/src/components/SwitchComponent.h b/es-core/src/components/SwitchComponent.h index cc7cadf9d..c21219144 100644 --- a/es-core/src/components/SwitchComponent.h +++ b/es-core/src/components/SwitchComponent.h @@ -19,7 +19,7 @@ public: SwitchComponent(Window* window, bool state = false); bool input(InputConfig* config, Input input) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void onSizeChanged() override { mImage.setSize(mSize); } void setResize(float width, float height) override { mImage.setResize(width, height); } diff --git a/es-core/src/components/TextComponent.cpp b/es-core/src/components/TextComponent.cpp index 332cc56c4..3b268955e 100644 --- a/es-core/src/components/TextComponent.cpp +++ b/es-core/src/components/TextComponent.cpp @@ -33,8 +33,8 @@ TextComponent::TextComponent(Window* window, const std::shared_ptr& font, unsigned int color, Alignment align, - Vector3f pos, - Vector2f size, + glm::vec3 pos, + glm::vec2 size, unsigned int bgcolor, float margin) : GuiComponent(window) @@ -60,7 +60,7 @@ TextComponent::TextComponent(Window* window, void TextComponent::onSizeChanged() { - mAutoCalcExtent = Vector2i((getSize().x() == 0), (getSize().y() == 0)); + mAutoCalcExtent = glm::ivec2{(getSize().x == 0), (getSize().y == 0)}; onTextChanged(); } @@ -115,66 +115,66 @@ void TextComponent::setUppercase(bool uppercase) onTextChanged(); } -void TextComponent::render(const Transform4x4f& parentTrans) +void TextComponent::render(const glm::mat4& parentTrans) { if (!isVisible()) return; - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; if (mRenderBackground) { Renderer::setMatrix(trans); - Renderer::drawRect(0.0f, 0.0f, mSize.x(), mSize.y(), mBgColor, mBgColor); + Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, mBgColor, mBgColor); } if (mTextCache) { - const Vector2f& textSize = mTextCache->metrics.size; - float yOff = 0; + const glm::vec2& textSize{mTextCache->metrics.size}; + float yOff = 0.0f; switch (mVerticalAlignment) { case ALIGN_TOP: { - yOff = 0; + yOff = 0.0f; break; } case ALIGN_BOTTOM: { - yOff = (getSize().y() - textSize.y()); + yOff = (getSize().y - textSize.y); break; } case ALIGN_CENTER: { - yOff = (getSize().y() - textSize.y()) / 2.0f; + yOff = (getSize().y - textSize.y) / 2.0f; break; } default: { break; } } - Vector3f off(0, yOff, 0); + glm::vec3 off{0.0f, yOff, 0.0f}; if (Settings::getInstance()->getBool("DebugText")) { // Draw the "textbox" area, what we are aligned within. Renderer::setMatrix(trans); - Renderer::drawRect(0.0f, 0.0f, mSize.x(), mSize.y(), 0x0000FF33, 0x0000FF33); + Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33); } - trans.translate(off); + trans = glm::translate(trans, off); Renderer::setMatrix(trans); // Draw the text area, where the text actually is located. if (Settings::getInstance()->getBool("DebugText")) { switch (mHorizontalAlignment) { case ALIGN_LEFT: { - Renderer::drawRect(0.0f, 0.0f, mTextCache->metrics.size.x(), - mTextCache->metrics.size.y(), 0x00000033, 0x00000033); + Renderer::drawRect(0.0f, 0.0f, mTextCache->metrics.size.x, + mTextCache->metrics.size.y, 0x00000033, 0x00000033); break; } case ALIGN_CENTER: { - Renderer::drawRect((mSize.x() - mTextCache->metrics.size.x()) / 2.0f, 0.0f, - mTextCache->metrics.size.x(), mTextCache->metrics.size.y(), + Renderer::drawRect((mSize.x - mTextCache->metrics.size.x) / 2.0f, 0.0f, + mTextCache->metrics.size.x, mTextCache->metrics.size.y, 0x00000033, 0x00000033); break; } case ALIGN_RIGHT: { - Renderer::drawRect(mSize.x() - mTextCache->metrics.size.x(), 0.0f, - mTextCache->metrics.size.x(), mTextCache->metrics.size.y(), + Renderer::drawRect(mSize.x - mTextCache->metrics.size.x, 0.0f, + mTextCache->metrics.size.x, mTextCache->metrics.size.y, 0x00000033, 0x00000033); break; } @@ -189,15 +189,15 @@ void TextComponent::render(const Transform4x4f& parentTrans) void TextComponent::calculateExtent() { - if (mAutoCalcExtent.x()) { + if (mAutoCalcExtent.x) { mSize = mFont->sizeText(mUppercase ? Utils::String::toUpper(mText) : mText, mLineSpacing); } else { - if (mAutoCalcExtent.y()) - mSize[1] = mFont - ->sizeWrappedText(mUppercase ? Utils::String::toUpper(mText) : mText, - getSize().x(), mLineSpacing) - .y(); + if (mAutoCalcExtent.y) + mSize.y = mFont + ->sizeWrappedText(mUppercase ? Utils::String::toUpper(mText) : mText, + getSize().x, mLineSpacing) + .y; } } @@ -213,7 +213,7 @@ void TextComponent::onTextChanged() std::string text = mUppercase ? Utils::String::toUpper(mText) : mText; std::shared_ptr f = mFont; - const bool isMultiline = (mSize.y() == 0 || mSize.y() > f->getHeight() * 1.2f); + const bool isMultiline = (mSize.y == 0.0f || mSize.y > f->getHeight() * 1.2f); bool addAbbrev = false; if (!isMultiline) { @@ -223,15 +223,15 @@ void TextComponent::onTextChanged() addAbbrev = newline != std::string::npos; } - Vector2f size = f->sizeText(text); - if (!isMultiline && mSize.x() > 0.0f && text.size() && (size.x() > mSize.x() || addAbbrev)) { + glm::vec2 size{f->sizeText(text)}; + if (!isMultiline && mSize.x > 0.0f && text.size() && (size.x > mSize.x || addAbbrev)) { // Abbreviate text. const std::string abbrev = "..."; - Vector2f abbrevSize = f->sizeText(abbrev); + glm::vec2 abbrevSize{f->sizeText(abbrev)}; // mMargin adds a margin around the text if it's abbreviated. - float marginAdjustedSize = mSize.x() - (mSize.x() * mMargin); + float marginAdjustedSize = mSize.x - (mSize.x * mMargin); - while (text.size() && size.x() + abbrevSize.x() > marginAdjustedSize) { + while (text.size() && size.x + abbrevSize.x > marginAdjustedSize) { size_t newSize = Utils::String::prevCursor(text, text.size()); text.erase(newSize, text.size() - newSize); size = f->sizeText(text); @@ -240,12 +240,12 @@ void TextComponent::onTextChanged() text.append(abbrev); mTextCache = std::shared_ptr( - f->buildTextCache(text, Vector2f(0, 0), (mColor >> 8 << 8) | mOpacity, mSize.x(), + f->buildTextCache(text, glm::vec2{}, (mColor >> 8 << 8) | mOpacity, mSize.x, mHorizontalAlignment, mLineSpacing, mNoTopMargin)); } else { mTextCache = std::shared_ptr(f->buildTextCache( - f->wrapText(text, mSize.x()), Vector2f(0, 0), (mColor >> 8 << 8) | mOpacity, mSize.x(), + f->wrapText(text, mSize.x), glm::vec2{}, (mColor >> 8 << 8) | mOpacity, mSize.x, mHorizontalAlignment, mLineSpacing, mNoTopMargin)); } } diff --git a/es-core/src/components/TextComponent.h b/es-core/src/components/TextComponent.h index 52a65d373..58ac31f69 100644 --- a/es-core/src/components/TextComponent.h +++ b/es-core/src/components/TextComponent.h @@ -30,8 +30,8 @@ public: const std::shared_ptr& font, unsigned int color = 0x000000FF, Alignment align = ALIGN_LEFT, - Vector3f pos = Vector3f::Zero(), - Vector2f size = Vector2f::Zero(), + glm::vec3 pos = {}, + glm::vec2 size = {}, unsigned int bgcolor = 0x00000000, float margin = 0.0f); @@ -48,7 +48,7 @@ public: void setBackgroundColor(unsigned int color); void setRenderBackground(bool render) { mRenderBackground = render; } - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; std::string getValue() const override { return mText; } void setValue(const std::string& value) override { setText(value); } @@ -88,7 +88,7 @@ private: bool mRenderBackground; bool mUppercase; - Vector2i mAutoCalcExtent; + glm::ivec2 mAutoCalcExtent; std::shared_ptr mTextCache; Alignment mHorizontalAlignment; Alignment mVerticalAlignment; diff --git a/es-core/src/components/TextEditComponent.cpp b/es-core/src/components/TextEditComponent.cpp index de9bd028d..7ed097944 100644 --- a/es-core/src/components/TextEditComponent.cpp +++ b/es-core/src/components/TextEditComponent.cpp @@ -28,7 +28,7 @@ TextEditComponent::TextEditComponent(Window* window) { addChild(&mBox); onFocusLost(); - mResolutionAdjustment = -(34 * Renderer::getScreenWidthModifier() - 34); + mResolutionAdjustment = -(34.0f * Renderer::getScreenWidthModifier() - 34.0f); setSize(4096, mFont->getHeight() + (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier())); } @@ -46,9 +46,9 @@ void TextEditComponent::onFocusLost() void TextEditComponent::onSizeChanged() { - mBox.fitTo(mSize, Vector3f::Zero(), - Vector2f(-34 + mResolutionAdjustment, - -32 - (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier()))); + mBox.fitTo(mSize, glm::vec3{}, + glm::vec2{-34.0f + mResolutionAdjustment, + -32.0f - (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier())}); onTextChanged(); // Wrap point probably changed. } @@ -239,10 +239,9 @@ void TextEditComponent::setCursor(size_t pos) void TextEditComponent::onTextChanged() { - std::string wrappedText = - (isMultiline() ? mFont->wrapText(mText, getTextAreaSize().x()) : mText); + std::string wrappedText = (isMultiline() ? mFont->wrapText(mText, getTextAreaSize().x) : mText); mTextCache = std::unique_ptr( - mFont->buildTextCache(wrappedText, 0, 0, 0x77777700 | getOpacity())); + mFont->buildTextCache(wrappedText, 0.0f, 0.0f, 0x77777700 | getOpacity())); if (mCursor > static_cast(mText.length())) mCursor = static_cast(mText.length()); @@ -251,44 +250,45 @@ void TextEditComponent::onTextChanged() void TextEditComponent::onCursorChanged() { if (isMultiline()) { - Vector2f textSize = - mFont->getWrappedTextCursorOffset(mText, getTextAreaSize().x(), mCursor); + glm::vec2 textSize{mFont->getWrappedTextCursorOffset(mText, getTextAreaSize().x, mCursor)}; // Need to scroll down? - if (mScrollOffset.y() + getTextAreaSize().y() < textSize.y() + mFont->getHeight()) - mScrollOffset[1] = textSize.y() - getTextAreaSize().y() + mFont->getHeight(); + if (mScrollOffset.y + getTextAreaSize().y < textSize.y + mFont->getHeight()) + mScrollOffset.y = textSize.y - getTextAreaSize().y + mFont->getHeight(); // Need to scroll up? - else if (mScrollOffset.y() > textSize.y()) - mScrollOffset[1] = textSize.y(); + else if (mScrollOffset.y > textSize.y) + mScrollOffset.y = textSize.y; } else { - Vector2f cursorPos = mFont->sizeText(mText.substr(0, mCursor)); + glm::vec2 cursorPos{mFont->sizeText(mText.substr(0, mCursor))}; - if (mScrollOffset.x() + getTextAreaSize().x() < cursorPos.x()) - mScrollOffset[0] = cursorPos.x() - getTextAreaSize().x(); - else if (mScrollOffset.x() > cursorPos.x()) - mScrollOffset[0] = cursorPos.x(); + if (mScrollOffset.x + getTextAreaSize().x < cursorPos.x) + mScrollOffset.x = cursorPos.x - getTextAreaSize().x; + else if (mScrollOffset.x > cursorPos.x) + mScrollOffset.x = cursorPos.x; } } -void TextEditComponent::render(const Transform4x4f& parentTrans) +void TextEditComponent::render(const glm::mat4& parentTrans) { - Transform4x4f trans = getTransform() * parentTrans; + glm::mat4 trans{getTransform() * parentTrans}; renderChildren(trans); // Text + cursor rendering. // Offset into our "text area" (padding). - trans.translation() += Vector3f(getTextAreaPos().x(), getTextAreaPos().y(), 0); + trans = glm::translate(trans, glm::vec3{getTextAreaPos().x, getTextAreaPos().y, 0.0f}); - Vector2i clipPos(static_cast(trans.translation().x()), - static_cast(trans.translation().y())); + glm::ivec2 clipPos{static_cast(trans[3].x), static_cast(trans[3].y)}; // Use "text area" size for clipping. - Vector3f dimScaled = trans * Vector3f(getTextAreaSize().x(), getTextAreaSize().y(), 0); - Vector2i clipDim(static_cast((dimScaled.x()) - trans.translation().x()), - static_cast((dimScaled.y()) - trans.translation().y())); + glm::vec3 dimScaled{}; + dimScaled.x = std::fabs(trans[3].x + getTextAreaSize().x); + dimScaled.y = std::fabs(trans[3].y + getTextAreaSize().y); + + glm::ivec2 clipDim{static_cast(dimScaled.x - trans[3].x), + static_cast(dimScaled.y - trans[3].y)}; Renderer::pushClipRect(clipPos, clipDim); - trans.translate(Vector3f(-mScrollOffset.x(), -mScrollOffset.y(), 0)); + trans = glm::translate(trans, glm::vec3{-mScrollOffset.x, -mScrollOffset.y, 0.0f}); Renderer::setMatrix(trans); if (mTextCache) @@ -299,9 +299,9 @@ void TextEditComponent::render(const Transform4x4f& parentTrans) // Draw cursor. if (mEditing) { - Vector2f cursorPos; + glm::vec2 cursorPos; if (isMultiline()) { - cursorPos = mFont->getWrappedTextCursorOffset(mText, getTextAreaSize().x(), mCursor); + cursorPos = mFont->getWrappedTextCursorOffset(mText, getTextAreaSize().x, mCursor); } else { cursorPos = mFont->sizeText(mText.substr(0, mCursor)); @@ -309,24 +309,24 @@ void TextEditComponent::render(const Transform4x4f& parentTrans) } float cursorHeight = mFont->getHeight() * 0.8f; - Renderer::drawRect( - cursorPos.x(), cursorPos.y() + (mFont->getHeight() - cursorHeight) / 2.0f, - 2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0x000000FF, 0x000000FF); + Renderer::drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f, + 2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0x000000FF, + 0x000000FF); } } -Vector2f TextEditComponent::getTextAreaPos() const +glm::vec2 TextEditComponent::getTextAreaPos() const { - return Vector2f( + return glm::vec2{ (-mResolutionAdjustment + (TEXT_PADDING_HORIZ * Renderer::getScreenWidthModifier())) / 2.0f, - (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier()) / 2.0f); + (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier()) / 2.0f}; } -Vector2f TextEditComponent::getTextAreaSize() const +glm::vec2 TextEditComponent::getTextAreaSize() const { - return Vector2f(mSize.x() + mResolutionAdjustment - - (TEXT_PADDING_HORIZ * Renderer::getScreenWidthModifier()), - mSize.y() - (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier())); + return glm::vec2{mSize.x + mResolutionAdjustment - + (TEXT_PADDING_HORIZ * Renderer::getScreenWidthModifier()), + mSize.y - (TEXT_PADDING_VERT * Renderer::getScreenHeightModifier())}; } std::vector TextEditComponent::getHelpPrompts() diff --git a/es-core/src/components/TextEditComponent.h b/es-core/src/components/TextEditComponent.h index 9365912a3..a350ed306 100644 --- a/es-core/src/components/TextEditComponent.h +++ b/es-core/src/components/TextEditComponent.h @@ -25,7 +25,7 @@ public: void textInput(const std::string& text) override; bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void onFocusGained() override; void onFocusLost() override; @@ -52,9 +52,9 @@ private: void updateCursorRepeat(int deltaTime); void moveCursor(int amt); - bool isMultiline() { return (getSize().y() > mFont->getHeight() * 1.25f); } - Vector2f getTextAreaPos() const; - Vector2f getTextAreaSize() const; + bool isMultiline() { return (getSize().y > mFont->getHeight() * 1.25f); } + glm::vec2 getTextAreaPos() const; + glm::vec2 getTextAreaSize() const; std::string mText; std::string mTextOrig; @@ -65,7 +65,7 @@ private: int mCursorRepeatTimer; int mCursorRepeatDir; - Vector2f mScrollOffset; + glm::vec2 mScrollOffset; NinePatchComponent mBox; float mResolutionAdjustment; diff --git a/es-core/src/components/TextListComponent.h b/es-core/src/components/TextListComponent.h index f38318a18..1261b9d05 100644 --- a/es-core/src/components/TextListComponent.h +++ b/es-core/src/components/TextListComponent.h @@ -12,7 +12,6 @@ #include "Log.h" #include "Sound.h" #include "components/IList.h" -#include "math/Misc.h" #include "resources/Font.h" #include "utils/StringUtil.h" @@ -48,7 +47,7 @@ public: bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void applyTheme(const std::shared_ptr& theme, const std::string& view, const std::string& element, @@ -155,22 +154,22 @@ TextListComponent::TextListComponent(Window* window) mColors[1] = 0x00FF00FF; } -template void TextListComponent::render(const Transform4x4f& parentTrans) +template void TextListComponent::render(const glm::mat4& parentTrans) { if (size() == 0) return; - Transform4x4f trans = parentTrans * getTransform(); - std::shared_ptr& font = mFont; + glm::mat4 trans{parentTrans * getTransform()}; + std::shared_ptr& font{mFont}; - int startEntry = 0; - float y = 0; + int startEntry{0}; + float y{0.0f}; - const float entrySize = - std::max(font->getHeight(1.0), static_cast(font->getSize())) * mLineSpacing; + const float entrySize{std::max(font->getHeight(1.0), static_cast(font->getSize())) * + mLineSpacing}; // Number of entries that can fit on the screen simultaneously. - int screenCount = static_cast(mSize.y() / entrySize + 0.5f); + int screenCount = static_cast(mSize.y / entrySize + 0.5f); if (size() >= screenCount) { startEntry = mCursor - screenCount / 2; @@ -193,25 +192,26 @@ template void TextListComponent::render(const Transform4x4f& par } else { Renderer::setMatrix(trans); - Renderer::drawRect(0.0f, (mCursor - startEntry) * entrySize + mSelectorOffsetY, - mSize.x(), mSelectorHeight, mSelectorColor, mSelectorColorEnd, + Renderer::drawRect(0.0f, (mCursor - startEntry) * entrySize + mSelectorOffsetY, mSize.x, + mSelectorHeight, mSelectorColor, mSelectorColorEnd, mSelectorColorGradientHorizontal); } } if (Settings::getInstance()->getBool("DebugText")) { - Renderer::drawRect(mHorizontalMargin, 0.0f, mSize.x() - mHorizontalMargin * 2.0f, mSize.y(), + Renderer::drawRect(mHorizontalMargin, 0.0f, mSize.x - mHorizontalMargin * 2.0f, mSize.y, 0x00000033, 0x00000033); - Renderer::drawRect(0.0f, 0.0f, mSize.x(), mSize.y(), 0x0000FF33, 0x0000FF33); + Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33); } // Clip to inside margins. - Vector3f dim(mSize.x(), mSize.y(), 0.0f); - dim = trans * dim - trans.translation(); + glm::vec3 dim{mSize.x, mSize.y, 0.0f}; + dim.x = (trans[0].x * dim.x + trans[3].x) - trans[3].x; + dim.y = (trans[1].y * dim.y + trans[3].y) - trans[3].y; + Renderer::pushClipRect( - Vector2i(static_cast(trans.translation().x() + mHorizontalMargin), - static_cast(trans.translation().y())), - Vector2i(static_cast(dim.x() - mHorizontalMargin * 2.0f), static_cast(dim.y()))); + glm::ivec2{static_cast(trans[3].x + mHorizontalMargin), static_cast(trans[3].y)}, + glm::ivec2{static_cast(dim.x - mHorizontalMargin * 2.0f), static_cast(dim.y)}); for (int i = startEntry; i < listCutoff; i++) { typename IList::Entry& entry = mEntries.at(static_cast(i)); @@ -235,34 +235,35 @@ template void TextListComponent::render(const Transform4x4f& par else entry.data.textCache->setColor(color); - Vector3f offset(0.0f, y, 0.0f); + glm::vec3 offset{0.0f, y, 0.0f}; switch (mAlignment) { case ALIGN_LEFT: - offset[0] = mHorizontalMargin; + offset.x = mHorizontalMargin; break; case ALIGN_CENTER: - offset[0] = - static_cast((mSize.x() - entry.data.textCache->metrics.size.x()) / 2.0f); - if (offset[0] < mHorizontalMargin) - offset[0] = mHorizontalMargin; + offset.x = + static_cast((mSize.x - entry.data.textCache->metrics.size.x) / 2.0f); + if (offset.x < mHorizontalMargin) + offset.x = mHorizontalMargin; break; case ALIGN_RIGHT: - offset[0] = (mSize.x() - entry.data.textCache->metrics.size.x()); - offset[0] -= mHorizontalMargin; - if (offset[0] < mHorizontalMargin) - offset[0] = mHorizontalMargin; + offset.x = (mSize.x - entry.data.textCache->metrics.size.x); + offset.x -= mHorizontalMargin; + if (offset.x < mHorizontalMargin) + offset.x = mHorizontalMargin; break; } // Render text. - Transform4x4f drawTrans = trans; + glm::mat4 drawTrans{trans}; // Currently selected item text might be scrolling. if (mCursor == i && mMarqueeOffset > 0) - drawTrans.translate(offset - Vector3f(static_cast(mMarqueeOffset), 0.0f, 0.0f)); + drawTrans = glm::translate( + drawTrans, offset - glm::vec3{static_cast(mMarqueeOffset), 0.0f, 0.0f}); else - drawTrans.translate(offset); + drawTrans = glm::translate(drawTrans, offset); // Needed to avoid flickering when returning to the start position. if (mMarqueeOffset == 0 && mMarqueeOffset2 == 0) @@ -275,13 +276,13 @@ template void TextListComponent::render(const Transform4x4f& par if ((mCursor == i && mMarqueeOffset2 < 0) || (mCursor == i && mMarqueeScroll)) { mMarqueeScroll = true; drawTrans = trans; - drawTrans.translate(offset - Vector3f(static_cast(mMarqueeOffset2), 0.0f, 0.0f)); + drawTrans = glm::translate( + drawTrans, offset - glm::vec3{static_cast(mMarqueeOffset2), 0.0f, 0.0f}); Renderer::setMatrix(drawTrans); font->renderTextCache(entry.data.textCache.get()); } y += entrySize; } - Renderer::popClipRect(); listRenderTitleOverlay(trans); GuiComponent::renderChildren(trans); @@ -347,13 +348,12 @@ template void TextListComponent::update(int deltaTime) const float textLength = mFont ->sizeText(Utils::String::toUpper( mEntries.at(static_cast(mCursor)).name)) - .x(); - const float limit = mSize.x() - mHorizontalMargin * 2.0f; + .x; + const float limit = mSize.x - mHorizontalMargin * 2.0f; if (textLength > limit) { - // Loop. - // Pixels per second (based on nes-mini font at 1920x1080 to produce a speed of 200). - const float speed = mFont->sizeText("ABCDEFGHIJKLMNOPQRSTUVWXYZ").x() * 0.247f; + // Loop the text. + const float speed = mFont->sizeText("ABCDEFGHIJKLMNOPQRSTUVWXYZ").x * 0.247f; const float delay = 3000.0f; const float scrollLength = textLength; const float returnLength = speed * 1.5f; @@ -365,9 +365,9 @@ template void TextListComponent::update(int deltaTime) while (mMarqueeTime > maxTime) mMarqueeTime -= maxTime; - mMarqueeOffset = static_cast(Math::Scroll::loop(delay, scrollTime + returnTime, - static_cast(mMarqueeTime), - scrollLength + returnLength)); + mMarqueeOffset = static_cast(Utils::Math::loop(delay, scrollTime + returnTime, + static_cast(mMarqueeTime), + scrollLength + returnLength)); if (mMarqueeOffset > (scrollLength - (limit - returnLength))) mMarqueeOffset2 = static_cast(mMarqueeOffset - (scrollLength + returnLength)); @@ -450,7 +450,7 @@ void TextListComponent::applyTheme(const std::shared_ptr& theme, } if (elem->has("horizontalMargin")) { mHorizontalMargin = elem->get("horizontalMargin") * - (this->mParent ? this->mParent->getSize().x() : + (this->mParent ? this->mParent->getSize().x : static_cast(Renderer::getScreenWidth())); } } @@ -464,7 +464,7 @@ void TextListComponent::applyTheme(const std::shared_ptr& theme, if (elem->has("selectorHeight")) setSelectorHeight(elem->get("selectorHeight") * Renderer::getScreenHeight()); if (elem->has("selectorOffsetY")) { - float scale = this->mParent ? this->mParent->getSize().y() : + float scale = this->mParent ? this->mParent->getSize().y : static_cast(Renderer::getScreenHeight()); setSelectorOffsetY(elem->get("selectorOffsetY") * scale); } @@ -477,7 +477,7 @@ void TextListComponent::applyTheme(const std::shared_ptr& theme, std::string path = elem->get("selectorImagePath"); bool tile = elem->has("selectorImageTile") && elem->get("selectorImageTile"); mSelectorImage.setImage(path, tile); - mSelectorImage.setSize(mSize.x(), mSelectorHeight); + mSelectorImage.setSize(mSize.x, mSelectorHeight); mSelectorImage.setColorShift(mSelectorColor); mSelectorImage.setColorShiftEnd(mSelectorColorEnd); } diff --git a/es-core/src/components/VideoComponent.cpp b/es-core/src/components/VideoComponent.cpp index 4ca19cc8e..78f6261dd 100644 --- a/es-core/src/components/VideoComponent.cpp +++ b/es-core/src/components/VideoComponent.cpp @@ -171,12 +171,12 @@ void VideoComponent::topWindow(bool isTop) manageState(); } -void VideoComponent::render(const Transform4x4f& parentTrans) +void VideoComponent::render(const glm::mat4& parentTrans) { if (!isVisible()) return; - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; GuiComponent::renderChildren(trans); Renderer::setMatrix(trans); @@ -191,7 +191,7 @@ void VideoComponent::render(const Transform4x4f& parentTrans) pauseVideo(); } -void VideoComponent::renderSnapshot(const Transform4x4f& parentTrans) +void VideoComponent::renderSnapshot(const glm::mat4& parentTrans) { // This function is called when the video is not currently being played. We need to // work out if we should display a static image. If the menu is open, then always render @@ -223,24 +223,24 @@ void VideoComponent::applyTheme(const std::shared_ptr& theme, if (!elem) return; - Vector2f scale = getParent() ? getParent()->getSize() : - Vector2f(static_cast(Renderer::getScreenWidth()), - static_cast(Renderer::getScreenHeight())); + glm::vec2 scale{getParent() ? getParent()->getSize() : + glm::vec2{static_cast(Renderer::getScreenWidth()), + static_cast(Renderer::getScreenHeight())}}; if (properties & ThemeFlags::SIZE) { if (elem->has("size")) { - setResize(elem->get("size") * scale); - mVideoAreaSize = elem->get("size") * scale; + setResize(elem->get("size") * scale); + mVideoAreaSize = elem->get("size") * scale; } else if (elem->has("maxSize")) { - setMaxSize(elem->get("maxSize") * scale); - mVideoAreaSize = elem->get("maxSize") * scale; + setMaxSize(elem->get("maxSize") * scale); + mVideoAreaSize = elem->get("maxSize") * scale; } } if (properties & ThemeFlags::POSITION) { if (elem->has("pos")) - mVideoAreaPos = elem->get("pos") * scale; + mVideoAreaPos = elem->get("pos") * scale; } if (elem->has("default")) @@ -275,15 +275,15 @@ void VideoComponent::update(int deltaTime) // Fade in videos, the time period is a bit different between the screensaver, // media viewer and gamelist view. if (mScreensaverMode && mFadeIn < 1.0f) { - mFadeIn = Math::clamp(mFadeIn + (deltaTime / static_cast(SCREENSAVER_FADE_IN_TIME)), - 0.0f, 1.0f); + mFadeIn = glm::clamp(mFadeIn + (deltaTime / static_cast(SCREENSAVER_FADE_IN_TIME)), + 0.0f, 1.0f); } else if (mMediaViewerMode && mFadeIn < 1.0f) { - mFadeIn = Math::clamp(mFadeIn + (deltaTime / static_cast(MEDIA_VIEWER_FADE_IN_TIME)), - 0.0f, 1.0f); + mFadeIn = glm::clamp(mFadeIn + (deltaTime / static_cast(MEDIA_VIEWER_FADE_IN_TIME)), + 0.0f, 1.0f); } else if (mFadeIn < 1.0f) { - mFadeIn = Math::clamp(mFadeIn + 0.01f, 0.0f, 1.0f); + mFadeIn = glm::clamp(mFadeIn + 0.01f, 0.0f, 1.0f); } GuiComponent::update(deltaTime); diff --git a/es-core/src/components/VideoComponent.h b/es-core/src/components/VideoComponent.h index 8a7653cc5..7f6ef5099 100644 --- a/es-core/src/components/VideoComponent.h +++ b/es-core/src/components/VideoComponent.h @@ -61,8 +61,8 @@ public: void onPositionChanged() override { mStaticImage.setPosition(mPosition); } void onSizeChanged() override { mStaticImage.onSizeChanged(); } - void render(const Transform4x4f& parentTrans) override; - void renderSnapshot(const Transform4x4f& parentTrans); + void render(const glm::mat4& parentTrans) override; + void renderSnapshot(const glm::mat4& parentTrans); virtual void applyTheme(const std::shared_ptr& theme, const std::string& view, @@ -78,13 +78,13 @@ public: // zero, no resizing. This can be set before or after a video is loaded. // setMaxSize() and setResize() are mutually exclusive. virtual void setResize(float width, float height) override = 0; - void setResize(const Vector2f& size) { setResize(size.x(), size.y()); } + void setResize(const glm::vec2& size) { setResize(size.x, size.y); } // Resize the video to be as large as possible but fit within a box of this size. // This can be set before or after a video is loaded. // Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive. virtual void setMaxSize(float width, float height) = 0; - void setMaxSize(const Vector2f& size) { setMaxSize(size.x(), size.y()); } + void setMaxSize(const glm::vec2& size) { setMaxSize(size.x, size.y); } private: // Start the video immediately. @@ -110,9 +110,9 @@ protected: Window* mWindow; unsigned mVideoWidth; unsigned mVideoHeight; - Vector2f mTargetSize; - Vector2f mVideoAreaPos; - Vector2f mVideoAreaSize; + glm::vec2 mTargetSize; + glm::vec2 mVideoAreaPos; + glm::vec2 mVideoAreaSize; std::shared_ptr mTexture; std::string mStaticImagePath; ImageComponent mStaticImage; diff --git a/es-core/src/components/VideoFFmpegComponent.cpp b/es-core/src/components/VideoFFmpegComponent.cpp index bfd364e14..923c02528 100644 --- a/es-core/src/components/VideoFFmpegComponent.cpp +++ b/es-core/src/components/VideoFFmpegComponent.cpp @@ -6,6 +6,8 @@ // Video player based on FFmpeg. // +#define DEBUG_VIDEO false + #include "components/VideoFFmpegComponent.h" #include "AudioManager.h" @@ -13,7 +15,7 @@ #include "Window.h" #include "resources/TextureResource.h" -#define DEBUG_VIDEO false +#include enum AVHWDeviceType VideoFFmpegComponent::sDeviceType = AV_HWDEVICE_TYPE_NONE; enum AVPixelFormat VideoFFmpegComponent::sPixelFormat = AV_PIX_FMT_NONE; @@ -57,7 +59,7 @@ VideoFFmpegComponent::~VideoFFmpegComponent() { stopVideo(); } void VideoFFmpegComponent::setResize(float width, float height) { // This resize function is used when stretching videos to full screen in the video screensaver. - mTargetSize = Vector2f(width, height); + mTargetSize = glm::vec2{width, height}; mTargetIsMax = false; mStaticImage.setResize(width, height); resize(); @@ -67,7 +69,7 @@ void VideoFFmpegComponent::setMaxSize(float width, float height) { // This resize function is used in most instances, such as non-stretched video screensaver // and the gamelist videos. - mTargetSize = Vector2f(width, height); + mTargetSize = glm::vec2{width, height}; mTargetIsMax = true; mStaticImage.setMaxSize(width, height); resize(); @@ -78,51 +80,51 @@ void VideoFFmpegComponent::resize() if (!mTexture) return; - const Vector2f textureSize(static_cast(mVideoWidth), static_cast(mVideoHeight)); + const glm::vec2 textureSize{static_cast(mVideoWidth), static_cast(mVideoHeight)}; - if (textureSize == Vector2f::Zero()) + if (textureSize == glm::vec2{}) return; if (mTargetIsMax) { mSize = textureSize; - Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y())); + glm::vec2 resizeScale{(mTargetSize.x / mSize.x), (mTargetSize.y / mSize.y)}; - if (resizeScale.x() < resizeScale.y()) { - mSize[0] *= resizeScale.x(); - mSize[1] *= resizeScale.x(); + if (resizeScale.x < resizeScale.y) { + mSize.x *= resizeScale.x; + mSize.y *= resizeScale.x; } else { - mSize[0] *= resizeScale.y(); - mSize[1] *= resizeScale.y(); + mSize.x *= resizeScale.y; + mSize.y *= resizeScale.y; } - mSize[1] = std::round(mSize[1]); - mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x(); + mSize.y = std::round(mSize.y); + mSize.x = (mSize.y / textureSize.y) * textureSize.x; } else { // If both components are set, we just stretch. // If no components are set, we don't resize at all. - mSize = mTargetSize == Vector2f::Zero() ? textureSize : mTargetSize; + mSize = mTargetSize == glm::vec2{} ? textureSize : mTargetSize; // If only one component is set, we resize in a way that maintains aspect ratio. - if (!mTargetSize.x() && mTargetSize.y()) { - mSize[1] = std::round(mTargetSize.y()); - mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x(); + if (!mTargetSize.x && mTargetSize.y) { + mSize.y = std::round(mTargetSize.y); + mSize.x = (mSize.y / textureSize.y) * textureSize.x; } - else if (mTargetSize.x() && !mTargetSize.y()) { - mSize[1] = std::round((mTargetSize.x() / textureSize.x()) * textureSize.y()); - mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x(); + else if (mTargetSize.x && !mTargetSize.y) { + mSize.y = std::round((mTargetSize.x / textureSize.x) * textureSize.y); + mSize.x = (mSize.y / textureSize.y) * textureSize.x; } } onSizeChanged(); } -void VideoFFmpegComponent::render(const Transform4x4f& parentTrans) +void VideoFFmpegComponent::render(const glm::mat4& parentTrans) { VideoComponent::render(parentTrans); - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; GuiComponent::renderChildren(trans); if (mIsPlaying && mFormatContext) { @@ -146,15 +148,15 @@ void VideoFFmpegComponent::render(const Transform4x4f& parentTrans) } // clang-format off - vertices[0] = { { 0.0f , 0.0f }, { 0.0f, 0.0f }, color }; - vertices[1] = { { 0.0f , mSize.y() }, { 0.0f, 1.0f }, color }; - vertices[2] = { { mSize.x(), 0.0f }, { 1.0f, 0.0f }, color }; - vertices[3] = { { mSize.x(), mSize.y() }, { 1.0f, 1.0f }, color }; + vertices[0] = {{0.0f, 0.0f }, {0.0f, 0.0f}, color}; + vertices[1] = {{0.0f, mSize.y}, {0.0f, 1.0f}, color}; + vertices[2] = {{mSize.x, 0.0f }, {1.0f, 0.0f}, color}; + vertices[3] = {{mSize.x, mSize.y}, {1.0f, 1.0f}, color}; // clang-format on // Round vertices. for (int i = 0; i < 4; i++) - vertices[i].pos.round(); + vertices[i].pos = glm::round(vertices[i].pos); // This is needed to avoid a slight gap before the video starts playing. if (!mDecodedFrame) @@ -290,7 +292,7 @@ bool VideoFFmpegComponent::setupVideoFilters() { int returnValue = 0; char errorMessage[512]; - const enum AVPixelFormat outPixFormats[] = { AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE }; + const enum AVPixelFormat outPixFormats[] = {AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE}; mVFilterInputs = avfilter_inout_alloc(); mVFilterOutputs = avfilter_inout_alloc(); @@ -416,8 +418,8 @@ bool VideoFFmpegComponent::setupAudioFilters() { int returnValue = 0; char errorMessage[512]; - const int outSampleRates[] = { AudioManager::getInstance()->sAudioFormat.freq, -1 }; - const enum AVSampleFormat outSampleFormats[] = { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }; + const int outSampleRates[] = {AudioManager::getInstance()->sAudioFormat.freq, -1}; + const enum AVSampleFormat outSampleFormats[] = {AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE}; mAFilterInputs = avfilter_inout_alloc(); mAFilterOutputs = avfilter_inout_alloc(); @@ -798,51 +800,49 @@ void VideoFFmpegComponent::calculateBlackRectangle() // otherwise it will exactly match the video size. The reason to add a black rectangle // behind videos in this second instance is that the scanline rendering will make the // video partially transparent so this may avoid some unforseen issues with some themes. - if (mVideoAreaPos != 0 && mVideoAreaSize != 0) { + if (mVideoAreaPos != glm::vec2{} && mVideoAreaSize != glm::vec2{}) { mVideoRectangleCoords.clear(); if (Settings::getInstance()->getBool("GamelistVideoPillarbox")) { float rectHeight; float rectWidth; // Video is in landscape orientation. - if (mSize.x() > mSize.y()) { + if (mSize.x > mSize.y) { // Checking the Y size should not normally be required as landscape format // should mean the height can't be higher than the max size defined by the // theme. But as the height in mSize is provided by FFmpeg in integer format // and then scaled, there could be rounding errors that make the video height // slightly higher than allowed. It's only a single pixel or a few pixels, but // it's still visible for some videos. - if (mSize.y() < mVideoAreaSize.y() && mSize.y() / mVideoAreaSize.y() < 0.90) - rectHeight = mVideoAreaSize.y(); + if (mSize.y < mVideoAreaSize.y && mSize.y / mVideoAreaSize.y < 0.90f) + rectHeight = mVideoAreaSize.y; else - rectHeight = mSize.y(); + rectHeight = mSize.y; // Don't add a black border that is too narrow, that's what the 0.85 constant // takes care of. - if (mSize.x() < mVideoAreaSize.x() && mSize.x() / mVideoAreaSize.x() < 0.85) - rectWidth = mVideoAreaSize.x(); + if (mSize.x < mVideoAreaSize.x && mSize.x / mVideoAreaSize.x < 0.85f) + rectWidth = mVideoAreaSize.x; else - rectWidth = mSize.x(); + rectWidth = mSize.x; } // Video is in portrait orientation (or completely square). else { - rectWidth = mVideoAreaSize.x(); - rectHeight = mSize.y(); + rectWidth = mVideoAreaSize.x; + rectHeight = mSize.y; } // Populate the rectangle coordinates to be used in render(). - mVideoRectangleCoords.push_back( - std::round(mVideoAreaPos.x() - rectWidth * mOrigin.x())); - mVideoRectangleCoords.push_back( - std::round(mVideoAreaPos.y() - rectHeight * mOrigin.y())); + mVideoRectangleCoords.push_back(std::round(mVideoAreaPos.x - rectWidth * mOrigin.x)); + mVideoRectangleCoords.push_back(std::round(mVideoAreaPos.y - rectHeight * mOrigin.y)); mVideoRectangleCoords.push_back(std::round(rectWidth)); mVideoRectangleCoords.push_back(std::round(rectHeight)); } // If the option to display pillarboxes is disabled, then make the rectangle equivalent // to the size of the video. else { - mVideoRectangleCoords.push_back(std::round(mPosition.x() - mSize.x() * mOrigin.x())); - mVideoRectangleCoords.push_back(std::round(mPosition.y() - mSize.y() * mOrigin.y())); - mVideoRectangleCoords.push_back(std::round(mSize.x())); - mVideoRectangleCoords.push_back(std::round(mSize.y())); + mVideoRectangleCoords.push_back(std::round(mPosition.x - mSize.x * mOrigin.x)); + mVideoRectangleCoords.push_back(std::round(mPosition.y - mSize.y * mOrigin.y)); + mVideoRectangleCoords.push_back(std::round(mSize.x)); + mVideoRectangleCoords.push_back(std::round(mSize.y)); } } } diff --git a/es-core/src/components/VideoFFmpegComponent.h b/es-core/src/components/VideoFFmpegComponent.h index 2d06b9709..255e2fe09 100644 --- a/es-core/src/components/VideoFFmpegComponent.h +++ b/es-core/src/components/VideoFFmpegComponent.h @@ -50,7 +50,7 @@ private: // Used internally whenever the resizing parameters or texture change. void resize(); - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; virtual void updatePlayer() override; // This will run the frame processing in a separate thread. diff --git a/es-core/src/components/VideoVlcComponent.cpp b/es-core/src/components/VideoVlcComponent.cpp index 60dd46b83..9c3fc3084 100644 --- a/es-core/src/components/VideoVlcComponent.cpp +++ b/es-core/src/components/VideoVlcComponent.cpp @@ -63,7 +63,7 @@ void VideoVlcComponent::deinit() void VideoVlcComponent::setResize(float width, float height) { // This resize function is used when stretching videos to full screen in the video screensaver. - mTargetSize = Vector2f(width, height); + mTargetSize = glm::vec2{width, height}; mTargetIsMax = false; mStaticImage.setResize(width, height); resize(); @@ -73,7 +73,7 @@ void VideoVlcComponent::setMaxSize(float width, float height) { // This resize function is used in most instances, such as non-stretched video screensaver // and the gamelist videos. - mTargetSize = Vector2f(width, height); + mTargetSize = glm::vec2{width, height}; mTargetIsMax = true; mStaticImage.setMaxSize(width, height); resize(); @@ -83,7 +83,7 @@ void VideoVlcComponent::setupVLC() { // If VLC hasn't been initialised yet then do it now. if (!mVLC) { - const char* args[] = { "--quiet" }; + const char* args[] = {"--quiet"}; #if defined(__APPLE__) // It's required to set the VLC_PLUGIN_PATH variable on macOS, or the libVLC @@ -127,48 +127,48 @@ void VideoVlcComponent::resize() if (!mTexture) return; - const Vector2f textureSize(static_cast(mVideoWidth), static_cast(mVideoHeight)); + const glm::vec2 textureSize(static_cast(mVideoWidth), static_cast(mVideoHeight)); - if (textureSize == Vector2f::Zero()) + if (textureSize == glm::vec2{}) return; if (mTargetIsMax) { mSize = textureSize; - Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y())); + glm::vec2 resizeScale{(mTargetSize.x / mSize.x), (mTargetSize.y / mSize.y)}; - if (resizeScale.x() < resizeScale.y()) { - mSize[0] *= resizeScale.x(); - mSize[1] *= resizeScale.x(); + if (resizeScale.x < resizeScale.y) { + mSize.x *= resizeScale.x; + mSize.y *= resizeScale.x; } else { - mSize[0] *= resizeScale.y(); - mSize[1] *= resizeScale.y(); + mSize.x *= resizeScale.y; + mSize.y *= resizeScale.y; } - mSize[1] = std::round(mSize[1]); - mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x(); + mSize.x = (mSize.y / textureSize.y) * textureSize.x; + mSize.y = std::round(mSize[1]); } else { // If both components are set, we just stretch. // If no components are set, we don't resize at all. - mSize = mTargetSize == Vector2f::Zero() ? textureSize : mTargetSize; + mSize = mTargetSize == glm::vec2{} ? textureSize : mTargetSize; // If only one component is set, we resize in a way that maintains aspect ratio. - if (!mTargetSize.x() && mTargetSize.y()) { - mSize[1] = std::round(mTargetSize.y()); - mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x(); + if (!mTargetSize.x && mTargetSize.y) { + mSize.y = std::round(mTargetSize.y); + mSize.x = (mSize.y / textureSize.y) * textureSize.x; } - else if (mTargetSize.x() && !mTargetSize.y()) { - mSize[1] = std::round((mTargetSize.x() / textureSize.x()) * textureSize.y()); - mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x(); + else if (mTargetSize.x && !mTargetSize.y) { + mSize.y = std::round((mTargetSize.x / textureSize.x) * textureSize.y); + mSize.x = (mSize.y / textureSize.y) * textureSize.x; } } onSizeChanged(); } -void VideoVlcComponent::render(const Transform4x4f& parentTrans) +void VideoVlcComponent::render(const glm::mat4& parentTrans) { // Set the audio volume. As libVLC is very unreliable we need to make an additional // attempt here in the render loop in addition to the initialization in startVideo(). @@ -179,7 +179,7 @@ void VideoVlcComponent::render(const Transform4x4f& parentTrans) setAudioVolume(); VideoComponent::render(parentTrans); - Transform4x4f trans = parentTrans * getTransform(); + glm::mat4 trans{parentTrans * getTransform()}; GuiComponent::renderChildren(trans); // Check the actual VLC state, i.e. if the video is really playing rather than @@ -213,15 +213,15 @@ void VideoVlcComponent::render(const Transform4x4f& parentTrans) } // clang-format off - vertices[0] = { { 0.0f , 0.0f }, { 0.0f, 0.0f }, color }; - vertices[1] = { { 0.0f , mSize.y() }, { 0.0f, 1.0f }, color }; - vertices[2] = { { mSize.x(), 0.0f }, { 1.0f, 0.0f }, color }; - vertices[3] = { { mSize.x(), mSize.y() }, { 1.0f, 1.0f }, color }; + vertices[0] = {{0.0f , 0.0f }, {0.0f, 0.0f}, color}; + vertices[1] = {{0.0f , mSize.y}, {0.0f, 1.0f}, color}; + vertices[2] = {{mSize.x, 0.0f }, {1.0f, 0.0f}, color}; + vertices[3] = {{mSize.x, mSize.y}, {1.0f, 1.0f}, color}; // clang-format on // Round vertices. for (int i = 0; i < 4; i++) - vertices[i].pos.round(); + vertices[i].pos = glm::round(vertices[i].pos); // Build a texture for the video frame. mTexture->initFromPixels(reinterpret_cast(mContext.surface->pixels), @@ -255,51 +255,49 @@ void VideoVlcComponent::calculateBlackRectangle() // otherwise it will exactly match the video size. The reason to add a black rectangle // behind videos in this second instance is that the scanline rendering will make the // video partially transparent so this may avoid some unforseen issues with some themes. - if (mVideoAreaPos != 0 && mVideoAreaSize != 0) { + if (mVideoAreaPos != glm::vec2{} && mVideoAreaSize != glm::vec2{}) { mVideoRectangleCoords.clear(); if (Settings::getInstance()->getBool("GamelistVideoPillarbox")) { float rectHeight; float rectWidth; // Video is in landscape orientation. - if (mSize.x() > mSize.y()) { + if (mSize.x > mSize.y) { // Checking the Y size should not normally be required as landscape format // should mean the height can't be higher than the max size defined by the // theme. But as the height in mSize is provided by libVLC in integer format // and then scaled, there could be rounding errors that make the video height // slightly higher than allowed. It's only a single pixel or a few pixels, but // it's still visible for some videos. - if (mSize.y() < mVideoAreaSize.y() && mSize.y() / mVideoAreaSize.y() < 0.90) - rectHeight = mVideoAreaSize.y(); + if (mSize.y < mVideoAreaSize.y && mSize.y / mVideoAreaSize.y < 0.90f) + rectHeight = mVideoAreaSize.y; else - rectHeight = mSize.y(); + rectHeight = mSize.y; // Don't add a black border that is too narrow, that's what the 0.85 constant // takes care of. - if (mSize.x() < mVideoAreaSize.x() && mSize.x() / mVideoAreaSize.x() < 0.85) - rectWidth = mVideoAreaSize.x(); + if (mSize.x < mVideoAreaSize.x && mSize.x / mVideoAreaSize.x < 0.85f) + rectWidth = mVideoAreaSize.x; else - rectWidth = mSize.x(); + rectWidth = mSize.x; } // Video is in portrait orientation (or completely square). else { - rectWidth = mVideoAreaSize.x(); - rectHeight = mSize.y(); + rectWidth = mVideoAreaSize.x; + rectHeight = mSize.y; } // Populate the rectangle coordinates to be used in render(). - mVideoRectangleCoords.push_back( - std::round(mVideoAreaPos.x() - rectWidth * mOrigin.x())); - mVideoRectangleCoords.push_back( - std::round(mVideoAreaPos.y() - rectHeight * mOrigin.y())); + mVideoRectangleCoords.push_back(std::round(mVideoAreaPos.x - rectWidth * mOrigin.x)); + mVideoRectangleCoords.push_back(std::round(mVideoAreaPos.y - rectHeight * mOrigin.y)); mVideoRectangleCoords.push_back(std::round(rectWidth)); mVideoRectangleCoords.push_back(std::round(rectHeight)); } // If the option to display pillarboxes is disabled, then make the rectangle equivalent // to the size of the video. else { - mVideoRectangleCoords.push_back(std::round(mPosition.x() - mSize.x() * mOrigin.x())); - mVideoRectangleCoords.push_back(std::round(mPosition.y() - mSize.y() * mOrigin.y())); - mVideoRectangleCoords.push_back(std::round(mSize.x())); - mVideoRectangleCoords.push_back(std::round(mSize.y())); + mVideoRectangleCoords.push_back(std::round(mPosition.x - mSize.x * mOrigin.x)); + mVideoRectangleCoords.push_back(std::round(mPosition.y - mSize.y * mOrigin.y)); + mVideoRectangleCoords.push_back(std::round(mSize.x)); + mVideoRectangleCoords.push_back(std::round(mSize.y)); } } } diff --git a/es-core/src/components/VideoVlcComponent.h b/es-core/src/components/VideoVlcComponent.h index 880852aa8..864060155 100644 --- a/es-core/src/components/VideoVlcComponent.h +++ b/es-core/src/components/VideoVlcComponent.h @@ -53,7 +53,7 @@ private: // Used internally whenever the resizing parameters or texture change. void resize(); - void render(const Transform4x4f& parentTrans) override; + void render(const glm::mat4& parentTrans) override; void calculateBlackRectangle(); void setAudioVolume(); diff --git a/es-core/src/guis/GuiComplexTextEditPopup.cpp b/es-core/src/guis/GuiComplexTextEditPopup.cpp index d649976ba..802f544ee 100644 --- a/es-core/src/guis/GuiComplexTextEditPopup.cpp +++ b/es-core/src/guis/GuiComplexTextEditPopup.cpp @@ -35,7 +35,7 @@ GuiComplexTextEditPopup::GuiComplexTextEditPopup( : GuiComponent(window) , mHelpStyle(helpstyle) , mBackground(window, ":/graphics/frame.svg") - , mGrid(window, Vector2i(1, 5)) + , mGrid(window, glm::ivec2{1, 5}) , mMultiLine(multiLine) , mInitValue(initValue) , mOkCallback(okCallback) @@ -75,12 +75,12 @@ GuiComplexTextEditPopup::GuiComplexTextEditPopup( mButtonGrid = makeButtonGrid(mWindow, buttons); - mGrid.setEntry(mTitle, Vector2i(0, 0), false, true); - mGrid.setEntry(mInfoString1, Vector2i(0, 1), false, true); - mGrid.setEntry(mInfoString2, Vector2i(0, 2), false, false); - mGrid.setEntry(mText, Vector2i(0, 3), true, false, Vector2i(1, 1), + mGrid.setEntry(mTitle, glm::ivec2{0, 0}, false, true); + mGrid.setEntry(mInfoString1, glm::ivec2{0, 1}, false, true); + mGrid.setEntry(mInfoString2, glm::ivec2{0, 2}, false, false); + mGrid.setEntry(mText, glm::ivec2{0, 3}, true, false, glm::ivec2{1, 1}, GridFlags::BORDER_TOP | GridFlags::BORDER_BOTTOM); - mGrid.setEntry(mButtonGrid, Vector2i(0, 4), true, false); + mGrid.setEntry(mButtonGrid, glm::ivec2{0, 4}, true, false); mGrid.setRowHeightPerc(1, 0.15f, true); float textHeight = mText->getFont()->getHeight(); @@ -91,27 +91,27 @@ GuiComplexTextEditPopup::GuiComplexTextEditPopup( // Adjust the width relative to the aspect ratio of the screen to make the GUI look coherent // regardless of screen type. The 1.778 aspect ratio value is the 16:9 reference. float aspectValue = 1.778f / Renderer::getScreenAspectRatio(); - float infoWidth = Math::clamp(0.70f * aspectValue, 0.60f, 0.85f) * Renderer::getScreenWidth(); - float windowWidth = Math::clamp(0.75f * aspectValue, 0.65f, 0.90f) * Renderer::getScreenWidth(); + float infoWidth = glm::clamp(0.70f * aspectValue, 0.60f, 0.85f) * Renderer::getScreenWidth(); + float windowWidth = glm::clamp(0.75f * aspectValue, 0.65f, 0.90f) * Renderer::getScreenWidth(); mText->setSize(0, textHeight); mInfoString2->setSize(infoWidth, mInfoString2->getFont()->getHeight()); - setSize(windowWidth, mTitle->getFont()->getHeight() + textHeight + mButtonGrid->getSize().y() + - mButtonGrid->getSize().y() * 1.85f); - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, - (Renderer::getScreenHeight() - mSize.y()) / 2.0f); + setSize(windowWidth, mTitle->getFont()->getHeight() + textHeight + mButtonGrid->getSize().y + + mButtonGrid->getSize().y * 1.85f); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, + (Renderer::getScreenHeight() - mSize.y) / 2.0f); mText->startEditing(); } void GuiComplexTextEditPopup::onSizeChanged() { - mBackground.fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); - mText->setSize(mSize.x() - 40.0f, mText->getSize().y()); + mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); + mText->setSize(mSize.x - 40.0f, mText->getSize().y); // Update grid. - mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y()); - mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y() / mSize.y()); + mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y); + mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y / mSize.y); mGrid.setSize(mSize); } diff --git a/es-core/src/guis/GuiDetectDevice.cpp b/es-core/src/guis/GuiDetectDevice.cpp index 2cf8d33ab..b2f4b51b0 100644 --- a/es-core/src/guis/GuiDetectDevice.cpp +++ b/es-core/src/guis/GuiDetectDevice.cpp @@ -25,7 +25,7 @@ GuiDetectDevice::GuiDetectDevice(Window* window, , mFirstRun(firstRun) , mForcedConfig(forcedConfig) , mBackground(window, ":/graphics/frame.svg") - , mGrid(window, Vector2i(1, 5)) + , mGrid(window, glm::ivec2{1, 5}) { mHoldingConfig = nullptr; mHoldTime = 0; @@ -38,7 +38,8 @@ GuiDetectDevice::GuiDetectDevice(Window* window, mTitle = std::make_shared(mWindow, firstRun ? "WELCOME" : "CONFIGURE INPUT DEVICE", Font::get(FONT_SIZE_LARGE), 0x555555FF, ALIGN_CENTER); - mGrid.setEntry(mTitle, Vector2i(0, 0), false, true, Vector2i(1, 1), GridFlags::BORDER_BOTTOM); + mGrid.setEntry(mTitle, glm::ivec2{0, 0}, false, true, glm::ivec2{1, 1}, + GridFlags::BORDER_BOTTOM); // Device info. std::stringstream deviceInfo; @@ -54,7 +55,7 @@ GuiDetectDevice::GuiDetectDevice(Window* window, mDeviceInfo = std::make_shared( mWindow, deviceInfo.str(), Font::get(FONT_SIZE_SMALL), 0x999999FF, ALIGN_CENTER); - mGrid.setEntry(mDeviceInfo, Vector2i(0, 1), false, true); + mGrid.setEntry(mDeviceInfo, glm::ivec2{0, 1}, false, true); // Message. if (numDevices > 0) { @@ -68,39 +69,39 @@ GuiDetectDevice::GuiDetectDevice(Window* window, 0x777777FF, ALIGN_CENTER); } - mGrid.setEntry(mMsg1, Vector2i(0, 2), false, true); + mGrid.setEntry(mMsg1, glm::ivec2{0, 2}, false, true); const std::string msg2str = firstRun ? "PRESS ESC TO SKIP (OR F4 TO QUIT AT ANY TIME)" : "PRESS ESC TO CANCEL"; mMsg2 = std::make_shared(mWindow, msg2str, Font::get(FONT_SIZE_SMALL), 0x777777FF, ALIGN_CENTER); - mGrid.setEntry(mMsg2, Vector2i(0, 3), false, true); + mGrid.setEntry(mMsg2, glm::ivec2{0, 3}, false, true); // Currently held device. mDeviceHeld = std::make_shared(mWindow, "", Font::get(FONT_SIZE_MEDIUM), 0xFFFFFFFF, ALIGN_CENTER); - mGrid.setEntry(mDeviceHeld, Vector2i(0, 4), false, true); + mGrid.setEntry(mDeviceHeld, glm::ivec2{0, 4}, false, true); // Adjust the width relative to the aspect ratio of the screen to make the GUI look coherent // regardless of screen type. The 1.778 aspect ratio value is the 16:9 reference. float aspectValue = 1.778f / Renderer::getScreenAspectRatio(); - float width = Math::clamp(0.60f * aspectValue, 0.50f, 0.80f) * Renderer::getScreenWidth(); + float width = glm::clamp(0.60f * aspectValue, 0.50f, 0.80f) * Renderer::getScreenWidth(); setSize(width, Renderer::getScreenHeight() * 0.5f); - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, - (Renderer::getScreenHeight() - mSize.y()) / 2.0f); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, + (Renderer::getScreenHeight() - mSize.y) / 2.0f); } void GuiDetectDevice::onSizeChanged() { - mBackground.fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); // Grid. mGrid.setSize(mSize); - mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y()); + mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y); // mGrid.setRowHeightPerc(1, mDeviceInfo->getFont()->getHeight() / mSize.y()); - mGrid.setRowHeightPerc(2, mMsg1->getFont()->getHeight() / mSize.y()); - mGrid.setRowHeightPerc(3, mMsg2->getFont()->getHeight() / mSize.y()); + mGrid.setRowHeightPerc(2, mMsg1->getFont()->getHeight() / mSize.y); + mGrid.setRowHeightPerc(3, mMsg2->getFont()->getHeight() / mSize.y); // mGrid.setRowHeightPerc(4, mDeviceHeld->getFont()->getHeight() / mSize.y()); } diff --git a/es-core/src/guis/GuiInputConfig.cpp b/es-core/src/guis/GuiInputConfig.cpp index c3c76e692..78c212051 100644 --- a/es-core/src/guis/GuiInputConfig.cpp +++ b/es-core/src/guis/GuiInputConfig.cpp @@ -33,7 +33,7 @@ GuiInputConfig::GuiInputConfig(Window* window, const std::function& okCallback) : GuiComponent(window) , mBackground(window, ":/graphics/frame.svg") - , mGrid(window, Vector2i(1, 7)) + , mGrid(window, glm::ivec2{1, 7}) , mTargetConfig(target) , mHoldingInput(false) { @@ -54,11 +54,11 @@ GuiInputConfig::GuiInputConfig(Window* window, addChild(&mGrid); // 0 is a spacer row. - mGrid.setEntry(std::make_shared(mWindow), Vector2i(0, 0), false); + mGrid.setEntry(std::make_shared(mWindow), glm::ivec2{0, 0}, false); mTitle = std::make_shared(mWindow, "CONFIGURING", Font::get(FONT_SIZE_LARGE), 0x555555FF, ALIGN_CENTER); - mGrid.setEntry(mTitle, Vector2i(0, 1), false, true); + mGrid.setEntry(mTitle, glm::ivec2{0, 1}, false, true); std::stringstream ss; if (target->getDeviceId() == DEVICE_KEYBOARD) @@ -70,7 +70,7 @@ GuiInputConfig::GuiInputConfig(Window* window, mSubtitle1 = std::make_shared(mWindow, Utils::String::toUpper(ss.str()), Font::get(FONT_SIZE_MEDIUM), 0x555555FF, ALIGN_CENTER); - mGrid.setEntry(mSubtitle1, Vector2i(0, 2), false, true); + mGrid.setEntry(mSubtitle1, glm::ivec2{0, 2}, false, true); mSubtitle2 = std::make_shared(mWindow, "HOLD ANY BUTTON 1 SECOND TO SKIP", @@ -78,11 +78,11 @@ GuiInputConfig::GuiInputConfig(Window* window, // The opacity will be set to visible for any row that is skippable. mSubtitle2->setOpacity(0); - mGrid.setEntry(mSubtitle2, Vector2i(0, 3), false, true); + mGrid.setEntry(mSubtitle2, glm::ivec2{0, 3}, false, true); // 4 is a spacer row. mList = std::make_shared(mWindow); - mGrid.setEntry(mList, Vector2i(0, 5), true, true); + mGrid.setEntry(mList, glm::ivec2{0, 5}, true, true); for (int i = 0; i < inputCount; i++) { ComponentListRow row; @@ -184,16 +184,16 @@ GuiInputConfig::GuiInputConfig(Window* window, [this, okFunction] { okFunction(); })); mButtonGrid = makeButtonGrid(mWindow, buttons); - mGrid.setEntry(mButtonGrid, Vector2i(0, 6), true, false); + mGrid.setEntry(mButtonGrid, glm::ivec2{0, 6}, true, false); // Adjust the width relative to the aspect ratio of the screen to make the GUI look coherent // regardless of screen type. The 1.778 aspect ratio value is the 16:9 reference. float aspectValue = 1.778f / Renderer::getScreenAspectRatio(); - float width = Math::clamp(0.60f * aspectValue, 0.50f, 0.80f) * Renderer::getScreenWidth(); + float width = glm::clamp(0.60f * aspectValue, 0.50f, 0.80f) * Renderer::getScreenWidth(); setSize(width, Renderer::getScreenHeight() * 0.75f); - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, - (Renderer::getScreenHeight() - mSize.y()) / 2.0f); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, + (Renderer::getScreenHeight() - mSize.y) / 2.0f); } void GuiInputConfig::populateConfigList() @@ -201,67 +201,67 @@ void GuiInputConfig::populateConfigList() std::string controllerType = Settings::getInstance()->getString("InputControllerType"); // clang-format off - sGuiInputConfigList[0] = { "Up", false, "D-PAD UP", ":/help/dpad_up.svg" }; - sGuiInputConfigList[1] = { "Down", false, "D-PAD DOWN", ":/help/dpad_down.svg" }; - sGuiInputConfigList[2] = { "Left", false, "D-PAD LEFT", ":/help/dpad_left.svg" }; - sGuiInputConfigList[3] = { "Right", false, "D-PAD RIGHT", ":/help/dpad_right.svg" }; + sGuiInputConfigList[0] = {"Up", false, "D-PAD UP", ":/help/dpad_up.svg"}; + sGuiInputConfigList[1] = {"Down", false, "D-PAD DOWN", ":/help/dpad_down.svg"}; + sGuiInputConfigList[2] = {"Left", false, "D-PAD LEFT", ":/help/dpad_left.svg"}; + sGuiInputConfigList[3] = {"Right", false, "D-PAD RIGHT", ":/help/dpad_right.svg"}; if (controllerType == "snes") { - sGuiInputConfigList[4] = { "Back", false, "SELECT", ":/help/button_back_SNES.svg" }; - sGuiInputConfigList[5] = { "Start", false, "START", ":/help/button_start_SNES.svg" }; - sGuiInputConfigList[6] = { "A", false, "B", ":/help/mbuttons_a_SNES.svg" }; - sGuiInputConfigList[7] = { "B", false, "A", ":/help/mbuttons_b_SNES.svg" }; - sGuiInputConfigList[8] = { "X", true, "Y", ":/help/mbuttons_x_SNES.svg" }; - sGuiInputConfigList[9] = { "Y", true, "X", ":/help/mbuttons_y_SNES.svg" }; + sGuiInputConfigList[4] = {"Back", false, "SELECT", ":/help/button_back_SNES.svg"}; + sGuiInputConfigList[5] = {"Start", false, "START", ":/help/button_start_SNES.svg"}; + sGuiInputConfigList[6] = {"A", false, "B", ":/help/mbuttons_a_SNES.svg"}; + sGuiInputConfigList[7] = {"B", false, "A", ":/help/mbuttons_b_SNES.svg"}; + sGuiInputConfigList[8] = {"X", true, "Y", ":/help/mbuttons_x_SNES.svg"}; + sGuiInputConfigList[9] = {"Y", true, "X", ":/help/mbuttons_y_SNES.svg"}; } else if (controllerType == "ps4") { - sGuiInputConfigList[4] = { "Back", false, "SHARE", ":/help/button_back_PS4.svg" }; - sGuiInputConfigList[5] = { "Start", false, "OPTIONS", ":/help/button_start_PS4.svg" }; - sGuiInputConfigList[6] = { "A", false, "CROSS", ":/help/mbuttons_a_PS.svg" }; - sGuiInputConfigList[7] = { "B", false, "CIRCLE", ":/help/mbuttons_b_PS.svg" }; - sGuiInputConfigList[8] = { "X", true, "SQUARE", ":/help/mbuttons_x_PS.svg" }; - sGuiInputConfigList[9] = { "Y", true, "TRIANGLE", ":/help/mbuttons_y_PS.svg" }; + sGuiInputConfigList[4] = {"Back", false, "SHARE", ":/help/button_back_PS4.svg"}; + sGuiInputConfigList[5] = {"Start", false, "OPTIONS", ":/help/button_start_PS4.svg"}; + sGuiInputConfigList[6] = {"A", false, "CROSS", ":/help/mbuttons_a_PS.svg"}; + sGuiInputConfigList[7] = {"B", false, "CIRCLE", ":/help/mbuttons_b_PS.svg"}; + sGuiInputConfigList[8] = {"X", true, "SQUARE", ":/help/mbuttons_x_PS.svg"}; + sGuiInputConfigList[9] = {"Y", true, "TRIANGLE", ":/help/mbuttons_y_PS.svg"}; } else if (controllerType == "ps5") { - sGuiInputConfigList[4] = { "Back", false, "CREATE", ":/help/button_back_PS5.svg" }; - sGuiInputConfigList[5] = { "Start", false, "OPTIONS", ":/help/button_start_PS5.svg" }; - sGuiInputConfigList[6] = { "A", false, "CROSS", ":/help/mbuttons_a_PS.svg" }; - sGuiInputConfigList[7] = { "B", false, "CIRCLE", ":/help/mbuttons_b_PS.svg" }; - sGuiInputConfigList[8] = { "X", true, "SQUARE", ":/help/mbuttons_x_PS.svg" }; - sGuiInputConfigList[9] = { "Y", true, "TRIANGLE", ":/help/mbuttons_y_PS.svg" }; + sGuiInputConfigList[4] = {"Back", false, "CREATE", ":/help/button_back_PS5.svg"}; + sGuiInputConfigList[5] = {"Start", false, "OPTIONS", ":/help/button_start_PS5.svg"}; + sGuiInputConfigList[6] = {"A", false, "CROSS", ":/help/mbuttons_a_PS.svg"}; + sGuiInputConfigList[7] = {"B", false, "CIRCLE", ":/help/mbuttons_b_PS.svg"}; + sGuiInputConfigList[8] = {"X", true, "SQUARE", ":/help/mbuttons_x_PS.svg"}; + sGuiInputConfigList[9] = {"Y", true, "TRIANGLE", ":/help/mbuttons_y_PS.svg"}; } else if (controllerType == "xbox360") { - sGuiInputConfigList[4] = { "Back", false, "BACK", ":/help/button_back_XBOX360.svg" }; - sGuiInputConfigList[5] = { "Start", false, "START", ":/help/button_start_XBOX360.svg" }; - sGuiInputConfigList[6] = { "A", false, "A", ":/help/mbuttons_a_XBOX.svg" }; - sGuiInputConfigList[7] = { "B", false, "B", ":/help/mbuttons_b_XBOX.svg" }; - sGuiInputConfigList[8] = { "X", true, "X", ":/help/mbuttons_x_XBOX.svg" }; - sGuiInputConfigList[9] = { "Y", true, "Y", ":/help/mbuttons_y_XBOX.svg" }; + sGuiInputConfigList[4] = {"Back", false, "BACK", ":/help/button_back_XBOX360.svg"}; + sGuiInputConfigList[5] = {"Start", false, "START", ":/help/button_start_XBOX360.svg"}; + sGuiInputConfigList[6] = {"A", false, "A", ":/help/mbuttons_a_XBOX.svg"}; + sGuiInputConfigList[7] = {"B", false, "B", ":/help/mbuttons_b_XBOX.svg"}; + sGuiInputConfigList[8] = {"X", true, "X", ":/help/mbuttons_x_XBOX.svg"}; + sGuiInputConfigList[9] = {"Y", true, "Y", ":/help/mbuttons_y_XBOX.svg"}; } else { // Xbox One and later. - sGuiInputConfigList[4] = { "Back", false, "VIEW", ":/help/button_back_XBOX.svg" }; - sGuiInputConfigList[5] = { "Start", false, "MENU", ":/help/button_start_XBOX.svg" }; - sGuiInputConfigList[6] = { "A", false, "A", ":/help/mbuttons_a_XBOX.svg" }; - sGuiInputConfigList[7] = { "B", false, "B", ":/help/mbuttons_b_XBOX.svg" }; - sGuiInputConfigList[8] = { "X", true, "X", ":/help/mbuttons_x_XBOX.svg" }; - sGuiInputConfigList[9] = { "Y", true, "Y", ":/help/mbuttons_y_XBOX.svg" }; + sGuiInputConfigList[4] = {"Back", false, "VIEW", ":/help/button_back_XBOX.svg"}; + sGuiInputConfigList[5] = {"Start", false, "MENU", ":/help/button_start_XBOX.svg"}; + sGuiInputConfigList[6] = {"A", false, "A", ":/help/mbuttons_a_XBOX.svg"}; + sGuiInputConfigList[7] = {"B", false, "B", ":/help/mbuttons_b_XBOX.svg"}; + sGuiInputConfigList[8] = {"X", true, "X", ":/help/mbuttons_x_XBOX.svg"}; + sGuiInputConfigList[9] = {"Y", true, "Y", ":/help/mbuttons_y_XBOX.svg"}; } - sGuiInputConfigList[10] = { "LeftShoulder", true, "LEFT SHOULDER", ":/help/button_l.svg" }; - sGuiInputConfigList[11] = { "RightShoulder", true, "RIGHT SHOULDER", ":/help/button_r.svg" }; - sGuiInputConfigList[12] = { "LeftTrigger", true, "LEFT TRIGGER", ":/help/button_lt.svg" }; - sGuiInputConfigList[13] = { "RightTrigger", true, "RIGHT TRIGGER", ":/help/button_rt.svg" }; - sGuiInputConfigList[14] = { "LeftThumbstickUp", true, "LEFT THUMBSTICK UP", ":/help/thumbstick_up.svg" }; - sGuiInputConfigList[15] = { "LeftThumbstickDown", true, "LEFT THUMBSTICK DOWN", ":/help/thumbstick_down.svg" }; - sGuiInputConfigList[16] = { "LeftThumbstickLeft", true, "LEFT THUMBSTICK LEFT", ":/help/thumbstick_left.svg" }; - sGuiInputConfigList[17] = { "LeftThumbstickRight", true, "LEFT THUMBSTICK RIGHT", ":/help/thumbstick_right.svg" }; - sGuiInputConfigList[18] = { "LeftThumbstickClick", true, "LEFT THUMBSTICK CLICK", ":/help/thumbstick_click.svg" }; - sGuiInputConfigList[19] = { "RightThumbstickUp", true, "RIGHT THUMBSTICK UP", ":/help/thumbstick_up.svg" }; - sGuiInputConfigList[20] = { "RightThumbstickDown", true, "RIGHT THUMBSTICK DOWN", ":/help/thumbstick_down.svg" }; - sGuiInputConfigList[21] = { "RightThumbstickLeft", true, "RIGHT THUMBSTICK LEFT", ":/help/thumbstick_left.svg" }; - sGuiInputConfigList[22] = { "RightThumbstickRight", true, "RIGHT THUMBSTICK RIGHT", ":/help/thumbstick_right.svg" }; - sGuiInputConfigList[23] = { "RightThumbstickClick", true, "RIGHT THUMBSTICK CLICK", ":/help/thumbstick_click.svg" }; + sGuiInputConfigList[10] = {"LeftShoulder", true, "LEFT SHOULDER", ":/help/button_l.svg"}; + sGuiInputConfigList[11] = {"RightShoulder", true, "RIGHT SHOULDER", ":/help/button_r.svg"}; + sGuiInputConfigList[12] = {"LeftTrigger", true, "LEFT TRIGGER", ":/help/button_lt.svg"}; + sGuiInputConfigList[13] = {"RightTrigger", true, "RIGHT TRIGGER", ":/help/button_rt.svg"}; + sGuiInputConfigList[14] = {"LeftThumbstickUp", true, "LEFT THUMBSTICK UP", ":/help/thumbstick_up.svg"}; + sGuiInputConfigList[15] = {"LeftThumbstickDown", true, "LEFT THUMBSTICK DOWN", ":/help/thumbstick_down.svg"}; + sGuiInputConfigList[16] = {"LeftThumbstickLeft", true, "LEFT THUMBSTICK LEFT", ":/help/thumbstick_left.svg"}; + sGuiInputConfigList[17] = {"LeftThumbstickRight", true, "LEFT THUMBSTICK RIGHT", ":/help/thumbstick_right.svg"}; + sGuiInputConfigList[18] = {"LeftThumbstickClick", true, "LEFT THUMBSTICK CLICK", ":/help/thumbstick_click.svg"}; + sGuiInputConfigList[19] = {"RightThumbstickUp", true, "RIGHT THUMBSTICK UP", ":/help/thumbstick_up.svg"}; + sGuiInputConfigList[20] = {"RightThumbstickDown", true, "RIGHT THUMBSTICK DOWN", ":/help/thumbstick_down.svg"}; + sGuiInputConfigList[21] = {"RightThumbstickLeft", true, "RIGHT THUMBSTICK LEFT", ":/help/thumbstick_left.svg"}; + sGuiInputConfigList[22] = {"RightThumbstickRight", true, "RIGHT THUMBSTICK RIGHT", ":/help/thumbstick_right.svg"}; + sGuiInputConfigList[23] = {"RightThumbstickClick", true, "RIGHT THUMBSTICK CLICK", ":/help/thumbstick_click.svg"}; // clang-format on } @@ -293,16 +293,16 @@ void GuiInputConfig::update(int deltaTime) void GuiInputConfig::onSizeChanged() { - mBackground.fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); // Update grid. mGrid.setSize(mSize); - mGrid.setRowHeightPerc(1, mTitle->getFont()->getHeight() * 0.75f / mSize.y()); - mGrid.setRowHeightPerc(2, mSubtitle1->getFont()->getHeight() / mSize.y()); - mGrid.setRowHeightPerc(3, mSubtitle2->getFont()->getHeight() / mSize.y()); - mGrid.setRowHeightPerc(5, (mList->getRowHeight(0) * 5 + 2) / mSize.y()); - mGrid.setRowHeightPerc(6, mButtonGrid->getSize().y() / mSize.y()); + mGrid.setRowHeightPerc(1, mTitle->getFont()->getHeight() * 0.75f / mSize.y); + mGrid.setRowHeightPerc(2, mSubtitle1->getFont()->getHeight() / mSize.y); + mGrid.setRowHeightPerc(3, mSubtitle2->getFont()->getHeight() / mSize.y); + mGrid.setRowHeightPerc(5, (mList->getRowHeight(0) * 5.0f + 2.0f) / mSize.y); + mGrid.setRowHeightPerc(6, mButtonGrid->getSize().y / mSize.y); } void GuiInputConfig::rowDone() @@ -313,7 +313,7 @@ void GuiInputConfig::rowDone() // At bottom of list, we're done. mConfiguringAll = false; mConfiguringRow = false; - mGrid.moveCursor(Vector2i(0, 1)); + mGrid.moveCursor(glm::ivec2{0, 1}); } else { // On another row. diff --git a/es-core/src/guis/GuiMsgBox.cpp b/es-core/src/guis/GuiMsgBox.cpp index 9006fec4e..22261cfc4 100644 --- a/es-core/src/guis/GuiMsgBox.cpp +++ b/es-core/src/guis/GuiMsgBox.cpp @@ -12,7 +12,7 @@ #include "components/ButtonComponent.h" #include "components/MenuComponent.h" -#define HORIZONTAL_PADDING_PX 20 +#define HORIZONTAL_PADDING_PX 20.0f GuiMsgBox::GuiMsgBox(Window* window, const HelpStyle& helpstyle, @@ -28,7 +28,7 @@ GuiMsgBox::GuiMsgBox(Window* window, : GuiComponent(window) , mHelpStyle(helpstyle) , mBackground(window, ":/graphics/frame.svg") - , mGrid(window, Vector2i(1, 2)) + , mGrid(window, glm::ivec2{1, 2}) , mDisableBackButton(disableBackButton) , mDeleteOnButtonPress(deleteOnButtonPress) { @@ -37,13 +37,13 @@ GuiMsgBox::GuiMsgBox(Window* window, float aspectValue = 1.778f / Renderer::getScreenAspectRatio(); float width = - floorf(Math::clamp(0.60f * aspectValue, 0.60f, 0.80f) * Renderer::getScreenWidth()); + floorf(glm::clamp(0.60f * aspectValue, 0.60f, 0.80f) * Renderer::getScreenWidth()); float minWidth = - floorf(Math::clamp(0.30f * aspectValue, 0.10f, 0.50f) * Renderer::getScreenWidth()); + floorf(glm::clamp(0.30f * aspectValue, 0.10f, 0.50f) * Renderer::getScreenWidth()); mMsg = std::make_shared(mWindow, text, Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_CENTER); - mGrid.setEntry(mMsg, Vector2i(0, 0), false, false); + mGrid.setEntry(mMsg, glm::ivec2{0, 0}, false, false); // Create the buttons. mButtons.push_back(std::make_shared( @@ -71,28 +71,29 @@ GuiMsgBox::GuiMsgBox(Window* window, // Put the buttons into a ComponentGrid. mButtonGrid = makeButtonGrid(mWindow, mButtons); - mGrid.setEntry(mButtonGrid, Vector2i(0, 1), true, false, Vector2i(1, 1), GridFlags::BORDER_TOP); + mGrid.setEntry(mButtonGrid, glm::ivec2{0, 1}, true, false, glm::ivec2{1, 1}, + GridFlags::BORDER_TOP); // Decide final width. - if (mMsg->getSize().x() < width && mButtonGrid->getSize().x() < width) { + if (mMsg->getSize().x < width && mButtonGrid->getSize().x < width) { // mMsg and buttons are narrower than width. - width = std::max(mButtonGrid->getSize().x(), mMsg->getSize().x()); + width = std::max(mButtonGrid->getSize().x, mMsg->getSize().x); width = std::max(width, minWidth); } - else if (mButtonGrid->getSize().x() > width) { - width = mButtonGrid->getSize().x(); + else if (mButtonGrid->getSize().x > width) { + width = mButtonGrid->getSize().x; } // Now that we know width, we can find height. - mMsg->setSize(width, 0); // mMsg->getSize.y() now returns the proper length. + mMsg->setSize(width, 0.0f); // mMsg->getSize.y() now returns the proper length. const float msgHeight = - std::max(Font::get(FONT_SIZE_LARGE)->getHeight(), mMsg->getSize().y() * 1.225f); - setSize(width + HORIZONTAL_PADDING_PX * 2 * Renderer::getScreenWidthModifier(), - msgHeight + mButtonGrid->getSize().y()); + std::max(Font::get(FONT_SIZE_LARGE)->getHeight(), mMsg->getSize().y * 1.225f); + setSize(width + HORIZONTAL_PADDING_PX * 2.0f * Renderer::getScreenWidthModifier(), + msgHeight + mButtonGrid->getSize().y); // Center for good measure. - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, - (Renderer::getScreenHeight() - mSize.y()) / 2.0f); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, + (Renderer::getScreenHeight() - mSize.y) / 2.0f); addChild(&mBackground); addChild(&mGrid); @@ -109,25 +110,25 @@ void GuiMsgBox::changeText(const std::string& newText) float aspectValue = 1.778f / Renderer::getScreenAspectRatio(); float width = - floorf(Math::clamp(0.60f * aspectValue, 0.60f, 0.80f) * Renderer::getScreenWidth()); + floorf(glm::clamp(0.60f * aspectValue, 0.60f, 0.80f) * Renderer::getScreenWidth()); float minWidth = Renderer::getScreenWidth() * 0.3f; // Decide final width. - if (mMsg->getSize().x() < width && mButtonGrid->getSize().x() < width) { + if (mMsg->getSize().x < width && mButtonGrid->getSize().x < width) { // mMsg and buttons are narrower than width. - width = std::max(mButtonGrid->getSize().x(), mMsg->getSize().x()); + width = std::max(mButtonGrid->getSize().x, mMsg->getSize().x); width = std::max(width, minWidth); } - else if (mButtonGrid->getSize().x() > mSize.x()) { - width = mButtonGrid->getSize().x(); + else if (mButtonGrid->getSize().x > mSize.x) { + width = mButtonGrid->getSize().x; } // Now that we know width, we can find height. mMsg->setSize(width, 0); // mMsg->getSize.y() now returns the proper length. const float msgHeight = - std::max(Font::get(FONT_SIZE_LARGE)->getHeight(), mMsg->getSize().y() * 1.225f); - setSize(width + HORIZONTAL_PADDING_PX * 2 * Renderer::getScreenWidthModifier(), - msgHeight + mButtonGrid->getSize().y()); + std::max(Font::get(FONT_SIZE_LARGE)->getHeight(), mMsg->getSize().y * 1.225f); + setSize(width + HORIZONTAL_PADDING_PX * 2.0f * Renderer::getScreenWidthModifier(), + msgHeight + mButtonGrid->getSize().y); } bool GuiMsgBox::input(InputConfig* config, Input input) @@ -153,14 +154,14 @@ bool GuiMsgBox::input(InputConfig* config, Input input) void GuiMsgBox::onSizeChanged() { mGrid.setSize(mSize); - mGrid.setRowHeightPerc(1, mButtonGrid->getSize().y() / mSize.y()); + mGrid.setRowHeightPerc(1, mButtonGrid->getSize().y / mSize.y); // Update messagebox size. - mMsg->setSize(mSize.x() - HORIZONTAL_PADDING_PX * 2 * Renderer::getScreenWidthModifier(), + mMsg->setSize(mSize.x - HORIZONTAL_PADDING_PX * 2.0f * Renderer::getScreenWidthModifier(), mGrid.getRowHeight(0)); mGrid.onSizeChanged(); - mBackground.fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); } void GuiMsgBox::deleteMeAndCall(const std::function& func) diff --git a/es-core/src/guis/GuiTextEditPopup.cpp b/es-core/src/guis/GuiTextEditPopup.cpp index 27fe9eb1d..d5f832a7c 100644 --- a/es-core/src/guis/GuiTextEditPopup.cpp +++ b/es-core/src/guis/GuiTextEditPopup.cpp @@ -25,7 +25,7 @@ GuiTextEditPopup::GuiTextEditPopup(Window* window, : GuiComponent(window) , mHelpStyle(helpstyle) , mBackground(window, ":/graphics/frame.svg") - , mGrid(window, Vector2i(1, 3)) + , mGrid(window, glm::ivec2{1, 3}) , mMultiLine(multiLine) , mInitValue(initValue) , mOkCallback(okCallback) @@ -53,10 +53,10 @@ GuiTextEditPopup::GuiTextEditPopup(Window* window, mButtonGrid = makeButtonGrid(mWindow, buttons); - mGrid.setEntry(mTitle, Vector2i(0, 0), false, true); - mGrid.setEntry(mText, Vector2i(0, 1), true, false, Vector2i(1, 1), + mGrid.setEntry(mTitle, glm::ivec2{0, 0}, false, true); + mGrid.setEntry(mText, glm::ivec2{0, 1}, true, false, glm::ivec2{1, 1}, GridFlags::BORDER_TOP | GridFlags::BORDER_BOTTOM); - mGrid.setEntry(mButtonGrid, Vector2i(0, 2), true, false); + mGrid.setEntry(mButtonGrid, glm::ivec2{0, 2}, true, false); float textHeight = mText->getFont()->getHeight(); @@ -67,24 +67,24 @@ GuiTextEditPopup::GuiTextEditPopup(Window* window, // Adjust the width relative to the aspect ratio of the screen to make the GUI look coherent // regardless of screen type. The 1.778 aspect ratio value is the 16:9 reference. float aspectValue = 1.778f / Renderer::getScreenAspectRatio(); - float width = Math::clamp(0.50f * aspectValue, 0.40f, 0.70f) * Renderer::getScreenWidth(); + float width = glm::clamp(0.50f * aspectValue, 0.40f, 0.70f) * Renderer::getScreenWidth(); - setSize(width, mTitle->getFont()->getHeight() + textHeight + mButtonGrid->getSize().y() + - mButtonGrid->getSize().y() / 2.0f); - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, - (Renderer::getScreenHeight() - mSize.y()) / 2.0f); + setSize(width, mTitle->getFont()->getHeight() + textHeight + mButtonGrid->getSize().y + + mButtonGrid->getSize().y / 2.0f); + setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, + (Renderer::getScreenHeight() - mSize.y) / 2.0f); mText->startEditing(); } void GuiTextEditPopup::onSizeChanged() { - mBackground.fitTo(mSize, Vector3f::Zero(), Vector2f(-32.0f, -32.0f)); + mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); - mText->setSize(mSize.x() - 40, mText->getSize().y()); + mText->setSize(mSize.x - 40.0f, mText->getSize().y); // Update grid. - mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y()); - mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y() / mSize.y()); + mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y); + mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y / mSize.y); mGrid.setSize(mSize); } diff --git a/es-core/src/math/Misc.cpp b/es-core/src/math/Misc.cpp deleted file mode 100644 index 6e14e0e10..000000000 --- a/es-core/src/math/Misc.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Misc.cpp -// -// Miscellaneous math functions. -// - -#include "math/Misc.h" - -namespace Math -{ - float lerp(const float _start, const float _end, const float _fraction) - { - return (_start + ((_end - _start) * clamp(_fraction, 0.0f, 1.0f))); - } - - float smoothStep(const float _left, const float _right, const float _x) - { - const float x = clamp((_x - _left) / (_right - _left), 0.0f, 1.0f); - return x * x * (3 - (2 * x)); - } - - float smootherStep(const float _left, const float _right, const float _x) - { - const float x = clamp((_x - _left) / (_right - _left), 0.0f, 1.0f); - return x * x * x * (x * ((x * 6) - 15) + 10); - } - - namespace Scroll - { - float bounce(const float _delayTime, - const float _scrollTime, - const float _currentTime, - const float _scrollLength) - { - if (_currentTime < _delayTime) { - // Wait. - return 0; - } - else if (_currentTime < (_delayTime + _scrollTime)) { - // Lerp from 0 to scrollLength. - const float fraction = (_currentTime - _delayTime) / _scrollTime; - return lerp(0.0f, _scrollLength, smootherStep(0, 1, fraction)); - } - else if (_currentTime < (_delayTime + _scrollTime + _delayTime)) { - // Wait some more. - return _scrollLength; - } - else if (_currentTime < (_delayTime + _scrollTime + _delayTime + _scrollTime)) { - // Lerp back from scrollLength to 0. - const float fraction = - (_currentTime - _delayTime - _scrollTime - _delayTime) / _scrollTime; - return lerp(_scrollLength, 0.0f, smootherStep(0, 1, fraction)); - } - // And back to waiting. - return 0; - } - - float loop(const float _delayTime, - const float _scrollTime, - const float _currentTime, - const float _scrollLength) - { - if (_currentTime < _delayTime) { - // Wait. - return 0; - } - else if (_currentTime < (_delayTime + _scrollTime)) { - // Lerp from 0 to scrollLength. - const float fraction = (_currentTime - _delayTime) / _scrollTime; - return lerp(0.0f, _scrollLength, fraction); - } - - // And back to waiting. - return 0; - - } // Math::Scroll::loop - - } // namespace Scroll - -} // namespace Math diff --git a/es-core/src/math/Misc.h b/es-core/src/math/Misc.h deleted file mode 100644 index e3e85ba91..000000000 --- a/es-core/src/math/Misc.h +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Misc.h -// -// Miscellaneous math functions. -// - -#ifndef ES_CORE_MATH_MISC_H -#define ES_CORE_MATH_MISC_H - -#include - -#define ES_PI (3.1415926535897932384626433832795028841971693993751058209749445923) -#define ES_RAD_TO_DEG(_x) ((_x) * (180.0 / ES_PI)) -#define ES_DEG_TO_RAD(_x) ((_x) * (ES_PI / 180.0)) - -namespace Math -{ - // When moving to the C++20 standard these functions are no longer required. - template T const& clamp(const T& _num, const T& _min, const T& _max) - { - return std::max(std::min(_num, _max), _min); - } - float lerp(const float _start, const float _end, const float _fraction); - - float smoothStep(const float _left, const float _right, const float _x); - float smootherStep(const float _left, const float _right, const float _x); - - namespace Scroll - { - float bounce(const float _delayTime, - const float _scrollTime, - const float _currentTime, - const float _scrollLength); - float loop(const float _delayTime, - const float _scrollTime, - const float _currentTime, - const float _scrollLength); - } // namespace Scroll - -} // namespace Math - -#endif // ES_CORE_MATH_MISC_H diff --git a/es-core/src/math/Transform4x4f.cpp b/es-core/src/math/Transform4x4f.cpp deleted file mode 100644 index 5d565a79d..000000000 --- a/es-core/src/math/Transform4x4f.cpp +++ /dev/null @@ -1,325 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Transform4x4f.cpp -// -// 4x4 matrix functions. -// - -#include "math/Transform4x4f.h" - -#include - -// clang-format off -const Transform4x4f Transform4x4f::operator*(const Transform4x4f& _other) const -{ - const float* tm = reinterpret_cast(this); - const float* om = reinterpret_cast(&_other); - - return - { - { - tm[ 0] * om[ 0] + tm[ 4] * om[ 1] + tm[ 8] * om[ 2], - tm[ 1] * om[ 0] + tm[ 5] * om[ 1] + tm[ 9] * om[ 2], - tm[ 2] * om[ 0] + tm[ 6] * om[ 1] + tm[10] * om[ 2], - 0 - }, - { - tm[ 0] * om[ 4] + tm[ 4] * om[ 5] + tm[ 8] * om[ 6], - tm[ 1] * om[ 4] + tm[ 5] * om[ 5] + tm[ 9] * om[ 6], - tm[ 2] * om[ 4] + tm[ 6] * om[ 5] + tm[10] * om[ 6], - 0 - }, - { - tm[ 0] * om[ 8] + tm[ 4] * om[ 9] + tm[ 8] * om[10], - tm[ 1] * om[ 8] + tm[ 5] * om[ 9] + tm[ 9] * om[10], - tm[ 2] * om[ 8] + tm[ 6] * om[ 9] + tm[10] * om[10], - 0 - }, - { - tm[ 0] * om[12] + tm[ 4] * om[13] + tm[ 8] * om[14] + tm[12], - tm[ 1] * om[12] + tm[ 5] * om[13] + tm[ 9] * om[14] + tm[13], - tm[ 2] * om[12] + tm[ 6] * om[13] + tm[10] * om[14] + tm[14], - 1 - } - }; -} - -const Vector3f Transform4x4f::operator*(const Vector3f& _other) const -{ - const float* tm = reinterpret_cast(this); - const float* ov = reinterpret_cast(&_other); - - return - { - tm[ 0] * ov[0] + tm[ 4] * ov[1] + tm[ 8] * ov[2] + tm[12], - tm[ 1] * ov[0] + tm[ 5] * ov[1] + tm[ 9] * ov[2] + tm[13], - tm[ 2] * ov[0] + tm[ 6] * ov[1] + tm[10] * ov[2] + tm[14] - }; -} - -Transform4x4f& Transform4x4f::orthoProjection( - float _left, - float _right, - float _bottom, - float _top, - float _near, - float _far) -{ - float* tm = reinterpret_cast(this); - - const float o[6] = { 2 / (_right - _left), - 2 / (_top - _bottom), - -2 / (_far - _near), - -(_right + _left) / (_right - _left), - -(_top + _bottom) / (_top - _bottom), - -(_far + _near) / (_far - _near) }; - const float temp[12] = { tm[ 0] * o[0], - tm[ 1] * o[0], - tm[ 2] * o[0], - tm[ 4] * o[1], - tm[ 5] * o[1], - tm[ 6] * o[1], - tm[ 8] * o[2], - tm[ 9] * o[2], - tm[10] * o[2], - tm[ 0] * o[3] + tm[ 4] * o[4] + tm[ 8] * o[5] + tm[12], - tm[ 1] * o[3] + tm[ 5] * o[4] + tm[ 9] * o[5] + tm[13], - tm[ 2] * o[3] + tm[ 6] * o[4] + tm[10] * o[5] + tm[14] }; - - tm[ 0] = temp[ 0]; - tm[ 1] = temp[ 1]; - tm[ 2] = temp[ 2]; - tm[ 4] = temp[ 3]; - tm[ 5] = temp[ 4]; - tm[ 6] = temp[ 5]; - tm[ 8] = temp[ 6]; - tm[ 9] = temp[ 7]; - tm[10] = temp[ 8]; - tm[12] = temp[ 9]; - tm[13] = temp[10]; - tm[14] = temp[11]; - - return *this; -} - -Transform4x4f& Transform4x4f::invert(const Transform4x4f& _other) -{ - float* tm = reinterpret_cast(this); - const float* om = reinterpret_cast(&_other); - - // Full invert - // tm[ 0] = ((om[ 5] * (om[10] * om[15] - om[11] * om[14])) - (om[ 9] * (om[ 6] * om[15] - om[ 7] * om[14])) + (om[13] * (om[ 6] * om[11] - om[ 7] * om[10]))); - // tm[ 1] = -((om[ 1] * (om[10] * om[15] - om[11] * om[14])) - (om[ 9] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[13] * (om[ 2] * om[11] - om[ 3] * om[10]))); - // tm[ 2] = ((om[ 1] * (om[ 6] * om[15] - om[ 7] * om[14])) - (om[ 5] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[13] * (om[ 2] * om[ 7] - om[ 3] * om[ 6]))); - // tm[ 3] = -((om[ 1] * (om[ 6] * om[11] - om[ 7] * om[10])) - (om[ 5] * (om[ 2] * om[11] - om[ 3] * om[10])) + (om[ 9] * (om[ 2] * om[ 7] - om[ 3] * om[ 6]))); - // tm[ 4] = -((om[ 4] * (om[10] * om[15] - om[11] * om[14])) - (om[ 8] * (om[ 6] * om[15] - om[ 7] * om[14])) + (om[12] * (om[ 6] * om[11] - om[ 7] * om[10]))); - // tm[ 5] = ((om[ 0] * (om[10] * om[15] - om[11] * om[14])) - (om[ 8] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[12] * (om[ 2] * om[11] - om[ 3] * om[10]))); - // tm[ 6] = -((om[ 0] * (om[ 6] * om[15] - om[ 7] * om[14])) - (om[ 4] * (om[ 2] * om[15] - om[ 3] * om[14])) + (om[12] * (om[ 2] * om[ 7] - om[ 3] * om[ 6]))); - // tm[ 7] = ((om[ 0] * (om[ 6] * om[11] - om[ 7] * om[10])) - (om[ 4] * (om[ 2] * om[11] - om[ 3] * om[10])) + (om[ 8] * (om[ 2] * om[ 7] - om[ 3] * om[ 6]))); - // tm[ 8] = ((om[ 4] * (om[ 9] * om[15] - om[11] * om[13])) - (om[ 8] * (om[ 5] * om[15] - om[ 7] * om[13])) + (om[12] * (om[ 5] * om[11] - om[ 7] * om[ 9]))); - // tm[ 9] = -((om[ 0] * (om[ 9] * om[15] - om[11] * om[13])) - (om[ 8] * (om[ 1] * om[15] - om[ 3] * om[13])) + (om[12] * (om[ 1] * om[11] - om[ 3] * om[ 9]))); - // tm[10] = ((om[ 0] * (om[ 5] * om[15] - om[ 7] * om[13])) - (om[ 4] * (om[ 1] * om[15] - om[ 3] * om[13])) + (om[12] * (om[ 1] * om[ 7] - om[ 3] * om[ 5]))); - // tm[11] = -((om[ 0] * (om[ 5] * om[11] - om[ 7] * om[ 9])) - (om[ 4] * (om[ 1] * om[11] - om[ 3] * om[ 9])) + (om[ 8] * (om[ 1] * om[ 7] - om[ 3] * om[ 5]))); - // tm[12] = -((om[ 4] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 5] * om[14] - om[ 6] * om[13])) + (om[12] * (om[ 5] * om[10] - om[ 6] * om[ 9]))); - // tm[13] = ((om[ 0] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[10] - om[ 2] * om[ 9]))); - // tm[14] = -((om[ 0] * (om[ 5] * om[14] - om[ 6] * om[13])) - (om[ 4] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[ 6] - om[ 2] * om[ 5]))); - // tm[15] = ((om[ 0] * (om[ 5] * om[10] - om[ 6] * om[ 9])) - (om[ 4] * (om[ 1] * om[10] - om[ 2] * om[ 9])) + (om[ 8] * (om[ 1] * om[ 6] - om[ 2] * om[ 5]))); - - // Optimized invert ( om[3, 7 and 11] is always 0, and om[15] is always 1 ). - tm[ 0] = ((om[ 5] * om[10]) - (om[ 9] * om[ 6])); - tm[ 1] = -((om[ 1] * om[10]) - (om[ 9] * om[ 2])); - tm[ 2] = ((om[ 1] * om[ 6]) - (om[ 5] * om[ 2])); - tm[ 3] = 0; - tm[ 4] = -((om[ 4] * om[10]) - (om[ 8] * om[ 6])); - tm[ 5] = ((om[ 0] * om[10]) - (om[ 8] * om[ 2])); - tm[ 6] = -((om[ 0] * om[ 6]) - (om[ 4] * om[ 2])); - tm[ 7] = 0; - tm[ 8] = ((om[ 4] * om[ 9]) - (om[ 8] * om[ 5])); - tm[ 9] = -((om[ 0] * om[ 9]) - (om[ 8] * om[ 1])); - tm[10] = ((om[ 0] * om[ 5]) - (om[ 4] * om[ 1])); - tm[11] = 0; - tm[12] = -((om[ 4] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 5] * om[14] - om[ 6] * om[13])) + (om[12] * (om[ 5] * om[10] - om[ 6] * om[ 9]))); - tm[13] = ((om[ 0] * (om[ 9] * om[14] - om[10] * om[13])) - (om[ 8] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[10] - om[ 2] * om[ 9]))); - tm[14] = -((om[ 0] * (om[ 5] * om[14] - om[ 6] * om[13])) - (om[ 4] * (om[ 1] * om[14] - om[ 2] * om[13])) + (om[12] * (om[ 1] * om[ 6] - om[ 2] * om[ 5]))); - tm[15] = 1; - - float Determinant = om[ 0] * tm[ 0] + - om[ 4] * tm[ 1] + - om[ 8] * tm[ 2] + - om[12] * tm[ 3]; - - if (Determinant != 0) - Determinant = 1 / Determinant; - - tm[ 0] *= Determinant; - tm[ 1] *= Determinant; - tm[ 2] *= Determinant; - tm[ 4] *= Determinant; - tm[ 5] *= Determinant; - tm[ 6] *= Determinant; - tm[ 8] *= Determinant; - tm[ 9] *= Determinant; - tm[10] *= Determinant; - tm[12] *= Determinant; - tm[13] *= Determinant; - tm[14] *= Determinant; - - return *this; -} - -Transform4x4f& Transform4x4f::scale(const Vector3f& _scale) -{ - float* tm = reinterpret_cast(this); - const float* sv = reinterpret_cast(&_scale); - - tm[ 0] *= sv[0]; - tm[ 1] *= sv[0]; - tm[ 2] *= sv[0]; - tm[ 4] *= sv[1]; - tm[ 5] *= sv[1]; - tm[ 6] *= sv[1]; - tm[ 8] *= sv[2]; - tm[ 9] *= sv[2]; - tm[10] *= sv[2]; - - return *this; -} - -Transform4x4f& Transform4x4f::rotate(const float _angle, const Vector3f& _axis) -{ - float* tm = reinterpret_cast(this); - const float* av = reinterpret_cast(&_axis); - const float s = sinf(-_angle); - const float c = cosf(-_angle); - const float t = 1 - c; - const float x = av[0]; - const float y = av[1]; - const float z = av[2]; - const float tx = t * x; - const float ty = t * y; - const float tz = t * z; - const float sx = s * x; - const float sy = s * y; - const float sz = s * z; - const float r[9] = { tx * x + c, - tx * y - sz, - tx * z + sy, - ty * x + sz, - ty * y + c, - ty * z - sx, - tz * x - sy, - tz * y + sx, - tz * z + c }; - const float temp[9] = { tm[ 0] * r[0] + tm[ 4] * r[1] + tm[ 8] * r[2], - tm[ 1] * r[0] + tm[ 5] * r[1] + tm[ 9] * r[2], - tm[ 2] * r[0] + tm[ 6] * r[1] + tm[10] * r[2], - tm[ 0] * r[3] + tm[ 4] * r[4] + tm[ 8] * r[5], - tm[ 1] * r[3] + tm[ 5] * r[4] + tm[ 9] * r[5], - tm[ 2] * r[3] + tm[ 6] * r[4] + tm[ 0] * r[5], - tm[ 0] * r[6] + tm[ 4] * r[7] + tm[ 8] * r[8], - tm[ 1] * r[6] + tm[ 5] * r[7] + tm[ 9] * r[8], - tm[ 2] * r[6] + tm[ 6] * r[7] + tm[10] * r[8] }; - - tm[ 0] = temp[0]; - tm[ 1] = temp[1]; - tm[ 2] = temp[2]; - tm[ 4] = temp[3]; - tm[ 5] = temp[4]; - tm[ 6] = temp[5]; - tm[ 8] = temp[6]; - tm[ 9] = temp[7]; - tm[10] = temp[8]; - - return *this; -} - -Transform4x4f& Transform4x4f::rotateX(const float _angle) -{ - float* tm = reinterpret_cast(this); - const float s = sinf(-_angle); - const float c = cosf(-_angle); - const float temp[6] = { tm[ 4] * c + tm[ 8] * -s, - tm[ 5] * c + tm[ 9] * -c, - tm[ 6] * c + tm[10] * -s, - tm[ 4] * s + tm[ 8] * c, - tm[ 5] * s + tm[ 9] * c, - tm[ 6] * s + tm[10] * c }; - - tm[ 4] = temp[0]; - tm[ 5] = temp[1]; - tm[ 6] = temp[2]; - tm[ 8] = temp[3]; - tm[ 9] = temp[4]; - tm[10] = temp[5]; - - return *this; -} - -Transform4x4f& Transform4x4f::rotateY(const float _angle) -{ - float* tm = reinterpret_cast(this); - const float s = sinf(-_angle); - const float c = cosf(-_angle); - const float temp[6] = { tm[ 0] * c + tm[ 8] * s, - tm[ 1] * c + tm[ 9] * s, - tm[ 2] * c + tm[10] * s, - tm[ 0] * -s + tm[ 8] * c, - tm[ 1] * -s + tm[ 9] * c, - tm[ 2] * -s + tm[10] * c }; - - tm[ 0] = temp[0]; - tm[ 1] = temp[1]; - tm[ 2] = temp[2]; - tm[ 8] = temp[3]; - tm[ 9] = temp[4]; - tm[10] = temp[5]; - - return *this; -} - -Transform4x4f& Transform4x4f::rotateZ(const float _angle) -{ - float* tm = reinterpret_cast(this); - const float s = sinf(-_angle); - const float c = cosf(-_angle); - const float temp[6] = { tm[ 0] * c + tm[ 4] * -s, - tm[ 1] * c + tm[ 5] * -s, - tm[ 2] * c + tm[ 6] * -s, - tm[ 0] * s + tm[ 4] * c, - tm[ 1] * s + tm[ 5] * c, - tm[ 2] * s + tm[ 6] * c }; - - tm[ 0] = temp[0]; - tm[ 1] = temp[1]; - tm[ 2] = temp[2]; - tm[ 4] = temp[3]; - tm[ 5] = temp[4]; - tm[ 6] = temp[5]; - - return *this; -} - -Transform4x4f& Transform4x4f::translate(const Vector3f& _translation) -{ - float* tm = reinterpret_cast(this); - const float* tv = reinterpret_cast(&_translation); - - tm[12] += tm[ 0] * tv[0] + tm[ 4] * tv[1] + tm[ 8] * tv[2]; - tm[13] += tm[ 1] * tv[0] + tm[ 5] * tv[1] + tm[ 9] * tv[2]; - tm[14] += tm[ 2] * tv[0] + tm[ 6] * tv[1] + tm[10] * tv[2]; - - return *this; -} - -Transform4x4f& Transform4x4f::round() -{ - float* tm = reinterpret_cast(this); - - tm[12] = std::round(tm[12]); - tm[13] = std::round(tm[13]); - tm[14] = std::round(tm[14]); - - return *this; -} -// clang-format on diff --git a/es-core/src/math/Transform4x4f.h b/es-core/src/math/Transform4x4f.h deleted file mode 100644 index c9f07da13..000000000 --- a/es-core/src/math/Transform4x4f.h +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Transform4x4f.h -// -// 4x4 matrix functions. -// - -#ifndef ES_CORE_MATH_TRANSFORM4X4F_H -#define ES_CORE_MATH_TRANSFORM4X4F_H - -#include "math/Vector3f.h" -#include "math/Vector4f.h" - -class Transform4x4f -{ -public: - Transform4x4f() {} - Transform4x4f(const Vector4f& _r0, - const Vector4f& _r1, - const Vector4f& _r2, - const Vector4f& _r3) - : mR0(_r0) - , mR1(_r1) - , mR2(_r2) - , mR3(_r3) - { - } - - const Transform4x4f operator*(const Transform4x4f& _other) const; - const Vector3f operator*(const Vector3f& _other) const; - Transform4x4f& operator*=(const Transform4x4f& _other) - { - *this = *this * _other; - return *this; - } - - Vector4f& r0() { return mR0; } - Vector4f& r1() { return mR1; } - Vector4f& r2() { return mR2; } - Vector4f& r3() { return mR3; } - const Vector4f& r0() const { return mR0; } - const Vector4f& r1() const { return mR1; } - const Vector4f& r2() const { return mR2; } - const Vector4f& r3() const { return mR3; } - - Transform4x4f& orthoProjection( - float _left, float _right, float _bottom, float _top, float _near, float _far); - Transform4x4f& invert(const Transform4x4f& _other); - Transform4x4f& scale(const Vector3f& _scale); - Transform4x4f& rotate(const float _angle, const Vector3f& _axis); - Transform4x4f& rotateX(const float _angle); - Transform4x4f& rotateY(const float _angle); - Transform4x4f& rotateZ(const float _angle); - Transform4x4f& translate(const Vector3f& _translation); - Transform4x4f& round(); - - Vector3f& translation() { return mR3.v3(); } - const Vector3f& translation() const { return mR3.v3(); } - - static const Transform4x4f Identity() - { - return { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; - } - -protected: - Vector4f mR0; - Vector4f mR1; - Vector4f mR2; - Vector4f mR3; -}; - -#endif // ES_CORE_MATH_TRANSFORM4X4F_H diff --git a/es-core/src/math/Vector2f.cpp b/es-core/src/math/Vector2f.cpp deleted file mode 100644 index 8d2a7cf1f..000000000 --- a/es-core/src/math/Vector2f.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Vector2f.cpp -// -// 2-dimensional floating point vector functions. -// - -#include "math/Vector2f.h" - -#include - -Vector2f& Vector2f::round() -{ - mX = std::round(mX); - mY = std::round(mY); - - return *this; -} - -Vector2f& Vector2f::lerp(const Vector2f& _start, const Vector2f& _end, const float _fraction) -{ - mX = Math::lerp(_start.x(), _end.x(), _fraction); - mY = Math::lerp(_start.y(), _end.y(), _fraction); - - return *this; -} diff --git a/es-core/src/math/Vector2f.h b/es-core/src/math/Vector2f.h deleted file mode 100644 index 193776e68..000000000 --- a/es-core/src/math/Vector2f.h +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Vector2f.h -// -// 2-dimensional floating point vector functions. -// - -#ifndef ES_CORE_MATH_VECTOR2F_H -#define ES_CORE_MATH_VECTOR2F_H - -#include "math/Misc.h" - -#include - -class Vector3f; -class Vector4f; - -class Vector2f -{ -public: - Vector2f() {} - Vector2f(const float _f) - : mX(_f) - , mY(_f) - { - } - Vector2f(const float _x, const float _y) - : mX(_x) - , mY(_y) - { - } - explicit Vector2f(const Vector3f& _v) - : mX((reinterpret_cast(_v)).mX) - , mY((reinterpret_cast(_v)).mY) - { - } - explicit Vector2f(const Vector4f& _v) - : mX((reinterpret_cast(_v)).mX) - , mY((reinterpret_cast(_v)).mY) - { - } - - // clang-format off - const bool operator==(const Vector2f& _other) const - { return ((mX == _other.mX) && (mY == _other.mY)); } - const bool operator!=(const Vector2f& _other) const - { return ((mX != _other.mX) || (mY != _other.mY)); } - - const Vector2f operator+(const Vector2f& _other) const - { return { mX + _other.mX, mY + _other.mY }; } - const Vector2f operator-(const Vector2f& _other) const - { return { mX - _other.mX, mY - _other.mY }; } - const Vector2f operator*(const Vector2f& _other) const - { return { mX * _other.mX, mY * _other.mY }; } - const Vector2f operator/(const Vector2f& _other) const - { return { mX / _other.mX, mY / _other.mY }; } - - const Vector2f operator+(const float& _other) const { return { mX + _other, mY + _other }; } - const Vector2f operator-(const float& _other) const { return { mX - _other, mY - _other }; } - const Vector2f operator*(const float& _other) const { return { mX * _other, mY * _other }; } - const Vector2f operator/(const float& _other) const { return { mX / _other, mY / _other }; } - - const Vector2f operator-() const { return { -mX , -mY }; } - - Vector2f& operator+=(const Vector2f& _other) { *this = *this + _other; return *this; } - Vector2f& operator-=(const Vector2f& _other) { *this = *this - _other; return *this; } - Vector2f& operator*=(const Vector2f& _other) { *this = *this * _other; return *this; } - Vector2f& operator/=(const Vector2f& _other) { *this = *this / _other; return *this; } - - Vector2f& operator+=(const float& _other) { *this = *this + _other; return *this; } - Vector2f& operator-=(const float& _other) { *this = *this - _other; return *this; } - Vector2f& operator*=(const float& _other) { *this = *this * _other; return *this; } - Vector2f& operator/=(const float& _other) { *this = *this / _other; return *this; } - - float& operator[](const int _index) - { assert(_index < 2 && "index out of range"); return (&mX)[_index]; } - const float& operator[](const int _index) const - { assert(_index < 2 && "index out of range"); return (&mX)[_index]; } - // clang-format on - - float& x() { return mX; } - float& y() { return mY; } - const float& x() const { return mX; } - const float& y() const { return mY; } - - Vector2f& round(); - Vector2f& lerp(const Vector2f& _start, const Vector2f& _end, const float _fraction); - - static const Vector2f Zero() { return { 0.0f, 0.0f }; } - static const Vector2f UnitX() { return { 1.0f, 0.0f }; } - static const Vector2f UnitY() { return { 0.0f, 1.0f }; } - -private: - float mX; - float mY; -}; - -#endif // ES_CORE_MATH_VECTOR2F_H diff --git a/es-core/src/math/Vector2i.cpp b/es-core/src/math/Vector2i.cpp deleted file mode 100644 index db183bf17..000000000 --- a/es-core/src/math/Vector2i.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Vector2i.cpp -// -// 2-dimensional integer vector functions. -// - -#include "math/Vector2i.h" diff --git a/es-core/src/math/Vector2i.h b/es-core/src/math/Vector2i.h deleted file mode 100644 index 1924852d6..000000000 --- a/es-core/src/math/Vector2i.h +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Vector2i.h -// -// 2-dimensional integer vector functions. -// - -#ifndef ES_CORE_MATH_VECTOR2I_H -#define ES_CORE_MATH_VECTOR2I_H - -#include - -class Vector2i -{ -public: - Vector2i() {} - Vector2i(const int _i) - : mX(_i) - , mY(_i) - { - } - Vector2i(const int _x, const int _y) - : mX(_x) - , mY(_y) - { - } - - // clang-format off - const bool operator==(const Vector2i& _other) const - { return ((mX == _other.mX) && (mY == _other.mY)); } - const bool operator!=(const Vector2i& _other) const - { return ((mX != _other.mX) || (mY != _other.mY)); } - - const Vector2i operator+(const Vector2i& _other) const - { return { mX + _other.mX, mY + _other.mY }; } - const Vector2i operator-(const Vector2i& _other) const - { return { mX - _other.mX, mY - _other.mY }; } - const Vector2i operator*(const Vector2i& _other) const - { return { mX * _other.mX, mY * _other.mY }; } - const Vector2i operator/(const Vector2i& _other) const - { return { mX / _other.mX, mY / _other.mY }; } - - const Vector2i operator+(const int& _other) const { return { mX + _other, mY + _other }; } - const Vector2i operator-(const int& _other) const { return { mX - _other, mY - _other }; } - const Vector2i operator*(const int& _other) const { return { mX * _other, mY * _other }; } - const Vector2i operator/(const int& _other) const { return { mX / _other, mY / _other }; } - - const Vector2i operator-() const { return { -mX , -mY }; } - - Vector2i& operator+=(const Vector2i& _other) { *this = *this + _other; return *this; } - Vector2i& operator-=(const Vector2i& _other) { *this = *this - _other; return *this; } - Vector2i& operator*=(const Vector2i& _other) { *this = *this * _other; return *this; } - Vector2i& operator/=(const Vector2i& _other) { *this = *this / _other; return *this; } - - Vector2i& operator+=(const int& _other) { *this = *this + _other; return *this; } - Vector2i& operator-=(const int& _other) { *this = *this - _other; return *this; } - Vector2i& operator*=(const int& _other) { *this = *this * _other; return *this; } - Vector2i& operator/=(const int& _other) { *this = *this / _other; return *this; } - - int& operator[](const int _index) - { assert(_index < 2 && "index out of range"); return (&mX)[_index]; } - const int& operator[](const int _index) const - { assert(_index < 2 && "index out of range"); return (&mX)[_index]; } - // clang-format on - - int& x() { return mX; } - int& y() { return mY; } - const int& x() const { return mX; } - const int& y() const { return mY; } - - static const Vector2i Zero() { return { 0, 0 }; } - static const Vector2i UnitX() { return { 1, 0 }; } - static const Vector2i UnitY() { return { 0, 1 }; } - -private: - int mX; - int mY; -}; - -#endif // ES_CORE_MATH_VECTOR2I_H diff --git a/es-core/src/math/Vector3f.cpp b/es-core/src/math/Vector3f.cpp deleted file mode 100644 index a89f464d5..000000000 --- a/es-core/src/math/Vector3f.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Vector3f.cpp -// -// 3-dimensional floating point vector functions. -// - -#include "math/Vector3f.h" - -#include - -Vector3f& Vector3f::round() -{ - mX = std::round(mX); - mY = std::round(mY); - mZ = std::round(mZ); - - return *this; -} - -Vector3f& Vector3f::lerp(const Vector3f& _start, const Vector3f& _end, const float _fraction) -{ - mX = Math::lerp(_start.x(), _end.x(), _fraction); - mY = Math::lerp(_start.y(), _end.y(), _fraction); - mZ = Math::lerp(_start.z(), _end.z(), _fraction); - - return *this; -} diff --git a/es-core/src/math/Vector3f.h b/es-core/src/math/Vector3f.h deleted file mode 100644 index 73a05f71d..000000000 --- a/es-core/src/math/Vector3f.h +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Vector3f.h -// -// 3-dimensional floating point vector functions. -// - -#ifndef ES_CORE_MATH_VECTOR3F_H -#define ES_CORE_MATH_VECTOR3F_H - -#include "math/Misc.h" - -#include - -class Vector2f; -class Vector4f; - -class Vector3f -{ -public: - Vector3f() {} - Vector3f(const float _f) - : mX(_f) - , mY(_f) - , mZ(_f) - { - } - Vector3f(const float _x, const float _y, const float _z) - : mX(_x) - , mY(_y) - , mZ(_z) - { - } - explicit Vector3f(const Vector2f& _v) - : mX((reinterpret_cast(_v)).mX) - , mY((reinterpret_cast(_v)).mY) - , mZ(0) - { - } - explicit Vector3f(const Vector2f& _v, const float _z) - : mX((reinterpret_cast(_v)).mX) - , mY((reinterpret_cast(_v)).mY) - , mZ(_z) - { - } - explicit Vector3f(const Vector4f& _v) - : mX((reinterpret_cast(_v)).mX) - , mY((reinterpret_cast(_v)).mY) - , mZ((reinterpret_cast(_v)).mZ) - { - } - - // clang-format off - const bool operator==(const Vector3f& _other) const - { return ((mX == _other.mX) && (mY == _other.mY) && (mZ == _other.mZ)); } - const bool operator!=(const Vector3f& _other) const - { return ((mX != _other.mX) || (mY != _other.mY) || (mZ != _other.mZ)); } - - const Vector3f operator+(const Vector3f& _other) const - { return { mX + _other.mX, mY + _other.mY, mZ + _other.mZ }; } - const Vector3f operator-(const Vector3f& _other) const - { return { mX - _other.mX, mY - _other.mY, mZ - _other.mZ }; } - const Vector3f operator*(const Vector3f& _other) const - { return { mX * _other.mX, mY * _other.mY, mZ * _other.mZ }; } - const Vector3f operator/(const Vector3f& _other) const - { return { mX / _other.mX, mY / _other.mY, mZ / _other.mZ }; } - - const Vector3f operator+(const float& _other) const - { return { mX + _other, mY + _other, mZ + _other }; } - const Vector3f operator-(const float& _other) const - { return { mX - _other, mY - _other, mZ - _other }; } - const Vector3f operator*(const float& _other) const - { return { mX * _other, mY * _other, mZ * _other }; } - const Vector3f operator/(const float& _other) const - { return { mX / _other, mY / _other, mZ / _other }; } - - const Vector3f operator-() const { return { -mX , -mY, -mZ }; } - - Vector3f& operator+=(const Vector3f& _other) { *this = *this + _other; return *this; } - Vector3f& operator-=(const Vector3f& _other) { *this = *this - _other; return *this; } - Vector3f& operator*=(const Vector3f& _other) { *this = *this * _other; return *this; } - Vector3f& operator/=(const Vector3f& _other) { *this = *this / _other; return *this; } - - Vector3f& operator+=(const float& _other) { *this = *this + _other; return *this; } - Vector3f& operator-=(const float& _other) { *this = *this - _other; return *this; } - Vector3f& operator*=(const float& _other) { *this = *this * _other; return *this; } - Vector3f& operator/=(const float& _other) { *this = *this / _other; return *this; } - - float& operator[](const int _index) - { assert(_index < 3 && "index out of range"); return (&mX)[_index]; } - const float& operator[](const int _index) const - { assert(_index < 3 && "index out of range"); return (&mX)[_index]; } - // clang-format on - - float& x() { return mX; } - float& y() { return mY; } - float& z() { return mZ; } - const float& x() const { return mX; } - const float& y() const { return mY; } - const float& z() const { return mZ; } - - Vector2f& v2() { return *reinterpret_cast(this); } - const Vector2f& v2() const { return *reinterpret_cast(this); } - - Vector3f& round(); - Vector3f& lerp(const Vector3f& _start, const Vector3f& _end, const float _fraction); - - static const Vector3f Zero() { return { 0.0f, 0.0f, 0.0f }; } - static const Vector3f UnitX() { return { 1.0f, 0.0f, 0.0f }; } - static const Vector3f UnitY() { return { 0.0f, 1.0f, 0.0f }; } - static const Vector3f UnitZ() { return { 0.0f, 0.0f, 1.0f }; } - -private: - float mX; - float mY; - float mZ; -}; - -#endif // ES_CORE_MATH_VECTOR3F_H diff --git a/es-core/src/math/Vector4f.cpp b/es-core/src/math/Vector4f.cpp deleted file mode 100644 index f3ab4cf15..000000000 --- a/es-core/src/math/Vector4f.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Vector4f.cpp -// -// 4-dimensional floating point vector functions. -// - -#include "math/Vector4f.h" - -#include - -Vector4f& Vector4f::round() -{ - mX = std::round(mX); - mY = std::round(mY); - mZ = std::round(mZ); - mW = std::round(mW); - - return *this; -} - -Vector4f& Vector4f::lerp(const Vector4f& _start, const Vector4f& _end, const float _fraction) -{ - mX = Math::lerp(_start.x(), _end.x(), _fraction); - mY = Math::lerp(_start.y(), _end.y(), _fraction); - mZ = Math::lerp(_start.z(), _end.z(), _fraction); - mW = Math::lerp(_start.w(), _end.w(), _fraction); - - return *this; -} diff --git a/es-core/src/math/Vector4f.h b/es-core/src/math/Vector4f.h deleted file mode 100644 index 000684ada..000000000 --- a/es-core/src/math/Vector4f.h +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: MIT -// -// EmulationStation Desktop Edition -// Vector4f.h -// -// 4-dimensional floating point vector functions. -// - -#ifndef ES_CORE_MATH_VECTOR4F_H -#define ES_CORE_MATH_VECTOR4F_H - -#include "math/Misc.h" - -#include - -class Vector2f; -class Vector3f; - -class Vector4f -{ -public: - Vector4f() {} - Vector4f(const float _f) - : mX(_f) - , mY(_f) - , mZ(_f) - , mW(_f) - { - } - Vector4f(const float _x, const float _y, const float _z, const float _w) - : mX(_x) - , mY(_y) - , mZ(_z) - , mW(_w) - { - } - explicit Vector4f(const Vector2f& _v) - : mX((reinterpret_cast(_v)).mX) - , mY((reinterpret_cast(_v)).mY) - , mZ(0) - , mW(0) - { - } - explicit Vector4f(const Vector2f& _v, const float _z) - : mX((reinterpret_cast(_v)).mX) - , mY((reinterpret_cast(_v)).mY) - , mZ(_z) - , mW(0) - { - } - explicit Vector4f(const Vector2f& _v, const float _z, const float _w) - : mX((reinterpret_cast(_v)).mX) - , mY((reinterpret_cast(_v)).mY) - , mZ(_z) - , mW(_w) - { - } - explicit Vector4f(const Vector3f& _v) - : mX((reinterpret_cast(_v)).mX) - , mY((reinterpret_cast(_v)).mY) - , mZ((reinterpret_cast(_v)).mZ) - , mW(0) - { - } - explicit Vector4f(const Vector3f& _v, const float _w) - : mX((reinterpret_cast(_v)).mX) - , mY((reinterpret_cast(_v)).mY) - , mZ((reinterpret_cast(_v)).mZ) - , mW(_w) - { - } - - // clang-format off - const bool operator==(const Vector4f& _other) const - { return ((mX == _other.mX) && (mY == _other.mY) && - (mZ == _other.mZ) && (mW == _other.mW)); } - const bool operator!=(const Vector4f& _other) const - { return ((mX != _other.mX) || (mY != _other.mY) || - (mZ != _other.mZ) || (mW != _other.mW)); } - - const Vector4f operator+(const Vector4f& _other) const - { return { mX + _other.mX, mY + _other.mY, mZ + _other.mZ, mW + _other.mW }; } - const Vector4f operator-(const Vector4f& _other) const - { return { mX - _other.mX, mY - _other.mY, mZ - _other.mZ, mW - _other.mW }; } - const Vector4f operator*(const Vector4f& _other) const - { return { mX * _other.mX, mY * _other.mY, mZ * _other.mZ, mW * _other.mW }; } - const Vector4f operator/(const Vector4f& _other) const - { return { mX / _other.mX, mY / _other.mY, mZ / _other.mZ, mW / _other.mW }; } - - const Vector4f operator+(const float& _other) const - { return { mX + _other, mY + _other, mZ + _other, mW + _other }; } - const Vector4f operator-(const float& _other) const - { return { mX - _other, mY - _other, mZ - _other, mW - _other }; } - const Vector4f operator*(const float& _other) const - { return { mX * _other, mY * _other, mZ * _other, mW * _other }; } - const Vector4f operator/(const float& _other) const - { return { mX / _other, mY / _other, mZ / _other, mW / _other }; } - - const Vector4f operator-() const { return {-mX , -mY, -mZ, -mW }; } - - Vector4f& operator+=(const Vector4f& _other) { *this = *this + _other; return *this; } - Vector4f& operator-=(const Vector4f& _other) { *this = *this - _other; return *this; } - Vector4f& operator*=(const Vector4f& _other) { *this = *this * _other; return *this; } - Vector4f& operator/=(const Vector4f& _other) { *this = *this / _other; return *this; } - - Vector4f& operator+=(const float& _other) { *this = *this + _other; return *this; } - Vector4f& operator-=(const float& _other) { *this = *this - _other; return *this; } - Vector4f& operator*=(const float& _other) { *this = *this * _other; return *this; } - Vector4f& operator/=(const float& _other) { *this = *this / _other; return *this; } - - float& operator[](const int _index) - { assert(_index < 4 && "index out of range"); return (&mX)[_index]; } - const float& operator[](const int _index) const - { assert(_index < 4 && "index out of range"); return (&mX)[_index]; } - // clang-format on - - float& x() { return mX; } - float& y() { return mY; } - float& z() { return mZ; } - float& w() { return mW; } - const float& x() const { return mX; } - const float& y() const { return mY; } - const float& z() const { return mZ; } - const float& w() const { return mW; } - - Vector2f& v2() { return *reinterpret_cast(this); } - const Vector2f& v2() const { return *reinterpret_cast(this); } - - Vector3f& v3() { return *reinterpret_cast(this); } - const Vector3f& v3() const { return *reinterpret_cast(this); } - - Vector4f& round(); - Vector4f& lerp(const Vector4f& _start, const Vector4f& _end, const float _fraction); - - static const Vector4f Zero() { return { 0.0f, 0.0f, 0.0f, 0.0f }; } - static const Vector4f UnitX() { return { 1.0f, 0.0f, 0.0f, 0.0f }; } - static const Vector4f UnitY() { return { 0.0f, 1.0f, 0.0f, 0.0f }; } - static const Vector4f UnitZ() { return { 0.0f, 0.0f, 1.0f, 0.0f }; } - static const Vector4f UnitW() { return { 0.0f, 0.0f, 0.0f, 1.0f }; } - -private: - float mX; - float mY; - float mZ; - float mW; -}; - -#endif // ES_CORE_MATH_VECTOR4F_H diff --git a/es-core/src/renderers/Renderer.cpp b/es-core/src/renderers/Renderer.cpp index 7b96c6d56..be619c006 100644 --- a/es-core/src/renderers/Renderer.cpp +++ b/es-core/src/renderers/Renderer.cpp @@ -12,8 +12,6 @@ #include "Log.h" #include "Settings.h" #include "Shader_GL21.h" -#include "math/Transform4x4f.h" -#include "math/Vector2i.h" #include "resources/ResourceManager.h" #include @@ -326,28 +324,19 @@ namespace Renderer if (!createWindow()) return false; - Transform4x4f projection = Transform4x4f::Identity(); - Rect viewport = Rect(0, 0, 0, 0); + glm::mat4 projection{getIdentity()}; + Rect viewport{0, 0, 0, 0}; switch (screenRotate) { - case 0: { - viewport.x = screenOffsetX; - viewport.y = screenOffsetY; - viewport.w = screenWidth; - viewport.h = screenHeight; - projection.orthoProjection(0.0f, static_cast(screenWidth), - static_cast(screenHeight), 0.0f, -1.0f, 1.0f); - break; - } case 1: { viewport.x = windowWidth - screenOffsetY - screenHeight; viewport.y = screenOffsetX; viewport.w = screenHeight; viewport.h = screenWidth; - projection.orthoProjection(0.0f, static_cast(screenHeight), - static_cast(screenWidth), 0.0f, -1.0f, 1.0f); - projection.rotate(static_cast(ES_DEG_TO_RAD(90)), { 0, 0, 1 }); - projection.translate({ 0, screenHeight * -1.0f, 0 }); + projection = glm::ortho(0.0f, static_cast(screenHeight), + static_cast(screenWidth), 0.0f, -1.0f, 1.0f); + projection = glm::rotate(projection, glm::radians(90.0f), {0.0f, 0.0f, 1.0f}); + projection = glm::translate(projection, {0.0f, screenHeight * -1.0f, 0.0f}); break; } case 2: { @@ -355,10 +344,11 @@ namespace Renderer viewport.y = windowHeight - screenOffsetY - screenHeight; viewport.w = screenWidth; viewport.h = screenHeight; - projection.orthoProjection(0.0f, static_cast(screenWidth), - static_cast(screenHeight), 0.0f, -1.0f, 1.0f); - projection.rotate(static_cast(ES_DEG_TO_RAD(180)), { 0, 0, 1 }); - projection.translate({ screenWidth * -1.0f, screenHeight * -1.0f, 0 }); + projection = glm::ortho(0.0f, static_cast(screenWidth), + static_cast(screenHeight), 0.0f, -1.0f, 1.0f); + projection = glm::rotate(projection, glm::radians(180.0f), {0.0f, 0.0f, 1.0f}); + projection = + glm::translate(projection, {screenWidth * -1.0f, screenHeight * -1.0f, 0.0f}); break; } case 3: { @@ -366,10 +356,19 @@ namespace Renderer viewport.y = windowHeight - screenOffsetX - screenWidth; viewport.w = screenHeight; viewport.h = screenWidth; - projection.orthoProjection(0.0f, static_cast(screenHeight), - static_cast(screenWidth), 0.0f, -1.0f, 1.0f); - projection.rotate(static_cast(ES_DEG_TO_RAD(270)), { 0, 0, 1 }); - projection.translate({ screenWidth * -1.0f, 0, 0 }); + projection = glm::ortho(0.0f, static_cast(screenHeight), + static_cast(screenWidth), 0.0f, -1.0f, 1.0f); + projection = glm::rotate(projection, glm::radians(270.0f), {0.0f, 0.0f, 1.0f}); + projection = glm::translate(projection, {screenWidth * -1.0f, 0.0f, 0.0f}); + break; + } + default: { + viewport.x = screenOffsetX; + viewport.y = screenOffsetY; + viewport.w = screenWidth; + viewport.h = screenHeight; + projection = glm::ortho(0.0f, static_cast(screenWidth), + static_cast(screenHeight), 0.0f, -1.0f, 1.0f); break; } } @@ -393,9 +392,9 @@ namespace Renderer destroyWindow(); } - void pushClipRect(const Vector2i& _pos, const Vector2i& _size) + void pushClipRect(const glm::ivec2& pos, const glm::ivec2& size) { - Rect box(_pos.x(), _pos.y(), _size.x(), _size.y()); + Rect box(pos.x, pos.y, size.x, size.y); if (box.w == 0) box.w = screenWidth - box.x; @@ -458,51 +457,51 @@ namespace Renderer setScissor(clipStack.top()); } - void drawRect(const float _x, - const float _y, - const float _w, - const float _h, + void drawRect(const float x, + const float y, + const float w, + const float h, const unsigned int _color, const unsigned int _colorEnd, bool horizontalGradient, - const float _opacity, - const Transform4x4f& _trans, - const Blend::Factor _srcBlendFactor, - const Blend::Factor _dstBlendFactor) + const float opacity, + const glm::mat4& trans, + const Blend::Factor srcBlendFactor, + const Blend::Factor dstBlendFactor) { - const unsigned int color = convertRGBAToABGR(_color); - const unsigned int colorEnd = convertRGBAToABGR(_colorEnd); + const unsigned int rColor = convertRGBAToABGR(_color); + const unsigned int rColorEnd = convertRGBAToABGR(_colorEnd); Vertex vertices[4]; - float _wL = _w; - float _hL = _h; + float wL = w; + float hL = h; // If the width or height was scaled down to less than 1 pixel, then set it to // 1 pixel so that it will still render on lower resolutions. - if (_wL > 0.0f && _wL < 1.0f) - _wL = 1.0f; - if (_hL > 0.0f && _hL < 1.0f) - _hL = 1.0f; + if (wL > 0.0f && wL < 1.0f) + wL = 1.0f; + if (hL > 0.0f && hL < 1.0f) + hL = 1.0f; // clang-format off - vertices[0] = { { _x , _y }, { 0.0f, 0.0f }, color }; - vertices[1] = { { _x , _y + _hL }, { 0.0f, 0.0f }, horizontalGradient ? colorEnd : color }; - vertices[2] = { { _x + _wL, _y }, { 0.0f, 0.0f }, horizontalGradient ? color : colorEnd }; - vertices[3] = { { _x + _wL, _y + _hL }, { 0.0f, 0.0f }, colorEnd }; + vertices[0] = {{x, y }, {0.0f, 0.0f}, rColor}; + vertices[1] = {{x, y + hL}, {0.0f, 0.0f}, horizontalGradient ? rColorEnd : rColor}; + vertices[2] = {{x + wL, y }, {0.0f, 0.0f}, horizontalGradient ? rColor : rColorEnd}; + vertices[3] = {{x + wL, y + hL}, {0.0f, 0.0f}, rColorEnd}; // clang-format on // Round vertices. for (int i = 0; i < 4; i++) - vertices[i].pos.round(); + vertices[i].pos = glm::round(vertices[i].pos); - if (_opacity < 1.0) { + if (opacity < 1.0) { vertices[0].shaders = SHADER_OPACITY; - vertices[0].opacity = _opacity; + vertices[0].opacity = opacity; } else { bindTexture(0); } - drawTriangleStrips(vertices, 4, _trans, _srcBlendFactor, _dstBlendFactor); + drawTriangleStrips(vertices, 4, trans, srcBlendFactor, dstBlendFactor); } unsigned int convertRGBAToABGR(const unsigned int _color) @@ -542,7 +541,7 @@ namespace Renderer return nullptr; }; - const Transform4x4f getProjectionMatrix() { return mProjectionMatrix; } + const glm::mat4 getProjectionMatrix() { return mProjectionMatrix; } SDL_Window* getSDLWindow() { return sdlWindow; } int getWindowWidth() { return windowWidth; } int getWindowHeight() { return windowHeight; } diff --git a/es-core/src/renderers/Renderer.h b/es-core/src/renderers/Renderer.h index 5fec1600e..ed6980c66 100644 --- a/es-core/src/renderers/Renderer.h +++ b/es-core/src/renderers/Renderer.h @@ -11,25 +11,21 @@ #include "Log.h" #include "Shader_GL21.h" -#include "math/Transform4x4f.h" -#include "math/Vector2f.h" +#include "utils/MathUtil.h" #include #include struct SDL_Window; -class Transform4x4f; -class Vector2i; - namespace Renderer { - const unsigned int SHADER_DESATURATE = 1; - const unsigned int SHADER_OPACITY = 2; - const unsigned int SHADER_DIM = 4; - const unsigned int SHADER_BLUR_HORIZONTAL = 8; - const unsigned int SHADER_BLUR_VERTICAL = 16; - const unsigned int SHADER_SCANLINES = 32; + const unsigned int SHADER_DESATURATE{1}; + const unsigned int SHADER_OPACITY{2}; + const unsigned int SHADER_DIM{4}; + const unsigned int SHADER_BLUR_HORIZONTAL{8}; + const unsigned int SHADER_BLUR_VERTICAL{16}; + const unsigned int SHADER_SCANLINES{32}; struct shaderParameters { std::array textureSize; @@ -40,19 +36,20 @@ namespace Renderer unsigned int blurPasses; shaderParameters() - : textureSize({ 0.0f, 0.0f }) - , textureCoordinates({ 0.0f, 0.0f, 0.0f, 0.0f }) - , fragmentSaturation(1.0f) - , fragmentDimValue(0.4f) - , fragmentOpacity(1.0f) - , blurPasses(1) + : textureSize{0.0f, 0.0f} + , textureCoordinates{0.0f, 0.0f, 0.0f, 0.0f} + , fragmentSaturation{1.0f} + , fragmentDimValue{0.4f} + , fragmentOpacity{1.0f} + , blurPasses{1} { } }; static std::vector sShaderProgramVector; static GLuint shaderFBO; - static Transform4x4f mProjectionMatrix; + static glm::mat4 mProjectionMatrix; + static constexpr glm::mat4 getIdentity() { return glm::mat4{1.0f}; } #if !defined(NDEBUG) #define GL_CHECK_ERROR(Function) (Function, _GLCheckError(#Function)) @@ -78,33 +75,33 @@ namespace Renderer namespace Blend { enum Factor { - ZERO = 0, - ONE = 1, - SRC_COLOR = 2, - ONE_MINUS_SRC_COLOR = 3, - SRC_ALPHA = 4, - ONE_MINUS_SRC_ALPHA = 5, - DST_COLOR = 6, - ONE_MINUS_DST_COLOR = 7, - DST_ALPHA = 8, - ONE_MINUS_DST_ALPHA = 9 + ZERO, + ONE, + SRC_COLOR, + ONE_MINUS_SRC_COLOR, + SRC_ALPHA, + ONE_MINUS_SRC_ALPHA, + DST_COLOR, + ONE_MINUS_DST_COLOR, + DST_ALPHA, + ONE_MINUS_DST_ALPHA }; } namespace Texture { enum Type { - RGBA = 0, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0). - ALPHA = 1 + RGBA, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0). + ALPHA }; } struct Rect { - Rect(const int _x, const int _y, const int _w, const int _h) - : x(_x) - , y(_y) - , w(_w) - , h(_h) + Rect(const int xValue, const int yValue, const int wValue, const int hValue) + : x(xValue) + , y(yValue) + , w(wValue) + , h(hValue) { } int x; @@ -115,35 +112,35 @@ namespace Renderer struct Vertex { Vertex() {} - Vertex(const Vector2f& _pos, const Vector2f& _tex, const unsigned int _col) - : pos(_pos) - , tex(_tex) - , col(_col) + Vertex(const glm::vec2& position, const glm::vec2& textureCoord, const unsigned int color) + : pos(position) + , tex(textureCoord) + , col(color) { } - Vector2f pos; - Vector2f tex; + glm::vec2 pos; + glm::vec2 tex; unsigned int col; - float saturation = 1.0; - float opacity = 1.0; - unsigned int shaders = 0; + float saturation{1.0}; + float opacity{1.0}; + unsigned int shaders{0}; }; bool init(); void deinit(); - void pushClipRect(const Vector2i& _pos, const Vector2i& _size); + void pushClipRect(const glm::ivec2& pos, const glm::ivec2& size); void popClipRect(); - void drawRect(const float _x, - const float _y, - const float _w, - const float _h, - const unsigned int _color, - const unsigned int _colorEnd, + void drawRect(const float x, + const float y, + const float w, + const float h, + const unsigned int color, + const unsigned int colorEnd, bool horizontalGradient = false, - const float _opacity = 1.0, - const Transform4x4f& _trans = Transform4x4f::Identity(), - const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA, - const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA); + const float opacity = 1.0, + const glm::mat4& trans = getIdentity(), + const Blend::Factor srcBlendFactor = Blend::SRC_ALPHA, + const Blend::Factor dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA); SDL_Window* getSDLWindow(); int getWindowWidth(); int getWindowHeight(); @@ -160,7 +157,7 @@ namespace Renderer unsigned int convertABGRToRGBA(unsigned int color); Shader* getShaderProgram(unsigned int shaderID); - const Transform4x4f getProjectionMatrix(); + const glm::mat4 getProjectionMatrix(); void shaderPostprocessing(unsigned int shaders, const Renderer::shaderParameters& parameters = shaderParameters(), unsigned char* textureRGBA = nullptr); @@ -170,35 +167,36 @@ namespace Renderer void setupWindow(); bool createContext(); void destroyContext(); - unsigned int createTexture(const Texture::Type _type, - const bool _linear, - const bool _repeat, - const unsigned int _width, - const unsigned int _height, - void* _data); - void destroyTexture(const unsigned int _texture); - void updateTexture(const unsigned int _texture, - const Texture::Type _type, - const unsigned int _x, - const unsigned _y, - const unsigned int _width, - const unsigned int _height, - void* _data); - void bindTexture(const unsigned int _texture); - void drawLines(const Vertex* _vertices, - const unsigned int _numVertices, - const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA, - const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA); - void drawTriangleStrips(const Vertex* _vertices, - const unsigned int _numVertices, - const Transform4x4f& _trans = Transform4x4f::Identity(), - const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA, - const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA, - const shaderParameters& _parameters = shaderParameters()); - void setProjection(const Transform4x4f& _projection); - void setMatrix(const Transform4x4f& _matrix); - void setViewport(const Rect& _viewport); - void setScissor(const Rect& _scissor); + unsigned int createTexture(const Texture::Type type, + const bool linearMinify, + const bool linearMagnify, + const bool repeat, + const unsigned int width, + const unsigned int height, + void* data); + void destroyTexture(const unsigned int texture); + void updateTexture(const unsigned int texture, + const Texture::Type type, + const unsigned int x, + const unsigned y, + const unsigned int width, + const unsigned int height, + void* data); + void bindTexture(const unsigned int texture); + void drawLines(const Vertex* vertices, + const unsigned int numVertices, + const Blend::Factor srcBlendFactor = Blend::SRC_ALPHA, + const Blend::Factor dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA); + void drawTriangleStrips(const Vertex* vertices, + const unsigned int numVertices, + const glm::mat4& trans = getIdentity(), + const Blend::Factor srcBlendFactor = Blend::SRC_ALPHA, + const Blend::Factor dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA, + const shaderParameters& parameters = shaderParameters()); + void setProjection(const glm::mat4& projection); + void setMatrix(const glm::mat4& matrix); + void setViewport(const Rect& viewport); + void setScissor(const Rect& scissor); void setSwapInterval(); void swapBuffers(); diff --git a/es-core/src/renderers/Renderer_GL21.cpp b/es-core/src/renderers/Renderer_GL21.cpp index 7f236ec8c..4957cd436 100644 --- a/es-core/src/renderers/Renderer_GL21.cpp +++ b/es-core/src/renderers/Renderer_GL21.cpp @@ -10,7 +10,6 @@ #include "Settings.h" #include "Shader_GL21.h" -#include "math/Transform4x4f.h" #include "renderers/Renderer.h" namespace Renderer @@ -138,8 +137,8 @@ namespace Renderer return false; } - uint8_t data[4] = { 255, 255, 255, 255 }; - whiteTexture = createTexture(Texture::RGBA, false, true, 1, 1, data); + uint8_t data[4] = {255, 255, 255, 255}; + whiteTexture = createTexture(Texture::RGBA, false, false, true, 1, 1, data); GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D)); @@ -163,163 +162,166 @@ namespace Renderer sdlContext = nullptr; } - unsigned int createTexture(const Texture::Type _type, - const bool _linear, - const bool _repeat, - const unsigned int _width, - const unsigned int _height, - void* _data) + unsigned int createTexture(const Texture::Type type, + const bool linearMinify, + const bool linearMagnify, + const bool repeat, + const unsigned int width, + const unsigned int height, + void* data) { - const GLenum type = convertTextureType(_type); + const GLenum textureType = convertTextureType(type); unsigned int texture; GL_CHECK_ERROR(glGenTextures(1, &texture)); GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - _repeat ? static_cast(GL_REPEAT) : - static_cast(GL_CLAMP_TO_EDGE))); + repeat ? static_cast(GL_REPEAT) : + static_cast(GL_CLAMP_TO_EDGE))); GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - _repeat ? static_cast(GL_REPEAT) : - static_cast(GL_CLAMP_TO_EDGE))); + repeat ? static_cast(GL_REPEAT) : + static_cast(GL_CLAMP_TO_EDGE))); GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - _linear ? static_cast(GL_LINEAR) : - static_cast(GL_NEAREST))); - GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + linearMinify ? static_cast(GL_LINEAR) : + static_cast(GL_NEAREST))); + GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + linearMagnify ? static_cast(GL_LINEAR) : + static_cast(GL_NEAREST))); - GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, type, _width, _height, 0, type, - GL_UNSIGNED_BYTE, _data)); + GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, textureType, + GL_UNSIGNED_BYTE, data)); return texture; } - void destroyTexture(const unsigned int _texture) + void destroyTexture(const unsigned int texture) { - GL_CHECK_ERROR(glDeleteTextures(1, &_texture)); + GL_CHECK_ERROR(glDeleteTextures(1, &texture)); } - void updateTexture(const unsigned int _texture, - const Texture::Type _type, - const unsigned int _x, - const unsigned _y, - const unsigned int _width, - const unsigned int _height, - void* _data) + void updateTexture(const unsigned int texture, + const Texture::Type type, + const unsigned int x, + const unsigned y, + const unsigned int width, + const unsigned int height, + void* data) { - const GLenum type = convertTextureType(_type); + const GLenum textureType = convertTextureType(type); - GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture)); - GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, _x, _y, _width, _height, type, - GL_UNSIGNED_BYTE, _data)); + GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, textureType, + GL_UNSIGNED_BYTE, data)); GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture)); } - void bindTexture(const unsigned int _texture) + void bindTexture(const unsigned int texture) { - if (_texture == 0) + if (texture == 0) GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture)); else - GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture)); + GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); } - void drawLines(const Vertex* _vertices, - const unsigned int _numVertices, - const Blend::Factor _srcBlendFactor, - const Blend::Factor _dstBlendFactor) + void drawLines(const Vertex* vertices, + const unsigned int numVertices, + const Blend::Factor srcBlendFactor, + const Blend::Factor dstBlendFactor) { - GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos)); - GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex)); - GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col)); + GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].pos)); + GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].tex)); + GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vertices[0].col)); GL_CHECK_ERROR( - glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor))); + glBlendFunc(convertBlendFactor(srcBlendFactor), convertBlendFactor(dstBlendFactor))); - GL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, _numVertices)); + GL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, numVertices)); } - void drawTriangleStrips(const Vertex* _vertices, - const unsigned int _numVertices, - const Transform4x4f& _trans, - const Blend::Factor _srcBlendFactor, - const Blend::Factor _dstBlendFactor, - const shaderParameters& _parameters) + void drawTriangleStrips(const Vertex* vertices, + const unsigned int numVertices, + const glm::mat4& trans, + const Blend::Factor srcBlendFactor, + const Blend::Factor dstBlendFactor, + const shaderParameters& parameters) { - float width = _vertices[3].pos[0]; - float height = _vertices[3].pos[1]; + float width = vertices[3].pos[0]; + float height = vertices[3].pos[1]; - GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos)); - GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex)); - GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col)); + GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].pos)); + GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].tex)); + GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vertices[0].col)); GL_CHECK_ERROR( - glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor))); + glBlendFunc(convertBlendFactor(srcBlendFactor), convertBlendFactor(dstBlendFactor))); #if defined(USE_OPENGL_21) - if (_vertices[0].shaders == 0) { - GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices)); + if (vertices[0].shaders == 0) { + GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); } else { // If saturation is set below the maximum (default) value, run the // desaturation shader. - if (_vertices->saturation < 1.0f || _parameters.fragmentSaturation < 1.0f) { + if (vertices->saturation < 1.0f || parameters.fragmentSaturation < 1.0f) { Shader* runShader = getShaderProgram(SHADER_DESATURATE); // Only try to use the shader if it has been loaded properly. if (runShader) { runShader->activateShaders(); - runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans); - runShader->setSaturation(_vertices->saturation); - GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices)); + runShader->setModelViewProjectionMatrix(getProjectionMatrix() * trans); + runShader->setSaturation(vertices->saturation); + GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); runShader->deactivateShaders(); } } - if (_vertices->shaders & SHADER_OPACITY) { + if (vertices->shaders & SHADER_OPACITY) { Shader* runShader = getShaderProgram(SHADER_OPACITY); if (runShader) { runShader->activateShaders(); - runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans); - _vertices->opacity < 1.0f ? runShader->setOpacity(_vertices->opacity) : - runShader->setOpacity(_parameters.fragmentOpacity); - GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices)); + runShader->setModelViewProjectionMatrix(getProjectionMatrix() * trans); + vertices->opacity < 1.0f ? runShader->setOpacity(vertices->opacity) : + runShader->setOpacity(parameters.fragmentOpacity); + GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); runShader->deactivateShaders(); } } // Check if any other shaders are set to be used and if so, run them. - if (_vertices->shaders & SHADER_DIM) { + if (vertices->shaders & SHADER_DIM) { Shader* runShader = getShaderProgram(SHADER_DIM); if (runShader) { runShader->activateShaders(); - runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans); - runShader->setDimValue(_parameters.fragmentDimValue); - GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices)); + runShader->setModelViewProjectionMatrix(getProjectionMatrix() * trans); + runShader->setDimValue(parameters.fragmentDimValue); + GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); runShader->deactivateShaders(); } } - if (_vertices->shaders & SHADER_BLUR_HORIZONTAL) { + if (vertices->shaders & SHADER_BLUR_HORIZONTAL) { Shader* runShader = getShaderProgram(SHADER_BLUR_HORIZONTAL); if (runShader) { runShader->activateShaders(); - runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans); - runShader->setTextureSize({ width, height }); - GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices)); + runShader->setModelViewProjectionMatrix(getProjectionMatrix() * trans); + runShader->setTextureSize({width, height}); + GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); runShader->deactivateShaders(); } } - if (_vertices->shaders & SHADER_BLUR_VERTICAL) { + if (vertices->shaders & SHADER_BLUR_VERTICAL) { Shader* runShader = getShaderProgram(SHADER_BLUR_VERTICAL); if (runShader) { runShader->activateShaders(); - runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans); - runShader->setTextureSize({ width, height }); - GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices)); + runShader->setModelViewProjectionMatrix(getProjectionMatrix() * trans); + runShader->setTextureSize({width, height}); + GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); runShader->deactivateShaders(); } } - if (_vertices->shaders & SHADER_SCANLINES) { + if (vertices->shaders & SHADER_SCANLINES) { Shader* runShader = getShaderProgram(SHADER_SCANLINES); float shaderWidth = width * 1.2f; // Scale the scanlines relative to screen resolution. @@ -343,9 +345,9 @@ namespace Renderer } if (runShader) { runShader->activateShaders(); - runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans); - runShader->setTextureSize({ shaderWidth, shaderHeight }); - GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices)); + runShader->setModelViewProjectionMatrix(getProjectionMatrix() * trans); + runShader->setTextureSize({shaderWidth, shaderHeight}); + GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); runShader->deactivateShaders(); } } @@ -353,37 +355,37 @@ namespace Renderer #endif } - void setProjection(const Transform4x4f& _projection) + void setProjection(const glm::mat4& projection) { GL_CHECK_ERROR(glMatrixMode(GL_PROJECTION)); - GL_CHECK_ERROR(glLoadMatrixf(reinterpret_cast(&_projection))); + GL_CHECK_ERROR(glLoadMatrixf(reinterpret_cast(&projection))); } - void setMatrix(const Transform4x4f& _matrix) + void setMatrix(const glm::mat4& matrix) { - Transform4x4f matrix = _matrix; - matrix.round(); + glm::mat4 newMatrix{matrix}; + newMatrix[3] = glm::round(newMatrix[3]); GL_CHECK_ERROR(glMatrixMode(GL_MODELVIEW)); - GL_CHECK_ERROR(glLoadMatrixf(reinterpret_cast(&matrix))); + GL_CHECK_ERROR(glLoadMatrixf(reinterpret_cast(&newMatrix))); } - void setViewport(const Rect& _viewport) + void setViewport(const Rect& viewport) { // glViewport starts at the bottom left of the window. - GL_CHECK_ERROR(glViewport(_viewport.x, getWindowHeight() - _viewport.y - _viewport.h, - _viewport.w, _viewport.h)); + GL_CHECK_ERROR(glViewport(viewport.x, getWindowHeight() - viewport.y - viewport.h, + viewport.w, viewport.h)); } - void setScissor(const Rect& _scissor) + void setScissor(const Rect& scissor) { - if ((_scissor.x == 0) && (_scissor.y == 0) && (_scissor.w == 0) && (_scissor.h == 0)) { + if ((scissor.x == 0) && (scissor.y == 0) && (scissor.w == 0) && (scissor.h == 0)) { GL_CHECK_ERROR(glDisable(GL_SCISSOR_TEST)); } else { // glScissor starts at the bottom left of the window. - GL_CHECK_ERROR(glScissor(_scissor.x, getWindowHeight() - _scissor.y - _scissor.h, - _scissor.w, _scissor.h)); + GL_CHECK_ERROR(glScissor(scissor.x, getWindowHeight() - scissor.y - scissor.h, + scissor.w, scissor.h)); GL_CHECK_ERROR(glEnable(GL_SCISSOR_TEST)); } } @@ -448,8 +450,9 @@ namespace Renderer if (parameters.fragmentSaturation < 1.0) vertices[0].saturation = parameters.fragmentSaturation; - setMatrix(Transform4x4f::Identity()); - GLuint screenTexture = createTexture(Texture::RGBA, false, false, width, height, nullptr); + setMatrix(getIdentity()); + GLuint screenTexture = + createTexture(Texture::RGBA, false, false, false, width, height, nullptr); GL_CHECK_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0)); @@ -475,7 +478,7 @@ namespace Renderer GL_COLOR_BUFFER_BIT, GL_NEAREST)); // Apply/render the shaders. - drawTriangleStrips(vertices, 4, Transform4x4f::Identity(), Blend::SRC_ALPHA, + drawTriangleStrips(vertices, 4, getIdentity(), Blend::SRC_ALPHA, Blend::ONE_MINUS_SRC_ALPHA, parameters); // If textureRGBA has an address, it means that the output should go to this diff --git a/es-core/src/renderers/Renderer_GLES10.cpp b/es-core/src/renderers/Renderer_GLES10.cpp index a179ca5fe..2d16db771 100644 --- a/es-core/src/renderers/Renderer_GLES10.cpp +++ b/es-core/src/renderers/Renderer_GLES10.cpp @@ -10,7 +10,6 @@ #include "Log.h" #include "Settings.h" -#include "math/Transform4x4f.h" #include "renderers/Renderer.h" #include @@ -91,8 +90,8 @@ namespace Renderer << (extensions.find("GL_OES_texture_npot") != std::string::npos ? "OK" : "MISSING"); - uint8_t data[4] = { 255, 255, 255, 255 }; - whiteTexture = createTexture(Texture::RGBA, false, true, 1, 1, data); + uint8_t data[4] = {255, 255, 255, 255}; + whiteTexture = createTexture(Texture::RGBA, false, false, true, 1, 1, data); GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D)); @@ -112,125 +111,127 @@ namespace Renderer sdlContext = nullptr; } - unsigned int createTexture(const Texture::Type _type, - const bool _linear, - const bool _repeat, - const unsigned int _width, - const unsigned int _height, - void* _data) + unsigned int createTexture(const Texture::Type type, + const bool linearMinify, + const bool linearMagnify, + const bool repeat, + const unsigned int width, + const unsigned int height, + void* data) { - const GLenum type = convertTextureType(_type); + const GLenum textureType = convertTextureType(type); unsigned int texture; GL_CHECK_ERROR(glGenTextures(1, &texture)); GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - _repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE)); + repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE)); GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - _repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE)); + repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE)); GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - _linear ? GL_LINEAR : GL_NEAREST)); - GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + linearMinify ? GL_LINEAR : GL_NEAREST)); + GL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + linearMagnify ? GL_LINEAR : GL_NEAREST)); - GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, type, _width, _height, 0, type, - GL_UNSIGNED_BYTE, _data)); + GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, textureType, + GL_UNSIGNED_BYTE, data)); return texture; } - void destroyTexture(const unsigned int _texture) + void destroyTexture(const unsigned int texture) { - GL_CHECK_ERROR(glDeleteTextures(1, &_texture)); + GL_CHECK_ERROR(glDeleteTextures(1, &texture)); } - void updateTexture(const unsigned int _texture, - const Texture::Type _type, - const unsigned int _x, - const unsigned _y, - const unsigned int _width, - const unsigned int _height, - void* _data) + void updateTexture(const unsigned int texture, + const Texture::Type type, + const unsigned int x, + const unsigned y, + const unsigned int width, + const unsigned int height, + void* data) { - const GLenum type = convertTextureType(_type); + const GLenum textureType = convertTextureType(type); - GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture)); - GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, _x, _y, _width, _height, type, - GL_UNSIGNED_BYTE, _data)); + GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); + GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, textureType, + GL_UNSIGNED_BYTE, data)); GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture)); } - void bindTexture(const unsigned int _texture) + void bindTexture(const unsigned int texture) { - if (_texture == 0) + if (texture == 0) GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture)); else - GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, _texture)); + GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); } - void drawLines(const Vertex* _vertices, - const unsigned int _numVertices, - const Blend::Factor _srcBlendFactor, - const Blend::Factor _dstBlendFactor) + void drawLines(const Vertex* vertices, + const unsigned int numVertices, + const Blend::Factor srcBlendFactor, + const Blend::Factor dstBlendFactor) { - GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos)); - GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex)); - GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col)); + GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].pos)); + GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].tex)); + GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vertices[0].col)); GL_CHECK_ERROR( - glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor))); + glBlendFunc(convertBlendFactor(srcBlendFactor), convertBlendFactor(dstBlendFactor))); - GL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, _numVertices)); + GL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, numVertices)); } - void drawTriangleStrips(const Vertex* _vertices, - const unsigned int _numVertices, - const Transform4x4f& _trans, - const Blend::Factor _srcBlendFactor, - const Blend::Factor _dstBlendFactor, - const shaderParameters& _parameters) + void drawTriangleStrips(const Vertex* vertices, + const unsigned int numVertices, + const glm::mat4& trans, + const Blend::Factor srcBlendFactor, + const Blend::Factor dstBlendFactor, + const shaderParameters& parameters) { - GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos)); - GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex)); - GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col)); + GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].pos)); + GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].tex)); + GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vertices[0].col)); GL_CHECK_ERROR( - glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor))); + glBlendFunc(convertBlendFactor(srcBlendFactor), convertBlendFactor(dstBlendFactor))); - GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices)); + GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); } - void setProjection(const Transform4x4f& _projection) + void setProjection(const glm::mat4& projection) { GL_CHECK_ERROR(glMatrixMode(GL_PROJECTION)); - GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&_projection)); + GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&projection)); } - void setMatrix(const Transform4x4f& _matrix) + void setMatrix(const glm::mat4& matrix) { - Transform4x4f matrix = _matrix; - matrix.round(); + glm::mat4 newMatrix{matrix}; + newMatrix[3] = glm::round(newMatrix[3]); GL_CHECK_ERROR(glMatrixMode(GL_MODELVIEW)); - GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&matrix)); + GL_CHECK_ERROR(glLoadMatrixf((GLfloat*)&newMatrix)); } - void setViewport(const Rect& _viewport) + void setViewport(const Rect& viewport) { // glViewport starts at the bottom left of the window. - GL_CHECK_ERROR(glViewport(_viewport.x, getWindowHeight() - _viewport.y - _viewport.h, - _viewport.w, _viewport.h)); + GL_CHECK_ERROR(glViewport(viewport.x, getWindowHeight() - viewport.y - viewport.h, + viewport.w, viewport.h)); } - void setScissor(const Rect& _scissor) + void setScissor(const Rect& scissor) { - if ((_scissor.x == 0) && (_scissor.y == 0) && (_scissor.w == 0) && (_scissor.h == 0)) { + if ((scissor.x == 0) && (scissor.y == 0) && (scissor.w == 0) && (scissor.h == 0)) { GL_CHECK_ERROR(glDisable(GL_SCISSOR_TEST)); } else { // glScissor starts at the bottom left of the window. - GL_CHECK_ERROR(glScissor(_scissor.x, getWindowHeight() - _scissor.y - _scissor.h, - _scissor.w, _scissor.h)); + GL_CHECK_ERROR(glScissor(scissor.x, getWindowHeight() - scissor.y - scissor.h, + scissor.w, scissor.h)); GL_CHECK_ERROR(glEnable(GL_SCISSOR_TEST)); } } diff --git a/es-core/src/renderers/Shader_GL21.cpp b/es-core/src/renderers/Shader_GL21.cpp index 52d376e53..edd2df610 100644 --- a/es-core/src/renderers/Shader_GL21.cpp +++ b/es-core/src/renderers/Shader_GL21.cpp @@ -114,7 +114,7 @@ namespace Renderer shaderDimValue = glGetUniformLocation(mProgramID, "dimValue"); } - void Renderer::Shader::setModelViewProjectionMatrix(Transform4x4f mvpMatrix) + void Renderer::Shader::setModelViewProjectionMatrix(glm::mat4 mvpMatrix) { if (shaderMVPMatrix != -1) GL_CHECK_ERROR(glUniformMatrix4fv(shaderMVPMatrix, 1, GL_FALSE, @@ -184,7 +184,7 @@ namespace Renderer glGetProgramInfoLog(programID, maxLength, &logLength, &infoLog.front()); if (logLength > 0) { - LOG(LogDebug) << "Renderer_GL21::printProgramLog():\n" + LOG(LogDebug) << "Renderer_GL21::printProgramInfoLog():\n" << std::string(infoLog.begin(), infoLog.end()); } } @@ -205,7 +205,7 @@ namespace Renderer glGetShaderInfoLog(shaderID, maxLength, &logLength, &infoLog.front()); if (logLength > 0) { - LOG(LogDebug) << "Renderer_GL21::printShaderLog(): Error in " + LOG(LogDebug) << "Renderer_GL21::printShaderInfoLog(): Error in " << (shaderType == GL_VERTEX_SHADER ? "VERTEX section:\n" : "FRAGMENT section:\n") << std::string(infoLog.begin(), infoLog.end()); diff --git a/es-core/src/renderers/Shader_GL21.h b/es-core/src/renderers/Shader_GL21.h index f9e0a970c..764a28af6 100644 --- a/es-core/src/renderers/Shader_GL21.h +++ b/es-core/src/renderers/Shader_GL21.h @@ -11,7 +11,7 @@ #define GL_GLEXT_PROTOTYPES -#include "math/Transform4x4f.h" +#include "utils/MathUtil.h" #if defined(_WIN64) #include @@ -45,7 +45,8 @@ namespace Renderer // Get references to the variables inside the compiled shaders. void getVariableLocations(GLuint programID); // One-way communication with the compiled shaders. - void setModelViewProjectionMatrix(Transform4x4f mvpMatrix); + void setModelViewProjectionMatrix(glm::mat4 mvpMatrix); + void setTextureSize(std::array shaderVec2); void setTextureCoordinates(std::array shaderVec4); void setColor(std::array shaderVec4); diff --git a/es-core/src/resources/Font.cpp b/es-core/src/resources/Font.cpp index 59011ce8f..e96bf3673 100644 --- a/es-core/src/resources/Font.cpp +++ b/es-core/src/resources/Font.cpp @@ -49,7 +49,7 @@ size_t Font::getMemUsage() const { size_t memUsage = 0; for (auto it = mTextures.cbegin(); it != mTextures.cend(); it++) - memUsage += it->textureSize.x() * it->textureSize.y() * 4; + memUsage += it->textureSize.x * it->textureSize.y * 4; for (auto it = mFaceCache.cbegin(); it != mFaceCache.cend(); it++) memUsage += it->second->data.length; @@ -137,8 +137,8 @@ Font::FontTexture::FontTexture(const int mSize) // I'm not entirely sure if the 16 and 6 constants are correct, but they seem to provide // a texture buffer large enough to hold the fonts (otherwise the application would crash). // This logic is obviously a hack though and needs to be properly reviewed and improved. - textureSize = Vector2i(mSize * 16, mSize * 6); - writePos = Vector2i::Zero(); + textureSize = glm::ivec2{mSize * 16, mSize * 6}; + writePos = glm::ivec2{}; rowHeight = 0; } @@ -148,28 +148,30 @@ Font::FontTexture::~FontTexture() deinitTexture(); } -bool Font::FontTexture::findEmpty(const Vector2i& size, Vector2i& cursor_out) +bool Font::FontTexture::findEmpty(const glm::ivec2& size, glm::ivec2& cursor_out) { - if (size.x() >= textureSize.x() || size.y() >= textureSize.y()) + if (size.x >= textureSize.x || size.y >= textureSize.y) return false; - if (writePos.x() + size.x() >= textureSize.x() && - writePos.y() + rowHeight + size.y() + 1 < textureSize.y()) { + if (writePos.x + size.x >= textureSize.x && + writePos.y + rowHeight + size.y + 1 < textureSize.y) { // Row full, but it should fit on the next row so move the cursor there. - writePos = Vector2i(0, writePos.y() + rowHeight + 1); // Leave 1px of space between glyphs. + // Leave 1px of space between glyphs. + writePos = glm::ivec2{0, writePos.y + rowHeight + 1}; rowHeight = 0; } - if (writePos.x() + size.x() >= textureSize.x() || writePos.y() + size.y() >= textureSize.y()) { + if (writePos.x + size.x >= textureSize.x || writePos.y + size.y >= textureSize.y) { // Nope, still won't fit. return false; } cursor_out = writePos; - writePos[0] += size.x() + 1; // Leave 1px of space between glyphs. + // Leave 1px of space between glyphs. + writePos.x += size.x + 1; - if (size.y() > rowHeight) - rowHeight = size.y(); + if (size.y > rowHeight) + rowHeight = size.y; return true; } @@ -177,8 +179,8 @@ bool Font::FontTexture::findEmpty(const Vector2i& size, Vector2i& cursor_out) void Font::FontTexture::initTexture() { assert(textureId == 0); - textureId = Renderer::createTexture(Renderer::Texture::ALPHA, false, false, textureSize.x(), - textureSize.y(), nullptr); + textureId = Renderer::createTexture(Renderer::Texture::ALPHA, false, false, false, + textureSize.x, textureSize.y, nullptr); } void Font::FontTexture::deinitTexture() @@ -189,9 +191,9 @@ void Font::FontTexture::deinitTexture() } } -void Font::getTextureForNewGlyph(const Vector2i& glyphSize, +void Font::getTextureForNewGlyph(const glm::ivec2& glyphSize, FontTexture*& tex_out, - Vector2i& cursor_out) + glm::ivec2& cursor_out) { if (mTextures.size()) { // Check if the most recent texture has space. @@ -210,7 +212,7 @@ void Font::getTextureForNewGlyph(const Vector2i& glyphSize, bool ok = tex_out->findEmpty(glyphSize, cursor_out); if (!ok) { LOG(LogError) << "Glyph too big to fit on a new texture (glyph size > " - << tex_out->textureSize.x() << ", " << tex_out->textureSize.y() << ")"; + << tex_out->textureSize.x << ", " << tex_out->textureSize.y << ")"; tex_out = nullptr; } } @@ -223,6 +225,7 @@ std::vector getFallbackFontPaths() // not really the correct location. (The application will crash if they are missing.) ResourceManager::getInstance()->getResourcePath(":/fonts/Akrobat-Regular.ttf"); ResourceManager::getInstance()->getResourcePath(":/fonts/Akrobat-SemiBold.ttf"); + ResourceManager::getInstance()->getResourcePath(":/fonts/Akrobat-Bold.ttf"); // Vera sans Unicode. fontPaths.push_back(ResourceManager::getInstance()->getResourcePath(":/fonts/DejaVuSans.ttf")); @@ -296,10 +299,10 @@ Font::Glyph* Font::getGlyph(unsigned int id) return nullptr; } - Vector2i glyphSize(g->bitmap.width, g->bitmap.rows); + glm::ivec2 glyphSize{g->bitmap.width, g->bitmap.rows}; FontTexture* tex = nullptr; - Vector2i cursor; + glm::ivec2 cursor; getTextureForNewGlyph(glyphSize, tex, cursor); // getTextureForNewGlyph can fail if the glyph is bigger than the max texture @@ -314,23 +317,23 @@ Font::Glyph* Font::getGlyph(unsigned int id) Glyph& glyph = mGlyphMap[id]; glyph.texture = tex; - glyph.texPos = Vector2f(cursor.x() / static_cast(tex->textureSize.x()), - cursor.y() / static_cast(tex->textureSize.y())); - glyph.texSize = Vector2f(glyphSize.x() / static_cast(tex->textureSize.x()), - glyphSize.y() / static_cast(tex->textureSize.y())); + glyph.texPos = glm::vec2{cursor.x / static_cast(tex->textureSize.x), + cursor.y / static_cast(tex->textureSize.y)}; + glyph.texSize = glm::vec2{glyphSize.x / static_cast(tex->textureSize.x), + glyphSize.y / static_cast(tex->textureSize.y)}; - glyph.advance = Vector2f(static_cast(g->metrics.horiAdvance) / 64.0f, - static_cast(g->metrics.vertAdvance) / 64.0f); - glyph.bearing = Vector2f(static_cast(g->metrics.horiBearingX) / 64.0f, - static_cast(g->metrics.horiBearingY) / 64.0f); + glyph.advance = glm::vec2{static_cast(g->metrics.horiAdvance) / 64.0f, + static_cast(g->metrics.vertAdvance) / 64.0f}; + glyph.bearing = glm::vec2{static_cast(g->metrics.horiBearingX) / 64.0f, + static_cast(g->metrics.horiBearingY) / 64.0f}; // Upload glyph bitmap to texture. - Renderer::updateTexture(tex->textureId, Renderer::Texture::ALPHA, cursor.x(), cursor.y(), - glyphSize.x(), glyphSize.y(), g->bitmap.buffer); + Renderer::updateTexture(tex->textureId, Renderer::Texture::ALPHA, cursor.x, cursor.y, + glyphSize.x, glyphSize.y, g->bitmap.buffer); // Update max glyph height. - if (glyphSize.y() > mMaxGlyphHeight) - mMaxGlyphHeight = glyphSize.y(); + if (glyphSize.y > mMaxGlyphHeight) + mMaxGlyphHeight = glyphSize.y; // Done. return &glyph; @@ -354,14 +357,14 @@ void Font::rebuildTextures() FontTexture* tex = it->second.texture; // Find the position/size. - Vector2i cursor(static_cast(it->second.texPos.x() * tex->textureSize.x()), - static_cast(it->second.texPos.y() * tex->textureSize.y())); - Vector2i glyphSize(static_cast(it->second.texSize.x() * tex->textureSize.x()), - static_cast(it->second.texSize.y() * tex->textureSize.y())); + glm::ivec2 cursor{static_cast(it->second.texPos.x * tex->textureSize.x), + static_cast(it->second.texPos.y * tex->textureSize.y)}; + glm::ivec2 glyphSize{static_cast(it->second.texSize.x * tex->textureSize.x), + static_cast(it->second.texSize.y * tex->textureSize.y)}; // Upload to texture. - Renderer::updateTexture(tex->textureId, Renderer::Texture::ALPHA, cursor.x(), cursor.y(), - glyphSize.x(), glyphSize.y(), glyphSlot->bitmap.buffer); + Renderer::updateTexture(tex->textureId, Renderer::Texture::ALPHA, cursor.x, cursor.y, + glyphSize.x, glyphSize.y, glyphSlot->bitmap.buffer); } } @@ -383,7 +386,7 @@ void Font::renderTextCache(TextCache* cache) } } -Vector2f Font::sizeText(std::string text, float lineSpacing) +glm::vec2 Font::sizeText(std::string text, float lineSpacing) { float lineWidth = 0.0f; float highestWidth = 0.0f; @@ -406,21 +409,21 @@ Vector2f Font::sizeText(std::string text, float lineSpacing) Glyph* glyph = getGlyph(character); if (glyph) - lineWidth += glyph->advance.x(); + lineWidth += glyph->advance.x; } if (lineWidth > highestWidth) highestWidth = lineWidth; - return Vector2f(highestWidth, y); + return glm::vec2{highestWidth, y}; } std::string Font::getTextMaxWidth(std::string text, float maxWidth) { - float width = sizeText(text).x(); + float width = sizeText(text).x; while (width > maxWidth) { text.pop_back(); - width = sizeText(text).x(); + width = sizeText(text).x; } return text; } @@ -435,7 +438,7 @@ float Font::getLetterHeight() { Glyph* glyph = getGlyph('S'); assert(glyph); - return glyph->texSize.y() * glyph->texture->textureSize.y(); + return glyph->texSize.y * glyph->texture->textureSize.y; } // Breaks up a normal string with newlines to make it fit xLen. @@ -448,8 +451,8 @@ std::string Font::wrapText(std::string text, float xLen) std::string temp; size_t space; - Vector2f textSize; - float dotsSize = sizeText("...").x(); + glm::vec2 textSize; + float dotsSize = sizeText("...").x; // While there's text or we still have text to render. while (text.length() > 0) { @@ -465,7 +468,7 @@ std::string Font::wrapText(std::string text, float xLen) textSize = sizeText(temp); // If the word will fit on the line, add it to our line, and continue. - if (textSize.x() <= xLen) { + if (textSize.x <= xLen) { line = temp; continue; } @@ -473,7 +476,7 @@ std::string Font::wrapText(std::string text, float xLen) // The next word won't fit, so break here. // If the word is too long to fit within xLen, then abbreviate it. - if (xLen > 0 && sizeText(word).x() > xLen) { + if (xLen > 0 && sizeText(word).x > xLen) { float length = xLen - dotsSize; if (length < 0) length = 0; @@ -495,16 +498,16 @@ std::string Font::wrapText(std::string text, float xLen) return out; } -Vector2f Font::sizeWrappedText(std::string text, float xLen, float lineSpacing) +glm::vec2 Font::sizeWrappedText(std::string text, float xLen, float lineSpacing) { text = wrapText(text, xLen); return sizeText(text, lineSpacing); } -Vector2f Font::getWrappedTextCursorOffset(std::string text, - float xLen, - size_t stop, - float lineSpacing) +glm::vec2 Font::getWrappedTextCursorOffset(std::string text, + float xLen, + size_t stop, + float lineSpacing) { std::string wrappedText = wrapText(text, xLen); @@ -535,10 +538,10 @@ Vector2f Font::getWrappedTextCursorOffset(std::string text, Glyph* glyph = getGlyph(character); if (glyph) - lineWidth += glyph->advance.x(); + lineWidth += glyph->advance.x; } - return Vector2f(lineWidth, y); + return glm::vec2{lineWidth, y}; } // @@ -560,7 +563,7 @@ float Font::getNewlineStartOffset(const std::string& text, return (xLen - sizeText(text.substr(charStart, endChar != std::string::npos ? endChar - charStart : endChar)) - .x()) / + .x) / 2.0f; } case ALIGN_RIGHT: { @@ -568,7 +571,7 @@ float Font::getNewlineStartOffset(const std::string& text, return xLen - (sizeText(text.substr(charStart, endChar != std::string::npos ? endChar - charStart : endChar)) - .x()); + .x); } default: return 0; @@ -576,7 +579,7 @@ float Font::getNewlineStartOffset(const std::string& text, } TextCache* Font::buildTextCache(const std::string& text, - Vector2f offset, + glm::vec2 offset, unsigned int color, float xLen, Alignment alignment, @@ -592,7 +595,7 @@ TextCache* Font::buildTextCache(const std::string& text, yBot = getHeight(1.5); } else { - yTop = getGlyph('S')->bearing.y(); + yTop = getGlyph('S')->bearing.y; yBot = getHeight(lineSpacing); } @@ -631,44 +634,41 @@ TextCache* Font::buildTextCache(const std::string& text, verts.resize(oldVertSize + 6); Renderer::Vertex* vertices = verts.data() + oldVertSize; - const float glyphStartX = x + glyph->bearing.x(); - const Vector2i& textureSize = glyph->texture->textureSize; + const float glyphStartX{x + glyph->bearing.x}; + const glm::ivec2& textureSize{glyph->texture->textureSize}; const unsigned int convertedColor = Renderer::convertRGBAToABGR(color); - vertices[1] = { { glyphStartX, y - glyph->bearing.y() }, - { glyph->texPos.x(), glyph->texPos.y() }, - convertedColor }; - vertices[2] = { { glyphStartX, - y - glyph->bearing.y() + (glyph->texSize.y() * textureSize.y()) }, - { glyph->texPos.x(), glyph->texPos.y() + glyph->texSize.y() }, - convertedColor }; - vertices[3] = { { glyphStartX + glyph->texSize.x() * textureSize.x(), - y - glyph->bearing.y() }, - { glyph->texPos.x() + glyph->texSize.x(), glyph->texPos.y() }, - convertedColor }; - vertices[4] = { { glyphStartX + glyph->texSize.x() * textureSize.x(), - y - glyph->bearing.y() + (glyph->texSize.y() * textureSize.y()) }, - { glyph->texPos.x() + glyph->texSize.x(), - glyph->texPos.y() + glyph->texSize.y() }, - convertedColor }; + vertices[1] = {{glyphStartX, y - glyph->bearing.y}, + {glyph->texPos.x, glyph->texPos.y}, + convertedColor}; + vertices[2] = {{glyphStartX, y - glyph->bearing.y + (glyph->texSize.y * textureSize.y)}, + {glyph->texPos.x, glyph->texPos.y + glyph->texSize.y}, + convertedColor}; + vertices[3] = {{glyphStartX + glyph->texSize.x * textureSize.x, y - glyph->bearing.y}, + {glyph->texPos.x + glyph->texSize.x, glyph->texPos.y}, + convertedColor}; + vertices[4] = {{glyphStartX + glyph->texSize.x * textureSize.x, + y - glyph->bearing.y + (glyph->texSize.y * textureSize.y)}, + {glyph->texPos.x + glyph->texSize.x, glyph->texPos.y + glyph->texSize.y}, + convertedColor}; // Round vertices. for (int i = 1; i < 5; i++) - vertices[i].pos.round(); + vertices[i].pos = glm::round(vertices[i].pos); // Make duplicates of first and last vertex so this can be rendered as a triangle strip. vertices[0] = vertices[1]; vertices[5] = vertices[4]; // Advance. - x += glyph->advance.x(); + x += glyph->advance.x; } // TextCache::CacheMetrics metrics = { sizeText(text, lineSpacing) }; TextCache* cache = new TextCache(); cache->vertexLists.resize(vertMap.size()); - cache->metrics = { sizeText(text, lineSpacing) }; + cache->metrics = {sizeText(text, lineSpacing)}; unsigned int i = 0; for (auto it = vertMap.cbegin(); it != vertMap.cend(); it++) { @@ -689,7 +689,7 @@ TextCache* Font::buildTextCache(const std::string& text, float lineSpacing, bool noTopMargin) { - return buildTextCache(text, Vector2f(offsetX, offsetY), color, 0.0f, ALIGN_LEFT, lineSpacing, + return buildTextCache(text, glm::vec2{offsetX, offsetY}, color, 0.0f, ALIGN_LEFT, lineSpacing, noTopMargin); } diff --git a/es-core/src/resources/Font.h b/es-core/src/resources/Font.h index 63bc3a757..30a24c872 100644 --- a/es-core/src/resources/Font.h +++ b/es-core/src/resources/Font.h @@ -11,8 +11,6 @@ #define ES_CORE_RESOURCES_FONT_H #include "ThemeData.h" -#include "math/Vector2f.h" -#include "math/Vector2i.h" #include "renderers/Renderer.h" #include "resources/ResourceManager.h" @@ -35,6 +33,7 @@ class TextCache; #define FONT_PATH_LIGHT ":/fonts/Akrobat-Regular.ttf" #define FONT_PATH_REGULAR ":/fonts/Akrobat-SemiBold.ttf" +#define FONT_PATH_BOLD ":/fonts/Akrobat-Bold.ttf" enum Alignment { ALIGN_LEFT, @@ -54,7 +53,7 @@ public: static std::shared_ptr get(int size, const std::string& path = getDefaultPath()); // Returns the expected size of a string when rendered. Extra spacing is applied to the Y axis. - Vector2f sizeText(std::string text, float lineSpacing = 1.5f); + glm::vec2 sizeText(std::string text, float lineSpacing = 1.5f); // Returns the portion of a string that fits within the passed argument maxWidth. std::string getTextMaxWidth(std::string text, float maxWidth); @@ -67,7 +66,7 @@ public: bool noTopMargin = false); TextCache* buildTextCache(const std::string& text, - Vector2f offset, + glm::vec2 offset, unsigned int color, float xLen, Alignment alignment = ALIGN_LEFT, @@ -80,13 +79,13 @@ public: std::string wrapText(std::string text, float xLen); // Returns the expected size of a string after wrapping is applied. - Vector2f sizeWrappedText(std::string text, float xLen, float lineSpacing = 1.5f); + glm::vec2 sizeWrappedText(std::string text, float xLen, float lineSpacing = 1.5f); // Returns the position of the cursor after moving a "cursor" amount of characters. - Vector2f getWrappedTextCursorOffset(std::string text, - float xLen, - size_t cursor, - float lineSpacing = 1.5f); + glm::vec2 getWrappedTextCursorOffset(std::string text, + float xLen, + size_t cursor, + float lineSpacing = 1.5f); float getHeight(float lineSpacing = 1.5f) const; float getLetterHeight(); @@ -115,14 +114,14 @@ private: struct FontTexture { unsigned int textureId; - Vector2i textureSize; + glm::ivec2 textureSize; - Vector2i writePos; + glm::ivec2 writePos; int rowHeight; FontTexture(const int mSize); ~FontTexture(); - bool findEmpty(const Vector2i& size, Vector2i& cursor_out); + bool findEmpty(const glm::ivec2& size, glm::ivec2& cursor_out); // You must call initTexture() after creating a FontTexture to get a textureId. // Initializes the OpenGL texture according to this FontTexture's settings, @@ -147,9 +146,9 @@ private: std::vector mTextures; - void getTextureForNewGlyph(const Vector2i& glyphSize, + void getTextureForNewGlyph(const glm::ivec2& glyphSize, FontTexture*& tex_out, - Vector2i& cursor_out); + glm::ivec2& cursor_out); std::map> mFaceCache; FT_Face getFaceForChar(unsigned int id); @@ -158,11 +157,11 @@ private: struct Glyph { FontTexture* texture; - Vector2f texPos; - Vector2f texSize; // In texels! + glm::vec2 texPos; + glm::vec2 texSize; // In texels. - Vector2f advance; - Vector2f bearing; + glm::vec2 advance; + glm::vec2 bearing; }; std::map mGlyphMap; @@ -202,7 +201,7 @@ protected: public: struct CacheMetrics { - Vector2f size; + glm::vec2 size; } metrics; void setColor(unsigned int color); diff --git a/es-core/src/resources/ResourceManager.cpp b/es-core/src/resources/ResourceManager.cpp index e61d69ea9..0f4072b09 100644 --- a/es-core/src/resources/ResourceManager.cpp +++ b/es-core/src/resources/ResourceManager.cpp @@ -107,7 +107,7 @@ const ResourceData ResourceManager::getFileData(const std::string& path) const } // If the file doesn't exist, return an "empty" ResourceData. - ResourceData data = { nullptr, 0 }; + ResourceData data = {nullptr, 0}; return data; } @@ -128,7 +128,7 @@ ResourceData ResourceManager::loadFile(const std::string& path) const stream.read(reinterpret_cast(data.get()), size); stream.close(); - ResourceData ret = { data, size }; + ResourceData ret = {data, size}; return ret; } diff --git a/es-core/src/resources/TextureData.cpp b/es-core/src/resources/TextureData.cpp index 58b114c4e..65e715512 100644 --- a/es-core/src/resources/TextureData.cpp +++ b/es-core/src/resources/TextureData.cpp @@ -13,7 +13,6 @@ #include "ImageIO.h" #include "Log.h" -#include "math/Misc.h" #include "renderers/Renderer.h" #include "resources/ResourceManager.h" @@ -29,6 +28,7 @@ TextureData::TextureData(bool tile) , mDataRGBA({}) , mScaleDuringLoad(1.0f) , mScalable(false) + , mLinearMagnify(false) , mWidth(0) , mHeight(0) , mSourceWidth(0.0f) @@ -197,9 +197,10 @@ bool TextureData::uploadAndBind() return false; // Upload texture. - mTextureID = Renderer::createTexture( - Renderer::Texture::RGBA, true, mTile, static_cast(mWidth), - static_cast(mHeight), mDataRGBA.data()); + mTextureID = + Renderer::createTexture(Renderer::Texture::RGBA, true, mLinearMagnify, mTile, + static_cast(mWidth), + static_cast(mHeight), mDataRGBA.data()); } return true; } diff --git a/es-core/src/resources/TextureData.h b/es-core/src/resources/TextureData.h index d038f0123..ebb27b3e8 100644 --- a/es-core/src/resources/TextureData.h +++ b/es-core/src/resources/TextureData.h @@ -56,6 +56,8 @@ public: // Define a factor for scaling the file when loading it (1.0f = no scaling). void setScaleDuringLoad(float scale) { mScaleDuringLoad = scale; } + // Whether to use linear filtering when magnifying the texture. + void setLinearMagnify(bool setting) { mLinearMagnify = setting; } std::vector getRawRGBAData() { return mDataRGBA; } std::string getTextureFilePath() { return mPath; } @@ -73,6 +75,7 @@ private: float mSourceHeight; float mScaleDuringLoad; bool mScalable; + bool mLinearMagnify; bool mReloadable; }; diff --git a/es-core/src/resources/TextureResource.cpp b/es-core/src/resources/TextureResource.cpp index 268a98e52..33fec7e8a 100644 --- a/es-core/src/resources/TextureResource.cpp +++ b/es-core/src/resources/TextureResource.cpp @@ -16,10 +16,8 @@ std::map> TextureResource::sTextureMap; std::set TextureResource::sAllTextures; -TextureResource::TextureResource(const std::string& path, - bool tile, - bool dynamic, - float scaleDuringLoad) +TextureResource::TextureResource( + const std::string& path, bool tile, bool dynamic, bool linearMagnify, float scaleDuringLoad) : mTextureData(nullptr) , mForceLoad(false) { @@ -33,6 +31,7 @@ TextureResource::TextureResource(const std::string& path, data->initFromPath(path); if (scaleDuringLoad != 1.0f) data->setScaleDuringLoad(scaleDuringLoad); + data->setLinearMagnify(linearMagnify); // Force the texture manager to load it using a blocking load. sTextureDataManager.load(data, true); } @@ -42,19 +41,20 @@ TextureResource::TextureResource(const std::string& path, data->initFromPath(path); if (scaleDuringLoad != 1.0f) data->setScaleDuringLoad(scaleDuringLoad); + data->setLinearMagnify(linearMagnify); // Load it so we can read the width/height. data->load(); } - mSize = Vector2i(static_cast(data->width()), static_cast(data->height())); - mSourceSize = Vector2f(data->sourceWidth(), data->sourceHeight()); + mSize = glm::ivec2{static_cast(data->width()), static_cast(data->height())}; + mSourceSize = glm::vec2{data->sourceWidth(), data->sourceHeight()}; } else { // Create a texture managed by this class because it cannot be dynamically // loaded and unloaded. This would normally be a video texture, where the player // reserves a texture to later be used for the video rendering. mTextureData = std::shared_ptr(new TextureData(tile)); - mSize = Vector2i(0, 0); + mSize = glm::ivec2{}; } sAllTextures.insert(this); } @@ -75,8 +75,8 @@ void TextureResource::initFromPixels(const unsigned char* dataRGBA, size_t width mTextureData->releaseRAM(); mTextureData->initFromRGBA(dataRGBA, width, height); // Cache the image dimensions. - mSize = Vector2i(static_cast(width), static_cast(height)); - mSourceSize = Vector2f(mTextureData->sourceWidth(), mTextureData->sourceHeight()); + mSize = glm::ivec2{static_cast(width), static_cast(height)}; + mSourceSize = glm::vec2{mTextureData->sourceWidth(), mTextureData->sourceHeight()}; } void TextureResource::initFromMemory(const char* data, size_t length) @@ -87,9 +87,9 @@ void TextureResource::initFromMemory(const char* data, size_t length) mTextureData->releaseRAM(); mTextureData->initImageFromMemory(reinterpret_cast(data), length); // Get the size from the texture data. - mSize = - Vector2i(static_cast(mTextureData->width()), static_cast(mTextureData->height())); - mSourceSize = Vector2f(mTextureData->sourceWidth(), mTextureData->sourceHeight()); + mSize = glm::ivec2{static_cast(mTextureData->width()), + static_cast(mTextureData->height())}; + mSourceSize = glm::vec2{mTextureData->sourceWidth(), mTextureData->sourceHeight()}; } void TextureResource::manualUnload(std::string path, bool tile) @@ -143,14 +143,19 @@ bool TextureResource::bind() } } -std::shared_ptr TextureResource::get( - const std::string& path, bool tile, bool forceLoad, bool dynamic, float scaleDuringLoad) +std::shared_ptr TextureResource::get(const std::string& path, + bool tile, + bool forceLoad, + bool dynamic, + bool linearMagnify, + float scaleDuringLoad) { std::shared_ptr& rm = ResourceManager::getInstance(); const std::string canonicalPath = Utils::FileSystem::getCanonicalPath(path); if (canonicalPath.empty()) { - std::shared_ptr tex(new TextureResource("", tile, false, scaleDuringLoad)); + std::shared_ptr tex( + new TextureResource("", tile, false, linearMagnify, scaleDuringLoad)); // Make sure we get properly deinitialized even though we do nothing on reinitialization. rm->addReloadable(tex); return tex; @@ -167,7 +172,7 @@ std::shared_ptr TextureResource::get( // Need to create it. std::shared_ptr tex; tex = std::shared_ptr( - new TextureResource(key.first, tile, dynamic, scaleDuringLoad)); + new TextureResource(key.first, tile, dynamic, linearMagnify, scaleDuringLoad)); std::shared_ptr data = sTextureDataManager.get(tex.get()); // Is it an SVG? @@ -197,7 +202,7 @@ void TextureResource::rasterizeAt(size_t width, size_t height) data = mTextureData; else data = sTextureDataManager.get(this); - mSourceSize = Vector2f(static_cast(width), static_cast(height)); + mSourceSize = glm::vec2{static_cast(width), static_cast(height)}; data->setSourceSize(static_cast(width), static_cast(height)); if (mForceLoad || (mTextureData != nullptr)) data->load(); @@ -220,11 +225,11 @@ size_t TextureResource::getTotalMemUsage() size_t TextureResource::getTotalTextureSize() { - size_t total = 0; + size_t total{0}; // Count up all textures that manage their own texture data. for (auto tex : sAllTextures) { if (tex->mTextureData != nullptr) - total += tex->getSize().x() * tex->getSize().y() * 4; + total += tex->getSize().x * tex->getSize().y * 4; } // Now get the total memory from the manager. total += sTextureDataManager.getTotalSize(); diff --git a/es-core/src/resources/TextureResource.h b/es-core/src/resources/TextureResource.h index ef0eae958..223d60fcc 100644 --- a/es-core/src/resources/TextureResource.h +++ b/es-core/src/resources/TextureResource.h @@ -9,10 +9,9 @@ #ifndef ES_CORE_RESOURCES_TEXTURE_RESOURCE_H #define ES_CORE_RESOURCES_TEXTURE_RESOURCE_H -#include "math/Vector2f.h" -#include "math/Vector2i.h" #include "resources/ResourceManager.h" #include "resources/TextureDataManager.h" +#include "utils/MathUtil.h" #include #include @@ -30,6 +29,7 @@ public: bool tile = false, bool forceLoad = false, bool dynamic = true, + bool linearMagnify = false, float scaleDuringLoad = 1.0f); void initFromPixels(const unsigned char* dataRGBA, size_t width, size_t height); virtual void initFromMemory(const char* data, size_t length); @@ -45,14 +45,14 @@ public: // situations. An alternative is to set a scaling factor directly when loading the texture // using get(), by using the scaleDuringLoad parameter (which also works for raster graphics). void rasterizeAt(size_t width, size_t height); - Vector2f getSourceImageSize() const { return mSourceSize; } + glm::vec2 getSourceImageSize() const { return mSourceSize; } virtual ~TextureResource(); bool isInitialized() const { return true; } bool isTiled() const; - const Vector2i getSize() const { return mSize; } + const glm::ivec2 getSize() const { return mSize; } bool bind(); // Returns an approximation of total VRAM used by textures (in bytes). @@ -61,7 +61,11 @@ public: static size_t getTotalTextureSize(); protected: - TextureResource(const std::string& path, bool tile, bool dynamic, float scaleDuringLoad); + TextureResource(const std::string& path, + bool tile, + bool dynamic, + bool linearMagnify, + float scaleDuringLoad); virtual void unload(std::shared_ptr& rm); virtual void reload(std::shared_ptr& rm); @@ -73,8 +77,8 @@ private: // The texture data manager manages loading and unloading of filesystem based textures. static TextureDataManager sTextureDataManager; - Vector2i mSize; - Vector2f mSourceSize; + glm::ivec2 mSize; + glm::vec2 mSourceSize; bool mForceLoad; typedef std::pair TextureKeyType; diff --git a/es-core/src/utils/MathUtil.cpp b/es-core/src/utils/MathUtil.cpp new file mode 100644 index 000000000..ab88a5642 --- /dev/null +++ b/es-core/src/utils/MathUtil.cpp @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: MIT +// +// EmulationStation Desktop Edition +// MathUtil.cpp +// +// Math utility functions. +// The GLM library headers are also included from here. +// + +#if defined(_MSC_VER) // MSVC compiler. +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "utils/MathUtil.h" + +#include +#include + +namespace Utils +{ + namespace Math + { + float smoothStep(const float left, const float right, const float value) + { + const float x{glm::clamp((value - left) / (right - left), 0.0f, 1.0f)}; + return x * x * (3.0f - (2.0f * x)); + } + + float smootherStep(const float left, const float right, const float value) + { + const float x{glm::clamp((value - left) / (right - left), 0.0f, 1.0f)}; + return x * x * x * (x * ((x * 6.0f) - 15.0f) + 10.0f); + } + + float loop(const float delayTime, + const float scrollTime, + const float currentTime, + const float scrollLength) + { + if (currentTime < delayTime) { + // Wait. + return 0.0f; + } + else if (currentTime < (delayTime + scrollTime)) { + // Interpolate from 0 to scrollLength. + const float fraction{(currentTime - delayTime) / scrollTime}; + return glm::mix(0.0f, scrollLength, fraction); + } + + // And back to waiting. + return 0.0f; + } + + float bounce(const float delayTime, + const float scrollTime, + const float currentTime, + const float scrollLength) + { + if (currentTime < delayTime) { + // Wait. + return 0.0f; + } + else if (currentTime < (delayTime + scrollTime)) { + // Interpolate from 0 to scrollLength. + const float fraction{(currentTime - delayTime) / scrollTime}; + return glm::mix(0.0f, scrollLength, smootherStep(0.0f, 1.0f, fraction)); + } + else if (currentTime < (delayTime + scrollTime + delayTime)) { + // Wait some more. + return scrollLength; + } + else if (currentTime < (delayTime + scrollTime + delayTime + scrollTime)) { + // Interpolate back from scrollLength to 0. + const float fraction{(currentTime - delayTime - scrollTime - delayTime) / + scrollTime}; + return glm::mix(scrollLength, 0.0f, smootherStep(0.0f, 1.0f, fraction)); + } + // And back to waiting. + return 0.0f; + } + + std::string md5Hash(const std::string& data) + { + // Data that didn't fit in last 64 byte chunk. + unsigned char buffer[64]{}; + // 64 bit counter for the number of bits (low, high). + unsigned int count[2]{}; + + // Digest so far. + unsigned int state[4]; + + // Magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; + + md5Update(reinterpret_cast(data.c_str()), + static_cast(data.length()), state, count, buffer); + + static unsigned char padding[64]{0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + // Encodes unsigned int input into unsigned char output. Assumes len is a multiple of 4. + auto encodeFunc = [](unsigned char output[], const unsigned int input[], + unsigned int len) { + for (unsigned int i = 0, j = 0; j < len; i++, j += 4) { + output[j] = input[i] & 0xff; + output[j + 1] = (input[i] >> 8) & 0xff; + output[j + 2] = (input[i] >> 16) & 0xff; + output[j + 3] = (input[i] >> 24) & 0xff; + } + }; + + // Save number of bits. + unsigned char bits[8]; + encodeFunc(bits, count, 8); + + // Pad out to 56 mod 64. + unsigned int index = count[0] / 8 % 64; + unsigned int padLen = (index < 56) ? (56 - index) : (120 - index); + md5Update(padding, padLen, state, count, buffer); + + // Append length (before padding). + md5Update(bits, 8, state, count, buffer); + + // The result. + unsigned char digest[16]; + + // Store state in digest. + encodeFunc(digest, state, 16); + + // Convert to hex string. + char buf[33]; + for (int i = 0; i < 16; i++) + sprintf(buf + i * 2, "%02x", digest[i]); + buf[32] = 0; + + return std::string(buf); + } + + void md5Update(const unsigned char input[], + unsigned int length, + unsigned int (&state)[4], + unsigned int (&count)[2], + unsigned char (&buffer)[64]) + { + // Compute number of bytes (mod 64). + unsigned int index = count[0] / 8 % 64; + + // Update number of bits. + if ((count[0] += (length << 3)) < (length << 3)) + count[1]++; + count[1] += (length >> 29); + + // Number of bytes we need to fill in buffer. + unsigned int firstpart = 64 - index; + + unsigned int i; + // Encodes unsigned int input into unsigned char output. Assumes len is a multiple of 4. + // Transform as many times as possible. + if (length >= firstpart) { + // Fill buffer first, then transform. + memcpy(&buffer[index], input, firstpart); + md5Transform(buffer, state); + + // Transform chunks of 64 (64 bytes). + for (i = firstpart; i + 64 <= length; i += 64) + md5Transform(&input[i], state); + + index = 0; + } + else + i = 0; + + // Buffer remaining input. + memcpy(&buffer[index], &input[i], length - i); + } + + void md5Transform(const unsigned char block[64], unsigned int (&state)[4]) + { + unsigned int a{state[0]}; + unsigned int b{state[1]}; + unsigned int c{state[2]}; + unsigned int d{state[3]}; + unsigned int x[16]{}; + + // Encodes unsigned int input into unsigned char output. Assumes len is a multiple of 4. + for (unsigned int i = 0, j = 0; j < 64; i++, j += 4) + x[i] = (static_cast(block[j])) | + ((static_cast(block[j + 1])) << 8) | + ((static_cast(block[j + 2])) << 16) | + ((static_cast(block[j + 3])) << 24); + + const unsigned int S11{7}; + const unsigned int S12{12}; + const unsigned int S13{17}; + const unsigned int S14{22}; + const unsigned int S21{5}; + const unsigned int S22{9}; + const unsigned int S23{14}; + const unsigned int S24{20}; + const unsigned int S31{4}; + const unsigned int S32{11}; + const unsigned int S33{16}; + const unsigned int S34{23}; + const unsigned int S41{6}; + const unsigned int S42{10}; + const unsigned int S43{15}; + const unsigned int S44{21}; + + // fFunc, gFunc, hFunc and iFunc are basic MD5 functions. + auto fFunc = [](unsigned int x, unsigned int y, unsigned int z) { + return (x & y) | (~x & z); + }; + auto gFunc = [](unsigned int x, unsigned int y, unsigned int z) { + return (x & z) | (y & ~z); + }; + auto hFunc = [](unsigned int x, unsigned int y, unsigned int z) { return x ^ y ^ z; }; + auto iFunc = [](unsigned int x, unsigned int y, unsigned int z) { + return y ^ (x | ~z); + }; + + auto rotateLeftFunc = [](unsigned int x, int n) { return (x << n) | (x >> (32 - n)); }; + + // ffFunc, ggFunc, hhFunc, and iiFunc transformations for rounds 1, 2, 3, and 4. + // Rotation is separate from addition to prevent recomputation. + auto ffFunc = [fFunc, rotateLeftFunc](unsigned int& a, unsigned int b, unsigned int c, + unsigned int d, unsigned int x, unsigned int s, + unsigned int ac) { + a = rotateLeftFunc(a + fFunc(b, c, d) + x + ac, s) + b; + }; + + auto ggFunc = [gFunc, rotateLeftFunc](unsigned int& a, unsigned int b, unsigned int c, + unsigned int d, unsigned int x, unsigned int s, + unsigned int ac) { + a = rotateLeftFunc(a + gFunc(b, c, d) + x + ac, s) + b; + }; + + auto hhFunc = [hFunc, rotateLeftFunc](unsigned int& a, unsigned int b, unsigned int c, + unsigned int d, unsigned int x, unsigned int s, + unsigned int ac) { + a = rotateLeftFunc(a + hFunc(b, c, d) + x + ac, s) + b; + }; + + auto iiFunc = [iFunc, rotateLeftFunc](unsigned int& a, unsigned int b, unsigned int c, + unsigned int d, unsigned int x, unsigned int s, + unsigned int ac) { + a = rotateLeftFunc(a + iFunc(b, c, d) + x + ac, s) + b; + }; + + // Round 1. + ffFunc(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + ffFunc(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + ffFunc(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + ffFunc(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + ffFunc(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + ffFunc(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + ffFunc(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + ffFunc(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + ffFunc(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + ffFunc(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + ffFunc(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + ffFunc(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + ffFunc(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + ffFunc(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + ffFunc(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + ffFunc(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + // Round 2. + ggFunc(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + ggFunc(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + ggFunc(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + ggFunc(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + ggFunc(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + ggFunc(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + ggFunc(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + ggFunc(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + ggFunc(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + ggFunc(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + ggFunc(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + ggFunc(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + ggFunc(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + ggFunc(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + ggFunc(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + ggFunc(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + // Round 3. + hhFunc(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + hhFunc(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + hhFunc(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + hhFunc(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + hhFunc(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + hhFunc(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + hhFunc(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + hhFunc(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + hhFunc(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + hhFunc(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + hhFunc(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + hhFunc(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + hhFunc(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + hhFunc(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + hhFunc(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + hhFunc(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + // Round 4. + iiFunc(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + iiFunc(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + iiFunc(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + iiFunc(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + iiFunc(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + iiFunc(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + iiFunc(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + iiFunc(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + iiFunc(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + iiFunc(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + iiFunc(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + iiFunc(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + iiFunc(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + iiFunc(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + iiFunc(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + iiFunc(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + } + + } // namespace Math + +} // namespace Utils diff --git a/es-core/src/utils/MathUtil.h b/es-core/src/utils/MathUtil.h new file mode 100644 index 000000000..f2443d313 --- /dev/null +++ b/es-core/src/utils/MathUtil.h @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +// +// EmulationStation Desktop Edition +// MathUtil.h +// +// Math utility functions. +// The GLM library headers are also included from here. +// + +#ifndef ES_CORE_UTILS_MATH_UTIL_H +#define ES_CORE_UTILS_MATH_UTIL_H + +#include +#include +#include +#include + +namespace Utils +{ + namespace Math + { + float smoothStep(const float left, const float right, const float value); + float smootherStep(const float left, const float right, const float value); + + // Used for horizontal scrolling, e.g. long names in TextListComponent. + float loop(const float delayTime, + const float scrollTime, + const float currentTime, + const float scrollLength); + // Variation of the loop, with an acceleration and deceleration at the start and ending. + float bounce(const float delayTime, + const float scrollTime, + const float currentTime, + const float scrollLength); + + // The MD5 functions are derived from the RSA Data Security, Inc. MD5 Message-Digest + // Algorithm. Based on this code: https://github.com/yaoyao-cn/md5/blob/master/md5.cpp + std::string md5Hash(const std::string& data); + void md5Update(const unsigned char* buf, + unsigned int length, + unsigned int (&state)[4], + unsigned int (&count)[2], + unsigned char (&buffer)[64]); + void md5Transform(const unsigned char block[64], unsigned int (&state)[4]); + + } // namespace Math + +} // namespace Utils + +#endif // ES_CORE_UTILS_MATH_UTIL_H diff --git a/es-core/src/utils/StringUtil.cpp b/es-core/src/utils/StringUtil.cpp index 552b23d7b..2bc8798ac 100644 --- a/es-core/src/utils/StringUtil.cpp +++ b/es-core/src/utils/StringUtil.cpp @@ -7,6 +7,10 @@ // Convert characters to Unicode, upper-/lowercase conversion, string formatting etc. // +#if defined(_MSC_VER) // MSVC compiler. +#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING +#endif + #include "utils/StringUtil.h" #include @@ -153,8 +157,7 @@ namespace Utils (wchar_t)0xFF4B, (wchar_t)0xFF4C, (wchar_t)0xFF4D, (wchar_t)0xFF4E, (wchar_t)0xFF4F, (wchar_t)0xFF50, (wchar_t)0xFF51, (wchar_t)0xFF52, (wchar_t)0xFF53, (wchar_t)0xFF54, (wchar_t)0xFF55, (wchar_t)0xFF56, (wchar_t)0xFF57, (wchar_t)0xFF58, (wchar_t)0xFF59, - (wchar_t)0xFF5A - }; + (wchar_t)0xFF5A}; static wchar_t unicodeUppercase[] = { (wchar_t)0x0041, (wchar_t)0x0042, (wchar_t)0x0043, (wchar_t)0x0044, (wchar_t)0x0045, @@ -290,8 +293,7 @@ namespace Utils (wchar_t)0xFF2B, (wchar_t)0xFF2C, (wchar_t)0xFF2D, (wchar_t)0xFF2E, (wchar_t)0xFF2F, (wchar_t)0xFF30, (wchar_t)0xFF31, (wchar_t)0xFF32, (wchar_t)0xFF33, (wchar_t)0xFF34, (wchar_t)0xFF35, (wchar_t)0xFF36, (wchar_t)0xFF37, (wchar_t)0xFF38, (wchar_t)0xFF39, - (wchar_t)0xFF3A - }; + (wchar_t)0xFF3A}; unsigned int chars2Unicode(const std::string& stringArg, size_t& cursor) { @@ -539,6 +541,27 @@ namespace Utils return stringUpper; } + std::string toCamelCase(const std::string& stringArg) + { + std::string line = stringArg; + bool active = true; + + for (int i = 0; line[i] != '\0'; i++) { + if (std::isalpha(line[i])) { + if (active) { + line[i] = Utils::String::toUpper(std::string(1, line[i]))[0]; + active = false; + } + else + line[i] = Utils::String::toLower(std::string(1, line[i]))[0]; + } + else if (line[i] == ' ') + active = true; + } + + return line; + } + std::string trim(const std::string& stringArg) { const size_t strBegin = stringArg.find_first_not_of(" \t"); @@ -592,7 +615,7 @@ namespace Utils std::string removeParenthesis(const std::string& stringArg) { - static std::vector remove = { '(', ')', '[', ']' }; + static std::vector remove = {'(', ')', '[', ']'}; std::string stringRemove = stringArg; size_t start; size_t end; diff --git a/es-core/src/utils/StringUtil.h b/es-core/src/utils/StringUtil.h index 98b1ecb23..28e9c9060 100644 --- a/es-core/src/utils/StringUtil.h +++ b/es-core/src/utils/StringUtil.h @@ -26,6 +26,7 @@ namespace Utils size_t moveCursor(const std::string& stringArg, const size_t cursor, const int amount); std::string toLower(const std::string& stringArg); std::string toUpper(const std::string& stringArg); + std::string toCamelCase(const std::string& stringArg); std::string trim(const std::string& stringArg); std::string replace(const std::string& stringArg, const std::string& replace, diff --git a/es-core/src/utils/TimeUtil.cpp b/es-core/src/utils/TimeUtil.cpp index 6d4a46cb1..ef829d351 100644 --- a/es-core/src/utils/TimeUtil.cpp +++ b/es-core/src/utils/TimeUtil.cpp @@ -18,7 +18,7 @@ namespace Utils DateTime::DateTime() { mTime = 0; - mTimeStruct = { 0, 0, 0, 1, 0, 0, 0, 0, -1 }; + mTimeStruct = {0, 0, 0, 1, 0, 0, 0, 0, -1}; mIsoString = "00000000T000000"; } @@ -83,7 +83,7 @@ namespace Utils { const char* s = string.c_str(); const char* f = format.c_str(); - tm timeStruct = { 0, 0, 0, 1, 0, 0, 0, 0, -1 }; + tm timeStruct = {0, 0, 0, 1, 0, 0, 0, 0, -1}; size_t parsedChars = 0; if (string == "19700101T010000") @@ -172,7 +172,7 @@ namespace Utils #else localtime_r(&time, &timeStruct); #endif - char buf[256] = { '\0' }; + char buf[256] = {'\0'}; char* s = buf; while (*f) { @@ -231,7 +231,7 @@ namespace Utils int daysInMonth(const int year, const int month) { - tm timeStruct = { 0, 0, 0, 0, month, year - 1900, 0, 0, -1 }; + tm timeStruct = {0, 0, 0, 0, month, year - 1900, 0, 0, -1}; mktime(&timeStruct); return timeStruct.tm_mday; @@ -239,7 +239,7 @@ namespace Utils int daysInYear(const int year) { - tm timeStruct = { 0, 0, 0, 0, 0, year - 1900 + 1, 0, 0, -1 }; + tm timeStruct = {0, 0, 0, 0, 0, year - 1900 + 1, 0, 0, -1}; mktime(&timeStruct); return timeStruct.tm_yday + 1; diff --git a/resources/fonts/Akrobat-Bold.ttf b/resources/fonts/Akrobat-Bold.ttf new file mode 100644 index 000000000..c4d96640f Binary files /dev/null and b/resources/fonts/Akrobat-Bold.ttf differ diff --git a/themes/rbsimple-DE/theme.xml b/themes/rbsimple-DE/theme.xml index 89679e9cb..0581ca581 100644 --- a/themes/rbsimple-DE/theme.xml +++ b/themes/rbsimple-DE/theme.xml @@ -121,7 +121,7 @@ based on: 'recalbox-multi' by the Recalbox community 1 1 - 1 1 + 1 1 - + @@ -337,7 +336,7 @@ based on: 'recalbox-multi' by the Recalbox community 1 1 - 1 1 + 1 1