Creating a C++ based MPC

Hi,

In our program, we are using a MPC to drive some custom effects into the material.

We were looking into a way to have intelligence inside the MPC itself. For instance, considering we have an array of usable index, we wanted to add some method for acquiring a slot in the array and returning the next available index.

What seems the appropriate thing to do for me was to create a C++ based MPC :

/**

*

*/

UCLASS()

class MYAPP_API UMyMaterialParameterCollection : public UMaterialParameterCollection

{

GENERATED_BODY()

public:

UFUNCTION (BlueprintCallable, BlueprintPure, Category = “Custom”)

intGeNextIndex () const { return 0; }

};

However, trying to implement this leads to linker errors:

symbole externe non résolu “public: virtual void __cdecl UMaterialParameterCollection::PreEditChange(class FProperty *)” (?PreEditChange@UMaterialParameterCollection@@UEAAXPEAVFProperty@@@Z)

symbole externe non résolu “public: virtual void __cdecl UMaterialParameterCollection::PostEditChangeProperty(struct FPropertyChangedEvent &)” (?PostEditChangeProperty@UMaterialParameterCollection@@UEAAXAEAUFPropertyChangedEvent@@@Z)

symbole externe non résolu “public: virtual void __cdecl UMaterialParameterCollection::PostInitProperties(void)” (?PostInitProperties@UMaterialParameterCollection@@UEAAXXZ)

symbole externe non résolu “public: virtual void __cdecl UMaterialParameterCollection::PostLoad(void)” (?PostLoad@UMaterialParameterCollection@@UEAAXXZ)

symbole externe non résolu “public: virtual void __cdecl UMaterialParameterCollection::BeginDestroy(void)” (?BeginDestroy@UMaterialParameterCollection@@UEAAXXZ)

It seems indeed those methods are not exported in the dll like many others.

Is there any reason why ?

Thanks,

Basile

Steps to Reproduce
Hi,

In our program, we are using a MPC to drive some custom effects into the material.

We were looking into a way to have intelligence inside the MPC itself. For instance, considering we have an array of usable index, we wanted to add some method for acquiring a slot in the array and returning the next available index.

What seems the appropriate thing to do for me was to create a C++ based MPC :

/**

*

*/

UCLASS()

class MYAPP_API UMyMaterialParameterCollection : public UMaterialParameterCollection

{

GENERATED_BODY()

public:

UFUNCTION (BlueprintCallable, BlueprintPure, Category = “Custom”)

intGeNextIndex () const { return 0; }

};

However, trying to implement this leads to linker errors:

symbole externe non résolu “public: virtual void __cdecl UMaterialParameterCollection::PreEditChange(class FProperty *)” (?PreEditChange@UMaterialParameterCollection@@UEAAXPEAVFProperty@@@Z)

symbole externe non résolu “public: virtual void __cdecl UMaterialParameterCollection::PostEditChangeProperty(struct FPropertyChangedEvent &)” (?PostEditChangeProperty@UMaterialParameterCollection@@UEAAXAEAUFPropertyChangedEvent@@@Z)

symbole externe non résolu “public: virtual void __cdecl UMaterialParameterCollection::PostInitProperties(void)” (?PostInitProperties@UMaterialParameterCollection@@UEAAXXZ)

symbole externe non résolu “public: virtual void __cdecl UMaterialParameterCollection::PostLoad(void)” (?PostLoad@UMaterialParameterCollection@@UEAAXXZ)

symbole externe non résolu “public: virtual void __cdecl UMaterialParameterCollection::BeginDestroy(void)” (?BeginDestroy@UMaterialParameterCollection@@UEAAXXZ)

It seems indeed those methods are not exported in the dll like many others.

Is there any reason why ?

Thanks,

Basile

Hi there,

The issue you are running into is that your module does not have access to the declared functions in MaterialParameterCollection.h. The UMaterialParameterCollection class is declared with only the MinimalAPI class specifier and is not exposed through ENGINE_API itself as a compiler optimisation. In modules that include “Engine” as a dependency, you can access the individual functions declared within the class that are exposed with ENGINE_API.

For example, the function GetScalarParameterNames is exported using ENGINE_API.

UFUNCTION(BlueprintCallable, Category="Rendering|Material", meta=(Keywords="GetScalarParameterNames"))
	ENGINE_API TArray<FName> GetScalarParameterNames() const;

You are correct that the UObject function overrides are not exposed with ENGINE_API, so they cannot be overridden (or see the implementation in UMaterialParameterCollection) in your child class (which is outside of the ENGINE_API module).

My recommendation would be to try to achieve the behaviour you are looking for without subclassing UMaterialParameterCollection. However, if you did want to modify the engine to allow for this, you could look at either exposing the entirety of UMaterialParameterCollection to ENGINE_API or explicitly exporting the UObject function overrides to ENGINE_API so they can be overriden in your child class.

Thanks,

Thomas

Hi Tom,

We are staying away from any engine code modification.

This is fine, I implemented the custom logic into my component C++ rather than within the MPC itself. It is less intuitive to me but sufficient.

Thanks,

Basile