CogEngine: Fix and improve Plot window

CogEngine: Fix and improve the Plot window
- Fix ImPlot assert
- Improve UI

CogSample:
-  Add Inputs and AnimNotify plot events
- Fix ability system warning
This commit is contained in:
Arnaud Jamin
2025-01-11 00:31:53 -05:00
parent 269f8ae469
commit 2f1361a412
12 changed files with 482 additions and 130 deletions
+52
View File
@@ -0,0 +1,52 @@
#include "CogSampleAnimNotify.h"
#include "CogCommon.h"
#include "Animation/AnimSequenceBase.h"
#include "Components/SkeletalMeshComponent.h"
#if ENABLE_COG
#include "CogDebugPlot.h"
#endif
//--------------------------------------------------------------------------------------------------------------------------
UCogSampleAnimNotify::UCogSampleAnimNotify(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
bIsNativeBranchingPoint = true;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleAnimNotify::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference)
{
Super::Notify(MeshComp, Animation, EventReference);
#if ENABLE_COG
FCogDebugPlot::PlotEventInstant(MeshComp->GetOwner(), "Anim Notify", GetFName())
.AddParam("Name", GetNameSafe(this))
.AddParam("Animation", GetNameSafe(Animation))
.AddParam("Debug Info", GetDebugInfo());
#endif
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleAnimNotify::BranchingPointNotify(FBranchingPointNotifyPayload& BranchingPointPayload)
{
//--------------------------------------------------------------------------------------------------------
// Replace UAnimNotify::BranchingPointNotify to fill the EventReference with the NotifyEvent for
// UGPCoreAnimMotifyFunctionLibrary::AnimNotifyEventReferenceGetMontage to work properly
//--------------------------------------------------------------------------------------------------------
// Super::BranchingPointNotify(BranchingPointPayload);
const FAnimNotifyEventReference EventReference(BranchingPointPayload.NotifyEvent,
BranchingPointPayload.SequenceAsset);
Notify(BranchingPointPayload.SkelMeshComponent, BranchingPointPayload.SequenceAsset, EventReference);
}
//--------------------------------------------------------------------------------------------------------------------------
FString UCogSampleAnimNotify::GetDebugInfo_Implementation() const
{
FString DebugInfo;
return DebugInfo;
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "CoreMinimal.h"
#include "Animation/AnimNotifies/AnimNotify.h"
#include "CogSampleAnimNotify.generated.h"
UCLASS()
class UCogSampleAnimNotify : public UAnimNotify
{
GENERATED_BODY()
public:
UCogSampleAnimNotify(const FObjectInitializer& ObjectInitializer);
UFUNCTION(BlueprintNativeEvent)
FString GetDebugInfo() const;
void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override;
void BranchingPointNotify(FBranchingPointNotifyPayload& BranchingPointPayload) override;
};
@@ -0,0 +1,86 @@
#include "CogSampleAnimNotifyState.h"
#include "CogCommon.h"
#include "Animation/AnimNotifies/AnimNotify.h"
#include "Animation/AnimNotifyEndDataContext.h"
#include "Animation/AnimSequenceBase.h"
#include "Components/SkeletalMeshComponent.h"
#if ENABLE_COG
#include "CogDebugPlot.h"
#endif
//--------------------------------------------------------------------------------------------------------------------------
UCogSampleAnimNotifyState::UCogSampleAnimNotifyState(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
bIsNativeBranchingPoint = false;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleAnimNotifyState::NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration, const FAnimNotifyEventReference& EventReference)
{
#if ENABLE_COG
FCogDebugPlot::PlotEventStart(MeshComp->GetOwner(), "Anim Notify", GetFName())
.AddParam("Name", GetNameSafe(this))
.AddParam("Animation", GetNameSafe(Animation))
.AddParam("Debug Info", GetDebugInfo());
#endif
Super::NotifyBegin(MeshComp, Animation, TotalDuration, EventReference);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleAnimNotifyState::NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference)
{
#if ENABLE_COG
FCogDebugPlot::PlotEventStop(MeshComp->GetOwner(), "Anim Notify", GetFName());
#endif
Super::NotifyEnd(MeshComp, Animation, EventReference);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleAnimNotifyState::BranchingPointNotifyBegin(FBranchingPointNotifyPayload& BranchingPointPayload)
{
//--------------------------------------------------------------------------------------------------------
// Replace UAnimNotifyState::BranchingPointNotifyBegin to fill the EventReference with the NotifyEvent for
// UGPCoreAnimMotifyFunctionLibrary::AnimNotifyEventReferenceGetMontage to work properly
//--------------------------------------------------------------------------------------------------------
// Super::BranchingPointNotifyBegin(BranchingPointPayload);
const FAnimNotifyEventReference EventReference(BranchingPointPayload.NotifyEvent,
BranchingPointPayload.SequenceAsset);
NotifyBegin(BranchingPointPayload.SkelMeshComponent,
BranchingPointPayload.SequenceAsset,
BranchingPointPayload.NotifyEvent
? BranchingPointPayload.NotifyEvent->GetDuration()
: 0.f,
EventReference);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleAnimNotifyState::BranchingPointNotifyEnd(FBranchingPointNotifyPayload& BranchingPointPayload)
{
//--------------------------------------------------------------------------------------------------------
// Replace UAnimNotifyState::BranchingPointNotifyEnd to fill the EventReference with the NotifyEvent for
// UGPCoreAnimMotifyFunctionLibrary::AnimNotifyEventReferenceGetMontage to work properly
//--------------------------------------------------------------------------------------------------------
// Super::BranchingPointNotifyEnd(BranchingPointPayload);
FAnimNotifyEventReference EventReference(BranchingPointPayload.NotifyEvent, BranchingPointPayload.SequenceAsset);
if (BranchingPointPayload.bReachedEnd)
{
EventReference.AddContextData<UE::Anim::FAnimNotifyEndDataContext>(true);
}
NotifyEnd(BranchingPointPayload.SkelMeshComponent, BranchingPointPayload.SequenceAsset, EventReference);
}
//--------------------------------------------------------------------------------------------------------------------------
FString UCogSampleAnimNotifyState::GetDebugInfo_Implementation() const
{
FString DebugInfo;
return DebugInfo;
}
@@ -0,0 +1,27 @@
#pragma once
#include "CoreMinimal.h"
#include "Animation/AnimNotifies/AnimNotifyState.h"
#include "CogSampleAnimNotifyState.generated.h"
UCLASS()
class UCogSampleAnimNotifyState : public UAnimNotifyState
{
GENERATED_BODY()
public:
UCogSampleAnimNotifyState(const FObjectInitializer& ObjectInitializer);
UFUNCTION(BlueprintNativeEvent)
FString GetDebugInfo() const;
void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration, const FAnimNotifyEventReference& EventReference) override;
void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override;
void BranchingPointNotifyBegin(FBranchingPointNotifyPayload& BranchingPointPayload) override;
void BranchingPointNotifyEnd(FBranchingPointNotifyPayload& BranchingPointPayload) override;
};
+22 -4
View File
@@ -370,8 +370,18 @@ void ACogSampleCharacter::SetupPlayerInputComponent(class UInputComponent* Playe
int32 AbilityIndex = 0;
for (const FActiveAbilityInfo& AbilityInfo : ActiveAbilities)
{
EnhancedInputComponent->BindAction(AbilityInfo.InputAction, ETriggerEvent::Started, this, &ACogSampleCharacter::OnAbilityInputStarted, AbilityIndex);
EnhancedInputComponent->BindAction(AbilityInfo.InputAction, ETriggerEvent::Completed, this, &ACogSampleCharacter::OnAbilityInputCompleted, AbilityIndex);
EnhancedInputComponent->BindActionValueLambda(AbilityInfo.InputAction, ETriggerEvent::Started,
[this, &AbilityInfo, AbilityIndex](const FInputActionValue& InputActionValue)
{
OnAbilityInputStarted(AbilityInfo.InputAction, InputActionValue, AbilityIndex);
});
EnhancedInputComponent->BindActionValueLambda(AbilityInfo.InputAction, ETriggerEvent::Completed,
[this, &AbilityInfo, AbilityIndex](const FInputActionValue& InputActionValue)
{
OnAbilityInputCompleted(AbilityInfo.InputAction, InputActionValue, AbilityIndex);
});
AbilityIndex++;
}
@@ -385,10 +395,14 @@ void ACogSampleCharacter::SetupPlayerInputComponent(class UInputComponent* Playe
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogSampleCharacter::OnAbilityInputStarted(const FInputActionValue& Value, int32 Index)
void ACogSampleCharacter::OnAbilityInputStarted(const UInputAction* InputAction, const FInputActionValue& Value, int32 Index)
{
COG_LOG_OBJECT(LogCogInput, ELogVerbosity::Verbose, this, TEXT("%d"), Index);
#if ENABLE_COG
FCogDebugPlot::PlotEventStart(this, "Input", InputAction->GetFName());
#endif
if (ActiveAbilityHandles.IsValidIndex(Index) == false)
{
return;
@@ -429,10 +443,14 @@ void ACogSampleCharacter::OnAbilityInputStarted(const FInputActionValue& Value,
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogSampleCharacter::OnAbilityInputCompleted(const FInputActionValue& Value, int32 Index)
void ACogSampleCharacter::OnAbilityInputCompleted(const UInputAction* InputAction, const FInputActionValue& Value, int32 Index)
{
COG_LOG_OBJECT(LogCogInput, ELogVerbosity::Verbose, this, TEXT("%d"), Index);
#if ENABLE_COG
FCogDebugPlot::PlotEventStop(this, "Input", InputAction->GetFName());
#endif
if (ActiveAbilityHandles.IsValidIndex(Index) == false)
{
return;
+2 -2
View File
@@ -310,9 +310,9 @@ protected:
void Look(const FInputActionValue& Value);
void OnAbilityInputStarted(const FInputActionValue& Value, int32 Index);
void OnAbilityInputStarted(const UInputAction* InputAction, const FInputActionValue& Value, int32 Index);
void OnAbilityInputCompleted(const FInputActionValue& Value, int32 Index);
void OnAbilityInputCompleted(const UInputAction* InputAction, const FInputActionValue& Value, int32 Index);
void ActivateItem(const FInputActionValue& Value, int32 Index);
+55 -3
View File
@@ -2,7 +2,9 @@
#include "CogSampleAbilitySystemComponent.h"
#include "GameFramework/GameState.h"
#include "GameFramework/PlayerState.h"
#include "Modules/ModuleManager.h"
#include "Net/UnrealNetwork.h"
#if ENABLE_COG
#include "CogAll.h"
@@ -25,6 +27,13 @@ ACogSampleGameState::ACogSampleGameState(const FObjectInitializer & ObjectInitia
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Minimal);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogSampleGameState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ThisClass, _ServerFramerateRaw);
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogSampleGameState::BeginPlay()
{
@@ -66,9 +75,52 @@ void ACogSampleGameState::Tick(float DeltaSeconds)
#if ENABLE_COG
extern ENGINE_API float GAverageFPS;
extern ENGINE_API float GAverageMS;
FCogDebugPlot::PlotValue(this, "Frame Rate", GAverageFPS);
FCogDebugPlot::PlotValue(this, "Frame Time", GAverageMS);
constexpr float smoothing = 10.0f;
_ClientFramerateSmooth = _ClientFramerateSmooth >= 0.0f
? FMath::FInterpTo(_ClientFramerateSmooth, GAverageFPS, DeltaSeconds, smoothing)
: GAverageFPS;
_ServerFramerateSmooth = _ServerFramerateSmooth >= 0.0f
? FMath::FInterpTo(_ServerFramerateSmooth, _ServerFramerateRaw, DeltaSeconds, smoothing)
: _ServerFramerateRaw;
if (GetLocalRole() != ROLE_Authority)
{
FCogDebugPlot::PlotValue(this, "Frame Rate Client Raw", GAverageFPS);
FCogDebugPlot::PlotValue(this, "Frame Rate Client Smooth", _ClientFramerateSmooth);
FCogDebugPlot::PlotValue(this, "Frame Rate Server Raw", _ServerFramerateRaw);
FCogDebugPlot::PlotValue(this, "Frame Rate Server Smooth", _ServerFramerateSmooth);
if (const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController())
{
if (const APlayerController* PlayerController = LocalPlayer->PlayerController)
{
if (const APlayerState* PlayerState = PlayerController->GetPlayerState<APlayerState>())
{
FCogDebugPlot::PlotValue(this, "Ping", PlayerState->GetPingInMilliseconds());
}
if (const UNetConnection* Connection = PlayerController->GetNetConnection())
{
FCogDebugPlot::PlotValue(this,
"Packet Loss In",
Connection->GetInLossPercentage().GetAvgLossPercentage() * 100.0f);
FCogDebugPlot::PlotValue(this,
"Packet Loss Out",
Connection->GetOutLossPercentage().GetAvgLossPercentage() * 100.0f);
}
}
}
}
else
{
FCogDebugPlot::PlotValue(this, "Frame Rate Raw", GAverageFPS);
FCogDebugPlot::PlotValue(this, "Frame Rate Smooth", _ClientFramerateSmooth);
}
if (CogWindowManager != nullptr)
{
+8
View File
@@ -36,11 +36,19 @@ private:
UPROPERTY()
TObjectPtr<UObject> CogWindowManagerRef = nullptr;
protected:
UPROPERTY(Replicated)
float _ServerFramerateRaw = 0.0f;
#if ENABLE_COG
void InitializeCog();
TObjectPtr<UCogWindowManager> CogWindowManager = nullptr;
float _ClientFramerateSmooth = 0.0f;
float _ServerFramerateSmooth = 0.0f;
#endif //ENABLE_COG
};
@@ -12,7 +12,6 @@
#if ENABLE_COG
#include "CogAbilityReplicator.h"
#include "CogDebugDraw.h"
#include "CogDebugPlot.h"
#include "CogDebugReplicator.h"
#include "CogEngineReplicator.h"
#include "Framework/Application/NavigationConfig.h"
@@ -47,7 +47,7 @@ FCogSampleSpawnPredictionKey FCogSampleSpawnPredictionKey::MakeFromAbility(const
FCogSampleSpawnPredictionKey Key;
Key.Creator = InAbility.GetAvatarActorFromActorInfo() != nullptr ? InAbility.GetAvatarActorFromActorInfo()->GetFName() : FName();
Key.Ability = InAbility.GetFName();
Key.PredictionKey = Spec->ActivationInfo.GetActivationPredictionKey();
Key.PredictionKey = InAbility.GetCurrentActivationInfo().GetActivationPredictionKey();
Key.InstanceIndex = InInstanceIndex;
Key.GameTime = InAbility.GetWorld()->GetTimeSeconds();
return Key;