The Game Discovery Center - Theme Tutorial
This post should help theme developers create a custom theme for the Game Discovery Center. I assume you already have some knowledge about how Big Box themes work.
Written By Brian Faeran
Last updated 26 days ago
What is the Game Discovery Center
From a themers perspective, the Game Discovery Center is a list embedded in another list. You have a list of games inside of a list of lists. It consists of just one xaml file where all code is located within. The file is called DiscoveryPageView.xaml
How to start coding this view in your Custom Theme
Assuming that you've run Big Box at least once with version 13.10 or higher, you can simply find the following file and copy it into your own custom theme's Views folder:
LaunchBox\Themes\Default\Views\DiscoveryPageView.xamlTo start editing the view, open your custom theme's project file, or open the DiscoveryPageView.xaml directly.
The View File
This section will break down the major parts of this file, so you can get an idea of what things are.
The Parent List (The List of Lists)
This will show up in the code as: <flow:DiscoveryPageList ...>
Place this code where you want all the lists to appear on the screen. Here's a list of some properties you should know about:
VisibleRows (int)
This controls how many rows should be visible at any given time. The lower the number the better performance, but go too low and you could get rows appearing from out of nowhere. You'll need to find a balance based on what your view looks like.
SelectedItemPosition
This controls where the selected row will appear in the space you provide. This can force the selected list to always appear in one spot on the screen.
The values are: Bottom, Center, None, Top
SelectedItemOffset (int)
This will offset the list on the y-axis, starting at the top of the space provided, to give you more granular control over where the selected list appears.
The following sections are used inside of the DiscoveryPageList:
flow:DiscoverypageList.Style (optional)
A basic Style section. In the default theme, it's used to change the SelectedItemOffset and SelectedItemPosition values for specific lists.
flow:DiscoveryPageList.ItemTemplate
This will contain what each list will look like.
A DataTemplate will hold the layout of what each list will look like.
Inside of a DataTemplate, you can add a FlowControl list or a ListView list (or both). These lists will contain the list of games (You can see examples of both inside of the default DiscoveryPageView.xml file). A FlowControl is a regular wheel type of list and is heavily documented inside of the Documentation.pdf file. A ListView is a type of list that is used in Text List Views, as well as the thumbnail lists on some platform views that display favorited and recently played games.
flow:DiscoveryPageList.ContentLists
This will contain the type of lists you want to see in your view. They will display in the order that you list them. The default theme contains a number of them that you can use. There are two distinct types of lists you can use:
Hardcoded Lists
We've hardcoded a number of lists that can be used inside your view
Lists a random group of favorited games
<win:BindingProxy x:Key="Favorites" Data="{Binding FavoritesList}" />Lists a random group of highly rated games of user ratings with a fallback to community star ratings
<win:BindingProxy x:Key="HighlyRated" Data="{Binding HighlyRatedList}" />Lists recently played games in the order of most recently played
<win:BindingProxy x:Key="RecentlyPlayed" Data="{Binding RecentlyPlayedList}" />Lists a random group of MAME Arcade games that are supported by the MAME High Score Leaderboard feature
<win:BindingProxy x:Key="MameHighScoresList" Data="{Binding MameHighScoresList}" />Lists a user's platforms in alphanumeric order
<win:BindingProxy x:Key="Platforms" Data="{Binding PlatformsList}" />Auto-Populated Lists
Lists based on our auto-populate playlist ruleset A list of all hardcoded binding options:
An example of a hardcoded list of recently played games:
Under the UserControl.Resources section of the view, add the following line to declare your list:
<win:BindingProxy x:Key="RecentlyPlayed" Data="{Binding RecentlyPlayedList}" />Then under the ContentLists section, place your list:
<controls:SingleItemCollection Item="{Binding Source={StaticResource RecentlyPlayed}, Path=Data}" />An example of a Auto-Populate list that shows recently added games: <controls:SingleItemCollection>
<controls:SingleItemCollection.Item>
<flow:GameContentList Title="Recently Added" Sort="DateAdded" MaximumItems="25" MinimumItems="5">
<flow:GameContentList.Criteria>
<flow:GameContentListCriteria Field="DateAdded" Comparison="RecentDays" Value="360" />
</flow:GameContentList.Criteria>
</flow:GameContentList>
</controls:SingleItemCollection.Item>
</controls:SingleItemCollection>flow:GameContentList
This list type will populate games based on the choices you make within. Here are notable properties and what they do:
Title
Gives your list a title which you could use in triggers and also use to display on the view somewhere
Sort
Will sort the list based on possible values:
DateAdded, DateModified, Developer, Favorite, GameCompleted, Genre, Installed, LastPlayed, LaunchBoxId, MameHighScore, MaxPlayers, Platform, PlayCount, PlayMode, PlayTime, Portable, Publisher, Rating, Region, ReleaseDate, ReleaseDateYear, ReleaseType, Series, Source, StarRating, Status, Title, Version, Random
SortAscending (bool)
Tells which direction the games will be sorted.
Default value is True
MaximumItems
The maximum amount of items that will be generated in this list
MinimumItems
The minimum amount of items that the list requires before it will be displayed
flow:GameContentList.Criteria
In this section, you can list all possible rules you want your list to adhere to. The rulesets are equal to what we have available under the auto-populate section when creating a playlist. It's highly recommended to build out an auto-populate playlist first so you can check if the games that get added to it meet what you want to accomplish. Then you can use that playlist to determine the values that need to be entered into the list.
The following are the 3 available fields and their potential values (Remember that not all Field values work with all Comparison values)
Field
AnyAchievement
AlternateName
Amazon
ApplicationRomPath
Broken
Complete
ControllerSupport
DateAdded
DateModified
Developer
Ea
EpicGames
Favorite
Genre
Gog
GogAchievements
Hide
Installed
LaunchBoxId
LastPlayed
HighScoreSupport
MaxPlayers
Notes
Platform
PlayCount
PlayMode
Portable
Publisher
Rating
Region
ReleaseDate
ReleaseType
RetroAchievements
Series
Source
SortTitle
Steam
SteamAchievements
StarRating
Status
Storefront
Title
Uplay
UseDosBox
UseScummVm
Version
XboxComparison
EqualTo
NotEqualTo
IsEmpty
IsNotEmpty
OnOrBefore
OnOrAfter
RecentDays
GreaterThan
LessThan
Contains
IsTrue
IsFalse
HasAllValues
HasAtLeastOneOf
HasNoneOfTheValues
IsBetweenDates
IsBetweenNumeric
MainGameIs
MainGameIsNot
AnyAppIs
NoAppIs
Supports
DoesntSupport
PartiallySupports
FullySupports
Requires
DoesntRequire
DoesntContain
IsSimilarTo
IsNotSimilarTo
IsAmazon
IsEpicGames
IsGog
IsOrigin
IsSteam
IsUplay
IsXbox
AchievementsSupported
AchievementsNotSupported
AchievementsNotStarted
AchievementsInProgress
AchievementsCompletedvValue
This is the value that you would input into the auto-populate playlist value field
Dynamic Lists
The system is designed to display an unlimited amount of dynamic lists which will start appearing after your lists in the XAML end. To the user this will be seamless, as a theme developer this is something you should be aware of when building your view. There's a lot of different types of lists that this can consist of, and each time the view loads, it will generate a completely random set of dynamic lists.
Here's a breakdown of some types of lists that may appear in this section:
Best - displays a random group of games that is above a specific user or community star rating
Explore - displays a random group of games
Worst - displays a random group of games that is below a specific user or community star rating
The above may also be combined with other pieces of metadata, for example:
Best of [year]
Explore [platform]
Worst of [genre]
Best [genre] games of [year]
F.A.Q.
I want some game lists to look different than other lists, how do I do this?
Within your UserControl.Resources section, you can create a number of different DataTemplates. You can use one DataTemplate as your default, while the others can be triggered for a specific type of list (ListType), or a specific list altogether (Title).
Let's say you create a "Default" template, a "Tall" template, and a "Sqaure" template.
ie: <DataTemplate x:Key=Default" ...>
ie: <DataTemplate x:Key=Tall" ...>
ie: <DataTemplate x:Key="Square" ...>
Under your flow:DiscoveryPageList.ItemTemplate section, you can use triggers to determine which lists or list types use which DataTemplates.
ie: Use the Tall template when displaying the MameHighScores listtype, and the Square template when displaying the list titled "Recently Added":
<ContentPresenter Content="{Binding}">
<ContentPresenter.Style>
<Style TargetType="ContentPresenter">
<Setter Property="ContentTemplate" Value="{StaticResource Default}"/> <Style.Triggers>
<DataTrigger Binding="{Binding ListType}" Value="MameHighScores">
<Setter Property="ContentTemplate" Value="{StaticResource Tall}" />
</DataTrigger>
<DataTrigger Binding="{Binding Title}" Value="Recently Added">
<Setter Property="ContentTemplate" Value="{StaticResource Square}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentPresenter.Style>
</ContentPresenter>How do I display an image or text outside of a template?
There are two distinctive ways to bind to the selected item:
SelectedListItem - changes instantly to the selected item (can cause performance issues) ie: Display publisher of selected game (points to the name of your DiscoveryPageList) <TextBlock Text="{Binding ElementName=DiscoveryList, Path=SelectedListItem.Publisher}" />
ActiveItem - changes to the selected item 500ms after navigation has stopped (more performant) ie: Display publisher of selected game <TextBlock Text="{Binding ActiveItem.Publisher}" />
It is recommended to use FlowImage to display your images.
Here are examples of it in use:
Display clear logo using ActiveItem:
<flow:FlowImage DataContext="{Binding ActiveItem}" ImageType="Clear Logos" />Display clear logo using SelectedListItem:
<flow:FlowImage DataContext="{Binding ElementName=DiscoveryList, Path=SelectedListItem}" ImageType="Clear Logos" />How do I display a video outside of a template?
It is recommended to use FlowVideo.
Here is an example of it in use:
Display video using ActiveItem:
<flow:FlowVideo DataContext="{Binding ActiveItem}" LoadDelay="3000" PlayVideo="True" PlayAudio="True" />How do I change the title of a hardcoded or dynamic list?
You can change the name of a title by using a DataTrigger. You'll find examples of this in the default theme.
Keep in mind that hardcoded and dynamic titles can not be translated into other languages. This DataTrigger will only work in the language you choose to make this DataTrigger for.
Here's an example of the code needed to change the Title of a specific list. This code will work if the TextBlock is outside of any lists:
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="{Binding ElementName=DiscoveryList, Path=SelectedList.Title}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=DiscoveryList, Path=SelectedList.Title}" Value="Best of Sega Genesis">
<Setter Property="Text" Value="Sega Genesis Does What Nintendon't" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>This code is saying if the title is equal to "Best of Sega Genesis", change it instead to "Sega Genesis Does What Nintendon't".