What exactly is SAssignNew doing?

I’m looking at various sample code and I see SAssignNew being used, but I’m still fuzzy as to why it is being used. Why would you use it instead of just SNew? Looking at the source the first argument is labeled as ExposeAs, but what purpose is that serving?

It assigns the slate widget to a variable in your class with that name. I believe it also uses the provided name to name the widget in the slate ui graph in order to access it by name and/or debug the tree.

/ Kyle

So it basically reuses the chunk of memory that the variable previously pointed to?


TSharedRef<SWidget> MyWidget = SNew(SButton);
---
TSharedPtr<SWidget> MyWidget = SNew(SButton);
---
TSharedPtr<SWidget> MyWidget;
SAssignNew(MyWidget, SButton);

all above examples does basically the same. They assign a variable MyWidget. So why use SAssignNew? Lets go through example and assume you wrote a code like this:


this->ChildSlot
		
			SNew(SVerticalBox)
                        + SVerticalBox::Slot()
			. FillHeight(1)
			
				// SPLITTERS
				SNew( SSplitter)
				.ResizeMode( ESplitterResizeMode::Fill )
				+ SSplitter::Slot()
				
					SNew(SSplitter)
					.Orientation(Orient_Vertical)
					.ResizeMode( ESplitterResizeMode::Fill )
					+SSplitter::Slot()
					
						SNew(SBorder)
						.Visibility(Col0Row0Vis, &FVisibilityCycler::GetVisibility)
						
							SNew(STextBlock)
								.Text( LOCTEXT("Col0Row0", "Col 0 Row 0") )
						]
					]
					+SSplitter::Slot()
					
						SNew(SBorder)
							.Visibility(Col0Row1Vis, &FVisibilityCycler::GetVisibility)
						
							SNew(STextBlock) .Text( LOCTEXT("Col0Row1", "Col 0 Row 1") )
						]
					]
					+SSplitter::Slot()
					
						SNew(SBorder)
						.Visibility(Col0Row2Vis, &FVisibilityCycler::GetVisibility)
						
							SNew(STextBlock) .Text( LOCTEXT("Col0Row2", "Col 0 Row 2") )
						]
					]
				]
]
]

You have everything working nice and dandy however later in the development you decided you want to have a reference/pointer to the splitters, so you can add slots dynamically to them. What you can do is create TSharedPtr TopLevelSplitter; in you widget class and now choose - you can cut/paste code so it looks like this:




TopLevelSplitter = SNew( SSplitter)
				.ResizeMode( ESplitterResizeMode::Fill )
				+ SSplitter::Slot()
				
					SNew(SSplitter)
					.Orientation(Orient_Vertical)
					.ResizeMode( ESplitterResizeMode::Fill )
					+SSplitter::Slot()
					
						SNew(SBorder)
						.Visibility(Col0Row0Vis, &FVisibilityCycler::GetVisibility)
						
							SNew(STextBlock)
								.Text( LOCTEXT("Col0Row0", "Col 0 Row 0") )
						]
					]
					+SSplitter::Slot()
					
						SNew(SBorder)
							.Visibility(Col0Row1Vis, &FVisibilityCycler::GetVisibility)
						
							SNew(STextBlock) .Text( LOCTEXT("Col0Row1", "Col 0 Row 1") )
						]
					]
					+SSplitter::Slot()
					
						SNew(SBorder)
						.Visibility(Col0Row2Vis, &FVisibilityCycler::GetVisibility)
						
							SNew(STextBlock) .Text( LOCTEXT("Col0Row2", "Col 0 Row 2") )
						]
					];
this->ChildSlot
		
			SNew(SVerticalBox)
                        + SVerticalBox::Slot()
			. FillHeight(1)
			
			      TopLevelSplitter.ToSharedRef()
				
			]
];

OR you can just use SAssignNew and change only one line of original code:


this->ChildSlot
		
			SNew(SVerticalBox)
                        + SVerticalBox::Slot()
			. FillHeight(1)
			
				// SPLITTERS
				SAssignNew(TopLevelSplitter, SSplitter)
				.ResizeMode( ESplitterResizeMode::Fill )
				+ SSplitter::Slot()
				
					SNew(SSplitter)
					.Orientation(Orient_Vertical)
					.ResizeMode( ESplitterResizeMode::Fill )
					+SSplitter::Slot()
					
						SNew(SBorder)
						.Visibility(Col0Row0Vis, &FVisibilityCycler::GetVisibility)
						
							SNew(STextBlock)
								.Text( LOCTEXT("Col0Row0", "Col 0 Row 0") )
						]
					]
					+SSplitter::Slot()
					
						SNew(SBorder)
							.Visibility(Col0Row1Vis, &FVisibilityCycler::GetVisibility)
						
							SNew(STextBlock) .Text( LOCTEXT("Col0Row1", "Col 0 Row 1") )
						]
					]
					+SSplitter::Slot()
					
						SNew(SBorder)
						.Visibility(Col0Row2Vis, &FVisibilityCycler::GetVisibility)
						
							SNew(STextBlock) .Text( LOCTEXT("Col0Row2", "Col 0 Row 2") )
						]
					]
				]
]
]

So SAssignNew is just more convenient way of assigning widgets to variables and it makes sure that you don’t disturb you declarative syntax code and split it into multiple blocks. Of course there are scenarios when you would prefer using SNew insted SAssignNew but thats totally up to you.

2 Likes

So it basically reuses the chunk of memory that the variable previously pointed to?