diff --git a/components/ActionButton.qml b/components/ActionButton.qml index fd09aa7..b0b91c1 100644 --- a/components/ActionButton.qml +++ b/components/ActionButton.qml @@ -29,6 +29,7 @@ Item { font.pixelSize: 14 visible: parent.activeFocus opacity: 0.5 + color: textColor anchors.bottom: parent.bottom anchors.bottomMargin: -20 anchors.horizontalCenter: parent.horizontalCenter diff --git a/components/GameDetail.qml b/components/GameDetail.qml index 64aafdb..920f53c 100644 --- a/components/GameDetail.qml +++ b/components/GameDetail.qml @@ -8,10 +8,10 @@ Item { property var active: false property var game: null property var showFullDescription: false - visible: active + //visible: active onGameChanged: { - console.log(game.assets.video) + //console.log(game.assets.video) } property var mainGenre: { @@ -19,26 +19,65 @@ Item { var s = g.split(',') return s[0] } + property var players: { + if (!game) { return "" } return game.players + " Player" + (game.players > 1 ? "s" : "") + ", " } + property var releaseDate: { + if (!game) { return "" } return "Released " + game.releaseYear } + property var developedBy: { + if (!game) { return "" } return "Developed By " + game.developer } property var textColor: { return "#333333" } + property var margin: { return 32 } + property var introDescription: { + if (!game) { return "" } return game.description.replace("\n"," ") } + property var gameIsFavorite: { + if (game) { + return game.modelData.favorite + } else { + return false + } + } + property var gameScreenshot: { + if (game) { + return game.assets.screenshot + } else { + return null + } + } + property var gameVideo: { + if (game) { + return game.assets.video + } else { + return null + } + } + property var textScroll: 10 + + Keys.onPressed: { + if (api.keys.isCancel(event) && active) { + event.accepted = true + showGameDetail(false) + } + } + /** * Background */ @@ -78,7 +117,7 @@ Item { anchors.left: parent.left anchors.top: parent.top maximumLineCount: 2 - text: game.title + text: game ? game.title : "No Game" lineHeight: 1.1 color: textColor font.pixelSize: 24 @@ -143,14 +182,9 @@ Item { KeyNavigation.right: actionFavorite KeyNavigation.down: gameDetailText Keys.onPressed: { - // Back to Home - + // Start Game if (api.keys.isAccept(event)) { - console.log("play") - - var g = gamesItems.get(gameList.currentIndex) - console.log(g.modelData) - g.modelData.launch() + startGame(game.modelData, currentGameDetailIndex) } } @@ -160,20 +194,18 @@ Item { textColor: gameDetail.textColor KeyNavigation.left: actionPlay KeyNavigation.down: gameDetailText - title: game.modelData.favorite ? "Unfavorite" : "Favorite" - icon: game.modelData.favorite ? "favorite-on" : "favorite-off" + title: gameIsFavorite ? "Unfavorite" : "Favorite" + icon: gameIsFavorite ? "favorite-on" : "favorite-off" focus: false height: 40 width: 120 Keys.onPressed: { - // Back to Home - if (api.keys.isAccept(event)) { - + // Favorite + if (api.keys.isAccept(event)) { game.modelData.favorite = !game.modelData.favorite event.accepted = true; - console.log("fav") } } @@ -188,8 +220,8 @@ Item { width: 280 anchors.right: parent.right anchors.top: parent.top - screenshot: game.assets.screenshot - video: game.assets.video + screenshot: gameScreenshot + video: gameVideo active: gameDetail.active } @@ -210,6 +242,16 @@ Item { //height: 100 height: 127 + // Rectangle { + // anchors.fill: parent + // anchors.leftMargin: -15 + // anchors.rightMargin: -15 + // anchors.bottomMargin: -15 + // radius: 8 + // color: "#000000" + // opacity: parent.activeFocus ? 0.1 : 0.0 + // } + Keys.onPressed: { // Back to Home if (api.keys.isAccept(event)) { @@ -244,7 +286,8 @@ Item { anchors.leftMargin: parent.left anchors.rightMargin: parent.right wrapMode: Text.WordWrap - color: parent.activeFocus ? "#50000000" : textColor + //color: parent.activeFocus ? "#50000000" : textColor + color: textColor font.pixelSize: 18 font.letterSpacing: -0.1 font.bold: true @@ -326,6 +369,17 @@ Item { height: 480 focus: showFullDescription + property var scrollMoveAmount : 100 + Keys.onDownPressed: { + var maxHeight = textElement.paintedHeight - (480 - 50 - 50) + + textScroll = Math.max(Math.min(textScroll + scrollMoveAmount, maxHeight), 10) + } + + Keys.onUpPressed: { + textScroll = Math.max(textScroll - scrollMoveAmount, 10) + } + Keys.onPressed: { // Back to Home if (api.keys.isCancel(event)) { @@ -336,6 +390,8 @@ Item { } } + + Rectangle { color: theme.background anchors.fill: parent @@ -344,7 +400,7 @@ Item { Image { id: boxart - source: game.assets.screenshot + source: gameScreenshot anchors.fill: parent fillMode: Image.PreserveAspectCrop visible: false @@ -367,19 +423,24 @@ Item { // } Text { + id: textElement text: game.description anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.leftMargin: 50 anchors.rightMargin: 50 - anchors.topMargin: 50 + anchors.topMargin: 50 - textScroll font.pixelSize: 18 font.letterSpacing: -0.35 font.bold: true wrapMode: Text.WordWrap maximumLineCount: 2000 lineHeight: 1.2 + + Behavior on anchors.topMargin { + PropertyAnimation { easing.type: Easing.OutCubic; duration: 200 } + } } } diff --git a/components/GameScreenshot.qml b/components/GameScreenshot.qml index d4009e6..813f17f 100644 --- a/components/GameScreenshot.qml +++ b/components/GameScreenshot.qml @@ -11,6 +11,14 @@ Item { width: parent.width height: parent.height property var active: false + onActiveChanged: { + if (video && active) { + videoPlayer.play() + } else { + videoPlayer.stop() + } + } + // Shadow. Using an image for better shadow visuals & performance. Image { id: game_box_shadow @@ -33,9 +41,10 @@ Item { } Video { + id: videoPlayer anchors.fill: parent fillMode: Image.PreserveAspectCrop - source: active ? video : null + source: video autoPlay: true loops: MediaPlayer.Infinite } diff --git a/components/GamesList.qml b/components/GamesList.qml index 76ac3c8..2c73f73 100755 --- a/components/GamesList.qml +++ b/components/GamesList.qml @@ -29,7 +29,6 @@ Item { property alias box_art : game_box_art property var hideFavoriteIcon : false property var defaultIndex: 0 - property var launchingGame : false property var items : [] property var indexItems : [] property var showIndex : false @@ -83,6 +82,13 @@ Item { Keys.onPressed: { // Show / Hide Index + // Details + if (api.keys.isDetails(event)) { + event.accepted = true + showGameDetail(selectedGame, gameView.currentIndex) + return + } + if (api.keys.isAccept(event) && showIndex) { event.accepted = true; showIndex = false; @@ -110,18 +116,6 @@ Item { onIndexChanged(gameView.currentIndex, items.count) } - Timer { - id: timer - } - - function delay(delayTime, cb) { - timer.interval = delayTime; - timer.repeat = false; - timer.triggered.connect(cb); - timer.start(); - } - - Rectangle { id: mainListContent color: "transparent" @@ -275,15 +269,7 @@ Item { //gameView.currentIndex = 0 onSeeAll() } else { - currentGameIndex = index - launchSound.play() - launchingGame = true - - setCollectionListIndex(index) - - delay(400, function() { - modelData.launch() - }) + startGame(modelData, index) } return; } @@ -355,39 +341,7 @@ Item { } } - - /** - Loading Overlay - */ - Rectangle { - id: loading_overlay - opacity: 0.0 - color: "#000000" - anchors { - fill: parent - bottomMargin: -100 - topMargin: -100 - } - states: [ - - State{ - name: "default"; when: !launchingGame - PropertyChanges { target: loading_overlay; opacity: 0.0} - }, - - State{ - name: "active"; when: launchingGame - PropertyChanges { target: loading_overlay; opacity: 1.0} - } - - ] - - transitions: Transition { - NumberAnimation { properties: "opacity"; easing.type: Easing.Out; duration: 350 } - } - z: 2002 - } - + Rectangle { id: game_detail visible: true diff --git a/components/GamesPage.qml b/components/GamesPage.qml index 2931f38..6a6f398 100644 --- a/components/GamesPage.qml +++ b/components/GamesPage.qml @@ -6,7 +6,7 @@ Item { anchors.leftMargin: 200 property var showSort : false - property var showGameDetail : false + //property var showGameDetail : false property alias currentIndex: gameList.currentIndex property alias showIndex: gameList.showIndex @@ -14,10 +14,6 @@ Item { property var footerTitle: { return gameList.footerTitle } - - property var systemColor: { - systemColors[currentCollection.shortName] || "#000000" - } property var headerTitle: { return (collectionShowAllItems) ? "All " + currentCollection.name : currentCollection.name @@ -98,20 +94,14 @@ Item { return; } - // Details - if (api.keys.isDetails(event)) { - event.accepted = true - showGameDetail = true - return - } - // Back to Home if (api.keys.isCancel(event)) { event.accepted = true - if (showGameDetail) { - showGameDetail = false + //if (showGameDetail) { + //showGameDetail(null) + //showGameDetail = false //listFocus.focus = true - } else if (showIndex == true) { + if (showIndex == true) { showIndex = false } else if (showSort) { showSort = false @@ -231,10 +221,10 @@ Item { ButtonLegend { id: button_legend_details - title: "Favorite" + title: "Details" key: "X" width: 75 - visible: collectionFilterMode == "all" || collectionShowAllItems + visible: true//collectionFilterMode == "all" || collectionShowAllItems anchors.left: button_legend_back.right anchors.leftMargin: 24 anchors.verticalCenter: parent.verticalCenter @@ -348,7 +338,7 @@ Item { */ FocusScope { id: listFocus - focus: currentPage === "GamesPage" && !showSort && !showGameDetail ? true : false ; + focus: currentPage === "GamesPage" && !showSort && !isShowingGameDetail ? true : false ; width: parent.width height: parent.height anchors.top: header.bottom @@ -370,7 +360,7 @@ Item { onSeeAll: onSeeAllEvent sortMode: collectionSortMode sortDirection: collectionSortDirection - focus: true + focus: true && !isShowingGameDetail } } } @@ -379,10 +369,4 @@ Item { active: showSort sortColor: systemColor } - - GameDetail { - anchors.fill: parent - active: showGameDetail - game: gameList.selectedGame - } } diff --git a/components/HomePage.qml b/components/HomePage.qml index 3f4f74e..0533656 100644 --- a/components/HomePage.qml +++ b/components/HomePage.qml @@ -84,7 +84,7 @@ Item { FocusScope { id: mainFocus - focus: currentPage === "HomePage" ? true : false ; + focus: currentPage === "HomePage" && !isShowingGameDetail ? true : false ; anchors { left: parent.left @@ -144,7 +144,7 @@ Item { items: allFavorites indexItems: allFavorites sortMode: "title" - focus: true + focus: true && !isShowingGameDetail hideFavoriteIcon: true } } @@ -169,7 +169,7 @@ Item { items: allRecentlyPlayed indexItems: allRecentlyPlayed sortMode: "recent" - focus: true + focus: true && !isShowingGameDetail } } @@ -194,7 +194,7 @@ Item { indexItems: androidCollection.games sortMode: "title" visible: currentHomeIndex == 3 - focus: currentHomeIndex == 3 + focus: currentHomeIndex == 3 && !isShowingGameDetail } } diff --git a/theme.cfg b/theme.cfg index e9a137b..add0df2 100644 --- a/theme.cfg +++ b/theme.cfg @@ -1,2 +1,3 @@ name: Retro Mega -author: djfumberger \ No newline at end of file +author: djfumberger +description: Clean and modern theme designed for the Retroid Pocket 2. \ No newline at end of file diff --git a/theme.qml b/theme.qml index ac00262..cd84011 100644 --- a/theme.qml +++ b/theme.qml @@ -8,6 +8,17 @@ import 'components' as Components FocusScope { id: root + Timer { + id: timer + } + + function delay(delayTime, cb) { + timer.interval = delayTime; + timer.repeat = false; + timer.triggered.connect(cb); + timer.start(); + } + Component.onCompleted: { currentHomeIndex = api.memory.get('homeIndex') ?? 0 currentCollectionIndex = api.memory.get('currentCollectionIndex') ?? 0 @@ -19,7 +30,7 @@ FocusScope { collectionShowAllItems = api.memory.get('collectionShowAllItems') ?? false startSound.play() } - + // Collection index property var currentCollectionIndex : 0 property var currentCollection: { @@ -111,6 +122,41 @@ FocusScope { currentPage = page } + property var currentGameDetail : null + property var currentGameDetailIndex : 0 + property var isShowingGameDetail : false + function showGameDetail(game, index) { + if (game) { + forwardSound.play() + currentGameDetail = game + currentGameDetailIndex = index + isShowingGameDetail = true + } else { + backSound.play() + isShowingGameDetail = false + } + } + + // When the game is launching + property var launchingGame : false + function startGame(game, index) { + currentGameIndex = index + setCollectionListIndex(index) + launchSound.play() + launchingGame = true + delay(400, function() { + game.launch() + }) + } + + property var systemColor: { + if (currentPage === 'GamesPage') { + return systemColors[currentCollection.shortName] || "#000000" + } else { + return "#000000" + } + } + property var theme : { "background": "#F3F3F3", "text":"#70000000", @@ -298,6 +344,8 @@ FocusScope { height: layoutScreen.height anchors.top: parent.top + + // Home Page Components.HomePage { visible: currentPage === 'HomePage' ? 1 : 0 ; @@ -307,7 +355,75 @@ FocusScope { Components.GamesPage { id: gamesPage visible: currentPage === 'GamesPage' ? 1 : 0 ; - } + opacity: 1.0 + transitions: Transition { + NumberAnimation { properties: "opacity"; easing.type: Easing.InCubic; duration: 200 } + } + + + } + + // Game Detail + Component { + id: gameDetail + Components.GameDetail { + //visible: isShowingGameDetail + id: gameDetailContentView + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.left + anchors.rightMargin: 0 + anchors.leftMargin: 0 + opacity: 1.0 + active: isShowingGameDetail + game: currentGameDetail + + transitions: Transition { + NumberAnimation { properties: "opacity"; easing.type: Easing.OutCubic; duration: 1600 } + } + + } + + } + + Loader { + id: gameDetailLoader + focus: isShowingGameDetail + active: isShowingGameDetail + anchors.fill: parent + sourceComponent: gameDetail + asynchronous: false + } } + + /** + Loading Game Overlay + */ + Rectangle { + id: loading_overlay + opacity: 0.0 + color: "#000000" + anchors { + fill: parent + } + states: [ + + State{ + name: "default"; when: !launchingGame + PropertyChanges { target: loading_overlay; opacity: 0.0} + }, + + State{ + name: "active"; when: launchingGame + PropertyChanges { target: loading_overlay; opacity: 1.0} + } + + ] + + transitions: Transition { + NumberAnimation { properties: "opacity"; easing.type: Easing.Out; duration: 350 } + } + z: 2002 + } } \ No newline at end of file