First Submit

This commit is contained in:
Arnaud Jamin
2023-10-02 01:32:41 -04:00
parent c34574e841
commit 1aabdb5c4e
445 changed files with 93851 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "CogAbility",
"Description": "",
"Category": "Other",
"CreatedBy": "Arnaud Jamin",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "CogAbility",
"Type": "Runtime",
"LoadingPhase": "Default"
}
],
"Plugins": [
{
"Name": "CogImgui",
"Enabled": true
},
{
"Name": "CogDebug",
"Enabled": true
},
{
"Name": "CogWindow",
"Enabled": true
},
{
"Name": "GameplayAbilities",
"Enabled": true
}
]
}
@@ -0,0 +1,50 @@
using UnrealBuildTool;
public class CogAbility : ModuleRules
{
public CogAbility(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
}
);
PrivateIncludePaths.AddRange(
new string[] {
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"CogImgui",
"CogDebug",
"CogWindow",
"GameplayAbilities",
"GameplayTags",
"NetCore",
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
}
);
}
}
@@ -0,0 +1,9 @@
#include "CogAbilityHelper.h"
//--------------------------------------------------------------------------------------------------------------------------
FString FCogAbilityHelper::CleanupName(FString Str)
{
Str.RemoveFromStart(TEXT("Default__"));
Str.RemoveFromEnd(TEXT("_c"));
return Str;
}
@@ -0,0 +1,50 @@
#include "CogAbilityModule.h"
#include "CogAbilityReplicator.h"
#define LOCTEXT_NAMESPACE "FCogAbilityModule"
//--------------------------------------------------------------------------------------------------------------------------
void FCogAbilityModule::StartupModule()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogAbilityModule::ShutdownModule()
{
}
//--------------------------------------------------------------------------------------------------------------------------
ACogAbilityReplicator* FCogAbilityModule::GetLocalReplicator()
{
return LocalReplicator;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogAbilityModule::SetLocalReplicator(ACogAbilityReplicator* Value)
{
LocalReplicator = Value;
}
//--------------------------------------------------------------------------------------------------------------------------
ACogAbilityReplicator* FCogAbilityModule::GetRemoteReplicator(const APlayerController* PlayerController)
{
for (ACogAbilityReplicator* Replicator : RemoteReplicators)
{
if (Replicator->GetPlayerController() == PlayerController)
{
return Replicator;
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogAbilityModule::AddRemoteReplicator(ACogAbilityReplicator* Value)
{
RemoteReplicators.Add(Value);
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FCogAbilityModule, CogAbility)
@@ -0,0 +1,378 @@
#include "CogAbilityReplicator.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "Components/SceneComponent.h"
#include "EngineUtils.h"
#include "GameplayEffect.h"
#include "Net/Core/PushModel/PushModel.h"
#include "Net/UnrealNetwork.h"
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::Create(APlayerController* Controller)
{
if (Controller->GetWorld()->GetNetMode() != NM_Client)
{
FActorSpawnParameters SpawnInfo;
SpawnInfo.Owner = Controller;
Controller->GetWorld()->SpawnActor<ACogAbilityReplicator>(SpawnInfo);
}
}
//--------------------------------------------------------------------------------------------------------------------------
ACogAbilityReplicator::ACogAbilityReplicator(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
bReplicates = true;
RootComponent = ObjectInitializer.CreateOptionalDefaultSubobject<USceneComponent>(this, TEXT("Root"));
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
FDoRepLifetimeParams Params;
Params.bIsPushBased = true;
Params.Condition = COND_OwnerOnly;
DOREPLIFETIME_WITH_PARAMS_FAST(ACogAbilityReplicator, TweakCurrentValues, Params);
DOREPLIFETIME_WITH_PARAMS_FAST(ACogAbilityReplicator, TweakProfileIndex, Params);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::BeginPlay()
{
Super::BeginPlay();
OwnerPlayerController = Cast<APlayerController>(GetOwner());
if (OwnerPlayerController->IsLocalController())
{
FCogAbilityModule::Get().SetLocalReplicator(this);
}
else
{
FCogAbilityModule::Get().AddRemoteReplicator(this);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::ApplyCheat(AActor* CheatInstigator, const TArray<AActor*>& Targets, const FCogAbilityCheat& Cheat)
{
Server_ApplyCheat(CheatInstigator, Targets, Cheat);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::Server_ApplyCheat_Implementation(const AActor* CheatInstigator, const TArray<AActor*>& Targets, const FCogAbilityCheat& Cheat) const
{
UAbilitySystemComponent* InstigatorAbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(CheatInstigator, true);
if (InstigatorAbilitySystem == nullptr)
{
return;
}
for (AActor* Target : Targets)
{
UAbilitySystemComponent* TargetAbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Target, true);
if (TargetAbilitySystem == nullptr)
{
continue;
}
if (TargetAbilitySystem->GetGameplayEffectCount(Cheat.Effect, nullptr) > 0)
{
TargetAbilitySystem->RemoveActiveGameplayEffectBySourceEffect(Cheat.Effect, nullptr);
}
else
{
FGameplayEffectContextHandle ContextHandle = InstigatorAbilitySystem->MakeEffectContext();
ContextHandle.AddSourceObject(InstigatorAbilitySystem);
FGameplayEffectSpecHandle SpecHandle = InstigatorAbilitySystem->MakeOutgoingSpec(Cheat.Effect, 1, ContextHandle);
if (FGameplayEffectSpec* EffectSpec = SpecHandle.Data.Get())
{
FHitResult HitResult;
HitResult.HitObjectHandle = FActorInstanceHandle(Target);
HitResult.Normal = FVector::ForwardVector;
HitResult.ImpactNormal = FVector::ForwardVector;
HitResult.Location = Target->GetActorLocation();
HitResult.ImpactPoint = Target->GetActorLocation();
HitResult.PhysMaterial = nullptr;
ContextHandle.AddHitResult(HitResult, true);
InstigatorAbilitySystem->ApplyGameplayEffectSpecToTarget(*EffectSpec, TargetAbilitySystem);
}
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
bool ACogAbilityReplicator::IsCheatActive(const AActor* EffectTarget, const FCogAbilityCheat& Cheat)
{
if (Cheat.Effect == nullptr)
{
return false;
}
UAbilitySystemComponent* AbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(EffectTarget, true);
if (AbilitySystem == nullptr)
{
return false;
}
const int32 Count = AbilitySystem->GetGameplayEffectCount(Cheat.Effect, nullptr);
return Count > 0;
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::GiveAbility(AActor* Target, TSubclassOf<UGameplayAbility> AbilityClass)
{
Server_GiveAbility(Target, AbilityClass);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::Server_GiveAbility_Implementation(AActor* TargetActor, TSubclassOf<UGameplayAbility> AbilityClass) const
{
UAbilitySystemComponent* AbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(TargetActor, true);
if (AbilitySystem == nullptr)
{
return;
}
if (IsValid(AbilityClass) == false)
{
return;
}
if (AbilitySystem->IsOwnerActorAuthoritative() == false)
{
return;
}
const FGameplayAbilitySpec Spec(AbilityClass, 1, INDEX_NONE, TargetActor);
AbilitySystem->GiveAbility(Spec);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::ResetAllTweaks()
{
Server_ResetAllTweaks();
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::Server_ResetAllTweaks_Implementation()
{
TweakCurrentValues.Empty();
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::SetTweakValue(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 TweakCategoryIndex, float Value)
{
Server_SetTweakValue(TweaksAsset, TweakIndex, TweakCategoryIndex, Value);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::Server_SetTweakValue_Implementation(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 TweakCategoryIndex, float Value)
{
if (TweaksAsset == nullptr)
{
return;
}
if (TweaksAsset->Tweaks.IsValidIndex(TweakIndex) == false)
{
return;
}
if (TweaksAsset->TweaksCategories.IsValidIndex(TweakCategoryIndex) == false)
{
return;
}
SetTweakCurrentValue(TweaksAsset, TweakIndex, TweakCategoryIndex, Value);
const FCogAbilityTweak& Tweak = TweaksAsset->Tweaks[TweakIndex];
TArray<AActor*> Actors;
GetActorsFromTweakCategory(TweaksAsset, TweakCategoryIndex, Actors);
for (AActor* Actor : Actors)
{
ApplyTweakOnActor(Actor, Tweak, Value, TweaksAsset->SetByCallerMagnitudeTag);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::ApplyAllTweaksOnActor(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakCategoryIndex, AActor* Actor)
{
if (TweaksAsset == nullptr)
{
return;
}
if (TweaksAsset->TweaksCategories.IsValidIndex(TweakCategoryIndex) == false)
{
return;
}
int32 TweakIndex = 0;
for (const FCogAbilityTweak& Tweak : TweaksAsset->Tweaks)
{
const float Value = GetTweakCurrentValue(TweaksAsset, TweakIndex, TweakCategoryIndex);
ApplyTweakOnActor(Actor, Tweak, Value, TweaksAsset->SetByCallerMagnitudeTag);
TweakIndex++;
}
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::ApplyTweakOnActor(AActor* Actor, const FCogAbilityTweak& Tweak, float Value, const FGameplayTag& SetByCallerMagnitudeTag)
{
UAbilitySystemComponent* AbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Actor, true);
if (AbilitySystem == nullptr)
{
return;
}
AbilitySystem->RemoveActiveGameplayEffectBySourceEffect(Tweak.Effect, nullptr);
if (Value != 0.0f)
{
FGameplayEffectSpecHandle SpecHandle = AbilitySystem->MakeOutgoingSpec(Tweak.Effect, 1, AbilitySystem->MakeEffectContext());
if (FGameplayEffectSpec* EffectSpec = SpecHandle.Data.Get())
{
EffectSpec->SetSetByCallerMagnitude(SetByCallerMagnitudeTag, (Value * Tweak.Multiplier) + Tweak.AddPostMultiplier);
AbilitySystem->ApplyGameplayEffectSpecToSelf(*EffectSpec);
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
float ACogAbilityReplicator::GetTweakCurrentValue(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 TweakCategoryIndex)
{
float* Value = GetTweakCurrentValuePtr(TweaksAsset, TweakIndex, TweakCategoryIndex);
if (Value == nullptr)
{
return 0.0f;
}
return *Value;
}
//--------------------------------------------------------------------------------------------------------------------------
float* ACogAbilityReplicator::GetTweakCurrentValuePtr(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 TweakCategoryIndex)
{
TweakCurrentValues.SetNum(TweaksAsset->Tweaks.Num() * TweaksAsset->TweaksCategories.Num());
const int32 Index = TweakIndex + (TweakCategoryIndex * TweaksAsset->Tweaks.Num());
if (TweakCurrentValues.IsValidIndex(Index) == false)
{
return nullptr;
}
return &TweakCurrentValues[Index];
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::SetTweakCurrentValue(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 TweakCategoryIndex, float Value)
{
if (TweaksAsset == nullptr)
{
return;
}
TweakCurrentValues.SetNum(TweaksAsset->Tweaks.Num() * TweaksAsset->TweaksCategories.Num());
const int32 Index = TweakIndex + (TweakCategoryIndex * TweaksAsset->Tweaks.Num());
if (TweakCurrentValues.IsValidIndex(TweakIndex) == false)
{
return;
}
TweakCurrentValues[Index] = Value;
MARK_PROPERTY_DIRTY_FROM_NAME(ACogAbilityReplicator, TweakCurrentValues, this);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::SetTweakProfile(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 ProfileIndex)
{
Server_SetTweakProfile(TweaksAsset, ProfileIndex);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::Server_SetTweakProfile_Implementation(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 ProfileIndex)
{
if (TweaksAsset == nullptr)
{
return;
}
if (TweaksAsset->TweakProfiles.IsValidIndex(ProfileIndex) == false)
{
ProfileIndex = INDEX_NONE;
}
TweakProfileIndex = ProfileIndex;
MARK_PROPERTY_DIRTY_FROM_NAME(ACogAbilityReplicator, TweakProfileIndex, this);
ResetAllTweaks();
if (TweaksAsset->TweakProfiles.IsValidIndex(TweakProfileIndex))
{
const FCogAbilityTweakProfile& TweakProfile = TweaksAsset->TweakProfiles[TweakProfileIndex];
for (const FCogAbilityTweakProfileValue& ProfileTweak : TweakProfile.Tweaks)
{
const int32 TweakIndex = TweaksAsset->Tweaks.IndexOfByPredicate([ProfileTweak](const FCogAbilityTweak& Tweak) { return ProfileTweak.Effect == Tweak.Effect; });
const int32 TweakCategoryIndex = TweaksAsset->TweaksCategories.IndexOfByPredicate([ProfileTweak](const FCogAbilityTweakCategory& TweakCategory) { return ProfileTweak.CategoryId == TweakCategory.Id; });
if (TweakIndex != INDEX_NONE && TweakCategoryIndex != INDEX_NONE)
{
SetTweakCurrentValue(TweaksAsset, TweakIndex, TweakCategoryIndex, ProfileTweak.Value);
}
}
}
for (int32 TweakCategoryIndex = 0; TweakCategoryIndex < TweaksAsset->TweaksCategories.Num(); ++TweakCategoryIndex)
{
TArray<AActor*> Actors;
GetActorsFromTweakCategory(TweaksAsset, TweakCategoryIndex, Actors);
for (AActor* Actor : Actors)
{
ApplyAllTweaksOnActor(TweaksAsset, TweakCategoryIndex, Actor);
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogAbilityReplicator::GetActorsFromTweakCategory(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakCategoryIndex, TArray<AActor*>& Actors)
{
if (TweaksAsset == nullptr)
{
return;
}
if (TweaksAsset->TweaksCategories.IsValidIndex(TweakCategoryIndex) == false)
{
return;
}
const FCogAbilityTweakCategory& TweakCategory = TweaksAsset->TweaksCategories[TweakCategoryIndex];
for (TActorIterator<AActor> It(GetWorld(), TweakCategory.ActorClass); It; ++It)
{
AActor* Actor = *It;
if (UAbilitySystemComponent* AbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Actor, true))
{
const bool bHasRequiredTags = AbilitySystem->HasAllMatchingGameplayTags(TweakCategory.RequiredTags);
const bool bHasIgnoredTags = AbilitySystem->HasAnyMatchingGameplayTags(TweakCategory.IgnoredTags);
if (bHasRequiredTags && bHasIgnoredTags == false)
{
Actors.AddUnique(Actor);
}
}
}
}
@@ -0,0 +1,440 @@
#include "CogAbilityWindow_Abilities.h"
#include "CogAbilityDataAsset_Abilities.h"
#include "CogAbilityHelper.h"
#include "CogWindowWidgets.h"
#include "imgui.h"
#include "imgui_internal.h"
ImVec4 ActiveColor(1.0f, 0.8f, 0.0f, 1.0f);
ImVec4 DeactiveColor(1.0f, 1.0f, 1.0f, 1.0f);
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::PreRender(ImGuiWindowFlags& WindowFlags)
{
WindowFlags = ImGuiWindowFlags_MenuBar;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::RenderTick(float DetlaTime)
{
Super::RenderTick(DetlaTime);
RenderOpenAbilities();
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::RenderOpenAbilities()
{
AActor* Selection = GetSelection();
if (Selection == nullptr)
{
return;
}
UAbilitySystemComponent* AbilitySystemComponent = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Selection, true);
if (AbilitySystemComponent == nullptr)
{
return;
}
for (int i = OpenedAbilities.Num() - 1; i >= 0; --i)
{
FGameplayAbilitySpecHandle Handle = OpenedAbilities[i];
FGameplayAbilitySpec* Spec = AbilitySystemComponent->FindAbilitySpecFromHandle(Handle);
if (Spec == nullptr)
{
continue;
}
UGameplayAbility* Ability = Spec->GetPrimaryInstance();
if (Ability == nullptr)
{
Ability = Spec->Ability;
}
bool Open = true;
if (ImGui::Begin(TCHAR_TO_ANSI(*GetAbilityName(Ability)), &Open))
{
RenderAbilityInfo(*Spec);
ImGui::End();
}
if (Open == false)
{
OpenedAbilities.RemoveAt(i);
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::RenderContent()
{
Super::RenderContent();
AActor* Selection = GetSelection();
if (Selection == nullptr)
{
return;
}
UAbilitySystemComponent* AbilitySystemComponent = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Selection, true);
if (AbilitySystemComponent == nullptr)
{
return;
}
RenderAbiltiesMenu(Selection);
//TArray<FGameplayAbilitySpec>& Abilities = AbilitySystemComponent->GetActivatableAbilities();
//static int FocusedAbilityIndex = INDEX_NONE;
//if (FocusedAbilityIndex != INDEX_NONE && FocusedAbilityIndex < Abilities.Num())
//{
// RenderAbilityInfo(Abilities[FocusedAbilityIndex]);
// if (ImGui::Button("Close", ImVec2(-1, 0)))
// {
// FocusedAbilityIndex = INDEX_NONE;
// }
// ImGui::Spacing();
//}
RenderAbilitiesTable(*AbilitySystemComponent);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::RenderAbiltiesMenu(AActor* Selection)
{
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("Add"))
{
if (AbilitiesAsset != nullptr)
{
int Index = 0;
for (TSubclassOf<UGameplayAbility> AbilityClass : AbilitiesAsset->Abilities)
{
ImGui::PushID(Index);
if (ImGui::MenuItem(TCHAR_TO_ANSI(*GetNameSafe(AbilityClass))))
{
FCogAbilityModule& Module = FCogAbilityModule::Get();
if (ACogAbilityReplicator* Replicator = Module.GetLocalReplicator())
{
Replicator->GiveAbility(Selection, AbilityClass);
}
}
ImGui::PopID();
Index++;
}
}
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::RenderAbilitiesTable(UAbilitySystemComponent& AbilitySystemComponent)
{
TArray<FGameplayAbilitySpec>& Abilities = AbilitySystemComponent.GetActivatableAbilities();
if (ImGui::BeginTable("Abilities", 4, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersH | ImGuiTableFlags_NoBordersInBody))
{
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Ability");
ImGui::TableSetupColumn("Level");
ImGui::TableSetupColumn("Input");
ImGui::TableHeadersRow();
static int SelectedIndex = -1;
int Index = 0;
for (FGameplayAbilitySpec& Spec : Abilities)
{
UGameplayAbility* Ability = Spec.GetPrimaryInstance();
if (Ability == nullptr)
{
Ability = Spec.Ability;
}
ImGui::TableNextRow();
ImGui::PushID(Index);
ImVec4 Color = Spec.ActiveCount > 0 ? ActiveColor : DeactiveColor;
ImGui::PushStyleColor(ImGuiCol_Text, Color);
//------------------------
// Activation
//------------------------
ImGui::TableNextColumn();
FCogWindowWidgets::PushStyleCompact();
bool IsActive = Spec.IsActive();
if (ImGui::Checkbox("##Activation", &IsActive))
{
AbilityHandleToActivate = Spec.Handle;
}
FCogWindowWidgets::PopStyleCompact();
//------------------------
// Name
//------------------------
ImGui::TableNextColumn();
if (ImGui::Selectable(TCHAR_TO_ANSI(*GetAbilityName(Ability)), SelectedIndex == Index, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap | ImGuiSelectableFlags_AllowDoubleClick))
{
SelectedIndex = Index;
if (ImGui::IsMouseDoubleClicked(0))
{
OpenAbility(Spec.Handle);
}
}
ImGui::PopStyleColor(1);
//------------------------
// Popup
//------------------------
if (ImGui::IsItemHovered())
{
FCogWindowWidgets::BeginTableTooltip();
RenderAbilityInfo(Spec);
FCogWindowWidgets::EndTableTooltip();
}
//------------------------
// ContextMenu
//------------------------
RenderAbilityContextMenu(AbilitySystemComponent, Spec, Index);
ImGui::PushStyleColor(ImGuiCol_Text, Color);
//------------------------
// Level
//------------------------
ImGui::TableNextColumn();
ImGui::Text("%d", Spec.Level);
//------------------------
// InputPressed
//------------------------
ImGui::TableNextColumn();
if (Spec.InputPressed > 0)
{
ImGui::Text("%d", Spec.InputPressed);
}
ImGui::PopStyleColor(1);
ImGui::PopID();
Index++;
}
ImGui::EndTable();
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::RenderAbilityContextMenu(UAbilitySystemComponent& AbilitySystemComponent, FGameplayAbilitySpec& Spec, int Index)
{
if (ImGui::BeginPopupContextItem())
{
bool bOpen = OpenedAbilities.Contains(Spec.Handle);
if (ImGui::Checkbox("Open", &bOpen))
{
if (bOpen)
{
OpenAbility(Spec.Handle);
}
else
{
CloseAbility(Spec.Handle);
}
ImGui::CloseCurrentPopup();
}
//if (ImGui::Button("Open Properties"))
//{
// GetOwner()->GetPropertyGrid()->Open(BaseAbility);
// ImGui::CloseCurrentPopup();
//}
ImGui::EndPopup();
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::OpenAbility(FGameplayAbilitySpecHandle Handle)
{
OpenedAbilities.AddUnique(Handle);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::CloseAbility(FGameplayAbilitySpecHandle Handle)
{
OpenedAbilities.Remove(Handle);
}
//--------------------------------------------------------------------------------------------------------------------------
FString UCogAbilityWindow_Abilities::GetAbilityName(const UGameplayAbility* Ability)
{
if (Ability == nullptr)
{
return FString("NULL");
}
FString Str = FCogAbilityHelper::CleanupName(Ability->GetName());
return Str;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::RenderAbilityInfo(FGameplayAbilitySpec& Spec)
{
UGameplayAbility* Ability = Spec.GetPrimaryInstance();
if (Ability == nullptr)
{
Ability = Spec.Ability;
}
if (ImGui::BeginTable("Ability", 2, ImGuiTableFlags_Borders))
{
const ImVec4 TextColor(1.0f, 1.0f, 1.0f, 0.5f);
ImGui::TableSetupColumn("Property");
ImGui::TableSetupColumn("Value");
//------------------------
// Name
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Name");
ImGui::TableNextColumn();
ImVec4 Color = Spec.ActiveCount > 0 ? ActiveColor : DeactiveColor;
ImGui::PushStyleColor(ImGuiCol_Text, Color);
ImGui::Text("%s", TCHAR_TO_ANSI(*GetAbilityName(Ability)));
ImGui::PopStyleColor(1);
//------------------------
// Activation
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Activation");
ImGui::TableNextColumn();
FCogWindowWidgets::PushStyleCompact();
bool IsActive = Spec.IsActive();
if (ImGui::Checkbox("##Activation", &IsActive))
{
AbilityHandleToActivate = Spec.Handle;
}
FCogWindowWidgets::PopStyleCompact();
//------------------------
// Active Count
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Active Count");
ImGui::TableNextColumn();
ImGui::Text("%u", Spec.ActiveCount);
//------------------------
// Handle
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Handle");
ImGui::TableNextColumn();
ImGui::Text("%s", TCHAR_TO_ANSI(*Spec.Handle.ToString()));
//------------------------
// Level
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Level");
ImGui::TableNextColumn();
ImGui::Text("%d", Spec.Level);
//------------------------
// InputID
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "InputID");
ImGui::TableNextColumn();
ImGui::Text("%d", Spec.InputID);
//------------------------
// InputPressed
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "InputPressed");
ImGui::TableNextColumn();
ImGui::Text("%d", Spec.InputPressed);
ImGui::EndTable();
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::GameTick(float DeltaTime)
{
if (AbilityHandleToActivate.IsValid())
{
ProcessAbilityActivation(AbilityHandleToActivate);
AbilityHandleToActivate = FGameplayAbilitySpecHandle();
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::ProcessAbilityActivation(FGameplayAbilitySpecHandle Handle)
{
AActor* Selection = GetSelection();
if (Selection == nullptr)
{
return;
}
UAbilitySystemComponent* AbilitySystemComponent = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Selection, true);
if (AbilitySystemComponent == nullptr)
{
return;
}
FGameplayAbilitySpec* Spec = AbilitySystemComponent->FindAbilitySpecFromHandle(Handle);
if (Spec == nullptr)
{
return;
}
if (Spec->IsActive())
{
DeactivateAbility(*AbilitySystemComponent, *Spec);
}
else
{
ActivateAbility(*AbilitySystemComponent, *Spec);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::ActivateAbility(UAbilitySystemComponent& AbilitySystemComponent, FGameplayAbilitySpec& Spec)
{
Spec.InputPressed = true;
AbilitySystemComponent.TryActivateAbility(Spec.Handle);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Abilities::DeactivateAbility(UAbilitySystemComponent& AbilitySystemComponent, FGameplayAbilitySpec& Spec)
{
Spec.InputPressed = false;
AbilitySystemComponent.CancelAbilityHandle(Spec.Handle);
}
@@ -0,0 +1,351 @@
#include "CogAbilityWindow_Attributes.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "CogAbilityHelper.h"
#include "CogWindowWidgets.h"
#include "AttributeSet.h"
#include "EngineUtils.h"
#include "GameFramework/Character.h"
//--------------------------------------------------------------------------------------------------------------------------
UCogAbilityWindow_Attributes::UCogAbilityWindow_Attributes()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Attributes::PreRender(ImGuiWindowFlags& WindowFlags)
{
WindowFlags = ImGuiWindowFlags_MenuBar;
}
//--------------------------------------------------------------------------------------------------------------------------
static void DrawAttributeInfo(const UAbilitySystemComponent& AbilitySystemComponent, const FGameplayAttribute& Attribute)
{
if (ImGui::BeginTable("Attribute", 2, ImGuiTableFlags_Borders))
{
const ImVec4 TextColor(1.0f, 1.0f, 1.0f, 0.5f);
ImGui::TableSetupColumn("Property");
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
const float BaseValue = AbilitySystemComponent.GetNumericAttributeBase(Attribute);
const float CurrentValue = AbilitySystemComponent.GetNumericAttribute(Attribute);
ImVec4 Color;
if (CurrentValue > BaseValue)
{
Color = ImVec4(0.0f, 1.0f, 0.0f, 1.0f);
}
else if (CurrentValue < BaseValue)
{
Color = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);
}
else
{
Color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
}
//------------------------
// Name
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Name");
ImGui::TableNextColumn();
ImGui::Text("%s", TCHAR_TO_ANSI(*Attribute.GetName()));
//------------------------
// Base Value
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Base Value");
ImGui::TableNextColumn();
ImGui::Text("%0.2f", BaseValue);
//------------------------
// Current Value
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Current Value");
ImGui::TableNextColumn();
ImGui::PushStyleColor(ImGuiCol_Text, Color);
ImGui::Text("%0.2f", CurrentValue);
ImGui::PopStyleColor(1);
//------------------------
// Modifiers
//------------------------
FGameplayEffectQuery Query;
for (const FActiveGameplayEffectHandle& ActiveHandle : AbilitySystemComponent.GetActiveEffects(Query))
{
const FActiveGameplayEffect* ActiveEffect = AbilitySystemComponent.GetActiveGameplayEffect(ActiveHandle);
if (ActiveEffect == nullptr)
{
continue;
}
for (int32 i = 0; i < ActiveEffect->Spec.Modifiers.Num(); ++i)
{
const FModifierSpec& ModSpec = ActiveEffect->Spec.Modifiers[i];
const FGameplayModifierInfo& ModInfo = ActiveEffect->Spec.Def->Modifiers[i];
if (ModInfo.Attribute == Attribute)
{
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Effect");
ImGui::TextColored(TextColor, "Operation");
ImGui::TextColored(TextColor, "Magnitude");
ImGui::TableNextColumn();
ImGui::Text("%s", TCHAR_TO_ANSI(*FCogAbilityHelper::CleanupName(GetNameSafe(ActiveEffect->Spec.Def))));
ImGui::Text("%s", TCHAR_TO_ANSI(*EGameplayModOpToString(ModInfo.ModifierOp)));
ImGui::Text("%0.2f", ModSpec.GetEvaluatedMagnitude());
}
}
}
ImGui::EndTable();
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Attributes::RenderContent()
{
Super::RenderContent();
UAbilitySystemComponent* AbilitySystemComponent = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(GetSelection(), true);
if (AbilitySystemComponent == nullptr)
{
return;
}
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("Options"))
{
ImGui::Checkbox("Sort by name", &bSortByNameSetting);
ImGui::Checkbox("Group by attribute set", &bGroupByAttributeSetSetting);
ImGui::Checkbox("Group by category", &bGroupByCategorySetting);
ImGui::Checkbox("Show Only Modified", &bShowOnlyModified);
ImGui::EndMenu();
}
FCogWindowWidgets::MenuSearchBar(Filter);
ImGui::EndMenuBar();
}
bool bGroupByAttributeSet = Filter.IsActive() == false && bShowOnlyModified == false && bGroupByAttributeSetSetting;
bool bGroupByCategory = Filter.IsActive() == false && bShowOnlyModified == false && bGroupByCategorySetting;
if (ImGui::BeginTable("Attributes", 3, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
{
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableSetupColumn("Attribute");
ImGui::TableSetupColumn("Base");
ImGui::TableSetupColumn("Current");
ImGui::TableHeadersRow();
static int Selected = -1;
int Index = 0;
//------------------------------------------------------------------------------------------
// Draw all the attribute sets
//------------------------------------------------------------------------------------------
for (const UAttributeSet* Set : AbilitySystemComponent->GetSpawnedAttributes())
{
//------------------------------------------------------------------------------------------
// Add an tree node categories are shown
//------------------------------------------------------------------------------------------
bool bOpenAttributeSet = true;
if (bGroupByAttributeSet)
{
ImGui::TableNextRow();
ImGui::TableNextColumn();
bOpenAttributeSet = ImGui::TreeNodeEx(TCHAR_TO_ANSI(*Set->GetName()), ImGuiTreeNodeFlags_SpanFullWidth);
}
if (bOpenAttributeSet)
{
TArray<FGameplayAttribute> AllAttributes;
for (TFieldIterator<FProperty> It(Set->GetClass()); It; ++It)
{
FGameplayAttribute Attribute = *It;
if (Attribute.IsValid())
{
AllAttributes.Add(Attribute);
}
}
TMap<FString, TArray<FGameplayAttribute>> AttributesByCategory;
//------------------------------------------------------------------------------------------
// Sort attributes by category to make sure categories are displayed in alphabetical order
//------------------------------------------------------------------------------------------
#if WITH_EDITORONLY_DATA
if (bGroupByCategory)
{
AllAttributes.Sort([](const FGameplayAttribute& Attribute1, const FGameplayAttribute& Attribute2)
{
FString Category1 = Attribute1.GetUProperty() != nullptr ? Attribute1.GetUProperty()->GetMetaData(TEXT("Category")) : "";
FString Category2 = Attribute2.GetUProperty() != nullptr ? Attribute2.GetUProperty()->GetMetaData(TEXT("Category")) : "";
return Category1.Compare(Category2) < 0;
});
}
#endif //WITH_EDITORONLY_DATA
//------------------------------------------------------------------------------------------
// If required, group by category, or put every attribute into the default category
// if this code is changed verify the SortByName works in all modes
//------------------------------------------------------------------------------------------
for (FGameplayAttribute& Attribute : AllAttributes)
{
FString Category = TEXT("Default");
#if WITH_EDITORONLY_DATA
if (bGroupByCategory)
{
FString ActualCategory = Attribute.GetUProperty() != nullptr ? Attribute.GetUProperty()->GetMetaData(TEXT("Category")) : "";
if (ActualCategory.IsEmpty() == false)
{
Category = ActualCategory;
}
}
#endif //WITH_EDITORONLY_DATA
AttributesByCategory.FindOrAdd(Category).Add(Attribute);
}
for (auto& It : AttributesByCategory)
{
//------------------------------------------------------------------------------------------
// Add a tree node with the name of the category if categories are shown
//------------------------------------------------------------------------------------------
bool bOpenCategory = true;
if (bGroupByCategory)
{
ImGui::TableNextRow();
ImGui::TableNextColumn();
bOpenCategory = ImGui::TreeNodeEx(TCHAR_TO_ANSI(*It.Key), ImGuiTreeNodeFlags_SpanFullWidth);
}
if (bOpenCategory)
{
TArray<FGameplayAttribute>& AttributesInCategory = It.Value;
//------------------------------------------------------------------------------------------
// Sort attributes within a category by their name
//------------------------------------------------------------------------------------------
if (bSortByNameSetting)
{
AttributesInCategory.Sort([](const FGameplayAttribute& Lhs, const FGameplayAttribute& Rhs)
{
return Lhs.GetName().Compare(Rhs.GetName()) < 0;
});
}
//------------------------------------------------------------------------------------------
// Draw all the attribute of the current category of the current attribute set
//------------------------------------------------------------------------------------------
for (const FGameplayAttribute& Attribute : AttributesInCategory)
{
if (!Attribute.IsValid())
{
continue;
}
const char* AttributeName = TCHAR_TO_ANSI(*Attribute.GetName());
if (Filter.PassFilter(AttributeName) == false)
{
continue;
}
const float BaseValue = AbilitySystemComponent->GetNumericAttributeBase(Attribute);
const float CurrentValue = AbilitySystemComponent->GetNumericAttribute(Attribute);
if (bShowOnlyModified && FMath::IsNearlyEqual(CurrentValue, BaseValue))
{
continue;
}
ImGui::TableNextRow();
ImVec4 Color;
if (CurrentValue > BaseValue)
{
Color = ImVec4(0.0f, 1.0f, 0.0f, 1.0f);
}
else if (CurrentValue < BaseValue)
{
Color = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);
}
else
{
Color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
}
ImGui::PushStyleColor(ImGuiCol_Text, Color);
//------------------------
// Name
//------------------------
ImGui::TableNextColumn();
ImGui::Text("");
ImGui::SameLine();
if (ImGui::Selectable(AttributeName, Selected == Index, ImGuiSelectableFlags_SpanAllColumns))
{
Selected = Index;
}
ImGui::PopStyleColor(1);
//------------------------
// Popup
//------------------------
if (ImGui::IsItemHovered())
{
FCogWindowWidgets::BeginTableTooltip();
DrawAttributeInfo(*AbilitySystemComponent, Attribute);
FCogWindowWidgets::EndTableTooltip();
}
ImGui::PushStyleColor(ImGuiCol_Text, Color);
//------------------------
// Base Value
//------------------------
ImGui::TableNextColumn();
ImGui::Text("%.2f", BaseValue);
//------------------------
// Current Value
//------------------------
ImGui::TableNextColumn();
ImGui::Text("%.2f", CurrentValue);
ImGui::PopStyleColor(1);
Index++;
}
}
if (bOpenCategory && bGroupByCategory)
{
ImGui::TreePop();
}
}
}
if (bOpenAttributeSet && bGroupByAttributeSet)
{
ImGui::TreePop();
}
}
ImGui::EndTable();
}
}
@@ -0,0 +1,176 @@
#include "CogAbilityWindow_Cheats.h"
#include "CogAbilityDataAsset_Cheats.h"
#include "CogDebugAllegianceInterface.h"
#include "CogDebugDraw.h"
#include "EngineUtils.h"
#include "GameFramework/Character.h"
#include "imgui.h"
#include "imgui_internal.h"
//--------------------------------------------------------------------------------------------------------------------------
UCogAbilityWindow_Cheats::UCogAbilityWindow_Cheats()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Cheats::RenderContent()
{
Super::RenderContent();
AActor* SelectedActor = GetSelection();
if (SelectedActor == nullptr)
{
return;
}
if (CheatsAsset == nullptr)
{
return;
}
APawn* LocalPawn = GetLocalPlayerPawn();
if (ImGui::BeginTable("Cheats", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize))
{
ImGui::TableSetupColumn("Toggle", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Instant", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow();
ImGui::TableNextColumn();
int Index = 0;
for (const FCogAbilityCheat& CheatEffect : CheatsAsset->PersistentEffects)
{
ImGui::PushID(Index);
AddCheat(LocalPawn, SelectedActor, CheatEffect, true);
ImGui::PopID();
Index++;
}
ImGui::TableNextColumn();
for (const FCogAbilityCheat& CheatEffect : CheatsAsset->InstantEffects)
{
ImGui::PushID(Index);
AddCheat(LocalPawn, SelectedActor, CheatEffect, false);
ImGui::PopID();
Index++;
}
ImGui::EndTable();
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Cheats::AddCheat(AActor* CheatInstigator, AActor* SelectedActor, const FCogAbilityCheat& Cheat, bool IsPersistent)
{
if (Cheat.Effect == nullptr)
{
return;
}
const FGameplayTagContainer& Tags = Cheat.Effect->GetDefaultObject<UGameplayEffect>()->InheritableGameplayEffectTags.CombinedTags;
FLinearColor Color;
if (Tags.HasTag(CheatsAsset->NegativeEffectTag))
{
Color = CheatsAsset->NegativeEffectColor;
}
else if (Tags.HasTag(CheatsAsset->PositiveEffectTag))
{
Color = CheatsAsset->PositiveEffectColor;
}
else
{
Color = CheatsAsset->NeutralEffectColor;
}
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(Color.R, Color.G, Color.B, 0.2f * Color.A));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(Color.R, Color.G, Color.B, 0.3f * Color.A));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(Color.R, Color.G, Color.B, 0.5f * Color.A));
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(Color.R, Color.G, Color.B, 0.8f * Color.A));
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(Color.R, Color.G, Color.B, 0.2f * Color.A));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(Color.R, Color.G, Color.B, 0.3f * Color.A));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(Color.R, Color.G, Color.B, 0.5f * Color.A));
if (IsPersistent)
{
bool isEnabled = ACogAbilityReplicator::IsCheatActive(SelectedActor, Cheat);
if (ImGui::Checkbox(TCHAR_TO_ANSI(*Cheat.Name), &isEnabled))
{
RequestCheat(CheatInstigator, SelectedActor, Cheat);
}
}
else
{
if (ImGui::Button(TCHAR_TO_ANSI(*Cheat.Name), ImVec2(-1, 0)))
{
RequestCheat(CheatInstigator, SelectedActor, Cheat);
}
}
if (ImGui::IsItemHovered())
{
const bool IsShiftDown = (ImGui::GetCurrentContext()->IO.KeyMods & ImGuiMod_Shift) != 0;
const bool IsAltDown = (ImGui::GetCurrentContext()->IO.KeyMods & ImGuiMod_Alt) != 0;
const bool IsControlDown = (ImGui::GetCurrentContext()->IO.KeyMods & ImGuiMod_Ctrl) != 0;
ImGui::BeginTooltip();
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsShiftDown || IsAltDown || IsControlDown ? 0.5f : 1.0f), "On Selection");
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsShiftDown ? 1.0f : 0.5f), "On Enemies [SHIFT]");
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsAltDown ? 1.0f : 0.5f), "On Allies [ALT]");
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsControlDown ? 1.0f : 0.5f), "On Controlled [CTRL]");
ImGui::EndTooltip();
}
ImGui::PopStyleColor(7);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Cheats::RequestCheat(AActor* CheatInstigator, AActor* SelectedActor, const FCogAbilityCheat& Cheat)
{
const bool IsShiftDown = (ImGui::GetCurrentContext()->IO.KeyMods & ImGuiMod_Shift) != 0;
const bool IsAltDown = (ImGui::GetCurrentContext()->IO.KeyMods & ImGuiMod_Alt) != 0;
const bool IsControlDown = (ImGui::GetCurrentContext()->IO.KeyMods & ImGuiMod_Ctrl) != 0;
TArray<AActor*> Actors;
if (IsControlDown)
{
Actors.Add(CheatInstigator);
}
if (IsShiftDown || IsAltDown)
{
for (TActorIterator<ACharacter> It(GetWorld(), ACharacter::StaticClass()); It; ++It)
{
if (AActor* OtherActor = *It)
{
ECogAllegiance Allegiance = ECogAllegiance::Enemy;
if (ICogAllegianceInterface* AllegianceInterface = Cast<ICogAllegianceInterface>(OtherActor))
{
AllegianceInterface->GetAllegiance(CheatInstigator);
}
if ((IsShiftDown && (Allegiance == ECogAllegiance::Enemy))
|| (IsAltDown && (Allegiance == ECogAllegiance::Ally)))
{
Actors.Add(OtherActor);
}
}
}
}
if ((IsControlDown || IsShiftDown || IsAltDown) == false)
{
Actors.Add(SelectedActor);
}
FCogAbilityModule& Module = FCogAbilityModule::Get();
if (ACogAbilityReplicator* Replicator = Module.GetLocalReplicator())
{
Replicator->ApplyCheat(CheatInstigator, Actors, Cheat);
}
}
@@ -0,0 +1,275 @@
#include "CogAbilityWindow_Damages.h"
#include "CogAbilityDamageActorInterface.h"
#include "CogImguiHelper.h"
#include "imgui.h"
//--------------------------------------------------------------------------------------------------------------------------
float FCogDamageStats::MaxDurationSetting = 0.0f;
float FCogDamageStats::RestartDelaySetting = 5.0f;
//--------------------------------------------------------------------------------------------------------------------------
void FCogDamageInstance::Restart()
{
DamageLast = 0.0f;
DamageMin = 0.0f;
DamageMax = 0.0f;
DamagePerSecond = 0.0f;
DamagePerFrame = 0.0f;
DamageTotal = 0.0f;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDamageInstance::AddDamage(const float Damage)
{
DamageLast = Damage;
DamageMin = DamageMin == 0.0f ? Damage : FMath::Min(DamageMin, Damage);
DamageMax = FMath::Max(DamageMax, Damage);
DamagePerFrame += Damage;
DamageTotal += Damage;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDamageInstance::UpdateDamagePerSecond(const float Duration)
{
DamagePerSecond = Duration > 1.0f ? DamageTotal / Duration : DamageTotal;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDamageStats::Restart()
{
Count = 0;
Crits = 0;
TotalCritChances = 0.0f;
IsInProgress = false;
Timer = 0.0f;
RestartTimer = 0.0f;
Mitigated.Restart();
Unmitigated.Restart();
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDamageStats::AddDamage(const float InMitigatedDamage, const float InUnmitigatedDamage, const bool bIsCrit)
{
// If the max duration is reached, stop adding
if (MaxDuration != 0 && Timer >= MaxDuration)
{
return;
}
IsInProgress = true;
Count++;
Crits += bIsCrit ? 1 : 0;
MaxDuration = MaxDurationSetting;
Mitigated.AddDamage(InMitigatedDamage);
Unmitigated.AddDamage(InUnmitigatedDamage);
Mitigated.UpdateDamagePerSecond(Timer);
Unmitigated.UpdateDamagePerSecond(Timer);
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDamageStats::Tick(const float DeltaSeconds)
{
if (IsInProgress)
{
// If the max duration is reached, stop increasing time.
if (MaxDuration <= 0 || Timer < MaxDuration)
{
Timer += DeltaSeconds;
}
else
{
IsInProgress = false;
Timer = MaxDuration;
Mitigated.UpdateDamagePerSecond(Timer);
Unmitigated.UpdateDamagePerSecond(Timer);
}
}
if (RestartDelaySetting > 0.0f)
{
if (Unmitigated.DamagePerFrame == 0.0f)
{
RestartTimer += DeltaSeconds;
if (RestartTimer > RestartDelaySetting)
{
Restart();
}
}
else
{
RestartTimer = 0.0f;
}
}
Mitigated.DamagePerFrame = 0.0f;
Unmitigated.DamagePerFrame = 0.0f;
}
//--------------------------------------------------------------------------------------------------------------------------
static void DrawRow(const char* Title, float MitigatedValue, float UnmitigatedValue, 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)));
}
//--------------------------------------------------------------------------------------------------------------------------
static void DrawDamages(FCogDamageStats& Damage)
{
ImGui::PushStyleColor(ImGuiCol_FrameBg, IM_COL32(150, 150, 150, 60));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, IM_COL32(150, 150, 150, 80));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, IM_COL32(150, 150, 150, 120));
ImGui::PushStyleColor(ImGuiCol_CheckMark, IM_COL32(150, 150, 150, 200));
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, IM_COL32(120, 120, 120, 255));
if (ImGui::BeginTable("Damages", 4, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_RowBg))
{
ImGui::TableSetupColumn("");
ImGui::TableSetupColumn("Mitigated");
ImGui::TableSetupColumn("Unmitigated");
ImGui::TableSetupColumn("Mitigation %");
ImGui::TableHeadersRow();
DrawRow("Damage Per Second", Damage.Mitigated.DamagePerSecond, Damage.Unmitigated.DamagePerSecond, ImVec4(1.0f, 1.0, 0.0f, 1.0f));
DrawRow("Damage Total", Damage.Mitigated.DamageTotal, Damage.Unmitigated.DamageTotal, ImVec4(1.0f, 1.0, 1.0f, 1.0f));
DrawRow("Damage Last", Damage.Mitigated.DamageLast, Damage.Unmitigated.DamageLast, ImVec4(1.0f, 1.0, 1.0f, 1.0f));
DrawRow("Damage Min", Damage.Mitigated.DamageMin, Damage.Unmitigated.DamageMin, ImVec4(1.0f, 1.0, 1.0f, 1.0f));
DrawRow("Damage Min", Damage.Mitigated.DamageMax, Damage.Unmitigated.DamageMax, ImVec4(1.0f, 1.0, 1.0f, 1.0f));
ImGui::EndTable();
}
ImGui::Text("Crits");
ImGui::SameLine(FCogWindowWidgets::TextBaseWidth * 20);
FCogWindowWidgets::ProgressBarCentered(Damage.Count == 0 ? 0.0f : Damage.Crits / (float)Damage.Count, ImVec2(-1, 0), TCHAR_TO_ANSI(*FString::Printf(TEXT("%d / %d"), Damage.Crits, Damage.Count)));
if (FCogDamageStats::MaxDurationSetting > 0)
{
ImGui::Text("Timer");
ImGui::SameLine(FCogWindowWidgets::TextBaseWidth * 20);
FCogWindowWidgets::ProgressBarCentered(Damage.Timer / Damage.MaxDuration, ImVec2(-1, 0), TCHAR_TO_ANSI(*FString::Printf(TEXT("%0.1f / %0.1f"), Damage.Timer, Damage.MaxDuration)));
}
ImGui::Spacing();
if (ImGui::Button("Restart"))
{
Damage.Restart();
}
ImGui::PopStyleColor(5);
ImGui::Spacing();
ImGui::Spacing();
}
//--------------------------------------------------------------------------------------------------------------------------
UCogAbilityWindow_Damages::UCogAbilityWindow_Damages()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Damages::RenderContent()
{
Super::RenderContent();
AActor* Selection = GetSelection();
if (Selection == nullptr)
{
return;
}
if (ImGui::CollapsingHeader("Damage Dealt"))
{
ImGui::PushID("Damage Dealt");
DrawDamages(DamageDealtStats);
ImGui::PopID();
}
if (ImGui::CollapsingHeader("Damage Received"))
{
ImGui::PushID("Damage Received");
DrawDamages(DamageReceivedStats);
ImGui::PopID();
}
if (ImGui::CollapsingHeader("Settings"))
{
ImGui::PushItemWidth(-1);
ImGui::Text("Auto Restart");
ImGui::SameLine(FCogWindowWidgets::TextBaseWidth * 20);
bool AutoRestart = FCogDamageStats::RestartDelaySetting > 0;
if (ImGui::Checkbox("##Auto Restart", &AutoRestart))
{
FCogDamageStats::RestartDelaySetting = AutoRestart ? 5.0f : 0.0f;
}
if (AutoRestart)
{
ImGui::Text("Auto Restart Delay");
ImGui::SameLine(FCogWindowWidgets::TextBaseWidth * 20);
ImGui::InputFloat("##Auto Restart Delay", &FCogDamageStats::RestartDelaySetting);
}
ImGui::Text("Max Time");
ImGui::SameLine(FCogWindowWidgets::TextBaseWidth * 20);
if (ImGui::InputFloat("##Max Time", &FCogDamageStats::MaxDurationSetting, 0.0f, 0.0f, "%0.1f"))
{
DamageDealtStats.Restart();
DamageReceivedStats.Restart();
}
ImGui::PopItemWidth();
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Damages::OnSelectionChanged(AActor* OldSelection, AActor* NewSelection)
{
if (ICogAbilityDamageActorInterface* DamageActor = Cast<ICogAbilityDamageActorInterface>(OldSelection))
{
DamageActor->OnDamageEvent().Remove(OnDamageEventDelegate);
}
if (ICogAbilityDamageActorInterface* DamageActor = Cast<ICogAbilityDamageActorInterface>(NewSelection))
{
OnDamageEventDelegate = DamageActor->OnDamageEvent().AddUObject(this, &UCogAbilityWindow_Damages::OnDamageEvent);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Damages::RenderTick(float DeltaSeconds)
{
Super::RenderTick(DeltaSeconds);
DamageReceivedStats.Tick(DeltaSeconds);
DamageDealtStats.Tick(DeltaSeconds);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Damages::OnDamageEvent(const FCogAbilityDamageParams& Params)
{
DamageDealtStats.Restart();
DamageReceivedStats.Restart();
AActor* Selection = GetSelection();
if (Selection == Params.DamageDealer.Get())
{
DamageDealtStats.AddDamage(Params.ReceivedDamage, Params.IncomingDamage, Params.IsCritical);
}
else if (Selection == Params.DamageReceiver.Get())
{
DamageReceivedStats.AddDamage(Params.ReceivedDamage, Params.IncomingDamage, Params.IsCritical);
}
}
@@ -0,0 +1,343 @@
#include "CogAbilityWindow_Effects.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "AttributeSet.h"
#include "CogAbilityHelper.h"
#include "CogWindowWidgets.h"
#include "EngineUtils.h"
#include "GameFramework/Character.h"
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Effects::PreRender(ImGuiWindowFlags& WindowFlags)
{
Super::PreRender(WindowFlags);
WindowFlags |= ImGuiWindowFlags_MenuBar;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Effects::RenderContent()
{
Super::RenderContent();
UAbilitySystemComponent* AbilitySystemComponent = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(GetSelection(), true);
if (AbilitySystemComponent == nullptr)
{
return;
}
ImGui::BeginTable("Effects", 4, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersH | ImGuiTableFlags_NoBordersInBody);
ImGui::TableSetupColumn("Effect");
ImGui::TableSetupColumn("Remaining Time");
ImGui::TableSetupColumn("Stacks");
ImGui::TableSetupColumn("Prediction");
ImGui::TableHeadersRow();
static int SelectedIndex = -1;
int Index = 0;
FGameplayEffectQuery Query;
for (const FActiveGameplayEffectHandle& ActiveHandle : AbilitySystemComponent->GetActiveEffects(Query))
{
DrawEffectRow(*AbilitySystemComponent, ActiveHandle, Index, SelectedIndex);
}
ImGui::EndTable();
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Effects::DrawEffectRow(const UAbilitySystemComponent& AbilitySystemComponent, const FActiveGameplayEffectHandle& ActiveHandle, int32 Index, int32& Selected)
{
ImGui::PushID(Index);
const FActiveGameplayEffect* ActiveEffectPtr = AbilitySystemComponent.GetActiveGameplayEffect(ActiveHandle);
if (ActiveEffectPtr == nullptr)
{
return;
}
const UGameplayEffect* EffectPtr = ActiveEffectPtr->Spec.Def;
if (EffectPtr == nullptr)
{
return;
}
const FActiveGameplayEffect& ActiveEffect = *ActiveEffectPtr;
const UGameplayEffect& Effect = *EffectPtr;
ImGui::TableNextRow(ImGuiTableRowFlags_None, 0.0f);
//------------------------
// Name
//------------------------
ImGui::TableNextColumn();
const FGameplayTagContainer& Tags = Effect.InheritableGameplayEffectTags.CombinedTags;
ImVec4 Color;
if (Tags.HasTag(NegativeEffectTag))
{
Color = ImVec4(1.0f, 0.5f, 0.5f, 1.0f);
}
else if (Tags.HasTag(PositiveEffectTag))
{
Color = ImVec4(0.5f, 1.0f, 0.5f, 1.0f);
}
else
{
Color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
}
ImGui::PushStyleColor(ImGuiCol_Text, Color);
if (ImGui::Selectable(TCHAR_TO_ANSI(*GetEffectName(Effect)), Selected == Index, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap | ImGuiSelectableFlags_AllowDoubleClick))
{
Selected = Index;
}
ImGui::PopStyleColor(1);
//------------------------
// Popup
//------------------------
if (ImGui::IsItemHovered())
{
FCogWindowWidgets::BeginTableTooltip();
DrawEffectInfo(AbilitySystemComponent, ActiveEffect, Effect);
FCogWindowWidgets::EndTableTooltip();
}
//------------------------
// ContextMenu
//------------------------
if (ImGui::BeginPopupContextItem())
{
if (ImGui::Button("Open Properties"))
{
//GetOwner()->GetPropertyGrid()->Open(EffectPtr);
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
//------------------------
// Remaining Time
//------------------------
ImGui::TableNextColumn();
DrawRemainingTime(AbilitySystemComponent, ActiveEffect);
//------------------------
// Stacks
//------------------------
ImGui::TableNextColumn();
DrawStacks(ActiveEffect, Effect);
//------------------------
// Prediction
//------------------------
ImGui::TableNextColumn();
DrawPrediction(ActiveEffect, true);
ImGui::PopID();
Index++;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Effects::DrawEffectInfo(const UAbilitySystemComponent& AbilitySystemComponent, const FActiveGameplayEffect& ActiveEffect, const UGameplayEffect& Effect)
{
if (ImGui::BeginTable("Effect", 2, ImGuiTableFlags_Borders))
{
const ImVec4 TextColor(1.0f, 1.0f, 1.0f, 0.5f);
ImGui::TableSetupColumn("Property");
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
//------------------------
// Name
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Name");
ImGui::TableNextColumn();
ImGui::Text("%s", TCHAR_TO_ANSI(*GetEffectName(Effect)));
//------------------------
// Level
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Level");
ImGui::TableNextColumn();
ImGui::Text("%0.0f", ActiveEffect.Spec.GetLevel());
//------------------------
// Remaining Time
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Remaining Time");
ImGui::TableNextColumn();
DrawRemainingTime(AbilitySystemComponent, ActiveEffect);
//------------------------
// Period
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Period");
ImGui::TableNextColumn();
ImGui::Text("%0.3f", ActiveEffect.GetPeriod());
//------------------------
// Stacks
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Stacks");
ImGui::TableNextColumn();
DrawStacks(ActiveEffect, Effect);
//------------------------
// Prediction
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Prediction");
ImGui::TableNextColumn();
DrawPrediction(ActiveEffect, false);
//------------------------
// Dynamic Asset Tags
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Dynamic Asset Tags");
ImGui::TableNextColumn();
DrawTagContainer(ActiveEffect.Spec.GetDynamicAssetTags());
//------------------------
// All Asset Tags
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "All Asset Tags");
ImGui::TableNextColumn();
FGameplayTagContainer AllAssetTagsContainer;
ActiveEffect.Spec.GetAllAssetTags(AllAssetTagsContainer);
DrawTagContainer(AllAssetTagsContainer);
//------------------------
// All Granted Tags
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "All Granted Tags");
ImGui::TableNextColumn();
FGameplayTagContainer AllGrantedTagsContainer;
ActiveEffect.Spec.GetAllGrantedTags(AllGrantedTagsContainer);
DrawTagContainer(AllGrantedTagsContainer);
//------------------------
// Modifiers
//------------------------
for (int32 i = 0; i < ActiveEffect.Spec.Modifiers.Num(); ++i)
{
const FModifierSpec& ModSpec = ActiveEffect.Spec.Modifiers[i];
const FGameplayModifierInfo& ModInfo = ActiveEffect.Spec.Def->Modifiers[i];
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Attribute Modifier");
ImGui::TextColored(TextColor, "Operation");
ImGui::TextColored(TextColor, "Magnitude");
ImGui::TableNextColumn();
ImGui::Text("%s", TCHAR_TO_ANSI(*ModInfo.Attribute.GetName()));
ImGui::Text("%s", TCHAR_TO_ANSI(*EGameplayModOpToString(ModInfo.ModifierOp)));
ImGui::Text("%0.2f", ModSpec.GetEvaluatedMagnitude());
}
ImGui::EndTable();
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Effects::DrawTagContainer(const FGameplayTagContainer& Container)
{
TArray<FGameplayTag> GameplayTags;
Container.GetGameplayTagArray(GameplayTags);
for (FGameplayTag Tag : GameplayTags)
{
ImGui::Text("%s", TCHAR_TO_ANSI(*Tag.ToString()));
}
}
//--------------------------------------------------------------------------------------------------------------------------
FString UCogAbilityWindow_Effects::GetEffectName(const UGameplayEffect& Effect)
{
FString Str = FCogAbilityHelper::CleanupName(Effect.GetName());
return Str;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Effects::DrawRemainingTime(const UAbilitySystemComponent& AbilitySystemComponent, const FActiveGameplayEffect& ActiveEffect)
{
float StartTime = ActiveEffect.StartWorldTime;
float Duration = ActiveEffect.GetDuration();
if (Duration <= 0)
{
ImGui::Text("NA");
}
else
{
UWorld* World = AbilitySystemComponent.GetWorld();
const float RemainingTime = StartTime + Duration - World->GetTimeSeconds();
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, IM_COL32(100, 100, 100, 255));
ImGui::PushStyleColor(ImGuiCol_FrameBg, IM_COL32(0, 0, 0, 100));
ImGui::ProgressBar(RemainingTime / Duration, ImVec2(FCogWindowWidgets::TextBaseWidth * 15, FCogWindowWidgets::TextBaseHeight * 0.8f), TCHAR_TO_ANSI(*FString::Printf(TEXT("%.2f / %.2f"), RemainingTime, Duration)));
ImGui::PopStyleColor(2);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Effects::DrawStacks(const FActiveGameplayEffect& ActiveEffect, const UGameplayEffect& Effect)
{
const int32 CurrentStackCount = ActiveEffect.Spec.StackCount;
if (Effect.StackLimitCount <= 0)
{
ImGui::Text("0");
}
else
{
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, IM_COL32(100, 100, 100, 255));
ImGui::PushStyleColor(ImGuiCol_FrameBg, IM_COL32(0, 0, 0, 100));
ImGui::SetNextItemWidth(-1);
ImGui::ProgressBar(CurrentStackCount / (float)Effect.StackLimitCount, ImVec2(FCogWindowWidgets::TextBaseWidth * 15, FCogWindowWidgets::TextBaseHeight * 0.8f), TCHAR_TO_ANSI(*FString::Printf(TEXT("%d / %d"), CurrentStackCount, Effect.StackLimitCount)));
ImGui::PopStyleColor(2);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Effects::DrawPrediction(const FActiveGameplayEffect& ActiveEffect, bool Short)
{
FString PredictionString;
if (ActiveEffect.PredictionKey.IsValidKey())
{
if (ActiveEffect.PredictionKey.WasLocallyGenerated())
{
PredictionString = Short ? FString("Wait") : FString("Predicted and Waiting");
}
else
{
PredictionString = Short ? FString("Done") : FString("Predicted and Caught Up");
}
}
else
{
PredictionString = Short ? FString("No") : FString("Not Predicted");
}
ImGui::Text("%s", TCHAR_TO_ANSI(*PredictionString));
}
@@ -0,0 +1,79 @@
#include "CogAbilityWindow_Pools.h"
#include "AbilitySystemComponent.h"
#include "CogImguiHelper.h"
//--------------------------------------------------------------------------------------------------------------------------
UCogAbilityWindow_Pools::UCogAbilityWindow_Pools()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void DrawPool(const UAbilitySystemComponent* AbilitySystemComponent, const FCogAbilityPool& Pool)
{
if (AbilitySystemComponent->HasAttributeSetForAttribute(Pool.Max) == false)
{
return;
}
if (AbilitySystemComponent->HasAttributeSetForAttribute(Pool.Value) == false)
{
return;
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%s", TCHAR_TO_ANSI(*Pool.Name));
const float Value = AbilitySystemComponent->GetNumericAttribute(Pool.Value);
const float Max = AbilitySystemComponent->GetNumericAttribute(Pool.Max);
//-------------------------------------------------------------------------------------------
// Use a different format base on max value for all pools to be nicely aligned at the center
//-------------------------------------------------------------------------------------------
const char* format = nullptr;
if (Max >= 100) { format = "%3.0f / %3.0f"; } // |200 / 200| |__1 / 200| 3 characters with 0 floating point
else if (Max >= 10) { format = "%4.1f / %4.1f"; } // |20.0 / 20.0| |_1.1 / 20.0| 4 characters with 1 floating point
else { format = "%3.2f / %3.2f"; } // |2.00 / 2.00| |1.11 / 2.00| 3 characters with 2 floating points
char Buffer[64];
ImFormatString(Buffer, IM_ARRAYSIZE(Buffer), format, Value, Max);
const float Ratio = Max > 0.0f ? Value / Max : 0.0f;
ImGui::TableNextColumn();
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, FCogImguiHelper::ToImVec4(Pool.Color));
ImGui::PushStyleColor(ImGuiCol_FrameBg, FCogImguiHelper::ToImVec4(Pool.BackColor));
FCogWindowWidgets::ProgressBarCentered(Ratio, ImVec2(-1, 0), Buffer);
ImGui::PopStyleColor(2);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Pools::RenderContent()
{
Super::RenderContent();
if (PoolsAsset == nullptr)
{
return;
}
UAbilitySystemComponent* AbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(GetSelection(), true);
if (AbilitySystem == nullptr)
{
return;
}
if (ImGui::BeginTable("Pools", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize))
{
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Pool", ImGuiTableColumnFlags_WidthStretch);
for (const FCogAbilityPool& Pool : PoolsAsset->Pools)
{
DrawPool(AbilitySystem, Pool);
}
ImGui::EndTable();
}
}
@@ -0,0 +1,171 @@
#include "CogAbilityWindow_Tags.h"
#include "AbilitySystemComponent.h"
#include "CogAbilityHelper.h"
#include "CogWindowWidgets.h"
//--------------------------------------------------------------------------------------------------------------------------
static void DrawTagInfo(const UAbilitySystemComponent& AbilitySystemComponent, const FGameplayTag& Tag)
{
if (ImGui::BeginTable("Tag", 2, ImGuiTableFlags_Borders))
{
const ImVec4 TextColor(1.0f, 1.0f, 1.0f, 0.5f);
ImGui::TableSetupColumn("Property");
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
//------------------------
// Name
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Name");
ImGui::TableNextColumn();
ImGui::Text("%s", TCHAR_TO_ANSI(*Tag.GetTagName().ToString()));
//------------------------
// Base Value
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Count");
ImGui::TableNextColumn();
const int32 TagCount = AbilitySystemComponent.GetTagCount(Tag);
ImGui::TextColored(TagCount > 1 ? ImVec4(1.0f, 1.0f, 0.0f, 1.0f) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f), "%d", TagCount);
//------------------------
// Abilities
//------------------------
//ImGui::TableNextRow();
//ImGui::TableNextColumn();
//ImGui::TextColored(TextColor, "Abilities");
//ImGui::TableNextColumn();
//for (FGameplayAbilitySpec AbilitySpec : AbilitySystemComponent.GetActivatableAbilities())
//{
// UGameplayAbility* Ability = AbilitySpec.GetPrimaryInstance() != nullptr ? AbilitySpec.GetPrimaryInstance() : AbilitySpec.Ability;
// if (Ability == nullptr)
// {
// continue;
// }
// if (Ability->ActivationOwnedTags GetActivationOwnedTags().HasTagExact(Tag))
// {
// ImGui::Text("%s", TCHAR_TO_ANSI(*FCogAbilityHelper::CleanupName(GetNameSafe(Ability))));
// }
//}
//------------------------
// Effects
//------------------------
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(TextColor, "Effects");
ImGui::TableNextColumn();
FGameplayEffectQuery Query;
for (const FActiveGameplayEffectHandle& ActiveHandle : AbilitySystemComponent.GetActiveEffects(Query))
{
const FActiveGameplayEffect* ActiveEffect = AbilitySystemComponent.GetActiveGameplayEffect(ActiveHandle);
if (ActiveEffect == nullptr)
{
continue;
}
FGameplayTagContainer Container;
ActiveEffect->Spec.GetAllGrantedTags(Container);
if (Container.HasTagExact(Tag))
{
ImGui::Text("%s", TCHAR_TO_ANSI(*FCogAbilityHelper::CleanupName(GetNameSafe(ActiveEffect->Spec.Def))));
}
}
ImGui::EndTable();
}
}
//--------------------------------------------------------------------------------------------------------------------------
static void DrawTags(const FString& Title, UAbilitySystemComponent& AbilitySystemComponent, FGameplayTagContainer& TagContainer)
{
if (ImGui::BeginTable(TCHAR_TO_ANSI(*Title), 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_BordersOuterV))
{
ImGui::TableSetupColumn("Count");
ImGui::TableSetupColumn(TCHAR_TO_ANSI(*Title));
ImGui::TableHeadersRow();
TArray<FGameplayTag> Tags;
TagContainer.GetGameplayTagArray(Tags);
static int Selected = -1;
int index = 0;
for (const FGameplayTag& Tag : Tags)
{
ImGui::TableNextRow();
ImGui::PushID(index);
//------------------------
// Count
//------------------------
ImGui::TableNextColumn();
const int32 TagCount = AbilitySystemComponent.GetTagCount(Tag);
ImGui::TextColored(TagCount > 1 ? ImVec4(1.0f, 1.0f, 0.0f, 1.0f) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f), "%d", TagCount);
//------------------------
// Name
//------------------------
ImGui::TableNextColumn();
if (ImGui::Selectable(TCHAR_TO_ANSI(*Tag.GetTagName().ToString()), Selected == index, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap | ImGuiSelectableFlags_AllowDoubleClick))
{
Selected = index;
}
//------------------------
// Popup
//------------------------
if (ImGui::IsItemHovered())
{
FCogWindowWidgets::BeginTableTooltip();
DrawTagInfo(AbilitySystemComponent, Tag);
FCogWindowWidgets::EndTableTooltip();
}
ImGui::PopID();
index++;
}
ImGui::EndTable();
}
}
//--------------------------------------------------------------------------------------------------------------------------
UCogAbilityWindow_Tags::UCogAbilityWindow_Tags()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Tags::PreRender(ImGuiWindowFlags& WindowFlags)
{
WindowFlags = ImGuiWindowFlags_MenuBar;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Tags::RenderContent()
{
Super::RenderContent();
UAbilitySystemComponent* AbilitySystemComponent = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(GetSelection(), true);
if (AbilitySystemComponent == nullptr)
{
return;
}
FGameplayTagContainer OwnedTags, BlockedTags;
AbilitySystemComponent->GetOwnedGameplayTags(OwnedTags);
AbilitySystemComponent->GetBlockedAbilityTags(BlockedTags);
DrawTags("Owned Tags", *AbilitySystemComponent, OwnedTags);
}
@@ -0,0 +1,149 @@
#include "CogAbilityWindow_Tweaks.h"
#include "AbilitySystemComponent.h"
//--------------------------------------------------------------------------------------------------------------------------
UCogAbilityWindow_Tweaks::UCogAbilityWindow_Tweaks()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void DrawTweak(ACogAbilityReplicator* Replicator, const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 TweakCategoryIndex)
{
if (TweaksAsset->TweaksCategories.IsValidIndex(TweakCategoryIndex) == false)
{
return;
}
float* Value = Replicator->GetTweakCurrentValuePtr(TweaksAsset, TweakIndex, TweakCategoryIndex);
if (Value == nullptr)
{
return;
}
const FCogAbilityTweakCategory& Category = TweaksAsset->TweaksCategories[TweakCategoryIndex];
const FLinearColor& Color = Category.Color;
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(Color.R, Color.G, Color.B, Color.A * 0.25f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(Color.R, Color.G, Color.B, Color.A * 0.3f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(Color.R, Color.G, Color.B, Color.A * 0.5f));
ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(Color.R, Color.G, Color.B, Color.A * 0.8f));
ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, ImVec4(Color.R, Color.G, Color.B, Color.A * 1.0f));
ImGui::PushItemWidth(-1);
ImGui::SliderFloat("##Value", Value, TweaksAsset->TweakMinValue, TweaksAsset->TweakMaxValue, "%+0.0f%%", 1.0f);
ImGui::PopItemWidth();
ImGui::PopStyleColor(5);
bool bUpdateValue = ImGui::IsItemDeactivatedAfterEdit();
if (ImGui::BeginPopupContextItem())
{
if (ImGui::Button("Reset"))
{
*Value = 0.f;
bUpdateValue = true;
}
ImGui::EndPopup();
}
if (bUpdateValue)
{
Replicator->SetTweakValue(TweaksAsset, TweakIndex, TweakCategoryIndex, *Value);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityWindow_Tweaks::RenderContent()
{
Super::RenderContent();
FCogAbilityModule& Module = FCogAbilityModule::Get();
ACogAbilityReplicator* Replicator = Module.GetLocalReplicator();
if (Replicator == nullptr)
{
return;
}
if (ImGui::BeginMenuBar())
{
if (ImGui::MenuItem("Reset"))
{
Replicator->ResetAllTweaks();
}
ImGui::EndMenuBar();
}
int32 CurrentTweakProfileIndex = Replicator->GetTweakProfileIndex();
FName CurrentProfileName = FName("None");
if (TweaksAsset->TweakProfiles.IsValidIndex(CurrentTweakProfileIndex))
{
CurrentProfileName = TweaksAsset->TweakProfiles[CurrentTweakProfileIndex].Name;
}
if (ImGui::BeginCombo("Profile", TCHAR_TO_ANSI(*CurrentProfileName.ToString())))
{
{
bool IsSelected = CurrentTweakProfileIndex == INDEX_NONE;
if (ImGui::Selectable("None", IsSelected))
{
Replicator->SetTweakProfile(TweaksAsset.Get(), INDEX_NONE);
}
}
for (int32 TweakProfileIndex = 0; TweakProfileIndex < TweaksAsset->TweakProfiles.Num(); ++TweakProfileIndex)
{
const FCogAbilityTweakProfile& TweakProfile = TweaksAsset->TweakProfiles[TweakProfileIndex];
bool IsSelected = TweakProfileIndex == CurrentTweakProfileIndex;
if (ImGui::Selectable(TCHAR_TO_ANSI(*TweakProfile.Name.ToString()), IsSelected))
{
Replicator->SetTweakProfile(TweaksAsset.Get(), TweakProfileIndex);
}
}
ImGui::EndCombo();
}
ImGui::Separator();
if (ImGui::BeginTable("Tweaks", 1 + TweaksAsset->TweaksCategories.Num(), ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize))
{
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
for (int32 TweakCategoryIndex = 0; TweakCategoryIndex < TweaksAsset->TweaksCategories.Num(); ++TweakCategoryIndex)
{
FCogAbilityTweakCategory& Category = TweaksAsset->TweaksCategories[TweakCategoryIndex];
ImGui::TableSetupColumn(TCHAR_TO_ANSI(*Category.Name), ImGuiTableColumnFlags_WidthStretch);
}
ImGui::TableHeadersRow();
ImGui::TableNextRow();
int32 TweakIndex = 0;
for (FCogAbilityTweak& Tweak : TweaksAsset->Tweaks)
{
if (Tweak.Effect != nullptr)
{
ImGui::PushID(TweakIndex);
ImGui::TableNextColumn();
ImGui::Text("%s", TCHAR_TO_ANSI(*Tweak.Name.ToString()));
for (int TweakCategoryIndex = 0; TweakCategoryIndex < TweaksAsset->TweaksCategories.Num(); ++TweakCategoryIndex)
{
ImGui::TableNextColumn();
ImGui::PushID(TweakCategoryIndex);
DrawTweak(Replicator, TweaksAsset.Get(), TweakIndex, TweakCategoryIndex);
ImGui::PopID();
}
ImGui::PopID();
TweakIndex++;
}
}
ImGui::EndTable();
}
}
@@ -0,0 +1,36 @@
#pragma once
#include "CoreMinimal.h"
#include "CogAbilityDamageActorInterface.generated.h"
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct COGABILITY_API FCogAbilityDamageParams
{
GENERATED_BODY()
TObjectPtr<AActor> DamageDealer;
TObjectPtr<AActor> DamageReceiver;
float ReceivedDamage = 0;
float IncomingDamage = 0;
bool IsCritical = false;
};
//--------------------------------------------------------------------------------------------------------------------------
DECLARE_MULTICAST_DELEGATE_OneParam(FCogAbilityOnDamageEvent, const FCogAbilityDamageParams&);
//--------------------------------------------------------------------------------------------------------------------------
UINTERFACE(MinimalAPI, Blueprintable)
class UCogAbilityDamageActorInterface : public UInterface
{
GENERATED_BODY()
};
//--------------------------------------------------------------------------------------------------------------------------
class ICogAbilityDamageActorInterface
{
GENERATED_BODY()
public:
virtual FCogAbilityOnDamageEvent& OnDamageEvent() = 0;
};
@@ -0,0 +1,21 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "CogAbilityDataAsset_Abilities.generated.h"
class UGameplayAbility;
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(Blueprintable)
class COGABILITY_API UCogAbilityDataAsset_Abilities : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UCogAbilityDataAsset_Abilities() {}
UPROPERTY(EditAnywhere)
TArray<TSubclassOf<UGameplayAbility>> Abilities;
};
@@ -0,0 +1,51 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "GameplayEffect.h"
#include "CogAbilityDataAsset_Cheats.generated.h"
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct COGABILITY_API FCogAbilityCheat
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
FString Name;
UPROPERTY(EditAnywhere)
TSubclassOf<UGameplayEffect> Effect;
};
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(Blueprintable)
class COGABILITY_API UCogAbilityDataAsset_Cheats : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UCogAbilityDataAsset_Cheats() {}
UPROPERTY(EditAnywhere)
FGameplayTag NegativeEffectTag;
UPROPERTY(EditAnywhere)
FGameplayTag PositiveEffectTag;
UPROPERTY(EditAnywhere)
FLinearColor NeutralEffectColor = FLinearColor(0.5f, 0.5f, 0.5f, 1.0f);
UPROPERTY(EditAnywhere)
FLinearColor NegativeEffectColor = FLinearColor(1.0f, 0.5f, 0.5f, 1.0f);
UPROPERTY(EditAnywhere)
FLinearColor PositiveEffectColor = FLinearColor(0.0f, 1.0f, 0.5f, 1.0f);
UPROPERTY(EditAnywhere, meta = (TitleProperty = "Name"))
TArray<FCogAbilityCheat> PersistentEffects;
UPROPERTY(EditAnywhere, meta = (TitleProperty = "Name"))
TArray<FCogAbilityCheat> InstantEffects;
};
@@ -0,0 +1,47 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "CogAbilityDataAsset_Pools.generated.h"
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct COGABILITY_API FCogAbilityPool
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
FString Name;
UPROPERTY(EditAnywhere)
FGameplayAttribute Value;
UPROPERTY(EditAnywhere)
FGameplayAttribute Min;
UPROPERTY(EditAnywhere)
FGameplayAttribute Max;
UPROPERTY(EditAnywhere)
FGameplayAttribute Regen;
UPROPERTY(EditAnywhere)
FLinearColor Color = FLinearColor(0.5f, 0.5f, 0.5f, 1.0f);
UPROPERTY(EditAnywhere)
FLinearColor BackColor = FLinearColor(0.15, 0.15, 0.15, 1.0f);
};
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(Blueprintable)
class COGABILITY_API UCogAbilityDataAsset_Pools : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UCogAbilityDataAsset_Pools() {}
UPROPERTY(EditAnywhere, meta = (TitleProperty = "Name"))
TArray<FCogAbilityPool> Pools;
};
@@ -0,0 +1,108 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "CogAbilityDataAsset_Tweaks.generated.h"
class UGameplayEffect;
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct FCogAbilityTweak
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
FName Name;
UPROPERTY(EditAnywhere)
TSubclassOf<UGameplayEffect> Effect;
UPROPERTY(EditAnywhere)
float Multiplier = 0.01f;
UPROPERTY(EditAnywhere)
float AddPostMultiplier = 1.0f;
};
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct FCogAbilityTweakCategory
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
FString Name;
UPROPERTY(EditAnywhere)
FGameplayTag Id;
UPROPERTY(EditAnywhere)
TSubclassOf<AActor> ActorClass;
UPROPERTY(EditAnywhere)
FGameplayTagContainer RequiredTags;
UPROPERTY(EditAnywhere)
FGameplayTagContainer IgnoredTags;
UPROPERTY(EditAnywhere)
FLinearColor Color = FLinearColor::White;
};
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct FCogAbilityTweakProfileValue
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
TSubclassOf<UGameplayEffect> Effect;
UPROPERTY(EditAnywhere)
FGameplayTag CategoryId;
UPROPERTY(EditAnywhere)
float Value = 0.0f;
};
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct FCogAbilityTweakProfile
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
FName Name;
UPROPERTY(EditAnywhere)
TArray<FCogAbilityTweakProfileValue> Tweaks;
};
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(Blueprintable)
class COGABILITY_API UCogAbilityDataAsset_Tweaks : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UCogAbilityDataAsset_Tweaks() {}
UPROPERTY(EditAnywhere)
float TweakMinValue = -100.0f;
UPROPERTY(EditAnywhere)
float TweakMaxValue = 200.0f;
UPROPERTY(EditAnywhere)
FGameplayTag SetByCallerMagnitudeTag;
UPROPERTY(EditAnywhere, meta = (TitleProperty = "Name"))
TArray<FCogAbilityTweak> Tweaks;
UPROPERTY(EditAnywhere, meta = (TitleProperty = "Name"))
TArray<FCogAbilityTweakCategory> TweaksCategories;
UPROPERTY(EditAnywhere, meta = (TitleProperty = "Name"))
TArray<FCogAbilityTweakProfile> TweakProfiles;
};
@@ -0,0 +1,10 @@
#pragma once
#include "CoreMinimal.h"
class COGABILITY_API FCogAbilityHelper
{
public:
static FString CleanupName(FString Str);
};
@@ -0,0 +1,30 @@
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
class ACogAbilityReplicator;
class APlayerController;
class COGABILITY_API FCogAbilityModule : public IModuleInterface
{
public:
static inline FCogAbilityModule& Get()
{
return FModuleManager::LoadModuleChecked<FCogAbilityModule>("CogAbility");
}
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
ACogAbilityReplicator* GetLocalReplicator();
void SetLocalReplicator(ACogAbilityReplicator* Value);
ACogAbilityReplicator* GetRemoteReplicator(const APlayerController* PlayerController);
void AddRemoteReplicator(ACogAbilityReplicator* Value);
private:
TObjectPtr<ACogAbilityReplicator> LocalReplicator;
TArray<TObjectPtr<ACogAbilityReplicator>> RemoteReplicators;
};
@@ -0,0 +1,74 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "CogAbilityReplicator.generated.h"
class AActor;
class UAbilitySystemComponent;
class UCogAbilityDataAsset_Tweaks;
struct FCogAbilityCheat;
struct FCogAbilityTweak;
struct FGameplayTag;
UCLASS(NotBlueprintable, NotBlueprintType, notplaceable, noteditinlinenew, hidedropdown, Transient)
class COGABILITY_API ACogAbilityReplicator : public AActor
{
GENERATED_UCLASS_BODY()
public:
static void Create(APlayerController* Controller);
virtual void BeginPlay() override;
APlayerController* GetPlayerController() const { return OwnerPlayerController.Get(); }
void ApplyCheat(AActor* CheatInstigator, const TArray<AActor*>& Targets, const FCogAbilityCheat& Cheat);
static bool IsCheatActive(const AActor* EffectTarget, const FCogAbilityCheat& Cheat);
void GiveAbility(AActor* TargetActor, TSubclassOf<UGameplayAbility> AbilityClass);
void ResetAllTweaks();
void SetTweakValue(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 CategoryIndex, float Value);
void SetTweakProfile(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 ProfileIndex);
int32 GetTweakProfileIndex() const { return TweakProfileIndex; }
float GetTweakCurrentValue(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 CategoryIndex);
float* GetTweakCurrentValuePtr(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 CategoryIndex);
private:
UFUNCTION(Reliable, Server)
void Server_ApplyCheat(const AActor* CheatInstigator, const TArray<AActor*>& TargetActors, const FCogAbilityCheat& Cheat) const;
UFUNCTION(Reliable, Server)
void Server_GiveAbility(AActor* TargetActor, TSubclassOf<UGameplayAbility> AbilityClass) const;
UFUNCTION(Reliable, Server)
void Server_ResetAllTweaks();
UFUNCTION(Reliable, Server)
void Server_SetTweakValue(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 TweakCategoryIndex, float Value);
UFUNCTION(Reliable, Server)
void Server_SetTweakProfile(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 ProfileIndex);
void SetTweakCurrentValue(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakIndex, int32 CategoryIndex, float Value);
void ApplyTweakOnActor(AActor* Actor, const FCogAbilityTweak& Tweak, float Value, const FGameplayTag& SetByCallerMagnitudeTag);
void ApplyAllTweaksOnActor(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 TweakCategoryIndex, AActor* Actor);
void GetActorsFromTweakCategory(const UCogAbilityDataAsset_Tweaks* TweaksAsset, int32 CategoryIndex, TArray<AActor*>& Actors);
TObjectPtr<APlayerController> OwnerPlayerController;
UPROPERTY(Replicated)
int32 TweakProfileIndex = INDEX_NONE;
UPROPERTY(Replicated)
TArray<float> TweakCurrentValues;
};
@@ -0,0 +1,57 @@
#pragma once
#include "CoreMinimal.h"
#include "CogWindow.h"
#include "CogAbilityWindow_Abilities.generated.h"
class UGameplayAbility;
class UCogAbilityDataAsset_Abilities;
struct FGameplayAbilitySpec;
UCLASS()
class COGABILITY_API UCogAbilityWindow_Abilities : public UCogWindow
{
GENERATED_BODY()
public:
TWeakObjectPtr<UCogAbilityDataAsset_Abilities> AbilitiesAsset;
protected:
virtual void PreRender(ImGuiWindowFlags& WindowFlags) override;
virtual void RenderTick(float DetlaTime) override;
virtual void RenderContent() override;
virtual void GameTick(float DeltaTime) override;
virtual void RenderAbiltiesMenu(AActor* Selection);
virtual FString GetAbilityName(const UGameplayAbility* Ability);
virtual void RenderAbilitiesTable(UAbilitySystemComponent& AbilitySystemComponent);
virtual void RenderAbilityContextMenu(UAbilitySystemComponent& AbilitySystemComponent, FGameplayAbilitySpec& Spec, int Index);
virtual void RenderOpenAbilities();
virtual void RenderAbilityInfo(FGameplayAbilitySpec& Spec);
virtual void ProcessAbilityActivation(FGameplayAbilitySpecHandle Handle);
virtual void ActivateAbility(UAbilitySystemComponent& AbilitySystemComponent, FGameplayAbilitySpec& Spec);
virtual void DeactivateAbility(UAbilitySystemComponent& AbilitySystemComponent, FGameplayAbilitySpec& Spec);
virtual void OpenAbility(FGameplayAbilitySpecHandle Handle);
virtual void CloseAbility(FGameplayAbilitySpecHandle Handle);
private:
FGameplayAbilitySpecHandle AbilityHandleToActivate;
TArray<FGameplayAbilitySpecHandle> OpenedAbilities;
};
@@ -0,0 +1,31 @@
#pragma once
#include "CoreMinimal.h"
#include "CogWindow.h"
#include "CogAbilityWindow_Attributes.generated.h"
UCLASS(Config = Cog)
class COGABILITY_API UCogAbilityWindow_Attributes : public UCogWindow
{
GENERATED_BODY()
public:
UCogAbilityWindow_Attributes();
virtual void PreRender(ImGuiWindowFlags& WindowFlags) override;
virtual void RenderContent() override;
UPROPERTY(Config)
bool bSortByNameSetting = true;
UPROPERTY(Config)
bool bGroupByAttributeSetSetting = false;
UPROPERTY(Config)
bool bGroupByCategorySetting = false;
UPROPERTY(Config)
bool bShowOnlyModified = false;
ImGuiTextFilter Filter;
};
@@ -0,0 +1,30 @@
#pragma once
#include "CoreMinimal.h"
#include "CogWindow.h"
#include "CogAbilityWindow_Cheats.generated.h"
class AActor;
class UCogAbilityDataAsset_Cheats;
struct FCogAbilityCheat;
UCLASS(Config = Cog)
class COGABILITY_API UCogAbilityWindow_Cheats : public UCogWindow
{
GENERATED_BODY()
public:
UCogAbilityWindow_Cheats();
virtual void RenderContent() override;
TWeakObjectPtr<UCogAbilityDataAsset_Cheats> CheatsAsset;
private:
void AddCheat(AActor* InstigatorActor, AActor* TargetActor, const FCogAbilityCheat& CheatEffect, bool IsPersistent);
void RequestCheat(AActor* InstigatorActor, AActor* TargetActor, const FCogAbilityCheat& CheatEffect);
UPROPERTY(Config)
TArray<FString> AppliedCheats;
};
@@ -0,0 +1,70 @@
#pragma once
#include "CoreMinimal.h"
#include "CogWindow.h"
#include "CogAbilityWindow_Damages.generated.h"
struct FCogAbilityDamageParams;
//--------------------------------------------------------------------------------------------------------------------------
class FCogDamageInstance
{
public:
void Restart();
void AddDamage(const float Damage);
void UpdateDamagePerSecond(const float Duration);
float DamageLast = 0.0f;
float DamageMin = 0.0f;
float DamageMax = 0.0f;
float DamagePerFrame = 0.0f;
float DamagePerSecond = 0.0f;
float DamageTotal = 0.0f;
};
//--------------------------------------------------------------------------------------------------------------------------
class FCogDamageStats
{
public:
void AddDamage(const float Damage, const float UnmitigatedDamage, const bool bIsCrit);
void Tick(const float DeltaSeconds);
void Restart();
int Count = 0;
int Crits = 0;
bool IsInProgress = false;
float TotalCritChances = 0.0f;
float Timer = 0.0f;
float MaxDuration = 0.0f;
float RestartTimer = 0.0f;
FCogDamageInstance Mitigated;
FCogDamageInstance Unmitigated;
static float MaxDurationSetting;
static float RestartDelaySetting;
};
//--------------------------------------------------------------------------------------------------------------------------
UCLASS()
class COGABILITY_API UCogAbilityWindow_Damages : public UCogWindow
{
GENERATED_BODY()
public:
UCogAbilityWindow_Damages();
virtual void RenderContent() override;
virtual void RenderTick(float DeltaSeconds) override;
protected:
virtual void OnSelectionChanged(AActor* OldSelection, AActor* NewSelection) override;
private:
UFUNCTION()
void OnDamageEvent(const FCogAbilityDamageParams& Params);
FCogDamageStats DamageDealtStats;
FCogDamageStats DamageReceivedStats;
FDelegateHandle OnDamageEventDelegate;
};
@@ -0,0 +1,38 @@
#pragma once
#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "CogWindow.h"
#include "CogAbilityWindow_Effects.generated.h"
UCLASS()
class COGABILITY_API UCogAbilityWindow_Effects : public UCogWindow
{
GENERATED_BODY()
public:
FGameplayTag NegativeEffectTag;
FGameplayTag PositiveEffectTag;
protected:
virtual void PreRender(ImGuiWindowFlags& WindowFlags) override;
virtual void RenderContent() override;
virtual void DrawEffectRow(const UAbilitySystemComponent& AbilitySystemComponent, const FActiveGameplayEffectHandle& ActiveHandle, int32 Index, int32& Selected);
virtual void DrawEffectInfo(const UAbilitySystemComponent& AbilitySystemComponent, const FActiveGameplayEffect& ActiveEffect, const UGameplayEffect& Effect);
virtual void DrawTagContainer(const FGameplayTagContainer& Container);
virtual FString GetEffectName(const UGameplayEffect& Effect);
virtual void DrawRemainingTime(const UAbilitySystemComponent& AbilitySystemComponent, const FActiveGameplayEffect& ActiveEffect);
virtual void DrawStacks(const FActiveGameplayEffect& ActiveEffect, const UGameplayEffect& Effect);
virtual void DrawPrediction(const FActiveGameplayEffect& ActiveEffect, bool Short);
};
@@ -0,0 +1,20 @@
#pragma once
#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "CogWindow.h"
#include "CogAbilityWindow_Pools.generated.h"
class UCogAbilityDataAsset_Pools;
UCLASS()
class COGABILITY_API UCogAbilityWindow_Pools : public UCogWindow
{
GENERATED_BODY()
public:
UCogAbilityWindow_Pools();
virtual void RenderContent() override;
TWeakObjectPtr<UCogAbilityDataAsset_Pools> PoolsAsset;
};
@@ -0,0 +1,17 @@
#pragma once
#include "CoreMinimal.h"
#include "CogWindow.h"
#include "CogAbilityWindow_Tags.generated.h"
UCLASS()
class COGABILITY_API UCogAbilityWindow_Tags : public UCogWindow
{
GENERATED_BODY()
public:
UCogAbilityWindow_Tags();
virtual void PreRender(ImGuiWindowFlags& WindowFlags) override;
virtual void RenderContent() override;
};
@@ -0,0 +1,23 @@
#pragma once
#include "CoreMinimal.h"
#include "CogWindow.h"
#include "CogAbilityWindow_Tweaks.generated.h"
class AActor;
class UCogAbilityDataAsset_Tweaks;
class ACogAbilityReplicator;
UCLASS()
class COGABILITY_API UCogAbilityWindow_Tweaks : public UCogWindow
{
GENERATED_BODY()
public:
UCogAbilityWindow_Tweaks();
virtual void RenderContent() override;
TWeakObjectPtr<UCogAbilityDataAsset_Tweaks> TweaksAsset;
private:
};
+35
View File
@@ -0,0 +1,35 @@
{
"FileVersion": 1,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "CogDebug",
"Description": "",
"Category": "Other",
"CreatedBy": "Arnaud Jamin",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "CogDebug",
"Type": "Runtime",
"LoadingPhase": "Default"
},
{
"Name": "CogDebugEditor",
"Type": "UncookedOnly",
"LoadingPhase": "Default"
}
],
"Plugins": [
{
"Name": "CogImgui",
"Enabled": true
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1,48 @@
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"
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"NetCore",
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
}
);
}
}
@@ -0,0 +1,520 @@
#include "CogDebugDraw.h"
#include "CogDebugDrawHelper.h"
#include "CogDebugShape.h"
#include "CogDebugHelper.h"
#include "CogDebugDrawImGui.h"
#include "CogImguiHelper.h"
#include "CogDebugLogCategoryManager.h"
#include "CogDebugModule.h"
#include "CogDebugReplicator.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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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 (FCogDebugLogCategoryManager::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)
{
const UWorld* World = WorldContextObject != nullptr ? WorldContextObject->GetWorld() : nullptr;
const ENetMode NetMode = World->GetNetMode();
if (NetMode == NM_DedicatedServer || NetMode == NM_ListenServer)
{
for (const TObjectPtr<ACogDebugReplicator>& Replicator : FCogDebugModule::Get().GetRemoteReplicators())
{
Replicator->ReplicatedShapes.Add(Shape);
}
}
}
#endif //ENABLE_COG
@@ -0,0 +1,191 @@
#include "CogDebugDrawBlueprint.h"
#include "CogDebugDraw.h"
//--------------------------------------------------------------------------------------------------------------------------
void UCogDebugDrawBlueprint::DebugLogString(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::DebugLogPoint(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::DebugLogSegment(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::DebugLogArrow(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::DebugLogAxis(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::DebugLogSphere(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::DebugLogBox(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::DebugLogSolidBox(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::DebugLogCapsule(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::DebugLogCircle(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::DebugLogCircleArc(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::DebugLogPoints(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::DebugLogPath(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::DebugLogString2D(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::DebugLogSegment2D(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::DebugLogCircle2D(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::DebugLogRect2D(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,54 @@
#include "CogDebugLogBlueprint.h"
#include "CogDebugLogCategoryManager.h"
#include "CogDebugLogMacros.h"
//--------------------------------------------------------------------------------------------------------------------------
void UCogDebugLogBlueprint::Log(FCogLogCategory LogCategory, ECogLogVerbosity Verbosity, const AActor* Actor, 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 (Actor != nullptr)
{
COG_LOG_ACTOR_NO_CONTEXT(*LogCategoryPtr, (ELogVerbosity::Type)Verbosity, Actor, TEXT("%s"), *Text);
}
else
{
COG_LOG(*LogCategoryPtr, (ELogVerbosity::Type)Verbosity, TEXT("%s"), *Text);
}
#endif //ENABLE_COG
}
//--------------------------------------------------------------------------------------------------------------------------
bool UCogDebugLogBlueprint::IsLogActive(FCogLogCategory LogCategory, const AActor* Actor)
{
#if ENABLE_COG
if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory())
{
if (FCogDebugLogCategoryManager::IsLogCategoryActive(*LogCategoryPtr) == false)
{
return false;
}
if (FCogDebugSettings::IsDebugActiveForActor(Actor) == false)
{
return false;
}
return true;
}
#endif //ENABLE_COG
return false;
}
@@ -0,0 +1,31 @@
#include "CogDebugLogCategory.h"
#include "CogDebugLogCategoryManager.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 = FCogDebugLogCategoryManager::GetLogCategories().Find(Name))
{
LogCategory = CategoryInfo->LogCategory;
}
}
return LogCategory;
#endif //NO_LOGGING
}
@@ -0,0 +1,122 @@
#include "CogDebugLogCategoryManager.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> FCogDebugLogCategoryManager::LogCategories;
//--------------------------------------------------------------------------------------------------------------------------
void FCogDebugLogCategoryManager::AddLogCategory(FLogCategoryBase& LogCategory)
{
LogCategories.Add(LogCategory.GetCategoryName(), FCogDebugLogCategoryInfo{ &LogCategory, ELogVerbosity::NumVerbosity });
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogDebugLogCategoryManager::IsVerbosityActive(ELogVerbosity::Type Verbosity)
{
return Verbosity >= ELogVerbosity::Verbose;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogDebugLogCategoryManager::IsLogCategoryActive(const FLogCategoryBase& LogCategory)
{
return IsVerbosityActive(LogCategory.GetVerbosity());
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogDebugLogCategoryManager::IsLogCategoryActive(FName CategoryName)
{
if (FLogCategoryBase* LogCategory = FindLogCategory(CategoryName))
{
return IsVerbosityActive(LogCategory->GetVerbosity());
}
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDebugLogCategoryManager::SetLogCategoryActive(FLogCategoryBase& LogCategory, bool Value)
{
LogCategory.SetVerbosity(Value ? ELogVerbosity::Verbose : ELogVerbosity::Warning);
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDebugLogCategoryManager::OnServerVerbosityChanged(FName CategoryName, ELogVerbosity::Type Verbosity)
{
if (FCogDebugLogCategoryInfo* LogCategoryInfo = FindLogCategoryInfo(CategoryName))
{
LogCategoryInfo->ServerVerbosity = Verbosity;
}
}
//--------------------------------------------------------------------------------------------------------------------------
ELogVerbosity::Type FCogDebugLogCategoryManager::GetServerVerbosity(FName CategoryName)
{
if (FCogDebugLogCategoryInfo* LogCategoryInfo = FindLogCategoryInfo(CategoryName))
{
return LogCategoryInfo->ServerVerbosity;
}
return ELogVerbosity::NoLogging;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDebugLogCategoryManager::SetServerVerbosity(FName CategoryName, ELogVerbosity::Type Verbosity)
{
if (ACogDebugReplicator* Replicator = FCogDebugModule::Get().GetLocalReplicator())
{
Replicator->Server_SetCategoryVerbosity(CategoryName, (ECogLogVerbosity)Verbosity);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDebugLogCategoryManager::SetServerVerbosityActive(FName CategoryName, bool Value)
{
SetServerVerbosity(CategoryName, Value ? ELogVerbosity::Verbose : ELogVerbosity::Warning);
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogDebugLogCategoryManager::IsServerVerbosityActive(FName CategoryName)
{
return IsVerbosityActive(GetServerVerbosity(CategoryName));
}
//--------------------------------------------------------------------------------------------------------------------------
FCogDebugLogCategoryInfo* FCogDebugLogCategoryManager::FindLogCategoryInfo(FName CategoryName)
{
return LogCategories.Find(CategoryName);
}
//--------------------------------------------------------------------------------------------------------------------------
FLogCategoryBase* FCogDebugLogCategoryManager::FindLogCategory(FName CategoryName)
{
if (FCogDebugLogCategoryInfo* LogCategoryInfo = FindLogCategoryInfo(CategoryName))
{
return LogCategoryInfo->LogCategory;
}
else
{
return nullptr;
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDebugLogCategoryManager::DeactivateAllLogCateories(UWorld& World)
{
FString ToggleStr = TEXT("Log LogCogNone Only");
GEngine->Exec(&World, *ToggleStr);
if (APlayerController* PlayerController = World.GetFirstPlayerController())
{
PlayerController->ServerExec(ToggleStr);
}
}
@@ -0,0 +1,48 @@
#include "CogDebugModule.h"
#define LOCTEXT_NAMESPACE "FCogDebugModule"
//--------------------------------------------------------------------------------------------------------------------------
void FCogDebugModule::StartupModule()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDebugModule::ShutdownModule()
{
}
//--------------------------------------------------------------------------------------------------------------------------
ACogDebugReplicator* FCogDebugModule::GetLocalReplicator()
{
return LocalReplicator;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDebugModule::SetLocalReplicator(ACogDebugReplicator* Value)
{
LocalReplicator = Value;
}
//--------------------------------------------------------------------------------------------------------------------------
ACogDebugReplicator* FCogDebugModule::GetRemoteReplicator(const APlayerController* PlayerController)
{
for (ACogDebugReplicator* Replicator : RemoteReplicators)
{
if (Replicator->GetPlayerController() == PlayerController)
{
return Replicator;
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogDebugModule::AddRemoteReplicator(ACogDebugReplicator* Value)
{
RemoteReplicators.Add(Value);
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FCogDebugModule, CogDebug)
@@ -0,0 +1,528 @@
#include "CogDebugPlot.h"
#include "CogDebugFilteredActorInterface.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;
}
//---------------------------------------------------------------------------------
// Cast to ICogActorFilteringDebugInterface to know if we should filter
//---------------------------------------------------------------------------------
if (Cast<ICogDebugFilteredActorInterface>(WorldContextObject))
{
if (WorldContextObject != FCogDebugSettings::GetSelection())
{
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 "CogDebugDefines.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,263 @@
#include "CogDebugReplicator.h"
#include "CogDebugDraw.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/WorldSettings.h"
#include "Net/Core/PushModel/PushModel.h"
#include "Net/UnrealNetwork.h"
//--------------------------------------------------------------------------------------------------------------------------
// 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;
}
//--------------------------------------------------------------------------------------------------------------------------
// ACogDebugReplicator
//--------------------------------------------------------------------------------------------------------------------------
void ACogDebugReplicator::Create(APlayerController* Controller)
{
if (Controller->GetWorld()->GetNetMode() != NM_Client)
{
FActorSpawnParameters SpawnInfo;
SpawnInfo.Owner = Controller;
Controller->GetWorld()->SpawnActor<ACogDebugReplicator>(SpawnInfo);
}
}
//--------------------------------------------------------------------------------------------------------------------------
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;
bHasAuthority = false;
bIsLocal = false;
bReplicates = true;
bOnlyRelevantToOwner = true;
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;
bIsLocal = NetMode != NM_DedicatedServer;
OwnerPlayerController = Cast<APlayerController>(GetOwner());
if (OwnerPlayerController->IsLocalController())
{
FCogDebugModule::Get().SetLocalReplicator(this);
Server_RequestAllCategoriesVerbosity();
}
else
{
FCogDebugModule::Get().AddRemoteReplicator(this);
}
}
//--------------------------------------------------------------------------------------------------------------------------
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_DedicatedServer)
{
if (FCogDebugLogCategoryInfo* LogCategoryInfo = FCogDebugLogCategoryManager::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)
{
FCogDebugLogCategoryManager::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)
{
FCogDebugLogCategoryManager::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_DedicatedServer)
{
TArray<FCogServerCategoryData> CategoriesData;
for (auto& Entry : FCogDebugLogCategoryManager::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
}
@@ -0,0 +1,202 @@
#include "CogDebugSettings.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::IsDebugActiveForActor(const AActor* Actor)
{
const AActor* SelectionPtr = Selection.Get();
if (Actor == nullptr || SelectionPtr == nullptr)
{
return true;
}
if (Cast<ICogDebugFilteredActorInterface>(Actor))
{
return (SelectionPtr == Actor || FilterBySelection == false);
}
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,628 @@
#include "CogDebugShape.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(FVector(Rotation.Pitch, Rotation.Yaw, Rotation.Roll));
NewElement.ShapeData.Add(Extent);
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[1].X, ShapeData[1].Y, ShapeData[1].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,29 @@
#pragma once
#include "CoreMinimal.h"
#include "CogDebugAllegianceInterface.generated.h"
//--------------------------------------------------------------------------------------------------------------------------
UENUM(BlueprintType)
enum class ECogAllegiance : uint8
{
Ally,
Enemy
};
//--------------------------------------------------------------------------------------------------------------------------
UINTERFACE(MinimalAPI, Blueprintable)
class UCogAllegianceInterface : public UInterface
{
GENERATED_BODY()
};
//--------------------------------------------------------------------------------------------------------------------------
class ICogAllegianceInterface
{
GENERATED_BODY()
public:
virtual ECogAllegiance GetAllegiance(const AActor* OtherActor) const = 0;
};
@@ -0,0 +1,7 @@
#pragma once
#include "CoreMinimal.h"
#ifndef ENABLE_COG
#define ENABLE_COG (ENABLE_DRAW_DEBUG && !NO_LOGGING)
#endif
@@ -0,0 +1,58 @@
#pragma once
#include "CoreMinimal.h"
#include "CogDebugLogMacros.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 DebugLogString(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FString& Text, const FVector Location, const FLinearColor Color, bool Persistent);
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
static void DebugLogPoint(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 DebugLogSegment(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 DebugLogArrow(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 DebugLogAxis(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 DebugLogSphere(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 DebugLogBox(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 DebugLogSolidBox(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 DebugLogCapsule(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 DebugLogCircle(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 DebugLogCircleArc(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 DebugLogPoints(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 DebugLogPath(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 DebugLogString2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FString& Text, const FVector2D Location, const FLinearColor Color, bool Persistent);
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
static void DebugLogSegment2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector2D SegmentStart, const FVector2D SegmentEnd, const FLinearColor Color, bool Persistent);
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
static void DebugLogCircle2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector2D Location, float Radius, const FLinearColor Color, bool Persistent);
UFUNCTION(BlueprintCallable, meta = (DevelopmentOnly, WorldContext = "WorldContextObject"))
static void DebugLogRect2D(const UObject* WorldContextObject, FCogLogCategory LogCategory, const FVector2D Min, const FVector2D Max, const FLinearColor Color, bool Persistent);
};
@@ -0,0 +1,40 @@
#pragma once
#include "CoreMinimal.h"
#include "CogDebugDefines.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 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,17 @@
#pragma once
#include "CoreMinimal.h"
#include "CogDebugFilteredActorInterface.generated.h"
UINTERFACE(MinimalAPI, Blueprintable)
class UCogDebugFilteredActorInterface : public UInterface
{
GENERATED_BODY()
};
class ICogDebugFilteredActorInterface
{
GENERATED_BODY()
virtual bool IsActorFilteringDebug() const { return true; }
};
@@ -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,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, Category = "Log", meta = (DevelopmentOnly))
static void Log(FCogLogCategory LogCategory, ECogLogVerbosity Verbosity = ECogLogVerbosity::Verbose, const AActor* Actor = nullptr, const FString& Text = FString(""));
UFUNCTION(BlueprintPure, Category = "Log", meta = (DevelopmentOnly, AdvancedDisplay = "ScreenTextColor"))
static bool IsLogActive(FCogLogCategory LogCategory, const AActor* Actor = nullptr);
};
@@ -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,53 @@
#pragma once
#include "CoreMinimal.h"
#include "CogDebugDefines.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;
};
//--------------------------------------------------------------------------------------------------------------------------
struct COGDEBUG_API FCogDebugLogCategoryManager
{
static void AddLogCategory(FLogCategoryBase& LogCategory);
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(FName LogCategory, bool Value);
static bool IsServerVerbosityActive(FName LogCategory);
static ELogVerbosity::Type GetServerVerbosity(FName LogCategory);
static void SetServerVerbosity(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,52 @@
#pragma once
#include "CoreMinimal.h"
#include "CogDebugDefines.h"
#include "CogDebugSettings.h"
#include "Templates/IsArrayOrRefOfType.h"
#if !ENABLE_COG
#define COG_LOG(LogCategory, Verbosity, Format, ...) (0)
#define COG_LOG_FUNC(LogCategory, Verbosity, Format, ...) (0)
#define COG_LOG_ACTOR(LogCategory, Verbosity, Actor, Format, ...) (0)
#define COG_LOG_ACTOR_NO_CONTEXT(LogCategory, Verbosity, Actor, Format, ...) (0)
#else //!ENABLE_COG
//--------------------------------------------------------------------------------------------------------------------------
#define COG_LOG_ACTIVE_FOR_ACTOR(Actor) (FCogDebugSettings::IsDebugActiveForActor(Actor))
//--------------------------------------------------------------------------------------------------------------------------
#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_ACTOR(LogCategory, Verbosity, Actor, Format, ...) \
if (COG_LOG_ACTIVE_FOR_ACTOR(Actor) || (int32)Verbosity <= (int32)ELogVerbosity::Warning) \
{ \
COG_LOG(LogCategory, Verbosity, TEXT("%s - %s - %s"), \
*GetNameSafe(Actor), \
ANSI_TO_TCHAR(__FUNCTION__), \
*FString::Printf(Format, ##__VA_ARGS__)); \
} \
//--------------------------------------------------------------------------------------------------------------------------
#define COG_LOG_ACTOR_NO_CONTEXT(LogCategory, Verbosity, Actor, Format, ...) \
if (COG_LOG_ACTIVE_FOR_ACTOR(Actor) || (int32)Verbosity <= (int32)ELogVerbosity::Warning) \
{ \
COG_LOG(LogCategory, Verbosity, TEXT("%s - %s"), *GetNameSafe(Actor), *FString::Printf(Format, ##__VA_ARGS__)); \
} \
#endif //!ENABLE_COG
@@ -0,0 +1,34 @@
#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;
ACogDebugReplicator* GetLocalReplicator();
void SetLocalReplicator(ACogDebugReplicator* Value);
ACogDebugReplicator* GetRemoteReplicator(const APlayerController* PlayerController);
TArray<TObjectPtr<ACogDebugReplicator>> GetRemoteReplicators() const { return RemoteReplicators; }
void AddRemoteReplicator(ACogDebugReplicator* Value);
private:
TObjectPtr<ACogDebugReplicator> LocalReplicator;
TArray<TObjectPtr<ACogDebugReplicator>> RemoteReplicators;
};
@@ -0,0 +1,123 @@
#pragma once
#include "CoreMinimal.h"
#include "CogDebugDefines.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,96 @@
#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 void Create(APlayerController* Controller);
virtual void BeginPlay() override;
virtual void TickActor(float DeltaTime, enum ELevelTick TickType, FActorTickFunction& ThisTickFunction) override;
APlayerController* GetPlayerController() const { return OwnerPlayerController.Get(); }
bool IsLocal() const { return bIsLocal; }
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;
uint32 bIsLocal : 1;
private:
UPROPERTY(Replicated)
FCogReplicatorNetPack ReplicatedData;
};
@@ -0,0 +1,45 @@
#pragma once
#include "CoreMinimal.h"
#include "CogDebugLogMacros.h"
struct COGDEBUG_API FCogDebugSettings
{
public:
//----------------------------------------------------------------------------------------------------------------------
static bool IsDebugActiveForActor(const AActor* Actor);
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 "CogDebugLogCategoryManager.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 : FCogDebugLogCategoryManager::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 : FCogDebugLogCategoryManager::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;
};
+38
View File
@@ -0,0 +1,38 @@
{
"FileVersion": 1,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "CogEngine",
"Description": "",
"Category": "Other",
"CreatedBy": "Arnaud Jamin",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules": [
{
"Name": "CogEngine",
"Type": "Runtime",
"LoadingPhase": "Default"
}
],
"Plugins": [
{
"Name": "CogImgui",
"Enabled": true
},
{
"Name": "CogDebug",
"Enabled": true
},
{
"Name": "CogWindow",
"Enabled": true
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1,50 @@
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",
"CogImgui",
"CogDebug",
"CogWindow",
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"NetCore",
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
}
);
}
}
@@ -0,0 +1,48 @@
#include "CogEngineModule.h"
#define LOCTEXT_NAMESPACE "FCogEngineModule"
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineModule::StartupModule()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineModule::ShutdownModule()
{
}
//--------------------------------------------------------------------------------------------------------------------------
ACogEngineReplicator* FCogEngineModule::GetLocalReplicator()
{
return LocalReplicator;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineModule::SetLocalReplicator(ACogEngineReplicator* Value)
{
LocalReplicator = Value;
}
//--------------------------------------------------------------------------------------------------------------------------
ACogEngineReplicator* FCogEngineModule::GetRemoteReplicator(const APlayerController* PlayerController)
{
for (ACogEngineReplicator* Replicator : RemoteReplicators)
{
if (Replicator->GetPlayerController() == PlayerController)
{
return Replicator;
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineModule::AddRemoteReplicator(ACogEngineReplicator* Value)
{
RemoteReplicators.Add(Value);
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FCogEngineModule, CogEngine)
@@ -0,0 +1,120 @@
#include "CogEngineReplicator.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/WorldSettings.h"
#include "Net/Core/PushModel/PushModel.h"
#include "Net/UnrealNetwork.h"
//--------------------------------------------------------------------------------------------------------------------------
void ACogEngineReplicator::Create(APlayerController* Controller)
{
if (Controller->GetWorld()->GetNetMode() != NM_Client)
{
FActorSpawnParameters SpawnInfo;
SpawnInfo.Owner = Controller;
Controller->GetWorld()->SpawnActor<ACogEngineReplicator>(SpawnInfo);
}
}
//--------------------------------------------------------------------------------------------------------------------------
ACogEngineReplicator::ACogEngineReplicator(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;
bHasAuthority = false;
bIsLocal = false;
bReplicates = true;
bOnlyRelevantToOwner = true;
#endif // !UE_BUILD_SHIPPING
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogEngineReplicator::BeginPlay()
{
Super::BeginPlay();
UWorld* World = GetWorld();
check(World);
const ENetMode NetMode = World->GetNetMode();
bHasAuthority = NetMode != NM_Client;
bIsLocal = NetMode != NM_DedicatedServer;
OwnerPlayerController = Cast<APlayerController>(GetOwner());
if (OwnerPlayerController->IsLocalController())
{
FCogEngineModule::Get().SetLocalReplicator(this);
}
else
{
FCogEngineModule::Get().AddRemoteReplicator(this);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogEngineReplicator::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
FDoRepLifetimeParams Params;
Params.bIsPushBased = true;
DOREPLIFETIME_WITH_PARAMS_FAST(ACogEngineReplicator, TimeDilation, Params);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogEngineReplicator::TickSpawnActions()
{
#if !UE_BUILD_SHIPPING
if (OwnerPlayerController == nullptr)
{
return;
}
for (int32 i = SpawnActions.Num() - 1; i >= 0; --i)
{
const FCogEngineReplicatorSpawnAction& SpawnInfo = SpawnActions[i];
SpawnActions.RemoveAt(i);
}
#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
}
@@ -0,0 +1,373 @@
#include "CogEngineWindow_Collisions.h"
#include "CogDebugDrawHelper.h"
#include "CogDebugSettings.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"
//--------------------------------------------------------------------------------------------------------------------------
UCogEngineWindow_Collisions::UCogEngineWindow_Collisions()
{
ObjectTypesToQuery = 0;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogEngineWindow_Collisions::SetCollisionsAsset(const UCogEngineDataAsset_Collisions* Asset)
{
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);
}
}
//--------------------------------------------------------------------------------------------------------------------------
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;
}
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();
}
ImGui::Separator();
//-------------------------------------------------
// Query Mode
//-------------------------------------------------
static int QueryType = 0;
ImGui::Combo("Query", &QueryType,
"Sphere\0"
"Raycast Crosshair\0"
"Raycast Cursor\0"
"\0"
);
//-------------------------------------------------
// Query Distance
//-------------------------------------------------
static float QueryDistance = 5000.0f;
ImGui::SliderFloat("Distance", &QueryDistance, 0.0f, 20000.0f, "%0.f");
//-------------------------------------------------
// Query Thickness
//-------------------------------------------------
static float QueryThickness = 0.0f;
if (QueryType == 1 || QueryType == 2)
{
ImGui::SliderFloat("Thickness", &QueryThickness, 0.0f, 1000.0f, "%0.f");
}
//-------------------------------------------------
// Query Use Complex Collisions
//-------------------------------------------------
static bool UseComplexCollisions = false;
ImGui::Checkbox("Use Complex Collisions", &UseComplexCollisions);
//-------------------------------------------------
// Show Names
//-------------------------------------------------
static bool ShowActorsNames = false;
ImGui::Checkbox("Show Actors Names", &ShowActorsNames);
//-------------------------------------------------
// Show Query
//-------------------------------------------------
static bool ShowQuery = false;
ImGui::Checkbox("Show Query", &ShowQuery);
//-------------------------------------------------
// Perform Query
//-------------------------------------------------
if (ObjectTypesToQuery == 0)
{
return;
}
UWorld* World = GetWorld();
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;
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;
}
}
}
}
@@ -0,0 +1,105 @@
#include "CogEngineWindow_DebugSettings.h"
#include "CogDebugSettings.h"
#include "CogWindowWidgets.h"
//--------------------------------------------------------------------------------------------------------------------------
UCogEngineWindow_DebugSettings::UCogEngineWindow_DebugSettings()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogEngineWindow_DebugSettings::PreRender(ImGuiWindowFlags& WindowFlags)
{
WindowFlags = ImGuiWindowFlags_MenuBar;
}
//--------------------------------------------------------------------------------------------------------------------------
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.");
const float ItemsWidth = FCogWindowWidgets::TextBaseWidth * 10;
ImGui::SetNextItemWidth(ItemsWidth);
ImGui::Checkbox("Fade 2D", &FCogDebugSettings::Fade2D);
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("Does the 2D debug is fading out.");
ImGui::SetNextItemWidth(ItemsWidth);
ImGui::DragFloat("Duration", &FCogDebugSettings::Duration, 0.01f, 0.0f, 100.0f, "%.1f");
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("The duration of debug elements.");
ImGui::SetNextItemWidth(ItemsWidth);
ImGui::DragFloat("Thickness", &FCogDebugSettings::Thickness, 0.05f, 0.0f, 5.0f, "%.1f");
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("The thickness of debug lines.");
ImGui::SetNextItemWidth(ItemsWidth);
ImGui::DragFloat("Server Thickness", &FCogDebugSettings::ServerThickness, 0.05f, 0.0f, 5.0f, "%.1f");
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("The thickness the server debug lines.");
ImGui::SetNextItemWidth(ItemsWidth);
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.");
ImGui::SetNextItemWidth(ItemsWidth);
ImGui::DragInt("Depth Priority", &FCogDebugSettings::DepthPriority, 0.1f, 0, 100);
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("The depth priority of debug elements.");
ImGui::SetNextItemWidth(ItemsWidth);
ImGui::DragInt("Segments", &FCogDebugSettings::Segments, 0.1f, 4, 20.0f);
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("The number of segments used for circular shapes.");
ImGui::SetNextItemWidth(ItemsWidth);
ImGui::DragFloat("Axes Scale", &FCogDebugSettings::AxesScale, 0.1f, 0, 10.0f, "%.1f");
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("The scaling debug axis.");
ImGui::SetNextItemWidth(ItemsWidth);
ImGui::DragFloat("Arrow Size", &FCogDebugSettings::ArrowSize, 1.0f, 0.0f, 200.0f, "%.0f");
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("The size of debug arrows.");
ImGui::SetNextItemWidth(ItemsWidth);
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.");
ImGui::SetNextItemWidth(ItemsWidth);
ImGui::DragFloat("Gradient Speed", &FCogDebugSettings::GradientColorSpeed, 0.1f, 0.0f, 10.0f, "%.1f");
ImGui::SameLine();
FCogWindowWidgets::HelpMarker("The speed of the gradient color change.");
ImGui::SetNextItemWidth(ItemsWidth);
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,207 @@
#include "CogEngineWindow_LogCategories.h"
#include "CogDebugHelper.h"
#include "CogWindowWidgets.h"
#include "CogDebugLogCategoryManager.h"
//--------------------------------------------------------------------------------------------------------------------------
void UCogEngineWindow_LogCategories::PreRender(ImGuiWindowFlags& WindowFlags)
{
WindowFlags = ImGuiWindowFlags_MenuBar;
}
//--------------------------------------------------------------------------------------------------------------------------
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"))
{
FCogDebugLogCategoryManager::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 : FCogDebugLogCategoryManager::GetLogCategories())
{
FName CategoryName = Entry.Key;
const FCogDebugLogCategoryInfo& CategoryInfo = Entry.Value;
FLogCategoryBase* Category = CategoryInfo.LogCategory;
ImGui::PushID(Index);
FString CategoryFriendlyName = Category->GetCategoryName().ToString();
if (bShowAllVerbosity == false)
{
const bool IsControlDown = ImGui::GetIO().KeyCtrl;
if (IsClient)
{
ELogVerbosity::Type Verbosity = FCogDebugLogCategoryManager::GetServerVerbosity(CategoryName);
bool IsActive = FCogDebugLogCategoryManager::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;
FCogDebugLogCategoryManager::SetServerVerbosity(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 = FCogDebugLogCategoryManager::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 = FCogDebugLogCategoryManager::GetServerVerbosity(CategoryName);
ImGui::SetNextItemWidth(FCogWindowWidgets::TextBaseWidth * 12);
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))
{
FCogDebugLogCategoryManager::SetServerVerbosity(CategoryName, Verbosity);
}
}
ImGui::EndCombo();
}
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Server");
ImGui::EndTooltip();
}
ImGui::SameLine();
}
{
ELogVerbosity::Type CurrentVerbosity = Category->GetVerbosity();
ImGui::SetNextItemWidth(FCogWindowWidgets::TextBaseWidth * 12);
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,201 @@
#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 DrawControls(UWorld* World)
{
FWorldContext& WorldContext = GEngine->GetWorldContextFromWorldChecked(World);
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;
}
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;
//-------------------------------------------------------------------------------------------
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.");
}
//-------------------------------------------------------------------------------------------
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.");
}
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.");
}
//-------------------------------------------------------------------------------------------
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.");
}
//-------------------------------------------------------------------------------------------
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();
//-------------------------------------------------------------------------------------------
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");
}
//-------------------------------------------------------------------------------------------
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");
}
//-------------------------------------------------------------------------------------------
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
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogEngineWindow_NetEmulation::RenderContent()
{
Super::RenderContent();
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);
}
ImGui::Separator();
DrawControls(GetWorld());
}
@@ -0,0 +1,307 @@
#include "CogEngineWindow_OutputLog.h"
#include "CogDebugHelper.h"
#include "Engine/Engine.h"
#include "Misc/StringBuilder.h"
char ImGuiTextBuffer::EmptyString[1] = { 0 };
//--------------------------------------------------------------------------------------------------------------------------
// 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);
}
}
//--------------------------------------------------------------------------------------------------------------------------
// FCogWindow_Log
//--------------------------------------------------------------------------------------------------------------------------
UCogEngineWindow_OutputLog::UCogEngineWindow_OutputLog()
{
OutputDevice.OutputLog = this;
}
//--------------------------------------------------------------------------------------------------------------------------
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::PreRender(ImGuiWindowFlags& WindowFlags)
{
WindowFlags = ImGuiWindowFlags_MenuBar;
}
//--------------------------------------------------------------------------------------------------------------------------
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);
//if (ImGui::SmallButton("Add Log"))
//{
// AddLog(TEXT("ABCD"), ELogVerbosity::Verbose, FName("Test"));
// AddLog(TEXT("EFGH"), ELogVerbosity::Warning, FName("Test"));
// AddLog(TEXT("WXYZ"), ELogVerbosity::Error, FName("Test"));
//}
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::TextBaseWidth * 4);
}
if (ShowCategory)
{
ImGui::TableSetupColumn("Category", ImGuiTableColumnFlags_WidthFixed, FCogWindowWidgets::TextBaseWidth * 10);
}
if (ShowVerbosity)
{
ImGui::TableSetupColumn("Verbosity", ImGuiTableColumnFlags_WidthFixed, FCogWindowWidgets::TextBaseWidth * 10);
}
ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthStretch);
}
}
if (IsTableShown == false)
{
ImGui::BeginChild("Scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysVerticalScrollbar);
}
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();
}
}
@@ -0,0 +1,477 @@
#include "CogEngineWindow_Plots.h"
#include "CogImGuiHelper.h"
#include "CogDebugPlot.h"
#include "CogWindowWidgets.h"
#include "imgui.h"
#include "implot_internal.h"
#include "Kismet/GameplayStatics.h"
//--------------------------------------------------------------------------------------------------------------------------
UCogEngineWindow_Plots::UCogEngineWindow_Plots()
{
}
//--------------------------------------------------------------------------------------------------------------------------
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::TextBaseWidth * 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,95 @@
#include "CogEngineWindow_Scalability.h"
#include "imgui.h"
#include "CogImguiHelper.h"
#include "Engine/Engine.h"
#define SCALABILITY_NUM_LEVELS 5
//--------------------------------------------------------------------------------------------------------------------------
UCogEngineWindow_Scalability::UCogEngineWindow_Scalability()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogEngineWindow_Scalability::RenderContent()
{
Super::RenderContent();
Scalability::FQualityLevels Levels = Scalability::GetQualityLevels();
FString CurrentQualityName = Scalability::GetQualityLevelText(Levels.GetMinQualityLevel(), SCALABILITY_NUM_LEVELS).ToString();
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();
if (ImGui::SliderFloat("Resolution", &Levels.ResolutionQuality, 10.0f, 100.0f, "%0.f"))
{
Scalability::SetQualityLevels(Levels);
}
if (ImGui::SliderInt("View Distance", &Levels.ViewDistanceQuality, 0, SCALABILITY_NUM_LEVELS - 1))
{
Scalability::SetQualityLevels(Levels);
}
if (ImGui::SliderInt("Anti Aliasing", &Levels.AntiAliasingQuality, 0, SCALABILITY_NUM_LEVELS - 1))
{
Scalability::SetQualityLevels(Levels);
}
if (ImGui::SliderInt("Shadow", &Levels.ShadowQuality, 0, SCALABILITY_NUM_LEVELS - 1))
{
Scalability::SetQualityLevels(Levels);
}
if (ImGui::SliderInt("Global Illumination", &Levels.GlobalIlluminationQuality, 0, SCALABILITY_NUM_LEVELS - 1))
{
Scalability::SetQualityLevels(Levels);
}
if (ImGui::SliderInt("Reflection", &Levels.ReflectionQuality, 0, SCALABILITY_NUM_LEVELS - 1))
{
Scalability::SetQualityLevels(Levels);
}
if (ImGui::SliderInt("Post Process", &Levels.PostProcessQuality, 0, SCALABILITY_NUM_LEVELS - 1))
{
Scalability::SetQualityLevels(Levels);
}
if (ImGui::SliderInt("Texture", &Levels.TextureQuality, 0, SCALABILITY_NUM_LEVELS - 1))
{
Scalability::SetQualityLevels(Levels);
}
if (ImGui::SliderInt("Effects", &Levels.EffectsQuality, 0, SCALABILITY_NUM_LEVELS - 1))
{
Scalability::SetQualityLevels(Levels);
}
if (ImGui::SliderInt("Foliage", &Levels.FoliageQuality, 0, SCALABILITY_NUM_LEVELS - 1))
{
Scalability::SetQualityLevels(Levels);
}
if (ImGui::SliderInt("Shading", &Levels.ShadingQuality, 0, SCALABILITY_NUM_LEVELS - 1))
{
Scalability::SetQualityLevels(Levels);
}
}
@@ -0,0 +1,485 @@
#include "CogEngineWindow_Selection.h"
#include "CogDebugDraw.h"
#include "CogImguiModule.h"
#include "CogWindowManager.h"
#include "CogWindowWidgets.h"
#include "EngineUtils.h"
#include "imgui.h"
#include "Kismet/GameplayStatics.h"
//--------------------------------------------------------------------------------------------------------------------------
UCogEngineWindow_Selection::UCogEngineWindow_Selection()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogEngineWindow_Selection::PreRender(ImGuiWindowFlags& WindowFlags)
{
WindowFlags = ImGuiWindowFlags_MenuBar;
}
//--------------------------------------------------------------------------------------------------------------------------
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::TextBaseWidth * 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.");
}
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::TextBaseWidth * 5;
const float SelectionButtonWidth = FCogWindowWidgets::TextBaseWidth * 30;
const float ResetButtonWidth = FCogWindowWidgets::TextBaseWidth * 2;
Width = PickButtonWidth + SelectionButtonWidth + ResetButtonWidth;
if (Draw == false)
{
return;
}
if (ImGui::BeginPopup("SelectionPopup"))
{
ImGui::BeginChild("Popup", ImVec2(Width, FCogWindowWidgets::TextBaseWidth * 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(ImGui::GetCursorPos().x - ResetButtonWidth + (ImGui::GetStyle().WindowPadding.x - 2) * ImGui::GetWindowDpiScale());
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,370 @@
#include "CogEngineWindow_Skeleton.h"
#include "CogDebugSettings.h"
#include "Components/LineBatchComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "Engine/SkeletalMesh.h"
//--------------------------------------------------------------------------------------------------------------------------
UCogEngineWindow_Skeleton::UCogEngineWindow_Skeleton()
{
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogEngineWindow_Skeleton::PreRender(ImGuiWindowFlags& WindowFlags)
{
WindowFlags = ImGuiWindowFlags_MenuBar;
}
//--------------------------------------------------------------------------------------------------------------------------
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::TextBaseWidth);
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,126 @@
#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::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)
{
const float ResetButtonWidth = FCogWindowWidgets::TextBaseWidth * 5;
Width = FCogWindowWidgets::TextBaseWidth * 15;
if (Draw == false)
{
return;
}
extern ENGINE_API float GAverageFPS;
ImGui::TextColored(GetFpsColor(GAverageFPS), "%3dfps ", (int32)GAverageFPS);
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);
}
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);
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
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,76 @@
#include "CogEngineWindow_Time.h"
#include "CogEngineReplicator.h"
#include "Engine/Engine.h"
#include "Engine/World.h"
//--------------------------------------------------------------------------------------------------------------------------
void 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::TextBaseWidth, 0)))
{
Replicator->Server_SetTimeDilation(Value);
}
if (IsSelected)
{
ImGui::PopStyleVar();
}
else
{
ImGui::PopStyleColor(3);
}
}
//--------------------------------------------------------------------------------------------------------------------------
UCogEngineWindow_Time::UCogEngineWindow_Time()
{
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_Time::RenderContent()
{
Super::RenderContent();
ACogEngineReplicator* Replicator = FCogEngineModule::Get().GetLocalReplicator();
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);
}
@@ -0,0 +1,32 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "CogEngineDataAsset_Collisions.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);
};
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(Blueprintable)
class COGENGINE_API UCogEngineDataAsset_Collisions : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UCogEngineDataAsset_Collisions() {}
UPROPERTY(EditAnywhere, meta = (TitleProperty = "Channel"))
TArray<FCogCollisionChannel> Channels;
};
@@ -0,0 +1,32 @@
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
class ACogEngineReplicator;
class APlayerController;
class COGENGINE_API FCogEngineModule : public IModuleInterface
{
public:
static inline FCogEngineModule& Get() { return FModuleManager::LoadModuleChecked<FCogEngineModule>("CogEngine"); }
virtual void StartupModule() override;
virtual void ShutdownModule() override;
ACogEngineReplicator* GetLocalReplicator();
void SetLocalReplicator(ACogEngineReplicator* Value);
ACogEngineReplicator* GetRemoteReplicator(const APlayerController* PlayerController);
TArray<TObjectPtr<ACogEngineReplicator>> GetRemoteReplicators() const { return RemoteReplicators; }
void AddRemoteReplicator(ACogEngineReplicator* Value);
private:
TObjectPtr<ACogEngineReplicator> LocalReplicator;
TArray<TObjectPtr<ACogEngineReplicator>> RemoteReplicators;
};
@@ -0,0 +1,60 @@
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "UObject/Class.h"
#include "UObject/ObjectMacros.h"
#include "CogEngineReplicator.generated.h"
class APlayerController;
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct FCogEngineReplicatorSpawnAction
{
GENERATED_USTRUCT_BODY()
bool Control = false;
bool Select = false;
};
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(NotBlueprintable, NotBlueprintType, notplaceable, noteditinlinenew, hidedropdown, Transient)
class COGENGINE_API ACogEngineReplicator : public AActor
{
GENERATED_UCLASS_BODY()
public:
static void Create(APlayerController* Controller);
virtual void BeginPlay() override;
APlayerController* GetPlayerController() const { return OwnerPlayerController.Get(); }
bool IsLocal() const { return bIsLocal; }
UFUNCTION(Server, Reliable)
void Server_SetTimeDilation(float Value);
float GetTimeDilation() const { return TimeDilation; }
protected:
void TickSpawnActions();
UFUNCTION()
void OnRep_TimeDilation();
UPROPERTY()
TArray<FCogEngineReplicatorSpawnAction> SpawnActions;
TObjectPtr<APlayerController> OwnerPlayerController;
uint32 bHasAuthority : 1;
uint32 bIsLocal : 1;
private:
UPROPERTY(ReplicatedUsing = OnRep_TimeDilation)
float TimeDilation = 1.0f;
};
@@ -0,0 +1,38 @@
#pragma once
#include "CoreMinimal.h"
#include "CogWindow.h"
#include "CogEngineWindow_Collisions.generated.h"
class UCogEngineDataAsset_Collisions;
UCLASS(Config = Cog)
class COGENGINE_API UCogEngineWindow_Collisions : public UCogWindow
{
GENERATED_BODY()
public:
UCogEngineWindow_Collisions();
virtual void RenderContent() override;
void SetCollisionsAsset(const UCogEngineDataAsset_Collisions* Asset);
private:
struct FChannel
{
bool IsValid = false;
FColor Color;
};
TWeakObjectPtr<UCogEngineDataAsset_Collisions> CollisionsAsset;
FChannel Channels[ECC_MAX];
UPROPERTY(Config)
int32 ObjectTypesToQuery;
UPROPERTY(Config)
int32 ProfileIndex = 0;
};
@@ -0,0 +1,18 @@
#pragma once
#include "CoreMinimal.h"
#include "CogWindow.h"
#include "CogEngineWindow_DebugSettings.generated.h"
UCLASS()
class COGENGINE_API UCogEngineWindow_DebugSettings : public UCogWindow
{
GENERATED_BODY()
public:
UCogEngineWindow_DebugSettings();
virtual void PreRender(ImGuiWindowFlags& WindowFlags) override;
virtual void RenderContent() override;
};
@@ -0,0 +1,24 @@
#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,16 @@
#pragma once
#include "CoreMinimal.h"
#include "CogWindow.h"
#include "CogEngineWindow_LogCategories.generated.h"
UCLASS()
class COGENGINE_API UCogEngineWindow_LogCategories : public UCogWindow
{
GENERATED_BODY()
public:
virtual void PreRender(ImGuiWindowFlags& WindowFlags) override;
virtual void RenderContent() override;
};
@@ -0,0 +1,18 @@
#pragma once
#include "CoreMinimal.h"
#include "CogWindow.h"
#include "CogEngineWindow_NetEmulation.generated.h"
UCLASS()
class COGENGINE_API UCogEngineWindow_NetEmulation : public UCogWindow
{
GENERATED_BODY()
public:
virtual void RenderContent() override;
private:
};
@@ -0,0 +1,78 @@
#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();
virtual void PreRender(ImGuiWindowFlags& WindowFlags) override;
virtual void RenderContent() override;
void Clear();
void AddLog(const TCHAR* Message, ELogVerbosity::Type Verbosity, const FName& Category);
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;
};

Some files were not shown because too many files have changed in this diff Show More