diff --git a/launcher/Application.cpp b/launcher/Application.cpp index b59d13824..1261e083d 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -786,6 +786,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) // The cat m_settings->registerSetting("TheCat", false); m_settings->registerSetting("CatOpacity", 100); + m_settings->registerSetting("CatFit", "fit"); m_settings->registerSetting("StatusBarVisible", true); diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index f8a287da7..9cb72f8ab 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -891,6 +891,8 @@ SET(LAUNCHER_SOURCES ui/themes/ThemeManager.h ui/themes/CatPack.cpp ui/themes/CatPack.h + ui/themes/CatPainter.cpp + ui/themes/CatPainter.h # Processes LaunchController.h diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp index 2349c684d..14d480e90 100644 --- a/launcher/ui/instanceview/InstanceView.cpp +++ b/launcher/ui/instanceview/InstanceView.cpp @@ -49,6 +49,7 @@ #include #include "VisualGroup.h" +#include "ui/themes/CatPainter.h" #include "ui/themes/ThemeManager.h" #include @@ -78,6 +79,9 @@ InstanceView::~InstanceView() { qDeleteAll(m_groups); m_groups.clear(); + if (m_cat) { + m_cat->deleteLater(); + } } void InstanceView::setModel(QAbstractItemModel* model) @@ -172,7 +176,7 @@ void InstanceView::updateScrollbar() void InstanceView::updateGeometries() { - geometryCache.clear(); + m_geometryCache.clear(); QMap cats; @@ -186,8 +190,8 @@ void InstanceView::updateGeometries() cat->update(); } else { auto cat = new VisualGroup(groupName, this); - if (fVisibility) { - cat->collapsed = fVisibility(groupName); + if (m_fVisibility) { + cat->collapsed = m_fVisibility(groupName); } cats.insert(groupName, cat); cat->update(); @@ -436,11 +440,15 @@ void InstanceView::mouseDoubleClickEvent(QMouseEvent* event) void InstanceView::setPaintCat(bool visible) { - m_catVisible = visible; - if (visible) - m_catPixmap.load(APPLICATION->themeManager()->getCatPack()); - else - m_catPixmap = QPixmap(); + if (m_cat) { + disconnect(m_cat, &CatPainter::updateFrame, this, nullptr); + delete m_cat; + m_cat = nullptr; + } + if (visible) { + m_cat = new CatPainter(APPLICATION->themeManager()->getCatPack(), this); + connect(m_cat, &CatPainter::updateFrame, this, [this] { viewport()->update(); }); + } } void InstanceView::paintEvent([[maybe_unused]] QPaintEvent* event) @@ -449,19 +457,8 @@ void InstanceView::paintEvent([[maybe_unused]] QPaintEvent* event) QPainter painter(this->viewport()); - if (m_catVisible) { - painter.setOpacity(APPLICATION->settings()->get("CatOpacity").toFloat() / 100); - int widWidth = this->viewport()->width(); - int widHeight = this->viewport()->height(); - if (m_catPixmap.width() < widWidth) - widWidth = m_catPixmap.width(); - if (m_catPixmap.height() < widHeight) - widHeight = m_catPixmap.height(); - auto pixmap = m_catPixmap.scaled(widWidth, widHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); - QRect rectOfPixmap = pixmap.rect(); - rectOfPixmap.moveBottomRight(this->viewport()->rect().bottomRight()); - painter.drawPixmap(rectOfPixmap.topLeft(), pixmap); - painter.setOpacity(1.0); + if (m_cat) { + m_cat->paint(&painter, this->viewport()->rect()); } QStyleOptionViewItem option; @@ -711,8 +708,8 @@ QRect InstanceView::geometryRect(const QModelIndex& index) const } int row = index.row(); - if (geometryCache.contains(row)) { - return *geometryCache[row]; + if (m_geometryCache.contains(row)) { + return *m_geometryCache[row]; } const VisualGroup* cat = category(index); @@ -727,7 +724,7 @@ QRect InstanceView::geometryRect(const QModelIndex& index) const out.setTop(cat->verticalPosition() + cat->headerHeight() + 5 + cat->rowTopOf(index)); out.setLeft(m_spacing + x * (itemWidth() + m_spacing)); out.setSize(itemDelegate()->sizeHint(option, index)); - geometryCache.insert(row, new QRect(out)); + m_geometryCache.insert(row, new QRect(out)); return out; } diff --git a/launcher/ui/instanceview/InstanceView.h b/launcher/ui/instanceview/InstanceView.h index dea8b1212..5d9dbf729 100644 --- a/launcher/ui/instanceview/InstanceView.h +++ b/launcher/ui/instanceview/InstanceView.h @@ -41,6 +41,7 @@ #include #include #include "VisualGroup.h" +#include "ui/themes/CatPainter.h" struct InstanceViewRoles { enum { GroupRole = Qt::UserRole, ProgressValueRole, ProgressMaximumRole }; @@ -56,7 +57,7 @@ class InstanceView : public QAbstractItemView { void setModel(QAbstractItemModel* model) override; using visibilityFunction = std::function; - void setSourceOfGroupCollapseStatus(visibilityFunction f) { fVisibility = f; } + void setSourceOfGroupCollapseStatus(visibilityFunction f) { m_fVisibility = f; } /// return geometry rectangle occupied by the specified model item QRect geometryRect(const QModelIndex& index) const; @@ -116,7 +117,7 @@ class InstanceView : public QAbstractItemView { friend struct VisualGroup; QList m_groups; - visibilityFunction fVisibility; + visibilityFunction m_fVisibility; // geometry int m_leftMargin = 5; @@ -127,9 +128,8 @@ class InstanceView : public QAbstractItemView { int m_itemWidth = 100; int m_currentItemsPerRow = -1; int m_currentCursorColumn = -1; - mutable QCache geometryCache; - bool m_catVisible = false; - QPixmap m_catPixmap; + mutable QCache m_geometryCache; + CatPainter* m_cat = nullptr; // point where the currently active mouse action started in geometry coordinates QPoint m_pressedPosition; diff --git a/launcher/ui/themes/CatPainter.cpp b/launcher/ui/themes/CatPainter.cpp new file mode 100644 index 000000000..7ff24932b --- /dev/null +++ b/launcher/ui/themes/CatPainter.cpp @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2025 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ui/themes/CatPainter.h" +#include +#include "Application.h" + +CatPainter::CatPainter(const QString& path, QObject* parent) : QObject(parent) +{ + m_image = QPixmap(path); +} + +void CatPainter::paint(QPainter* painter, const QRect& viewport) +{ + QPixmap frame = m_image; + + auto fit = APPLICATION->settings()->get("CatFit").toString(); + painter->setOpacity(APPLICATION->settings()->get("CatOpacity").toFloat() / 100); + int widWidth = viewport.width(); + int widHeight = viewport.height(); + auto aspectMode = Qt::IgnoreAspectRatio; + if (fit == "fill") { + aspectMode = Qt::KeepAspectRatio; + } else if (fit == "fit") { + aspectMode = Qt::KeepAspectRatio; + if (frame.width() < widWidth) + widWidth = frame.width(); + if (frame.height() < widHeight) + widHeight = frame.height(); + } + auto pixmap = frame.scaled(widWidth, widHeight, aspectMode, Qt::SmoothTransformation); + QRect rectOfPixmap = pixmap.rect(); + rectOfPixmap.moveBottomRight(viewport.bottomRight()); + painter->drawPixmap(rectOfPixmap.topLeft(), pixmap); + painter->setOpacity(1.0); +}; diff --git a/launcher/ui/themes/CatPainter.h b/launcher/ui/themes/CatPainter.h new file mode 100644 index 000000000..3b790c640 --- /dev/null +++ b/launcher/ui/themes/CatPainter.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher - Minecraft Launcher + * Copyright (c) 2025 Trial97 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include + +class CatPainter : public QObject { + Q_OBJECT + public: + CatPainter(const QString& path, QObject* parent = nullptr); + virtual ~CatPainter() = default; + void paint(QPainter*, const QRect&); + + signals: + void updateFrame(); + + private: + QPixmap m_image; +}; diff --git a/launcher/ui/widgets/AppearanceWidget.cpp b/launcher/ui/widgets/AppearanceWidget.cpp index ae9c6ee5e..cfe3b8c0d 100644 --- a/launcher/ui/widgets/AppearanceWidget.cpp +++ b/launcher/ui/widgets/AppearanceWidget.cpp @@ -97,22 +97,28 @@ void AppearanceWidget::applySettings() settings->set("ConsoleFont", consoleFontFamily); settings->set("ConsoleFontSize", m_ui->fontSizeBox->value()); settings->set("CatOpacity", m_ui->catOpacitySlider->value()); + auto catFit = m_ui->catFitComboBox->currentIndex(); + settings->set("CatFit", catFit == 0 ? "fit" : catFit == 1 ? "fill" : "strech"); } void AppearanceWidget::loadSettings() { - QString fontFamily = APPLICATION->settings()->get("ConsoleFont").toString(); + SettingsObjectPtr settings = APPLICATION->settings(); + QString fontFamily = settings->get("ConsoleFont").toString(); QFont consoleFont(fontFamily); m_ui->consoleFont->setCurrentFont(consoleFont); bool conversionOk = true; - int fontSize = APPLICATION->settings()->get("ConsoleFontSize").toInt(&conversionOk); + int fontSize = settings->get("ConsoleFontSize").toInt(&conversionOk); if (!conversionOk) { fontSize = 11; } m_ui->fontSizeBox->setValue(fontSize); - m_ui->catOpacitySlider->setValue(APPLICATION->settings()->get("CatOpacity").toInt()); + m_ui->catOpacitySlider->setValue(settings->get("CatOpacity").toInt()); + + auto catFit = settings->get("CatFit").toString(); + m_ui->catFitComboBox->setCurrentIndex(catFit == "fit" ? 0 : catFit == "fill" ? 1 : 2); } void AppearanceWidget::retranslateUi() @@ -245,9 +251,7 @@ void AppearanceWidget::updateConsolePreview() workCursor.insertBlock(); }; - print(QString("%1 version: %2\n") - .arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString()), - MessageLevel::Launcher); + print(QString("%1 version: %2\n").arg(BuildConfig.LAUNCHER_DISPLAYNAME, BuildConfig.printableVersionString()), MessageLevel::Launcher); QDate today = QDate::currentDate(); diff --git a/launcher/ui/widgets/AppearanceWidget.ui b/launcher/ui/widgets/AppearanceWidget.ui index c672279f0..99bf4a500 100644 --- a/launcher/ui/widgets/AppearanceWidget.ui +++ b/launcher/ui/widgets/AppearanceWidget.ui @@ -7,7 +7,7 @@ 0 0 600 - 700 + 711 @@ -203,6 +203,53 @@ + + + + + 0 + 0 + + + + Fit + + + + + + + + 0 + 0 + + + + + 77 + 30 + + + + 0 + + + + Fit + + + + + Fill + + + + + Stretch + + + + @@ -372,8 +419,7 @@ - - .. + true @@ -389,8 +435,7 @@ - - .. + true @@ -406,8 +451,7 @@ - - .. + true @@ -423,8 +467,7 @@ - - .. + true @@ -440,8 +483,7 @@ - - .. + true @@ -457,8 +499,7 @@ - - .. + true @@ -474,8 +515,7 @@ - - .. + true @@ -491,8 +531,7 @@ - - .. + true @@ -508,8 +547,7 @@ - - .. + true @@ -525,8 +563,7 @@ - - .. + true @@ -586,6 +623,7 @@ reloadThemesButton consoleFont fontSizeBox + catFitComboBox catOpacitySlider consolePreview