#slate

1 messages · Page 10 of 1

pallid gyro
#

You can add custom widgets via an IDetailsCustomization class, it doesn’t hide the regular property based details

stuck jewel
#

i'm just curious why you used ISettingsModule instead of UDeveloperSettings 😄

vale stump
vale stump
pallid gyro
#

Yes it does

#

Details Panel

vale stump
#

thats a details panel?

pallid gyro
#

yup

vale stump
#

............ive made a continuous lapse of judgement

pallid gyro
#

Meh, Unreal is a journey 🙂

vale stump
#

i thought the details panel was only in the editor itself, when referencing an object

#

like the outside widget

pallid gyro
#

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

vale stump
#

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!!

pallid gyro
#

np.

vale stump
#

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

pallid gyro
#

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

vale stump
#

wowow

pallid gyro
#

In another project I actually went a little crazy and spawned a thread for the details class so that it could animate

vale stump
#

ok so i have to replace this then? ISettingsModule doesnt seem the way to go?

pallid gyro
#

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

vale stump
#

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

pallid gyro
#

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

vale stump
#

interesting. thats the UDevsettings.

#

i heard that doesnt package well, but maybe i heard wrong?

pallid gyro
#

Settings can expose variables that need to be accessible in runtime, after all

vale stump
#

wait actually

stuck jewel
vale stump
#

i heard UDeveloperPlatform iddnt package well

stuck jewel
#

😄

vale stump
#

im very tired tbh

pallid gyro
#

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

vale stump
#

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

stuck jewel
#

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.

vale stump
#

well, my current setup can use configs

stuck jewel
#

in practice usually not a big deal, but if someone actually needs that, it's bleh

pallid gyro
#

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

vale stump
#

idk if i care about configs. i can do some save logic myself if i rly have to

pallid gyro
#

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

vale stump
#

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

pallid gyro
#

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

vale stump
#

i had looked through a few. most just made it entirely through SWidgets, or never interacted with the editorpreferences/project settings

pallid gyro
#

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

vale stump
#

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

pallid gyro
#

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

vale stump
#

idk, i need that motivation right now! thanks mate

pallid gyro
#

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

vale stump
#

damn only a year and you made this beast??

#

leave some talent for the rest of us

pallid gyro
#

Epic made the beast I just add fluff on top of it

vale stump
#

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!

tribal bolt
#

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

grave hatch
#

That's where the file was on the machine that built the editor.

tribal bolt
#

Okay good to know, I assume all other absolute paths will behave in the same way then?

grave hatch
#

All the ones from the widget reflector, probably, yes.

vale stump
#

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

vale stump
grave hatch
#

It does let you choose.

#

@vale stump

vale stump
#

tell me your secrets great wizard

grave hatch
#

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 = "...";```
vale stump
#

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.

grave hatch
#

Instead of being in the project settings?

vale stump
#

right

grave hatch
#

If you want some settings in the project and some in the editor, you'd want 2 classes?

vale stump
#

i only want them in the editor

grave hatch
#

Then that'd be one of the Config = ... options.

vale stump
#

i cant do much more than this

#

i have no way to change the CategoryName beyond description

grave hatch
#

So which Config options did you try to get it into the editor settings?

vale stump
#

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?

grave hatch
#

Nah.

#

I'm gonna try some stuff.

vale stump
#

k

grave hatch
#
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;
}```
vale stump
#

another thing im trying to do is get the Module somehow, but ive not managed to do that

grave hatch
#

We use EditorPerProjectUserSettings pretty much everywhere and it gets put into editor settings.

vale stump
#

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

grave hatch
#

So use EditorSettings...

#

It's right there 😛

vale stump
#

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?

grave hatch
#

Np. Why?

vale stump
#

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

vale stump
#

lol

grave hatch
#

You probably can't.

vale stump
#

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

grave hatch
#

Yeah, you can modify teh sections, but section buttons don't appear in the settings tabs.

#

Only in the details panel.

vale stump
#

ic

grave hatch
#

Do you specifically want to change the reset to default?

vale stump
#

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

grave hatch
#

Yeah...

#

You can definitely override the buttons with a details customisation.

