Interactable modificator cleanup, modificator move

This commit is contained in:
Oleg Petruny 2024-06-06 22:59:25 +02:00
parent 15244e3936
commit 8856ce7dd8
46 changed files with 690 additions and 123 deletions

View File

@ -49,6 +49,7 @@ r.ReflectionMethod=1
r.Shadow.Virtual.Enable=1
r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True
r.DefaultFeature.MotionBlur=False
r.CustomDepth=3
[/Script/WorldPartitionEditor.WorldPartitionEditorSettings]
CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet'

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,6 @@
{
"FileVersion": 3,
"EngineAssociation": "5.4",
"EngineAssociation": "{42CC8720-4DDD-EF11-BECE-CEBF292119D8}",
"Category": "",
"Description": "",
"Modules": [

View File

@ -19,6 +19,7 @@ public class Lost_Edge : ModuleRules {
// UE_LOG(LogTemp, Log, TEXT("capture: %s"), (capture ? TEXT("true") : TEXT("false")));
// GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("1"));
// GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("Rescaled: %f"), scale));
// DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, PrimaryComponentTick.TickInterval, 0, 0.1f);
}
}

View File

@ -10,6 +10,7 @@
#include "InputMappingContext.h"
#include "Kismet/GameplayStatics.h"
#include "CustomGameInstanceBase.h"
#include "CustomGameUserSettings.h"
#include "MainGameModeBase.h"
@ -34,18 +35,20 @@ void ACameraModeBase::BeginPlay()
camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f;
}
if(inputMapping)
if(auto PC = Cast<APlayerController>(GetController()))
{
if(auto PC = Cast<APlayerController>(GetController()))
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
{
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
if(auto GI = Cast<UCustomGameInstanceBase>(GetWorld()->GetGameInstance()))
{
inputSubsystem->ClearAllMappings();
inputSubsystem->AddMappingContext(inputMapping.LoadSynchronous(), 0);
for(auto& inputContext : GI->inputContexts)
{
inputSubsystem->AddMappingContext(inputContext.LoadSynchronous(), 0);
}
}
}
}
}
void ACameraModeBase::Tick(float DeltaTime)

View File

@ -29,14 +29,8 @@ protected:
UFUNCTION(BlueprintCallable, Category = Pawn)
void SwitchRun(bool run);
UPROPERTY(EditDefaultsOnly)
TSoftObjectPtr<class UInputMappingContext> inputMapping;
UPROPERTY(EditDefaultsOnly)
float moveSpeed = 200;
UPROPERTY(EditDefaultsOnly)
float runSpeedMultiplier = 4;
private:
};

View File

@ -4,19 +4,31 @@
#include "CustomGameInstanceBase.h"
#include "EnhancedInputLibrary.h"
#include "EnhancedInputSubsystems.h"
#include "InputMappingContext.h"
#include "Kismet/GameplayStatics.h"
#include "CustomGameUserSettings.h"
#include "Interactable/Activators/InCameraInteractableActivator.h"
#include "Interactable/Activators/RaycastInteractableActivator.h"
#include "Interactable/Modificators/ActivateInteractableModificator.h"
#include "Interactable/Modificators/SawInteractableModificator.h"
void UCustomGameInstanceBase::Init()
{
UGameInstance::Init();
// IN FUTURE ASSIGN FROM CONTENT LOADER MEMBER
interactionsActivators.Add(URaycastInteractableActivator::StaticClass());
interactionsActivators.Add(UInCameraInteractableActivator::StaticClass());
UGameInstance::Init();
for(auto& modificator : interactionsModificators)
{
if(modificator.GetDefaultObject()->GetMappingContext())
{
inputContexts.Add(modificator.GetDefaultObject()->GetMappingContext());
}
}
ApplyMouseSettings();
}
@ -25,27 +37,49 @@ void UCustomGameInstanceBase::ApplyMouseSettings()
{
if(auto gameSettings = UCustomGameUserSettings::GetCustomGameUserSettings())
{
for(auto context_it = defaultInputContexts.begin(); context_it != defaultInputContexts.end(); ++context_it)
for(auto& context : inputContexts)
{
auto& mappings = (*context_it).LoadSynchronous()->GetMappings();
for(auto mapping_it = mappings.begin(); mapping_it != mappings.end(); ++mapping_it)
if(!context.LoadSynchronous())
continue;
for(auto& mapping : context.LoadSynchronous()->GetMappings())
{
if((*mapping_it).Key == EKeys::Mouse2D)
if(mapping.Key == EKeys::Mouse2D)
{
for(auto modifiers_it = (*mapping_it).Modifiers.begin(); modifiers_it != (*mapping_it).Modifiers.end(); ++modifiers_it)
for(auto& modifier : mapping.Modifiers)
{
if(auto negate_modifier = Cast<UInputModifierNegate>(*modifiers_it))
if(auto negate_modifier = Cast<UInputModifierNegate>(modifier))
{
negate_modifier->bY = !gameSettings->bMouseInverted;
}
if(auto scalar_modifier = Cast<UInputModifierScalar>(*modifiers_it))
if(auto scalar_modifier = Cast<UInputModifierScalar>(modifier))
{
scalar_modifier->Scalar = FVector{ gameSettings->GetMouseSensetivity() * 0.5 };
}
}
}
}
UEnhancedInputLibrary::RequestRebuildControlMappingsUsingContext((*context_it).LoadSynchronous());
UEnhancedInputLibrary::RequestRebuildControlMappingsUsingContext(context.LoadSynchronous());
}
}
}
void UCustomGameInstanceBase::AppendInteractableModificatorClass(TSubclassOf<class UInteractableModificator> modificator)
{
bool alreadyPresent = false;
interactionsModificators.Add(modificator, &alreadyPresent);
if(!alreadyPresent)
{
if(auto IC = modificator.GetDefaultObject()->GetMappingContext())
{
inputContexts.Add(IC);
if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
{
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
{
inputSubsystem->AddMappingContext(IC, 0);
}
}
}
}
}

