Modular Menu System Support Thread

Hmm, I just double-checked it here with two different projects, it works fine in both cases.

Two questions come to mind:
*) Have you tried it with the new UE4.12?
*) Have you tried it with a completly fresh project?

Sorry for all the large images, it seems the forum doesn’t support resizing or spoiler button tags.

I’m still having no luck with UE4.12 or a fresh project. This is what I’m doing, perhaps I’m doing something wrong.

  1. New project - C++ - Third Person
  2. Open "ProjectName.Build.cs - add “RHI” to dependencies.

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class MyProject2 : ModuleRules
{
	public MyProject2(TargetInfo Target)
	{
		PublicDependencyModuleNames.AddRange(new string] { "Core", "CoreUObject", "Engine", "InputCore", "RHI" });
	}
}


  1. Build Project

Now these are the 2 different routes I have tried for the BP Function library, both in fresh new projects.

  1. Right click PROJECTNAME folder in Visual Studio - Add - Class - C++ Class.


2. Add code to Header.


#pragma once

#include "Kismet/BlueprintFunctionLibrary.h"
#include "UBpVideoSettingsLib.generated.h"

#define MIN_SCREEN_WIDTH 1024
#define MIN_SCREEN_HEIGHT 768


/**
* Custom Blueprint Function Library.
*/
UCLASS()
class MYPROJECT_API UBpVideoSettingsLib : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

public:
	// Get a list of screen resolutions supported on this machine
	UFUNCTION(BlueprintPure, Category = "Video Settings")
		static bool GetSupportedScreenResolutions(TArray<FString>& Resolutions);

	// Get currently set screen resolution
	UFUNCTION(BlueprintPure, Category = "Video Settings")
		static FString GetScreenResolution();

	// Check whether or not we are currently running in fullscreen mode
	UFUNCTION(BlueprintPure, Category = "Video Settings")
		static bool IsInFullscreen();

	// Set the desired screen resolution (does not change it yet)
	UFUNCTION(BlueprintCallable, Category = "Video Settings")
		static bool SetScreenResolution(const int32 Width, const int32 Height, const bool Fullscreen);

	// Change the current screen resolution
	UFUNCTION(BlueprintCallable, Category = "Video Settings")
		static bool ChangeScreenResolution(const int32 Width, const int32 Height, const bool Fullscreen);

	// Get the current video quality settings
	UFUNCTION(BlueprintCallable, Category = "Video Settings")
		static bool GetVideoQualitySettings(int32& AntiAliasing, int32& Effects, int32& PostProcess, int32& Resolution, int32& Shadow, int32& Texture, int32& ViewDistance);

	// Set the quality settings (not applied nor saved yet)
	UFUNCTION(BlueprintCallable, Category = "Video Settings")
		static bool SetVideoQualitySettings(const int32 AntiAliasing = 3, const int32 Effects = 3, const int32 PostProcess = 3,
			const int32 Resolution = 100, const int32 Shadow = 3, const int32 Texture = 3, const int32 ViewDistance = 3);

	// Check whether or not we have vertical sync enabled
	UFUNCTION(BlueprintPure, Category = "Video Settings")
		static bool IsVSyncEnabled();

	// Set the vertical sync flag
	UFUNCTION(BlueprintCallable, Category = "Video Settings")
		static bool SetVSyncEnabled(const bool VSync);

	// Confirm and save current video mode (resolution and fullscreen/windowed) as well as quality settings
	UFUNCTION(BlueprintCallable, Category = "Video Settings")
		static bool SaveVideoModeAndQuality();

	// Revert to original video settings
	UFUNCTION(BlueprintCallable, Category = "Video Settings")
		static bool RevertVideoMode();

private:
	// Try to get the GameUserSettings object from the engine
	static UGameUserSettings* GetGameUserSettings();
};

  1. Add code to CPP


#include"MyProject2.h"
#include "UBpVideoSettingsLib.h"


// Get a list of screen resolutions supported by video adapter
// NOTE: This function needs "RHI" to be added to <Project>.Build.cs file!
bool UBpVideoSettingsLib::GetSupportedScreenResolutions(TArray<FString>& Resolutions)
{
	FScreenResolutionArray ResolutionsArray;

	if (RHIGetAvailableResolutions(ResolutionsArray, true))  // needs the "RHI" dependency
	{
		for (const FScreenResolutionRHI& Resolution : ResolutionsArray)
		{
			if (Resolution.Width < MIN_SCREEN_WIDTH || Resolution.Height < MIN_SCREEN_HEIGHT)
			{
				continue;
			}

			FString Str = FString::FromInt(Resolution.Width) + "x" + FString::FromInt(Resolution.Height);
			Resolutions.AddUnique(Str);
		}

		return true;
	}

	return false;  // failed to obtain screen resolutions
}


