diff --git a/src/eden/interface/qt_config.cpp b/src/eden/interface/qt_config.cpp index 5dcad01eb1..463bbc72a8 100644 --- a/src/eden/interface/qt_config.cpp +++ b/src/eden/interface/qt_config.cpp @@ -282,13 +282,13 @@ void QtConfig::ReadUIGamelistValues() { ReadCategory(Settings::Category::UiGameList); - const int favorites_size = BeginArray("favorites"); - for (int i = 0; i < favorites_size; i++) { - SetArrayIndex(i); - UISettings::values.favorited_ids.append( - ReadUnsignedIntegerSetting(std::string("program_id"))); - } - EndArray(); + // const int favorites_size = BeginArray("favorites"); + // for (int i = 0; i < favorites_size; i++) { + // SetArrayIndex(i); + // UISettings::values.favorited_ids.append( + // ReadUnsignedIntegerSetting(std::string("program_id"))); + // } + // EndArray(); EndGroup(); } @@ -490,12 +490,12 @@ void QtConfig::SaveUIGamelistValues() WriteCategory(Settings::Category::UiGameList); - BeginArray(std::string("favorites")); - for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { - SetArrayIndex(i); - WriteIntegerSetting(std::string("program_id"), UISettings::values.favorited_ids[i]); - } - EndArray(); // favorites + // BeginArray(std::string("favorites")); + // for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { + // SetArrayIndex(i); + // WriteIntegerSetting(std::string("program_id"), UISettings::values.favorited_ids[i]); + // } + // EndArray(); // favorites EndGroup(); } diff --git a/src/eden/interface/uisettings.h b/src/eden/interface/uisettings.h index b8ac6a1e11..aaedb99e8b 100644 --- a/src/eden/interface/uisettings.h +++ b/src/eden/interface/uisettings.h @@ -59,6 +59,12 @@ enum class Theme { MidnightBlueColorful, }; +enum class GameView { + Grid, + List, + Carousel, +}; + static constexpr Theme default_theme{ #ifdef _WIN32 Theme::DarkColorful @@ -192,15 +198,15 @@ struct Values { std::pair, std::vector> multiplayer_ban_list; // Game List - Setting show_add_ons{linkage, true, "show_add_ons", Category::UiGameList}; - Setting game_icon_size{linkage, 64, "game_icon_size", Category::UiGameList}; - Setting folder_icon_size{linkage, 48, "folder_icon_size", Category::UiGameList}; - Setting row_1_text_id{linkage, 3, "row_1_text_id", Category::UiGameList}; - Setting row_2_text_id{linkage, 2, "row_2_text_id", Category::UiGameList}; - std::atomic_bool is_game_list_reload_pending{false}; - Setting cache_game_list{linkage, true, "cache_game_list", Category::UiGameList}; - Setting favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList}; - QVector favorited_ids; + // Setting show_add_ons{linkage, true, "show_add_ons", Category::UiGameList}; + // Setting game_icon_size{linkage, 64, "game_icon_size", Category::UiGameList}; + // Setting folder_icon_size{linkage, 48, "folder_icon_size", Category::UiGameList}; + // Setting row_1_text_id{linkage, 3, "row_1_text_id", Category::UiGameList}; + // Setting row_2_text_id{linkage, 2, "row_2_text_id", Category::UiGameList}; + // std::atomic_bool is_game_list_reload_pending{false}; + // Setting cache_game_list{linkage, true, "cache_game_list", Category::UiGameList}; + // Setting favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList}; + // QVector favorited_ids; Setting grid_columns{linkage, 4, 1, 8, "grid_columns", Category::UiGameList}; diff --git a/src/eden/models/GameListModel.cpp b/src/eden/models/GameListModel.cpp index e20717970b..61c51ac08f 100644 --- a/src/eden/models/GameListModel.cpp +++ b/src/eden/models/GameListModel.cpp @@ -56,9 +56,6 @@ void GameListModel::reload() qreal size = entry.size(); QString sizeString = QLocale::system().formattedDataSize(size); - qDebug() << path << name << size; - // m_data << Game{path, name, size}; - QStandardItem *game = new QStandardItem(name); game->setData(path, GLMRoleTypes::PATH); game->setData(sizeString, GLMRoleTypes::FILESIZE); diff --git a/src/eden/qml/main/CMakeLists.txt b/src/eden/qml/main/CMakeLists.txt index c2a9e6eed8..c0441d539d 100644 --- a/src/eden/qml/main/CMakeLists.txt +++ b/src/eden/qml/main/CMakeLists.txt @@ -9,5 +9,10 @@ qt_add_qml_module(edenMain Main.qml StatusBar.qml GameList.qml - GamePreview.qml + GameGridCard.qml + MarqueeText.qml + GameGrid.qml + + GameCarouselCard.qml + GameCarousel.qml ) diff --git a/src/eden/qml/main/GameCarousel.qml b/src/eden/qml/main/GameCarousel.qml new file mode 100644 index 0000000000..7989d46d71 --- /dev/null +++ b/src/eden/qml/main/GameCarousel.qml @@ -0,0 +1,94 @@ +import QtQuick +import QtQuick.Controls +import Qt.labs.platform +import QtCore + +import org.eden_emu.constants +import org.eden_emu.interface + +ListView { + id: carousel + + focus: true + focusPolicy: Qt.StrongFocus + + model: EdenGameList + orientation: ListView.Horizontal + clip: false + flickDeceleration: 1000 + snapMode: ListView.SnapToItem + + onHeightChanged: console.log(width, height) + + spacing: 20 + + Keys.enabled: true + Keys.onRightPressed: incrementCurrentIndex() + Keys.onLeftPressed: decrementCurrentIndex() + + onCurrentIndexChanged: scrollToCenter() + + highlight: Rectangle { + id: hg + clip: false + z: 3 + + color: "transparent" + border { + color: "deepskyblue" + width: 4 * Constants.scalar + } + + radius: 8 * Constants.scalar + + // TODO: marquee + Text { + function toTitleCase(str) { + return str.replace(/\w\S*/g, text => text.charAt(0).toUpperCase( + ) + text.substring(1).toLowerCase()) + } + + property var item: carousel.currentItem + + text: toTitleCase(item.title) + font.pixelSize: 22 * Constants.scalar + color: "lightblue" + + anchors { + bottom: hg.top + + bottomMargin: 10 * Constants.scalar + left: hg.left + right: hg.right + } + + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideRight + } + } + + highlightFollowsCurrentItem: true + highlightMoveDuration: 300 + highlightMoveVelocity: -1 + + delegate: GameCarouselCard { + id: game + width: 300 + height: 300 + } + + function scrollToCenter() { + let targetX = currentIndex * 320 - (width - 320) / 2 + let min = 0 + let max = contentWidth + + contentX = Math.max(min, Math.min(max, targetX)) + } + + Behavior on contentX { + NumberAnimation { + duration: 300 + easing.type: Easing.OutQuad + } + } +} diff --git a/src/eden/qml/main/GameGrid.qml b/src/eden/qml/main/GameGrid.qml new file mode 100644 index 0000000000..8094ae4cdd --- /dev/null +++ b/src/eden/qml/main/GameGrid.qml @@ -0,0 +1,44 @@ +import QtQuick +import QtQuick.Controls +import Qt.labs.platform +import QtCore + +import org.eden_emu.constants +import org.eden_emu.interface +import org.eden_emu.gamepad + +GridView { + property var setting + id: grid + + property int cellSize: Math.floor(width / setting.value) + + highlightFollowsCurrentItem: true + clip: true + + cellWidth: cellSize + cellHeight: cellSize + 60 * Constants.scalar + + model: EdenGameList + + delegate: GameGridCard { + id: game + + width: grid.cellSize - 20 * Constants.scalar + height: grid.cellHeight - 20 * Constants.scalar + } + + highlight: Rectangle { + color: "transparent" + z: 5 + + radius: 16 * Constants.scalar + border { + color: Constants.text + width: 3 + } + } + + focus: true + focusPolicy: "StrongFocus" +} diff --git a/src/eden/qml/main/GamePreview.qml b/src/eden/qml/main/GameGridCard.qml similarity index 100% rename from src/eden/qml/main/GamePreview.qml rename to src/eden/qml/main/GameGridCard.qml diff --git a/src/eden/qml/main/GameList.qml b/src/eden/qml/main/GameList.qml index 1540452774..81937d1f87 100644 --- a/src/eden/qml/main/GameList.qml +++ b/src/eden/qml/main/GameList.qml @@ -20,15 +20,16 @@ Rectangle { color: Constants.bg - // TODO: make this optional. - // Probably just make a Gamepad frontend/backend split with a null backend + // TODO: use the original yuzu backend for dis Gamepad { id: gamepad - onUpPressed: grid.moveCurrentIndexUp() - onDownPressed: grid.moveCurrentIndexDown() - onLeftPressed: grid.moveCurrentIndexLeft() - onRightPressed: grid.moveCurrentIndexRight() + // onUpPressed: grid.moveCurrentIndexUp() + // onDownPressed: grid.moveCurrentIndexDown() + // onLeftPressed: grid.moveCurrentIndexLeft() + // onRightPressed: grid.moveCurrentIndexRight() + onLeftPressed: carousel.decrementCurrentIndex() + onRightPressed: carousel.incrementCurrentIndex() onAPressed: console.log("A pressed") onLeftStickMoved: (x, y) => { gx = x @@ -54,67 +55,56 @@ Rectangle { } } } - Timer { interval: 16 running: true repeat: true onTriggered: gamepad.pollEvents() } - FolderDialog { id: openDir folder: StandardPaths.writableLocation(StandardPaths.HomeLocation) onAccepted: { button.visible = false - grid.anchors.bottom = root.bottom + view.anchors.bottom = root.bottom EdenGameList.addDir(folder) } } - GridView { - id: grid + // GameGrid { + // setting: parent.setting - property int cellSize: Math.floor(width / setting.value) + // id: grid - highlightFollowsCurrentItem: true - clip: true - - cellWidth: cellSize - cellHeight: cellSize + 60 * Constants.scalar + // anchors.bottom: button.top + // anchors.left: parent.left + // anchors.margins: 8 + // anchors.right: parent.right + // anchors.top: parent.top + // } + Item { + id: view anchors { - top: parent.top + bottom: button.top left: parent.left right: parent.right - - bottom: button.top - - margins: 8 + top: parent.top + margins: 8 * Constants.scalar } - model: EdenGameList + GameCarousel { + id: carousel - delegate: GamePreview { - id: game + height: 300 - width: grid.cellSize - 20 * Constants.scalar - height: grid.cellHeight - 20 * Constants.scalar - } + anchors { + right: view.right + left: view.left - highlight: Rectangle { - color: "transparent" - z: 5 - - radius: 16 * Constants.scalar - border { - color: Constants.text - width: 3 + verticalCenter: view.verticalCenter } } - - focus: true - focusPolicy: "StrongFocus" } Button { diff --git a/src/eden/qml/main/MarqueeText.qml b/src/eden/qml/main/MarqueeText.qml new file mode 100644 index 0000000000..7a70c53141 --- /dev/null +++ b/src/eden/qml/main/MarqueeText.qml @@ -0,0 +1,43 @@ +import QtQuick + +Item { + required property string text + + property int spacing: 30 + property int startDelay: 2000 + property int speed: 40 + + property alias font: t1.font + property alias color: t1.color + + id: root + + width: t1.width + spacing + height: t1.height + clip: true + + Text { + id: t1 + + SequentialAnimation on x { + loops: Animation.Infinite + running: true + + PauseAnimation { + duration: root.startDelay + } + + NumberAnimation { + from: root.width + to: -t1.width + duration: (root.width + t1.width) * 1000 / root.speed + easing.type: Easing.Linear + } + } + + Text { + x: root.width + text: t1.text + } + } +}