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.
										
									
								
							| @@ -8,9 +8,9 @@ | ||||
|  | ||||
| UGasaAttributeSet::UGasaAttributeSet() | ||||
| { | ||||
| 	InitHealth( 80.f ); | ||||
| 	InitHealth( 50.f ); | ||||
| 	InitMaxHealth( 100.f ); | ||||
| 	InitMana( 20.f ); | ||||
| 	InitMana( 25.f ); | ||||
| 	InitMaxMana( 50.f ); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
|  | ||||
| #pragma region Engine Forwards | ||||
| struct FInputActionValue; | ||||
| struct FOnAttributeChangeData; | ||||
|  | ||||
| class IAbilitySystemInterface; | ||||
|  | ||||
| @@ -34,6 +35,8 @@ class UCogWindowManager; | ||||
| // Gasa | ||||
|  | ||||
| #pragma region Forwards | ||||
| struct FWidgetControllerData; | ||||
|  | ||||
| class ACameraMount; | ||||
| class AGasaCharacter; | ||||
| class AGasaGameInstance; | ||||
| @@ -52,8 +55,6 @@ class UGasaSizeBox; | ||||
| class UHostWidgetController; | ||||
| class UHUDHostWidget; | ||||
| class UWidgetController; | ||||
|  | ||||
| struct FWidgetControllerData; | ||||
| #pragma endregion Forwards | ||||
|  | ||||
| #pragma region Logging | ||||
|   | ||||
| @@ -12,13 +12,18 @@ void FGasaDevOptionsCache::CachedDevOptions() | ||||
| 	UGasaDevOptions* DevOpts = GetMutDevOptions(); | ||||
|  | ||||
| 	Template_PlayerCamera = DevOpts->Template_PlayerCamera.LoadSynchronous(); | ||||
| 	ensureMsgf( Template_PlayerCamera != nullptr, TEXT( "Template_PlayerCamera is null, DO NOT RUN PIE or else you may get a crash if not handled in BP or C++" ) ); | ||||
| 	ensureMsgf( | ||||
| 	    Template_PlayerCamera != nullptr, TEXT( "Template_PlayerCamera is null, DO NOT RUN PIE or else you may get a crash if not handled in BP or C++" ) | ||||
| 	); | ||||
|  | ||||
| 	Template_HUD_HostUI = DevOpts->Template_HUD_HostUI.LoadSynchronous(); | ||||
| 	ensureMsgf( Template_HUD_HostUI != nullptr, TEXT( "Template_HUD_HostUI is null, DO NOT RUN PIE or else you may get a crash if not handled in BP or C++" ) ); | ||||
|  | ||||
| 	Template_HostWidgetController = DevOpts->Template_HostWidgetController.LoadSynchronous(); | ||||
| 	ensureMsgf( Template_HostWidgetController != nullptr, TEXT( "Template_HostWidgetController is null, DO NOT RUN PIE or else you may get a crash if not handled in BP or C++" ) ); | ||||
| 	ensureMsgf( | ||||
| 	    Template_HostWidgetController != nullptr, | ||||
| 	    TEXT( "Template_HostWidgetController is null, DO NOT RUN PIE or else you may get a crash if not handled in BP or C++" ) | ||||
| 	); | ||||
|  | ||||
| 	Tag_GlobalPPV = DevOpts->Tag_GlobalPPV; | ||||
| } | ||||
|   | ||||
| @@ -14,6 +14,7 @@ void AGasaHUD::InitHostWidget(FWidgetControllerData const* WidgetControllerData) | ||||
| 	HostWidgetController = NewObject<UHostWidgetController>(this, GetDevOptions()->Template_HostWidgetController.Get()); | ||||
| 	HostWidgetController->Data = (* WidgetControllerData); | ||||
| 	HostWidget->SetWidgetController(HostWidgetController); | ||||
| 	HostWidgetController->BindCallbacksToDependencies(); | ||||
| 	 | ||||
| 	HostWidgetController->BroadcastInitialValues(); | ||||
| 	HostWidget->AddToViewport(); | ||||
|   | ||||
| @@ -1,8 +1,34 @@ | ||||
| #include "HostWidgetController.h" | ||||
| #include "AbilitySystem/GasaAbilitySystemComponent_Inlines.h" | ||||
| #include "AbilitySystem/GasaAttributeSet.h" | ||||
| #include "GameplayEffectTypes.h" | ||||
|  | ||||
| #pragma region Attribute Changed Callbacks | ||||
| // Attribute Changed Callbacks are generated by GasaGen/GasaGen_HostWidgetController.cpp | ||||
|  | ||||
| void UHostWidgetController::HealthChanged( FOnAttributeChangeData const& Attribute ) | ||||
| { | ||||
| 	Event_OnHealthChanged.Broadcast( Attribute.NewValue ); | ||||
| } | ||||
|  | ||||
| void UHostWidgetController::MaxHealthChanged( FOnAttributeChangeData const& Attribute ) | ||||
| { | ||||
| 	Event_OnMaxHealthChanged.Broadcast( Attribute.NewValue ); | ||||
| } | ||||
|  | ||||
| void UHostWidgetController::ManaChanged( FOnAttributeChangeData const& Attribute ) | ||||
| { | ||||
| 	Event_OnManaChanged.Broadcast( Attribute.NewValue ); | ||||
| } | ||||
|  | ||||
| void UHostWidgetController::MaxManaChanged( FOnAttributeChangeData const& Attribute ) | ||||
| { | ||||
| 	Event_OnMaxManaChanged.Broadcast( Attribute.NewValue ); | ||||
| } | ||||
| #pragma endregion Attribute Changed Callbacks | ||||
|  | ||||
| void UHostWidgetController::BroadcastInitialValues() | ||||
| { | ||||
| 	Super::BroadcastInitialValues(); | ||||
| 	UGasaAttributeSet* GasaAttribs = Cast<UGasaAttributeSet>( Data.Attributes ); | ||||
| 	if ( GasaAttribs ) | ||||
| 	{ | ||||
| @@ -12,3 +38,24 @@ void UHostWidgetController::BroadcastInitialValues() | ||||
| 		Event_OnMaxManaChanged.Broadcast( GasaAttribs->GetMaxMana() ); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void UHostWidgetController::BindCallbacksToDependencies() | ||||
| { | ||||
| 	UGasaAbilitySystemComp* AbilitySystem = Cast<UGasaAbilitySystemComp>( Data.AbilitySystem ); | ||||
| 	UGasaAttributeSet*      GasaAttribs   = Cast<UGasaAttributeSet>( Data.Attributes ); | ||||
|  | ||||
| 	FOnGameplayAttributeValueChange& HealthAttributeChangedDelegate = | ||||
| 	    AbilitySystem->GetGameplayAttributeValueChangeDelegate( GasaAttribs->GetHealthAttribute() ); | ||||
| 	HealthAttributeChangedDelegate.AddUObject( this, &ThisClass::HealthChanged ); | ||||
|  | ||||
| 	FOnGameplayAttributeValueChange& MaxHealthAttributeChangedDelegate = | ||||
| 	    AbilitySystem->GetGameplayAttributeValueChangeDelegate( GasaAttribs->GetMaxHealthAttribute() ); | ||||
| 	MaxHealthAttributeChangedDelegate.AddUObject( this, &ThisClass::MaxHealthChanged ); | ||||
|  | ||||
| 	FOnGameplayAttributeValueChange& ManaAttributeChangedDelegate = AbilitySystem->GetGameplayAttributeValueChangeDelegate( GasaAttribs->GetManaAttribute() ); | ||||
| 	ManaAttributeChangedDelegate.AddUObject( this, &ThisClass::ManaChanged ); | ||||
|  | ||||
| 	FOnGameplayAttributeValueChange& MaxManaAttributeChangedDelegate = | ||||
| 	    AbilitySystem->GetGameplayAttributeValueChangeDelegate( GasaAttribs->GetMaxManaAttribute() ); | ||||
| 	MaxManaAttributeChangedDelegate.AddUObject( this, &ThisClass::MaxManaChanged ); | ||||
| } | ||||
|   | ||||
| @@ -23,9 +23,15 @@ public: | ||||
|  | ||||
| 	UPROPERTY( BlueprintAssignable, Category = "Attributes" ) | ||||
| 	FAttributeFloatChangedSig Event_OnMaxManaChanged; | ||||
|  | ||||
| 	void HealthChanged( FOnAttributeChangeData const& Data ); | ||||
| 	void MaxHealthChanged( FOnAttributeChangeData const& Data ); | ||||
| 	void ManaChanged( FOnAttributeChangeData const& Data ); | ||||
| 	void MaxManaChanged( FOnAttributeChangeData const& Data ); | ||||
| #pragma endregion Attribute Events | ||||
|  | ||||
| #pragma region WidgetController | ||||
| 	void BroadcastInitialValues() override; | ||||
| 	void BindCallbacksToDependencies() override; | ||||
| #pragma endregion WidgetController | ||||
| }; | ||||
|   | ||||
| @@ -45,4 +45,5 @@ public: | ||||
|  | ||||
| 	UFUNCTION() | ||||
| 	virtual void BroadcastInitialValues() {}; | ||||
| 	virtual void BindCallbacksToDependencies() {}; | ||||
| }; | ||||
|   | ||||
| @@ -19,196 +19,6 @@ using namespace gen; | ||||
| #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() | ||||
| { | ||||
| 	gen::init(); | ||||
|   | ||||
| @@ -0,0 +1,304 @@ | ||||
| #if GASA_INTELLISENSE_DIRECTIVES | ||||
| #pragma once | ||||
| #define GEN_EXPOSE_BACKEND | ||||
| #include "gen.hpp" | ||||
| #include "gen.builder.hpp" | ||||
| #include "GasaGenCommon.cpp" | ||||
| #endif | ||||
|  | ||||
| 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(); ++id ) | ||||
| 			{ | ||||
| 				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; )) | ||||
| 				)); | ||||
| 				attribute_events.append(fmt_newline); | ||||
| 			} | ||||
|  | ||||
| 			for ( s32 id = 0; id < attribute_fields.num(); ++id ) | ||||
| 			{ | ||||
| 				StringCached attribute_field = attribute_fields[id]; | ||||
|  | ||||
| 				attribute_events.append( parse_function( | ||||
| 					token_fmt( "field", (StrC) attribute_field, stringize( void <field>Changed(FOnAttributeChangeData const& Data); )) | ||||
| 				)); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		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); | ||||
|  | ||||
| 		CodeFn BroadcastInitialValues = NoCode; | ||||
| 		{ | ||||
| 			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>() ); ) | ||||
| 				)); | ||||
| 			} | ||||
|  | ||||
| 			BroadcastInitialValues = parse_function( token_fmt( | ||||
| 				"broadcast_calls",   (StrC)broadcast_calls.to_string(), | ||||
| 				"generation_notice", txt("\n// This function is managed by: GenGasa/GenGasa_HostWidgetController.cpp\n\n"), | ||||
| 			stringize( | ||||
| 				void UHostWidgetController::BroadcastInitialValues() | ||||
| 				{ | ||||
| 					<generation_notice> | ||||
|  | ||||
| 					UGasaAttributeSet* GasaAttribs = Cast<UGasaAttributeSet>(Data.Attributes); | ||||
| 					if (GasaAttribs) | ||||
| 					{ | ||||
| 						<broadcast_calls> | ||||
| 					} | ||||
|  | ||||
| 					BindCallbacksToDependencies(); | ||||
| 				}) | ||||
| 			)); | ||||
| 		} | ||||
|  | ||||
| 		CodeFn BindCallbacksToDependencies = NoCode; | ||||
| 		{ | ||||
| 			CodeBody bindings = def_body(ECode::Function_Body); | ||||
| 			bindings.append(fmt_newline); | ||||
| 			bindings.append(fmt_newline); | ||||
| 			for (StringCached field : attribute_fields) | ||||
| 			{ | ||||
| 				bindings.append( code_fmt( "field", (StrC)field, | ||||
| 				stringize( | ||||
| 					FOnGameplayAttributeValueChange& <field>AttributeChangedDelegate = AbilitySystem->GetGameplayAttributeValueChangeDelegate(GasaAttribs->Get<field>Attribute()); | ||||
| 					<field>AttributeChangedDelegate.AddUObject(this, &ThisClass::<field>Changed); | ||||
| 				))); | ||||
| 				bindings.append(fmt_newline); | ||||
| 				bindings.append(fmt_newline); | ||||
| 			} | ||||
|  | ||||
| 			BindCallbacksToDependencies = parse_function( token_fmt( | ||||
| 				"generation_notice", txt("\n// This function is managed by: GenGasa/GenGasa_HostWidgetController.cpp\n\n"), | ||||
| 				"bindings",          (StrC)bindings.to_string(), | ||||
| 			stringize( | ||||
| 				void UHostWidgetController::BindCallbacksToDependencies() | ||||
| 				{ | ||||
| 					<generation_notice> | ||||
|  | ||||
| 					UGasaAbilitySystemComp* AbilitySystem = Cast<UGasaAbilitySystemComp>(Data.AbilitySystem); | ||||
| 					UGasaAttributeSet*      GasaAttribs   = Cast<UGasaAttributeSet>( Data.Attributes ); | ||||
|  | ||||
| 					<bindings> | ||||
| 				}) | ||||
| 			)); | ||||
| 		} | ||||
|  | ||||
| 		CodeBody attribute_callbacks = def_body(ECode::Global_Body); | ||||
| 		{ | ||||
| 			attribute_callbacks.append( def_comment(txt("Attribute Changed Callbacks are generated by GasaGen/GasaGen_HostWidgetController.cpp"))); | ||||
| 			attribute_callbacks.append(fmt_newline); | ||||
|  | ||||
| 			for ( s32 id = 0; id < attribute_fields.num(); ) | ||||
| 			{ | ||||
| 				StringCached attribute_field = attribute_fields[id]; | ||||
|  | ||||
| 				attribute_callbacks.append( parse_function( token_fmt( | ||||
| 					"field", (StrC) attribute_field, | ||||
| 				stringize( | ||||
| 					void UHostWidgetController::<field>Changed(FOnAttributeChangeData const& Attribute) | ||||
| 					{ | ||||
| 						Event_On<field>Changed.Broadcast(Attribute.NewValue); | ||||
| 					}) | ||||
| 				))); | ||||
|  | ||||
| 				++ id; | ||||
| 				if ( id < attribute_fields.num() ) | ||||
| 				{ | ||||
| 					attribute_callbacks.append(fmt_newline); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		for ( Code code = ori_HostWidgetController_source.begin(); | ||||
| 			code != ori_HostWidgetController_source.end(); | ||||
| 			++ code | ||||
| 		) | ||||
| 		{ | ||||
| 			switch (code->Type) | ||||
| 			{ | ||||
| 				case ECode::Preprocess_Pragma: | ||||
| 				{ | ||||
| 					local_persist bool found = false; | ||||
| 					if (found) | ||||
| 					{ | ||||
| 						source_body.append(code); | ||||
| 						++ code; | ||||
| 						continue; | ||||
| 					} | ||||
|  | ||||
| 					CodePragma pragma = code.cast<CodePragma>(); | ||||
| 					if ( pragma->Content.starts_with(txt("region Attribute Changed Callbacks")) ) | ||||
| 					{ | ||||
| 						source_body.append(fmt_newline); | ||||
| 						source_body.append(pragma); | ||||
| 						++ code; | ||||
|  | ||||
| 						source_body.append(attribute_callbacks); | ||||
|  | ||||
| 						while (code->Type != ECode::Preprocess_Pragma | ||||
| 							|| ! code->Content.starts_with(txt("endregion Attribute Changed Callbacks"))) | ||||
| 							++ code; | ||||
|  | ||||
| 						found = true; | ||||
| 					} | ||||
| 				} | ||||
| 				break; | ||||
|  | ||||
| 				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)) | ||||
| 					{ | ||||
| 						source_body.append(BroadcastInitialValues); | ||||
| 						log_fmt("Swapped: %S\n", BroadcastInitialValues->Name); | ||||
| 						continue; | ||||
| 					} | ||||
| 					else if (String::are_equal(function_def->Name, BindCallbacksToDependencies->Name) | ||||
| 						&& 	function_def->Params.is_equal(BindCallbacksToDependencies->Params)) | ||||
| 					{ | ||||
| 						source_body.append(BindCallbacksToDependencies); | ||||
| 						log_fmt("Swapped: %S\n", BindCallbacksToDependencies->Name); | ||||
| 						continue; | ||||
| 					} | ||||
| 				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"); | ||||
| 	} | ||||
| } | ||||
| @@ -79,7 +79,7 @@ BreakBeforeTernaryOperators: true | ||||
| BreakConstructorInitializers: BeforeComma | ||||
| BreakStringLiterals: true | ||||
|  | ||||
| ColumnLimit: 240 | ||||
| ColumnLimit: 160 | ||||
|  | ||||
| CompactNamespaces: true | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user