// Get currently set screen resolution
FString UBpVideoSettingsLib::GetScreenResolution()
{
	UGameUserSettings* Settings = GetGameUserSettings();
	if (!Settings)
	{
		return FString("");
	}

	FIntPoint Resolution = Settings->GetScreenResolution();
	return FString::FromInt(Resolution.X) + "x" + FString::FromInt(Resolution.Y);
}


// Check whether or not we are currently running in fullscreen mode
bool UBpVideoSettingsLib::IsInFullscreen()
{
	UGameUserSettings* Settings = GetGameUserSettings();
	if (!Settings)
	{
		return false;
	}

	return Settings->GetFullscreenMode() == EWindowMode::Fullscreen;
}


// Set the desired screen resolution (does not change it yet)
bool UBpVideoSettingsLib::SetScreenResolution(const int32 Width, const int32 Height, const bool Fullscreen)
{
	UGameUserSettings* Settings = GetGameUserSettings();
	if (!Settings)
	{
		return false;
	}

	Settings->SetScreenResolution(FIntPoint(Width, Height));
	Settings->SetFullscreenMode(Fullscreen ? EWindowMode::Fullscreen : EWindowMode::Windowed);
	return true;
}


// Change the current screen resolution
bool UBpVideoSettingsLib::ChangeScreenResolution(const int32 Width, const int32 Height, const bool Fullscreen)
{
	UGameUserSettings* Settings = GetGameUserSettings();
	if (!Settings)
	{
		return false;
	}

	EWindowMode::Type WindowMode = Fullscreen ? EWindowMode::Fullscreen : EWindowMode::Windowed;
	Settings->RequestResolutionChange(Width, Height, WindowMode, false);
	return true;
}


// Get the current video quality settings
bool UBpVideoSettingsLib::GetVideoQualitySettings(int32& AntiAliasing, int32& Effects, int32& PostProcess,
	int32& Resolution, int32& Shadow, int32& Texture, int32& ViewDistance)
{
	UGameUserSettings* Settings = GetGameUserSettings();
	if (!Settings)
	{
		return false;
	}

	AntiAliasing = Settings->ScalabilityQuality.AntiAliasingQuality;
	Effects = Settings->ScalabilityQuality.EffectsQuality;
	PostProcess = Settings->ScalabilityQuality.PostProcessQuality;
	Resolution = Settings->ScalabilityQuality.ResolutionQuality;
	Shadow = Settings->ScalabilityQuality.ShadowQuality;
	Texture = Settings->ScalabilityQuality.TextureQuality;
	ViewDistance = Settings->ScalabilityQuality.ViewDistanceQuality;
	return true;
}


// Set the quality settings (not applied nor saved yet)
bool UBpVideoSettingsLib::SetVideoQualitySettings(const int32 AntiAliasing, const int32 Effects, const int32 PostProcess,
	const int32 Resolution, const int32 Shadow, const int32 Texture, const int32 ViewDistance)
{
	UGameUserSettings* Settings = GetGameUserSettings();
	if (!Settings)
	{
		return false;
	}

	Settings->ScalabilityQuality.AntiAliasingQuality = AntiAliasing;
	Settings->ScalabilityQuality.EffectsQuality = Effects;
	Settings->ScalabilityQuality.PostProcessQuality = PostProcess;
	Settings->ScalabilityQuality.ResolutionQuality = Resolution;
	Settings->ScalabilityQuality.ShadowQuality = Shadow;
	Settings->ScalabilityQuality.TextureQuality = Texture;
	Settings->ScalabilityQuality.ViewDistanceQuality = ViewDistance;
	return true;
}


// Check whether or not we have vertical sync enabled
bool UBpVideoSettingsLib::IsVSyncEnabled()
{
	UGameUserSettings* Settings = GetGameUserSettings();
	if (!Settings)
	{
		return false;
	}

	return Settings->IsVSyncEnabled();
}


