mirror of
https://github.com/Ed94/Cog.git
synced 2026-08-02 20:58:15 +00:00
Move most modules in the same Cog plugin
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class CogCommon : ModuleRules
|
||||
{
|
||||
public CogCommon(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "CogCommonModule.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FCogCommonModule"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogCommonModule::StartupModule()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogCommonModule::ShutdownModule()
|
||||
{
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FCogCommonModule, CogCommon)
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Templates/IsArrayOrRefOfType.h"
|
||||
|
||||
#ifndef ENABLE_COG
|
||||
#define ENABLE_COG !UE_BUILD_SHIPPING
|
||||
#endif
|
||||
|
||||
#if ENABLE_COG
|
||||
|
||||
#include "CogDebugSettings.h"
|
||||
|
||||
#define IF_COG(expr) { expr; }
|
||||
#define COG_LOG_CATEGORY FLogCategoryBase
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
#define COG_LOG_ACTIVE_FOR_OBJECT(Object) (FCogDebugSettings::IsDebugActiveForObject(Object))
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
#define COG_LOG(LogCategory, Verbosity, Format, ...) \
|
||||
{ \
|
||||
static_assert(TIsArrayOrRefOfType<decltype(Format), TCHAR>::Value, "Formatting string must be a TCHAR array."); \
|
||||
if ((LogCategory).IsSuppressed(Verbosity) == false) \
|
||||
{ \
|
||||
FMsg::Logf_Internal(nullptr, 0, (LogCategory).GetCategoryName(), Verbosity, Format, ##__VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
#define COG_LOG_FUNC(LogCategory, Verbosity, Format, ...) \
|
||||
COG_LOG(LogCategory, Verbosity, TEXT("%s - %s"), ANSI_TO_TCHAR(__FUNCTION__), *FString::Printf(Format, ##__VA_ARGS__)); \
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
#define COG_LOG_OBJECT(LogCategory, Verbosity, Object, Format, ...) \
|
||||
if (COG_LOG_ACTIVE_FOR_OBJECT(Object) || (int32)Verbosity <= (int32)ELogVerbosity::Warning) \
|
||||
{ \
|
||||
COG_LOG(LogCategory, Verbosity, TEXT("%s - %s - %s"), \
|
||||
*GetNameSafe(Object), \
|
||||
ANSI_TO_TCHAR(__FUNCTION__), \
|
||||
*FString::Printf(Format, ##__VA_ARGS__)); \
|
||||
} \
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
#define COG_LOG_OBJECT_NO_CONTEXT(LogCategory, Verbosity, Object, Format, ...) \
|
||||
if (COG_LOG_ACTIVE_FOR_OBJECT(Object) || (int32)Verbosity <= (int32)ELogVerbosity::Warning) \
|
||||
{ \
|
||||
COG_LOG(LogCategory, Verbosity, TEXT("%s - %s"), *GetNameSafe(Object), *FString::Printf(Format, ##__VA_ARGS__)); \
|
||||
} \
|
||||
|
||||
#else //ENABLE_COG
|
||||
|
||||
#define IF_COG(expr) (0)
|
||||
#define COG_LOG_CATEGORY FNoLoggingCategory
|
||||
#define COG_LOG_ABILITY(...) (0)
|
||||
|
||||
#define COG_LOG_ACTIVE_FOR_OBJECT(Object) (0)
|
||||
#define COG_LOG(LogCategory, Verbosity, Format, ...) (0)
|
||||
#define COG_LOG_FUNC(LogCategory, Verbosity, Format, ...) (0)
|
||||
#define COG_LOG_OBJECT(LogCategory, Verbosity, Actor, Format, ...) (0)
|
||||
#define COG_LOG_OBJECT_NO_CONTEXT(LogCategory, Verbosity, Actor, Format, ...) (0)
|
||||
|
||||
#endif //ENABLE_COG
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogCommonAllegianceActorInterface.generated.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM(BlueprintType)
|
||||
enum class ECogCommonAllegiance : uint8
|
||||
{
|
||||
Friendly,
|
||||
Enemy,
|
||||
Neutral
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UINTERFACE(MinimalAPI, Blueprintable)
|
||||
class UCogCommonAllegianceActorInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
class ICogCommonAllegianceActorInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
virtual ECogCommonAllegiance GetAllegianceWithOtherActor(const AActor* OtherActor) const = 0;
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogCommonDebugFilteredActorInterface.generated.h"
|
||||
|
||||
UINTERFACE(MinimalAPI, Blueprintable)
|
||||
class UCogCommonDebugFilteredActorInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class ICogCommonDebugFilteredActorInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class COGCOMMON_API FCogCommonModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
static inline FCogCommonModule& Get() { return FModuleManager::LoadModuleChecked<FCogCommonModule>("CogCommon"); }
|
||||
|
||||
virtual void StartupModule() override;
|
||||
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
private:
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogCommonPossessorInterface.generated.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UINTERFACE(MinimalAPI, Blueprintable)
|
||||
class UCogCommonPossessorInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
class ICogCommonPossessorInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
virtual void SetPossession(APawn* Pawn) = 0;
|
||||
|
||||
virtual void ResetPossession() = 0;
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class CogDebug : ModuleRules
|
||||
{
|
||||
public CogDebug(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CogImgui",
|
||||
"CogCommon",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"NetCore",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,532 @@
|
||||
#include "CogDebugDraw.h"
|
||||
|
||||
#include "CogDebugDrawHelper.h"
|
||||
#include "CogDebugDrawImGui.h"
|
||||
#include "CogDebugHelper.h"
|
||||
#include "CogDebugLog.h"
|
||||
#include "CogDebugModule.h"
|
||||
#include "CogDebugReplicator.h"
|
||||
#include "CogDebugSettings.h"
|
||||
#include "CogDebugShape.h"
|
||||
#include "CogImguiHelper.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "VisualLogger/VisualLogger.h"
|
||||
|
||||
#if ENABLE_COG
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::String2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FString& Text, const FVector2D& Location, const FColor& Color, bool Persistent)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
FCogDebugDrawImGui::AddText(
|
||||
FCogImguiHelper::ToImVec2(Location),
|
||||
Text,
|
||||
FCogImguiHelper::ToImU32(Color),
|
||||
true,
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::Fade2D);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Segment2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& SegmentStart, const FVector2D& SegmentEnd, const FColor& Color, bool Persistent)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
FCogDebugDrawImGui::AddLine(
|
||||
FCogImguiHelper::ToImVec2(SegmentStart),
|
||||
FCogImguiHelper::ToImVec2(SegmentEnd),
|
||||
FCogImguiHelper::ToImU32(Color),
|
||||
FCogDebugSettings::GetDebugThickness(0),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::Fade2D);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Circle2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& Location, float Radius, const FColor& Color, bool Persistent)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
FCogDebugDrawImGui::AddCircle(
|
||||
FCogImguiHelper::ToImVec2(Location),
|
||||
Radius,
|
||||
FCogImguiHelper::ToImU32(Color),
|
||||
FCogDebugSettings::GetDebugSegments(),
|
||||
FCogDebugSettings::GetDebugThickness(0),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::Fade2D);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugDraw::Rect2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& Min, const FVector2D& Max, const FColor& Color, bool Persistent)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const ImVec2 ImMin = FCogImguiHelper::ToImVec2(Min);
|
||||
const ImVec2 ImMax = FCogImguiHelper::ToImVec2(Max);
|
||||
|
||||
FCogDebugDrawImGui::AddRect(
|
||||
ImMin,
|
||||
ImMax,
|
||||
FCogImguiHelper::ToImU32(Color),
|
||||
0.0f,
|
||||
FCogDebugSettings::GetDebugThickness(0),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::Fade2D);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::String(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FString& Text, const FVector& Location, const FColor& Color, const bool Persistent)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
UE_VLOG_LOCATION(WorldContextObject, LogCategory, Verbose, Location, 10.0f, NewColor, TEXT("%s"), *Text);
|
||||
|
||||
::DrawDebugString(
|
||||
WorldContextObject->GetWorld(),
|
||||
Location,
|
||||
*Text,
|
||||
nullptr,
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugTextDuration(Persistent),
|
||||
FCogDebugSettings::TextShadow,
|
||||
FCogDebugSettings::TextSize);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Point(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Location, const float Size, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
::DrawDebugPoint(
|
||||
WorldContextObject->GetWorld(),
|
||||
Location,
|
||||
Size,
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority));
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakePoint(Location, Size, NewColor, Persistent, FCogDebugSettings::DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Segment(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& SegmentStart, const FVector& SegmentEnd, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
UE_VLOG_SEGMENT(WorldContextObject, LogCategory, Verbose, SegmentStart, SegmentEnd, NewColor, TEXT_EMPTY);
|
||||
::DrawDebugLine(
|
||||
WorldContextObject->GetWorld(),
|
||||
SegmentStart,
|
||||
SegmentEnd,
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0));
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeSegment(SegmentStart, SegmentEnd, NewColor, 0.0f, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Bone(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& BoneLocation, const FVector& ParentLocation, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
UE_VLOG_SEGMENT(WorldContextObject, LogCategory, Verbose, BoneLocation, ParentLocation, NewColor, TEXT_EMPTY);
|
||||
|
||||
::DrawDebugLine(
|
||||
WorldContextObject->GetWorld(),
|
||||
BoneLocation,
|
||||
ParentLocation,
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0));
|
||||
|
||||
::DrawDebugPoint(
|
||||
WorldContextObject->GetWorld(),
|
||||
BoneLocation,
|
||||
FCogDebugSettings::GetDebugThickness(4.0f),
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority));
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeBone(BoneLocation, ParentLocation, NewColor, 0.0f, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Arrow(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& SegmentStart, const FVector& SegmentEnd, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
UE_VLOG_ARROW(WorldContextObject, LogCategory, Verbose, SegmentStart, SegmentEnd, NewColor, TEXT_EMPTY);
|
||||
::DrawDebugDirectionalArrow(
|
||||
WorldContextObject->GetWorld(),
|
||||
SegmentStart,
|
||||
SegmentEnd,
|
||||
FCogDebugSettings::ArrowSize,
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0));
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeArrow(SegmentStart, SegmentEnd, FCogDebugSettings::ArrowSize, NewColor, 0.0f, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Axis(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& AxisLoc, const FRotator& AxisRot, float Scale, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
FRotationMatrix R(AxisRot);
|
||||
UE_VLOG_ARROW(WorldContextObject, LogCategory, Verbose, AxisLoc, AxisLoc + R.GetScaledAxis(EAxis::X) * Scale, FColor::Red, TEXT_EMPTY);
|
||||
UE_VLOG_ARROW(WorldContextObject, LogCategory, Verbose, AxisLoc, AxisLoc + R.GetScaledAxis(EAxis::Y) * Scale, FColor::Green, TEXT_EMPTY);
|
||||
UE_VLOG_ARROW(WorldContextObject, LogCategory, Verbose, AxisLoc, AxisLoc + R.GetScaledAxis(EAxis::Z) * Scale, FColor::Blue, TEXT_EMPTY);
|
||||
::DrawDebugCoordinateSystem(
|
||||
WorldContextObject->GetWorld(),
|
||||
AxisLoc,
|
||||
AxisRot,
|
||||
Scale * FCogDebugSettings::AxesScale,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0));
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeAxes(AxisLoc, AxisRot, FCogDebugSettings::ArrowSize, FColor::Red, 0.0f, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Circle(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FMatrix& Matrix, float Radius, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
const FVector Center = Matrix.GetOrigin();
|
||||
const FVector UpVector = Matrix.GetUnitAxis(EAxis::X);
|
||||
UE_VLOG_CIRCLE(WorldContextObject, LogCategory, Verbose, Center, UpVector, Radius, NewColor, TEXT_EMPTY);
|
||||
::DrawDebugCircle(
|
||||
WorldContextObject->GetWorld(),
|
||||
Matrix,
|
||||
Radius,
|
||||
FCogDebugSettings::GetCircleSegments(),
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0),
|
||||
false);
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeCircle(Center, Matrix.Rotator(), Radius, NewColor, 0.0f, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::CircleArc(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FMatrix& Matrix, float InnerRadius, float OuterRadius, float Angle, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
|
||||
//TODO : Add VLOG
|
||||
|
||||
FCogDebugDrawHelper::DrawArc(
|
||||
WorldContextObject->GetWorld(),
|
||||
Matrix,
|
||||
InnerRadius,
|
||||
OuterRadius,
|
||||
Angle,
|
||||
FCogDebugSettings::GetCircleSegments(),
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0));
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeCircleArc(Matrix.GetOrigin(), Matrix.Rotator(), InnerRadius, OuterRadius, Angle, NewColor, 0.0f, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::FlatCapsule(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& Start, const FVector2D& End, const float Radius, const float Z, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
// TODO : Add VLOG
|
||||
|
||||
FCogDebugDrawHelper::DrawFlatCapsule(
|
||||
WorldContextObject->GetWorld(),
|
||||
Start,
|
||||
End,
|
||||
Radius,
|
||||
Z,
|
||||
FCogDebugSettings::GetCircleSegments(),
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0));
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeFlatCapsule(Start, End, Radius, Z, NewColor, 0.0f, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Sphere(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Location, float Radius, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
UE_VLOG_CAPSULE(WorldContextObject, LogCategory, Verbose, Location, 0.0f, Radius, FQuat::Identity, NewColor, TEXT_EMPTY);
|
||||
FCogDebugDrawHelper::DrawSphere(
|
||||
WorldContextObject->GetWorld(),
|
||||
Location,
|
||||
Radius,
|
||||
FCogDebugSettings::GetDebugSegments(),
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0));
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeCapsule(Location, FQuat::Identity, Radius, 0.0f, NewColor, 0.0f, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Box(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Center, const FVector& Extent, const FQuat& Rotation, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
UE_VLOG_OBOX(WorldContextObject, LogCategory, Verbose, FBox(-Extent, Extent), FQuatRotationTranslationMatrix::Make(Rotation, Center), NewColor, TEXT_EMPTY);
|
||||
|
||||
::DrawDebugBox(
|
||||
WorldContextObject->GetWorld(),
|
||||
Center,
|
||||
Extent,
|
||||
Rotation,
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0));
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeBox(Center, FRotator(Rotation), Extent, NewColor, 0.0f, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::SolidBox(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Center, const FVector& Extent, const FQuat& Rotation, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
UE_VLOG_OBOX(WorldContextObject, LogCategory, Verbose, FBox(-Extent, Extent), FQuatRotationTranslationMatrix::Make(Rotation, Center), NewColor, TEXT_EMPTY);
|
||||
|
||||
// If we make the Box Thick enough, it will be displayed as a filled box.
|
||||
// We don't use "DrawDebugSolidBox" because it produced weird result, with color being darker than what is intended
|
||||
const float NeededThickness = FMath::Min3(Extent.X, Extent.Y, Extent.Z) * 10.f;
|
||||
|
||||
::DrawDebugBox(
|
||||
WorldContextObject->GetWorld(),
|
||||
Center,
|
||||
Extent,
|
||||
Rotation,
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
NeededThickness);
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeSolidBox(Center, FRotator(Rotation), Extent, NewColor, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Frustrum(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FMatrix& Matrix, const float Angle, const float AspectRatio, const float NearPlane, const float FarPlane, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
|
||||
FCogDebugDrawHelper::DrawFrustum(
|
||||
WorldContextObject->GetWorld(),
|
||||
Matrix,
|
||||
Angle,
|
||||
AspectRatio,
|
||||
NearPlane,
|
||||
FarPlane,
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0));
|
||||
|
||||
// TODO: Replicate Shape
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Capsule(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Center, const float HalfHeight, const float Radius, const FQuat& Rotation, const FColor& Color, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent);
|
||||
UE_VLOG_CAPSULE(WorldContextObject, LogCategory, Verbose, Center, HalfHeight, Radius, FQuat::Identity, NewColor, TEXT_EMPTY);
|
||||
|
||||
DrawDebugCapsule(
|
||||
WorldContextObject->GetWorld(),
|
||||
Center,
|
||||
HalfHeight,
|
||||
Radius,
|
||||
Rotation,
|
||||
NewColor,
|
||||
FCogDebugSettings::GetDebugPersistent(Persistent),
|
||||
FCogDebugSettings::GetDebugDuration(Persistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugThickness(0));
|
||||
|
||||
ReplicateShape(WorldContextObject, FCogDebugShape::MakeCapsule(Center, Rotation, Radius, HalfHeight, NewColor, 0.0f, Persistent, DepthPriority));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Points(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const TArray<FVector>& Points, float Radius, const FColor& StartColor, const FColor& EndColor, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
int32 index = 0;
|
||||
for (const FVector& Point : Points)
|
||||
{
|
||||
const FLinearColor Color = FLinearColor::LerpUsingHSV(FLinearColor(StartColor), FLinearColor(EndColor), Points.Num() <= 1 ? 0.0f : index / (float)(Points.Num() - 1));
|
||||
Sphere(LogCategory, WorldContextObject, Point, Radius, Color.ToFColor(true), Persistent, DepthPriority);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Path(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const TArray<FVector>& Points, float PointSize, const FColor& StartColor, const FColor& EndColor, const bool Persistent, const uint8 DepthPriority)
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
if (Points.Num() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FVector LastPoint = Points[0];
|
||||
|
||||
int32 Index = 0;
|
||||
for (const FVector& Position : Points)
|
||||
{
|
||||
const FLinearColor LinearColor = FLinearColor::LerpUsingHSV(FLinearColor(StartColor), FLinearColor(EndColor), Points.Num() <= 1 ? 0.0f : Index / (float)(Points.Num() - 1));
|
||||
FColor Color = LinearColor.ToFColor(true);
|
||||
|
||||
Point(LogCategory, WorldContextObject, Position, PointSize, Color, Persistent, DepthPriority);
|
||||
|
||||
if (Index > 0)
|
||||
{
|
||||
Segment(LogCategory, WorldContextObject, LastPoint, Position, Color, Persistent, DepthPriority);
|
||||
}
|
||||
|
||||
Index++;
|
||||
LastPoint = Position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::Skeleton(const FLogCategoryBase& LogCategory, const USkeletalMeshComponent* Skeleton, const FColor& Color, bool DrawSecondaryBones, uint8 DepthPriority)
|
||||
{
|
||||
if (Skeleton == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCategory))
|
||||
{
|
||||
const FReferenceSkeleton& ReferenceSkeleton = Skeleton->GetSkeletalMeshAsset()->GetRefSkeleton();
|
||||
const FTransform WorldTransform = Skeleton->GetComponentTransform();
|
||||
const TArray<FTransform>& ComponentSpaceTransforms = Skeleton->GetComponentSpaceTransforms();
|
||||
|
||||
for (int32 BoneIndex = 0; BoneIndex < ComponentSpaceTransforms.Num(); ++BoneIndex)
|
||||
{
|
||||
if (DrawSecondaryBones == false)
|
||||
{
|
||||
FName BoneName = ReferenceSkeleton.GetBoneName(BoneIndex);
|
||||
if (FCogDebugSettings::IsSecondarySkeletonBone(BoneName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const FTransform Transform = ComponentSpaceTransforms[BoneIndex] * WorldTransform;
|
||||
const FVector BoneLocation = Transform.GetLocation();
|
||||
const FRotator BoneRotation = FRotator(Transform.GetRotation());
|
||||
const int32 ParentIndex = ReferenceSkeleton.GetParentIndex(BoneIndex);
|
||||
|
||||
FVector ParentLocation;
|
||||
if (ParentIndex >= 0)
|
||||
{
|
||||
ParentLocation = (ComponentSpaceTransforms[ParentIndex] * WorldTransform).GetLocation();
|
||||
}
|
||||
else
|
||||
{
|
||||
ParentLocation = WorldTransform.GetLocation();
|
||||
}
|
||||
|
||||
Bone(LogCategory, Skeleton->GetOwner(), BoneLocation, ParentLocation, Color, false, DepthPriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDraw::ReplicateShape(const UObject* WorldContextObject, const FCogDebugShape& Shape)
|
||||
{
|
||||
UWorld* World = WorldContextObject != nullptr ? WorldContextObject->GetWorld() : nullptr;
|
||||
if (World == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ENetMode NetMode = World->GetNetMode();
|
||||
if (NetMode == NM_DedicatedServer || NetMode == NM_ListenServer)
|
||||
{
|
||||
TArray<ACogDebugReplicator*> Replicators;
|
||||
ACogDebugReplicator::GetRemoteReplicators(*World, Replicators);
|
||||
|
||||
for (ACogDebugReplicator* Replicator : Replicators)
|
||||
{
|
||||
if (Replicator != nullptr)
|
||||
{
|
||||
Replicator->ReplicatedShapes.Add(Shape);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
@@ -0,0 +1,191 @@
|
||||
#include "CogDebugDrawBlueprint.h"
|
||||
|
||||
#include "CogDebugDraw.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawString(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FString& Text, const FVector Location, const FLinearColor Color, bool Persistent)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::String(*LogCategoryPtr, WorldContextObject, Text, Location, Color.ToFColor(true), Persistent);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawPoint(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Location, float Size, const FLinearColor Color, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Point(*LogCategoryPtr, WorldContextObject, Location, Size, Color.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawSegment(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector SegmentStart, const FVector SegmentEnd, const FLinearColor Color, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Segment(*LogCategoryPtr, WorldContextObject, SegmentStart, SegmentEnd, Color.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawArrow(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector SegmentStart, const FVector SegmentEnd, const FLinearColor Color, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Arrow(*LogCategoryPtr, WorldContextObject, SegmentStart, SegmentEnd, Color.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawAxis(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Location, const FRotator Rotation, float Scale, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Axis(*LogCategoryPtr, WorldContextObject, Location, Rotation, Scale, Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawSphere(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Location, float Radius, const FLinearColor Color, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Sphere(*LogCategoryPtr, WorldContextObject, Location, Radius, Color.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawBox(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Center, const FVector Extent, const FQuat Rotation, const FLinearColor Color, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Box(*LogCategoryPtr, WorldContextObject, Center, Extent, Rotation, Color.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawSolidBox(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Center, const FVector Extent, const FQuat Rotation, const FLinearColor Color, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::SolidBox(*LogCategoryPtr, WorldContextObject, Center, Extent, Rotation, Color.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawCapsule(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Center, const float HalfHeight, const float Radius, const FQuat Rotation, const FLinearColor Color, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Capsule(*LogCategoryPtr, WorldContextObject, Center, HalfHeight, Radius, Rotation, Color.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawCircle(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FMatrix& Matrix, float Radius, const FLinearColor Color, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Circle(*LogCategoryPtr, WorldContextObject, Matrix, Radius, Color.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawCircleArc(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FMatrix& Matrix, float InnerRadius, float OuterRadius, float Angle, const FLinearColor Color, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::CircleArc(*LogCategoryPtr, WorldContextObject, Matrix, InnerRadius, OuterRadius, Angle, Color.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawPoints(const UObject* WorldContextObject, FCogLogCategory LogCategory, const TArray<FVector>& Points, float Radius, const FLinearColor StartColor, const FLinearColor EndColor, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Points(*LogCategoryPtr, WorldContextObject, Points, Radius, StartColor.ToFColor(true), EndColor.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawPath(const UObject* WorldContextObject, FCogLogCategory LogCategory, const TArray<FVector>& Points, float PointSize, const FLinearColor StartColor, const FLinearColor EndColor, bool Persistent, uint8 DepthPriority)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Path(*LogCategoryPtr, WorldContextObject, Points, PointSize, StartColor.ToFColor(true), EndColor.ToFColor(true), Persistent, DepthPriority);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawString2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FString& Text, const FVector2D Location, const FLinearColor Color, bool Persistent)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::String2D(*LogCategoryPtr, WorldContextObject, Text, Location, Color.ToFColor(true), Persistent);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawSegment2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector2D SegmentStart, const FVector2D SegmentEnd, const FLinearColor Color, bool Persistent)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Segment2D(*LogCategoryPtr, WorldContextObject, SegmentStart, SegmentEnd, Color.ToFColor(true), Persistent);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawCircle2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector2D Location, float Radius, const FLinearColor Color, bool Persistent)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Circle2D(*LogCategoryPtr, WorldContextObject, Location, Radius, Color.ToFColor(true), Persistent);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugDrawBlueprint::DebugDrawRect2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector2D Min, const FVector2D Max, const FLinearColor Color, bool Persistent)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
FCogDebugDraw::Rect2D(*LogCategoryPtr, WorldContextObject, Min, Max, Color.ToFColor(true), Persistent);
|
||||
}
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
@@ -0,0 +1,448 @@
|
||||
#include "CogDebugDrawHelper.h"
|
||||
|
||||
#include "Components/LineBatchComponent.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
ULineBatchComponent* GetDebugLineBatcher(const UWorld* InWorld, bool bPersistentLines, float LifeTime, bool bDepthIsForeground)
|
||||
{
|
||||
return (InWorld ? (bDepthIsForeground ? InWorld->ForegroundLineBatcher : ((bPersistentLines || (LifeTime > 0.f)) ? InWorld->PersistentLineBatcher : InWorld->LineBatcher)) : nullptr);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
static float GetLineLifeTime(ULineBatchComponent* LineBatcher, float LifeTime, bool bPersistent)
|
||||
{
|
||||
return bPersistent ? -1.0f : ((LifeTime > 0.f) ? LifeTime : LineBatcher->DefaultLifeTime);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawArc(
|
||||
const UWorld* InWorld,
|
||||
const FMatrix& Matrix,
|
||||
float InnerRadius,
|
||||
float OuterRadius,
|
||||
float Angle,
|
||||
int32 Segments,
|
||||
const FColor& Color,
|
||||
bool bPersistentLines,
|
||||
float LifeTime,
|
||||
uint8 DepthPriority,
|
||||
float Thickness)
|
||||
{
|
||||
if (GEngine->GetNetMode(InWorld) == NM_DedicatedServer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground));
|
||||
if (LineBatcher == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const float LineLifeTime = GetLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
||||
|
||||
const float AngleRad = FMath::DegreesToRadians(Angle);
|
||||
const FVector Center = Matrix.GetOrigin();
|
||||
const FVector Direction = Matrix.GetUnitAxis(EAxis::Z);
|
||||
|
||||
// Need at least 4 segments
|
||||
Segments = FMath::Max(Segments, 4);
|
||||
|
||||
FVector AxisY, AxisZ;
|
||||
FVector DirectionNorm = Direction.GetSafeNormal();
|
||||
DirectionNorm.FindBestAxisVectors(AxisZ, AxisY);
|
||||
|
||||
TArray<FBatchedLine> Lines;
|
||||
Lines.Empty(Segments * 2 + 2);
|
||||
|
||||
if (InnerRadius != OuterRadius)
|
||||
{
|
||||
FVector P0 = Center + InnerRadius * (AxisY * -FMath::Sin(-AngleRad) + DirectionNorm * FMath::Cos(-AngleRad));
|
||||
FVector P1 = Center + OuterRadius * (AxisY * -FMath::Sin(-AngleRad) + DirectionNorm * FMath::Cos(-AngleRad));
|
||||
Lines.Emplace(FBatchedLine(P0, P1, Color, LineLifeTime, Thickness, DepthPriority));
|
||||
|
||||
FVector P2 = Center + InnerRadius * (AxisY * -FMath::Sin(AngleRad) + DirectionNorm * FMath::Cos(AngleRad));
|
||||
FVector P3 = Center + OuterRadius * (AxisY * -FMath::Sin(AngleRad) + DirectionNorm * FMath::Cos(AngleRad));
|
||||
Lines.Emplace(FBatchedLine(P2, P3, Color, LineLifeTime, Thickness, DepthPriority));
|
||||
}
|
||||
|
||||
float CurrentAngle = -AngleRad;
|
||||
const float AngleStep = AngleRad / float(Segments) * 2.f;
|
||||
FVector PrevVertex = Center + OuterRadius * (AxisY * -FMath::Sin(CurrentAngle) + DirectionNorm * FMath::Cos(CurrentAngle));
|
||||
int32 Count = Segments;
|
||||
while (Count--)
|
||||
{
|
||||
CurrentAngle += AngleStep;
|
||||
FVector NextVertex = Center + OuterRadius * (AxisY * -FMath::Sin(CurrentAngle) + DirectionNorm * FMath::Cos(CurrentAngle));
|
||||
Lines.Emplace(FBatchedLine(PrevVertex, NextVertex, Color, LineLifeTime, Thickness, DepthPriority));
|
||||
PrevVertex = NextVertex;
|
||||
}
|
||||
|
||||
if (InnerRadius != 0.0f)
|
||||
{
|
||||
CurrentAngle = -AngleRad;
|
||||
PrevVertex = Center + InnerRadius * (AxisY * -FMath::Sin(CurrentAngle) + DirectionNorm * FMath::Cos(CurrentAngle));
|
||||
|
||||
Count = Segments;
|
||||
while (Segments--)
|
||||
{
|
||||
CurrentAngle += AngleStep;
|
||||
FVector NextVertex = Center + InnerRadius * (AxisY * -FMath::Sin(CurrentAngle) + DirectionNorm * FMath::Cos(CurrentAngle));
|
||||
Lines.Emplace(FBatchedLine(PrevVertex, NextVertex, Color, LineLifeTime, Thickness, DepthPriority));
|
||||
PrevVertex = NextVertex;
|
||||
}
|
||||
}
|
||||
|
||||
LineBatcher->DrawLines(Lines);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawSphere(
|
||||
const UWorld* InWorld,
|
||||
const FVector& Center,
|
||||
const float Radius,
|
||||
const int32 Segments,
|
||||
const FColor& Color,
|
||||
const bool bPersistentLines,
|
||||
const float LifeTime,
|
||||
const uint8 DepthPriority,
|
||||
const float Thickness)
|
||||
{
|
||||
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
||||
{
|
||||
DrawCircle(InWorld, Center, FVector::XAxisVector, FVector::YAxisVector, Color, Radius, Segments, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawCircle(InWorld, Center, FVector::XAxisVector, FVector::ZAxisVector, Color, Radius, Segments, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawCircle(InWorld, Center, FVector::YAxisVector, FVector::ZAxisVector, Color, Radius, Segments, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawFlatCapsule(
|
||||
const UWorld* InWorld,
|
||||
const FVector2D& Start,
|
||||
const FVector2D& End,
|
||||
const float Radius,
|
||||
const float Z,
|
||||
const float Segments,
|
||||
const FColor& Color,
|
||||
const bool bPersistentLines,
|
||||
const float LifeTime,
|
||||
const uint8 DepthPriority,
|
||||
const float Thickness)
|
||||
{
|
||||
FVector2D Forward = (End - Start).GetSafeNormal();
|
||||
FVector2D Right = FVector2D(-Forward.Y, Forward.X);
|
||||
|
||||
::DrawDebugLine(InWorld, FVector(Start - Right * Radius, Z), FVector(End - Right * Radius, Z), Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
::DrawDebugLine(InWorld, FVector(Start + Right * Radius, Z), FVector(End + Right * Radius, Z), Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
::DrawDebugCircle(InWorld, FRotationTranslationMatrix(FRotator(90, 0, 0), FVector(Start, Z)), Radius, Segments, Color, bPersistentLines, LifeTime, DepthPriority, Thickness, false);
|
||||
::DrawDebugCircle(InWorld, FRotationTranslationMatrix(FRotator(90, 0, 0), FVector(End, Z)), Radius, Segments, Color, bPersistentLines, LifeTime, DepthPriority, Thickness, false);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawRaycastSingle(
|
||||
const UWorld* World,
|
||||
const FVector& Start,
|
||||
const FVector& End,
|
||||
const EDrawDebugTrace::Type DrawType,
|
||||
const bool bHit,
|
||||
const FHitResult& Hit,
|
||||
const float HitSize,
|
||||
const FLinearColor DrawColor,
|
||||
const FLinearColor DrawHitColor,
|
||||
const float DrawDuration,
|
||||
const uint8 DepthPriority /*= 0*/
|
||||
)
|
||||
{
|
||||
if (DrawType != EDrawDebugTrace::None)
|
||||
{
|
||||
bool DrawPersistent = DrawType == EDrawDebugTrace::Persistent;
|
||||
float DrawTime = (DrawType == EDrawDebugTrace::ForDuration) ? DrawDuration : 0.f;
|
||||
|
||||
if (bHit && Hit.bBlockingHit)
|
||||
{
|
||||
::DrawDebugLine(World, Start, Hit.ImpactPoint, DrawColor.ToFColor(true), DrawPersistent, DrawTime);
|
||||
::DrawDebugLine(World, Hit.ImpactPoint, End, DrawHitColor.ToFColor(true), DrawPersistent, DrawTime);
|
||||
|
||||
DrawHitResult(World, Hit, 0, DrawType, false, HitSize, DrawHitColor, DrawTime, DepthPriority);
|
||||
}
|
||||
else
|
||||
{
|
||||
::DrawDebugLine(World, Start, End, DrawColor.ToFColor(true), DrawPersistent, DrawTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawSphereOverlapMulti(
|
||||
const UWorld* World,
|
||||
const FVector& Position,
|
||||
const float Radius,
|
||||
const EDrawDebugTrace::Type DrawType,
|
||||
const bool bOverlap,
|
||||
const TArray<AActor*>& OutActors,
|
||||
const FLinearColor DrawColor,
|
||||
const FLinearColor DrawHitColor,
|
||||
const float DrawDuration /*= 0*/
|
||||
)
|
||||
{
|
||||
if (DrawType == EDrawDebugTrace::None)
|
||||
return;
|
||||
|
||||
const bool DrawPersistent = DrawType == EDrawDebugTrace::Persistent;
|
||||
const float DrawTime = (DrawType == EDrawDebugTrace::ForDuration) ? DrawDuration : 0.f;
|
||||
|
||||
DrawSphereOverlapSingle(World, Position, Radius, DrawColor.ToFColor(true), DrawPersistent, DrawTime);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawSphereOverlapSingle(
|
||||
const UWorld* World,
|
||||
const FVector& Position,
|
||||
const float Radius,
|
||||
const FColor& DrawColor,
|
||||
const bool DrawPersistent,
|
||||
const float DrawTime /*= -1.f*/,
|
||||
const uint8 DepthPriority /*= 0*/
|
||||
)
|
||||
{
|
||||
::DrawDebugSphere(World, Position, Radius, 16, DrawColor, DrawPersistent, DrawTime, DepthPriority);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawCapsuleCastMulti(const UWorld* World, const FVector& Start, const FVector& End, const FQuat& Rotation, const float HalfHeight, const float Radius, const EDrawDebugTrace::Type DrawType, const bool bHit, const TArray<FHitResult>& OutHits, const FLinearColor DrawColor, const FLinearColor DrawHitColor, const float DrawDuration /*= 0*/)
|
||||
{
|
||||
if (DrawType == EDrawDebugTrace::None)
|
||||
return;
|
||||
|
||||
const bool DrawPersistent = DrawType == EDrawDebugTrace::Persistent;
|
||||
const float DrawTime = (DrawType == EDrawDebugTrace::ForDuration) ? DrawDuration : 0.f;
|
||||
|
||||
if (bHit && OutHits.Last().bBlockingHit)
|
||||
{
|
||||
FVector const BlockingHitPoint = OutHits.Last().Location;
|
||||
|
||||
DrawCapsuleCastSingle(World, Start, BlockingHitPoint, Rotation, HalfHeight, Radius, DrawHitColor.ToFColor(true), DrawPersistent, DrawTime);
|
||||
DrawCapsuleCastSingle(World, Start, End, Rotation, HalfHeight, Radius, DrawColor.ToFColor(true), DrawPersistent, DrawTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawCapsuleCastSingle(World, Start, End, Rotation, HalfHeight, Radius, DrawColor.ToFColor(true), DrawPersistent, DrawTime);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawCapsuleCastSingle(const UWorld* World, const FVector& Start, const FVector& End, const FQuat& Rotation, const float HalfHeight, const float Radius, const FColor& DrawColor, const bool DrawPersistent, const float DrawDuration /*= -1.f*/, const uint8 DepthPriority /*= 0*/)
|
||||
{
|
||||
::DrawDebugCapsule(World, Start, HalfHeight, Radius, Rotation, DrawColor, DrawPersistent, DrawDuration, DepthPriority);
|
||||
::DrawDebugLine(World, Start, End, DrawColor, DrawPersistent, DrawDuration, DepthPriority, 0.5f);
|
||||
::DrawDebugCapsule(World, End, HalfHeight, Radius, Rotation, DrawColor, DrawPersistent, DrawDuration, DepthPriority);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawSphereCastMulti(
|
||||
const UWorld* World,
|
||||
const FVector& Start,
|
||||
const FVector& End,
|
||||
const float Radius,
|
||||
const EDrawDebugTrace::Type DrawType,
|
||||
const bool bHit,
|
||||
const TArray<FHitResult>& OutHits,
|
||||
const FLinearColor DrawColor,
|
||||
const FLinearColor DrawHitColor,
|
||||
const float DrawDuration /*= 0*/
|
||||
)
|
||||
{
|
||||
if (DrawType == EDrawDebugTrace::None)
|
||||
return;
|
||||
|
||||
const bool DrawPersistent = DrawType == EDrawDebugTrace::Persistent;
|
||||
const float DrawTime = (DrawType == EDrawDebugTrace::ForDuration) ? DrawDuration : 0.f;
|
||||
|
||||
if (bHit && OutHits.Last().bBlockingHit)
|
||||
{
|
||||
FVector const BlockingHitPoint = OutHits.Last().Location;
|
||||
DrawSphereCastSingle(World, Start, BlockingHitPoint, Radius, DrawColor.ToFColor(true), DrawPersistent, DrawTime);
|
||||
DrawSphereCastSingle(World, BlockingHitPoint, End, Radius, DrawHitColor.ToFColor(true), DrawPersistent, DrawTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSphereCastSingle(World, Start, End, Radius, DrawColor.ToFColor(true), DrawPersistent, DrawTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawSphereCastSingle(
|
||||
const UWorld* World,
|
||||
const FVector& Start,
|
||||
const FVector& End,
|
||||
const float Radius,
|
||||
const FColor& DrawColor,
|
||||
const bool DrawPersistent,
|
||||
const float DrawDuration /*= -1.f*/,
|
||||
const uint8 DepthPriority /*= 0*/
|
||||
)
|
||||
{
|
||||
FVector const TraceVec = End - Start;
|
||||
float const Dist = TraceVec.Size();
|
||||
|
||||
FVector const Center = Start + TraceVec * 0.5f;
|
||||
float const HalfHeight = (Dist * 0.5f) + Radius;
|
||||
|
||||
FQuat const CapsuleRot = FRotationMatrix::MakeFromZ(TraceVec).ToQuat();
|
||||
::DrawDebugCapsule(World, Center, HalfHeight, Radius, CapsuleRot, DrawColor, DrawPersistent, DrawDuration, DepthPriority);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawHitResults(
|
||||
const UWorld* World,
|
||||
const TArray<FHitResult>& OutHits,
|
||||
const EDrawDebugTrace::Type DrawType,
|
||||
const bool ShowHitIndex,
|
||||
const float HitSize,
|
||||
const FLinearColor HitColor,
|
||||
const float DrawDuration,
|
||||
const uint8 DepthPriority /*= 0*/
|
||||
)
|
||||
{
|
||||
if (DrawType == EDrawDebugTrace::None)
|
||||
return;
|
||||
|
||||
for (int32 i = 0; i < OutHits.Num(); ++i)
|
||||
{
|
||||
DrawHitResult(World, OutHits[i], i, DrawType, ShowHitIndex, HitSize, HitColor, DrawDuration, DepthPriority);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawHitResultsDiscarded(
|
||||
const UWorld* World,
|
||||
const TArray<FHitResult>& AllHits,
|
||||
const TArray<FHitResult>& KeptHits,
|
||||
const EDrawDebugTrace::Type DrawType,
|
||||
const float HitSize,
|
||||
const FLinearColor DrawColor,
|
||||
const float DrawDuration,
|
||||
const uint8 DepthPriority /*= 0*/
|
||||
)
|
||||
{
|
||||
if (DrawType == EDrawDebugTrace::None)
|
||||
return;
|
||||
|
||||
for (int32 i = 0; i < AllHits.Num(); ++i)
|
||||
{
|
||||
const FHitResult& PhysicHit = AllHits[i];
|
||||
if (!KeptHits.ContainsByPredicate([&](const FHitResult& Hit)
|
||||
{
|
||||
return Hit.GetActor() == PhysicHit.GetActor() && Hit.Component == PhysicHit.Component && Hit.Distance == PhysicHit.Distance;
|
||||
}))
|
||||
{
|
||||
DrawHitResult(World, PhysicHit, i, DrawType, false, HitSize, DrawColor, DrawDuration, DepthPriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawHitResult(
|
||||
const UWorld* World,
|
||||
const FHitResult& Hit,
|
||||
const int HitIndex,
|
||||
const EDrawDebugTrace::Type DrawType,
|
||||
const bool ShowHitIndex,
|
||||
const float HitSize,
|
||||
const FLinearColor HitColor,
|
||||
const float DrawDuration,
|
||||
const uint8 DepthPriority /*= 0*/
|
||||
)
|
||||
{
|
||||
if (DrawType == EDrawDebugTrace::None)
|
||||
return;
|
||||
|
||||
const bool DrawPersistent = DrawType == EDrawDebugTrace::Persistent;
|
||||
const float DrawTime = (DrawType == EDrawDebugTrace::ForDuration) ? DrawDuration : 0.f;
|
||||
|
||||
::DrawDebugSphere(World, Hit.ImpactPoint, HitSize, 12, HitColor.ToFColor(true), DrawPersistent, DrawTime, DepthPriority);
|
||||
if (ShowHitIndex)
|
||||
{
|
||||
::DrawDebugString(World, Hit.ImpactPoint, FString::Printf(TEXT("%d"), HitIndex), nullptr, HitColor.ToFColor(true), DrawTime, true, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawHelper::DrawFrustum(
|
||||
const UWorld* World,
|
||||
const FMatrix& Matrix,
|
||||
const float Angle,
|
||||
const float AspectRatio,
|
||||
const float NearPlane,
|
||||
const float FarPlane,
|
||||
const FColor& Color,
|
||||
const bool bPersistentLines,
|
||||
const float LifeTime,
|
||||
const uint8 DepthPriority,
|
||||
const float Thickness)
|
||||
{
|
||||
FVector Direction(1, 0, 0);
|
||||
FVector LeftVector(0, 1, 0);
|
||||
FVector UpVector(0, 0, 1);
|
||||
|
||||
FVector Verts[8];
|
||||
|
||||
const float HozHalfAngleInRadians = FMath::DegreesToRadians(Angle * 0.5f);
|
||||
|
||||
float HozLength = 0.0f;
|
||||
float VertLength = 0.0f;
|
||||
|
||||
if (Angle > 0.0f)
|
||||
{
|
||||
HozLength = NearPlane * FMath::Tan(HozHalfAngleInRadians);
|
||||
VertLength = HozLength / AspectRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float OrthoWidth = (Angle == 0.0f) ? 1000.0f : -Angle;
|
||||
HozLength = OrthoWidth * 0.5f;
|
||||
VertLength = HozLength / AspectRatio;
|
||||
}
|
||||
|
||||
// near plane verts
|
||||
Verts[0] = (Direction * NearPlane) + (UpVector * VertLength) + (LeftVector * HozLength);
|
||||
Verts[1] = (Direction * NearPlane) + (UpVector * VertLength) - (LeftVector * HozLength);
|
||||
Verts[2] = (Direction * NearPlane) - (UpVector * VertLength) - (LeftVector * HozLength);
|
||||
Verts[3] = (Direction * NearPlane) - (UpVector * VertLength) + (LeftVector * HozLength);
|
||||
|
||||
if (Angle > 0.0f)
|
||||
{
|
||||
HozLength = FarPlane * FMath::Tan(HozHalfAngleInRadians);
|
||||
VertLength = HozLength / AspectRatio;
|
||||
}
|
||||
|
||||
// far plane verts
|
||||
Verts[4] = (Direction * FarPlane) + (UpVector * VertLength) + (LeftVector * HozLength);
|
||||
Verts[5] = (Direction * FarPlane) + (UpVector * VertLength) - (LeftVector * HozLength);
|
||||
Verts[6] = (Direction * FarPlane) - (UpVector * VertLength) - (LeftVector * HozLength);
|
||||
Verts[7] = (Direction * FarPlane) - (UpVector * VertLength) + (LeftVector * HozLength);
|
||||
|
||||
for (int32 X = 0; X < 8; ++X)
|
||||
{
|
||||
Verts[X] = Matrix.TransformPosition(Verts[X]);
|
||||
}
|
||||
|
||||
DrawDebugLine(World, Verts[0], Verts[1], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[1], Verts[2], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[2], Verts[3], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[3], Verts[0], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[4], Verts[5], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[5], Verts[6], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[6], Verts[7], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[7], Verts[4], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[0], Verts[4], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[1], Verts[5], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[2], Verts[6], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
DrawDebugLine(World, Verts[3], Verts[7], Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
#include "CogDebugDrawImGui.h"
|
||||
|
||||
#include "imgui_internal.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TArray<FCogDebugDrawImGui::FLine> FCogDebugDrawImGui::Lines;
|
||||
TArray<FCogDebugDrawImGui::FTriangle> FCogDebugDrawImGui::Triangles;
|
||||
TArray<FCogDebugDrawImGui::FTriangle> FCogDebugDrawImGui::TrianglesFilled;
|
||||
TArray<FCogDebugDrawImGui::FRectangle> FCogDebugDrawImGui::Rectangles;
|
||||
TArray<FCogDebugDrawImGui::FRectangle> FCogDebugDrawImGui::RectanglesFilled;
|
||||
TArray<FCogDebugDrawImGui::FQuad> FCogDebugDrawImGui::Quads;
|
||||
TArray<FCogDebugDrawImGui::FQuad> FCogDebugDrawImGui::QuadsFilled;
|
||||
TArray<FCogDebugDrawImGui::FCircle> FCogDebugDrawImGui::Circles;
|
||||
TArray<FCogDebugDrawImGui::FCircle> FCogDebugDrawImGui::CirclesFilled;
|
||||
TArray<FCogDebugDrawImGui::FText> FCogDebugDrawImGui::Texts;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::AddLine(const ImVec2& P1, const ImVec2& P2, ImU32 Color, float Thickness /*= 1.0f*/, float Duration /*= 0.0f*/, bool FadeColor /*= false*/)
|
||||
{
|
||||
FLine Line;
|
||||
Line.P1 = P1;
|
||||
Line.P2 = P2;
|
||||
Line.Color = Color;
|
||||
Line.Thickness = Thickness;
|
||||
Line.Time = ImGui::GetCurrentContext()->Time;
|
||||
Line.Duration = Duration;
|
||||
Line.FadeColor = FadeColor;
|
||||
Lines.Add_GetRef(Line);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::AddRect(const ImVec2& Min, const ImVec2& Max, ImU32 Color, float Rounding /*= 0.0f*/, float Thickness /*= 1.0f*/, float Duration /*= 0.0f*/, bool FadeColor /*= false*/)
|
||||
{
|
||||
FRectangle Rectangle;
|
||||
Rectangle.Min = Min;
|
||||
Rectangle.Max = Max;
|
||||
Rectangle.Color = Color;
|
||||
Rectangle.Rounding = Rounding;
|
||||
Rectangle.Thickness = Thickness;
|
||||
Rectangle.Time = ImGui::GetCurrentContext()->Time;
|
||||
Rectangle.Duration = Duration;
|
||||
Rectangle.FadeColor = FadeColor;
|
||||
Rectangles.Add_GetRef(Rectangle);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::AddRectFilled(const ImVec2& Min, const ImVec2& Max, ImU32 Color, float Rounding /*= 0.0f*/, float Duration /*= 0.0f*/, bool FadeColor /*= false*/)
|
||||
{
|
||||
FRectangle Rectangle;
|
||||
Rectangle.Min = Min;
|
||||
Rectangle.Max = Max;
|
||||
Rectangle.Color = Color;
|
||||
Rectangle.Rounding = Rounding;
|
||||
Rectangle.Thickness = 0.0f;
|
||||
Rectangle.Time = ImGui::GetCurrentContext()->Time;
|
||||
Rectangle.Duration = Duration;
|
||||
Rectangle.FadeColor = FadeColor;
|
||||
RectanglesFilled.Add_GetRef(Rectangle);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::AddQuad(const ImVec2& P1, const ImVec2& P2, const ImVec2& P3, const ImVec2& P4, ImU32 Color, float Thickness/* = 1.0f*/, float Duration /*= 0.0f*/, bool FadeColor /*= false*/)
|
||||
{
|
||||
FQuad Quad;
|
||||
Quad.P1 = P1;
|
||||
Quad.P2 = P2;
|
||||
Quad.P3 = P3;
|
||||
Quad.P4 = P4;
|
||||
Quad.Color = Color;
|
||||
Quad.Thickness = Thickness;
|
||||
Quad.Time = ImGui::GetCurrentContext()->Time;
|
||||
Quad.Duration = Duration;
|
||||
Quad.FadeColor = FadeColor;
|
||||
Quads.Add_GetRef(Quad);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::AddQuadFilled(const ImVec2& P1, const ImVec2& P2, const ImVec2& P3, const ImVec2& P4, ImU32 Color, float Duration /*= 0.0f*/, bool FadeColor /*= false*/)
|
||||
{
|
||||
FQuad Quad;
|
||||
Quad.P1 = P1;
|
||||
Quad.P2 = P2;
|
||||
Quad.P3 = P3;
|
||||
Quad.P4 = P4;
|
||||
Quad.Color = Color;
|
||||
Quad.Thickness = 0.0f;
|
||||
Quad.Time = ImGui::GetCurrentContext()->Time;
|
||||
Quad.Duration = Duration;
|
||||
Quad.FadeColor = FadeColor;
|
||||
QuadsFilled.Add_GetRef(Quad);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::AddTriangle(const ImVec2& P1, const ImVec2& P2, const ImVec2& P3, ImU32 Color, float Thickness/* = 1.0f*/, float Duration /*= 0.0f*/, bool FadeColor /*= false*/)
|
||||
{
|
||||
FTriangle Triangle;
|
||||
Triangle.P1 = P1;
|
||||
Triangle.P2 = P2;
|
||||
Triangle.P3 = P3;
|
||||
Triangle.Color = Color;
|
||||
Triangle.Thickness = Thickness;
|
||||
Triangle.Time = ImGui::GetCurrentContext()->Time;
|
||||
Triangle.Duration = Duration;
|
||||
Triangle.FadeColor = FadeColor;
|
||||
Triangles.Add_GetRef(Triangle);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::AddTriangleFilled(const ImVec2& P1, const ImVec2& P2, const ImVec2& P3, ImU32 Color, float Duration /*= 0.0f*/, bool FadeColor /*= false*/)
|
||||
{
|
||||
FTriangle Triangle;
|
||||
Triangle.P1 = P1;
|
||||
Triangle.P2 = P2;
|
||||
Triangle.P3 = P3;
|
||||
Triangle.Color = Color;
|
||||
Triangle.Thickness = 0.0f;
|
||||
Triangle.Time = ImGui::GetCurrentContext()->Time;
|
||||
Triangle.Duration = Duration;
|
||||
Triangle.FadeColor = FadeColor;
|
||||
TrianglesFilled.Add_GetRef(Triangle);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::AddCircle(const ImVec2& Center, float Radius, ImU32 Color, int Segments /*= 0*/, float Thickness /*= 1.0f*/, float Duration /*= 0.0f*/, bool FadeColor /*= false*/)
|
||||
{
|
||||
FCircle Circle;
|
||||
Circle.Center = Center;
|
||||
Circle.Radius = Radius > 0.0f ? Radius : 1.0f;
|
||||
Circle.Color = Color;
|
||||
Circle.Segments = Segments;
|
||||
Circle.Thickness = Thickness;
|
||||
Circle.Time = ImGui::GetCurrentContext()->Time;
|
||||
Circle.Duration = Duration;
|
||||
Circle.FadeColor = FadeColor;
|
||||
Circles.Add_GetRef(Circle);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::AddCircleFilled(const ImVec2& Center, float Radius, ImU32 Color, int Segments /*= 0*/, float Duration /*= 0.0f*/, bool FadeColor /*= false*/)
|
||||
{
|
||||
FCircle Circle;
|
||||
Circle.Center = Center;
|
||||
Circle.Radius = Radius > 0.0f ? Radius : 1.0f;
|
||||
Circle.Color = Color;
|
||||
Circle.Segments = Segments;
|
||||
Circle.Thickness = 0.0f;
|
||||
Circle.Time = ImGui::GetCurrentContext()->Time;
|
||||
Circle.Duration = Duration;
|
||||
Circle.FadeColor = FadeColor;
|
||||
CirclesFilled.Add_GetRef(Circle);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::AddText(const ImVec2& Pos, const FString& Text, ImU32 Color, bool AddShadow /*= false*/, float Duration/* = 0.0f*/, bool FadeColor /*= false*/)
|
||||
{
|
||||
if (AddShadow)
|
||||
{
|
||||
FText ShadowTextElement;
|
||||
ShadowTextElement.Pos = Pos + ImVec2(1, 1);
|
||||
ShadowTextElement.Text = Text;
|
||||
float Alpha = ImGui::ColorConvertU32ToFloat4(Color).w; // Keep original Alpha and set to black
|
||||
ShadowTextElement.Color = ImGui::ColorConvertFloat4ToU32(ImVec4(0, 0, 0, Alpha));
|
||||
ShadowTextElement.Time = ImGui::GetCurrentContext()->Time;
|
||||
ShadowTextElement.Duration = Duration;
|
||||
ShadowTextElement.FadeColor = FadeColor;
|
||||
Texts.Add_GetRef(ShadowTextElement);
|
||||
}
|
||||
|
||||
FText TextElement;
|
||||
TextElement.Pos = Pos;
|
||||
TextElement.Text = Text;
|
||||
TextElement.Color = Color;
|
||||
TextElement.Time = ImGui::GetCurrentContext()->Time;
|
||||
TextElement.Duration = Duration;
|
||||
TextElement.FadeColor = FadeColor;
|
||||
Texts.Add_GetRef(TextElement);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugDrawImGui::Draw()
|
||||
{
|
||||
ImDrawList* DrawList = ImGui::GetBackgroundDrawList();
|
||||
double Time = ImGui::GetCurrentContext()->Time;
|
||||
|
||||
DrawShapes(Lines, [DrawList](const FLine& Line, const ImColor Color) { DrawList->AddLine(Line.P1, Line.P2, Color, Line.Thickness); });
|
||||
DrawShapes(Rectangles, [DrawList](const FRectangle& Rectangle, const ImColor Color) { DrawList->AddRect(Rectangle.Min, Rectangle.Max, Color, Rectangle.Rounding, Rectangle.Thickness); });
|
||||
DrawShapes(RectanglesFilled, [DrawList](const FRectangle& Rectangle, const ImColor Color) { DrawList->AddRectFilled(Rectangle.Min, Rectangle.Max, Color, Rectangle.Rounding); });
|
||||
DrawShapes(Quads, [DrawList](const FQuad& Quad, const ImColor Color) { DrawList->AddQuad(Quad.P1, Quad.P2, Quad.P3, Quad.P4, Color, Quad.Thickness); });
|
||||
DrawShapes(QuadsFilled, [DrawList](const FQuad& Quad, const ImColor Color) { DrawList->AddQuadFilled(Quad.P1, Quad.P2, Quad.P3, Quad.P4, Color); });
|
||||
DrawShapes(Triangles, [DrawList](const FTriangle& Triangle, const ImColor Color) { DrawList->AddTriangle(Triangle.P1, Triangle.P2, Triangle.P3, Color, Triangle.Thickness); });
|
||||
DrawShapes(TrianglesFilled, [DrawList](const FTriangle& Triangle, const ImColor Color) { DrawList->AddTriangleFilled(Triangle.P1, Triangle.P2, Triangle.P3, Color); });
|
||||
DrawShapes(Circles, [DrawList](const FCircle& Circle, const ImColor Color) { DrawList->AddCircle(Circle.Center, Circle.Radius, Color, Circle.Segments, Circle.Thickness); });
|
||||
DrawShapes(CirclesFilled, [DrawList](const FCircle& Circle, const ImColor Color) { DrawList->AddCircleFilled(Circle.Center, Circle.Radius, Color, Circle.Segments); });
|
||||
DrawShapes(Texts, [DrawList](const FText& Text, const ImColor Color) { DrawList->AddText(Text.Pos, Color, TCHAR_TO_ANSI(*Text.Text)); });
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "CogDebugHelper.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FColor FCogDebugHelper::GetAutoColor(FName Name, const FColor& UserColor)
|
||||
{
|
||||
if (UserColor != FColor::Transparent)
|
||||
{
|
||||
return UserColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 Hash = GetTypeHash(Name.ToString());
|
||||
FMath::RandInit(Hash);
|
||||
|
||||
const uint8 Hue = (uint8)(FMath::FRand() * 255);
|
||||
const uint8 Saturation = 255;
|
||||
const uint8 Value = FMath::Rand() > 0.5f ? 200 : 255;
|
||||
|
||||
return FLinearColor::MakeFromHSV8(Hue, Saturation, Value).ToFColor(true);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
const char* FCogDebugHelper::VerbosityToString(ELogVerbosity::Type Verbosity)
|
||||
{
|
||||
switch (Verbosity & ELogVerbosity::VerbosityMask)
|
||||
{
|
||||
case ELogVerbosity::NoLogging: return "No Logging";
|
||||
case ELogVerbosity::Fatal: return "Fatal";
|
||||
case ELogVerbosity::Error: return "Error";
|
||||
case ELogVerbosity::Warning: return "Warning";
|
||||
case ELogVerbosity::Display: return "Display";
|
||||
case ELogVerbosity::Log: return "Log";
|
||||
case ELogVerbosity::Verbose: return "Verbose";
|
||||
case ELogVerbosity::VeryVerbose: return "Very Verbose";
|
||||
}
|
||||
|
||||
return "None";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FString FCogDebugHelper::ShortenEnumName(FString EnumNameString)
|
||||
{
|
||||
int32 ScopeIndex = EnumNameString.Find(TEXT("::"), ESearchCase::CaseSensitive);
|
||||
if (ScopeIndex != INDEX_NONE)
|
||||
{
|
||||
return EnumNameString.Mid(ScopeIndex + 2);
|
||||
}
|
||||
return EnumNameString;
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
#include "CogDebugLog.h"
|
||||
|
||||
#include "CogDebugModule.h"
|
||||
#include "CogDebugReplicator.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "Engine/World.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
DEFINE_LOG_CATEGORY(LogCogNone);
|
||||
DEFINE_LOG_CATEGORY(LogCogServerDebug);
|
||||
|
||||
TMap<FName, FCogDebugLogCategoryInfo> FCogDebugLog::LogCategories;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogDebugLogCategoryInfo
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FString FCogDebugLogCategoryInfo::GetDisplayName() const
|
||||
{
|
||||
if (DisplayName.IsEmpty() == false)
|
||||
{
|
||||
return DisplayName;
|
||||
}
|
||||
|
||||
if (LogCategory != nullptr)
|
||||
{
|
||||
return LogCategory->GetCategoryName().ToString();
|
||||
}
|
||||
|
||||
return FString("Invalid");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogDebugLogCategoryManager
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugLog::AddLogCategory(FLogCategoryBase& LogCategory, const FString& DisplayName, bool bVisible)
|
||||
{
|
||||
LogCategories.Add(LogCategory.GetCategoryName(),
|
||||
FCogDebugLogCategoryInfo
|
||||
{
|
||||
&LogCategory,
|
||||
ELogVerbosity::NumVerbosity,
|
||||
DisplayName,
|
||||
bVisible,
|
||||
});
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogDebugLog::IsVerbosityActive(ELogVerbosity::Type Verbosity)
|
||||
{
|
||||
return Verbosity >= ELogVerbosity::Verbose;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogDebugLog::IsLogCategoryActive(const FLogCategoryBase& LogCategory)
|
||||
{
|
||||
return IsVerbosityActive(LogCategory.GetVerbosity());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogDebugLog::IsLogCategoryActive(FName CategoryName)
|
||||
{
|
||||
if (FLogCategoryBase* LogCategory = FindLogCategory(CategoryName))
|
||||
{
|
||||
return IsVerbosityActive(LogCategory->GetVerbosity());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugLog::SetLogCategoryActive(FLogCategoryBase& LogCategory, bool Value)
|
||||
{
|
||||
LogCategory.SetVerbosity(Value ? ELogVerbosity::Verbose : ELogVerbosity::Warning);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugLog::OnServerVerbosityChanged(FName CategoryName, ELogVerbosity::Type Verbosity)
|
||||
{
|
||||
if (FCogDebugLogCategoryInfo* LogCategoryInfo = FindLogCategoryInfo(CategoryName))
|
||||
{
|
||||
LogCategoryInfo->ServerVerbosity = Verbosity;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ELogVerbosity::Type FCogDebugLog::GetServerVerbosity(FName CategoryName)
|
||||
{
|
||||
if (FCogDebugLogCategoryInfo* LogCategoryInfo = FindLogCategoryInfo(CategoryName))
|
||||
{
|
||||
return LogCategoryInfo->ServerVerbosity;
|
||||
}
|
||||
|
||||
return ELogVerbosity::NoLogging;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugLog::SetServerVerbosity(UWorld& World, FName CategoryName, ELogVerbosity::Type Verbosity)
|
||||
{
|
||||
if (ACogDebugReplicator* Replicator = ACogDebugReplicator::GetLocalReplicator(World))
|
||||
{
|
||||
Replicator->Server_SetCategoryVerbosity(CategoryName, (ECogLogVerbosity)Verbosity);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugLog::SetServerVerbosityActive(UWorld& World, FName CategoryName, bool Value)
|
||||
{
|
||||
SetServerVerbosity(World, CategoryName, Value ? ELogVerbosity::Verbose : ELogVerbosity::Warning);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogDebugLog::IsServerVerbosityActive(FName CategoryName)
|
||||
{
|
||||
return IsVerbosityActive(GetServerVerbosity(CategoryName));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugLogCategoryInfo* FCogDebugLog::FindLogCategoryInfo(FName CategoryName)
|
||||
{
|
||||
return LogCategories.Find(CategoryName);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FLogCategoryBase* FCogDebugLog::FindLogCategory(FName CategoryName)
|
||||
{
|
||||
if (FCogDebugLogCategoryInfo* LogCategoryInfo = FindLogCategoryInfo(CategoryName))
|
||||
{
|
||||
return LogCategoryInfo->LogCategory;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugLog::DeactivateAllLogCateories(UWorld& World)
|
||||
{
|
||||
FString ToggleStr = TEXT("Log LogCogNone Only");
|
||||
GEngine->Exec(&World, *ToggleStr);
|
||||
|
||||
if (APlayerController* PlayerController = World.GetFirstPlayerController())
|
||||
{
|
||||
PlayerController->ServerExec(ToggleStr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "CogDebugLogBlueprint.h"
|
||||
|
||||
#include "CogCommon.h"
|
||||
#include "CogDebugLog.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugLogBlueprint::Log(const UObject* WorldContextObject, FCogLogCategory LogCategory, ECogLogVerbosity Verbosity, const FString& Text)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory();
|
||||
|
||||
if (LogCategoryPtr == nullptr)
|
||||
{
|
||||
COG_LOG(LogCogNone, ELogVerbosity::Warning, TEXT("Blueprint Log - Invalid Log Category: %s"), *Text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (WorldContextObject != nullptr)
|
||||
{
|
||||
COG_LOG_OBJECT_NO_CONTEXT(*LogCategoryPtr, (ELogVerbosity::Type)Verbosity, WorldContextObject, TEXT("%s"), *Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
COG_LOG(*LogCategoryPtr, (ELogVerbosity::Type)Verbosity, TEXT("%s"), *Text);
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogDebugLogBlueprint::IsLogActive(const UObject* WorldContextObject, FCogLogCategory LogCategory)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
|
||||
{
|
||||
if (FCogDebugLog::IsLogCategoryActive(*LogCategoryPtr) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FCogDebugSettings::IsDebugActiveForObject(WorldContextObject) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "CogDebugLogCategory.h"
|
||||
|
||||
#include "CogDebugLog.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FLogCategoryBase* FCogLogCategory::GetLogCategory() const
|
||||
{
|
||||
#if NO_LOGGING
|
||||
|
||||
return nullptr;
|
||||
|
||||
#else
|
||||
|
||||
if (Name.IsNone() || Name.IsValid() == false)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (LogCategory == nullptr)
|
||||
{
|
||||
if (FCogDebugLogCategoryInfo* CategoryInfo = FCogDebugLog::GetLogCategories().Find(Name))
|
||||
{
|
||||
LogCategory = CategoryInfo->LogCategory;
|
||||
}
|
||||
}
|
||||
|
||||
return LogCategory;
|
||||
|
||||
#endif //NO_LOGGING
|
||||
}
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
#include "CogDebugMetric.h"
|
||||
|
||||
#include "CogDebugSettings.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
float FCogDebugMetric::MaxDurationSetting = 0.0f;
|
||||
float FCogDebugMetric::RestartDelaySetting = 5.0f;
|
||||
bool FCogDebugMetric::IsVisible = false;
|
||||
TMap<FName, FCogDebugMetricEntry> FCogDebugMetric::Metrics;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogDebugMetric
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugMetric::AddMetric(const FCogDebugMetricParams& Params)
|
||||
{
|
||||
if (FCogDebugSettings::IsDebugActiveForObject(Params.WorldContextObject) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FCogDebugMetricEntry& Entry = Metrics.FindOrAdd(Params.Name);
|
||||
Entry.Add(Params);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugMetric::AddMetric(const UObject* WorldContextObject, FName Name, float MitigatedValue, float UnmitigatedValue, bool IsCritical)
|
||||
{
|
||||
FCogDebugMetricParams Params;
|
||||
Params.WorldContextObject = WorldContextObject;
|
||||
Params.Name = Name;
|
||||
Params.MitigatedValue = MitigatedValue;
|
||||
Params.UnmitigatedValue = UnmitigatedValue;
|
||||
Params.IsCritical = IsCritical;
|
||||
AddMetric(Params);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugMetric::Tick(float DeltaSeconds)
|
||||
{
|
||||
for (auto& Entry : Metrics)
|
||||
{
|
||||
FCogDebugMetricEntry& Metric = Entry.Value;
|
||||
Metric.Tick(DeltaSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugMetric::Reset()
|
||||
{
|
||||
for (auto& Entry : Metrics)
|
||||
{
|
||||
FCogDebugMetricEntry& Metric = Entry.Value;
|
||||
Metric.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogMetricInstance
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugMetricValue::Reset()
|
||||
{
|
||||
Last = 0.0f;
|
||||
Min = 0.0f;
|
||||
Max = 0.0f;
|
||||
PerSecond = 0.0f;
|
||||
PerFrame = 0.0f;
|
||||
Total = 0.0f;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugMetricValue::AddMetric(const float Metric)
|
||||
{
|
||||
Last = Metric;
|
||||
Min = Min == 0.0f ? Metric : FMath::Min(Min, Metric);
|
||||
Max = FMath::Max(Max, Metric);
|
||||
PerFrame += Metric;
|
||||
Total += Metric;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugMetricValue::UpdateMetricPerSecond(const float Duration)
|
||||
{
|
||||
PerSecond = Duration > 1.0f ? Total / Duration : Total;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugMetricEntry::Reset()
|
||||
{
|
||||
Count = 0;
|
||||
Crits = 0;
|
||||
TotalCritChances = 0.0f;
|
||||
|
||||
IsInProgress = false;
|
||||
Timer = 0.0f;
|
||||
RestartTimer = 0.0f;
|
||||
|
||||
Mitigated.Reset();
|
||||
Unmitigated.Reset();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugMetricEntry::Add(const FCogDebugMetricParams& Params)
|
||||
{
|
||||
// If the max duration is reached, stop adding
|
||||
if (FCogDebugMetric::MaxDurationSetting != 0 && Timer >= FCogDebugMetric::MaxDurationSetting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsInProgress = true;
|
||||
Count++;
|
||||
Crits += Params.IsCritical ? 1 : 0;
|
||||
|
||||
Mitigated.AddMetric(Params.MitigatedValue);
|
||||
Unmitigated.AddMetric(Params.UnmitigatedValue);
|
||||
Mitigated.UpdateMetricPerSecond(Timer);
|
||||
Unmitigated.UpdateMetricPerSecond(Timer);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugMetricEntry::Tick(const float DeltaSeconds)
|
||||
{
|
||||
if (IsInProgress)
|
||||
{
|
||||
// If the max duration is reached, stop increasing time.
|
||||
if (FCogDebugMetric::MaxDurationSetting <= 0 || Timer < FCogDebugMetric::MaxDurationSetting)
|
||||
{
|
||||
Timer += DeltaSeconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsInProgress = false;
|
||||
Timer = FCogDebugMetric::MaxDurationSetting;
|
||||
Mitigated.UpdateMetricPerSecond(Timer);
|
||||
Unmitigated.UpdateMetricPerSecond(Timer);
|
||||
}
|
||||
}
|
||||
|
||||
if (FCogDebugMetric::RestartDelaySetting > 0.0f)
|
||||
{
|
||||
if (Unmitigated.PerFrame == 0.0f)
|
||||
{
|
||||
RestartTimer += DeltaSeconds;
|
||||
if (RestartTimer > FCogDebugMetric::RestartDelaySetting)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RestartTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Mitigated.PerFrame = 0.0f;
|
||||
Unmitigated.PerFrame = 0.0f;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "CogDebugModule.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FCogDebugModule"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugModule::StartupModule()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugModule::ShutdownModule()
|
||||
{
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FCogDebugModule, CogDebug)
|
||||
@@ -0,0 +1,521 @@
|
||||
#include "CogDebugPlot.h"
|
||||
|
||||
#include "CogDebugDraw.h"
|
||||
#include "CogDebugHelper.h"
|
||||
#include "CogImguiHelper.h"
|
||||
|
||||
FCogDebugPlotEvent FCogDebugPlot::DefaultEvent;
|
||||
TArray<FCogDebugPlotEntry> FCogDebugPlot::Plots;
|
||||
bool FCogDebugPlot::IsVisible = false;
|
||||
bool FCogDebugPlot::Pause = false;
|
||||
FName FCogDebugPlot::LastAddedEventPlotName = NAME_None;
|
||||
int32 FCogDebugPlot::LastAddedEventIndex = INDEX_NONE;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogPlotEvent
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
float FCogDebugPlotEvent::GetActualEndTime(const FCogDebugPlotEntry& Plot) const
|
||||
{
|
||||
const float ActualEndTime = EndTime == 0.0f ? Plot.Time : EndTime;
|
||||
return ActualEndTime;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
uint64 FCogDebugPlotEvent::GetActualEndFrame(const FCogDebugPlotEntry& Plot) const
|
||||
{
|
||||
const float ActualEndFame = EndFrame == 0.0f ? Plot.Frame : EndFrame;
|
||||
return ActualEndFame;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlotEvent::AddParam(const FName Name, bool Value)
|
||||
{
|
||||
if (FCogDebugPlot::IsVisible)
|
||||
{
|
||||
AddParam(Name, FString::Printf(TEXT("%s"), Value ? TEXT("True") : TEXT("False")));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlotEvent::AddParam(const FName Name, int Value)
|
||||
{
|
||||
if (FCogDebugPlot::IsVisible)
|
||||
{
|
||||
AddParam(Name, FString::Printf(TEXT("%d"), Value));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlotEvent::AddParam(const FName Name, float Value)
|
||||
{
|
||||
if (FCogDebugPlot::IsVisible)
|
||||
{
|
||||
AddParam(Name, FString::Printf(TEXT("%0.2f"), Value));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlotEvent::AddParam(const FName Name, FName Value)
|
||||
{
|
||||
if (FCogDebugPlot::IsVisible)
|
||||
{
|
||||
AddParam(Name, Value.ToString());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlotEvent::AddParam(const FName Name, const FString& Value)
|
||||
{
|
||||
if (FCogDebugPlot::IsVisible)
|
||||
{
|
||||
|
||||
if (Name == "Name")
|
||||
{
|
||||
DisplayName = Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
FCogDebugPlotEventParams& Param = Params.AddDefaulted_GetRef();
|
||||
Param.Name = Name;
|
||||
Param.Value = Value;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogPlotEntry
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugPlotEntry::AddPoint(float X, float Y)
|
||||
{
|
||||
if (Values.Capacity == 0)
|
||||
{
|
||||
Values.reserve(2000);
|
||||
}
|
||||
|
||||
if (Values.size() < Values.Capacity)
|
||||
{
|
||||
Values.push_back(ImVec2(X, Y));
|
||||
}
|
||||
else
|
||||
{
|
||||
Values[ValueOffset] = ImVec2(X, Y);
|
||||
ValueOffset = (ValueOffset + 1) % Values.size();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlotEntry::AddEvent(
|
||||
const FCogDebugPlotEntry& OwnwePlot,
|
||||
FString OwnerName,
|
||||
bool IsInstant,
|
||||
const FName EventId,
|
||||
const int32 Row,
|
||||
const FColor& Color)
|
||||
{
|
||||
if (Events.Max() < 200)
|
||||
{
|
||||
Events.Reserve(200);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// We currently having two events with the same name at the same time.
|
||||
// So we stop the current one if any exist.
|
||||
//-----------------------------------------------------------------------
|
||||
StopEvent(EventId);
|
||||
|
||||
FCogDebugPlotEvent* Event = nullptr;
|
||||
|
||||
int32 AddedIndex = 0;
|
||||
if (Events.Num() < Events.Max())
|
||||
{
|
||||
Event = &Events.AddDefaulted_GetRef();
|
||||
AddedIndex = Events.Num() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Event = &Events[EventOffset];
|
||||
AddedIndex = EventOffset;
|
||||
EventOffset = (EventOffset + 1) % Events.Num();
|
||||
}
|
||||
|
||||
Event->Id = EventId;
|
||||
Event->OwnerName = OwnerName;
|
||||
Event->DisplayName = EventId.ToString();
|
||||
Event->StartTime = OwnwePlot.Time;
|
||||
Event->EndTime = IsInstant ? OwnwePlot.Time : 0.0f;
|
||||
Event->StartFrame = OwnwePlot.Frame;
|
||||
Event->EndFrame = IsInstant ? OwnwePlot.Frame : 0.0f;
|
||||
Event->Row = (Row == FCogDebugPlot::AutoRow) ? OwnwePlot.FindFreeRow() : Row;
|
||||
|
||||
MaxRow = FMath::Max(Event->Row, MaxRow);
|
||||
|
||||
const FColor BorderColor = FCogDebugHelper::GetAutoColor(EventId, Color).WithAlpha(200);
|
||||
const FColor FillColor = BorderColor.WithAlpha(100);
|
||||
Event->BorderColor = FCogImguiHelper::ToImColor(BorderColor);
|
||||
Event->FillColor = FCogImguiHelper::ToImColor(FillColor);
|
||||
|
||||
FCogDebugPlot::LastAddedEventPlotName = OwnwePlot.Name;
|
||||
FCogDebugPlot::LastAddedEventIndex = AddedIndex;
|
||||
|
||||
return *Event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlotEntry::StopEvent(const FName EventId)
|
||||
{
|
||||
FCogDebugPlotEvent* Event = FindLastEventByName(EventId);
|
||||
if (Event == nullptr)
|
||||
{
|
||||
return FCogDebugPlot::DefaultEvent;
|
||||
}
|
||||
|
||||
if (Event->EndTime == 0.0f)
|
||||
{
|
||||
Event->EndTime = Time;
|
||||
Event->EndFrame = Frame;
|
||||
}
|
||||
|
||||
return *Event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugPlotEntry::UpdateTime(const UWorld* World)
|
||||
{
|
||||
Time = World ? World->GetTimeSeconds() : 0.0;
|
||||
Frame = GFrameCounter;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent* FCogDebugPlotEntry::GetLastEvent()
|
||||
{
|
||||
if (Events.Num() == 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int32 Index = Events.Num() - 1;
|
||||
if (EventOffset != 0)
|
||||
{
|
||||
Index = (Index + EventOffset) % Events.Num();
|
||||
}
|
||||
|
||||
return &Events[Index];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent* FCogDebugPlotEntry::FindLastEventByName(FName EventId)
|
||||
{
|
||||
for (int32 i = Events.Num() - 1; i >= 0; --i)
|
||||
{
|
||||
//--------------------------------------------------
|
||||
// The array cycle so we must offset the index
|
||||
//--------------------------------------------------
|
||||
int32 Index = i;
|
||||
if (EventOffset != 0)
|
||||
{
|
||||
Index = (i + EventOffset) % Events.Num();
|
||||
}
|
||||
|
||||
if (Events[Index].Id == EventId)
|
||||
{
|
||||
return &Events[Index];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
int32 FCogDebugPlotEntry::FindFreeRow() const
|
||||
{
|
||||
static float InstantTimeThreshold = 1.0f;
|
||||
static float TotalTimeThreshold = 10.0f;
|
||||
TSet<int32> OccupiedRows;
|
||||
|
||||
for (int32 i = Events.Num() - 1; i >= 0; --i)
|
||||
{
|
||||
int32 Index = i;
|
||||
if (EventOffset != 0)
|
||||
{
|
||||
Index = (i + EventOffset) % Events.Num();
|
||||
}
|
||||
const FCogDebugPlotEvent& Event = Events[Index];
|
||||
|
||||
if (Event.EndTime != 0.0f && Time > Event.EndTime + TotalTimeThreshold)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (Event.StartTime == Event.EndTime && Time > Event.EndTime + InstantTimeThreshold)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Event.EndTime != 0.0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
OccupiedRows.Add(Event.Row);
|
||||
}
|
||||
|
||||
int32 FreeRow = 0;
|
||||
while (true)
|
||||
{
|
||||
if (OccupiedRows.Contains(FreeRow) == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
FreeRow++;
|
||||
}
|
||||
|
||||
return FreeRow;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugPlotEntry::AssignAxis(int32 Row, ImAxis YAxis)
|
||||
{
|
||||
CurrentRow = Row;
|
||||
CurrentYAxis = YAxis;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugPlotEntry::ResetAxis()
|
||||
{
|
||||
CurrentRow = INDEX_NONE;
|
||||
CurrentYAxis = ImAxis_COUNT;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugPlotEntry::Clear()
|
||||
{
|
||||
FCogDebugPlot::ResetLastAddedEvent();
|
||||
|
||||
MaxRow = 0;
|
||||
|
||||
if (Values.size() > 0)
|
||||
{
|
||||
Values.shrink(0);
|
||||
ValueOffset = 0;
|
||||
}
|
||||
|
||||
if (Events.Num() > 0)
|
||||
{
|
||||
Events.Empty();
|
||||
Events.Shrink();
|
||||
EventOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogDebugPlotEntry::FindValue(float x, float& y) const
|
||||
{
|
||||
y = 0.0f;
|
||||
|
||||
bool FoundAfter = false;
|
||||
bool FoundBefore = false;
|
||||
|
||||
for (int32 i = Values.size() - 1; i >= 0; --i)
|
||||
{
|
||||
//--------------------------------------------------
|
||||
// The array cycle so we must offset the index
|
||||
//--------------------------------------------------
|
||||
int32 Index = i;
|
||||
if (ValueOffset != 0)
|
||||
{
|
||||
Index = (i + ValueOffset) % Values.size();
|
||||
}
|
||||
|
||||
ImVec2 Point = Values[Index];
|
||||
if (Point.x > x)
|
||||
{
|
||||
FoundAfter = true;
|
||||
}
|
||||
|
||||
if (Point.x < x)
|
||||
{
|
||||
FoundBefore = true;
|
||||
}
|
||||
|
||||
if (FoundAfter && FoundBefore)
|
||||
{
|
||||
y = Point.y;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogPlot
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugPlot::Reset()
|
||||
{
|
||||
Plots.Empty();
|
||||
Pause = false;
|
||||
ResetLastAddedEvent();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugPlot::Clear()
|
||||
{
|
||||
for (FCogDebugPlotEntry& Entry : FCogDebugPlot::Plots)
|
||||
{
|
||||
Entry.Clear();
|
||||
}
|
||||
|
||||
ResetLastAddedEvent();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugPlot::ResetLastAddedEvent()
|
||||
{
|
||||
LastAddedEventPlotName = NAME_None;
|
||||
LastAddedEventIndex = INDEX_NONE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent* FCogDebugPlot::GetLastAddedEvent()
|
||||
{
|
||||
FCogDebugPlotEntry* Plot = FindPlot(LastAddedEventPlotName);
|
||||
if (Plot == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return Plot->GetLastEvent();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEntry* FCogDebugPlot::FindPlot(const FName Name)
|
||||
{
|
||||
FCogDebugPlotEntry* Plot = Plots.FindByPredicate([Name](const FCogDebugPlotEntry& P) { return P.Name == Name; });
|
||||
return Plot;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEntry* FCogDebugPlot::RegisterPlot(const UObject* WorldContextObject, const FName PlotName, bool IsEventPlot)
|
||||
{
|
||||
//----------------------------------------------------------
|
||||
// When not visible, we don't go further for performances.
|
||||
//----------------------------------------------------------
|
||||
if (IsVisible == false)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull);
|
||||
if (World == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (FCogDebugSettings::IsDebugActiveForObject(WorldContextObject) == false)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FCogDebugPlotEntry* EntryPtr = FindPlot(PlotName);
|
||||
if (EntryPtr == nullptr)
|
||||
{
|
||||
EntryPtr = &Plots.AddDefaulted_GetRef();
|
||||
EntryPtr->Name = PlotName;
|
||||
EntryPtr->IsEventPlot = IsEventPlot;
|
||||
Plots.Sort([](const FCogDebugPlotEntry& A, const FCogDebugPlotEntry& B) { return A.Name.ToString().Compare(B.Name.ToString()) < 0; });
|
||||
}
|
||||
|
||||
if (EntryPtr->CurrentYAxis == ImAxis_COUNT)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const float Time = World->GetTimeSeconds();
|
||||
if (Time < EntryPtr->Time)
|
||||
{
|
||||
EntryPtr->Clear();
|
||||
}
|
||||
|
||||
EntryPtr->Time = World->GetTimeSeconds();
|
||||
EntryPtr->Frame = GFrameCounter;
|
||||
|
||||
return EntryPtr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugPlot::PlotValue(const UObject* WorldContextObject, const FName PlotName, const float Value)
|
||||
{
|
||||
FCogDebugPlotEntry* Plot = RegisterPlot(WorldContextObject, PlotName, false);
|
||||
if (Plot == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Plot->AddPoint(Plot->Time, Value);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlot::PlotEvent(const UObject* WorldContextObject, const FName PlotName, const FName EventId, bool IsInstant, const int32 Row, const FColor& Color)
|
||||
{
|
||||
FCogDebugPlotEntry* Plot = RegisterPlot(WorldContextObject, PlotName, true);
|
||||
if (Plot == nullptr)
|
||||
{
|
||||
ResetLastAddedEvent();
|
||||
return DefaultEvent;
|
||||
}
|
||||
|
||||
FCogDebugPlotEvent& Event = Plot->AddEvent(*Plot, GetNameSafe(WorldContextObject), IsInstant, EventId, Row, Color);
|
||||
return Event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlot::PlotEventInstant(const UObject* WorldContextObject, const FName PlotName, const FName EventId, const int32 Row, const FColor& Color)
|
||||
{
|
||||
FCogDebugPlotEvent& Event = PlotEvent(WorldContextObject, PlotName, EventId, true, Row, Color);
|
||||
return Event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlot::PlotEventStart(const UObject* WorldContextObject, const FName PlotName, const FName EventId, const int32 Row, const FColor& Color)
|
||||
{
|
||||
FCogDebugPlotEvent& Event = PlotEvent(WorldContextObject, PlotName, EventId, false, Row, Color);
|
||||
return Event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlot::PlotEventStop(const UObject* WorldContextObject, const FName PlotName, const FName EventId)
|
||||
{
|
||||
FCogDebugPlotEntry* Plot = RegisterPlot(WorldContextObject, PlotName, true);
|
||||
if (Plot == nullptr)
|
||||
{
|
||||
return DefaultEvent;
|
||||
}
|
||||
|
||||
FCogDebugPlotEvent& Event = Plot->StopEvent(EventId);
|
||||
return Event;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogDebugPlotEvent& FCogDebugPlot::PlotEventToggle(const UObject* WorldContextObject, const FName PlotName, const FName EventId, const bool ToggleValue, const int32 Row, const FColor& Color)
|
||||
{
|
||||
if (ToggleValue)
|
||||
{
|
||||
return PlotEventStart(WorldContextObject, PlotName, EventId, Row, Color);
|
||||
}
|
||||
else
|
||||
{
|
||||
return PlotEventStop(WorldContextObject, PlotName, EventId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "CogDebugPlotBlueprint.h"
|
||||
|
||||
#include "CogCommon.h"
|
||||
#include "CogDebugPlot.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogDebugPlotBlueprint::Plot(const UObject* Owner, const FName Name, const float Value)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
FCogDebugPlot::PlotValue(Owner, Name, Value);
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
#include "CogDebugReplicator.h"
|
||||
|
||||
#include "CogDebugDraw.h"
|
||||
#include "EngineUtils.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "GameFramework/WorldSettings.h"
|
||||
#include "Net/Core/PushModel/PushModel.h"
|
||||
#include "Net/UnrealNetwork.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// ACogDebugReplicator
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ACogDebugReplicator* ACogDebugReplicator::Spawn(APlayerController* Controller)
|
||||
{
|
||||
if (Controller->GetWorld()->GetNetMode() == NM_Client)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FActorSpawnParameters SpawnInfo;
|
||||
SpawnInfo.Owner = Controller;
|
||||
return Controller->GetWorld()->SpawnActor<ACogDebugReplicator>(SpawnInfo);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ACogDebugReplicator* ACogDebugReplicator::GetLocalReplicator(UWorld& World)
|
||||
{
|
||||
for (TActorIterator<ACogDebugReplicator> It(&World, ACogDebugReplicator::StaticClass()); It; ++It)
|
||||
{
|
||||
ACogDebugReplicator* Replicator = *It;
|
||||
return Replicator;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogDebugReplicator::GetRemoteReplicators(UWorld& World, TArray<ACogDebugReplicator*>& Replicators)
|
||||
{
|
||||
for (TActorIterator<ACogDebugReplicator> It(&World, ACogDebugReplicator::StaticClass()); It; ++It)
|
||||
{
|
||||
ACogDebugReplicator* Replicator = Cast<ACogDebugReplicator>(*It);
|
||||
Replicators.Add(Replicator);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ACogDebugReplicator::ACogDebugReplicator(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
PrimaryActorTick.bAllowTickOnDedicatedServer = true;
|
||||
PrimaryActorTick.bTickEvenWhenPaused = true;
|
||||
PrimaryActorTick.bStartWithTickEnabled = true;
|
||||
PrimaryActorTick.TickGroup = TG_PrePhysics;
|
||||
|
||||
bReplicates = true;
|
||||
bOnlyRelevantToOwner = true;
|
||||
|
||||
bHasAuthority = false;
|
||||
ReplicatedData.Owner = this;
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogDebugReplicator::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
UWorld* World = GetWorld();
|
||||
check(World);
|
||||
const ENetMode NetMode = World->GetNetMode();
|
||||
bHasAuthority = NetMode != NM_Client;
|
||||
|
||||
OwnerPlayerController = Cast<APlayerController>(GetOwner());
|
||||
|
||||
if (OwnerPlayerController->IsLocalController())
|
||||
{
|
||||
Server_RequestAllCategoriesVerbosity();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogDebugReplicator::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||
{
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
|
||||
FDoRepLifetimeParams Params;
|
||||
Params.bIsPushBased = true;
|
||||
|
||||
DOREPLIFETIME_WITH_PARAMS_FAST(ACogDebugReplicator, ReplicatedData, Params);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogDebugReplicator::TickActor(float DeltaTime, enum ELevelTick TickType, FActorTickFunction& ThisTickFunction)
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
Super::TickActor(DeltaTime, TickType, ThisTickFunction);
|
||||
if (OwnerPlayerController)
|
||||
{
|
||||
if (GetWorld()->GetNetMode() == NM_Client)
|
||||
{
|
||||
for (FCogDebugShape ReplicatedShape : ReplicatedShapes)
|
||||
{
|
||||
ReplicatedShape.Draw(GetWorld());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogDebugReplicator::Server_SetCategoryVerbosity_Implementation(FName LogCategoryName, ECogLogVerbosity Verbosity)
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
ENetMode NetMode = GetWorld()->GetNetMode();
|
||||
if (NetMode == NM_DedicatedServer || NetMode == NM_ListenServer)
|
||||
{
|
||||
if (FCogDebugLogCategoryInfo* LogCategoryInfo = FCogDebugLog::FindLogCategoryInfo(LogCategoryName))
|
||||
{
|
||||
LogCategoryInfo->LogCategory->SetVerbosity((ELogVerbosity::Type)Verbosity);
|
||||
|
||||
TArray<FCogServerCategoryData> CategoriesData;
|
||||
CategoriesData.Add({ LogCategoryName, Verbosity });
|
||||
NetMulticast_SendCategoriesVerbosity(CategoriesData);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogDebugReplicator::NetMulticast_SendCategoriesVerbosity_Implementation(const TArray<FCogServerCategoryData>& Categories)
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
if (GetWorld()->GetNetMode() == NM_Client)
|
||||
{
|
||||
for (const FCogServerCategoryData& Category : Categories)
|
||||
{
|
||||
FCogDebugLog::OnServerVerbosityChanged(Category.LogCategoryName, (ELogVerbosity::Type)Category.Verbosity);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogDebugReplicator::Client_SendCategoriesVerbosity_Implementation(const TArray<FCogServerCategoryData>& Categories)
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
if (GetWorld()->GetNetMode() == NM_Client)
|
||||
{
|
||||
for (const FCogServerCategoryData& Category : Categories)
|
||||
{
|
||||
FCogDebugLog::OnServerVerbosityChanged(Category.LogCategoryName, (ELogVerbosity::Type)Category.Verbosity);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogDebugReplicator::Server_RequestAllCategoriesVerbosity_Implementation()
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
ENetMode NetMode = GetWorld()->GetNetMode();
|
||||
if (NetMode == NM_DedicatedServer || NetMode == NM_ListenServer)
|
||||
{
|
||||
TArray<FCogServerCategoryData> CategoriesData;
|
||||
for (auto& Entry : FCogDebugLog::GetLogCategories())
|
||||
{
|
||||
FCogDebugLogCategoryInfo& CategoryInfo = Entry.Value;
|
||||
if (CategoryInfo.LogCategory != nullptr)
|
||||
{
|
||||
CategoriesData.Add(
|
||||
{
|
||||
CategoryInfo.LogCategory->GetCategoryName(),
|
||||
(ECogLogVerbosity)CategoryInfo.LogCategory->GetVerbosity()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Client_SendCategoriesVerbosity(CategoriesData);
|
||||
}
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogReplicatorNetPack
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
class FCogReplicatorNetState : public INetDeltaBaseState
|
||||
{
|
||||
public:
|
||||
|
||||
virtual bool IsStateEqual(INetDeltaBaseState* OtherState) override
|
||||
{
|
||||
FCogReplicatorNetState* Other = static_cast<FCogReplicatorNetState*>(OtherState);
|
||||
return (ShapesRepCounter == Other->ShapesRepCounter);
|
||||
}
|
||||
|
||||
int32 ShapesRepCounter = 0;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogReplicatorNetPack
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogReplicatorNetPack::NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms)
|
||||
{
|
||||
if (DeltaParms.bUpdateUnmappedObjects || Owner == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DeltaParms.Writer)
|
||||
{
|
||||
const bool bIsOwnerClient = !Owner->bHasAuthority;
|
||||
if (bIsOwnerClient)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FCogReplicatorNetState* OldState = static_cast<FCogReplicatorNetState*>(DeltaParms.OldState);
|
||||
FCogReplicatorNetState* NewState = new FCogReplicatorNetState();
|
||||
check(DeltaParms.NewState);
|
||||
*DeltaParms.NewState = TSharedPtr<INetDeltaBaseState>(NewState);
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Find delta to replicate
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
const bool bMissingOldState = (OldState == nullptr);
|
||||
const bool bShapesChanged = (SavedShapes != Owner->ReplicatedShapes);
|
||||
NewState->ShapesRepCounter = (bMissingOldState ? 0 : OldState->ShapesRepCounter) + (bShapesChanged ? 1 : 0);
|
||||
if (bShapesChanged)
|
||||
{
|
||||
SavedShapes = Owner->ReplicatedShapes;
|
||||
Owner->ReplicatedShapes.Empty();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Write
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
const bool bMissingOldState = (OldState == nullptr);
|
||||
const uint8 ShouldUpdateShapes = bMissingOldState || (OldState->ShapesRepCounter != NewState->ShapesRepCounter);
|
||||
|
||||
FBitWriter& Writer = *DeltaParms.Writer;
|
||||
Writer.WriteBit(ShouldUpdateShapes);
|
||||
if (ShouldUpdateShapes)
|
||||
{
|
||||
Writer << SavedShapes;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (DeltaParms.Reader)
|
||||
{
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Read
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
FBitReader& Reader = *DeltaParms.Reader;
|
||||
const uint8 ShouldUpdateShapes = Reader.ReadBit();
|
||||
if (ShouldUpdateShapes)
|
||||
{
|
||||
Reader << Owner->ReplicatedShapes;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
#include "CogDebugSettings.h"
|
||||
|
||||
#include "CogCommonDebugFilteredActorInterface.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TWeakObjectPtr<AActor> FCogDebugSettings::Selection;
|
||||
bool FCogDebugSettings::FilterBySelection = true;
|
||||
bool FCogDebugSettings::Persistent = false;
|
||||
bool FCogDebugSettings::TextShadow = true;
|
||||
bool FCogDebugSettings::Fade2D = true;
|
||||
float FCogDebugSettings::Duration = 3.0f;
|
||||
int FCogDebugSettings::DepthPriority = 0;
|
||||
int FCogDebugSettings::Segments = 12;
|
||||
float FCogDebugSettings::Thickness = 0.0f;
|
||||
float FCogDebugSettings::ServerThickness = 2.0f;
|
||||
float FCogDebugSettings::ServerColorMultiplier = 0.8f;
|
||||
float FCogDebugSettings::ArrowSize = 10.0f;
|
||||
float FCogDebugSettings::AxesScale = 1.0f;
|
||||
float FCogDebugSettings::GradientColorIntensity = 0.0f;
|
||||
float FCogDebugSettings::GradientColorSpeed = 2.0f;
|
||||
float FCogDebugSettings::TextSize = 1.0f;
|
||||
TArray<FString> FCogDebugSettings::SecondaryBoneWildcards =
|
||||
{
|
||||
"interaction",
|
||||
"center_of_mass",
|
||||
"ik_*",
|
||||
"index_*",
|
||||
"middle_*",
|
||||
"pinky_*",
|
||||
"ring_*",
|
||||
"thumb_*",
|
||||
"wrist_*",
|
||||
"*_bck_*",
|
||||
"*_fwd_*",
|
||||
"*_in_*",
|
||||
"*_out_*",
|
||||
"*_pec_*",
|
||||
"*_scap_*",
|
||||
"*_bicep_*",
|
||||
"*_tricep_*",
|
||||
"*ankle*",
|
||||
"*knee*",
|
||||
"*corrective*",
|
||||
"*twist*",
|
||||
"*latissimus*",
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugSettings::Reset()
|
||||
{
|
||||
FilterBySelection = true;
|
||||
Persistent = false;
|
||||
TextShadow = true;
|
||||
Fade2D = true;
|
||||
Duration = 3.0f;
|
||||
DepthPriority = 0;
|
||||
Segments = 12;
|
||||
Thickness = 0.0f;
|
||||
ServerThickness = 2.0f;
|
||||
ServerColorMultiplier = 0.8f;
|
||||
ArrowSize = 10.0f;
|
||||
AxesScale = 1.0f;
|
||||
GradientColorIntensity = 0.0f;
|
||||
GradientColorSpeed = 2.0f;
|
||||
TextSize = 1.0f;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogDebugSettings::IsDebugActiveForObject(const UObject* WorldContextObject)
|
||||
{
|
||||
if (FilterBySelection == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (WorldContextObject == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const AActor* SelectionPtr = Selection.Get();
|
||||
if (SelectionPtr == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const UObject* Outer = WorldContextObject;
|
||||
for (;;)
|
||||
{
|
||||
if (SelectionPtr == Outer)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Cast<ICogCommonDebugFilteredActorInterface>(Outer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const UObject* NewOuter = Outer->GetOuter();
|
||||
if (NewOuter == Outer || NewOuter == nullptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Outer = NewOuter;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
AActor* FCogDebugSettings::GetSelection()
|
||||
{
|
||||
return Selection.Get();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugSettings::SetSelection(AActor* Value)
|
||||
{
|
||||
Selection = Value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogDebugSettings::GetDebugPersistent(bool bPersistent)
|
||||
{
|
||||
return Persistent && bPersistent;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
float FCogDebugSettings::GetDebugDuration(bool bPersistent)
|
||||
{
|
||||
return bPersistent == false ? 0.0f : Duration;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
float FCogDebugSettings::GetDebugTextDuration(bool bPersistent)
|
||||
{
|
||||
if (bPersistent)
|
||||
{
|
||||
return Persistent ? 100 : Duration;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
int FCogDebugSettings::GetDebugSegments()
|
||||
{
|
||||
return Segments;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
int FCogDebugSettings::GetCircleSegments()
|
||||
{
|
||||
return (Segments * 2) + 2; // because DrawDebugCircle does Segments = FMath::Max((Segments - 2) / 2, 4) for some reason
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
float FCogDebugSettings::GetDebugThickness(float InThickness)
|
||||
{
|
||||
return (Thickness + InThickness);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
float FCogDebugSettings::GetDebugServerThickness(float InThickness)
|
||||
{
|
||||
return (ServerThickness + InThickness);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
uint8 FCogDebugSettings::GetDebugDepthPriority(float InDepthPriority)
|
||||
{
|
||||
return (DepthPriority + InDepthPriority);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FColor FCogDebugSettings::ModulateDebugColor(const UWorld* World, const FColor& Color, bool bPersistent)
|
||||
{
|
||||
if (bPersistent == false)
|
||||
{
|
||||
return Color;
|
||||
}
|
||||
|
||||
const float Time = World->GetTimeSeconds();
|
||||
const FLinearColor BaseColor(Color);
|
||||
FLinearColor ComplementaryColor = BaseColor.LinearRGBToHSV();
|
||||
|
||||
ComplementaryColor.R = ComplementaryColor.R - 180.0f;
|
||||
if (ComplementaryColor.R < 0.0f)
|
||||
{
|
||||
ComplementaryColor.R = 360.0f - ComplementaryColor.R;
|
||||
}
|
||||
|
||||
ComplementaryColor = ComplementaryColor.HSVToLinearRGB();
|
||||
|
||||
const FLinearColor GradientColor = FLinearColor::LerpUsingHSV(FLinearColor(Color), ComplementaryColor, FMath::Cos(GradientColorSpeed * Time));
|
||||
const FLinearColor FBlendColor = BaseColor * (1.0f - FCogDebugSettings::GradientColorIntensity) + GradientColor * GradientColorIntensity;
|
||||
return FBlendColor.ToFColor(true);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FColor FCogDebugSettings::ModulateServerColor(const FColor& Color)
|
||||
{
|
||||
FColor ServerColor(
|
||||
Color.R * ServerColorMultiplier,
|
||||
Color.G * ServerColorMultiplier,
|
||||
Color.B * ServerColorMultiplier,
|
||||
Color.A);
|
||||
|
||||
return ServerColor;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogDebugSettings::IsSecondarySkeletonBone(FName BoneName)
|
||||
{
|
||||
FString BoneString = BoneName.ToString().ToLower();
|
||||
|
||||
for (const FString& Wildcard : SecondaryBoneWildcards)
|
||||
{
|
||||
if (BoneString.MatchesWildcard(Wildcard))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,629 @@
|
||||
#include "CogDebugShape.h"
|
||||
|
||||
#include "CogCommon.h"
|
||||
#include "CogDebugDrawHelper.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakePoint(const FVector& Location, const float Size, const FColor& Color, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(Location);
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Point;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Size;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawPoint(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 1)
|
||||
{
|
||||
DrawDebugPoint(
|
||||
World,
|
||||
ShapeData[0],
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness),
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeSegment(const FVector& StartLocation, const FVector& EndLocation, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(StartLocation);
|
||||
NewElement.ShapeData.Add(EndLocation);
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Segment;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawSegment(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 2)
|
||||
{
|
||||
DrawDebugLine(
|
||||
World,
|
||||
ShapeData[0],
|
||||
ShapeData[1],
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeArrow(const FVector& StartLocation, const FVector& EndLocation, const float HeadSize, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(StartLocation);
|
||||
NewElement.ShapeData.Add(EndLocation);
|
||||
NewElement.ShapeData.Add(FVector(HeadSize, 0, 0));
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Arrow;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawArrow(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 3)
|
||||
{
|
||||
DrawDebugDirectionalArrow(
|
||||
World,
|
||||
ShapeData[0],
|
||||
ShapeData[1],
|
||||
ShapeData[2].X,
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeAxes(const FVector& Location, const FRotator& Rotation, const float HeadSize, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(Location);
|
||||
NewElement.ShapeData.Add(FVector(Rotation.Pitch, Rotation.Yaw, Rotation.Roll));
|
||||
NewElement.ShapeData.Add(FVector(HeadSize, 0, 0));
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Axes;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawAxes(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 3)
|
||||
{
|
||||
DrawDebugCoordinateSystem(
|
||||
World,
|
||||
ShapeData[0],
|
||||
FRotator(ShapeData[1].X, ShapeData[1].Y, ShapeData[1].Z),
|
||||
ShapeData[2].X,
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeBox(const FVector& Center, const FRotator& Rotation, const FVector& Extent, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(Center);
|
||||
NewElement.ShapeData.Add(Extent);
|
||||
NewElement.ShapeData.Add(FVector(Rotation.Pitch, Rotation.Yaw, Rotation.Roll));
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Box;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawBox(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 3)
|
||||
{
|
||||
DrawDebugBox(
|
||||
World,
|
||||
ShapeData[0],
|
||||
ShapeData[1],
|
||||
FQuat(FRotator(ShapeData[2].X, ShapeData[2].Y, ShapeData[2].Z)),
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeSolidBox(const FVector& Center, const FRotator& Rotation, const FVector& Extent, const FColor& Color, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(Center);
|
||||
NewElement.ShapeData.Add(FVector(Rotation.Pitch, Rotation.Yaw, Rotation.Roll));
|
||||
NewElement.ShapeData.Add(Extent);
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::SolidBox;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
|
||||
void FCogDebugShape::DrawSolidBox(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 12)
|
||||
{
|
||||
DrawDebugSolidBox(
|
||||
World,
|
||||
ShapeData[0],
|
||||
ShapeData[1],
|
||||
FQuat(FRotator(ShapeData[1].X, ShapeData[1].Y, ShapeData[1].Z)),
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeCone(const FVector& Location, const FVector& Direction, const float Length, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(Location);
|
||||
NewElement.ShapeData.Add(Direction);
|
||||
NewElement.ShapeData.Add(FVector(Length, 0, 0));
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Cone;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawCone(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 3 && ShapeData[2].X > 0)
|
||||
{
|
||||
const float DefaultConeAngle = 0.25f; // ~ 15 degrees
|
||||
DrawDebugCone(
|
||||
World,
|
||||
ShapeData[0],
|
||||
ShapeData[1],
|
||||
ShapeData[2].X,
|
||||
DefaultConeAngle,
|
||||
DefaultConeAngle,
|
||||
FCogDebugSettings::GetCircleSegments(),
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeCylinder(const FVector& Center, const float Radius, const float HalfHeight, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(Center);
|
||||
NewElement.ShapeData.Add(FVector(Radius, 0, HalfHeight));
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Cylinder;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawCylinder(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 2)
|
||||
{
|
||||
DrawDebugCylinder(
|
||||
World,
|
||||
ShapeData[0] - FVector(0, 0, ShapeData[1].Z),
|
||||
ShapeData[0] + FVector(0, 0, ShapeData[1].Z),
|
||||
ShapeData[1].X,
|
||||
FCogDebugSettings::GetCircleSegments(),
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeCircle(const FVector& Center, const FRotator& Rotation, const float Radius, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(Center);
|
||||
NewElement.ShapeData.Add(FVector(Rotation.Pitch, Rotation.Yaw, Rotation.Roll));
|
||||
NewElement.ShapeData.Add(FVector(Radius, 0, 0));
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Circle;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawCicle(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 3)
|
||||
{
|
||||
DrawDebugCircle(
|
||||
World,
|
||||
FRotationTranslationMatrix(FRotator(ShapeData[1].X, ShapeData[1].Y, ShapeData[1].Z), ShapeData[0]),
|
||||
ShapeData[2].X,
|
||||
FCogDebugSettings::GetCircleSegments(),
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness),
|
||||
false);
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeCircleArc(const FVector& Center, const FRotator& Rotation, const float InnerRadius, const float OuterRadius, const float Angle, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(Center);
|
||||
NewElement.ShapeData.Add(FVector(Rotation.Pitch, Rotation.Yaw, Rotation.Roll));
|
||||
NewElement.ShapeData.Add(FVector(InnerRadius, OuterRadius, Angle));
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::CircleArc;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawCicleArc(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 3)
|
||||
{
|
||||
FCogDebugDrawHelper::DrawArc(
|
||||
World,
|
||||
FRotationTranslationMatrix(FRotator(ShapeData[1].X, ShapeData[1].Y, ShapeData[1].Z), ShapeData[0]),
|
||||
ShapeData[2].X,
|
||||
ShapeData[2].Y,
|
||||
ShapeData[2].Z,
|
||||
FCogDebugSettings::GetDebugSegments(),
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeCapsule(const FVector& Center, const FQuat& Rotation, const float Radius, const float HalfHeight, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(Center);
|
||||
NewElement.ShapeData.Add(FVector(Radius, HalfHeight, 0));
|
||||
NewElement.ShapeData.Add(Rotation.Euler());
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Capsule;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawCapsule(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 3)
|
||||
{
|
||||
DrawDebugCapsule(
|
||||
World,
|
||||
ShapeData[0],
|
||||
ShapeData[1].Y,
|
||||
ShapeData[1].X,
|
||||
FQuat::MakeFromEuler(ShapeData[2]),
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeFlatCapsule(const FVector2D& Start, const FVector2D& End, const float Radius, const float Z, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(FVector(Start.X, Start.Y, 0));
|
||||
NewElement.ShapeData.Add(FVector(End.X, End.Y, 0));
|
||||
NewElement.ShapeData.Add(FVector(Radius, Z, 0));
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::FlatCapsule;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawFlatCapsule(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() > 0)
|
||||
{
|
||||
FCogDebugDrawHelper::DrawFlatCapsule(
|
||||
World,
|
||||
FVector2D(ShapeData[0].X, ShapeData[0].Y),
|
||||
FVector2D(ShapeData[1].X, ShapeData[1].Y),
|
||||
ShapeData[2].X,
|
||||
ShapeData[2].Y,
|
||||
FCogDebugSettings::GetCircleSegments(),
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakeBone(const FVector& BoneLocation, const FVector& ParentLocation, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
|
||||
NewElement.ShapeData.Add(BoneLocation);
|
||||
NewElement.ShapeData.Add(ParentLocation);
|
||||
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Bone;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = Thickness;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawBone(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() == 2)
|
||||
{
|
||||
DrawDebugLine(
|
||||
World,
|
||||
ShapeData[0],
|
||||
ShapeData[1],
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority),
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness));
|
||||
|
||||
DrawDebugPoint(
|
||||
World,
|
||||
ShapeData[0],
|
||||
FCogDebugSettings::GetDebugServerThickness(Thickness) + 4.0f,
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FCogDebugShape FCogDebugShape::MakePolygon(const TArray<FVector>& Verts, const FColor& Color, const bool bPersistent, const uint8 DepthPriority)
|
||||
{
|
||||
FCogDebugShape NewElement;
|
||||
NewElement.ShapeData = Verts;
|
||||
NewElement.Color = Color;
|
||||
NewElement.Type = ECogDebugShape::Polygon;
|
||||
NewElement.bPersistent = bPersistent;
|
||||
NewElement.DepthPriority = DepthPriority;
|
||||
NewElement.Thickness = 0.0f;
|
||||
return NewElement;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::DrawPolygon(UWorld* World)
|
||||
{
|
||||
#if ENABLE_COG
|
||||
|
||||
if (ShapeData.Num() > 0)
|
||||
{
|
||||
FVector MidPoint = FVector::ZeroVector;
|
||||
TArray<int32> Indices;
|
||||
for (int32 Idx = 0; Idx < ShapeData.Num(); Idx++)
|
||||
{
|
||||
Indices.Add(Idx);
|
||||
MidPoint += ShapeData[Idx];
|
||||
}
|
||||
|
||||
DrawDebugMesh(
|
||||
World,
|
||||
ShapeData,
|
||||
Indices,
|
||||
FCogDebugSettings::ModulateServerColor(Color),
|
||||
FCogDebugSettings::GetDebugPersistent(bPersistent),
|
||||
FCogDebugSettings::GetDebugDuration(bPersistent),
|
||||
FCogDebugSettings::GetDebugDepthPriority(DepthPriority));
|
||||
}
|
||||
|
||||
#endif //ENABLE_COG
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FCogDebugShape::Draw(UWorld* World)
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case ECogDebugShape::Arrow: DrawArrow(World); break;
|
||||
case ECogDebugShape::Axes: DrawAxes(World); break;
|
||||
case ECogDebugShape::Bone: DrawBone(World); break;
|
||||
case ECogDebugShape::Box: DrawBox(World); break;
|
||||
case ECogDebugShape::Capsule: DrawCapsule(World); break;
|
||||
case ECogDebugShape::Circle: DrawCicle(World); break;
|
||||
case ECogDebugShape::CircleArc: DrawCicleArc(World); break;
|
||||
case ECogDebugShape::Cone: DrawCone(World); break;
|
||||
case ECogDebugShape::Cylinder: DrawCylinder(World); break;
|
||||
case ECogDebugShape::FlatCapsule: DrawFlatCapsule(World); break;
|
||||
case ECogDebugShape::Point: DrawPoint(World); break;
|
||||
case ECogDebugShape::Polygon: DrawPolygon(World); break;
|
||||
case ECogDebugShape::Segment: DrawSegment(World); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
FArchive& operator<<(FArchive& Ar, FCogDebugShape& Shape)
|
||||
{
|
||||
Ar << Shape.ShapeData;
|
||||
Ar << Shape.Color;
|
||||
Ar << Shape.bPersistent;
|
||||
Ar << Shape.DepthPriority;
|
||||
Ar << Shape.Thickness;
|
||||
|
||||
uint8 TypeNum = static_cast<uint8>(Shape.Type);
|
||||
Ar << TypeNum;
|
||||
Shape.Type = static_cast<ECogDebugShape>(TypeNum);
|
||||
|
||||
return Ar;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogCommon.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
struct FCogDebugShape;
|
||||
|
||||
#if ENABLE_COG
|
||||
|
||||
struct COGDEBUG_API FCogDebugDraw
|
||||
{
|
||||
static void String2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FString& Text, const FVector2D& Location, const FColor& Color, bool Persistent);
|
||||
|
||||
static void Segment2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& SegmentStart, const FVector2D& SegmentEnd, const FColor& Color, bool Persistent);
|
||||
|
||||
static void Circle2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& Location, float Radius, const FColor& Color, const bool Persistent);
|
||||
|
||||
static void Rect2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& Min, const FVector2D& Max, const FColor& Color, const bool Persistent);
|
||||
|
||||
static void String(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FString& Text, const FVector& Location, const FColor& Color, const bool Persistent);
|
||||
|
||||
static void Point(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Location, float Size, const FColor& Color, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Segment(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& SegmentStart, const FVector& SegmentEnd, const FColor& Color, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Bone(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& BoneLocation, const FVector& ParentLocation, const FColor& Color, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Arrow(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& SegmentStart, const FVector& SegmentEnd, const FColor& Color, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Axis(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& AxisLoc, const FRotator& AxisRot, float Scale, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Circle(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FMatrix& Matrix, float Radius, const FColor& Color, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void CircleArc(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FMatrix& Matrix, float InnerRadius, float OuterRadius, float Angle, const FColor& Color, bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void FlatCapsule(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& Start, const FVector2D& End, const float Radius, const float Z, const FColor& Color, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Sphere(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Location, float Radius, const FColor& Color, bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Box(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Center, const FVector& Extent, const FQuat& Rotation, const FColor& Color, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void SolidBox(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Center, const FVector& Extent, const FQuat& Rotation, const FColor& Color, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Capsule(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Center, const float HalfHeight, const float Radius, const FQuat& Rotation, const FColor& Color, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Points(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const TArray<FVector>& Points, float Radius, const FColor& StartColor, const FColor& EndColor, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Path(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const TArray<FVector>& Points, float PointSize, const FColor& StartColor, const FColor& EndColor, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Frustrum(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FMatrix& Matrix, const float Angle, const float AspectRatio, const float NearPlane, const float FarPlane, const FColor& Color, const bool Persistent, const uint8 DepthPriority = 0U);
|
||||
|
||||
static void Skeleton(const FLogCategoryBase& LogCategory, const USkeletalMeshComponent* Skeleton, const FColor& Color, bool DrawSecondaryBones = false, const uint8 DepthPriority = 1);
|
||||
|
||||
static void ReplicateShape(const UObject* WorldContextObject, const FCogDebugShape& Shape);
|
||||
};
|
||||
|
||||
#endif //ENABLE_COG
|
||||
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "CogDebugDrawBlueprint.generated.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS(meta = (ScriptName = "CogDebugDrawBlueprint"))
|
||||
class COGDEBUG_API UCogDebugDrawBlueprint : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawString(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FString& Text, const FVector Location, const FLinearColor Color, bool Persistent);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawPoint(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Location, float size, const FLinearColor Color, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawSegment(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector SegmentStart, const FVector SegmentEnd, const FLinearColor Color, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawArrow(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector SegmentStart, const FVector SegmentEnd, const FLinearColor Color, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawAxis(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Location, const FRotator Rotation, float Scale, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawSphere(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Location, float Radius, const FLinearColor Color, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawBox(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Center, const FVector Extent, const FQuat Rotation, const FLinearColor Color, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawSolidBox(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Center, const FVector Extent, const FQuat Rotation, const FLinearColor Color, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawCapsule(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector Center, const float HalfHeight, const float Radius, const FQuat Rotation, const FLinearColor Color, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawCircle(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FMatrix& Matrix, float Radius, const FLinearColor Color, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawCircleArc(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FMatrix& Matrix, float InnerRadius, float OuterRadius, float Angle, const FLinearColor Color, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawPoints(const UObject* WorldContextObject, FCogLogCategory LogCategory, const TArray<FVector>& Points, float Radius, const FLinearColor StartColor, const FLinearColor EndColor, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawPath(const UObject* WorldContextObject, FCogLogCategory LogCategory, const TArray<FVector>& Points, float PointSize, const FLinearColor StartColor, const FLinearColor EndColor, bool Persistent, uint8 DepthPriority);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawString2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FString& Text, const FVector2D Location, const FLinearColor Color, bool Persistent);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawSegment2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector2D SegmentStart, const FVector2D SegmentEnd, const FLinearColor Color, bool Persistent);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawCircle2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector2D Location, float Radius, const FLinearColor Color, bool Persistent);
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void DebugDrawRect2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector2D Min, const FVector2D Max, const FLinearColor Color, bool Persistent);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
namespace EDrawDebugTrace { enum Type; }
|
||||
|
||||
class COGDEBUG_API FCogDebugDrawHelper
|
||||
{
|
||||
public:
|
||||
|
||||
static void DrawArc(const UWorld* InWorld, const FMatrix& Matrix, const float InnterRadius, const float OuterRadius, const float ArcAngle, const int32 Segments, const FColor& Color, const bool bPersistentLines = false, const float LifeTime = -1.f, const uint8 DepthPriority = 0U, const float Thickness = 0.0f);
|
||||
|
||||
static void DrawSphere(const UWorld* InWorld, const FVector& Center, const float Radius, const int32 Segments, const FColor& Color, const bool bPersistentLines = false, const float LifeTime = -1.f, const uint8 DepthPriority = 0U, const float Thickness = 0.0f);
|
||||
|
||||
static void DrawFrustum(const UWorld* World, const FMatrix& Matrix, const float Angle, const float AspectRatio, const float NearPlane, const float FarPlane, const FColor& Color, const bool bPersistentLines = false, const float LifeTime = -1.f, const uint8 DepthPriority = 0U, const float Thickness = 0.0f);
|
||||
|
||||
static void DrawFlatCapsule(const UWorld* InWorld, const FVector2D& Start, const FVector2D& End, const float Radius, const float Z, const float Segments, const FColor& Color, const bool bPersistentLines = false, const float LifeTime = -1.0f, const uint8 DepthPriority = 0, const float Thickness = 0.0f);
|
||||
|
||||
static void DrawRaycastSingle(const UWorld* World, const FVector& Start, const FVector& End, const EDrawDebugTrace::Type DrawType, const bool bHit, const FHitResult& Hit, const float HitSize, const FLinearColor DrawColor, const FLinearColor DrawHitColor, const float DrawDuration, const uint8 DepthPriority = 0);
|
||||
|
||||
static void DrawSphereOverlapMulti(const UWorld* World, const FVector& Position, const float Radius, const EDrawDebugTrace::Type DrawType, const bool bOverlap, const TArray<AActor*>& OutActors, const FLinearColor DrawColor, const FLinearColor DrawHitColor, const float DrawDuration = 0);
|
||||
|
||||
static void DrawSphereOverlapSingle(const UWorld* World, const FVector& Position, const float Radius, const FColor& DrawColor, const bool DrawPersistent, const float DrawDuration = -1.f, const uint8 DepthPriority = 0);
|
||||
|
||||
static void DrawCapsuleCastMulti(const UWorld* World, const FVector& Start, const FVector& End, const FQuat& Rotation, const float HalfHeight, const float Radius, const EDrawDebugTrace::Type DrawType, const bool bHit, const TArray<FHitResult>& OutHits, const FLinearColor DrawColor, const FLinearColor DrawHitColor, const float DrawDuration = 0);
|
||||
|
||||
static void DrawCapsuleCastSingle(const UWorld* World, const FVector& Start, const FVector& End, const FQuat& Rotation, const float HalfHeight, const float Radius, const FColor& DrawColor, const bool DrawPersistent, const float DrawDuration = -1.f, const uint8 DepthPriority = 0);
|
||||
|
||||
static void DrawSphereCastMulti(const UWorld* World, const FVector& Start, const FVector& End, const float Radius, const EDrawDebugTrace::Type DrawType, const bool bHit, const TArray<FHitResult>& OutHits, const FLinearColor DrawColor, const FLinearColor DrawHitColor, const float DrawDuration = 0);
|
||||
|
||||
static void DrawSphereCastSingle(const UWorld* World, const FVector& Start, const FVector& End, const float Radius, const FColor& DrawColor, const bool DrawPersistent, const float LifeTime = -1.f, const uint8 DepthPriority = 0);
|
||||
|
||||
static void DrawHitResults(const UWorld* World, const TArray<FHitResult>& OutHits, const EDrawDebugTrace::Type DrawType, const bool ShowHitIndex, const float HitSize, const FLinearColor HitColor, const float DrawDuration, const uint8 DepthPriority = 0);
|
||||
|
||||
static void DrawHitResultsDiscarded(const UWorld* World, const TArray<FHitResult>& AllHits, const TArray<FHitResult>& KeptHits, const EDrawDebugTrace::Type DrawType, const float HitSize, const FLinearColor DrawColor, const float DrawDuration, const uint8 DepthPriority = 0);
|
||||
|
||||
static void DrawHitResult(const UWorld* World, const FHitResult& Hit, const int HitIndex, const EDrawDebugTrace::Type DrawType, const bool ShowHitIndex, const float HitSize, const FLinearColor HitColor, const float DrawDuration, const uint8 DepthPriority = 0);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "imgui.h"
|
||||
|
||||
class COGDEBUG_API FCogDebugDrawImGui
|
||||
{
|
||||
public:
|
||||
static void AddLine(const ImVec2& P1, const ImVec2& P2, ImU32 Color, float Thickness = 1.0f, float Duration = 0.0f, bool FadeColor = false);
|
||||
static void AddRect(const ImVec2& Min, const ImVec2& Max, ImU32 Color, float Rounding = 0.0f, float Thickness = 1.0f, float Duration = 0.0f, bool FadeColor = false);
|
||||
static void AddRectFilled(const ImVec2& Min, const ImVec2& Max, ImU32 Color, float Rounding = 0.0f, float Duration = 0.0f, bool FadeColor = false);
|
||||
static void AddQuad(const ImVec2& P1, const ImVec2& P2, const ImVec2& P3, const ImVec2& P4, ImU32 Color, float Thickness = 1.0f, float Duration = 0.0f, bool FadeColor = false);
|
||||
static void AddQuadFilled(const ImVec2& P1, const ImVec2& P2, const ImVec2& P3, const ImVec2& P4, ImU32 Color, float Duration = 0.0f, bool FadeColor = false);
|
||||
static void AddTriangle(const ImVec2& P1, const ImVec2& P2, const ImVec2& P3, ImU32 Color, float Thickness = 1.0f, float Duration = 0.0f, bool FadeColor = false);
|
||||
static void AddTriangleFilled(const ImVec2& P1, const ImVec2& P2, const ImVec2& P3, ImU32 Color, float Duration = 0.0f, bool FadeColor = false);
|
||||
static void AddCircle(const ImVec2& Center, float Radius, ImU32 Color, int Segments = 0, float Thickness = 1.0f, float Duration = 0.0f, bool FadeColor = false);
|
||||
static void AddCircleFilled(const ImVec2& Center, float Radius, ImU32 Color, int Segments = 0, float Duration = 0.0f, bool FadeColor = false);
|
||||
static void AddText(const ImVec2& Pos, const FString& Text, ImU32 Color, bool AddShadow = false, float Duration = 0.0f, bool FadeColor = false);
|
||||
|
||||
static void Draw();
|
||||
|
||||
private:
|
||||
struct FShape
|
||||
{
|
||||
ImU32 Color = 0;
|
||||
float Duration = 0.0f;
|
||||
double Time = 0.0f;
|
||||
bool FadeColor = false;
|
||||
};
|
||||
|
||||
struct FLine : FShape
|
||||
{
|
||||
ImVec2 P1 = ImVec2(0, 0);
|
||||
ImVec2 P2 = ImVec2(0, 0);
|
||||
float Thickness = 0.0f;
|
||||
};
|
||||
|
||||
struct FRectangle : FShape
|
||||
{
|
||||
ImVec2 Min = ImVec2(0, 0);
|
||||
ImVec2 Max = ImVec2(0, 0);
|
||||
float Rounding = 0.0f;
|
||||
float Thickness = 0.0f;
|
||||
};
|
||||
|
||||
struct FQuad : FShape
|
||||
{
|
||||
ImVec2 P1 = ImVec2(0, 0);
|
||||
ImVec2 P2 = ImVec2(0, 0);
|
||||
ImVec2 P3 = ImVec2(0, 0);
|
||||
ImVec2 P4 = ImVec2(0, 0);
|
||||
float Thickness = 0.0f;
|
||||
};
|
||||
|
||||
struct FTriangle : FShape
|
||||
{
|
||||
ImVec2 P1 = ImVec2(0, 0);
|
||||
ImVec2 P2 = ImVec2(0, 0);
|
||||
ImVec2 P3 = ImVec2(0, 0);
|
||||
float Thickness = 0.0f;
|
||||
};
|
||||
|
||||
struct FCircle : FShape
|
||||
{
|
||||
ImVec2 Center = ImVec2(0, 0);
|
||||
float Radius = 0.0f;
|
||||
int Segments = 12;
|
||||
float Thickness = 0.0f;
|
||||
};
|
||||
|
||||
struct FText : FShape
|
||||
{
|
||||
ImVec2 Pos = ImVec2(0, 0);
|
||||
FString Text;
|
||||
ImU32 Color = 0;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
static TArray<FLine> Lines;
|
||||
static TArray<FTriangle> Triangles;
|
||||
static TArray<FTriangle> TrianglesFilled;
|
||||
static TArray<FRectangle> Rectangles;
|
||||
static TArray<FRectangle> RectanglesFilled;
|
||||
static TArray<FQuad> Quads;
|
||||
static TArray<FQuad> QuadsFilled;
|
||||
static TArray<FCircle> Circles;
|
||||
static TArray<FCircle> CirclesFilled;
|
||||
static TArray<FText> Texts;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
template<typename TShape, typename TDrawFunction>
|
||||
static void DrawShapes(TArray<TShape>& Shapes, TDrawFunction DrawFunction)
|
||||
{
|
||||
ImDrawList* ImDrawList = ImGui::GetBackgroundDrawList();
|
||||
const double Time = ImGui::GetCurrentContext()->Time;
|
||||
|
||||
for (int32 i = 0; i < Shapes.Num(); i++)
|
||||
{
|
||||
const TShape& Shape = Shapes[i];
|
||||
const double ElapsedTime = Time - Shape.Time;
|
||||
const float Fade = Shape.FadeColor && Shape.Duration > 0.0f ? 1.0f - (ElapsedTime / Shape.Duration) : 1.0f;
|
||||
ImColor Color(Shape.Color);
|
||||
Color.Value.w = Fade * Color.Value.w;
|
||||
DrawFunction(Shape, Color);
|
||||
|
||||
if (ElapsedTime < 0 || ElapsedTime > Shape.Duration)
|
||||
{
|
||||
Shapes.RemoveAtSwap(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "imgui.h"
|
||||
|
||||
class COGDEBUG_API FCogDebugHelper
|
||||
{
|
||||
public:
|
||||
|
||||
static FColor GetAutoColor(FName Name, const FColor& UserColor);
|
||||
|
||||
static const char* VerbosityToString(ELogVerbosity::Type Verbosity);
|
||||
|
||||
static FString ShortenEnumName(FString EnumNameString);
|
||||
|
||||
template<typename EnumType>
|
||||
static FString GetValueAsStringShort(const EnumType EnumeratorValue)
|
||||
{
|
||||
FString EnumNameString = UEnum::GetValueAsString(EnumeratorValue);
|
||||
return ShortenEnumName(EnumNameString);
|
||||
}
|
||||
|
||||
template<typename EnumType>
|
||||
static FName GetValueAsNameShort(const EnumType EnumeratorValue)
|
||||
{
|
||||
return FName(GetValueAsStringShort(EnumeratorValue));
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Logging/LogVerbosity.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogNone, Warning, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogServerDebug, Verbose, All);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct COGDEBUG_API FCogDebugLogCategoryInfo
|
||||
{
|
||||
FLogCategoryBase* LogCategory = nullptr;
|
||||
ELogVerbosity::Type ServerVerbosity = ELogVerbosity::NoLogging;
|
||||
FString DisplayName;
|
||||
bool bVisible = true;
|
||||
|
||||
FString GetDisplayName() const;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct COGDEBUG_API FCogDebugLog
|
||||
{
|
||||
static void AddLogCategory(FLogCategoryBase& LogCategory, const FString& DisplayName = "", bool bVisible = true);
|
||||
|
||||
static bool IsVerbosityActive(ELogVerbosity::Type Verbosity);
|
||||
|
||||
static bool IsLogCategoryActive(const FLogCategoryBase& LogCategory);
|
||||
|
||||
static bool IsLogCategoryActive(FName CategoryName);
|
||||
|
||||
static void SetLogCategoryActive(FLogCategoryBase& LogCategory, bool Value);
|
||||
|
||||
static FLogCategoryBase* FindLogCategory(FName LogCategory);
|
||||
|
||||
static FCogDebugLogCategoryInfo* FindLogCategoryInfo(FName LogCategory);
|
||||
|
||||
static TMap<FName, FCogDebugLogCategoryInfo>& GetLogCategories() { return LogCategories; }
|
||||
|
||||
static void SetServerVerbosityActive(UWorld& World, FName LogCategory, bool Value);
|
||||
|
||||
static bool IsServerVerbosityActive(FName LogCategory);
|
||||
|
||||
static ELogVerbosity::Type GetServerVerbosity(FName LogCategory);
|
||||
|
||||
static void SetServerVerbosity(UWorld& World, FName LogCategory, ELogVerbosity::Type Verbosity);
|
||||
|
||||
static void OnServerVerbosityChanged(FName LogCategory, ELogVerbosity::Type Verbosity);
|
||||
|
||||
static void DeactivateAllLogCateories(UWorld& World);
|
||||
|
||||
private:
|
||||
|
||||
static TMap<FName, FCogDebugLogCategoryInfo> LogCategories;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
#include "Logging/LogVerbosity.h"
|
||||
#include "CogDebugLogBlueprint.generated.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM()
|
||||
enum class ECogLogVerbosity : uint8
|
||||
{
|
||||
Fatal = ELogVerbosity::Fatal,
|
||||
Error = ELogVerbosity::Error,
|
||||
Warning = ELogVerbosity::Warning,
|
||||
Display = ELogVerbosity::Display,
|
||||
Log = ELogVerbosity::Log,
|
||||
Verbose = ELogVerbosity::Verbose,
|
||||
VeryVerbose = ELogVerbosity::VeryVerbose
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS(meta = (ScriptName = "CogLogBlueprint"))
|
||||
class COGDEBUG_API UCogDebugLogBlueprint : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static void Log(const UObject* WorldContextObject, FCogLogCategory LogCategory, ECogLogVerbosity Verbosity = ECogLogVerbosity::Verbose, const FString& Text = FString(""));
|
||||
|
||||
UFUNCTION(BlueprintPure, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
|
||||
static bool IsLogActive(const UObject* WorldContextObject, FCogLogCategory LogCategory);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogDebugLogCategory.generated.h"
|
||||
|
||||
struct FCogLogCategory;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
USTRUCT(BlueprintType)
|
||||
struct COGDEBUG_API FCogLogCategory
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
FCogLogCategory() {}
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FName Name;
|
||||
|
||||
FString GetName() const { return Name.ToString(); }
|
||||
|
||||
FLogCategoryBase* GetLogCategory() const;
|
||||
|
||||
private:
|
||||
|
||||
mutable FLogCategoryBase* LogCategory = nullptr;
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogCommon.h"
|
||||
|
||||
#ifdef ENABLE_COG
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct COGDEBUG_API FCogDebugMetricParams
|
||||
{
|
||||
TObjectPtr<const UObject> WorldContextObject = nullptr;
|
||||
|
||||
FName Name;
|
||||
|
||||
float MitigatedValue = 0;
|
||||
|
||||
float UnmitigatedValue = 0;
|
||||
|
||||
bool IsCritical = false;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct COGDEBUG_API FCogDebugMetricValue
|
||||
{
|
||||
void Reset();
|
||||
|
||||
void AddMetric(const float Damage);
|
||||
|
||||
void UpdateMetricPerSecond(const float Duration);
|
||||
|
||||
float Last = 0.0f;
|
||||
|
||||
float Min = 0.0f;
|
||||
|
||||
float Max = 0.0f;
|
||||
|
||||
float PerFrame = 0.0f;
|
||||
|
||||
float PerSecond = 0.0f;
|
||||
|
||||
float Total = 0.0f;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct COGDEBUG_API FCogDebugMetricEntry
|
||||
{
|
||||
public:
|
||||
|
||||
void Add(const FCogDebugMetricParams& Params);
|
||||
|
||||
void Tick(const float DeltaSeconds);
|
||||
|
||||
void Reset();
|
||||
|
||||
int Count = 0;
|
||||
|
||||
int Crits = 0;
|
||||
|
||||
bool IsInProgress = false;
|
||||
|
||||
float TotalCritChances = 0.0f;
|
||||
|
||||
float Timer = 0.0f;
|
||||
|
||||
float RestartTimer = 0.0f;
|
||||
|
||||
FCogDebugMetricValue Mitigated;
|
||||
|
||||
FCogDebugMetricValue Unmitigated;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
class COGDEBUG_API FCogDebugMetric
|
||||
{
|
||||
public:
|
||||
|
||||
static void Tick(float DeltaSeconds);
|
||||
|
||||
static void AddMetric(const FCogDebugMetricParams& Params);
|
||||
|
||||
static void AddMetric(const UObject* WorldContextObject, FName Name, float MitigatedValue, float UnmitigatedValue, bool IsCritical);
|
||||
|
||||
static void Reset();
|
||||
|
||||
static bool IsVisible;
|
||||
|
||||
static float MaxDurationSetting;
|
||||
|
||||
static float RestartDelaySetting;
|
||||
|
||||
static TMap<FName, FCogDebugMetricEntry> Metrics;
|
||||
};
|
||||
|
||||
#endif //ENABLE_COG
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class ACogDebugReplicator;
|
||||
class APlayerController;
|
||||
|
||||
class COGDEBUG_API FCogDebugModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
static inline FCogDebugModule& Get() { return FModuleManager::LoadModuleChecked<FCogDebugModule>("CogDebug"); }
|
||||
|
||||
virtual void StartupModule() override;
|
||||
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogCommon.h"
|
||||
#include "imgui.h"
|
||||
#include "implot.h"
|
||||
|
||||
#ifdef ENABLE_COG
|
||||
|
||||
struct FCogDebugPlotEntry;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct COGDEBUG_API FCogDebugPlotEventParams
|
||||
{
|
||||
FName Name;
|
||||
FString Value;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct COGDEBUG_API FCogDebugPlotEvent
|
||||
{
|
||||
float GetActualEndTime(const FCogDebugPlotEntry& Plot) const;
|
||||
|
||||
uint64 GetActualEndFrame(const FCogDebugPlotEntry& Plot) const;
|
||||
|
||||
FCogDebugPlotEvent& AddParam(const FName Name, bool Value);
|
||||
|
||||
FCogDebugPlotEvent& AddParam(const FName Name, int Value);
|
||||
|
||||
FCogDebugPlotEvent& AddParam(const FName Name, float Value);
|
||||
|
||||
FCogDebugPlotEvent& AddParam(const FName Name, FName Value);
|
||||
|
||||
FCogDebugPlotEvent& AddParam(const FName Name, const FString& Value);
|
||||
|
||||
FName Id;
|
||||
float StartTime = 0.0f;
|
||||
float EndTime = 0.0f;
|
||||
uint64 StartFrame = 0;
|
||||
uint64 EndFrame = 0;
|
||||
ImU32 BorderColor;
|
||||
ImU32 FillColor;
|
||||
int32 Row;
|
||||
FString OwnerName;
|
||||
FString DisplayName;
|
||||
TArray<FCogDebugPlotEventParams> Params;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct COGDEBUG_API FCogDebugPlotEntry
|
||||
{
|
||||
void AssignAxis(int32 AssignedRow, ImAxis CurrentYAxis);
|
||||
void AddPoint(float X, float Y);
|
||||
bool FindValue(float Time, float& Value) const;
|
||||
void ResetAxis();
|
||||
void Clear();
|
||||
FCogDebugPlotEvent& AddEvent(const FCogDebugPlotEntry& OwnwePlot, FString OwnerName, bool IsInstant, const FName EventId, const int32 Row, const FColor& Color);
|
||||
FCogDebugPlotEvent& StopEvent(const FName EventId);
|
||||
void UpdateTime(const UWorld* World);
|
||||
int32 FindFreeRow() const;
|
||||
FCogDebugPlotEvent* GetLastEvent();
|
||||
FCogDebugPlotEvent* FindLastEventByName(FName EventId);
|
||||
|
||||
FName Name;
|
||||
bool IsEventPlot = false;
|
||||
int32 CurrentRow = INDEX_NONE;
|
||||
ImAxis CurrentYAxis = ImAxis_COUNT;
|
||||
float Time = 0;
|
||||
uint64 Frame = 0;
|
||||
|
||||
//--------------------------
|
||||
// Values
|
||||
//--------------------------
|
||||
int32 ValueOffset = 0;
|
||||
ImVector<ImVec2> Values;
|
||||
bool ShowValuesMarkers = false;
|
||||
|
||||
//--------------------------
|
||||
// Events
|
||||
//--------------------------
|
||||
int32 EventOffset = 0;
|
||||
TArray<FCogDebugPlotEvent> Events;
|
||||
int32 MaxRow = 1;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
class COGDEBUG_API FCogDebugPlot
|
||||
{
|
||||
public:
|
||||
static const int32 AutoRow = -1;
|
||||
|
||||
static void PlotValue(const UObject* WorldContextObject, const FName PlotName, const float Value);
|
||||
static FCogDebugPlotEvent& PlotEvent(const UObject* WorldContextObject, const FName PlotName, const FName EventId, bool IsInstant, const int32 Row = AutoRow, const FColor& Color = FColor::Transparent);
|
||||
static FCogDebugPlotEvent& PlotEventInstant(const UObject* WorldContextObject, const FName PlotName, const FName EventId, const int32 Row = AutoRow, const FColor& Color = FColor::Transparent);
|
||||
static FCogDebugPlotEvent& PlotEventStart(const UObject* WorldContextObject, const FName PlotName, const FName EventId, const int32 Row = AutoRow, const FColor& Color = FColor::Transparent);
|
||||
static FCogDebugPlotEvent& PlotEventStop(const UObject* WorldContextObject, const FName PlotName, const FName EventId);
|
||||
static FCogDebugPlotEvent& PlotEventToggle(const UObject* WorldContextObject, const FName PlotName, const FName EventId, const bool ToggleValue, const int32 Row = AutoRow, const FColor& Color = FColor::Transparent);
|
||||
|
||||
static void Reset();
|
||||
static void Clear();
|
||||
static FCogDebugPlotEntry* FindPlot(const FName Name);
|
||||
|
||||
static TArray<FCogDebugPlotEntry> Plots;
|
||||
static bool IsVisible;
|
||||
static bool Pause;
|
||||
|
||||
private:
|
||||
friend struct FCogDebugPlotEntry;
|
||||
|
||||
static void ResetLastAddedEvent();
|
||||
static FCogDebugPlotEntry* RegisterPlot(const UObject* Owner, const FName PlotName, bool IsEventPlot);
|
||||
FCogDebugPlotEventParams* PlotEventAddParam(const FName Name);
|
||||
static FCogDebugPlotEvent* GetLastAddedEvent();
|
||||
|
||||
static FName LastAddedEventPlotName;
|
||||
static int32 LastAddedEventIndex;
|
||||
|
||||
static FCogDebugPlotEvent DefaultEvent;
|
||||
};
|
||||
|
||||
#endif //ENABLE_COG
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "CogDebugPlotBlueprint.generated.h"
|
||||
|
||||
UCLASS(meta = (ScriptName = "CogDebugPlot"))
|
||||
class COGDEBUG_API UCogDebugPlotBlueprint : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly))
|
||||
static void Plot(const UObject* Owner, const FName Name, const float Value);
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "CogDebugShape.h"
|
||||
#include "CogDebugLogBlueprint.h"
|
||||
#include "UObject/Class.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "CogDebugReplicator.generated.h"
|
||||
|
||||
class ACogDebugReplicator;
|
||||
class APlayerController;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
USTRUCT()
|
||||
struct FCogServerCategoryData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY()
|
||||
FName LogCategoryName;
|
||||
|
||||
UPROPERTY()
|
||||
ECogLogVerbosity Verbosity = ECogLogVerbosity::Fatal;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
USTRUCT()
|
||||
struct FCogReplicatorNetPack
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
ACogDebugReplicator* Owner = nullptr;
|
||||
|
||||
bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms);
|
||||
|
||||
private:
|
||||
|
||||
TArray<FCogDebugShape> SavedShapes;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TStructOpsTypeTraits<FCogReplicatorNetPack> : public TStructOpsTypeTraitsBase2<FCogReplicatorNetPack>
|
||||
{
|
||||
enum
|
||||
{
|
||||
WithNetDeltaSerializer = true,
|
||||
};
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS(NotBlueprintable, NotBlueprintType, notplaceable, noteditinlinenew, hidedropdown, Transient)
|
||||
class COGDEBUG_API ACogDebugReplicator : public AActor
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
static ACogDebugReplicator* Spawn(APlayerController* Controller);
|
||||
|
||||
static ACogDebugReplicator* GetLocalReplicator(UWorld& World);
|
||||
|
||||
static void GetRemoteReplicators(UWorld& World, TArray<ACogDebugReplicator*>& Replicators);
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void TickActor(float DeltaTime, enum ELevelTick TickType, FActorTickFunction& ThisTickFunction) override;
|
||||
|
||||
APlayerController* GetPlayerController() const { return OwnerPlayerController.Get(); }
|
||||
|
||||
TArray<FCogDebugShape> ReplicatedShapes;
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_RequestAllCategoriesVerbosity();
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_SetCategoryVerbosity(FName LogCategoryName, ECogLogVerbosity Verbosity);
|
||||
|
||||
UFUNCTION(NetMulticast, Reliable)
|
||||
void NetMulticast_SendCategoriesVerbosity(const TArray<FCogServerCategoryData>& Categories);
|
||||
|
||||
UFUNCTION(Client, Reliable)
|
||||
void Client_SendCategoriesVerbosity(const TArray<FCogServerCategoryData>& Categories);
|
||||
|
||||
protected:
|
||||
friend FCogReplicatorNetPack;
|
||||
|
||||
TObjectPtr<APlayerController> OwnerPlayerController;
|
||||
|
||||
uint32 bHasAuthority : 1;
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(Replicated)
|
||||
FCogReplicatorNetPack ReplicatedData;
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
struct COGDEBUG_API FCogDebugSettings
|
||||
{
|
||||
public:
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
static bool IsDebugActiveForObject(const UObject* WorldContextObject);
|
||||
|
||||
static AActor* GetSelection();
|
||||
|
||||
static void SetSelection(AActor* Value);
|
||||
|
||||
static bool GetDebugPersistent(bool bPersistent);
|
||||
|
||||
static float GetDebugDuration(bool bPersistent);
|
||||
|
||||
static float GetDebugTextDuration(bool bPersistent);
|
||||
|
||||
static int GetCircleSegments();
|
||||
|
||||
static int GetDebugSegments();
|
||||
|
||||
static float GetDebugThickness(float Thickness);
|
||||
|
||||
static float GetDebugServerThickness(float Thickness);
|
||||
|
||||
static uint8 GetDebugDepthPriority(float DepthPriority);
|
||||
|
||||
static FColor ModulateDebugColor(const UWorld* World, const FColor& Color, bool bPersistent = true);
|
||||
|
||||
static FColor ModulateServerColor(const FColor& Color);
|
||||
|
||||
static bool IsSecondarySkeletonBone(FName BoneName);
|
||||
|
||||
static void Reset();
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
static TWeakObjectPtr<AActor> Selection;
|
||||
|
||||
static bool FilterBySelection;
|
||||
|
||||
static bool Persistent;
|
||||
|
||||
static bool TextShadow;
|
||||
|
||||
static bool Fade2D;
|
||||
|
||||
static float Duration;
|
||||
|
||||
static int DepthPriority;
|
||||
|
||||
static int Segments;
|
||||
|
||||
static float Thickness;
|
||||
|
||||
static float ServerThickness;
|
||||
|
||||
static float ServerColorMultiplier;
|
||||
|
||||
static float ArrowSize;
|
||||
|
||||
static float AxesScale;
|
||||
|
||||
static float GradientColorIntensity;
|
||||
|
||||
static float GradientColorSpeed;
|
||||
|
||||
static float TextSize;
|
||||
|
||||
static TArray<FString> SecondaryBoneWildcards;
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
enum class ECogDebugShape : uint8
|
||||
{
|
||||
Invalid,
|
||||
|
||||
Arrow,
|
||||
Axes,
|
||||
Bone,
|
||||
Box,
|
||||
Capsule,
|
||||
Circle,
|
||||
CircleArc,
|
||||
Cone,
|
||||
Cylinder,
|
||||
FlatCapsule,
|
||||
Point,
|
||||
Polygon,
|
||||
Segment,
|
||||
SolidBox
|
||||
};
|
||||
|
||||
struct COGDEBUG_API FCogDebugShape
|
||||
{
|
||||
ECogDebugShape Type = ECogDebugShape::Invalid;
|
||||
TArray<FVector> ShapeData;
|
||||
FColor Color;
|
||||
bool bPersistent = false;
|
||||
float Thickness = 0.0f;
|
||||
uint8 DepthPriority = 0;
|
||||
|
||||
FCogDebugShape() {}
|
||||
|
||||
bool operator==(const FCogDebugShape& Other) const
|
||||
{
|
||||
return (Type == Other.Type)
|
||||
&& (Color == Other.Color)
|
||||
&& (ShapeData == Other.ShapeData)
|
||||
&& (bPersistent == Other.bPersistent)
|
||||
&& (Thickness == Other.Thickness)
|
||||
&& (DepthPriority == Other.DepthPriority);
|
||||
}
|
||||
|
||||
static FCogDebugShape MakePoint(const FVector& Location, const float Size, const FColor& Color, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeSegment(const FVector& StartLocation, const FVector& EndLocation, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeBone(const FVector& BoneLocation, const FVector& ParentLocation, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeArrow(const FVector& StartLocation, const FVector& EndLocation, const float HeadSize, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeAxes(const FVector& Location, const FRotator& Rotation, const float HeadSize, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeBox(const FVector& Center, const FRotator& Rotation, const FVector& Extent, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeSolidBox(const FVector& Center, const FRotator& Rotation, const FVector& Extent, const FColor& Color, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeCone(const FVector& Location, const FVector& Direction, const float Length, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeCylinder(const FVector& Center, const float Radius, const float HalfHeight, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeCircle(const FVector& Center, const FRotator& Rotation, const float Radius, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeCircleArc(const FVector& Center, const FRotator& Rotation, const float InnerRadius, const float OuterRadius, const float Angle, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeCapsule(const FVector& Center, const FQuat& Rotation, const float Radius, const float HalfHeight, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakeFlatCapsule(const FVector2D& Start, const FVector2D& End, const float Radius, const float Z, const FColor& Color, const float Thickness, const bool bPersistent, const uint8 DepthPriority);
|
||||
static FCogDebugShape MakePolygon(const TArray<FVector>& Verts, const FColor& Color, const bool bPersistent, const uint8 DepthPriority);
|
||||
|
||||
void DrawPoint(UWorld* World);
|
||||
void DrawSegment(UWorld* World);
|
||||
void DrawBone(UWorld* World);
|
||||
void DrawArrow(UWorld* World);
|
||||
void DrawAxes(UWorld* World);
|
||||
void DrawBox(UWorld* World);
|
||||
void DrawSolidBox(UWorld* World);
|
||||
void DrawCone(UWorld* World);
|
||||
void DrawCylinder(UWorld* World);
|
||||
void DrawCicle(UWorld* World);
|
||||
void DrawCicleArc(UWorld* World);
|
||||
void DrawCapsule(UWorld* World);
|
||||
void DrawFlatCapsule(UWorld* World);
|
||||
void DrawPolygon(UWorld* World);
|
||||
|
||||
void Draw(UWorld* World);
|
||||
};
|
||||
|
||||
FArchive& operator<<(FArchive& Ar, FCogDebugShape& Shape);
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class CogDebugEditor : ModuleRules
|
||||
{
|
||||
public CogDebugEditor(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.Add(ModuleDirectory + "/Public");
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"AssetTools",
|
||||
"CogDebug",
|
||||
"EditorStyle",
|
||||
"EditorWidgets",
|
||||
"InputCore",
|
||||
"PropertyEditor",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"SubobjectEditor",
|
||||
"ToolMenus",
|
||||
"UnrealEd",
|
||||
"BlueprintGraph",
|
||||
"GraphEditor",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "CogDebugEditorModule.h"
|
||||
|
||||
#include "CogDebugGraphPanelPinFactory.h"
|
||||
#include "CogDebugLogCategoryDetails.h"
|
||||
#include "IAssetTools.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "GameplayCoreEditorModule"
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
class FCogDebugEditorModule : public ICogDebugEditorModule
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
private:
|
||||
/** Pin factory for abilities graph; Cached so it can be unregistered */
|
||||
TSharedPtr<FCogGraphPanelPinFactory> GraphPanelPinFactory;
|
||||
|
||||
EAssetTypeCategories::Type AssetCategory;
|
||||
};
|
||||
|
||||
IMPLEMENT_MODULE(FCogDebugEditorModule, CogEditor);
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugEditorModule::StartupModule()
|
||||
{
|
||||
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
|
||||
PropertyModule.RegisterCustomPropertyTypeLayout("CogLogCategory", FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FCogLogCategoryDetails::MakeInstance));
|
||||
|
||||
// Register factories for pins and nodes
|
||||
GraphPanelPinFactory = MakeShareable(new FCogGraphPanelPinFactory());
|
||||
FEdGraphUtilities::RegisterVisualPinFactory(GraphPanelPinFactory);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void FCogDebugEditorModule::ShutdownModule()
|
||||
{
|
||||
if (FModuleManager::Get().IsModuleLoaded("PropertyEditor"))
|
||||
{
|
||||
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
|
||||
PropertyModule.UnregisterCustomPropertyTypeLayout("CogLogCategory");
|
||||
}
|
||||
|
||||
// Unregister graph factories
|
||||
if (GraphPanelPinFactory.IsValid())
|
||||
{
|
||||
FEdGraphUtilities::UnregisterVisualPinFactory(GraphPanelPinFactory);
|
||||
GraphPanelPinFactory.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "CogDebugLogCategoryDetails.h"
|
||||
|
||||
#include "CogDebugLogCategory.h"
|
||||
#include "CogDebugLog.h"
|
||||
#include "DetailWidgetRow.h"
|
||||
#include "Editor.h"
|
||||
#include "IPropertyUtilities.h"
|
||||
#include "Misc/TextFilter.h"
|
||||
#include "PropertyHandle.h"
|
||||
#include "SCogDebugLogCategoryWidget.h"
|
||||
#include "SlateOptMacros.h"
|
||||
#include "Widgets/Input/SSearchBox.h"
|
||||
#include "Widgets/Layout/SSeparator.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "AttributeDetailsCustomization"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TSharedRef<IPropertyTypeCustomization> FCogLogCategoryDetails::MakeInstance()
|
||||
{
|
||||
return MakeShareable(new FCogLogCategoryDetails());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogLogCategoryDetails::CustomizeHeader(TSharedRef<IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
|
||||
{
|
||||
NameProperty = StructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FCogLogCategory, Name));
|
||||
|
||||
PropertyOptions.Empty();
|
||||
PropertyOptions.Add(MakeShareable(new FString("None")));
|
||||
for (auto& Entry : FCogDebugLog::GetLogCategories())
|
||||
{
|
||||
PropertyOptions.Add(MakeShareable(new FString(Entry.Value.LogCategory->GetCategoryName().ToString())));
|
||||
}
|
||||
|
||||
const FString& FilterMetaStr = StructPropertyHandle->GetProperty()->GetMetaData(TEXT("FilterMetaTag"));
|
||||
|
||||
FName Value;
|
||||
if (NameProperty.IsValid())
|
||||
{
|
||||
NameProperty->GetValue(Value);
|
||||
}
|
||||
|
||||
HeaderRow.
|
||||
NameContent()
|
||||
[
|
||||
StructPropertyHandle->CreatePropertyNameWidget()
|
||||
]
|
||||
.ValueContent()
|
||||
.MinDesiredWidth(500)
|
||||
.MaxDesiredWidth(4096)
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
+ SHorizontalBox::Slot()
|
||||
//.FillWidth(1.0f)
|
||||
.HAlign(HAlign_Fill)
|
||||
.Padding(0.f, 0.f, 2.f, 0.f)
|
||||
[
|
||||
SNew(SCogLogCategoryWidget)
|
||||
.OnLogCategoryChanged(this, &FCogLogCategoryDetails::OnLogCategoryChanged)
|
||||
.DefaultName(Value)
|
||||
.FilterMetaData(FilterMetaStr)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogLogCategoryDetails::CustomizeChildren(TSharedRef<IPropertyHandle> StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogLogCategoryDetails::OnLogCategoryChanged(FName SelectedName)
|
||||
{
|
||||
if (NameProperty.IsValid())
|
||||
{
|
||||
NameProperty->SetValue(SelectedName);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "SCogDebugLogCategoryGraphPin.h"
|
||||
|
||||
#include "ScopedTransaction.h"
|
||||
#include "SCogDebugLogCategoryWidget.h"
|
||||
#include "UObject/CoreRedirects.h"
|
||||
#include "UObject/UObjectIterator.h"
|
||||
#include "Widgets/SBoxPanel.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "K2Node"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogLogCategoryGraphPin::Construct(const FArguments& InArgs, UEdGraphPin* InGraphPinObj)
|
||||
{
|
||||
SGraphPin::Construct( SGraphPin::FArguments(), InGraphPinObj );
|
||||
LastSelectedName = FName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TSharedRef<SWidget> SCogLogCategoryGraphPin::GetDefaultValueWidget()
|
||||
{
|
||||
// Parse out current default value
|
||||
FString DefaultString = GraphPinObj->GetDefaultAsString();
|
||||
FCogLogCategory DefaultLogCategory;
|
||||
|
||||
UScriptStruct* PinLiteralStructType = FCogLogCategory::StaticStruct();
|
||||
if (!DefaultString.IsEmpty())
|
||||
{
|
||||
PinLiteralStructType->ImportText(*DefaultString, &DefaultLogCategory, nullptr, EPropertyPortFlags::PPF_SerializedAsImportText, GError, PinLiteralStructType->GetName(), true);
|
||||
}
|
||||
|
||||
//Create widget
|
||||
return SNew(SVerticalBox)
|
||||
+SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
[
|
||||
SNew(SCogLogCategoryWidget)
|
||||
.OnLogCategoryChanged(this, &SCogLogCategoryGraphPin::OnLogCategoryChanged)
|
||||
.DefaultName(DefaultLogCategory.Name)
|
||||
.Visibility(this, &SGraphPin::GetDefaultValueVisibility)
|
||||
.IsEnabled(this, &SCogLogCategoryGraphPin::GetDefaultValueIsEnabled)
|
||||
];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogLogCategoryGraphPin::OnLogCategoryChanged(FName SelectedName)
|
||||
{
|
||||
FString FinalValue;
|
||||
FCogLogCategory NewLogCategoryStruct;
|
||||
NewLogCategoryStruct.Name = SelectedName;
|
||||
|
||||
FCogLogCategory::StaticStruct()->ExportText(FinalValue, &NewLogCategoryStruct, &NewLogCategoryStruct, nullptr, EPropertyPortFlags::PPF_SerializedAsImportText, nullptr);
|
||||
|
||||
if (FinalValue != GraphPinObj->GetDefaultAsString())
|
||||
{
|
||||
const FScopedTransaction Transaction(NSLOCTEXT("GraphEditor", "ChangePinValue", "Change Pin Value"));
|
||||
GraphPinObj->Modify();
|
||||
GraphPinObj->GetSchema()->TrySetDefaultValue(*GraphPinObj, FinalValue);
|
||||
}
|
||||
|
||||
LastSelectedName = SelectedName;
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,348 @@
|
||||
#include "SCogDebugLogCategoryWidget.h"
|
||||
|
||||
#include "Misc/TextFilter.h"
|
||||
#include "SlateOptMacros.h"
|
||||
#include "UObject/UnrealType.h"
|
||||
#include "UObject/UObjectHash.h"
|
||||
#include "UObject/UObjectIterator.h"
|
||||
#include "Widgets/Input/SComboBox.h"
|
||||
#include "Widgets/Input/SSearchBox.h"
|
||||
#include "Widgets/Layout/SBox.h"
|
||||
#include "Widgets/Layout/SSeparator.h"
|
||||
#include "Widgets/Views/SListView.h"
|
||||
#include "Widgets/Views/STableRow.h"
|
||||
#include "Widgets/Views/STableViewBase.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "K2Node"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
DECLARE_DELEGATE_OneParam(FOnLogCategoryPicked, FName);
|
||||
|
||||
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct FLogCategoryViewerNode
|
||||
{
|
||||
public:
|
||||
FLogCategoryViewerNode(FName InName)
|
||||
{
|
||||
Name = InName;
|
||||
}
|
||||
|
||||
FName Name;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
class SLogCategoryItem : public SComboRow<TSharedPtr<FLogCategoryViewerNode>>
|
||||
{
|
||||
public:
|
||||
|
||||
SLATE_BEGIN_ARGS(SLogCategoryItem)
|
||||
: _HighlightText()
|
||||
, _TextColor(FLinearColor(1.0f, 1.0f, 1.0f, 1.0f))
|
||||
{}
|
||||
|
||||
SLATE_ARGUMENT(FText, HighlightText)
|
||||
SLATE_ARGUMENT(FSlateColor, TextColor)
|
||||
SLATE_ARGUMENT(TSharedPtr<FLogCategoryViewerNode>, AssociatedNode)
|
||||
|
||||
SLATE_END_ARGS()
|
||||
|
||||
void Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwnerTableView)
|
||||
{
|
||||
AssociatedNode = InArgs._AssociatedNode;
|
||||
|
||||
this->ChildSlot
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
|
||||
+ SHorizontalBox::Slot()
|
||||
.FillWidth(1.0f)
|
||||
.Padding(0.0f, 3.0f, 6.0f, 3.0f)
|
||||
.VAlign(VAlign_Center)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(FText::FromString(*AssociatedNode->Name.ToString()))
|
||||
.HighlightText(InArgs._HighlightText)
|
||||
.ColorAndOpacity(this, &SLogCategoryItem::GetTextColor)
|
||||
.IsEnabled(true)
|
||||
]
|
||||
];
|
||||
|
||||
TextColor = InArgs._TextColor;
|
||||
|
||||
STableRow< TSharedPtr<FLogCategoryViewerNode> >::ConstructInternal(
|
||||
STableRow::FArguments()
|
||||
.ShowSelection(true),
|
||||
InOwnerTableView
|
||||
);
|
||||
}
|
||||
|
||||
/** Returns the text color for the item based on if it is selected or not. */
|
||||
FSlateColor GetTextColor() const
|
||||
{
|
||||
const TSharedPtr<ITypedTableView<TSharedPtr<FLogCategoryViewerNode>>> OwnerWidget = OwnerTablePtr.Pin();
|
||||
const TSharedPtr<FLogCategoryViewerNode>* MyItem = OwnerWidget->Private_ItemFromWidget(this);
|
||||
const bool bIsSelected = OwnerWidget->Private_IsItemSelected(*MyItem);
|
||||
|
||||
if (bIsSelected)
|
||||
{
|
||||
return FSlateColor::UseForeground();
|
||||
}
|
||||
|
||||
return TextColor;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** The text color for this item. */
|
||||
FSlateColor TextColor;
|
||||
|
||||
/** The LogCategory Viewer Node this item is associated with. */
|
||||
TSharedPtr<FLogCategoryViewerNode> AssociatedNode;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
class SLogCategoryListWidget : public SCompoundWidget
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS(SLogCategoryListWidget)
|
||||
{
|
||||
}
|
||||
|
||||
SLATE_ARGUMENT(FString, FilterMetaData)
|
||||
SLATE_ARGUMENT(FOnLogCategoryPicked, OnLogCategoryPickedDelegate)
|
||||
|
||||
SLATE_END_ARGS()
|
||||
|
||||
/**
|
||||
* Construct the widget
|
||||
*
|
||||
* @param InArgs A declaration from which to construct the widget
|
||||
*/
|
||||
void Construct(const FArguments& InArgs);
|
||||
|
||||
virtual ~SLogCategoryListWidget();
|
||||
|
||||
private:
|
||||
typedef TTextFilter<const FName&> FLogCategoryTextFilter;
|
||||
|
||||
/** Called by Slate when the filter box changes text. */
|
||||
void OnFilterTextChanged(const FText& InFilterText);
|
||||
|
||||
/** Creates the row widget when called by Slate when an item appears on the list. */
|
||||
TSharedRef< ITableRow > OnGenerateRowForLogCategoryViewer(TSharedPtr<FLogCategoryViewerNode> Item, const TSharedRef< STableViewBase >& OwnerTable);
|
||||
|
||||
/** Called by Slate when an item is selected from the tree/list. */
|
||||
void OnLogCategorySelectionChanged(TSharedPtr<FLogCategoryViewerNode> Item, ESelectInfo::Type SelectInfo);
|
||||
|
||||
/** Updates the list of items in the dropdown menu */
|
||||
TSharedPtr<FLogCategoryViewerNode> UpdatePropertyOptions();
|
||||
|
||||
/** Delegate to be called when an LogCategory is picked from the list */
|
||||
FOnLogCategoryPicked OnLogCategoryPicked;
|
||||
|
||||
/** The search box */
|
||||
TSharedPtr<SSearchBox> SearchBoxPtr;
|
||||
|
||||
/** Holds the Slate List widget which holds the LogCategorys for the LogCategory Viewer. */
|
||||
TSharedPtr<SListView<TSharedPtr< FLogCategoryViewerNode > >> LogCategoryList;
|
||||
|
||||
/** Array of items that can be selected in the dropdown menu */
|
||||
TArray<TSharedPtr<FLogCategoryViewerNode>> PropertyOptions;
|
||||
|
||||
/** Filters needed for filtering the assets */
|
||||
TSharedPtr<FLogCategoryTextFilter> LogCategoryTextFilter;
|
||||
|
||||
/** Filter for meta data */
|
||||
FString FilterMetaData;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
SLogCategoryListWidget::~SLogCategoryListWidget()
|
||||
{
|
||||
if (OnLogCategoryPicked.IsBound())
|
||||
{
|
||||
OnLogCategoryPicked.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SLogCategoryListWidget::Construct(const FArguments& InArgs)
|
||||
{
|
||||
struct Local
|
||||
{
|
||||
static void LogCategoryToStringArray(const FName& Name, OUT TArray< FString >& StringArray)
|
||||
{
|
||||
StringArray.Add(Name.ToString());
|
||||
}
|
||||
};
|
||||
|
||||
FilterMetaData = InArgs._FilterMetaData;
|
||||
OnLogCategoryPicked = InArgs._OnLogCategoryPickedDelegate;
|
||||
|
||||
// Setup text filtering
|
||||
LogCategoryTextFilter = MakeShareable(new FLogCategoryTextFilter(FLogCategoryTextFilter::FItemToStringArray::CreateStatic(&Local::LogCategoryToStringArray)));
|
||||
|
||||
UpdatePropertyOptions();
|
||||
|
||||
TSharedPtr< SWidget > ClassViewerContent;
|
||||
|
||||
SAssignNew(ClassViewerContent, SVerticalBox)
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
[
|
||||
SAssignNew(SearchBoxPtr, SSearchBox)
|
||||
.HintText(NSLOCTEXT("Log", "SearchBoxHint", "Search LogCategories"))
|
||||
.OnTextChanged(this, &SLogCategoryListWidget::OnFilterTextChanged)
|
||||
.DelayChangeNotificationsWhileTyping(true)
|
||||
]
|
||||
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
[
|
||||
SNew(SSeparator)
|
||||
.Visibility(EVisibility::Collapsed)
|
||||
]
|
||||
|
||||
+ SVerticalBox::Slot()
|
||||
.FillHeight(1.0f)
|
||||
[
|
||||
SAssignNew(LogCategoryList, SListView<TSharedPtr<FLogCategoryViewerNode>>)
|
||||
.Visibility(EVisibility::Visible)
|
||||
.SelectionMode(ESelectionMode::Single)
|
||||
.ListItemsSource(&PropertyOptions)
|
||||
|
||||
// Generates the actual widget for a tree item
|
||||
.OnGenerateRow(this, &SLogCategoryListWidget::OnGenerateRowForLogCategoryViewer)
|
||||
|
||||
// Find out when the user selects something in the tree
|
||||
.OnSelectionChanged(this, &SLogCategoryListWidget::OnLogCategorySelectionChanged)
|
||||
];
|
||||
|
||||
|
||||
ChildSlot
|
||||
[
|
||||
ClassViewerContent.ToSharedRef()
|
||||
];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TSharedRef<ITableRow> SLogCategoryListWidget::OnGenerateRowForLogCategoryViewer(TSharedPtr<FLogCategoryViewerNode> Item, const TSharedRef< STableViewBase >& OwnerTable)
|
||||
{
|
||||
TSharedRef< SLogCategoryItem > ReturnRow = SNew(SLogCategoryItem, OwnerTable)
|
||||
.HighlightText(SearchBoxPtr->GetText())
|
||||
.TextColor(FLinearColor(1.0f, 1.0f, 1.0f, 1.f))
|
||||
.AssociatedNode(Item);
|
||||
|
||||
return ReturnRow;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TSharedPtr<FLogCategoryViewerNode> SLogCategoryListWidget::UpdatePropertyOptions()
|
||||
{
|
||||
PropertyOptions.Empty();
|
||||
TSharedPtr<FLogCategoryViewerNode> InitiallySelected = MakeShareable(new FLogCategoryViewerNode(FName()));
|
||||
|
||||
PropertyOptions.Add(InitiallySelected);
|
||||
|
||||
// Gather all ULogCategory classes
|
||||
for (auto& Entry : FCogDebugLog::GetLogCategories())
|
||||
{
|
||||
// if we have a search string and this doesn't match, don't show it
|
||||
if (LogCategoryTextFilter.IsValid() && !LogCategoryTextFilter->PassesFilter(Entry.Value.LogCategory->GetCategoryName()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
TSharedPtr<FLogCategoryViewerNode> SelectableProperty = MakeShareable(new FLogCategoryViewerNode(Entry.Value.LogCategory->GetCategoryName()));
|
||||
PropertyOptions.Add(SelectableProperty);
|
||||
}
|
||||
|
||||
return InitiallySelected;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SLogCategoryListWidget::OnFilterTextChanged(const FText& InFilterText)
|
||||
{
|
||||
LogCategoryTextFilter->SetRawFilterText(InFilterText);
|
||||
SearchBoxPtr->SetError(LogCategoryTextFilter->GetFilterErrorText());
|
||||
|
||||
UpdatePropertyOptions();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SLogCategoryListWidget::OnLogCategorySelectionChanged(TSharedPtr<FLogCategoryViewerNode> Item, ESelectInfo::Type SelectInfo)
|
||||
{
|
||||
OnLogCategoryPicked.ExecuteIfBound(Item->Name);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogLogCategoryWidget::Construct(const FArguments& InArgs)
|
||||
{
|
||||
FilterMetaData = InArgs._FilterMetaData;
|
||||
OnLogCategoryChanged = InArgs._OnLogCategoryChanged;
|
||||
SelectedName = InArgs._DefaultName;
|
||||
|
||||
// set up the combo button
|
||||
SAssignNew(ComboButton, SComboButton)
|
||||
.OnGetMenuContent(this, &SCogLogCategoryWidget::GenerateLogCategoryPicker)
|
||||
.ContentPadding(FMargin(2.0f, 2.0f))
|
||||
.ToolTipText(this, &SCogLogCategoryWidget::GetSelectedValueAsText)
|
||||
.ButtonContent()
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(this, &SCogLogCategoryWidget::GetSelectedValueAsText)
|
||||
];
|
||||
|
||||
ChildSlot
|
||||
[
|
||||
ComboButton.ToSharedRef()
|
||||
];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogLogCategoryWidget::OnItemPicked(FName Name)
|
||||
{
|
||||
if (OnLogCategoryChanged.IsBound())
|
||||
{
|
||||
OnLogCategoryChanged.Execute(Name);
|
||||
}
|
||||
|
||||
// Update the selected item for displaying
|
||||
SelectedName = Name;
|
||||
|
||||
// close the list
|
||||
ComboButton->SetIsOpen(false);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TSharedRef<SWidget> SCogLogCategoryWidget::GenerateLogCategoryPicker()
|
||||
{
|
||||
FOnLogCategoryPicked OnPicked(FOnLogCategoryPicked::CreateRaw(this, &SCogLogCategoryWidget::OnItemPicked));
|
||||
|
||||
return SNew(SBox)
|
||||
.WidthOverride(280)
|
||||
[
|
||||
SNew(SVerticalBox)
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.MaxHeight(500)
|
||||
[
|
||||
SNew(SLogCategoryListWidget)
|
||||
.OnLogCategoryPickedDelegate(OnPicked)
|
||||
.FilterMetaData(FilterMetaData)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FText SCogLogCategoryWidget::GetSelectedValueAsText() const
|
||||
{
|
||||
return FText::FromName(SelectedName);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Modules/ModuleInterface.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class ICogDebugEditorModule : public IModuleInterface
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
static inline ICogDebugEditorModule& Get() { return FModuleManager::LoadModuleChecked<ICogDebugEditorModule>("CogDebugEditor"); }
|
||||
|
||||
static inline bool IsAvailable() { return FModuleManager::Get().IsModuleLoaded("CogDebugEditor"); }
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogDebugGraphPanelPinFactory.h"
|
||||
#include "CogDebugLogCategory.h"
|
||||
#include "EdGraphSchema_K2.h"
|
||||
#include "EdGraphUtilities.h"
|
||||
#include "SCogDebugLogCategoryGraphPin.h"
|
||||
#include "SGraphPin.h"
|
||||
#include "Widgets/DeclarativeSyntaxSupport.h"
|
||||
|
||||
class FCogGraphPanelPinFactory : public FGraphPanelPinFactory
|
||||
{
|
||||
virtual TSharedPtr<class SGraphPin> CreatePin(class UEdGraphPin* InPin) const override
|
||||
{
|
||||
if (InPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Struct && InPin->PinType.PinSubCategoryObject == FCogLogCategory::StaticStruct())
|
||||
{
|
||||
return SNew(SCogLogCategoryGraphPin, InPin);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "IPropertyTypeCustomization.h"
|
||||
#include "Layout/Visibility.h"
|
||||
#include "PropertyEditorModule.h"
|
||||
#include "Widgets/SWidget.h"
|
||||
|
||||
class FCogLogCategoryDetails : public IPropertyTypeCustomization
|
||||
{
|
||||
public:
|
||||
static TSharedRef<IPropertyTypeCustomization> MakeInstance();
|
||||
|
||||
/** IPropertyTypeCustomization interface */
|
||||
virtual void CustomizeHeader(TSharedRef<class IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override;
|
||||
virtual void CustomizeChildren(TSharedRef<class IPropertyHandle> StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override;
|
||||
|
||||
private:
|
||||
|
||||
TSharedPtr<IPropertyHandle> NameProperty;
|
||||
TArray<TSharedPtr<FString>> PropertyOptions;
|
||||
|
||||
void OnLogCategoryChanged(FName SelectedName);
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Widgets/DeclarativeSyntaxSupport.h"
|
||||
#include "Widgets/SWidget.h"
|
||||
#include "SGraphPin.h"
|
||||
|
||||
class SCogLogCategoryGraphPin : public SGraphPin
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS(SCogLogCategoryGraphPin) {}
|
||||
SLATE_END_ARGS()
|
||||
|
||||
void Construct(const FArguments& InArgs, UEdGraphPin* InGraphPinObj);
|
||||
|
||||
//~ Begin SGraphPin Interface
|
||||
virtual TSharedRef<SWidget> GetDefaultValueWidget() override;
|
||||
//~ End SGraphPin Interface
|
||||
|
||||
void OnLogCategoryChanged(FName SelectedName);
|
||||
|
||||
FName LastSelectedName;
|
||||
|
||||
private:
|
||||
bool GetDefaultValueIsEnabled() const
|
||||
{
|
||||
return !GraphPinObj->bDefaultValueIsReadOnly;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Widgets/SWidget.h"
|
||||
#include "Widgets/SCompoundWidget.h"
|
||||
#include "Widgets/DeclarativeSyntaxSupport.h"
|
||||
#include "Widgets/Input/SComboButton.h"
|
||||
|
||||
class SCogLogCategoryWidget : public SCompoundWidget
|
||||
{
|
||||
public:
|
||||
DECLARE_DELEGATE_OneParam(FOnLogCategoryChanged, FName)
|
||||
|
||||
SLATE_BEGIN_ARGS(SCogLogCategoryWidget)
|
||||
: _FilterMetaData()
|
||||
, _DefaultName()
|
||||
{}
|
||||
SLATE_ARGUMENT(FString, FilterMetaData)
|
||||
SLATE_ARGUMENT(FName, DefaultName)
|
||||
SLATE_EVENT(FOnLogCategoryChanged, OnLogCategoryChanged)
|
||||
SLATE_END_ARGS()
|
||||
|
||||
void Construct(const FArguments& InArgs);
|
||||
|
||||
private:
|
||||
TSharedRef<SWidget> GenerateLogCategoryPicker();
|
||||
FText GetSelectedValueAsText() const;
|
||||
void OnItemPicked(FName Name);
|
||||
|
||||
FOnLogCategoryChanged OnLogCategoryChanged;
|
||||
FString FilterMetaData;
|
||||
FName SelectedName;
|
||||
TSharedPtr<class SComboButton> ComboButton;
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class CogEngine : ModuleRules
|
||||
{
|
||||
public CogEngine(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CogCommon",
|
||||
"CogImgui",
|
||||
"CogDebug",
|
||||
"CogWindow",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"NetCore",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "CogEngineModule.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FCogEngineModule"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogEngineModule::StartupModule()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogEngineModule::ShutdownModule()
|
||||
{
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FCogEngineModule, CogEngine)
|
||||
@@ -0,0 +1,181 @@
|
||||
#include "CogEngineReplicator.h"
|
||||
|
||||
#include "CogCommon.h"
|
||||
#include "CogCommonPossessorInterface.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "GameFramework/WorldSettings.h"
|
||||
#include "EngineUtils.h"
|
||||
#include "Net/Core/PushModel/PushModel.h"
|
||||
#include "Net/UnrealNetwork.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogCogEngine);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ACogEngineReplicator* ACogEngineReplicator::Spawn(APlayerController* Controller)
|
||||
{
|
||||
if (Controller->GetWorld()->GetNetMode() == NM_Client)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FActorSpawnParameters SpawnInfo;
|
||||
SpawnInfo.Owner = Controller;
|
||||
ACogEngineReplicator* Replicator = Controller->GetWorld()->SpawnActor<ACogEngineReplicator>(SpawnInfo);
|
||||
|
||||
return Replicator;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ACogEngineReplicator* ACogEngineReplicator::GetLocalReplicator(UWorld& World)
|
||||
{
|
||||
for (TActorIterator<ACogEngineReplicator> It(&World, ACogEngineReplicator::StaticClass()); It; ++It)
|
||||
{
|
||||
ACogEngineReplicator* Replicator = *It;
|
||||
return Replicator;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogEngineReplicator::GetRemoteReplicators(UWorld& World, TArray<ACogEngineReplicator*>& Replicators)
|
||||
{
|
||||
for (TActorIterator<ACogEngineReplicator> It(&World, ACogEngineReplicator::StaticClass()); It; ++It)
|
||||
{
|
||||
ACogEngineReplicator* Replicator = Cast<ACogEngineReplicator>(*It);
|
||||
Replicators.Add(Replicator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ACogEngineReplicator::ACogEngineReplicator(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
bHasAuthority = false;
|
||||
bIsLocal = false;
|
||||
bReplicates = true;
|
||||
bOnlyRelevantToOwner = true;
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogEngineReplicator::BeginPlay()
|
||||
{
|
||||
COG_LOG_OBJECT(LogCogEngine, ELogVerbosity::Verbose, this, TEXT(""));
|
||||
|
||||
Super::BeginPlay();
|
||||
|
||||
UWorld* World = GetWorld();
|
||||
check(World);
|
||||
const ENetMode NetMode = World->GetNetMode();
|
||||
bHasAuthority = NetMode != NM_Client;
|
||||
bIsLocal = NetMode != NM_DedicatedServer;
|
||||
|
||||
OwnerPlayerController = Cast<APlayerController>(GetOwner());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void ACogEngineReplicator::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||
{
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
FDoRepLifetimeParams Params;
|
||||
Params.bIsPushBased = true;
|
||||
DOREPLIFETIME_WITH_PARAMS_FAST(ACogEngineReplicator, TimeDilation, Params);
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogEngineReplicator::Server_Spawn_Implementation(const FCogEngineSpawnEntry& SpawnEntry)
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
if (GetWorld() == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (SpawnFunction)
|
||||
{
|
||||
SpawnFunction(SpawnEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
FTransform Transform(FTransform::Identity);
|
||||
if (APawn* Pawn = GetPlayerController()->GetPawn())
|
||||
{
|
||||
Transform = Pawn->GetTransform();
|
||||
Transform.SetLocation(Transform.GetLocation() + Transform.GetUnitAxis(EAxis::X) * 200.0f);
|
||||
Transform.SetScale3D(FVector(1.0f));
|
||||
}
|
||||
|
||||
FActorSpawnParameters Params;
|
||||
Params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
||||
GetWorld()->SpawnActor(SpawnEntry.Class, &Transform, Params);
|
||||
}
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogEngineReplicator::Server_SetTimeDilation_Implementation(float Value)
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
COMPARE_ASSIGN_AND_MARK_PROPERTY_DIRTY(ACogEngineReplicator, TimeDilation, Value, this);
|
||||
OnRep_TimeDilation();
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogEngineReplicator::OnRep_TimeDilation()
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
UWorld* World = GetWorld();
|
||||
if (World == nullptr)
|
||||
return;
|
||||
|
||||
AWorldSettings* WorldSettings = World->GetWorldSettings();
|
||||
if (WorldSettings == nullptr)
|
||||
return;
|
||||
|
||||
WorldSettings->SetTimeDilation(TimeDilation);
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogEngineReplicator::Server_Possess_Implementation(APawn* Pawn)
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
if (ICogCommonPossessorInterface* Possessor = Cast<ICogCommonPossessorInterface>(OwnerPlayerController))
|
||||
{
|
||||
Possessor->SetPossession(Pawn);
|
||||
}
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogEngineReplicator::Server_ResetPossession_Implementation()
|
||||
{
|
||||
#if !UE_BUILD_SHIPPING
|
||||
|
||||
if (ICogCommonPossessorInterface* Possessor = Cast<ICogCommonPossessorInterface>(OwnerPlayerController))
|
||||
{
|
||||
Possessor->ResetPossession();
|
||||
}
|
||||
|
||||
#endif // !UE_BUILD_SHIPPING
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "CogEngineWindow_Audio.h"
|
||||
|
||||
#include "Engine/Engine.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Audio::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window displays audio settings. "
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Audio::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
#include "CogEngineWindow_Collisions.h"
|
||||
|
||||
#include "CogDebugDrawHelper.h"
|
||||
#include "CogDebugSettings.h"
|
||||
#include "CogEngineDataAsset.h"
|
||||
#include "CogImGuiHelper.h"
|
||||
#include "Components/BoxComponent.h"
|
||||
#include "Components/CapsuleComponent.h"
|
||||
#include "Components/PrimitiveComponent.h"
|
||||
#include "Components/SceneComponent.h"
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "imgui.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Collisions::RenderHelp()
|
||||
{
|
||||
ImGui::Text("This window is used to inspect collisions by performing a collision query with the selected channels. "
|
||||
"The query can be configured in the options. "
|
||||
"The displayed collision channels can be configured in the '%s' data asset. "
|
||||
, TCHAR_TO_ANSI(*GetNameSafe(Asset.Get()))
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogEngineWindow_Collisions::UCogEngineWindow_Collisions()
|
||||
{
|
||||
bHasMenu = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Collisions::ResetConfig()
|
||||
{
|
||||
Super::ResetConfig();
|
||||
|
||||
ObjectTypesToQuery = 0;
|
||||
ProfileIndex = 0;
|
||||
QueryType = 0;
|
||||
QueryDistance = 5000.0f;
|
||||
QueryThickness = 0.0f;
|
||||
UseComplexCollisions = false;
|
||||
ShowActorsNames = false;
|
||||
ShowQuery = false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Collisions::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
const APlayerController* PlayerController = GetLocalPlayerController();
|
||||
if (PlayerController == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Query Profile
|
||||
//-------------------------------------------------
|
||||
|
||||
const UCollisionProfile* CollisionProfile = UCollisionProfile::Get();
|
||||
if (CollisionProfile == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Menu
|
||||
//-------------------------------------------------
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("Options"))
|
||||
{
|
||||
//-------------------------------------------------
|
||||
// Query Mode
|
||||
//-------------------------------------------------
|
||||
ImGui::Combo("Query", &QueryType,
|
||||
"Sphere\0"
|
||||
"Raycast Crosshair\0"
|
||||
"Raycast Cursor\0"
|
||||
"\0"
|
||||
);
|
||||
|
||||
//-------------------------------------------------
|
||||
// Query Distance
|
||||
//-------------------------------------------------
|
||||
ImGui::SliderFloat("Distance", &QueryDistance, 0.0f, 20000.0f, "%0.f");
|
||||
|
||||
//-------------------------------------------------
|
||||
// Query Thickness
|
||||
//-------------------------------------------------
|
||||
if (QueryType == 1 || QueryType == 2)
|
||||
{
|
||||
ImGui::SliderFloat("Thickness", &QueryThickness, 0.0f, 1000.0f, "%0.f");
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Query Use Complex Collisions
|
||||
//-------------------------------------------------
|
||||
ImGui::Checkbox("Use Complex Collisions", &UseComplexCollisions);
|
||||
|
||||
//-------------------------------------------------
|
||||
// Show Names
|
||||
//-------------------------------------------------
|
||||
ImGui::Checkbox("Show Actors Names", &ShowActorsNames);
|
||||
|
||||
//-------------------------------------------------
|
||||
// Show Query
|
||||
//-------------------------------------------------
|
||||
ImGui::Checkbox("Show Query", &ShowQuery);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Profile
|
||||
//-------------------------------------------------
|
||||
const FCollisionResponseTemplate* SelectedProfile = CollisionProfile->GetProfileByIndex(ProfileIndex);
|
||||
FName SelectedProfileName = SelectedProfile != nullptr ? SelectedProfile->Name : FName("Custom");
|
||||
|
||||
if (ImGui::BeginCombo("Profile", TCHAR_TO_ANSI(*SelectedProfileName.ToString()), ImGuiComboFlags_HeightLargest))
|
||||
{
|
||||
for (int i = 0; i < CollisionProfile->GetNumOfProfiles(); ++i)
|
||||
{
|
||||
const FCollisionResponseTemplate* Profile = CollisionProfile->GetProfileByIndex(i);
|
||||
if (ImGui::Selectable(TCHAR_TO_ANSI(*Profile->Name.ToString()), false))
|
||||
{
|
||||
ProfileIndex = i;
|
||||
ObjectTypesToQuery = 0;
|
||||
SelectedProfile = CollisionProfile->GetProfileByIndex(ProfileIndex);
|
||||
|
||||
if (Profile->CollisionEnabled != ECollisionEnabled::NoCollision)
|
||||
{
|
||||
for (int j = 0; j < ECC_MAX; ++j)
|
||||
{
|
||||
ECollisionResponse Response = Profile->ResponseToChannels.GetResponse((ECollisionChannel)j);
|
||||
if (Response != ECR_Ignore)
|
||||
{
|
||||
ObjectTypesToQuery |= ECC_TO_BITFIELD(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
//-------------------------------------------------
|
||||
// Query Filtering
|
||||
//-------------------------------------------------
|
||||
for (int ChannelIndex = 0; ChannelIndex < (int32)ECC_MAX; ++ChannelIndex)
|
||||
{
|
||||
ImGui::PushID(ChannelIndex);
|
||||
|
||||
const FChannel& Channel = Channels[ChannelIndex];
|
||||
if (Channel.IsValid == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImColor Color = FCogImguiHelper::ToImColor(Channel.Color);
|
||||
ImGui::ColorEdit4("Color", (float*)&Color.Value, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
|
||||
ImGui::SameLine();
|
||||
|
||||
bool IsCollisionActive = (ObjectTypesToQuery & ECC_TO_BITFIELD(ChannelIndex)) > 0;
|
||||
const FName ChannelName = CollisionProfile->ReturnChannelNameFromContainerIndex(ChannelIndex);
|
||||
if (ImGui::Checkbox(TCHAR_TO_ANSI(*ChannelName.ToString()), &IsCollisionActive))
|
||||
{
|
||||
if (IsCollisionActive)
|
||||
{
|
||||
ObjectTypesToQuery |= ECC_TO_BITFIELD(ChannelIndex);
|
||||
ProfileIndex = INDEX_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectTypesToQuery &= ~ECC_TO_BITFIELD(ChannelIndex);
|
||||
ProfileIndex = INDEX_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Perform Query
|
||||
//-------------------------------------------------
|
||||
if (ObjectTypesToQuery == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FVector QueryStart;
|
||||
FVector QueryEnd;
|
||||
float QueryRadius = 0.0f;
|
||||
|
||||
switch (QueryType)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
FVector Location = FVector::ZeroVector;
|
||||
if (APawn* Pawn = PlayerController->GetPawn())
|
||||
{
|
||||
Location = Pawn->GetActorLocation();
|
||||
}
|
||||
|
||||
QueryRadius = QueryDistance;
|
||||
QueryStart = Location;
|
||||
QueryEnd = QueryStart;
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
FVector Location;
|
||||
FRotator Rotation;
|
||||
PlayerController->GetPlayerViewPoint(Location, Rotation);
|
||||
QueryStart = Location;
|
||||
QueryEnd = QueryStart + Rotation.Vector() * QueryDistance;
|
||||
QueryRadius = QueryThickness;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
FVector Direction;
|
||||
UGameplayStatics::DeprojectScreenToWorld(PlayerController, FCogImguiHelper::ToVector2D(ImGui::GetMousePos()), QueryStart, Direction);
|
||||
QueryEnd = QueryStart + Direction * QueryDistance;
|
||||
QueryRadius = QueryThickness;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const FName TraceTag(TEXT("FCogWindow_Collision"));
|
||||
FCollisionQueryParams QueryParams(TraceTag, SCENE_QUERY_STAT_ONLY(CogHitDetection), UseComplexCollisions);
|
||||
|
||||
FCollisionObjectQueryParams QueryObjectParams;
|
||||
QueryObjectParams.ObjectTypesToQuery = ObjectTypesToQuery;
|
||||
|
||||
FCollisionShape QueryShape;
|
||||
QueryShape.SetSphere(QueryRadius);
|
||||
|
||||
TArray<FHitResult> QueryHits;
|
||||
UWorld* World = GetWorld();
|
||||
World->SweepMultiByObjectType(
|
||||
QueryHits,
|
||||
QueryStart,
|
||||
QueryEnd,
|
||||
FQuat::Identity,
|
||||
QueryObjectParams,
|
||||
QueryShape,
|
||||
QueryParams);
|
||||
|
||||
if (ShowQuery)
|
||||
{
|
||||
FCogDebugDrawHelper::DrawCapsuleCastMulti(World, QueryStart, QueryEnd, FQuat::Identity, 0.0f, QueryRadius, EDrawDebugTrace::ForOneFrame, false, QueryHits, FLinearColor::White, FLinearColor::Red, FCogDebugSettings::GetDebugDuration(true));
|
||||
}
|
||||
|
||||
TSet<const AActor*> AlreadyDrawnActors;
|
||||
TSet<const UPrimitiveComponent*> AlreadyDrawnComponents;
|
||||
|
||||
for (const FHitResult& HitResult : QueryHits)
|
||||
{
|
||||
//-------------------------------------------------------
|
||||
// Don't draw same primitives multiple times (for bones)
|
||||
//-------------------------------------------------------
|
||||
const UPrimitiveComponent* PrimitiveComponent = HitResult.GetComponent();
|
||||
if (AlreadyDrawnComponents.Contains(PrimitiveComponent))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AlreadyDrawnComponents.Add(PrimitiveComponent);
|
||||
|
||||
ECollisionChannel CollisionObjectType = PrimitiveComponent->GetCollisionObjectType();
|
||||
FColor Color = Channels[CollisionObjectType].Color;
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Draw Name
|
||||
//-------------------------------------------------------
|
||||
if (ShowActorsNames)
|
||||
{
|
||||
const AActor* Actor = HitResult.GetActor();
|
||||
if (Actor != nullptr)
|
||||
{
|
||||
if (AlreadyDrawnActors.Contains(Actor) == false)
|
||||
{
|
||||
FColor TextColor = Color.WithAlpha(255);
|
||||
DrawDebugString(World, Actor->GetActorLocation(), GetNameSafe(Actor->GetClass()), nullptr, FColor::White, 0.0f, FCogDebugSettings::TextShadow, FCogDebugSettings::TextSize);
|
||||
AlreadyDrawnActors.Add(Actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Draw Shape
|
||||
//-------------------------------------------------------
|
||||
FCollisionShape Shape = PrimitiveComponent->GetCollisionShape();
|
||||
switch (Shape.ShapeType)
|
||||
{
|
||||
case ECollisionShape::Box:
|
||||
{
|
||||
FVector Location;
|
||||
FVector Extent;
|
||||
FQuat Rotation;
|
||||
|
||||
if (const UBoxComponent* BoxComponent = Cast<UBoxComponent>(PrimitiveComponent))
|
||||
{
|
||||
Location = BoxComponent->GetComponentLocation();
|
||||
Extent = BoxComponent->GetScaledBoxExtent();
|
||||
Rotation = BoxComponent->GetComponentQuat();
|
||||
}
|
||||
else
|
||||
{
|
||||
PrimitiveComponent->Bounds.GetBox().GetCenterAndExtents(Location, Extent);
|
||||
Extent += FVector::OneVector;
|
||||
Rotation = FQuat::Identity;
|
||||
}
|
||||
|
||||
DrawDebugSolidBox(
|
||||
World,
|
||||
Location,
|
||||
Extent,
|
||||
Rotation,
|
||||
Color,
|
||||
false,
|
||||
0.0f,
|
||||
FCogDebugSettings::GetDebugDepthPriority(0));
|
||||
|
||||
DrawDebugBox(
|
||||
World,
|
||||
Location,
|
||||
Extent,
|
||||
Rotation,
|
||||
Color,
|
||||
false,
|
||||
0.0f,
|
||||
FCogDebugSettings::GetDebugDepthPriority(0),
|
||||
FCogDebugSettings::GetDebugThickness(0.0f));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECollisionShape::Sphere:
|
||||
{
|
||||
if (const USphereComponent* SphereComponent = Cast<USphereComponent>(PrimitiveComponent))
|
||||
{
|
||||
FCogDebugDrawHelper::DrawSphere(
|
||||
World,
|
||||
SphereComponent->GetComponentLocation(),
|
||||
SphereComponent->GetScaledSphereRadius(),
|
||||
FCogDebugSettings::GetCircleSegments(),
|
||||
Color,
|
||||
false,
|
||||
0.0f,
|
||||
FCogDebugSettings::GetDebugDepthPriority(0),
|
||||
FCogDebugSettings::GetDebugThickness(0.0f));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ECollisionShape::Capsule:
|
||||
{
|
||||
if (const UCapsuleComponent* CapsuleComponent = Cast<UCapsuleComponent>(PrimitiveComponent))
|
||||
{
|
||||
DrawDebugCapsule(World,
|
||||
CapsuleComponent->GetComponentLocation(),
|
||||
CapsuleComponent->GetScaledCapsuleHalfHeight(),
|
||||
CapsuleComponent->GetScaledCapsuleRadius(),
|
||||
CapsuleComponent->GetComponentQuat(),
|
||||
Color,
|
||||
false,
|
||||
0.0f,
|
||||
FCogDebugSettings::GetDebugDepthPriority(0),
|
||||
FCogDebugSettings::GetDebugThickness(0.0f));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Collisions::SetAsset(const UCogEngineDataAsset* Value)
|
||||
{
|
||||
Asset = Value;
|
||||
|
||||
if (Asset == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (FChannel& Channel : Channels)
|
||||
{
|
||||
Channel.IsValid = false;
|
||||
}
|
||||
|
||||
for (const FCogCollisionChannel& AssetChannel : Asset->Channels)
|
||||
{
|
||||
FChannel& Channel = Channels[(uint8)AssetChannel.Channel];
|
||||
Channel.IsValid = true;
|
||||
Channel.Color = AssetChannel.Color.ToFColor(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "CogEngineWindow_DebugSettings.h"
|
||||
|
||||
#include "CogDebugSettings.h"
|
||||
#include "CogWindowWidgets.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_DebugSettings::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window can be used to tweak how the debug display is drawn. "
|
||||
"Check each item for more info. "
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_DebugSettings::ResetConfig()
|
||||
{
|
||||
Super::ResetConfig();
|
||||
|
||||
FilterBySelection = true;
|
||||
Persistent = false;
|
||||
TextShadow = true;
|
||||
Fade2D = true;
|
||||
Duration = 3.0f;
|
||||
DepthPriority = 0;
|
||||
Segments = 12;
|
||||
Thickness = 0.0f;
|
||||
ServerThickness = 2.0f;
|
||||
ServerColorMultiplier = 0.8f;
|
||||
ArrowSize = 10.0f;
|
||||
AxesScale = 1.0f;
|
||||
GradientColorIntensity = 0.0f;
|
||||
GradientColorSpeed = 2.0f;
|
||||
TextSize = 1.0f;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_DebugSettings::PostInitProperties()
|
||||
{
|
||||
Super::PostInitProperties();
|
||||
|
||||
FCogDebugSettings::FilterBySelection = FilterBySelection;
|
||||
FCogDebugSettings::Persistent = Persistent;
|
||||
FCogDebugSettings::TextShadow = TextShadow;
|
||||
FCogDebugSettings::Fade2D = Fade2D;
|
||||
FCogDebugSettings::Duration = Duration;
|
||||
FCogDebugSettings::DepthPriority = DepthPriority;
|
||||
FCogDebugSettings::Segments = Segments;
|
||||
FCogDebugSettings::Thickness = Thickness;
|
||||
FCogDebugSettings::ServerThickness = ServerThickness;
|
||||
FCogDebugSettings::ServerColorMultiplier = ServerColorMultiplier;
|
||||
FCogDebugSettings::ArrowSize = ArrowSize;
|
||||
FCogDebugSettings::AxesScale = AxesScale;
|
||||
FCogDebugSettings::GradientColorIntensity = GradientColorIntensity;
|
||||
FCogDebugSettings::GradientColorSpeed = GradientColorSpeed;
|
||||
FCogDebugSettings::TextSize = TextSize;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_DebugSettings::PreSaveConfig()
|
||||
{
|
||||
Super::PreSaveConfig();
|
||||
|
||||
FilterBySelection = FCogDebugSettings::FilterBySelection;
|
||||
Persistent = FCogDebugSettings::Persistent;
|
||||
TextShadow = FCogDebugSettings::TextShadow;
|
||||
Fade2D = FCogDebugSettings::Fade2D;
|
||||
Duration = FCogDebugSettings::Duration;
|
||||
DepthPriority = FCogDebugSettings::DepthPriority;
|
||||
Segments = FCogDebugSettings::Segments;
|
||||
Thickness = FCogDebugSettings::Thickness;
|
||||
ServerThickness = FCogDebugSettings::ServerThickness;
|
||||
ServerColorMultiplier = FCogDebugSettings::ServerColorMultiplier;
|
||||
ArrowSize = FCogDebugSettings::ArrowSize;
|
||||
AxesScale = FCogDebugSettings::AxesScale;
|
||||
GradientColorIntensity = FCogDebugSettings::GradientColorIntensity;
|
||||
GradientColorSpeed = FCogDebugSettings::GradientColorSpeed;
|
||||
TextSize = FCogDebugSettings::TextSize;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogEngineWindow_DebugSettings::UCogEngineWindow_DebugSettings()
|
||||
{
|
||||
bHasMenu = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_DebugSettings::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::MenuItem("Reset"))
|
||||
{
|
||||
FCogDebugSettings::Reset();
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Filter by selection", &FCogDebugSettings::FilterBySelection);
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("If checked, only show the debug of the currently selected actor. Otherwise show the debug of all actors.");
|
||||
|
||||
ImGui::Checkbox("Persistent", &FCogDebugSettings::Persistent);
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("Make debug draw always persist");
|
||||
|
||||
ImGui::Checkbox("Text Shadow", &FCogDebugSettings::TextShadow);
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("Show a shadow below debug text.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::Checkbox("Fade 2D", &FCogDebugSettings::Fade2D);
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("Does the 2D debug is fading out.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragFloat("Duration", &FCogDebugSettings::Duration, 0.01f, 0.0f, 100.0f, "%.1f");
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("The duration of debug elements.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragFloat("Thickness", &FCogDebugSettings::Thickness, 0.05f, 0.0f, 5.0f, "%.1f");
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("The thickness of debug lines.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragFloat("Server Thickness", &FCogDebugSettings::ServerThickness, 0.05f, 0.0f, 5.0f, "%.1f");
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("The thickness the server debug lines.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragFloat("Server Color Mult", &FCogDebugSettings::ServerColorMultiplier, 0.01f, 0.0f, 1.0f, "%.1f");
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("The color multiplier applied to the server debug lines.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragInt("Depth Priority", &FCogDebugSettings::DepthPriority, 0.1f, 0, 100);
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("The depth priority of debug elements.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragInt("Segments", &FCogDebugSettings::Segments, 0.1f, 4, 20.0f);
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("The number of segments used for circular shapes.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragFloat("Axes Scale", &FCogDebugSettings::AxesScale, 0.1f, 0, 10.0f, "%.1f");
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("The scaling debug axis.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragFloat("Arrow Size", &FCogDebugSettings::ArrowSize, 1.0f, 0.0f, 200.0f, "%.0f");
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("The size of debug arrows.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragFloat("Gradient Intensity", &FCogDebugSettings::GradientColorIntensity, 0.01f, 0.0f, 1.0f, "%.2f");
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("How much the debug elements color should be changed by a gradient color over time.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragFloat("Gradient Speed", &FCogDebugSettings::GradientColorSpeed, 0.1f, 0.0f, 10.0f, "%.1f");
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("The speed of the gradient color change.");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
ImGui::DragFloat("Text Size", &FCogDebugSettings::TextSize, 0.1f, 0.1f, 5.0f, "%.1f");
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("The size of the debug texts.");
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "CogEngineWindow_ImGui.h"
|
||||
|
||||
#include "imgui.h"
|
||||
#include "implot.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogEngineWindow_ImGui::UCogEngineWindow_ImGui()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_ImGui::RenderTick(float DeltaTime)
|
||||
{
|
||||
Super::RenderTick(DeltaTime);
|
||||
|
||||
if (bShowImguiDemo)
|
||||
{
|
||||
ImGui::ShowDemoWindow(&bShowImguiDemo);
|
||||
}
|
||||
|
||||
if (bShowImguiMetric)
|
||||
{
|
||||
ImGui::ShowMetricsWindow(&bShowImguiMetric);
|
||||
}
|
||||
|
||||
if (bShowImguiDebugLog)
|
||||
{
|
||||
ImGui::ShowDebugLogWindow(&bShowImguiDebugLog);
|
||||
}
|
||||
|
||||
if (bShowImguiStyleEditor)
|
||||
{
|
||||
ImGui::Begin("Dear ImGui Style Editor", &bShowImguiStyleEditor);
|
||||
ImGui::ShowStyleEditor();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (bShowImguiPlot)
|
||||
{
|
||||
ImPlot::ShowDemoWindow(&bShowImguiPlot);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_ImGui::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
ImGui::MenuItem("ImGui Demo", nullptr, &bShowImguiDemo);
|
||||
ImGui::MenuItem("ImGui Metric", nullptr, &bShowImguiMetric);
|
||||
ImGui::MenuItem("ImGui Debug Log", nullptr, &bShowImguiDebugLog);
|
||||
ImGui::MenuItem("ImGui Style Editor", nullptr, &bShowImguiStyleEditor);
|
||||
ImGui::MenuItem("Plot Demo", "", &bShowImguiPlot);
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
#include "CogEngineWindow_LogCategories.h"
|
||||
|
||||
#include "CogDebugHelper.h"
|
||||
#include "CogWindowWidgets.h"
|
||||
#include "CogDebugLog.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_LogCategories::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window can be used to activate and deactivate log categories."
|
||||
"Activating a log category set its verbosity to VeryVerbose. "
|
||||
"Deactivating a log category set its verbosity to Warning. "
|
||||
"The detailed verbosity of each log category can shown by using the Option menu. "
|
||||
"On a client, both the client and the server verbosity can be modified. "
|
||||
"The log categories are used to display both output log and debug display in the world. "
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogEngineWindow_LogCategories::UCogEngineWindow_LogCategories()
|
||||
{
|
||||
bHasMenu = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_LogCategories::ResetConfig()
|
||||
{
|
||||
Super::ResetConfig();
|
||||
|
||||
FCogDebugLog::DeactivateAllLogCateories(*GetWorld());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_LogCategories::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
UWorld* World = GetWorld();
|
||||
if (World == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static bool bShowAllVerbosity = false;
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("Options"))
|
||||
{
|
||||
ImGui::Checkbox("Show detailed verbosity", &bShowAllVerbosity);
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::HelpMarker("Show the verbosity level of each log category.");
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Reset"))
|
||||
{
|
||||
FCogDebugLog::DeactivateAllLogCateories(*World);
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Deactivate all the log categories");
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Flush"))
|
||||
{
|
||||
FlushPersistentDebugLines(World);
|
||||
FlushDebugStrings(GWorld);
|
||||
GEngine->ClearOnScreenDebugMessages();
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Clear all the debug drawn on screen");
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
const bool IsClient = World->GetNetMode() == NM_Client;
|
||||
|
||||
ImGuiStyle& Style = ImGui::GetStyle();
|
||||
|
||||
int Index = 0;
|
||||
for (const auto& Entry : FCogDebugLog::GetLogCategories())
|
||||
{
|
||||
FName CategoryName = Entry.Key;
|
||||
const FCogDebugLogCategoryInfo& CategoryInfo = Entry.Value;
|
||||
if (CategoryInfo.bVisible == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FLogCategoryBase* Category = CategoryInfo.LogCategory;
|
||||
|
||||
ImGui::PushID(Index);
|
||||
FString CategoryFriendlyName = CategoryInfo.GetDisplayName();
|
||||
|
||||
if (bShowAllVerbosity == false)
|
||||
{
|
||||
const bool IsControlDown = ImGui::GetIO().KeyCtrl;
|
||||
if (IsClient)
|
||||
{
|
||||
ELogVerbosity::Type Verbosity = FCogDebugLog::GetServerVerbosity(CategoryName);
|
||||
bool IsActive = FCogDebugLog::IsVerbosityActive(Verbosity);
|
||||
|
||||
if (Verbosity == ELogVerbosity::VeryVerbose)
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_CheckMark, IM_COL32(255, 0, 0, 200));
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("##Server", &IsActive))
|
||||
{
|
||||
ELogVerbosity::Type NewVerbosity = IsActive ? (IsControlDown ? ELogVerbosity::VeryVerbose : ELogVerbosity::Verbose) : ELogVerbosity::Warning;
|
||||
FCogDebugLog::SetServerVerbosity(*World, CategoryName, NewVerbosity);
|
||||
}
|
||||
|
||||
if (Verbosity == ELogVerbosity::VeryVerbose)
|
||||
{
|
||||
ImGui::PopStyleColor(1);
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Server");
|
||||
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsControlDown ? 1.0f : 0.5f), "Very Verbose [CTRL]");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
{
|
||||
ELogVerbosity::Type Verbosity = Category->GetVerbosity();
|
||||
bool IsActive = FCogDebugLog::IsVerbosityActive(Verbosity);
|
||||
|
||||
if (Verbosity == ELogVerbosity::VeryVerbose)
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_CheckMark, IM_COL32(255, 0, 0, 200));
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(TCHAR_TO_ANSI(*CategoryFriendlyName), &IsActive))
|
||||
{
|
||||
ELogVerbosity::Type NewVerbosity = IsActive ? (IsControlDown ? ELogVerbosity::VeryVerbose : ELogVerbosity::Verbose) : ELogVerbosity::Warning;
|
||||
Category->SetVerbosity(NewVerbosity);
|
||||
}
|
||||
|
||||
if (Verbosity == ELogVerbosity::VeryVerbose)
|
||||
{
|
||||
ImGui::PopStyleColor(1);
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
if (IsClient)
|
||||
{
|
||||
ImGui::Text("Local Client");
|
||||
}
|
||||
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsControlDown ? 1.0f : 0.5f), "Very Verbose [CTRL]");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsClient)
|
||||
{
|
||||
ELogVerbosity::Type CurrentVerbosity = FCogDebugLog::GetServerVerbosity(CategoryName);
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::BeginCombo("##Server", FCogDebugHelper::VerbosityToString(CurrentVerbosity)))
|
||||
{
|
||||
for (int32 i = (int32)ELogVerbosity::Error; i <= (int32)ELogVerbosity::VeryVerbose; ++i)
|
||||
{
|
||||
bool IsSelected = i == (int32)CurrentVerbosity;
|
||||
ELogVerbosity::Type Verbosity = (ELogVerbosity::Type)i;
|
||||
|
||||
if (ImGui::Selectable(FCogDebugHelper::VerbosityToString(Verbosity), IsSelected))
|
||||
{
|
||||
FCogDebugLog::SetServerVerbosity(*World, CategoryName, Verbosity);
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Server");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
{
|
||||
ELogVerbosity::Type CurrentVerbosity = Category->GetVerbosity();
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::BeginCombo("##Local", FCogDebugHelper::VerbosityToString(CurrentVerbosity)))
|
||||
{
|
||||
for (int32 i = (int32)ELogVerbosity::Error; i <= (int32)ELogVerbosity::VeryVerbose; ++i)
|
||||
{
|
||||
bool IsSelected = i == (int32)CurrentVerbosity;
|
||||
ELogVerbosity::Type Verbosity = (ELogVerbosity::Type)i;
|
||||
|
||||
if (ImGui::Selectable(FCogDebugHelper::VerbosityToString(Verbosity), IsSelected))
|
||||
{
|
||||
Category->SetVerbosity(Verbosity);
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (IsClient && ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Local Client");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", TCHAR_TO_ANSI(*CategoryFriendlyName));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
Index++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
#include "CogEngineWindow_Metrics.h"
|
||||
|
||||
#include "CogDebugMetric.h"
|
||||
#include "CogImguiHelper.h"
|
||||
#include "CogWindowWidgets.h"
|
||||
#include "imgui.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Metrics::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window gather events generated by the selected actor to compute how much output it produces or receives per second. "
|
||||
"This is typically useful to compute the damage dealt per second, the damage received per second, etc. "
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Metrics::ResetConfig()
|
||||
{
|
||||
Super::ResetConfig();
|
||||
|
||||
MaxDurationSetting = 0.0f;
|
||||
RestartDelaySetting = 5.0f;
|
||||
PostInitProperties();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Metrics::PostInitProperties()
|
||||
{
|
||||
Super::PostInitProperties();
|
||||
|
||||
FCogDebugMetric::MaxDurationSetting = MaxDurationSetting;
|
||||
FCogDebugMetric::RestartDelaySetting = RestartDelaySetting;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Metrics::PreSaveConfig()
|
||||
{
|
||||
Super::PreSaveConfig();
|
||||
|
||||
MaxDurationSetting = FCogDebugMetric::MaxDurationSetting;
|
||||
RestartDelaySetting = FCogDebugMetric::RestartDelaySetting;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogEngineWindow_Metrics::UCogEngineWindow_Metrics()
|
||||
{
|
||||
bHasMenu = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Metrics::RenderTick(float DeltaTime)
|
||||
{
|
||||
Super::RenderTick(DeltaTime);
|
||||
FCogDebugMetric::IsVisible = GetIsVisible();
|
||||
|
||||
FCogDebugMetric::Tick(DeltaTime);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Metrics::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("Options"))
|
||||
{
|
||||
bool bSettingModified = false;
|
||||
|
||||
FCogWindowWidgets::PushStyleCompact();
|
||||
ImGui::DragFloat("Auto Restart Delay", &FCogDebugMetric::RestartDelaySetting, 0.1f, 0.0f, FLT_MAX, "%0.1f");
|
||||
FCogWindowWidgets::PopStyleCompact();
|
||||
|
||||
FCogWindowWidgets::PushStyleCompact();
|
||||
ImGui::DragFloat("Max Time", &FCogDebugMetric::MaxDurationSetting, 0.1f, 0.0f, FLT_MAX, "%0.1f");
|
||||
FCogWindowWidgets::PopStyleCompact();
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
if (GetWorld()->GetNetMode() == ENetMode::NM_Client)
|
||||
{
|
||||
ImGui::Text("Currently not available on client");
|
||||
return;
|
||||
}
|
||||
|
||||
if (FCogDebugMetric::Metrics.IsEmpty())
|
||||
{
|
||||
ImGui::Text("No metric received yet");
|
||||
return;
|
||||
}
|
||||
|
||||
int32 Index = 0;
|
||||
for (auto& Entry : FCogDebugMetric::Metrics)
|
||||
{
|
||||
FName MetricName = Entry.Key;
|
||||
FCogDebugMetricEntry& Metric = Entry.Value;
|
||||
|
||||
if (ImGui::CollapsingHeader(TCHAR_TO_ANSI(*MetricName.ToString()), ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::PushID(Index);
|
||||
DrawMetric(Metric);
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
Index++;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Metrics::DrawMetric(FCogDebugMetricEntry& Metric)
|
||||
{
|
||||
FCogWindowWidgets::PushBackColor(ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
|
||||
|
||||
if (ImGui::BeginTable("MetricTable", 4, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_RowBg))
|
||||
{
|
||||
ImGui::TableSetupColumn("");
|
||||
ImGui::TableSetupColumn("Mitigated");
|
||||
ImGui::TableSetupColumn("Unmitigated");
|
||||
ImGui::TableSetupColumn("Mitigation %");
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
DrawMetricRow("Per Second", Metric.Mitigated.PerSecond, Metric.Unmitigated.PerSecond, ImVec4(1.0f, 1.0, 0.0f, 1.0f));
|
||||
DrawMetricRow("Total", Metric.Mitigated.Total, Metric.Unmitigated.Total, ImVec4(1.0f, 1.0, 1.0f, 1.0f));
|
||||
DrawMetricRow("Last", Metric.Mitigated.Last, Metric.Unmitigated.Last, ImVec4(1.0f, 1.0, 1.0f, 1.0f));
|
||||
DrawMetricRow("Min", Metric.Mitigated.Min, Metric.Unmitigated.Min, ImVec4(1.0f, 1.0, 1.0f, 1.0f));
|
||||
DrawMetricRow("Min", Metric.Mitigated.Max, Metric.Unmitigated.Max, ImVec4(1.0f, 1.0, 1.0f, 1.0f));
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::Text("Crits");
|
||||
ImGui::SameLine(FCogWindowWidgets::GetFontWidth() * 20);
|
||||
FCogWindowWidgets::ProgressBarCentered(Metric.Count == 0 ? 0.0f : Metric.Crits / (float)Metric.Count, ImVec2(-1, 0), TCHAR_TO_ANSI(*FString::Printf(TEXT("%d / %d"), Metric.Crits, Metric.Count)));
|
||||
|
||||
if (FCogDebugMetric::MaxDurationSetting > 0.0f)
|
||||
{
|
||||
ImGui::Text("Timer");
|
||||
ImGui::SameLine(FCogWindowWidgets::GetFontWidth() * 20);
|
||||
FCogWindowWidgets::ProgressBarCentered(Metric.Timer / (float)FCogDebugMetric::MaxDurationSetting, ImVec2(-1, 0), TCHAR_TO_ANSI(*FString::Printf(TEXT("%0.1f / %0.1f"), Metric.Timer, FCogDebugMetric::MaxDurationSetting)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Timer");
|
||||
ImGui::SameLine(FCogWindowWidgets::GetFontWidth() * 20);
|
||||
ImGui::Text("%0.1f", Metric.Timer);
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
FCogWindowWidgets::PopBackColor();
|
||||
|
||||
if (ImGui::Button("Restart"))
|
||||
{
|
||||
Metric.Reset();
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Metrics::DrawMetricRow(const char* Title, float MitigatedValue, float UnmitigatedValue, const ImVec4& Color)
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Selectable(Title, false, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap | ImGuiSelectableFlags_AllowDoubleClick);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextColored(Color, "%.1f", MitigatedValue);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%.1f", UnmitigatedValue);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%.0f%%", UnmitigatedValue <= 0 ? 0.0 : 100.0f * (1.0f - (MitigatedValue / UnmitigatedValue)));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
#include "CogEngineWindow_NetEmulation.h"
|
||||
|
||||
#include "CogEngineWindow_Stats.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "Engine/NetDriver.h"
|
||||
#include "Engine/NetConnection.h"
|
||||
#include "Engine/World.h"
|
||||
#include "GameFramework/PlayerState.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_NetEmulation::RenderHelp()
|
||||
{
|
||||
ImGui::Text("This window is used to configure the network emulation.");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_NetEmulation::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
DrawStats();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
DrawControls();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_NetEmulation::DrawStats()
|
||||
{
|
||||
const APlayerController* PlayerController = GetLocalPlayerController();
|
||||
if (PlayerController == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (const APlayerState* PlayerState = PlayerController->GetPlayerState<APlayerState>())
|
||||
{
|
||||
const float Ping = PlayerState->GetPingInMilliseconds();
|
||||
ImGui::Text("Ping ");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(UCogEngineWindow_Stats::GetPingColor(Ping), "%0.0fms", Ping);
|
||||
}
|
||||
|
||||
if (UNetConnection* Connection = PlayerController->GetNetConnection())
|
||||
{
|
||||
const float OutPacketLost = Connection->GetOutLossPercentage().GetAvgLossPercentage() * 100.0f;
|
||||
ImGui::Text("Packet Loss Out ");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(UCogEngineWindow_Stats::GetPacketLossColor(OutPacketLost), "%0.0f%%", OutPacketLost);
|
||||
|
||||
const float InPacketLost = Connection->GetInLossPercentage().GetAvgLossPercentage() * 100.0f;
|
||||
ImGui::Text("Packet Loss In ");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(UCogEngineWindow_Stats::GetPacketLossColor(InPacketLost), "%0.0f%%", InPacketLost);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_NetEmulation::DrawControls()
|
||||
{
|
||||
FWorldContext& WorldContext = GEngine->GetWorldContextFromWorldChecked(GetWorld());
|
||||
|
||||
if (WorldContext.ActiveNetDrivers.Num() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int32 SelectedIndex = 0;
|
||||
|
||||
if (SelectedIndex >= WorldContext.ActiveNetDrivers.Num())
|
||||
{
|
||||
SelectedIndex = 0;
|
||||
}
|
||||
|
||||
FNamedNetDriver* SelectedNetDriver = &WorldContext.ActiveNetDrivers[SelectedIndex];
|
||||
if (SelectedNetDriver == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::BeginCombo("Driver", TCHAR_TO_ANSI(*SelectedNetDriver->NetDriver->GetName())))
|
||||
{
|
||||
int i = 0;
|
||||
for (FNamedNetDriver& NamedNetDriver : WorldContext.ActiveNetDrivers)
|
||||
{
|
||||
if (NamedNetDriver.NetDriver != nullptr)
|
||||
{
|
||||
if (ImGui::Selectable(TCHAR_TO_ANSI(*NamedNetDriver.NetDriver->GetName())))
|
||||
{
|
||||
SelectedIndex = i;
|
||||
SelectedNetDriver = &WorldContext.ActiveNetDrivers[i];
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (SelectedNetDriver == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if DO_ENABLE_NET_TEST
|
||||
|
||||
FPacketSimulationSettings Settings = SelectedNetDriver->NetDriver->PacketSimulationSettings;
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::DragInt("Lag Min", &Settings.PktLagMin, 1.0f, 0, INT_MAX, "%d ms"))
|
||||
{
|
||||
SelectedNetDriver->NetDriver->SetPacketSimulationSettings(Settings);
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip(
|
||||
"If set lag values will randomly fluctuate between Min and Max.");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::DragInt("Lag Max", &Settings.PktLagMax, 1.0f, 0, INT_MAX, "%d ms"))
|
||||
{
|
||||
SelectedNetDriver->NetDriver->SetPacketSimulationSettings(Settings);
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip(
|
||||
"If set lag values will randomly fluctuate between Min and Max.");
|
||||
}
|
||||
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::SliderInt("Packet Loss", &Settings.PktLoss, 0, 100, "%d%%"))
|
||||
{
|
||||
SelectedNetDriver->NetDriver->SetPacketSimulationSettings(Settings);
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip(
|
||||
"When set, will cause calls to FlushNet to drop packets.\n"
|
||||
"Value is treated as %% of packets dropped (i.e. 0 = None, 100 = All).\n"
|
||||
"No general pattern / ordering is guaranteed.\n"
|
||||
"Clamped between 0 and 100.\n"
|
||||
"Works with all other settings.");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::SliderInt("Packet Order", &Settings.PktOrder, 0, 100, "%d%%"))
|
||||
{
|
||||
SelectedNetDriver->NetDriver->SetPacketSimulationSettings(Settings);
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip(
|
||||
"When set, will cause calls to FlushNet to change ordering of packets at random.\n"
|
||||
"Value is treated as a bool(i.e. 0 = False, anything else = True). \n"
|
||||
"This works by randomly selecting packets to be delayed until a subsequent call to FlushNet.\n"
|
||||
"Takes precedence over PktDup and PktLag.");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::SliderInt("Packet Dup", &Settings.PktDup, 0, 100, "%d%%"))
|
||||
{
|
||||
SelectedNetDriver->NetDriver->SetPacketSimulationSettings(Settings);
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip(
|
||||
"When set, will cause calls to FlushNet to duplicate packets.\n"
|
||||
"Value is treated as %% of packets duplicated(i.e. 0 = None, 100 = All).\n"
|
||||
"No general pattern / ordering is guaranteed.\n"
|
||||
"Clamped between 0 and 100.\n"
|
||||
"Cannot be used with PktOrder or PktLag.");
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::DragInt("Incoming Lag Min", &Settings.PktIncomingLagMin, 1.0f, 0, INT_MAX, "%d ms"))
|
||||
{
|
||||
SelectedNetDriver->NetDriver->SetPacketSimulationSettings(Settings);
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip(
|
||||
"The minimum delay in milliseconds to incoming packets before they are processed");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::DragInt("Incoming Lag Max", &Settings.PktIncomingLagMax, 1.0f, 0, INT_MAX, "%d ms"))
|
||||
{
|
||||
SelectedNetDriver->NetDriver->SetPacketSimulationSettings(Settings);
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip(
|
||||
"The maximum delay in milliseconds to add to incoming packets before they are processed");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::SliderInt("Incoming Packet Loss", &Settings.PktIncomingLoss, 0, 100, "%d%%"))
|
||||
{
|
||||
SelectedNetDriver->NetDriver->SetPacketSimulationSettings(Settings);
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip(
|
||||
"The ratio of incoming packets that will be dropped to simulate packet loss");
|
||||
}
|
||||
|
||||
#endif //DO_ENABLE_NET_TEST
|
||||
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
#include "CogEngineWindow_OutputLog.h"
|
||||
|
||||
#include "CogDebugHelper.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "Misc/StringBuilder.h"
|
||||
|
||||
char ImGuiTextBuffer::EmptyString[1] = { 0 };
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogWindow_Log
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogEngineWindow_OutputLog::UCogEngineWindow_OutputLog()
|
||||
{
|
||||
bHasMenu = true;
|
||||
OutputDevice.OutputLog = this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_OutputLog::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window output the log based on each log categories verbosity. "
|
||||
"The verbosity of each log category can be configured in the 'Log Categories' window. "
|
||||
);
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_OutputLog::ResetConfig()
|
||||
{
|
||||
Super::ResetConfig();
|
||||
|
||||
AutoScroll = true;
|
||||
ShowFrame = true;
|
||||
ShowCategory = true;
|
||||
ShowVerbosity = false;
|
||||
ShowAsTable = false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_OutputLog::Clear()
|
||||
{
|
||||
TextBuffer.clear();
|
||||
LineInfos.Empty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_OutputLog::AddLog(const TCHAR* Message, ELogVerbosity::Type Verbosity, const class FName& Category)
|
||||
{
|
||||
static TAnsiStringBuilder<512> Format;
|
||||
|
||||
Format.Reset();
|
||||
|
||||
if (Message)
|
||||
{
|
||||
Format.Append(Message);
|
||||
}
|
||||
|
||||
FLineInfo& LineInfo = LineInfos.AddDefaulted_GetRef();
|
||||
LineInfo.Frame = GFrameCounter % 1000;
|
||||
LineInfo.Verbosity = Verbosity;
|
||||
LineInfo.Category = Category;
|
||||
LineInfo.Start = TextBuffer.size();
|
||||
|
||||
TextBuffer.append(Format.GetData(), Format.GetData() + Format.Len());
|
||||
|
||||
LineInfo.End = TextBuffer.size();
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_OutputLog::DrawRow(const char* BufferStart, const FLineInfo& LineInfo, bool IsTableShown)
|
||||
{
|
||||
ImU32 Color;
|
||||
switch (LineInfo.Verbosity)
|
||||
{
|
||||
case ELogVerbosity::Error: Color = IM_COL32(255, 0, 0, 255); break;
|
||||
case ELogVerbosity::Warning: Color = IM_COL32(255, 200, 0, 255); break;
|
||||
default: Color = IM_COL32(200, 200, 200, 255); break;
|
||||
}
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, Color);
|
||||
|
||||
if (IsTableShown)
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
|
||||
if (ShowFrame)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%3d", LineInfo.Frame);
|
||||
}
|
||||
|
||||
if (ShowCategory)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", TCHAR_TO_ANSI(*LineInfo.Category.ToString()));
|
||||
}
|
||||
|
||||
if (ShowVerbosity)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", TCHAR_TO_ANSI(ToString(LineInfo.Verbosity)));
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
const char* LineStart = BufferStart + LineInfo.Start;
|
||||
const char* LineEnd = BufferStart + LineInfo.End;
|
||||
ImGui::TextUnformatted(LineStart, LineEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ShowFrame)
|
||||
{
|
||||
ImGui::Text("[%3d] ", LineInfo.Frame);
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
if (ShowCategory)
|
||||
{
|
||||
ImGui::Text("%s: ", TCHAR_TO_ANSI(*LineInfo.Category.ToString()));
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
if (ShowVerbosity)
|
||||
{
|
||||
ImGui::Text("%s: ", TCHAR_TO_ANSI(ToString(LineInfo.Verbosity)));
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
const char* LineStart = BufferStart + LineInfo.Start;
|
||||
const char* LineEnd = BufferStart + LineInfo.End;
|
||||
ImGui::TextUnformatted(LineStart, LineEnd);
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_OutputLog::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
bool ClearPressed = false;
|
||||
bool CopyPressed = false;
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("Options"))
|
||||
{
|
||||
if (ImGui::MenuItem("Copy"))
|
||||
{
|
||||
ImGui::LogToClipboard();
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Checkbox("Auto Scroll", &AutoScroll);
|
||||
ImGui::Checkbox("Show Frame", &ShowFrame);
|
||||
ImGui::Checkbox("Show Category", &ShowCategory);
|
||||
ImGui::Checkbox("Show Verbosity", &ShowVerbosity);
|
||||
ImGui::Checkbox("Show As Table", &ShowAsTable);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::MenuItem("Clear"))
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 9);
|
||||
if (ImGui::BeginCombo("##Verbosity", FCogDebugHelper::VerbosityToString((ELogVerbosity::Type)VerbosityFilter)))
|
||||
{
|
||||
for (int32 i = (int32)ELogVerbosity::Error; i <= (int32)ELogVerbosity::VeryVerbose; ++i)
|
||||
{
|
||||
bool IsSelected = i == VerbosityFilter;
|
||||
ELogVerbosity::Type Verbosity = (ELogVerbosity::Type)i;
|
||||
|
||||
if (ImGui::Selectable(FCogDebugHelper::VerbosityToString(Verbosity), IsSelected))
|
||||
{
|
||||
VerbosityFilter = i;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
FCogWindowWidgets::MenuSearchBar(Filter);
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
int32 ColumnCount = 1;
|
||||
ColumnCount += (int32)ShowFrame;
|
||||
ColumnCount += (int32)ShowCategory;
|
||||
ColumnCount += (int32)ShowVerbosity;
|
||||
|
||||
bool IsTableShown = false;
|
||||
if (ShowAsTable)
|
||||
{
|
||||
if (ImGui::BeginTable("LogTable", ColumnCount, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ScrollX))
|
||||
{
|
||||
IsTableShown = true;
|
||||
if (ShowFrame)
|
||||
{
|
||||
ImGui::TableSetupColumn("Frame", ImGuiTableColumnFlags_WidthFixed, FCogWindowWidgets::GetFontWidth() * 4);
|
||||
}
|
||||
|
||||
if (ShowCategory)
|
||||
{
|
||||
ImGui::TableSetupColumn("Category", ImGuiTableColumnFlags_WidthFixed, FCogWindowWidgets::GetFontWidth() * 10);
|
||||
}
|
||||
|
||||
if (ShowVerbosity)
|
||||
{
|
||||
ImGui::TableSetupColumn("Verbosity", ImGuiTableColumnFlags_WidthFixed, FCogWindowWidgets::GetFontWidth() * 10);
|
||||
}
|
||||
|
||||
ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthStretch);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsTableShown == false)
|
||||
{
|
||||
ImGui::BeginChild("Scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
||||
}
|
||||
|
||||
const char* BufferStart = TextBuffer.begin();
|
||||
|
||||
if (Filter.IsActive())
|
||||
{
|
||||
for (int32 LineIndex = 0; LineIndex < LineInfos.Num(); LineIndex++)
|
||||
{
|
||||
const FLineInfo& LineInfo = LineInfos[LineIndex];
|
||||
const char* LineStart = BufferStart + LineInfo.Start;
|
||||
const char* LineEnd = BufferStart + LineInfo.End;
|
||||
if (Filter.PassFilter(LineStart, LineEnd))
|
||||
{
|
||||
DrawRow(BufferStart, LineInfo, IsTableShown);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (VerbosityFilter != ELogVerbosity::VeryVerbose)
|
||||
{
|
||||
for (int32 LineIndex = 0; LineIndex < LineInfos.Num(); LineIndex++)
|
||||
{
|
||||
const FLineInfo& LineInfo = LineInfos[LineIndex];
|
||||
|
||||
if (LineInfo.Verbosity <= (ELogVerbosity::Type)VerbosityFilter)
|
||||
{
|
||||
const char* LineStart = BufferStart + LineInfo.Start;
|
||||
const char* LineEnd = BufferStart + LineInfo.End;
|
||||
DrawRow(BufferStart, LineInfo, IsTableShown);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGuiListClipper Clipper;
|
||||
Clipper.Begin(LineInfos.Num());
|
||||
while (Clipper.Step())
|
||||
{
|
||||
for (int32 LineIndex = Clipper.DisplayStart; LineIndex < Clipper.DisplayEnd; LineIndex++)
|
||||
{
|
||||
if (LineInfos.IsValidIndex(LineIndex))
|
||||
{
|
||||
const FLineInfo& LineInfo = LineInfos[LineIndex];
|
||||
DrawRow(BufferStart, LineInfo, IsTableShown);
|
||||
}
|
||||
}
|
||||
}
|
||||
Clipper.End();
|
||||
}
|
||||
|
||||
if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
|
||||
{
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
}
|
||||
|
||||
if (IsTableShown)
|
||||
{
|
||||
ImGui::EndTable();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// FCogLogOutputDevice
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogLogOutputDevice::UCogLogOutputDevice()
|
||||
{
|
||||
GLog->AddOutputDevice(this);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogLogOutputDevice::~UCogLogOutputDevice()
|
||||
{
|
||||
if (GLog != nullptr)
|
||||
{
|
||||
GLog->RemoveOutputDevice(this);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogLogOutputDevice::Serialize(const TCHAR* Message, ELogVerbosity::Type Verbosity, const class FName& Category)
|
||||
{
|
||||
if (OutputLog != nullptr)
|
||||
{
|
||||
OutputLog->AddLog(Message, Verbosity, Category);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,480 @@
|
||||
#include "CogEngineWindow_Plots.h"
|
||||
|
||||
#include "CogImGuiHelper.h"
|
||||
#include "CogDebugPlot.h"
|
||||
#include "CogWindowWidgets.h"
|
||||
#include "imgui.h"
|
||||
#include "implot_internal.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Plots::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window plots values overtime. When applicable, only the values of the selected actor are displayed."
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Plots::RenderTick(float DeltaTime)
|
||||
{
|
||||
Super::RenderTick(DeltaTime);
|
||||
FCogDebugPlot::IsVisible = GetIsVisible();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Plots::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
static int Rows = 1;
|
||||
static int Cols = 1;
|
||||
|
||||
if (ImGui::BeginTable("PlotTable", 2, ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable))
|
||||
{
|
||||
ImGui::TableSetupColumn("Settings", ImGuiTableColumnFlags_WidthFixed, FCogWindowWidgets::GetFontWidth() * 20.0f);
|
||||
ImGui::TableSetupColumn("Graph", ImGuiTableColumnFlags_WidthStretch, 0.0f);
|
||||
ImGui::TableNextRow();
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Settings and Entries
|
||||
//--------------------------------------------------------------------------------------
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Button("Settings"))
|
||||
{
|
||||
ImGui::OpenPopup("SettingsPopup");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
FCogWindowWidgets::ToggleButton(&FCogDebugPlot::Pause, "Pause", "Pause", ImVec4(1.0f, 0.0f, 0.0f, 1.0f), ImVec4(0.5f, 0.5f, 0.5f, 1.0f));
|
||||
|
||||
if (ImGui::BeginPopup("SettingsPopup"))
|
||||
{
|
||||
ImGui::SliderInt("Rows", &Rows, 1, 5);
|
||||
|
||||
if (ImGui::Button("Clear Data", ImVec2(-1, 0)))
|
||||
{
|
||||
FCogDebugPlot::Clear();
|
||||
}
|
||||
|
||||
if (ImGui::Button("Reset Layout", ImVec2(-1, 0)))
|
||||
{
|
||||
FCogDebugPlot::Pause = false;
|
||||
Rows = 1;
|
||||
|
||||
FCogDebugPlot::Reset();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::BeginChild("Separator", ImVec2(0, 2)))
|
||||
{
|
||||
ImGui::Separator();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
TArray<FCogDebugPlotEntry*> VisiblePlots;
|
||||
if (ImGui::BeginChild("Plots", ImVec2(0, -1)))
|
||||
{
|
||||
int Index = 0;
|
||||
|
||||
for (FCogDebugPlotEntry& Plot : FCogDebugPlot::Plots)
|
||||
{
|
||||
const auto Label = StringCast<ANSICHAR>(*Plot.Name.ToString());
|
||||
|
||||
if (Plot.CurrentYAxis != ImAxis_COUNT && Plot.CurrentRow != INDEX_NONE)
|
||||
{
|
||||
VisiblePlots.Add(&Plot);
|
||||
}
|
||||
|
||||
ImGui::PushID(Index);
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, Plot.IsEventPlot ? IM_COL32(128, 128, 255, 255) : IM_COL32(255, 255, 255, 255));
|
||||
ImGui::Selectable(Label.Get(), false, 0);
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
|
||||
{
|
||||
ImGui::SetDragDropPayload("DragAndDrop", Label.Get(), Label.Length() + 1);
|
||||
ImGui::TextUnformatted(Label.Get());
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
Index++;
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
if (const ImGuiPayload* Payload = ImGui::AcceptDragDropPayload("DragAndDrop"))
|
||||
{
|
||||
if (FCogDebugPlotEntry* Plot = FCogDebugPlot::FindPlot(FName((const char*)Payload->Data)))
|
||||
{
|
||||
Plot->ResetAxis();
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Graph
|
||||
//--------------------------------------------------------------------------------------
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::BeginChild("Graph", ImVec2(0, -1)))
|
||||
{
|
||||
static float RowRatios[] = { 1, 1, 1, 1, 1, 1 };
|
||||
static float ColRatios[] = { 1 };
|
||||
static ImPlotSubplotFlags SubplotsFlags = ImPlotSubplotFlags_LinkCols;
|
||||
if (ImPlot::BeginSubplots("", Rows, Cols, ImVec2(-1, -1), SubplotsFlags, RowRatios, ColRatios))
|
||||
{
|
||||
for (int PlotIndex = 0; PlotIndex < Rows; ++PlotIndex)
|
||||
{
|
||||
if (ImPlot::BeginPlot("##Plot", ImVec2(-1, 250)))
|
||||
{
|
||||
ImPlotAxisFlags HasPlotOnAxisY1 = false;
|
||||
ImPlotAxisFlags HasPlotOnAxisY2 = false;
|
||||
ImPlotAxisFlags HasPlotOnAxisY3 = false;
|
||||
|
||||
for (FCogDebugPlotEntry* PlotPtr : VisiblePlots)
|
||||
{
|
||||
HasPlotOnAxisY1 |= PlotPtr->CurrentYAxis == ImAxis_Y1 && PlotPtr->CurrentRow == PlotIndex;
|
||||
HasPlotOnAxisY2 |= PlotPtr->CurrentYAxis == ImAxis_Y2 && PlotPtr->CurrentRow == PlotIndex;
|
||||
HasPlotOnAxisY3 |= PlotPtr->CurrentYAxis == ImAxis_Y3 && PlotPtr->CurrentRow == PlotIndex;
|
||||
}
|
||||
|
||||
ImPlot::SetupAxis(ImAxis_X1, NULL, ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines);
|
||||
ImPlot::SetupAxis(ImAxis_Y1, HasPlotOnAxisY1 ? "" : "[drop here]", (HasPlotOnAxisY1 ? ImPlotAxisFlags_None : (ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines)) | ImPlotAxisFlags_AutoFit);
|
||||
ImPlot::SetupAxis(ImAxis_Y2, HasPlotOnAxisY2 ? "" : "[drop here]", (HasPlotOnAxisY2 ? ImPlotAxisFlags_None : (ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines)) | ImPlotAxisFlags_AutoFit | ImPlotAxisFlags_Opposite);
|
||||
ImPlot::SetupAxis(ImAxis_Y3, HasPlotOnAxisY3 ? "" : "[drop here]", (HasPlotOnAxisY3 ? ImPlotAxisFlags_None : (ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines)) | ImPlotAxisFlags_AutoFit | ImPlotAxisFlags_Opposite);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Set the initial X axis range. After it is automatically updated to move with the current time.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
ImPlot::SetupAxisLimits(ImAxis_X1, 0, 10.0f, ImGuiCond_Appearing);
|
||||
|
||||
const ImPlotRange& Range = ImPlot::GetCurrentPlot()->Axes[ImAxis_X1].Range;
|
||||
const float AxisXRange = Range.Max - Range.Min;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Draw a vertical lines representing the current time and the mouse time
|
||||
//----------------------------------------------------------------
|
||||
ImDrawList* PlotDrawList = ImPlot::GetPlotDrawList();
|
||||
const ImVec2 PlotMin = ImPlot::GetPlotPos();
|
||||
const ImVec2 PlotSize = ImPlot::GetPlotSize();
|
||||
const ImVec2 PlotMax = ImVec2(PlotMin.x + PlotSize.x, PlotMin.y + PlotSize.y);
|
||||
const float PlotTop = PlotMin.y;
|
||||
const float TimeBarBottom = PlotTop + PlotSize.y;
|
||||
|
||||
ImPlot::PushPlotClipRect();
|
||||
PlotDrawList->AddLine(ImVec2(ImGui::GetMousePos().x, PlotTop), ImVec2(ImGui::GetMousePos().x, TimeBarBottom), IM_COL32(128, 128, 128, 64));
|
||||
if (FCogDebugPlot::Pause)
|
||||
{
|
||||
const float Time = GetWorld() ? GetWorld()->GetTimeSeconds() : 0.0;
|
||||
const float TimeBarX = ImPlot::PlotToPixels(Time, 0.0f).x;
|
||||
PlotDrawList->AddLine(ImVec2(TimeBarX, PlotTop), ImVec2(TimeBarX, TimeBarBottom), IM_COL32(255, 255, 255, 64));
|
||||
}
|
||||
ImPlot::PopPlotClipRect();
|
||||
|
||||
for (FCogDebugPlotEntry* PlotPtr : VisiblePlots)
|
||||
{
|
||||
if (PlotPtr == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FCogDebugPlotEntry& Entry = *PlotPtr;
|
||||
|
||||
if (Entry.CurrentRow == PlotIndex)
|
||||
{
|
||||
//--------------------------------------------------------------------------------
|
||||
// Make the time axis move forward automatically, unless the user pauses or zoom.
|
||||
//--------------------------------------------------------------------------------
|
||||
if (FCogDebugPlot::Pause == false && ImGui::GetIO().MouseWheel == 0)
|
||||
{
|
||||
ImPlot::SetupAxisLimits(ImAxis_X1, Entry.Time - AxisXRange, Entry.Time, ImGuiCond_Always);
|
||||
}
|
||||
|
||||
ImPlot::SetAxis(Entry.CurrentYAxis);
|
||||
|
||||
ImPlot::SetNextLineStyle(IMPLOT_AUTO_COL);
|
||||
const auto Label = StringCast<ANSICHAR>(*Entry.Name.ToString());
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Pause the scrolling if the user drag inside
|
||||
//----------------------------------------------------------------
|
||||
ImVec2 Mouse = ImGui::GetMousePos();
|
||||
if (Mouse.x > PlotMin.x
|
||||
&& Mouse.y > PlotMin.y
|
||||
&& Mouse.x < PlotMax.x
|
||||
&& Mouse.y < PlotMax.y
|
||||
&& ImGui::GetDragDropPayload() == nullptr)
|
||||
{
|
||||
ImVec2 Drag = ImGui::GetMouseDragDelta(0);
|
||||
if (FMath::Abs(Drag.x) > 10)
|
||||
{
|
||||
FCogDebugPlot::Pause = true;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Plot Events
|
||||
//-------------------------------------------------------
|
||||
const bool IsEventPlot = Entry.Events.Num() > 0;
|
||||
if (IsEventPlot)
|
||||
{
|
||||
//--------------------------------------------------------------------
|
||||
// Update plot time for events as events are not pushed every frames
|
||||
//--------------------------------------------------------------------
|
||||
Entry.UpdateTime(GetWorld());
|
||||
|
||||
ImPlot::SetupAxisLimits(Entry.CurrentYAxis, 0, Entry.MaxRow + 2, ImGuiCond_Always);
|
||||
|
||||
ImPlot::PushPlotClipRect();
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Plot line only to make the plotter move in time and auto scale
|
||||
//----------------------------------------------------------------
|
||||
ImVector<ImVec2> DummyData;
|
||||
DummyData.push_back(ImVec2(0, 0));
|
||||
DummyData.push_back(ImVec2(0, 8));
|
||||
ImPlot::PlotLine(Label.Get(), &DummyData[0].x, &DummyData[0].y, DummyData.size(), Entry.ValueOffset, 2 * sizeof(float));
|
||||
|
||||
const FCogDebugPlotEvent* HoveredEvent = nullptr;
|
||||
|
||||
for (const FCogDebugPlotEvent& Event : Entry.Events)
|
||||
{
|
||||
const ImVec2 PosBot = ImPlot::PlotToPixels(ImPlotPoint(Event.StartTime, Event.Row + 0.8f));
|
||||
const ImVec2 PosTop = ImPlot::PlotToPixels(ImPlotPoint(Event.StartTime, Event.Row + 0.2f));
|
||||
const ImVec2 PosMid(PosBot.x, PosBot.y + (PosTop.y - PosBot.y) * 0.5f);
|
||||
|
||||
const bool IsInstant = Event.StartTime == Event.EndTime;
|
||||
if (IsInstant)
|
||||
{
|
||||
const float Radius = 10.0f;
|
||||
PlotDrawList->AddNgon(PosMid, 10, Event.BorderColor, 4);
|
||||
PlotDrawList->AddNgonFilled(PosMid, 10, Event.FillColor, 4);
|
||||
PlotDrawList->AddText(ImVec2(PosMid.x + 15, PosMid.y - 6), IM_COL32(255, 255, 255, 255), TCHAR_TO_ANSI(*Event.DisplayName));
|
||||
|
||||
if ((Mouse.x > PosMid.x - Radius) && (Mouse.x < PosMid.x + Radius) && (Mouse.y > PosMid.y - Radius) && (Mouse.y < PosMid.y + Radius))
|
||||
{
|
||||
HoveredEvent = &Event;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const float ActualEndTime = Event.GetActualEndTime(Entry);
|
||||
const ImVec2 PosEnd = ImPlot::PlotToPixels(ImPlotPoint(ActualEndTime, 0));
|
||||
const ImVec2 Min = ImVec2(PosBot.x, PosBot.y);
|
||||
const ImVec2 Max = ImVec2(PosEnd.x, PosTop.y);
|
||||
|
||||
ImDrawFlags Flags = Event.EndTime == 0.0f ? ImDrawFlags_RoundCornersLeft : ImDrawFlags_RoundCornersAll;
|
||||
PlotDrawList->AddRect(Min, Max, Event.BorderColor, 6.0f, Flags);
|
||||
PlotDrawList->AddRectFilled(Min, Max, Event.FillColor, 6.0f, Flags);
|
||||
PlotDrawList->PushClipRect(ImMax(Min, PlotMin), ImMin(Max, PlotMax));
|
||||
PlotDrawList->AddText(ImVec2(PosMid.x + 5, PosMid.y - 7), IM_COL32(255, 255, 255, 255), TCHAR_TO_ANSI(*Event.DisplayName));
|
||||
PlotDrawList->PopClipRect();
|
||||
|
||||
if (Mouse.x > Min.x && Mouse.x < Max.x && Mouse.y > Min.y && Mouse.y < Max.y)
|
||||
{
|
||||
HoveredEvent = &Event;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Write info on the graph to help debugging
|
||||
//-------------------------------------------------------
|
||||
//char Buffer[64];
|
||||
//ImFormatString(Buffer, 64, "%0.1f %0.1f", Mouse.x, Mouse.y);
|
||||
//PlotDrawList->AddText(ImVec2(PlotMin.x + 50, PlotMin.y + 100), IM_COL32(255, 255, 255, 255), Buffer);
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Hovered event tooltip
|
||||
//-------------------------------------------------------
|
||||
if (ImPlot::IsPlotHovered() && HoveredEvent != nullptr)
|
||||
{
|
||||
FCogWindowWidgets::BeginTableTooltip();
|
||||
if (ImGui::BeginTable("Params", 2, ImGuiTableFlags_Borders))
|
||||
{
|
||||
//------------------------
|
||||
// Event Name
|
||||
//------------------------
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Name");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", TCHAR_TO_ANSI(*HoveredEvent->DisplayName));
|
||||
|
||||
//------------------------
|
||||
// Owner Name
|
||||
//------------------------
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Owner");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", TCHAR_TO_ANSI(*HoveredEvent->OwnerName));
|
||||
|
||||
//------------------------
|
||||
// Times
|
||||
//------------------------
|
||||
if (HoveredEvent->EndTime != HoveredEvent->StartTime)
|
||||
{
|
||||
const float ActualEndTime = HoveredEvent->GetActualEndTime(Entry);
|
||||
const uint64 ActualEndFrame = HoveredEvent->GetActualEndFrame(Entry);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Duration");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%0.2fs", ActualEndTime - HoveredEvent->StartTime);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Frames");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d [%d-%d]",
|
||||
(int32)(ActualEndFrame - HoveredEvent->StartFrame),
|
||||
(int32)(HoveredEvent->StartFrame % 1000),
|
||||
(int32)(ActualEndFrame % 1000));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Frame");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", (int32)(HoveredEvent->StartFrame % 1000));
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// Params
|
||||
//------------------------
|
||||
for (FCogDebugPlotEventParams Param : HoveredEvent->Params)
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", TCHAR_TO_ANSI(*Param.Name.ToString()));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", TCHAR_TO_ANSI(*Param.Value));
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
FCogWindowWidgets::EndTableTooltip();
|
||||
}
|
||||
|
||||
ImPlot::PopPlotClipRect();
|
||||
}
|
||||
//-------------------------------------------------------
|
||||
// Plot Values
|
||||
//-------------------------------------------------------
|
||||
else
|
||||
{
|
||||
//----------------------------------------------------------------
|
||||
// Custom tooltip
|
||||
//----------------------------------------------------------------
|
||||
if (ImPlot::IsPlotHovered())
|
||||
{
|
||||
float Value;
|
||||
if (Entry.FindValue(ImPlot::GetPlotMousePos().x, Value))
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("%s: %0.1f", Label.Get(), Value);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
if (Entry.ShowValuesMarkers)
|
||||
{
|
||||
ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle);
|
||||
}
|
||||
|
||||
ImPlot::PlotLine(Label.Get(), &Entry.Values[0].x, &Entry.Values[0].y, Entry.Values.size(), ImPlotLineFlags_None, Entry.ValueOffset, 2 * sizeof(float));
|
||||
|
||||
if (ImPlot::BeginLegendPopup(Label.Get()))
|
||||
{
|
||||
if (ImGui::Button("Clear"))
|
||||
{
|
||||
Entry.Clear();
|
||||
}
|
||||
ImGui::Checkbox("Show Markers", &Entry.ShowValuesMarkers);
|
||||
ImPlot::EndLegendPopup();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Allow legend item labels to be drag and drop sources
|
||||
//-------------------------------------------------------
|
||||
if (ImPlot::BeginDragDropSourceItem(Label.Get()))
|
||||
{
|
||||
ImGui::SetDragDropPayload("DragAndDrop", Label.Get(), Label.Length() + 1);
|
||||
ImGui::TextUnformatted(Label.Get());
|
||||
ImPlot::EndDragDropSource();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Allow the main plot area to be a drag and drop target
|
||||
//-------------------------------------------------------
|
||||
if (ImPlot::BeginDragDropTargetPlot())
|
||||
{
|
||||
if (const ImGuiPayload* Payload = ImGui::AcceptDragDropPayload("DragAndDrop"))
|
||||
{
|
||||
if (FCogDebugPlotEntry* Plot = FCogDebugPlot::FindPlot(FName((const char*)Payload->Data)))
|
||||
{
|
||||
Plot->AssignAxis(PlotIndex, ImAxis_Y1);
|
||||
}
|
||||
}
|
||||
ImPlot::EndDragDropTarget();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Allow each y-axis to be a drag and drop target
|
||||
//-------------------------------------------------------
|
||||
for (int y = ImAxis_Y1; y <= ImAxis_Y3; ++y)
|
||||
{
|
||||
if (ImPlot::BeginDragDropTargetAxis(y))
|
||||
{
|
||||
if (const ImGuiPayload* Payload = ImGui::AcceptDragDropPayload("DragAndDrop"))
|
||||
{
|
||||
if (FCogDebugPlotEntry* Plot = FCogDebugPlot::FindPlot(FName((const char*)Payload->Data)))
|
||||
{
|
||||
Plot->AssignAxis(PlotIndex, y);
|
||||
}
|
||||
}
|
||||
ImPlot::EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Allow the legend to be a drag and drop target
|
||||
//-------------------------------------------------------
|
||||
if (ImPlot::BeginDragDropTargetLegend())
|
||||
{
|
||||
if (const ImGuiPayload* Payload = ImGui::AcceptDragDropPayload("DragAndDrop"))
|
||||
{
|
||||
if (FCogDebugPlotEntry* Plot = FCogDebugPlot::FindPlot(FName((const char*)Payload->Data)))
|
||||
{
|
||||
Plot->AssignAxis(PlotIndex, ImAxis_Y1);
|
||||
}
|
||||
}
|
||||
ImPlot::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
}
|
||||
ImPlot::EndSubplots();
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "CogEngineWindow_Scalability.h"
|
||||
|
||||
#include "imgui.h"
|
||||
#include "CogImguiHelper.h"
|
||||
#include "CogWindowWidgets.h"
|
||||
#include "Engine/Engine.h"
|
||||
|
||||
|
||||
#define SCALABILITY_NUM_LEVELS 5
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Scalability::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window can be used to configure the rendering quality."
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Scalability::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
Scalability::FQualityLevels Levels = Scalability::GetQualityLevels();
|
||||
FString CurrentQualityName = Scalability::GetQualityLevelText(Levels.GetMinQualityLevel(), SCALABILITY_NUM_LEVELS).ToString();
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
if (ImGui::BeginCombo("Scalability", TCHAR_TO_ANSI(*CurrentQualityName)))
|
||||
{
|
||||
for (int32 i = 0; i < SCALABILITY_NUM_LEVELS; ++i)
|
||||
{
|
||||
FString QualityName = Scalability::GetQualityLevelText(i, SCALABILITY_NUM_LEVELS).ToString();
|
||||
if (ImGui::Selectable(TCHAR_TO_ANSI(*QualityName)))
|
||||
{
|
||||
Levels.SetFromSingleQualityLevel(i);
|
||||
Scalability::SetQualityLevels(Levels);
|
||||
|
||||
ImGui::LogToClipboard();
|
||||
ImGui::LogText("%s", TCHAR_TO_ANSI(*FString::Printf(TEXT("Setting Quality Level to %s"), *QualityName)));
|
||||
ImGui::LogFinish();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
bool Modified = false;
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderFloat("Resolution", &Levels.ResolutionQuality, 10.0f, 100.0f, "%0.f");
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderInt("View Distance", &Levels.ViewDistanceQuality, 0, SCALABILITY_NUM_LEVELS - 1);
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderInt("Anti Aliasing", &Levels.AntiAliasingQuality, 0, SCALABILITY_NUM_LEVELS - 1);
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderInt("Shadow", &Levels.ShadowQuality, 0, SCALABILITY_NUM_LEVELS - 1);
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderInt("Global Illumination", &Levels.GlobalIlluminationQuality, 0, SCALABILITY_NUM_LEVELS - 1);
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderInt("Reflection", &Levels.ReflectionQuality, 0, SCALABILITY_NUM_LEVELS - 1);
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderInt("Post Process", &Levels.PostProcessQuality, 0, SCALABILITY_NUM_LEVELS - 1);
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderInt("Texture", &Levels.TextureQuality, 0, SCALABILITY_NUM_LEVELS - 1);
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderInt("Effects", &Levels.EffectsQuality, 0, SCALABILITY_NUM_LEVELS - 1);
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderInt("Foliage", &Levels.FoliageQuality, 0, SCALABILITY_NUM_LEVELS - 1);
|
||||
|
||||
FCogWindowWidgets::SetNextItemToShortWidth();
|
||||
Modified |= ImGui::SliderInt("Shading", &Levels.ShadingQuality, 0, SCALABILITY_NUM_LEVELS - 1);
|
||||
|
||||
if (Modified)
|
||||
{
|
||||
Scalability::SetQualityLevels(Levels);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,521 @@
|
||||
#include "CogEngineWindow_Selection.h"
|
||||
|
||||
#include "CogDebugDraw.h"
|
||||
#include "CogImguiModule.h"
|
||||
#include "CogWindowManager.h"
|
||||
#include "CogWindowWidgets.h"
|
||||
#include "EngineUtils.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "imgui.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Selection::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window can be used to select an actor either by picking an actor in the world, "
|
||||
"or by selecting an actor in the actor list. "
|
||||
"The actor list can be filtered by actor type (Actor, Character, etc). "
|
||||
"The current selection is used by various debug windows to filter out their content"
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogEngineWindow_Selection::UCogEngineWindow_Selection()
|
||||
{
|
||||
bHasMenu = true;
|
||||
SubClasses = { AActor::StaticClass(), ACharacter::StaticClass() };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Selection::ToggleSelectionMode()
|
||||
{
|
||||
if (bSelectionModeActive)
|
||||
{
|
||||
DeactivateSelectionMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
ActivateSelectionMode();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Selection::ActivateSelectionMode()
|
||||
{
|
||||
bSelectionModeActive = true;
|
||||
bImGuiHadInputBeforeEnteringSelectionMode = FCogImguiModule::Get().GetEnableInput();
|
||||
FCogImguiModule::Get().SetEnableInput(true);
|
||||
GetOwner()->SetHideAllWindows(true);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void UCogEngineWindow_Selection::HackWaitInputRelease()
|
||||
{
|
||||
WaitInputReleased = 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Selection::DeactivateSelectionMode()
|
||||
{
|
||||
bSelectionModeActive = false;
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// We can enter selection mode by a command, and imgui might not have the input focus
|
||||
// When in selection mode we need imgui to have the input focus
|
||||
// When leaving selection mode we want to leave it as is was before
|
||||
//--------------------------------------------------------------------------------------------
|
||||
if (bImGuiHadInputBeforeEnteringSelectionMode == false)
|
||||
{
|
||||
FCogImguiModule::Get().SetEnableInput(false);
|
||||
}
|
||||
|
||||
GetOwner()->SetHideAllWindows(false);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Selection::RenderTick(float DeltaTime)
|
||||
{
|
||||
Super::RenderTick(DeltaTime);
|
||||
|
||||
if (FCogDebugSettings::GetSelection() == nullptr)
|
||||
{
|
||||
FCogDebugSettings::SetSelection(GetLocalPlayerPawn());
|
||||
}
|
||||
|
||||
if (bSelectionModeActive)
|
||||
{
|
||||
TickSelectionMode();
|
||||
}
|
||||
|
||||
if (AActor* Actor = GetSelection())
|
||||
{
|
||||
if (Actor != GetLocalPlayerPawn())
|
||||
{
|
||||
DrawActorFrame(Actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Selection::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::MenuItem("Pick"))
|
||||
{
|
||||
ActivateSelectionMode();
|
||||
HackWaitInputRelease();
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
DrawSelectionCombo();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogEngineWindow_Selection::DrawSelectionCombo()
|
||||
{
|
||||
bool SelectionChanged = false;
|
||||
|
||||
APawn* LocalPlayerPawn = GetLocalPlayerPawn();
|
||||
|
||||
//------------------------
|
||||
// Actor Class Combo
|
||||
//------------------------
|
||||
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
if (ImGui::BeginCombo("##SelectionType", TCHAR_TO_ANSI(*GetNameSafe(SelectedSubClass))))
|
||||
{
|
||||
for (TSubclassOf<AActor> ItSubClass : SubClasses)
|
||||
{
|
||||
if (ImGui::Selectable(TCHAR_TO_ANSI(*GetNameSafe(ItSubClass)), false))
|
||||
{
|
||||
SelectedSubClass = ItSubClass;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
//------------------------
|
||||
// Actor List
|
||||
//------------------------
|
||||
ImGui::BeginChild("ActorList", ImVec2(-1, -1), false);
|
||||
|
||||
TArray<AActor*> Actors;
|
||||
for (TActorIterator<AActor> It(GetWorld(), SelectedSubClass); It; ++It)
|
||||
{
|
||||
AActor* Actor = *It;
|
||||
Actors.Add(Actor);
|
||||
}
|
||||
|
||||
ImGuiListClipper Clipper;
|
||||
Clipper.Begin(Actors.Num());
|
||||
while (Clipper.Step())
|
||||
{
|
||||
for (int32 i = Clipper.DisplayStart; i < Clipper.DisplayEnd; i++)
|
||||
{
|
||||
AActor* Actor = Actors[i];
|
||||
if (Actor == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, Actor == LocalPlayerPawn ? IM_COL32(255, 255, 0, 255) : IM_COL32(255, 255, 255, 255));
|
||||
|
||||
bool bIsSelected = Actor == FCogDebugSettings::GetSelection();
|
||||
const FString ActorName = GetNameSafe(Actor);
|
||||
if (ImGui::Selectable(TCHAR_TO_ANSI(*ActorName), bIsSelected))
|
||||
{
|
||||
FCogDebugSettings::SetSelection(Actor);
|
||||
SelectionChanged = true;
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
DrawActorContextMenu(Actor);
|
||||
|
||||
//------------------------
|
||||
// Draw Frame
|
||||
//------------------------
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
DrawActorFrame(Actor);
|
||||
}
|
||||
|
||||
if (bIsSelected)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
Clipper.End();
|
||||
ImGui::EndChild();
|
||||
|
||||
return SelectionChanged;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void UCogEngineWindow_Selection::DrawActorContextMenu(AActor* Actor)
|
||||
{
|
||||
//------------------------
|
||||
// ContextMenu
|
||||
//------------------------
|
||||
ImGui::SetNextWindowSize(ImVec2(FCogWindowWidgets::GetFontWidth() * 20, 0));
|
||||
if (ImGui::BeginPopupContextItem())
|
||||
{
|
||||
if (ImGui::Button("Reset Selection", ImVec2(-1, 0)))
|
||||
{
|
||||
ImGui::CloseCurrentPopup();
|
||||
FCogDebugSettings::SetSelection(GetLocalPlayerPawn());
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Reset the selection to the controlled actor.");
|
||||
}
|
||||
|
||||
if (APawn* Pawn = Cast<APawn>(Actor))
|
||||
{
|
||||
if (ImGui::Button("Possess", ImVec2(-1, 0)))
|
||||
{
|
||||
if (ACogEngineReplicator* Replicator = ACogEngineReplicator::GetLocalReplicator(*GetWorld()))
|
||||
{
|
||||
Replicator->Server_Possess(Pawn);
|
||||
}
|
||||
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Possess this pawn.");
|
||||
}
|
||||
|
||||
if (ImGui::Button("Reset Possession", ImVec2(-1, 0)))
|
||||
{
|
||||
if (ACogEngineReplicator* Replicator = ACogEngineReplicator::GetLocalReplicator(*GetWorld()))
|
||||
{
|
||||
Replicator->Server_ResetPossession();
|
||||
}
|
||||
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Reset pawn.");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Selection::TickSelectionMode()
|
||||
{
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right))
|
||||
{
|
||||
DeactivateSelectionMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AnyWindow))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
APlayerController* PlayerController = GetLocalPlayerController();
|
||||
if (PlayerController == nullptr)
|
||||
{
|
||||
DeactivateSelectionMode();
|
||||
return;
|
||||
}
|
||||
|
||||
ImDrawList* DrawList = ImGui::GetBackgroundDrawList();
|
||||
DrawList->AddRect(ImVec2(0, 0), ImGui::GetIO().DisplaySize, IM_COL32(255, 0, 0, 128), 0.0f, 0, 20.0f);
|
||||
FCogWindowWidgets::AddTextWithShadow(DrawList, ImVec2(20, 20), IM_COL32(255, 255, 255, 255), "Picking Mode. \n[LMB] Pick \n[RMB] Cancel");
|
||||
|
||||
AActor* HoveredActor = nullptr;
|
||||
|
||||
FVector WorldOrigin, WorldDirection;
|
||||
if (UGameplayStatics::DeprojectScreenToWorld(PlayerController, FCogImguiHelper::ToVector2D(ImGui::GetMousePos()), WorldOrigin, WorldDirection))
|
||||
{
|
||||
TArray<AActor*> IgnoreList;
|
||||
|
||||
FHitResult HitResult;
|
||||
if (UKismetSystemLibrary::LineTraceSingle(GetWorld(), WorldOrigin, WorldOrigin + WorldDirection * 10000, TraceType, false, IgnoreList, EDrawDebugTrace::None, HitResult, true))
|
||||
{
|
||||
if (HitResult.GetActor() != nullptr)
|
||||
{
|
||||
if (HitResult.GetActor()->GetClass()->IsChildOf(SelectedSubClass))
|
||||
{
|
||||
HoveredActor = HitResult.GetActor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HoveredActor != nullptr)
|
||||
{
|
||||
DrawActorFrame(HoveredActor);
|
||||
}
|
||||
|
||||
if (bSelectionModeActive)
|
||||
{
|
||||
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||
{
|
||||
if (WaitInputReleased == 0)
|
||||
{
|
||||
if (HoveredActor != nullptr)
|
||||
{
|
||||
FCogDebugSettings::SetSelection(HoveredActor);
|
||||
}
|
||||
|
||||
DeactivateSelectionMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
WaitInputReleased--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Selection::DrawActorFrame(const AActor* Actor)
|
||||
{
|
||||
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
|
||||
if (PlayerController == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImDrawList* DrawList = ImGui::GetBackgroundDrawList();
|
||||
|
||||
FVector BoxOrigin, BoxExtent;
|
||||
|
||||
bool PrimitiveFound = false;
|
||||
FBox Bounds(ForceInit);
|
||||
|
||||
if (const UPrimitiveComponent* PrimitiveComponent = Cast<UPrimitiveComponent>(Actor->GetRootComponent()))
|
||||
{
|
||||
PrimitiveFound = true;
|
||||
Bounds += PrimitiveComponent->Bounds.GetBox();
|
||||
}
|
||||
else
|
||||
{
|
||||
Actor->ForEachComponent<UPrimitiveComponent>(true, [&](const UPrimitiveComponent* InPrimComp)
|
||||
{
|
||||
if (InPrimComp->IsRegistered() && InPrimComp->IsCollisionEnabled())
|
||||
{
|
||||
Bounds += InPrimComp->Bounds.GetBox();
|
||||
PrimitiveFound = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (PrimitiveFound)
|
||||
{
|
||||
Bounds.GetCenterAndExtents(BoxOrigin, BoxExtent);
|
||||
}
|
||||
else
|
||||
{
|
||||
BoxOrigin = Actor->GetActorLocation();
|
||||
BoxExtent = FVector(50.f, 50.f, 50.f);
|
||||
}
|
||||
|
||||
FVector2D ScreenPosMin, ScreenPosMax;
|
||||
if (ComputeBoundingBoxScreenPosition(PlayerController, BoxOrigin, BoxExtent, ScreenPosMin, ScreenPosMax))
|
||||
{
|
||||
const ImU32 Color = (Actor == GetSelection()) ? IM_COL32(255, 255, 255, 255) : IM_COL32(255, 255, 255, 128);
|
||||
DrawList->AddRect(FCogImguiHelper::ToImVec2(ScreenPosMin), FCogImguiHelper::ToImVec2(ScreenPosMax), Color, 0.0f, 0, 1.0f);
|
||||
FCogWindowWidgets::AddTextWithShadow(DrawList, FCogImguiHelper::ToImVec2(ScreenPosMin + FVector2D(0, -14.0f)), Color, TCHAR_TO_ANSI(*Actor->GetName()));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
bool UCogEngineWindow_Selection::ComputeBoundingBoxScreenPosition(const APlayerController* PlayerController, const FVector& Origin, const FVector& Extent, FVector2D& Min, FVector2D& Max)
|
||||
{
|
||||
FVector Corners[8];
|
||||
Corners[0].Set(-Extent.X, -Extent.Y, -Extent.Z); // - - -
|
||||
Corners[1].Set(Extent.X, -Extent.Y, -Extent.Z); // + - -
|
||||
Corners[2].Set(-Extent.X, Extent.Y, -Extent.Z); // - + -
|
||||
Corners[3].Set(-Extent.X, -Extent.Y, Extent.Z); // - - +
|
||||
Corners[4].Set(Extent.X, Extent.Y, -Extent.Z); // + + -
|
||||
Corners[5].Set(Extent.X, -Extent.Y, Extent.Z); // + - +
|
||||
Corners[6].Set(-Extent.X, Extent.Y, Extent.Z); // - + +
|
||||
Corners[7].Set(Extent.X, Extent.Y, Extent.Z); // + + +
|
||||
|
||||
Min.X = FLT_MAX;
|
||||
Min.Y = FLT_MAX;
|
||||
Max.X = -FLT_MAX;
|
||||
Max.Y = -FLT_MAX;
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
FVector2D ScreenLocation;
|
||||
if (PlayerController->ProjectWorldLocationToScreen(Origin + Corners[i], ScreenLocation, false) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Min.X = FMath::Min(ScreenLocation.X, Min.X);
|
||||
Min.Y = FMath::Min(ScreenLocation.Y, Min.Y);
|
||||
Max.X = FMath::Max(ScreenLocation.X, Max.X);
|
||||
Max.Y = FMath::Max(ScreenLocation.Y, Max.Y);
|
||||
}
|
||||
|
||||
// Prevent getting large values when the camera get close to the target
|
||||
ImVec2 DisplaySize = ImGui::GetIO().DisplaySize;
|
||||
Min.X = FMath::Max(-DisplaySize.x, Min.X);
|
||||
Min.Y = FMath::Max(-DisplaySize.y, Min.Y);
|
||||
Max.X = FMath::Min(DisplaySize.x * 2, Max.X);
|
||||
Max.Y = FMath::Min(DisplaySize.y * 2, Max.Y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Selection::DrawMainMenuWidget(bool Draw, float& Width)
|
||||
{
|
||||
const float PickButtonWidth = FCogWindowWidgets::GetFontWidth() * 6;
|
||||
const float SelectionButtonWidth = FCogWindowWidgets::GetFontWidth() * 30;
|
||||
const float ResetButtonWidth = FCogWindowWidgets::GetFontWidth() * 2;
|
||||
Width = PickButtonWidth + SelectionButtonWidth + ResetButtonWidth;
|
||||
|
||||
if (Draw == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("SelectionPopup"))
|
||||
{
|
||||
ImGui::BeginChild("Popup", ImVec2(Width, FCogWindowWidgets::GetFontWidth() * 40), false);
|
||||
|
||||
if (DrawSelectionCombo())
|
||||
{
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// Pick Button
|
||||
//-----------------------------------
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0));
|
||||
|
||||
if (ImGui::Button("Pick", ImVec2(PickButtonWidth, 0)))
|
||||
{
|
||||
ActivateSelectionMode();
|
||||
HackWaitInputRelease();
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Enter picking mode to select an actor on screen.");
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(1);
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
AActor* GlobalSelection = FCogDebugSettings::GetSelection();
|
||||
|
||||
//-----------------------------------
|
||||
// Selection
|
||||
//-----------------------------------
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4((ImGuiCol_FrameBg)));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4((ImGuiCol_FrameBgActive)));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4((ImGuiCol_FrameBgHovered)));
|
||||
ImGui::SameLine();
|
||||
FString SelectionName = GetNameSafe(GlobalSelection);
|
||||
|
||||
if (ImGui::Button(TCHAR_TO_ANSI(*SelectionName), ImVec2(SelectionButtonWidth, 0)))
|
||||
{
|
||||
ImGui::OpenPopup("SelectionPopup");
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Current Selection: %s", TCHAR_TO_ANSI(*SelectionName));
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
DrawActorContextMenu(GlobalSelection);
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// Reset Button
|
||||
//-----------------------------------
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4((ImGuiCol_FrameBg)));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4((ImGuiCol_FrameBgActive)));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4((ImGuiCol_FrameBgHovered)));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("X", ImVec2(ResetButtonWidth, 0)))
|
||||
{
|
||||
FCogDebugSettings::SetSelection(nullptr);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Reset the selection to the controlled actor.");
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleVar(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
#include "CogEngineWindow_Skeleton.h"
|
||||
|
||||
#include "CogDebugSettings.h"
|
||||
#include "Components/LineBatchComponent.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogEngineWindow_Skeleton::UCogEngineWindow_Skeleton()
|
||||
{
|
||||
bHasMenu = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Skeleton::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window display the bone hierarchy and the skeleton debug draw of the selected actor if it has a Skeletal Mesh. "
|
||||
"Mouse over a bone to highlight it. "
|
||||
"Right click a bone to access more debug display. "
|
||||
"Use the [Ctrl] key to toggle the bone debug draw recursively. "
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Skeleton::OnSelectionChanged(AActor* OldSelection, AActor* NewSelection)
|
||||
{
|
||||
RefreshSkeleton();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Skeleton::RenderTick(float DeltaTime)
|
||||
{
|
||||
Super::RenderTick(DeltaTime);
|
||||
|
||||
if (GetIsVisible() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DrawSkeleton();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Skeleton::RefreshSkeleton()
|
||||
{
|
||||
CurrentSkeleton = nullptr;
|
||||
BonesInfos.Empty();
|
||||
|
||||
|
||||
AActor* Selection = GetSelection();
|
||||
if (Selection == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentSkeleton = Selection->FindComponentByClass<USkeletalMeshComponent>();
|
||||
if (CurrentSkeleton == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const FTransform WorldTransform = CurrentSkeleton->GetComponentTransform();
|
||||
const TArray<FTransform>& ComponentSpaceTransforms = CurrentSkeleton->GetComponentSpaceTransforms();
|
||||
BonesInfos.SetNum(ComponentSpaceTransforms.Num());
|
||||
|
||||
for (int32 BoneIndex = 0; BoneIndex < ComponentSpaceTransforms.Num(); ++BoneIndex)
|
||||
{
|
||||
const FReferenceSkeleton& ReferenceSkeleton = CurrentSkeleton->GetSkeletalMeshAsset()->GetRefSkeleton();
|
||||
|
||||
FBoneInfo& CurrentBoneInfo = BonesInfos[BoneIndex];
|
||||
CurrentBoneInfo.Index = BoneIndex;
|
||||
CurrentBoneInfo.Name = ReferenceSkeleton.GetBoneName(BoneIndex);
|
||||
const FTransform Transform = ComponentSpaceTransforms[BoneIndex] * WorldTransform;
|
||||
CurrentBoneInfo.LastLocation = Transform.GetLocation();
|
||||
CurrentBoneInfo.IsSecondaryBone = FCogDebugSettings::IsSecondarySkeletonBone(CurrentBoneInfo.Name);
|
||||
CurrentBoneInfo.ShowBone = !(HideSecondaryBones && CurrentBoneInfo.IsSecondaryBone);
|
||||
|
||||
const int32 ParentIndex = ReferenceSkeleton.GetParentIndex(BoneIndex);
|
||||
if (ParentIndex != INDEX_NONE)
|
||||
{
|
||||
FBoneInfo& ParentBoneInfo = BonesInfos[ParentIndex];
|
||||
ParentBoneInfo.Children.Add(BoneIndex);
|
||||
CurrentBoneInfo.ParentIndex = ParentIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Skeleton::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("Options"))
|
||||
{
|
||||
ImGui::Checkbox("Hide secondary bones", &HideSecondaryBones);
|
||||
ImGui::Separator();
|
||||
ImGui::Checkbox("Show bones", &ShowBones);
|
||||
ImGui::Checkbox("Show name", &ShowNames);
|
||||
ImGui::Checkbox("Show axes", &ShowAxes);
|
||||
ImGui::Checkbox("Show local velocity", &ShowVelocities);
|
||||
ImGui::Checkbox("Show trajectories", &ShowTrajectories);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
FCogWindowWidgets::MenuSearchBar(Filter);
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, FCogWindowWidgets::GetFontWidth());
|
||||
|
||||
HoveredBoneIndex = INDEX_NONE;
|
||||
DrawBoneEntry(0, false);
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Skeleton::DrawBoneEntry(int32 BoneIndex, bool OpenAllChildren)
|
||||
{
|
||||
if (BonesInfos.IsValidIndex(BoneIndex) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FBoneInfo& BoneInfo = BonesInfos[BoneIndex];
|
||||
|
||||
if (HideSecondaryBones && BoneInfo.IsSecondaryBone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const char* BoneName = TCHAR_TO_ANSI(*BoneInfo.Name.ToString());
|
||||
const bool ShowNode = Filter.PassFilter(BoneName);
|
||||
bool OpenChildren = false;
|
||||
|
||||
if (ShowNode)
|
||||
{
|
||||
ImGui::PushID(BoneIndex);
|
||||
|
||||
if (OpenAllChildren)
|
||||
{
|
||||
ImGui::SetNextItemOpen(true, ImGuiCond_Always);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// TreeNode
|
||||
//------------------------
|
||||
if (BoneInfo.Children.Num() > 0 && Filter.IsActive() == false)
|
||||
{
|
||||
OpenChildren = ImGui::TreeNodeEx("##Bone", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::TreeNodeEx("##Bone", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
}
|
||||
|
||||
const bool IsControlDown = ImGui::GetCurrentContext()->IO.KeyCtrl;
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left) && IsControlDown)
|
||||
{
|
||||
OpenAllChildren = true;
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// ContextMenu
|
||||
//------------------------
|
||||
if (ImGui::BeginPopupContextItem())
|
||||
{
|
||||
ImGui::Checkbox("Show Name", &BoneInfo.ShowName);
|
||||
ImGui::Checkbox("Show Axe", &BoneInfo.ShowAxes);
|
||||
ImGui::Checkbox("Show Local Velocity", &BoneInfo.ShowLocalVelocity);
|
||||
ImGui::Checkbox("Show Trajectory", &BoneInfo.ShowTrajectory);
|
||||
ImGui::EndPopup();
|
||||
HoveredBoneIndex = BoneIndex;
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// Tooltip
|
||||
//------------------------
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::Checkbox("Show Name", &BoneInfo.ShowName);
|
||||
ImGui::Checkbox("Show Axe", &BoneInfo.ShowAxes);
|
||||
ImGui::Checkbox("Show Local Velocity", &BoneInfo.ShowLocalVelocity);
|
||||
ImGui::Checkbox("Show Trajectory", &BoneInfo.ShowTrajectory);
|
||||
ImGui::EndDisabled();
|
||||
ImGui::EndTooltip();
|
||||
HoveredBoneIndex = BoneIndex;
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// Checkbox
|
||||
//------------------------
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Checkbox("##Visible", &BoneInfo.ShowBone))
|
||||
{
|
||||
if (IsControlDown)
|
||||
{
|
||||
SetChildrenVisibility(BoneIndex, BoneInfo.ShowBone);
|
||||
}
|
||||
|
||||
if (BoneInfo.ShowBone == false)
|
||||
{
|
||||
BoneInfo.ShowName = false;
|
||||
BoneInfo.ShowAxes = false;
|
||||
BoneInfo.ShowLocalVelocity = false;
|
||||
BoneInfo.ShowTrajectory = false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool HasCustomVisiblity = BoneInfo.ShowName || BoneInfo.ShowAxes || BoneInfo.ShowLocalVelocity || BoneInfo.ShowTrajectory;
|
||||
if (HasCustomVisiblity)
|
||||
{
|
||||
BoneInfo.ShowBone = true;
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// Name
|
||||
//------------------------
|
||||
ImGui::SameLine();
|
||||
ImVec4 NameColor = HasCustomVisiblity ? ImVec4(1.0f, 1.0f, 0.0f, 1.0f) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
ImGui::TextColored(NameColor, "%s", BoneName);
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// Children
|
||||
//------------------------
|
||||
if (OpenChildren || Filter.IsActive())
|
||||
{
|
||||
for (int32 ChildIndex : BoneInfo.Children)
|
||||
{
|
||||
DrawBoneEntry(ChildIndex, OpenAllChildren);
|
||||
}
|
||||
}
|
||||
|
||||
if (ShowNode)
|
||||
{
|
||||
if (OpenChildren && ShowNode)
|
||||
{
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Skeleton::SetChildrenVisibility(int32 BoneIndex, bool IsVisible)
|
||||
{
|
||||
if (BonesInfos.IsValidIndex(BoneIndex) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FBoneInfo& BoneInfo = BonesInfos[BoneIndex];
|
||||
for (int32 ChildIndex : BoneInfo.Children)
|
||||
{
|
||||
FBoneInfo& ChildBoneInfo = BonesInfos[ChildIndex];
|
||||
ChildBoneInfo.ShowBone = IsVisible && !(HideSecondaryBones && ChildBoneInfo.IsSecondaryBone);
|
||||
SetChildrenVisibility(ChildIndex, IsVisible);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Skeleton::DrawSkeleton()
|
||||
{
|
||||
if (CurrentSkeleton == nullptr || CurrentSkeleton->GetWorld() == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const UWorld* World = CurrentSkeleton->GetWorld();
|
||||
const FTransform WorldTransform = CurrentSkeleton->GetComponentTransform();
|
||||
const TArray<FTransform>& ComponentSpaceTransforms = CurrentSkeleton->GetComponentSpaceTransforms();
|
||||
|
||||
for (int32 BoneIndex = 0; BoneIndex < ComponentSpaceTransforms.Num(); ++BoneIndex)
|
||||
{
|
||||
FBoneInfo& BoneInfo = BonesInfos[BoneIndex];
|
||||
|
||||
const FTransform Transform = ComponentSpaceTransforms[BoneIndex] * WorldTransform;
|
||||
FVector BoneLocation = Transform.GetLocation();
|
||||
FRotator BoneRotation = FRotator(Transform.GetRotation());
|
||||
|
||||
FVector ParentLocation;
|
||||
if (BoneInfo.ParentIndex >= 0)
|
||||
{
|
||||
ParentLocation = (ComponentSpaceTransforms[BoneInfo.ParentIndex] * WorldTransform).GetLocation();
|
||||
}
|
||||
else
|
||||
{
|
||||
ParentLocation = WorldTransform.GetLocation();
|
||||
}
|
||||
|
||||
if (BoneInfo.ShowBone)
|
||||
{
|
||||
const bool IsHovered = BoneIndex == HoveredBoneIndex;
|
||||
|
||||
if (ShowBones)
|
||||
{
|
||||
::DrawDebugLine(World, ParentLocation, BoneLocation, IsHovered ? FColor::Red : FColor::White, false, 0.0f, 1, FCogDebugSettings::GetDebugThickness(IsHovered ? 0.5f : 0.0f));
|
||||
::DrawDebugPoint(World, BoneLocation, FCogDebugSettings::GetDebugThickness(IsHovered ? 6.0f : 4.0f), IsHovered ? FColor::Red : FColor::White, false, 0.0f, 1);
|
||||
}
|
||||
|
||||
if (ShowNames || BoneInfo.ShowName || IsHovered)
|
||||
{
|
||||
::DrawDebugString(World, BoneLocation, BoneInfo.Name.ToString(), nullptr, IsHovered ? FColor::Red : FColor::White, 0.0f, true, FCogDebugSettings::TextSize);
|
||||
}
|
||||
|
||||
if (ShowAxes || BoneInfo.ShowAxes)
|
||||
{
|
||||
::DrawDebugCoordinateSystem(
|
||||
World,
|
||||
BoneLocation,
|
||||
BoneRotation,
|
||||
10.0f * FCogDebugSettings::AxesScale,
|
||||
false,
|
||||
0.0f,
|
||||
1,
|
||||
FCogDebugSettings::GetDebugThickness(0.0f));
|
||||
}
|
||||
|
||||
if (ShowVelocities || BoneInfo.ShowLocalVelocity)
|
||||
{
|
||||
if (const FBodyInstance* ParentBodyInstance = CurrentSkeleton->GetBodyInstance(BoneInfo.Name))
|
||||
{
|
||||
DrawDebugDirectionalArrow(
|
||||
World,
|
||||
BoneLocation,
|
||||
BoneLocation + ParentBodyInstance->GetUnrealWorldVelocity() * World->GetDeltaSeconds(),
|
||||
FCogDebugSettings::ArrowSize,
|
||||
FCogDebugSettings::ModulateDebugColor(World, FColor::Cyan),
|
||||
FCogDebugSettings::GetDebugPersistent(true),
|
||||
FCogDebugSettings::GetDebugDuration(true),
|
||||
0,
|
||||
FCogDebugSettings::GetDebugThickness(0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
if (ShowTrajectories || BoneInfo.ShowTrajectory)
|
||||
{
|
||||
const FColor Color = FCogDebugSettings::ModulateDebugColor(World, FColor::Yellow);
|
||||
DrawDebugLine(
|
||||
World,
|
||||
BoneInfo.LastLocation,
|
||||
BoneLocation,
|
||||
Color,
|
||||
FCogDebugSettings::GetDebugPersistent(true),
|
||||
FCogDebugSettings::GetDebugDuration(true),
|
||||
0,
|
||||
FCogDebugSettings::GetDebugThickness(0.0f));
|
||||
|
||||
DrawDebugPoint(
|
||||
World,
|
||||
BoneLocation,
|
||||
FCogDebugSettings::GetDebugThickness(2.0f),
|
||||
Color,
|
||||
FCogDebugSettings::GetDebugPersistent(true),
|
||||
FCogDebugSettings::GetDebugDuration(true),
|
||||
0);
|
||||
}
|
||||
|
||||
BoneInfo.LastLocation = BoneLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
#include "CogEngineWindow_Spawns.h"
|
||||
|
||||
#include "CogEngineDataAsset.h"
|
||||
#include "CogEngineReplicator.h"
|
||||
#include "CogImguiHelper.h"
|
||||
#include "CogWindowWidgets.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Spawns::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window can be used to spawn new actors in the world. "
|
||||
"The spawn list can be configured in the '%s' data asset. "
|
||||
, TCHAR_TO_ANSI(*GetNameSafe(Asset.Get()))
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Spawns::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
if (Asset == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const FCogEngineSpawnGroup& SpawnGroup : Asset->SpawnGroups)
|
||||
{
|
||||
RenderSpawnGroup(SpawnGroup);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Spawns::RenderSpawnGroup(const FCogEngineSpawnGroup& SpawnGroup)
|
||||
{
|
||||
int32 GroupIndex = 0;
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, IM_COL32(66, 66, 66, 79));
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, IM_COL32(62, 62, 62, 204));
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive, IM_COL32(86, 86, 86, 255));
|
||||
|
||||
if (ImGui::CollapsingHeader(TCHAR_TO_ANSI(*SpawnGroup.Name), ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::PushID(GroupIndex);
|
||||
|
||||
const bool PushColor = (SpawnGroup.Color != FColor::Transparent);
|
||||
if (PushColor)
|
||||
{
|
||||
FCogWindowWidgets::PushBackColor(FCogImguiHelper::ToImVec4(SpawnGroup.Color));
|
||||
}
|
||||
|
||||
static int32 SelectedAssetIndex = -1;
|
||||
int32 AssetIndex = 0;
|
||||
|
||||
for (const FCogEngineSpawnEntry& SpawnEntry : SpawnGroup.Spawns)
|
||||
{
|
||||
if (RenderSpawnAsset(SpawnEntry, SelectedAssetIndex == GroupIndex))
|
||||
{
|
||||
SelectedAssetIndex = AssetIndex;
|
||||
}
|
||||
|
||||
AssetIndex++;
|
||||
}
|
||||
|
||||
if (PushColor)
|
||||
{
|
||||
FCogWindowWidgets::PopBackColor();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
GroupIndex++;
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogEngineWindow_Spawns::RenderSpawnAsset(const FCogEngineSpawnEntry& SpawnEntry, bool IsLastSelected)
|
||||
{
|
||||
bool IsPressed = false;
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, IsLastSelected ? ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive) : ImGui::GetStyleColorVec4(ImGuiCol_Button));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
|
||||
|
||||
FString EntryName;
|
||||
if (SpawnEntry.Asset != nullptr)
|
||||
{
|
||||
EntryName = SpawnEntry.Asset->GetName();
|
||||
}
|
||||
else
|
||||
{
|
||||
EntryName = GetNameSafe(SpawnEntry.Class);
|
||||
}
|
||||
|
||||
if (ImGui::Button(TCHAR_TO_ANSI(*EntryName), ImVec2(-1, 0)))
|
||||
{
|
||||
if (ACogEngineReplicator* Replicator = ACogEngineReplicator::GetLocalReplicator(*GetWorld()))
|
||||
{
|
||||
Replicator->Server_Spawn(SpawnEntry);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(1);
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
return IsPressed;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
#include "CogEngineWindow_Stats.h"
|
||||
|
||||
#include "Engine/Engine.h"
|
||||
#include "Engine/NetConnection.h"
|
||||
#include "GameFramework/PlayerState.h"
|
||||
|
||||
ImVec4 StatRedColor(1.0f, 0.4f, 0.3f, 1.0f);
|
||||
ImVec4 StatOrangeColor(1.0f, 0.7f, 0.4f, 1.0f);
|
||||
ImVec4 StatGreenColor(0.5f, 1.0f, 0.6f, 1.0f);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Stats::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window displays engine stats such as FPS, Ping, Packet Loss. "
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Stats::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
extern ENGINE_API float GAverageFPS;
|
||||
ImGui::Text("FPS ");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(GetFpsColor(GAverageFPS), "%0.0f", GAverageFPS);
|
||||
|
||||
if (const APlayerController* PlayerController = GetLocalPlayerController())
|
||||
{
|
||||
if (const APlayerState* PlayerState = PlayerController->GetPlayerState<APlayerState>())
|
||||
{
|
||||
const float Ping = PlayerState->GetPingInMilliseconds();
|
||||
ImGui::Text("Ping ");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(GetPingColor(Ping), "%0.0fms", Ping);
|
||||
}
|
||||
|
||||
if (UNetConnection* Connection = PlayerController->GetNetConnection())
|
||||
{
|
||||
const float OutPacketLost = Connection->GetOutLossPercentage().GetAvgLossPercentage() * 100.0f;
|
||||
ImGui::Text("Packet Loss Out ");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(GetPacketLossColor(OutPacketLost), "%0.0f%%", OutPacketLost);
|
||||
|
||||
const float InPacketLost = Connection->GetInLossPercentage().GetAvgLossPercentage() * 100.0f;
|
||||
ImGui::Text("Packet Loss In ");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(GetPacketLossColor(InPacketLost), "%0.0f%%", InPacketLost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_Stats::DrawMainMenuWidget(bool Draw, float& Width)
|
||||
{
|
||||
Width = FCogWindowWidgets::GetFontWidth() * 25;
|
||||
|
||||
if (Draw == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
extern ENGINE_API float GAverageFPS;
|
||||
ImGui::TextColored(GetFpsColor(GAverageFPS), "%3dfps ", (int32)GAverageFPS);
|
||||
ImGui::SetItemTooltip("Frame Per Second");
|
||||
|
||||
if (const APlayerController* PlayerController = GetLocalPlayerController())
|
||||
{
|
||||
if (const APlayerState* PlayerState = PlayerController->GetPlayerState<APlayerState>())
|
||||
{
|
||||
const float Ping = PlayerState->GetPingInMilliseconds();
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(GetPingColor(Ping), "%3dms ", (int32)Ping);
|
||||
ImGui::SetItemTooltip("Ping");
|
||||
}
|
||||
|
||||
if (UNetConnection* Connection = PlayerController->GetNetConnection())
|
||||
{
|
||||
const float OutPacketLost = Connection->GetOutLossPercentage().GetAvgLossPercentage() * 100.0f;
|
||||
const float InPacketLost = Connection->GetInLossPercentage().GetAvgLossPercentage() * 100.0f;
|
||||
const float TotalPacketLost = OutPacketLost + InPacketLost;
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(GetPacketLossColor(TotalPacketLost), "%2d%% ", (int32)TotalPacketLost);
|
||||
ImGui::SetItemTooltip("Packet Loss");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImVec4 UCogEngineWindow_Stats::GetFpsColor(float Value, float Good /*= 50.0f*/, float Medium /*= 30.0f*/)
|
||||
{
|
||||
if (Value > Good)
|
||||
{
|
||||
return StatGreenColor;
|
||||
}
|
||||
|
||||
if (Value > Medium)
|
||||
{
|
||||
return StatOrangeColor;
|
||||
}
|
||||
|
||||
return StatRedColor;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImVec4 UCogEngineWindow_Stats::GetPingColor(float Value, float Good /*= 100.0f*/, float Medium /*= 200.0f*/)
|
||||
{
|
||||
if (Value > Medium)
|
||||
{
|
||||
return StatRedColor;
|
||||
}
|
||||
|
||||
if (Value > Good)
|
||||
{
|
||||
return StatOrangeColor;
|
||||
}
|
||||
|
||||
return StatGreenColor;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImVec4 UCogEngineWindow_Stats::GetPacketLossColor(float Value, float Good /*= 10.0f*/, float Medium /*= 20.0f*/)
|
||||
{
|
||||
if (Value > Medium)
|
||||
{
|
||||
return StatRedColor;
|
||||
}
|
||||
|
||||
if (Value > Good)
|
||||
{
|
||||
return StatOrangeColor;
|
||||
}
|
||||
|
||||
return StatGreenColor;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#include "CogEngineWindow_TimeScale.h"
|
||||
|
||||
#include "CogEngineReplicator.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "Engine/World.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_TimeScale::RenderHelp()
|
||||
{
|
||||
ImGui::Text(
|
||||
"This window can be used to change the game global time scale. "
|
||||
"If changed on a client the time scale is also modified on the game server. "
|
||||
);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCogEngineWindow_TimeScale::UCogEngineWindow_TimeScale()
|
||||
{
|
||||
TimingScales.Add(0.00f);
|
||||
TimingScales.Add(0.01f);
|
||||
TimingScales.Add(0.10f);
|
||||
TimingScales.Add(0.50f);
|
||||
TimingScales.Add(1.00f);
|
||||
TimingScales.Add(2.00f);
|
||||
TimingScales.Add(5.00f);
|
||||
TimingScales.Add(10.0f);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_TimeScale::RenderContent()
|
||||
{
|
||||
Super::RenderContent();
|
||||
|
||||
UWorld* World = GetWorld();
|
||||
if (World == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ACogEngineReplicator* Replicator = ACogEngineReplicator::GetLocalReplicator(*World);
|
||||
if (Replicator == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiStyle& Style = ImGui::GetStyle();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(Style.WindowPadding.x * 0.40f, (float)(int)(Style.WindowPadding.y * 0.60f)));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(Style.FramePadding.x * 0.40f, (float)(int)(Style.FramePadding.y * 0.60f)));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(Style.ItemSpacing.x * 0.30f, (float)(int)(Style.ItemSpacing.y * 0.60f)));
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, IM_COL32(255, 255, 255, 180));
|
||||
|
||||
for (float TimeScale : TimingScales)
|
||||
{
|
||||
DrawTimeButton(Replicator, TimeScale);
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(1);
|
||||
ImGui::PopStyleVar(3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogEngineWindow_TimeScale::DrawTimeButton(ACogEngineReplicator* Replicator, float Value)
|
||||
{
|
||||
const bool IsSelected = FMath::IsNearlyEqual(Replicator->GetTimeDilation(), Value, 0.0001f);
|
||||
if (IsSelected)
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(128, 128, 128, 50));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, IM_COL32(128, 128, 128, 100));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, IM_COL32(128, 128, 128, 150));
|
||||
}
|
||||
|
||||
const char* Text = TCHAR_TO_ANSI(*FString::Printf(TEXT("%g"), Value).Replace(TEXT("0."), TEXT(".")));
|
||||
if (ImGui::Button(Text, ImVec2(3.5f * FCogWindowWidgets::GetFontWidth(), 0)))
|
||||
{
|
||||
Replicator->Server_SetTimeDilation(Value);
|
||||
}
|
||||
|
||||
if (IsSelected)
|
||||
{
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::PopStyleColor(3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/DataAsset.h"
|
||||
#include "CogEngineDataAsset.generated.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
USTRUCT()
|
||||
struct COGENGINE_API FCogCollisionChannel
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
TEnumAsByte<ECollisionChannel> Channel = ECollisionChannel::ECC_WorldStatic;
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
FLinearColor Color = FLinearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
USTRUCT()
|
||||
struct COGENGINE_API FCogEngineSpawnEntry
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
TSubclassOf<AActor> Class;
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
TObjectPtr<const UObject> Asset = nullptr;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
USTRUCT()
|
||||
struct COGENGINE_API FCogEngineSpawnGroup
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
FString Name;
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
FLinearColor Color = FLinearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
TArray<FCogEngineSpawnEntry> Spawns;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS(Blueprintable)
|
||||
class COGENGINE_API UCogEngineDataAsset : public UPrimaryDataAsset
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UCogEngineDataAsset() {}
|
||||
|
||||
UPROPERTY(Category = "Spawns", EditAnywhere, meta = (TitleProperty = "Name"))
|
||||
TArray<FCogEngineSpawnGroup> SpawnGroups;
|
||||
|
||||
UPROPERTY(Category = "Collisions", EditAnywhere, meta = (TitleProperty = "Channel"))
|
||||
TArray<FCogCollisionChannel> Channels;
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class COGENGINE_API FCogEngineModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
static inline FCogEngineModule& Get() { return FModuleManager::LoadModuleChecked<FCogEngineModule>("CogEngine"); }
|
||||
|
||||
virtual void StartupModule() override;
|
||||
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
private:
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "UObject/Class.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "CogEngineReplicator.generated.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogEngine, Verbose, All);
|
||||
|
||||
class APlayerController;
|
||||
|
||||
using FCogEnineSpawnFunction = TFunction<void(const FCogEngineSpawnEntry& SpawnEntry)>;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS(NotBlueprintable, NotBlueprintType, notplaceable, noteditinlinenew, hidedropdown, Transient)
|
||||
class COGENGINE_API ACogEngineReplicator : public AActor
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
static ACogEngineReplicator* Spawn(APlayerController* Controller);
|
||||
|
||||
static ACogEngineReplicator* GetLocalReplicator(UWorld& World);
|
||||
|
||||
static void GetRemoteReplicators(UWorld& World, TArray<ACogEngineReplicator*>& Replicators);
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
APlayerController* GetPlayerController() const { return OwnerPlayerController.Get(); }
|
||||
|
||||
FCogEnineSpawnFunction GetSpawnFunction() const { return SpawnFunction; }
|
||||
|
||||
void SetSpawnFunction(FCogEnineSpawnFunction Value) { SpawnFunction = Value; }
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_Spawn(const FCogEngineSpawnEntry& SpawnEntry);
|
||||
|
||||
float GetTimeDilation() const { return TimeDilation; }
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_SetTimeDilation(float Value);
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_Possess(APawn* Pawn);
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_ResetPossession();
|
||||
|
||||
protected:
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_TimeDilation();
|
||||
|
||||
TObjectPtr<APlayerController> OwnerPlayerController;
|
||||
|
||||
uint32 bHasAuthority : 1;
|
||||
uint32 bIsLocal : 1;
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(ReplicatedUsing = OnRep_TimeDilation)
|
||||
float TimeDilation = 1.0f;
|
||||
|
||||
FCogEnineSpawnFunction SpawnFunction;
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_Audio.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_Audio : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
protected:
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_Collisions.generated.h"
|
||||
|
||||
class UCogEngineDataAsset;
|
||||
|
||||
UCLASS(Config = Cog)
|
||||
class COGENGINE_API UCogEngineWindow_Collisions : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UCogEngineWindow_Collisions();
|
||||
|
||||
const UCogEngineDataAsset* GetAsset() const { return Asset.Get(); }
|
||||
|
||||
void SetAsset(const UCogEngineDataAsset* Value);
|
||||
|
||||
private:
|
||||
|
||||
virtual void ResetConfig() override;
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
struct FChannel
|
||||
{
|
||||
bool IsValid = false;
|
||||
FColor Color;
|
||||
};
|
||||
|
||||
FChannel Channels[ECC_MAX];
|
||||
|
||||
UPROPERTY(Config)
|
||||
int32 ObjectTypesToQuery = 0;
|
||||
|
||||
UPROPERTY(Config)
|
||||
int32 ProfileIndex = 0;
|
||||
|
||||
UPROPERTY(Config)
|
||||
int QueryType = 0;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float QueryDistance = 5000.0f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float QueryThickness = 0.0f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool UseComplexCollisions = false;
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool ShowActorsNames = false;
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool ShowQuery = false;
|
||||
|
||||
UPROPERTY()
|
||||
TWeakObjectPtr<const UCogEngineDataAsset> Asset = nullptr;
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_DebugSettings.generated.h"
|
||||
|
||||
UCLASS(Config = Cog)
|
||||
class COGENGINE_API UCogEngineWindow_DebugSettings : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UCogEngineWindow_DebugSettings();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void ResetConfig() override;
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void PreSaveConfig() override;
|
||||
|
||||
virtual void PostInitProperties() override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool FilterBySelection = true;
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool Persistent = false;
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool TextShadow = true;
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool Fade2D = true;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float Duration = 3.0f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
int DepthPriority = 0;
|
||||
|
||||
UPROPERTY(Config)
|
||||
int Segments = 12;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float Thickness = 0.0f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float ServerThickness = 2.0f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float ServerColorMultiplier = 0.8f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float ArrowSize = 10.0f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float AxesScale = 1.0f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float GradientColorIntensity = 0.0f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float GradientColorSpeed = 2.0f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float TextSize = 1.0f;
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_ImGui.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_ImGui : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UCogEngineWindow_ImGui();
|
||||
|
||||
virtual void RenderTick(float DeltaTime) override;
|
||||
virtual void RenderContent() override;
|
||||
|
||||
private:
|
||||
|
||||
bool bShowImguiDemo = false;
|
||||
|
||||
bool bShowImguiPlot = false;
|
||||
|
||||
bool bShowImguiMetric = false;
|
||||
|
||||
bool bShowImguiDebugLog = false;
|
||||
|
||||
bool bShowImguiStyleEditor = false;
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_LogCategories.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_LogCategories : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UCogEngineWindow_LogCategories();
|
||||
|
||||
virtual void ResetConfig() override;
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_Metrics.generated.h"
|
||||
|
||||
struct FCogDebugMetricEntry;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS(Config = Cog)
|
||||
class COGENGINE_API UCogEngineWindow_Metrics : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UCogEngineWindow_Metrics();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void ResetConfig() override;
|
||||
|
||||
virtual void PostInitProperties() override;
|
||||
|
||||
virtual void PreSaveConfig() override;
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
virtual void RenderTick(float DeltaTime) override;
|
||||
|
||||
virtual void DrawMetric(FCogDebugMetricEntry& Metric);
|
||||
|
||||
virtual void DrawMetricRow(const char* Title, float MitigatedValue, float UnmitigatedValue, const ImVec4& Color);
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(Config)
|
||||
float MaxDurationSetting = 0.0f;
|
||||
|
||||
UPROPERTY(Config)
|
||||
float RestartDelaySetting = 5.0f;
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_NetEmulation.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_NetEmulation : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
virtual void DrawStats();
|
||||
|
||||
virtual void DrawControls();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "imgui.h"
|
||||
#include "Misc/OutputDevice.h"
|
||||
#include "CogEngineWindow_OutputLog.generated.h"
|
||||
|
||||
class UCogEngineWindow_OutputLog;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
class UCogLogOutputDevice : public FOutputDevice
|
||||
{
|
||||
public:
|
||||
friend class UCogEngineWindow_OutputLog;
|
||||
|
||||
UCogLogOutputDevice();
|
||||
~UCogLogOutputDevice();
|
||||
|
||||
virtual void Serialize(const TCHAR* Message, ELogVerbosity::Type Verbosity, const FName& Category) override;
|
||||
|
||||
UCogEngineWindow_OutputLog* OutputLog = nullptr;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS(Config = Cog)
|
||||
class COGENGINE_API UCogEngineWindow_OutputLog : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UCogEngineWindow_OutputLog();
|
||||
|
||||
void AddLog(const TCHAR* Message, ELogVerbosity::Type Verbosity, const FName& Category);
|
||||
|
||||
void Clear();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void ResetConfig() override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
private:
|
||||
|
||||
struct FLineInfo
|
||||
{
|
||||
int32 Start = 0;
|
||||
int32 End = 0;
|
||||
int32 Frame = 0;
|
||||
ELogVerbosity::Type Verbosity;
|
||||
FName Category;
|
||||
};
|
||||
|
||||
void DrawRow(const char* BufferStart, const FLineInfo& Info, bool IsTableShown);
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool AutoScroll = true;
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool ShowFrame = true;
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool ShowCategory = true;
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool ShowVerbosity = false;
|
||||
|
||||
UPROPERTY(Config)
|
||||
bool ShowAsTable = false;
|
||||
|
||||
UPROPERTY(Config)
|
||||
int32 VerbosityFilter = ELogVerbosity::VeryVerbose;
|
||||
|
||||
ImGuiTextBuffer TextBuffer;
|
||||
|
||||
ImGuiTextFilter Filter;
|
||||
|
||||
TArray<FLineInfo> LineInfos;
|
||||
|
||||
UCogLogOutputDevice OutputDevice;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_Plots.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_Plots : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void RenderTick(float DeltaTime) override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_Scalability.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_Scalability : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_Selection.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_Selection : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UCogEngineWindow_Selection();
|
||||
|
||||
bool GetIsSelecting() const { return bSelectionModeActive; }
|
||||
|
||||
void SetCurrentActorSubClass(TSubclassOf<AActor> Value) { SelectedSubClass = Value; }
|
||||
|
||||
TSubclassOf<AActor> GetCurrentActorSubClass() const { return SelectedSubClass; }
|
||||
|
||||
const TArray<TSubclassOf<AActor>>& GetActorSubClasses() const { return SubClasses; }
|
||||
|
||||
void SetActorSubClasses(const TArray<TSubclassOf<AActor>>& Value) { SubClasses = Value; }
|
||||
|
||||
ETraceTypeQuery GetTraceType() const { return TraceType; }
|
||||
|
||||
void SetTraceType(ETraceTypeQuery Value) { TraceType = Value; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void RenderTick(float DeltaTime) override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
virtual void DrawMainMenuWidget(bool Draw, float& Width) override;
|
||||
|
||||
bool DrawSelectionCombo();
|
||||
|
||||
void DrawActorContextMenu(AActor* Actor);
|
||||
|
||||
void ActivateSelectionMode();
|
||||
|
||||
void HackWaitInputRelease();
|
||||
|
||||
private:
|
||||
|
||||
void TickSelectionMode();
|
||||
|
||||
void ToggleSelectionMode();
|
||||
|
||||
void DeactivateSelectionMode();
|
||||
|
||||
void DrawActorFrame(const AActor* Actor);
|
||||
|
||||
bool ComputeBoundingBoxScreenPosition(const APlayerController* PlayerController, const FVector& Origin, const FVector& Extent, FVector2D& Min, FVector2D& Max);
|
||||
|
||||
FVector LastSelectedActorLocation = FVector::ZeroVector;
|
||||
|
||||
bool bSelectionModeActive = false;
|
||||
|
||||
bool bImGuiHadInputBeforeEnteringSelectionMode = false;
|
||||
|
||||
int32 WaitInputReleased = 0;
|
||||
|
||||
TSubclassOf<AActor> SelectedSubClass;
|
||||
|
||||
TArray<TSubclassOf<AActor>> SubClasses;
|
||||
|
||||
ETraceTypeQuery TraceType = TraceTypeQuery1;
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_Skeleton.generated.h"
|
||||
|
||||
class USkeletalMeshComponent;
|
||||
|
||||
struct FBoneInfo
|
||||
{
|
||||
FName Name;
|
||||
TArray<int32> Children;
|
||||
int32 Index = 0;
|
||||
int32 ParentIndex = INDEX_NONE;
|
||||
FVector LastLocation = FVector::ZeroVector;
|
||||
bool IsSecondaryBone = false;
|
||||
|
||||
bool ShowBone = true;
|
||||
bool ShowName = false;
|
||||
bool ShowLocalVelocity = false;
|
||||
bool ShowAxes = false;
|
||||
bool ShowTrajectory = false;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_Skeleton : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UCogEngineWindow_Skeleton();
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
virtual void RenderTick(float DeltaTime) override;
|
||||
|
||||
virtual void OnSelectionChanged(AActor* OldSelection, AActor* NewSelection) override;
|
||||
|
||||
private:
|
||||
void DrawBoneEntry(int32 BoneIndex, bool OpenAllChildren);
|
||||
void SetChildrenVisibility(int32 BoneIndex, bool IsVisible);
|
||||
void DrawSkeleton();
|
||||
void RefreshSkeleton();
|
||||
|
||||
TWeakObjectPtr<USkeletalMeshComponent> CurrentSkeleton = nullptr;
|
||||
bool ShowBones = true;
|
||||
bool ShowNames = false;
|
||||
bool ShowAxes = false;
|
||||
bool ShowVelocities = false;
|
||||
bool ShowTrajectories = false;
|
||||
bool HideSecondaryBones = true;
|
||||
int32 HoveredBoneIndex = INDEX_NONE;
|
||||
TArray<FBoneInfo> BonesInfos;
|
||||
ImGuiTextFilter Filter;
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_Spawns.generated.h"
|
||||
|
||||
class UCogEngineDataAsset;
|
||||
struct FCogEngineSpawnGroup;
|
||||
struct FCogEngineSpawnEntry;
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_Spawns : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
const UCogEngineDataAsset* GetAsset() const { return Asset.Get(); }
|
||||
|
||||
void SetAsset(const UCogEngineDataAsset* Value) { Asset = Value; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual void RenderHelp();
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
virtual void RenderSpawnGroup(const FCogEngineSpawnGroup& SpawnGroup);
|
||||
|
||||
virtual bool RenderSpawnAsset(const FCogEngineSpawnEntry& SpawnEntry, bool IsLastSelected);
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY()
|
||||
TWeakObjectPtr<const UCogEngineDataAsset> Asset = nullptr;
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_Stats.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_Stats : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
static ImVec4 GetFpsColor(float Value, float Good = 50.0f, float Medium = 30.0f);
|
||||
|
||||
static ImVec4 GetPingColor(float Value, float Good = 100.0f, float Medium = 200.0f);
|
||||
|
||||
static ImVec4 GetPacketLossColor(float Value, float Good = 10.0f, float Medium = 20.0f);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
virtual void DrawMainMenuWidget(bool Draw, float& Width) override;
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogWindow.h"
|
||||
#include "CogEngineWindow_TimeScale.generated.h"
|
||||
|
||||
class ACogEngineReplicator;
|
||||
|
||||
UCLASS()
|
||||
class COGENGINE_API UCogEngineWindow_TimeScale : public UCogWindow
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UCogEngineWindow_TimeScale();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void RenderHelp() override;
|
||||
|
||||
virtual void RenderContent() override;
|
||||
|
||||
virtual void DrawTimeButton(ACogEngineReplicator* Replicator, float Value);
|
||||
|
||||
TArray<float> TimingScales;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
using UnrealBuildTool;
|
||||
using System.IO;
|
||||
|
||||
public class CogImgui : ModuleRules
|
||||
{
|
||||
public CogImgui(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
bLegacyPublicIncludePaths = false;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
Path.Combine(ModuleDirectory, "../ThirdParty/imgui/"),
|
||||
Path.Combine(ModuleDirectory, "../ThirdParty/implot/"),
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"ThirdParty/imgui",
|
||||
"ThirdParty/implot",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"Projects"
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"InputCore",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
}
|
||||
);
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
}
|
||||
);
|
||||
|
||||
if (Target.bBuildEditor)
|
||||
{
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"EditorStyle",
|
||||
"Settings",
|
||||
"UnrealEd",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "CogImguiDrawList.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogImguiDrawList::CopyVertexData(TArray<FSlateVertex>& OutVertexBuffer, const FTransform2D& Transform) const
|
||||
{
|
||||
// Reset and reserve space in destination buffer.
|
||||
OutVertexBuffer.SetNumUninitialized(ImGuiVertexBuffer.Size, false);
|
||||
|
||||
// Transform and copy vertex data.
|
||||
for (int Idx = 0; Idx < ImGuiVertexBuffer.Size; Idx++)
|
||||
{
|
||||
const ImDrawVert& ImGuiVertex = ImGuiVertexBuffer[Idx];
|
||||
FSlateVertex& SlateVertex = OutVertexBuffer[Idx];
|
||||
|
||||
// Final UV is calculated in shader as XY * ZW, so we need set all components.
|
||||
SlateVertex.TexCoords[0] = ImGuiVertex.uv.x;
|
||||
SlateVertex.TexCoords[1] = ImGuiVertex.uv.y;
|
||||
SlateVertex.TexCoords[2] = SlateVertex.TexCoords[3] = 1.f;
|
||||
|
||||
const FVector2D VertexPosition = Transform.TransformPoint(FCogImguiHelper::ToVector2D(ImGuiVertex.pos));
|
||||
SlateVertex.Position[0] = VertexPosition.X;
|
||||
SlateVertex.Position[1] = VertexPosition.Y;
|
||||
|
||||
// Unpack ImU32 color.
|
||||
SlateVertex.Color = FCogImguiHelper::UnpackImU32Color(ImGuiVertex.col);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogImguiDrawList::DrawCommand FCogImguiDrawList::GetCommand(int CommandCount, const FTransform2D& Transform) const
|
||||
{
|
||||
const ImDrawCmd& ImGuiCommand = ImGuiCommandBuffer[CommandCount];
|
||||
return
|
||||
{
|
||||
ImGuiCommand.ElemCount,
|
||||
TransformRect(Transform, FCogImguiHelper::ToSlateRect(ImGuiCommand.ClipRect)),
|
||||
FCogImguiHelper::ToTextureIndex(ImGuiCommand.TextureId)
|
||||
};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogImguiDrawList::CopyIndexData(TArray<SlateIndex>& OutIndexBuffer, const int32 StartIndex, const int32 NumElements) const
|
||||
{
|
||||
// Reset buffer.
|
||||
OutIndexBuffer.SetNumUninitialized(NumElements, false);
|
||||
|
||||
// Copy elements (slow copy because of different sizes of ImDrawIdx and SlateIndex and because SlateIndex can
|
||||
// have different size on different platforms).
|
||||
for (int i = 0; i < NumElements; i++)
|
||||
{
|
||||
OutIndexBuffer[i] = ImGuiIndexBuffer[StartIndex + i];
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogImguiDrawList::TransferDrawData(ImDrawList& Src)
|
||||
{
|
||||
// Move data from source to this list.
|
||||
Src.CmdBuffer.swap(ImGuiCommandBuffer);
|
||||
Src.IdxBuffer.swap(ImGuiIndexBuffer);
|
||||
Src.VtxBuffer.swap(ImGuiVertexBuffer);
|
||||
|
||||
// ImGui seems to clear draw lists in every frame, but since source list can contain pointers to buffers that
|
||||
// we just swapped, it is better to clear explicitly here.
|
||||
Src._ResetForNewFrame();
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
#include "CogImguiHelper.h"
|
||||
|
||||
#include "InputCoreTypes.h"
|
||||
#include "imgui_internal.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
FString FCogImguiHelper::GetIniSaveDirectory()
|
||||
{
|
||||
const FString SavedDir = FPaths::ProjectSavedDir();
|
||||
const FString Directory = FPaths::Combine(*SavedDir, TEXT("ImGui"));
|
||||
IPlatformFile::GetPlatformPhysical().CreateDirectory(*Directory);
|
||||
return Directory;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
FString FCogImguiHelper::GetIniFilePath(const FString& Filename)
|
||||
{
|
||||
FString SaveDirectory = GetIniSaveDirectory();
|
||||
FString FilePath = FPaths::Combine(SaveDirectory, Filename + TEXT(".ini"));
|
||||
return FilePath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImGuiWindow* FCogImguiHelper::GetCurrentWindow()
|
||||
{
|
||||
ImGuiContext& Context = *ImGui::GetCurrentContext();
|
||||
Context.CurrentWindow->WriteAccessed = true;
|
||||
return Context.CurrentWindow;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FColor FCogImguiHelper::UnpackImU32Color(ImU32 Color)
|
||||
{
|
||||
return FColor
|
||||
{
|
||||
(uint8)((Color >> IM_COL32_R_SHIFT) & 0xFF),
|
||||
(uint8)((Color >> IM_COL32_G_SHIFT) & 0xFF),
|
||||
(uint8)((Color >> IM_COL32_B_SHIFT) & 0xFF),
|
||||
(uint8)((Color >> IM_COL32_A_SHIFT) & 0xFF)
|
||||
};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FSlateRect FCogImguiHelper::ToSlateRect(const ImVec4& Value)
|
||||
{
|
||||
return FSlateRect{ Value.x, Value.y, Value.z, Value.w };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FVector2D FCogImguiHelper::ToVector2D(const ImVec2& Value)
|
||||
{
|
||||
return FVector2D(Value.x, Value.y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImVec2 FCogImguiHelper::ToImVec2(const FVector2D& Value)
|
||||
{
|
||||
return ImVec2(Value.X, Value.Y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImColor FCogImguiHelper::ToImColor(const FColor& Value)
|
||||
{
|
||||
return ImColor(Value.R, Value.G, Value.B, Value.A);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImColor FCogImguiHelper::ToImColor(const FLinearColor& Value)
|
||||
{
|
||||
return ImColor(Value.R, Value.G, Value.B, Value.A);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImVec4 FCogImguiHelper::ToImVec4(const FColor& Value)
|
||||
{
|
||||
return ToImColor(Value).Value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImVec4 FCogImguiHelper::ToImVec4(const FLinearColor& Value)
|
||||
{
|
||||
return ImVec4(Value.R, Value.G, Value.B, Value.A);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImVec4 FCogImguiHelper::ToImVec4(const FVector4f& Value)
|
||||
{
|
||||
return ImVec4(Value.X, Value.Y, Value.Z, Value.W);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImU32 FCogImguiHelper::ToImU32(const FColor& Value)
|
||||
{
|
||||
return (ImU32)ToImColor(Value);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImU32 FCogImguiHelper::ToImU32(const FVector4f& Value)
|
||||
{
|
||||
return ImGui::GetColorU32(ToImVec4(Value));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
CogTextureIndex FCogImguiHelper::ToTextureIndex(ImTextureID Index)
|
||||
{
|
||||
return static_cast<CogTextureIndex>(reinterpret_cast<intptr_t>(Index));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImTextureID FCogImguiHelper::ToImTextureID(CogTextureIndex Index)
|
||||
{
|
||||
return reinterpret_cast<ImTextureID>(static_cast<intptr_t>(Index));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FVector2D FCogImguiHelper::RoundVector(const FVector2D& Vector)
|
||||
{
|
||||
return FVector2D(FMath::RoundToFloat(Vector.X), FMath::RoundToFloat(Vector.Y));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FSlateRenderTransform FCogImguiHelper::RoundTranslation(const FSlateRenderTransform& Transform)
|
||||
{
|
||||
return FSlateRenderTransform(Transform.GetMatrix(), RoundVector(Transform.GetTranslation()));
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
#include "CogImguiInputHelper.h"
|
||||
|
||||
#include "CogImguiModule.h"
|
||||
#include "Framework/Commands/UICommandInfo.h"
|
||||
#include "GameFramework/GameUserSettings.h"
|
||||
#include "GameFramework/InputSettings.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "imgui_internal.h"
|
||||
#include "InputCoreTypes.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
#include "Kismet2/DebuggerCommands.h"
|
||||
#endif //WITH_EDITOR
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TMap<FKey, ImGuiKey> FCogImguiInputHelper::KeyMap;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
APlayerController* FCogImguiInputHelper::GetFirstLocalPlayerController(UWorld& World)
|
||||
{
|
||||
for (FConstPlayerControllerIterator Iterator = World.GetPlayerControllerIterator(); Iterator; ++Iterator)
|
||||
{
|
||||
APlayerController* PlayerController = Iterator->Get();
|
||||
if (PlayerController->IsLocalController())
|
||||
{
|
||||
return PlayerController;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogImguiInputHelper::IsKeyEventHandled(const FKeyEvent& KeyEvent)
|
||||
{
|
||||
if (FCogImguiModule::Get().GetEnableInput() == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (KeyEvent.GetKey().IsGamepadKey())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsConsoleEvent(KeyEvent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsStopPlaySessionEvent(KeyEvent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsImGuiToggleInputEvent(KeyEvent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogImguiInputHelper::IsCheckBoxStateMatchingValue(ECheckBoxState CheckBoxState, bool bValue)
|
||||
{
|
||||
const bool Result = (CheckBoxState == ECheckBoxState::Undetermined) || ((CheckBoxState == ECheckBoxState::Checked) == bValue);
|
||||
return Result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogImguiInputHelper::IsKeyEventMatchingKeyInfo(const FKeyEvent& KeyEvent, const FCogImGuiKeyInfo& KeyInfo)
|
||||
{
|
||||
const bool Result = (KeyInfo.Key == KeyEvent.GetKey())
|
||||
&& IsCheckBoxStateMatchingValue(KeyInfo.Shift, KeyEvent.IsShiftDown())
|
||||
&& IsCheckBoxStateMatchingValue(KeyInfo.Ctrl, KeyEvent.IsControlDown())
|
||||
&& IsCheckBoxStateMatchingValue(KeyInfo.Alt, KeyEvent.IsAltDown())
|
||||
&& IsCheckBoxStateMatchingValue(KeyInfo.Cmd, KeyEvent.IsCommandDown());
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogImguiInputHelper::WasKeyInfoJustPressed(APlayerController& PlayerController, const FCogImGuiKeyInfo& KeyInfo)
|
||||
{
|
||||
if (PlayerController.WasInputKeyJustPressed(KeyInfo.Key))
|
||||
{
|
||||
const FModifierKeysState& ModifierKeys = FSlateApplication::Get().GetModifierKeys();
|
||||
|
||||
const bool MatchCtrl = IsCheckBoxStateMatchingValue(KeyInfo.Ctrl, ModifierKeys.IsControlDown());
|
||||
const bool MatchAlt = IsCheckBoxStateMatchingValue(KeyInfo.Alt, ModifierKeys.IsAltDown());
|
||||
const bool MatchShift = IsCheckBoxStateMatchingValue(KeyInfo.Shift, ModifierKeys.IsShiftDown());
|
||||
const bool MatchCmd = IsCheckBoxStateMatchingValue(KeyInfo.Cmd, ModifierKeys.IsCommandDown());
|
||||
|
||||
const bool Result = MatchCtrl && MatchAlt && MatchShift && MatchCmd;
|
||||
return Result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogImguiInputHelper::IsConsoleEvent(const FKeyEvent& KeyEvent)
|
||||
{
|
||||
const bool bModifierDown = KeyEvent.IsControlDown() || KeyEvent.IsShiftDown() || KeyEvent.IsAltDown() || KeyEvent.IsCommandDown();
|
||||
const bool Result = !bModifierDown && GetDefault<UInputSettings>()->ConsoleKeys.Contains(KeyEvent.GetKey());
|
||||
return Result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogImguiInputHelper::IsStopPlaySessionEvent(const FKeyEvent& KeyEvent)
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
static TSharedPtr<FUICommandInfo> StopPlaySessionCommandInfo = FInputBindingManager::Get().FindCommandInContext("PlayWorld", "StopPlaySession");
|
||||
|
||||
if (StopPlaySessionCommandInfo.IsValid())
|
||||
{
|
||||
const FInputChord InputChord(KeyEvent.GetKey(), KeyEvent.IsShiftDown(), KeyEvent.IsControlDown(), KeyEvent.IsAltDown(), KeyEvent.IsCommandDown());
|
||||
const bool bHasActiveChord = StopPlaySessionCommandInfo->HasActiveChord(InputChord);
|
||||
return bHasActiveChord && FPlayWorldCommands::GlobalPlayWorldActions->CanExecuteAction(StopPlaySessionCommandInfo.ToSharedRef());
|
||||
}
|
||||
#endif // WITH_EDITOR
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool FCogImguiInputHelper::IsImGuiToggleInputEvent(const FKeyEvent& KeyEvent)
|
||||
{
|
||||
const bool Result = IsKeyEventMatchingKeyInfo(KeyEvent, FCogImguiModule::Get().GetToggleInputKey());
|
||||
return Result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ImGuiKey FCogImguiInputHelper::KeyEventToImGuiKey(const FKeyEvent& KeyEvent)
|
||||
{
|
||||
if (KeyMap.IsEmpty())
|
||||
{
|
||||
InitializeKeyMap();
|
||||
}
|
||||
|
||||
if (const ImGuiKey* Key = KeyMap.Find(KeyEvent.GetKey()))
|
||||
{
|
||||
return *Key;
|
||||
}
|
||||
|
||||
return ImGuiKey_None;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
uint32 FCogImguiInputHelper::MouseButtonToImGuiMouseButton(const FKey& MouseButton)
|
||||
{
|
||||
if (MouseButton == EKeys::LeftMouseButton) { return 0; }
|
||||
if (MouseButton == EKeys::RightMouseButton) { return 1; }
|
||||
if (MouseButton == EKeys::MiddleMouseButton) { return 2; }
|
||||
if (MouseButton == EKeys::ThumbMouseButton) { return 3; }
|
||||
if (MouseButton == EKeys::ThumbMouseButton2) { return 4; }
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
EMouseCursor::Type FCogImguiInputHelper::ToSlateMouseCursor(ImGuiMouseCursor MouseCursor)
|
||||
{
|
||||
switch (MouseCursor)
|
||||
{
|
||||
case ImGuiMouseCursor_Arrow: return EMouseCursor::Default;
|
||||
case ImGuiMouseCursor_TextInput: return EMouseCursor::TextEditBeam;
|
||||
case ImGuiMouseCursor_ResizeAll: return EMouseCursor::CardinalCross;
|
||||
case ImGuiMouseCursor_ResizeNS: return EMouseCursor::ResizeUpDown;
|
||||
case ImGuiMouseCursor_ResizeEW: return EMouseCursor::ResizeLeftRight;
|
||||
case ImGuiMouseCursor_ResizeNESW: return EMouseCursor::ResizeSouthWest;
|
||||
case ImGuiMouseCursor_ResizeNWSE: return EMouseCursor::ResizeSouthEast;
|
||||
|
||||
case ImGuiMouseCursor_None:
|
||||
default:
|
||||
return EMouseCursor::None;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogImguiInputHelper::InitializeKeyMap()
|
||||
{
|
||||
KeyMap.Add(EKeys::LeftMouseButton, ImGuiKey_MouseLeft);
|
||||
KeyMap.Add(EKeys::RightMouseButton, ImGuiKey_MouseRight);
|
||||
KeyMap.Add(EKeys::MiddleMouseButton, ImGuiKey_MouseMiddle);
|
||||
KeyMap.Add(EKeys::ThumbMouseButton, ImGuiKey_MouseX1);
|
||||
KeyMap.Add(EKeys::ThumbMouseButton2, ImGuiKey_MouseX2);
|
||||
|
||||
KeyMap.Add(EKeys::BackSpace, ImGuiKey_Backspace);
|
||||
KeyMap.Add(EKeys::Tab, ImGuiKey_Tab);
|
||||
KeyMap.Add(EKeys::Enter, ImGuiKey_Enter);
|
||||
KeyMap.Add(EKeys::Pause, ImGuiKey_Pause);
|
||||
|
||||
KeyMap.Add(EKeys::CapsLock, ImGuiKey_CapsLock);
|
||||
KeyMap.Add(EKeys::Escape, ImGuiKey_Escape);
|
||||
KeyMap.Add(EKeys::SpaceBar, ImGuiKey_Space);
|
||||
KeyMap.Add(EKeys::PageUp, ImGuiKey_PageUp);
|
||||
KeyMap.Add(EKeys::PageDown, ImGuiKey_PageDown);
|
||||
KeyMap.Add(EKeys::End, ImGuiKey_End);
|
||||
KeyMap.Add(EKeys::Home, ImGuiKey_Home);
|
||||
|
||||
KeyMap.Add(EKeys::Left, ImGuiKey_LeftArrow);
|
||||
KeyMap.Add(EKeys::Up, ImGuiKey_UpArrow);
|
||||
KeyMap.Add(EKeys::Right, ImGuiKey_RightArrow);
|
||||
KeyMap.Add(EKeys::Down, ImGuiKey_DownArrow);
|
||||
|
||||
KeyMap.Add(EKeys::Insert, ImGuiKey_Insert);
|
||||
KeyMap.Add(EKeys::Delete, ImGuiKey_Delete);
|
||||
|
||||
KeyMap.Add(EKeys::Zero, ImGuiKey_0);
|
||||
KeyMap.Add(EKeys::One, ImGuiKey_1);
|
||||
KeyMap.Add(EKeys::Two, ImGuiKey_2);
|
||||
KeyMap.Add(EKeys::Three, ImGuiKey_3);
|
||||
KeyMap.Add(EKeys::Four, ImGuiKey_4);
|
||||
KeyMap.Add(EKeys::Five, ImGuiKey_5);
|
||||
KeyMap.Add(EKeys::Six, ImGuiKey_6);
|
||||
KeyMap.Add(EKeys::Seven, ImGuiKey_7);
|
||||
KeyMap.Add(EKeys::Eight, ImGuiKey_8);
|
||||
KeyMap.Add(EKeys::Nine, ImGuiKey_9);
|
||||
|
||||
KeyMap.Add(EKeys::A, ImGuiKey_A);
|
||||
KeyMap.Add(EKeys::B, ImGuiKey_B);
|
||||
KeyMap.Add(EKeys::C, ImGuiKey_C);
|
||||
KeyMap.Add(EKeys::D, ImGuiKey_D);
|
||||
KeyMap.Add(EKeys::E, ImGuiKey_E);
|
||||
KeyMap.Add(EKeys::F, ImGuiKey_F);
|
||||
KeyMap.Add(EKeys::G, ImGuiKey_G);
|
||||
KeyMap.Add(EKeys::H, ImGuiKey_H);
|
||||
KeyMap.Add(EKeys::I, ImGuiKey_I);
|
||||
KeyMap.Add(EKeys::J, ImGuiKey_J);
|
||||
KeyMap.Add(EKeys::K, ImGuiKey_K);
|
||||
KeyMap.Add(EKeys::L, ImGuiKey_L);
|
||||
KeyMap.Add(EKeys::M, ImGuiKey_M);
|
||||
KeyMap.Add(EKeys::N, ImGuiKey_N);
|
||||
KeyMap.Add(EKeys::O, ImGuiKey_O);
|
||||
KeyMap.Add(EKeys::P, ImGuiKey_P);
|
||||
KeyMap.Add(EKeys::Q, ImGuiKey_Q);
|
||||
KeyMap.Add(EKeys::R, ImGuiKey_R);
|
||||
KeyMap.Add(EKeys::S, ImGuiKey_S);
|
||||
KeyMap.Add(EKeys::T, ImGuiKey_T);
|
||||
KeyMap.Add(EKeys::U, ImGuiKey_U);
|
||||
KeyMap.Add(EKeys::V, ImGuiKey_V);
|
||||
KeyMap.Add(EKeys::W, ImGuiKey_W);
|
||||
KeyMap.Add(EKeys::X, ImGuiKey_X);
|
||||
KeyMap.Add(EKeys::Y, ImGuiKey_Y);
|
||||
KeyMap.Add(EKeys::Z, ImGuiKey_Z);
|
||||
|
||||
KeyMap.Add(EKeys::NumPadZero, ImGuiKey_Keypad0);
|
||||
KeyMap.Add(EKeys::NumPadOne, ImGuiKey_Keypad1);
|
||||
KeyMap.Add(EKeys::NumPadTwo, ImGuiKey_Keypad2);
|
||||
KeyMap.Add(EKeys::NumPadThree, ImGuiKey_Keypad3);
|
||||
KeyMap.Add(EKeys::NumPadFour, ImGuiKey_Keypad4);
|
||||
KeyMap.Add(EKeys::NumPadFive, ImGuiKey_Keypad5);
|
||||
KeyMap.Add(EKeys::NumPadSix, ImGuiKey_Keypad6);
|
||||
KeyMap.Add(EKeys::NumPadSeven, ImGuiKey_Keypad7);
|
||||
KeyMap.Add(EKeys::NumPadEight, ImGuiKey_Keypad8);
|
||||
KeyMap.Add(EKeys::NumPadNine, ImGuiKey_Keypad9);
|
||||
|
||||
KeyMap.Add(EKeys::Multiply, ImGuiKey_KeypadMultiply);
|
||||
KeyMap.Add(EKeys::Add, ImGuiKey_KeypadAdd);
|
||||
KeyMap.Add(EKeys::Subtract, ImGuiKey_KeypadSubtract);
|
||||
KeyMap.Add(EKeys::Decimal, ImGuiKey_KeypadDecimal);
|
||||
KeyMap.Add(EKeys::Divide, ImGuiKey_KeypadDivide);
|
||||
|
||||
KeyMap.Add(EKeys::F1, ImGuiKey_F1);
|
||||
KeyMap.Add(EKeys::F2, ImGuiKey_F2);
|
||||
KeyMap.Add(EKeys::F3, ImGuiKey_F3);
|
||||
KeyMap.Add(EKeys::F4, ImGuiKey_F4);
|
||||
KeyMap.Add(EKeys::F5, ImGuiKey_F5);
|
||||
KeyMap.Add(EKeys::F6, ImGuiKey_F6);
|
||||
KeyMap.Add(EKeys::F7, ImGuiKey_F7);
|
||||
KeyMap.Add(EKeys::F8, ImGuiKey_F8);
|
||||
KeyMap.Add(EKeys::F9, ImGuiKey_F9);
|
||||
KeyMap.Add(EKeys::F10, ImGuiKey_F10);
|
||||
KeyMap.Add(EKeys::F11, ImGuiKey_F11);
|
||||
KeyMap.Add(EKeys::F12, ImGuiKey_F12);
|
||||
|
||||
KeyMap.Add(EKeys::NumLock, ImGuiKey_NumLock);
|
||||
|
||||
KeyMap.Add(EKeys::ScrollLock, ImGuiKey_ScrollLock);
|
||||
|
||||
KeyMap.Add(EKeys::LeftShift, ImGuiKey_LeftShift);
|
||||
KeyMap.Add(EKeys::RightShift, ImGuiKey_RightShift);
|
||||
KeyMap.Add(EKeys::LeftControl, ImGuiKey_LeftCtrl);
|
||||
KeyMap.Add(EKeys::RightControl, ImGuiKey_RightCtrl);
|
||||
KeyMap.Add(EKeys::LeftAlt, ImGuiKey_LeftAlt);
|
||||
KeyMap.Add(EKeys::RightAlt, ImGuiKey_RightAlt);
|
||||
KeyMap.Add(EKeys::LeftCommand, ImGuiKey_LeftSuper);
|
||||
KeyMap.Add(EKeys::RightCommand, ImGuiKey_RightSuper);
|
||||
|
||||
KeyMap.Add(EKeys::Semicolon, ImGuiKey_Semicolon);
|
||||
KeyMap.Add(EKeys::Equals, ImGuiKey_Equal);
|
||||
KeyMap.Add(EKeys::Comma, ImGuiKey_Comma);
|
||||
KeyMap.Add(EKeys::Hyphen, ImGuiKey_Minus);
|
||||
KeyMap.Add(EKeys::Period, ImGuiKey_Period);
|
||||
KeyMap.Add(EKeys::Slash, ImGuiKey_Slash);
|
||||
|
||||
KeyMap.Add(EKeys::LeftBracket, ImGuiKey_LeftBracket);
|
||||
KeyMap.Add(EKeys::Backslash, ImGuiKey_Backslash);
|
||||
KeyMap.Add(EKeys::RightBracket, ImGuiKey_RightBracket);
|
||||
KeyMap.Add(EKeys::Apostrophe, ImGuiKey_Apostrophe);
|
||||
|
||||
//KeyMap.Add(EKeys::MouseX, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::MouseY, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::Mouse2D, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::MouseScrollUp, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::MouseScrollDown, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::MouseWheelAxis, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::Underscore, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::Tilde, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::Ampersand, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::Asterix, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::Caret, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::Colon, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::Dollar, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::Exclamation, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::LeftParantheses, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::RightParantheses, ImGuiKey_None;
|
||||
//KeyMap.Add(EKeys::Quote, ImGuiKey_None;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#include <Windows/AllowWindowsPlatformTypes.h>
|
||||
#endif // PLATFORM_WINDOWS
|
||||
|
||||
#include "imgui.cpp"
|
||||
#include "imgui_demo.cpp"
|
||||
#include "imgui_draw.cpp"
|
||||
#include "imgui_tables.cpp"
|
||||
#include "imgui_widgets.cpp"
|
||||
|
||||
#include "implot.cpp"
|
||||
#include "implot_demo.cpp"
|
||||
#include "implot_items.cpp"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#include <Windows/HideWindowsPlatformTypes.h>
|
||||
#endif // PLATFORM_WINDOWS
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "CogImguiModule.h"
|
||||
|
||||
#include "Engine/GameViewportClient.h"
|
||||
#include "Widgets/Layout/SScaleBox.h"
|
||||
#include "CogImguiWidget.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FCogImguiModule"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
constexpr int32 Cog_ZOrder = 10000;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogImguiModule::StartupModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogImguiModule::ShutdownModule()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogImguiModule::Initialize()
|
||||
{
|
||||
TextureManager.InitializeErrorTexture();
|
||||
TextureManager.CreatePlainTexture("ImGuiModule_Plain", 2, 2, FColor::White);
|
||||
|
||||
unsigned char* Pixels;
|
||||
int Width, Height, Bpp;
|
||||
|
||||
DefaultFontAtlas.Clear();
|
||||
DefaultFontAtlas.GetTexDataAsRGBA32(&Pixels, &Width, &Height, &Bpp);
|
||||
const CogTextureIndex FontsTexureIndex = TextureManager.CreateTexture("ImGuiModule_FontAtlas", Width, Height, Bpp, Pixels);
|
||||
DefaultFontAtlas.TexID = FCogImguiHelper::ToImTextureID(FontsTexureIndex);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TSharedPtr<SCogImguiWidget> FCogImguiModule::CreateImGuiViewport(UGameViewportClient* GameViewport, FCogImguiRenderFunction Render, ImFontAtlas* FontAtlas /*= nullptr*/)
|
||||
{
|
||||
if (bIsInitialized == false)
|
||||
{
|
||||
Initialize();
|
||||
bIsInitialized = true;
|
||||
}
|
||||
|
||||
if (FontAtlas == nullptr)
|
||||
{
|
||||
FontAtlas = &DefaultFontAtlas;
|
||||
}
|
||||
|
||||
TSharedPtr<SCogImguiWidget> ImguiWidget;
|
||||
SAssignNew(ImguiWidget, SCogImguiWidget)
|
||||
.GameViewport(GameViewport)
|
||||
.FontAtlas(FontAtlas)
|
||||
.Render(Render)
|
||||
.Clipping(EWidgetClipping::ClipToBounds);
|
||||
|
||||
TSharedPtr<SScaleBox> ScaleWidget;
|
||||
SAssignNew(ScaleWidget, SScaleBox)
|
||||
.IgnoreInheritedScale(true)
|
||||
.HAlign(HAlign_Fill)
|
||||
.VAlign(VAlign_Fill)
|
||||
.Visibility(EVisibility::SelfHitTestInvisible)
|
||||
[
|
||||
ImguiWidget.ToSharedRef()
|
||||
];
|
||||
|
||||
GameViewport->AddViewportWidgetContent(ScaleWidget.ToSharedRef(), Cog_ZOrder);
|
||||
|
||||
return ImguiWidget;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FCogImguiModule, CogImGui)
|
||||
@@ -0,0 +1,195 @@
|
||||
#include "CogImguiTextureManager.h"
|
||||
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogImguiTextureManager::InitializeErrorTexture()
|
||||
{
|
||||
CreatePlainTextureInternal(NAME_ErrorTexture, 2, 2, FColor::Magenta);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
CogTextureIndex FCogImguiTextureManager::CreateTexture(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction<void(uint8*)> SrcDataCleanup)
|
||||
{
|
||||
checkf(Name != NAME_None, TEXT("Trying to create a texture with a name 'NAME_None' is not allowed."));
|
||||
|
||||
return CreateTextureInternal(Name, Width, Height, SrcBpp, SrcData, SrcDataCleanup);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
CogTextureIndex FCogImguiTextureManager::CreatePlainTexture(const FName& Name, int32 Width, int32 Height, FColor Color)
|
||||
{
|
||||
checkf(Name != NAME_None, TEXT("Trying to create a texture with a name 'NAME_None' is not allowed."));
|
||||
|
||||
return CreatePlainTextureInternal(Name, Width, Height, Color);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
CogTextureIndex FCogImguiTextureManager::CreateTextureResources(const FName& Name, UTexture2D* Texture)
|
||||
{
|
||||
checkf(Name != NAME_None, TEXT("Trying to create texture resources with a name 'NAME_None' is not allowed."));
|
||||
checkf(Texture, TEXT("Null Texture."));
|
||||
|
||||
// Create an entry for the texture.
|
||||
return AddTextureEntry(Name, Texture, false);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogImguiTextureManager::ReleaseTextureResources(CogTextureIndex Index)
|
||||
{
|
||||
checkf(IsInRange(Index), TEXT("Invalid texture index %d. Texture resources array has %d entries total."), Index, TextureResources.Num());
|
||||
|
||||
TextureResources[Index] = {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
CogTextureIndex FCogImguiTextureManager::CreateTextureInternal(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction<void(uint8*)> SrcDataCleanup)
|
||||
{
|
||||
// Create a texture.
|
||||
UTexture2D* Texture = UTexture2D::CreateTransient(Width, Height);
|
||||
|
||||
// Create a new resource for that texture.
|
||||
Texture->UpdateResource();
|
||||
|
||||
// Update texture data.
|
||||
FUpdateTextureRegion2D* TextureRegion = new FUpdateTextureRegion2D(0, 0, 0, 0, Width, Height);
|
||||
auto DataCleanup = [SrcDataCleanup](uint8* Data, const FUpdateTextureRegion2D* UpdateRegion)
|
||||
{
|
||||
SrcDataCleanup(Data);
|
||||
delete UpdateRegion;
|
||||
};
|
||||
Texture->UpdateTextureRegions(0, 1u, TextureRegion, SrcBpp * Width, SrcBpp, SrcData, DataCleanup);
|
||||
|
||||
// Create an entry for the texture.
|
||||
if (Name == NAME_ErrorTexture)
|
||||
{
|
||||
ErrorTexture = { Name, Texture, true };
|
||||
return INDEX_ErrorTexture;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AddTextureEntry(Name, Texture, true);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
CogTextureIndex FCogImguiTextureManager::CreatePlainTextureInternal(const FName& Name, int32 Width, int32 Height, const FColor& Color)
|
||||
{
|
||||
// Create buffer with raw data.
|
||||
const uint32 ColorPacked = Color.ToPackedARGB();
|
||||
const uint32 Bpp = sizeof(ColorPacked);
|
||||
const uint32 SizeInPixels = Width * Height;
|
||||
const uint32 SizeInBytes = SizeInPixels * Bpp;
|
||||
uint8* SrcData = new uint8[SizeInBytes];
|
||||
std::fill(reinterpret_cast<uint32*>(SrcData), reinterpret_cast<uint32*>(SrcData) + SizeInPixels, ColorPacked);
|
||||
auto SrcDataCleanup = [](uint8* Data) { delete[] Data; };
|
||||
|
||||
// Create new texture from raw data.
|
||||
return CreateTextureInternal(Name, Width, Height, Bpp, SrcData, SrcDataCleanup);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
CogTextureIndex FCogImguiTextureManager::AddTextureEntry(const FName& Name, UTexture2D* Texture, bool bAddToRoot)
|
||||
{
|
||||
// Try to find an entry with that name.
|
||||
CogTextureIndex Index = FindTextureIndex(Name);
|
||||
|
||||
// If this is a new name, try to find an entry to reuse.
|
||||
if (Index == INDEX_NONE)
|
||||
{
|
||||
Index = FindTextureIndex(NAME_None);
|
||||
}
|
||||
|
||||
// Either update/reuse an entry or add a new one.
|
||||
if (Index != INDEX_NONE)
|
||||
{
|
||||
TextureResources[Index] = { Name, Texture, bAddToRoot };
|
||||
return Index;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TextureResources.Emplace(Name, Texture, bAddToRoot);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogImguiTextureManager::FTextureEntry::FTextureEntry(const FName& InName, UTexture2D* InTexture, bool bAddToRoot)
|
||||
: Name(InName)
|
||||
{
|
||||
checkf(InTexture, TEXT("Null texture."));
|
||||
|
||||
if (bAddToRoot)
|
||||
{
|
||||
// Get pointer only for textures that we added to root, so we can later release them.
|
||||
Texture = InTexture;
|
||||
// Add texture to the root to prevent garbage collection.
|
||||
InTexture->AddToRoot();
|
||||
}
|
||||
|
||||
// Create brush and resource handle for input texture.
|
||||
Brush.SetResourceObject(InTexture);
|
||||
CachedResourceHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(Brush);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogImguiTextureManager::FTextureEntry::~FTextureEntry()
|
||||
{
|
||||
Reset(true);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCogImguiTextureManager::FTextureEntry& FCogImguiTextureManager::FTextureEntry::operator=(FTextureEntry&& Other)
|
||||
{
|
||||
// Release old resources if allocated.
|
||||
Reset(true);
|
||||
|
||||
// Move data and ownership to this instance.
|
||||
Name = MoveTemp(Other.Name);
|
||||
Texture = MoveTemp(Other.Texture);
|
||||
Brush = MoveTemp(Other.Brush);
|
||||
CachedResourceHandle = MoveTemp(Other.CachedResourceHandle);
|
||||
|
||||
// Reset the other entry (without releasing resources which are already moved to this instance) to remove tracks
|
||||
// of ownership and mark it as empty/reusable.
|
||||
Other.Reset(false);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
const FSlateResourceHandle& FCogImguiTextureManager::FTextureEntry::GetResourceHandle() const
|
||||
{
|
||||
if (!CachedResourceHandle.IsValid() && Brush.HasUObject())
|
||||
{
|
||||
CachedResourceHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(Brush);
|
||||
}
|
||||
return CachedResourceHandle;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void FCogImguiTextureManager::FTextureEntry::Reset(bool bReleaseResources)
|
||||
{
|
||||
if (bReleaseResources)
|
||||
{
|
||||
// Release brush.
|
||||
if (Brush.HasUObject() && FSlateApplication::IsInitialized())
|
||||
{
|
||||
FSlateApplication::Get().GetRenderer()->ReleaseDynamicResource(Brush);
|
||||
}
|
||||
|
||||
// Remove texture from root to allow for garbage collection (it might be invalid, if we never set it
|
||||
// or this is an application shutdown).
|
||||
if (Texture.IsValid())
|
||||
{
|
||||
Texture->RemoveFromRoot();
|
||||
}
|
||||
}
|
||||
|
||||
// We use empty name to mark unused entries.
|
||||
Name = NAME_None;
|
||||
|
||||
// Clean fields to make sure that we don't reference released or moved resources.
|
||||
Texture.Reset();
|
||||
Brush = FSlateNoResource();
|
||||
CachedResourceHandle = FSlateResourceHandle();
|
||||
}
|
||||
@@ -0,0 +1,498 @@
|
||||
#include "CogImguiWidget.h"
|
||||
|
||||
#include "CogImguiInputHelper.h"
|
||||
#include "CogImguiInputHelper.h"
|
||||
#include "CogImguiModule.h"
|
||||
#include "CogImguiModule.h"
|
||||
#include "CogImguiTextureManager.h"
|
||||
#include "CogImguiWidget.h"
|
||||
#include "Engine/Console.h"
|
||||
#include "Engine/GameViewportClient.h"
|
||||
#include "Engine/LocalPlayer.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
#include "implot.h"
|
||||
#include "SlateOptMacros.h"
|
||||
#include "UnrealClient.h"
|
||||
#include "Widgets/Layout/SBorder.h"
|
||||
#include "Widgets/Layout/SBox.h"
|
||||
#include "Widgets/SViewport.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||
void SCogImguiWidget::Construct(const FArguments& InArgs)
|
||||
{
|
||||
checkf(InArgs._GameViewport, TEXT("Null Game Viewport argument"));
|
||||
|
||||
GameViewport = InArgs._GameViewport;
|
||||
FontAtlas = InArgs._FontAtlas;
|
||||
Render = InArgs._Render;
|
||||
|
||||
ImGuiContext = ImGui::CreateContext(FontAtlas);
|
||||
ImPlotContext = ImPlot::CreateContext();
|
||||
ImPlot::SetImGuiContext(ImGuiContext);
|
||||
|
||||
const char* InitFilenameTemp = TCHAR_TO_ANSI(*FCogImguiHelper::GetIniFilePath("imgui"));
|
||||
ImStrncpy(IniFilename, InitFilenameTemp, IM_ARRAYSIZE(IniFilename));
|
||||
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
IO.IniFilename = IniFilename;
|
||||
IO.DisplaySize = ImVec2(100, 100);
|
||||
IO.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
}
|
||||
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
SCogImguiWidget::~SCogImguiWidget()
|
||||
{
|
||||
ImPlot::DestroyContext(ImPlotContext);
|
||||
ImGui::DestroyContext(ImGuiContext);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
|
||||
{
|
||||
Super::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);
|
||||
|
||||
TickKeyModifiers();
|
||||
TickFocus();
|
||||
TickImGui(InDeltaTime);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::TickKeyModifiers()
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// Refresh modifiers otherwise, when pressing ALT-TAB, the Alt modifier is always true
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
FModifierKeysState ModifierKeys = FSlateApplication::Get().GetModifierKeys();
|
||||
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
if (ModifierKeys.IsControlDown() != IO.KeyCtrl) { IO.AddKeyEvent(ImGuiMod_Ctrl, ModifierKeys.IsControlDown()); }
|
||||
if (ModifierKeys.IsShiftDown() != IO.KeyShift) { IO.AddKeyEvent(ImGuiMod_Shift, ModifierKeys.IsShiftDown()); }
|
||||
if (ModifierKeys.IsAltDown() != IO.KeyAlt) { IO.AddKeyEvent(ImGuiMod_Alt, ModifierKeys.IsAltDown()); }
|
||||
if (ModifierKeys.IsCommandDown() != IO.KeySuper) { IO.AddKeyEvent(ImGuiMod_Super, ModifierKeys.IsCommandDown()); }
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::TickImGui(float InDeltaTime)
|
||||
{
|
||||
if (ImGuiContext == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::SetCurrentContext(ImGuiContext);
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
IO.DeltaTime = InDeltaTime;
|
||||
|
||||
ImPlot::SetImGuiContext(ImGuiContext);
|
||||
ImPlot::SetCurrentContext(ImPlotContext);
|
||||
|
||||
FVector2D DisplaySize;
|
||||
GameViewport->GetViewportSize(DisplaySize);
|
||||
IO.DisplaySize = FCogImguiHelper::ToImVec2(DisplaySize);
|
||||
|
||||
ImGui::NewFrame();
|
||||
Render(InDeltaTime);
|
||||
ImGui::Render();
|
||||
|
||||
SetCursor(FCogImguiInputHelper::ToSlateMouseCursor(ImGui::GetMouseCursor()));
|
||||
|
||||
ImDrawData* DrawData = ImGui::GetDrawData();
|
||||
if (DrawData && DrawData->CmdListsCount > 0)
|
||||
{
|
||||
DrawLists.SetNum(DrawData->CmdListsCount, false);
|
||||
for (int i = 0; i < DrawData->CmdListsCount; i++)
|
||||
{
|
||||
DrawLists[i].TransferDrawData(*DrawData->CmdLists[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawLists.Empty();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::TickFocus()
|
||||
{
|
||||
FCogImguiModule& Module = FCogImguiModule::Get();
|
||||
|
||||
if (UWorld* World = GameViewport->GetWorld())
|
||||
{
|
||||
if (APlayerController* Controller = FCogImguiInputHelper::GetFirstLocalPlayerController(*World))
|
||||
{
|
||||
if (FCogImguiInputHelper::WasKeyInfoJustPressed(*Controller, Module.GetToggleInputKey()))
|
||||
{
|
||||
Module.ToggleEnableInput();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool bShouldEnableInput = Module.GetEnableInput();
|
||||
if (bEnableInput != bShouldEnableInput)
|
||||
{
|
||||
bEnableInput = bShouldEnableInput;
|
||||
|
||||
if (bEnableInput)
|
||||
{
|
||||
TakeFocus();
|
||||
}
|
||||
else
|
||||
{
|
||||
ReturnFocus();
|
||||
}
|
||||
}
|
||||
else if (bEnableInput)
|
||||
{
|
||||
const auto& ViewportWidget = GameViewport->GetGameViewportWidget();
|
||||
if (!HasKeyboardFocus() && !IsConsoleOpened() && (ViewportWidget->HasKeyboardFocus() || ViewportWidget->HasFocusedDescendants()))
|
||||
{
|
||||
TakeFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::TakeFocus()
|
||||
{
|
||||
FSlateApplication& SlateApplication = FSlateApplication::Get();
|
||||
|
||||
PreviousUserFocusedWidget = SlateApplication.GetUserFocusedWidget(SlateApplication.GetUserIndexForKeyboard());
|
||||
|
||||
if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
|
||||
{
|
||||
TSharedRef<SWidget> FocusWidget = SharedThis(this);
|
||||
LocalPlayer->GetSlateOperations().CaptureMouse(FocusWidget);
|
||||
LocalPlayer->GetSlateOperations().SetUserFocus(FocusWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
SlateApplication.SetKeyboardFocus(SharedThis(this));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::ReturnFocus()
|
||||
{
|
||||
if (HasKeyboardFocus())
|
||||
{
|
||||
auto FocusWidgetPtr = PreviousUserFocusedWidget.IsValid()
|
||||
? PreviousUserFocusedWidget.Pin()
|
||||
: GameViewport->GetGameViewportWidget();
|
||||
|
||||
if (ULocalPlayer* LocalPlayer = GetLocalPlayer())
|
||||
{
|
||||
auto FocusWidgetRef = FocusWidgetPtr.ToSharedRef();
|
||||
|
||||
if (FocusWidgetPtr == GameViewport->GetGameViewportWidget())
|
||||
{
|
||||
LocalPlayer->GetSlateOperations().CaptureMouse(FocusWidgetRef);
|
||||
}
|
||||
|
||||
LocalPlayer->GetSlateOperations().SetUserFocus(FocusWidgetRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
FSlateApplication& SlateApplication = FSlateApplication::Get();
|
||||
SlateApplication.ResetToDefaultPointerInputSettings();
|
||||
SlateApplication.SetUserFocus(SlateApplication.GetUserIndexForKeyboard(), FocusWidgetPtr);
|
||||
}
|
||||
}
|
||||
|
||||
PreviousUserFocusedWidget.Reset();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
int32 SCogImguiWidget::OnPaint(
|
||||
const FPaintArgs& Args,
|
||||
const FGeometry& AllottedGeometry,
|
||||
const FSlateRect& MyClippingRect,
|
||||
FSlateWindowElementList& OutDrawElements,
|
||||
int32 LayerId,
|
||||
const FWidgetStyle& WidgetStyle,
|
||||
bool bParentEnabled) const
|
||||
{
|
||||
|
||||
const FSlateRenderTransform& WidgetToScreen = AllottedGeometry.GetAccumulatedRenderTransform();
|
||||
const FSlateRenderTransform ImGuiToScreen = FCogImguiHelper::RoundTranslation(ImGuiRenderTransform.Concatenate(WidgetToScreen));
|
||||
|
||||
FCogImguiTextureManager& TextureManager = FCogImguiModule::Get().GetTextureManager();
|
||||
|
||||
for (const auto& DrawList : DrawLists)
|
||||
{
|
||||
DrawList.CopyVertexData(VertexBuffer, ImGuiToScreen);
|
||||
|
||||
int IndexBufferOffset = 0;
|
||||
for (int i = 0; i < DrawList.NumCommands(); i++)
|
||||
{
|
||||
const auto& DrawCommand = DrawList.GetCommand(i, ImGuiToScreen);
|
||||
|
||||
DrawList.CopyIndexData(IndexBuffer, IndexBufferOffset, DrawCommand.NumElements);
|
||||
|
||||
// Advance offset by number of copied elements to position it for the next command.
|
||||
IndexBufferOffset += DrawCommand.NumElements;
|
||||
|
||||
// Get texture resource handle for this draw command (null index will be also mapped to a valid texture).
|
||||
const FSlateResourceHandle& Handle = TextureManager.GetTextureHandle(DrawCommand.TextureId);
|
||||
|
||||
// Transform clipping rectangle to screen space and apply to elements that we draw.
|
||||
const FSlateRect ClippingRect = DrawCommand.ClippingRect.IntersectionWith(MyClippingRect);
|
||||
|
||||
OutDrawElements.PushClip(FSlateClippingZone{ ClippingRect });
|
||||
|
||||
// Add elements to the list.
|
||||
FSlateDrawElement::MakeCustomVerts(OutDrawElements, LayerId, Handle, VertexBuffer, IndexBuffer, nullptr, 0, 0);
|
||||
|
||||
OutDrawElements.PopClip();
|
||||
}
|
||||
}
|
||||
|
||||
return Super::OnPaint(Args, AllottedGeometry, MyClippingRect, OutDrawElements, LayerId, WidgetStyle, bParentEnabled);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FVector2D SCogImguiWidget::ComputeDesiredSize(float Scale) const
|
||||
{
|
||||
return Super::ComputeDesiredSize(Scale);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ULocalPlayer* SCogImguiWidget::GetLocalPlayer() const
|
||||
{
|
||||
if (GameViewport.IsValid())
|
||||
{
|
||||
if (UWorld* World = GameViewport->GetWorld())
|
||||
{
|
||||
if (ULocalPlayer* LocalPlayer = World->GetFirstLocalPlayerFromController())
|
||||
{
|
||||
return World->GetFirstLocalPlayerFromController();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FVector2D SCogImguiWidget::TransformScreenPointToImGui(const FGeometry& MyGeometry, const FVector2D& Point) const
|
||||
{
|
||||
const FSlateRenderTransform ImGuiToScreen = MyGeometry.GetAccumulatedRenderTransform();
|
||||
return ImGuiToScreen.Inverse().TransformPoint(Point);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool SCogImguiWidget::IsConsoleOpened() const
|
||||
{
|
||||
return GameViewport->ViewportConsole && GameViewport->ViewportConsole->ConsoleState != NAME_None;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool SCogImguiWidget::IsCurrentContext() const
|
||||
{
|
||||
return ImGui::GetCurrentContext() == ImGuiContext;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::SetAsCurrentContext()
|
||||
{
|
||||
ImGui::SetCurrentContext(ImGuiContext);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::SetDPIScale(float Scale)
|
||||
{
|
||||
if (DpiScale == Scale)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DpiScale = Scale;
|
||||
OnDpiChanged();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::OnDpiChanged()
|
||||
{
|
||||
if (FontAtlas == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FontAtlas->Clear();
|
||||
|
||||
ImFontConfig FontConfig = {};
|
||||
FontConfig.SizePixels = FMath::RoundFromZero(13.f * DpiScale);
|
||||
FontAtlas->AddFontDefault(&FontConfig);
|
||||
|
||||
unsigned char* Pixels;
|
||||
int Width, Height, Bpp;
|
||||
FontAtlas->GetTexDataAsRGBA32(&Pixels, &Width, &Height, &Bpp);
|
||||
const CogTextureIndex FontsTexureIndex = FCogImguiModule::Get().GetTextureManager().CreateTexture("xx", Width, Height, Bpp, Pixels);
|
||||
FontAtlas->TexID = FCogImguiHelper::ToImTextureID(FontsTexureIndex);
|
||||
|
||||
ImGuiStyle NewStyle = ImGuiStyle();
|
||||
ImGui::GetStyle() = MoveTemp(NewStyle);
|
||||
NewStyle.ScaleAllSizes(DpiScale);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent)
|
||||
{
|
||||
if (FCogImguiModule::Get().GetEnableInput())
|
||||
{
|
||||
ImGui::GetIO().AddInputCharacter(FCogImguiInputHelper::CastInputChar(CharacterEvent.GetCharacter()));
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent)
|
||||
{
|
||||
if (FCogImguiInputHelper::IsKeyEventHandled(KeyEvent) == false)
|
||||
{
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
IO.AddKeyEvent(FCogImguiInputHelper::KeyEventToImGuiKey(KeyEvent), true);
|
||||
IO.AddKeyEvent(ImGuiMod_Ctrl, KeyEvent.IsControlDown());
|
||||
IO.AddKeyEvent(ImGuiMod_Shift, KeyEvent.IsShiftDown());
|
||||
IO.AddKeyEvent(ImGuiMod_Alt, KeyEvent.IsAltDown());
|
||||
IO.AddKeyEvent(ImGuiMod_Super, KeyEvent.IsCommandDown());
|
||||
|
||||
return FReply::Handled();
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent)
|
||||
{
|
||||
if (FCogImguiInputHelper::IsKeyEventHandled(KeyEvent) == false)
|
||||
{
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
ImGuiIO& IO = ImGui::GetIO();
|
||||
IO.AddKeyEvent(FCogImguiInputHelper::KeyEventToImGuiKey(KeyEvent), false);
|
||||
IO.AddKeyEvent(ImGuiMod_Ctrl, KeyEvent.IsControlDown());
|
||||
IO.AddKeyEvent(ImGuiMod_Shift, KeyEvent.IsShiftDown());
|
||||
IO.AddKeyEvent(ImGuiMod_Alt, KeyEvent.IsAltDown());
|
||||
IO.AddKeyEvent(ImGuiMod_Super, KeyEvent.IsCommandDown());
|
||||
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnAnalogValueChanged(const FGeometry& MyGeometry, const FAnalogInputEvent& AnalogInputEvent)
|
||||
{
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||||
{
|
||||
if (FCogImguiModule::Get().GetEnableInput() == false)
|
||||
{
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
ImGui::GetIO().AddMouseSourceEvent(ImGuiMouseSource_Mouse);
|
||||
ImGui::GetIO().AddMouseButtonEvent(FCogImguiInputHelper::MouseButtonToImGuiMouseButton(MouseEvent.GetEffectingButton()), true);
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||||
{
|
||||
if (FCogImguiModule::Get().GetEnableInput() == false)
|
||||
{
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
ImGui::GetIO().AddMouseSourceEvent(ImGuiMouseSource_Mouse);
|
||||
ImGui::GetIO().AddMouseButtonEvent(FCogImguiInputHelper::MouseButtonToImGuiMouseButton(MouseEvent.GetEffectingButton()), false);
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||||
{
|
||||
if (FCogImguiModule::Get().GetEnableInput() == false)
|
||||
{
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
ImGui::GetIO().AddMouseSourceEvent(ImGuiMouseSource_Mouse);
|
||||
ImGui::GetIO().AddMouseWheelEvent(0, MouseEvent.GetWheelDelta());
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||||
{
|
||||
if (FCogImguiModule::Get().GetEnableInput() == false)
|
||||
{
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
ImGui::GetIO().AddMouseSourceEvent(ImGuiMouseSource_Mouse);
|
||||
const FVector2D Pos = TransformScreenPointToImGui(MyGeometry, MouseEvent.GetScreenSpacePosition());
|
||||
ImGui::GetIO().AddMousePosEvent(Pos.X, Pos.Y);
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent)
|
||||
{
|
||||
Super::OnFocusReceived(MyGeometry, FocusEvent);
|
||||
|
||||
FSlateApplication::Get().ResetToDefaultPointerInputSettings();
|
||||
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::OnFocusLost(const FFocusEvent& FocusEvent)
|
||||
{
|
||||
return Super::OnFocusLost(FocusEvent);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||||
{
|
||||
Super::OnMouseEnter(MyGeometry, MouseEvent);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void SCogImguiWidget::OnMouseLeave(const FPointerEvent& MouseEvent)
|
||||
{
|
||||
Super::OnMouseLeave(MouseEvent);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnTouchStarted(const FGeometry& MyGeometry, const FPointerEvent& TouchEvent)
|
||||
{
|
||||
return Super::OnTouchStarted(MyGeometry, TouchEvent);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnTouchMoved(const FGeometry& MyGeometry, const FPointerEvent& TouchEvent)
|
||||
{
|
||||
return Super::OnTouchMoved(MyGeometry, TouchEvent);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FReply SCogImguiWidget::OnTouchEnded(const FGeometry& MyGeometry, const FPointerEvent& TouchEvent)
|
||||
{
|
||||
return Super::OnTouchEnded(MyGeometry, TouchEvent);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogImguiHelper.h"
|
||||
#include "imgui.h"
|
||||
#include "Rendering/RenderingCommon.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
class FCogImguiDrawList
|
||||
{
|
||||
public:
|
||||
|
||||
struct DrawCommand
|
||||
{
|
||||
uint32 NumElements;
|
||||
FSlateRect ClippingRect;
|
||||
CogTextureIndex TextureId;
|
||||
};
|
||||
|
||||
// Get the number of draw commands in this list.
|
||||
FORCEINLINE int NumCommands() const { return ImGuiCommandBuffer.Size; }
|
||||
|
||||
// Get the draw command by number.
|
||||
// @param CommandNb - Number of draw command
|
||||
// @param Transform - Transform to apply to clipping rectangle
|
||||
// @returns Draw command data
|
||||
DrawCommand GetCommand(int CommandCount, const FTransform2D& Transform) const;
|
||||
|
||||
// Transform and copy vertex data to target buffer (old data in the target buffer are replaced).
|
||||
// @param OutVertexBuffer - Destination buffer
|
||||
// @param Transform - Transform to apply to all vertices
|
||||
void CopyVertexData(TArray<FSlateVertex>& OutVertexBuffer, const FTransform2D& Transform) const;
|
||||
|
||||
// Transform and copy index data to target buffer (old data in the target buffer are replaced).
|
||||
// Internal index buffer contains enough data to match the sum of NumElements from all draw commands.
|
||||
// @param OutIndexBuffer - Destination buffer
|
||||
// @param StartIndex - Start copying source data starting from this index
|
||||
// @param NumElements - How many elements we want to copy
|
||||
void CopyIndexData(TArray<SlateIndex>& OutIndexBuffer, const int32 StartIndex, const int32 NumElements) const;
|
||||
|
||||
// Transfers data from ImGui source list to this object. Leaves source cleared.
|
||||
void TransferDrawData(ImDrawList& Src);
|
||||
|
||||
private:
|
||||
|
||||
ImVector<ImDrawCmd> ImGuiCommandBuffer;
|
||||
ImVector<ImDrawIdx> ImGuiIndexBuffer;
|
||||
ImVector<ImDrawVert> ImGuiVertexBuffer;
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "imgui.h"
|
||||
#include "Layout/SlateRect.h"
|
||||
|
||||
struct ImGuiWindow;
|
||||
|
||||
using CogTextureIndex = int32;
|
||||
|
||||
class COGIMGUI_API FCogImguiHelper
|
||||
{
|
||||
public:
|
||||
|
||||
static FString GetIniSaveDirectory();
|
||||
|
||||
static FString GetIniFilePath(const FString& Filename);
|
||||
|
||||
static ImGuiWindow* GetCurrentWindow();
|
||||
|
||||
static FColor UnpackImU32Color(ImU32 Color);
|
||||
|
||||
static FSlateRect ToSlateRect(const ImVec4& Value);
|
||||
|
||||
static FVector2D ToVector2D(const ImVec2& Value);
|
||||
|
||||
static ImVec2 ToImVec2(const FVector2D& Value);
|
||||
|
||||
static ImColor ToImColor(const FColor& Value);
|
||||
|
||||
static ImColor ToImColor(const FLinearColor& Value);
|
||||
|
||||
static ImVec4 ToImVec4(const FColor& Value);
|
||||
|
||||
static ImVec4 ToImVec4(const FLinearColor& Value);
|
||||
|
||||
static ImVec4 ToImVec4(const FVector4f& Value);
|
||||
|
||||
static ImU32 ToImU32(const FColor& Value);
|
||||
|
||||
static ImU32 ToImU32(const FVector4f& Value);
|
||||
|
||||
static CogTextureIndex ToTextureIndex(ImTextureID Index);
|
||||
|
||||
static ImTextureID ToImTextureID(CogTextureIndex Index);
|
||||
|
||||
static FVector2D RoundVector(const FVector2D& Vector);
|
||||
|
||||
static FSlateRenderTransform RoundTranslation(const FSlateRenderTransform& Transform);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogImguiInputHelper.h"
|
||||
#include "imgui.h"
|
||||
|
||||
struct FCogImGuiKeyInfo;
|
||||
|
||||
class COGIMGUI_API FCogImguiInputHelper
|
||||
{
|
||||
public:
|
||||
|
||||
static APlayerController* GetFirstLocalPlayerController(UWorld& World);
|
||||
|
||||
static bool IsKeyEventHandled(const FKeyEvent& KeyEvent);
|
||||
|
||||
static bool WasKeyInfoJustPressed(APlayerController& PlayerController, const FCogImGuiKeyInfo& KeyInfo);
|
||||
|
||||
static bool IsCheckBoxStateMatchingValue(ECheckBoxState CheckBoxState, bool bValue);
|
||||
|
||||
static bool IsKeyEventMatchingKeyInfo(const FKeyEvent& KeyEvent, const FCogImGuiKeyInfo& InputChord);
|
||||
|
||||
static bool IsConsoleEvent(const FKeyEvent& KeyEvent);
|
||||
|
||||
static bool IsImGuiToggleInputEvent(const FKeyEvent& KeyEvent);
|
||||
|
||||
static bool IsStopPlaySessionEvent(const FKeyEvent& KeyEvent);
|
||||
|
||||
static ImGuiKey KeyEventToImGuiKey(const FKeyEvent& KeyEvent);
|
||||
|
||||
static uint32 MouseButtonToImGuiMouseButton(const FKey& MouseButton);
|
||||
|
||||
static EMouseCursor::Type ToSlateMouseCursor(ImGuiMouseCursor MouseCursor);
|
||||
|
||||
template<typename T, std::enable_if_t<(sizeof(T) <= sizeof(ImWchar)), T>* = nullptr>
|
||||
static ImWchar CastInputChar(T Char)
|
||||
{
|
||||
return static_cast<ImWchar>(Char);
|
||||
}
|
||||
|
||||
static void InitializeKeyMap();
|
||||
|
||||
static TMap<FKey, ImGuiKey> KeyMap;
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "InputCoreTypes.h"
|
||||
#include "CogImGuiKeyInfo.generated.h"
|
||||
|
||||
USTRUCT()
|
||||
struct COGIMGUI_API FCogImGuiKeyInfo
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
FKey Key = EKeys::Invalid;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
ECheckBoxState Shift = ECheckBoxState::Undetermined;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
ECheckBoxState Ctrl = ECheckBoxState::Undetermined;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
ECheckBoxState Alt = ECheckBoxState::Undetermined;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
ECheckBoxState Cmd = ECheckBoxState::Undetermined;
|
||||
|
||||
FCogImGuiKeyInfo()
|
||||
{
|
||||
}
|
||||
|
||||
FCogImGuiKeyInfo(const FKey InKey,
|
||||
const ECheckBoxState InShift = ECheckBoxState::Undetermined,
|
||||
const ECheckBoxState InCtrl = ECheckBoxState::Undetermined,
|
||||
const ECheckBoxState InAlt = ECheckBoxState::Undetermined,
|
||||
const ECheckBoxState InCmd = ECheckBoxState::Undetermined)
|
||||
: Key(InKey)
|
||||
, Shift(InShift)
|
||||
, Ctrl(InCtrl)
|
||||
, Alt(InAlt)
|
||||
, Cmd(InCmd)
|
||||
{
|
||||
}
|
||||
|
||||
friend bool operator==(const FCogImGuiKeyInfo& Lhs, const FCogImGuiKeyInfo& Rhs)
|
||||
{
|
||||
return Lhs.Key == Rhs.Key
|
||||
&& Lhs.Shift == Rhs.Shift
|
||||
&& Lhs.Ctrl == Rhs.Ctrl
|
||||
&& Lhs.Alt == Rhs.Alt
|
||||
&& Lhs.Cmd == Rhs.Cmd;
|
||||
}
|
||||
|
||||
friend bool operator!=(const FCogImGuiKeyInfo& Lhs, const FCogImGuiKeyInfo& Rhs)
|
||||
{
|
||||
return !(Lhs == Rhs);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogImguiWidget.h"
|
||||
#include "CogImguiKeyInfo.h"
|
||||
#include "CogImguiTextureManager.h"
|
||||
#include "imgui.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class COGIMGUI_API FCogImguiModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
static inline FCogImguiModule& Get()
|
||||
{
|
||||
return FModuleManager::LoadModuleChecked<FCogImguiModule>("CogImgui");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// IModuleInterface implementation
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
TSharedPtr<SCogImguiWidget> CreateImGuiViewport(UGameViewportClient* GameViewport, FCogImguiRenderFunction Render, ImFontAtlas* FontAtlas = nullptr);
|
||||
|
||||
FCogImguiTextureManager& GetTextureManager() { return TextureManager; }
|
||||
|
||||
ImFontAtlas& GetDefaultFontAtlas() { return DefaultFontAtlas; }
|
||||
|
||||
bool GetEnableInput() const { return bEnabledInput; }
|
||||
|
||||
void SetEnableInput(bool Value) { bEnabledInput = Value; }
|
||||
|
||||
void ToggleEnableInput() { bEnabledInput = !bEnabledInput; }
|
||||
|
||||
const FCogImGuiKeyInfo& GetToggleInputKey() const { return ToggleInputKey; }
|
||||
|
||||
void SetToggleInputKey(const FCogImGuiKeyInfo& Value) { ToggleInputKey = Value; }
|
||||
|
||||
private:
|
||||
|
||||
void Initialize();
|
||||
|
||||
FCogImguiTextureManager TextureManager;
|
||||
ImFontAtlas DefaultFontAtlas;
|
||||
bool bEnabledInput = true;
|
||||
bool bIsInitialized = false;
|
||||
FCogImGuiKeyInfo ToggleInputKey;
|
||||
};
|
||||
@@ -0,0 +1,147 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogImguiHelper.h"
|
||||
#include "Engine/Texture2D.h"
|
||||
#include "Styling/SlateBrush.h"
|
||||
#include "Textures/SlateShaderResource.h"
|
||||
#include "UObject/WeakObjectPtr.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
class FCogImguiTextureManager
|
||||
{
|
||||
public:
|
||||
|
||||
// Creates an empty manager.
|
||||
FCogImguiTextureManager() = default;
|
||||
|
||||
// Copying is disabled to protected resource ownership.
|
||||
FCogImguiTextureManager(const FCogImguiTextureManager&) = delete;
|
||||
FCogImguiTextureManager& operator=(const FCogImguiTextureManager&) = delete;
|
||||
|
||||
// Moving transfers ownership and leaves source empty.
|
||||
FCogImguiTextureManager(FCogImguiTextureManager&&) = delete;
|
||||
FCogImguiTextureManager& operator=(FCogImguiTextureManager&&) = delete;
|
||||
|
||||
void InitializeErrorTexture();
|
||||
|
||||
// Find texture index by name.
|
||||
// @param Name - The name of a texture to find
|
||||
// @returns The index of a texture with given name or INDEX_NONE if there is no such texture
|
||||
CogTextureIndex FindTextureIndex(const FName& Name) const
|
||||
{
|
||||
return TextureResources.IndexOfByPredicate([&](const auto& Entry) { return Entry.GetName() == Name; });
|
||||
}
|
||||
|
||||
// Get the name of a texture at given index. Returns NAME_None, if index is out of range.
|
||||
// @param Index - Index of a texture
|
||||
// @returns The name of a texture at given index or NAME_None if index is out of range.
|
||||
FName GetTextureName(CogTextureIndex Index) const
|
||||
{
|
||||
return IsInRange(Index) ? TextureResources[Index].GetName() : NAME_None;
|
||||
}
|
||||
|
||||
// Get the Slate Resource Handle to a texture at given index. If index is out of range or resources are not valid
|
||||
// it returns a handle to the error texture.
|
||||
// @param Index - Index of a texture
|
||||
// @returns The Slate Resource Handle for a texture at given index or to error texture, if no valid resources were
|
||||
// found at given index
|
||||
const FSlateResourceHandle& GetTextureHandle(CogTextureIndex Index) const
|
||||
{
|
||||
return IsValidTexture(Index) ? TextureResources[Index].GetResourceHandle() : ErrorTexture.GetResourceHandle();
|
||||
}
|
||||
|
||||
// Create a texture from raw data.
|
||||
// @param Name - The texture name
|
||||
// @param Width - The texture width
|
||||
// @param Height - The texture height
|
||||
// @param SrcBpp - The size in bytes of one pixel
|
||||
// @param SrcData - The source data
|
||||
// @param SrcDataCleanup - Optional function called to release source data after texture is created (only needed, if data need to be released)
|
||||
// @returns The index of a texture that was created
|
||||
CogTextureIndex CreateTexture(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction<void(uint8*)> SrcDataCleanup = [](uint8*) {});
|
||||
|
||||
// Create a plain texture.
|
||||
// @param Name - The texture name
|
||||
// @param Width - The texture width
|
||||
// @param Height - The texture height
|
||||
// @param Color - The texture color
|
||||
// @returns The index of a texture that was created
|
||||
CogTextureIndex CreatePlainTexture(const FName& Name, int32 Width, int32 Height, FColor Color);
|
||||
|
||||
// Create Slate resources to an existing texture, managed externally.
|
||||
// @param Name - The texture name
|
||||
// @param Texture - The texture
|
||||
// @returns The index to created/updated texture resources
|
||||
CogTextureIndex CreateTextureResources(const FName& Name, UTexture2D* Texture);
|
||||
|
||||
// Release resources for given texture. Ignores invalid indices.
|
||||
// @param Index - The index of a texture resources
|
||||
void ReleaseTextureResources(CogTextureIndex Index);
|
||||
|
||||
private:
|
||||
|
||||
// See CreateTexture for general description.
|
||||
// Internal implementations doesn't validate name or resource uniqueness. Instead it uses NAME_ErrorTexture
|
||||
// (aka NAME_None) and INDEX_ErrorTexture (aka INDEX_NONE) to identify ErrorTexture.
|
||||
CogTextureIndex CreateTextureInternal(const FName& Name, int32 Width, int32 Height, uint32 SrcBpp, uint8* SrcData, TFunction<void(uint8*)> SrcDataCleanup = [](uint8*) {});
|
||||
|
||||
// See CreatePlainTexture for general description.
|
||||
// Internal implementations doesn't validate name or resource uniqueness. Instead it uses NAME_ErrorTexture
|
||||
// (aka NAME_None) and INDEX_ErrorTexture (aka INDEX_NONE) to identify ErrorTexture.
|
||||
CogTextureIndex CreatePlainTextureInternal(const FName& Name, int32 Width, int32 Height, const FColor& Color);
|
||||
|
||||
// Add or reuse texture entry.
|
||||
// @param Name - The texture name
|
||||
// @param Texture - The texture
|
||||
// @param bAddToRoot - If true, we should add texture to root to prevent garbage collection (use for own textures)
|
||||
// @returns The index of the entry that we created or reused
|
||||
CogTextureIndex AddTextureEntry(const FName& Name, UTexture2D* Texture, bool bAddToRoot);
|
||||
|
||||
// Check whether index is in range allocated for TextureResources (it doesn't mean that resources are valid).
|
||||
FORCEINLINE bool IsInRange(CogTextureIndex Index) const
|
||||
{
|
||||
return static_cast<uint32>(Index) < static_cast<uint32>(TextureResources.Num());
|
||||
}
|
||||
|
||||
// Check whether index is in range and whether texture resources are valid (using NAME_None sentinel).
|
||||
FORCEINLINE bool IsValidTexture(CogTextureIndex Index) const
|
||||
{
|
||||
return IsInRange(Index) && TextureResources[Index].GetName() != NAME_None;
|
||||
}
|
||||
|
||||
// Entry for texture resources. Only supports explicit construction.
|
||||
struct FTextureEntry
|
||||
{
|
||||
FTextureEntry() = default;
|
||||
FTextureEntry(const FName& InName, UTexture2D* InTexture, bool bAddToRoot);
|
||||
~FTextureEntry();
|
||||
|
||||
// Copying is not supported.
|
||||
FTextureEntry(const FTextureEntry&) = delete;
|
||||
FTextureEntry& operator=(const FTextureEntry&) = delete;
|
||||
|
||||
// We rely on TArray and don't implement custom move constructor...
|
||||
FTextureEntry(FTextureEntry&&) = delete;
|
||||
// ... but we need move assignment to support reusing entries.
|
||||
FTextureEntry& operator=(FTextureEntry&& Other);
|
||||
|
||||
const FName& GetName() const { return Name; }
|
||||
const FSlateResourceHandle& GetResourceHandle() const;
|
||||
|
||||
private:
|
||||
|
||||
void Reset(bool bReleaseResources);
|
||||
|
||||
FName Name = NAME_None;
|
||||
mutable FSlateResourceHandle CachedResourceHandle;
|
||||
TWeakObjectPtr<UTexture2D> Texture;
|
||||
FSlateBrush Brush;
|
||||
};
|
||||
|
||||
TArray<FTextureEntry> TextureResources;
|
||||
FTextureEntry ErrorTexture;
|
||||
|
||||
static constexpr EName NAME_ErrorTexture = NAME_None;
|
||||
static constexpr CogTextureIndex INDEX_ErrorTexture = INDEX_NONE;
|
||||
};
|
||||
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogImguiDrawList.h"
|
||||
#include "Rendering/RenderingCommon.h"
|
||||
#include "UObject/WeakObjectPtr.h"
|
||||
#include "Widgets/DeclarativeSyntaxSupport.h"
|
||||
#include "Widgets/SCompoundWidget.h"
|
||||
|
||||
class UGameViewportClient;
|
||||
class ULocalPlayer;
|
||||
struct ImFontAtlas;
|
||||
struct ImGuiContext;
|
||||
struct ImPlotContext;
|
||||
|
||||
using FCogImguiRenderFunction = TFunction<void(float DeltaTime)>;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
class COGIMGUI_API SCogImguiWidget : public SCompoundWidget
|
||||
{
|
||||
typedef SCompoundWidget Super;
|
||||
|
||||
public:
|
||||
|
||||
SLATE_BEGIN_ARGS(SCogImguiWidget) {}
|
||||
SLATE_ARGUMENT(UGameViewportClient*, GameViewport)
|
||||
SLATE_ARGUMENT(ImFontAtlas*, FontAtlas)
|
||||
SLATE_ARGUMENT(FCogImguiRenderFunction, Render)
|
||||
SLATE_END_ARGS()
|
||||
|
||||
void Construct(const FArguments& InArgs);
|
||||
|
||||
~SCogImguiWidget();
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// SWidget overrides
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;
|
||||
virtual bool SupportsKeyboardFocus() const override { return true; }
|
||||
virtual FReply OnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) override;
|
||||
virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override;
|
||||
virtual FReply OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override;
|
||||
virtual FReply OnAnalogValueChanged(const FGeometry& MyGeometry, const FAnalogInputEvent& AnalogInputEvent) override;
|
||||
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
||||
virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
||||
virtual FReply OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
||||
virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
||||
virtual FReply OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& FocusEvent) override;
|
||||
virtual void OnFocusLost(const FFocusEvent& FocusEvent) override;
|
||||
virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
||||
virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override;
|
||||
virtual FReply OnTouchStarted(const FGeometry& MyGeometry, const FPointerEvent& TouchEvent) override;
|
||||
virtual FReply OnTouchMoved(const FGeometry& MyGeometry, const FPointerEvent& TouchEvent) override;
|
||||
virtual FReply OnTouchEnded(const FGeometry& MyGeometry, const FPointerEvent& TouchEvent) override;
|
||||
virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& WidgetStyle, bool bParentEnabled) const override;
|
||||
virtual FVector2D ComputeDesiredSize(float Scale) const override;
|
||||
|
||||
ULocalPlayer* SCogImguiWidget::GetLocalPlayer() const;
|
||||
|
||||
float GetDpiScale() const { return DpiScale; }
|
||||
|
||||
void SetDPIScale(float Scale);
|
||||
|
||||
bool IsCurrentContext() const;
|
||||
|
||||
void SetAsCurrentContext();
|
||||
|
||||
protected:
|
||||
|
||||
FVector2D TransformScreenPointToImGui(const FGeometry& MyGeometry, const FVector2D& Point) const;
|
||||
|
||||
virtual void TickKeyModifiers();
|
||||
|
||||
virtual void TickImGui(float InDeltaTime);
|
||||
|
||||
virtual void TickFocus();
|
||||
|
||||
virtual void TakeFocus();
|
||||
|
||||
virtual void ReturnFocus();
|
||||
|
||||
virtual void OnDpiChanged();
|
||||
|
||||
bool IsConsoleOpened() const;
|
||||
|
||||
TWeakObjectPtr<UGameViewportClient> GameViewport;
|
||||
|
||||
ImFontAtlas* FontAtlas;
|
||||
|
||||
TWeakPtr<SWidget> PreviousUserFocusedWidget;
|
||||
|
||||
bool bEnableInput = false;
|
||||
|
||||
FSlateRenderTransform ImGuiRenderTransform;
|
||||
|
||||
mutable TArray<FSlateVertex> VertexBuffer;
|
||||
|
||||
mutable TArray<SlateIndex> IndexBuffer;
|
||||
|
||||
TArray<FCogImguiDrawList> DrawLists;
|
||||
|
||||
ImGuiContext* ImGuiContext = nullptr;
|
||||
|
||||
ImPlotContext* ImPlotContext = nullptr;
|
||||
|
||||
FCogImguiRenderFunction Render;
|
||||
|
||||
float DpiScale = 1.f;
|
||||
|
||||
char IniFilename[512];
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class CogWindow : ModuleRules
|
||||
{
|
||||
public CogWindow(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CogImgui",
|
||||
"CogDebug",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"InputCore",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"NetCore",
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user