antsonthetree
Topic Author
Posts: 44
Joined: 09 Jan 2018, 15:56

UE4 Multiple NoesisViews

11 Jan 2018, 19:36

Hello,

I want to show two NoesisViews simultaneously on my display for a menu system. One view will have a button list on the left side. Clicking each button will display a new Noesis View on the right side. I realize I could combine all of this into a single Xaml file, but for specific reasons (very complex menus) I want the menus details on the right panel to have their own separate DataContexts.

Currently when I open a submenu in the right panel, I am no longer able to click any other buttons on the left panel. I've set the second NoesisView to Self HitTest Invisible, and there are no controls covering the buttons on the left. I've also experimented with Transparencey and NoHitTest in XAML but still no luck.

Any thoughts on how I could make this scenario work?
Is there a way to get click-thru behavior working on a NoesisView and still have functioning controls?
Alternately is it possible to set a different DataContext to 'sections' of a single Xaml file? (this would be ideal)

One method I have not tried yet is to build a standard UMG widget as my fullscreen menu container. I would then add NamedSlot controls for the left panel and right panels. Then I could dynamically switch out the correct NoesisViews into the NamedSlot panel on the right. Not sure if this is ideal or not but I'm just brainstorming. I'd rather not have to do this honestly. My primary interest in this product is that it lets me ditch UMG entirely.

Thanks
Jake
 
User avatar
Scherub
Posts: 141
Joined: 06 May 2014, 20:53
Contact:

Re: UE4 Multiple NoesisViews

11 Jan 2018, 20:33

Just use one NoesisView and multiple UserControls. Each UserControl can also have its own DataContext. For instance you could have one UserControl called '(Main)Menu', which contains another two UserControls 'MenuLeft' and 'MenuRight'. It's probably not the way I would structure/build it but in the end it really depends on your exact scenario.
 
User avatar
hcpizzi
Site Admin
Posts: 213
Joined: 09 Feb 2012, 12:40

Re: UE4 Multiple NoesisViews

11 Jan 2018, 23:37

Hi Jake,

Going with your initial approach (multiple NoesisViews), maybe the problem is that the first one still has the input when then second one is created. I'm guessing you're adding it to the viewport, since it's being displayed, but are you calling SetInputModeUIOnly passing the new NoesisView as the widget to focus?

As per other ways to get this done, as Scherub mentions, you could have custom UserControl classes. We have a sample (Menu3D) that does that, and I have a version working in Unreal, but we were in the process of making some changes to it, so it's not on GitHub yet. It requires some C++ for the UserControl code-behinds, but it's minimal, and you could set the data contexts there. You can take a look at the Unity version, as well as the Blend project here: https://github.com/Noesis/Tutorials/tre ... nu3D/Unity. The code behind is a bit different in Unreal (you need to reference a NoesisXaml object), but the idea is the same.

As per setting different data contexts for different elements in the tree, that's definitely supported by Noesis. It should be pretty straightforward to expose it at the NoesisView level for named elements, something like SetDataContext(FName ElementName, UObject* DataContext);
 
antsonthetree
Topic Author
Posts: 44
Joined: 09 Jan 2018, 15:56

Re: UE4 Multiple NoesisViews

12 Jan 2018, 02:26

Going with your initial approach (multiple NoesisViews), maybe the problem is that the first one still has the input when then second one is created. I'm guessing you're adding it to the viewport, since it's being displayed, but are you calling SetInputModeUIOnly passing the new NoesisView as the widget to focus?
Yep I am calling the SetInputMode on the new NoesisView. The new one (the topmost) is actually receiving the mouse clicks just fine. It's the one behind it that is no longer receiving input. Normally in UMG you would just set topmost to SelfHitTestInvisible and then the empty areas will pass clicks to whatever is under it. This does not seem to happen with a NoesisView though. I think it may be because the NoesisView seems to force it's xaml content to fill the screen, and in my case that will cause a mostly invisible <Grid> to fill the screen. I've also tried forcing the topmost NoesisView to be a different size via SetPositionInViewport, SetDesiredSizeInViewport, etc, but those functions don't seem to affect the size of the xaml control. It is always stretched to full screen.