vale stump
#

alright! guess ill finally get started figuring out how i can figure that out.

#

unreal engine is painful tbh

#

thanks for your help dude!

grave hatch
#

Np

vale stump
#

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.

grave hatch
#

Did you sent the CategoryName to "EditorFontSettings" or whatever?

vale stump
#

there is no setter i can call

grave hatch
#

You just set the value in the constructor.

#

CategoryName = "EditorFontSettings";

vale stump
#

amazing

grave hatch
#

🙂

vale stump
#

once again, thank you for your help and your patience with my dumb-ass

grave hatch
#

No worries.

vale stump
#

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

vale stump
#

i think i might give up

grave hatch
#

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.

vale stump
#

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

grave hatch
#

Did you register a customisation for your settings class?

stuck jewel
#

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

vale stump
vale stump
grave hatch
#

You'll want to be using the property editor module.

vale stump
#

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

grave hatch
#

RegisterCustomClassLayout, RegisterCustomPropertyTypeLayout and RegisterPropertyHandleLayoutOverride probably.

vale stump
#

Right I did see those

grave hatch
#

What do you actually want to do?

#

Not "customise the settings page"

#

I mean specifics.

vale stump
#

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

stuck jewel
vale stump
#

i get that, but it has no Property Module

stuck jewel
#

What has no module?

grave hatch
#

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.

stuck jewel
#

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

pallid gyro
#

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

vale stump
#

no button appeared

pallid gyro
#

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

grave hatch
#

Some details views just don't support certain things. Apparently CallInEditor is not on the settings tabs. 😦

grave hatch
pallid gyro
#

is it a repo pun?

grave hatch
#

It is.

vale stump
#

nice

pallid gyro
#

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

vale stump
#

ive looked through the widget reflector. its all categorized as normal SWidget stuff

#

but its created through different processes

grave hatch
pallid gyro
#

you can't see any SSinglePropertyViewer or or something like?

grave hatch
#

I don't believe that at all.

grave hatch
#

In the widget tree for the settings pages.

vale stump
#

oh

#

i can check

#

no property viewer

pallid gyro
#

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

stuck jewel
#

Every single row of the page is a property customization

#

The panel containing all of those rows is a details customization

pallid gyro
#

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

vale stump
#

ill give it a shot

stuck jewel
#

Callineditor isn't allowed on cdo it's for actors in level

#

Dunno why

pallid gyro
#

it can also go in uobjects?

#

I use it in a few

grave hatch
#

It's definitely got a load of details view widgets in the settings pages.

vale stump
#

rly doesnt help that the docs lie to me. this is not a class. i think it means DetailLayoutBuilder

pallid gyro
#

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 😦

vale stump
#

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

grave hatch
#

It'll be IDetailCustomization now.

#

Just search for that in the engine.

vale stump
#

whatever ill just take it all and retrofit to my needs

pallid gyro
#

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

vale stump
#

i did a code search and it doesnt exist

#

and i searched the docs

grave hatch
#

It's IDetailLayoutBuilder

stuck jewel
#

Ooh the name.

vale stump
#

where does CustomizeDetails() get called?

grave hatch
#

By the details view somewhere, I expect.

vale stump
#

alright

stuck jewel
#

My preferred answer is "magic"

vale stump
#

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

grave hatch
#

A "section" is the blue buttons you see on the details panel.

vale stump
#

i forgot to call this function

grave hatch
#

I don't believe they are available in the settings windows.

vale stump
#

.................................................amir told me i should copy his code

grave hatch
#

The correct bits.

vale stump
#

ok well following his code doesnt work for me because its all based on this

grave hatch
#

His code isn't doing what you think it's doing.

vale stump
#

i dont think its doing anything because im not convinced any of this shit works in the settings window

grave hatch
#

I haven't seen him paste any code.

grave hatch
#

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.

vale stump
#

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

grave hatch
#

Yeah, that part didn't work. The CallInEditor thing.

#

But you need to create a class to send a creation delegate to RegisterCustomClassLayout.

vale stump
#

i use the UDeveloperSettings class for that no?

#

i mean, the property editor section stuff doesnt work i guess

