HateDread
Topic Author
Posts: 71
Joined: 06 Feb 2020, 10:27

Recommendations for transitioning overall UI state/context, e.g. Main Menu -> Game UI?

29 Jun 2021, 17:20

I'm currently loading in a xaml file on start-up to represent the main menu, based off of the samples.

What I'm not sure about is how others tend to handle the transition from the menu into the game. For example, I could imagine driving most of it from the xaml itself, swapping out elements / loading another xaml asset all from within UI code, as opposed to a button click that talks to some underlying systems that manually load another xaml asset, destroying the current view and swapping it out (more of a clean break, I suppose, with the authority outside of UI land), or at least somehow swapping out the xaml asset used by the view without destroying it if possible.

Basically; does your game become completely UI-driven where the xaml itself knows which other assets to load and triggers that on world/level/state switch that it manages, or are your button presses firing off some events/callbacks that live far outside the Code-Behind / XAML? How are you handling moving between these major states and back again?

Thanks.
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: Recommendations for transitioning overall UI state/context, e.g. Main Menu -> Game UI?

01 Jul 2021, 10:33

If you use a MVVM pattern you can say that game is driven by the Model, and the UI only reflects the current state of the Model.

For example, you can have a root XAML with a ContentControl that is bound to the current screen ViewModel. Depending on the type of the ViewModel there will be a DataTemplate that represents each of the screens. When you change in code the current viewmodel, the UI will load a new data template to show the corresponding screen.
<ContentControl Content="{Binding CurrentScreen}"/>
 
HateDread
Topic Author
Posts: 71
Joined: 06 Feb 2020, 10:27

Re: Recommendations for transitioning overall UI state/context, e.g. Main Menu -> Game UI?

01 Jul 2021, 18:04

If you use a MVVM pattern you can say that game is driven by the Model, and the UI only reflects the current state of the Model.

For example, you can have a root XAML with a ContentControl that is bound to the current screen ViewModel. Depending on the type of the ViewModel there will be a DataTemplate that represents each of the screens. When you change in code the current viewmodel, the UI will load a new data template to show the corresponding screen.
<ContentControl Content="{Binding CurrentScreen}"/>
Ahh, thanks - I didn't even know that was possible! Will try to wrap my head around it.

Sounds like I'd have a fairly bare base/shell xaml and swap out on top of that based on the binding. By "When you change in code the current viewmodel", if set up right it sounds like the type of the value passed to IView::SetDataContext would control the active data template? Thus the backend/game/engine could just swap that out and the UI would follow.

From some searching, it sounds like it's basically similar to this implementation? https://stackoverflow.com/a/15960843/3475248

PS I realized some of my confusion was that in my testing and integration, I copied the Scoreboard sample's MainWindow.xaml.* files for experimentation, and got confused over the 'ownership'/control since it has "GUI::LoadComponent(this, "MainWindow.xaml");" in its InitializeComponent definition yet I'm setting the xaml to load when I call "GUI::CreateView(MainWindowXAMLGoesHere);". Guess I was just setting it twice so I never noticed the problem.

EDIT: Figured it out. Will come back later today/tonight with some more questions.
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: Recommendations for transitioning overall UI state/context, e.g. Main Menu -> Game UI?

05 Jul 2021, 10:17

If set up right it sounds like the type of the value passed to IView::SetDataContext would control the active data template? Thus the backend/game/engine could just swap that out and the UI would follow. From some searching, it sounds like it's basically similar to this implementation? https://stackoverflow.com/a/15960843/3475248
Yes, that was exactly the idea.
PS I realized some of my confusion was that in my testing and integration, I copied the Scoreboard sample's MainWindow.xaml.* files for experimentation, and got confused over the 'ownership'/control since it has "GUI::LoadComponent(this, "MainWindow.xaml");" in its InitializeComponent definition yet I'm setting the xaml to load when I call "GUI::CreateView(MainWindowXAMLGoesHere);". Guess I was just setting it twice so I never noticed the problem.
This is needed when including a UserControl in other xaml. It indicates the xaml used to load the contents of the control when it gets instantiated.
 
HateDread
Topic Author
Posts: 71
Joined: 06 Feb 2020, 10:27

Re: Recommendations for transitioning overall UI state/context, e.g. Main Menu -> Game UI?

06 Jul 2021, 19:20

