New generic attribute set codegen from table implemented
This commit is contained in:
parent
d4bf7cfaec
commit
8ba9170794
@ -5,7 +5,7 @@ ProjectName=GASATHON
|
||||
CopyrightNotice=
|
||||
|
||||
[/Script/Gasa.GasaDevOptions]
|
||||
+AttributeSets=/Game/Core/Tables/DT_AttributeSet.DT_AttributeSet
|
||||
+AttributeSets=/Game/Core/Tables/DT_GasaAttributeSet.DT_GasaAttributeSet
|
||||
TaggedMessageTable=/Game/Core/Tables/DT_TaggedMessages.DT_TaggedMessages
|
||||
Template_PlayerCamera=/Game/Actors/BP_CameraMount.BP_CameraMount_C
|
||||
Template_HUD_HostUI=/Game/UI/UI_Host.UI_Host_C
|
||||
|
@ -0,0 +1,10 @@
|
||||
{
|
||||
"ColumnWidths":
|
||||
{
|
||||
"MaxValue": 165,
|
||||
"Description": 135,
|
||||
"Category": 96,
|
||||
"BaseValue": 106,
|
||||
"Name": 82
|
||||
}
|
||||
}
|
@ -13,8 +13,8 @@ struct GASA_API FAttributeSetField : public FTableRowBase
|
||||
|
||||
FAttributeSetField()
|
||||
: Name("Provide_Name")
|
||||
, Description("Provide Description")
|
||||
, Category("Optional Category")
|
||||
, Description("Provide Description")
|
||||
, BaseValue(0)
|
||||
, bUseMinAttribute(false)
|
||||
, bUseMaxAttribute(false)
|
||||
@ -27,14 +27,14 @@ struct GASA_API FAttributeSetField : public FTableRowBase
|
||||
{}
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gameplay Attribute")
|
||||
FString Name;
|
||||
FName Name;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gameplay Attribute")
|
||||
FName Category;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gameplay Attribute")
|
||||
FString Description;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gameplay Attribute")
|
||||
FString Category;
|
||||
|
||||
// UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gameplay Attribute")
|
||||
// FGameplayTag Tag;
|
||||
|
||||
@ -59,4 +59,3 @@ struct GASA_API FAttributeSetField : public FTableRowBase
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Gameplay Attribute", meta =( EditCondition="bUseMaxAttribute==false", EditConditionHides))
|
||||
float MaxValue;
|
||||
};
|
||||
|
||||
|
@ -16,9 +16,6 @@ public:
|
||||
// NOTE(Ed): Any Soft-References must have their includes defined in GasaDevOptions.cpp
|
||||
// They are used by GasaGen for the GasaDevOptionsCache
|
||||
|
||||
UPROPERTY(Config)
|
||||
TSoftObjectPtr<UDataTable> RandomBullshit;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GAS")
|
||||
TArray< TSoftObjectPtr<UDataTable>> AttributeSets;
|
||||
|
||||
|
@ -11,9 +11,6 @@ void FGasaDevOptionsCache::CachedDevOptions()
|
||||
{
|
||||
UGasaDevOptions* DevOpts = GetMutDevOptions();
|
||||
|
||||
RandomBullshit = DevOpts->RandomBullshit.LoadSynchronous();
|
||||
ensureMsgf( RandomBullshit != nullptr, TEXT( "RandomBullshit is null, DO NOT RUN PIE or else you may get a crash if not handled in BP or C++" ) );
|
||||
|
||||
for ( auto& entry : DevOpts->AttributeSets )
|
||||
{
|
||||
AttributeSets.Push( entry.LoadSynchronous() );
|
||||
|
@ -8,8 +8,6 @@ struct GASA_API FGasaDevOptionsCache
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY()
|
||||
UObject* RandomBullshit;
|
||||
UPROPERTY()
|
||||
TArray<UObject*> AttributeSets;
|
||||
UPROPERTY()
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "GasaGen.h"
|
||||
#include "GasaGen_Common.h"
|
||||
#include "GasaGen_AttributeSets.h"
|
||||
#include "GasaGen_DevOptionsCache.h"
|
||||
|
||||
// Editor Module
|
||||
@ -19,9 +20,9 @@ global Code UModule_GASA_API;
|
||||
void Execute_GasaModule_Codegen()
|
||||
{
|
||||
FScopedSlowTask SlowTask(100.0f, LOCTEXT("RunningGasaGen", "Running GasaGen..."));
|
||||
SlowTask.MakeDialog(); // Shows a progress dialog
|
||||
SlowTask.MakeDialog(false, true); // Shows a progress dialog
|
||||
|
||||
AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [&SlowTask]()
|
||||
AsyncTask(ENamedThreads::AnyBackgroundHiPriTask, [&SlowTask]()
|
||||
{
|
||||
Gasa::LogEditor("Executing: Gasa Module code generation.");
|
||||
|
||||
@ -36,9 +37,7 @@ void Execute_GasaModule_Codegen()
|
||||
char const* ue_ansi_rooot_path = TCHAR_TO_ANSI(*ue_project_path);
|
||||
|
||||
Project_Path = String::make_length(GlobalAllocator, ue_ansi_project_path, ue_project_path.Len());
|
||||
Root_Path = String::make_length(GlobalAllocator, ue_ansi_rooot_path, ue_root_path.Len());
|
||||
UE_LOG(LogTemp, Log, TEXT("Current ROOT Directory: %s"), *ue_project_path);
|
||||
UE_LOG(LogTemp, Log, TEXT("Current Project Directory: %s"), *ue_root_path);
|
||||
Root_Path = String::make_length(GlobalAllocator, ue_ansi_rooot_path, ue_root_path.Len());
|
||||
|
||||
// Initialize Globals
|
||||
{
|
||||
@ -112,16 +111,11 @@ void Execute_GasaModule_Codegen()
|
||||
PreprocessorDefines.append(get_cached_string(str_UE_REQUIRES));
|
||||
}
|
||||
|
||||
//generate_AttributeSets();
|
||||
generate_DevOptionsCache();
|
||||
generate_AttributeSets();
|
||||
//generate_DevOptionsCache();
|
||||
//generate_HostWidgetController();
|
||||
|
||||
gen::deinit();
|
||||
|
||||
AsyncTask(ENamedThreads::GameThread, []()
|
||||
{
|
||||
// UI updates if needed
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,463 @@
|
||||
#include "GasaGen_AttributeSets.h"
|
||||
#include "GasaGen_Common.h"
|
||||
|
||||
#include "Gasa/AbilitySystem/GasaAbilitySystem.h"
|
||||
#include "Gasa/GasaDevOptions.h"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
#pragma push_macro("UPROPERTY")
|
||||
#pragma push_macro("UFUNCTION")
|
||||
#pragma push_macro("FORCEINLINE")
|
||||
#pragma push_macro("ensure")
|
||||
#undef UPROPERTY
|
||||
#undef UFUNCTION
|
||||
#undef FORCEINLINE
|
||||
#undef ensure
|
||||
|
||||
PRAGMA_DISABLE_OPTIMIZATION
|
||||
void generate_AttributeSets()
|
||||
{
|
||||
// All attribute sets are tracked in Gasa's dev options for this project.
|
||||
TArray< TSoftObjectPtr<UDataTable>> AttributeSetTables = Gasa::GetDevOptions()->AttributeSets;
|
||||
check( AttributeSetTables.Num() > 0 );
|
||||
|
||||
// TODO(Ed): Doing one for now
|
||||
FGraphEventRef LoadTableTask;
|
||||
UDataTable* AttributeSetTable = nullptr;
|
||||
FGraphEventArray Prerequisites;
|
||||
LoadTableTask = FFunctionGraphTask::CreateAndDispatchWhenReady(
|
||||
[ & AttributeSetTable, & AttributeSetTables ]()
|
||||
{
|
||||
AttributeSetTable = AttributeSetTables[0].LoadSynchronous();
|
||||
},
|
||||
TStatId(), &Prerequisites, ENamedThreads::GameThread
|
||||
);
|
||||
FTaskGraphInterface::Get().WaitUntilTaskCompletes(LoadTableTask);
|
||||
|
||||
TMap<FName, TArray<FAttributeSetField>> AttributesByCategory;
|
||||
{
|
||||
TMap< FName, uint8* > const& RowMap = AttributeSetTable->GetRowMap();
|
||||
for (const TPair<FName, uint8*>& Row : RowMap)
|
||||
{
|
||||
FAttributeSetField const* RowData = rcast( FAttributeSetField const* , Row.Value);
|
||||
|
||||
// If category is empty, use a default category name
|
||||
FName CategoryName = RowData->Category.IsNone() ? FName(TEXT("Default")) : RowData->Category;
|
||||
|
||||
TArray<FAttributeSetField>& CategoryAttributes = AttributesByCategory.FindOrAdd(CategoryName);
|
||||
CategoryAttributes.Add( * RowData);
|
||||
}
|
||||
}
|
||||
|
||||
FString AssetName = AttributeSetTables[0].GetAssetName();
|
||||
check( AssetName.StartsWith(TEXT("DT_") ))
|
||||
AssetName = AssetName.RightChop(3);
|
||||
|
||||
String str_AssetName = to_string(AssetName);
|
||||
|
||||
String class_name = String::fmt_buf(GlobalAllocator, "U%S", str_AssetName);
|
||||
String header_file_name = String::fmt_buf(GlobalAllocator, "%S.h", str_AssetName);
|
||||
String inlines_file_name = String::fmt_buf(GlobalAllocator, "%S_Inlines.h", str_AssetName);
|
||||
String path_header_file = String::fmt_buf(GlobalAllocator, path_gasa_ability_system "%S.h", str_AssetName);
|
||||
String path_inlines_file = String::fmt_buf(GlobalAllocator, path_gasa_ability_system "%S_Inlines.h", str_AssetName);
|
||||
String path_source_file = String::fmt_buf(GlobalAllocator, path_gasa_ability_system "%S.cpp", str_AssetName);
|
||||
String uht_include_file = String::fmt_buf(GlobalAllocator, "%S.generated.h", str_AssetName);
|
||||
|
||||
CodeType type_UAttributeSet = def_type( txt("UAttributeSet") );
|
||||
CodeComment generation_notice = def_comment(txt("Generated by GasaEditor/GasaGen/GasaGen_AttributeSets.cpp"));
|
||||
|
||||
CodeAttributes api_attribute = def_attributes( UModule_GASA_API->Name);
|
||||
|
||||
Builder header = builder_open( path_header_file );
|
||||
{
|
||||
header.print(generation_notice);
|
||||
header.print(pragma_once);
|
||||
header.print(fmt_newline);
|
||||
|
||||
CodeInclude Include_AttributeSet = def_include(txt("AttributeSet.h"));
|
||||
CodeInclude Include_GasaAttributeSet_Generated = def_include(uht_include_file);
|
||||
header.print( Include_AttributeSet);
|
||||
header.print( Include_GasaAttributeSet_Generated);
|
||||
header.print( fmt_newline);
|
||||
|
||||
gen::CodeClass attribute_set_class = {};
|
||||
{
|
||||
CodeBody body = def_body( CodeT::Class_Body );
|
||||
{
|
||||
body.append( UHT_GENERATED_BODY);
|
||||
body.append( access_public );
|
||||
|
||||
body.append( def_constructor() );
|
||||
body.append(fmt_newline);
|
||||
|
||||
// Generate UPROPERTIES for each attribute field, organized by category
|
||||
for ( TPair< FName, TArray<FAttributeSetField>>& attributes : AttributesByCategory )
|
||||
{
|
||||
String category_name = to_string(attributes.Key);
|
||||
CodeComment category_cmt = def_comment(token_fmt("category_name", (StrC)category_name, "<category_name> Attributes"));
|
||||
body.append(category_cmt);
|
||||
body.append(fmt_newline);
|
||||
for (FAttributeSetField attribute : attributes.Value)
|
||||
{
|
||||
Code field_uproperty = code_fmt(
|
||||
"category", (StrC)to_string(attribute.Category),
|
||||
"property", (StrC)to_string(attribute.Name),
|
||||
stringize(
|
||||
UPROPERTY(ReplicatedUsing = Client_OnRep_<property>, EditAnywhere, BlueprintReadWrite, Category = "Attributes|<category>")
|
||||
FGameplayAttributeData <property>;
|
||||
));
|
||||
body.append(field_uproperty);
|
||||
}
|
||||
body.append(fmt_newline);
|
||||
body.append(fmt_newline);
|
||||
}
|
||||
|
||||
// Generate OnReps for each attribute field
|
||||
for ( TPair< FName, TArray<FAttributeSetField>>& attributes : AttributesByCategory )
|
||||
for ( FAttributeSetField attribute : attributes.Value )
|
||||
{
|
||||
Code umeta_UFUNCTION = code_str(UFUNCTION());
|
||||
|
||||
body.append(fmt_newline);
|
||||
body.append(umeta_UFUNCTION);
|
||||
body.append(fmt_newline);
|
||||
body.append(code_fmt("property", (StrC)to_string(attribute.Name), stringize(
|
||||
void Client_OnRep_<property>(FGameplayAttributeData& Prev<property>);
|
||||
)));
|
||||
}
|
||||
body.append(fmt_newline);
|
||||
body.append(fmt_newline);
|
||||
|
||||
body.append(def_pragma(txt("region Getters")));
|
||||
{
|
||||
// Generate property getters
|
||||
for ( TPair< FName, TArray<FAttributeSetField>>& attributes : AttributesByCategory )
|
||||
for (FAttributeSetField attribute : attributes.Value)
|
||||
{
|
||||
CodeFn generated_get_attribute = parse_function(token_fmt(
|
||||
"class_name", (StrC)class_name,
|
||||
"property", (StrC)to_string(attribute.Name),
|
||||
stringize(
|
||||
static FGameplayAttribute Get<property>Attribute()
|
||||
{
|
||||
static FProperty* Prop = FindFieldChecked<FProperty>(<class_name>::StaticClass(), GET_MEMBER_NAME_CHECKED(<class_name>, <property>));
|
||||
return Prop;
|
||||
}
|
||||
)));
|
||||
body.append(generated_get_attribute);
|
||||
}
|
||||
body.append(fmt_newline);
|
||||
|
||||
// Generate value getters
|
||||
for ( TPair< FName, TArray<FAttributeSetField>>& attributes : AttributesByCategory )
|
||||
for (FAttributeSetField attribute : attributes.Value)
|
||||
{
|
||||
body.append(code_fmt("property", (StrC)to_string(attribute.Name),
|
||||
stringize(
|
||||
FORCEINLINE float Get<property>() const
|
||||
{
|
||||
return <property>.GetCurrentValue();
|
||||
}
|
||||
)));
|
||||
}
|
||||
body.append(fmt_newline);
|
||||
}
|
||||
body.append(def_pragma(txt("endregion Getters")));
|
||||
body.append(fmt_newline);
|
||||
|
||||
body.append(def_pragma(txt("region Setters")));
|
||||
{
|
||||
// Generate value setter forwards
|
||||
for ( TPair< FName, TArray<FAttributeSetField>>& attributes : AttributesByCategory )
|
||||
for (FAttributeSetField attribute : attributes.Value)
|
||||
{
|
||||
body.append(code_fmt("property", (StrC)to_string(attribute.Name),
|
||||
stringize(
|
||||
FORCEINLINE void Set<property>(float NewVal);
|
||||
)));
|
||||
}
|
||||
body.append(fmt_newline);
|
||||
body.append(fmt_newline);
|
||||
|
||||
// Generate initers
|
||||
for ( TPair< FName, TArray<FAttributeSetField>>& attributes : AttributesByCategory )
|
||||
for (FAttributeSetField attribute : attributes.Value)
|
||||
{
|
||||
body.append(code_fmt("property", (StrC)to_string(attribute.Name),
|
||||
stringize(
|
||||
FORCEINLINE void Init<property>(float NewVal)
|
||||
{
|
||||
<property>.SetBaseValue(NewVal);
|
||||
<property>.SetCurrentValue(NewVal);
|
||||
}
|
||||
)));
|
||||
}
|
||||
}
|
||||
body.append(def_pragma(txt("endregion Setters")));
|
||||
body.append(fmt_newline);
|
||||
|
||||
body.append(def_pragma(txt("region AttributeSet")));
|
||||
body.append(code_str(
|
||||
void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
|
||||
void PostGameplayEffectExecute(FGameplayEffectModCallbackData const& Data) override;
|
||||
));
|
||||
body.append(def_pragma(txt("endregion AttributeSet")));
|
||||
body.append(fmt_newline);
|
||||
|
||||
body.append(def_pragma(txt("region UObject")));
|
||||
CodeFn GetLifetimeOfReplicatedProps = parse_function(code(
|
||||
void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>&OutLifetimeProps) const override;
|
||||
));
|
||||
body.append(GetLifetimeOfReplicatedProps);
|
||||
body.append(def_pragma(txt("endregion UObject")));
|
||||
body.append(fmt_newline);
|
||||
}
|
||||
|
||||
attribute_set_class = def_class( class_name, body
|
||||
, type_UAttributeSet, AccessSpec::Public
|
||||
, api_attribute
|
||||
);
|
||||
header.print(UHT_UCLASS);
|
||||
header.print(attribute_set_class);
|
||||
}
|
||||
|
||||
header.write();
|
||||
format_file(path_header_file);
|
||||
}
|
||||
|
||||
Builder inlines = builder_open( path_inlines_file );
|
||||
{
|
||||
inlines.print(generation_notice);
|
||||
inlines.print(pragma_once);
|
||||
inlines.print(fmt_newline);
|
||||
inlines.print(def_include(header_file_name));
|
||||
inlines.print(def_include(txt("AbilitySystemComponent.h")));
|
||||
inlines.print(fmt_newline);
|
||||
|
||||
CodeBody body = def_body(ECode::Global_Body);
|
||||
{
|
||||
body.append(def_pragma(txt("region Attribute Setters")));
|
||||
{
|
||||
for (TPair< FName, TArray<FAttributeSetField>>& attributes : AttributesByCategory)
|
||||
for (FAttributeSetField attribute : attributes.Value)
|
||||
{
|
||||
CodeFn generated_get_attribute = parse_function(token_fmt(
|
||||
"class_name", (StrC)class_name,
|
||||
"property", (StrC)to_string(attribute.Name),
|
||||
stringize(
|
||||
FORCEINLINE void <class_name>::Set<property>(float NewVal)
|
||||
{
|
||||
UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
|
||||
if (ensure(AbilityComp))
|
||||
{
|
||||
AbilityComp->SetNumericAttributeBase(Get<property>Attribute(), NewVal);
|
||||
};
|
||||
}
|
||||
)));
|
||||
body.append(generated_get_attribute);
|
||||
}
|
||||
}
|
||||
body.append(def_pragma(txt("endregion Attribute Setters")));
|
||||
}
|
||||
inlines.print(body);
|
||||
inlines.print(fmt_newline);
|
||||
|
||||
CodeNS ns_gasa = parse_namespace(token_fmt(
|
||||
"class_name", (StrC)class_name,
|
||||
stringize(
|
||||
namespace Gasa
|
||||
{
|
||||
inline
|
||||
<class_name> const* GetAttributeSet(UAbilitySystemComponent* ASC)
|
||||
{
|
||||
return Cast< <class_name> >(ASC->GetAttributeSet(<class_name>::StaticClass()));
|
||||
}
|
||||
}
|
||||
)));
|
||||
|
||||
inlines.print(ns_gasa);
|
||||
inlines.write();
|
||||
format_file(path_inlines_file);
|
||||
}
|
||||
|
||||
Builder source = builder_open( path_source_file );
|
||||
{
|
||||
source.print(generation_notice);
|
||||
header.print(fmt_newline);
|
||||
source.print(def_include(header_file_name));
|
||||
source.print(def_include(inlines_file_name));
|
||||
source.print(def_include(txt("EffectProperties.h")));
|
||||
source.print(fmt_newline);
|
||||
source.print(def_include(txt("AbilitySystemComponent.h")));
|
||||
source.print(def_include(txt("Net/UnrealNetwork.h")));
|
||||
source.print(def_include(txt("Networking/GasaNetLibrary.h")));
|
||||
source.print(def_include(txt("GameplayEffectExtension.h")));
|
||||
{
|
||||
CodeBody body = def_body(CodeT::Global_Body);
|
||||
body.append(fmt_newline);
|
||||
|
||||
CodeConstructor constructor_for_UGasaAttributeSet = parse_constructor(code(
|
||||
UGasaAttributeSet::UGasaAttributeSet()
|
||||
{}
|
||||
));
|
||||
body.append(constructor_for_UGasaAttributeSet);
|
||||
|
||||
// Generate Attribute fields implementation
|
||||
{
|
||||
body.append(fmt_newline);
|
||||
body.append(def_pragma(txt("region Rep Notifies")));
|
||||
|
||||
for (TPair< FName, TArray<FAttributeSetField>>& attributes : AttributesByCategory)
|
||||
for (FAttributeSetField attribute : attributes.Value)
|
||||
{
|
||||
CodeFn field_impl = parse_function(token_fmt(
|
||||
"class_name", (StrC)class_name,
|
||||
"property", (StrC)to_string(attribute.Name),
|
||||
"from_notice", txt("\n// From GAMEPLAYATTRIBUTE_REPNOTIFY\n"),
|
||||
stringize(
|
||||
void <class_name>::Client_OnRep_<property>(FGameplayAttributeData & Prev<property>)
|
||||
{
|
||||
<from_notice>
|
||||
static FProperty* <class_name>Property = FindFieldChecked<FProperty>(StaticClass(), GET_MEMBER_NAME_CHECKED(<class_name>, <property>));
|
||||
GetOwningAbilitySystemComponentChecked()->SetBaseAttributeValueFromReplication(FGameplayAttribute(<class_name>Property), <property>, Prev<property>);
|
||||
}
|
||||
)));
|
||||
body.append(field_impl);
|
||||
}
|
||||
body.append(def_pragma(txt("endregion Rep Notifies")));
|
||||
body.append(fmt_newline);
|
||||
}
|
||||
|
||||
CodeFn PostGameplayEffectExecute;
|
||||
CodeFn PreAttributeChange;
|
||||
{
|
||||
CodeBody pre_attribute_clamps = def_body(CodeT::Function_Body);
|
||||
CodeBody post_attribute_clamps = def_body(CodeT::Function_Body);
|
||||
|
||||
// Generate field clamping ops for the pre & post functions
|
||||
{
|
||||
pre_attribute_clamps.append(fmt_newline);
|
||||
pre_attribute_clamps.append(fmt_newline);
|
||||
post_attribute_clamps.append(fmt_newline);
|
||||
post_attribute_clamps.append(fmt_newline);
|
||||
|
||||
for (TPair< FName, TArray<FAttributeSetField>>& attributes : AttributesByCategory)
|
||||
for (FAttributeSetField attribute : attributes.Value)
|
||||
{
|
||||
String clamp_min;
|
||||
if (attribute.bUseMinAttribute)
|
||||
clamp_min = get_cached_string(token_fmt("MinName", (StrC)to_string(attribute.MinAttribute), "Get<MinName>()"));
|
||||
else
|
||||
clamp_min = String::fmt_buf(GlobalAllocator, "%f", attribute.MinValue);
|
||||
|
||||
String clamp_max;
|
||||
if (attribute.bUseMaxAttribute)
|
||||
clamp_max = get_cached_string(token_fmt("MaxName", (StrC)to_string(attribute.MaxAttribute), "Get<MaxName>()"));
|
||||
else
|
||||
clamp_max = String::fmt_buf(GlobalAllocator, "%f", attribute.MaxValue);
|
||||
|
||||
pre_attribute_clamps.append(code_fmt(
|
||||
"field", (StrC)to_string(attribute.Name),
|
||||
"clamp_min", (StrC)clamp_min,
|
||||
"clamp_max", (StrC)clamp_max,
|
||||
stringize(
|
||||
if (Attribute == Get<field>Attribute())
|
||||
{
|
||||
NewValue = FMath::Clamp(NewValue, <clamp_min>, <clamp_max>);
|
||||
}
|
||||
)));
|
||||
|
||||
post_attribute_clamps.append(code_fmt(
|
||||
"field", (StrC)to_string(attribute.Name),
|
||||
"clamp_min", (StrC)clamp_min,
|
||||
"clamp_max", (StrC)clamp_max,
|
||||
stringize(
|
||||
if (Data.EvaluatedData.Attribute == Get<field>Attribute())
|
||||
{
|
||||
Set<field>(FMath::Clamp(Get<field>(), <clamp_min>, <clamp_max>));
|
||||
}
|
||||
)));
|
||||
}
|
||||
|
||||
pre_attribute_clamps.append(fmt_newline);
|
||||
pre_attribute_clamps.append(fmt_newline);
|
||||
post_attribute_clamps.append(fmt_newline);
|
||||
post_attribute_clamps.append(fmt_newline);
|
||||
}
|
||||
|
||||
PreAttributeChange = parse_function(token_fmt(
|
||||
"class_name", (StrC)class_name,
|
||||
"attribute_clamps", (StrC)pre_attribute_clamps.to_string(),
|
||||
stringize(
|
||||
void <class_name>::PreAttributeChange(FGameplayAttribute const& Attribute, float& NewValue)
|
||||
{
|
||||
Super::PreAttributeChange(Attribute, NewValue);
|
||||
|
||||
<attribute_clamps>
|
||||
}
|
||||
)));
|
||||
|
||||
PostGameplayEffectExecute = parse_function(token_fmt(
|
||||
"class_name", (StrC)class_name,
|
||||
"attribute_clamps", (StrC)post_attribute_clamps.to_string(),
|
||||
stringize(
|
||||
void <class_name>::PostGameplayEffectExecute(FGameplayEffectModCallbackData const& Data)
|
||||
{
|
||||
Super::PostGameplayEffectExecute(Data);
|
||||
FEffectProperties Props;
|
||||
Props.Populate(Data);
|
||||
|
||||
<attribute_clamps>
|
||||
}
|
||||
)));
|
||||
|
||||
body.append(PostGameplayEffectExecute);
|
||||
body.append(fmt_newline);
|
||||
|
||||
body.append(PreAttributeChange);
|
||||
body.append(fmt_newline);
|
||||
}
|
||||
|
||||
CodeFn GetLifetimeOfReplicatedProps;
|
||||
{
|
||||
CodeBody field_lifetimes = def_body(CodeT::Function_Body);
|
||||
field_lifetimes.append(fmt_newline);
|
||||
field_lifetimes.append(fmt_newline);
|
||||
for (TPair< FName, TArray<FAttributeSetField>>& attributes : AttributesByCategory)
|
||||
for (FAttributeSetField attribute : attributes.Value)
|
||||
{
|
||||
field_lifetimes.append(code_fmt(
|
||||
"class_name", (StrC)class_name,
|
||||
"property", (StrC)to_string(attribute.Name),
|
||||
stringize(
|
||||
DOREPLIFETIME_DEFAULT_GAS( <class_name>, <property> );
|
||||
)));
|
||||
}
|
||||
|
||||
GetLifetimeOfReplicatedProps = parse_function(token_fmt(
|
||||
"class_name", (StrC)class_name,
|
||||
"property_lifetimes", (StrC)(field_lifetimes.to_string()),
|
||||
stringize(
|
||||
void <class_name>::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||
{
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
<property_lifetimes>
|
||||
}
|
||||
)));
|
||||
|
||||
body.append(GetLifetimeOfReplicatedProps);
|
||||
}
|
||||
source.print(body);
|
||||
}
|
||||
source.write();
|
||||
format_file(path_source_file);
|
||||
}
|
||||
}
|
||||
PRAGMA_ENABLE_OPTIMIZATION
|
||||
|
||||
#pragma pop_macro("UPROPERTY")
|
||||
#pragma pop_macro("UFUNCTION")
|
||||
#pragma pop_macro("FORCEINLINE")
|
||||
#pragma pop_macro("ensure")
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
void generate_attribute_sets();
|
||||
void generate_AttributeSets();
|
||||
|
||||
|
||||
|
||||
|
@ -4,8 +4,6 @@
|
||||
#include "gencpp/gen.builder.hpp"
|
||||
using namespace gen;
|
||||
|
||||
#undef check
|
||||
|
||||
// Codegen assumes its working directory is the project
|
||||
#define path_scripts "/scripts/"
|
||||
#define path_project "/Project/"
|
||||
@ -121,11 +119,20 @@ void format_file( char const* path )
|
||||
log_fmt("\tRunning clang-format on file:\n");
|
||||
system( command );
|
||||
log_fmt("\tclang-format finished reformatting.\n");
|
||||
|
||||
FString command_fstr = FString( command.Data, command.length());
|
||||
UE_LOG(LogTemp, Log, TEXT("clang format command: %s"), *command_fstr );
|
||||
#undef cf_cmd
|
||||
#undef cf_format_inplace
|
||||
#undef cf_style
|
||||
#undef cf_verbse
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
String to_string( FString ue_string ) {
|
||||
char const* ansi_str = TCHAR_TO_ANSI(*ue_string);
|
||||
return String::make_length(GlobalAllocator, ansi_str, ue_string.Len());
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
String to_string( FName ue_fname ) {
|
||||
char const* ansi_str = TCHAR_TO_ANSI(*ue_fname.ToString());
|
||||
return String::make_length(GlobalAllocator, ansi_str, ue_fname.GetStringLength());
|
||||
}
|
||||
|
@ -105,9 +105,9 @@ void gen_UGasaAttributeSet()
|
||||
Array<GAS_AttributeEntry> primary_attribute_fields = get_gasa_primary_attribute_fields();
|
||||
Array<GAS_AttributeEntry> secondary_attribute_fields = get_gasa_secondary_attribute_fields();
|
||||
Array<GAS_AttributeEntry> vital_attribute_fields = get_gasa_vital_attribute_fields();
|
||||
|
||||
|
||||
s32 all_attrib_count = primary_attribute_fields.num() + secondary_attribute_fields.num() + vital_attribute_fields.num();
|
||||
|
||||
|
||||
Array< GAS_AttributeEntry>
|
||||
all_attribute_fields = Array<GAS_AttributeEntry>::init_reserve(GlobalAllocator, all_attrib_count);
|
||||
all_attribute_fields.append( primary_attribute_fields);
|
||||
@ -124,6 +124,9 @@ void gen_UGasaAttributeSet()
|
||||
{
|
||||
CodeInclude Include_AttributeSet = def_include(txt("AttributeSet.h"));
|
||||
CodeInclude Include_GasaAttributeSet_Generated = def_include(txt("GasaAttributeSet.generated.h"));
|
||||
header.print( Include_AttributeSet);
|
||||
header.print( Include_GasaAttributeSet_Generated);
|
||||
header.print( fmt_newline);
|
||||
|
||||
CodeAttributes api_attribute = def_attributes( UModule_GASA_API->Name);
|
||||
|
||||
@ -144,8 +147,7 @@ void gen_UGasaAttributeSet()
|
||||
body.append(fmt_newline);
|
||||
|
||||
// body.append( def_comment(txt("Secondary Attribute Fields")));
|
||||
// body.append(fmt_newline);
|
||||
// def_attribute_properties( body, secondary_attribute_fields);
|
||||
// body.append(fmt_newline);sssss// def_attribute_properties( body, secondary_attribute_fields);
|
||||
// body.append(fmt_newline);
|
||||
// body.append(fmt_newline);
|
||||
|
||||
@ -205,9 +207,6 @@ void gen_UGasaAttributeSet()
|
||||
);
|
||||
}
|
||||
|
||||
header.print( Include_AttributeSet);
|
||||
header.print( Include_GasaAttributeSet_Generated);
|
||||
header.print( fmt_newline);
|
||||
header.print( UHT_UCLASS );
|
||||
header.print(GasaAttributeSet);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user