grave hatch
#

Delete this bit. It is not needed.

vale stump
#

alright

grave hatch
#

These are the bits you need.

vale stump
#

ok so how do i construct a button in the CustomizeDetails() function without anything to put it in

grave hatch
#

"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.

vale stump
#

i need some access to the things that are already there no? like if i just do SNew(TextBox) a new textbox will appear?

grave hatch
#

You get the category from the builder, then the property from the category, tehn edit the property. Something like that.

pallid gyro
#

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

grave hatch
#

Or you get the prperty row directly from the layout builder actually.

#

virtual IDetailPropertyRow* EditDefaultProperty(TSharedPtr<IPropertyHandle> InPropertyHandle) = 0; with this.

vale stump
#

trying this

#

and then ill try that

grave hatch
#

That would add a custom row, yes.

#

Not customise an existing property.

vale stump
#

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

grave hatch
#

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?

vale stump
#

no, that would be smart

#

nothing is calling it

grave hatch
#

Is the registering code being called?

vale stump
#

yeah it is

#

maybe it hasnt generated yet

grave hatch
#

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.

vale stump
#

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

grave hatch
#

👍

#

Good luck. I'm off to sleep.

vale stump
#

good night mate.

vale stump
#

its able to read my properties, but idk why im getting null for the rows

#

imma take a break tho

pallid gyro
#

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 😄

vale stump
#

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

steady walrus
#

Hi there, Is there any possibility that I can create second window and set it a UMG widget that I created in Editor?

grave hatch
#

Sounds like a blutility widget?

steady walrus
#

but it is usually for editor stuff

#

I want to create it for runtime to make an external debug window

pallid gyro
#

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

steady walrus
#

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

pallid gyro
#

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?

steady walrus
#

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

pallid gyro
#

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.

pallid gyro
#

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.

pallid gyro
#

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.

vale stump
#

can you call 'create widget' in c++?

lunar estuary
#

Is slate still used? iIt seems very performance intense.

stuck jewel
#

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]]

pallid gyro
vale stump
#

But I also know blueprint classes are .uasset or something, and I haven't looked into modifying them from an editor

pallid gyro
#

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!!!!"

vale stump
#

I'm the other side of the brain

#

But idk enough about C++ or unreal to rly help more

pallid gyro
#

LoadClass, is that what I'm looking for here?

stuck jewel
#

well... yes, but also no, not for anything you would ever use in finished code

pallid gyro
#

I mean, that screenshot is from the UMovieRenderPipeline code?

stuck jewel
#

if "all" you're using UE for is rendering movies then i suppose you could probably cut some shortcuts without getting assbited

pallid gyro
#

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

stuck jewel
#

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)

pallid gyro
#

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.

stuck jewel
#

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

pallid gyro
#

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.

pallid gyro
#

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.

vale stump
#

congrats

shy wharf
#

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.

dry swift
#

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!

dry swift
#

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.

shy wharf
#

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?

dry swift
#

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 😦

shy wharf
#

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

dry swift
#

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...

shy wharf
#

oh yeah there's not even a repo hahaha

#

it's just code snippets

dry swift
#

Have you asked the author? They wanted to share the code, maybe they'll be happy to have a fan base 🙂

shy wharf
#

that might be the next step. good call 🙂

dry swift
grave hatch
grave hatch
# pallid gyro

Note the _C at the end of this string and the missing _C on your code.

lunar estuary
#

Alright. I was looking a trace and trying to find why things were so slow.

#

Named Events help a bunch don't they?

grave hatch
#

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).

lunar estuary
#

True. It's just so slow in my trace, I'm trying to find why.

grave hatch
#

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.

rain heron
#

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)

grave hatch
#

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

rain heron
rain heron
#

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.

grave hatch
#

Before you start copying it everywehere.

#

Hopefully you won't have to change that style much in the future.

grave hatch
#

And then you'd have to recreate all your widgets.

rain heron
# grave hatch _Before_ you start copying it everywehere.

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.

rain heron
grave hatch
grave hatch
rain heron
# grave hatch Then you're good.

(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)