View File

@ -18,10 +18,13 @@ public:
UFUNCTION(BlueprintCallable, Category = Settings)
void ApplyMouseSettings();
UPROPERTY(EditDefaultsOnly)
TArray<TSubclassOf<class UInteractableActivator>> interactionsActivators;
void AppendInteractableModificatorClass(TSubclassOf<class UInteractableModificator> modificator);
protected:
UPROPERTY(EditDefaultsOnly)
TArray<TSoftObjectPtr<class UInputMappingContext>> defaultInputContexts;
TSet<TSubclassOf<class UInteractableActivator>> interactionsActivators;
TSet<TSubclassOf<class UInteractableModificator>> interactionsModificators;
UPROPERTY(EditDefaultsOnly)
TSet<TSoftObjectPtr<class UInputMappingContext>> inputContexts;
};

View File

@ -33,7 +33,7 @@ protected:
EActivatorType activatorType;
UPROPERTY(EditDefaultsOnly)
float scanDistance = 200;
float scanDistance = 250;
class UWorld* world;
class APlayerBase* player;

View File

@ -47,6 +47,7 @@ UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitialize
PostProcessBlendWeight = 1;
auto ppMaterial = LoadObject<UMaterial>(this, TEXT("/Game/Misc/Interactables/M_InteractableScreencapturerPP"));
PostProcessSettings.AddBlendable(ppMaterial, 1.0f);
PostProcessSettings.Sharpen = 0;
bUseCustomProjectionMatrix = false;
bAlwaysPersistRenderingState = true;
@ -81,7 +82,7 @@ void UInteractableScreenCapturer::TickComponent(float DeltaTime, enum ELevelTick
USceneCaptureComponent2D::TickComponent(DeltaTime, TickType, ThisTickFunction);
CaptureScene();
GetCameraView(DeltaTime, _view);
//Process();
Process();
}
break;
default:
@ -261,15 +262,15 @@ void UInteractableScreenCapturer::Process()
}
}
#ifdef INTERACTABLE_ACTIVATOR_DEBUG
DrawDebugLine(world, startLocation, endLocation, FColor::Green, false, tickInterval, 0, 0.5f);
DrawDebugLine(world, startLocation, endLocation, FColor::Green, false, tickInterval, 0, 0.1f);
#endif // INTERACTABLE_ACTIVATOR_DEBUG
}
#ifdef INTERACTABLE_ACTIVATOR_DEBUG
else
{
DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 10, 0.5f);
}
DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 10, 0.1f);
}
#endif // INTERACTABLE_ACTIVATOR_DEBUG
}
@ -277,7 +278,7 @@ void UInteractableScreenCapturer::Process()
GEngine->AddOnScreenDebugMessage(30 + (int)EActivatorType::Saw, 0.5f, FColor::Yellow, FString::Printf(TEXT("ScreenCapturer calltime: %f"), FPlatformTime::Seconds() - StartTime));
#endif // INTERACTABLE_ACTIVATOR_DEBUG
running = false;
}
}
);
}
}
}
}

View File

