#slate
1 messages · Page 10 of 1
i'm just curious why you used ISettingsModule instead of UDeveloperSettings 😄
i heard UDeveloperSettings had portability issues and doesnt package correctly for plugins.
im trying to make a purely settings-based setting, it has no details panel, so i cant use that method
thats a details panel?
yup
............ive made a continuous lapse of judgement
Meh, Unreal is a journey 🙂
i thought the details panel was only in the editor itself, when referencing an object
like the outside widget
It's used in many places, every class that doesn't have a custom editor, in many places the editor uses the details customizations combined with details viewers widgets to create 'selection' panels (like the main editor's selection, just shows you actor's details).
Generally if you have a window that gets populated by 'UPROPERTY(EditAnywhere/VisibleAnywhere)' that's a details panel
damn ok. that opens up a lot of possibilities
ive been banging my head against this for days.
thanks for giving me a direction to work towards mate!!
np.
do you know how im able to integrate that into my current window? do i instantiate it somehow within my object, or maybe in the module registration? im not sure how to register 2 things in the same settings category or whatever, im not sure its possible
You need to register the details customization class in an editor module's InitModule, in this case the customized class should be the Settings class itself, it is a UObject after all, as I wrote earlier the custom widgets and categories you add are appended to the categories/properties that are specified as UPROPERTIES in the UObject
And then stuff like this:
In the startup module -
So you can extend an existing category, and the such
End result can be something like this -
combining uproperties and ufunctions as well as custom widgets
wowow
In another project I actually went a little crazy and spawned a thread for the details class so that it could animate
ok so i have to replace this then? ISettingsModule doesnt seem the way to go?
I... don't know if there's a conflict here, I'm pretty sure the settings just shows the object's current details, ergo you can extend them normally
hmm ok. there is a lot to think about here and a lot to go through.
its too late for thinking about this.
thank you so much for your help, and this git link. i hope you dont mind i take a look over it. i will work on this more tomorrow
But I also don't think you actually need to register a settings class, I think they auto register
This one is in a runtime module, I don't register it but it appears in my project settings just fine
Of course adding IDetailsCustomizations on the other hand must be in an editor module, cause the actual details view is an editor thing
interesting. thats the UDevsettings.
i heard that doesnt package well, but maybe i heard wrong?
Settings can expose variables that need to be accessible in runtime, after all
wait actually
well dang it's a darn good thing the engine doesn't use it in a couple hundred places then including core things like the renderer settings... oh wait
i heard UDeveloperPlatform iddnt package well
😄
im very tired tbh
I don't know, all the configs you package are a bit weird and slightly mysterious to me, I think you're just meant to point your 'filterplugin.ini' at them or something, my plugin is not on my marketplace
man, if only my hours and hours of googling and trying to look through source code actually told me any of this stuff.
and chatGPT just lies to me
one big nuisance of this is that you can't store ini configs in a plugin for a UDeveloperSettings... idk if manually registering a class does any different though, i would expect not.
well, my current setup can use configs
in practice usually not a big deal, but if someone actually needs that, it's bleh
I think ChatGPT is generally not great for unreal and particularly useless for Slate/Editor-Customizations cause the sources it's drawing from are largely just outdated forums posts
idk if i care about configs. i can do some save logic myself if i rly have to
I think Co-pilot works quite well, it copy/paste/replaces slate declarations quite competently
I'm pretty sure that the problems with the configs occur when you want to override the settings of your plugin via an .ini in a packaging of the plugin, if someone packages your plugin in a project the configs will go in the DefaultEngine/DefaultGame or wherever and it'll be fine
AND really - just correct the defaults for your plugin in the UDevSettings class
ic. chatGPT kept telling me to use methods that simply didnt exist for the classes it used in its example code, and when i told it that it didnt exist it gave me a slightly revised code with another class method that doesnt exist, and then it just did those 2 replies in an endless loop
oh ic, thats no problem then
Looking for similar usages in the editor code is the way, and if they're hard to parse look for 3rd party plugins because they'll usually be implemented in much less elegant yet easier to comprehend manner
There are also some decent tutorials on these subjects, but usually they only get you to the 'bare bones' - 'now you have this class' level of things
Personally my DAWSettings class is adapted from the engine's MetasoundSettings class
i had looked through a few. most just made it entirely through SWidgets, or never interacted with the editorpreferences/project settings
People don't usually put custom widgets in the settings pages, it's a pretty esoteric thing you're doing
from what I can tell
which of course doesn't help in finding examples
yeah its been rough
i thought this would be a small little plugin. take a few days.
its been a week and a half of depression
doesnt help that i only started learning unreal engine like a month ago
Meh sorry if I come off as a motivational speaker but I actually believe that if you're asking questions that don't have obvious tutorial level answers it generally means you're on the right track
idk, i need that motivation right now! thanks mate
yeah a month is rough, I've only been using unreal for like a year and a half and knew 0 c++ before I started making my plugin thingie (the learning journey is definitely reflected in the codebase) but really I think confronting the engine source head's on is probably the best way to get 'deep unreal knowledge', you're not just learning how to achieve specific outcomes with tutorials, you actually get a good glimpse at how the editor works and where the various building blocks go and how Epic are doing things
Epic made the beast I just add fluff on top of it
well imma go to bed. thanks so much for the help dude, ill actually start in on this sometime tomorrow, or the next day if im too beat.
if i have more questions i hope i can bug you then!
trying to dive into the c++ for a widget in the windows tab up top left. Using the widget reflector I get the location for it but when I try to access it I get this field notification. If I click the root window or the selected SEnvironmentLightingViewer.
Even trying to search for it within VS itself proves nothing. Has anyone seen this before? for context this is a launcher version of Unreal not a source built version. Could the actual data be hidden to non source builds?
nevermind a more thourough search using similar keywords brought me to where I needed to be. but still confused on the field notify error
That's where the file was on the machine that built the editor.
Okay good to know, I assume all other absolute paths will behave in the same way then?
All the ones from the widget reflector, probably, yes.
right now im able to get a setting section ptr because RegisterSettings() returns it, and i need that ptr. i cant find another way to access the section itself without that.
any ideas?
well nvm i can just put it in a class variable
Using this i was able to decide where my setting actually showed up in the ISettingsModule. with the autoregistration of the UDeveloperSettings class, it doesnt seem to let you choose, and i also cant figure out how to move it myself. im pretty lost
tell me your secrets great wizard
You can specify the type by using the Config = ... in the UCLASS and then in the constructor of the UDeveloperSettings, you can set things like Category and such.
CategoryName = "...";
SectionName = "...";```
nah been trying that. config= is very limited as far as i know. it only decides where the settings are saved to, not where the actual module ends up.
category options are also limited. without using ISettingsSections::Register() i have no way to get the pointer to the actual settings. i cant move my module to the Editor Preferences page for example.
Instead of being in the project settings?
right
If you want some settings in the project and some in the editor, you'd want 2 classes?
Then that'd be one of the Config = ... options.
i cant do much more than this
i have no way to change the CategoryName beyond description
So which Config options did you try to get it into the editor settings?
i dont think that affects where it goes, but im currently using this. it makes a new section in the default.ini file
and i was told capitalization didnt matter
but i could try caps?
k
FName UDeveloperSettings::GetContainerName() const
{
static const FName ProjectName(TEXT("Project"));
static const FName EditorName(TEXT("Editor"));
static const FName EditorSettingsName(TEXT("EditorSettings"));
static const FName EditorPerProjectUserSettingsName(TEXT("EditorPerProjectUserSettings"));
FName ConfigName = GetClass()->ClassConfigName;
if ( ConfigName == EditorSettingsName || ConfigName == EditorPerProjectUserSettingsName )
{
return EditorName;
}
return ProjectName;
}```
another thing im trying to do is get the Module somehow, but ive not managed to do that
We use EditorPerProjectUserSettings pretty much everywhere and it gets put into editor settings.
mm. i had not wanted to use that because my program is meant to be global, but i guess it wouldnt rly matter where it was since the effects of it are global regardless. it would reset the FFields if they opened it in another project tho
i will try that
iiiiiinteresting. ok
so that works
i didnt know the config options changed where it went
@grave hatch thanks for that help!! do you happen to know how to get a module pointer to the EditorSettings?
Np. Why?
also, before i was using this to rebind the Reset to Defaults button, but i cant find out how to get the settingsections ptr without the RegisterSettings
You probably can't.
ive been seeing a lot of different ways to do different things, and none quite fit my exact needs but im hoping to make it work for what i need
for example, someone did stuff like this and ive been trying to make it work for the Settings module
so i can manipulate it a bit more freely
but i cant figure out the F{whatever}Module name for Settings
Yeah, you can modify teh sections, but section buttons don't appear in the settings tabs.
Only in the details panel.
ic
Do you specifically want to change the reset to default?
either that, or i want to make my own. im only even using the UDeveloperSettings class because i was told i can use IDetailCustomization to add custom buttons to the EditorSettings module i make, though i havent looked into that yet.
my workaround when i was using a UObject inhereted class was to use hijack the reset to defaults button
alright! guess ill finally get started figuring out how i can figure that out.
unreal engine is painful tbh
thanks for your help dude!
Np
ok so, sry to be like this but for some reason i cant just let it go even tho it rly doesnt matter....
i still cant figure out how to make a customized and new section for this, like i can with my other UObject.
Did you sent the CategoryName to "EditorFontSettings" or whatever?
there is no setter i can call
i feel like such a fool. you had told me this before and i tried it, but i made a new variable instead of just setting the Super variable and i didnt consider that for some reason.
amazing
🙂
once again, thank you for your help and your patience with my dumb-ass
No worries.
welp im just as lost as before on how to use DetailCustomization to alter my settings. every example ive seen uses the PropertyEditor module and RegisterCustomPropertyTypeLayout() to customize it.
i cant find any examples of people directly adding SWidget things directly to the EditorSettings/ProjectSettings
there is this override in the UDeveloperSettings class, but i cant find any information on how to use it
i think i might give up
You don't add things directly to the settings.
You customise the class or property layout.
(using a details customisation)
A class customisation lets you control how the properties of a class are laid out. The property customisation lets you control how a property of a specific type is displayed.
They may not be the exact names, but you get the idea.
from everything i can see, the settings pages are a different kind of widget and dont have that kind of customization. i cant edit the properties of it
i cant access the property module for example, and have no way to register independent sections or child categories
Did you register a customisation for your settings class?
have you followed any tutorial to just make a normal details customization yet for any class blueprint? because that's what you should have been doing
I can't figure out how. All the things I've seen use the Property module, register a new category for it, and then extend that
I have not, but I am not attempting to make anything that has functionality in the graph or viewport or anything. I have looked at some of these tutorials tho and they use aspects of the code I'm not working with to make it function
You'll want to be using the property editor module.
Is this another one of those things I'm thinking about incorrectly? From all my research it looks to me like the Property module is specific to the details panel
RegisterCustomClassLayout, RegisterCustomPropertyTypeLayout and RegisterPropertyHandleLayoutOverride probably.
Right I did see those
What do you actually want to do?
Not "customise the settings page"
I mean specifics.
Add a custom button to my plugin's settings area in the Editor Preferences
And maybe add some other things, but I'll start with a button
The reason why we keep repeatedly telling you to make a details panel customization is because you're trying to customize a details panel
i get that, but it has no Property Module
What has no module?
You don't need a details customisation to add a button.
Assuming it works like a normal details panel
Add: cpp UFUNCTION(CallInEditor, Category = "Fonts") void SomeFunction(); and it will add a button called SomeFunction to your settings.
It won't be on the same line / in the position you have specified, but that isn't really necessary. This is 100x easier than writing a details customisation.
Doubt that will work since that specifier doesn't work on CDO's/blueprints but maybe
Doesn't satisfy their future goal anyway
Though they may prefer a property type customization for that future goal of row buttons
Sometimes things are not possible, maybe DevSettings can't be extended, it has some quirks, the way to find out is to implement the parts that do work in the context in which they work and then testing them in the new context, I believe.
I spent over a day one trying to get the user set ranges on metasound input variables only to find they're hidden from me behind two private headers, spent another try trying to figure out if I can extend the Sequencer's timeline, I couldn't
well i tried this and it didnt work
no button appeared
idk, it's not like anyone really has fully enyclopedic knowledge of the engine
some things just can't be done without editor source changes and unless someone tried this specific thing and can tell you not to bother it might just be a deadend you're gonna run into on your own
Some details views just don't support certain things. Apparently CallInEditor is not on the settings tabs. 😦
There is one with a complete knowledge. A total git, though.
is it a repo pun?
It is.
nice
BUT like, DevSettings should be able to display property customizations I'd think? because they sometimes have curves and other fancy widgets I think? like how do they get that without property customizations? even if the DETAILS can't be edited making some custom struct with a custom property customization can get you to the point of a text field and a button probably?
the widget reflector can potentially help here
ive looked through the widget reflector. its all categorized as normal SWidget stuff
but its created through different processes
Yeah. It should. It doesn't mean it supports all things, though, like CallInEditor functions, apparently.
you can't see any SSinglePropertyViewer or or something like?
I don't believe that at all.
from what
In the widget tree for the settings pages.
SDetailSingleItemRow
that's the guy
i mean, you're not going to see in this tree exactly where it gets invoked cause the whole widget is build by well, some variant or the details builder, but the detail single item for a given data type is well, a property viewer, which, you can create somehow
I only extended the details view never a single property, I'd assume that there are some custom property customizations registered in the engine source code
details customizations are all over the place
Every single row of the page is a property customization
The panel containing all of those rows is a details customization
I mean, it is possible that the UDevSettings details customizations is created differently by the engine and that it has certain restrictions, like if it doesn't allow 'CallInEditor' it might have other things going, no idea, but I think it's also possible that it works just fine and that things are just not registered properly and that it might be good a idea to test in the normal UObject with custom details use case you can find multiple tutorials for
It's really just like, 30-40 lines of code to test at the end of the day
ill give it a shot
It's definitely got a load of details view widgets in the settings pages.
rly doesnt help that the docs lie to me. this is not a class. i think it means DetailLayoutBuilder
probably just outdated?
I sent you the link to my details customization two days ago or something, you're really just a couple of copy paste deletes from running it in your editor module
I even sent you a screenshot to the registration line and all
Like I know it might appear conceited to link to my shitty code but 1. I load that repo every day and it works 2. I can answer questions about it rather specifically, it was supposed to be helpful 😦
it has a lot of stuff that is particular to your project, and i dont rly like just taking the code wholesale and using it that way, id prefer trying to understand how things are working
whatever ill just take it all and retrofit to my needs
taking something that works and stripping everything you don't need out of it is part of understanding what you do need
but yeah the IDetailCustomization class is used many times in the engine, the usage pattern is the same in my class as it is an engine classes
you register the class, you declare the supported type, you build a widget in the CustomizeDetails method
doing these three things and sticking an SNew(STextBlock).Text(INVTEXT("Hello World!")) is where it starts
The statement is correct...
It's IDetailLayoutBuilder
Ooh the name.
where does CustomizeDetails() get called?
By the details view somewhere, I expect.
alright
My preferred answer is "magic"
what "section" am i looking for. i dont even know the name of it. i tried EditorSettings because thats what goes in the config= part of the UCLASS and seems to alter where the class shows up, but it didnt work.
wait i got them backwards
well neither works
A "section" is the blue buttons you see on the details panel.
i forgot to call this function
I don't believe they are available in the settings windows.
.................................................amir told me i should copy his code
The correct bits.
ok well following his code doesnt work for me because its all based on this
His code isn't doing what you think it's doing.
i dont think its doing anything because im not convinced any of this shit works in the settings window
I haven't seen him paste any code.
he gave me his github earlier
maybe i need this?
idk what the detail view id be looking for tho
No
I told you what you needed to do earlier and you've basically not done any of it. Or even attempted it.
So shrug.
ive done the RegisterCustomClassLayout, its part of his code. i tried to do the UFUCTION(CallInEditor) thing you said. you havent actually given me any further advice
Yeah, that part didn't work. The CallInEditor thing.
But you need to create a class to send a creation delegate to RegisterCustomClassLayout.
i use the UDeveloperSettings class for that no?
i mean, the property editor section stuff doesnt work i guess
Delete this bit. It is not needed.
alright
ok so how do i construct a button in the CustomizeDetails() function without anything to put it in
"without anything to put it in?"
You use the customise details function to customise the details :/
It gives you all the context you need.
virtual void CustomizeDetails( IDetailLayoutBuilder& DetailBuilder ) = 0; you override this.
i need some access to the things that are already there no? like if i just do SNew(TextBox) a new textbox will appear?
You get the category from the builder, then the property from the category, tehn edit the property. Something like that.
Extending this with slate widgets might be easier if you have some basic slate knowledge
honestly like if looking at my customize details method doesn't 'ring any bells' for you it's likely that you lack some basic slate syntax context
Or you get the prperty row directly from the layout builder actually.
virtual IDetailPropertyRow* EditDefaultProperty(TSharedPtr<IPropertyHandle> InPropertyHandle) = 0; with this.
well right now im mostly trying to see if i can just get anything to change the settings page
that didnt work, but maybe SNew() is better
yeah its not making anything new
There's nothing in the vertical box.
Though maybe that won't matter.
Did you add a breakpoint to your customisation to see if it's being called?
Is the registering code being called?
Are you sure you have the name right?
It's not meant to be "DevEditor" without the U?
You should look at how other classes have registered their layouts.
i think so?
hmm seems people leave out the U
ill try that
ok started up the same, but when i went to click on "Edit" to open settings it triggered the other breakpoints, so now its definitely being triggered
a mysterious thing appeared
fuck me
thats a good sign
once again, thank you for your patience and your continued heaven-sent help
good night mate.
its able to read my properties, but idk why im getting null for the rows
imma take a break tho
hah, so it is a details viewer and it can be extended, I feel vindicated, I would have felt bad if I sent you on a wild goose chase 😄
You were totally right my dude, and I do appreciate your help. I'm just not very smart and couldn't put the pieces together without some additional hand-holding.
All the tutorial on the issue and your code as well, they start with things that work for me and quickly go in a direction I'm not working towards, and its rly hard for me to know which parts work when the end result is so different
Hi there, Is there any possibility that I can create second window and set it a UMG widget that I created in Editor?
Sounds like a blutility widget?
but it is usually for editor stuff
I want to create it for runtime to make an external debug window
sounds about right, it's from a while ago and maybe some methods changed but I think creating a slate window is probably the same
that is exactly what I need
thanks
I ve already did similar but I created it via ActorComponent 😄 I know sounds like weird but no idea how can I do directly in Widget
or slate
I know you asked for a window but having a custom widget debug overlay thingie is a thing people do rather frequently and there are multiple guides on how to do it and multiple engine examples
did you create a window with an actor component?
yes
for testing purposes
but I need to know the best practice I know some people also creates in Slates but I need to set a UMG that I created via editor
Uhm, I mean, perhaps you can probably create the widgets and window from anywhere, if you have a window it probably has some root content widget, if you have some code that already opens up a window you can just run it from somewhere else? I mean, I don't know actually know what you're making or what's wrong with the current implementation, invoking the new window is done with a static function, it really can be called from anywhere in the code.
Happened to find myself wanting to test some window spawning on my own and basically just wound up doing what that thread said, it's really quite straight forward, you can call it from anywhere and you can populate your window with slate as per usual -
.AutoCenter(EAutoCenter::None)
.Title(FText::FromString(TEXT("Control Window")))
.IsInitiallyMaximized(false)
.ScreenPosition(FVector2D(0, 0))
.ClientSize(FVector2D(500, 800))
.CreateTitleBar(true)
.SizingRule(ESizingRule::UserSized)
.SupportsMaximize(false)
.SupportsMinimize(true)
.HasCloseButton(true);
FSlateApplication& SlateApp = FSlateApplication::Get();
SlateApp.AddWindow(PerformanceWindow.ToSharedRef(), true);
PerformanceWindow->SetContent(
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.Text(FText::FromString(TEXT("Close Window")))
.OnClicked_Lambda([this]() -> FReply {
PerformanceWindow->RequestDestroyWindow();
return FReply::Handled();
})
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.Text(FText::FromString(TEXT("Test Button")))
.OnClicked_Lambda([]() -> FReply {
UE_LOG(LogTemp, Warning, TEXT("Button Clicked"));
return FReply::Handled();
})
]
);
no issue opening the window either from game or editor, it seems, I guess it's just an editor widget with a few extra steps in a way?
though the fact that you can invoke it from in-game is kinda useful, I guess.
I'm feeling so stupid, I'm trying to use this window to stick a UMG widget in it, and if I pass in a UUserWidget* to the window creation method I can 'TakeWidget()' from this widget and it works perfectly, but for the life of my I can't figure out how to take the widget's BP referene path and spawn it from there, like I can only 'make it work' if I use the 'create widget' node in BP. Annoying.
can you call 'create widget' in c++?
Is slate still used? iIt seems very performance intense.
literally everything you've ever looked at is all running on slate
[more or less]
[[assuming that unreal is the only thing you've ever looked at]]
That's a good question
I figured if you can, then you can access it that way, or maybe make a child class of whatever calls it so you have access to it
But I also know blueprint classes are .uasset or something, and I haven't looked into modifying them from an editor
a CreateWidget method exists, but when I try to load the class like this the Widget is null -
Do the same for this very widget in BP and pass it as a parameter and it works
So, maybe it's the lack of world, maybe it's the path resolution... I am not sure, also the 'CreateWidget' BP node is a k2 node so double clicking doesn't take you to the definition
One of those things you go "meh, so just expose it as a parameter, create the widget in BP, who cares" and the other side of your brain goes "I will not stand for that!!!!"
LoadClass, is that what I'm looking for here?
well... yes, but also no, not for anything you would ever use in finished code
I mean, that screenshot is from the UMovieRenderPipeline code?
if "all" you're using UE for is rendering movies then i suppose you could probably cut some shortcuts without getting assbited
Right now it's still returning a nullptr for the widget so it doesn't work for me but what I mean is that that's an implementation from an Epic plugin, what's wrong with it?
They load the DefaultPreviewWidgetAsset from an FString path
it's hardcoding asset paths in code
it's hiding assets from the editor's cook/packaging process
none of this matters if you aren't packaging a game though
(and it's a sync blocking load - also no matter for any non-game usage)
I'm trying to find a solution for a bit of a hybrid usecase, this guy made a synthesizer instruments you can play inside unreal, and he made a fancy UserWidget in UMG but he drew this widget on the viewport and this kinda limits the ability to actually play it while other things are happening in game or to preview/create-presets for it when in the editor; I figured it can be cool to create a 'control window', so, like, it'd be nice if it works in a packaged game as well.
But right now I still can't actually construct the widget from c++, can only 'CreateWidget' in BP and pass the UUserWidget pointer to c++, CreateWidget in c++ just gives me a nullptr.
Also taking this opportunity to figure out nice ways to combine UMG widgets into my own hierarchies, like an easy way for users to create custom nodes in my custom graph editor, and stuff like that, I guess.
you would use a UPROPERTY to assign the widget class to make it packageable and avoid headaches figuring out manual asset paths
in case your manual path is just 'incorrect' causing it to fail
I might do that, right now I have all the functionality in a subsystem but I might change that.
Well yeah, that WidgetClass variable is null... I guess I can't blame CreateWidget in this scenario.
Yeah I'm having something wrong with the path, I can CreateWidget just fine from the GetClass() of the 'InWidget'
Ok well, seems like this largely only interests me but after comparing my code to the epic code I finally found the difference in the class loading, you must add the "_C" at the end of the path, it seems - this works
took me three times to notice that the Epic path had that going.
Nice I guess.
congrats
does anyone have any advice on getting this to compile? SRichTextRuby is a child of SCompoundWidget. i can include any other info if this isn't enough.
Hey there, I'm trying to wrap a SVectorInputBox in a UMG component like this:
TSharedRef<SWidget> SlateWidget = SNew(SVectorInputBox)
.bColorAxisLabels(true)...
But my RebuildWidget() function fails an assertion when I drag my component onto a CanvasPanel. It "works" when I drag the component onto the component tree in the editor. It happens for any SNew() I return because of this:
if (!WidgetTree || !WidgetTree->RootWidget)
{
UE_LOG(LogTemp, Warning, TEXT("UCupcakeEditVector: WidgetTree or RootWidget is null before WidgetTree operation."));
return SNew(STextBlock).Text(FText::FromString("Invalid WidgetTree or RootWidget."));
}
For whatever reason WidgetTree->RootWidget throws an assertion error at if(RootWidget) here:
void UWidgetTree::ForEachWidget(TFunctionRef<void(UWidget*)> Predicate) const
{
// Start with the root widget.
if ( RootWidget )
{
Predicate(RootWidget);
ForWidgetAndChildren(RootWidget, Predicate);
}
Is there a better way? I feel like I'm either missing something obvious or hit a bug in plain sight 😦
Thanks for reading and any help!
LOL, RebuildWidget() :shake_fist_at_sky:
Rider's "AI Assist" says that the return from SNew macro is already a TSharedRef<> and can't be checked for validity. Returning the SNew() directly builds and runs for me.
thanks for taking a look! when i try returning that directly i get a different error.
SRichTextRuby is a class declared in RichTextBlockRubyDecorator.cpp.
i've included the RichTextBlockRubyDecorator.h in my .cpp for the widget and setup a forward declaration.
does SRichTextRuby need to be put in it's own .cpp and .h files or is there a way to work around it being part of another class?
Man I'm way out of my element. An "AI Assistant" has written most of my code so far. I haven't heard of the SRichRuby component. Does it need arguments to be instantiated? Can you instantiate a simpler component?
I've gotten slate to make a tab that holds a UMG widget, but that's the only thing I've gotten to work 😦
https://qiita.com/koorinonaka/items/34a47303e9d9c5393105
it's a pretty obscure thing. it's basically for making the smaller characters appear for japanese localizations.
this code is incomplete though, so i've been trying to fill in the gaps hahaha
slate is pretty intense so far lol
getting anything to display is a win
Ooof! That's tough. I like Chineese people, but Chineese code is always risky to me. It's hard enough to tell if an English git repo is complete or vaporware...
Have you asked the author? They wanted to share the code, maybe they'll be happy to have a fan base 🙂
that might be the next step. good call 🙂
Why can't my custom UUserWidget create a SNew(SVectorInputBox), but changing the base class to UContentWidget ?
UMG is just Slate for blueprints. If you use UMG, you're using Slate under the hood. (If you didn't get that from HoJo's reply.)
Note the _C at the end of this string and the missing _C on your code.
Alright. I was looking a trace and trying to find why things were so slow.
Named Events help a bunch don't they?
Shrug
If you're looking for UMG optimisation, #umg
Whatever you're doing, Slate will be faster than UMG, though, because UMG is combining Slate (already slow) with BP (even slower).
True. It's just so slow in my trace, I'm trying to find why.
If you use the widget reflector (debug -> tools -> widget reflector) and pick some widgets in your game viewport, it will show you which widgets are taking the most time (to render, at least)
(and only works in the editor/pie)
Actually I'm not even sure it works in pie.
Does someone have resources on how to "properly" use Style Sets?
I generally know how to Create a Style set and make it rely on Style Containers.
But my main problem is with updating it in editor runtime and on defaults.
Imagine i have Widget A, B, C and D in a diamond relationship. A requires B and C, B and C require each D. But B and C should also be usable independently.
I want to allow the style change for B, C and their depending D Widget. But A aswell should also allow the styling of its children.
But I also would be fine if they cant affect the style of their dependencies, but then I wonder why is there the SLATE_STYLE_ARGUMENT to begin with?
But most important is, that I can use the Slate Widget(s) in UWidget, view it in a UMG editor, and then change my Styling Settings there, and prefely only require a Recompile (if at all) to update the styling.
I know i could build one giant slate style struct and pass it to every widget, but that sounds rather bad. Idk...
Are there any resources on how to use style sets "effectively"? (when to use style sets, when to use style args, when to combine style structs and when to sepparate them)
If you're hitting a diamond problem, I would redesign your classes.
Only time you should really hit diamonds is possibly interfaces.
Afaik you can't update a style set at runtime. Perhaps you could add a button that re-runs the create method.
Unless you mean update teh style set that a widget uses, rather than the style set itself?
As for when to use style sets of individual settings? I would use individual settings until you've got a good layout and then only move them to style sets once you're happy. It all depends on your "style" 😂
As for styles themselves, I'd only really use a style if I was going to re-use a group of settings more than once. Shrug
Its not about the classes, its about the styling.
Where depending on the style choice you may want alter some stuff or not.
And when reusing the same Widget, you ultimatively end up with a Diamond at some point.
Mhm... bummer...
Well... My main problem is that if I use individual settings, I may create many duplicates, depending on how complex the UI becomes.
It seems that once you have a widget that you "reuse", its better to with style sets, but thats quite a bit annoying if there is no good way to "live-edit" style sets in the editor.
That's why I'm saying find something you're happy with and then move it to a style and style set.
Before you start copying it everywehere.
Hopefully you won't have to change that style much in the future.
I think you could if you trigger live coding and then had a function to re-run all the Set() methods in your style.
And then you'd have to recreate all your widgets.
But then you cant check if looks any good within the whole composition. You may be able to fine tune the reused button for one spot. But that style may not work for the larger UI. or well... as reusable widget. Which you cant check if you dont use the same style within a larger composition.
That, the UMG compile button already does.
Then you're good.
Well, you don't have to define styles in a style set. You can define them just in a random c++ method and live coding will reload that easily enough.
(well, it doesnt reload the sets, but I get that you reccomend to implement that my self as there seems to be no existing functionallity for that)
static FMyStyleSet& GetStyleSet() { static FMyStyleSet() Style ... stuff ... return &Style; }```
Not wanna force people doing styling mostly in UMG to now have to work with C++ code.
Well you're in the #slate channel. When you talk about style, you have to assume you're talking about c++ style sets.
You can also expose those styles to the editor using a developer settings class if you want to.
Yes? But we got USlateWidgetStyleContainerBase and FSlateGameResources to kinda allow Slate Style Set changes within UE Editor...
at least... most stuff you can find in the web about slate style sets, is about those
not about the hardcoded style sets that are mostly used by the engine it self
Most people don't really use slate for game stuff. 🙂
Except for base classes with named slots for logic, not actual widgets.
Well... ik... but the layouting and control over Widgets I have with Slate is just way better then UMG... creating complex UIs and layouts is a lot easier with slate than UMG. But styling is still something done best with direct visual feedback.
And Slate is even more performant (duh). UMG List View buckles with already just a few hundret entries. Slate rocks with thousands xD
Tell that to the details panel that can't get scrolling right.
If you have a widget that is higher than the details view itself, the scrollbar spazzes out.
idk... i just know that in most UIs I've made so far, Slate was usually the better choice. Until you have to animate something. But I dont have that requirement anyway, so only left is a better way to do styling with live feedback.
Oh
What you could do is override PostEditChangeProperty in the container and re-run the setup on the style.
That should update the style whenever you make a change, as long as your styles are based on upropertys.
Every single property you want to cahnge would need to be a uproperty, though.
they already are anyway... since... otherwise they would not be showin in the editor where they can be changed
That is true.
I think I will create one container will a style struct that contains all other style structs independently, then let the style set load the game assets, then I "redirect" the individual style structs from the attributes within the "master style" to their own Set Properties and the container for that master style set has the PostEditChangeProperty thing...
to lazy to create a container for every single style struct
Sounds like a plan!
With the way style classes work isn't it always not a big deal to just organize things more like 'tags'? you can just have MyStyleSet.MyButtonStyle.VariantA and so on? Is there a downside to that?
i tried to do that, but that didnt work... I guess I just messed up something then xD
and cuz it didnt work I experimented with "adding them manually"
i was looking through stuff and i saw this, maybe there is an avenue here. i know you already solved the problem.
I am not sure what's the question, you want to spawn a UMG widget inside a new slate window?
if so, here's how I did it, I didn't use a GEditor call, instead the method expects a UObject to use for world context, so it can be invoked for any world - https://github.com/Amir-BK/MetaSoundsSynthRepo/blob/master/Source/MS1Performer/Private/PerformanceWindowManager.cpp
what component could be use to draw a line? ist there something like a spline?
Draw it where?
On a canvas for example
so basically I just want to draw a line from point a to point b
maybe even a bezier curve
there was no question, i was just pointing out something interesting i saw in passing and i remembered you were doing something that might have involved it
love it, thank you very much! 🙂
i learned how to live-update slate fonts so i dont have to restart my editor every time i want to see a change i made in my plugin
Live coding?
not that.
maybe live update was the wrong term. im able to refresh the fonts that the editor is using
Hey all. Should I use SVectorInputBox for an FVector2D property and is there a way to hide the Z value or is there another slate widget that’s more appropriate for them?
I think most of those things use the slider boxes, where dragging the mouse changes the value. I forget what it's called
I think if you add the property from your UClass through the CustomDetailRow.AddExternalObjectProperty or AddProperty it will choose the appropriate default styling, tho I'm mostly just guessing I haven't tried it
You could make 2 separate float properties that on change will update your float vector 2d
Maybe I'm wrong actually. I feel like if SVectorInputBox exists it should be able to have or remove the Z. Check all of its methods. Maybe there is a way to remove a slot, like for horizontal box you can do + HorizontalBox::Slot() to add a slot, maybe if you use a - you can subtract
Does it not detect when it's a 2d vector?
using SVectorInputBox = SNumericVectorInputBox<float, UE::Math::TVector<float>, 3>
Just change it to SNumericVectorInputBox with the different type and 2 instead of 3.
This dude is an absolute Chad. What an awesome repository for widget stuff. It seems a bit outdated tho, but it has a lot of stuff regardless
All information about UE is outdated tho lol
benUI has some stuff on widgets/slate but not a whole lot. Still some interesting information there
Yeah. @narrow terrace is the shit!
I still need to add more but I am curious about what is outdated, if you want you can make an issue ticket for me to address. We recently got greenlit for full production at work so I haven't had as much availability lately
Yeah we're usually just heads down on different things but usually pretty accessible
i didnt see, for example, the SVectorInputBox that firebugs mentioned earlier
Just don't expect immediate responses and don't expect a lot of one on one sort of thing.
understandable. i try to be considerate of people's time, and ill try not to bug you too much now that i know you are listening
and watching...
and waiting....
scary
Is that internally used for the engine stuff or common UI? I don't have time to cover common UI which I talk about in FAQ that nobody reads lol
I'm rarely watching, usually heads down lol
i have no idea, i just saw your git repo a few days ago, and in my attempt to be helpful i looked through it for the widget he was talking about
SVectorInputBox is a details panel class, though it's public.
is there a way to delay CustomizeDetails being called? im getting null pointers and im wondering if its because things havent loaded in yet
No
k
maybe you know the answer to my question. i have this UDeveloperSettings inherited class, and it has some default singleton properties on it that i want to edit the widgets for. they are not in a struct or an enum.
(ive already tried removing the edit condition and it didnt do anything)
no matter what ive tried, my Row variable always returns NULL pointers. the property handle is correct, and it prints the name out fine, but i cant figure out how to edit those properties.
got any ideas for how i would go about modifying those default properties?
Frankly I never mess with editor customization stuff, usually am living in runtime gameplay land. My assumption is that it would be an order of operations issue or incorrect widget class that its trying to create/get
i see.
i dont think its order of operations, i triple checked that. possibly incorrect widget class, but the function text for the EditDefaultProperty() should be able to find it correctly. unless its actually very specific about it needing to be in the details panel, which i am not working in.
almost all of this stuff says that its for the details panel, but that also includes the settings panel
oh my god i figured it out
and by i figured it out, i mean i finally managed to find how other people figured it out
instead of trying to access the widget row, you instead use AddProperty(). i had passed it over before because i already had a property, so it didnt make sense to me to add a new one, but apparently you add a property, and then CustomWidget() will overwrite the widget that was already there, and then you can resupply the name and value content
this took me so many hours to figure out
its starting to look awesome guys
man every time i hit record i run into bugs. for the most part my plugin works tho!! im super happy
idk why font swapping is not native to the program
oh i may be accidentally overwriting the path somewhere
I think my next project will be learning how to do slate styling.
Then I can actually make some in-game slate stuff
I should probably also add some boxes for the console font and debug log fonts, just for the sake of making it complete
@vale stump Talking of fonts, motion design (avalanche) has a system font loader/selector. There might be some helpful code there.
ill look into that. most of the other font tools ive seen only interact with UMG or Slate, but there is no easy code for changing the base fonts of the editor (that ive seen at least)
i activated motion design and im now bombarded with a bunch of new things im not used to!! the horror. maybe some other time ill take a look at it, what i have for fonts works for now
Oh I think I did see some of those files in my research. I don't recall them having the stuff I needed.
So it looks like rectangular widget bounds are very much hard coded into slate. Would the best way to get hittest's working properly on a widget spline just be a bunch of simple bounds widget for each segment?
I've got the spline widget that takes up a rectangle bounds between the min and max points of the spline with a sort of virtual hittest system for hovering but that means MouseEnter/MouseLeave events can't reach widgets occluded by the invisible rectangle.
There's a thing in teh engine called vertex tringulation. It will convert a list of border vertices into a set of triangles.
I would do a "am I in the rectangle?" test and then, if so, do a "am I over a triangle?" test.
virtual hovering
```for (int32 i = 0; i < WirePath.Num() - 1; ++i)
{
FVector2D Start = WirePath[i];
FVector2D End = WirePath[i + 1];
FVector2D ClosestPoint = FMath::ClosestPointOnSegment2D(MousePosition, Start, End);
float Distance = FVector2D::Distance(MousePosition, ClosestPoint);
if (Distance <= HoverThreshold)
{
bCurrentlyHovered = true;
break;
}
}```
Is this you trying to hover over just the line itself?
I thought you'd be hovering over the shape it defined, my mistake!
just the line. Though the shape would also have the same occlusion problem
say A wins the slate lottery and counts as higher up in the stack
Even though I'm only doing the hovering via that little virtual function up above. B line will never get the OnEnter/OnLeave events to do the virtual hovering because of the A bounds occluding it
You can use an input preprocessor if it's super important.
You get the option to intercept input before it's ever processed by Slate.
GridSpaceGeometry.AppendTransform(FSlateLayoutTransform(-GridWindowOrigin));
// Currently using grid offset because the grid covers all desktop space.
const FSlateRect BoundingRect = GridSpaceGeometry.GetRenderBoundingRect();
// Starting and ending cells covered by this widget.
const FIntPoint UpperLeftCell = GetCellCoordinate(BoundingRect.GetTopLeft());
const FIntPoint LowerRightCell = GetCellCoordinate(BoundingRect.GetBottomRight());
const int64 PrimarySort = (((int64)InBatchPriorityGroup << 32) | InLayerId);
bool bAddWidget = true;
if (int32* FoundIndex = WidgetMap.Find(InWidget))
{
FWidgetData& WidgetData = WidgetArray[*FoundIndex];
if (WidgetData.UpperLeftCell != UpperLeftCell || WidgetData.LowerRightCell != LowerRightCell)
{
// Need to be updated
RemoveWidget(InWidget);
}
else
{
// Only update
bAddWidget = false;
WidgetData.PrimarySort = PrimarySort;
WidgetData.SecondarySort = InSecondarySort;
WidgetData.UserIndex = CurrentUserIndex;
}
}
if (bAddWidget)
{
int32& WidgetIndex = WidgetMap.Add(InWidget);
WidgetIndex = WidgetArray.Emplace(const_cast<SWidget*>(InWidget)->AsShared(), UpperLeftCell, LowerRightCell, PrimarySort, InSecondarySort, CurrentUserIndex);
for (int32 XIndex = UpperLeftCell.X; XIndex <= LowerRightCell.X; ++XIndex)
{
for (int32 YIndex = UpperLeftCell.Y; YIndex <= LowerRightCell.Y; ++YIndex)
{
if (IsValidCellCoord(XIndex, YIndex))
{
CellAt(XIndex, YIndex).AddIndex(WidgetIndex);
}
}
}
}```
I've looked into the guts of slate and it doesn't seem like there is anything that can be overriden to get a different shape
An input preprocessor would work. I guess I would need to do this same sort of hittest grid to get it nice and performant.
but before that is it reasonable do to all that to avoid the UImage as bounding box segment method?
I expect to have a max of say 1000 of these splines in a canvaspanel each with 2-20 segments
I would do a broadphase search on their rectangular bounding boxes and then check individual lines.
Checking the bounds of 1000 square is entirely trivial.
works pretty good
{
LastMouseLocation = CanvasPanel->GetCachedGeometry().AbsoluteToLocal(InMouseEvent.GetScreenSpacePosition());
for (auto Child : CanvasPanel->GetAllChildren())
{
if (auto Spline = Cast<USplineWireWidget>(Child))
{
UCanvasPanelSlot* ComponentSlot = Cast<UCanvasPanelSlot>(Spline->Slot);
FVector2D ComponentSize = ComponentSlot->GetSize();
FVector2D ComponentPos = ComponentSlot->GetPosition();
FBox2D ComponentBox(ComponentPos, ComponentPos + ComponentSize);
if (ComponentBox.IsInside(LastMouseLocation))
{
Spline->CheckMouseHover(LastMouseLocation);
}
else if (Spline->GetHovered())
{
Spline->MouseLeft();
}
}
}```
{
SetVisibility(ESlateVisibility::Visible);
SetFocus();
}
else
{
SetVisibility(ESlateVisibility::HitTestInvisible);
HoverEnded();
}```
this bit actually allows me to keep the standard unreal tooltips working
I was expecting a race condition
I'm trying to make a local multiplayer UI, where in this screen each new player owns their own UI box. I have spawned the UI passing in the PC.
The issue is that the players are able to navigate towards widgets they don't own.
From debugging it seems that FHittestGrid::FindFocusableWidget it is not reading the player owner for widgets correctly. Does anyone have any idea how to fix this? Or am I missing something 🤔
I've created a UMG wrapper for a slate widget and I'm passing a array from the UMG wrapper to the slate widget.
But how could I tell the UMG widget or slate widget to redraw, so that the array elements would be updated.
What would be the appropriate way to handle that?
When you 'pass' the array, do it via some setter, set up some 'regenerate vertical box' method, call that.
@pallid gyro @grave hatch I think its done. everything seems to work finally, and its ready for use. if you guys want the plugin, HMU, and ill send you a free copy. Your help has been invaluable.
dont share it around tho, if i can figure out how to package and sell it i will. people have paid $5 for objectively dumber and simpler plugins
@vale stump and @grave hatch thanks for your help the other day regarding the type aliasing for the SNumericVectorInputBox. Sorry I didn’t see your replies until yesterday and forgot to reply. But it was very helpful!
I ended up doing something like that and it worked thanks! 🙂
I made a button to spawn a slate tab.
The first time I click it, it spawns the tab.
Clicking more and it brings the tab to focus.
But if I close the tab and click the button again, I see no tab. What am I missing?
void FCupcakeDebugProModule::StartupModule()
{
...
PluginCommands = MakeShareable(new FUICommandList);
PluginCommands->MapAction(
FCupcakeEditorCommands::Get().OpenPluginWindow,
FExecuteAction::CreateRaw(this, &FCupcakeDebugProModule::PluginButtonClicked),
FCanExecuteAction());
// Add that button to the Editor window
UToolMenus::RegisterStartupCallback(
FSimpleMulticastDelegate::FDelegate::CreateRaw(this, &FCupcakeDebugProModule::RegisterMenus));
// Register the tab spawner
FGlobalTabmanager::Get()->RegisterNomadTabSpawner(CupcakeDebugProTabName, FOnSpawnTab::CreateRaw(this, &FCupcakeDebugProModule::OnSpawnPluginTab))
.SetDisplayName(FText::FromString(TEXT("Cupcake Debug Pro")))
.SetAutoGenerateMenuEntry(true)
.SetMenuType(ETabSpawnerMenuType::Enabled);
...
}
void FCupcakeDebugProModule::PluginButtonClicked()
{
// Check if the tab is already open and valid
TSharedPtr<SDockTab> ExistingTab = FGlobalTabmanager::Get()->FindExistingLiveTab(CupcakeDebugProTabName);
if (ExistingTab.IsValid())
{
ExistingTab->ActivateInParent(ETabActivationCause::UserClickedOnTab);
UE_LOG(LogTemp, Log, TEXT("Cupcake Debug Pro Tab is already open and brought to the front."));
}
else
{
FGlobalTabmanager::Get()->TryInvokeTab(CupcakeDebugProTabName);
UE_LOG(LogTemp, Log, TEXT("Cupcake Debug Pro Tab was hidden or closed, showing it again."));
}
}
In the log:
LogTemp: Cupcake Debug Pro Tab was hidden or closed, showing it again.
LogTemp: Cupcake Debug Pro Tab is already open and brought to the front.
LogSlate: Window 'Cupcake Debug Pro' being destroyed
LogTemp: Cupcake Debug Pro Tab was hidden or closed, showing it again.
i think that when you close the tab it deconstructs and possibly unregisters.
TryInvokeTab seems like it probably deals with some exception that youre missing by not logging it. if it has an "OutReason" or some other parameter you should try printing that and see what the issue is
actually, your if statement checks the validity of the tab, so it reaching the else means it doesnt exist for you to open, but its not triggering a breakpoint because youre dealing with whatever exception is brought up
most likely you need to re-register the tab spawner
you should also add an UnregisterNomadTabSpawner() in its deconstructer
just to make sure youre not running into problems somewhere
Thank you, I'll try reregistering the spawner.
Hey guys, I'm trying to add a UMG UserWidget to a SlateCanvas, but I'm only seeing the Uswerwidget Text but not the button wrapping the text. I'm even seeing everything in the Widget Reflector.
How is this even possible? 😅
Use the widget reflector.
I'm doing that, and I'm seeing the button in there, but just the text is shown, also if I'm wrapping it with a border it is not shown just the text.
But is the border there in the reflector?
Yea also the button is there
It's probably some kind of issue how I add it to the Canvas, because adding the button in a UMG widget works fine.
yea no, this is just to position the widget in the canvas
I delete it to avoid confusion ^^
but maybe UUserWidget* NewWidget = CreateWidget<UUserWidget>(this, EntryWidgetClass); creating the Widget like that in the UMG wrapper is an issue?
Because I'm creating the widget in my UMG wrapper, because creating a UMG widget in a Slate widget didn't work and after thinking about it, also didn't feel right.
How could I check that?
Also if I try to select the button with the Picking tool from the Widget Reflector, I can't select it.
I went with this for a singleton tab. Thanks for the help!
void FCupcakeDebugProModule::PluginButtonClicked()
{
// Attempt to bring the tab to the foreground if it's already open
if (const TSharedPtr<SDockTab> ExistingTab = FGlobalTabmanager::Get()->FindExistingLiveTab(FTabId(CupcakeDebugProTabName)))
{
// The tab was successfully focused
// Bring the existing tab to the front
ExistingTab->DrawAttention();
FGlobalTabmanager::Get()->DrawAttention(ExistingTab.ToSharedRef());
return;
}
ReregisterTabSpawner();
FGlobalTabmanager::Get()->TryInvokeTab(CupcakeDebugProTabName);
}
Ok it appears to be an issue, where ihave to set the Size for the children I'm adding to the SCanvas, is there an option like "size to content" for SCanvas?
Glad my advice worked out for you!!
I think children have a Fill function of some sort. FillWidth() maybe?
Horizontal boxes have some Fill stuff. Try putting a horizontal box in the canvas and then the button in that
And then you can fiddle with both to get positioning and sizing correctly
I see you changed from NomadTab to a normal Tab. What's the difference here?
But I want to size it to the content not to fill the parent.
Use clamping
LOL, I'm using AI Assist in Rider to generate most of my code, and it's confused as sh** about Tabs. So I may be mixing two different API's. Here is the ReregisterTabSpawner()
void FCupcakeDebugProModule::ReregisterTabSpawner()
{
FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(CupcakeDebugProTabName);
// Register the tab spawner to persist in the system
FGlobalTabmanager::Get()->RegisterNomadTabSpawner(CupcakeDebugProTabName, FOnSpawnTab::CreateRaw(this, &FCupcakeDebugProModule::OnSpawnPluginTab))
.SetDisplayName(FText::FromString(TEXT("Cupcake Debug Pro")))
.SetTooltipText(FText::FromString(TEXT("Opens the Cupcake Debug Window")))
.SetGroup(WorkspaceMenu::GetMenuStructure().GetDeveloperToolsDebugCategory()) // Group it under Developer Tools or similar
.SetIcon(FSlateIcon(FCupcakeEditorStyle::GetStyleSetName(), "CupcakeDebugPro.OpenPluginWindow"));
}
Or set MinWidth or MinHeight for the button
Or the horizontal box you put it in
If the button doesn't have those methods the HorizontalBox definitely does
The issue for me currently is, I'm trying to add a widget like that to the canvas, i tried it without having a size set, but then only the text in the child widget appears and the button is completely cut of.
If you put it inside the horizontal box and make the button fill the parent, and then you change the size of the horizontal box, the button will change with it
But I want the child to be it's size not to fit the parents size 🙈
Listen to my words. Add a horizontal box between the canvas and the button
The buttons parent will be the box
Ok, but how is the Horizontal Boxs size definied? Because you said "change the size of the horizontal box" then I just move the issue to the horizontal box instead of the button directly. 😅
By design, the sizing is done in a wrapper. If you're not used to that, it can be very confusing. I haven't seen other component frameworks like it. You have the button fill the wrapper and size the wrapper. There's even a Size component I think for this.
Horizontal boxes have native width and height methods
Right now, your size method is affecting the canvas, not the button
I don't think so
Go with the flow bro, you got this
Just try putting in a horizontal box, add a horizontal box slot, use the .MinWidth() and .MinHeight() methods to set the size of it. Put the button inside that
Yea I'll do it, I also get that in most cases the childs will fit to the parent same as divs in html.
I'll probably just take a look at the UMG canvas how they did it 😅
In all the stuff I've seen that uses canvas, there is always a horizontal box, border, or other child inside of it that you then nest buttons or text into
Oh ic. You made your own method named ReregisterTabSpawner. And I had misread it earlier I thought it was RegisterTabSpawner
I'm about to embark on creating a slate style. Do any of you have any good resources or examples I can look at?
Can't test it right now because I was fixing other stuff, but it probably should be GetDesiredSize, thats how the UMG canvas does it 🙂
I wish I could help better. If I had that problem to solve, I'd wrangle the requirments with AI Assist or search github for examples. Voxel has a free plugin I sometimes use as a reference.
// Include necessary headers
#include "SlateBasics.h"
#include "SlateExtras.h"
// Define your style class
class FMySlateStyle
{
public:
static void Initialize();
static void Shutdown();
static TSharedPtr<class ISlateStyle> Get();
static FName GetStyleSetName();
private:
static TSharedPtr<class FSlateStyleSet> Create();
private:
static TSharedPtr<class FSlateStyleSet> StyleInstance;
};
#include "MySlateStyle.h"
TSharedPtr<FSlateStyleSet> FMySlateStyle::StyleInstance = nullptr;
void FMySlateStyle::Initialize()
{
if (!StyleInstance.IsValid())
{
StyleInstance = Create();
FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance);
}
}
void FMySlateStyle::Shutdown()
{
FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance);
ensure(StyleInstance.IsUnique());
StyleInstance.Reset();
}
FName FMySlateStyle::GetStyleSetName()
{
static FName StyleSetName(TEXT("MySlateStyle"));
return StyleSetName;
}
TSharedPtr<ISlateStyle> FMySlateStyle::Get()
{
return StyleInstance;
}
TSharedPtr<FSlateStyleSet> FMySlateStyle::Create()
{
TSharedPtr<FSlateStyleSet> Style = MakeShareable(new FSlateStyleSet("MySlateStyle"));
// Define your style here
Style->Set("MyCustomButton", FButtonStyle()
.SetNormal(FSlateBoxBrush("Path/to/normal/image", FVector2D(32, 32)))
.SetHovered(FSlateBoxBrush("Path/to/hovered/image", FVector2D(32, 32)))
.SetPressed(FSlateBoxBrush("Path/to/pressed/image", FVector2D(32, 32))));
// ... Add more styles as needed
return Style;
}
-- AI Assist
Well yeah I've seen how starship core style is made. It's just a huuuuge block of code for every aspect of it all in one function and it's pretty overwhelming so my brain forgot I had seen it
I can take a closer look and try not to die
There are other style set classes. 🙂
I find it hard to actually find examples in the engine that don't have a bunch of confusing macros (I am not very familiar with C++ so even tho I know what they do conceptually it's hard to read) and delegate stuff (absolutely lost)
Search for : public FSlateStyleSet in teh engine code and have a browse.
Alright I'll do that
Thanks for this. I do know how to make the class tho.
I guess the real issue I have is like....understanding the art aspect of it. I need texture assets and stuff to use as brushes.
And I don't know the first thing about any of that
Slate styles don't use imported assets generally. They use raw pngs or svgs.
What's an SVG
Scalable Vector Graphic. It's a web format for icons and graphics. Inkscape is a good editor and you can find lots of files online.
Instead of saving pixels, it saves a description of how to draw the shape. Lines, fills, etc.
So it can scale to any size. It is rendered to a texture at a specific size when used.
Instead of stretching, it'd be better to make images larger and shrink them.
If you need static images at different resolutions from a single image.
Does it scale in runtime or only at initialization or what not. Like if you make a drag scalable window will it match?
That depends on the component using it. SVG just draws in abstract space.
Here's a page with some examples. SVGs are just a UTF8 string
https://www.w3schools.com/graphics/svg_examples.asp
Ah ic
Does a convenient free help tool exist that lets you make shapes and draw stuff and it will create an SVG out of it based on what you draw?
Here is some AI generated code that may or may not work:
class FMyStyle
{
public:
static void Initialize()
{
if (!StyleSet.IsValid())
{
StyleSet = MakeShareable(new FSlateStyleSet("MyStyle"));
const FVector2D Icon64x64(64.0f, 64.0f);
StyleSet->SetContentRoot(FPaths::ProjectContentDir() / TEXT("Editor/Slate"));
// Load SVG into Slate Brush
StyleSet->Set("MyIcon", new FSlateVectorImageBrush(StyleSet->RootToContentDir(TEXT("MyIcon.svg")), Icon64x64));
FSlateStyleRegistry::RegisterSlateStyle(*StyleSet);
}
}
static const ISlateStyle& Get()
{
return *StyleSet;
}
static void Shutdown()
{
if (StyleSet.IsValid())
{
FSlateStyleRegistry::UnRegisterSlateStyle(*StyleSet);
ensure(StyleSet.IsUnique());
StyleSet.Reset();
}
}
private:
static TSharedPtr<FSlateStyleSet> StyleSet;
};
TSharedPtr<FSlateStyleSet> FMyStyle::StyleSet = nullptr;
void FMyModule::StartupModule()
{
FMyStyle::Initialize();
// Create Slate Icon
FSlateIcon MyIcon = FSlateIcon(FMyStyle::Get().GetStyleSetName(), "MyIcon");
// Use MyIcon wherever needed
}
Inkscape is the best I know of: https://inkscape.org/
Inkscape is professional vector graphics software which runs on Linux, Mac OS X and Windows desktop computers.
It's open source
Go team!
One last tip - https://thenounproject.com/ is a great source for reference art.
Noun Project has the most diverse collection of free icons and stock photos. Download SVG and PNG. Over 5 million art-quality icons and free photos.
oooh. thanks!
oh no....i just spent weeks making a font plugin, and ive encountered another bad font program!!
idk how to change the font on this either
this isnt just a problem with my monitor right? why are the lines of the font getting RBG colors
and its so blurry
That's a problem with your monitor.
And/or OS configuration.
I can see it in your screenshot, so it can't be a monitor issue.
If it's an os issue it would affect all my other programs right? I think everything else looks ok. It's just this inkscape program
And the unreal engine font was so bad I had to make that plugin to change it
It's might be a rendering issue with the program specifically, but it's not a font issue.
finally figured out how to change it a bit. i had to find the style sheet for the UI and add some code that changes the font family. its not accepting some fonts i have, but i guess this is still better
i rly shouldnt have to do this for every damn program i download. what the hell is wrong with these programmers!!!!
Hey, whats slate unit? im trying to set position relative to size of button somehow. I got % position of button. I just do not know how to get translation pos 😄
I want to move it after user click
If thats pixels i think i kmow what to do
waiiit. if that are pixels, why they are not named pixels? 😆
thats fishy
I think they are technically termed Slate Units. But I'm not sure there is a difference, it's just how they built the system to interpret pixels probably
It’s not guaranteed that a slate unit will represent a pixel as local widget geometries are affected by the transformations to the slate geometries they’re contained in
So a 100 unit long text block inside a 500 unit border will be different to a 100 unit text block in a 400 border?
Idk, there several types of geometry transformations that can be applied, there are layout transforms and render transforms, like being contained inside a scale box affects the internal widgets differently than being on a canvas
I know that when overriding on paint or mouse move events you have to pay attention to this and convert to the right ‘space’ to work on, there are helper functions for it
So if I drag an expandable box out, and check the dimensions of it, they won't have changed? I feel like a transformation also changes the units. You may set it at 100, but it won't be like that when rendered and messed with, and I think the pixels are still the same size probably.
Easy to test, just check the GetCachedSize vector on a given widget.
Personally I just trial and error this stuff until I get the behavior I want, the nice part is that it’s usually very obvious if you got the right geometry or not
Slate Units are a way for us to make UI that is independent of pixels ( more precisely: independent of the pixel density of your monitor). A brief motivation is needed: building a UI where you specify everything in pixels just wouldn’t work across multiple platforms these days. The size of a pixel and number of pixels packed into a a single squa...
This guy has a good explanation
but you were right
You did great mate, I just wasn't understanding
My fault for being dumb 😦
does user picks dpi? 😄
You can
DPI just affects image quality I think
in practice its like pixel density
I believe so, you are effectively calculating the relevant units per pixel when dividing the absolute space with the local space
Right, but changing the dpi won't scale anything I don't think
There is however a ready made method that does this for you
what method ?
Oh so you're saying the calculation might be more exact with higher DPI?
I think same as you. methods will just return other screen pos or widget scales, so I should not worry
Ah that absolute to local thing, you’re already using it I missed it
Having more dots might make your .000001 into a .000002
I have a piano roll widget and the user can zoom in and out vertically and horizontally independently, the local space geometry can be very different from the screen space geometry, I never worried about dpis and only used the provided absolute to local etc methods
one step closer ;d
Painting something under the mouse cursor and moving it around will let you know with utmost certainty if you got it right or not, really
Yeah just like that 🙂
Nice. Shapes!!
need to limit it to triangle now
and somehow reduce underlying button click visbility :d
There some intersects with methods in slate, at least for rectangles, I’d assume triangles are also handled somehow
are you supposed to be able to drag the dot?
ye, that would be cool
i think all you need to do for that would be hooking this up to an enhanced input and use the hold option
or the rapid trigger
so it looks like its being dragged
even tho its moving a pixel each micro-second
you can hook UMG up with enhanced inputs i think
especially because this is ingame
you definitely can
Btw the editor classes usually implement everything in the mouse move event using the isKeyDown and various getters you can get from the mouse event itself, it’s possible to do all the mouse interactions in one method without needing to create member variables for things like “is left mouse button down”
yeah you could just implement an enhanced input yourself
Also for events which can potentially end with the mouse outside the widget you need to return the ‘capture mouse’ option
I never used enhanced inputs with widgets idk, I think the philosophy is to leave the actual user interaction options down to the designer, if you use the slate mouse events they can be invoked with a widget interaction actor component, or by being placed in an existing widget hierarchy etc.
Whbat did you meant with that ?
For rectangles there’s an FRectangle struct and one of its methods is something like “is point inside rectangle “ I don’t really remember how it’s called, I am not next to visual studio now
I’m just saying look around those classes, there might be code that already does what you need
So you can’t drag
definitely switch to using some Focus methods and mouse captures
and such
and mouse events
Reread what I said about implementing everything in the mouse move event, it might be confusing now but it’ll make sense later, it is specifically relevant for dragging
oki
oh also if you want the drag to look nice, you could maybe see if you can implement some sort of non-snapping movement to it. like vector movement in blueprints has that "teleport" state and the other one that makes something move over a set duration
maybe you can find something like that
make the movement a bit smoother.
but make the duration really short so the image is still under your cursor
It doesn’t let you override? Anyway this is the slate channel I kind of assume people are overriding slate widgets, umg is just slate with a few extras so generally everything can be used but my replies might not make sense if you are not actually slating
and if your mouse is inside the bounds of the triangle
blue is button
that shouldnt matter
your mouse event can hit 2 things if you let it
I used button just, that it wont hit in game
if your mouse is inside the bounds of the rectangle, move the image. if your mouse clicks the button, the button is clicked
remove the button mate, and use mouse capture to make it so the mouse doesnt affect things in the game
you can focus the widget, and make it so the mouse is captured by the widget
mouse capture ?
yeah like, you know how when you start the viewport, your mouse can move around outside
but when you click on the viewport your mouse controls the character
well thats most annoying thing, that you have to click to activate widget / game
but how
i think i have an example lying around, tho i used enhanced input settings for it
one sec
is it bp? slate?
its bp, but you can do the same with slate
wtf. someone on my team broke the project i was working on. cant show you it in action lol.
THANK YOU for helping us achieve 150 subscribers! Learn how to attach a widget to your mouse cursor! Special thanks to one of my subscribers, n v, for suggesting this!
This is an Unreal Engine 5 tutorial (might work for UE4) about the three input modes, setting focus and isfocusable nodes, using override functions to capture keyboard input, and...
i think this will help 😄
kinda
here we go
basically just this
easily replicatable in C++
those 2 blue nodes are the capture functions
this is it's c++ code
why you got flipflop there? 😭
well I don't use enhanced input yet
you can replace enhanced input with any other input
its just an example. you can get mouse events in other ways
this method requires a player controller, which you should have
you can just call it directly on the player controller youre using
flip flop is for the 2 states of my UI. i have it so that when i click a button, it brings up an overlay, and it gives me back cursor control, which i can then use to click on UI elements
when i click the button again, the UI disappears and the cursor is captured by the Actor
😆 guys
I forget to mention
my mouse is always visible
I don't need to switch focus on enable disable widget, but rather on mouse move 🤔
but I got invisible button that does it for me
but I would like to integrate some gamepad controls later, so I probably need Enhanced input
that shouldnt rly affect anything. cursor visibility is not the issue, its cursor capture
but then I need to find click position myself 🤔
you already have that no?
you just need to check for the mouse being in the geometry of your triangle
and if it is, capture it
Nooo, I have used event of image component
............click position means the position of where you clicked
you already have that math working
and again, what youre clicking doesnt matter
what matters is that youre clicking in the space
its arbitrary
use a different event
a more global one
or create your own event
i think there are global delegates you can bind your widget to, so it reads the mouse event
and you can also make your own delegates
i quite don't follow you
the game is reading your mouse events. find where that is. its in many places. either your PlayerController, your level, or anything else.
take that event, and do some math. if your cursor is within the coordinates of your triangle, then call a method (you must make a method, call it OnDrag or something) of your own on your widget.
when that method is called, move the dot image to your cursor. the method will be called every tick, as long as your mouse is held down
when your mouse leaves the bounds of your triangle, turn off the method
do you want to add every single widget to do such thing ?
you can make a delegate if you like, that will call a similar method on every widget that binds to the delegate
delegates do not block input
but you can also use the same method for every widget you want
you can block input by just removing the mouse capture from your player controller
or you can set the capture on your canvas to be forced
so it steals the cursor inputs
anyway, i do have to go to bed. its very late
i hope you are able to make this work!!
im gonna re read thsi and re think later 😆 im clearly missing something
I really don't know why all of that would be neccesary, the widget will know where the cursor is in its relative space, the logic of actually checking whether the mouse is in a certain position in the relative space of the widget should take place in the widget itself, getting the mouse/cursor/pointer/vr-widget to actually interact with it is done using widget interaction components if the widget is in the world, if it's not in the world it is handled via being attached to the viewport and setting the UI input thingie on the player controller, I can see why you may want to have some 'show hud' action mapped as an enhanced input, if you actually need get to enhanced input actions inside the widget this is probably something you'd want to look at the Common UI plugin for cause this it is kind of set up for it.
And of course if it's an editor widget the mouse is also taken care of for you and there's an entire system (kinda confusing) that lets you define "chords" for editor keyboard inputs.
And really in common ui the use for enhanced input is for mapping things like d-pad navigation and universal confirm/cancel to specific buttons in the UI, I don't think using enhanced input for 'cursor manipulation' on a widget is ever neccesary.
There are convenient built in methods for doing things like mouse capture inside the widget's events, if your you reply with 'EventHandled.CaptureMouse(AsShared(this))' the mouse will be captured by the widget, for instance.
long question/topic - I posted in #enhanced-input-system but the more I google and test, the more it seems to be a slate related question.
I am trying to set up a screen for handling controller assignment for players. P1-P4 are able to press left/right and pick a side they want to play on. All their inputs register fine in my debug, but as soon as I add this User Widget to the viewport, none of their input callbacks work (the callbacks are set up in the gamemode, which I believe should go through regardless).
Currently, I have tried to set up some delegates to listen for inputs from all my controllers and then hook up the events inside of this User Widget. I also tried tapping into the EnhancedUserInput callbacks directly, but there's no way to get the controllerId that triggered the event so I've abandoned that (but it also didnt work).
What is unclear to me is the following:
-
User widgets have a function for SetOwningPlayer - is there only one focused player/user at a time? If so, what does that mean exactly? only that player's input is parsed? how would you handle parsing multiple player UI inputs? do you need to abstract them into some internal system which the UI just renders?
-
even if the latter solution of abstracting it into some other internal non-ui system works, I dont understand why adding this widget to the viewport disables all my player inputs? the project ive been referencing has a CommonActivatableWidget from CommonUI, which I don't really know enough about to come to any meaningful conclusion on - could that be blocking my inputs somehow? or is it Slate itself parsing inputs differently?
I realise im asking a lot so, if theres any clarification needed please let me know. This UI system seems quite invasive to me, but I also cant find meaningful documentation so its most likely my own lack of knowledge
Ok, I found the issue - my common UI came with a GetDesiredInputConfig and I had to override that to all. Hope this helps someone out there
Still having issues getting inputs from other players, but its a start
That's good to know.
I'm not telling him to use enhanced input tho, my example just happened to be using it.
I'm using enhanced input because I wanted to set up player-customizable mappings, and enhanced input has all that stuff worked out already. Why make my own tools when that exists you know.
I haven't checked out common ui either. I'll take a look at it
Also the important thing I was showing was how I'm capturing the mouse. His problem is that his mouse clicks are interacting with too much. It's going through the widget to affect thing behind it, so he put a button there to stop that. I was showing him that he doesn't need the button there, by using input captures
So, I'm trying to canibalize the unifnished code editor plugin inside unreal for my own purposes and overall it's clear I'm gonna have to fix a bunch of things and finish stuff epic never did but I'm happy, there's an annoying issue though, all of the regular 'editor actions' take precedence over the text editor window actions, so tab switches elements, the arrows don't move the cursor but rather navigate through the widget as well, etc etc, I can fix but intercepting the keyboard actions in the slate class, which I've already confirmed works with tab, but idk, am I really gonna have to do this for every action? I'm sure there's some setting I'm missing here, even ctrl+c/ctrl+v are seemingly ignored by the text editor, I'm sure this isn't the case with other text editors in the engine
(guess the answer is: I should go look at other text editors and see what's up with that)
but it's so fun to canibalize an unused experimental plugin instead of starting from scratch, it's already so cute -
What you're meant to do is have a local command list on the root widget.
Then you override all the mouse and key down events and check if that command list accepts them and return handled if so.
Then you set up your commands in that command list.
So like a TSharedPtr<FUICommandList> which you bind commands to.
I tried to capture tab like this and it didn't work but probably I didn't do it right. Will give it another spin.
It may be that tab is a processed before slate does it.
Before the normal key press flow, that is.
i made a material that i want to overlay on some buttons with slate. its a material with changeable values. how would i do that? do i need to somehow put the material into am SBrush? but then i dont think SBrushes have parameters
Create a MID of the material and assign it to a FSlateMaterialBrush
nice! thanks
I have a UObject, with a TArray<FCustomStruct>
I am attempting to pass this data to a slate list view, and be able to operate on the data and have the changes propogate back into the original TArray.
Im kind of new in the world of smart pointers, and trying to understand them, but it seems im doing something wrong, as when I change a variable inside the FCustomStruct in my SListView, i then attempt to print the value of that same entry on the original item, but it doesnt update.
First just checking to see that what im trying to do is possible or if its even the normal way of doing things...
I could easily pass in the UObject directly and do the manipulation on the struct members directly, but it seems like a lot of extra boilerplate code
Show code
Passing in a uobject and saving it is really extremely minimal code.
And you should probalby do this anyway so that the data doesn't get deleted out from under you.
TArray<TSharedPtr<FCustomStruct>> DisplayedItems
/* Turn out ptr array into shared pointers. */
for (const FCustomStruct& Item : *Items) {
DisplayedItems.Add(MakeShared<FCustomStruct>(Item));
}
This is some of it, sorry, just trying to make it more readable, got like 4 classes involved in this
Yes. That makes a new item it doesn't make a pointer to the original one.
Ah, is there a way to make a pointer to the original one safely? Is this just a bad way of doing things?
I needed to do something like like this and I ended up just making a struct which held the array index of the item in original array.
And then used the original UObject and array combined with the index in the struct to modify it.
(the original object and array were not changeable by me)
Ah, ok maybe im just making this too complicated. I just got excited about being able to go like..
RowContent->Boolean = true; // propogate back into the array
vs
UObject -> FindRowContentByPredicate -> Update the data there
Having 2 copies of the data is generally not a good idea.
Unless 1) the lookup for the data is extremely slow or 2) you want to confirm any changes made.
hm, dont i need copies of the data in order to display it in an SListView? As it requires the TSharedPtr<FStruct> instead of naked structs?
Hence the "have a struct with the array index in it" ?
Ok so thats all it contains is what you are saying?
Yes
Unless you can do just raw ints with the list view. Probably not.
Either way it's a stupid requirement.
Item type T must be a UObjectBase pointer, TFieldPath, TSharedRef, TSharedPtr or FName.
Technically you could use an FName but with different string indices to represent your index.
That'd be funny.
hm but how do I get the data to actually display in the list view, im new to anything outside of TObjectPtr 🙂
I make a TSharedPtr to a struct that has just the index of the array element, i get that... But then what do I give my SListView to display the details of my actual strcut
I pass it the UObject as well so i can look up the element?
You save a copy of the object to your slate widget and acccess the array contained in that object using the index from the struct.
TWeakObjectPtr<UYourObject> ObjectWithList;
You can add your uobject to your widget class's Construct (to make it a mandatory parameter) and then construct hte widget using SNew(SYourWidget, YourObjectWithList)
Example: void Construct(const FArguments& Args, UYourObject* InObjectWithList) { ObjectWithList = InObjectWithList; }
cool cool yea i think i get that
It's literally 3 lines
yea, passing the index in is a great idea in this case
If you had a Map instead of an Array, you could just use a list view based on FName and use the FName as the map key.
But you can't make a listview based on ints. Very annoying.
lol ironically i do, i thought it was making it easier by making it an array instead
and inside that construct function, id know the index of my element.. so when making subwidgets I would just go
ObjectWithList->ArrayProperty[RowContent.Index]; to find my struct data, and then use it to construct my various widgets based on the various properties same as before...
Im still learning about all the Ref/Ptr conversion methods. Could I store a ptr to the element in the array on construct?
FCustomStruct* Ptr = ObjectWithList->ArrayProperty[RowContent.Index];
Im sure my syntax is off there ^
And then when I change a checkbox in the slate widget, i could call Ptr->Bool = new bool;
If it's already a map with an fname as key, just make a list view with an fname base.
@woven gate Idk if this is helpful to you at all, but there is an inheritable class called IPropertyTypeCustomization that seems to be for the express purpose of modifying properties within structs and Enums. I believe that also includes accessing them, and changing how they are presented.
I haven't looked too deeply into it and idk if it's helpful for listview
You should give it a look and peruse some docs about it
Also if you want to loop over the items within a struct i think you can do that by accessing the property handles within it
oh man thanks that might be exactly what im looking for, i will look into it
First you have to get a pointer to the struct and then do something like
TArray<IPropertyHandle> props;
Struct.GetDefaultProperties(props) // I think this is an Out-parameter type function
for(TSharedPtr<IPropertyHandle> handle: props: ++handle)
Structs might have a GetChildProperties actually
Anyway, hope that helps
If you have a detail customization class, and you set the struct as a UPROPERTY() in your UObject, then you can access your UObject properties through GetContainer or something and then access the container's properties by name.
UPROPERTY()
FYourStruct* Struct;
And then you can fiddle with your struct that way, as a child of your object
Im not sure ive been going about my current project correctly.
Im trying to make a Slate/UWidget crossover type system, where a lot of the basics are created in C++ while still have it be interactable and customizable in blueprints.
Ive made a basic SlateStyleSet and WidgetStyle (though im not sure i need both or if im overcomplicating this), and im not sure how to bring that together with Widgets. should i use UUserWidget or SUserWidget, should i make everything in Slate with SCompoundWidgets or tie it into UMG with UWidget components?
also idk what a HUD is supposed to be, when all the "HUD"s ive seen are actually made with UMG or Slate. whats the point of this class?
could i do a double inheritence and combine them that way?
copilot suggests making SWidgets and wrapping them in custom UWidgets, which sounds like how it normally works so ill go with that
Anyway to unregister a slateuser from a UI? So it runs with no slateuser and stops interfering with the playercontroller inputs
Have you tried setting the input mode to game only?
^
You can read the earlier conversation i had with another guy about this. You just need to do the opposite
And then there is a blueprint example I showed for how to accomplish it there, and the same idea applies to C++
If you want mouse control to not be captured by the game, but still have UI elements that are clickable to not be clicked, there are a few options for that.
I think widgets have hit-testability, so you can mess with those.
You can also set a meta property for your widgets. If you put UPROPERTY(meta=(EditCondition, "MyBool")) and you flip that book to false, then the property under that macro will not be interactable
Idk if that syntax is correct
yes, it doesnt work
edit: all my player controllers have their input callbacks working correctly, except for user 2 who is the designated SlateUser in control of the menu
is this a splitscreen game or something?
yes local multiplayer
so is the problem that user1 is able to interact with the menu that user2 opens?
no, I have a menu where all users should be active - its controller assignment, every player can tap left or right to pick a side.
most of them work, except for player index 2 specifically, who happens to also be the slate user that gets assigned that user widget.
im not sure i know what a slate user is. why is only index 2 a slate user?
if you need a slate user to control the widgets, then you can make a non-player assigned player controller just for that
tho im not sure what it is or why you need it in the first place
I dont really know either, im just trying to determine what's blocking my inputs. my assumption is slate based on this documentation: https://github.com/YawLighthouse/UMG-Slate-Compendium?tab=readme-ov-file#100-input-framework-of-unreal-enginerelating-to-umgslate
i suspect that whatever user the SlateApplication selects, their input will be parsed thru that system and avoid my later handling of the input in PlayerController (which is what ive been doing to avoid the added complication of UE UI).
right now im trying to bind the controls to the individual controller widgets and each players focus to a separate one in the hopes that it will be more consistant. so one slateuser per controllericon
yeah, I have no control over index 2 - personally id rather not have any slate user in the first place since its hijacking my implementation. I cant really explain why it selects 2, but its consistent at 2 and up to 4 controllers
LogUIActionRouter: Display: [User 2] No focus target for leaf-most node [WBP_ControllerIcon_CUSTOM_85], and the widget isn't focusable - focusing the game viewport.
this print here made me suspect this SlateApplication layer, since they explicitly print the SlateUser index that owns the user widget element
have you tried accessing the ULocalPlayer that this doc talks about?
not really, ive been primarily looking at inputs
it also seems too low level to permit modifications (in the context of UE gamestate/instace)
it seems to me that instead of having no slate user, you need 1 for each controller. they independently track the focus of each player
yeah, I think that may be the solution here as well once you suggested it - im trying to set that up now
alright, hope it works out!
thank you v much
np
if you still run into problems, it may be because you dont actually have a second controller plugged in or some other external issue, where its not generating more slate users for you. you might have to find some way to make a slate user manually for testing
whats the correct way to give control of a widget to a particular playerIndex? I got them split up, but tapping left on P0 triggers all the widgets right now
- SetOwningPlayer
and - SetUserFocus
on a playerController don't seem to do the trick
fair enough - i suspect its something in CommonUI
nope, stuck differently now
ill try to sleep this off and maybe i can think of a solution tomorrow
Is it possible, to draw something like a bezier curve with slate, or do I have to implment that myself?
I think it's possible, though I don't have proof. I think I saw something about it somewhere.
FSlateDrawElement statics contain the commonly used slate drawing functions
i used to be able to paste screenshots from my clipboard into copilot, but they removed that feature for some reason. wtf
thats so stupid
also they decided to center justify everything and its fixed to a max width, so everything is cut off and i have to scroll side to side, even if i expand the window
do any of you know why my includes keep breaking, even tho nothing has changed regarding them when i built the project last?
using plain visual studio 2022?
yup
well... just normal behavior then
its rly annoying. i reload my project many times, and refresh the solution, i try rebuilds, and it sometimes doesnt work. then like half an hour later it suddenly comes back for no discernable reason. its hard to do error checking when everything shows up as an error
you have to buy resharper or rider.
I'm having an issue with Detail View
when the containing widget is created Detail View isn't drawn for a single frame. though the rest of my content is. Thuogh because DetailView doesn't have a size, all content is pushed up.
a frame later, and the detail view is drawn, and now my content gets pushed downwards
this is really jarring on the eyes.
Does anyone have a fix for this?
Frame detail view is created / visible vs next frame
because it doesn't' have a size the first frame any content under it would naturally get pulled up
why does it not have a size? make sure the category is not hidden by default, so that when you open it its already expanded
that's just how the details view works
It's not something weird I'm doing with it. it's just how epic programmed it
even if you try setting it's visibility to off, the frame you enable it's visibility it still doesn't actually draw the widget until the next frame
GetDesiredSize() returns 0 first frame. even epic states it's only useful after a prepass
are you talking about when you open it for the first time in a session?
i think it makes the window first and then populates the widget on initialization
/**
* Gets the widgets desired size.
* NOTE: The underlying Slate widget must exist and be valid, also at least one pre-pass must
* have occurred before this value will be of any use.
*
* @return The widget's desired size
*/
UFUNCTION(BlueprintCallable, Category="Widget")
UMG_API FVector2D GetDesiredSize() const;
no. I'm talking about when i create the widget containing the details view
one second let me shoot a video
if you unregister the widget every time you close it, then this will always happen i think
yeah that's the problem, but since I need to reorder my widgets, it creates the visual glitches
think of a list of detail views
as i re-order the list, it has to create and dispose of the widgets causing them to not be drawn for a single frame
you could do an animation pass. overlay the widget with an image or a static representation of how it should look and then hide that image when its done populating. kinda janky. im sure theres more sophisticated ways to do it
My janky fix was to save the height some frames after it's rendered, and then have a parent box with that as the minsize when it spawns
that works too. maybe theres some better way out there
I tried ForceLayoutPrepass to no avail 😦
I saw others recommending it, but i wasn't able to get that to work unfortunately.
@vale stump Here's the video
oh ic
yeah my janky fix works, but only after it's rendered the first time. not a huge deal since it's just an internal tool I'm working on. but still an irritating bug lol
maybe instead of destroying the widgets each time you could do some slot swapping?
i think verticle boxes have some Slot methods, like StealSlot, where you can change which property is in which slot

if you wrap each widget in a verticle box and assign a slot to each, you might be able to then access that verticle box and and its slot array, and then move stuff around
that sounsd like an intersting approach. I'm gonna give that a shot
good luck!
I'll let you know if i can get it working. gracias
np np. looks like a cool thing you got going there, im excited to see it working well
Really I'm trying to do some of what the hogwarts team did
https://youtu.be/M-Xoa4shre4?t=255 (timestamped video)
They don't use a details panel, i don't have many ideas as to how they did their custom widget for their steps
(to show the details of each step in their quest)
i just got this individual setting lock working
These seem like a custom widget rather than just a details panel with IDetailCustomization
ooh that's neat actually
yeah I'm trying to make it project agnostic. and i do love me some reflection
so I'm going with what's more versatile
it be like that. I've now spent one day thinking of the jank fix for my issue lol.
the worst part is my project was already done. i was just gonna do some work on making it package ready, and then i had this idea for an individual property locker that i DONT EVEN NEED
it's good enough for now lol. no visible jank in that video, but if i load a different quest there is some small jank for the first load
thats not bad at all
afterall, is a project ever really complete if we don't keep adding features that we don't need?
that is true
that is a pretty neat idea to lock settings though. make things less error prone.
i could do that for quests so that I don't accidently modify them once they're in a complete state
while still allowing you to see all the details
yeah. the solution i found was to basically make a checkbox, and based on the state of that checkbox i flipped the enabled state of an SBox i wrapped around the properties i wanted to turn off
but i had some trouble with things being initialized in the wrong order so i had to add all the states to a TMap that i instantiated in my DetailCustomization and then add the properties im modifying into there with an attached bool
i did all this because i wanted to have multiple properties have their own check box (using the same SAssignedNew Checkbox widget) and all their values will be separate