diff --git a/Config/DefaultGame.ini b/Config/DefaultGame.ini index 6fbf2c699..7fb50bced 100644 --- a/Config/DefaultGame.ini +++ b/Config/DefaultGame.ini @@ -15,4 +15,6 @@ bIsDrawHitCursorLine=False bIsDrawDeprojectedCursorLine=False bIsShowMouseCursor=False NetGraph=1 +UnUsedEnum=Everything +UnUsedStruct=(IntField0=3,FloatField1=0.000000) diff --git a/Source/Cloud9/Cloud9.h b/Source/Cloud9/Cloud9.h index b9135291b..41e9fffd3 100644 --- a/Source/Cloud9/Cloud9.h +++ b/Source/Cloud9/Cloud9.h @@ -1,7 +1,54 @@ -// Copyright Epic Games, Inc. All Rights Reserved. +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. #pragma once #include "CoreMinimal.h" DECLARE_LOG_CATEGORY_EXTERN(LogCloud9, Log, All); + +#define let const auto +#define var auto + +template +class TOperator +{ +public: + template + constexpr friend auto operator|(const TValue* Value, const TFunction& Function) + { + return Function(Value); + } + + template + constexpr friend auto operator|(TValue& Value, const TFunction& Function) + { + return Function(Value); + } + + template + constexpr friend auto operator|(TValue&& Value, const TFunction& Function) + { + return Function(Value); + } +}; diff --git a/Source/Cloud9/Game/Cloud9DeveloperSettings.cpp b/Source/Cloud9/Game/Cloud9DeveloperSettings.cpp index 9da0ec927..64da32be6 100644 --- a/Source/Cloud9/Game/Cloud9DeveloperSettings.cpp +++ b/Source/Cloud9/Game/Cloud9DeveloperSettings.cpp @@ -1 +1,53 @@ -#include "Cloud9DeveloperSettings.h" +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#include "Cloud9DeveloperSettings.h" + +#include "Cloud9/Cloud9.h" +#include "Cloud9/Tools/Extensions/UObject.h" + +const UCloud9DeveloperSettings* UCloud9DeveloperSettings::GetCloud9DeveloperSettings() +{ + static var bIsInitialized = false; + static let Settings = GetDefault(); + + if (!bIsInitialized) + { + Cast(Settings)->Log(); + bIsInitialized = true; + } + + return Settings; +} + +void UCloud9DeveloperSettings::Save() +{ + UpdateDefaultConfigFile(); + Log(); +} + +void UCloud9DeveloperSettings::Log() const +{ + let String = this | EUObject::Stringify(); + UE_LOG(LogCloud9, Display, TEXT("%s"), *String); +} diff --git a/Source/Cloud9/Game/Cloud9DeveloperSettings.h b/Source/Cloud9/Game/Cloud9DeveloperSettings.h index 3fd6d84a4..f75dd637d 100644 --- a/Source/Cloud9/Game/Cloud9DeveloperSettings.h +++ b/Source/Cloud9/Game/Cloud9DeveloperSettings.h @@ -1,9 +1,53 @@ -#pragma once +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#pragma once #include "CoreMinimal.h" -#include "Cloud9/Cloud9.h" #include "Cloud9DeveloperSettings.generated.h" +USTRUCT(BlueprintType) +struct FUnUsedStruct +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite) + int IntField0 = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + float FloatField1 = 0.0f; +}; + +UENUM() +enum class EUnUsedEnum : int32 +{ + Special = 0, + Anything = 1, + Everything = 2, + Whatever = 3, +}; + UCLASS(Config=Game, defaultconfig, meta = (DisplayName="Save Game Settings")) class CLOUD9_API UCloud9DeveloperSettings : public UDeveloperSettings { @@ -11,25 +55,13 @@ class CLOUD9_API UCloud9DeveloperSettings : public UDeveloperSettings public: UFUNCTION(BlueprintCallable, Category=Settings) - static const UCloud9DeveloperSettings* GetCloud9DeveloperSettings() - { - static auto bIsLoaded = false; - static const auto Settings = GetDefault(); - - if (!bIsLoaded) - { - UE_LOG(LogCloud9, Display, TEXT("IsDrawHitCursorLine: %d"), Settings->bIsShowMouseCursor); - UE_LOG(LogCloud9, Display, TEXT("IsDrawDeprojectedCursorLine: %d"), Settings->bIsDrawDeprojectedCursorLine); - UE_LOG(LogCloud9, Display, TEXT("IsShowMouseCursor: %d"), Settings->bIsShowMouseCursor); - UE_LOG(LogCloud9, Display, TEXT("NetGraph: %d"), Settings->NetGraph); - bIsLoaded = true; - } - - return Settings; - } + static const UCloud9DeveloperSettings* GetCloud9DeveloperSettings(); + + UFUNCTION(BlueprintCallable) + void Save(); UFUNCTION(BlueprintCallable) - void Save() { UpdateDefaultConfigFile(); } + void Log() const; // Debug @@ -44,4 +76,10 @@ class CLOUD9_API UCloud9DeveloperSettings : public UDeveloperSettings UPROPERTY(Config, EditAnywhere, BlueprintReadWrite, Category = "Debug") int NetGraph; + + UPROPERTY(Config, EditAnywhere, BlueprintReadWrite, Category = "Debug") + EUnUsedEnum UnUsedEnum; + + UPROPERTY(Config, EditAnywhere, BlueprintReadWrite, Category = "Debug") + FUnUsedStruct UnUsedStruct; }; diff --git a/Source/Cloud9/Tools/Cloud9ReflectionLibrary.cpp b/Source/Cloud9/Tools/Cloud9ReflectionLibrary.cpp new file mode 100644 index 000000000..f1c4c391c --- /dev/null +++ b/Source/Cloud9/Tools/Cloud9ReflectionLibrary.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#include "Cloud9ReflectionLibrary.h" + +#include "Cloud9/Cloud9.h" +#include "Extensions/FTextBuilder.h" + +FString UCloud9ReflectionLibrary::UObjectToString(const UObject* Object, const UStruct* Type) +{ + using namespace EFTextBuilder; + + let Text = FTextBuilder() + | AppendObject(Object, Type) + | ToText(); + return Text.ToString(); +} diff --git a/Source/Cloud9/Tools/Cloud9ReflectionLibrary.h b/Source/Cloud9/Tools/Cloud9ReflectionLibrary.h new file mode 100644 index 000000000..afd29a744 --- /dev/null +++ b/Source/Cloud9/Tools/Cloud9ReflectionLibrary.h @@ -0,0 +1,42 @@ +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Cloud9ReflectionLibrary.generated.h" + +/** + * Class to work with UE4 UPROPERTY/UCLASS reflection for debugging. + */ +UCLASS() +class CLOUD9_API UCloud9ReflectionLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable) + static FString UObjectToString(const UObject* Object, const UStruct* Type); +}; + diff --git a/Source/Cloud9/Tools/Cloud9ToolsLibrary.cpp b/Source/Cloud9/Tools/Cloud9ToolsLibrary.cpp index 50e62eadd..c0d22e01d 100644 --- a/Source/Cloud9/Tools/Cloud9ToolsLibrary.cpp +++ b/Source/Cloud9/Tools/Cloud9ToolsLibrary.cpp @@ -1,6 +1,32 @@ -#include "Cloud9ToolsLibrary.h" +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#include "Cloud9ToolsLibrary.h" + +#include "Cloud9/Cloud9.h" #include "Cloud9/Game/Cloud9GameMode.h" + void UCloud9ToolsLibrary::SetCollisionComplexity(UStaticMesh* StaticMesh, uint8 CollisionTraceFlag) { StaticMesh->GetBodySetup()->CollisionTraceFlag = static_cast(CollisionTraceFlag); @@ -8,9 +34,9 @@ void UCloud9ToolsLibrary::SetCollisionComplexity(UStaticMesh* StaticMesh, uint8 float UCloud9ToolsLibrary::CalculateCollisionVolumeScale(UStaticMesh* StaticMesh) { - const auto Scale = FVector{1.0f, 1.0f, 1.0f}; - const auto BoundingBoxVolume = StaticMesh->GetBoundingBox().GetVolume(); - const auto SimpleCollisionVolume = StaticMesh->GetBodySetup()->AggGeom.GetVolume(Scale); + let Scale = FVector{1.0f, 1.0f, 1.0f}; + let BoundingBoxVolume = StaticMesh->GetBoundingBox().GetVolume(); + let SimpleCollisionVolume = StaticMesh->GetBodySetup()->AggGeom.GetVolume(Scale); return SimpleCollisionVolume / BoundingBoxVolume; } @@ -18,7 +44,7 @@ UWorld* UCloud9ToolsLibrary::GetWorld() { return GEngine->GameViewport->GetWorld ACloud9GameMode* UCloud9ToolsLibrary::GetGameMode() { - const auto MyWorld = GetWorld(); + let MyWorld = GetWorld(); return Cast(UGameplayStatics::GetGameMode(MyWorld)); } @@ -27,21 +53,20 @@ ACloud9GameMode* UCloud9ToolsLibrary::GetGameMode() */ FBox UCloud9ToolsLibrary::GetAccurateReferencePoseBounds(const USkeletalMesh* Mesh) { - auto Box = FBox(ForceInitToZero); + var Box = FBox(ForceInitToZero); if (!Mesh || !Mesh->GetPhysicsAsset()) { return {}; } - for (const auto BodySetups : Mesh->GetPhysicsAsset()->SkeletalBodySetups) + for (let BodySetups : Mesh->GetPhysicsAsset()->SkeletalBodySetups) { - const FReferenceSkeleton& RefSkeleton = Mesh->GetSkeleton()->GetReferenceSkeleton(); - auto ComponentSpaceBoneTransform = FTransform::Identity; + let& RefSkeleton = Mesh->GetSkeleton()->GetReferenceSkeleton(); + var ComponentSpaceBoneTransform = FTransform::Identity; - auto BoneIndex = RefSkeleton.FindBoneIndex(BodySetups->BoneName); + var BoneIndex = RefSkeleton.FindBoneIndex(BodySetups->BoneName); while (BoneIndex != INDEX_NONE) { - const FTransform& BoneLocalTM = RefSkeleton.GetRefBonePose()[BoneIndex]; + let& BoneLocalTM = RefSkeleton.GetRefBonePose()[BoneIndex]; ComponentSpaceBoneTransform = ComponentSpaceBoneTransform * BoneLocalTM; - BoneIndex = RefSkeleton.GetParentIndex(BoneIndex); } @@ -56,7 +81,7 @@ FBox UCloud9ToolsLibrary::GetAccurateReferencePoseBounds(const USkeletalMesh* Me */ void UCloud9ToolsLibrary::GetWidthHeightDepth(const FBox& Box, float& Width, float& Height, float& Depth) { - const auto Size = Box.GetExtent(); + let Size = Box.GetExtent(); Width = Size.Y; Height = Size.X; Depth = Size.Z; @@ -77,13 +102,13 @@ FVector UCloud9ToolsLibrary::VInterpTo( float DeltaTime, const FVector InterpSpeed) { - const auto ClampLerp = [](auto Current, auto Dist, auto Alpha, auto Target) + let ClampLerp = [](auto Current, auto Dist, auto Alpha, auto Target) { return Alpha <= 0.0f ? Target : Current + Dist * FMath::Clamp(Alpha, 0.0f, 1.0f); }; // Distance to reach - const auto Dist = Target - Current; + let Dist = Target - Current; // If distance is too small, just set the desired location if (Dist.SizeSquared() < KINDA_SMALL_NUMBER) @@ -91,7 +116,7 @@ FVector UCloud9ToolsLibrary::VInterpTo( return Target; } - const auto Alpha = DeltaTime * InterpSpeed; + let Alpha = DeltaTime * InterpSpeed; return { ClampLerp(Current.X, Dist.X, Alpha.X, Target.X), @@ -99,3 +124,5 @@ FVector UCloud9ToolsLibrary::VInterpTo( ClampLerp(Current.Z, Dist.Z, Alpha.Z, Target.Z), }; } + + diff --git a/Source/Cloud9/Tools/Cloud9ToolsLibrary.h b/Source/Cloud9/Tools/Cloud9ToolsLibrary.h index c4a3e3361..1f5661217 100644 --- a/Source/Cloud9/Tools/Cloud9ToolsLibrary.h +++ b/Source/Cloud9/Tools/Cloud9ToolsLibrary.h @@ -1,4 +1,27 @@ -#pragma once +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#pragma once #include "CoreMinimal.h" #include "Kismet/BlueprintFunctionLibrary.h" @@ -67,4 +90,5 @@ class CLOUD9_API UCloud9ToolsLibrary : public UBlueprintFunctionLibrary const FVector Target, float DeltaTime, const FVector InterpSpeed); + }; diff --git a/Source/Cloud9/Tools/Extensions/FTextBuilder.cpp b/Source/Cloud9/Tools/Extensions/FTextBuilder.cpp new file mode 100644 index 000000000..dc09c5adb --- /dev/null +++ b/Source/Cloud9/Tools/Extensions/FTextBuilder.cpp @@ -0,0 +1,158 @@ +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#pragma once + +#include "FTextBuilder.h" + +auto LexToString(const FText& Text) { return *Text.ToString(); } + +namespace EFTextBuilder +{ + template + TResult UPropertyGetValue(const void* Object, const TType* Property) + { + let Ptr = Property->template ContainerPtrToValuePtr(Object); + return TType::GetPropertyValue(Ptr); + } + + template <> + bool UPropertyGetValue(const void* Object, const FBoolProperty* Property) + { + return Property->GetPropertyValue_InContainer(Object); + } + + template + FString Format(const FProperty* Property, TValue Value) + { + let Name = Property->GetFName(); + let TypeName = Property->GetCPPType(); + return FString::Printf(TEXT("%s: %s = %s"), *Name.ToString(), *TypeName, *LexToString(Value)); + } + + template + bool UPropertyAppendTo(FTextBuilder& Builder, const void* Object, const FProperty* Property) + { + if (let TypedProperty = CastField(Property)) + { + let Value = UPropertyGetValue(Object, TypedProperty); + let String = Format(Property, Value); + Builder.AppendLine(String); + return true; + } + return false; + } + + template <> + bool UPropertyAppendTo(FTextBuilder& Builder, const void* Object, const FProperty* Property) + { + if (let TypedProperty = CastField(Property)) + { + let UnderlyingProperty = TypedProperty->GetUnderlyingProperty(); + let Ptr = Property->ContainerPtrToValuePtr(Object); + let Index = UnderlyingProperty->GetSignedIntPropertyValue(Ptr); + let Enum = TypedProperty->GetEnum(); + let Value = Enum->GetNameByIndex(Index); + let String = Format(Property, Value); + Builder.AppendLine(String); + return true; + } + return false; + } + + template <> + bool UPropertyAppendTo(FTextBuilder& Builder, const void* Object, const FProperty* Property) + { + if (let TypedProperty = CastField(Property)) + { + let Ptr = TypedProperty->ContainerPtrToValuePtr(Object); + Builder | AppendObject(Ptr, TypedProperty->Struct); + return true; + } + return false; + } + + template + bool UPropertyNotSupported(FTextBuilder& Builder, const void* Object, const FProperty* Property) + { + if (let TypedProperty = CastField(Property)) + { + let String = Format(Property, TEXT("")); + Builder.AppendLine(String); + return true; + } + return false; + } + + FTextBuilder& AppendProperty::operator()(FTextBuilder& Builder) const + { + UPropertyAppendTo(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyNotSupported(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property) + || UPropertyAppendTo(Builder, Object, Property); + return Builder; + } + + FTextBuilder& AppendObject::operator()(FTextBuilder& Builder) const + { + let TypeClass = Type->GetClass(); + let Header = FString::Printf(TEXT("%s %s {"), *TypeClass->GetName(), *Type->GetName()); + + Builder.AppendLine(Header); + Builder.Indent(); + + for (TFieldIterator It(Type); It; ++It) + { + Builder | AppendProperty(Object, *It); + } + + Builder.Unindent(); + Builder.AppendLine(FString{"}"}); + + return Builder; + } + + FText ToText::operator()(const FTextBuilder& Builder) const { return Builder.ToText(); } +} diff --git a/Source/Cloud9/Tools/Extensions/FTextBuilder.h b/Source/Cloud9/Tools/Extensions/FTextBuilder.h new file mode 100644 index 000000000..59670fc0d --- /dev/null +++ b/Source/Cloud9/Tools/Extensions/FTextBuilder.h @@ -0,0 +1,58 @@ +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#pragma once + +#include "Cloud9/Cloud9.h" + +namespace EFTextBuilder +{ + struct AppendObject : TOperator + { + AppendObject(const UObject* Object, const UStruct* Type) + : Object(Object), Type(Type) { } + + FTextBuilder& operator()(FTextBuilder& Builder) const; + + private: + const UObject* Object; + const UStruct* Type; + }; + + struct AppendProperty : TOperator + { + AppendProperty(const UObject* Object, const FProperty* Property) + : Object(Object), Property(Property) { } + + FTextBuilder& operator()(FTextBuilder& Builder) const; + + private: + const UObject* Object; + const FProperty* Property; + }; + + struct ToText : TOperator + { + FText operator()(const FTextBuilder& Builder) const; + }; +} diff --git a/Source/Cloud9/Tools/Extensions/UObject.cpp b/Source/Cloud9/Tools/Extensions/UObject.cpp new file mode 100644 index 000000000..75e74c4c5 --- /dev/null +++ b/Source/Cloud9/Tools/Extensions/UObject.cpp @@ -0,0 +1,31 @@ +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#include "UObject.h" + +#include "Cloud9/Tools/Cloud9ReflectionLibrary.h" + +FString EUObject::Stringify::operator()(const UObject* Object) const +{ + return UCloud9ReflectionLibrary::UObjectToString(Object, Object->GetClass()); +} diff --git a/Source/Cloud9/Tools/Extensions/UObject.h b/Source/Cloud9/Tools/Extensions/UObject.h new file mode 100644 index 000000000..c6b070f3e --- /dev/null +++ b/Source/Cloud9/Tools/Extensions/UObject.h @@ -0,0 +1,35 @@ +// Copyright (c) 2023 Alexei Gladkikh +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#pragma once + +#include "Cloud9/Cloud9.h" + +namespace EUObject +{ + struct Stringify : TOperator + { + public: + FString operator()(const UObject* Object) const; + }; +}