@ -25,8 +25,6 @@ void URaycastInteractableActivator::Scan_Implementation()
collisionChannel
);
static AInteractable* _last = nullptr;
static bool _activated = false;
if(result.bBlockingHit)
{
if(_last != result.GetActor())
@ -44,13 +42,13 @@ void URaycastInteractableActivator::Scan_Implementation()
{
interactableActivatedDelegate.Execute(interactable, activatorType);
}
}
}
}
#ifdef INTERACTABLE_ACTIVATOR_DEBUG
DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Green, false, 0.5f, 0, 0.5f);
DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Green, false, PrimaryComponentTick.TickInterval, 0, 0.1f);
#endif // INTERACTABLE_ACTIVATOR_DEBUG
}
}
else
{
if(_activated)
@ -61,10 +59,10 @@ void URaycastInteractableActivator::Scan_Implementation()
}
_activated = false;
_last = nullptr;
}
}
#ifdef INTERACTABLE_ACTIVATOR_DEBUG
DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, 0.5f, 10, 0.5f);
DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, PrimaryComponentTick.TickInterval, 10, 0.1f);
#endif // INTERACTABLE_ACTIVATOR_DEBUG
}
}
}
}

View File

@ -18,4 +18,8 @@ public:
protected:
void Scan();
virtual void Scan_Implementation() override;
private:
class AInteractable* _last = nullptr;
bool _activated = false;
};

View File

@ -6,11 +6,19 @@
#include "Kismet/GameplayStatics.h"
#include "../MainGameModeBase.h"
#include "../PlayerBase.h"
#include "../Widgets/WidgetsManager.h"
#include "Modificators/InteractableModificator.h"
int32 AInteractable::GetActivatedFlags()
{
return activated;
}
void AInteractable::BeginPlay()
{
AActor::BeginPlay();
// FOR ADRESS TO COLOR
//if(auto m = material.LoadSynchronous())
//{
@ -20,29 +28,77 @@ void AInteractable::BeginPlay()
// }
//}
TArray<UInteractableModificator*> instancedModificators;
GetComponents(instancedModificators);
uint8 activatorTypes = 0;
for(auto& modificator : instancedModificators)
{
uint8 modificatorActivatorTypes = static_cast<uint8>(modificator->GetActivatorTypes());
activatorTypes |= modificatorActivatorTypes;
switch(modificatorActivatorTypes & static_cast<uint8>(EActivatorType::Use))
{
case static_cast<uint8>(EActivatorType::Use):
modificators.Add({ EActivatorType::Use, modificator });
break;
default:
break;
}
switch(modificatorActivatorTypes & static_cast<uint8>(EActivatorType::Saw))
{
case static_cast<uint8>(EActivatorType::Saw):
modificators.Add({ EActivatorType::Saw, modificator });
break;
default:
break;
}
}
TArray<UMeshComponent*> meshes;
GetComponents(meshes);
for(auto mesh : meshes)
{
mesh->CustomDepthStencilValue = 0;
mesh->CustomDepthStencilWriteMask = ERendererStencilMask::ERSM_Default;
mesh->SetRenderCustomDepth(true);
if(activatorTypes)
{
mesh->SetCollisionProfileName(TEXT("Interactable"));
}
if(activatorTypes & static_cast<uint8>(EActivatorType::Saw))
{
mesh->CustomDepthStencilValue = 128;
mesh->CustomDepthStencilWriteMask = ERendererStencilMask::ERSM_Default;
mesh->SetRenderCustomDepth(true);
}
}
for(auto& modificatorClass : modificatorsClasses)
{
_modificators.Add(NewObject<UInteractableModificator>(this, modificatorClass));
}
if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
player = Cast<APlayerBase>(PC->GetPawn());
}
void AInteractable::_Activate(EActivatorType type)
{
#ifdef INTERACTABLE_DEBUG
GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Cyan, TEXT("Player activate: ") + this->GetName()
+ TEXT(" by: ") + StaticEnum<EActivatorType>()->GetNameByValue(static_cast<int64>(type)).ToString());
#endif // INTERACTABLE_DEBUG
if(!player)
return;
if(modificators.Num() == 0)
return;
activated |= static_cast<uint8>(type);
if(auto WM = AMainGameModeBase::GetWidgetManager())
{
for(const auto modificator : _modificators)
for(const auto& modificator : modificators)
{
WM->ShowInteractionHints(modificator);
if(static_cast<uint8>(modificator.Value->GetActivatorTypes()) & static_cast<uint8>(type))
{
WM->ShowInteractionHints(modificator.Value);
modificator.Value->Bind_Implementation(player->inputComponent);
}
}
}
@ -51,10 +107,28 @@ void AInteractable::_Activate(EActivatorType type)
void AInteractable::_Deactivate(EActivatorType type)
{
#ifdef INTERACTABLE_DEBUG
GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Magenta, TEXT("Player deactivate: ") + this->GetName()
+ TEXT(" by: ") + StaticEnum<EActivatorType>()->GetNameByValue(static_cast<int64>(type)).ToString());
#endif // INTERACTABLE_DEBUG
if(!player)
return;
if(modificators.Num() == 0)
return;
activated &= ~static_cast<uint8>(type);
if(auto WM = AMainGameModeBase::GetWidgetManager())
{
WM->HideInteractionHints(type);
for(const auto& modificator : modificators)
{
if(static_cast<uint8>(modificator.Value->GetActivatorTypes()) & static_cast<uint8>(type))
{
modificator.Value->Unbind_Implementation();
}
}
}
Deactivate_Implementation(type);