grave hatch
#
static FMyStyleSet& GetStyleSet() { static FMyStyleSet() Style ... stuff ... return &Style; }```
rain heron
grave hatch
#

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.

rain heron
#

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

grave hatch
#

Most people don't really use slate for game stuff. 🙂

#

Except for base classes with named slots for logic, not actual widgets.

rain heron
#

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.

grave hatch
#

I totally agree lol

#

On both points.

rain heron
#

And Slate is even more performant (duh). UMG List View buckles with already just a few hundret entries. Slate rocks with thousands xD

grave hatch
#

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.

rain heron
#

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.

grave hatch
#

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.

rain heron
#

that sounds like a good solution

#

i will try that, thanks ^^

grave hatch
#

Every single property you want to cahnge would need to be a uproperty, though.

rain heron
grave hatch
#

That is true.

rain heron
#

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

grave hatch
#

Sounds like a plan!

pallid gyro
#

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?

rain heron
#

and cuz it didnt work I experimented with "adding them manually"

vale stump
#

that moment when you reset the corestyle

#

happened after this breakpoint got called

vale stump
pallid gyro
#

I am not sure what's the question, you want to spawn a UMG widget inside a new slate window?

toxic badger
#

what component could be use to draw a line? ist there something like a spline?

grave hatch
#

Draw it where?

toxic badger
#

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

grave hatch
#

FCanvasLineItem

#

Check the file that contains that for all your options.

vale stump
toxic badger
vale stump
#

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

grave hatch
#

Live coding?

vale stump
#

not that.

#

maybe live update was the wrong term. im able to refresh the fonts that the editor is using

topaz fox
#

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?

vale stump
#

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

vale stump
#

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

grave hatch
#

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.

vale stump
#

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

grave hatch
#

Yeah. @narrow terrace is the shit!

narrow terrace
vale stump
#

omg you are real

#

nice work on this mate

narrow terrace
#

I am a human

#

Yes I am human glad to work on it

vale stump
#

haha

#

i just dont expect to see the actual creators of things

narrow terrace
#

Yeah we're usually just heads down on different things but usually pretty accessible

vale stump
narrow terrace
#

Just don't expect immediate responses and don't expect a lot of one on one sort of thing.

vale stump
#

and watching...

#

and waiting....

#

scary

narrow terrace
#

I'm rarely watching, usually heads down lol

vale stump
#

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

grave hatch
#

SVectorInputBox is a details panel class, though it's public.

vale stump
#

is there a way to delay CustomizeDetails being called? im getting null pointers and im wondering if its because things havent loaded in yet

grave hatch
#

No

vale stump
#

k

vale stump
# narrow terrace Is that internally used for the engine stuff or common UI? I don't have time to ...

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?

narrow terrace
vale stump
#

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

vale stump
#

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

vale stump
#

its starting to look awesome guys

vale stump
#

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

vale stump
#

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

grave hatch
#

@vale stump Talking of fonts, motion design (avalanche) has a system font loader/selector. There might be some helpful code there.

vale stump
#

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

grave hatch
#

I meant more look at the code. 🙂

#

It's the AvaFont module or some such.

vale stump
#

Oh I think I did see some of those files in my research. I don't recall them having the stuff I needed.

maiden lance
#

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.

grave hatch
#

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.

maiden lance
#

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;
    }
}```
grave hatch
#

Is this you trying to hover over just the line itself?

#

I thought you'd be hovering over the shape it defined, my mistake!

maiden lance
#

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

grave hatch
#

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.

maiden lance
#
    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

grave hatch
#

There isn't.

#

You'd have to do something custom.

maiden lance
#

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

grave hatch
#

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.

maiden lance
# grave hatch I would do a broadphase search on their rectangular bounding boxes and then chec...

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

rain pecan
#

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 🤔

toxic badger
#

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?

pallid gyro
#

When you 'pass' the array, do it via some setter, set up some 'regenerate vertical box' method, call that.

vale stump
#

@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

topaz fox
#

@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!

toxic badger
dry swift
#

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.

vale stump
#

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

dry swift
toxic badger
#

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? 😅

grave hatch
#

Use the widget reflector.

toxic badger
#

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.

