Skip to content

Commit

Permalink
#274 Refactored effect applying after skeletal mesh change
Browse files Browse the repository at this point in the history
  • Loading branch information
xthebat committed May 1, 2024
1 parent 66b0bce commit 45c0991
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 69 deletions.
18 changes: 3 additions & 15 deletions Source/Cloud9/Character/Components/Cloud9SkeletalMeshComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,18 @@ void UCloud9SkeletalMeshComponent::SetSkeletalMesh(USkeletalMesh* NewMesh, bool
| ETContainer::Transform{[](let It) { return It.MaterialInterface; }}
| ETContainer::ToArray{};
MakeDynamicMaterials(Materials);
OnSkeletalMeshChanged.Broadcast(bReinitPose);
}

void UCloud9SkeletalMeshComponent::MakeDynamicMaterials(const TArray<UMaterialInterface*>& Materials)
{
// Material to copy dynamic properties from
var FoundMaterialToCopy = GetMaterials() | ETContainer::Find{
[](let It) { return Cast<UMaterialInstanceDynamic>(It); }
};

var MaterialToCopy = FoundMaterialToCopy ? Cast<UMaterialInstanceDynamic>(*FoundMaterialToCopy) : nullptr;

Materials
| ETContainer::WithIndex{}
| ETContainer::Filter{[](let It) { return not Cast<UMaterialInstanceDynamic>(It.Value); }}
| ETContainer::ForEach{
[this, MaterialToCopy](let It)
[this](let It)
{
var DynamicMaterial = UMaterialInstanceDynamic::Create(It.Value, this);

if (MaterialToCopy)
{
DynamicMaterial->CopyParameterOverrides(MaterialToCopy);
}

let DynamicMaterial = UMaterialInstanceDynamic::Create(It.Value, this);
SetMaterial(It.Key, DynamicMaterial);
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "Components/SkeletalMeshComponent.h"
#include "Cloud9SkeletalMeshComponent.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSkeletalMeshChanged, bool, bReinitPose);

UCLASS()
class CLOUD9_API UCloud9SkeletalMeshComponent : public USkeletalMeshComponent
{
Expand All @@ -16,6 +18,9 @@ class CLOUD9_API UCloud9SkeletalMeshComponent : public USkeletalMeshComponent

virtual void SetSkeletalMesh(USkeletalMesh* NewMesh, bool bReinitPose) override;

UPROPERTY(BlueprintAssignable, Category=Events)
FOnSkeletalMeshChanged OnSkeletalMeshChanged;

protected:
void MakeDynamicMaterials(const TArray<UMaterialInterface*>& Materials);
};
40 changes: 25 additions & 15 deletions Source/Cloud9/Character/Effects/Cloud9CharacterEffectTrait.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,27 @@
#include "Cloud9/Tools/Macro/Common.h"
#include "Cloud9/Tools/Macro/Logging.h"

#include "Cloud9/Character/Cloud9Character.h"
#include "Cloud9/Character/Components/Cloud9EffectsComponent.h"
#include "Cloud9/Character/Components/Cloud9SkeletalMeshComponent.h"

bool UCloud9CharacterEffectTrait::IsExtinguished_Implementation() const { return true; }

void UCloud9CharacterEffectTrait::OnApply_Implementation() {}
void UCloud9CharacterEffectTrait::OnApply_Implementation()
{
let Character = GetCharacter();
let MeshComponent = Cast<UCloud9SkeletalMeshComponent>(Character->GetMesh());
CheckIsValid(MeshComponent, Error, "SkeletalMeshComponent is invalid");
MeshComponent->OnSkeletalMeshChanged.AddDynamic(this, &UCloud9CharacterEffectTrait::OnSkeletalMeshChanged);
}

void UCloud9CharacterEffectTrait::OnRemove_Implementation() {}
void UCloud9CharacterEffectTrait::OnRemove_Implementation()
{
let Character = GetCharacter();
let MeshComponent = Cast<UCloud9SkeletalMeshComponent>(Character->GetMesh());
CheckIsValid(MeshComponent, Error, "SkeletalMeshComponent is invalid");
MeshComponent->OnSkeletalMeshChanged.RemoveDynamic(this, &UCloud9CharacterEffectTrait::OnSkeletalMeshChanged);
}

bool UCloud9CharacterEffectTrait::CanApply_Implementation() const { return true; }

Expand All @@ -23,22 +37,18 @@ void UCloud9CharacterEffectTrait::OnTick_Implementation(float DeltaSeconds) {}

void UCloud9CharacterEffectTrait::OnApplyDamage_Implementation(float Damage) {}

const UCloud9EffectsComponent* UCloud9CharacterEffectTrait::GetContainer() const
void UCloud9CharacterEffectTrait::OnSkeletalMeshChanged_Implementation(bool bReinitPose) {}

ACloud9Character* UCloud9CharacterEffectTrait::GetCharacter() const
{
let MyOuter = GetOuter();

if (not IsValid(MyOuter))
{
log(Fatal, "Effect outer parent object wasn't specified");
return nullptr;
}
CheckIsValid(MyOuter, Fatal, "Effect outer parent object wasn't specified", nullptr);

let Container = Cast<UCloud9EffectsComponent>(MyOuter);
if (not IsValid(Container))
{
log(Fatal, "Effect outer parent object is invalid");
return nullptr;
}
CheckIsValid(Container, Fatal, "Outer parent object is invalid", nullptr);

let Character = Container->GetOwner<ACloud9Character>();
CheckIsValid(Character, Fatal, "Owner is invalid", nullptr);

return Container;
return Character;
}
8 changes: 7 additions & 1 deletion Source/Cloud9/Character/Effects/Cloud9CharacterEffectTrait.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "Cloud9CharacterEffectTrait.generated.h"

class ACloud9Character;
class UCloud9EffectsComponent;

UCLASS(Abstract, BlueprintType, Blueprintable, meta=(BlueprintSpawnableComponent))
Expand Down Expand Up @@ -39,6 +40,9 @@ class CLOUD9_API UCloud9CharacterEffectTrait : public UObject
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void OnApplyDamage(float Damage);

UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void OnSkeletalMeshChanged(bool bReinitPose);

virtual bool IsExtinguished_Implementation() const;

virtual void OnApply_Implementation();
Expand All @@ -55,6 +59,8 @@ class CLOUD9_API UCloud9CharacterEffectTrait : public UObject

virtual void OnApplyDamage_Implementation(float Damage);

virtual void OnSkeletalMeshChanged_Implementation(bool bReinitPose);

protected:
const UCloud9EffectsComponent* GetContainer() const;
ACloud9Character* GetCharacter() const;
};
80 changes: 43 additions & 37 deletions Source/Cloud9/Character/Effects/Cloud9CharacterShieldEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,46 @@

#include "Cloud9CharacterShieldEffect.h"

#include "Cloud9/Character/Cloud9Character.h"
#include "Cloud9/Tools/Extensions/TContainer.h"
#include "Cloud9/Character/Components/Cloud9EffectsComponent.h"
#include "Cloud9/Character/Cloud9Character.h"
#include "Cloud9/Character/Components/Cloud9HealthComponent.h"

const FName UCloud9CharacterShieldEffect::ShieldEnableName = TEXT("Shield Enabled");
const FName UCloud9CharacterShieldEffect::ShieldReflectName = TEXT("Shield Reflect");
const FName UCloud9CharacterShieldEffect::ShieldPowerName = TEXT("Shield Power");
const FName UCloud9CharacterShieldEffect::ShieldColorName = TEXT("Shield Color");

void UCloud9CharacterShieldEffect::ToggleEffect(bool IsEnabled) const
void UCloud9CharacterShieldEffect::ToggleEffect(bool NewState)
{
let Character = GetContainer()->GetOwner<ACloud9Character>();

if (not IsValid(Character))
{
log(Error, "[Effect='%s'] Owner is invalid", *GetName());
return;
}

IsEnabled = NewState;
let Character = GetCharacter();
let HealthComponent = Character->GetHealthComponent();
if (not IsValid(HealthComponent))
{
log(Error, "[Effect='%s'] Character HealthComponent is invalid", *GetName());
return;
}

HealthComponent->SetIsInvulnerable(IsEnabled);
CheckIsValid(HealthComponent, Error, "HealthComponent is invalid");
HealthComponent->SetIsInvulnerable(NewState);
ToggleVisual(NewState);
}

if (let Mesh = Character->GetMesh(); IsValid(Mesh))
{
Mesh->GetMaterials()
| ETContainer::Transform{[](let It) { return Cast<UMaterialInstanceDynamic>(It); }}
| ETContainer::Filter{[](let It) { return IsValid(It); }}
| ETContainer::ForEach{
[this, IsEnabled](let It)
void UCloud9CharacterShieldEffect::ToggleVisual(bool NewState)
{
let Character = GetCharacter();
let MeshComponent = Character->GetMesh();
CheckIsValid(MeshComponent, Error, "MeshComponent is invalid");
MeshComponent->GetMaterials()
| ETContainer::Transform{[](let It) { return Cast<UMaterialInstanceDynamic>(It); }}
| ETContainer::Filter{[](let It) { return IsValid(It); }}
| ETContainer::ForEach{
[this, NewState](let It)
{
if (NewState)
{
if (IsEnabled)
{
It->SetScalarParameterValue(ShieldReflectName, Reflect);
It->SetScalarParameterValue(ShieldPowerName, Power);
It->SetVectorParameterValue(ShieldColorName, Color);
}

It->SetScalarParameterValue(ShieldEnableName, IsEnabled);
It->SetScalarParameterValue(ShieldReflectName, Reflect);
It->SetScalarParameterValue(ShieldPowerName, Power);
It->SetVectorParameterValue(ShieldColorName, Color);
}
};
}

It->SetScalarParameterValue(ShieldEnableName, NewState);
}
};
}

UCloud9CharacterShieldEffect::UCloud9CharacterShieldEffect()
Expand All @@ -60,13 +52,22 @@ UCloud9CharacterShieldEffect::UCloud9CharacterShieldEffect()
Power = 10.0f;
Reflect = 0.004f;
ElapsedTime = 0.0f;
IsEnabled = false;
}

bool UCloud9CharacterShieldEffect::IsExtinguished_Implementation() const { return ElapsedTime >= Duration; }

void UCloud9CharacterShieldEffect::OnApply_Implementation() { ToggleEffect(true); }
void UCloud9CharacterShieldEffect::OnApply_Implementation()
{
Super::OnApply_Implementation();
ToggleEffect(true);
}

void UCloud9CharacterShieldEffect::OnRemove_Implementation() { ToggleEffect(false); }
void UCloud9CharacterShieldEffect::OnRemove_Implementation()
{
Super::OnRemove_Implementation();
ToggleEffect(false);
}

bool UCloud9CharacterShieldEffect::CanApply_Implementation() const
{
Expand All @@ -77,3 +78,8 @@ bool UCloud9CharacterShieldEffect::CanApply_Implementation() const
bool UCloud9CharacterShieldEffect::CanTick_Implementation() const { return true; }

void UCloud9CharacterShieldEffect::OnTick_Implementation(float DeltaSeconds) { ElapsedTime += DeltaSeconds; }

void UCloud9CharacterShieldEffect::OnSkeletalMeshChanged_Implementation(bool bReinitPose)
{
ToggleVisual(IsEnabled);
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class CLOUD9_API UCloud9CharacterShieldEffect : public UCloud9CharacterEffectTra
UPROPERTY(BlueprintReadOnly, Category=Implementation)
float ElapsedTime;

UPROPERTY(BlueprintReadOnly, Category=Implementation)
bool IsEnabled;

virtual bool IsExtinguished_Implementation() const override;

virtual void OnApply_Implementation() override;
Expand All @@ -51,6 +54,10 @@ class CLOUD9_API UCloud9CharacterShieldEffect : public UCloud9CharacterEffectTra

virtual void OnTick_Implementation(float DeltaSeconds) override;

virtual void OnSkeletalMeshChanged_Implementation(bool bReinitPose) override;

private:
void ToggleEffect(bool IsEnabled) const;
void ToggleEffect(bool NewState);

void ToggleVisual(bool NewState);
};
9 changes: 9 additions & 0 deletions Source/Cloud9/Tools/Macro/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,12 @@
// Simplification of const auto/auto
#define let const auto
#define var auto

#define CheckIsValid(What, Severity, Message, ...) \
do { \
if (not IsValid(What)) \
{ \
log(Severity, Message); \
return __VA_ARGS__; \
} \
} while(false);

0 comments on commit 45c0991

Please sign in to comment.