View File

@ -10,18 +10,19 @@
#define INTERACTABLE_DEBUG
//#define INTERACTABLE_ACTIVATOR_DEBUG
UENUM(BlueprintType, meta = (Bitflags))
UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
enum class EActivatorType : uint8
{
None = 0,
None = 0 UMETA(Hidden),
Use = 1 << 0,
Saw = 1 << 1,
Custom1 = 1 << 2 UMETA(DisplayName = "Custom 1"),
Custom2 = 1 << 3 UMETA(DisplayName = "Custom 2"),
Custom3 = 1 << 4 UMETA(DisplayName = "Custom 3"),
Custom4 = 1 << 5 UMETA(DisplayName = "Custom 4"),
Custom5 = 1 << 6 UMETA(DisplayName = "Custom 5"),
Custom6 = 1 << 7 UMETA(DisplayName = "Custom 6")
Collide = 1 << 2,
Custom1 = 1 << 3 UMETA(DisplayName = "Custom 1"),
Custom2 = 1 << 4 UMETA(DisplayName = "Custom 2"),
Custom3 = 1 << 5 UMETA(DisplayName = "Custom 3"),
Custom4 = 1 << 6 UMETA(DisplayName = "Custom 4"),
Custom5 = 1 << 7 UMETA(DisplayName = "Custom 5")
};
ENUM_CLASS_FLAGS(EActivatorType)
@ -31,6 +32,8 @@ class AInteractable : public AActor
GENERATED_BODY()
public:
int32 GetActivatedFlags();
void _Activate(EActivatorType type);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Activate(EActivatorType type);
@ -44,15 +47,12 @@ public:
protected:
virtual void BeginPlay() override;
UPROPERTY(BlueprintReadWrite, meta = (Bitmask, BitmaskEnum = "EActivatorType"))
uint8 activated = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (Bitmask, BitmaskEnum = "EActivatorType"))
int32 activated = 0;
UPROPERTY(EditDefaultsOnly)
TArray<TSubclassOf<class UInteractableModificator>> modificatorsClasses;
TMap<EActivatorType, class UInteractableModificator*> modificators = {};
class APlayerBase* player;
private:
//UPROPERTY(EditDefaultsOnly)
//TSoftObjectPtr<UMaterialInstance> material;
TArray<class UInteractableModificator*> _modificators;
};

View File

@ -0,0 +1,46 @@
// Oleg Petruny proprietary.
#include "ActivateInteractableModificator.h"
#include "EnhancedInputComponent.h"
#include "InputMappingContext.h"
#include "../Interactable.h"
UActivateInteractableModificator::UActivateInteractableModificator(const FObjectInitializer& ObjectInitializer)
: UInteractableModificator(ObjectInitializer)
{
activatorTypes |= static_cast<uint8>(EActivatorType::Use);
inputMapping = LoadObject<UInputMappingContext>(this, TEXT("/Game/Input/Interactables/IMC_InteractableActivate"));
}
void UActivateInteractableModificator::Bind_Implementation(class UEnhancedInputComponent* input)
{
if(!input && !inputMapping)
return;
for(auto& mapping : inputMapping->GetMappings())
{
auto handle = input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &UActivateInteractableModificator::ActivateInteractable).GetHandle();
bindindingHandlers.Add(handle);
}
}
void UActivateInteractableModificator::Unbind_Implementation()
{
if(!lastInput)
return;
for(auto handle : bindindingHandlers)
{
lastInput->RemoveBindingByHandle(handle);
}
bindindingHandlers.Empty();
}
void UActivateInteractableModificator::ActivateInteractable()
{
OnActivated.Broadcast();
}

View File

@ -0,0 +1,32 @@
// Oleg Petruny proprietary.
#pragma once
#include "CoreMinimal.h"
#include "InteractableModificator.h"
#include "ActivateInteractableModificator.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FActivateInteractableModificatorActivatedDelegate);
UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType)
class UActivateInteractableModificator : public UInteractableModificator
{
GENERATED_BODY()
public:
UActivateInteractableModificator(const FObjectInitializer& ObjectInitializer);
void Bind_Implementation(class UEnhancedInputComponent* input) override;
void Unbind_Implementation() override;
UPROPERTY(BlueprintAssignable)
FActivateInteractableModificatorActivatedDelegate OnActivated;
protected:
void ActivateInteractable();
private:
class UEnhancedInputComponent* lastInput;
TArray<int32> bindindingHandlers;
};

