#slate
1 messages · Page 1 of 1 (latest)
You can use the property editor module's CreateSinglePropertyView method
It will require an FNotifyHook to respond to changes, though.
Whats the FNotifyHook?
It's just an "interface" you can extend to get PostEditChange etc
wait is the prop editor only for UProp's?
Yeah..
gotcha
what options for non uprops
its for editor tooling
actually I guess it is a uprop
SNumericalEntryBox or whatever it's claled?
so I prob have to use this
sdjug=s[g
class SNumericVectorInputBox : public SCompoundWidget
I am guessing
That's the one
That'll be the on with the nice red/blue/green color blocks
How do you have the SNumericVectorInputBoxFVector::FReal update its vector value on commit?
seems to reset its self hmm
nvm works fine
If you have the value bound, it will reset to the bound valeu after commit
Hello!
Is there any way to make auto ui element for fproperty? Like alternative to SProperty?
Its not working with structs 😦
About this one, i couldnt find good explanation how it works. For example it requries structOnScope, but how i can make it from struct i already have and want to use?
I don't really know.
You just created one via MakeShared, give it the ustruct and give it the data pointer of the struct you already have
This is by memory as I'm on way to Croatia for vacation, sitting at the airport lol
I tried giving it a struct, but it didn't update the struct. I probably did it wrong. I ended up just using TStructOnScope as the base uproperty. Worked fine 😄
Can you please give me example? 🙂
Not of doing it wrong, no. 😦
super beginner question but I need an editor callable function in an actor component that will launch a slate window to open. The editor callable function part is easy but how do i create just create/instantiate/etc a blank slate window and show it on the screen?.
Check fslateaoolication. I think there's an add window function there somewhere.
Application *
You can find out how to instantiate an swindow in the engine source.
alright thank you
If you want to add a window that grabs focus, you're looking for like a modal window. Add modal window?
Something modal.
I think....doesn't a modal need a parent window?
just saying that from looking through FSlateApplication for a minute, don't actually know
I know when you create a plugin, there is an option to have a button on the main toolbar in the editor that will create a window when you click on it. Maybe I'll take a look at that code.
You can leave the parent of a modal null.
It'll still work.
It just finds the "best" window to parent it to.
Np
Can I not bind slate widgets to dynamic multicast delegates in C++?
It will let my AddDynamic but I get an error when I try to call RemoveDynamic.
DelegateSignatureImpl.inl(1165): [C2664] 'void TMulticastScriptDelegate<FWeakObjectPtr>::Remove(const UObject *,FName)': cannot convert argument 1 from 'UserClass *' to 'const UObject *'
This is what I'm trying to do:
D_PlayerCharacter->TeamChangeDelegate.AddDynamic(this, &STeamMemberSlateWidget::TeamUpdated);
D_PlayerCharacter->TeamChangeDelegate.RemoveDynamic(this, &STeamMemberSlateWidget::TeamUpdated);
That would make sense, so how would a make a blueprint assignable delegate that can also be bound to in slate widgets via C++? Do I need to create 2 delegates: a dynamic multicast and a non-dynamic multicast?
You need to bind the dynamic one to a UObject
So you need a UObject reference somewhere in your slate widgets.
Interesting, so could I do this: D_PlayerCharacter->TeamChangeDelegate.AddDynamic(D_PlayerCharacter, &STeamMemberSlateWidget::TeamUpdated);
That doesn't make sense though :P
I'm guessing not because although D_PlayerCharacter wouldn't have any idea how to invoke STeamMemberSlateWidget::TeamUpdated right?
Yop
It would try to invoke STeamMemberSlateWidget::TeamUpdated using D_PlayerCharacter as this and fail terribly.
(and obviously not even compile)
Slate usually uses Bindings
The ones you want to avoid in UMG
I would suggest not doing this in the STeamMemberSlateWidget if you need it to be a dynamic delegate
Are you using that Widget in UMG?
Or is it pure Slate?
Well for now I just made it a BlueprintAssignable dynamic multicast delegate and bind to it in the UMG child class. Just figured I could bind in the parent slate widget instead but...guess not
You can wrap your Slate Widget into a UWidget
That's basically what all the native ones are
In that you should be able to bind
You won't be able to bind the Slate Widget to the DYNAMIC Delegate
Ah okay, that makes sense. Still unfamiliar with Slate in general.
Well you can either stay in slate
Fully
Or you wrap your Slate Widget into a UWidget (not UUserWidget!) and expose it that way to the Palette of UMG
There is theoretically barely a need to make Slate Widgets by default
You are basically trying to make 2 systems which weren't designed to interact... interact.
You need some sort of bridge.
Okay cool, thanks for the help fellas!
Best way to display array of structs in slate
That u can modify
And have changed push a fybc
Function
In editor or runtime?
create a single property view from the property module?
no uprop stuff
actually
maybe it could be uprop
but I have never used uprop module before
Last time I used a SNumericVectorInputBox
But that was for a vector
is there any examples of using the property module thats simple?
got a pea brain here
wait is there not a thing for editor utility widgets for this
Not really?
cursed question - I have an SWebBrowser (which extends SCompoundWidget), and it has this declared in its .h file under public:
/** Called when document loading completed. */
SLATE_EVENT(FSimpleDelegate, OnLoadCompleted)
However, the actual FSimpleDelegate OnLoadCompleted; is declared as private
If I have a reference to the SWebBrowser, can I somehow hook up to that delegate and get a callback? 🤔
Is there a method that returns the delegate?
No, but I can probably reinterpret_cast my way in
Er dude
You pass it in as a construction parameter.
SLATE_EVENT(FOnLoadUrl, OnLoadUrl)
yeah, but i'm not the one constructing the thing
I have a reference to an existing one
and i want to add an event handler to that thing
the SLATE_EVENT thing is internal code from a 3rd party plugin
I wanna do some evil hackery like, at runtime, do FOnLoadURL.BindUObject
So you can't create your own SWebBrowser?
Hey there guys, I ran into an need to somehow get from the SWidget I'm dealing with in C++ to a UWidget that manages that data (if I understand the setup correctly).
I'm using a UWidgetInteractionComponent and trying to get the widget it's currently hovering over to do some logic in blueprints, but the data it returns is the SWidget. Any clue how I might get the UMG "identity" of the UI element?
I'm currently writing a multi-touch interaction setup for 3D widgets, and in order to obtain the identity of the pointer (of which it could be any of the fingers) and track it properly I need to compare pointers stored in the interaction class and the pointer of the UI element that detected the hover. This way in the logic I can be sure that "this button is being touched by FingerIndex n)" and so on
Anyway, is there any way to possibly get the UWidget from the SWidget that the Widget Interaction Component is detecting? Maybe they have some internal ID I can compare?
Alternatively do UWidgets in BP have a capability to write some arbitrary data to their SWidgets that they can be identified by in C++?
Did you manage to solve this? I've hit this a few times, needing to go from Slate back up int UMG land.
I've done some odd hacks like looking at the name to find its ID.
There's also a SWidget::SetTag(FName InTag) func that might be useful?
I have!
@mild oracle
TArray<int> ASpellPlayerController::IsWidgetHoveredOver(UWidget* Widget)
{
TArray<int> ReturnArray = TArray<int>();
int num = InterfaceInteraction.Components.Num();
SWidget* SlateWidget = &Widget->TakeWidget().Get();
for (int i = 0; i < num; i++)
{
if (InterfaceInteraction.HoveredWidgets[i].Contains(SlateWidget))
{
ReturnArray.Add(i);
}
}
return ReturnArray;
}
I have the relevant widgets call this at the end of my drag/drop event, I imagine it would work just fine in a hover event as well, though I'm not sure how the order of operations goes there.
Basically the idea here is that since afaik there's no way to climb back up to UMG after going down to Slate, you just go the other way around
Thanks for sharing!
❤️
I am using an simage to show an image in slate. For the first frame I see the image but then it disappears and is replaced with a square. I set the f slate brush in the scompound widget class variable.
Probably, I don’t know how to check since I SNew the item.
I then set that widget as the swidget of a widget computer bent that I move around in world space.
Should I just dump that here or is there a format?
.cpp
#include "Misc/Paths.h"
#include "PointMarker.h"
#include "SlateOptMacros.h"
#include "Widgets/Images/SImage.h"
#include "Brushes/SlateImageBrush.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void UPointMarker::Construct(const FArguments& InArgs) {
ChildSlot
[
SNew(SBorder)
[
SNew(SImage).Image(&(UPointMarker::FSB)).ColorAndOpacity(FLinearColor(255, 0, 0, 255))
]
];
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
.h
#pragma once
#include "CoreMinimal.h"
#include "Brushes/SlateImageBrush.h"
#include "Widgets/SCompoundWidget.h"
/**
*
*/
class PLOTRAMGUNDATAGUI_API UPointMarker : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(UPointMarker) {}
SLATE_ARGUMENT(TWeakObjectPtr<class FText>, tooltip);
SLATE_END_ARGS()
FText tooltip;
FSlateBrush FSB = FSlateImageBrush(FName("C:/Users/TarkiTarel/Documents/Unreal Projects/MyCoolProject/Content/TempArt/cross.uasset"), FVector2D(25, 25));;
void Construct(const FArguments& InArgs);
}; ```
Put 3 ` before and after it
You should really not hard link files like that!
But I digress.
It might be that it's loading your uasset and then gc'ing it.
Load your asset and put it into a TStrongObjectPtr<UTexture>
Yes
I never load the texture, I supply the asset to the fslatebrush
Yeah, that you need to keep a reference to it so it doesn't unload!
I am trying to do a static load of the texture. Can I do a static load of the texture using only the full file name?
It would be better if you didn't use a uasset at all.
Just link to a png file or whatever.
I do have a png, but I need to load it I assume with static load object. But I don’t know if it needs the full path, a relative path, or where the path starts.
What brush do I use to make a fslatebrush from a png? I only need a fslatebrush that doesn’t get garbage collected after construction.
FSlateImageBrush(path, size)
So how do I save a reference to the fslatebrush? It isn’t a uobject and I have it saved as a class variable.
Just as you're doing now.
You can use a TSharedPtr<FSlateBrush> in your class maybe?
I will try that. Thanks for all the help by the way!
Np 🙂
I am creating an editor widget via SpawnAndRegisterTab. If I resize the tab and re-open it, it'll remember the previous size and set hte widget to be that size. Is it somewhat simple to make it always spawn my editor widget at a fixed size and disabled resizing of the window?
by "disable resizing" i mean make it so the user cant click on the edge of the widget and drag to modify the size of the widget
has anyone managed to use CommonWidgetCarouse. i cant find any documentation or resoureces on how to use them?
Your documentation is probably Lyra.
hey, new to slate and C++, why's this incomplete type error coming up when it works fine for the overlay?
Did you include the headers for those types?
Anybody here with experience using UCommonButtonBase from Common UI?
oh, I didn't have the includes in the header file. bruh why has C++ gotta be like this
Yes, but in the future I would recommend asking your question directly 🙂
Thx, I already tried earlier asking directly and didn't get any answer. My question is if it is intended that UCommonButtons are not focused properly by set focus (aka I can't press them via the default keyboard navigation keys until I navigate atleast one time).
Since set focus has no idea that common button in fact wraps an internal button which wraps an SCommonButton...
You aren't supposed to use SetFocus() directly with CommonUI, so that could be why. Which is weird because it should give a warning in the log when trying to call the function
Navigating focuses the SCommonButton correctly and doesn't have this issue
Well commonbuttonbase is focusable, internal button isn't and SCommonButton is focusable again.
And even funnier, the auto focus feature of common UI fails just as miserably at properly focusing it as Set Focus
I haven't had any issues with button focusing with CommonUI, so that's odd
(aka I can't press them via the default keyboard navigation keys until I navigate atleast one time).
Does this also happen with gamepad navigation?
The issue is exclusive to the moment before ure navigating the first time after acitvating a menu
You're talking about ActivatableWidget's GetDesiredFocusTarget(), right?
I would see if the issue happens in Lyra. If it doesn't, then it's most likely something on your end
No, when I toggle gamepad mode by pressing a gamepad button, it seems that Common UI automatically executes a single navigation, which focuses the underlying slate button correctly
Well I'm just using the plain common ui stuff, without Lyra, I even tried in an empty project from scratch, with or without desired focus target, the common button can never be keyboard pressed initially, only after navigating once
I know, so I would recommend seeing if it's also an issue in Lyra
if it isn't, then it must be due to how you're structuring/setting up the CommonUI classes
because Lyra also uses CommonUI as its base. It does use other plugins such as CommonGame, but that wouldn't affect button focusing
I guess I'll have to download and look at lyra, but from what I heard they subclassed a lot of the common UI stuff to adjust it
So it's definitely not the vanilla common ui
I mean I would just feel a lot more reassured if somebody could test this outside of lyra, if they can get the common button to be pressable without prior navigation
You said this also happens with gamepad right? Not just keyboard?
Because I checked the entire source code of common ui, there's nothing in it to properly focus the underlying slate button of a common button. The problem is kinda triple, first of all common button wraps an internal common button which again wraps an SBox which again wraps an SCommonButton, it's literally impossible to focus this properly with the code existing in common UI. The only reason why navigation focuses it correctly is because it does a geometry trace that manages to hit the SCommonButton
Well gamepad is fine if I switch to gamepad after the menu is already open, which triggers a brief navigation it seems
Okay because I just tested with gamepad, not using mouse at all, and it seems to focus the buttons without issue
in a separate project
Yeah gamepad is not my issue here really. But keyboard prior to navigation is
Only this one niche situation
To my knowledge keyboard and gamepad navigation would be the same in this case
or have the same functionality, that is
Common UI does differentiate between them, but not sure to what extent
Did u by chance test with keyboard?
I potentially found an issue with our project because arrow key navigation doesn't work at all lol, so that's an issue on my end
i see, also, let´s say I do not directly use set focus, when I use desired focus target instead, the source code of common UI doesn´t do anything else either, it calls Set User Focus on whatever ure feeding it with here
so I don´t really get what the deal with not using Set Focus in Common UI is
{
UE_LOG(LogUIActionRouter, Display, TEXT("[User %d] Focused desired target %s"), OwnerSlateId, *DesiredTarget->GetName());
DesiredTarget->SetFocus();
}```
that´s all it does
i don´t see any magic here
CommonUI has its own system for handling focus to ensure there's always something to focus when switching between mouse and gamepad
What you're supposed to do is override/implement the GetDesiredFocusTarget(), and then call RequestRefreshFocus() if you want to change focus at runtime
Right below that it should explain why you shouldn't use SetFocus directly
request refresh focus, yeah, I´ve seen the function before, it´s not even exposed to BP from what I remember
// Temporary support for existing stuff that manually sets focus in Activate. If they just requested it this frame,
// we won't actually be updating the focus until the LocalPlayer's FReply is processed. So if we've got a new focus target already set,
// evaluate that. Otherwise evaluate the currently focused widget. Going forward, all widgets should be built to rely fully on GetDesiredFocusTarget().
it is
UFUNCTION(BlueprintImplementableEvent, Category = ActivatableWidget, meta = (DisplayName = "Get Desired Focus Target"))
UWidget* BP_GetDesiredFocusTarget() const
Lyra almost exclusively uses the blueprint event for it as well
they have a compile check in their subclass to make sure there's always a focus target set
* Ask for focus to be re-set to our current DesiredFocusTarget,
* but only if our node is currently the leaf-most active node (no stealing!).
* This is useful for complex cases like: the buttons animate in from off-screen,
* or the buttons are deeply nested in a multi-switcher hierarchy and it would be burdensome
* to wrap each element in a CommonActivatableWidget.
*/
void RequestRefreshFocus();```
atleast not in UE 5.0.3
the function should be right above that
* Implement to provide the desired widget to focus if/when this activatable becomes the primary active widget.
* Note: This is a fallback used only if the native class parentage does not provide a target.
*/
UFUNCTION(BlueprintImplementableEvent, Category = ActivatableWidget, meta = (DisplayName = "Get Desired Focus Target"))
UWidget* BP_GetDesiredFocusTarget() const;
/**
* Ask for focus to be re-set to our current DesiredFocusTarget,
* but only if our node is currently the leaf-most active node (no stealing!).
* This is useful for complex cases like: the buttons animate in from off-screen,
* or the buttons are deeply nested in a multi-switcher hierarchy and it would be burdensome
* to wrap each element in a CommonActivatableWidget.
*/
void RequestRefreshFocus();```
only the BP get focus target is above it
Oh my bad. I thought you were referring to GetDesiredFocusTarget
Yeah RequestRefreshFocus isn't exposed, but it's obviously really easy to add
yeah, I´ll try with it, though I have my doubts if it will fix the button issue
ok so basically refresh focus ends up calling void FActivatableTreeRoot::FocusLeafmostNode()
which ends up directly setting focus to either auto restore target or desired focus target
Thx for the help, I will report back if using Refresh Focus fixes it, even if I can´t see how it would do that from looking at the source
Ok tested it, made a subclass of activatable widget which exposes refresh to BP, calling refresh in Focus Lost and Focus Received, result is the same, button cannot be pressed via keyboard until navigating once. My common buttons don´t use Triggering Input Actions (yet)
regular buttons don´t have this issue for me obviously
If you have a controller, could you test out to see if the issue continues happening when navigating with it?
controller works fine
just tested it
for some reason, Common Button is hardcoded to ignore Enter Key navigation requests to begin with
so that only leaves spacebar for navigation accept input
and this input only works after navigating at least once with the arrow keys for example.
widget reflector also shows the issue nicely, namely that the underlying SCommonButton is not focused correctly until navigating once
using gamepad, it´s focused correctly right from the start according to widget reflector
to be quite frank, since I´ve worked on this issue for several days now, I already made a hacky fix, but it´s definitely not great. I basically redirect focus to the underlying SCommonButton whenever a UCommonButtonBase is focused (which is quite difficult since SCommonButton is a private member of a private wrapper class etc...)
using this fix, I can instantly press the button with the keyboard
Hm, yeah I could be completely wrong and it is a bug, but it's such a weird issue
I would still be very curious if it happens in Lyra
I´m just starting to wonder, are navigation accept inputs not meant to be used with common buttons? I mean epic even hardcoded them to ignore the Enter key, like, why?
{
if (InKeyEvent.GetKey() == EKeys::Enter)
{
return FReply::Unhandled();
}
return SButton::OnKeyDown(MyGeometry, InKeyEvent);
}```
what´s the purpose of ignoring Enter?
Beats me. I don't think I've ever used the arrows keys to navigate the UI in an Unreal game, both when playing and developing, so I've never looked into it
also SCommonButton is 100% not subclassable, its entire header file is inside a private folder
so this behavior is hardcoded for real here
i mean the common ui docs even boast about how cardinal navigation works out of the box for keyboard and gamepad
and the accept inputs are part of that navigation too (space/enter for keyboard)
so it just made me think, maybe they want us to exclusively use Triggering Input Actions for the buttons and forget about the entire navigation accept input that has been in unreal forever?
but even when using that approach, it´s not really nice, since it will lack any button animation/sound etc. then
Is there a built in slate widget for FGameplayTag? Like the picker. I'm not at my pc right now to check
...nvm
There are hacky-type things you can do to expose it. Adding the private folder for CommonUI to your include paths, for instance.
I see. But even then, I would have to subclass both common button base and common internal button and it would be one big mess. Do u happen to know if what I mentioned about common button press with keyboard prior to navigation is a known issue?
Ah yes, a purist. I wanna try with pure common ui, didn't even look at lyra yet, but I guess I'll have to this time
Stick to UMG then 😛
Is common ui that unpolished XD
Well, I mean, Common UI is a UMG library
It also has some new slate classes here and there
Like SCommonButton
Btw it's not possible to access a widget from an swidget, right?
Only the other way around?
Great, more hacky stuff
I think the methods I've seen is iterating over all the UWidgets of the correct type and finding the matching underlying slate widget.
Lol
That isn't as bad as it seems as all uobjects are stored in a list of their class
Same reason GetAllActorsOfClass isn't as bad as it sounds, performance-wise
It's still terrible and you shouldn't use it unless you actually need every actor.
I see, hmm. It just always says use get all widgets of class sparingly. The weird thing with common button is that epic has common internal button as its root, which in turn has an SBox which contains the SCommonButton. So if u call set focus on common internal button, it says that it does not support focus, since it has sbox instead of scommonbutton as its underlying slate...
Hey, I have this local variable and I want to have it as a class scope variable so I can access it in other methods:
TSharedRef<SVerticalBox> PageContainer = SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
//...
I tried doing this:
SAssignNew(PageContainer, SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
//...
But I am getting SharedPointer.h(210): [C2248] 'FSlateControlledConstruction::operator new': cannot access private member declared in class 'FSlateControlledConstruction' error. What is wrong?
Note that I have TSharedRef<SVerticalBox> PageContainer; declared in the header class.
The problem is your header is attempting to construct the SVerticalBox
Change your header to a TSharedPtr and it will work
@simple delta
Oh, thanks"
One more question, is there a reason I can't SetUserFocus for SHorizontalBox but I can SetUserFocus to a SButton? Is there a way to make SHorizontalBox focusable by FSlateApplication::Get().SetUserFocus?
I will try, thank you
bCanSupportFocus needs to be true, I think
@grave hatch Interestingly I can't set user focus for SCheckBox as well and I would assume that CheckBox is focusable by default. In the base class it has bIsFocusable as a Construct parameter, does that mean the only way to make checkbox focusable is to subclass it and set it manually?
Oh nevermind, you have to set it manually "IsFocuasble(true)"
Does the Editor have a string combo box equivalent like UMG does? ( I was told to ask this here instead of #cpp )
SComboBox ?
You have to implement the "string" part yourself, though, using an STextBlock
if im making a custom slate widget, is there specific functions i need to make it "work"? i see a lot of Construct functions but cant find where they are called. does SNew call it?
ah sweet, thanks. are the SLATE_*_ARGS macros needed as well? ive seen some that are just SLATE_BEGIN_ARGS() {} SLATE_END_ARGS()
They're what define the .Blah(x) stuff after SNew()
ah
They are optional
sweet, thanks
You can also make mandatory arguments by adding them to Construct()
SLATE_ARGUMENT is a sort of yes/no situation, SLATE_ATTRIBUTE use TOptional (and can bind to functions and such)
And there's SLATE_EVENT and some slot ones too that I've never used.
thanks. ive seen these around, its quite difficult to decipher it all lol. i bet it would be worse without these macros though
Probably 🙂
so my slate widget isnt showing in the editor. the widget reflector says MyWidget -> SNullWidgetContent. im doing SNew inside of Construct, is that allowed?
my problem was that i was using a compound widget and didnt do ChildSlot[ ... ]. so thats all fixed now
How to get center of the widget regardless of what anchor is used
Can anyone have idea of it in ui
In c++ sure
So on my adventure to add a ComboBox to the Editor for a custom struct.
I've created my Customization class, and ran some example code fine.
But when I add the ComboBox, using
.ValueContent()[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(SComboBox<FComboItemType>)
.OptionsSource(&Items)
.OnSelectionChanged(this, &FTestCustomization::OnSelectionChanged)
.OnGenerateWidget(this, &FTestCustomization::MakeWidgetForOption)
.InitiallySelectedItem(SelectedItem)
[
SNew(STextBlock)
.Text(this, &FTestCustomization::GetCurrentItemLabel)
]
]
];```
I get 12 unresolved externals aka errors.
I'm not sure what includes I'm missing even looking at it?
unresolved external symbol "__declspec(dllimport) public: static struct FKey const EKeys::PageUp" (__imp_?PageUp@EKeys@@2UFKey@@B) referenced in function "public: virtual class FReply __cdecl SListView<class TSharedPtr<class FString,0> >::OnKeyDown(struct FGeometry const &,struct FKeyEvent const &)" (?OnKeyDown@?$SListView@V?$TSharedPtr@VFString@@$0A@@@@@UEAA?AVFReply@@AEBUFGeometry@@AEBUFKeyEvent@@@Z)
unresolved external symbol "__declspec(dllimport) public: static struct FKey const EKeys::PageDown" (__imp_?PageDown@EKeys@@2UFKey@@B) referenced in function "public: virtual class FReply __cdecl SListView<class TSharedPtr<class FString,0> >::OnKeyDown(struct FGeometry const &,struct FKeyEvent const &)" (?OnKeyDown@?$SListView@V?$TSharedPtr@VFString@@$0A@@@@@UEAA?AVFReply@@AEBUFGeometry@@AEBUFKeyEvent@@@Z)```
Seem to deal with key inputs? PageUp, PageDown, Home, End? I'm not trying to use or touch those? If I comment out the creation of the ComboBox via SNew those errors go away
Add InputCore and Input to your build.cs
InputCore is a thing, input doesn't seem to be? But InputCore did the trick!
Given that UUserWidget has NativePaint(), is there a reason to create a slate widget that projects to UMG widget? What do you gain by doing this vs Just making a UUserWidget?
Is it possible to have per player widgets including navigation without using splitscreen?
Hey guys, my goal is to have a Localizable text box in my utility widgets.
So I managed to put a STextPropertyEditableTextBox in a UMG Widget and I can now use it. But when I click on my String Table nothing happens, I can't even click the check Localize for example.
I think I have to set better the second parameter of the STextPropertyEditableTextBox - the IEditableTextProperty. I can't really understand how can I use it though from the examples in the engine. For now I'm just returning simple values from the interface functions. Any help is appreciated 🙂
I am trying to make an simage Based on a png. I do use a strong pointer for the fslateimagebrush, but I still get no images. I can confirm that the fslateimagebrush brush is used, but the image is not shown, instead it is a blank box. Is there any thing I need to do for fslateimagebrush to appear aside from providing a file name to the png?
Make sure the png is actually in thje place you say it is?
There will be an error if it isn't.
Have you checked the widget reflector to make sure your image isn't just 0x0 ?
I can make a FSlateImageBrush with a wrong file name, it just doesn’t load.
I can’t tell if the image is null though in the reflector.
Like I have the widget reflector looking at the images and I have inspected other images, but I can’t tell what image is loaded for any of them.
The details page is blank.
@grave hatch sorry for the ping, but I read on the unreal forums that u had a deeper understanding of the splitscreen code. Is it possible to have the same per player widgets including per player navigation one would get when using splitscreen, but without splitscreen? E.g. local co-op with one shared screen, but players still get their own character selection menus e.t.c
I've literally never used split screen
Yeah I don't plan on using it either, I just want the per player widget stuff from unreal
What's giving you the problem?
There's Add to player screen, right? When I use it without having splitscreen enabled, it does nothing for player 2
So add them all to player one's screen.
And I made sure that each widget has the right owning player
Ok but then I need to create custom navigation, right? Cause ue built in per player widget navigation kinda relies on the widgets owning player?
Or can I add a child widget with a different owning player to a parent widget to make it work?
...Probably?
E.g. I have a UI Base widget that's owned by the primary local player and then I add child widgets to it that are owned by various local players?
It all just works out of the box when splitscreen is enabled, kinda a pity that there's no documentation regarding non splitscreen local multiplayer
Try it out.
To be honest, I'm not sure you need to worry about anything beyond which player's screen you add it to via "add to screen"
Will do, thx for the suggestion, fingers crossed
Also let's hope common UI doesn't get fed up when adding widgets owned by other players to a stack...
How do I persist drawing operations performed in UserWidget's NativePaint()? I'm overriding it in my class, and drawing text, lines, and boxes. But I need to be able to preserve the objects I drew last pass rather than redrawing every time.
The reason is, my VR displays are driven from an external application (Which I have no control over) sending commands to draw objects and text to the screen. The application expects that everything remains on screen until a section is cleared and overwritten. (See First and Second Pass Images)
Draw them to a custom texture and then render that texture, rather than drawing htem
Alternatively use the volatility stuff, but I'm not 100% sure how that works. People have talked abotu it in here, so do a search.
Do you have any material you can point me to for drawing to a render target or texture using c++? I haven’t found c++ functions with the same versatility as the DrawTextFormatted() that Im using in NativePaint() right now. I need to be able to define font size and stuff like that.
Thx Daekesh, worked like a charm!
Thanks anyway!
When I load an FSlateImageBrush based on a file name I get a resource object of null. The jpg is in the right position and the name I use is the fully qualified name.
void UPointMarker::Construct(const FArguments& InArgs) {
//FSlateImageBrush test = FSlateImageBrush("C:/Users/Me/Documents/Unreal Projects/Project/Content/TempArt/cross.png", FVector2D(25, 25));
UPointMarker::permanentBrush = TSharedPtr<FSlateImageBrush>(
new FSlateImageBrush(
"C:/Users/Me/Documents/Unreal Projects/PlotRamGunDataGUI/Content/TempArt/cool.jpg",
FVector2D(25, 25)
)
);
ChildSlot
[
SNew(SBox).WidthOverride(90)[
SNew(SBorder)
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()[
SNew(SBox).WidthOverride(30)[
SNew(STextBlock).Text(FText::FromString("test"))
]
]
+ SHorizontalBox::Slot()[
SNew(SBox).WidthOverride(30)[
SNew(SButton).ButtonColorAndOpacity(FLinearColor(255, 0, 0, 255))
]
]
+ SHorizontalBox::Slot()[
SNew(SBox).WidthOverride(30)[
SNew(SImage).Image(this, &UPointMarker::getMarkerImage)
]
]
]
]
];
const FSlateBrush* UPointMarker::getMarkerImage() const {
return UPointMarker::permanentBrush.Get();
} ```
Suggest taking a look at something like FSlateStyleSet to see how to use it properly
yeah, should really make that a relative path at the very least
Have you checked the output log to see if it's spittng out an error saying it can't find it?
Also TSharedPtr usage is fairly pointless since widgets are going to hold onto the raw pointer anyway, and won't be referenced counted
I see no error for the image loading
How do I force the load?
I will worry about hard linking and style sets and all the unreal best practices once I can prove that I can put an image in slate. At this point I’m not sure that is possible. I have been trying to get an image in unreal for about 20 hours now, this doesn’t seem like it should be that hard.
Have you used the widget reflector to see if the image just isn't 0x0 in size?
The slate image, not your image.
I see the image as a white square, and it does have a size 25x25 but the image I want to see is not in the square.
I can get text and buttons to show up right in the widget, but not the image.
I did check the code with a break point and saw that the image resource object is null.
anyone knows why button color and opacity seems to be much darker than the hexcode I enter? Also, can I disable that without writing my own style or something similar? Would be too much effort to just adjust some colors.
I had that issue, I think it's because the buttons apply the tint to a texture that isn't white.
Might not have been with buttons, but it was something like that .
Or there's some sort of color multiplication under the hood somewhere.
yeah I think it's because of the Brush it's using or so. But anyway. Did you find a solution?
Nope
You'd need a new style.
I have a TSharedPtr<IPropertyHandle> of an Array of NiagaraSystem* and want to just show it in my custom slate code via Handle->CreatePropertyValueWidget() and it shows up fine, the add button just doesn't add an element to the array, any idea what's going on? I had a single NiagaraSystem* before and it worked fine with that.
It's also the case that my struct does not get created by this function at all.
Are you sure it's just not refreshing the view, rather than not adding the element?
yeah I debugged the array. But apparently TSharedPtr<IPropertyHandleArray> is also not supposed to get used in a Box slot.
Heh.
Trying to do the same thing you did here. How'd you insert the custom subclass between the root SObjectWidget and Widget tree so it would rely on the custom drag drop class? last thing I cant figure out
here's what i did in detail:
- create a subclass of UUserWidget called UExuUserWidget
- create a subclass of SObjectWidget called SExuObjectWidget
- UExuUserWidget has two purposes: it wraps its widget content with an SExuObjectWidget, and it handles dragdrop related callbacks initiated by SExuObjectWidget. it's just a glue layer.
- SExuObjectWidget listens for dragdrop events and forwards them to its parent UExuUserWidget
got 1 and 2, not sure how to wrap the content with the "SExoObjectWidget"
i can paste code one sec
wouldnt it automatically do #4?
TSharedRef<SWidget> UExuUserWidget::RebuildWidget() {
ExuObjectWidget = SNew(SExuObjectWidget, this)[Super::RebuildWidget()];
ExuObjectWidget->SetOnDragDetected(BIND_UOBJECT_DELEGATE(FOnDragDetected, HandleDragDetected));
ExuObjectWidget->SetOnDragEnter(BIND_UOBJECT_DELEGATE(FOnDragEnter, HandleDragEnter));
ExuObjectWidget->SetOnDragLeave(BIND_UOBJECT_DELEGATE(FOnDragLeave, HandleDragLeave));
ExuObjectWidget->SetOnDragOver(BIND_UOBJECT_DELEGATE(FOnDragOver, HandleDragOver));
ExuObjectWidget->SetOnDrop(BIND_UOBJECT_DELEGATE(FOnDrop, HandleDrop));
return ExuObjectWidget.ToSharedRef();
}
the first line of RebuildWidget basically builds an SExuObjectWidget and puts the base class UUserWidget's contents inside it
Yeah got at least ExuObjectWidget = SNew(SExuObjectWidget, this)[Super::RebuildWidget()]; working, seemingly it sets it to my custom SObjectWidget, but doesnt seem like my custom FDragdrop op OnDragDetected is getting called for some reason. Am I missing a step here?
I am also a little confused about the delegate handling, whats going on in SetOnDrag functions?
HandleDrag functions are last to be called as those are the forwarded functions, and the Native Drag events are still being called inside the custom FDragDrop class?
did you override SObjectWidget::OnDragEnter? otherwise, it will expect to find a regular FUMGDragDropOp in this cast: https://github.com/EpicGames/UnrealEngine/blob/46544fa5e0aa9e6740c19b44b0628b72e7bbd5ce/Engine/Source/Runtime/UMG/Private/Slate/SObjectWidget.cpp#L388
this means that you will not get drag callbacks when dragging your custom widget over a regular UUserWidget, too
happy to help more when i’m back at my laptop tomo
yeah I think partially was that and not overriding NativeOnMouseDown to handle detect drag, still confused about the other delegate part though. Thanks for the help so far as I have been wondering for a long long time on how to fix this drag drop behavior.
@cobalt hare were the delegates to make UserWidgets drag drop events work with the custom UserWidget's drag drop events? I was just going about trying to make the native events work and they work on each other, which I guess is fine for me since I can just subclass the custom UserWidget for all dragdrop stuff. And perhaps to get around the fact that DragCancelled event is nonvirtual?
there are many different ways you could do the dragdrop delegates. i don't remember exactly why i did them this way -- you might be able to use the builtin UUserWidget/UWidget delegate handlers, as long as the logic to create your specific DragDropOp type is in your SObjectWidget subclass
did you get it working?
kinda, using the native events, just created a custom OnCancelled and copied the standard code and casted to the custom class. So that means I can only use the events that are triggered from the custom UserWidget within that class which works for me. Though would be nice to have the interoperability with the base UUserWidgets but it would probably be easier to build from source to fix that.
I need some guidance on how I am supposed to be replacing a Slate Widget with another.
Ive got an Overlay Slot thats being filled with an STextBlock during Construct(). This STextBlock is contained in a TSharedPtr<SBox> ContentWindow variable.
SNew(SOverlay)
+ SOverlay::Slot()
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
[
ContentWindow->AsShared()
]
Later on when something happens, I want to change that variable content to a more complex Slate Widget.
However whenever I set the value of ContentWindow to something else, nothing changes.
I am calling Invalidate() after i set it to a new Slate Widget, but I am not sure if this is correct?
Why is the new content not showing?
How should I be handling replacing existing content with new content?
Are you changing the value of ContentWindow after construction?
That won't work.
What you'll need to do have a reference to the overlay (or its slot) and replace the slot's content.
(or change ContentWindow before construction)
Ah right, of course. Not sure why that didnt occur to me before.
If ue5, you can use Widget->GetChildren()->GetSlotAt or SetWidgetAt etc I think
Something like that.
UE4's GetSlotAt is protected, so if you wanna use it, you gotta use cast hacks!
Im just going to create a new Widget that sits in the slot and change its content instead.
Is there a better way of setting a background for a vertical box other than using an SOverlay with the first slot being a SImage? Trying to make this a solid color for better readability. Right now I'm hunting for a solid color image to use for SImage but hoping there's a better way.
Use SColorBlock
And, no, that's a pretty good solution.
I use a similar tactic for a nested details panel style display alternating between a black color block background with 90% and 100% transparency
(to provide alternate row shading that works with nested tables )
And 1 pixel wide or high color blocks for grid lines.
I'd use an imagine, but the grid is not uniform.
Ah that works wonderfully
Thank you!
Hmm, interesting. I might do that down the line. But right now my text is just one text block with one long string with a bunch of "\n" :p
Fair. :)
Do you do that with an overlay as well though?
Yup.
4 overlay slots. Background, grid lines and content.
With sboxes with alignments.
And width / height overrides for the single pixel lines.
This slate stuff is pretty nifty ngl
It is.
Can you collapse [ ] sections in your IDE by chance? I'm using Rider and I cannot 😦
#pragma region? 🙂
And, no, I can't collapse them.
Makes slate annoying.
You can always instantiate smaller parts of your widget somewhere else and combine later.
Does anyone know why visual studio can't find SEnumCombobox.h? It seems like it is included like that throughout the engine but it doesn't work when I try it. This is on 4.27 if it makes a difference
Related question, using a regular SComboBox, the box says "no content provided", and I get a crash when I try to interact with it
Don't say "it says this." Do not paraphrase errors.
Show your code and the entire error log.
And not the errors list. The raw output log.
It's not an error the box literally says "no content provided"
!SListView<TSharedPtr<FString,0> >::ScrollIntoView() [D:\UE_4.27\Engine\Source\Runtime\Slate\Public\Widgets\Views\SListView.h:1714]
UE4Editor_Slate
UE4Editor_SlateCore
UE4Editor_Slate
UE4Editor_SlateCore
UE4Editor_SlateCore
UE4Editor_Slate
UE4Editor_SlateCore
UE4Editor_SlateCore
UE4Editor_SlateCore
UE4Editor_SlateCore
UE4Editor_Slate
UE4Editor_Slate
UE4Editor_Slate
UE4Editor_Slate
UE4Editor_Slate
UE4Editor_Slate
UE4Editor_Slate
UE4Editor
UE4Editor
UE4Editor
UE4Editor
UE4Editor
UE4Editor
kernel32
ntdll
Install the debug symbols
They are that's what it gives me
If hte debug symbols are installed, you get more details than that.
Hey folks, I've been running in circles all day with a slate problem -looking for some advice.
I have a UStruct, with a customized editor view.
I'm trying to detect changes to the properties, so I can rebuild the customized view.
My attempts:
PostEditChangePropertydoesn't work because it's only in UCLASSSetOnPropertyValueChangedisn't firing for some reasonPostChangeisn't firing for some reason
The closest I got is SetOnMouseLeave on the slate widget rather than the property, which is.... very unpleasant.
You can use CustomizationUtils.GetPropertyUtilities()->RequestRefresh()
The main thing to be extremely careful of, is to NOT cache the GetPropertyUtilities return value - or you get shared ptr crashes.
You can use the FNotifyHook parameter to do stuff
Refreshing itself is solved, the issue is detecting WHEN to refresh.
Hence my hack of detecting mouse movement on the slate widget.
You mean like GetPropertyUtilities()->GetNotifyHook()->NotifyPostChange(...)?
I mean more like, setting the notify hook for the details panel so that you actually get a notification.
Or single details instance, whatever.
I'm not entirely sure how to do that, but I will look into it.
Where are you expecting to change to happen? Like in a custom slate widget?
And are you using the PropertyEditor module to create property editors?
I don't think this is technically the correct channel, but it seems the most appropriate.
I am running this on my widget every time the user presses the mouse button in the applicaiton window:
FSlateApplication::Get().SetKeyboardFocus(GetCachedWidget()->AsShared());
However, I cannot use the console after I do this
Is there a fix for this?
fixed it
How did you fix it?
It's usually good practice to edit your message to include your fix so anyone in the future searching through old messages can see how to fix it themselves
I see. Turns out using SetKeyboardFocus focus all input to the widget. That combined with the fact I was resetting focus when it was lost (using OnFocusLost), and my native key down as always returning FReply::Handled, meant only the widget was ever received the I put.
I changed the FReply to Unhandled (unless I handled it, that was more due to laziness thb), and stopped resetting focus everytime.
Can anyone tell me how do i create a virtual joystick in widget from sketch in UE5
when it says no slate widget, does it mean its removed? or is it still there in memory?
It would mean the pointer to teh slate widget is null.
Whether the slate widget itself still exists in some plane of Unreality... that's anyone's guess.
How can i make my WIDGET act as material? so for example my watch uses the Widget as material? can anyone send me a tutorial for that
When using SAssignNew(var, type), can I change the var?
As in if I have a TSharedPtr<SPanel> CurrentContainer that I pass in for the var
then can I use that same variable for different types of Panels (e.g. HorizontalBox, VerticalBox, Overlay)
Well before I test that ive run into another issue lol. Any way to add stuff to a SBox after it has been created?
Set its Content?
Oh, sorry, forgot to update. I though it would be an AddSlot function, but yeah I figured it out.
You can't AddSlot to an SBox because it only has 1 static slot.
Yeah, would help with templating though
Is there any decent documentation on how to work with SDockTab and the TabManager?
Seems very convoluted to me.
Well, I guess I worked out ONE way to use it. Not sure how correct it is.
I can't give you code, but I can help.
Show code!
Basically you should extend from FTabWorkflowApplication (or whatever it's called) and then register tab spawners with that
Hey folks, I was wondering if anyone has any good tricks for detecting whether an FProperty is wrapping a compound type?
i.e., I want to sort my property into two buckets: One for strings, ints, floats, names... and the other for TArrays, Structs, etc.
One attempt:
TArray<FField*> outFields;
propertyIter->GetInnerFields(outFields);
if (outFields.Num() > 1)
This doesn't work, so I must have misunderstood something about how inner fields work.
I think you can solve one of those by trying to cast it to a StructProperty
As for arrays? No idea.
There are big if/then/else blocks in the engine where they try to cast to the different types. Try looking at those.
Yeah that's a good idea. I did something similar recently, but in that case I had access to more information (the pin type I think).
That was a good hint though. I think this might work:
FFieldClass* fieldClass = propertyIter->GetClass();
if (fieldClass == FStructProperty::StaticClass())
Sorry, should have updated: This worked a charm. I also realized I didn't need TArrays since they already sorta have their own handling, so sorting out structs was perfect 🙂
Is there a way I can customize the bulk editing / property matrix? The way it displays DataAsset references is unsatisfying:
I dont understand why it even displays it like this if it does it can do it better in the details panel
Any way I can modify this or would i need to write a custom tool?
I doubt it has a method to override how it displays type values.
You would likely need to modify the engine.
As its not normally something you would need to extend.
Thanks. I found out there are Editor Utility Widgets and they allow me to write custom editors very simply with UMG so i ll use that instead to make custom tools, i guess.
very difficult to debug anything when the editor crashes basically 5 nodes after begin play - ```
Assertion failed: IsValid() [File:D:\Build++UE4\Sync\Engine\Source\Runtime\Core\Public\Templates/SharedPointer.h] [Line: 890]
UE4Editor_SlateRHIRenderer!TEnqueueUniqueRenderCommandType<FSlateRHIRenderer::DrawWindows_Private'::39'::SlateDrawWindowsCommandName,<lambda_f9feabdceba9d88a5c7b2ca3d59100d9> >::DoTask() [D:\Build++UE4\Sync\Engine\Source\Runtime\RenderCore\Public\RenderingThread.h:183]
Seems like the editor's slate interface is the problem...anyone have familiarity with this?
Not sure what this has to do with Slate.
Is there a way to expose slate to Level Sequencer? A combo box in my case.
To what end?
I have a Combo Box added via Detail Customization, this combo box gives a limited set of strings to pick from to set the value of a struct property.
I'd like it so that you can do the same thing via Level Sequencer. If I expose just the property of struct I can see the value but can't edit it as it's set by the Combo Box as intended. And If I could edit it, It would be just as a regular old string (but I don't want them putting in any string in the level sequencer anyways, hence the Custom Detail Combo Box).
So at frame 0 of the Level Sequencer they can pick "String1" and at frame 20 if they want "String2" etc...
In general this opens up some Detail Customization questions. If the Combo Box sets the value of the Struct Property, it seems like I can't even alter that value at runtime via BP now. So I think there are two issues to solve.
One is being able to edit the Struct Property via other means aside from just the Combo Box and the other showing the Combo Box in Level Sequencer.
The distinction was just made clear to me, but to keep it slate based in regards to this channel it is the latter I'm curious about here.
Details customisation won't affect anything at runtime.
If it's not changing at runtime, there's another issue, such as the level sequence overriding your changes.
I don't think you'll ever be able to show the combo box in the level sequencer.
The best you can probably do is just edit it via the details panel at the appropriate points in the sequence.
The details panel customisation isn't a validation thing for your property. It's just a custom editor. You can still change the value through code/bp/whatever and the details panel customisation won't know or care about those changes.
ah ok, you are correct, it does change, so no runtime issue
ok one less headache, I thought since the Editor Field didn't update it didn't change but it did in fact change as shown by printing the value of the struct after changing it
That's sad, no way to show combo box in sequencer : (
Looking into it to understand how they do it here for "Sound"
But there is a dropdown there, so it should be possible
and its keyframable
There's a "string source" or something you may be able to use
It's a UPROPERTY specifier
(then you wouldn't need your details customisation either)
I've come across that and made a note of it. I didn't go that route because it won't have events for OnChange/OnSelected which I need atm
It'd probably solve your level sequence issue
On another note, why don't you use post edit change property for your events?
The owner of the struct should get those notifications.
Or Post Edit Chain Property
Hmm, So I could do the GetOptions and use PostEdit for my event needs?
Yeah.
Hmm
I mean, I don't know that GetOptions works with the level sequence!
I figured Detail Customization would give me the most flexibility
Ironic, that doing more work for more control is giving me less control ...
Testing to see if it even does work for level sequencer
So it is keyframeable which is good, but doesn't give me a dropdown menu in sequencer which is bad, still that is better
To be honest, that's probably a bug.
I sure know how to find them lol
🙂
So it just shows you a text input field in the level sequence when you use GetOptions?
yeah
can't type in it, can't select any changes but can key frame it to be different directly via the field in details pane
And I'm just thinking why can't I do the same thing to my Custom Combo Box with slate in my Details Customization class?
Like it shouldn't be a big deal to add that key frame thingy to it, it has no issue doing it for GetOptions flag
Where do I use ESlateSizeRule::Fill? I saw in in some AddSlot funcitons, however, SVerticalBox and SHorizontalBox does not have that option. I also could not find any slate argument or slate attribute using it
I have been using the FillHeight() but it does not do what I expect it to. I have modeled it in UMG to be sure and the UMG version does work how I expected.
Guess I just have to guess and check a bit
On what type of widget?
Hey, does anyone know how to bind some keyboard shortcuts to a button created with Slate?
Stupid question, but what's the equivalent for SNew that returns a widget so I can store it in a variable?
This is a question that can go pretty deep. Unreal inputs are bubble-policy based, which means input handling bubbles up the widget hierarchy, beginning with the widget that has focus (i.e. the last widget you clicked).
You generally don't bind a shortcut to a button, but to the same action as the button, so they execute the same function.
The usual way to do this would be to create an FCommands class inheriting from TCommands.
There, you add FUICommandInfos that you can initialize to use specific Inputs (FInputChord).
FUICommandInfo only contains a name, description, interaction method and base shortcut; it contains no functionality yet.
In the parent widget that contains your FUICommandList you then bind the commands found within your FCommands class to specific functions (i.e. your slate button function). This will create the mapping from UI Command to actual behavior.
Then, on Input, you will let the FUICommandList try to Process the given input via ProcessCommandBindings function and it will execute your function for you if conditions are fulfilled
so if you clicked somewhere in your tool, then hit the shortcut, the last focused widget will receive your input, but usually return an FReply::Unhandled() so the input bubbles up until it reaches your parent widget that will handle the input via FUICommandList.
Ah cool. Thanks. I will give it a try.
I am trying to make a button that only accepts right clicks, and lets the left clicks click buttons behind it. Is there a way to do that easily?
Not with an SButton.
Or maybe you can use the ClickType thingy it has?
Nope.
I think it's pretty hard coded to use left click.
Think you have to inherit from SButton and override the ondown function to only accept right clicks
There was something about the SButton that didn't like me doing that. Some private variable that meant I had to copy+paste entire functions to replace references to it.
(at this point I wanted a different function to happen on right click)
Having a weird problem... I'm building an editor asset in editor widgets, but I'm creating an SWindow to hold them inside as a container for several practical and cosmetical reasons
Anyway, everything works ok, but I'm trying to call the LoadMap() function from inside it and I get a memory allocation error and crash
When I run the same function in the same widget but run the usual way (right click, Run), it works. It only crashes when run inside a SWindow. Any ideas?
Well, we'd need your code and the output log (not the "errors list")
Here's the code:
`// Load Widget and World Objects
UClass* WidgetClass = LoadObject<UClass>(nullptr, WidgetPath);
if(WidgetClass == nullptr)
return;
UWorld World = GEditor->GetEditorWorldContext().World();
UEditorUtilityWidget* EditorWidget = CreateWidget<UEditorUtilityWidget>(World, WidgetClass);
if(EditorWidget == nullptr)
return;
// Create SWindow and Apply Settings
const TSharedRef<SWindow> Window = SNew(SWindow)
.Title(FText::FromString(WindowTitle))
.SizingRule(ESizingRule::FixedSize)
.SupportsMaximize(true)
.SupportsMinimize(true)
.ClientSize(WindowSize);
Window->SetContent(EditorWidget->TakeWidget());
const TSharedPtr<SWindow> TopWindow = FSlateApplication::Get().GetActiveTopLevelWindow();
if(TopWindow.IsValid())
{
FSlateApplication::Get().AddWindowAsNativeChild(Window, TopWindow.ToSharedRef(), true);
}
else {FSlateApplication::Get().AddWindow(Window);} `
And looking at the output, the error seems to be this:
[2022.08.30-12.42.22:125][953]LogLoad: Error: Old Package /Game/Maps/NewWorld not cleaned up by GC! Object Package /Game/Maps/NewWorld is being referenced by Polys /Game/Maps/NewWorld.NewWorld:PersistentLevel.Polys_1: (root) GCObjectReferencer /Engine/Transient.GCObjectReferencer_0 -> SObjectWidget(UI_MainConfigurationWindow_C_12)::AddReferencedObjects( UI_MainConfigurationWindow_C /Game/Maps/NewWorld.NewWorld:UI_MainConfigurationWindow_C_12) ^ UGCObjectReferencer::AddReferencedObjects() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\Misc\GCObjectReferencer.cpp:48] -> UObject* UObject::Outer = World /Game/Maps/NewWorld.NewWorld -> UObject* UObject::Outer = Package /Game/Maps/NewWorld ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ This reference is preventing the old Package from being GC'd ^
Are you storing a strong reference to your world?
Don't think so. And also tried calling it from an empty map, and same thing happens
I would put a breakpoint in the engine where it says "not cleaned up by GC!"
And find out what the call stack is that's causing it.
If you aren't storing any references, I don't see why that would happen.
What's the actual full code for your class and hte header file?
Also find out what, exactly, the working method does in terms of calls
Good idea, I'll give it a shot
You say right click works? DId you make the right click version?
It's a static function in a blueprint library, it recieves the widget, the title and the size and that's all
And that loads a map? Fascinating.
Oh, well actually that function loads a widget blueprint
Is the problem loading the widget or with changing the world?
And inside the widget blueprint right now for testing I just have a button calling the LoadMap node
Changing the world. Everything else works perfectly with the widget (been using it for a while)
Alright. So what method works for changing the world?
All others. Including right clicking the same widget and choosing Run
Except when it's called from within that SWindow
And what do the other methods do?
When I click the button from the regular editor widget window, it just changes the map seamlessly, as if you load it from the menu
I don't know if that was your question
Or did you mean other functions inside the widget or the BP library?
Could it be maybe these two lines that are somehow tying the widget to World?
UWorld* World = GEditor->GetEditorWorldContext().World(); UEditorUtilityWidget* EditorWidget = CreateWidget<UEditorUtilityWidget>(World, WidgetClass);
Because I checked the breakpoint thing and it also appears to show that it's being referenced by UI_MainConfigurationWindow, which is my main widget, but there's zero references to the level in it
Ok, yeah. That was apparently the dumb problem. I hadn't considered this case use when I made it. I'll find a way to work around it
Thanks!
how do global invalidation and manually-placed InvalidationBoxes differ? which one should i be using?
GI is pretty much meant to replace everything I'm fairly sure
nice
so GI basically auto-detects when to invalidate widgets with attribute updates, instead of manually placing invalidation boxes to manually invalidate stuff when they changed, right?
I believe that's the idea yeah
great
huh
My slate widget in my hud is consuming all left clicks, is there a way to ensure that the hud only consumes clicks on the items in the slate widget? I can’t tell if the widget is taking up more space than I can see.
Ok, it is definitely the slate widget, I have it in an s box that should limit its size, but it still consumes all clicks.
Go to tools -> debug -> widget reflector
There's a button at hte top left of that window.
Very useful for debugging widgets!
Right, I know about that but forgot that works on widgets in the game. Thanks!
I am trying to limit the size of the widget using a size box, but the widget reflector says the desired size is less than the actual size. I am using height override and using vertical align top.
Hey guys, unfortunately I first asked my question in the wrong channel but I got pointed to this channel so maybe someone here is able to help
#cpp message
I think the issue might be buried somewhere deep inside the slate system.
What is slate
how do you change the order of custom row in CustomizeDetails
MyCategory.AddCustomRow(...);
this adds the row to the bottom of the category, can I add it to the top instead?
Slate is the low level UI system that powers UMG (also available to use by itself)
What's an advantage of using slate then?
You get access to all the features not exposed to UMG.
You have to live in the UObject ecosystem
With Slate, the full power of the UI system and c++ are available.
Of course, you can use these things with a bit of work with UMG as well, but it's just a pain.
UMG has the advantage of being design/designer friendly with a WYSIWYG editor.
You can work with a combination of the two easier these days with named slots.
Anybody dealt with multitouch and interface interaction component before? I’m sending pointer events with the right keys but the result is still identical to as if I was using a mouse - i.e. it’s impossible to press more than one button at a time as the new button takes priority
It’s driving me nuts tbqf, I’m reading code and it seems there’s stuff to handle specifically touch keys but no luck so far
How can i use function with two params in buttonOnClick event🤔
Just put thr params on the function and specify their values in thr binding.
. OnClick(this, & clsss:fubc, val1, val2)
Mobile typing terrible. Hope you get the idea!
I am adding a slate widget to the viewport with GEngine->GameViewport->AddViewportWidgetContent() however, the widget takes up the whole screen, not just the space it uses, is there a way to make the widget only take up the space it needs in the viewport?
Wrap it with something like an SCanvas and use the position and size properties?
Or a constraint canvas etc
If this was a bunch of buttons, and 5 was currently selected, how can I move to 2, 4, 6, 8 when up, left, right, or down is pressed respectively? I would use a simple int variable as in index if I only had to move one way, How can I go about two way?
SButton have OnClicked delegate which is basically empty. Someone know how to get UserIndex who clicked the button? FKeyEvent has InUserIndex but for some reason button OnClicked doesn't have anything. I have messaging system like in Lyra Example and want to support controller disconnected state on consoles but I dont know which user clicked the button after connecting the controller again.
You may need to track the last thing to mouse up with lmb on the button in that case.
If that even triggers
How would you go about doing in slate, the same thing that the TooltipWidget binding in UMG editor does? I have a function that returns a UWidget*. Just having trouble finding uses of the tooltip binding in slate.
UMG has to be doing something different. I've created an STooltip, and set it via SetTooltip. And it's working as intended, but alt tabbing does not remove the slate version. Alt tabbing does remove the UMG one.
Do you need a specific tooltip element that isn't just text?
Just curious why you aren't using .TooltipText()
Or whatever the method is to just use text.
Because I'm trying to use a widget as a tooltip.
I don't mind prespecifying it with SetTooltip. Which kinda wastes by creating them beforehand. The UMG binding only creates the tooltip at hover time. But I'm still baffled why alt tabbing doesn't remove the Slate one.
I assumed that was what the Tooltip_Lambda and such were for. But I can't seem to figure out how to use them.
One way to do it might be to use your widget in umg and track the destructor. See where it's called and for what reason.
@grave hatch Having a bit of a slow day. I don't suppose you know how this would be called?
.Tooltip_Lambda(this{ return YourWidget; }) or replaced YourWidget with some SNew(blah)
You don't even need [this], it can just be [], if you don't need member vars.
Is it possible to mark widgets as exempt/ignored by global invalidation? I assumed "IsVolatile" would do it, but this doesn't seem to be the case, at least the floating health bars cause significant lag when using global invalidation due to tree rebuilding each frame despite being marked volatile (the floating health bars are part of a widget component if that matters), does the "IsVolatile" propagate to children? I only set it for the parent most widget (my user widget)
Specifically my performance drop when using moving widget components with global invalidation is:
Isn't there a invalidation widget thing you can use to control when something is invalidated?
I'm sure someone did a test to determine which is better if you just search the history here.
Hello all 👋 prefacing with being new to slate.
I've got a SPropertySceneOutliner with respective FOnActorSelected bind setup. My question is,
I'd like to change what's shown on my Interface accordingly to the selected actor. So for instance, on Construct() is just a STextBlock saying no actor selected. After the actual callback the Interface changes to my actual SCompoundWidget.
How could I approach this? Could i "repopulate" ChildSlot on the FOnActorSelected callback? Any other suggestion?
That'd probably be the best way to do it.
It makes the most logical sense too.
When you construct the widget the first time just call the select callback manually instead of using 2 copies of your code.
(1 in construct and 1 in select.)
Or have them both call a third function which does the constructing. That'd probably be best.
I'm assuming that funtion would return the SWidget accordingly? And it's possible to have the callback when creating the ChildSlot?
You can also use an SWidgetSwitcher if you only want to alternate between a set of widgets
Thats what Ive been using in a few places in Niagara
Didn't know that 👍
The details widget is going to replace itself (or its contents at least) on switch anyway.
But yeah, you could do either the switcher or a method that returns a widget shared ref. And do childslot [ Get Widget] and Set Content ( Get Widget())
Phone is hard.
Indeed, Im taking a bath right now lol
No better way to relax in a bath than to help other folks 👍
Thank you for the feedback @grave hatch , @split laurel I'll give it a go
Np good luck.
Also because this will drive me nuts, I'm using this a SWrapBox to create this "fill on width" effect. But then it's not possible to scroll down if theres overfill on height? What's the actual best approach to this? I went with WrapBox cause SUniformGridPanel and Grid like panels were asking for a x,y position (Is this the only way?) and I just want to increment based on an array. Is there an actual way to scroll down?
If you want to scroll, wrap the wrap box in a scroll panel?
Or a scroll box. I can never remember which one you're meant to use.
One wraps the other...
Makes sense... I guess? xd Kinda weird hierarchy since it's the content under the WrapBox that needs scrolling?
I'll give it a go, thank you again 👍
The scroll box will provide the space for the wrap box to fill. Then scrolling will move the entire wrap box around.
Assuming you don't want to scroll the wrap box elements individually...
You might come up against other issues like thr scroll box providing infinite space and the wrap box not knowing what to do with it.
Glad you didn't!
having SWidget how do I get its UWidget owner?
This is a bad way, but it should work: Use TObjectIterator<UWhateverWidget> and check for a matching slate widget.
well, it will work but it will iterate all of the objects, isnt there any other way? doesnt SWidget have any references or anything?
UObjects are stored in buckets based on their class.
If you iterate on UMyClass it will only check objects of UMyClass and its descendents.
Hello 👋
Is it possible to draw UTextureRenderTarget2D on to some SWidget ? How?
I'm assuming it requires a SViewPort looking over on how STextureEditorViewport does it
an simage with an fslateimagebrush should do it?
The widgets that are as a widget component are not using Global Invalidation. Only widgets that are on player screen (HUD, menus etc.) are.
Hmm, Global Invalidation increases their cost though, they definitely go through a different pipeline when global invalidation is on vs when it's off (can see it in the breakdown of function calls in profiler)
For now I opted to use invalidation boxes instead so I lost some perf on the HUD but substantially gained perf back due to not affecting the widget components of which there are many
Hello everyone. Is there a way to access the delete button in a Tarray property? I want to do extra functionality when an element is removed but I am not sure how to access that when it appears. Or would be better off creating a custom array using slate in the details panel
Is it a specific property on a specific class you're interested in?
Or just any tarray anywhere?
Its on a specific class. I understand how to grab the array property from the class but there is no delegates for these other elements like the insert/delete
Do you want to add your own things or just respond to changes in the array?
Do you specifically want to respond to deletions?
Yeah I want to add on to the deletions. Like if click it I want it to be removed from the array but also destroy the actor or something extra like that
You can use PreEditChange and PostEditChangeProperty to respond to things like that in code.
Is that a part of IPropertyHandle?
Oh ok now I see it. I'll see if I can get what I want using that. Thank you!
I see "SetOnPropertyValuePreChange" on IPropertyHandle. Is that what you meant?
No. On your class itself override PreEditChange and PostEditPropertyChange.
Doesn't require you to do anything with the details panel.
In the past, and don't shoot me because I know someone will, I've used PreEditChange to store an array and compared it to the new version in PostEditChangeProperty.
Depending on your needs you may do something else.
But this would run even if I didnt change that specific property?
That's why you check the property name.
PropertyChangeEvent.MemberProperty->GetFName() == GET_MEMBER_NAME_CHECKED(YourClass, VarName)
or some such
Oh ok yeah that can definitely work. Ty!
I have another question. If I created a list view in the details customization file. How do I reference it for later use?
i'm getting a client crash with this message displayed, tbh I have no idea why it's happening, the code that is crashing it doesn't really have to do with slate or UI elements really. anyone know what might cause this?
You're accessing slate from tbr render thread probably. Or some other worker thread.
That usually happens when peeps try to use umg from a native steam callback. Not sure if that's the reason here but maybe it helps (:
Not exactly slate, but is there an easy way to make an actor with a widget component without making new class for the actor? I just need to be able to set the widget and place in 3D space.
Add an actor and add a uwidgetcomponent to it.
Is it possible to use DetailBuilder.GetProperty() to access a property from a different actor? I want to get IPropertyHandle of an actor that referenced in my data asset.
Should be, yup.
The property will have a GetValueInContainer or some such property, just supply the actor as the container.
As long as it's returning the type of property I think it is!
Thanks! I'm working on it, hope it will work
Is there a good/proper way to create a drop down menu for an enum? Currently we have to create a TArray<SharedPtr<MyEnum>>, then we have to use the reflection stuff to get all the enum values and make shared pointers for them and add them to the array
refer to SGraphPinEnum.cpp
you make array of TSharedPtr<int32> indexes, and customize GetText/Tooltip/OnChange in combobox
to take enum element by index
SEnumComboBox ?
There's no way to filter the enum with that class, which is annoying, but it will produce a combo box for all enum values
(filter at runtime, not with UMETA())
sounds pretty much the same as how we do it right now. ```cpp
TArray<TSharedPtr<EDialogueDisplayTypeV2>> DisplayTypes;
const UEnum* DialogueDisplayTypeEnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("EDialogueDisplayTypeV2"), true);
if (DialogueDisplayTypeEnumPtr)
{
for (int i = 0; i < DialogueDisplayTypeEnumPtr->NumEnums() - 1; i++)
{
DisplayTypes.Add(MakeShareable(new EDialogueDisplayTypeV2(static_cast<EDialogueDisplayTypeV2>(DialogueDisplayTypeEnumPtr->GetValueByIndex(i)))));
}
}
...
SNew(SComboBox<TSharedPtr<EDialogueDisplayTypeV2>>)
.OptionsSource(&DisplayTypes)
.OnGenerateWidget(this, &SDialogueChoiceBox::OnGenerateDisplayTypesDropdown)
.OnSelectionChanged(this, &SDialogueChoiceBox::UpdateValue_SelectedDisplayType)
.Content()
[
SNew(STextBlock)
.Text_Lambda([this] {
const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("EDialogueDisplayTypeV2"), true);
return EnumPtr->GetDisplayNameTextByIndex(static_cast<int32>(Choice->DisplayType));
})
]```
Hello all.
I've got a SCompoundWidget which refers an existing AActor.
If by any means that actor gets deleted within the editor (and ui slate is still loaded) leads to a crash for lacking of proper references pointer.
What's the best way to avoid this? Binding AActors OnDestroyed? How? Any better approach to this?
Depending on where it crashes, it may be possible to check the validity, and avoid a crash?
But getting slate crash-free is definitely a little tricky.
--
I'm wondering how the heck I detect whether a property is disabled or not. I have an FProperty, an IDetailLayoutBuilder, and a IPropertyHandle.
None of these seem to contain the information on whether a property is disabled or not.
I can actually get my hands on the stupid Parser, but it's private (so not possible to actually evaluate anything: ->GetPropertyUtilities()->GetEditConditionParser()
The actual condition can be gotten with prop->GetMetaData("EditCondition")
IsPropertyVisible always returns true, even when using EditConditionHides (as a way to try and sneak around the issue).
--
I think what I need is FPropertyEditor::IsEditConditionMet() (or similar methods), but I just cannot seem to get access to them.
FDetailPropertyRow::GetPropertyVisibility() also likely works
You were right I was just seing checking for the point if (MyActor) had to if (MyActor->IsValidLowLevel()) 🤦
Thank you for the feedback
Glad you found it, although it sounds like I should take little credit in this case 🙂
TWeakObjectPtr<AActor> MyActor
if (MyActor.IsValid()) { do stuff } else { do failure stuff }
That's how you should do it.
Still stuck on validating whether a property is disabled from inside of IDetailCustomization
I need some logic that customizes the properties differently, depending on whether it's disabled.
I'm making a graph editor based on that GenericGraph plugin on github. I want to dynamically change the color of the spline arrows that are drawn to connect the nodes:
So the arrow on the left would be red, the middle yellow, the right green. And I want the color to be based off of the value input into the edge node
If you're doing a hard fork, should be possible in-place.
Or you can make your own 'MyCoolGraph' which inherits from GenericGraph, and then write children types as appropriate to take control over the styling.
I did the second option already.
i overrided the FConnectionDrawingPolicy::DetermineWiringStyle
and set the wire color in there. But that didn't do anything. Not sure how it works or where I should be doing that
did you change FConnectionDrawingPolicy or FConnectionDrawingPolicy_GenericGraph?
because if it's the former the latter will have overridden your changes in any case
Is there a way to redraw the customized widget? I'm doing certain actions and I can only see the results after I restart the related thing.
Figured it out. It's StructCustomizationUtils.GetPropertyUtilities.ForceRefresh();
I changed the latter
FConnectionDrawingPolicy_GenericGraph
its pretty janky tho
i'm wondering if maybe my class thats ovcerriding the genericgraph isn't actually overriding it maybe its not being used in the right places properly.
Where can I find instanced UObject's property/details customization code?
Use the widget reflector?
It displays the slate types but I cant find where it populates properties to edit
I want to write a custom system to exclude EditDefaultsOnly properties
by default instaced uobjects displays every property which is annoying
Last Activation Time here is a BP variable that is both private and not instance editable
Looks like a bug.
its a default feature, sadly 😄
recently #cpp was complaining a lot about it
how unfortunate almost every AI system I have relies on instaced uobjects too
its very annoying
Does it still show them even if they're not editable or visible at all?
I'm getting some major deja vu from Ben's server lol, because this conversation happened yesterday. It displaying default only properties is a bug, not a default feature
And does it only do it for bp classes or c++ too?
c++ too
That's definitely some serious bug.
benui was also a victim of this a while ago 😄
Yep that's how it came up. It's a known issue with Unreal.
I guess there is no straightforward fix too either 
I thought maybe I could get away with some simple code to filter the properties to display with customization methods
There's probably some explanation for it deep within the code.
// we display all properties because tim makes us
I searched it a lot but couldnt find a relevant code to filter properties.. Probably I'm too alien to slate
even EditInline property flag has no relevant usage
in whole source
It might make more sense to search for the Instanced uproperty specifier and where it's used in code.
(not "Instanced", but the enum for it)
Funny thing is there isnt one for it too 😄 There are only flags that tells actor X has instanced objects or if object X is instanced by default (another class specifier)
there isnt one tells "X object is instanced"
probably because its a property flag
based on MrHibbits Instanced implies EditInline flag
and EditInline flag has no relevant usages with property filtering etc
maybe thats the issue, it just doesnt filter anything 😂
What you could do is trick it a little
This is a very cunning plan, Baldric would be proud.
Create a uobject with a data type that has a unique detail customiser.
Then simply breakpoint the point it tries to use it and track back the call stack until you find where it's creating the object properties
I guess I found it!
FFindInstancedReferenceSubobjectHelper::ForEachInstancedSubObject
it just shamelessly adding every FProperty it founds to the list
without checking anything
Hey guys, kinda a funny one, which I'm curios about
What exactly is SAssignNew and SNew doing which allows setting stuff like OnGenerateWidget_Lambda
I'm calling an engine method which returns TSharedRef<SWidget>. I cannot set really much at all on this variable.
My understanding is I need to do SAssignNew(.., ..)
This got me curios what's happening during this assignment, that's different than just the normal var?
What are you trying to do?
If you want to put that widget in your widget tree, just do [ GetMyEngineWidget() ]
Exactly! What I was trying to do was something like:
GetMyEngineWidget().IsEnabled_Lambda(...)
In this case I just did SNew(SBox) and wrapped the engine widget
So my question was more theoretical. At a casual glance, GetMyEngineWidget and SNew both return the same type: A TSharedPtr<SWidget>
The IsEnabled_Lambda will only work when used with SNew or SAssignNew.
In the case of GetMyEngineWidget(), that phase is already over.
So you've have to use EngineWidget->Set_Something_
If that property isn't assignable after construction, you're boned.
It worked out OK to wrap it in an SBox
Yeah, but that will enable/disable the sbox, surely? Does that enable/disable the content of the sbox?
Yeah
In this case it's inherited.
It's just like setting no-input on a Div or something like that.
Neat.
You specialise things either by type or by specific property on a class.
So you could add a customisation for FVector or AActor::MyVector
Do you want to specialise a specific property on a specific class? Or just fix the editor ?
So you want to fix the editor?
I'm not sure you can do that with a details customisation. Unless you added a uobject customiser and checked all the properties and specifically removed the ones that are editdefaultsonly
But any custom layout code for any subclass would override it
https://docs.unrealengine.com/4.26/en-US/API/Editor/PropertyEditor/FPropertyEditorModule/RegisterCustomClassLayout/ is where you'd start for that.
Registers a custom detail layout delegate for a specific class
I think?
https://docs.unrealengine.com/5.0/en-US/API/Editor/PropertyEditor/FPropertyEditorModule/RegisterCustomPropertyTypeLayout/1/ Maybe this one actually.
Registers a property type customization A property type is a specific FProperty type, a struct, or enum type
It will.
It will chain the customisers together, I think.
But you can't customise a class more than once. So if the engine already has a uobject customiser, you will need to either extend or chain it together yourself.
Basically the property module has a tmap of class name -> customiser
So if Epic have written a UObject customiser and have added it to the property module, you need to either extend from it, replace it or combine your class with theirs using a proxy class.
does slate have an equivalent to size box?
i can only find USizeBox
oh looks like its just SBox
SBox, yeah.
Please somebody help me
There is a function in SlateApppication.h header file and i want to call that in my code to show the virtual keyboard and I’m unable to do that
Is it static? If it's not static then you may have to get the slate application which you can do with FSlateApplication::Get()
So i find something doing the same way that you showed me but it doesn’t work
Do you have any idea that how can i show the virtual keyboard
I'm on my phone ATM, also what are you talking about finding something the same way but it doesn't work? Can you please share the code?
FSlateApplication::Get().ShowVirtualKeyboard(true, 0/optional text entry slate widget parameter is nullptr, so the function will internally create one/);
What does the error say?
Did you include the slate module in your build.cs?
Yea its there
No error
Just that the virtual keyboard doesn’t show up
I have a virtual keyboard issue on iOS - any time a user finishes entering a word, and then presses the space bar or return key, the virtual keyboard tries to dismiss and re-appear quickly, which interrupts typing any sentences or phrases longer than one word. is there somewhere I can try logging when the keyboard is getting dismissed to see what might be calling that?
this is using the integrated keyboard on iOS on a multi-line text box
lol it's almost like sending a telegram
tbd, I just ripped some random parts out of the source code around it lol so we'll see
what's weird is it seems related to any time a "word" is entered, even if I enter it via native voice dictation or type it manually or select a suggested word on the predictive keyboard, it will reset after a single word is committed no matter what
just removed any mention of deactivating the keyboard that I could find from the iOS source code and its still happening, so taking any and all suggestions 🙌
I'd suggest posting on the epic forums.
It may not be a UE issue either. Or it may be UE misconfiguring the keyboard.
Try searching for it happening outside of UE.
Thanks, yeah I've been trying to search around that kind of thing happening in apps in general. I think you're def onto something with it possibly being os/engine mismatch kind of thing.
I'm just looking for anyway I can suppress the behavior for the time being but will post it on forums and see if I can work around it 👍
Np. Good luck!
Is there a way to create Array or Map slates similar to SNew(SNumericEntryBox)?
I've deep dived into the engine code and couldn't find an example, but maybe I'm missing something?
Sorry for using bad terminology
I would like to know if there is a way to manually create this:
I'm pretty new to the world of Slate, is it possible to return different content, bound to a variable?
Or force a redraw of the whole widget
You can bind, just like in UMG, yes.
E.g. for text you could do .Text(this, &SMyWidget::GetText)
or .Text_UObject .Text_Lambda etc
Hello everyone. I am trying to recreate a check box with an image over it like shown in the Landscape Editor mode but my image gets put to the side. Anyone know what I need to position the image over the box?
Gave it a try but no luck. Not sure if I am reading the documentation correctly
That's correct.
It should overlay the image on top of the checkbox.
Well, I'd do
SNew(SOverlay)
+ SOverlay::Slot()
[
Stuff here
]
+ SOverlay::Slot()
[
other stuff
]```
I can't seem to get custom Slate events to work, the macro is undefined
Is that a compile or code inspection error?
How do I reference image to add the image I want? Do I do that inside the brackets underneath where I declared the image? Sorry I am new to slate finding it hard to find resources for some things
compile
That isn't saying SLATE_EVENT isn't valid, it's saying the code generated by the macro is invalid.
Did you define FOnReturn somewhere?
e.g. DELCARE_DELEGATE(FOnReturn)
That makes sense, I hadn't thought about defining it, I thought the macro took care of it
Hmm, I think i'm doing something wrong
I'm not sure it's actually DECLARE_DELEGATE
Check out DECLARE_DELEGATE_OneParam and find the one for zero params.
is there a built in way for STextBlock to line break on a word?
Binding to a custom SLATE_EVENT doesn't work, it doesnt get fired
What are you expecting to fire it?
thism in the SSDialogueLine widget
Are you assigning the onreturn construct args value to the event?
Is this the correct way to change the color around the check mark of a checkbox?
i don't think so
In your construct event, assign InArgs._OnReturn to OnReturn
Now it works perfectly! Thank you! 😄
Np
Does anyone know why my TextBlock in my custom button made in Slate is not in the centre of the button.
MyTextBlock =
SNew(STextBlock)
.Justification(TextJustification)
.Text(GetDisplayLabelText());
if (ButtonTextStyleAsset)
{
MyTextBlock->SetTextStyle(ButtonTextStyleAsset->GetStyleChecked<FTextBlockStyle>());
}
MyButton = SNew(SButton)
.OnClicked(BIND_UOBJECT_DELEGATE(FOnClicked, SlateHandleClicked))
.OnPressed(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandlePressed))
.OnReleased(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandlePressed))
.OnHovered_UObject(this, &ThisClass::SlateHandleHovered)
.ClickMethod(ClickMethod)
.TouchMethod(TouchMethod)
.PressMethod(PressMethod)
.IsFocusable(IsFocusable)
[
MyTextBlock.ToSharedRef()
];
if (ButtonStyleAsset)
{
ApplyButtonStyleAsset();
}
Have you tried adding VAlign(VAlign_Center) to your SButton?
Thank you. That worked perfectly!
You making mirrors edge?
No.
I am working on a university assignment
How can I get a IPropertyHandle from a struct in DetailsBuilder?
For UObjects I see there is something like that exist:
TSharedRef<IPropertyHandle> Prop = DetailBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(ULuaCode, Code));
but I need same behavior for one of my structs
Originally this is the code I have (from LuaMachine plugin, its an editor customization that provides syntax coloring when writing lua to FText on details tab)
TWeakObjectPtr<ULuaCode> LuaCode = Cast<ULuaCode>(Objects[0].Get());
TSharedRef<IPropertyHandle> Prop = DetailBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(ULuaCode, Code));
DetailBuilder.HideProperty(Prop);
IDetailCategoryBuilder& Category = DetailBuilder.EditCategory("Code");
Category.AddCustomRow(FText::FromString("Code")).WholeRowContent()[ SNew(SLuaEditor).LuaCodeOwner(LuaCode) ];
I want to refactor this into struct
And I have this:
const FStructOnScope* StructOnScope = Structs[i].Get();
const UStruct* Struct = StructOnScope ? StructOnScope->GetStruct() : nullptr;
FProperty* Prop = Struct ? Struct->FindPropertyByName("Code") : nullptr;
if (ensure(Prop))
{
TSharedRef<IPropertyHandle> PropHandle = DetailBuilder.GetProperty(??????); /// <---- what to pass here?
DetailBuilder.HideProperty(PropHandle);
IDetailCategoryBuilder& Category = DetailBuilder.EditCategory("Code");
// note: nullptr here is look fine, its doesnt seem to be used.
Category.AddCustomRow(FText::FromString("Code")).WholeRowContent()[SNew(SLuaEditor).LuaCodeOwner(nullptr)];
}
Anyone happen to know how to iterate over all the tabs managed/opened by an ftabmanager? I can't seem to find anything. 😦
I can find how to get individual tabs with a given id, but there doesn't seem to be an agnostic iterator. 😦
why can i not access SGraphNode::GetAdvancedViewArrow when my class is a SGraphNode? its protected so i should have access. is it because its not my class thats making the call?
Might be somethng in FSlateApplication to do what you want - or to give you the building blocks to do so.
(Don't forget FSlateApplication::Get())
It's possible UGameViewportClient::RemoveAllViewportWidgets() does what you want.
Although I suppose not if you want to toggle UI visibility.
If you want to affect all UMG widgets then you would grab the game viewport client's widget and set its visibility or something. For all slate widgets then you have to use the slate application to get all windows and root widgets and turn off their visibility that way(but I've never done that because I just use the game viewport client route)
🤔 i think it was because i was doing SNew(SImage).Image(this, &SGraphNode::GetAdvancedViewArrow). changing it to .Image(this, &SGraphNode_MyNode::GetAdvancedViewArrow fixed it
Were you doing it outside the context of the class?
Hello, I have an array of FNames in a slate class that I would like to save to a custom config file so that when you restart the engine, the values are loaded into the TArray.
I found a way how to save to config file via UCLASS specifier "config". But slate doesn't inherit from UObject, how would you save an array from slate?
No it was inside a member function of my SGraphNode class
Give errors next time!
Hey, I'm trying to make a plugin in Slate. I want to spawn actors when the editor is in Play mode, and attach listeners to delegates on actors, so I can know when to update the plugin's slate UI fields.
Can I add a widget as a listener despite it not being a UObject?
I think I can't, so I should wrap it in a UWidget. But, I'm not sure how to display a UWidget. I made an "Editor Standalone Widget" plugin in the editor, which seems to just want me to populate a an SDockTab, and I'm not sure how to add UWidgets into an SDockTab.
is it possible to make my own linebreak/wrap thing for STextBlock? i need it to break around words instead of splitting the words
just use regular non-dynamic delegates and then you can use any type, including slate widgets.
I'm sure it had something like that. Maybe I'm wrong...
Yeah, it does.
support for custom wrappers? or support for breaking on words instead of breaking words?
Breaking on words
@grave hatch Thanks
Ok, so now I have a binding that can update a state variable. I'm trying to figure out what the best practice is for having my slate UI update when the backing state changes.
Ex:
Let's say I have a struct:
struct FUnitInfo
{
float Health;
float MaxHealth;
}
// Display "${Health} / ${MaxHealth}"
void SMyWidget::Construct(const FArguments& InArgs)
{
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
[
SNew(STextBlock)
.Text( /* Health */ )
]
+SHorizontalBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString(" / "))
]
+SHorizontalBox::Slot()
[
SNew(STextBlock)
.Text( /* MaxHealth */ )
]
}
I could do something like:
// .h
FUnitInfo UnitInfo;
// In Slot()
SNew(STextBlock)
.Text(
TAttribute<FText>::Create(TAttribute<FText>::FGetter::CreateLambda([=]()
{
return FText::AsNumber(UnitInfo.MaxHealth);
}))
)
But this lambda is called every frame. I feel like there's a way to make it only update this field if the backing field (the UnitInfo struct) is updated, but I'm not sure what does that.
I could also use something like
// .h
TSharedPtr<STextBlock> HealthBox;
SAssignNew(HealthBox, STextBlock)
.Text(...);
// In update function:
HealthBox->SetText(...)
But, this seems against a polling model if I have to explicitly update fields that changed.
Add a delegate to your player (a multicast one)
Trigger it when your health changes.
Subscribe to it from your UI
I think I have that set up using GAS. So, I have a method that is being called when the new value comes in:
void SMyWidget::OnUnitHealthChanged(const FOnAttributeChangeData& Data)
{
UnitInfo.Health = Data.NewValue;
// How do I alert Slate to re-run Construct's field that rely on the UnitInfo backing state?
}
My question is about what is a good pattern for Slate such that the fields' values are derived from some common State struct (in this case a UnitInfo struct with relevant fields of stats to display), and Slate is updated when the backing state object is updated.
To hopefully be a little clearer, I come from the SwiftUI world of iOS. Here is an example of how they solve this:
struct PlayButton: View {
// Source of truth state
@State private var isPlaying: Bool = false
// body function is basically Construct()
var body: some View {
Button(
// This is a TextLabel for the button.
// It creates a dependency implicitly on the isPlaying state variable
// When isPlaying is changed, the UI will update the text of this button
// This is *not* checked every frame, it's only done when the backing @State field is updated.
isPlaying ? "Pause" : "Play"
) {
// This is an onClick lambda for isPlaying = !isPlaying
// This updates the @State variable, triggering the text field update.
isPlaying.toggle()
}
}
}
Not sure slate has something like that. UMG is getting MVVM support soonish though
You can definitely do that sort of thing, but, as you mentioned, it is polled every tick. It's not fantastic.
But it's okay if you keep it to a minimum.
Much like putting everything on tick in actors is generally bad.
It's not the best design choice, it's a quick and dirty one.
Unless you know something is changing every tick, of course.
I'm trying to use the old IDetailCategoryBuilder.AddWidget but seems like that's gone from 5.0 and the documentation isn't up to date. https://docs.unrealengine.com/5.0/en-US/details-panel-customization-in-unreal-engine/
I want to add an IDetailsView to a given category but I'm not sure how to. What would be the updated method?
You want to nest a details panel without a details panel?
I’m trying to create a SDockingArea that can contain spawned tabs. I’m unsure how to position the SDockingArea in slate and then add tabs to it.
My overall goal is to have tabs that I can put under a file menu.
I'm having the strangest bug right now regarding CommonUI's AnalogSlider. Wondering if there are any threads I can pull at.
The bug in question is that I cannot seem to navigate away from them using analog stick, but only in one specific hierarchy of widgets. DPad navigation works perfectly fine.
I've moved the exact sliders to a new set of parents and they work fine.
I've put new sliders into the bad area and they also fail to navigate away from.
SSliders are fine. I would use them except they don't handle analog selection easily.
No other widgets in this view have a single nav problem with analog stick.
Bad hierarchy of widgets causing the problem have no analog overrides being used anywhere.
In regards to this. They messed up nav movement in some cases in SAnalogSlider::OnAnalogValueChanged. They overrode SWidget's version and never called SWidget::OnAnalogValueChanged, and never handled that case in their override.
Hey folks,
I'm looking into the FComponentReferenceCustomization to see if I can make a variant that lets you pick a component from the blueprint you're editing, but I can't seem to find where the customization determines what options you can pick from. Can anyone point me in the right direction?
