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
@@ -1,6 +1,7 @@
#include "CogEngineWindow_Plots.h"
#include "CogDebugPlot.h"
#include "CogImguiHelper.h"
#include "CogWindowWidgets.h"
#include "Engine/World.h"
#include "imgui.h"
@@ -80,7 +81,7 @@ void FCogEngineWindow_Plots::RenderMenu()
{
if (ImGui::BeginMenu("Options"))
{
if (ImGui::MenuItem("Clear Data"))
if (ImGui::MenuItem("Clear data"))
{
FCogDebugPlot::Clear();
}
@@ -101,11 +102,27 @@ void FCogEngineWindow_Plots::RenderMenu()
}
FCogWindowWidgets::SetNextItemToShortWidth();
if (ImGui::SliderFloat("Time Range", &Config->TimeRange, 1.0f, 30.0f, "%0.1f"))
if (ImGui::SliderFloat("Time range", &Config->TimeRange, 1.0f, 30.0f, "%0.1f"))
{
bApplyTimeScale = true;
}
FCogWindowWidgets::SetNextItemToShortWidth();
ImGui::SliderFloat("Drag view sensitivity", &Config->DragViewSensitivity, 1.0f, 50.0f, "%0.0f");
FCogWindowWidgets::SetNextItemToShortWidth();
ImGui::Checkbox("Show time bar at game time", &Config->ShowTimeBarAtGameTime);
FCogWindowWidgets::SetNextItemToShortWidth();
ImGui::Checkbox("Show time bar at cursor", &Config->ShowTimeBarAtCursor);
FCogWindowWidgets::SetNextItemToShortWidth();
ImGui::Checkbox("Show value at cursor", &Config->ShowValueAtCursor);
constexpr ImGuiColorEditFlags ColorEditFlags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_AlphaPreviewHalf;
FCogImguiHelper::ColorEdit4("Pause background color", Config->PauseBackgroundColor, ColorEditFlags);
ImGui::SetItemTooltip("Background color of the plot when paused.");
ImGui::EndMenu();
}
@@ -124,22 +141,35 @@ void FCogEngineWindow_Plots::RenderPlotsList(TArray<FCogDebugPlotEntry*>& Visibl
ImGui::Indent(6);
for (FCogDebugPlotEntry& Entry : FCogDebugPlot::Plots)
for (FCogDebugPlotEntry& Plot : FCogDebugPlot::Plots)
{
if (Entry.CurrentYAxis != ImAxis_COUNT && Entry.CurrentRow != INDEX_NONE)
if (Plot.CurrentYAxis != ImAxis_COUNT && Plot.CurrentRow != INDEX_NONE)
{
VisiblePlots.Add(&Entry);
VisiblePlots.Add(&Plot);
}
ImGui::PushID(Index);
ImGui::PushStyleColor(ImGuiCol_Text, Entry.IsEventPlot ? IM_COL32(128, 128, 255, 255) : IM_COL32(255, 255, 255, 255));
ImGui::Selectable(TCHAR_TO_ANSI(*Entry.Name.ToString()), false, 0);
ImGui::PushStyleColor(ImGuiCol_Text, Plot.IsEventPlot ? IM_COL32(128, 128, 255, 255) : IM_COL32(255, 255, 255, 255));
const bool IsAssignedToRow = Plot.CurrentRow != INDEX_NONE;
if (ImGui::Selectable(TCHAR_TO_ANSI(*Plot.Name.ToString()), IsAssignedToRow, ImGuiSelectableFlags_AllowDoubleClick))
{
if (IsAssignedToRow)
{
Plot.ResetAxis();
}
else
{
Plot.AssignAxis(0, ImAxis_Y1);
}
}
ImGui::PopStyleColor();
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
{
const auto EntryName = StringCast<ANSICHAR>(*Entry.Name.ToString());
const auto EntryName = StringCast<ANSICHAR>(*Plot.Name.ToString());
ImGui::SetDragDropPayload("DragAndDrop", EntryName.Get(), EntryName.Length() + 1);
ImGui::Text("%s", EntryName.Get());
ImGui::EndDragDropSource();
@@ -174,6 +204,13 @@ void FCogEngineWindow_Plots::RenderPlots(const TArray<FCogDebugPlotEntry*>& Visi
static float RowRatios[] = { 1, 1, 1, 1, 1, 1 };
static float ColRatios[] = { 1 };
static ImPlotSubplotFlags SubplotsFlags = ImPlotSubplotFlags_LinkCols;
const bool PushPlotBgStyle = FCogDebugPlot::Pause;
if (PushPlotBgStyle)
{
ImPlot::PushStyleColor(ImPlotCol_PlotBg, FCogImguiHelper::ToImVec4(Config->PauseBackgroundColor));
}
if (ImPlot::BeginSubplots("", Config->Rows, 1, ImVec2(-1, -1), SubplotsFlags, RowRatios, ColRatios))
{
for (int PlotIndex = 0; PlotIndex < Config->Rows; ++PlotIndex)
@@ -209,94 +246,136 @@ void FCogEngineWindow_Plots::RenderPlots(const TArray<FCogDebugPlotEntry*>& Visi
Config->TimeRange = TimeRange;
}
const float Time = GetWorld() ? GetWorld()->GetTimeSeconds() : 0.0;
//------------------------------------------------------------------
// Setup all the Z and Y axis limits. Must be done before calling
// ImPlot::GetPlotPos or ImPlot::GetPlotSize as it calls SetupLock()
//------------------------------------------------------------------
{
//--------------------------------------------------------------------------------
// 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, Time - TimeRange, Time, ImGuiCond_Always);
}
if (bApplyTimeScale)
{
ImPlot::SetupAxisLimits(ImAxis_X1, Time - Config->TimeRange, Time, ImGuiCond_Always);
}
//--------------------------------------------------------------------------------
// Set the Y axis limit for Events.
//--------------------------------------------------------------------------------
for (const FCogDebugPlotEntry* PlotPtr : VisiblePlots)
{
if (PlotPtr == nullptr)
{ continue; }
if (PlotPtr->CurrentRow != PlotIndex)
{ continue; }
if (PlotPtr->IsEventPlot)
{
ImPlot::SetupAxisLimits(PlotPtr->CurrentYAxis, 0, PlotPtr->MaxRow + 2, ImGuiCond_Always);
}
}
}
const ImVec2 PlotMin = ImPlot::GetPlotPos();
const ImVec2 PlotSize = ImPlot::GetPlotSize();
const ImVec2 PlotMax = PlotMin + PlotSize;
//----------------------------------------------------------------
// Draw a vertical lines representing the current time and the mouse time
// Pause the scrolling if the user drag inside
//----------------------------------------------------------------
RenderTimeMarker();
const ImVec2 Mouse = ImGui::GetMousePos();
if (Mouse.x > PlotMin.x
&& Mouse.y > PlotMin.y
&& Mouse.x < PlotMax.x
&& Mouse.y < PlotMax.y
&& ImGui::GetDragDropPayload() == nullptr)
{
const ImVec2 Drag = ImGui::GetMouseDragDelta(0);
if (FMath::Abs(Drag.x) > Config->DragViewSensitivity)
{
FCogDebugPlot::Pause = true;
}
}
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
FCogDebugPlot::Pause = false;
}
//---------------------------------------------------------------------------
// Draw a vertical lines representing the current time and the mouse time
//---------------------------------------------------------------------------
if (Config->ShowTimeBarAtGameTime || Config->ShowTimeBarAtGameTime)
{
ImDrawList* PlotDrawList = ImPlot::GetPlotDrawList();
const float PlotTop = PlotMin.y;
const float TimeBarBottom = PlotTop + PlotSize.y;
ImPlot::PushPlotClipRect();
if (Config->ShowTimeBarAtCursor)
{
PlotDrawList->AddLine(ImVec2(ImGui::GetMousePos().x, PlotTop), ImVec2(ImGui::GetMousePos().x, TimeBarBottom), IM_COL32(128, 128, 128, 64));
}
if (Config->ShowTimeBarAtGameTime && FCogDebugPlot::Pause)
{
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();
}
//-----------------------------------------------------------
// Draw all the plots assigned to this row
//-----------------------------------------------------------
for (FCogDebugPlotEntry* PlotPtr : VisiblePlots)
{
if (PlotPtr == nullptr)
{ continue; }
FCogDebugPlotEntry& Plot = *PlotPtr;
if (Plot.CurrentRow != PlotIndex)
{ continue; }
ImPlot::SetAxis(Plot.CurrentYAxis);
ImPlot::SetNextLineStyle(IMPLOT_AUTO_COL);
const auto Label = StringCast<ANSICHAR>(*Plot.Name.ToString());
//-------------------------------------------------------
// Plot Events
//-------------------------------------------------------
if (Plot.IsEventPlot)
{
continue;
RenderEvents(Plot, Label.Get(), PlotMin, PlotMax);
}
//-------------------------------------------------------
// Plot Values
//-------------------------------------------------------
else if (Plot.Values.empty() == false)
{
RenderValues(Plot, Label.Get());
}
FCogDebugPlotEntry& Entry = *PlotPtr;
if (Entry.Values.empty())
//-------------------------------------------------------
// Allow legend item labels to be drag and drop sources
//-------------------------------------------------------
if (ImPlot::BeginDragDropSourceItem(Label.Get()))
{
continue;
const auto EntryName = StringCast<ANSICHAR>(*Plot.Name.ToString());
ImGui::SetDragDropPayload("DragAndDrop", EntryName.Get(), EntryName.Length() + 1);
ImGui::TextUnformatted(EntryName.Get());
ImPlot::EndDragDropSource();
}
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 - TimeRange, Entry.Time, ImGuiCond_Always);
}
if (bApplyTimeScale)
{
ImPlot::SetupAxisLimits(ImAxis_X1, Entry.Time - Config->TimeRange, 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
//----------------------------------------------------------------
const ImVec2 Mouse = ImGui::GetMousePos();
if (Mouse.x > PlotMin.x
&& Mouse.y > PlotMin.y
&& Mouse.x < PlotMax.x
&& Mouse.y < PlotMax.y
&& ImGui::GetDragDropPayload() == nullptr)
{
const 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)
{
RenderEvents(Entry, Label.Get(), PlotMin, PlotMax);
}
//-------------------------------------------------------
// Plot Values
//-------------------------------------------------------
else
{
RenderValues(Entry, Label.Get());
}
//-------------------------------------------------------
// Allow legend item labels to be drag and drop sources
//-------------------------------------------------------
if (ImPlot::BeginDragDropSourceItem(Label.Get()))
{
const auto EntryName = StringCast<ANSICHAR>(*Entry.Name.ToString());
ImGui::SetDragDropPayload("DragAndDrop", EntryName.Get(), EntryName.Length() + 1);
ImGui::TextUnformatted(EntryName.Get());
ImPlot::EndDragDropSource();
}
}
}
//-------------------------------------------------------
@@ -352,45 +431,37 @@ void FCogEngineWindow_Plots::RenderPlots(const TArray<FCogDebugPlotEntry*>& Visi
}
ImPlot::EndSubplots();
}
if (PushPlotBgStyle)
{
ImPlot::PopStyleColor();
}
}
ImGui::EndChild();
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Plots::RenderTimeMarker() const
{
const ImVec2 PlotMin = ImPlot::GetPlotPos();
const ImVec2 PlotSize = ImPlot::GetPlotSize();
ImDrawList* PlotDrawList = ImPlot::GetPlotDrawList();
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();
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Plots::RenderValues(FCogDebugPlotEntry& Entry, const char* Label)
void FCogEngineWindow_Plots::RenderValues(FCogDebugPlotEntry& Entry, const char* Label) const
{
//----------------------------------------------------------------
// Custom tooltip
// Value at cursor tooltip
//----------------------------------------------------------------
if (ImPlot::IsPlotHovered())
if (Config->ShowValueAtCursor && ImPlot::IsPlotHovered())
{
float Value;
if (Entry.FindValue(ImPlot::GetPlotMousePos().x, Value))
{
ImGui::BeginTooltip();
ImGui::Text("%s: %0.2f", Label, Value);
ImGui::EndTooltip();
FCogWindowWidgets::BeginTableTooltip();
if (ImGui::BeginTable("Params", 2, ImGuiTableFlags_Borders))
{
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%s", Label);
ImGui::TableNextColumn();
ImGui::Text("%0.2f", Value);
ImGui::EndTable();
}
FCogWindowWidgets::EndTableTooltip();
}
}
@@ -423,8 +494,6 @@ void FCogEngineWindow_Plots::RenderEvents(FCogDebugPlotEntry& Entry, const char*
//--------------------------------------------------------------------
Entry.UpdateTime(GetWorld());
ImPlot::SetupAxisLimits(Entry.CurrentYAxis, 0, Entry.MaxRow + 2, ImGuiCond_Always);
ImPlot::PushPlotClipRect();
@@ -447,7 +516,7 @@ void FCogEngineWindow_Plots::RenderEvents(FCogDebugPlotEntry& Entry, const char*
const bool IsInstant = Event.StartTime == Event.EndTime;
if (IsInstant)
{
constexpr float Radius = 10.0f;
constexpr 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));
@@ -494,7 +563,7 @@ void FCogEngineWindow_Plots::RenderEvents(FCogDebugPlotEntry& Entry, const char*
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Plots::RenderEventTooltip(const FCogDebugPlotEvent* HoveredEvent, FCogDebugPlotEntry& Entry)
void FCogEngineWindow_Plots::RenderEventTooltip(const FCogDebugPlotEvent* HoveredEvent, const FCogDebugPlotEntry& Entry)
{
if (ImPlot::IsPlotHovered() && HoveredEvent != nullptr)
{
@@ -32,13 +32,11 @@ protected:
void RenderMenu();
void RenderTimeMarker() const;
static void RenderValues(FCogDebugPlotEntry& Entry, const char* Label);
void RenderValues(FCogDebugPlotEntry& Entry, const char* Label) const;
void RenderEvents(FCogDebugPlotEntry& Entry, const char* Label, const ImVec2& PlotMin, const ImVec2& PlotMax) const;
static void RenderEventTooltip(const FCogDebugPlotEvent* HoveredEvent, FCogDebugPlotEntry& Entry);
static void RenderEventTooltip(const FCogDebugPlotEvent* HoveredEvent, const FCogDebugPlotEntry& Entry);
TObjectPtr<UCogEngineConfig_Plots> Config = nullptr;
@@ -60,11 +58,31 @@ public:
int Rows = 1;
UPROPERTY(Config)
float TimeRange = 10.0f;
float TimeRange = 20.0f;
UPROPERTY(Config)
bool ShowTimeBarAtGameTime = true;
UPROPERTY(Config)
bool ShowTimeBarAtCursor = true;
UPROPERTY(Config)
bool ShowValueAtCursor = true;
UPROPERTY(Config)
float DragViewSensitivity = 10.0f;
UPROPERTY(Config)
FColor PauseBackgroundColor = FColor(10, 0, 0, 255);
virtual void Reset() override
{
Rows = 1;
TimeRange = 10.0f;
TimeRange = 20.0f;
ShowTimeBarAtGameTime = true;
ShowTimeBarAtCursor = true;
ShowValueAtCursor = true;
DragViewSensitivity = 10.0f;
PauseBackgroundColor = FColor(10, 0, 0, 255);
}
};
+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;