View File

@ -0,0 +1,14 @@
// Oleg Petruny proprietary.
#include "EditInteractableModificator.h"
#include "../Interactable.h"
UEditInteractableModificator::UEditInteractableModificator(const FObjectInitializer& ObjectInitializer)
: UInteractableModificator(ObjectInitializer)
{
activatorTypes |= static_cast<uint8>(EActivatorType::Collide);
}

View File

@ -0,0 +1,18 @@
// Oleg Petruny proprietary.
#pragma once
#include "CoreMinimal.h"
#include "InteractableModificator.h"
#include "EditInteractableModificator.generated.h"
UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType)
class UEditInteractableModificator : public UInteractableModificator
{
GENERATED_BODY()
public:
UEditInteractableModificator(const FObjectInitializer& ObjectInitializer);
};

View File

@ -5,9 +5,24 @@
#include "InputMappingContext.h"
#include "CustomGameInstanceBase.h"
void UInteractableModificator::OnRegister()
{
UActorComponent::OnRegister();
if(auto world = GetWorld())
{
if(auto GI = Cast<UCustomGameInstanceBase>(world->GetGameInstance()))
{
GI->AppendInteractableModificatorClass(this->GetClass());
}
}
}
const UInputMappingContext* UInteractableModificator::GetMappingContext() const
{
return inputMapping.LoadSynchronous();
return inputMapping;
}
EActivatorType UInteractableModificator::GetActivatorTypes() const

View File

@ -15,13 +15,24 @@ class UInteractableModificator : public UActorComponent
GENERATED_BODY()
public:
void OnRegister() override;
const class UInputMappingContext* GetMappingContext() const;
EActivatorType GetActivatorTypes() const;
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Bind(class UEnhancedInputComponent* input);
virtual void Bind_Implementation(class UEnhancedInputComponent* input) {}
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Unbind();
virtual void Unbind_Implementation() {}
protected:
UPROPERTY(EditDefaultsOnly)
TSoftObjectPtr<class UInputMappingContext> inputMapping;
class UInputMappingContext* inputMapping;
UPROPERTY(EditAnywhere, meta = (Bitmask, BitmaskEnum = "EActivatorType"))
uint8 activatorTypes = 0;
int32 activatorTypes = 0;
};

View File

@ -1,5 +0,0 @@
// Oleg Petruny proprietary.
#include "InteractableUsableModificator.h"

View File

@ -1,18 +0,0 @@
// Oleg Petruny proprietary.
#pragma once
#include "InteractableModificator.h"
#include "InteractableUsableModificator.generated.h"
UCLASS(Blueprintable, BlueprintType)
class UInteractableUsableModificator : public UInteractableModificator
{
GENERATED_BODY()
public:
protected:
};

View File

