diff --git a/CHANGELOG.md b/CHANGELOG.md index 13f0b735f..d43970015 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ Many bugs have been fixed, and numerous features that were only partially implem * Added volume sliders for navigation sounds and game videos to the sound settings menu * Added support for OpenGL GLSL shaders (OpenGL 2.1 renderer only, no support for OpenGL ES 1.0 renderer) * Added multiple animations and shader effects, such as when opening menus, playing videos in the gamelists and via the screensaver etc. +* Updated the application to work properly on high resolution devices (such as 4K) * Seamless (almost) launch of games without showing the desktop when starting and returning from RetroArch and other emulators * Updated scraper to support additional media files, detailed configuration of what to scrape, semi-automatic mode etc. * Added user account support when scraping using ScreenScraper @@ -114,6 +115,7 @@ Many bugs have been fixed, and numerous features that were only partially implem * Unknown command line options were silently accepted instead of generating an error and notifying the user * Deleting a game from the metadata editor did not delete the game media files or its entry in the gamelist.xml file * Hidden files still showed up if they had a gamelist.xml entry +* Fixed multiple instances of misaligned GUI elements on high-resolution displays due to the use of fixed-pixel constants * The VRAM statistics overlay was somewhat broken and incorrectly displayed numbers in megabytes instead of mebibytes * Long game names would sometimes not scroll in the gamelist view * Game media was not rendered when moving between gamelists using the slide transition style diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index 79efeed78..88cc4e210 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -402,6 +402,7 @@ void Window::render() } } + // Render the quick list scrolling overlay, which is triggered in IList. if (mListScrollOpacity != 0) { Renderer::setMatrix(Transform4x4f::Identity()); Renderer::drawRect(0.0f, 0.0f, static_cast(Renderer::getScreenWidth()), diff --git a/es-core/src/components/ButtonComponent.cpp b/es-core/src/components/ButtonComponent.cpp index 89af804db..cdc577dc1 100644 --- a/es-core/src/components/ButtonComponent.cpp +++ b/es-core/src/components/ButtonComponent.cpp @@ -16,12 +16,13 @@ ButtonComponent::ButtonComponent( const std::string& helpText, const std::function& func) : GuiComponent(window), - mBox(window, ":/graphics/button.png"), + mBox(window, ":/graphics/button.svg"), mFont(Font::get(FONT_SIZE_MEDIUM)), mFocused(false), mEnabled(true), mTextColorFocused(0xFFFFFFFF), mTextColorUnfocused(0x777777FF) { + mBox.setIsScalable(true); setPressedFunc(func); setText(text, helpText); updateImage(); @@ -83,7 +84,7 @@ void ButtonComponent::setEnabled(bool state) void ButtonComponent::updateImage() { if (!mEnabled || !mPressedFunc) { - mBox.setImagePath(":/graphics/button_filled.png"); + mBox.setImagePath(":/graphics/button_filled.svg"); mBox.setCenterColor(0x770000FF); mBox.setEdgeColor(0x770000FF); return; @@ -91,7 +92,7 @@ void ButtonComponent::updateImage() mBox.setCenterColor(0xFFFFFFFF); mBox.setEdgeColor(0xFFFFFFFF); - mBox.setImagePath(mFocused ? ":/graphics/button_filled.png" : ":/graphics/button.png"); + mBox.setImagePath(mFocused ? ":/graphics/button_filled.svg" : ":/graphics/button.svg"); } void ButtonComponent::render(const Transform4x4f& parentTrans) diff --git a/es-core/src/components/NinePatchComponent.cpp b/es-core/src/components/NinePatchComponent.cpp index 6e707fc03..02bb1aaac 100644 --- a/es-core/src/components/NinePatchComponent.cpp +++ b/es-core/src/components/NinePatchComponent.cpp @@ -22,7 +22,8 @@ NinePatchComponent::NinePatchComponent( mEdgeColor(edgeColor), mCenterColor(centerColor), mPath(path), - mVertices(nullptr) + mVertices(nullptr), + mIsScalable(false) { if (!mPath.empty()) buildVertices(); @@ -39,10 +40,10 @@ void NinePatchComponent::updateColors() const unsigned int edgeColor = Renderer::convertRGBAToABGR(mEdgeColor); const unsigned int centerColor = Renderer::convertRGBAToABGR(mCenterColor); - for (int i = 0; i < 6*9; ++i) + for (int i = 0; i < 6 * 9; i++) mVertices[i].col = edgeColor; - for (int i = 6*4; i < 6; ++i) + for (int i = 6*4; i < 6; i++) mVertices[(6*4)+i].col = centerColor; } @@ -55,14 +56,29 @@ void NinePatchComponent::buildVertices() if (mTexture->getSize() == Vector2i::Zero()) { mVertices = nullptr; - LOG(LogWarning) << "NinePatchComponent missing texture!"; + LOG(LogWarning) << "NinePatchComponent has no texture"; return; } + Vector2f texSize; mVertices = new Renderer::Vertex[6 * 9]; - const Vector2f texSize = Vector2f(static_cast(mTexture->getSize().x()), - static_cast(mTexture->getSize().y())); + // This is just a partial fix, the plan is to always scale according to the screen + // resolution. But unfortunately doing this for the menu frame leads to flickering when + // entering a submenu, probably because the texture is unloaded and re-rasterized at the + // higher resolution. So for the moment the frame.png texture is still used (which won't be + // scaled as that leads to ugly pixelated corners for the menus). Scaling ButtonComponent + // works perfect with the below code though. + if (mIsScalable) { + texSize = Vector2f(static_cast(mTexture->getSize().x()) * + Renderer::getScreenWidthModifier(), static_cast(mTexture->getSize().y()) * + Renderer::getScreenHeightModifier()); + mTexture->rasterizeAt(static_cast(texSize.x()), static_cast(texSize.y())); + } + else { + texSize = Vector2f(static_cast(mTexture->getSize().x()), + static_cast(mTexture->getSize().y())); + } const float imgSizeX[3] = { mCornerSize.x(), mSize.x() - mCornerSize.x() * 2, mCornerSize.x()}; const float imgSizeY[3] = { mCornerSize.y(), mSize.y() - mCornerSize.y() * 2, mCornerSize.y()}; @@ -79,8 +95,8 @@ void NinePatchComponent::buildVertices() int v = 0; for (int slice = 0; slice < 9; slice++) { - const int sliceX = slice % 3; - const int sliceY = slice / 3; + 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]); @@ -92,7 +108,7 @@ void NinePatchComponent::buildVertices() mVertices[v + 4] = { { imgPos.x() + imgSize.x(), imgPos.y() + imgSize.y() }, { texPos.x() + texSize.x(), texPos.y() + texSize.y() }, 0 }; // Round vertices. - for (int i = 1; i < 5; ++i) + for (int i = 1; i < 5; i++) mVertices[v + i].pos.round(); // Make duplicates of first and last vertex so this can be rendered as a triangle strip. diff --git a/es-core/src/components/NinePatchComponent.h b/es-core/src/components/NinePatchComponent.h index c7ff33145..6f8c95dcd 100644 --- a/es-core/src/components/NinePatchComponent.h +++ b/es-core/src/components/NinePatchComponent.h @@ -50,6 +50,7 @@ public: const std::string& element, unsigned int properties) override; inline const Vector2f& getCornerSize() const { return mCornerSize; }; + void setIsScalable(bool scalable) { mIsScalable = scalable; }; inline void setCornerSize(const Vector2f& size) { mCornerSize = size; @@ -67,6 +68,7 @@ private: unsigned int mEdgeColor; unsigned int mCenterColor; std::shared_ptr mTexture; + bool mIsScalable; }; #endif // ES_CORE_COMPONENTS_NINE_PATCH_COMPONENT_H diff --git a/resources/graphics/button.png b/resources/graphics/button.png deleted file mode 100644 index 7ac2297f9..000000000 Binary files a/resources/graphics/button.png and /dev/null differ diff --git a/resources/graphics/button.svg b/resources/graphics/button.svg new file mode 100644 index 000000000..b70113cf1 --- /dev/null +++ b/resources/graphics/button.svg @@ -0,0 +1,6 @@ + + + + diff --git a/resources/graphics/button_filled.png b/resources/graphics/button_filled.png deleted file mode 100644 index ac543584f..000000000 Binary files a/resources/graphics/button_filled.png and /dev/null differ diff --git a/resources/graphics/button_filled.svg b/resources/graphics/button_filled.svg new file mode 100644 index 000000000..ab6e12ec9 --- /dev/null +++ b/resources/graphics/button_filled.svg @@ -0,0 +1,9 @@ + + + + + diff --git a/resources/graphics/frame.svg b/resources/graphics/frame.svg new file mode 100644 index 000000000..82331d6b1 --- /dev/null +++ b/resources/graphics/frame.svg @@ -0,0 +1,6 @@ + + + + diff --git a/resources/graphics/off.svg b/resources/graphics/off.svg index e7344de64..e7730bf15 100644 --- a/resources/graphics/off.svg +++ b/resources/graphics/off.svg @@ -1,55 +1,6 @@ - - - - - - image/svg+xml - - - - - - - + + + d="M 10.491203,0.17871838 C 4.9585292,0.17871839 0.45799999,5.0240707 0.45799999,10.979499 c 0,5.95543 4.50053021,10.800782 10.03320301,10.800782 h 22.933594 c 5.53267,0 10.033203,-4.845352 10.033203,-10.800782 0,-5.9554283 -4.500533,-10.80078062 -10.033203,-10.80078062 z m 0,3.08593752 c 3.951701,0 7.166015,3.4611877 7.166015,7.7148431 0,4.253654 -3.214314,7.714844 -7.166015,7.714844 -3.9517019,0 -7.1660155,-3.46119 -7.1660155,-7.714844 0,-4.2536554 3.2143137,-7.7148431 7.1660155,-7.7148431 z m 0,1.5429688 c -3.1612188,0 -5.7343748,2.7691042 -5.7343748,6.1718743 -1e-7,3.402769 2.5731559,6.171875 5.7343748,6.171875 3.161215,0 5.732422,-2.769106 5.732422,-6.171875 0,-3.4027701 -2.571207,-6.1718743 -5.732422,-6.1718743 z"/> diff --git a/resources/graphics/on.svg b/resources/graphics/on.svg index 244bd0dcd..9e8b2507f 100644 --- a/resources/graphics/on.svg +++ b/resources/graphics/on.svg @@ -1,56 +1,6 @@ - - - - - - image/svg+xml - - - - - - - + + + d="m 10.491337,21.7795 h 22.933327 c 5.532673,0 10.033336,-4.84457 10.033336,-10.8 0,-5.9554292 -4.500663,-10.80000018 -10.033337,-10.80000018 H 10.491337 c -5.5326701,0 -10.03333682,4.84457098 -10.03333682,10.80000018 0,5.95543 4.50066672,10.8 10.03333682,10.8 z M 33.424664,3.2652139 c 3.9517,0 7.166673,3.4606284 7.166673,7.7142861 0,4.253657 -3.214973,7.714287 -7.166673,7.714287 -3.9517,0 -7.166663,-3.46063 -7.166663,-7.714287 0,-4.2536577 3.214963,-7.7142861 7.166663,-7.7142861 z" + style="fill:#808080;fill-opacity:1;stroke-width:0.74354357"/>