How to call a BlueprintImplementableEvent from a static function?

Hi, I want to create an event that is callable from a static function, the event can be seen on blueprints but I can’t manage to fire it. Is there any form to do it? This is the code that I’m using:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "../ThirdParty/include/EDSDK.h"
#include "../ThirdParty/include/EDSDKErrors.h"
#include "../ThirdParty/include/EDSDKTypes.h"
#include <iostream>   
#include <string>
#include "CameraNikon.generated.h"



UCLASS()
class THIRDTEST_API ACameraNikon : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ACameraNikon();

	UFUNCTION(BlueprintPure)
		static ACameraNikon* GetInstance();

public:
	UFUNCTION(BlueprintCallable, Category = "CanonObjSDK")
		static void InitCanonSDK();

	UFUNCTION(BlueprintPure, Category = "CanonObjSDK")
		float GetApertureSDK();

	UFUNCTION(BlueprintPure, Category = "CanonObjSDK")
		float GetFocalLengthSDK();

	UFUNCTION(BlueprintImplementableEvent, Category = "CanonObjSDK")
		void ShutterDown();

	

public:
	static EdsError EDSCALLBACK handleObjectEvent(EdsObjectEvent event,
		EdsBaseRef object,
		EdsVoid* context) {
	
		static ACameraNikon* Cam=GetInstance();

		if (event == kEdsObjectEvent_DirItemCreated) {
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Orange, ("DirItemCreated"));
			Cam->ShutterDown();
			
			
		}

		// Object must be released
		if (object)
		{
			EdsRelease(object);
		}
		return EDS_ERR_OK;

	}

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;


};

And the GetInstance function is written in the source file as:

ACameraNikon* ACameraNikon::GetInstance()
{
	static ACameraNikon* i = 0; if (!i)
	{ 
		
		i = NewObject<ACameraNikon>();
		i->AddToRoot();
		// Do various other things here that you need to do
	}

	return i;
}

Hello! Can you explain why you are using this code

static ACameraNikon* Cam=GetInstance();

Because you declare this as static, this variable would be set only for first time…

Hi Kehel18, and thanks for your time, since BlueprintImplementableEvent cannot have a static function, and I want to trigger that event from a static function, I wanted to create an object of the class inside the static function and then call the non-static function using that object, for that I first writed:

static EdsError EDSCALLBACK handleObjectEvent(EdsObjectEvent event,
		EdsBaseRef object,
		EdsVoid* context) {
	
		ACameraNikon Camera;  //Triggers the error: UE4Editor.exe has triggered a breakpoint.
		static ACameraNikon* Cam=GetInstance();

		if (event == kEdsObjectEvent_DirItemCreated) {
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Orange, ("DirItemCreated"));
			
			Camera.ShutterDown();
			
		}

		// Object must be released
		if (object)
		{
			EdsRelease(object);
		}
		return EDS_ERR_OK;

	}

But, since it triggers the error: “UE4Editor.exe has triggered a breakpoint”, I was not able to make it work. Then I was trying to get an instance of the class as static and then use that instance to invoke my non-static ShutterDown function, but it still don’t work. I found the code for that instance from this discussion:

So the main thing is that I want to generate an event that can be used as blueprint and can be triggered from a static function.

At first sight the “Cam->ShutterDown();” should work fine

question where/when do you register the event ?

because you code instanciate a new camera ( not event in world ?? )

your problem is more arround that part of code than the actuall calling

Hi, what do you mean with register the event? I just created the event in C++ inside the actor as BlueprintImplementableEvent and then I tried to use it my actor blueprint editor.

Hi, since BlueprintImplementableEvent does not let me add a static function I was trying to do two things:
the first one was to create an class object like this:

EdsError EDSCALLBACK handleObjectEvent(EdsObjectEvent event,
		EdsBaseRef object,
		EdsVoid* context) {
		
		ACameraNikon Camera;
		

		if (event == kEdsObjectEvent_DirItemCreated) {
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Orange, ("DirItemCreated"));
			
			Camera.ShutterDown();
		}

		

		// Object must be released
		if (object)
		{
			EdsRelease(object);
		}
		return EDS_ERR_OK;

	}

But this gives me the error: “UE4 created a Breakpoint”, and then it closes. So I was trying to get an instance of the class following the code in this discussion:

But still don’t know why it doesn’t work. I also deleted “static” in the line that you showed me, but still don’t have any response from the event.

I basically want to create an event that can be seen in Blueprints and that can be triggered from a static function. Thanks for your time

So you created a blueprint based on this class ?
thing is you did a “NewObject();” creating a base class object, you would need to instanciate an actor based on the blueprint

What do you plan to do with this actor ? ( many possibilities to handle this )
classic ones are :

  • place the actor yourself on the map you need it
  • have a configurable variable on map setting and read it before spawning
  • same but variable on game mode

Yes, in the editor I created a blueprint based on that class and placed it directly on the map. Inside the blueprint I just dragged a print node from the event execution pin to see if the event is called.
Thing is, I know that the static function is working because I can see this line on the viewport
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Orange, (“DirItemCreated”));

but I cannot see the message from the print node inside the blueprint.

Ok. I think I found the problem - you create object with this

NewObject<ACameraNikon>()

But this is native class! It has no any implementation of BlueprintImplementableEvent. If you have some BP over ACameraNikon, then you need to create object of that class

PS. @Dream Powered is also right - if you create actor without any World there can be issues, so if this is not an actor on the scene you would better do it as UObject

Ok, I made an UObject and transfer my functions there as you suggested but still don’t have any response. Is there any other method to make a blueprint type event that can be triggered on a static c++ function?

Hello again! Just think of two points - what class is created and in which class you define (not declare but define!) BlueprintImplementableEvent. Can you answer on this?

The class that I first created was an Actor type Class, and in the header I declared the BlueprintImplementableEvent, but as far as I know it doesn’t need a definition in the source file, or should I define it on editor?

In editor mode I created an Actor Blueprint that has ThirdTest.CameraNikon as a parent, there I’m able to look at all the parameters that I declared including the “Event Shutter Button”, so I just dragged a node frome its execution to print a message in the viewport when the event is called.

So, thanks to Dream Powered and Kehel18 comments, I just realized that in my code I was not getting the actor from the world (in editor I created an actor blueprint from my ACameraNikon class and added to the level that I needed). So I made a function to look for all the actors of my class like this:

void FindAllActors(UWorld* World, TArray<ACameraNikon*>& Out)
	{
		for (TActorIterator<ACameraNikon> It(World); It; ++It)
		{
			Out.Add(*It);
		}
	}

And I called this function from my Actor Begin Play standard function like this:

TArray<ACameraNikon*> FoundActors;

void ACameraNikon::BeginPlay()
{
	Super::BeginPlay();
	FindAllActors(GetWorld(), FoundActors);
}

Finally, I was able to call the ShutterButton event from my static function using: FoundActors[0]->ShutterDown();

Thanks guys.