Skip to content

Commit

Permalink
#248 Fixed dynamic materials behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
xthebat committed Apr 29, 2024
1 parent 8d86201 commit e0e7880
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 14 deletions.
32 changes: 18 additions & 14 deletions Source/Cloud9/Character/Cloud9Character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "Components/Cloud9HealthComponent.h"
#include "Components/Cloud9AnimationComponent.h"
#include "Components/Cloud9EffectsComponent.h"
#include "Components/Cloud9SkeletalMeshComponent.h"

const FName ACloud9Character::SpringArmComponentName = TEXT("CameraBoom");
const FName ACloud9Character::CameraComponentName = TEXT("TopDownCamera");
Expand All @@ -58,7 +59,9 @@ const FName ACloud9Character::AnimationComponentName = TEXT("AnimationComponent"
const FName ACloud9Character::WidgetInteractionComponentName = TEXT("WidgetInteractionComponent");

ACloud9Character::ACloud9Character(const FObjectInitializer& ObjectInitializer) : Super(
ObjectInitializer.SetDefaultSubobjectClass<UCloud9CharacterMovement>(CharacterMovementComponentName))
ObjectInitializer
.SetDefaultSubobjectClass<UCloud9CharacterMovement>(CharacterMovementComponentName)
.SetDefaultSubobjectClass<UCloud9SkeletalMeshComponent>(MeshComponentName))
{
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
Expand Down Expand Up @@ -102,9 +105,9 @@ ACloud9Character::ACloud9Character(const FObjectInitializer& ObjectInitializer)
);
CursorToWorld->SetRelativeRotation({CrosshairRotationPitch, 0.0, 0.0f});

EffectsComponent = CreateDefaultSubobject<UCloud9EffectsComponent>(EffectsComponentName);
InventoryComponent = CreateDefaultSubobject<UCloud9InventoryComponent>(InventoryComponentName);
HealthComponent = CreateDefaultSubobject<UCloud9HealthComponent>(HealthComponentName);
EffectsComponent = CreateDefaultSubobject<UCloud9EffectsComponent>(EffectsComponentName);
AnimationComponent = CreateDefaultSubobject<UCloud9AnimationComponent>(AnimationComponentName);
WidgetInteractionComponent = CreateDefaultSubobject<UWidgetInteractionComponent>(WidgetInteractionComponentName);
WidgetInteractionComponent->SetupAttachment(RootComponent);
Expand All @@ -114,6 +117,7 @@ ACloud9Character::ACloud9Character(const FObjectInitializer& ObjectInitializer)
HealthComponent->OnCharacterDie.AddDynamic(this, &ACloud9Character::OnCharacterDie);

Score = 0;
bIsPlayer = false;

// Activate ticking to update the cursor every frame.
PrimaryActorTick.bCanEverTick = true;
Expand Down Expand Up @@ -281,7 +285,7 @@ UCloud9AnimationComponent* ACloud9Character::GetAnimationComponent() const { ret
// ReSharper disable once CppMemberFunctionMayBeConst
UCloud9CharacterEffectTrait* ACloud9Character::AddCharacterEffect(TSubclassOf<UCloud9CharacterEffectTrait> EffectClass)
{
return EffectsComponent->AddEffect(EffectClass);
return IsValid(EffectClass) ? EffectsComponent->AddEffect(EffectClass) : nullptr;
}

// ReSharper disable once CppMemberFunctionMayBeConst
Expand Down Expand Up @@ -426,17 +430,6 @@ void ACloud9Character::OnConstruction(const FTransform& Transform)
MyMesh->bAffectDynamicIndirectLighting = true;
MyMesh->SetCollisionProfileName(COLLISION_PROFILE_HITBOX);

MyMesh->GetMaterials()
| ETContainer::WithIndex{}
| ETContainer::Filter{[](let It) { return not Cast<UMaterialInstanceDynamic>(It.Value); }}
| ETContainer::ForEach{
[&MyMesh](let It)
{
let Dynamic = UMaterialInstanceDynamic::Create(It.Value, MyMesh);
MyMesh->SetMaterial(It.Key, Dynamic);
}
};

#ifdef USE_PHYSICAL_ASSET_HITBOX
// TODO: Make same hit boxes for all character's type - currently disabled
let PhysicsAsset = MyMesh->GetPhysicsAsset();
Expand Down Expand Up @@ -473,10 +466,21 @@ void ACloud9Character::BeginPlay()

if (not IsPlayerControlled())
{
bIsPlayer = false;
CursorToWorld->Deactivate();
TopDownCameraComponent->Deactivate();
CameraBoom->Deactivate();
}
else
{
bIsPlayer = true;
}
}