// Set the vertical sync flag
bool UBpVideoSettingsLib::SetVSyncEnabled(const bool VSync)
{
	UGameUserSettings* Settings = GetGameUserSettings();
	if (!Settings)
	{
		return false;
	}

	Settings->SetVSyncEnabled(VSync);
	return true;
}


// Confirm and save current video mode (resolution and fullscreen/windowed)
bool UBpVideoSettingsLib::SaveVideoModeAndQuality()
{
	UGameUserSettings* Settings = GetGameUserSettings();
	if (!Settings)
	{
		return false;
	}

	Settings->ConfirmVideoMode();
	Settings->ApplyNonResolutionSettings();
	Settings->SaveSettings();
	return true;
}


// Revert to original video settings
bool UBpVideoSettingsLib::RevertVideoMode()
{
	UGameUserSettings* Settings = GetGameUserSettings();
	if (!Settings)
	{
		return false;
	}

	Settings->RevertVideoMode();
	return true;
}


//---- PRIVATE METHODS -------------------------------------------------------------------------------

// Try to get the GameUserSettings object from the engine
UGameUserSettings* UBpVideoSettingsLib::GetGameUserSettings()
{
	if (GEngine != nullptr)
	{
		return GEngine->GameUserSettings;
	}

	return nullptr;
}



  1. Build Solution. No errors.
  2. Compile in editor. Compile Complete with no errors.
  3. Can’t call new functions in a blueprint within the editor.
  4. Relaunch editor - Still not able to call functions.

Second way of creating the BP function library.

  1. In the editor - File - Add C++ Class - BluePrintFunctionLibrary


2. Add code to Header.
3. Add code to CPP.
4 Build solution. - Compile errors.


That’s as far as I’ve got, I must be doing something wrong but I’ve no idea what it is. Hopefully this long list will help identify exactly what it is.

Hmm, that is weird. So far I was not able to reproduce your problem, even with a fresh project.
I will give it a bit more time this weekend and get back to you then!

Thank you for taking the time! I wonder if my install of Visual Studio is missing something? I have the C++ language and common tools installed but I might try a fresh install of it and see how that goes.

Now this is odd, I’ve managed to get it working. Here’s what I did.

  1. Started a new Blue Print Only project rather than a C++ one.
  2. File - New C++ Class.
  3. Add “RHI” to build.cs.
  4. Add code to to Header.
  5. Add code to CPP.
  6. Build project.

Now all of the new blueprint library functions show up in blueprint. Very odd that it doesn’t work for me in a fresh C++ project but does work in a blueprint project with C++ added to it.

Very odd indeed. But I am glad it’s working for you now :slight_smile:

Ok, I was curious to try it with a C++ project as well, as I only tried it with a BP project, to which I added a C++ class later on. But also in the fresh C++ project everything works fine, including the BP library functions showing up in the context menu of the level BP.

So, the C++ from our web site is working fine. I can think of two potential issues on your end:

*) You have not replaced the API in the new class header, e.g. in “class CPPTEST_API UBpVideoSettingsLib : public UBlueprintFunctionLibrary”
*) You have added a “U” prefix to the class name, so that in the auto-generated code it becomes “UUBpVideoSettingsLib” instead of “UBpVideoSettingsLib”

Does that help?

Can I make it not scale. I hate how unreal scales everything when the window is resized, can this get around that?

Scaling is set via “DPI Scaling” in project settings:

This is the same with the Modular Menu System.
Hope that helps!

I have purchased the MMS system, and, its really nice. Saves me a ton of time.

I am having an issue tho, I am trying to implement a steam server list onto a scroll that will find all games of the current ID (in this example, all games hosting “Spacewar”)
I am pretty stuck. I think the code im using (blueprint steam code) is just not working for this system. I want to continue to use it, of course, but, i cant get the steam server list to work properly.

Im ready to even rebuild using YOUR system, but, i dont know where to start to add the “Find Session” / “Join Session” nodes.

work flow:

Main Menu w/ a “Join” button > click button > open server list widget > “find session” display with scroll bar that will size depending on the number of servers > click the server of choice > click “join” (or double click) > load screen > play with friends

I am reaching out in hopes that you can atleast get me started on the server widget, or, better yet, the additional things i need to add to this … Thanks for your time.