@ -0,0 +1,171 @@
// Oleg Petruny proprietary.
#include "MoveInteractableModificator.h"
#include "EnhancedInputComponent.h"
#include "InputMappingContext.h"
#include "Interactable/Interactable.h"
#include "PlayerBase.h"
UMoveInteractableModificator::UMoveInteractableModificator(const FObjectInitializer& ObjectInitializer)
: UInteractableModificator(ObjectInitializer)
{
activatorTypes |= static_cast<uint8>(EActivatorType::Use);
inputMapping = LoadObject<UInputMappingContext>(this, TEXT("/Game/Input/Interactables/IMC_InteractableMove"));
actor = Cast<AInteractable>(GetOwner());
PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = false;
}
void UMoveInteractableModificator::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
UpdatePosition(DeltaTime);
}
void UMoveInteractableModificator::Bind_Implementation(class UEnhancedInputComponent* input)
{
if(!input && !inputMapping)
return;
if(state != State::Nothing)
return;
for(auto& mapping : inputMapping->GetMappings())
{
if(mapping.Key == EKeys::LeftMouseButton
|| mapping.Key == EKeys::RightMouseButton)
{
auto handle = input->BindAction(mapping.Action, ETriggerEvent::Started, this, &UMoveInteractableModificator::IncreaseState).GetHandle();
bindindingHandlers.Add(handle);
handle = input->BindAction(mapping.Action, ETriggerEvent::Completed, this, &UMoveInteractableModificator::DecreaseState).GetHandle();
bindindingHandlers.Add(handle);
}
else if(mapping.Key == EKeys::MouseWheelAxis)
{
auto handle = input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &UMoveInteractableModificator::Zooming).GetHandle();
bindindingHandlers.Add(handle);
}
else if(mapping.Key == EKeys::Mouse2D)
{
auto handle = input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &UMoveInteractableModificator::Rotating).GetHandle();
bindindingHandlers.Add(handle);
}
}
lastInput = input;
player = Cast<APlayerBase>(Cast<APlayerController>(lastInput->GetOwner())->GetPawn());
SetComponentTickEnabled(true);
OnMoveActivated.Broadcast();
}
void UMoveInteractableModificator::Unbind_Implementation()
{
if(!lastInput)
return;
if(state != State::Nothing)
return;
for(auto handle : bindindingHandlers)
{
lastInput->RemoveBindingByHandle(handle);
}
bindindingHandlers.Empty();
state = static_cast<State>(0);
ProcessState();
SetComponentTickEnabled(false);
OnMoveDeactivated.Broadcast();
}
void UMoveInteractableModificator::IncreaseState()
{
state = static_cast<State>(static_cast<uint8>(state) + 1);
if(static_cast<uint8>(state) > static_cast<uint8>(State::Rotating))
state = State::Rotating;
ProcessState();
}
void UMoveInteractableModificator::DecreaseState()
{
state = static_cast<State>(static_cast<uint8>(state) - 1);
if(static_cast<uint8>(state) > static_cast<uint8>(State::Rotating))
state = State::Nothing;
ProcessState();
}
void UMoveInteractableModificator::ProcessState()
{
switch(state)
{
case State::Nothing:
{
player->cameraLocked = false;
break;
}
case State::Holding:
{
player->cameraLocked = false;
OnHolding.Broadcast();
break;
}
case State::Rotating:
{
player->cameraLocked = true;
OnRotating.Broadcast();
break;
}
default:
break;
}
if(state == State::Nothing)
{
if((actor->GetActivatedFlags() & static_cast<uint32>(EActivatorType::Use)) == 0
&& bindindingHandlers.Num() > 0)
{
Unbind_Implementation();
}
}
}
void UMoveInteractableModificator::UpdatePosition(float deltaTime)
{
if(!player)
return;
if(state == State::Nothing)
{
distance = (player->GetCameraLocation() - actor->GetActorLocation()).Length();
return;
}
auto camLoc = player->GetCameraLocation();
auto dir = player->GetCameraDirection();
auto newLoc = camLoc + dir * distance;
auto currentLoc = actor->GetActorLocation();
auto interpLoc = FMath::VInterpTo(currentLoc, newLoc, deltaTime, 20.0f);
actor->SetActorLocation(interpLoc, true, nullptr, ETeleportType::None);
}
void UMoveInteractableModificator::Zooming(const FInputActionValue& value)
{
if(state != State::Holding)
return;
distance += value.Get<float>() * zoomSpeed;
distance = FMath::Clamp<float>(distance, minDistance, maxDistance);
}
void UMoveInteractableModificator::Rotating(const FInputActionValue& axis)
{
if(state != State::Rotating)
return;
auto v = axis.Get<FVector>();
auto vec = player->GetCameraDirection();
actor->AddActorWorldRotation(FRotator{ v.Y * vec.X, v.X, v.Y * vec.Y * -1 }, true, nullptr, ETeleportType::None);
}

View File

@ -0,0 +1,66 @@
// Oleg Petruny proprietary.
#pragma once
#include "CoreMinimal.h"
#include "InputActionValue.h"
#include "InteractableModificator.h"
#include "MoveInteractableModificator.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FActivateMoveInteractableModificatorActivatedDelegate);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDeactivateMoveInteractableModificatorActivatedDelegate);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FHoldingMoveInteractableModificatorActivatedDelegate);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FRotatingMoveInteractableModificatorActivatedDelegate);
UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType)
class UMoveInteractableModificator : public UInteractableModificator
{
GENERATED_BODY()
public:
UMoveInteractableModificator(const FObjectInitializer& ObjectInitializer);
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
void Bind_Implementation(class UEnhancedInputComponent* input) override;
void Unbind_Implementation() override;
UPROPERTY(BlueprintAssignable)
FActivateMoveInteractableModificatorActivatedDelegate OnMoveActivated;
UPROPERTY(BlueprintAssignable)
FDeactivateMoveInteractableModificatorActivatedDelegate OnMoveDeactivated;
UPROPERTY(BlueprintAssignable)
FHoldingMoveInteractableModificatorActivatedDelegate OnHolding;
UPROPERTY(BlueprintAssignable)
FRotatingMoveInteractableModificatorActivatedDelegate OnRotating;
protected:
float distance = 0;
float minDistance = 100.0f;
float maxDistance = 200.0f;
float zoomSpeed = 10.0f;
float moveSpeed = 1.0f;
float rotateSpeed = 10.0f;
private:
void IncreaseState();
void DecreaseState();
void ProcessState();
void UpdatePosition(float deltaTime);
void Zooming(const FInputActionValue& value);
void Rotating(const FInputActionValue& axis);
enum class State : uint8
{
Nothing = 0,
Holding,
Rotating
};
class UEnhancedInputComponent* lastInput;
TArray<int32> bindindingHandlers;
State state = State::Nothing;
class AInteractable* actor;
class APlayerBase* player;
};