void ACloud9Character::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
log(Error, "[Character='%s'] EndPlay IsPlayer=%d", *GetName(), bIsPlayer);
}

void ACloud9Character::Tick(float DeltaSeconds)
Expand Down
8 changes: 8 additions & 0 deletions Source/Cloud9/Character/Cloud9Character.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class ACloud9Character : public ACharacter

virtual void OnConstruction(const FTransform& Transform) override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual void Tick(float DeltaSeconds) override;

/** Returns TopDownCameraComponent subobject **/
Expand Down Expand Up @@ -208,6 +209,13 @@ class ACloud9Character : public ACharacter
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Effects, meta=(AllowPrivateAccess))
UCloud9EffectsComponent* EffectsComponent;

/**
* Cache variable is this Character a player or a bot
* TODO: Looks like on EndPlay method IsPlayerControlled() returns wrong value
*/
UPROPERTY()
bool bIsPlayer;

/** Current number of frags made by character */
UPROPERTY(BlueprintReadOnly, Category=State, meta=(AllowPrivateAccess))
int Score;
Expand Down
34 changes: 34 additions & 0 deletions Source/Cloud9/Character/Components/Cloud9SkeletalMeshComponent.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) 2024 Alexei Gladkikh

#include "Cloud9SkeletalMeshComponent.h"

#include "Cloud9/Tools/Extensions/TContainer.h"

void UCloud9SkeletalMeshComponent::BeginPlay()
{
Super::BeginPlay();
MakeDynamicMaterials(GetMaterials());
}

void UCloud9SkeletalMeshComponent::SetSkeletalMesh(USkeletalMesh* NewMesh, bool bReinitPose)
{
Super::SetSkeletalMesh(NewMesh, bReinitPose);
let Materials = NewMesh->GetMaterials()
| ETContainer::Transform{[](let It) { return It.MaterialInterface; }}
| ETContainer::ToArray{};
MakeDynamicMaterials(Materials);
}

void UCloud9SkeletalMeshComponent::MakeDynamicMaterials(const TArray<UMaterialInterface*>& Materials)
{
Materials
| ETContainer::WithIndex{}
| ETContainer::Filter{[](let It) { return not Cast<UMaterialInstanceDynamic>(It.Value); }}
| ETContainer::ForEach{
[this](let It)
{
let DynamicMaterial = UMaterialInstanceDynamic::Create(It.Value, this);
SetMaterial(It.Key, DynamicMaterial);
}
};
}
21 changes: 21 additions & 0 deletions Source/Cloud9/Character/Components/Cloud9SkeletalMeshComponent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) 2024 Alexei Gladkikh

#pragma once

#include "CoreMinimal.h"
#include "Components/SkeletalMeshComponent.h"
#include "Cloud9SkeletalMeshComponent.generated.h"

UCLASS()
class CLOUD9_API UCloud9SkeletalMeshComponent : public USkeletalMeshComponent
{
GENERATED_BODY()

public:
virtual void BeginPlay() override;

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

protected:
void MakeDynamicMaterials(const TArray<UMaterialInterface*>& Materials);
};

0 comments on commit e0e7880

Please sign in to comment.