• Recent
  • Tags
  • Popular
  • Home
  • Docs
  • Register
  • Login
RetroPie forum home
  • Recent
  • Tags
  • Popular
  • Home
  • Docs
  • Register
  • Login

Pegasus theme development general

Scheduled Pinned Locked Moved Ideas and Development
pegasusqmltheme makingtheme help
156 Posts 16 Posters 50.9k Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S
    SinisterSpatula
    last edited by SinisterSpatula 18 Sept 2019, 03:39

    Hi @fluffypillow thanks for the info on favorites, I'm going to see if I can do that now. I'm having some problems using metadata and asset files I'm hoping you can help me. I am so stuck and confused right now. So, I'm trying to use cartridge artwork. I'm using source: game.assets.cartridge and in my metadata.pegasus.txt I have: assets.cartridge: media/cartridge/Bomberman Max - Blue Champion (USA).png and I verify that everything is valid, true, and correct, and it mentions in the documentation that cartridge is supposed to be a valid asset, yet none of them are loading. The true path on the SD card is: /home/pi/RetroPie/roms/genesis/media/cartridge/ I guess for now I'll look at finding a different asset that will work, like poster perhaps. Unless I'm just missing something. In fact, all the various media when using the pegasus metadata all seem to not work, I must be missing something.

    1 Reply Last reply Reply Quote 0
    • S
      SinisterSpatula
      last edited by 18 Sept 2019, 07:16

      Latest Video:

      1 Reply Last reply Reply Quote 2
      • A
        AndersHP @SinisterSpatula
        last edited by 18 Sept 2019, 08:43

        @SinisterSpatula
        Your theme's looking good!

        Will it support cover/box art as well as the marquees you use in the videos?

        My "Bubble Bobble" Themed Bartop Arcade
        My Gameboy

        S 1 Reply Last reply 18 Sept 2019, 08:47 Reply Quote 0
        • S
          SinisterSpatula @AndersHP
          last edited by SinisterSpatula 18 Sept 2019, 08:47

          @AndersHP Thanks! :D Yes currently for grid art it supports: Box Front art, screenshot, wheel, Steam tile's, and cartridges. For backgrounds, it can do: screenshot, fan art, the default image, or a solid color. All are changeable on a whim in the settings menu (select button). This is the guide I'm putting together for it: https://sinisterspatula.github.io/RetroflagGpiGuides/Pegasus

          A 1 Reply Last reply 18 Sept 2019, 08:50 Reply Quote 0
          • A
            AndersHP @SinisterSpatula
            last edited by 18 Sept 2019, 08:50

            @SinisterSpatula
            That's great! I don't know RetroFlag that well, but I guess this platform doesn't do anything differently than a Raspberry Pi-based Pegasus installation will?

            Can't wait to smash this theme on my new Gameboy build!

            My "Bubble Bobble" Themed Bartop Arcade
            My Gameboy

            S 1 Reply Last reply 18 Sept 2019, 08:53 Reply Quote 0
            • S
              SinisterSpatula @AndersHP
              last edited by 18 Sept 2019, 08:53

              @AndersHP Yeah, the Retroflag Gpi is just a pi zero in a shell. The screen image is sent over GPIO that's about the only thing special about it. It's a killer design (the zero is inside a fake gameboy cart shell, and the PCB in the shell connects to the main body via a cart slot.

              1 Reply Last reply Reply Quote 0
              • S
                SinisterSpatula
                last edited by SinisterSpatula 19 Sept 2019, 04:29

                I tried the favorites filtering, and it does filter properly, but there are so many moving parts to the theme that it goes sideways fast, if I simply just update the grid itself with the new model, then other things that are pointing at variables like collectionData, gameData, currentGameIdx start to get wrong information. The grid indexes get changed so what used to be game index 10 is now game index 0, etc. -- I took another hard look and I'm thinking the theme is grabbing the current collection of games with this: property var currentCollection: api.collections.get(collectionIndex) and I just am not figuring out how the sort proxy filter can be used with this, like it is a different Item Model type or something?

                F P A 3 Replies Last reply 19 Sept 2019, 07:04 Reply Quote 0
                • F
                  fluffypillow @SinisterSpatula
                  last edited by 19 Sept 2019, 07:04

                  @SinisterSpatula don't panic, it can be solved! :) The sorting/filtering produces a new list of objects (as it doesn't touch the source), so if some games get rearranged or removed then their index (ie. position) in the new list will also differ from what they have in the source model. The SortFilterProxyModel objects have two handy functions for this:

                  • int mapToSource(int proxyRow): based on an index from the sorted/filtered list, it tells you the game's position in the original model
                  • int mapFromSource(int sourceRow): based on an index from the original model, it tells you the game's new position in the sorted/filtered list

                  Both return -1 for missing items. The original documentation is here.

                  I'm trying to use cartridge artwork

                  I've just tried this, with the same filename and such, but it seems to work fine for me. Do you see any loading errors in the log? There should be either a warning related to the metadata file if the value could not be read, or there should be a QML error saying that the image could not be opened.

                  Also I'm happy to see the video progress too, nice!

                  1 Reply Last reply Reply Quote 0
                  • P
                    PlayingKarrde @SinisterSpatula
                    last edited by 19 Sept 2019, 17:08

                    @SinisterSpatula When I made the theme originally it was mainly just me learning QML so I was doing a lot of bad practices. Ultimately really the best way to make these themes (and if I ever get around to doing a proper cleanup pass I'll do this) is to keep all your variables stored in one place and pass them down rather than referencing them again and again. @fluffypillow may want to correct me if I'm wrong on this (and he's already provided a solution above), but ideally these variables you are getting and setting should get stored in the theme.qml and passed down each time.

                    I mean it's kind of annoying having to do this rather than being able to reference the top level directly within (maybe this is possible I don't know) but at least then you have clean references that only need to be updated in one place then.

                    1 Reply Last reply Reply Quote 0
                    • S
                      SinisterSpatula
                      last edited by SinisterSpatula 20 Sept 2019, 04:41

                      Thanks for the replies guys. I'm still wracking my brain trying to figure it out, lol. But I was having similar thoughts about it. Was just thinking, I need to refactor the code so that I have a "clean, focused" set of variables that everything else will access from. So that I know everything is grabbing and using the same information across all places. What I am really struggling with is, when using the ProxySortFilter it provides me with a model. I guess I'm trying to figure out how to best use that model as a "variable" so that for example, the game's title at the top of the screen, can access the currently selected game's name. Currently, the game details view, and the Title of the game, and launching of the game, etc, are all pulling from readonly property var currentGame: currentCollection.games.get(currentGameIndex) so I'm trying to figure out, how I can take the results from the ProxySortFilter, and place it into currentGame, by using the mapFromSource(int sourceRow). I guess I really need some hand holding on this LOL. Maybe, in the theme.qml main file, I just need to maintain two sets of data, one that is filtered, and one that is not. And a third set which everything accesses. Then I would swap the third with the first or second.

                      Another issue I'm thinking about, I noticed when I broke a lot of the logic, that the grid view scrolling actually gained a lot of performance. I think it's being slowed down by the logic of switching the background art immediately upon moving to the next grid item. Wondering if there is a simple way to wait for scrolling to stop for 5 seconds, before switching the background art.

                      It almost seems like, maybe I just need to redo the DetailsRequested() to include the game that belongs to the grid item? That way it shows the proper game always, when being opened. And the game title just needs a way to point at the currently selected grid items, modelData?

                      1 Reply Last reply Reply Quote 0
                      • F
                        fluffypillow
                        last edited by 20 Sept 2019, 08:00

                        I've just made an example theme, might help with sorting/filtering: https://github.com/mmatyas/pegasus-theme-proxy-example

                        Yes, it is possible to use variables from the top level file (and, in general, from parent files), and collecting them in one place is also a good idea. Just make sure you keep track which part of the code modifies which; global variables are easier to use, but may make harder to track down issues in large projects. It should be fine in most themes though.

                        Proxy models also have a get(index) function you can use to get a game. There shouldn't be a need to manually swap sets of data, unless you do some very special processing I think. You can create as many proxies as you wish, and you can also turn on/off the filters/sorters individually as well.

                        For the background imges, you can use Timers; there should be one already in the theme (unless it was removed since), similar to your case, but for waiting before starting videos.

                        S 1 Reply Last reply 20 Sept 2019, 09:47 Reply Quote 1
                        • S
                          SinisterSpatula @fluffypillow
                          last edited by 20 Sept 2019, 09:47

                          @fluffypillow Thank you so much for the example! It's clarified some things for me, a bit and given me ideas of things to try. If I still can't get it, I think I'll just start over from scratch and build from there. Since I'm just learning, that might not be a bad thing.

                          1 Reply Last reply Reply Quote 0
                          • S
                            SinisterSpatula
                            last edited by SinisterSpatula 21 Sept 2019, 18:36

                            I loaded up the example, just to see what it would do, and it looks like the favorites get populated, but the other's don't. Looking at the code, the only difference between favorites and "GameList" (all games) is that GameList does not use a filter. I would expect allGames to have a better chance at populating than the favorites? If the favorites can populate, allGames and Recently played certainly should. Very strange.
                            alt text

                            So api.allGames does not work (it's blank). But I can do this and it works:

                                property var currentCollection: api.collections.get(2)
                                SortFilterProxyModel {
                                    id: sortedGames
                                    sourceModel: currentCollection.games
                                    sorters: RoleSorter {
                                        roleName: "lastPlayed"
                                    }
                                }
                            

                            alt text

                            F 2 Replies Last reply 22 Sept 2019, 18:28 Reply Quote 0
                            • F
                              fluffypillow @SinisterSpatula
                              last edited by 22 Sept 2019, 18:28

                              @SinisterSpatula hm that's interesting, it works fine for me on desktop (that's how I made it). Do you see anything in the log? I wonder if it's related to the Pi, can you try it on other devices?

                              1 Reply Last reply Reply Quote 0
                              • A
                                AndersHP @SinisterSpatula
                                last edited by 23 Sept 2019, 06:49

                                @SinisterSpatula
                                If I was to just use your theme for grid view with box art only, is it then possible to try it out now? It looks great in your videos, and I could help you with feedback :)

                                My "Bubble Bobble" Themed Bartop Arcade
                                My Gameboy

                                S 1 Reply Last reply 27 Sept 2019, 22:57 Reply Quote 0
                                • F
                                  fluffypillow @SinisterSpatula
                                  last edited by 23 Sept 2019, 16:20

                                  @SinisterSpatula another idea, maybe it's just that those games have no image? There isn't any fallback added for that case, but you should still be able to click on the "place" of the games, and the rectangle and title on the top should update.

                                  1 Reply Last reply Reply Quote 0
                                  • M
                                    msheehan79
                                    last edited by 25 Sept 2019, 01:31

                                    @fluffypillow I've been going through your theme tutorials to try and learn a bit about QML and theme design - one of the features I was trying to take a stab at was a way to incorporate a "Recently Played" collection into a theme so that it would appear as another collection in the list. That is one of the features of ES2 that I really liked and I think would be a nice addition to themes on Pegasus.

                                    The challenge seems to be that in a ListView or PathView you can only have one model, which in most themes would be api.collections. But in order to have a recently played that spans all collections, I would need to use api.allGames as the source for the filter proxy.

                                    So I guess the question I have is do you have any suggestions for how one might go about incorporating 2 different models into a theme in some fashion? I'm still learning about QML so I might have missed something obvious. Still going to keep trying things and looking into it here but thought I'd bounce it off of you in case you have any tips.

                                    Thanks!

                                    F 1 Reply Last reply 25 Sept 2019, 19:43 Reply Quote 0
                                    • F
                                      fluffypillow @msheehan79
                                      last edited by 25 Sept 2019, 19:43

                                      @msheehan79 actually that's a really interesting question! A View operates over a list of items, which in practice either an item model you can access from the Api, or a plain JavaScript array. In fact, you could actually do this:

                                      model: [ api.collections.get(0),  api.collections.get(1),  api.collections.get(2) ] // etc.
                                      

                                      So the simplest way to add a "fake" collection would be setting the model to an array of collections, and put our custom one into it too. Now if we have a filter like this:

                                          SortFilterProxyModel {
                                              id: filteredGames
                                              sourceModel: api.allGames
                                              filters: ValueFilter {
                                                  roleName: "favorite"
                                                  value: true
                                              }
                                          }
                                      

                                      , a tempting first idea might be to put this filteredGames into the array... However, a filter over api.allGames produces a list of games, not a collection (it doesn't have a name, for example), so we should turn the list into one somehow. Themes can't "officially" create new collections, however this is JavaScript, so as long as it looks like a collections, ie. has the same properties as a collection, then it can be used as one just fine. If we then create a new object like this somewhere:

                                          // There are various ways to do this, this is just an example
                                          property var newCollection: {
                                              return {
                                                  name: "My Little Favorites",
                                                  games: filteredGames,
                                                  // feel free to add things like `shortName`, etc.
                                              }
                                          }
                                      

                                      , we can then include it in an array together with the other collections, and it will be treated just like the others:

                                      model: [ newCollection,  api.collections.get(0),  api.collections.get(1) ] // etc.
                                      

                                      And indeed it should work as expected:

                                      https://snipboard.io/DhJj8L.jpg

                                      Now obviously nobody wants to fill that array manually. Since it's a plain JS array, you could fill in a for loop or something. Item models also have a not really documented function called toVarArray which just returns the list of items as a plain array. For the nicest code however, we can use the fact that modern JavaScript constructs like the spread operator are also supported, and combine all that into this nice line:

                                      model: [ newCollection, ...api.collections.toVarArray() ]
                                      

                                      Example code repo here.

                                      1 Reply Last reply Reply Quote 3
                                      • M
                                        msheehan79
                                        last edited by 26 Sept 2019, 00:30

                                        @fluffypillow Nice! This is very helpful indeed. Hope to get some time in the next day or two to take another crack at it.

                                        I'm still figuring out exactly where in the code I can leverage JavaScript, so knowing I can use it in the model declaration for example is really useful info for me. Up until now I had pretty much just used it inside of functions called on keyPress events.

                                        1 Reply Last reply Reply Quote 0
                                        • S
                                          SinisterSpatula @AndersHP
                                          last edited by SinisterSpatula 27 Sept 2019, 22:57

                                          Hi @AndersHP you can definitely give it a try. I got a little frustrated with the project because I'm not versed enough on QML and finding it extremely difficult to understand lol. I haven't done anything for about a week, and I'm just now starting to regain motivation to try any more with it. I came back to see some really neat stuff about making a fake collection, and that is definitely one of the pieces of the puzzle that was confusing the hell out of me. My only issue is, whenever I start adding the sort proxy filter, things with the gameOS theme start behaving erratically. Once the model changes, the gridview disappears for a moment, but then if you start pressing navigating buttons, it reappears and everything is fine. I just couldn't figure out how I'm supposed to do it so that this doesn't cause it to bug out like that. My other problem is the performance of the grid scrolling. And I think this is down to all the fancy stuff in the theme, slowing it down. I feel like I want to just start over on a very basic code, with none of the fancy elements. I want the grid to flow and scroll as smooth as possible, and I'm thinking the best way is a grid view that only wants to show cartridge art (and maybe screenshot as fallback) but no scaling the currently selected tile, no changing font color to gray, or changing opacity, no animations at all, just the scrolling, and maybe a border around the current selection. Feel like I might start over on a clean code, just keeping the platform menu, and game details screens, and cutting back all the bling on the gridview. Then, trying to implement the fake collections of "Last Played" and "Favorites". If I could get to that point, I would be so happy with it. :D But man, it's a challenge, because I really don't know anything about javascript and QML and everything I try to do is really guesswork and trial and error. Someone who actually has skills at this could do it an 30 minutes, what is taking me weeks LOL.

                                          P 1 Reply Last reply 27 Sept 2019, 23:02 Reply Quote 1
                                          108 out of 156
                                          • First post
                                            108/156
                                            Last post

                                          Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.

                                          Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.

                                            This community forum collects and processes your personal information.
                                            consent.not_received