grave hatch
#

But is the border there in the reflector?

toxic badger
#

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.

grave hatch
#

Might be a style failure.

#

I mean, position is not size?

toxic badger
#

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.

toxic badger
grave hatch
#

shrug

#

Debug SButton.

toxic badger
#

Also if I try to select the button with the Picking tool from the Widget Reflector, I can't select it.

dry swift
# vale stump most likely you need to re-register the tab spawner

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);
}
toxic badger
#

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?

vale stump
vale stump
#

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

vale stump
toxic badger
dry swift
# vale stump I see you changed from NomadTab to a normal Tab. What's the difference here?

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"));
}
vale stump
#

Or the horizontal box you put it in

#

If the button doesn't have those methods the HorizontalBox definitely does

toxic badger
vale stump
#

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

toxic badger
vale stump
#

The buttons parent will be the box

toxic badger
#

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. 😅

dry swift
vale stump
#

Horizontal boxes have native width and height methods

#

Right now, your size method is affecting the canvas, not the button

dry swift
#

Go with the flow bro, you got this

vale stump
#

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

toxic badger
#

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 😅

vale stump
#

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

vale stump
#

I'm about to embark on creating a slate style. Do any of you have any good resources or examples I can look at?

toxic badger
#

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 🙂

grave hatch
#

The engine code?

#

(@Theos)

dry swift
#
// 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

vale stump
# grave hatch The engine code?

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

grave hatch
#

There are other style set classes. 🙂

vale stump
#

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)

grave hatch
#

Search for : public FSlateStyleSet in teh engine code and have a browse.

vale stump
#

And I don't know the first thing about any of that

grave hatch
#

Slate styles don't use imported assets generally. They use raw pngs or svgs.

vale stump
#

What's an SVG

grave hatch
#

Something vector graphic.

#

Scalable!

dry swift
#

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.

grave hatch
#

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.

vale stump
#

I see. That sounds useful tbh

#

Better than stretching static images

grave hatch
#

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.

vale stump
#

Does it scale in runtime or only at initialization or what not. Like if you make a drag scalable window will it match?

dry swift
#

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

vale stump
#

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?

dry swift
#

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
}
dry swift
#

It's open source

vale stump
#

Oh that's awesome

#

Thanks so much!!

dry swift
#

Go team!

dry swift
vale stump
#

oooh. thanks!

vale stump
#

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

grave hatch
#

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.

vale stump
#

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

grave hatch
#

It's might be a rendering issue with the program specifically, but it's not a font issue.

vale stump
#

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!!!!

little mauve
#

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 😄

grave hatch
#

Pixels.

#

If you want to align to the centre, use an SBox with a slot alignment.

little mauve
#

If thats pixels i think i kmow what to do

#

waiiit. if that are pixels, why they are not named pixels? 😆

#

thats fishy

vale stump
#

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

pallid gyro
#

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

vale stump
#

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?

pallid gyro
#

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

vale stump
#

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.

pallid gyro
#

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

little mauve
vale stump
#
Epic Developer Community Forums

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

pallid gyro
#

Not far from my explanation, vindicated once again

#

I’m very insecure 😞

little mauve
#

but you were right

vale stump
#

My fault for being dumb 😦

little mauve
#

does user picks dpi? 😄

vale stump
#

You can

little mauve
#

is this dpi independent? 🤔

#

its mouse clikc on image

#

should be imo

vale stump
#

DPI just affects image quality I think

little mauve
#

in practice its like pixel density

pallid gyro
#

I believe so, you are effectively calculating the relevant units per pixel when dividing the absolute space with the local space

vale stump
#

Right, but changing the dpi won't scale anything I don't think

pallid gyro
#

There is however a ready made method that does this for you

little mauve
#

what method ?

vale stump
#

Oh so you're saying the calculation might be more exact with higher DPI?

little mauve
pallid gyro
#

Ah that absolute to local thing, you’re already using it I missed it

vale stump
#

Having more dots might make your .000001 into a .000002

pallid gyro
#

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

little mauve
pallid gyro
#

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 🙂

vale stump
#

Nice. Shapes!!

little mauve
#

need to limit it to triangle now

