Hey everyone!
I’m working on a plugin, but I’m still a tad wet behind my ears when it comes to the build system and modules beyond the game module.
At the moment, I’m attempting to add a new asset class with its own custom graph editor - sort of like a sound cue, but for dialogue trees instead. However, I’ve ran into some troubles getting it to compile. A bunch of stuff in the plugin is taken directly from SoundCue.h and SoundCue.cpp, along with its associated graphs and schemas.
On to my issue - I have two modules, one editor and one runtime. The runtime module has, at the moment, only the asset itself while the editor module contains the asset factory, type actions, graph, schema and nodes. What I’ve done so far is have a UDialogueGraph* variable wrapped in WITH_EDITOR #ifdefs and some related functions, and I have forward declared the UDialogueGraph class in the header. However, when I compile, the following error occurs:
In file included from /home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Source/DialoguePluginRuntime/Private/DialogueAsset.cpp:1:
In file included from /home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Intermediate/Build/Linux/x86_64-unknown-linux-gnu/UE4Editor/Development/DialoguePluginRuntime/DialoguePluginRuntimePrivatePCH.h:4:
In file included from /home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Source/DialoguePluginRuntime/Private/DialoguePluginRuntimePrivatePCH.h:4:
In file included from /home//Programming/UnrealEngine/Engine/Source/Runtime/Engine/Public/Engine.h:10:
In file included from /home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/CoreUObject.h:12:
In file included from /home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/UObject/ObjectBase.h:1563:
/home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/UObject/UObjectBaseUtility.h:330:14: error: incomplete type 'UDialogueGraph' named in nested name specifier
return IsA(T::StaticClass());
^~~
/home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/Templates/Casts.h:112:22: note: in instantiation of function template specialization 'UObjectBaseUtility::IsA<UDialogueGraph>' requested here
return Src && Src->IsA<To>() ? (To*)Src : nullptr;
^
/home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/Templates/Casts.h:176:30: note: in instantiation of member function 'TCastImpl<UEdGraph, UDialogueGraph, 0>::DoCast' requested here
return TCastImpl<From, To>::DoCast(Src);
^
/home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/Templates/Casts.h:192:17: note: in instantiation of function template specialization 'Cast<UDialogueGraph, UEdGraph>' requested here
To* Result = Cast<To>(Src);
^
/home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Source/DialoguePluginRuntime/Private/DialogueAsset.cpp:17:12: note: in instantiation of function template specialization 'CastChecked<UDialogueGraph, UEdGraph>' requested here
return CastChecked<UDialogueGraph>(DialogueGraph);
^
../../../../Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Source/DialoguePluginRuntime/Public/DialogueAsset.h:46:37: note: forward declaration of 'UDialogueGraph'
DIALOGUEPLUGINRUNTIME_API class UDialogueGraph* GetGraph();
^
In file included from /home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Source/DialoguePluginRuntime/Private/DialogueAsset.cpp:1:
In file included from /home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Intermediate/Build/Linux/x86_64-unknown-linux-gnu/UE4Editor/Development/DialoguePluginRuntime/DialoguePluginRuntimePrivatePCH.h:4:
In file included from /home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Source/DialoguePluginRuntime/Private/DialoguePluginRuntimePrivatePCH.h:4:
In file included from /home//Programming/UnrealEngine/Engine/Source/Runtime/Engine/Public/Engine.h:10:
In file included from /home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/CoreUObject.h:12:
In file included from /home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/UObject/ObjectBase.h:1563:
/home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/UObject/UObjectBaseUtility.h:330:15: error: incomplete definition of type 'UDialogueGraph'
return IsA(T::StaticClass());
~^~
In file included from /home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Source/DialoguePluginRuntime/Private/DialogueAsset.cpp:1:
In file included from /home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Intermediate/Build/Linux/x86_64-unknown-linux-gnu/UE4Editor/Development/DialoguePluginRuntime/DialoguePluginRuntimePrivatePCH.h:4:
In file included from /home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Source/DialoguePluginRuntime/Private/DialoguePluginRuntimePrivatePCH.h:4:
In file included from /home//Programming/UnrealEngine/Engine/Source/Runtime/Engine/Public/Engine.h:10:
In file included from /home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/CoreUObject.h:18:
/home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/Templates/Casts.h:53:9: error: incomplete type 'UDialogueGraph' named in nested name specifier
return T::StaticClass()->GetName();
^~~
/home//Programming/UnrealEngine/Engine/Source/Runtime/CoreUObject/Public/Templates/Casts.h:195:55: note: in instantiation of function template specialization 'GetTypeName<UDialogueGraph>' requested here
CastLogError(*Cast<UObject>(Src)->GetFullName(), *GetTypeName<To>());
^
/home//Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Source/DialoguePluginRuntime/Private/DialogueAsset.cpp:17:12: note: in instantiation of function template specialization 'CastChecked<UDialogueGraph, UEdGraph>' requested here
return CastChecked<UDialogueGraph>(DialogueGraph);
^
../../../../Documents/Unreal Projects/DialogueGraphProject/Plugins/DialoguePlugin/Source/DialoguePluginRuntime/Public/DialogueAsset.h:46:37: note: forward declaration of 'UDialogueGraph'
DIALOGUEPLUGINRUNTIME_API class UDialogueGraph* GetGraph();
^
This happens when I attempt to cast to the graph type and return it via a function on the asset (also wrapped in WITH_EDITOR) - line 1 in UDialogueAsset::GetGraph(). Here are the relevant classes:
DialogueAsset.h (Runtime module, public)
#pragma once
#include "Engine.h"
#include "DialogueAsset.generated.h"
USTRUCT()
struct FDialogueNodeEditorData
{
GENERATED_USTRUCT_BODY()
int32 NodePosX;
int32 NodePosY;
FDialogueNodeEditorData()
: NodePosX (0)
, NodePosY (0)
{
}
// Overload the << operator to allow archiving of the struct properly.
friend FArchive& operator<<(FArchive& Ar, FDialogueNodeEditorData& MyDialogueNodeEditorData)
{
return Ar << MyDialogueNodeEditorData.NodePosX << MyDialogueNodeEditorData.NodePosY;
}
};
UCLASS(BlueprintType)
class UDialogueAsset : public UObject
{
GENERATED_BODY()
public:
UDialogueAsset();
#if WITH_EDITORONLY_DATA
// Variables
class UEdGraph* DialogueGraph;
#endif
#if WITH_EDITOR
// Functions
DIALOGUEPLUGINRUNTIME_API void CreateGraph();
DIALOGUEPLUGINRUNTIME_API void ClearGraph();
DIALOGUEPLUGINRUNTIME_API class UDialogueGraph* GetGraph();
#endif
};
DialogueAsset.cpp (Runtime module, private)
#include "Private/DialoguePluginRuntimePrivatePCH.h"
#include "Public/DialogueAsset.h"
#if WITH_EDITOR
#include "Kismet2/BlueprintEditorUtils.h"
#include "UnrealEd.h"
#endif //WITH_EDITOR
UDialogueAsset::UDialogueAsset()
{
}
#if WITH_EDITOR
UDialogueGraph* UDialogueAsset::GetGraph()
{
return CastChecked<UDialogueGraph>(DialogueGraph);
}
void UDialogueAsset::CreateGraph()
{
//TODO: incomplete type named in nested name specifier
/*
if (DialogueGraph == nullptr)
{
DialogueGraph = CastChecked<UDialogueGraph>(FBlueprintEditorUtils::CreateNewGraph(this, NAME_None, UDialogueGraph::StaticClass(), UDialogueGraphSchema::StaticClass()));
DialogueGraph->bAllowDeletion = false;
// Give the schema a chance to fill out any required nodes
const UEdGraphSchema* Schema = DialogueGraph->GetSchema();
Schema->CreateDefaultNodesForGraph(*DialogueGraph);
}
*/
}
void UDialogueAsset::ClearGraph()
{
if (DialogueGraph)
{
DialogueGraph->Nodes.Empty();
// Give the schema a chance to fill out any required nodes
const UEdGraphSchema* Schema = DialogueGraph->GetSchema();
Schema->CreateDefaultNodesForGraph(*DialogueGraph);
}
}
#endif //WITH_EDITOR
DialoguePlugin.Build.cs (Editor module)
// Some copyright should be here...
using UnrealBuildTool;
public class DialoguePlugin : ModuleRules
{
public DialoguePlugin(TargetInfo Target)
{
PublicIncludePaths.AddRange(
new string[] {
"DialoguePlugin/Public"
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
"DialoguePlugin/Private",
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"UnrealEd",
"GraphEditor",
"ContentBrowser",
"DialoguePluginRuntime"
// ... add private dependencies that you statically link with here ...
}
);
PrivateIncludePathModuleNames.AddRange(
new string[]
{
"AssetTools"
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
"AssetTools"
// ... add any modules that your module loads dynamically here ...
}
);
}
}
DialoguePluginRuntime.Build.cs (Runtime module)
// Some copyright should be here...
using UnrealBuildTool;
public class DialoguePluginRuntime : ModuleRules
{
public DialoguePluginRuntime(TargetInfo Target)
{
PublicIncludePaths.AddRange(
new string[]
{
"DialoguePluginRuntime/Public",
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[]
{
"DialoguePluginRuntime/Private",
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject", "Engine", "Slate", "SlateCore"
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}
Plugins are strange! Any help would be greatly appreciated