CommonUI: Switch CommonInputBaseControllerData at Runtime?

Ok Guys… For over 2 Weeks i got no response…

But a really nice Guy from the Unreal Source Discord (@sp1r1t_d1tch, you are my Hero!!!) gave me the Solution.

1st:
I created a new class inherited from UCommonInputBaseControllerData:

// Header
#pragma once

#include "CoreMinimal.h"
#include "CommonInputBaseTypes.h"
#include "YourNewControllerDataClassName.generated.h"

UCLASS()
class YOURGAME_API UYourNewControllerDataClassName : public UCommonInputBaseControllerData
{
	GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Gamepad")
	FName GamepadNameOverride = FName("");
	
	UYourNewControllerDataClassName();

	void UpdateGamepadName();
};
// Source
#include "YourNewControllerDataClassName.h"

UYourNewControllerDataClassName ::UYourNewControllerDataClassName ()
{
	GamepadName = GamepadNameOverride;
}

void UYourNewControllerDataClassName ::UpdateGamepadName()
{
	GamepadName = GamepadNameOverride;
}

This overrides the GamepadName on Construct. But… we wanna have a method to update it when already existing… just by giving our ControllerData a new Parent class…

Therefor… i added a Button…

We need this Customization Class:

// Header

#pragma once

#include "CoreMinimal.h"
#include "IDetailCustomization.h"
#include "DetailLayoutBuilder.h"
#include "YourNewControllerDataClassName.h"

class FYourCustomization : public IDetailCustomization
{
public:
	static TSharedRef<IDetailCustomization> MakeInstance();

	virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override;

private:
	FReply OnUpdateGamepadNameClicked();

	// Store a pointer to the object being customized
	UYourNewControllerDataClassName* CustomizedObject;
};
// Source

#include "FYourCustomization.h"
#include "DetailCategoryBuilder.h"
#include "DetailWidgetRow.h"
#include "IDetailChildrenBuilder.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Text/STextBlock.h"
#include "Editor/PropertyEditor/Public/PropertyEditorModule.h"
#include "Modules/ModuleManager.h"

#define LOCTEXT_NAMESPACE "FYourCustomization"

TSharedRef<IDetailCustomization> FYourCustomization::MakeInstance()
{
	return MakeShareable(new FYourCustomization);
}

void FYourCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailLayout)
{
	// Get the object being customized
	TArray<TWeakObjectPtr<UObject>> ObjectsBeingCustomized;
	DetailLayout.GetObjectsBeingCustomized(ObjectsBeingCustomized);

	if (ObjectsBeingCustomized.Num() > 0)
	{
		CustomizedObject = Cast<UYourNewControllerDataClassName>(ObjectsBeingCustomized[0].Get());
	}

	IDetailCategoryBuilder& CustomCategory = DetailLayout.EditCategory("Gamepad");

	CustomCategory.AddCustomRow(LOCTEXT("UpdateGamepadName", "Update Gamepad Name"))
	.ValueContent()
	[
		SNew(SButton)
		.Text(LOCTEXT("UpdateGamepadNameButton", "Update Gamepad Name"))
		.OnClicked(FOnClicked::CreateSP(this, &FYourCustomization::OnUpdateGamepadNameClicked))
	];
}

FReply FYourCustomization::OnUpdateGamepadNameClicked()
{
	if (CustomizedObject)
	{
		UE_LOG(LogTemp, Warning, TEXT("Calling UpdateGamepadName on %s"), *CustomizedObject->GetName());
		CustomizedObject->UpdateGamepadName();
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("CustomizedObject is null"));
	}

	return FReply::Handled();
}

#undef LOCTEXT_NAMESPACE

And we need to implement this to our Modules

You Modules normally are the Projectname.h and Projectname.cpp Files, in your Source Root Directory.

// Module Header
#pragma once

#include "CoreMinimal.h"

class F<ProjectName>Module : public FDefaultGameModuleImpl
{
public:
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;
};
// Module Source
// <Projectname>.cpp

#include "<Projectname>.h"
#include "Modules/ModuleManager.h"
#include "PropertyEditorModule.h"
#include "YourCustomization.h"

IMPLEMENT_PRIMARY_GAME_MODULE(F<Projectname>Module, <Projectname>, "<Projectname>");

void F<Projectname>Module::StartupModule()
{
	// Register customizations
	FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
	PropertyModule.RegisterCustomClassLayout("YourNewControllerDataClassName", FOnGetDetailCustomizationInstance::CreateStatic(&FYourCustomization::MakeInstance));
	PropertyModule.NotifyCustomizationModuleChanged();
}

void F<Projectname>Module::ShutdownModule()
{
	// Unregister customizations
	if (FModuleManager::Get().IsModuleLoaded("PropertyEditor"))
	{
		FPropertyEditorModule& PropertyModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
		PropertyModule.UnregisterCustomClassLayout("YourNewControllerDataClassName");
	}
}

Resulting in:
image

Which now allows to Type in ANY new name in the Gamepad name Override… hit the Button… done…
image
Works…

Ps.:
If you have existing CommonInputBaseControllerData Assets, open them and head to the “Class Default”. At the top, select the Box for Parent Class and select your own Class there… the Button and Override Input immediately will appear, ready for all mischiefs :wink:

1 Like