removed unused methods(BeginPlay, Tick) and added rider plugin
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
#include "UObject/Class.h"
|
||||
#include "DebugLogger.h"
|
||||
#include "UnrealFunctions.h"
|
||||
#include "UObject/UObjectBaseUtility.h"
|
||||
#include "WideStringWrapper.h"
|
||||
#include "EdGraph/EdGraphNode.h"
|
||||
|
||||
namespace RiderDebuggerSupport
|
||||
{
|
||||
constexpr int StringBufferSizeInWideChars = 1024;
|
||||
constexpr int GWideCharSizeInBytes = sizeof(wchar_t);
|
||||
constexpr int GStringSizeInBytes = StringBufferSizeInWideChars * GWideCharSizeInBytes;
|
||||
constexpr int GLengthSizeInBytes = sizeof(uint32_t);
|
||||
constexpr int GResultCodeSizeInBytes = sizeof(uint32_t);
|
||||
constexpr int GStringEntrySizeInBytes = GStringSizeInBytes + GLengthSizeInBytes;
|
||||
constexpr int GFirstStringOffset = GLengthSizeInBytes;
|
||||
constexpr int GSecondStringOffset = GFirstStringOffset + GStringEntrySizeInBytes;
|
||||
constexpr int GThirdStringOffset = GSecondStringOffset + GStringEntrySizeInBytes;
|
||||
constexpr int GBufferSizeInBytes = GResultCodeSizeInBytes + 3 * GStringEntrySizeInBytes;
|
||||
}
|
||||
|
||||
/* Start Identifiers available from IDEA */
|
||||
|
||||
extern "C" DLLEXPORT void __stdcall RiderDebuggerSupport_GetBlueprintFunction(void* PFunction, void* PContext);
|
||||
|
||||
struct FJbCallContextModule
|
||||
{
|
||||
void* Context;
|
||||
void* Function;
|
||||
} RiderDebuggerSupportBlueprintFunctionCallContext;
|
||||
|
||||
int RiderDebuggerSupportModuleVersion = 1346;
|
||||
|
||||
char RiderDebuggerSupportBlueprintFunctionBuffer[RiderDebuggerSupport::GBufferSizeInBytes] = {0};
|
||||
int RiderDebuggerSupportBlueprintBufferSizeInBytes = RiderDebuggerSupport::GBufferSizeInBytes;
|
||||
int RiderDebuggerSupportBlueprintStringBufferSizeInChars = RiderDebuggerSupport::StringBufferSizeInWideChars;
|
||||
int RiderDebuggerSupportBlueprintWideCharSizeInBytes = RiderDebuggerSupport::GWideCharSizeInBytes;
|
||||
|
||||
/* End Identifiers available from IDEA */
|
||||
|
||||
namespace RiderDebuggerSupport
|
||||
{
|
||||
static FWideStringWrapper GJbFullNameWrapper(RiderDebuggerSupportBlueprintFunctionBuffer + GFirstStringOffset, GStringEntrySizeInBytes);
|
||||
static FWideStringWrapper GJbScopeDisplayNameWrapper(RiderDebuggerSupportBlueprintFunctionBuffer + GSecondStringOffset, GStringEntrySizeInBytes);
|
||||
static FWideStringWrapper GJbFunctionDisplayNameWrapper(RiderDebuggerSupportBlueprintFunctionBuffer + GThirdStringOffset, GStringEntrySizeInBytes);
|
||||
|
||||
uint32_t* GJbPOperationResultCode = reinterpret_cast<uint32_t*>(RiderDebuggerSupportBlueprintFunctionBuffer);
|
||||
|
||||
static void SetLastExecutedLine(const uint16 LineNumber)
|
||||
{
|
||||
*GJbPOperationResultCode = (*GJbPOperationResultCode & 0xFFFF0000) | LineNumber;
|
||||
}
|
||||
|
||||
static void SetResultCodeFlag(const uint8 FlagOffset)
|
||||
{
|
||||
*GJbPOperationResultCode |= 1 << FlagOffset;
|
||||
}
|
||||
}
|
||||
|
||||
void RiderDebuggerSupport_GetBlueprintFunction(void* PFunction, void* PContext)
|
||||
{
|
||||
using namespace RiderDebuggerSupport;
|
||||
|
||||
SendLogToDebugger("Called %s: Context=%p Function=%p", __func__, PContext, PFunction);
|
||||
*GJbPOperationResultCode = 0;
|
||||
|
||||
const UObject* Context = static_cast<UObject*>(PContext);
|
||||
UFunction* Function = static_cast<UFunction*>(PFunction);
|
||||
|
||||
if (nullptr == Context)
|
||||
{
|
||||
SendLogToDebugger("Context is null");
|
||||
SetLastExecutedLine(__LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nullptr == Function)
|
||||
{
|
||||
SendLogToDebugger("Function is null");
|
||||
SetLastExecutedLine(__LINE__);
|
||||
return;
|
||||
}
|
||||
SetLastExecutedLine(__LINE__);
|
||||
|
||||
FString FullName;
|
||||
SetLastExecutedLine(__LINE__);
|
||||
|
||||
Function->GetFullName(nullptr, FullName, EObjectFullNameFlags::None);
|
||||
GJbFullNameWrapper.CopyFromNullTerminatedStr(
|
||||
GetData(FullName), FullName.Len());
|
||||
SetLastExecutedLine(__LINE__);
|
||||
|
||||
const auto Outer = Function->GetOuter();
|
||||
|
||||
SendLogToDebugger("Trying to get SourceClass");
|
||||
|
||||
const UClass* SourceClass = CastToUClass(Outer);
|
||||
|
||||
SendLogToDebugger("SourceClass=%p", SourceClass);
|
||||
|
||||
SetLastExecutedLine(__LINE__);
|
||||
if (nullptr != SourceClass)
|
||||
{
|
||||
constexpr int SourceCodeNotNullFlag = 16;
|
||||
SetResultCodeFlag(SourceCodeNotNullFlag);
|
||||
}
|
||||
|
||||
FString SourceClassDisplayName = GetClassNameWithoutSuffix(SourceClass);
|
||||
SendLogToDebugger(
|
||||
"SourceClassDisplayName length=%u, str_ptr=%p",
|
||||
SourceClassDisplayName.Len(), GetData(SourceClassDisplayName));
|
||||
SetLastExecutedLine(__LINE__);
|
||||
|
||||
SendLogToDebugger("Trying to get outerDisplayName");
|
||||
FString OuterDisplayName = FText::FromName(Outer->GetFName()).ToString();
|
||||
SendLogToDebugger(
|
||||
"OuterDisplayName length=%u, str_ptr=%p",
|
||||
OuterDisplayName.Len(), GetData(OuterDisplayName));
|
||||
|
||||
const auto ScopeDisplayName = SourceClass ? &SourceClassDisplayName : &OuterDisplayName;
|
||||
GJbScopeDisplayNameWrapper.CopyFromNullTerminatedStr(
|
||||
GetData(*ScopeDisplayName), ScopeDisplayName->Len());
|
||||
SetLastExecutedLine(__LINE__);
|
||||
|
||||
auto FunctionDisplayName = FText::FromName(Function->GetFName()).ToString();
|
||||
GJbFunctionDisplayNameWrapper.CopyFromNullTerminatedStr(GetData(FunctionDisplayName), FunctionDisplayName.Len());
|
||||
SetLastExecutedLine(__LINE__);
|
||||
|
||||
#if WITH_EDITORONLY_DATA
|
||||
if (SourceClass)
|
||||
{
|
||||
const auto GraphNode = FindSourceNodeForCodeLocation(Context, Function);
|
||||
SetLastExecutedLine(__LINE__);
|
||||
|
||||
if (nullptr != GraphNode)
|
||||
{
|
||||
constexpr int SourceCodeNotNullFlag = 17;
|
||||
SetResultCodeFlag(SourceCodeNotNullFlag);
|
||||
|
||||
const FText NodeTitle = GraphNode->GetNodeTitle(ENodeTitleType::Type::ListView);
|
||||
SetLastExecutedLine(__LINE__);
|
||||
|
||||
FString NodeTitleStr = NodeTitle.ToString();
|
||||
SetLastExecutedLine(__LINE__);
|
||||
|
||||
GJbFunctionDisplayNameWrapper.CopyFromNullTerminatedStr(
|
||||
GetData(NodeTitleStr), NodeTitleStr.Len());
|
||||
SetLastExecutedLine(__LINE__);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "DebugLogger.h"
|
||||
|
||||
#define JB_DEBUG_MODE 0
|
||||
#define LOG_DBG_PREFIX "JB_UNR_BP_DBG_MSG>"
|
||||
#define LOG_DBG_PREFIX_LENGTH (sizeof(LOG_DBG_PREFIX) - 1)
|
||||
|
||||
#if JB_DEBUG_MODE
|
||||
#include "UObject/UnrealType.h"
|
||||
|
||||
// Avoid including windows.h
|
||||
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* LpOutputString);
|
||||
|
||||
#endif
|
||||
|
||||
void RiderDebuggerSupport::SendLogToDebugger(
|
||||
#if !JB_DEBUG_MODE && __cplusplus >= 201703L
|
||||
[[maybe_unused]]
|
||||
#endif
|
||||
const char* FormatStr, ...)
|
||||
{
|
||||
#if JB_DEBUG_MODE
|
||||
|
||||
va_list Args;
|
||||
va_start(Args, FormatStr);
|
||||
|
||||
char OutputBuffer[1024] = {LOG_DBG_PREFIX};
|
||||
|
||||
char* FormatBuffer = OutputBuffer + LOG_DBG_PREFIX_LENGTH;
|
||||
constexpr int FormatBufferSize = sizeof(OutputBuffer) - LOG_DBG_PREFIX_LENGTH;
|
||||
|
||||
const auto Res = vsprintf_s(FormatBuffer, FormatBufferSize, FormatStr, Args);
|
||||
|
||||
if (Res > 0)
|
||||
OutputDebugStringA(OutputBuffer);
|
||||
else
|
||||
OutputDebugStringA("Error in SendLogToDebugger");
|
||||
|
||||
va_end(Args);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace RiderDebuggerSupport
|
||||
{
|
||||
void SendLogToDebugger(const char* FormatStr, ...);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "RiderDebuggerSupport.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FRiderDebuggerSupportModule"
|
||||
|
||||
|
||||
void FRiderDebuggerSupportModule::StartupModule()
|
||||
{
|
||||
}
|
||||
|
||||
void FRiderDebuggerSupportModule::ShutdownModule()
|
||||
{
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FRiderDebuggerSupportModule, RiderDebuggerSupport)
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class FRiderDebuggerSupportModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "UnrealFunctions.h"
|
||||
#include "Engine/BlueprintGeneratedClass.h"
|
||||
#include "Templates/Casts.h"
|
||||
|
||||
UClass* RiderDebuggerSupport::FindClassForNode(const UObject* Object, const UFunction* Function)
|
||||
{
|
||||
if (nullptr != Function) return Function->GetOwnerClass();
|
||||
|
||||
if (nullptr != Object) return Object->GetClass();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UEdGraphNode* RiderDebuggerSupport::FindSourceNodeForCodeLocation(const UObject* Object, UFunction* Function)
|
||||
{
|
||||
#if WITH_EDITORONLY_DATA
|
||||
|
||||
if (nullptr == Object) return nullptr;
|
||||
|
||||
if (UBlueprintGeneratedClass* Class = Cast<UBlueprintGeneratedClass>(FindClassForNode(Object, Function)))
|
||||
{
|
||||
return Class->GetDebugData().
|
||||
FindSourceNodeFromCodeLocation(Function, 0, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FString RiderDebuggerSupport::GetClassNameWithoutSuffix(const UClass* Class)
|
||||
{
|
||||
FString Result = TEXT("Null");
|
||||
if (nullptr == Class) return Result;
|
||||
|
||||
Result = Class->GetName();
|
||||
if (nullptr != Class->ClassGeneratedBy)
|
||||
{
|
||||
Result.RemoveFromEnd(TEXT("_C"), ESearchCase::CaseSensitive);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
const UClass* RiderDebuggerSupport::CastToUClass(const UObject* Object)
|
||||
{
|
||||
if (nullptr == Object) return nullptr;
|
||||
|
||||
const auto& TypeOfObject = Object->GetClass();
|
||||
if (nullptr == TypeOfObject) return nullptr;
|
||||
|
||||
const auto& TypeOfTypeOfObject = TypeOfObject->GetClass();
|
||||
if (nullptr == TypeOfTypeOfObject) return nullptr;
|
||||
|
||||
const auto& TypeOfClass = TypeOfTypeOfObject->GetClass();
|
||||
if (nullptr == TypeOfClass) return nullptr;
|
||||
|
||||
if (TypeOfClass != TypeOfTypeOfObject) return nullptr;
|
||||
|
||||
return static_cast<const UClass*>(Object);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
class UEdGraphNode;
|
||||
class UFunction;
|
||||
class UObject;
|
||||
class UClass;
|
||||
class FString;
|
||||
|
||||
namespace RiderDebuggerSupport
|
||||
{
|
||||
UClass* FindClassForNode(const UObject* Object, const UFunction* Function);
|
||||
UEdGraphNode* FindSourceNodeForCodeLocation(const UObject* Object, UFunction* Function);
|
||||
FString GetClassNameWithoutSuffix(const UClass* Class);
|
||||
const UClass* CastToUClass(const UObject* Object);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "WideStringWrapper.h"
|
||||
|
||||
#include "HAL/UnrealMemory.h"
|
||||
|
||||
|
||||
RiderDebuggerSupport::FWideStringWrapper::FWideStringWrapper(char* Buf, uint32 BufLen):
|
||||
AllocatedBuffer(Buf),
|
||||
AllocatedBufferLength(BufLen)
|
||||
{
|
||||
if (AllocatedBuffer != nullptr && AllocatedBufferLength > LengthPrefixSize)
|
||||
{
|
||||
WideStringLength = reinterpret_cast<uint32*>(AllocatedBuffer);
|
||||
*WideStringLength = 0;
|
||||
PointerToString = reinterpret_cast<wchar_t*>(AllocatedBuffer + LengthPrefixSize);
|
||||
AvailableStringSpaceInBytes = AllocatedBufferLength - LengthPrefixSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
WideStringLength = nullptr;
|
||||
PointerToString = nullptr;
|
||||
AvailableStringSpaceInBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 RiderDebuggerSupport::FWideStringWrapper::CopyFromNullTerminatedStr(const wchar_t* SourceStr, uint32 SourceStrLength) const
|
||||
{
|
||||
if (nullptr == SourceStr || 0 == SourceStrLength) return 0;
|
||||
if (PointerToString == nullptr || AllocatedBufferLength <= LengthPrefixSize) return 0;
|
||||
|
||||
uint32 LocalDataLength = SourceStrLength;
|
||||
|
||||
while (LocalDataLength > 0 && SourceStr[LocalDataLength - 1] == L'\0')
|
||||
{
|
||||
--LocalDataLength;
|
||||
}
|
||||
|
||||
uint32 BytesToCopy = LocalDataLength * sizeof(wchar_t);
|
||||
|
||||
if (BytesToCopy > AvailableStringSpaceInBytes)
|
||||
{
|
||||
BytesToCopy = AvailableStringSpaceInBytes;
|
||||
LocalDataLength = BytesToCopy / sizeof(wchar_t);
|
||||
}
|
||||
|
||||
*WideStringLength = LocalDataLength;
|
||||
|
||||
FMemory::Memcpy(PointerToString, SourceStr, BytesToCopy);
|
||||
|
||||
return LocalDataLength;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "HAL/Platform.h"
|
||||
|
||||
namespace RiderDebuggerSupport
|
||||
{
|
||||
class FWideStringWrapper
|
||||
{
|
||||
char* AllocatedBuffer; // Raw buffer to store data as bytes
|
||||
uint32 AllocatedBufferLength; // Total buffer length in bytes, including space for length prefix
|
||||
uint32* WideStringLength;
|
||||
uint32 AvailableStringSpaceInBytes;
|
||||
wchar_t* PointerToString; // Pointer to the start of the string within AllocatedBuffer
|
||||
|
||||
static constexpr uint32 LengthPrefixSize = sizeof(uint32); // Size of the length prefix in bytes
|
||||
public:
|
||||
FWideStringWrapper(char* Buf, uint32 BufLen);
|
||||
uint32 CopyFromNullTerminatedStr(const wchar_t* SourceStr, uint32 SourceStrLength) const;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class RiderDebuggerSupport : ModuleRules
|
||||
{
|
||||
public RiderDebuggerSupport(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
#if UE_4_22_OR_LATER
|
||||
PCHUsage = PCHUsageMode.NoPCHs;
|
||||
#else
|
||||
PCHUsage = PCHUsageMode.NoSharedPCHs;
|
||||
#endif
|
||||
|
||||
#if UE_5_2_OR_LATER
|
||||
bDisableStaticAnalysis = true;
|
||||
#endif
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine"
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user