Editor and Runtime versions of the same plugin/library ?

I’m creating a BP library as a plugin. I have a function in the lib class that would need to work differently when InEditor. The problem of course is that the Runtime library can’t link to UnrealEd, and, preferably, I’d like to use the same “node” in my Blueprints with the same function name. Specifically, the function has to do with Viewports. When Simulating inEditor, the viewport is not the player’s one, it’s the EditorViewport… so whatever my Runtime function does with the viewport, will only work only if PIE, and not when Simulating.

Is there any way out of this ? Thanks!

Search engine source for #if WITH_EDITOR examples.

If you want to use UnrealEd classes you have to create another module to include and use Editor dlls tho.

Thanks for the hint!
I was about to try something like that, i.e. creating an “Editor” module of the same library… the point is, how do you then use the same BP nodes “seamlessly” ?!
AFAIK, this route creates 2 distinct modules (in the same plugin)… but they will be 2 different classes altogether (?!).

Yes, Editor module can include “Developer” (debug/engine) modules + runtime modules…

But a runtime module cannot include “Editor” modules.

Exactly the problem.
So, is there any way to have the same BP Node “MyFunc” that uses Editor code when in Editor and behaves differently when used at Runtime ?
Or they necessarily need to be 2 different nodes ? (MyFunc and MyFuncEditor)
Thanks!

There are several ways to do it, so depends on what you need to access from engine code.

If you need to access editor classes you should not create the function in a runtime module.

UFunctions can also have a meta flag “DevelopmentOnly” to indicate to users that the node will not execute in a packaged build.

I see. I guess I’ve hit a very hard bump then. :slight_smile:
I wanted to get the current LOD being drawn, since it looks like all the methods to get it are “broken” (namely, MeshComponent->PreviousLODLevel always returns 0).
So I managed to get the info, both InEditor and in PIE… but only if the library plugin is an Editor module. If I strip the UnrealEd reference and compile it as a Runtime lib, I lose the ability to get the LOD level during Simulation in Editor.

It bugs me, and it kinda sucks… :confused: :slight_smile:

Ok, so It looks like I managed to do it, thanks to [USER=“434”]BrUnO XaVIeR[/USER] hint.

To wrap it up for ppl just starting like me :), here’s a mini tutorial if you’re creating a runtime (game) project plugin that needs Editor functionalities when in Editor:

1. Add a Module of type Editor to your plugin: [Project_root]/Plugins/<yourPluginName>/Source/[Add YourPluginEditor folder] and replicate the folder structure (Private/Public… etc.)
2. Add the Editor Module to the <YourPluginName>.uplugin descriptor:


"Modules":  {
"Name": "<YourRuntimePluginName>", // <-- Your existing Runtime Plugin module
"Type": "Runtime",
"LoadingPhase": "PreLoadingScreen" // <-- This is up to you...
},
{
"Name": "<YourEditorModuleName>", // <--- This is your new Editor Module!
"Type": "Editor",  // <-- This could also be "UncookedOnly"... try it out
"LoadingPhase": "PreDefault" // <-- This is up to you...
}
 

 ]

3. Your Runtime module needs to statically link the Editor Module when in Editor. This happens only when UBT builds the Editor target: in .Build.cs, somewhere inside the Module class “public YoutPlugin(ReadOnlyTargetRules Target) : base(Target)”:



if (Target.Type == TargetType.Editor) // Is UBT building for Editor ?
{
      PrivateDependencyModuleNames.Add("<YourEditorModuleName>");
}


4. In your Runtime Module source code you need to safeguard from Editor functionalities by using the pre “WITH_EDITOR”. This clearly goes for actual implementation and include directives:


#include <StuffForRuntime>
#if WITH_EDITOR
#include <YourEditorModuleHeader>
#endif
...
...
[Runtime code]
#if WITH_EDITOR
<Use YourEditorModule Classes>
#endif

This also won’t cause issues when packaging your entire Plugin, from the Editor (Plugin -> Package).
How to expose the class in your new Editor module to the Runtime code is entirely another story. To learn a bit more I went the hard route of implementing a UINTERFACE, but I guess it can be done in many different, simpler ways.

5 Likes

As a side note, one thing got in my way with implementing interfaces, that is the official documentation:

In the example, the override to the interface method in the derived class header is written this way:



[Trap.h]

public:
virtual bool ReactToTrigger() override;


…compiling though it looks like this is seen as an overload of the interface class method instead.
What seems to be working instead is:



public:
bool ReactToTrigger() override;


A bit more practical example, as it is presently working for me:



[Interface.h]

class IMyInterface
{
    GENERATED_BODY()

public:

    virtual bool MyMethod() const
    {
        return false;
    }    
};

//###############################################

[MyClass.h that implements Interface]

UCLASS()
class UMyClass : public UObject, public IMyInterface
{
    GENERATED_BODY()

public:

    bool MyMethod() const override;

};

//###############################################

[MyClass.cpp]

bool UMyClass::MyMethod() const
{
    //Implementation code....
}