USTRUCT(BlueprintType)
struct FTwixtSkeletalMeshAsset
{
GENERATED_BODY()
UPROPERTY(BlueprintReadOnly, EditAnywhere)
TObjectPtr<USkeletalMesh> Mesh;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
TSubclassOf<UAnimInstance> AnimClass;
};
USTRUCT(BlueprintType)
struct FTwixtSkeletalMeshContainer
{
GENERATED_BODY()
UPROPERTY(BlueprintReadOnly, EditAnywhere, EditFixedSize, meta=(ReadOnlyKeys, ForceInlineRow, ShowOnlyInnerProperties))
TMap<FGameplayTag, FTwixtSkeletalMeshAsset> Meshes;
};
#slate
1 messages ยท Page 7 of 1
which gives you this
when I want this
So I just need to figure out how to find InTreeNode and I can call SetNodeExpansionState(TSharedRef<FDetailTreeNode> InTreeNode, bool bIsItemExpanded, bool bRecursive)
Ah. You see. I think this is the issue.
I've had the issue before...
Have you tried ShowInnerProperties?
FullyExpand ?
I've tried FullyExpand
It might be the array that's confusing it. Have you tried it without an array? Just to test.
Array/map
If only.
Can I access the tree from IDetailsView?
I highly doubt it.
They export the minimum required for their own stuff to work.
There should be a combination that works, It may just be the map customisation not working correctly.
Hence the suggestion to just add one outside of the map to check.
Why did it even appear, though?
What was the UPROPERTY line?
Does not work outside the map either
That's just weird.
Suppose it doesn't like nested structs
No, maybe not.
So I figured out a way to get into the tree.....but it doesn't seem I have any way to identify which widget is the correct one
Oh?
It definitely is.
/**
* Gets the text assigned to this text block
*
* @return This text block's text string
*/
const FText& GetText() const
{
if (bIsAttributeBoundTextBound)
{
STextBlock& MutableSelf = const_cast<STextBlock&>(*this);
MutableSelf.BoundText.UpdateNow(MutableSelf);
}
return BoundText.Get();
}
the expansion shit isn't exported...
Yup
What you can do, because it's a widget, is traverse the widget tree yourself to find it.
Good luck ๐
You sound the SExpandableArea?
Is it doesn't use SExpandableArea? It's all a custom thing in SDetailSingleItemRow?
It's in the DetailsView actually
IDetailsViewPrivate is where it's declared
looks like STreeView is where it actually happens
Oh yeah, wow, it's a whole load of shittery.
surprise surprise lol
I don't think the non-expanded stuff even gets added to teh tree view.
I may be wrong
why wouldn't they just export all the slate shit
so you can do whatever you want
i don't understand
Because then they have to maintain it.
And they aren't free to change it.
You're free to export it yourself, just change the source.
Fslateapplication::get().pushmenu
@warm vault
Ah. Modal windows will still you interactibg with the editor until you close the modal.
Yeah. Absolutely!
There's a dialog box thing with yes/no question boxes.
Fmessagedialog or something?
Fdialogbox?!
If you search for yesnocancel in the engine it will lead you to a type used with them.
They are exclusive windows and will block your function execution until they receive an answer.
1 moment.
๐
Btw, don't use FText::FromString("...") if you don't want stuff to be translateable, just use INVTEXT("...")
static const FText MessageBoxTitle = LOCTEXT("...", "...");
static const FText MessageBoxPrompt = LOCTEXT("...", "...");
const EAppReturnType::Type Response = FMessageDialog::Open(
EAppMsgType::YesNoCancel,
MessageBoxPrompt,
MessageBoxTitle);
switch (Response)
{
case EAppReturnType::Yes:
//do the thing
break;
case EAppReturnType::No:
//don't do teh thing
break;
case EAppReturnType::Cance;:
//cancel whatever you're doing
break;
}
You need to either use NSLOCTEXT(Namespace, Token, String) or you can predefine a namespace for an entire file by doing #define LOCTEXT_NAMESPACE "Something" near the top of your cpp and #undef LOCTEXT_NAMESPACE at the bottom. Do not forget the undef.
It's generally a bad idea to use NSLOCTEXT because you might get your namespaces wrong.
Set it once, don't copy+paste the name over and over.
Something like that.
#include "CoreMinimal.h"
#include "Widgets/Input/SButton.h"
#include "Input/Reply.h"
class SCustomButton
: public SButton
{
public:
virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override;
}```
Does anyone know why I am getting the error "variable "FReply" is not a type name" from this? I have Slate and SlateCore in my dependencies in the .Build
Copy+paste your exact header and the exact error from the output tab.
Disregard, the issue was I was missing a ; at the end there ๐
๐
@grave hatch Thanks man! #undef LOCTEXT_NAMESPACE was what I needed to get my apply instance changes function to work!
I'm slightly concerned that you have value content, then an alignment param and then the actual value content slate layout.
Like how does that even work?!
Is no longer on his phone and can actually read teh code now
Having issues with SComboBox<FName>. If I have the dropdown open, and I click out, it doesn't generate things properly.
What does this mean? Screenshot?
You could try binding to OnComboBoxOpening and forcing a refresh each time it's opened.
Calling RefreshOptions on the combo box
That won't be calling it on the widget, though?
So what you'd have to do in this instance is save teh combo box in the containing widget as a TSharedPtr member var (using SAssignNew) and then do .OnComboBoxOpening(this, &SYourWidget::RefreshList); and then make a RefreshList function which called RefreshOptions on that sharedptr var.
(if it's valid)
Or &SYourWidget::OnListOpen probably be better.
It'd be lovely if these events passed in the widget itself as an event param for lambdas.
DECLARE_DELEGATE( FOnComboBoxOpening ) SO USEFUL
It does.
Though I still prefer to do TSharedRef<SWhatever> ... = SNew(...) if it's outside of a slate layout tree.
Awesome.
It may take a frame to update the combo box sometimes... because slate.
Np!
You should be able to just lift the code from the property editor for that one. Use the widget reflector to find the code that creates it in thr details panel.
Is there a "proper" way to hold references to UObjects inside a slate widget to prevent them from being collected?
You have 2 options. TStrongObjectPtr<UWhatever>
And using TObjectPtr members, extending from FGCObject and overriding the appropriate methods,
You should prefer the latter if you have multiple objects to keep alive.
thanks, I have been using TStrongObjectPtr before, but have seen the FGCObject approach used by a lot of the built-in module so wasn't sure if the one was preferred over the other. For this use case I am only handling a single object.
I'm not exactly sure how TStrongObjectPtr works, but I've heard it's not particularly efficient.
For a single object, a strong pointer is perfectly fine.
Widget Reflector is a psychedelic drug with all those fancy colored hitboxes
When populating an SCanvas, what's the best practice to later access the slots you've created in order to reposition them? does it even make sense to do so or is it preferable to just clear the children and re-create the slots? I can get the slots from the widget using 'getAllChildren' but when I try to change the position attribute unreal seems unhappy and crashes.
if I restart the editor, my slate widgets created automatically from last state. Somehow I always need to avoid making engine remember the latest tabs opened before closing and don't let open my slate widget automatically when engine restarted
You can do .ExposeSlot on them to get the slot pointer.
Or you can just process the FChildren object. I usually do that, tbh.
is there a nice way to get rider to properly indent the slate operator overloading magic? (construct etc.)
Guess that's 2 things Rider can't do: format slate and debugging!
I made a slate widget that is basically a wrapper for SCanvas that allows zooming in and out and different axis, I only managed to achieve this by binding Lambdas to the Size and Position properties of the the SCanvas::FSlots I created and while this works I noticed that the lambdas get called very frequently, is this something I should be concerned with? I tried to figure out how to simple change the value of a TAttribute after creating it but couldn't figure it out.
Not really. That's just how slate works.
Though I would probably try to adjust the scale of the canvas, rather than adjsut every single slot.
Cool thanks, I did that at first but what I'm going for is a 'timeline' so I wanted to be able to keep horizontal zoom seperate from vertical zoom, I couldn't figure out a way to create an FSlateLayoutTransform that takes seperate values for x/y scale. I still use the the offset paint geometry to 'pan' the entire canvas.
So cool, glad to hear that the lambda's are 'legit', all in all.
I mean Slate in general isn't the best. A few lambdas isn't going to slow it down overmuch.
Just don't add 5000.
Also SCanvas very specifically has bad performance because every child widget is rendered separately.
Just keep an eye on your performance.
Will do, thanks.
Same goes for SConstraintCanvas.
You can turn off the individual rendering with a slate setting somewhere if it gets to be a problem. But I think overlapping stuff starts to become an issue.
still I cannot handle delegate binding
My Function argument TFunction<FReply()>& ButtonClick
The way I used the parameter
.OnClicked(FOnClicked::CreateLambda(ButtonClick))```
The function I want to pass to TFunction
``` FReply OnButtonClickSelectExcludeTile();
When I pass the function as TFunction like this &SBlockRoomWidget::OnButtonClickSelectExcludeTile I get
Non-const lvalue reference to type TFunction<FReply()> cannot bind to rvalue of type FReply(SBlockRoomWidget::*)()
I learned today that adding const makes it accept rvalue
{
return OnButtonClickSelectExcludeTile();
});``` I couldn't bind the delegate the way I wanted but this worked
mutable didn't work in my case. I deleted const and wrote mutable.
[
ConstructButtonAndItsTextBox(PropertyTextFont, "If box component extends are incorrect", "Open " + FirstRoom->GetName(), [this]() mutable -> FReply
{
return OnButtonClickSelectExcludeTile();
})
]```
```Non-const lvalue reference to type TFunction<FReply()> cannot bind to rvalue of type <lambda auto() -> FReply>```
Maybe it would work if I were made lambda local first and then pass it but I am in slot's square brackets. I Had better make **TFunction** **const** again
You can just do: void SomeFunction(FOnClicked InClickHandler);
And then pass in the FOnClicked::CreateLambda(...) object.
So SomeFunction(FOnClicked::CreateLambda(...));
I don't know why you'd use an intermediate TDelegate.
When I populate a panel, what's the proper way to give the children a reference to the populating parent? I'm still confused about shared refs and pointers and I tried to pass a shared reference to the parent widget through the slate arguments and this led to an error, I also couldn't pass a raw pointer or *this, or something, is it better to try to get the parent from the spawned widget and cast the reference to the relevant class?
Hmmm, okay so assigning the new slate widget to a weak pointer with SAssignNew and then just passing the raw pointer to the widget works. cool.
Don't pass the raw pointer. Pass the shared ptr.
The only raw pointer you should ever use for slate objects is for exposed slot objects.
Ok cool! That took me a while to parse, just cache the SharedPtr that's created when I build the widget in the UWidget wrapper and pass it down the hierarchy as needed! Thank you!
I don't think you can do something like this: cpp SAssignNew(Var, ...) [ SNew(...) .Parent(Var) ]; though.
Because it will instantiate the children before the parent.
So var will be passed in as a nullptr
Generally you'd have to do something like: cpp Var = SNew(...); Var->SetContent( SNew(...) .Parent(Var) );
I think shrug
Or you do something like: cpp Child = SNew(...); Var = SNew(...) [ Child ]; Child->SetParent(Var);
However!
You can do this: cpp void SYourWidget::Construct(const FArguments& Args) { ChildSlot [ // Some randm outer widget SNew(...) [ // Inner widget that needs to know about a parent SNew(...) .Parent(SharedThis(this)) // The SYourWidget being constructed ] ]; }
That is an example extending from SCompoundWidget where a child widget needs to know about a parent.
You don't have to give it the immediate parent, just the one that matters - in this case it is the SYourWidget instance.
In the majority of cases, a widget doesn't need to know about a random widget in the hierarchy but the actual outer object that is creating it.
Hi, m trying to find good resources or guidance on what would be the idiomatic way to implement the Marquee selection (RTS like, for not necessarily strictly RTS purposes). How should i approach coding it into the game? Is it any custom SLeafWidget? Or some extension of anything in UMG currently? Could you assist?
Doesn't the rts sample have that?
You could implement it pretty easily with a umg widget or slate.
Like have an overlay that goes across the entire screen and basically implement it with drag and drop. You "drag" the starting location and track the current location to make a box and then convert that into selecting the units within the box from some viewport to world shenanigans.
To me finding actors is not a problem, i am a bit struggling to find a right tool to just render the square on the screen
what method should i use to just spawn the rectangle (when and how to scale it - i have that)
In slate you could use a leaf widget to send direct draw calls.
and if i wanted to "pretty up" the box?
In what way?
well make it a bit more eye pleasing, not just a debug square
Same question
You could use an SBorder (or a umg border) to do it if you want fanciness.
i was looking for references now but you can imagine some irregular pattern on the border, and something to fill the space
texture maybe
Borders are good for that.
DrawRect im assuming uses regular debug square
Or you can build your own border with a series of triangle draw calls.
Is there any specific setup i need on the UBorder to scale it?
I used the Desired SizeScale and nothing chagnes
Any reason to do it in slate? a scalable decal material can create a pleasing effect that can easily be project to the landscape if needed, you can also override the On Paint method in a UMG widget to draw things on the widget
I am looking for the best place to implement it, in a way i am looking for a way you sort of should do it if for example going for production needs
No idea. #umg
Chances are it's scaling to its slot or its slot alignment settings, though.
https://www.youtube.com/watch?v=gg9uMw8Speg i think this is a good example, you can also switch the 'draw rect' call he uses with 'draw box' which will allow you to use an FSlateBrush asset which you can populate with a texture. you can also call those same methods in cpp of course, you don't need to create a custom slate widget in order to paint on a widget, in code or in BP.
Assets Available from here: https://marketplace-website-node-launcher-prod.ol.epicgames.com/ue/marketplace/en-US/profile/PolygonBlacksmith?count=20&sortBy=effectiveDate&sortDir=DESC&start=0
In this series we are creating the common mechanics found in RTS games, everything from unit selection, AI combat, and base building.
In Part 3 we work on ...
Yeah. The RTS sample!
combining the sizing the guy does in the tutorial together with the various 'draw' options you have available or applying them to an Image widget which can have some custom material is probably a decent enough option, it probably won't be easier to make it prettier using slate, if your game world is 3d I'd also consider using a widget to control an actor that projects a decal in world. It's also possible to draw paths using niagara, epic do it in the 'cropout' casual-RTS sample.
When I click a point in scene capture image, is there a way to convert it's location to world
I created actors for each debug box visualization. I somehow need to know which actor I selected when I select with my mouse on slate's image. Is this even possible to do :/
This is how I decided to handle tile selection any suggestions
Hi! I am working with a slate brush in order to draw e texture into UI. I am researching if there is a way to scale the texture (not the brush itself, just the resource texture), similarly to how the preview on this window allows to center and scale that texture into the preview window:
Maybe I should be using a material or something else than a texture?
That's probably what they're using.
makes sense, will research, shader and UV time 
Though.
I don't know why you can't just use a texture?
Why not scale/move the brush?
Well, this textures are generated from a scene capture (when developing the game, not at runtime) and we wanted to avoid the hassle of manually scaling each. The brush cannot be moved/scaled because more visual elements depend on it. If the shader turns too complicated, an option is to separate some stuff from the brush and have two brushes instead of one, but I don't think it's necessary
yeah I figured out eventually, was just lazy to do the maths 
yeah, fortunately didn't need rotation, just location and scale ๐ฅณ everything working fine now
I'm having some trouble with the SScrollBox, or really with grasping what determines sizes in Slate, I try to have a SCrollBox that has a child SVerticalBox that can receive an arbitrary amount of panels, all works well but the VerticalBox always 'fills' the scroll area and I can't quite figure how to make the scroll box area larger, ideally I just want to create the panel in some arbitrary size and if they take more space then is available have the scrollbox do its thing. I feel like I'm missing something basic.
perhaps the vertical box is not neccesary in this setup?
Really I guess my question is how can I set a ScrollBox slot to be of a specific size in units rather than just proportional to the alloted size?
These are two canvases nested inside the scrollbox (inside a vertical box), you can see the scroll bar shows up and all but the widgets 'fit to size'
OK. Got it, Override the 'Compute Desired Size' method and return whatever size you want! so indeed I failed to grasp something basic
It'll be based on the alignment info of its container.
If it's inside a container set to fill on both axes, it should fill the area.
SCanvas, specifically, has no default size and its desired size will always be 0,0 (unless you override it like you have) or align it correctly.
And also I didn't need to stick a vertical box inside a scrollbox set to vertical orientation.
You did not! Just add more slots.
I think vertical is the default, but you can specifically set the orientation of the scrollbox too.
That's a very good question and one of the many reasons the details panel can sod off ๐
Unfortunately CreatePropertyValueWidget() isn't able to handle other customisations for that property, you have to sort of hack around it by getting the Customisation Instance for that type, then stealing widgets from it. Had to do the same thing for Gameplay Tags ๐ฆ
Pretty much
Hey folks, I need to implement a scene outliner in my project just like the scene outliner in the editor. I'm very new to Slate and am looking at SSceneOutliner; It's very different than other Slate examples I've seen, and instead of creating a "tree" structure similar to how HTML looks, they add one vertical box to "ChildSlot" and then add slots to that vertical box outside of "ChildSlot"
Is there an advantage to doing it that way?
To make the tool bar for example, they create a new SHorizontalBox called "ToolBar", add children to ToolBar, and finally add ToolBar as a child to the main VerticalBox, all outside of ChildSlot
No particular advantage. Just a bit cleaner code.
The one thing you can't do with SAssignNew is use the variable you are assigning to in the same block to pass to children.
But they aren't doing that.
Ah okay, makes sense for large widgets like this
in slate, after I open FMessageDialogBox, my slate widgets created as SWindow faded into the background. I always have to select with Alt Tab
FSlateApplication::Get().SetKeyboardFocus Didn't do anything.
All the discussions on forums are for runtime. I am looking for editor to bring my SWindow to front in C++
The message dialog box shouldn't put it in the background... assuming you're using the right one.
FMessageDialogBox always returning to main editor widget after I click ok. I using this ```FMessageDialog::Open()
Yeah. That's the rgiht one.
Isn't it meant to return to the main edtor when you click okay?
no based on some conditional check, in my SWindow, I just using Messagebox to signify you doing something wrong. It shouldn't return to main window
I will take a quick video
Oh. So you open a second window, that window opens the message dialog and it returns to the original editor window, isntead of your new window, when it's done?
It's probably popping up the modal window on the main ue window.
You'll have to pop up your own modal window (with fslateapplication) on the window of your choice.
I will try that I have another question
Have you ever used std::initializer_list to minimize code duplication? Is this a good practice?
{
TSharedRef<SHorizontalBox> HorizontalBox = SNew(SHorizontalBox);
for (const auto& Element : Content)
{
//All the long repeated stuff
HorizontalBox->AddSlot()
[
Element
];
}
return HorizontalBox;
}```
```HorizontalField(
{
Snew(Something),
Snew(Something),
})````
it's at least not that bad right?
this method will save tons of lines because I will repeat 20 times
I don't know why you're using an initializer list, though, instead of just an array?
that becuse I calling the extracted method. I need to call many things HorizontalField( { Snew(Something), Snew(Something), })
I call first a slate then call another one for slots
I might construct all inside the function call scope
array will make everything complicated because I will have to define all in another place away from Slot's Square brackets?
No
could you give me an example
TSharedRef<SHorizontalBox> SAllCorridorTestWidget::HorizontalField(TArray<TSharedRef<SWidget>>&& Content)
{
TSharedRef<SHorizontalBox> HorizontalBox = SNew(SHorizontalBox);
for (const auto& Element : Content)
{
//All the long repeated stuff
HorizontalBox->AddSlot()
[
Element
];
}
return HorizontalBox;
}
HorizontalField({
SNew(thing),
SNew(thing)
});```
I maybe, maybe you can use an initializer list, but I don't know why you would.
(I really don't know the answer)
I think initializer list is much more flexible anyway many thanks \
Tf is this
Does TSharedRef<SWidget>... Content not work? I'm not super familiar with variadic templates
Nah, by Laura using auto here it treats it like a template and allows for variadic arguments, you cannot pack literal types like your example afaik. Like void Foo(int... i) could never compile but void Foo(auto... i) will, and by her constraining auto to a TSharedRef with the concept its just forces it to be of that type
I'll be sure to hire Laura via discord next time I need a template written
Theyre extremely useful and common, I just wish unreal had reflection support for them, you're stuck with wrappers or the manual way in most cases 
Want to make scrollbox working horizontal and vertical at same time like in texture editor, can someone direct me into a source I can read or give me general idea? I tried looking at the source code for texture editor to see how it is done but couldn't find it.
https://forums.unrealengine.com/t/two-ways-scroll-box/89955/4
Something like that might be of help?
Already looked into that and not suitable for my needs, thanks for suggestion though.
What I did was to make a widget that wraps an SCanvas and then you offset (and scale) the widget in the paint event, it doesn't have scrollbars though, but it's an infinitely pannable canvas which you can scroll.
For what I want that doesn't work and need the scrolls to work just like texture editor ( with panning when holding right click when zoomed in)
Yeah, it would take some fidgeting but you can do it, you need to override the 'OnMouseButton' down event and the 'OnMouseMoved' event then save some vector which represents your offset vector and use that to make a geometry child in the paint event
Yeah If i can't find any other method I will have to do it manually, ty.
Why not put one scrollbox inside the other?
One set to vertical, one to. Horizontal?
That doesn't work, it will only show the one at the top until you reach the end of the top one so not at the same time and ofc both have 'alwaysShowScrollbar' boolean set to true.
If you however open a texture and zoom in you will see both scrolls visible which is why I want to know how epic made it so I replicate the behavior
Go to the widget reflector. Target the thing you want to look at. Click the source code links.
It does work, but it's a but janky. You'd need to use an external scrollbar.
TSharedRef<SScrollBar> VertScrollBar = SNew(SScrollBar)
.Orientation(EOrientation::Orient_Vertical);
return SNew(SScrollBox)
.Orientation(Orient_Horizontal)
.ScrollBarAlwaysVisible(true)
+ SScrollBox::Slot()
.FillSize(1)
[
SNew(SScrollBox)
.Orientation(EOrientation::Orient_Vertical)
.ScrollBarAlwaysVisible(true)
.ExternalScrollbar(VertScrollBar)
+ SScrollBox::Slot()
.AutoSize()
[
SNew(SImage)
.DesiredSizeOverride(FVector2D(500, 500))
]
]
+ SScrollBox::Slot()
.AutoSize()
[
VertScrollBar
];```
Something like that.
Thanks I will start from here.
I've never used an external scrollbar and have no idea if that the entire setup you need.
Better having starting point than none, I will brute force my way as usual which I should be used to it by now.
๐
If you want to make it look a little less janky, you need that square at the bottom right.
Where the scrollbars don't overlap.
Yep
You can change the background color of the row if you use the whole row widget, maybe?
But that doesn't mean it won't be placed inside another widget which has a different background
FDetailWidgetRow doesn't even give you access to the row itself. It's just a collection of widgets which are added to the details panel by the internal code.
It'll be in the property editor module somewhere
A lot of this stuff is hidden from you. On purpose.
You can't change the style of the details panel.
You can change the style of the individual components, but not the overall design.
In a customisation?
Heh
You will be amazed how many production grade apps do the exact some thing you shared here
anyone know if there's an "easy" way to add a default details view to my dock tab of whatever UObject* I pass in?
I have one dock tab with a list of UObject's and I want to be able to open a details view of the selected UObject in the right tab, but I'm new to slate ๐
You should probably 1) statically define that name so that you don't create a new fname every time and 2) use GET_MEMBER_NAME_CHECKED instead of just a raw string.
I tried to figure this out but I'm a little lost, I have buttons (based on SColorBlock) and I want to open an SColorPicker window when they're clicked (and of course also get the new color value when they're closed), the documentation suggests that I shouldn't create a new widget with SNew but rather invoke 'OpenColorPicker' but it seems like OpenColorPicker is a private method of SColorPicker? So... uhm... how to I open the static color picker?
Use CreateColorPicker
Do I need an instance of FColorStructCustomization for that?
Ah, I'm super confused, I think I got plenty wrong in how I set things up, I didn't actually set up the color as a property it's just an FLinearColor variable in one of the class. When I try to invoke 'create color picker' I just see it's inaccessible from my widget, I think I need to better understand how to use the property viewers.
This sodesn't seem to work
Cool, after including #include <Runtime/AppFramework/Public/Widgets/Colors/SColorPicker.h> and the AppFrameWork module in the build file it seems to work
Thanks for the help!!
Np
"DialogueEmotion"
Yes. I know what it is.
I'm saying that using raw strings that is a bad idea.
GET_MEMBER_NAME_CHECKED(UYourClass, MemberName) is a much safer way. It means if you change the variable name, your code will no longer compile.
Until you update and fix it.
There's an IDetailLayoutBuilder::GetDefaultFont() or some such
I have a decorator class RichTextBockInlineDecorator. I successfully manage to change the color but not the style of the font when I apply the <span> tag can someone help me on this?
When using a SComboBox, is there a way to make it so that the combo dropdown's width remains the width of the widest item within it, instead of adjusting the width based on the width of the currently visible items?
Not with the numeric entry boxes on each end I don't think, but SSlider has range parameters
HEllo guys any idea how to make colors more readable (like twitch options) when given foreground and backbround color
"More readable"? A colour is a colour isn't it? Give it a colour chip and a name. Or just a chip.
It's like contrast and brightness I think but I don't know exactly (e.g. purple and pink)
Choose your own colours? Make them distinct?
You could just copy the twitch ones.
Epic also has a series of colours called the "style colors"
Such as EStyleColor::AccentRed
You can save that enum (so it's updated when Epic change things) or use FSlateColor(EStyleColor::AccentRed).GetSpecifiedColor() to get the current underlying colour.
I am copying twitch ones, thing is you can activate a parameter to make them more readable since any user can actually choose any color they want, some very bright or very dark colors might not be easy to read.
You could use the Value of the HSV (you can convert to that) to get a baseline of the intensity.
Wrap colours with low V in a white outline, colours with a high V in a black outline.
V is basically just max(r,g,b)
I don't see the range parameters in SSlider as you mentioned
SetMinAndMaxValues
Why is the Widget Detail panel in Widget Reflector always empty no matter what widget I am looking at?
Shrug
I wonder how hard would it be to get Doom to render into a Slate component lol
Was thinking that would be pretty funny, just drop Doom into a random extension point in the editor lol
Pretty "easy"
It's just a viewport into a world, like the level viewport.
Just take a lot of faffing to set up the world and the viewport
Yeah I remember the recent Doom-talks, but I don't think they were trying to embed it in Slate as a joke? lol
I have GetDefault<UFooSettings>() that store my settings.
I want to use SNew(SProperty, ...) but I'm in a custom window (SCompoundWidget). I want to show a bool property from a custom CDO.
I retrieve the FProperty like this :
FProperty *Property = UFooSettings::StaticClass()->FindPropertyByName(GET_MEMBER_NAME_CHECKED(UFooSettings, BarProperty));
but the SNew(SProperty, ...) needs a IPropertyHandle but I don't know how to get it.
It's really, really, really, really, reaaaaaaaaaaaaaaally shitty to get IPropertyHandles.
If somebody can tell me a simpler way, I'll give them many beers.
Basically you need to use the property editor module to create a property row generator. Use that generator's root node to traverse the property tree until you find the one you want and then create a property handle from the detail tree node. You also need to store strong refs to the detail tree node that you got the handle from and probably the property row generator used to create them.

The only alternative I know is to implement the IPropertyHandle interface yourself
It can be done, but it's just a lengthy process.
There's a lot of methods.
FPropertyEditorModule* Module = &FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
const FPropertyRowGeneratorArgs Args;
TSharedRef<IPropertyRowGenerator> Generator = Module->CreatePropertyRowGenerator(Args);
TSharedPtr<IPropertyHandle> Handle;
for (TSharedRef<IDetailTreeNode> DetailTreeNode : Generator->GetRootTreeNodes()) {
if (???) { // Idk what to put here
Handle = DetailTreeNode->CreatePropertyHandle();
break;
}
}
like this ?
but I don't know what is the condition to find the corresponding detailTreeNode
https://gist.github.com/Daekesh/37055b78f2716e30bcbd154fba75d17f is an example I did recently.
I'll take a look
Anyone here know if there's some way to keep the Slate widget from IMoviePlayer on screen after loading finishes?
I'm currently trying to just add it manually to the viewport, but it causes a noticeable flash as the level loads and the widget scale is also different between the movieplayer and viewport
The reason I want to do this is because I have actors that need to do some initialization after they load in, so even though the level has technically finished loading, it isn't quite ready yet, so I want to keep the loading screen visible
My best solution so far... Viewport->AddViewportWidgetContent, wait for the next tick so it renders, then begin loading level. Seems to avoid the flash, but the scale is still off
Can you sort the scale using the tickspace geometry on that next tick?
I need to execute a function when SWindow is closed.
Before I always handled with deconstructor but now it doesn't execute when I close the window
I looked everywhere and couldn't find anything OnWindowClosed, how can I invoke something when the window closed
The destructor should be called unless you're holding a strong ref to it somewhere...
my widget crash when open is there way to open without compile so it not crash
?
Without compile?
Hmm will have to try it out
I'm using a FCurveSequence to animate the render transform of a widget that I'm displaying during level loading. It all works for the most part, but for some reason the animation immediately jumps to the final frame in Standalone game. It works perfectly fine in "normal" PIE. Are there any gotchas with this I should be aware of that could be causing this?
Basically I'm just triggering Animation.Play(AsShared()) once the level has loaded to play the animation out, and in my component's Tick, I calculate the desired position from the GetLerp() value
In PIE, it plays out smoothly, but in Standalone, it just instantly disappears
I would add some logging ๐ฆ
Yeah currently doing that but figured I'd ask if there's something typical with this
I'm using the animation to first slide the widget in, so it lerps from 0 to 1, then load the level, then play it again to slide the widget out... it lerps from 0 to 1 correctly in PIE at the slide out stage, but in standalone it immediately starts from 1 and the animation ends. Not sure what's causing that just yet
Hmm okay it seems to be some kind of a timing issue with the loading I think...
If I set a long enough timer for triggering the animation after loading, it plays out... It doesn't work from next tick so not quite sure what is the right way to do it, just setting an arbitrary 5 second timer seems completely wrong...
I imagine it's because everygthing is already loaded in PIE because it's all loaded in the editor.
Or near enough.
Yeah. I'm trying to find if there's some other delegate that would fire later after switching levels, hopefully when whatever it is still doing is done
Currently using PostLoadMapWithWorld which at least so far seems to be the last delegate that fires
I think I solved it but posted it on #cpp message as I think I'd have more luck getting someone telling me "no don't do that" on #cpp lol
I had initalzied SWindow as member variable, I changed to be local and now destructor called when I closed the editor. Thank you
It can be a member var if you want, you just need to reset it when you're done. But there's no point it being a member var unless you need to access it from somewhere else.
Hello, How can i change image of a button via button ref in blueprint ?
I'm trying to make a slate editor window for an editor plugin and I found documentation on slate to be pretty limited. E.g. I want to create a drop-down menu of checkboxes but I'm struggling on finding info to achieve this. Is it really just a matter of jumping into source code and figuring it out?
Pretty much, yes.
Taek a look at FWorkflowCentricApplication - your editor should extend from that.
Check out subclasses of that to see where stuff is used.
Hint: You can track back how things are added to the editor by checking tooltips on things, look for those tooltips in code, find out where the associated objects are used, etc.
Or FBaseAssetToolkit, the parent class.
Or its parent classes.
Is that a recommended strategy for working on large projects in general? Start at a class high in the project's class hierarchy and work your way through subclasses to find relevant code?
I suppose I could also look through the engine's files in the Editor dir
Going through the editor stuff just at random is going to take years.
Maybe try using the slate widget reflector to see what the widget is for the menu.
I'll have a look
Btw, is this what you meant with your original message?
Pretty much
is using .IsChecked() for determining Checkbox state inefficient ? ( for a very large number of them ofc)
Using it how?
Because that's basically how it checks if it's checked. You can supply a callback or a static value, either way it's checked every frame.
as a callback
Is there a way that I can ensure my text is always filling the box like the way images do
no matter the alignment they just use the absolute size that is defined in font
Calculate the size of the text and then set the scale each tick? Something like that.
I'm trying to construct a list of SScrollBox but when I add it to the child slot, I get an error as seen in the image.
void SAssetCleanupWindow::Construct(const FArguments& InArgs)
{
TSharedPtr<SScrollBox> AssetTypeMenuItems = SNew(SScrollBox);
for (FCustomAssetMapping Asset : AssetMapping)
{
AssetTypeMenuItems->AddSlot()
.Padding(3.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(SCheckBox)
.OnCheckStateChanged(FOnCheckStateChanged::CreateSP(this, &SAssetCleanupWindow::OnBlueprintCheckStateChanged))
.IsChecked(this, &SAssetCleanupWindow::GetBlueprintCheckState)
]
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(STextBlock)
.Text(FText::FromString(Asset.AssetName))
]
];
}
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(10.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString("Include asset types:"))
]
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
[
SNew(SComboButton)
.ButtonContent()
[
SNew(STextBlock)
.Text(FText::FromString("Select Asset Type"))
]
.MenuContent()
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
[
AssetTypeMenuItems // Gives error
]
]
]
]
];
}
In the engine code they have the following example which looks similar to mine but with a different slate type (SVerticalBox)
void Construct( const FArguments& InArgs )
{
TSharedRef<SVerticalBox> VBox = SNew(SVerticalBox);
for (int RowIndex=0; RowIndex < 15; ++RowIndex)
{
VBox->AddSlot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
MakeRow(15)
];
}
this->ChildSlot
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.FillWidth(1.17)
+SHorizontalBox::Slot()
.FillWidth(1.0f)
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.FillHeight(1.17)
+SVerticalBox::Slot()
.FillHeight(1)
[
VBox
]
]
];
}
TSharedPtr is not TSharedRef
Do .ToSharedRef()
In fact, just change the type of your variable to TSharedRef.
Do you know how can I FontHandle->SetValue() ? FontHandle is a property handle for a struct property and SetValue doesn't have a override version for that ?
Cast it to an FStructPropertyHandle?
If that's possible.
Something will have a setvalue.
(I'm thinking of FProperty...)
Tht
and how to convert struct to string then?
lemme check in engine source
StructProperty->Struct->ExportText(TextValue, &NewSubjectKey, PreviousValue, nullptr, EPropertyPortFlags::PPF_None, nullptr);
so clear
the handle for the property requires the property which it was supposed to handle
Struct Property Handle (For feature guys)
FStructProperty* StructProperty = CastFieldChecked<FStructProperty>(FontHandle->GetProperty());
TArray<void*> RawData;
FontHandle->AccessRawData(RawData);
FSlateFontInfo* PreviousValue = reinterpret_cast<FSlateFontInfo*>(RawData[0]);
FSlateFontInfo NewFont = Font;
FString TextValue;
StructProperty->Struct->ExportText(TextValue, &NewFont, PreviousValue, nullptr, EPropertyPortFlags::PPF_None, nullptr);
ensure(FontHandle->SetValueFromFormattedString(TextValue, EPropertyValueSetFlags::DefaultFlags) == FPropertyAccess::Result::Success);
It might be better to use the struct property, not the property handle, to get and set the property.
shrug
I'm trying to move the combo button in the center of the image to the left so it is right next to the text, however I can't get it to work. I have tried the attributes here https://docs.unrealengine.com/5.0/en-US/slate-ui-widget-examples-for-unreal-engine/
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString("Include Asset Types:"))
]
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
[
SNew(SComboButton)
.ButtonContent()
[
SNew(STextBlock)
.Text(FText::FromString("Select Asset Type"))
]
.MenuContent()
[
]
]
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.HAlign(HAlign_Right)
[
SNew(SButton)
.Text(FText::FromString("Start Cleanup"))
.OnClicked(FOnClicked::CreateSP(this, &SAssetCleanupWindow::OnStartCleanupButtonClicked))
]
Are there attributes of the SHorizontalBox that I have somehow missed that can help me achieve this?
It's because it's sharing the space between the elements.
Add .AutoSize() to your first slot
Make a custom subclass and intercept on click?
Or on mousebuttondown/up whichever it uses
You'd stop it opening the menu entirely...
You want to stop it opening an empty menu for a couple of frames?
So stop it opening the menu when the list is empty.
It does that when you click the button.
So intercept the flow from click button -> open menu.
A TSharedPtr will never "go null". It's a strong pointer. It keeps the things it's referencing alive.
To use a shared ptr in the first place.
How do you know it's being reset?
Have you checked that it's not the object containing the shared ptr that has been destroyed?
And have you checked if the owner of the shared ptr is valid?
((FSomeClass*)nullptr) ->SomeSharedPtr.IsValid() could also return false.
Or it could be entirely trash data.
Hello, (hoping not to interrupt)
I'm implementing a custom graph editor via subclassing UEdGraph and related classes. I am wondering if there is a way of dragging a pin out of a node via node's context menu action. I can fire the custom command without a problem, but I cannot start the dragging process. For instance: User clicks "New Link" from the context menu and a pin is displayed behind a cursor simillar to as if the user was dragging it out of a node's output pin.
My findings / ideas:
There is a functionality in SGraphPanel displaying PreviewConnectorFromPins, but the PreviewConnectorEndpoint is private and can only be manipulated from within a FDragConnection drag drop action. I thought about subclassing SGraphPanel, but its instantiation seems to be hard-coded in SGraphEditorImpl. I also tried creating an FDragConnection (subclass) instance, but the preview pin is stuck either at 0,0 or near the center of the screen and wouldn't update.
Does anyone have a different idea or can suggest an approach I could try? Thanks in advance.
Maybe different question: Is there a way for me to change the SGraphPanel to a different class?
I saw that one could make a custom factory for Nodes, Pins and Connections, but I cannot find simillar one for SGraphPanel.
I would look at why the connector is stuck at 0,0 or the centre. Add some debug to the engine to see what happens with the original FDragConnection and then to your own subclass to find the differences.
That should be the way to do it.
On this I have no idea. ๐ฆ
Not many people make custom graphs... let alone custom graph panel classes ๐
I'll try to recreate it. It's been over a week since I last tried that specific approach and I believe that my understanding of the system is a little bit better now, so I might be able to see more this time.
Thank you ๐
Good luck
I think I narrowed down the issue. My subclass does not trigger SGraphPanel::OnDragOver and I get a lot less method calls than the original DragConnection class. (for instance OnDragged method of my operation is not being called)
I suspect that this might be connected to my initialization.
I've read that one would usually do it from OnMouseDown/Up, return FReply::Handled() with DetectDragDrop or BeginDragDrop called on that reply. I am trying to do it from a context menu (just a simple method called by a delegate) and I'm just calling a static ::New(...) method of the operation and storing a TSharedPtr to it, so I might be missing some important step.
Ah, btw. I'm learning a lot through browsing this channel and your replies to people's questions. Thanks for that too.
Np!
I'm doing some property type customizations, I have a customization on my type FExample, but if I have a TArray<FExample>, it appears to lose the default array UI markers, like Index [0] > ... etc.
How do I get them back?
(Basically I'm just trying to take properties from a child struct of FExample, and display them "inline" instead of showing the nested bits it normally does)
Nevermind- I probably should have implemented the CustomizeHeader function with CreatePropertyNameWidget and CreatePropertyValueWidget first :P
๐
@grave hatch hello Its me again I was speaking with you earlier in regards to drag drop for file explorer to application, im running into an issue and any help would be appreciated if possible. Apart of my widget class im trying to override the native on drop function but its not firing, when i click in the file explorer to select and drag the file my ue5 application loses focus and i think thats why. You said this approach is possible and would like to know your approach and perspective on how to approach this, also in my widgets i set them to visible and IsEnabled = true. Thank you
Have you checked that NativeDrop is called in the base class?
As I said, I have no idea about UMG. I don't use it.
im not sure i did, i dont think it will be called because the application loses focus, if im wrong could you correct me?
actually @grave hatch im incorrect, that only deals with game drag drops not external, if i may ask what class where the functions OnDragDrop apart of, SWidget?
The application is always going to lose focus when you start a drag+drop from outside
I believe they are in swidget, yes
im thinking about just making an SWidget and stylizing it like I have styled my User Widget, because all of this communication crap is not worth it so ill ditch the userwidget
๐
What is the actual difference between a border and an image?
For example I have a button and i want the button to have an icon, should i use a border or an image to apply my icon texture to?
I think the main difference for me is that the border can accept children and the image cannot. I also noticed that the border has more events (Mouse Button Down, Up, Mouse Double Click and Move vs only Mouse Button Down in image), but I might be missing something.
I think I'd use a simpler one if I don't need the additional stuff.
And just in case: You can take a look at ButtonStyle, it has a few places where you could set an image too (Normal, Hovered, Pressed, Disabled)
Update: I managed to create my drag drop operation from a custom context menu entry's OnMouseButtonDown and everything is working fine, the only thing left for me to do is letting the user lift the mouse button after pressing the context menu option haha, because for now it feels awkward.
Is there a way to prevent a drop when releasing a mouse button?
I feels like the OnDrop is triggered externally and not by the dragdrop operation itself, so I dunno if it's possible to prevent it. The ugly solution I thought of is forcing the window out of focus (when the breakpoint is hit, user can drag no problem), but I'm kind of reluctant to do that right now, since there might be an easier/cleaner way.
I think I might be able to ignore the input in AffectedByPointerEvent()... I just need to debug why the connection widget disappears ๐
A border is a 3x3 grid too
@grave hatch so i got the right data. Inside the OnDrop function im trying to get the game instance so that way i can set the savegame instance. Im having a hard time. if you could help that would be appreciated UTexture2D* Texture = FVisualSaveModule::LoadTextureFromFilePath(FileName); UVisualSaveGame* SaveGame = FVisualSaveModule::LoadGameFromImage(Texture); UVisualSaveBpLibrary::GetVisualSaveGameInstance()->CurrentSaveGame = SaveGame; return FReply::Handled(); this is the getter```UVisualSaveGameInstance* UVisualSaveBpLibrary::GetVisualSaveGameInstance()
{
if (GEngine)
{
// Get the primary game world context. This works in a game environment.
UWorld* World = GEngine->GetWorldFromContextObject(GWorld, EGetWorldErrorMode::LogAndReturnNull);
if (World)
{
return Cast<UVisualSaveGameInstance>(UGameplayStatics::GetGameInstance(World));
}
}
return nullptr;
}```
What appears not to be working?
i got it never mind, i was trying to get the game instance so i took what Laura said and passed in a world contextobject, pased that into my slate widget construction and it works
my whole goal was to override the save game object
For the record: SGraphPanel called OnStopMakingConnection with force from OnHandleLeftMouseRelease. Since I can't modify SGraphPanel directly, I settled for calling OnBeginMakingConnection again after a short delay. It's not the cleanest solution, but I'm glad I figured it out. Thanks for all the help ๐
Yeah, I did ๐ Later I just need to click on the thing I want to drop on ๐
hey all, I am new to learning slate and was wondering if there are an good resources on learning it. Also how do I dynamically set the visibility of a slate widget for example if a propert is not null then show the widgert
Pass something to the Visibility parameter
Slate works a lot on 3 different kinds of parameters: arguments (just values), attributes (values or delegates) and events (just delegates)
Visibility is, luckily, an attribute, so you can either just turn it on or off (or set it any time) or make a delegate that it will poll every frame to determine visibility.
Things like button styles or what not tend to be arguments (they can't be changed after construction)
Things like on click events are... events.
I find a lot of value in looking at some plugins other people made and sometimes seeing how it's done in the engine. Other than that, just found some very specific articles on the things I wanted to do.
I noticed now, there are some pinned links in this channel too, they can be worth checking out ๐
Thanks guys, is there an SWidget I can use to just draw the default property drawer for a struct?
or rather how to draw what is show in the details panel for a struct in my custome ditor window
i cannot help much currently, but take a look at classes implementing IDetailsView. If you still need help by Monday, tag me
There might be some examples in classes inheriting from FAssetEditorToolkit too
I think I'd take a look at Generic Graph source code at github and look there
Thanks alot @woven cave Will check that out
@maiden sparrow you'd use hte propertyeditor module. It has a method for getting a struct's detail view
Thank you @grave hatch , Managed to figure it out lookign at the reources Mromru talked about
I have a custom slate widget that contains an arbitrary amount of child widgets as slots. When I add two overlays to this custom widget, each overlay containing a set of image widgets. I thought it'd draw the first overlay with all of its children before it draws the second overlay. But in my case, images from both overlays are drawn at the same time causing images to be interleaved even though they have different parents.
Could this be due to my OnArrangeChildren implementation? But it doesn't make any sense to me. I thought I shouldn't care about children of slotted widgets directly.
Ok, I needed to override OnPaint with the same implementation by SOverlay. My slate widget derives from SPanel but apparently the base implementation doesn't handle child widgets correctly. But I'm not understanding exactly what SOverlay does to fix this issue.
Ok I figured out why. I think it's a bug in SPanel's implementation. https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Runtime/SlateCore/Private/Widgets/SPanel.cpp#L30C124-L30C131
On line 30, LayerId is passed, but it should be MaxLayerId. Copying the implementation then passing in MaxLayerId instead fixed my issue.
That's by design, SPanel doesn't do explicit ordering because it's much more expensive to draw. SConstraintCanvas provides an explicit ZOrder for that reason.
That can be turned off if you want cheap canvases, though.
Is there anything that I have to do for Slate Widgets to scale similarly to how UMG does it?
I created a Widgets in Slate to use it as a proper LoadingScreen, but the scaling doesn't seem to work that well.
It's bascially stuck at fullscreen size and if the window is made smaller, it starts overlapping.
The UMG version scales everything down.
Is there some builtin way to have a SWindow remember its size across editor restarts similar to how builtin windows do? Or does this need to be manually managed somewhere such as in the window's Construct and OnPaint to determine the active size since there doesn't seem to be a resize event anywhere?
Check out what underlying widget umg is using as as base.
mabye an SBox? That's the size box umg uses I think.
Or SScaleBox maybe? I'm sure there's something like that.
@grave hatch @orchid nova It's the MoviePlayer itself that is at fault
I searched for the wrong stuff. My partner found some answers via Google.
float FDefaultGameMoviePlayer::GetViewportDPIScale() const
{
return ViewportDPIScale;
}
That's always 1.0
Classic DefaultGameMoviePlayer
It needs to return the DPI Scale based on size
Sadly the function isn't virtual
but on this project we have source, so w/e
if (MainWindow.IsValid())
{
const FVector2D ViewportSize = MainWindow.Pin()->GetClientSizeInScreen();
return GetDefault<UUserInterfaceSettings>()->GetDPIScaleBasedOnSize(FIntPoint(ViewportSize.X, ViewportSize.Y));
}
This is why I set up a custom system to put a widget directly into the viewport instead of using it, it's just too much trouble lol
That's the only trouble I had so far
Although in my case the widget doesn't animate during loading, which would probably be more complicated to set up for a manual solution
The only remaining thing I wonder about is how I would add a Key to go to the next Tip
Ah, yeah the issue I was having is that you can't block the movie player from exiting once the game has loaded the world, if there's any input the movie player will just go away
I assume I need to hard code the key in one way or another
Cause Slate def doesn't support input actions
which makes it so that I can't do my own initialization and keep the loading screen visible until I'm done
I'm not sure that's still the case
I have the Loading Screen forced on the screen since I started implementing it
DOesn't matter what keys I press
I know the level is loaded in the BG already
Do you have an actual video clip playing also?
No, it's a Widget
Really, I just could not get that working at all
Ah ha. Well that's fun.
No matter what settings I gave the movie player it would always exit if there was input
Doesn't do anything
What if you press a key instead of mouse?
KB = Keyboard
Oh right somehow missed that lol
You know, I really wish they'd just gone with an html interface like most people these days ๐
FLoadingScreenAttributes LoadingScreenAttributes;
LoadingScreenAttributes.bAutoCompleteWhenLoadingCompletes = false;
LoadingScreenAttributes.bWaitForManualStop = true;
LoadingScreenAttributes.MinimumLoadingScreenDisplayTime = 5.f;
LoadingScreenAttributes.bMoviesAreSkippable = false;
LoadingScreenAttributes.WidgetLoadingScreen = GetLoadingScreenWidget();
GetMoviePlayer()->SetupLoadingScreen(LoadingScreenAttributes);
It works and it's relatively fast...
Yeah those are basically the same settings I was using ๐ค
I would love to somehow forward a keypress to it
I just didn't have a minimum display time
I can listen to KeyDown in the Widget, but that's of course nothing I can rebind I guess
Unless I can pass it an InputAction + IMC
And pull the Key out of that
๐ค
Ah well, different issue
Maybe an input preprocessor woudl help?
The problem is more the definition of the key to press
void SomeInputEvent(FKey Key)
{
if (Key == ???)
{
}
}
Doing that in the Widget or the PreProcessor wouldn't change
You can examine the keybinds via slate, surely?
Keep in mind how early those LoadingScreens play
I'm not sure the PlayerInput stuff is ready
Will have to test
Hm, OnKeyDown doesn't even seem to trigger in the Widget
Ah well, I will leave that for now
Topic: using the Tab key to open/close a menu widget.
This seems so stupid, is there really no way of disabling tab as key to toggle between widget elements apart from basically globally disabling it in the player controller on begin play? Why on earth wouldnt there be project settings for this?
Also, where the heck are menu inputs defined? All I can find is all inputs I add counting as โgameโ inputs
For along time, and with slate especially, there is no real UI input, despite the obvious KeyDown stuff
With UMG, which you should use most of the time unless you have a very good reason to use Slate instead for some of your UI elements, you can by now start utilizing CommonUI (official Plugin) which allows combining enhanced input with your UI for input
I see, so there is no really way to define any inputs, and I have to bind to the enhanced input action I want to use on the widget specifically, if I want to use โMenuโ input mode?
Despite the default navigation that you already encountered ,no
Eh yes I guess
In Widgets, may it be Slate or UMG, inputs are routed directly from the viewport to the widget (+- focus stuff). There is no InputComponent in between as it is with Characters and Controllers.
You have the InputKeyDown etc events that give you the naked key
Which you can of course compare to something and do your stuff, but it's pretty hard coded that way
You can also use Input preprocessors to maybe get around the Tab button being consumed
I think there might also be away if one digs through the code a bit to find the part where they more or less hard code that
With UMG, CommonUI and InputAction you get a more Gameplay like setup
With widgets being able to push Input mapping contexts and binding to input actions
That's how we handle or esc button to close the menu
And generally also the back input fwiw
CommonUI also has an action button bar or something like that that considers all input actions currently bound in the menu and creates buttons for them iirc
So if you need something like that you gotta step away from slate afaik
Yeah I ended up exposing NavigatinConfig Settings to BP and setting the tab navigation on the player controller.
The widget is common ui, the slate part was only the tab consumption, as far as I could tell.
But thanks, have a few pointers to try and implement the rest of it, appreciate it ๐
Sorry, noobie here!
Is there any way to display an HUD -type text when I take a HighRes Screenshot from the editor (not in game mode)?
I have an SOverlay, and I manage to display it in the editor with LevelViewport->AddOverlayWidget(RenderHUD->AsShared());, but it doesn't show in the Screenshot. I'm wondering what viewport I can add my SOverlay to so that it would show up. Or do I just have to add a TextRenderComponent to the scene in place it in front of the camera?
@obsidian lynx This sounds like the same thing as the photo-finish in Epic's Platformer Game Demo. It's a simple platformer game in which a photo-finish completes the run with the time indicated on the screenshot. It's all blueprint of course, but maybe you could translate this in slate. Video: https://www.youtube.com/watch?v=f-mo4XynkxA Project: https://www.unrealengine.com/marketplace/en-US/product/platformer-game
Follow along to hear about upcoming Unreal Engine events in Montreal, Boston, and London, and watch Sr, Designer Jim Brown cover a number of aspects about the Platformer Game sample content, now available for download!
[0:00] Intro
[0:23] Zen Garden
[1:22] Marketplace Update
[2:12] Events
[4:47] Community Spotlight
[8:36] Boston FIG/MIT
[12:20]...
I have a question regarding SSlider. I've created a SSlider to modify a value in an actor component. Moving the slider updates the value in the component, but its effect on the editor with only happen when I release the slider. If I use my mouse to scroll up and down the component value, the editor will react immediately, but the slider as a means to drive that number up and down ? Nada.
Are you binding to OnValueCommitted or OnValueChanged?
The slider doesn't cause committed to fire until you stop sliding
@grave hatch OnValueChanged.
Are you calling GEditor->RedrawLevelEditingViewports(); ?
Ah ... no. At each OnValueChanged call ?
Yeah
np
Thank you for this @keen rover ! However, I'm looking for a way to include a slate HUD within the High-resolution Screenshot that you take from the editor, not from within the game.
I've made a function for simulating mouse button clicks in c++ after not being able to find anything online for how to do so. I would love to hear any feedback on approach or refactor opportunities for it before I paste it to unanswered forum posts. My personal use case was trying to interact with widgets when controlling a mouse with a gamepad.
Pastebin: https://pastebin.com/QqsTYYkv
Pastebin
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
~~What slate widget is this picker? https://files.trdwll.net/2024/02/IH9cm7.png~~
Possibly the SObjectPropertyEntryBox.
tools -> debug -> widget reflector -> hit the button at the top-left and hover over the widget you want to know about and hit escape
Then examine the widget reflector.
(for future reference anyway, you're probably rigth about that one)
How do FPointerEvents get updated? I don't see any setter functions for ScreenSpacePosition and it points out "Events are immutable once constructed." But, for example, with drag and drop it's calculating PointerEvent.GetScreenSpacePosition() - ScreenSpaceOrigin. If it was immutable, wouldn't this always have the same result?
I see "a constructor to alter cursor positions" and another MakeTranslatedEvent function but these both make new events with the original's values.
A new event is fired each tick
Any good slate tutorial to recommend?
Im a newbie who just started tool programming and im completely lost
The pinned messages are a good start.
Is there a way to manipulate the size and alignment of ToolBarButtons?
FToolBarBuilder ToolbarBuilder(TSharedPtr<FUICommandList>(), FMultiBoxCustomization::None);
FUIAction(FExecuteAction::CreateSP(this, &OnClickNewButton)),
NAME_None,
LOCTEXT("New", "New"),
LOCTEXT("Create New System", "Create New System"),
FSlateIcon(FAppStyle::GetAppStyleSetName(), "MainFrame.NewProject"));```
Not really. You could add a widget instead of a button and do it manually, but yeah.
So use AddWidget with a SBox instead of AddToolBarButton?
Thank you!~
+1
np
Hello there! I'm trying to create an editor window tab with docktabs and im following SessionFrontend as an example. I run into a problem though..
when i try to declare and implement the Construct with 3 arguments:
void Construct( const FArguments& InArgs, const TSharedRef<SDockTab>& ConstructUnderMajorTab, const TSharedPtr<SWindow>& ConstructUnderWindow );
I get the following error:
0>DeclarativeSyntaxSupport.h(732): Error C2660 : 'SMyEditorWindow::Construct': function does not take 1 arguments
0>MyEditorWindow.h(28): Reference : see declaration of 'SMyEditorWindow::Construct'
0>DeclarativeSyntaxSupport.h(732): Reference : while trying to match the argument list '(const SMyEditorWindow::FArguments)'
0>DeclarativeSyntaxSupport.h(970): Reference : see reference to function template instantiation 'void RequiredArgs::T0RequiredArgs::CallConstruct<SMyEditorWindow>(const TSharedRef<SMyEditorWindow,ESPMode::ThreadSafe> &,const SMyEditorWindow::FArguments &) const' being compiled
0>DeclarativeSyntaxSupport.h(968): Reference : while compiling class template member function 'TSharedRef<SMyEditorWindow,ESPMode::ThreadSafe> TSlateDecl<SMyEditorWindow,RequiredArgs::T0RequiredArgs>::operator <<=(const SMyEditorWindow::FArguments &) const'
0>MyEditorWindow.cpp(89): Reference : see reference to function template instantiation 'TSharedRef<SMyEditorWindow,ESPMode::ThreadSafe> TSlateDecl<SMyEditorWindow,RequiredArgs::T0RequiredArgs>::operator <<=(const SMyEditorWindow::FArguments &) const' being compiled
0>MyEditorWindow.cpp(89): Reference : see reference to class template instantiation 'TSlateDecl<SMyEditorWindow,RequiredArgs::T0RequiredArgs>' being compiled
Does someone know how this is achieved?
Edit: I'm using 5.2
Are you doing SNew(SMyEditorWindow) ?
If you add parameters to the Construct function you need to add them to your SNew call as well.
TSharedRef<SDockTab> FMyEditorModule::CreateKOCEditorTab(const FSpawnTabArgs& Args)
{
const TSharedRef<SDockTab> DockTab = SNew(SDockTab)
.TabRole(ETabRole::MajorTab);
const TSharedRef<SMyEditorWindow> Frontend = SNew(SMyEditorWindow, DockTab, Args.GetOwnerWindow());
WeakFrontend = Frontend;
DockTab->SetContent(Frontend);
return DockTab;
}
I copied the approach used to new the SessionFrontend here as well
@grave hatch thank you for your help. I did not realize i had some old code calling it 'SNew' with only the Type... now i feel dumb ๐ค haha
๐
Template errors can get... annoying.
Awlays find the errors from your own code files and ignore the engine fi les.
indeed.. ๐
For an SButton, what is the difference between .OnClicked and .OnClickedRaw?
difference is that the .OnClickedRaw is used when you need to access the details of the click event itself for more complex interactions. It gives you more detailed information about the click event but requires you to manage the function binding's lifetime manually. The .OnClicked doesn't require any arguments and doesnt return any value also it makes it easy to manage the function call's lifetime and ensuring that the function exists when called.
@silent thicket
@grave hatch apologies for the ping but remember the assistance you gave me with drag drop events? if the drop function returns unhandled i get this message LogActorFactory: Actor Factory attempting to spawn ImgMediaSource /Engine/Transient.ImgMediaSource_0 LogActorFactory: Actor Factory attempting to spawn ImgMediaSource /Engine/Transient.ImgMediaSource_0 LogMediaPlate: Warning: Could not play anything. LogActorFactory: Actor Factory spawned ImgMediaSource /Engine/Transient.ImgMediaSource_0 as actor: MediaPlate /Game/ThirdPerson/Maps/UEDPIE_0_ThirdPersonMap.ThirdPersonMap:PersistentLevel.MediaPlate_0 LogActorFactory: Actor Factory spawned ImgMediaSource /Engine/Transient.ImgMediaSource_0 as actor: MediaPlate /Game/ThirdPerson/Maps/UEDPIE_0_ThirdPersonMap.ThirdPersonMap:PersistentLevel.MediaPlate_0 LogWorldSubsystemInput: UEnhancedInputDeveloperSettings::bEnableWorldSubsystem is false, the world subsystem will not be created! LogWorldSubsystemInput: UEnhancedInputDeveloperSettings::bEnableWorldSubsystem is false, the world subsystem will not be created! it spawns an actor in the world that looks like a black rectangle, how can i prevent this, now the solution is to return handled but i dont want to do that
it seems to happen when i also drag and drop an image in the game as well
That works thank you
i thought this was a slate question but aparently it was not, thank you
@grave hatch I also have a question if you dont mind me asking. How did you become proficient at tool development?
Years of experience? ๐
When I started out I was not as good as I am now. Years of working with UE and specifically on tools and I think I'm quite proficient now.
You really just have to go stuck in and use the engine in all kinds of ways.
We (the team I work with) frequently break the engine because we use things in unexpected ways.
You just learn a lot doing stuff!
What sparked your interested in tools?
I got a job offer in tool development ๐
how do you like it?
I like it!
Hello guys ๐
How can i center a widget inside a FToolBarBuilder?
Put it in an sbox with vertical align set to center?
Uhm, it doesnt work
Why if i use an SBox it gets automatically wrapped into a SHorizontalBox?
Solved.
I was using .AddToolBarWidget instead of .AddWidget.
Apparently the .AddToolBarWidget does something under the hood which ends up wrapping my widget in additional stuff.
Ah ha.
Am I just missing something or are a lot of editor slate widgets annoyingly private? I just want to add a class picker like this but SPropertyEditorClass is declared in a private header
Context is I'm making a factory configuration prompt and I didn't want to have to make a whole UObject just to make a details panel
Ya, Slate widgets in general are WAY too private when there isn't an inherent need for them to be. Makes doing a lot of things super hard.
IMO, Epic should really stop making things private for our own safety when it's ultimately our own responsibility whether some custom code we write breaks or not.
It makes me wonder how much of it really is "Oh I didn't think about it" because for their own needs they're working on the engine source anyway :P
Like the widget used for displaying the blueprint search window was randomly made public in UE5 but exists in 4 as private
If they're public they are of the view that they cannot be changed and must be maintained.
So they make as little stuff as possible public.
I suppose that's one reason for it ๐ค
maybe silly question but what's the best way to make an 'asset picker' drop down in Slate? in BP the most convenient way is to use a single property viewer and it's definitely possible in my case as well but as this combobox is shown in a slate widget the field I'm trying to manipulate is currently not marked as a Uproperty at all.
Definitely possible to populate a combobox or even to extend it, but in BPs I can do it with one widget, I feel like I'm drawing a blank here.
(it's for an editor widget usecase)
SAssetDropPicker ... always use the reflector before running to discord. I should remember that.
๐
Is there a way to tell a GridPanel to add items in a specific order? I want to add things in alternating columns, like this:
1 | 2
3 | 4
5 | 6
7
Do I have to do something like if(GridPanel->GetChildren.Num() % 2 == 0) { AddToFirstColumn() } else { AddToSecondColumn() }? If possible, I'd like to just define a rule on the GridPanel itself.
The former
Or just GridPanel->AddSlot(GridPanel->GetChildren().Num() % 2, row)[ stuff ]
You could do GridPanel->GetChildren().Num() / 2 for the row, it should come out with 0 0 1 1 2 2 etc
How do I get a Widget in a ChildSlot to change without rebuilding it?
// .H
class SSomeSlateWidget : public SCompoundWidget
{
TSharedPtr<IPropertyHandle> SomePropertyHandle
TSharedPtr<SWidget> ContentWidget;
void Construct(...);
void SomePropertyValueChanged();
};
// .CPP
void SSomeSlateWidget::Construct(...)
{
SomePropertyHandle->SetOnPropertyValueChanged(FSimpleDelegate::CreateSP(this, &SSomeSlateWidget::SomePropertyValueChanged));
ContentWidget = SNullWidget::NullWidget;
ChildSlot
[
ContentWidget
]
}
void SSomeSlateWidget::SomePropertyValueChanged()
{
uint8 SomePropertyValue;
SomePropertyHandle->GetValue(SomePropertyValue);
if(SomePropertyValue == 0)
{
ContentWidget = SNew(SSomeDifferentWidget...);
}
else
{
ContentWidget = SNullWidget::NullWidget;
}
}
This is what I thought would work.
Swapping the ContentWidget when I need it to change based on a property value changing?
But this doesnt work. Im wondering how I am supposed to manage this instead?
Essentially I just want to display a different Widget based on the value of a Combo box.
Well I guess I just solved the above with a WidgetSwitcher...
Which makes sense now lol
How do I properly embed an FGameplayTagContainer property widget into a new Slate Widget ๐ฌ
SNew(SProperty, TagContainerPropertyHandle) Only shows the name of the Property.
Im guessing because Tag Containers have a Details Customization its not as simple as that?
Hey guys, I made a simple custom tool in unreal engine.
I would like to localize all the labels present in the tool.
I would like it to follow the language set in the unreal editor preferences.
How can I achieve this?
After few hours of research i came across the localization dashboard and tried to implement it with this tool.
I created a new target with 2 cultures (english and korean) and fortunately my project already used LOCTEXT pretty much everywhere so i only had to press the "Gather Text" button to fetch translation from my source code.
I set english as my native language and then opened the korean translations and translate a random label.
Now the funny part:
- I open unreal engine with Korean set as the editor language and the label is correctly displayed in korean.
- I change the language to english and the label correctly changes to the english translation.
- I change the language back to korean but the label stays in english.
Why is that? Did I mess something up in my localization dashboard configuration??
Thank you in advance for the help.
You can do SetContent on some widgets, I think. Probably SBox?
Ill keep that in mind next time.
What I mean is, you have an intermediate widget that acts as a container and just set thr content of that widget.
How come FSlimHorizontalToolBarBuilder::AddToolBarButton() can't show both icon and text at the same time?
Hi, I have the following error message, when trying to use SAssignNew with a custom widget. Does anyone have an idea what this message means?
MissionTree is a TSharedPtr<SMissionTreeObjectiveWidget>
Could it be that SAssignNew works only inside of Slate classes?
Figured it out, I called them in a const function :)
the answer is in the class name...
I asked this in UMG but perhaps slate is better fit since itโs related to key presses and FReplyโs.
ive solved this several times, so hopefully i can help.
What kind of widget is your dropdown? MenuAnchor popups and ComboBox dropdowns should automatically close when you click outside of them. Ideally you would use one of them.
If neither is those is possible for whatever reason, the long way around is to create an IInputProcessor which can intercept input prior to it being routed through the widget tree, and you can choose to handle it however you want. I have had to do this for some particularly convoluted input handling before.
Alright interesting, I was originally using a tile view to populate a second widget which was just being added to a named slot when I interact with a button, perhaps I should look more into the other 2 you suggested? I still need it to be a tile view dropdown and not like a list view
then a MenuAnchor is probably what you want
you specify an arbitrary child widget for it to create
Perfect! Thanks a ton
an location ๐ฆ
Anyone have any idea for to set a default value for a k2 node color pin?
auto* ColorPin = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Struct, TBaseStructure<FColor>::Get(), PinNames::ColorPin);
ColorPin->DefaultValue = "(1.0 , 0.75, 0.0)"; // this requires a fname
I get these errors: The current value ((1.0 , 0.75, 0.0)) of the ' Color ' pin is invalid: Invalid value for an FLinearColor
I tried all kinds of with/without alpha, with/without brackets, flinearcolor vs fcolor. and i scoured the engine source for examples. any ideas are welcomed
EDIT: oh gpt4 solved it for me: ColorPin->DefaultValue = "(R=1.0,G=1.0,B=1.0,A=1.0)";
That's pretty cursed if that's the expected way to do it instead of assigning a value like FColor::White into it
you have to assign a string or an object reference
You can .ToString() them to get that value
All copying + pasting goes through that stringification in the engine anyway
Well, for most things anyway
Hey all. Is there a way in blueprints to switch between using software and hardware mouse cursor? (aka just giving players the option to NOT use my software cursors).
I've been searching the internet but it seems nowhere mentioned, and couldn't find a way on my own.
The closest I came up with was a nasty hack:
Assigning my software cursors to other enum slots, for example Default pointer to ResizeLeftRight, since the game is unlikely to use these anyway (?). But surely there's a more sane way of doing this?
Is there any way to convert a FSlateBrush to FSlateIcon?
I'm not 100% sure but I think you can potentially register the brush in a styleset and then make an FSlateIcon from that style using the name you gave the brush
I poked around it a bit a while back to get a list of available slate icons and at least superficially it looked like that might be how it works
Yeah. That'd be how that works. You can also just define your own (potentially static) FSlateIcon in your class.
Here's a good one. In 5.3.2, As I'm trying to compile a Widget and show it to the screen, a private new operator is called although I call SAssignNew to create the widget. In what circumstance would new not be available for it's calling function ?
What is SGreetings?
@grave hatch It's a custom child class of SCompoundWidget, taken from this gist https://gist.github.com/yateam/d85bcc25c032190396376cff2fa14bc5 to which I reduced to this portion below just to see if any of the more intricate pieces were causing this, but does equally the same thing.
Are you trying to assign an SWeakWidget to an SGreetings variable?
Yes.
That won't work...
Ha! Suggestions ?
Slate widget vars follow the same type restrictions as other classes.
If you want to create a weak widget and assign it to a variable, make the variable a weak widget variable.
Though be warned that the widget linked inside the weak widget will most likely be automatically destroyed unless you have it referenced somewhere else
(hint: it's a weak reference)
What If I don't want it to be weak ? The Unreal docs limited themselves to using those weak pointers for some reasons ...
Ok, this is a nomenclature that eludes me: What is MyWidgetClass ? Is it SGreetings::StaticClass() ?
In your case, SGreetings
TSlateDecl<SGreetings,RequiredArgs::T0RequiredArgs>::Expose': no matching overloaded function found. I thought this would be an Expose() arg from the contructor class but no ...
It's from the slot type
The problem was that the MyWidget needed to be inside a TSharedPtr. ::Expose issue was a red herring.
Thanks for the help @grave hatch
I see
Hello y'all, I have this code (just essential snippet here) that is supposed to update the content of an SListView when selection changed in another SListView:
But the thing is that it doesn't updates at all (nor even seems to add anything in fact...), any idea what I'm missing ?
(sry for the screenshot, there are too many characters for discord)
is there a way to access the numeric editor widget? i tried to SNew a SPropertyEditorNumeric but its privated (thanks epic)
i want to make a details customization that implements an intermediate data layer for editor only
i guess i can just use SNumericEntryBox
If you really want, you can traverse the FChildren property to find the child widgets.
Hi! I'm trying to create a standalone app using slate (for UGC creation purposes) but for some reason all editable text fields are invisible. I can enter text and I cursor changes when I hover it, and everything works fine, but the user cannot see it.
I have same layout for file picker down there and it works and looks fine. Same issue with one-line editable text. Does anyone know why it might happen?
Okay, I found my problem. I was using SMultiLineEditableText instead of SMultiLineEditableTextBox
Got some issues loading the font for a custom BP node using the following code
if (!StyleInstance)
{
StyleInstance = MakeShareable(new FSlateStyleSet(TEXT("RichTextStyle")));
}
if (!StyleInstance.Get()->GetDefaultBrush()->IsSet())
{
if (TextStyleSet && TextStyleSet->RowStruct->IsChildOf(FRichTextStyleRow::StaticStruct()))
{
for (const auto& Entry : TextStyleSet->GetRowMap())
{
FName SubStyleName = Entry.Key;
const FRichTextStyleRow* RichTextStyle = reinterpret_cast<FRichTextStyleRow*>(Entry.Value);
if (SubStyleName == FName(TEXT("Default")))
{
DefaultTextStyle = RichTextStyle->TextStyle;
}
StyleInstance->Set(SubStyleName, RichTextStyle->TextStyle);
}
}
else
{
DefaultTextStyle = FCoreStyle::Get().GetWidgetStyle<FTextBlockStyle>("NormalText");
DefaultTextStyle.SetFontSize(10);
DefaultTextStyle.SetColorAndOpacity(FSlateColor(FLinearColor(1.0f, 0.9f, 0.9f)));
}
}
It seem to work fine once i refresh the node in the graph manually..
It's used in RichTextBlocks if that matters
Hmm
Seems it's r elated to the StyleInstance
the pointer is valid through the second refresh, but it's now empty
Yey, fixed!
What was it? Specifically.
The StyleInstance didnt retain its content , and my checks didnt catch it
I'm not sure exactly why that happened tho
the final snippet ended up like this:
if (!StyleInstance)
{
StyleInstance = MakeShareable(new FSlateStyleSet(TEXT("RichTextStyle")));
}
if (TextStyleSet && TextStyleSet->RowStruct->IsChildOf(FRichTextStyleRow::StaticStruct()))
{
for (const auto& Entry : TextStyleSet->GetRowMap())
{
FName SubStyleName = Entry.Key;
const FRichTextStyleRow* RichTextStyle = reinterpret_cast<FRichTextStyleRow*>(Entry.Value);
if (SubStyleName == FName(TEXT("Default")))
{
DefaultTextStyle = RichTextStyle->TextStyle;
}
StyleInstance->Set(SubStyleName, RichTextStyle->TextStyle);
}
}
if (!DefaultTextStyle.Font.HasValidFont())
{
DefaultTextStyle = FCoreStyle::Get().GetWidgetStyle<FTextBlockStyle>("NormalText");
DefaultTextStyle.SetFontSize(10);
DefaultTextStyle.SetColorAndOpacity(FSlateColor(FLinearColor(1.0f, 0.9f, 0.9f)));
}
so during the reconstruction of the node StyleInstance was stil valid, but default brush was empty ..
Compared to the original snippet :
if (!StyleInstance)
{
StyleInstance = MakeShareable(new FSlateStyleSet(TEXT("RichTextStyle")));
if (TextStyleSet && TextStyleSet->RowStruct->IsChildOf(FRichTextStyleRow::StaticStruct()))
{
for (const auto& Entry : TextStyleSet->GetRowMap())
{
FName SubStyleName = Entry.Key;
FRichTextStyleRow* RichTextStyle = (FRichTextStyleRow*)Entry.Value;
if (SubStyleName == FName(TEXT("Default")))
{
DefaultTextStyle = RichTextStyle->TextStyle;
}
StyleInstance->Set(SubStyleName, RichTextStyle->TextStyle);
}
}
else
{
DefaultTextStyle = FCoreStyle::Get().GetWidgetStyle<FTextBlockStyle>("NormalText");
DefaultTextStyle.SetFontSize(10);
DefaultTextStyle.SetColorAndOpacity(FSlateColor(FLinearColor(1.0f, 0.9f, 0.9f)));
}
}
/* tried adding this now, as this wasn't originally handled */
else
{
DefaultTextStyle = StyleInstance.Get()->GetWidgetStyle<FTextBlockStyle>("Default");
}
DefaultTextStyle (which is the one used later) was empty a swell.
Hmm. Its a local variable, so ofcourse that's gonna be empty...
(not my code originally)
but then the coloring is just gone
Only happens when I call Reconstruct node tho
If i right click and refresh, it recovers to normal color again
trying to inspect it , it just seem to be totally empty
Ohhhhhhhh
I get whats going on I think
If there's no datatable, it initialize the DefaultTextStylelocal variable, initially
But during reconstruct, the Styleset is valid (as it was created the first time), but no entry to it was ever made
Final fix; Actually intialize DefaultTextStyle with the fallback font, and override it if DT exist.
FTextBlockStyle DefaultTextStyle = FCoreStyle::Get().GetWidgetStyle<FTextBlockStyle>("NormalText");
DefaultTextStyle.SetFontSize(10);
DefaultTextStyle.SetColorAndOpacity(FSlateColor(FLinearColor(1.0f, 0.9f, 0.9f)));
const TArray<TSharedRef<class ITextDecorator>> CreatedDecorators;
if (!StyleInstance)
{
StyleInstance = MakeShareable(new FSlateStyleSet(TEXT("RichTextStyle")));
if (TextStyleSet && TextStyleSet->RowStruct->IsChildOf(FRichTextStyleRow::StaticStruct()))
{
for (const auto& Entry : TextStyleSet->GetRowMap())
{
FName SubStyleName = Entry.Key;
FRichTextStyleRow* RichTextStyle = (FRichTextStyleRow*)Entry.Value;
if (SubStyleName == FName(TEXT("Default")))
{
DefaultTextStyle = RichTextStyle->TextStyle;
}
StyleInstance->Set(SubStyleName, RichTextStyle->TextStyle);
}
}
}
else if (StyleInstance.Get()->HasWidgetStyle<FTextBlockStyle>("Default"))
{
DefaultTextStyle = StyleInstance.Get()->GetWidgetStyle<FTextBlockStyle>("Default");
}
๐
i was trying to compile the unreal's ShooterGame sampe project of UE4.27 in UE5.3.2 and found this Error in the FShooterGameLoadingScreenBrush in line 37 any idea how to fix it ?
It's an abstract class. Add the missing methods.
Also don't use the error list, use the output tab.
Hey guys! ๐
I am using a IStructureDetailsView to display my data in a detail view.
I noticed that the IStructureDetailsView takes a FDetailsViewArgs from where you can enable the search bar.
ViewArgs.bAllowSearch = true;
Now, I would like to programatically insert text into the search bar. Is this possible?
Or are there other way to programatically filter the data in the detail view? (I simply need to filter by property name)
Regarding Input passthrough can someone give a workable example regarding it. This post is very vague https://dev.epicgames.com/community/learning/knowledge-base/LJjB/unreal-engine-slate-intercepting-input-events-with-preprocessors
Technically. You'd have to go through the widget tree manually and find it.
99% of the property editor module is private and you won't find anything that isn't absolutely necessary being exposed.
You want to use a input preprocessor specifically? Or just process input on a widget?
Oh, thank you for the answer!
How can I do that?
I'd start off with using the widget reflector to see the widget tree.
Then you can check the GetChildren() of the highest widget you have access to and iterate over the results...
If you can get access to anything.
Thank you for the help.
Just out of curiosity, if not with the SearchBox, is there another way to filter out the property of a DetailView?
Let's say I want to see only the property called "Color" is there a way to do it with a custom filter or something? Or am I forced to use the SearchBox?
You can create your own custom "sections" at the top.
But they only filter by category name
So, not by property name, that's a no then.
Thank you Daekesh, I will proceed with the SearchBox approach ๐
You could create a category unique to your color property and add that to its own section ๐
There's also the ability to "favourite" properties.
You can turn that on in the settings at the top-right of the panel.
Again, not accessible outside etc
I managed to get the SSearchBox widget from my widget tree.
Now, I set the search text but it works only on the first click. All the following clicks erase the text and populate again the detail view.
SearchBarWidget->SetSearchText(FText::FromString("Color")); ```
Do i need to manage something else other than this?
Just a input in widget eg. Button which can be use to fire weapon and look the camera simultaneously
Probably don't want to use input preprocessors then.
Just override onkeydown on the widget.
If you want it to work with a specific key.
If it's actually a button, set the on click event?
If you want just a keybind to do stuff, you shouldn't even be using slate, but #enhanced-input-system
Mysteries of the details panel.
You'll have to dive into their code and figure out what's going on.
Thereโs no way to go from the underlying slate widget back to its object counter part is there?
Iโm trying to get ahold of the UUserwidget spawned by UAnchorWidget but it seems to only store and care about the underlying slate widget and discards to UUserWidget
Not very easily, no.
You could iterate all the objects of the correct type and compare their slate widget.
It's pretty quick if there aren't many of that ui object.
It's all hash bucketed.
But it'll only work for the direct child of that umg widget. Any child slate widget won't show up ofc.
I donโt think itโs stored as a child, itโs really been weird I think, I donโt have the most experience with slate so Iโll gladly be proven wrong but I donโt think there is an easy way to get the spawned widget of a menuanchor. I honestly am just considering doing something similar to what you suggested (but worse) and iterating all objects and checking for the UUserWidget of type I just spawned through calling โOpenโ on the anchormenu.
This is really tripping me up and I feel like there would be an easy way to get it but I canโt find it
Just to confirm there is no way to bind 'OnPropertyChanged' delegate from UPropertyViewBase from c++ because is protected variable right?
Iterate the UObject instances. Yeah.
Honestly if there is only 1... you instnatly find it.
It will only look through a list of 1 items.
TObjectRange or whatever
At the end I opted for a IDetailCustomization class for filtering my properties in my DetailView.
But by default the main category displayed is expanded but its properties are all collapsed.
Is there a way to expand all the children properties?
My OnMouseButtonUp event is not firing, are there other requirements?
FEventReply UMyClass::NativeOnMouseButtonUp_Implementation(FGeometry MyGeometry, const FPointerEvent& MouseEvent)
{
Super::NativeOnMouseButtonUp(MyGeometry, MouseEvent);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("something"));
if (MouseEvent.GetEffectingButton() == DeselectKey)
{
Deselect();
return FEventReply(true);
}
return FEventReply();
}
Yeah sorry I keep messing these channels up
It's cool. Good luck!
Does slate have any support for drawing paths like the ones in adobe illustrator?
You'll have to be a little more specific!
Anyone know how to check if UserWidget is rendering ?
I want to display certain data about the actors on a level right inside level editor viewport (for example as labels right above the actors) - should I use slate for that? Is there another example of such use case in engine source?
Hm, I wanted it to be more of a generic tool, without the need to make the Actor aware of the editor-side UI ๐ค Right now I'm using a custom editor mode and injecting a simple slate widget to the editor's viewport, but I'm pretty sure that there must be a better way to do something like that.
You mean in one of the editor panels? Or maybe a custom panel?
Not really. ๐ฆ
Thanks for the answer! Then I'll just try to hack my way through that and see what comes out of it ๐
How do I remove a slate widget, there is no function like RemoveFromParent like there is for UWidget
It would depend on the parent.
You can kinda force it with ConditionallyDetatchParentWidget I guess, but I've never used it.
It seems rather hamfisted to design a widget to work that way.
hmmm, okay, thank you, I will rethink my approach
anyone know why they put two check boxes to turn screen traces on and off? One on the left and one on the right. Right now screen traces turns on when clicking the left check box already
That would be my guess also, although the behavior is kinda confusing if it turns the feature on when the right side box is not enabled ๐ค
Easy mistake to make ๐
Using the wrong bool for the actual thing(atleast if named poorly)
Yeah, that might be the reason :D
I'm new to slate and am trying to remove a widget added to the viewport, but it is not removing it from the viewport. I'm in belief it's because the game being made is a multiplayer game, but I'm not completely sure. I checked for validity on my MenuWidget and MenuWidgetContainer objects and both are valid. Does anyone know what the problem might be?
https://www.youtube.com/watch?v=jeK6DPB5weA&list=PLk93UR9bCmNk9paQ9QLj5fym01hByaSTA&index=2&t=1080s
This is the video I used to help me if it helps at all. If any more information is needed, I'll give it
Try my C++ Survival Game Course:
http://bit.ly/unrealsurvival
Discord:
https://discord.gg/meFRZfm
Today we're going to be using the Slate Framework to do pure C++ UI in Unreal. This gives you more features, and better performance.
Business Email: contact@reubs.io
I should also probably mention that MenuWidgetContainer is what removes/add the menu to the viewport
hi all,
I've tried focusing on my ActionsWidget (3 buttons) for my popup and i've tried using all of the above but can't get to autofocus on my buttons?
i just want to set keyboard focus (blue highlight on Cancel button) as soon as popup appears - without me having to click first somewhere inside the popup and then use my up/down arrows
i've tried looking into the functions in c++ and online can't find any info... ๐ฆ any help is appreciated!! ๐
Hello guys,
I have made a custom asset which contains various Color and Vector Curves.
And when I click on the preview curve inside the asset window, I can open the Curve Editor, as expected (see image below).
I also have made a custom tool with a DetailView as one of the tab.
The DetailView displays the same Color/Vector curve, but when I click to open the Curve Editor it crashes (see call stack below)
The crash happens in the following function:
{
if (!OpenedEditors.Contains(InInstance))
{
FOpenedEditorTime EditorTime;
EditorTime.EditorName = InInstance->GetEditorName();
EditorTime.OpenedTime = FDateTime::UtcNow();
OpenedEditorTimes.Add(InInstance, EditorTime);
}
FString AssetPath = Asset->GetOuter()->GetPathName(); // Asset is nullptr
OpenedAssets.Add(Asset, InInstance);
OpenedEditors.Add(InInstance, Asset);
RecentAssetToAssetEditorMap.Add(AssetPath, InInstance->GetEditorName().ToString());
AssetOpenedInEditorEvent.Broadcast(Asset, InInstance);
if(InInstance->IncludeAssetInRestoreOpenAssetsPrompt())
{
SaveOpenAssetEditors(false);
}
}```
Why the Curve Editor correctly opens in the asset window but doesn't in a separate DetailView?
Ok I found the source of the issue, but I am not sure on how to solve it.
Basically the RuntimeCurveLinearColor class has its own Customization class in order to show the pretty curve graph in the editor.
In this class there is a Owner member variable which is usually set to the first parent UObject* found in the property hierarchy.
In my case, when opening the custom Asset Window the owner is set to my asset class.
But in my tool, the detail view is built just by passing a member struct of this asset class (which is just a struct containing my RuntimeCurveLinearColor property).
So the RuntimeCurveLinearColor in my tool's detail view does not have any owner.
I tried to run the following code in my detail customization class:
OuterObjects.Empty();
OuterObjects.Add(pDayLightTool->GetCurrentDayLightInfo());
PropertyHandle->ReplaceOuterObjects(OuterObjects);```
But the `ReplaceOuterObjects` doesn't work if i dont have any outer objects to begin with.
Isnt there a way to just set it instead of replacing it?
Gave up and opted for sending my whole UObject class to the detailview and hiding properties.
Details customisations are the devil.
๐ฎ no fan ? or bad experience with it ?
It's just terribly made.
does anyone know how i can make a text in the canvas of a widget in ue4 with this glowing effect like in the print of the youtube channel?
It'd look roughly teh same if you use a translucent colour?
Or created your own font with the correct glow (using glyphs)
Or use the text settings in umg?
Maybe ask #umg
explain this
pls
and text settings? i don't know where that is
Me either. #umg
Never done it, but if you look in the UE4 font assets, many of them are made by just having a large texture with all the letters/numbers (glyphs) in it, like a large atlas texture.
You'd have to google how that works.
ah got it, you want me to make a digital font, with a fake "glow", to then reuse within unreal? the problem is that I can't get this desaturation of light, since the brighter a light is, the less saturated it is, that's why in the screenshot of the real binoculars, the edge of the text is reddish half pink, while the text itself is "white"
I'm pretty sure text has glow settings - it does in UE5 at least.
Though that's with slate.
yes, the ue5 has it, but not the ue4.27
๐ฆ
You could make each individual number and then, isntead of using a font/text, just render an actual image for each number.
If your number is "1234" then render 4 images, 1.png 2.png 3.png and 4.png
how many ifs would I need to create in the functions?
You could even use materials to change the glow colour.
No need for many ifs. Just an array of images (1 entry for each number) use the digit to convert to the array index.
E.g. 0034 -> array index 0, 0, 3, 4.
You'd have to use a bit of math to extract the digits.
Hey Guys,
What is the trick, feel free to link some docs or tutorials.
How do we combine CommonUI widgets with UMG widgets?
I have an asset from the MP that uses CommonUI that works great, but I also have quite some normal UMG widgets that stop worki g the second time they are created.
I'm not sure if it is due to them being different types of widgets or if it has to do with changing the InputMode or something..
But I can't be the only one running into this?
You'd probably ask in #umg
Yeah I did, but it got runover.. I'll try again, thanks, wasn't sure what the difference was.. ๐ถ
Slate is the c++ UI framework.
UMG is built on top of that to allow BP access.
CommonUI is then built on top of UMG.
Good luck!
Hi there, I've been trying to blend these colors using lerps but i have two gradiants that fade to transparent and when i try to blend using lerp i get color from the furthest layer.. is there another way to blend other than using lerp ?
There's white behind the red while the red should fade to transparent
Hello guys!
If I close the engine when my custom tools are open I get the error below.
Exception occurred (0x00007FFFEE775FDC(ntdll.dll), UnrealEditor.exe): Access violation occurred while reading location 0xC0000005: 0x0000000000000000.
It happens on a engine class called FICUTextBiDi, which is used for internationalization.
I leave the CallStack below, even tho is not really informative.
I don't undestand if I implemented internationalization wrong, or if it's not related at all.
What do you guys think? ๐
I don't think it's that you implemented it wrong, it's probably that you are holding onto a text block somewhere by mistake.
Or maybe the text you're using inside a text block.
Or something with text blocks.
I encountered a similar issue with notifications from remote control that were active when the engine shut down. Possibly a thread issue?
the text inside the textblock is hard coded
and if i was holding onto the textblock i would get this error 100% of the times
I only get it like half of the times
Sometimes i dont >.<
What you can do, and this should fix it, is bind to FCoreDelegates::OnEnginePreExit
And use that event to close your widget.
It's a workaround, 100%, but it should stop you crashing.
That's a good idea
Im gonna investigate few more hours and if i cant find the issue im gonna use the delegate.
Thank you @grave hatch you are always present lol
Np. Good luck!
If you do track down the issue, I'd be interested to know the cause as well.
I'm not sure the issue with RC was ever fixed, I just don't think I get that specific popup any more.
Ok, I debugged and, when it crashes, it is every time on a different STextBlock.
It's weird cause I am not using any type of multithreading. I mean its a custom module/tool, but that should be handled by unreal on its own.
Anyway, Im gonna use that delegate and see if it works.
It'll just be whichever random text block is destroyed after the i18n system is destroyed
Which you'd think would be none, but yeah...
Hi guys - does anyone know if thereโs a way to navigate to different button widgets diagonally (keyboard/gamepad)?
If my buttons are not aligned in main HUD widget then navigation doesnโt work ๐
You can override what the navigation buttons do, I think.
How you do that... no diea ๐
I jsut remember seeing some options in umg for it once. Never touched it in Slate.
i implement a map rotation system where clicking on a map selects it but doesn't load it until the player presses start, and the selected map changes what is loaded when start is pressed again
Hi, there is something i dont understand with SComboBox, I fill it a bunch of options and the first time I click on it, it display the list fine but right after I select an option I then need to click twice on it for it to display the list of widgets and i dont really understand why, did this already happen to someone ?
thx in advance for your help and answers
Okay nevermind I found it, it's because I was trying to select an item whose string was equal to an option but was not a ptr in the available option I transmited to the combox and because of that it was not able to display them because it threw an error
i apologize for my poor english
๐
I've never seen somebody apologise for their poor English who was actually bad at English. You included. ๐
So how do you usually deal with the unreliable geometry from GetCachedGeometry?
Say you need the size of your widget... is there anyway to force a render immediately? is there anyway to check how old the cachedgeometry is? can you reliably predict the size ?
CachedGeometry is literally the geometry that was used to render it last tick
Unless, for some reason, it didn't get rendered.
I wouldn't be surprised if it's buggy tbh. There's several issues where the rendering doesn't immediately give you the correct layout on the first render and only does it after multiple frames
Yes, Thatโs true. But sometimes i need the size info before rendering.
Also there is a note โavoid using thisโ meaning cached geometry, but they donโt explain alternatives
The initial size will definitely be wrong because it only caches it after rendering and any code that runs before that will have no geometry to work with.
Yep exactlyโฆ i kind of get whyโฆ its not really a bugโฆ im just wondering what do they suggest you do on the very first few frames when you need the information?
I would definitely call it a bug if it resolves after a second render... I ran into this a lot when rendering widgets to texture, would have to render twice to get the correct layout
Hmm. I've never had that happen, but then again I've never render complex widgets to texture.
Just simple ones that don't have any kind of dynamic size.
You can do the slate prepass to get sizes that way.
Idk if it stores the size in the cached geometry or not though.
Yeah I forget what the specific things were, I think it might've had something to do with automatic text sizing or line breaks or something
I donโt followโฆ is that a function to call? or to override, or a delegate?
Yes it happens more often than not, you need to dance around it until its ready
It's a fucntion on widgets SlatePrepass. It will cache the desiredsize of all widgets.
And also sometimes the cache doesnโt get updated, like if the user changes window sizeโฆ Some widgets will still reference the old cached data,
How can i force a refresh?
My workaround in my widget render code was to... just render every widget twice because that seemed to fix it in my case :P
(all child widgets)
Problem with desired size is it wonโt be the final size so it can be way offโฆ.
But that doesn't get you the actual render size of widgets, only the size they want.
Yeah.
Basically on frame 0 there's no way, unless you render twice, like zomg says.
What does render twice mean? do you call a function?
i was under the impression you canโt manually trigger paintโฆ unless you mean while overriding the on paint i call it again within the same function
sort of recursion?
Currently i just wait a minimum of 3 frames, itโs not bad and it worksโฆ.
I have a huge problem with InEditor display of my widgets at design time, they donโt behave like the runtime ones at all. the runtime ones work well with the cached geometry
the design time is tricky, the cache is outdated sometimes
You could just call Paint
(on the first frame)
Though not sure what you'd use for the parameters.
What did you do?
Hello everyone,
I'm currently working on a SlateViewer, and I'm facing an issue with including the UnrealEd module. I followed the setup instructions provided in this document (link to the document: https://habr.com/ru/articles/591135/). I want to include the UnrealEd module to get reference to the files located in Engine/Developer/Editor/... . However, I'm encountering difficulties compiling the code due to the limitation that SlateViewer cannot run Editor-specific code.
I need assistance in finding a workaround to access the UnrealEd module within the SlateViewer project without violating this constraint. If anyone has experience with similar situations or has suggestions on how to tackle this problem, I would greatly appreciate your insights and guidance.
You aren't allowed to distribute apps that reference anything in a /developer or /editor directory
There is no workaround.
If you want to use editor functionality, you need to reimplement (not copy) the stuff you want or you're in breach of the eula.
Hey guys, do you know how to read a value from the Stats System? (let's say: StaticMeshTris from Stat Engine)
I found this old post: https://forums.unrealengine.com/t/saving-stats-to-file/382142/5
Although it is only able to read values when the stat has been enabled from the console.
Is there no way to access its value when its not enabled?
If the stat isn't enabled, what value would it hold?
Yeah I realized.. lol
I ended up running stat commands with -nodisplay so they don't display but i can get the values.
Can you help me? Where can I start learning how to create a graph editor? I'm creating a dialog system, but I want to understand this issue from scratch, so I don't use ready-made plugins.
^and may sometimes save you the trouble of making your own editor graph because flow is pretty flexible, just need to make your own set of nodes
Yeah, extending a plugin can save you a lot of work. Another one I could think of is GenericGraph. (https://github.com/jinyuliao/GenericGraph)
If you want to make one from scratch, you'll need a lot of patience.
I'd start with learning how to create a custom asset (Asset, Factory, AssetTypeActions)
Then I'd override OpenAssetEditor in FAssetTypeActions_Base's subclass.
Next, you instantiate FAssetEditorToolkit and from this point on, I think there aren't many guides, so it's probably best to look at some reference code to figure it out.
@mental jewel
Often when I try to debug UMG blueprint graphs I get this error spammed in the console and the editor UI freezes up solid until I press escape to stop simulation. Anyone know what's wrong?
"LogSlate: Warning: Slate: Had to block on waiting for a draw buffer"
I get that a lot when I run in debug config and right click to get a menu up.
No ide what actually causes it.
I guess it's just doing it because you're in tree view?
If you had actual subclasses, it may not.
When changing the visibility of widgets from Visible to Collapsed and vice versa, I'm consistently getting a stretching/squishing visual artifact, as shown in the attached video. What are some ways to reduce and/or eliminated this artifact?
Why is my widget not updating every frame? (Data is not missing)
{
ChildSlot
[
SAssignNew(StatsVerticalBox, SVerticalBox)
];
}```
```void SStatsWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
StatsVerticalBox->ClearChildren();
// Iterate through Stats
for (auto Stat : StatData)
{
// Get Raw Name
FName StatName = Stat.NameAndInfo.GetShortName();
// Get Value
int64 iVal = 0;
double dVal = 0;
switch (Stat.NameAndInfo.GetField<EStatDataType>())
{
case EStatDataType::ST_int64: iVal = Stat.GetValue_int64(); break;
case EStatDataType::ST_double: dVal = Stat.GetValue_double(); break;
default: check(0);
}
StatsVerticalBox->AddSlot()
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString(StatName.ToString()))
]
];
}
}```
If I comment out the ClearChildren in the Tick function, it works correctly but it keeps adding slots every frame
Am i not supposed to clear children every frame?
It's just how slate is ๐ฆ You could try setting a fixed size for a container?
Does it show the original data for like 1 frame?
Or is it never displayed?
Never displayed
It may be that it's not working out the size of the children correctly.
You may want to consider event-based updates rather than just every tick..
Usually it takes more than one frame to calculate sizes? And im clearing children before it can do that?
I will try giving it a fixed size tomorrow, thank you for the answer as always
Oh. ๐ That's unfortunate. I'm surprised no one has created a solution for it.
A fixed size removed the issue, but I prefer the dynamic resizing (even with the ugly stretch/squish). ๐คท๐ปโโ๏ธ
I mean a fixed size not for the box you have, but for an outer container that your inner box would be rendered on to.
Oh, I see. Duh. Haha. I'll try that and see how it looks.
I'm trying to create a SScrollbox that populates with vertical boxes based on the number of animation Sequence assets selected in the editor. (The SScrollbox is meant to be part of a subwidget within the window I showed [here](#slate message) yesterday.)
I've tried to create a loop in Slate before, so I tried to the below approach, where I'm first using a function to add slots to the AnimContainer, which is defined in the header as TSharedPtr<SVerticalBox> AnimContainer{SNew(SVerticalBox)}.
void SMCTDialog::SetAnimContainerForAlign()
{
for (int32 i = 0; i < AnimSequencesToModify.Num(); ++i)
{
AnimContainer->AddSlot()
.AutoHeight()
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SHorizontalBox)
/** Add animation name. */
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(STextBlock)
.Text(FText::FromString(AnimSequencesToModify[i]->GetName()))
.Justification(ETextJustify::Left)
.Font(FCoreStyle::GetDefaultFontStyle("Regular", FontSize))
]
/** Fill-in: Editable text box for entering the angle value. */
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(0.25 * PaddingParams.ContentPadding, 0, 0, PaddingParams.SlotPadding)
[
// Another SBox with details...
]
]
];
}
}```
Then, in the ChildSlot, and inside a SVerticalBox, I add a SScrollbox, add a slot to the box, and place the AnimContainer in slot of the SScrollbox, as shown below.
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(2 * PadParams.ContentPadding, 0, 0, 0)
[
SNew(SScrollBox)
.Orientation(Orient_Vertical)
.Visibility(this, &SMCTDialog::GetVisibility_AngleOfAligningAxis)
+ SScrollBox::Slot()
[
AnimContainer.ToSharedRef()
]
]
I can compile and open the project, but nothing related to the scrollbox is displayed in the widget. (All other widgets are displayed properly.) I've been staring at this thing for a while, and I can't figure out what the issue is.
Any ideas?
Is your visibility method returning collapsed?
I'm about pack up my things and head home from work. I'll check once I get through the rush-hour traffic.
If the overall approach is correct, then the visibility must be the issue. I've never written a for loop for Slate, so I wasn't sure whether I was doing something that simply wouldn't work in Slate.
I was just being dumb and not calling the SetAnimContainerForAlign function at all. ๐คฆ๐ปโโ๏ธ I guess I really had been staring at things too long.
I'm back with another question. I'm trying hard to not consider Slate to be evil. ๐
I'm making a SScrollbox to hold the AnimContainer mentioned yesterday. However, I haven't been able to figure out how to make the SScrollbox actually scroll. Regardless of what I do, the scrollbar always takes up the entire SScrollbox, meaning there is nowhere to scroll. (I hope I'm making sense.) For example, in the below code, I place a SBox inside a SScrollbox slot, and I limit the size of the SBox. My thought would be that the SScrollbox should allow me to scroll to the non-viewable area, but that does not seem to be the case.
SNew(SScrollBox)
.Orientation(Orient_Vertical)
.Visibility(this, &SMCTDialog::GetVisibility_AngleOfAligningAxis)
.ScrollBarAlwaysVisible(true)
.ConsumeMouseWheel(EConsumeMouseWheel::Always)
+ SScrollBox::Slot()
.MaxSize(500.0f)
[
SNew(SBox)
.WidthOverride(150.0f)
.HeightOverride(100.0f)
.Visibility(this, &SMCTDialog::GetVisibility_AngleOfAligningAxis)
[
AnimContainer.ToSharedRef()
]
]
I must be going wrong somewhere.
In the below picture, the dotted yellow line indicates the actual size of the AnimContainer container. All I would like to figure out is how to make the SScrollbox allow me to scroll to the currently non-viewable items.
Does anyone have any ideas?
may or may not help you on the road
https://forums.unrealengine.com/t/scrollbox-slate/24872/2
the answer appears to be a working solution , take from it what you can
The problem here is that your sbox is limited in size. It won't scroll to the lower regions because there is no lower region. The SBox is hard limiting the height.
And your visibility should be on the scrolbox, no the sbox.
Well, it's on both atm, you only need it on the scrollbox.
If you remove the height override on the sbox, it should just work.