forked from eden-emu/eden
carousel/list view
Signed-off-by: crueter <swurl@swurl.xyz>
This commit is contained in:
parent
0e13a362f1
commit
97d648cac6
9 changed files with 244 additions and 65 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<std::string>, std::vector<std::string>> multiplayer_ban_list;
|
||||
|
||||
// Game List
|
||||
Setting<bool> show_add_ons{linkage, true, "show_add_ons", Category::UiGameList};
|
||||
Setting<u32> game_icon_size{linkage, 64, "game_icon_size", Category::UiGameList};
|
||||
Setting<u32> folder_icon_size{linkage, 48, "folder_icon_size", Category::UiGameList};
|
||||
Setting<u8> row_1_text_id{linkage, 3, "row_1_text_id", Category::UiGameList};
|
||||
Setting<u8> row_2_text_id{linkage, 2, "row_2_text_id", Category::UiGameList};
|
||||
std::atomic_bool is_game_list_reload_pending{false};
|
||||
Setting<bool> cache_game_list{linkage, true, "cache_game_list", Category::UiGameList};
|
||||
Setting<bool> favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList};
|
||||
QVector<u64> favorited_ids;
|
||||
// Setting<bool> show_add_ons{linkage, true, "show_add_ons", Category::UiGameList};
|
||||
// Setting<u32> game_icon_size{linkage, 64, "game_icon_size", Category::UiGameList};
|
||||
// Setting<u32> folder_icon_size{linkage, 48, "folder_icon_size", Category::UiGameList};
|
||||
// Setting<u8> row_1_text_id{linkage, 3, "row_1_text_id", Category::UiGameList};
|
||||
// Setting<u8> row_2_text_id{linkage, 2, "row_2_text_id", Category::UiGameList};
|
||||
// std::atomic_bool is_game_list_reload_pending{false};
|
||||
// Setting<bool> cache_game_list{linkage, true, "cache_game_list", Category::UiGameList};
|
||||
// Setting<bool> favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList};
|
||||
// QVector<u64> favorited_ids;
|
||||
|
||||
Setting<u8, true> grid_columns{linkage, 4, 1, 8, "grid_columns", Category::UiGameList};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
94
src/eden/qml/main/GameCarousel.qml
Normal file
94
src/eden/qml/main/GameCarousel.qml
Normal file
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
44
src/eden/qml/main/GameGrid.qml
Normal file
44
src/eden/qml/main/GameGrid.qml
Normal file
|
@ -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"
|
||||
}
|
|
@ -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 {
|
||||
|
|
43
src/eden/qml/main/MarqueeText.qml
Normal file
43
src/eden/qml/main/MarqueeText.qml
Normal file
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue