34. Listening for Attribute Changes
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								Project/Binaries/Win64/UnrealEditor-Gasa.dll
									 (Stored with Git LFS)
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Project/Binaries/Win64/UnrealEditor-Gasa.dll
									 (Stored with Git LFS)
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Project/Binaries/Win64/UnrealEditor-GasaEditor.dll
									 (Stored with Git LFS)
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Project/Binaries/Win64/UnrealEditor-GasaEditor.dll
									 (Stored with Git LFS)
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -9,7 +9,7 @@ Tag_PPV=Global_PPV
 | 
			
		||||
Tag_GlobalPPV=Global_PPV
 | 
			
		||||
Template_PlayerCamera=/Game/Actors/BP_CameraMount.BP_CameraMount_C
 | 
			
		||||
Template_HUD_HostUI=/Game/UI/UI_Host.UI_Host_C
 | 
			
		||||
Template_HostWidgetController=/Game/Core/BP_HostWidgetController.BP_HostWidgetController_C
 | 
			
		||||
Template_HostWidgetController=/Game/UI/BP_HostWidgetController.BP_HostWidgetController_C
 | 
			
		||||
 | 
			
		||||
[/Script/GameplayAbilities.AbilitySystemGlobals]
 | 
			
		||||
bUseDebugTargetFromHud=true
 | 
			
		||||
 
 | 
			
		||||
@@ -8,9 +8,9 @@
 | 
			
		||||
 | 
			
		||||
UGasaAttributeSet::UGasaAttributeSet()
 | 
			
		||||
{
 | 
			
		||||
	InitHealth( 100.f );
 | 
			
		||||
	InitHealth( 80.f );
 | 
			
		||||
	InitMaxHealth( 100.f );
 | 
			
		||||
	InitMana( 50.f );
 | 
			
		||||
	InitMana( 20.f );
 | 
			
		||||
	InitMaxMana( 50.f );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -33,7 +33,6 @@ void UGasaAttributeSet::Client_OnRep_MaxMana( FGameplayAttributeData& PrevMaxMan
 | 
			
		||||
{
 | 
			
		||||
	GAMEPLAYATTRIBUTE_REPNOTIFY( UGasaAttributeSet, MaxMana, PrevMaxMana )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UGasaAttributeSet::GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps ) const
 | 
			
		||||
{
 | 
			
		||||
	Super::GetLifetimeReplicatedProps( OutLifetimeProps );
 | 
			
		||||
 
 | 
			
		||||
@@ -90,7 +90,6 @@ public:
 | 
			
		||||
	#pragma endregion Setters
 | 
			
		||||
 | 
			
		||||
#pragma region UObject
 | 
			
		||||
 | 
			
		||||
	    void
 | 
			
		||||
	    GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps ) const override;
 | 
			
		||||
#pragma endregion UObject
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ void APlayerCharacter::PossessedBy(AController* NewController)
 | 
			
		||||
	AGasaPlayerController* PC   = GetController<AGasaPlayerController>();
 | 
			
		||||
	AGasaHUD*              HUD  = PC->GetHUD<AGasaHUD>();
 | 
			
		||||
	FWidgetControllerData  Data = { PC, PS, AbilitySystem, Attributes };
 | 
			
		||||
	HUD->InitOverlay(& Data);
 | 
			
		||||
	HUD->InitHostWidget(& Data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO(Ed): We need to setup Net Slime...
 | 
			
		||||
@@ -49,6 +49,6 @@ void APlayerCharacter::OnRep_PlayerState()
 | 
			
		||||
		AGasaPlayerController* PC   = GetController<AGasaPlayerController>();
 | 
			
		||||
		AGasaHUD*              HUD  = PC->GetHUD<AGasaHUD>();
 | 
			
		||||
		FWidgetControllerData  Data = { PC, PS, AbilitySystem, Attributes };
 | 
			
		||||
		HUD->InitOverlay(& Data);
 | 
			
		||||
		HUD->InitHostWidget(& Data);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,14 +6,16 @@
 | 
			
		||||
#include "Blueprint/UserWidget.h"
 | 
			
		||||
using namespace Gasa;
 | 
			
		||||
 | 
			
		||||
void AGasaHUD::InitOverlay(FWidgetControllerData const* WidgetControllerData)
 | 
			
		||||
void AGasaHUD::InitHostWidget(FWidgetControllerData const* WidgetControllerData)
 | 
			
		||||
{
 | 
			
		||||
	HostWidget = CreateWidget<UHUDHostWidget>( GetWorld() 
 | 
			
		||||
		, GetDevOptions()->Template_HUD_HostUI.LoadSynchronous() );
 | 
			
		||||
 | 
			
		||||
	HostWidgetController = NewObject<UHostWidgetController>(this, GetDevOptions()->Template_HostWidgetController.Get());
 | 
			
		||||
	HostWidgetController->Data = (* WidgetControllerData);
 | 
			
		||||
	HostWidget->SetWidgetController(HostWidgetController);
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	HostWidgetController->BroadcastInitialValues();
 | 
			
		||||
	HostWidget->AddToViewport();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ public:
 | 
			
		||||
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
 | 
			
		||||
	TObjectPtr<UHostWidgetController> HostWidgetController;
 | 
			
		||||
	
 | 
			
		||||
	void InitOverlay(FWidgetControllerData const* WidgetControllerData);
 | 
			
		||||
	void InitHostWidget(FWidgetControllerData const* WidgetControllerData);
 | 
			
		||||
	
 | 
			
		||||
#pragma region HUD	
 | 
			
		||||
	void ShowHUD() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -89,6 +89,11 @@ void UGlobeProgressBar::SetGlassStyle(FSlateBrush brush)
 | 
			
		||||
	Glass->SetBrush(brush);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UGlobeProgressBar::SetPercentage(float CurrentValue, float MaxValue)
 | 
			
		||||
{
 | 
			
		||||
	Bar->SetPercent( MaxValue > 0.f ? CurrentValue / MaxValue : 0.f );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UGlobeProgressBar::SetSize(float width, float height)
 | 
			
		||||
{
 | 
			
		||||
	Root_SB->SetWidthOverride(  width );
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,9 @@ public:
 | 
			
		||||
	
 | 
			
		||||
	UFUNCTION(BlueprintCallable, Category="Globe")
 | 
			
		||||
	void SetGlassStyle(FSlateBrush brush);
 | 
			
		||||
 | 
			
		||||
	UFUNCTION(BlueprintCallable, Category="Globe")
 | 
			
		||||
	void SetPercentage(float CurrentValue, float MaxValue);
 | 
			
		||||
	
 | 
			
		||||
	UFUNCTION(BlueprintCallable, Category="Globe")
 | 
			
		||||
	void SetSize(float width, float height);
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +1,14 @@
 | 
			
		||||
#include "HostWidgetController.h"
 | 
			
		||||
#include "HostWidgetController.h"
 | 
			
		||||
#include "AbilitySystem/GasaAttributeSet.h"
 | 
			
		||||
void UHostWidgetController::BroadcastInitialValues()
 | 
			
		||||
{
 | 
			
		||||
	Super::BroadcastInitialValues();
 | 
			
		||||
	UGasaAttributeSet* GasaAttribs = Cast<UGasaAttributeSet>( Data.Attributes );
 | 
			
		||||
	if ( GasaAttribs )
 | 
			
		||||
	{
 | 
			
		||||
		Event_OnHealthChanged.Broadcast( GasaAttribs->GetHealth() );
 | 
			
		||||
		Event_OnMaxHealthChanged.Broadcast( GasaAttribs->GetMaxHealth() );
 | 
			
		||||
		Event_OnManaChanged.Broadcast( GasaAttribs->GetMana() );
 | 
			
		||||
		Event_OnMaxManaChanged.Broadcast( GasaAttribs->GetMaxMana() );
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,31 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "WidgetController.h"
 | 
			
		||||
 | 
			
		||||
#include "HostWidgetController.generated.h"
 | 
			
		||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FAttributeFloatChangedSig, float, NewValue );
 | 
			
		||||
 | 
			
		||||
UCLASS()
 | 
			
		||||
UCLASS( Blueprintable, BlueprintType )
 | 
			
		||||
class GASA_API UHostWidgetController : public UWidgetController
 | 
			
		||||
{
 | 
			
		||||
	GENERATED_BODY()
 | 
			
		||||
public:
 | 
			
		||||
#pragma region Attribute Events
 | 
			
		||||
	// Attribute Events are generated by GasaGen/GasaGen_HostWidgetController.cpp
 | 
			
		||||
 | 
			
		||||
	UPROPERTY( BlueprintAssignable, Category = "Attributes" )
 | 
			
		||||
	FAttributeFloatChangedSig Event_OnHealthChanged;
 | 
			
		||||
 | 
			
		||||
	UPROPERTY( BlueprintAssignable, Category = "Attributes" )
 | 
			
		||||
	FAttributeFloatChangedSig Event_OnMaxHealthChanged;
 | 
			
		||||
 | 
			
		||||
	UPROPERTY( BlueprintAssignable, Category = "Attributes" )
 | 
			
		||||
	FAttributeFloatChangedSig Event_OnManaChanged;
 | 
			
		||||
 | 
			
		||||
	UPROPERTY( BlueprintAssignable, Category = "Attributes" )
 | 
			
		||||
	FAttributeFloatChangedSig Event_OnMaxManaChanged;
 | 
			
		||||
#pragma endregion Attribute Events
 | 
			
		||||
 | 
			
		||||
#pragma region WidgetController
 | 
			
		||||
	void BroadcastInitialValues() override;
 | 
			
		||||
#pragma endregion WidgetController
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -7,27 +7,19 @@ USTRUCT(BlueprintType)
 | 
			
		||||
struct GASA_API FWidgetControllerData
 | 
			
		||||
{
 | 
			
		||||
	GENERATED_BODY()
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	FWidgetControllerData() = default;
 | 
			
		||||
 | 
			
		||||
	FWidgetControllerData(AGasaPlayerController*   Controller
 | 
			
		||||
						, AGasaPlayerState*        PlayerState
 | 
			
		||||
						, UAbilitySystemComponent* AbilitySystem
 | 
			
		||||
						, UAttributeSet*           Attributes )
 | 
			
		||||
#if 1
 | 
			
		||||
	FWidgetControllerData
 | 
			
		||||
	( AGasaPlayerController*   Controller
 | 
			
		||||
	, AGasaPlayerState*        PlayerState
 | 
			
		||||
	, UAbilitySystemComponent* AbilitySystem
 | 
			
		||||
	, UAttributeSet*           Attributes )
 | 
			
		||||
	: Controller(Controller)
 | 
			
		||||
	, PlayerState(PlayerState)
 | 
			
		||||
	, AbilitySystem(AbilitySystem)
 | 
			
		||||
	, Attributes(Attributes)
 | 
			
		||||
#endif
 | 
			
		||||
	{
 | 
			
		||||
#if 0
 | 
			
		||||
		this->Controller    = Controller;
 | 
			
		||||
		this->PlayerState   = PlayerState;
 | 
			
		||||
		this->AbilitySystem = AbilitySystem;
 | 
			
		||||
		this->Attributes    = Attributes;
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
	{}
 | 
			
		||||
	
 | 
			
		||||
	UPROPERTY(BlueprintReadOnly, Category="Player")
 | 
			
		||||
	TObjectPtr<AGasaPlayerController> Controller;
 | 
			
		||||
@@ -50,4 +42,7 @@ public:
 | 
			
		||||
 | 
			
		||||
	UPROPERTY(BlueprintReadOnly, Category="Player")
 | 
			
		||||
	FWidgetControllerData Data;
 | 
			
		||||
 | 
			
		||||
	UFUNCTION()
 | 
			
		||||
	virtual void BroadcastInitialValues() {};
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,197 @@ using namespace gen;
 | 
			
		||||
#include "GasaGen_UGasaAttributeSet.cpp"
 | 
			
		||||
#include "GasaGen_ChangeBPActionMenu.cpp"
 | 
			
		||||
#include "GasaGen_DevOptionsCache.cpp"
 | 
			
		||||
#include "GasaGen_HostWidgetController.cpp"
 | 
			
		||||
 | 
			
		||||
void gen_UHostWidgetController()
 | 
			
		||||
{
 | 
			
		||||
	Array<StringCached> attribute_fields = get_gasa_attribute_fields();
 | 
			
		||||
 | 
			
		||||
	CodeBody ori_HostWidgetController_header = parse_file(path_gasa_ui "HostWidgetController.h");
 | 
			
		||||
	{
 | 
			
		||||
		CodeBody header_body = def_body(ECode::Global_Body);
 | 
			
		||||
 | 
			
		||||
		StrC      str_UHostWidgetController = txt("UHostWidgetController");
 | 
			
		||||
		CodeClass ori_UHostWidgetController = NoCode;
 | 
			
		||||
 | 
			
		||||
		Code file_code = ori_HostWidgetController_header.begin();
 | 
			
		||||
		for ( ; file_code != ori_HostWidgetController_header.end(); ++ file_code )
 | 
			
		||||
		{
 | 
			
		||||
			if (s32 never_enter = 0; never_enter)
 | 
			
		||||
				found: break;
 | 
			
		||||
 | 
			
		||||
			switch (file_code->Type)
 | 
			
		||||
			{
 | 
			
		||||
			default:
 | 
			
		||||
				header_body.append(file_code);
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			case ECode::Class:
 | 
			
		||||
				if ( ! file_code->Name.starts_with(str_UHostWidgetController))
 | 
			
		||||
					continue;
 | 
			
		||||
				ori_UHostWidgetController = file_code.cast<CodeClass>();
 | 
			
		||||
				++ file_code;
 | 
			
		||||
				goto found;
 | 
			
		||||
 | 
			
		||||
			case ECode::Preprocess_Include:
 | 
			
		||||
				header_body.append(file_code);
 | 
			
		||||
 | 
			
		||||
				if ( file_code->Content.starts_with(txt("HostWidgetController.generated.h")))
 | 
			
		||||
				{
 | 
			
		||||
					header_body.append(fmt_newline);
 | 
			
		||||
					header_body.append(fmt_newline);
 | 
			
		||||
				}
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
			case ECode::Untyped:
 | 
			
		||||
				header_body.append(file_code);
 | 
			
		||||
 | 
			
		||||
				if (file_code->Content.starts_with( txt("DECLARE_"))
 | 
			
		||||
				||	file_code->Content.starts_with( txt("UCLASS"))
 | 
			
		||||
				)
 | 
			
		||||
					header_body.append(fmt_newline);
 | 
			
		||||
			continue;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		CodeBody attribute_events = def_body(ECode::Class_Body);
 | 
			
		||||
		{
 | 
			
		||||
			attribute_events.append( def_comment( txt("Attribute Events are generated by GasaGen/GasaGen_HostWidgetController.cpp")));
 | 
			
		||||
			attribute_events.append(fmt_newline);
 | 
			
		||||
 | 
			
		||||
			for ( s32 id = 0; id < attribute_fields.num(); )
 | 
			
		||||
			{
 | 
			
		||||
				StringCached attribute_field = attribute_fields[id];
 | 
			
		||||
 | 
			
		||||
				attribute_events.append( code_str(
 | 
			
		||||
					UPROPERTY(BlueprintAssignable, Category = "Attributes")
 | 
			
		||||
				));
 | 
			
		||||
				attribute_events.append(fmt_newline);
 | 
			
		||||
				attribute_events.append( parse_variable(
 | 
			
		||||
					token_fmt( "field", (StrC) attribute_field, stringize( FAttributeFloatChangedSig Event_On<field>Changed; ))
 | 
			
		||||
				));
 | 
			
		||||
 | 
			
		||||
				++ id;
 | 
			
		||||
				if ( id < attribute_fields.num() )
 | 
			
		||||
				{
 | 
			
		||||
					attribute_events.append(fmt_newline);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		CodeClass new_UHostWidgetController = ori_UHostWidgetController.duplicate().cast<CodeClass>();
 | 
			
		||||
		CodeBody  new_body                  = def_body(ECode::Class_Body);
 | 
			
		||||
		for (Code	code = ori_UHostWidgetController->Body.begin();
 | 
			
		||||
					code != ori_UHostWidgetController->Body.end();
 | 
			
		||||
					++ code )
 | 
			
		||||
		{
 | 
			
		||||
			switch (code->Type)
 | 
			
		||||
			{
 | 
			
		||||
				default:
 | 
			
		||||
					new_body.append(code);
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				case ECode::Preprocess_Pragma:
 | 
			
		||||
				{
 | 
			
		||||
					local_persist bool found = false;
 | 
			
		||||
					if (found)
 | 
			
		||||
					{
 | 
			
		||||
						new_body.append(code);
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					CodePragma pragma = code.cast<CodePragma>();
 | 
			
		||||
					if ( pragma->Content.starts_with(txt("region Attribute Events")) )
 | 
			
		||||
					{
 | 
			
		||||
						new_body.append(pragma);
 | 
			
		||||
						++ code;
 | 
			
		||||
 | 
			
		||||
						new_body.append(attribute_events);
 | 
			
		||||
 | 
			
		||||
						while (code->Type != ECode::Preprocess_Pragma
 | 
			
		||||
							|| ! code->Content.starts_with(txt("endregion Attribute Events"))) 
 | 
			
		||||
							++ code;
 | 
			
		||||
 | 
			
		||||
						new_body.append( code );
 | 
			
		||||
						found = true;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
				case ECode::Untyped:
 | 
			
		||||
					new_body.append(code);
 | 
			
		||||
 | 
			
		||||
					if (code->Content.starts_with( txt("GENERATED_BODY")))
 | 
			
		||||
						new_body.append(fmt_newline);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		new_body.append(fmt_newline);
 | 
			
		||||
		new_UHostWidgetController->Body = new_body;
 | 
			
		||||
		header_body.append(new_UHostWidgetController);
 | 
			
		||||
 | 
			
		||||
		for (; file_code != ori_HostWidgetController_header.end(); ++ file_code)
 | 
			
		||||
		{
 | 
			
		||||
			header_body.append(file_code);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Builder header = Builder::open(path_gasa_ui "HostWidgetController.h");
 | 
			
		||||
		header.print(header_body);
 | 
			
		||||
		header.write();
 | 
			
		||||
		format_file(path_gasa_ui "HostWidgetController.h");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CodeBody ori_HostWidgetController_source = parse_file(path_gasa_ui "HostWidgetController.cpp");
 | 
			
		||||
	{
 | 
			
		||||
		CodeBody source_body = def_body(ECode::Global_Body);
 | 
			
		||||
 | 
			
		||||
		CodeBody broadcast_calls = def_body(ECode::Function_Body);
 | 
			
		||||
		for (StringCached field : attribute_fields)
 | 
			
		||||
		{
 | 
			
		||||
			broadcast_calls.append( code_fmt( "field", (StrC)field,
 | 
			
		||||
				stringize( Event_On<field>Changed.Broadcast( GasaAttribs->Get<field>() ); )
 | 
			
		||||
			));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		CodeFn BroadcastInitialValues = parse_function( token_fmt( "broadcast_calls", (StrC)broadcast_calls.to_string(),
 | 
			
		||||
		stringize(
 | 
			
		||||
			void UHostWidgetController::BroadcastInitialValues()
 | 
			
		||||
			{
 | 
			
		||||
				Super::BroadcastInitialValues();
 | 
			
		||||
				// Thiis function is managed by: GasaGen/GasaGen_HostWidgetController.cpp
 | 
			
		||||
 | 
			
		||||
				UGasaAttributeSet* GasaAttribs = Cast<UGasaAttributeSet>(Data.Attributes);
 | 
			
		||||
				if (GasaAttribs)
 | 
			
		||||
				{
 | 
			
		||||
					<broadcast_calls>
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		));
 | 
			
		||||
 | 
			
		||||
		for ( Code code : ori_HostWidgetController_source)
 | 
			
		||||
		{
 | 
			
		||||
			switch (code->Type)
 | 
			
		||||
			{
 | 
			
		||||
				case ECode::Function:
 | 
			
		||||
					CodeFn function_def = code.cast<CodeFn>();
 | 
			
		||||
 | 
			
		||||
					if ( String::are_equal(function_def->Name, BroadcastInitialValues->Name)
 | 
			
		||||
					&&	function_def->Params.is_equal(BroadcastInitialValues->Params))
 | 
			
		||||
					{
 | 
			
		||||
						code = BroadcastInitialValues;
 | 
			
		||||
						log_fmt("Swapped: %S", BroadcastInitialValues->Name);
 | 
			
		||||
					}
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			source_body.append(code);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Builder source = Builder::open(path_gasa_ui "HostWidgetController.cpp");
 | 
			
		||||
		source.print(source_body);
 | 
			
		||||
		source.write();
 | 
			
		||||
		format_file(path_gasa_ui "HostWidgetController.cpp");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int gen_main()
 | 
			
		||||
{
 | 
			
		||||
@@ -38,6 +229,7 @@ int gen_main()
 | 
			
		||||
		PreprocessorDefines.append( get_cached_string(str_DECLARE_DELEGATE_RetVal_OneParam));
 | 
			
		||||
		PreprocessorDefines.append( get_cached_string(str_DECLARE_DELEGATE_RetVal_ThreeParams));
 | 
			
		||||
		PreprocessorDefines.append( get_cached_string(str_DECLARE_DELEGATE_SixParams));
 | 
			
		||||
		PreprocessorDefines.append( get_cached_string(str_DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam));
 | 
			
		||||
		PreprocessorDefines.append( get_cached_string(str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FiveParams));
 | 
			
		||||
		PreprocessorDefines.append( get_cached_string(str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FourParams));
 | 
			
		||||
		PreprocessorDefines.append( get_cached_string(str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_NineParams));
 | 
			
		||||
@@ -77,6 +269,7 @@ int gen_main()
 | 
			
		||||
 | 
			
		||||
	gen_UGasaAttributeSet();
 | 
			
		||||
	gen_FGasaDevOptionsCache();
 | 
			
		||||
	gen_UHostWidgetController();
 | 
			
		||||
 | 
			
		||||
	// One offs
 | 
			
		||||
	if (0)
 | 
			
		||||
 
 | 
			
		||||
@@ -13,11 +13,13 @@ using namespace gen;
 | 
			
		||||
#define path_config              path_source      "Config/"
 | 
			
		||||
#define path_module_gasa         path_source      "Gasa/"
 | 
			
		||||
#define path_gasa_ability_system path_module_gasa "AbilitySystem/"
 | 
			
		||||
#define path_gasa_ui             path_module_gasa "UI/"
 | 
			
		||||
 | 
			
		||||
constexpr StrC str_DECLARE_CLASS                                         = txt("DECLARE_CLASS(");
 | 
			
		||||
constexpr StrC str_DECLARE_DELEGATE_RetVal_OneParam                      = txt("DECLARE_DELEGATE_RetVal_OneParam(");
 | 
			
		||||
constexpr StrC str_DECLARE_DELEGATE_RetVal_ThreeParams                   = txt("DECLARE_DELEGATE_RetVal_ThreeParams(");
 | 
			
		||||
constexpr StrC str_DECLARE_DELEGATE_SixParams                            = txt("DECLARE_DELEGATE_SixParams(");
 | 
			
		||||
constexpr StrC str_DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam           = txt("DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(");
 | 
			
		||||
constexpr StrC str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FiveParams  = txt("DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FiveParams(");
 | 
			
		||||
constexpr StrC str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FourParams  = txt("DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FourParams(");
 | 
			
		||||
constexpr StrC str_DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_NineParams  = txt("DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_NineParams(");
 | 
			
		||||
 
 | 
			
		||||
@@ -16,16 +16,26 @@ void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name
 | 
			
		||||
void def_attribute_field_initers                ( CodeBody body, Array<StringCached> properties );
 | 
			
		||||
void impl_attribute_fields                      ( CodeBody body, StrC class_name, Array<StringCached> properties );
 | 
			
		||||
 | 
			
		||||
Array<StringCached> get_gasa_attribute_fields()
 | 
			
		||||
{
 | 
			
		||||
	local_persist
 | 
			
		||||
	Array<StringCached> attribute_fields = Array<StringCached>::init_reserve(GlobalAllocator, 64);
 | 
			
		||||
 | 
			
		||||
	for (local_persist s32 do_once = 0; do_once == 0; ++ do_once) {
 | 
			
		||||
		attribute_fields.append( get_cached_string(txt("Health")));
 | 
			
		||||
		attribute_fields.append( get_cached_string(txt("MaxHealth")));
 | 
			
		||||
		attribute_fields.append( get_cached_string(txt("Mana")));
 | 
			
		||||
		attribute_fields.append( get_cached_string(txt("MaxMana")));
 | 
			
		||||
	}
 | 
			
		||||
	return attribute_fields;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gen_UGasaAttributeSet()
 | 
			
		||||
{
 | 
			
		||||
	CodeType   type_UAttributeSet = def_type( txt("UAttributeSet") );
 | 
			
		||||
	CodeComment generation_notice = def_comment(txt("Generated by GasaGen/GasaGen_UGasaAttributeSet.cpp"));
 | 
			
		||||
 | 
			
		||||
	Array<StringCached> attribute_fields = Array<StringCached>::init( GlobalAllocator);
 | 
			
		||||
	attribute_fields.append( get_cached_string(txt("Health")));
 | 
			
		||||
	attribute_fields.append( get_cached_string(txt("MaxHealth")));
 | 
			
		||||
	attribute_fields.append( get_cached_string(txt("Mana")));
 | 
			
		||||
	attribute_fields.append( get_cached_string(txt("MaxMana")));
 | 
			
		||||
	Array<StringCached> attribute_fields = get_gasa_attribute_fields();
 | 
			
		||||
 | 
			
		||||
	StrC class_name = txt("UGasaAttributeSet");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1950,6 +1950,7 @@ void CodeFn::to_string_def( String& result )
 | 
			
		||||
	if ( ast->Attributes )
 | 
			
		||||
		result.append_fmt( " %S ", ast->Attributes.to_string() );
 | 
			
		||||
 | 
			
		||||
	b32 prefix_specs = false;
 | 
			
		||||
	if ( ast->Specs )
 | 
			
		||||
	{
 | 
			
		||||
		for ( SpecifierT spec : ast->Specs )
 | 
			
		||||
@@ -1958,11 +1959,13 @@ void CodeFn::to_string_def( String& result )
 | 
			
		||||
			{
 | 
			
		||||
				StrC spec_str = ESpecifier::to_str( spec );
 | 
			
		||||
				result.append_fmt( " %.*s", spec_str.Len, spec_str.Ptr );
 | 
			
		||||
 | 
			
		||||
				prefix_specs = true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ( ast->Attributes || ast->Specs )
 | 
			
		||||
	if ( ast->Attributes || prefix_specs )
 | 
			
		||||
		result.append( "\n" );
 | 
			
		||||
 | 
			
		||||
	if ( ast->ReturnType )
 | 
			
		||||
@@ -2000,19 +2003,22 @@ void CodeFn::to_string_fwd( String& result )
 | 
			
		||||
	if ( ast->Attributes )
 | 
			
		||||
		result.append_fmt( "%S ", ast->Attributes.to_string() );
 | 
			
		||||
 | 
			
		||||
	bool prefix_specs = false;
 | 
			
		||||
	if ( ast->Specs )
 | 
			
		||||
	{
 | 
			
		||||
		for ( SpecifierT spec : ast->Specs )
 | 
			
		||||
		{
 | 
			
		||||
			if ( ESpecifier::is_trailing( spec ) && ! ( spec != ESpecifier::Pure ) )
 | 
			
		||||
			if ( ! ESpecifier::is_trailing( spec ) || ! ( spec != ESpecifier::Pure ) )
 | 
			
		||||
			{
 | 
			
		||||
				StrC spec_str = ESpecifier::to_str( spec );
 | 
			
		||||
				result.append_fmt( " %.*s", spec_str.Len, spec_str.Ptr );
 | 
			
		||||
 | 
			
		||||
				prefix_specs = true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ( ast->Attributes || ast->Specs )
 | 
			
		||||
	if ( ast->Attributes || prefix_specs )
 | 
			
		||||
	{
 | 
			
		||||
		result.append( "\n" );
 | 
			
		||||
	}
 | 
			
		||||
@@ -2894,17 +2900,17 @@ internal void define_constants()
 | 
			
		||||
 | 
			
		||||
	access_private       = make_code();
 | 
			
		||||
	access_private->Type = ECode::Access_Private;
 | 
			
		||||
	access_private->Name = get_cached_string( txt( "private:" ) );
 | 
			
		||||
	access_private->Name = get_cached_string( txt( "private:\n" ) );
 | 
			
		||||
	access_private.set_global();
 | 
			
		||||
 | 
			
		||||
	access_protected       = make_code();
 | 
			
		||||
	access_protected->Type = ECode::Access_Protected;
 | 
			
		||||
	access_protected->Name = get_cached_string( txt( "protected:" ) );
 | 
			
		||||
	access_protected->Name = get_cached_string( txt( "protected:\n" ) );
 | 
			
		||||
	access_protected.set_global();
 | 
			
		||||
 | 
			
		||||
	access_public       = make_code();
 | 
			
		||||
	access_public->Type = ECode::Access_Public;
 | 
			
		||||
	access_public->Name = get_cached_string( txt( "public:" ) );
 | 
			
		||||
	access_public->Name = get_cached_string( txt( "public:\n" ) );
 | 
			
		||||
	access_public.set_global();
 | 
			
		||||
 | 
			
		||||
	attrib_api_export = def_attributes( code( GEN_API_Export_Code ) );
 | 
			
		||||
 
 | 
			
		||||
@@ -5146,6 +5146,9 @@ Code CodeParam::duplicate()
 | 
			
		||||
 | 
			
		||||
bool CodeParam::is_equal( Code other )
 | 
			
		||||
{
 | 
			
		||||
	if ( ast == nullptr && other.ast == nullptr)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	if ( ast == nullptr || other.ast == nullptr )
 | 
			
		||||
	{
 | 
			
		||||
		log_failure( "Code::is_equal: Cannot compare code, AST is null!" );
 | 
			
		||||
 
 | 
			
		||||
@@ -166,7 +166,16 @@ SpacesInSquareBrackets: false
 | 
			
		||||
 | 
			
		||||
Standard: c++20
 | 
			
		||||
 | 
			
		||||
StatementMacros: ['UPROPERTY', 'UFUNCTION', 'UCLASS', 'USTRUCT', 'UENUM', 'UINTERFACE', 'GENERATED_BODY']
 | 
			
		||||
StatementMacros: [
 | 
			
		||||
  'UPROPERTY',
 | 
			
		||||
  'UFUNCTION',
 | 
			
		||||
  'UCLASS',
 | 
			
		||||
  'USTRUCT',
 | 
			
		||||
  'UENUM',
 | 
			
		||||
  'UINTERFACE',
 | 
			
		||||
  'GENERATED_BODY',
 | 
			
		||||
  'DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam'
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
TabWidth: 4
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -79,6 +79,7 @@ function build-gengasa
 | 
			
		||||
 | 
			
		||||
	$compiler_args = @()
 | 
			
		||||
	$compiler_args += ($flag_define + 'GEN_TIME')
 | 
			
		||||
	$compiler_args += ($flag_cpp_version + 'c++17')
 | 
			
		||||
 | 
			
		||||
	$linker_args = @()
 | 
			
		||||
	$linker_args += $flag_link_win_subsystem_console
 | 
			
		||||
 
 | 
			
		||||
@@ -94,6 +94,7 @@ if ( $vendor -match "clang" )
 | 
			
		||||
	# https://clang.llvm.org/docs/ClangCommandLineReference.html
 | 
			
		||||
	$flag_all_c 					   = '-x c'
 | 
			
		||||
	$flag_all_cpp                      = '-x c++'
 | 
			
		||||
	$flag_cpp_version                  = '-std='
 | 
			
		||||
	$flag_compile                      = '-c'
 | 
			
		||||
	$flag_color_diagnostics            = '-fcolor-diagnostics'
 | 
			
		||||
	$flag_no_color_diagnostics         = '-fno-color-diagnostics'
 | 
			
		||||
@@ -318,6 +319,7 @@ if ( $vendor -match "msvc" )
 | 
			
		||||
	# https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category?view=msvc-170
 | 
			
		||||
	$flag_all_c 					 = '/TC'
 | 
			
		||||
	$flag_all_cpp                    = '/TP'
 | 
			
		||||
	$flag_cpp_version                = '/std:'
 | 
			
		||||
	$flag_compile			         = '/c'
 | 
			
		||||
	$flag_debug                      = '/Zi'
 | 
			
		||||
	$flag_define		             = '/D'
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user