#

and somehow reduce underlying button click visbility :d

pallid gyro
#

There some intersects with methods in slate, at least for rectangles, I’d assume triangles are also handled somehow

vale stump
#

are you supposed to be able to drag the dot?

little mauve
#

ye, that would be cool

vale stump
#

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

little mauve
#

first of all, im using umg 😆

#

emm

vale stump
#

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

pallid gyro
#

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”

vale stump
#

yeah you could just implement an enhanced input yourself

pallid gyro
#

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.

little mauve
pallid gyro
#

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

little mauve
#

I

#

I just set bool when click was good

#

and bools gets consumned on read

pallid gyro
#

So you can’t drag

little mauve
#

if widget was clicked, but not the image, bool is still false

#

not yet 😄

vale stump
#

definitely switch to using some Focus methods and mouse captures

#

and such

#

and mouse events

pallid gyro
#

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

little mauve
#

oki

vale stump
#

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

little mauve
#

well

#

Image has only OnMouse Down event

#

so I have to find other way around

vale stump
#

whats your triangle made out of?

#

it should have mouse events as well

little mauve
#

2 mirrored images

#

and there is only1event

vale stump
#

oh ic

#

then you just have to steal the global mouse event

#

and check for focus

pallid gyro
#

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

vale stump
#

and if your mouse is inside the bounds of the triangle

little mauve
#

blue is button

vale stump
#

that shouldnt matter

little mauve
#

can you toggle events?

#

after hovering over button

vale stump
#

your mouse event can hit 2 things if you let it

little mauve
#

I used button just, that it wont hit in game

vale stump
#

if your mouse is inside the bounds of the rectangle, move the image. if your mouse clicks the button, the button is clicked

little mauve
#

No

#

it was pure image, but it always clicked through, thats why I put button under

vale stump
#

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

little mauve
#

mouse capture ?

vale stump
#

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

little mauve
#

well thats most annoying thing, that you have to click to activate widget / game

vale stump
#

and you can uncapture the mouse by hitting shift+f1

#

you can make the widget do that

little mauve
#

but how

vale stump
#

i think i have an example lying around, tho i used enhanced input settings for it

#

one sec

little mauve
#

is it bp? slate?

vale stump
#

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.

little mauve
#

i think this will help 😄

#

kinda

vale stump
#

here we go

#

basically just this

#

easily replicatable in C++

#

those 2 blue nodes are the capture functions

#

this is it's c++ code

little mauve
#

why you got flipflop there? 😭

vale stump
little mauve
#

well I don't use enhanced input yet

vale stump
#

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

vale stump
#

when i click the button again, the UI disappears and the cursor is captured by the Actor

little mauve
#

😆 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

vale stump
#

that shouldnt rly affect anything. cursor visibility is not the issue, its cursor capture

little mauve
#

but then I need to find click position myself 🤔

vale stump
#

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

little mauve
vale stump
#

............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

little mauve
#

i quite don't follow you

vale stump
#

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

little mauve
#

do you want to add every single widget to do such thing ?

vale stump
#

you can make a delegate if you like, that will call a similar method on every widget that binds to the delegate

little mauve
#

delegates do not block input

vale stump
#

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!!

little mauve
#

im gonna re read thsi and re think later 😆 im clearly missing something

pallid gyro
#

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.

brisk granite
#

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

brisk granite
#

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

vale stump
#

I haven't checked out common ui either. I'll take a look at it

vale stump
#

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

vale stump
#

oh hey i found it

#

commonUI does have the exact blueprint node i was using

pallid gyro
#

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 -

grave hatch
#

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.

pallid gyro
#

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.

grave hatch
#

It may be that tab is a processed before slate does it.

#

Before the normal key press flow, that is.

vale stump
#

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

grave hatch
#

Create a MID of the material and assign it to a FSlateMaterialBrush

vale stump
#

nice! thanks

woven gate
#

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

grave hatch
#

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.

woven gate
#
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

grave hatch
#

Yes. That makes a new item it doesn't make a pointer to the original one.

woven gate
#

Ah, is there a way to make a pointer to the original one safely? Is this just a bad way of doing things?

