[C++] I wrote a visual studio extension to fix the annoying smart indenting issues around UE4 macros

Visual studio smart indenting issues around UE4 macros have annoyed me for a long time now, so I wrote an extension for Visual Commander that resolves some of the issues. Most of the solutions I’ve read online around this involved simply disabling smart indenting, which I didn’t really want to do. I figured others might find this useful.

You can find the extension on my github here: GitHub - hackalyze/ue4-vs-extensions: Useful UE4 Visual Studio extensions.

It only requires the Visual Commander extension for visual studio, which has a free edition that works perfectly fine. You’ll find installation instructions on github as well as some gifs illustrating what the extension does. If you find any bugs, feel free to open issues or pull requests.


Hey! Awesome extension! Thank you so much for getting rid of this issue :slight_smile:

Btw. I spotted it doesnt work with copy&paste, any way to fix it?

Oh wow. I was just asking about this indentation annoyance on irc yesterday. Thanks!

No problem guys, glad it’s helpful for you. Vebski, I was thinking about fixing the copy/paste issue too. Maybe I’ll give that a go sometime this weekend, I’ll update here if I do.

I just went ahead and pushed a change that fixes indenting issues when copy/pasting as well. Let me know if you have any issues with it.

Useful stuff, thanks! :slight_smile:

Very nice!

Is there anything out there that can add UPROPERTY args to Intellisense?

“using namespace UP;” should get you what you need there, which works for me at least with VAssistX.

dude, i love you

Is that really a thing? If so, this needs more awareness. I’ve seen a ton of C++ tuts and not one of them has known this.


Awesome! I shared it with my coworkers :wink: thanks again for making coding pleasant again :smiley:

EDIT: We just spotted small bug if I copy and paste the ‘asd’ at the front of the line indicator is moved to the end

oops, good catch. I just pushed a fix out for that, let me know if that resolves it for you.

Sweet, its fixed. Thanks again! :slight_smile:

Hey there.

First of all, thanks for creating this plugin. My ocd is much more calm now. :smiley:
Despite the fact how awesome it is, I’ve found a bug. Whenever I copy a code containing one of GENERATED_X()'s the very next
UPROPERTY/UFUNCTION macro along with property/function to which it belongs has extra indent.

Pressing Ctrl+Z once/twice seems to do the trick, tho it would be way more convenient to not have to do that. :stuck_out_tongue:
Got any idea how to fix it?

PS. It works fine when I type whole that struct by hand
PPS. I tested it on latest version of your plugin.

Pushed a fix for that just now, let me know if it works for ya.

I was just editing my post when you answered. :stuck_out_tongue:

The fix you provided works as charm, thanks!

Would it be possible that you’d also make it work with slate syntax? This one is also annoying as hell. :<

PS. It happens when I click somewhere after typing/pasting the code like the one above.
The indents aren’t touched when i move down via arrow keys. Also, it’s the case for slate in general. It’s not caused by your plugin.

Thanks alot for this epic stuff! Save in my stash))

I haven’t yet written any slate c++, that does look really annoying though. From a quick look over the syntax, it looks like everything simply needs to be indented one level further from the brackets they’re in? Maybe I’ll try to tackle that at some point.

I can’t think of any other example of slate where it uses something else besides ] that breaks the indents.
The only additional think I can add here is that the code may be deeply nested. Here’s modified version of a code from Rama’s hello slate tutorial:

void SStandardSlateWidget::Construct(const FArguments& InArgs)
	OwnerHUD = InArgs._OwnerHUD;
	/////If the code below doesn't look like C++ to you it's because it (sort-of) isn't,
	/////Slate makes extensive use of the C++ Prerocessor(macros) and operator overloading,
	/////Epic is trying to make our lives easier, look-up the macro/operator definitions to see why.

			.Text(LOCTEXT("Some text"))
		] // ; here

			.Text(LOCTEXT("Another text"))
		] // no ; here either

Dunno if the lack of ‘;’ would matter for you, but I pointed that out just in case.

Actually, I’ve found more thing about slate that could malfunction. It’s the declaration of slate arguments in header files.
Here’s how it looks like:

class STableRow : public ITableRow, public SBorder
	static_assert(TIsValidListItem<ItemType>::Value, "Item type T must be UObjectBase*, TSharedRef<>, or TSharedPtr<>.");

	DECLARE_DELEGATE_RetVal_ThreeParams(TOptional<EItemDropZone>, FOnCanAcceptDrop, const FDragDropEvent&, EItemDropZone, ItemType);
	DECLARE_DELEGATE_RetVal_ThreeParams(FReply, FOnAcceptDrop, const FDragDropEvent&, EItemDropZone, ItemType);


	SLATE_BEGIN_ARGS( STableRow< ItemType > )
		: _Style( &FCoreStyle::Get().GetWidgetStyle<FTableRowStyle>("TableView.Row") )
		, _ExpanderStyleSet( &FCoreStyle::Get() )
		, _Padding( FMargin(0) )
		, _ShowSelection( true )
		, _Content()
		SLATE_STYLE_ARGUMENT( FTableRowStyle, Style )
		SLATE_ARGUMENT(const ISlateStyle*, ExpanderStyleSet)

		SLATE_EVENT( FOnCanAcceptDrop, OnCanAcceptDrop )
		SLATE_EVENT( FOnAcceptDrop,    OnAcceptDrop )

		SLATE_EVENT( FOnDragDetected,      OnDragDetected )
		SLATE_EVENT( FOnTableRowDragEnter, OnDragEnter )
		SLATE_EVENT( FOnTableRowDragLeave, OnDragLeave )
		SLATE_EVENT( FOnTableRowDrop,      OnDrop )

		SLATE_ATTRIBUTE( FMargin, Padding )
		SLATE_ARGUMENT( bool, ShowSelection )
		SLATE_DEFAULT_SLOT( typename STableRow<ItemType>::FArguments, Content )


// the rest of the class


And custom subclass:

class SSomeSubclass: public SMultiColumnTableRow<FSomeDataStruct>


	SLATE_BEGIN_ARGS(SSomeSubclass) {}

	SLATE_ARGUMENT(TSharedPtr<class FSomeOtherClass>, Class)

	SLATE_ARGUMENT(FSomeDataStruct, Data)


// the rest of the class


Thanks a ton for the extension. The only issue I noticed is that when I type in private: or public: or protected: it no longer tabs it back all the way to the left.