PS I realized some of my confusion was that in my testing and integration, I copied the Scoreboard sample's MainWindow.xaml.* files for experimentation, and got confused over the 'ownership'/control since it has "GUI::LoadComponent(this, "MainWindow.xaml");" in its InitializeComponent definition yet I'm setting the xaml to load when I call "GUI::CreateView(MainWindowXAMLGoesHere);". Guess I was just setting it twice so I never noticed the problem.
This is needed when including a UserControl in other xaml. It indicates the xaml used to load the contents of the control when it gets instantiated.
Would you expect that this would lead to multiple log messages loading the same xaml file? I presume the file is cached? Example:
class ShipListEntryView : public Noesis::UserControl
{
public:
	ShipListEntryView()
	{
		InitializeComponent();
	}

	void InitializeComponent()
	{
		Noesis::GUI::LoadComponent(this, "Controls/ShipListEntryView.xaml");
	}

private:
	NS_IMPLEMENT_INLINE_REFLECTION(ShipListEntryView, UserControl, "rtg.Controls.ShipListEntryView")
	{

	}
};
And I have a few of those hard-coded into the main game UI xaml just to test the appearance.
[ 07/07/21 03:09:04 ] [info] [RTG] 'Controls/ShipListEntryView.xaml' loaded
[ 07/07/21 03:09:51 ] [info] [RTG] 'Controls/ShipListEntryView.xaml' loaded
[ 07/07/21 03:09:52 ] [info] [RTG] 'Controls/ShipListEntryView.xaml' loaded
[ 07/07/21 03:09:52 ] [info] [RTG] 'Controls/ShipListEntryView.xaml' loaded
[ 07/07/21 03:10:00 ] [info] [RTG] 'Controls/ShipListEntryView.xaml' loaded
[ 07/07/21 03:10:00 ] [info] [RTG] 'Controls/ShipListEntryView.xaml' loaded
Additionally, I've got this kind of thing working, as stated, where I can switch the main xaml by swapping out the ViewModel. My MainWindow.xaml (a Grid for now since I already have a window outside of Noesis land):
<Grid
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:rtg"
    xmlns:local-views="clr-namespace:rtg.Views" Background="Transparent">
    <Grid.Resources>
        <DataTemplate DataType="{x:Type MenuViewModel}">
            <local-views:MenuView/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type GameViewModel}">
            <local-views:GameView/>
        </DataTemplate>
    </Grid.Resources>
	<ContentControl Content="{Binding Path=CurrentViewModel}"></ContentControl>
</Grid>
And I set "CurrentViewModel" on my class "MainViewModel", which is always set as the data context for the IView. E.g.
class MainViewModel : public ViewModelBase
{
public:

	ViewModelBase* GetCurrentViewModel() const;
	void SetCurrentViewModel(ViewModelBase* viewModel);

private:
	ViewModelBase* currentViewModel_ = nullptr;

	NS_DECLARE_REFLECTION(MainViewModel, ViewModelBase)
};
Called via some (crappy) code like so
	if (world->name_ == "menuWorld")
	{
		SetCurrentViewModel(impl_->pMenuViewModel.GetPtr());
	}
	else
	{
		SetCurrentViewModel(impl_->pGameViewModel.GetPtr());
	}
This all seems to work. Is this what you'd expect?

Presuming that it is;
  • How do you then have multiple ViewModels in play at once if you need to set a 'main' view model to swap the overall xaml out? E.g. I set 'current view model' to my GameViewModel and that automatically switches the UI to some GameView.xaml, which is great! But what if I want a half-dozen other ViewModels on top that contain different things required for parts of the UI? E.g. one for the group of units the player controls (needed for unit icons, status bars, etc), another for world data (current world time, state, time/play/pause control delegates etc), and so on. Any views that are created from this GameView.xaml simply inherit GameViewModel as their DataContext, and I don't want that ViewModel to be monolithic. How would you wrangle/layer these additional ViewModels with this setup?
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: Recommendations for transitioning overall UI state/context, e.g. Main Menu -> Game UI?

08 Jul 2021, 01:14

Would you expect that this would lead to multiple log messages loading the same xaml file? I presume the file is cached?
The log messages are expected when using the usercontrol to render items of a list, because it creates one for each visible item.
Right now we are not caching the xaml file because the loading is fast enough and didn't have reports about real problems with this. Anyway we have plans to incorporate some sort of caching of the parsed tree to optimize xaml loading: #1301.

Regarding the viewmodels, an application usually has like a tree of viewmodels (a root viewmodel with properties exposing other viewmodels or lists of viewmodels, which will expose more viewmodels, etc.). In your main UI you can have several regions (different ContentControls or ItemsControls) that bind to those different properties. So you are not limited to a single VM and a single ContentControl, you can have many at the same time rendering the UI.

Who is online

Users browsing this forum: Bing [Bot] and 88 guests