I would be very interested in seeing how you do code behinds in C++ in UE4. That will probably be a better path for me. I hope you will be able to update that Menu3D sample for UE4 soon!

Thanks
Jake
 
User avatar
hcpizzi
Site Admin
Posts: 213
Joined: 09 Feb 2012, 12:40

Re: UE4 Multiple NoesisViews

13 Jan 2018, 02:26

There's still some work to do on that, but I can paste here the code-behind for one of the for MainMenu.xaml in that sample:
class MainMenu : public Noesis::UserControl
{
public:

	MainMenu()
	{
		Initialized() += Noesis::MakeDelegate(this, &MainMenu::OnInitialized);
		InitializeComponent();
	}

	virtual ~MainMenu() {}

	void FadeIn()
	{
		if (FadeInStoryboard)
		{
			FadeInStoryboard->Begin();
		}
	}

	void FadeOut()
	{
		if (FadeOutStoryboard)
		{
			FadeOutStoryboard->Begin();
		}
	}

private:
	void InitializeComponent()
	{
		UNoesisXaml* Xaml = LoadObject<UNoesisXaml>(nullptr, TEXT("/Game/Assets/NoesisGUI/Samples/Menu/MainMenu"));
		Xaml->LoadComponent(this);
	}

	void OnInitialized(Noesis::BaseComponent* Sender, const Noesis::EventArgs& Args)
	{
		Noesis::Ptr<Noesis::ResourceKeyString> FadeInKey = Noesis::ResourceKeyString::Create("FadeIn");
		FadeInStoryboard.Reset(FindResource<Noesis::Storyboard>(FadeInKey.GetPtr()));
		Noesis::Ptr<Noesis::ResourceKeyString> FadeOutKey = Noesis::ResourceKeyString::Create("FadeOut"); 
		FadeOutStoryboard.Reset(FindResource<Noesis::Storyboard>(FadeOutKey.GetPtr()));

		if (FadeInStoryboard)
		{
			FadeInStoryboard->Completed() += MakeDelegate(this, &MainMenu::OnFadeInCompleted);
		}

		Start.Reset(FindName<Noesis::ToggleButton>("Start"));
		Settings.Reset(FindName<Noesis::ToggleButton>("Settings"));
		Exit.Reset(FindName<Noesis::ToggleButton>("Exit"));

		PreviewKeyDown() += MakeDelegate(this, &MainMenu::ProcessKeyDown);
	}

	void OnFadeInCompleted(Noesis::BaseComponent* Sender, const Noesis::TimelineEventArgs& Args)
	{
		if (Start)
		{
			Start->Focus();
		}
	}

	void ProcessKeyDown(Noesis::BaseComponent* Sender, const Noesis::KeyEventArgs& Args)
	{
		if (Args.key == Noesis::Key_Return)
		{
			if (Start->GetIsKeyboardFocused())
			{
				Start->GetCommand()->Execute(nullptr);
			}
			else if (Settings->GetIsKeyboardFocused())
			{
				Settings->GetCommand()->Execute(nullptr);
			}
			else if (Exit->GetIsKeyboardFocused())
			{
				Exit->GetCommand()->Execute(nullptr);
			}
		}
		else if (Args.key == Noesis::Key_Escape)
		{
			Exit->GetCommand()->Execute(nullptr);
		}
	}

	Noesis::Ptr<Noesis::Storyboard> FadeInStoryboard;
	Noesis::Ptr<Noesis::Storyboard> FadeOutStoryboard;

	Noesis::Ptr<Noesis::ToggleButton> Start;
	Noesis::Ptr<Noesis::ToggleButton> Settings;
	Noesis::Ptr<Noesis::ToggleButton> Exit;

	NS_IMPLEMENT_INLINE_REFLECTION(MainMenu, Noesis::UserControl)
	{
		NsMeta<Noesis::TypeId>("Menu3D.MainMenu");
	}
};
The bit that's different is in InitializeComponent, where it does the LoadObject to load the imported NoesisXaml asset, and then uses NoesisXaml::LoadComponent to initialize the user control. You could also set the DataContext there as well.

Who is online

Users browsing this forum: No registered users and 4 guests