I’m having an issue where various Blueprint assets that are in any way connected with MMS are getting locked… It’s very odd and this bug has thus far nuked several Blueprints in the process. I’ve narrowed it down to MMS, but can’t figure out why it’s happening. The error window that pops up following the one in the shot below says I’m in Standalone Play mode, which is a bold-faced lie, haha. I even ran default Windows and other process managers to confirm I wasn’t crazy. So as soon as I do a basic MMS set up in a clean project, and call various functions from one Blueprint to another that has MMS related bits and bobs, that starts happening.

Also, I still want to suggest you do something more elaborate and friendly for handling button clicks. It’s way more work than it needs to be to set up a proper button handling routine. I just want to have a controller Blueprint for my GUI that has functions in it for handling button activity for each of my menus. Having to jump into the Event Handler and build a spaghetti monster to handle all the buttons is just plain wrong. Anyways, below is a quick screenshot of the error message that pops up. Oh, also- I just noticed MMS created a Changelog.txt file inside my project, without warning. Why?

Ok then, first things first. You write that it seems that your BP Steam code is maybe not working properly.
Can you first verify that you are acutally receiving the list of servers from Steam? e.g. print them out or so.

If that is working, then I would suggest to build a small prototype menu with MMS in order to get things on track. Add a TextScrollbox and to it the list of Steam games (i.e. their names or IDs or whatever you like) as options. If that is working you can for example add a button which reads the selected option from TextScrollbox, so that you can process that further…

Does that help you with your problem?

That is really strange. I have never seen that error message myself – neither related to MMS or in any other project. Now from Googling on this issue I found that there are serveral others who have the same or a similar issue, even without MMS. So from reading those other threads and my experience with UE4 I would suggest to find out the reason for this issue by first trying to not save the BP asset, close the editor, restart it and try to save it again.

Another option would be to delete Saved and Intermediate folders before starting the edtor.

Also you could try to right-click on the main folder in your content browser and select the “Fix Up Redirectors in Folder” option.

Here are threads I found on this issue:

First of all: thanks for your feedback. We are always willing to improve on the MMS, so we appreciate your suggestions a lot. But I am not sure whether I have fully understood what you would prefer instead of the event handler. For example, if you look into the AddButton BP node of the MMS framework, on the right side you will find a section with a comment “Bind Event Handler and apply Theme”. There you can see menu button object has an event dispatcher, and the event handler object is binding to that dispatcher.

Would it help you if you receive either the menu button object itself from the AddButton function as return parameter, or the event dispatcher? That way you could bind your own events to the dispatcher. Or would you prefer another solution?

You can ignore (or delete) that file. It’s just a plain text file for information, no functionality attached to it :slight_smile:

Those solutions would be better than none, haha! Would be great actually.

As for my other issue, with not being able to save… I’ve narrowed it down, to only happening when I add an event dispatcher in my child MMS event handler BP. I’m calling that (I copied the signature from ButtonCallback) on the function override ButtonCallback event. As soon as I wipe out that event dispatcher, compile and save, I can save normally in my other blueprint. Very strange indeed!

[edit]
Even further drilled down, this happens as soon as I override the ButtonCallback function in my child event handler. The event dispatcher wasn’t the culprit.
[/edit]

Fine then, we have updated the MMS so that every Add… BP node returns a reference to the newly created menu element. Using that you can easily hook your own function to the new menu element’s event dispatcher, as discussed before. I have already sent the update to Epic, will let you know when the new version has been published by them!

That is strange, as we do the same in MyEventHandler in the demo project. You can have a look there in its event graph: the EventButtonCallback function overrides the same function in the parent class MMS_EventHandler. And that can be saved fine! Do you maybe try to override the private version of the same function (but prefixed with “Private”)?

We have updated the Modular Menu System to version 1.4.
Now you can hook directly to the event dispatchers of the menu elements.

Please have a look at the official announcement in the MMS thread.

Hey, thanks a bunch haimat… It’s these little things that make Market content worth it. In the end, it saves us time and gives us more power to do greater things :slight_smile:

Awesome, glad you like it!
And thanks for the positive feedback :slight_smile:

Hello, sorry for the late reply. I am that kind of person who learns best with pictures, could you take some screenshots or make a vid on this topic with the screen resolutions. Thank you bunch!

You can see all of that in the demo application shipped with the Modular Menu System. Have a look at the MyEventHandler BP. It shows you how to populate a combo box with screen resolutions (strings), as well as how to react to events like clicks on buttons.

And of course, there is the MMS manual, which explains all these features in detail, with screenshots.