View File

@ -0,0 +1,17 @@
// Oleg Petruny proprietary.
#include "SawInteractableModificator.h"
#include "../Interactable.h"
USawInteractableModificator::USawInteractableModificator(const FObjectInitializer& ObjectInitializer)
: UInteractableModificator(ObjectInitializer)
{
activatorTypes |= static_cast<uint8>(EActivatorType::Saw);
}
void USawInteractableModificator::Bind_Implementation(class UEnhancedInputComponent* input)
{
OnSaw.Broadcast();
}

View File

@ -0,0 +1,24 @@
// Oleg Petruny proprietary.
#pragma once
#include "CoreMinimal.h"
#include "InteractableModificator.h"
#include "SawInteractableModificator.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FSawInteractableModificatorActivatedDelegate);
UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType)
class USawInteractableModificator : public UInteractableModificator
{
GENERATED_BODY()
public:
USawInteractableModificator(const FObjectInitializer& ObjectInitializer);
void Bind_Implementation(class UEnhancedInputComponent* input) override;
UPROPERTY(BlueprintAssignable)
FSawInteractableModificatorActivatedDelegate OnSaw;
};

View File

@ -4,6 +4,7 @@
#include "PlayerBase.h"
#include "Camera/CameraComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "InputMappingContext.h"
@ -11,9 +12,8 @@
#include "Kismet/KismetMathLibrary.h"
#include "CustomGameInstanceBase.h"
#include "Interactable/Activators/InteractableActivator.h"
#include "CustomGameUserSettings.h"
#include "Interactable/Activators/InteractableActivator.h"
#include "MainGameModeBase.h"
APlayerBase::APlayerBase()
@ -27,6 +27,12 @@ void APlayerBase::Tick(float DeltaTime)
// stabilize move speed by fps
AddActorLocalOffset(ConsumeMovementInputVector() * DeltaTime);
if(moved)
{
moved = false;
//OnPlayerMoved.Broadcast();
}
}
void APlayerBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
@ -57,14 +63,20 @@ void APlayerBase::BeginPlay()
camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f;
}
if(inputMapping)
if(auto PC = Cast<APlayerController>(GetController()))
{
if(auto PC = Cast<APlayerController>(GetController()))
inputComponent = Cast<UEnhancedInputComponent>(PC->InputComponent);;
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
{
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
if(auto GI = Cast<UCustomGameInstanceBase>(GetWorld()->GetGameInstance()))
{
inputSubsystem->ClearAllMappings();
inputSubsystem->AddMappingContext(inputMapping.LoadSynchronous(), 0);
for(auto& inputContext : GI->inputContexts)
{
inputSubsystem->AddMappingContext(inputContext.LoadSynchronous(), 0);
}
}
}
}
@ -72,6 +84,37 @@ void APlayerBase::BeginPlay()
LoadInteractablesActivators();
}
APlayerBase* APlayerBase::LockCamera(UWorld* world, bool locked)
{
if(auto PC = UGameplayStatics::GetPlayerController(world, 0))
{
if(auto pawn = Cast<APlayerBase>(PC->GetPawn()))
{
pawn->cameraLocked = locked;
return pawn;
}
}
return nullptr;
}
void APlayerBase::AttachToCamera(AActor* actor)
{
if(!actor)
return;
actor->AttachToComponent(camera, FAttachmentTransformRules::KeepWorldTransform);
}
FVector APlayerBase::GetCameraDirection()
{
return camera->GetComponentRotation().Vector();
}
FVector APlayerBase::GetCameraLocation()
{
return camera->GetComponentLocation();
}
void APlayerBase::SwitchToCameraPawn()
{
if(auto gamemode_base = UGameplayStatics::GetGameMode(GetWorld()))
@ -90,6 +133,8 @@ void APlayerBase::MoveCamera(FVector2D value)
AddControllerYawInput(value.X);
AddControllerPitchInput(value.Y);
moved = true;
}
void APlayerBase::MoveCharacter(FVector2D value)
@ -99,6 +144,8 @@ void APlayerBase::MoveCharacter(FVector2D value)
AddMovementInput(GetActorRightVector(), value.X);
AddMovementInput(GetActorForwardVector(), value.Y);
moved = true;
}
void APlayerBase::Jump()
@ -107,6 +154,8 @@ void APlayerBase::Jump()
return;
ACharacter::Jump();
moved = true;
}
void APlayerBase::SwitchRun(bool run)
@ -154,24 +203,22 @@ void APlayerBase::LoadInteractablesActivators()
void APlayerBase::InteractableActivated(AInteractable* interactable, EActivatorType type)
{
if(!interactable)
return;
if(interactionLocked)
return;
interactable->Activate(type);
#ifdef INTERACTABLE_DEBUG
GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Cyan, TEXT("Player activate: ") + interactable->GetName()
+ TEXT(" by: ") + StaticEnum<EActivatorType>()->GetNameByValue(static_cast<int64>(type)).ToString());
#endif // INTERACTABLE_DEBUG
interactable->_Activate(type);
}
void APlayerBase::InteractableDeactivated(AInteractable* interactable, EActivatorType type)
{
if(!interactable)
return;
if(interactionLocked)
return;
interactable->Deactivate(type);
#ifdef INTERACTABLE_DEBUG
GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Magenta, TEXT("Player deactivate: ") + interactable->GetName()
+ TEXT(" by: ") + StaticEnum<EActivatorType>()->GetNameByValue(static_cast<int64>(type)).ToString());
#endif // INTERACTABLE_DEBUG
interactable->_Deactivate(type);
}

