第一次提交
This commit is contained in:
@@ -0,0 +1,289 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
|
||||
#include "Feedback/GES_ContextEffectsSubsystem.h"
|
||||
|
||||
#include "Feedback/GES_ContextEffectsLibrary.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "NiagaraFunctionLibrary.h"
|
||||
#include "NiagaraSystem.h"
|
||||
|
||||
#include UE_INLINE_GENERATED_CPP_BY_NAME(GES_ContextEffectsSubsystem)
|
||||
|
||||
class AActor;
|
||||
class UAudioComponent;
|
||||
class UNiagaraSystem;
|
||||
class USceneComponent;
|
||||
class USoundBase;
|
||||
|
||||
void UGES_ContextEffectsSubsystem::SpawnContextEffects(UObject* WorldContextObject, TSoftObjectPtr<UGES_ContextEffectsLibrary> EffectsLibrary, FGES_SpawnContextEffectsInput Input,
|
||||
FGES_SpawnContextEffectsOutput& Output)
|
||||
{
|
||||
if (WorldContextObject == nullptr || WorldContextObject->GetWorld() == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (EffectsLibrary.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare Arrays for Sounds and Niagara Systems
|
||||
TArray<USoundBase*> TotalSounds;
|
||||
TArray<UNiagaraSystem*> TotalNiagaraSystems;
|
||||
TArray<UParticleSystem*> TotalParticleSystems;
|
||||
|
||||
// Cycle through Effect Libraries
|
||||
if (UGES_ContextEffectsLibrary* EffectLibrary = EffectsLibrary.LoadSynchronous())
|
||||
{
|
||||
if (EffectLibrary && EffectLibrary->GetContextEffectsLibraryLoadState() == EGES_ContextEffectsLibraryLoadState::Unloaded)
|
||||
{
|
||||
// Sync load effects
|
||||
EffectLibrary->LoadEffects();
|
||||
}
|
||||
|
||||
// Check if the Effect Library is valid and data Loaded
|
||||
if (EffectLibrary->GetContextEffectsLibraryLoadState() == EGES_ContextEffectsLibraryLoadState::Loaded)
|
||||
{
|
||||
// Set up local list of Sounds and Niagara Systems
|
||||
TArray<USoundBase*> Sounds;
|
||||
TArray<UNiagaraSystem*> NiagaraSystems;
|
||||
TArray<UParticleSystem*> ParticleSystems;
|
||||
|
||||
// Get Sounds and Niagara Systems
|
||||
EffectLibrary->GetEffects(Input.EffectName, Input.SourceContext, Input.TargetContext, Sounds, NiagaraSystems, ParticleSystems);
|
||||
|
||||
// Append to accumulating array
|
||||
TotalSounds.Append(Sounds);
|
||||
TotalNiagaraSystems.Append(NiagaraSystems);
|
||||
TotalParticleSystems.Append(ParticleSystems);
|
||||
}
|
||||
}
|
||||
|
||||
// Cycle through found Sounds
|
||||
for (USoundBase* Sound : TotalSounds)
|
||||
{
|
||||
if (Input.bAttached)
|
||||
{
|
||||
// Spawn Sounds Attached, add Audio Component to List of ACs
|
||||
UAudioComponent* AudioComponent = UGameplayStatics::SpawnSoundAttached(Sound, Input.ComponentToAttach, Input.Bone, Input.LocationOffset, Input.RotationOffset,
|
||||
EAttachLocation::KeepRelativeOffset,
|
||||
false, Input.AudioVolume, Input.AudioPitch, 0.0f, nullptr, nullptr, true);
|
||||
Output.AudioComponents.Add(AudioComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
UAudioComponent* AudioComponent = UGameplayStatics::SpawnSoundAtLocation(WorldContextObject, Sound, Input.Location, Input.Rotation, Input.AudioVolume, Input.AudioPitch, 0.0f, nullptr,
|
||||
nullptr, true);
|
||||
Output.AudioComponents.Add(AudioComponent);
|
||||
}
|
||||
}
|
||||
|
||||
// Cycle through found Niagara Systems
|
||||
for (UNiagaraSystem* NiagaraSystem : TotalNiagaraSystems)
|
||||
{
|
||||
if (Input.bAttached)
|
||||
{
|
||||
// Spawn Niagara Systems Attached, add Niagara Component to List of NCs
|
||||
UNiagaraComponent* NiagaraComponent = UNiagaraFunctionLibrary::SpawnSystemAttached(NiagaraSystem, Input.ComponentToAttach, Input.Bone, Input.LocationOffset,
|
||||
Input.RotationOffset, Input.VFXScale, EAttachLocation::KeepRelativeOffset, true,
|
||||
ENCPoolMethod::None,
|
||||
true,
|
||||
true);
|
||||
Output.NiagaraComponents.Add(NiagaraComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
UNiagaraComponent* NiagaraComponent = UNiagaraFunctionLibrary::SpawnSystemAtLocation(WorldContextObject, NiagaraSystem, Input.Location,
|
||||
Input.Rotation, Input.VFXScale, true, true,
|
||||
ENCPoolMethod::None, true);
|
||||
|
||||
Output.NiagaraComponents.Add(NiagaraComponent);
|
||||
}
|
||||
}
|
||||
|
||||
// Cycle through found Particle Systems
|
||||
for (UParticleSystem* ParticleSystem : TotalParticleSystems)
|
||||
{
|
||||
if (Input.bAttached)
|
||||
{
|
||||
// Spawn Particle Systems Attached, add Niagara Component to List of NCs
|
||||
UParticleSystemComponent* ParticleComponent = UGameplayStatics::SpawnEmitterAttached(ParticleSystem, Input.ComponentToAttach, Input.Bone, Input.LocationOffset,
|
||||
Input.RotationOffset, Input.VFXScale, EAttachLocation::KeepRelativeOffset, true,
|
||||
EPSCPoolMethod::None,
|
||||
true);
|
||||
Output.ParticlesComponents.Add(ParticleComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
UParticleSystemComponent* ParticleComponent = UGameplayStatics::SpawnEmitterAtLocation(WorldContextObject, ParticleSystem, Input.Location, Input.Rotation, Input.VFXScale, true,
|
||||
EPSCPoolMethod::None, true);
|
||||
Output.ParticlesComponents.Add(ParticleComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UGES_ContextEffectsSubsystem::SpawnContextEffectsExt(const AActor* SpawningActor, const FGES_SpawnContextEffectsInput& Input, FGES_SpawnContextEffectsOutput& Output)
|
||||
{
|
||||
// First determine if this Actor has a matching Set of Libraries
|
||||
if (TObjectPtr<UGES_ContextEffectsSet>* EffectsLibrariesSetPtr = ActiveActorEffectsMap.Find(SpawningActor))
|
||||
{
|
||||
// Validate the pointers from the Map Find
|
||||
if (UGES_ContextEffectsSet* EffectsLibraries = *EffectsLibrariesSetPtr)
|
||||
{
|
||||
// Prepare Arrays for Sounds and Niagara Systems
|
||||
TArray<USoundBase*> TotalSounds;
|
||||
TArray<UNiagaraSystem*> TotalNiagaraSystems;
|
||||
TArray<UParticleSystem*> TotalParticleSystems;
|
||||
|
||||
// Cycle through Effect Libraries
|
||||
for (UGES_ContextEffectsLibrary* EffectLibrary : EffectsLibraries->ContextEffectsLibraries)
|
||||
{
|
||||
// Check if the Effect Library is valid and data Loaded
|
||||
if (EffectLibrary && EffectLibrary->GetContextEffectsLibraryLoadState() == EGES_ContextEffectsLibraryLoadState::Loaded)
|
||||
{
|
||||
// Set up local list of Sounds and Niagara Systems
|
||||
TArray<USoundBase*> Sounds;
|
||||
TArray<UNiagaraSystem*> NiagaraSystems;
|
||||
TArray<UParticleSystem*> ParticleSystems;
|
||||
|
||||
// Get Sounds and Niagara Systems
|
||||
EffectLibrary->GetEffects(Input.EffectName, Input.SourceContext, Input.TargetContext, Sounds, NiagaraSystems, ParticleSystems);
|
||||
|
||||
// Append to accumulating array
|
||||
TotalSounds.Append(Sounds);
|
||||
TotalNiagaraSystems.Append(NiagaraSystems);
|
||||
TotalParticleSystems.Append(ParticleSystems);
|
||||
}
|
||||
else if (EffectLibrary && EffectLibrary->GetContextEffectsLibraryLoadState() == EGES_ContextEffectsLibraryLoadState::Unloaded)
|
||||
{
|
||||
// Else load effects
|
||||
EffectLibrary->LoadEffects();
|
||||
}
|
||||
}
|
||||
|
||||
// Cycle through found Sounds
|
||||
for (USoundBase* Sound : TotalSounds)
|
||||
{
|
||||
if (Input.bAttached)
|
||||
{
|
||||
// Spawn Sounds Attached, add Audio Component to List of ACs
|
||||
UAudioComponent* AudioComponent = UGameplayStatics::SpawnSoundAttached(Sound, Input.ComponentToAttach, Input.Bone, Input.LocationOffset, Input.RotationOffset,
|
||||
EAttachLocation::KeepRelativeOffset,
|
||||
false, Input.AudioVolume, Input.AudioPitch, 0.0f, nullptr, nullptr, true);
|
||||
Output.AudioComponents.Add(AudioComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
UAudioComponent* AudioComponent = UGameplayStatics::SpawnSoundAtLocation(SpawningActor, Sound, Input.Location, Input.Rotation, Input.AudioVolume, Input.AudioPitch, 0.0f, nullptr,
|
||||
nullptr, true);
|
||||
Output.AudioComponents.Add(AudioComponent);
|
||||
}
|
||||
}
|
||||
|
||||
// Cycle through found Niagara Systems
|
||||
for (UNiagaraSystem* NiagaraSystem : TotalNiagaraSystems)
|
||||
{
|
||||
if (Input.bAttached)
|
||||
{
|
||||
// Spawn Niagara Systems Attached, add Niagara Component to List of NCs
|
||||
UNiagaraComponent* NiagaraComponent = UNiagaraFunctionLibrary::SpawnSystemAttached(NiagaraSystem, Input.ComponentToAttach, Input.Bone, Input.LocationOffset,
|
||||
Input.RotationOffset, Input.VFXScale, EAttachLocation::KeepRelativeOffset, true,
|
||||
ENCPoolMethod::None,
|
||||
true,
|
||||
true);
|
||||
Output.NiagaraComponents.Add(NiagaraComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
UNiagaraComponent* NiagaraComponent = UNiagaraFunctionLibrary::SpawnSystemAtLocation(SpawningActor, NiagaraSystem, Input.Location,
|
||||
Input.Rotation, Input.VFXScale, true, true,
|
||||
ENCPoolMethod::None, true);
|
||||
|
||||
Output.NiagaraComponents.Add(NiagaraComponent);
|
||||
}
|
||||
}
|
||||
|
||||
// Cycle through found Particle Systems
|
||||
for (UParticleSystem* ParticleSystem : TotalParticleSystems)
|
||||
{
|
||||
if (Input.bAttached)
|
||||
{
|
||||
// Spawn Particle Systems Attached, add Niagara Component to List of NCs
|
||||
UParticleSystemComponent* ParticleComponent = UGameplayStatics::SpawnEmitterAttached(ParticleSystem, Input.ComponentToAttach, Input.Bone, Input.LocationOffset,
|
||||
Input.RotationOffset, Input.VFXScale, EAttachLocation::KeepRelativeOffset, true,
|
||||
EPSCPoolMethod::None,
|
||||
true);
|
||||
Output.ParticlesComponents.Add(ParticleComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
UParticleSystemComponent* ParticleComponent = UGameplayStatics::SpawnEmitterAtLocation(SpawningActor, ParticleSystem, Input.Location, Input.Rotation, Input.VFXScale, true,
|
||||
EPSCPoolMethod::None, true);
|
||||
Output.ParticlesComponents.Add(ParticleComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UGES_ContextEffectsSubsystem::GetContextFromSurfaceType(
|
||||
TEnumAsByte<EPhysicalSurface> PhysicalSurface, FGameplayTag& Context)
|
||||
{
|
||||
// Get Project Settings
|
||||
if (const UGES_ContextEffectsSettings* ProjectSettings = GetDefault<UGES_ContextEffectsSettings>())
|
||||
{
|
||||
// Find which Gameplay Tag the Surface Type is mapped to
|
||||
if (const FGameplayTag* GameplayTagPtr = ProjectSettings->SurfaceTypeToContextMap.Find(PhysicalSurface))
|
||||
{
|
||||
Context = *GameplayTagPtr;
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if Context is Valid
|
||||
return Context.IsValid();
|
||||
}
|
||||
|
||||
void UGES_ContextEffectsSubsystem::LoadAndAddContextEffectsLibraries(AActor* OwningActor,
|
||||
TSet<TSoftObjectPtr<UGES_ContextEffectsLibrary>> ContextEffectsLibraries)
|
||||
{
|
||||
// Early out if Owning Actor is invalid or if the associated Libraries is 0 (or less)
|
||||
if (OwningActor == nullptr || ContextEffectsLibraries.Num() <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new Context Effect Set
|
||||
UGES_ContextEffectsSet* EffectsLibrariesSet = NewObject<UGES_ContextEffectsSet>(this);
|
||||
|
||||
// Cycle through Libraries getting Soft Obj Refs
|
||||
for (const TSoftObjectPtr<UGES_ContextEffectsLibrary>& ContextEffectSoftObj : ContextEffectsLibraries)
|
||||
{
|
||||
// Load Library Assets from Soft Obj refs
|
||||
// TODO Support Async Loading of Asset Data
|
||||
if (UGES_ContextEffectsLibrary* EffectsLibrary = ContextEffectSoftObj.LoadSynchronous())
|
||||
{
|
||||
// Call load on valid Libraries
|
||||
EffectsLibrary->LoadEffects();
|
||||
|
||||
// Add new library to Set
|
||||
EffectsLibrariesSet->ContextEffectsLibraries.Add(EffectsLibrary);
|
||||
}
|
||||
}
|
||||
|
||||
// Update Active Actor Effects Map
|
||||
ActiveActorEffectsMap.Emplace(OwningActor, EffectsLibrariesSet);
|
||||
}
|
||||
|
||||
void UGES_ContextEffectsSubsystem::UnloadAndRemoveContextEffectsLibraries(AActor* OwningActor)
|
||||
{
|
||||
// Early out if Owning Actor is invalid
|
||||
if (OwningActor == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove ref from Active Actor/Effects Set Map
|
||||
ActiveActorEffectsMap.Remove(OwningActor);
|
||||
}
|
||||
Reference in New Issue
Block a user