Editor Plugin toolbar button is transparent

Hello,

I’ve tried to get a toolbar icon to appear for a plugin I need to develop but have not been able to get one.
The button is there but it is transparent. How can I get any icon visible for my editor plugin?

See attached image to understand what I mean.

transparent_icon

Thanks for any help!

Do you have an alpha channel with your icon or PNG with transparent BG?

Thanks for the question :slight_smile:

I have no icon at all. That is probably the issue. Where can I read up on how to configure such an icon?

I don’t know myself but there are a few articles and videos out there.

1 Like

Hello again,

You need to register a slate-style set with the module.
This style sheet then contains property names and attached brushes (images).

This is the code I used to enable it in the test module “JustForIcon”.

JustForIcon.h

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
#include "Styling/SlateStyle.h"

class FJustForIconModule : public IModuleInterface
{
public:
	/** IModuleInterface implementation */
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;

private:
	void RegisterStyleSet();
	void UnregisterStyleSet();

	TSharedPtr<class FSlateStyleSet> StyleSet;
};

JustForIcon.cpp

// Copyright Epic Games, Inc. All Rights Reserved.

#include "JustForIcon.h"
#include "JustForIconEdMode.h"

#include "Misc/Paths.h"
#include "Styling/SlateStyleRegistry.h"
#include "Templates/SharedPointer.h"

#define LOCTEXT_NAMESPACE "FJustForIconModule"

void FJustForIconModule::StartupModule()
{
	RegisterStyleSet();

	FEditorModeRegistry::Get().RegisterMode<FJustForIconEdMode>(
		FJustForIconEdMode::EM_JustForIconEdModeId,
		LOCTEXT("JustForIconEdModeName", "JustForIconEdMode"),
		FSlateIcon(StyleSet->GetStyleSetName(), "JustForIconEdMode", "JustForIconEdMode.Small"),
		true);
}

void FJustForIconModule::ShutdownModule()
{
	// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,
	// we call this function before unloading the module.
	FEditorModeRegistry::Get().UnregisterMode(FJustForIconEdMode::EM_JustForIconEdModeId);

	UnregisterStyleSet();
}

void FJustForIconModule::RegisterStyleSet()
{
	StyleSet = MakeShareable(new FSlateStyleSet("JustForIconEdModeToolStyle"));
	StyleSet->SetContentRoot(FPaths::ProjectContentDir() / TEXT("Resources"));
	StyleSet->SetCoreContentRoot(FPaths::ProjectContentDir() / TEXT("Resources"));

	const FVector2D Icon40x40(40.0f, 40.0f);
	const FVector2D Icon20x20(20.0f, 20.0f);
	StyleSet->Set("JustForIconEdMode", new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("MyTest_x40"), TEXT(".png")), Icon40x40));
	StyleSet->Set("JustForIconEdMode.Small", new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("MyTest_x40"), TEXT(".png")), Icon20x20));

	FSlateStyleRegistry::RegisterSlateStyle(*StyleSet.Get());
}

void FJustForIconModule::UnregisterStyleSet()
{
	FSlateStyleRegistry::UnRegisterSlateStyle(*StyleSet.Get());
	ensure(StyleSet.IsUnique());
	StyleSet.Reset();
}

#undef LOCTEXT_NAMESPACE

IMPLEMENT_MODULE(FJustForIconModule, JustForIcon)

Just a note about this line:

	FEditorModeRegistry::Get().RegisterMode<FJustForIconEdMode>(
		FJustForIconEdMode::EM_JustForIconEdModeId,
		LOCTEXT("JustForIconEdModeName", "JustForIconEdMode"),
		FSlateIcon(StyleSet->GetStyleSetName(), "JustForIconEdMode", "JustForIconEdMode.Small"),
		true);

The brushes (icons) are refered through the property names “JustForIconEdMode” and “JustForIconEdMode.Small”.

The actual file references and icon sizes are set up in this section:

	StyleSet->Set("JustForIconEdMode", new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("MyTest_x40"), TEXT(".png")), Icon40x40));
	StyleSet->Set("JustForIconEdMode.Small", new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("MyTest_x40"), TEXT(".png")), Icon20x20));

I guess one has to think more carefully about whether to use “RootToContentDir” or “RootToCoreContentDir” given a specific use case.
For now, I use it internally in the editor only so RootToContentDir will suffice for me.
I set both the content root and core content root to the same folder for this module so it won’t really matter but according to the docs, I think RootToContentDir is more appropriate.

I have verified in UE code that the ownership of the brushes is transferred to StyleSet so it’s safe to initialize with "new "in the method call.

The lines here:

	StyleSet->SetContentRoot(FPaths::ProjectContentDir() / TEXT("Resources"));
	StyleSet->SetCoreContentRoot(FPaths::ProjectContentDir() / TEXT("Resources"));

Sets the directory to the folder where I have my icon.
For example, it can be: “C:/MyProject/Content/Resources”
Where the icon file MyTest_x40.png resides.

1 Like