Adding my own buttons to BPW_MapMenu

I'm looking for some help from somebody who knows about UI/widget modding. I am attempting to add some buttons to the BPW_MapMenu hierarchy. Specifically, the map menu has the "Show Stamps on Map" checkbox button at the bottom and I'm trying to add some of my own buttons alongside it. I've attached an unreal editor screenshot of the hierarchy I'm talking about, with the button I'm trying to create siblings for highlighted. My approach has been to create a UVerticalBox containing my button (starting with one) and add it to the [Overlay] widget, so the vbox is itself a sibling to the mShowStampsButton. But nothing I added to the vbox shows up. I am inexperienced with UI programming, so I don't know if I'm doing something wrong or just falling into common pitfalls. Here's some code to show what I'm doing:
const auto* mapMenuClass = Cast<UWidgetBlueprintGeneratedClass>(BPW_MapMenuClass.Get());
UWidgetTree* mapMenuWidgetTree = mapMenuClass->GetWidgetTreeArchetype();
UWidget* showStampsButton = mapMenuWidgetTree->FindWidget("mShowStampsButton");
int32 showStampsButton ChildIndex;
UPanelWidget* overlayWidget = UWidgetTree::FindWidgetParent(showStampsButton, showStampsButton ChildIndex);
UVerticalBox* vbox = NewObject<UVerticalBox>(overlayWidget, UVerticalBox::StaticClass(), "VisibilityButtonsBox", RF_Transient);
vbox->Slot = overlayWidget->Slot;
UWidget* hideAllResourcesOnCompassButton = CreateResourceVisibilityButton(
vbox,
TEXT("SRMHideAllOnCompass"),
LOCTEXT("SRMHideAllOnCompass", "Hide All Resources On Compass"),
EResourceVisibilityLocation::Compass,
false,
buttonTemplateWidget);
vbox ->AddChild(hideAllResourcesOnCompassButton);
const auto* mapMenuClass = Cast<UWidgetBlueprintGeneratedClass>(BPW_MapMenuClass.Get());
UWidgetTree* mapMenuWidgetTree = mapMenuClass->GetWidgetTreeArchetype();
UWidget* showStampsButton = mapMenuWidgetTree->FindWidget("mShowStampsButton");
int32 showStampsButton ChildIndex;
UPanelWidget* overlayWidget = UWidgetTree::FindWidgetParent(showStampsButton, showStampsButton ChildIndex);
UVerticalBox* vbox = NewObject<UVerticalBox>(overlayWidget, UVerticalBox::StaticClass(), "VisibilityButtonsBox", RF_Transient);
vbox->Slot = overlayWidget->Slot;
UWidget* hideAllResourcesOnCompassButton = CreateResourceVisibilityButton(
vbox,
TEXT("SRMHideAllOnCompass"),
LOCTEXT("SRMHideAllOnCompass", "Hide All Resources On Compass"),
EResourceVisibilityLocation::Compass,
false,
buttonTemplateWidget);
vbox ->AddChild(hideAllResourcesOnCompassButton);
I looked at Cartograph's code to add these buttons next to the show/hide menu button using an HBox and that worked fine, so I know the buttons actually get created and work. It's getting them into the BPW_MapMenu hierarchy I need help with.
No description
Solution:
To recap the solution, rather than piece together widgets in C++, I made the whole widget in UE and then used Bind on BP Function: Construct to find and insert the widget at runtime, but only because widget blueprint hooks didn't work (the widget only got inserted on the first map screen open... there's a quirk there that somebody might want to sort out... I'd do it if I had more time right now). Then I had to sort out button layout and alignment, which yeshjho helped with.
Jump to solution
69 Replies
Robb
Robb2w ago
I highly recommend you do widget injection stuff like this in blueprint because the iteration time is way faster (you can even test in editor with most widgets, looks even better if you have a complete project dump) and because you won't need to juggle as many bp asset refs on the c++ side it's possible to do in C++ as I assume cartograph is doing, but I don't think it's a good idea, especially because you mentioned you're inexperienced with UI programming - making the faster iteration time all that much more valuable check out Mam Enhancer's source code for some examples of doing it in blueprint. it uses both the data-asset-hook method in the game instance module, and in blueprint event graphs for the more precise ones a useful way to test stuff like this is to make a copy of the widget you're trying to modify in the editor, then try to actually make the change yourself in the widget editor. you can very quickly find out what kind of slot alignment and padding settings you need and you can test your hooks in the editor by making an editor utility widget, adding a copy of the target widget to it, then calling your "Bind on BP Function: Construct" hook function with a reference to that widget
Epp
EppOP2w ago
I recognize some of these words! j/k That’s super helpful and I’ll play around with that when I have some time later. I started by looking for an example of how to edit the map screen and I knew Cartogtaph did it so I started there. I DO feel like I’m really close since I can manipulate the widget tree - I just don’t understand what its final state needs to be.
Rex
Rex2w ago
You really want to use the widget editor in UE to know what the final state you want is I would highly recommend widget blueprint hooks unless those won't cut it for you (in which case we might want to consider making the API more flexible?)
Robb
Robb2w ago
I dislike widget blueprint hooks because there's a ton of noise trying to follow them later (from the properties I don't care about) + they are "always on" (I can conditionally decide on hook trigger if I actually want to modify something). but they work for most purposes
yeshjho
yeshjho2w ago
You can alleviate the pain of iterating of using C++ by trying modifying the widget blueprint you're editing as Robb said. I guess you're trying to wrap the mShowStampButton with a vertical box and add your button below it? You could modify the widget blueprint and preview the result like this:
No description
yeshjho
yeshjho2w ago
It might be hard to see, but the second button got outside of screen. So in this case, you should check Size to Content checkbox of the Overlay, and it'll look like this:
No description
yeshjho
yeshjho2w ago
Apparently, Image_195's position doesn't depend on the overlay so you'll need to modify it manually in this case.
Epp
EppOP2w ago
Thank you, yeshjho! Even little pointers like "Size to Content" are super helpful for me. I had figured out how to move the image and resize the scrollbox because I wondered if the buttons needed space to be shown, but that hadn't worked so I'm sure it's a confluence of little things I'm messing up. I will play with the widget editor and see if I can work backwards from there.
yeshjho
yeshjho2w ago
Saw your code again, and tried to remember the time I was writing the UI code of Cartograph... It might not be true, but IIRC, You can't just vbox->Slot = overlayWidget->Slot, because a slot and the widget contained in the slot references each other and the parent referenced it somehow, I think. The point is, it was better to just create a new slot object. That's why I'm creating a new slot and manually setting the references with
c++
auto* HBoxPanelSlot = NewObject<UCanvasPanelSlot>(Parent, UCanvasPanelSlot::StaticClass(), NAME_None, RF_Transient);
HBoxPanelSlot->Content = HBox;
HBoxPanelSlot->Parent = Parent;
HBox->Slot = HBoxPanelSlot;
HBox->AddChild(ShowHideButton);
c++
auto* HBoxPanelSlot = NewObject<UCanvasPanelSlot>(Parent, UCanvasPanelSlot::StaticClass(), NAME_None, RF_Transient);
HBoxPanelSlot->Content = HBox;
HBoxPanelSlot->Parent = Parent;
HBox->Slot = HBoxPanelSlot;
HBox->AddChild(ShowHideButton);
and then inserting it back with
c++
TArray<UPanelSlot*>& MutablePanelSlots = UCartographPanelWidgetAccessor::GetPanelSlots(Parent);
MutablePanelSlots.Insert(HBoxPanelSlot, Index);
c++
TArray<UPanelSlot*>& MutablePanelSlots = UCartographPanelWidgetAccessor::GetPanelSlots(Parent);
MutablePanelSlots.Insert(HBoxPanelSlot, Index);
Epp
EppOP2w ago
Thanks, yeah, I'm still playing with it but part of my gap was understanding what slots were even for and was having trouble finding a complete explanation. It eventually became clear that the slots are decoupling layout options from the widget type but that the slot type is determined by the containing widget because it's the containing widget that controls what layout options are possible. I'm still not positive whether slots are 1:1 with contained widgets (I think they are) but, instead of just setting a slot or making a new one, I tried configuring the slot returned by AddChild (or, for an Hbox, you can skip a cast with AddChildToHorizontalBox) and that seems to be working better - I can see the one button I'm adding now, though I have yet to sort out its full styling. So I think AddChild creates the slot for you, which I think makes some sense, as the containing widget needs a slot per widget and is the one that knows what slot type to use.
Epp
EppOP2w ago
Aha! Getting closer:
No description
yeshjho
yeshjho2w ago
Good that you figured out, yeah using the slot returned by AddChild would be a better solution. You're right slots are 1:1 with the contained widgets. Widgets that can have multiple children widgets such as HBox, VBox, and Overlay have slots for their children, and a slot contains one child widget. You can see the slot-related data appearing at the top for the child widgets in the editor
No description
Epp
EppOP2w ago
In this screenshot, you can see that the buttons and labels are too tall and overlapping. The layout there is a vbox of hboxes and when I try wrapping the hboxes in sizeboxes and setting the height override, it works in the editor but not in-game. I was able to set the padding and text alignment on the "Resources on *" TextBlocks, but the sizeboxes don't seem to affect what I see there in-game. Here's what I configured in the editor just to prototype what I was trying to do:
No description
Epp
EppOP2w ago
It looks like this:
Epp
EppOP2w ago
No description
Epp
EppOP2w ago
With all sizeboxes configured like so (though I've tried different alignments and Auto/Fill in both the editor and in-game - nothing seems to change behavior in this case)
No description
Epp
EppOP2w ago
For the actual code that's running in-game, here's how I'm creating the vbox:
UVerticalBox* vbox = NewObject<UVerticalBox>(overlayWidget, UVerticalBox::StaticClass(), "BelowScrollBoxVerticalBox", RF_Transient);
auto vboxOverlaySlot = Cast<UOverlaySlot>(overlayWidget->AddChild(vbox));
UVerticalBox* vbox = NewObject<UVerticalBox>(overlayWidget, UVerticalBox::StaticClass(), "BelowScrollBoxVerticalBox", RF_Transient);
auto vboxOverlaySlot = Cast<UOverlaySlot>(overlayWidget->AddChild(vbox));
And the first hbox row:
USizeBox* compassHBoxSizeBox = NewObject<USizeBox>(vbox, UHorizontalBox::StaticClass(), "CompassHBoxSizeBox", RF_Transient);
vbox->AddChildToVerticalBox(compassHBoxSizeBox);
compassHBoxSizeBox->SetHeightOverride(32.0);

UHorizontalBox* compassHBox = NewObject<UHorizontalBox>(compassHBoxSizeBox, UHorizontalBox::StaticClass(), "ShowHideOnCompassHBox", RF_Transient);
compassHBoxSizeBox->AddChild(compassHBox);

UTextBlock* showHideOnCompassTextBlock = NewObject<UTextBlock>(compassHBox, UTextBlock::StaticClass(), "ShowHideOnCompassMessage", RF_Transient);
showHideOnCompassTextBlock->Text = LOCTEXT("SRMResourcesOnCompass", "Resources on Compass:");
showHideOnCompassTextBlock->SetFont(showStampsTextBlock->GetFont());
auto showHideOnCompassMessageHBoxSlot = compassHBox->AddChildToHorizontalBox(showHideOnCompassTextBlock);
showHideOnCompassMessageHBoxSlot->SetPadding({ 5.0, 0.0 });
showHideOnCompassMessageHBoxSlot->SetVerticalAlignment(EVerticalAlignment::VAlign_Center);

UWidget* hideAllResourcesOnCompassButton = CreateResourceVisibilityButton(
compassHBox,
TEXT("SRMHideAllOnCompass"),
LOCTEXT("SRMHideAllOnCompass", "Hide All"),
EResourceVisibilityLocation::Compass,
false,
buttonTemplateWidget);
auto hideAllCompassHBoxSlot = compassHBox->AddChildToHorizontalBox(hideAllResourcesOnCompassButton);

UWidget* showAllResourcesOnCompassButton = CreateResourceVisibilityButton(
compassHBox,
TEXT("SRMShowAllOnCompass"),
LOCTEXT("SRMShowAllOnCompass", "Show All"),
EResourceVisibilityLocation::Compass,
true,
buttonTemplateWidget);
auto showAllCompassHBoxSlot = compassHBox->AddChildToHorizontalBox(showAllResourcesOnCompassButton);
USizeBox* compassHBoxSizeBox = NewObject<USizeBox>(vbox, UHorizontalBox::StaticClass(), "CompassHBoxSizeBox", RF_Transient);
vbox->AddChildToVerticalBox(compassHBoxSizeBox);
compassHBoxSizeBox->SetHeightOverride(32.0);

UHorizontalBox* compassHBox = NewObject<UHorizontalBox>(compassHBoxSizeBox, UHorizontalBox::StaticClass(), "ShowHideOnCompassHBox", RF_Transient);
compassHBoxSizeBox->AddChild(compassHBox);

UTextBlock* showHideOnCompassTextBlock = NewObject<UTextBlock>(compassHBox, UTextBlock::StaticClass(), "ShowHideOnCompassMessage", RF_Transient);
showHideOnCompassTextBlock->Text = LOCTEXT("SRMResourcesOnCompass", "Resources on Compass:");
showHideOnCompassTextBlock->SetFont(showStampsTextBlock->GetFont());
auto showHideOnCompassMessageHBoxSlot = compassHBox->AddChildToHorizontalBox(showHideOnCompassTextBlock);
showHideOnCompassMessageHBoxSlot->SetPadding({ 5.0, 0.0 });
showHideOnCompassMessageHBoxSlot->SetVerticalAlignment(EVerticalAlignment::VAlign_Center);

UWidget* hideAllResourcesOnCompassButton = CreateResourceVisibilityButton(
compassHBox,
TEXT("SRMHideAllOnCompass"),
LOCTEXT("SRMHideAllOnCompass", "Hide All"),
EResourceVisibilityLocation::Compass,
false,
buttonTemplateWidget);
auto hideAllCompassHBoxSlot = compassHBox->AddChildToHorizontalBox(hideAllResourcesOnCompassButton);

UWidget* showAllResourcesOnCompassButton = CreateResourceVisibilityButton(
compassHBox,
TEXT("SRMShowAllOnCompass"),
LOCTEXT("SRMShowAllOnCompass", "Show All"),
EResourceVisibilityLocation::Compass,
true,
buttonTemplateWidget);
auto showAllCompassHBoxSlot = compassHBox->AddChildToHorizontalBox(showAllResourcesOnCompassButton);
BTW, I'm not intentionally ignoring the advice to do this in blueprint. It's just that when I realized how close I was and how I should be using slots, I realized it would likely be more work to completely reset. The only serious hiccup I've hit since then is why SetHeightOverride (called at line 3 of the first hbox row C++) doesn't seem to do anything for me in C++. I tried setting it as low as 5.0 and it didn't seem to make a difference. In case it matters, buttonTemplateWidget is currently nullptr (I was using a template before but it doesn't seem to be necessary to get the default styling I want). And CreateResourceVisibilityButton is pretty straightforward:
UWidget* USRMRootInstanceModule::CreateResourceVisibilityButton(
UObject* outer,
FName name,
FText label,
EResourceVisibilityLocation visibilityLocation,
bool visible,
UWidget* templateWidget)
{
auto buttonClass = SRMResourceVisibilityButtonClass.Get();

UWidget* button = NewObject<UWidget>(outer, buttonClass, name, RF_Transient, templateWidget);

FProperty* mTextProperty = buttonClass->FindPropertyByName("mText");
checkf(mTextProperty, TEXT("Did not find mText property"));
FText* mTextPtr = mTextProperty->ContainerPtrToValuePtr<FText>(button);
*mTextPtr = label;

FProperty* mVisibilityLocationProperty = buttonClass->FindPropertyByName("mVisibilityLocation");
checkf(mVisibilityLocationProperty, TEXT("Did not find mVisibilityLocation property"));
EResourceVisibilityLocation* mVisibilityLocationPtr = mVisibilityLocationProperty->ContainerPtrToValuePtr<EResourceVisibilityLocation>(button);
*mVisibilityLocationPtr = visibilityLocation;

FBoolProperty* mVisibilityToSetProperty = CastField<FBoolProperty>(buttonClass->FindPropertyByName("mVisibilityToSet"));
checkf(mVisibilityToSetProperty, TEXT("Did not find mVisibilityToSet property"));
void* mVisibilityToSetPtr = mVisibilityToSetProperty->ContainerPtrToValuePtr<void>(button);
mVisibilityToSetProperty->SetPropertyValue(mVisibilityToSetPtr, visible);

return button;
}
UWidget* USRMRootInstanceModule::CreateResourceVisibilityButton(
UObject* outer,
FName name,
FText label,
EResourceVisibilityLocation visibilityLocation,
bool visible,
UWidget* templateWidget)
{
auto buttonClass = SRMResourceVisibilityButtonClass.Get();

UWidget* button = NewObject<UWidget>(outer, buttonClass, name, RF_Transient, templateWidget);

FProperty* mTextProperty = buttonClass->FindPropertyByName("mText");
checkf(mTextProperty, TEXT("Did not find mText property"));
FText* mTextPtr = mTextProperty->ContainerPtrToValuePtr<FText>(button);
*mTextPtr = label;

FProperty* mVisibilityLocationProperty = buttonClass->FindPropertyByName("mVisibilityLocation");
checkf(mVisibilityLocationProperty, TEXT("Did not find mVisibilityLocation property"));
EResourceVisibilityLocation* mVisibilityLocationPtr = mVisibilityLocationProperty->ContainerPtrToValuePtr<EResourceVisibilityLocation>(button);
*mVisibilityLocationPtr = visibilityLocation;

FBoolProperty* mVisibilityToSetProperty = CastField<FBoolProperty>(buttonClass->FindPropertyByName("mVisibilityToSet"));
checkf(mVisibilityToSetProperty, TEXT("Did not find mVisibilityToSet property"));
void* mVisibilityToSetPtr = mVisibilityToSetProperty->ContainerPtrToValuePtr<void>(button);
mVisibilityToSetProperty->SetPropertyValue(mVisibilityToSetPtr, visible);

return button;
}
Where SRMResourceVisibilityButtonClass is just my own blueprint class that extends Widget_StandardButton per what Cartograph does to make its Show/Hide Cartograph Menu button.
Robb
Robb2w ago
you may still want to try and do it in blueprint to compare anyway as a learning experience, to see how the two approaches compare in length, ease of following the logic, and documentation obscurity
Epp
EppOP2w ago
I know I dumped several walls of text there but buried in it was a question - does anybody know how to use sizebox to limit the height of a vbox row in C++? My approach in C++ above calling SetHeightOverride doesn't seem to be having any effect, even though I used what I thought was the same approach in a blueprint prototype and it DID work.
Robb
Robb2w ago
Other things in the layout can sometimes cause a size box height override to be ignored. That's just an observation I've made. I don't have anything more specific, sorry Try changing its alignment within the slot
Epp
EppOP2w ago
That's still helpful to know. I noticed that there was no vbox there at all before and my next experiment is to remove it and just put the widgets directly and see what happens.
Robb
Robb2w ago
Try to make as much of the the widget you're adding in blueprint as possible so you only have one element to add and one set of slots properties to worry about changing
Epp
EppOP2w ago
Good call, that also makes sense
Robb
Robb2w ago
Especially because UIs can change across updates Although that's less of a concern now that we're in full release land
yeshjho
yeshjho2w ago
Ooh seeing that you're putting your buttons above the vanilla one, not below it, it would have been much much simpler to do it with blueprint hooking, adding a widget under the overlay and manually adjusting the position. That's how I've added Cartograph's "Cartograph: Initializing..." text at the top right corner. I didn't use C++ for that. The only reason I've done that way to add the Show/Hide Cartograph menu button was that I needed that horizontal box because the width of the vanilla button changes depending on its state (the widths of "Show" and "Hide" are different). But I don't think that's the case for you, so manually adding would have alleviated the headache a lot 😅 Anyway, about the size box, the size box doesn't actually "sizes" its contents. It just changes the size it reports to its parent. If you want its child to automatically scale depending on the size(height) of the size box, you should use scale box.
yeshjho
yeshjho2w ago
No description
No description
No description
yeshjho
yeshjho2w ago
without scalebox:
No description
Epp
EppOP2w ago
So I wrapped all the UI I want to add into a single widget whose tree looks like this:
No description
Epp
EppOP2w ago
Then I tried adding it to BPW_MapMenu using a widget blueprint hook configured like so:
No description
Epp
EppOP2w ago
And that appears to (mostly) work until the SECOND time I open the map screen - then the buttons are just gone. Is there something I'm doing wrong that they aren't being added every time?
Epp
EppOP2w ago
Also, this is just a general layout question, but I can't seem to get the buttons truly centered in their hbox slot. They look like this:
No description
Epp
EppOP2w ago
Even though all of their slots are configured like this:
No description
Epp
EppOP2w ago
Now, the buttons themselves are custom buttons I made that extend Widget_StandardButton so could it be that the standard button is simply inherently not centered? And what can I do to center it?
Robb
Robb2w ago
The data hooks shoooould mean that they get added every time. But it really sounds like the hook just isn't triggering again. That's weird. My next step would be trying to do it with Bind on BP Function: Construct instead, since that can tell me if the function is actually getting called or not, and give me some kind of error reporting Do you see anything in the logs? There is a decent chance it is standard button's fault. Try with stock ue buttons and see if they have the same problem. If it is standard button's fault, you can use code in your own widget subclass to change the button's layout to do what you need, but it will be some trial and error What functionality did you need that required subclassing standard button?
Epp
EppOP2w ago
From LogSatisfactoryModLoader? Not that I can tell Just following what I saw done in Cartograph, but it also has appropriately-themed styling/hover behavior/slick button sounds built in Are widget blueprint hooks supposed to log their behavior? Do I need to change a log level to see them?
Robb
Robb2w ago
Possibly try with plain ol standard button too then in case the subclassing breaks something
yeshjho
yeshjho2w ago
Ah, I've encountered it before. For me, I was adding a widget to mMapObjectPanel in Widget_Map, but the widget disappeared the second time I open the map. My guess was the game was detaching all the children and recreating the children every time(or the first time) I open the map, so I attached my widget to a different widget, in this case mMapScrollContainer, and it didn't get disappear anymore. Try different parent widget.
Epp
EppOP2w ago
Good to know, thanks. Unfortunately, there was only one parent widget available in BPW_MapMenu in the hook dropdown, but I will look into Bind on BP Function Construct as well as finding a different place for them.
yeshjho
yeshjho2w ago
You could choose any widget if you change the Parent Widget Typ to Direct(Any), but I guess it doesn't make sense to attach your widget to anywhere else since otherwise it'll hide other widgets... So yeah, going with Construct would be your best bet, I think. How are you initializing the buttons? i.e., how are you setting the texts? Horizontal alignment being centered there doesn't mean the children of the widget the slot contains are also centered horizontally. It simply means the button's position inside the hbox is aligned at center.
Epp
EppOP2w ago
With this approach, I’m just setting the mText property in the editor UI.
yeshjho
yeshjho2w ago
You should use the SetText function of the Widget_StandardButton, since it'll deal with the visibility of the mLeftSlot and the IconContainer. Otherwise they'll remain visible even though they contain nothing, pushing the text to the right.
yeshjho
yeshjho2w ago
No description
yeshjho
yeshjho2w ago
This one
Epp
EppOP2w ago
Hmm, I thought that was going to work but no change. I even tried creating my own text property and passing it to SetText in the Construct event but it's not fixing the alignment at all.
yeshjho
yeshjho2w ago
Huh, I might try subsequently calling SetTextStyle and SetButtonAlignment(true) too, then (or try calling one only). If it's still not centered after calling those 2 functions, I have no idea.
Epp
EppOP2w ago
Unfortunately, neither of those solved the button alignment, so I still need to figure that out. But I got the buttons added to the map menu regularly using Bind on BP Function: Construct... combined with a LOT more glue work than normal widget blueprint hooks. I was able to sort of solve the button issues by wrapping them all in individual scale boxes. That centered them but also shrunk them a bit more than I'd like. Shouldn't there be some way to center the button but also hide/clip off the parts that would extend outside of the hbox cell? Ah, yes, there it is and it was simpler than I realized. Just set the alignments to Center (NOT Fill) and Clipping to Clip to Bounds.
yeshjho
yeshjho2w ago
I just tested with a fresh subclass, simple SetText call should work, so I'm not sure what's going on there
No description
yeshjho
yeshjho2w ago
But I guess that's all problem solved, right?
Epp
EppOP2w ago
When did you call SetText?
yeshjho
yeshjho2w ago
In Construct
yeshjho
yeshjho2w ago
No description
Epp
EppOP2w ago
Curious - do you also have that in an hbox slot?
yeshjho
yeshjho2w ago
Yeah that's the only difference I noticed so I just tested it and it seems like it's fine
No description
yeshjho
yeshjho2w ago
Is your HBox's Size To Content turned off? That's the only way I can think of
Epp
EppOP2w ago
I don't even see a Size to Content option on my HBoxes. But, here, let me describe what I did to get it to work. Here's the final result:
No description
Epp
EppOP2w ago
And here's the full widget tree:
No description
Epp
EppOP2w ago
The size boxes are set like so (with a height override of 36)
No description
Epp
EppOP2w ago
Text:
No description
Epp
EppOP2w ago
Scale boxes:
No description
Epp
EppOP2w ago
And buttons:
No description
Epp
EppOP2w ago
I had to "Clip to Bounds" on BOTH the scale boxes AND the buttons to get it to look right. I don't really know why; I tried without the scale boxes and it reverted to funky alignment.
yeshjho
yeshjho2w ago
Ah, I see what's going on now. First of all, since it works, don't touch anything 😉 If you want to know why... - HBox and VBox have their own sizes, too. So if the size of the children gets bigger than its size, it'll clip their content. That was what's happening here: https://discord.com/channels/555424930502541343/1353175379455774811/1354168117038944438 - If you don't want the clipping and want only the alignment from the HBox/VBox, you can check the SizeToContent checkbox so their size gets dependent on their children. - The SizeToContent option disappeared here(https://discord.com/channels/555424930502541343/1353175379455774811/1354248987837861999) since you wrapped the HBox with a SizeBox, which has sized slots. Since the size of the HBox will now be determined by the slot, UE hides the size-related options from the details view. - Your solution works because Instead of resizing the outer HBoxes, now you're resizing the inner ones(buttons) with ScaleBoxes.
Epp
EppOP2w ago
Ah, very interesting - thanks for the explanation! And for all the help and advice! I learned a lot doing this!
Solution
Epp
Epp2w ago
To recap the solution, rather than piece together widgets in C++, I made the whole widget in UE and then used Bind on BP Function: Construct to find and insert the widget at runtime, but only because widget blueprint hooks didn't work (the widget only got inserted on the first map screen open... there's a quirk there that somebody might want to sort out... I'd do it if I had more time right now). Then I had to sort out button layout and alignment, which yeshjho helped with.
Rex
Rex2w ago
Which function did you hook from C++ to inject the widget, that resulted in the hooked stuff no longer working the second time the widget gets opened?
Epp
EppOP7d ago
That was just using WidgetBlueprintHooks on the instance module, no extra hooking.
Rex
Rex7d ago
Ah, so it's a bug with widget blueprint hooks? Would be nice to open an issue in the SML GitHub repo to not forget about it
Epp
EppOP7d ago
Gonna be away for a few days but will try to remember when I get back.
Epp
EppOP5d ago
GitHub
Widget Blueprint Hooks only seems to work the first time for some w...
Summary: in figuring out how to add custom buttons to BPW_MapMenu, I tried creating a custom widget and then inserting it into BPW_MapMenu using Widget Blueprint Hooks on my root instance module. T...

Did you find this page helpful?