diff --git a/Pawn_Unreal/Pawn.sln.DotSettings b/Pawn_Unreal/Pawn.sln.DotSettings
index 28ae13f..e1333b1 100644
--- a/Pawn_Unreal/Pawn.sln.DotSettings
+++ b/Pawn_Unreal/Pawn.sln.DotSettings
@@ -1,3 +1,4 @@
True
- True
\ No newline at end of file
+ True
+ True
\ No newline at end of file
diff --git a/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp b/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp
index 755c2b2..5a353c5 100644
--- a/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp
+++ b/Pawn_Unreal/Source/Pawn/Private/Characters/PwnCharacterMovementComponent.cpp
@@ -5,8 +5,10 @@
#include "Components/SplineComponent.h"
#include "GameplayModes/PwnGameplayModeSubsystem.h"
#include "GameplayModes/Combat/PwnCombatPlatformerPath.h"
+#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Utils/EngineUtils.h"
+#include "Utils/PwnImGuiLibrary.h"
constexpr float LineTraceDistance = 10000.0f;
@@ -84,6 +86,76 @@ void UPwnCharacterMovementComponent::PhysCustom(const float DeltaTime, const int
}
bool UPwnCharacterMovementComponent::DisplayDebug_Implementation() {
+ UPwnImGuiLibrary::Title("Movement");
+ UPwnImGuiLibrary::ColoredVariable(FColor::Purple, "Movement Mode", UEnum::GetValueAsString(MovementMode));
+ UPwnImGuiLibrary::ColoredVariable(FColor::Purple, "Custom Movement Mode",
+ UEnum::GetValueAsString(
+ static_cast>(CustomMovementMode)));
+
+ UPwnImGuiLibrary::ColoredVariable(FColor::Red, "Is Grounded", BOOL_TO_STR(IsMovingOnGround()));
+ UPwnImGuiLibrary::ColoredVariable(FColor::Red, "Is Falling", BOOL_TO_STR(IsFalling()));
+ UPwnImGuiLibrary::ColoredVariable(FColor::Red, "IsFollowingSpline", BOOL_TO_STR(IsFollowingSpline));
+ UPwnImGuiLibrary::ColoredVariable(FColor::Yellow, "Velocity", Velocity.ToString());
+
+ if (CombatPath != nullptr) {
+ UPwnImGuiLibrary::Title("Spline Following Movement");
+ UPwnImGuiLibrary::ColoredVariable(FColor::Cyan, "Combat Path", CombatPath->GetActorNameOrLabel());
+ UPwnImGuiLibrary::ColoredVariable(FColor::Green, "Distance Along Spline", FString::SanitizeFloat(DistanceAlongSpline));
+ UPwnImGuiLibrary::ColoredVariable(FColor::Green, "Dot Direction", FString::SanitizeFloat(DotDirection));
+ UPwnImGuiLibrary::ColoredVariable(FColor::Green, "Tangent 2D", Tangent2D.ToString());
+ UPwnImGuiLibrary::ColoredVariable(FColor::Yellow, "Acceleration", Acceleration.ToString());
+
+ if (UPwnImGuiLibrary::Checkbox(this, "Draw World Debug", true)) {
+ UPwnImGuiLibrary::Indent();
+ UPwnImGuiLibrary::ColoredString(FColor::Yellow, "Velocity");
+ UPwnImGuiLibrary::ColoredString(FColor::Green, "Tangent");
+ DrawDebugDirectionalArrow(GetWorld(), UpdatedComponent->GetComponentLocation(), UpdatedComponent->GetComponentLocation() + Velocity,
+ 100.0f, FColor::Yellow, false, -1.0f, 0, 3.0f);
+ DrawDebugDirectionalArrow(GetWorld(), UpdatedComponent->GetComponentLocation(),
+ UpdatedComponent->GetComponentLocation() + Tangent2D * 50.0f,
+ 100.0f, FColor::Green, false, -1.0f, 0, 3.0f);
+ UPwnImGuiLibrary::Unindent();
+ }
+ if (UPwnImGuiLibrary::Checkbox(this, "Draw Splines", true)) {
+ UPwnImGuiLibrary::Indent();
+ UPwnImGuiLibrary::ColoredString(FColor::Cyan, "Flattened Spline");
+ UPwnImGuiLibrary::ColoredString(FColor::Magenta, "Location on Spline");
+
+ const float Length = CombatPath->FlattenedSpline->GetSplineLength();
+ constexpr float Step = 15.0f;
+
+ float ZLocation;
+ if (UPwnImGuiLibrary::Checkbox(this, "Track Ground", true)) {
+ FHitResult Hit;
+ LineTraceToGround(Hit, UpdatedComponent->GetComponentLocation());
+ ZLocation = Hit.ImpactPoint.Z + 200.0f;
+ } else {
+ ZLocation = UpdatedComponent->GetComponentLocation().Z + 100.0f;
+ }
+
+ FVector PreviousLocation = CombatPath->FlattenedSpline->GetLocationAtDistanceAlongSpline(0.0f, ESplineCoordinateSpace::World);
+ PreviousLocation.Z = ZLocation;
+ for (float Distance = Step; Distance <= Length; Distance += Step) {
+ FVector Location = CombatPath->FlattenedSpline->GetLocationAtDistanceAlongSpline(Distance, ESplineCoordinateSpace::World);
+ Location.Z = ZLocation;
+ DrawDebugLine(GetWorld(), PreviousLocation, Location, FColor::Cyan, false, -1.0f, 0, 3.0f);
+ PreviousLocation = Location;
+ }
+
+ FVector LocationOnSpline = CombatPath->FlattenedSpline->GetLocationAtDistanceAlongSpline(
+ DistanceAlongSpline, ESplineCoordinateSpace::World);
+ LocationOnSpline.Z = ZLocation;
+ DrawDebugSphere(GetWorld(), LocationOnSpline, 10.0f, 12, FColor::Magenta, false, -1.0f, 0,
+ 3.0f);
+
+ const FVector TextLocation = LocationOnSpline + 15.0f;
+ DrawDebugString(GetWorld(), TextLocation, CombatPath->GetActorNameOrLabel(), nullptr, FColor::Cyan,
+ 0.008f * UGameplayStatics::GetGlobalTimeDilation(this), false, 1.5f);
+
+ UPwnImGuiLibrary::Unindent();
+ }
+ }
+
return true;
}
@@ -104,12 +176,16 @@ bool UPwnCharacterMovementComponent::IsCustomMovementMode(const ECustomMovementM
return MovementMode == MOVE_Custom && CustomMovementMode == Mode;
}
-bool UPwnCharacterMovementComponent::LineTraceToGround(FHitResult& OutHit, const FVector& StartLocation, const FLinearColor& DebugColor) const {
+bool UPwnCharacterMovementComponent::LineTraceToGround(FHitResult& OutHit, const FVector& StartLocation) const {
const FVector EndLocation = StartLocation + FVector(0.0f, 0.0f, -LineTraceDistance);
- return UKismetSystemLibrary::LineTraceSingle(this, StartLocation, EndLocation, UEngineTypes::ConvertToTraceType(ECC_Visibility), false, TArray(),
- DebugColor == FLinearColor::White ? EDrawDebugTrace::None : EDrawDebugTrace::None, OutHit, true, DebugColor, FLinearColor::Green, 0.5f);
+ return UKismetSystemLibrary::LineTraceSingle(this, StartLocation, EndLocation, UEngineTypes::ConvertToTraceType(ECC_Visibility), false,
+ TArray(),
+ EDrawDebugTrace::None, OutHit, true,
+ FColor::White, FLinearColor::Green, 0.5f);
}
+
float AccumulatedTimer = 0.0f;
+
void UPwnCharacterMovementComponent::UpdateCurrentCombatPath(const bool Force, const bool UpdateLocation) {
AccumulatedTimer += GetWorld()->GetDeltaSeconds();
if (AccumulatedTimer < 0.5f && !Force) {
@@ -124,13 +200,13 @@ void UPwnCharacterMovementComponent::UpdateCurrentCombatPath(const bool Force, c
APwnCombatPlatformerPath* OutCombatPath;
FVector ClosestLocation;
FHitResult Hit;
- if (LineTraceToGround(Hit, UpdatedComponent->GetComponentLocation(), FLinearColor::Red)
+ if (LineTraceToGround(Hit, UpdatedComponent->GetComponentLocation())
&& UPwnGameplayModeSubsystem::Get(this).FindClosestCombatPathLocation(Hit.ImpactPoint, OutCombatPath, ClosestLocation)
&& OutCombatPath != CombatPath) {
CombatPath = OutCombatPath;
DotDirection = CombatPath->Reversed ? -1.0f : 1.0f;
- if (LineTraceToGround(Hit, ClosestLocation, FLinearColor::Blue)) {
+ if (LineTraceToGround(Hit, ClosestLocation)) {
const float SplineKey = CombatPath->FlattenedSpline->FindInputKeyClosestToWorldLocation(Hit.ImpactPoint);
DistanceAlongSpline = CombatPath->FlattenedSpline->GetDistanceAlongSplineAtSplineInputKey(SplineKey);
@@ -151,7 +227,8 @@ void UPwnCharacterMovementComponent::UpdateCurrentCombatPath(const bool Force, c
void UPwnCharacterMovementComponent::UpdateTangentAndAcceleration() {
// Clamp distance because tangents are not defined at the ends of the spline
const float ClampedDistanceAlongSpline = FMath::Clamp(DistanceAlongSpline, 0.0001f, CombatPath->FlattenedSpline->GetSplineLength() - 0.0001f);
- Tangent2D = CombatPath->FlattenedSpline->GetTangentAtDistanceAlongSpline(ClampedDistanceAlongSpline, ESplineCoordinateSpace::World).GetSafeNormal2D();
+ Tangent2D = CombatPath->FlattenedSpline->GetTangentAtDistanceAlongSpline(ClampedDistanceAlongSpline, ESplineCoordinateSpace::World).
+ GetSafeNormal2D();
// Recalculate acceleration so the input is relative to the spline
Acceleration = Tangent2D * Acceleration.Size2D() * FMath::Sign(Acceleration.X) * DotDirection;
}
@@ -181,7 +258,7 @@ void UPwnCharacterMovementComponent::UpdatePawnVelocity(const float TimeTick) {
void UPwnCharacterMovementComponent::UpdateDistanceAlongSpline() {
FHitResult Hit;
- if (LineTraceToGround(Hit, UpdatedComponent->GetComponentLocation(), FLinearColor::White)) {
+ if (LineTraceToGround(Hit, UpdatedComponent->GetComponentLocation())) {
const FVector ImpactPoint = Hit.ImpactPoint;
const float InputKey = CombatPath->FlattenedSpline->FindInputKeyClosestToWorldLocation(ImpactPoint);
DistanceAlongSpline = CombatPath->FlattenedSpline->GetDistanceAlongSplineAtSplineInputKey(InputKey);
diff --git a/Pawn_Unreal/Source/Pawn/Private/Debug/PwnDebugSubsystem.cpp b/Pawn_Unreal/Source/Pawn/Private/Debug/PwnDebugSubsystem.cpp
index 0bb4e42..fe046ba 100644
--- a/Pawn_Unreal/Source/Pawn/Private/Debug/PwnDebugSubsystem.cpp
+++ b/Pawn_Unreal/Source/Pawn/Private/Debug/PwnDebugSubsystem.cpp
@@ -4,6 +4,7 @@
#include "Utils/PwnImGuiLibrary.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetStringLibrary.h"
+#include "Utils/EngineUtils.h"
UPwnDebugSubsystem& UPwnDebugSubsystem::Get(const UObject* WorldContextObject) {
return *WorldContextObject->GetWorld()->GetSubsystem();
@@ -18,7 +19,7 @@ void UPwnDebugSubsystem::SaveVariable(const UObject* Object, const FString& Name
ObjectVariables.Add(Object, FVariableList());
}
FVariableList& VariableList = ObjectVariables[Object];
- VariableList.Variables.Add(Name, UKismetStringLibrary::Conv_BoolToString(Value));
+ VariableList.Variables.Add(Name, BOOL_TO_STR(Value));
}
bool UPwnDebugSubsystem::GetVariableAsBool(const UObject* Object, const FString& Name, const bool DefaultValue) {
@@ -51,7 +52,7 @@ void UPwnDebugSubsystem::Tick(float DeltaTime) {
TArray Components = Actor->GetComponentsByInterface(UIPwnDebuggable::StaticClass());
if (Actor->Implements() || Components.Num() > 0) {
bool Show = DebuggableComponents.Contains(Actor);
- UPwnImGuiLibrary::CheckboxStringCustom(Actor->GetActorNameOrLabel(), Show);
+ UPwnImGuiLibrary::CheckboxCustom(Actor->GetActorNameOrLabel(), Show);
if (Show) {
DebuggableComponents.Add(Actor, Components);
} else {
@@ -76,11 +77,11 @@ void UPwnDebugSubsystem::DrawDebugWindowForActor(AActor* DebugActor, TArray 0) {
- UPwnImGuiLibrary::TitleString("Components");
+ UPwnImGuiLibrary::Title("Components");
}
for (UActorComponent* Component : DebugComponents) {
if (IsValid(Component)) {
- if (UPwnImGuiLibrary::TreeNodeString(Component->GetClass()->GetName())) {
+ if (UPwnImGuiLibrary::TreeNode(Component->GetClass()->GetName())) {
IIPwnDebuggable::Execute_DisplayDebug(Component);
UPwnImGuiLibrary::TreePop();
}
diff --git a/Pawn_Unreal/Source/Pawn/Private/Utils/PwnImGuiLibrary.cpp b/Pawn_Unreal/Source/Pawn/Private/Utils/PwnImGuiLibrary.cpp
index 6f681bb..e085639 100644
--- a/Pawn_Unreal/Source/Pawn/Private/Utils/PwnImGuiLibrary.cpp
+++ b/Pawn_Unreal/Source/Pawn/Private/Utils/PwnImGuiLibrary.cpp
@@ -4,26 +4,36 @@
#include "Debug/PwnDebugSubsystem.h"
void UPwnImGuiLibrary::Text(const FText Text) {
- TextString(Text.ToString());
+ String(Text.ToString());
}
-void UPwnImGuiLibrary::TextString(const FString Text) {
+void UPwnImGuiLibrary::String(const FString Text) {
ImGui::Text(STRING_TO_ANSI(Text));
}
void UPwnImGuiLibrary::ColoredText(const FColor Color, const FText Text) {
- ColoredTextString(Color, Text.ToString());
+ ColoredString(Color, Text.ToString());
}
-void UPwnImGuiLibrary::ColoredTextString(const FColor Color, const FString Text) {
+void UPwnImGuiLibrary::ColoredString(const FColor Color, const FString Text) {
ImGui::TextColored(COLOR_TO_IMVEC4(Color), STRING_TO_ANSI(Text));
}
-void UPwnImGuiLibrary::Title(const FText Title) {
- TitleString(Title.ToString());
+void UPwnImGuiLibrary::Variable(const FString Name, const FString Value) {
+ ColoredVariable(FColor::White, Name, Value);
}
-void UPwnImGuiLibrary::TitleString(const FString Title) {
+void UPwnImGuiLibrary::ColoredVariable(const FColor Color, const FString Name, const FString Value) {
+ String(Name + ": ");
+ SameLine();
+ ColoredString(Color, Value);
+}
+
+void UPwnImGuiLibrary::TitleText(const FText InTitle) {
+ Title(InTitle.ToString());
+}
+
+void UPwnImGuiLibrary::Title(const FString Title) {
ImGui::SeparatorText(STRING_TO_ANSI(Title));
}
@@ -36,35 +46,51 @@ void UPwnImGuiLibrary::EndWindow() {
ImGui::End();
}
-bool UPwnImGuiLibrary::Checkbox(const UObject* WoldContextObject, const FText Label) {
- return CheckboxString(WoldContextObject, Label.ToString());
+bool UPwnImGuiLibrary::CheckboxText(const UObject* WoldContextObject, const FText Label, const bool DefaultValue) {
+ return Checkbox(WoldContextObject, Label.ToString(), DefaultValue);
}
-bool UPwnImGuiLibrary::CheckboxString(const UObject* WoldContextObject, const FString Label) {
+bool UPwnImGuiLibrary::Checkbox(const UObject* WoldContextObject, const FString Label, const bool DefaultValue) {
UPwnDebugSubsystem& SubSystem = UPwnDebugSubsystem::Get(WoldContextObject);
- bool Show = SubSystem.GetVariableAsBool(WoldContextObject, Label);
+ bool Show = SubSystem.GetVariableAsBool(WoldContextObject, Label, DefaultValue);
ImGui::Checkbox(STRING_TO_ANSI(Label), &Show);
SubSystem.SaveVariable(WoldContextObject, Label, Show);
return Show;
}
-bool UPwnImGuiLibrary::CheckboxCustom(const FText Label, bool& Show) {
- return CheckboxStringCustom(Label.ToString(), Show);
+bool UPwnImGuiLibrary::CheckboxTextCustom(const FText Label, bool& Show) {
+ return CheckboxCustom(Label.ToString(), Show);
}
-bool UPwnImGuiLibrary::CheckboxStringCustom(const FString Label, bool& Show) {
+bool UPwnImGuiLibrary::CheckboxCustom(const FString Label, bool& Show) {
ImGui::Checkbox(STRING_TO_ANSI(Label), &Show);
return Show;
}
-bool UPwnImGuiLibrary::TreeNode(const FText Label) {
- return TreeNodeString(Label.ToString());
+bool UPwnImGuiLibrary::TreeNodeText(const FText Label) {
+ return TreeNode(Label.ToString());
}
-bool UPwnImGuiLibrary::TreeNodeString(const FString Label) {
+bool UPwnImGuiLibrary::TreeNode(const FString Label) {
return ImGui::TreeNode(STRING_TO_ANSI(Label));
}
void UPwnImGuiLibrary::TreePop() {
return ImGui::TreePop();
}
+
+void UPwnImGuiLibrary::SameLine() {
+ ImGui::SameLine();
+}
+
+void UPwnImGuiLibrary::Separator() {
+ ImGui::Separator();
+}
+
+void UPwnImGuiLibrary::Indent(const float Width) {
+ ImGui::Indent(Width);
+}
+
+void UPwnImGuiLibrary::Unindent(const float Width) {
+ ImGui::Unindent(Width);
+}
diff --git a/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h b/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h
index dea7885..34a33a3 100644
--- a/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h
+++ b/Pawn_Unreal/Source/Pawn/Public/Characters/PwnCharacterMovementComponent.h
@@ -58,7 +58,7 @@ public:
bool IsCustomMovementMode(const ECustomMovementMode Mode) const;
private:
- bool LineTraceToGround(FHitResult& OutHit, const FVector& StartLocation, const FLinearColor& DebugColor) const;
+ bool LineTraceToGround(FHitResult& OutHit, const FVector& StartLocation) const;
void UpdateCurrentCombatPath(bool Force = false, const bool UpdateLocation = false);
diff --git a/Pawn_Unreal/Source/Pawn/Public/Utils/PwnImGuiLibrary.h b/Pawn_Unreal/Source/Pawn/Public/Utils/PwnImGuiLibrary.h
index 87424aa..7c527f1 100644
--- a/Pawn_Unreal/Source/Pawn/Public/Utils/PwnImGuiLibrary.h
+++ b/Pawn_Unreal/Source/Pawn/Public/Utils/PwnImGuiLibrary.h
@@ -19,23 +19,29 @@ class PAWN_API UPwnImGuiLibrary : public UBlueprintFunctionLibrary {
public:
// Widgets: Text
+ UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Text")
+ static void TitleText(const FText InTitle);
+
+ UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Text")
+ static void Title(const FString Title);
+
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Text")
static void Text(const FText Text);
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Text")
- static void TextString(const FString Text);
+ static void String(const FString Text);
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Text")
static void ColoredText(const FColor Color, const FText Text);
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Text")
- static void ColoredTextString(const FColor Color, const FString Text);
+ static void ColoredString(const FColor Color, const FString Text);
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Text")
- static void Title(const FText Title);
+ static void Variable(const FString Name, const FString Value);
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Text")
- static void TitleString(const FString Title);
+ static void ColoredVariable(const FColor Color, const FString Name, const FString Value);
// Widgets: Main
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Main")
@@ -45,24 +51,37 @@ public:
static void EndWindow();
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Main", meta=(WorldContext="WorldContextObject"))
- static bool Checkbox(const UObject* WoldContextObject, const FText Label);
+ static bool CheckboxText(const UObject* WoldContextObject, const FText Label, const bool DefaultValue = false);
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Main", meta=(WorldContext="WorldContextObject"))
- static bool CheckboxString(const UObject* WoldContextObject, const FString Label);
+ static bool Checkbox(const UObject* WoldContextObject, const FString Label, const bool DefaultValue = false);
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Main")
- static bool CheckboxCustom(const FText Label, UPARAM(Ref) bool& Show);
+ static bool CheckboxTextCustom(const FText Label, UPARAM(Ref) bool& Show);
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Main")
- static bool CheckboxStringCustom(const FString Label, UPARAM(Ref) bool& Show);
+ static bool CheckboxCustom(const FString Label, UPARAM(Ref) bool& Show);
// Widgets: Trees
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Trees")
- static bool TreeNode(const FText Label);
+ static bool TreeNodeText(const FText Label);
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Trees")
- static bool TreeNodeString(const FString Label);
+ static bool TreeNode(const FString Label);
UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Trees")
static void TreePop();
+
+ // Widgets: Layouts
+ UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Layouts")
+ static void SameLine();
+
+ UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Layouts")
+ static void Separator();
+
+ UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Layouts")
+ static void Indent(const float Width = 0);
+
+ UFUNCTION(BlueprintCallable, Category = "ImGui|Widgets|Layouts")
+ static void Unindent(const float Width = 0);
};