grave hatch
#

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)

woven gate
#

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

grave hatch
#

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.

woven gate
#

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?

grave hatch
#

Hence the "have a struct with the array index in it" ?

woven gate
#

Ok so thats all it contains is what you are saying?

grave hatch
#

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.

woven gate
#

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?

grave hatch
#

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; }

woven gate
#

cool cool yea i think i get that

grave hatch
#

It's literally 3 lines

woven gate
#

yea, passing the index in is a great idea in this case

grave hatch
#

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.

woven gate
#

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;

grave hatch
#

If it's already a map with an fname as key, just make a list view with an fname base.

vale stump
#

@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

woven gate
#

oh man thanks that might be exactly what im looking for, i will look into it

vale stump
#

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

vale stump
#

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

brisk granite
#

Anyway to unregister a slateuser from a UI? So it runs with no slateuser and stops interfering with the playercontroller inputs

grave hatch
#

Have you tried setting the input mode to game only?

vale stump
#

^

vale stump
#

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

brisk granite
vale stump
brisk granite
#

yes local multiplayer

vale stump
#

so is the problem that user1 is able to interact with the menu that user2 opens?

brisk granite
#

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.

vale stump
#

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

brisk granite
vale stump
#

seems to me like every player should be a slate user

#

not just index2

brisk granite
#

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

brisk granite
# vale stump not just index2

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

vale stump
#

have you tried accessing the ULocalPlayer that this doc talks about?

brisk granite
#

not really, ive been primarily looking at inputs

#

it also seems too low level to permit modifications (in the context of UE gamestate/instace)

vale stump
#

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

brisk granite
#

yeah, I think that may be the solution here as well once you suggested it - im trying to set that up now

vale stump
#

alright, hope it works out!

brisk granite
#

thank you v much

vale stump
#

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

brisk granite
#

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
vale stump
#

im not sure

#

i havent dealt with multiplayer stuff yet

brisk granite
#

fair enough - i suspect its something in CommonUI

brisk granite
#

nope, stuck differently now

#

ill try to sleep this off and maybe i can think of a solution tomorrow

toxic badger
#

Is it possible, to draw something like a bezier curve with slate, or do I have to implment that myself?

vale stump
pallid gyro
#

FSlateDrawElement statics contain the commonly used slate drawing functions

vale stump
#

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

vale stump
#

do any of you know why my includes keep breaking, even tho nothing has changed regarding them when i built the project last?

stuck jewel
vale stump
#

yup

stuck jewel
#

well... just normal behavior then

vale stump
#

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

stuck jewel
#

you have to buy resharper or rider.

fluid jewel
#

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

vale stump
#

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

fluid jewel
#

GetDesiredSize() returns 0 first frame. even epic states it's only useful after a prepass

vale stump
#

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

fluid jewel
#
    /**
     * 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;
fluid jewel
#

one second let me shoot a video

vale stump
#

if you unregister the widget every time you close it, then this will always happen i think

fluid jewel
#

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

vale stump
#

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

fluid jewel
#

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

vale stump
#

that works too. maybe theres some better way out there

fluid jewel
#

I tried ForceLayoutPrepass to no avail 😦
I saw others recommending it, but i wasn't able to get that to work unfortunately.

vale stump
#

oh ic

fluid jewel
#

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

vale stump
#

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

fluid jewel
vale stump
#

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

fluid jewel
#

that sounsd like an intersting approach. I'm gonna give that a shot

vale stump
#

good luck!

fluid jewel
#

I'll let you know if i can get it working. gracias

vale stump
#

np np. looks like a cool thing you got going there, im excited to see it working well

fluid jewel
#

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)

vale stump
#

i just got this individual setting lock working

fluid jewel
#

These seem like a custom widget rather than just a details panel with IDetailCustomization

vale stump
#

yeah most likely

#

probably doesnt use UPROPERTY macros at all

fluid jewel
vale stump
#

it took me all day

#

for one little button

fluid jewel
fluid jewel
vale stump
#

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

fluid jewel
#

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

vale stump
fluid jewel
vale stump
#

that is true

fluid jewel
#

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

vale stump
#

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