View File

@ -9,6 +9,8 @@
#include "PlayerBase.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FPlayerMovedDelegate);
UCLASS()
class APlayerBase : public ACharacter
{
@ -20,6 +22,20 @@ public:
virtual void Tick(float DeltaTime) override;
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
static APlayerBase* LockCamera(UWorld* world, bool locked);
void AttachToCamera(AActor* actor);
FVector GetCameraLocation();
FVector GetCameraDirection();
UPROPERTY(BlueprintAssignable)
FPlayerMovedDelegate OnPlayerMoved;
class UEnhancedInputComponent* inputComponent;
UPROPERTY(EditAnywhere)
bool interactionLocked = false;
UPROPERTY(EditAnywhere)
bool cameraLocked = false;
protected:
virtual void BeginPlay() override;
@ -37,9 +53,6 @@ protected:
UFUNCTION(BlueprintCallable, Category = Character)
void UpdatePitch(float min, float max);
UPROPERTY(EditDefaultsOnly)
TSoftObjectPtr<class UInputMappingContext> inputMapping;
UPROPERTY(EditAnywhere)
float moveSpeed = 200;
UPROPERTY(EditAnywhere)
@ -51,18 +64,16 @@ protected:
bool jumpLocked = false;
UPROPERTY(EditAnywhere)
bool runLocked = false;
UPROPERTY(EditAnywhere)
bool interactionLocked = false;
APlayerCameraManager* cameraManager;
class UCameraComponent* camera;
UPROPERTY(EditAnywhere)
bool cameraLocked = false;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
float minPitch = -80;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
float maxPitch = 65;
bool moved = false;
private:
void LoadInteractablesActivators();
void InteractableActivated(AInteractable* interactable, EActivatorType type);

View File

@ -34,9 +34,12 @@ void UWidgetsManager::Init()
instance->AddToViewport();
}
}
if(auto instance = CreateWidget<UInteractableHintWidgetManager>(PC, interactableHintWidgetManagerClass))
{
interactableHintWidgetManager = instance;
instance->AddToViewport();
}
}
interactableHintWidgetManager = NewObject<UInteractableHintWidgetManager>(this, interactableHintWidgetManagerClass);
}
void UWidgetsManager::HideOverlayWidgets()
@ -84,9 +87,11 @@ void UWidgetsManager::UpdateOverlayWidgetsOwner()
void UWidgetsManager::ShowInteractionHints(const UInteractableModificator* modificator)
{
interactableHintWidgetManager->Append(modificator);
if(interactableHintWidgetManager.IsValid())
interactableHintWidgetManager->Append_Implementation(modificator);
}
void UWidgetsManager::HideInteractionHints(const EActivatorType type)
{
interactableHintWidgetManager->Remove(type);
if(interactableHintWidgetManager.IsValid())
interactableHintWidgetManager->Remove_Implementation(type);
}

View File

@ -26,14 +26,14 @@ public:
protected:
UPROPERTY(EditDefaultsOnly)
TArray<TSubclassOf<class UUserWidget>> permaOverlayWidgets; // never hidden
TSet<TSubclassOf<class UUserWidget>> permaOverlayWidgets; // never hidden
TArray<TWeakObjectPtr<class UUserWidget>> permaOverlayWidgetsInstances;
UPROPERTY(EditDefaultsOnly)
TArray<TSubclassOf<class UUserWidget>> overlayWidgets; // hidden in pause
TSet<TSubclassOf<class UUserWidget>> overlayWidgets; // hidden in pause
TArray<TWeakObjectPtr<class UUserWidget>> overlayWidgetsInstances;
UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UInteractableHintWidgetManager> interactableHintWidgetManagerClass;
class UInteractableHintWidgetManager* interactableHintWidgetManager;
TWeakObjectPtr<class UInteractableHintWidgetManager> interactableHintWidgetManager;
};