Interactables: cleanup, UI, UI animations

This commit is contained in:
Oleg Petruny 2024-06-16 08:51:16 +02:00
parent 8856ce7dd8
commit a52d2aaa4a
38 changed files with 429 additions and 157 deletions

View File

@ -8,3 +8,105 @@ bPreloadEnginePluginModules=False
bPreloadProjectModules=True
bPreloadProjectPluginModules=True
[/Script/GraphEditor.GraphEditorSettings]
DataPinStyle=BPST_VariantA
PanningMouseButton=Right
PaddingAbovePin=4.000000
PaddingBelowPin=4.000000
PaddingRightOfInput=10.000000
PaddingLeftOfOutput=10.000000
PaddingTowardsNodeEdge=10.000000
bTreatSplinesLikePins=True
SplineHoverTolerance=2.000000
SplineCloseTolerance=6.000000
ForwardSplineHorizontalDeltaRange=1000.000000
ForwardSplineVerticalDeltaRange=1000.000000
ForwardSplineTangentFromHorizontalDelta=(X=-1.000000,Y=0.000000)
ForwardSplineTangentFromVerticalDelta=(X=1.000000,Y=0.000000)
BackwardSplineHorizontalDeltaRange=200.000000
BackwardSplineVerticalDeltaRange=200.000000
BackwardSplineTangentFromHorizontalDelta=(X=0.000000,Y=0.000000)
BackwardSplineTangentFromVerticalDelta=(X=1.000000,Y=0.000000)
DefaultPinTypeColor=(R=0.750000,G=0.600000,B=0.400000,A=1.000000)
ExecutionPinTypeColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000)
BooleanPinTypeColor=(R=0.300000,G=0.000000,B=0.000000,A=1.000000)
BytePinTypeColor=(R=0.000000,G=0.160000,B=0.131270,A=1.000000)
ClassPinTypeColor=(R=0.100000,G=0.000000,B=0.500000,A=1.000000)
IntPinTypeColor=(R=0.013575,G=0.770000,B=0.429609,A=1.000000)
Int64PinTypeColor=(R=0.413575,G=0.770000,B=0.429609,A=1.000000)
FloatPinTypeColor=(R=0.357667,G=1.000000,B=0.060000,A=1.000000)
DoublePinTypeColor=(R=0.039216,G=0.666667,B=0.000000,A=1.000000)
RealPinTypeColor=(R=0.039216,G=0.666667,B=0.000000,A=1.000000)
NamePinTypeColor=(R=0.607717,G=0.224984,B=1.000000,A=1.000000)
SoftObjectPinTypeColor=(R=0.300000,G=1.000000,B=1.000000,A=1.000000)
SoftClassPinTypeColor=(R=1.000000,G=0.300000,B=1.000000,A=1.000000)
DelegatePinTypeColor=(R=1.000000,G=0.040000,B=0.040000,A=1.000000)
ObjectPinTypeColor=(R=0.000000,G=0.400000,B=0.910000,A=1.000000)
InterfacePinTypeColor=(R=0.878400,G=1.000000,B=0.400000,A=1.000000)
StringPinTypeColor=(R=1.000000,G=0.000000,B=0.660537,A=1.000000)
TextPinTypeColor=(R=0.800000,G=0.200000,B=0.400000,A=1.000000)
StructPinTypeColor=(R=0.000000,G=0.100000,B=0.600000,A=1.000000)
WildcardPinTypeColor=(R=0.220000,G=0.195800,B=0.195800,A=1.000000)
VectorPinTypeColor=(R=1.000000,G=0.591255,B=0.016512,A=1.000000)
RotatorPinTypeColor=(R=0.353393,G=0.454175,B=1.000000,A=1.000000)
TransformPinTypeColor=(R=1.000000,G=0.172585,B=0.000000,A=1.000000)
IndexPinTypeColor=(R=0.013575,G=0.770000,B=0.429609,A=1.000000)
EventNodeTitleColor=(R=1.000000,G=0.000000,B=0.000000,A=1.000000)
FunctionCallNodeTitleColor=(R=0.190525,G=0.583898,B=1.000000,A=1.000000)
PureFunctionCallNodeTitleColor=(R=0.400000,G=0.850000,B=0.350000,A=1.000000)
ParentFunctionCallNodeTitleColor=(R=1.000000,G=0.170000,B=0.000000,A=1.000000)
FunctionTerminatorNodeTitleColor=(R=0.600000,G=0.000000,B=1.000000,A=1.000000)
ExecBranchNodeTitleColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000)
ExecSequenceNodeTitleColor=(R=0.800000,G=0.400000,B=0.400000,A=1.000000)
ResultNodeTitleColor=(R=1.000000,G=0.650000,B=0.400000,A=1.000000)
DefaultCommentNodeTitleColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000)
PreviewNodeTitleColor=(R=0.000000,G=0.000000,B=1.000000,A=1.000000)
DefaultDataWireThickness=1.500000
DefaultExecutionWireThickness=2.500000
TraceAttackColor=(R=1.000000,G=0.050000,B=0.000000,A=1.000000)
TraceAttackWireThickness=6.000000
TraceSustainColor=(R=1.000000,G=0.700000,B=0.400000,A=1.000000)
TraceSustainWireThickness=3.500000
TraceReleaseColor=(R=0.500000,G=0.500000,B=0.500000,A=1.000000)
TraceReleaseWireThickness=1.500000
PaddingAutoCollateIncrement=20.000000
bOpenCreateMenuOnBlankGraphAreas=True
DefaultCommentNodeMoveMode=GroupMovement
bShowCommentBubbleWhenZoomedOut=False
[/Script/UnrealEd.EditorStyleSettings]
ApplicationScale=1.000000
bEnableUserEditorLayoutManagement=True
ColorVisionDeficiencyPreviewType=NormalVision
ColorVisionDeficiencySeverity=3
bColorVisionDeficiencyCorrection=False
bColorVisionDeficiencyCorrectionPreviewWithDeficiency=False
SelectionColor=(R=0.828000,G=0.364000,B=0.003000,A=1.000000)
AdditionalSelectionColors[0]=(R=0.019382,G=0.496933,B=1.000000,A=1.000000)
AdditionalSelectionColors[1]=(R=0.356400,G=0.040915,B=0.520996,A=1.000000)
AdditionalSelectionColors[2]=(R=1.000000,G=0.168269,B=0.332452,A=1.000000)
AdditionalSelectionColors[3]=(R=1.000000,G=0.051269,B=0.051269,A=1.000000)
AdditionalSelectionColors[4]=(R=1.000000,G=0.715693,B=0.010330,A=1.000000)
AdditionalSelectionColors[5]=(R=0.258183,G=0.539479,B=0.068478,A=1.000000)
ViewportToolOverlayColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000)
bEnableEditorWindowBackgroundColor=False
EditorWindowBackgroundColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000)
bUseSmallToolBarIcons=False
MenuSearchFieldVisibilityThreshold=10
bUseGrid=True
RegularColor=(R=0.035000,G=0.035000,B=0.035000,A=1.000000)
RuleColor=(R=0.008000,G=0.008000,B=0.008000,A=1.000000)
CenterColor=(R=0.000000,G=0.000000,B=0.000000,A=1.000000)
GridSnapSize=16
GraphBackgroundBrush=(bIsDynamicallyLoaded=False,DrawAs=Image,Tiling=NoTile,Mirroring=NoMirror,ImageType=NoImage,ImageSize=(X=32.000000,Y=32.000000),Margin=(Left=0.000000,Top=0.000000,Right=0.000000,Bottom=0.000000),TintColor=(SpecifiedColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),ColorUseRule=UseColor_Specified),OutlineSettings=(CornerRadii=(X=0.000000,Y=0.000000,Z=0.000000,W=1.000000),Color=(SpecifiedColor=(R=0.000000,G=0.000000,B=0.000000,A=0.000000),ColorUseRule=UseColor_Specified),Width=0.000000,RoundingType=HalfHeightRadius,bUseBrushTransparency=False),ResourceObject=None,ResourceName="",UVRegion=(Min=(X=0.000000,Y=0.000000),Max=(X=0.000000,Y=0.000000),bIsValid=False))
bShowFriendlyNames=True
bShowNativeComponentNames=True
bExpandConfigurationMenus=False
bShowProjectMenus=True
bShowLaunchMenus=True
bShowAllAdvancedDetails=False
bShowHiddenPropertiesWhilePlaying=False
AssetEditorOpenLocation=Default
bEnableColorizedEditorTabs=True
CurrentAppliedTheme=134380265FBB4A9CA00A1DC9770217B8

Binary file not shown.

View File

@ -1,6 +1,6 @@
{
"FileVersion": 3,
"EngineAssociation": "{42CC8720-4DDD-EF11-BECE-CEBF292119D8}",
"EngineAssociation": "5.4",
"Category": "",
"Description": "",
"Modules": [
@ -359,6 +359,16 @@
"Name": "AutoSizeComments",
"Enabled": false,
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/ae89a2c4ab384de0a3f213b23de324f3"
},
{
"Name": "RenameTool",
"Enabled": true,
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/c6e227383f754209ab1eeb294aa0f6d6"
},
{
"Name": "FlatNodes",
"Enabled": true,
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/b719437f3fb54c259b34227363df8cab"
}
],
"TargetPlatforms": [

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));
// GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("v: %f, %f, %f"), scale));
// DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, PrimaryComponentTick.TickInterval, 0, 0.1f);
}

View File

@ -0,0 +1,13 @@
// Oleg Petruny proprietary.
#include "CommonFunctions.h"
#include "UObject/Object.h"
bool CommonFunctions::IsNonGameObject(UObject* object)
{
if(object->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
return true;
return false;
}

View File

@ -0,0 +1,9 @@
// Oleg Petruny proprietary.
#pragma once
class CommonFunctions
{
public:
static inline bool IsNonGameObject(class UObject* object);
};

View File

@ -3,11 +3,15 @@
#include "InCameraInteractableActivator.h"
#include "CommonFunctions.h"
#include "InteractableScreenCapturer.h"
UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInitializer& ObjectInitializer)
: UInteractableActivator(ObjectInitializer)
{
if(CommonFunctions::IsNonGameObject(this))
return;
if(!world || !player)
{
return;

View File

@ -13,7 +13,8 @@
#include "SceneView.h"
#include "TextureCompressorModule.h"
#include "../Interactable.h"
#include "CommonFunctions.h"
#include "Interactable/Interactable.h"
#include "InteractableScreenCapturerBitMapCS.h"
constexpr float tickInterval = 1.0f / 5;
@ -23,6 +24,9 @@ constexpr float textureHeight = 720 / 2;
UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer)
: USceneCaptureComponent2D(ObjectInitializer)
{
if(CommonFunctions::IsNonGameObject(this))
return;
PrimaryComponentTick.bCanEverTick = false;
PrimaryComponentTick.bStartWithTickEnabled = false;
@ -270,7 +274,7 @@ void UInteractableScreenCapturer::Process()
else
{
DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 10, 0.1f);
}
}
#endif // INTERACTABLE_ACTIVATOR_DEBUG
}
@ -278,7 +282,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

@ -83,13 +83,13 @@ void AInteractable::_Activate(EActivatorType type)
+ 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(!player
|| modificators.IsEmpty()
|| !activationLockers.IsEmpty())
return;
if(auto WM = AMainGameModeBase::GetWidgetManager())
{
for(const auto& modificator : modificators)
@ -97,12 +97,12 @@ void AInteractable::_Activate(EActivatorType type)
if(static_cast<uint8>(modificator.Value->GetActivatorTypes()) & static_cast<uint8>(type))
{
WM->ShowInteractionHints(modificator.Value);
modificator.Value->Bind_Implementation(player->inputComponent);
modificator.Value->Bind(player->inputComponent);
}
}
}
Activate_Implementation(type);
Activate(type);
}
void AInteractable::_Deactivate(EActivatorType type)
@ -112,24 +112,24 @@ void AInteractable::_Deactivate(EActivatorType type)
+ 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(!player
|| modificators.IsEmpty()
|| !activationLockers.IsEmpty())
return;
if(auto WM = AMainGameModeBase::GetWidgetManager())
{
WM->HideInteractionHints(type);
for(const auto& modificator : modificators)
{
if(static_cast<uint8>(modificator.Value->GetActivatorTypes()) & static_cast<uint8>(type))
if(static_cast<uint8>(modificator.Key) & static_cast<uint8>(type))
{
modificator.Value->Unbind_Implementation();
WM->HideInteractionHints(modificator.Value);
modificator.Value->Unbind();
}
}
}
Deactivate_Implementation(type);
Deactivate(type);
}

View File

@ -44,15 +44,17 @@ public:
void Deactivate(EActivatorType type);
virtual void Deactivate_Implementation(EActivatorType type) {}
TSet<class UInteractableModificator*> activationLockers;
protected:
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (Bitmask, BitmaskEnum = "EActivatorType"))
int32 activated = 0;
TMap<EActivatorType, class UInteractableModificator*> modificators = {};
TMap<EActivatorType, class UInteractableModificator*> modificators;
class APlayerBase* player;
class APlayerBase* player = nullptr;
};

View File

@ -6,19 +6,27 @@
#include "EnhancedInputComponent.h"
#include "InputMappingContext.h"
#include "../Interactable.h"
#include "CommonFunctions.h"
#include "Interactable/Interactable.h"
#include "MainGameModeBase.h"
#include "Widgets/InteractableHintWidget.h"
#include "Widgets/WidgetsManager.h"
UActivateInteractableModificator::UActivateInteractableModificator(const FObjectInitializer& ObjectInitializer)
: UInteractableModificator(ObjectInitializer)
{
activatorTypes |= static_cast<uint8>(EActivatorType::Use);
inputMapping = LoadObject<UInputMappingContext>(this, TEXT("/Game/Input/Interactables/IMC_InteractableActivate"));
inputMapping = { FSoftObjectPath{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/Interactables/IMC_InteractableActivate.IMC_InteractableActivate'") } };
}
void UActivateInteractableModificator::Bind_Implementation(class UEnhancedInputComponent* input)
void UActivateInteractableModificator::Bind_Implementation(UEnhancedInputComponent* input)
{
if(!input && !inputMapping)
if(!input)
return;
inputMapping.LoadSynchronous();
if(!inputMapping)
return;
for(auto& mapping : inputMapping->GetMappings())
@ -26,6 +34,7 @@ void UActivateInteractableModificator::Bind_Implementation(class UEnhancedInputC
auto handle = input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &UActivateInteractableModificator::ActivateInteractable).GetHandle();
bindindingHandlers.Add(handle);
}
lastInput = input;
}
void UActivateInteractableModificator::Unbind_Implementation()
@ -42,5 +51,6 @@ void UActivateInteractableModificator::Unbind_Implementation()
void UActivateInteractableModificator::ActivateInteractable()
{
AMainGameModeBase::GetWidgetManager()->AnimateInteractionHint(this, 0, EInteractableHintWidgetAnimation::Click);
OnActivated.Broadcast();
}

View File

@ -27,6 +27,6 @@ protected:
void ActivateInteractable();
private:
class UEnhancedInputComponent* lastInput;
class UEnhancedInputComponent* lastInput = nullptr;
TArray<int32> bindindingHandlers;
};

View File

@ -6,6 +6,7 @@
#include "InputMappingContext.h"
#include "CustomGameInstanceBase.h"
#include "Widgets/InteractableHintWidget.h"
void UInteractableModificator::OnRegister()
{
@ -22,7 +23,7 @@ void UInteractableModificator::OnRegister()
const UInputMappingContext* UInteractableModificator::GetMappingContext() const
{
return inputMapping;
return inputMapping.LoadSynchronous();
}
EActivatorType UInteractableModificator::GetActivatorTypes() const

View File

@ -17,7 +17,9 @@ class UInteractableModificator : public UActorComponent
public:
void OnRegister() override;
UFUNCTION(BlueprintCallable)
const class UInputMappingContext* GetMappingContext() const;
UFUNCTION(BlueprintCallable)
EActivatorType GetActivatorTypes() const;
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
@ -29,8 +31,9 @@ public:
virtual void Unbind_Implementation() {}
protected:
UPROPERTY(EditDefaultsOnly)
class UInputMappingContext* inputMapping;
TSoftObjectPtr<class UInputMappingContext> inputMapping;
UPROPERTY(EditAnywhere, meta = (Bitmask, BitmaskEnum = "EActivatorType"))
int32 activatorTypes = 0;

View File

@ -7,43 +7,54 @@
#include "InputMappingContext.h"
#include "Interactable/Interactable.h"
#include "MainGameModeBase.h"
#include "PlayerBase.h"
#include "Widgets/InteractableHintWidget.h"
#include "Widgets/WidgetsManager.h"
UMoveInteractableModificator::UMoveInteractableModificator(const FObjectInitializer& ObjectInitializer)
: UInteractableModificator(ObjectInitializer)
{
activatorTypes |= static_cast<uint8>(EActivatorType::Use);
inputMapping = LoadObject<UInputMappingContext>(this, TEXT("/Game/Input/Interactables/IMC_InteractableMove"));
inputMapping = { FSoftObjectPath{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/Interactables/IMC_InteractableMove.IMC_InteractableMove'") } };
actor = Cast<AInteractable>(GetOwner());
PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = false;
PrimaryComponentTick.TickGroup = ETickingGroup::TG_PostUpdateWork;
}
void UMoveInteractableModificator::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
UInteractableModificator::TickComponent(DeltaTime, TickType, ThisTickFunction);
UpdatePosition(DeltaTime);
UpdatePosition();
}
void UMoveInteractableModificator::Bind_Implementation(class UEnhancedInputComponent* input)
{
if(!input && !inputMapping)
return;
if(state != State::Nothing)
if(holding || rotating)
return;
for(auto& mapping : inputMapping->GetMappings())
{
if(mapping.Key == EKeys::LeftMouseButton
|| mapping.Key == EKeys::RightMouseButton)
if(mapping.Key == EKeys::LeftMouseButton)
{
auto handle = input->BindAction(mapping.Action, ETriggerEvent::Started, this, &UMoveInteractableModificator::IncreaseState).GetHandle();
auto handle = input->BindAction(mapping.Action, ETriggerEvent::Started, this, &UMoveInteractableModificator::TurnOnHolding).GetHandle();
bindindingHandlers.Add(handle);
handle = input->BindAction(mapping.Action, ETriggerEvent::Completed, this, &UMoveInteractableModificator::DecreaseState).GetHandle();
handle = input->BindAction(mapping.Action, ETriggerEvent::Completed, this, &UMoveInteractableModificator::TurnOffHolding).GetHandle();
bindindingHandlers.Add(handle);
}
else if(mapping.Key == EKeys::RightMouseButton)
{
auto handle = input->BindAction(mapping.Action, ETriggerEvent::Started, this, &UMoveInteractableModificator::TurnOnRotating).GetHandle();
bindindingHandlers.Add(handle);
handle = input->BindAction(mapping.Action, ETriggerEvent::Completed, this, &UMoveInteractableModificator::TurnOffRotating).GetHandle();
bindindingHandlers.Add(handle);
}
else if(mapping.Key == EKeys::MouseWheelAxis)
@ -67,93 +78,87 @@ void UMoveInteractableModificator::Bind_Implementation(class UEnhancedInputCompo
void UMoveInteractableModificator::Unbind_Implementation()
{
if(!lastInput)
if(!lastInput || bindindingHandlers.IsEmpty())
return;
if(state != State::Nothing)
if(holding || rotating)
return;
for(auto handle : bindindingHandlers)
{
lastInput->RemoveBindingByHandle(handle);
}
bindindingHandlers.Empty();
state = static_cast<State>(0);
ProcessState();
SetComponentTickEnabled(false);
actor->_Deactivate(GetActivatorTypes());
OnMoveDeactivated.Broadcast();
}
void UMoveInteractableModificator::IncreaseState()
void UMoveInteractableModificator::TurnOnHolding()
{
state = static_cast<State>(static_cast<uint8>(state) + 1);
if(static_cast<uint8>(state) > static_cast<uint8>(State::Rotating))
state = State::Rotating;
holding = true;
ProcessState();
distance = (player->GetCameraLocation() - actor->GetActorLocation()).Length();
AMainGameModeBase::GetWidgetManager()->AnimateInteractionHint(this, 0, EInteractableHintWidgetAnimation::Hold);
OnHolding.Broadcast();
}
void UMoveInteractableModificator::DecreaseState()
void UMoveInteractableModificator::TurnOffHolding()
{
state = static_cast<State>(static_cast<uint8>(state) - 1);
if(static_cast<uint8>(state) > static_cast<uint8>(State::Rotating))
state = State::Nothing;
holding = false;
ProcessState();
AMainGameModeBase::GetWidgetManager()->AnimateInteractionHint(this, 0, EInteractableHintWidgetAnimation::Unhold);
}
void UMoveInteractableModificator::TurnOnRotating()
{
rotating = true;
player->cameraLocked = true;
ProcessState();
AMainGameModeBase::GetWidgetManager()->AnimateInteractionHint(this, 1, EInteractableHintWidgetAnimation::Hold);
OnRotating.Broadcast();
}
void UMoveInteractableModificator::TurnOffRotating()
{
rotating = false;
player->cameraLocked = false;
ProcessState();
AMainGameModeBase::GetWidgetManager()->AnimateInteractionHint(this, 1, EInteractableHintWidgetAnimation::Unhold);
}
void UMoveInteractableModificator::ProcessState()
{
switch(state)
if(holding || rotating)
{
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;
actor->activationLockers.Add(this);
}
if(state == State::Nothing)
else
{
if((actor->GetActivatedFlags() & static_cast<uint32>(EActivatorType::Use)) == 0
&& bindindingHandlers.Num() > 0)
actor->activationLockers.Remove(this);
if((actor->GetActivatedFlags() & static_cast<int32>(GetActivatorTypes())) == 0
&& !bindindingHandlers.IsEmpty())
{
Unbind_Implementation();
}
}
}
void UMoveInteractableModificator::UpdatePosition(float deltaTime)
void UMoveInteractableModificator::UpdatePosition()
{
if(!player)
if(!player || (!holding && !rotating))
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);
//auto oldLoc = actor->GetActorLocation();
//auto interpLoc = FMath::VInterpTo(oldLoc, newLoc, GetWorld()->GetDeltaSeconds(), 20.0f);
//auto interpLoc = FMath::Lerp(oldLoc, newLoc, 0.5f);
actor->SetActorLocation(newLoc, true, nullptr, ETeleportType::None);
}
void UMoveInteractableModificator::Zooming(const FInputActionValue& value)
{
if(state != State::Holding)
if(!holding && !rotating)
return;
distance += value.Get<float>() * zoomSpeed;
@ -162,10 +167,13 @@ void UMoveInteractableModificator::Zooming(const FInputActionValue& value)
void UMoveInteractableModificator::Rotating(const FInputActionValue& axis)
{
if(state != State::Rotating)
if(!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);
auto currentRot = actor->GetActorRotation();
auto currentLoc = actor->GetActorLocation();
auto newRot = FRotator{ v.Y * vec.X, v.X, v.Y * vec.Y * -1 };
actor->AddActorWorldRotation(newRot, true, nullptr, ETeleportType::None); // sweep not supported from 4.xx+
}

View File

@ -20,8 +20,7 @@ class UMoveInteractableModificator : public UInteractableModificator
public:
UMoveInteractableModificator(const FObjectInitializer& ObjectInitializer);
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
void Bind_Implementation(class UEnhancedInputComponent* input) override;
void Unbind_Implementation() override;
@ -44,23 +43,19 @@ protected:
float rotateSpeed = 10.0f;
private:
void IncreaseState();
void DecreaseState();
void TurnOnHolding();
void TurnOffHolding();
void TurnOnRotating();
void TurnOffRotating();
void ProcessState();
void UpdatePosition(float deltaTime);
void UpdatePosition();
void Zooming(const FInputActionValue& value);
void Rotating(const FInputActionValue& axis);
enum class State : uint8
{
Nothing = 0,
Holding,
Rotating
};
class UEnhancedInputComponent* lastInput;
class UEnhancedInputComponent* lastInput = nullptr;
TArray<int32> bindindingHandlers;
State state = State::Nothing;
class AInteractable* actor;
class APlayerBase* player;
bool holding = false;
bool rotating = false;
class AInteractable* actor = nullptr;
class APlayerBase* player = nullptr;
};

View File

@ -14,6 +14,7 @@
#include "CustomGameInstanceBase.h"
#include "CustomGameUserSettings.h"
#include "Interactable/Activators/InteractableActivator.h"
#include "Interactable/Modificators/InteractableModificator.h"
#include "MainGameModeBase.h"
APlayerBase::APlayerBase()
@ -28,11 +29,12 @@ void APlayerBase::Tick(float DeltaTime)
// stabilize move speed by fps
AddActorLocalOffset(ConsumeMovementInputVector() * DeltaTime);
if(moved)
{
moved = false;
//OnPlayerMoved.Broadcast();
}
// update isMoving flag
auto loc = GetActorLocation();
isMoving = (loc != oldLocation);
oldLocation = std::move(loc);
rotationInput = FRotator::ZeroRotator;
}
void APlayerBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
@ -46,6 +48,7 @@ void APlayerBase::BeginPlay()
auto world = GetWorld();
oldLocation = GetActorLocation();
GetCharacterMovement()->MaxWalkSpeed = moveSpeed;
cameraManager = UGameplayStatics::GetPlayerCameraManager(world, 0);
@ -63,12 +66,12 @@ void APlayerBase::BeginPlay()
camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f;
}
if(auto PC = Cast<APlayerController>(GetController()))
playerController = Cast<APlayerController>(GetController());
if(playerController)
{
inputComponent = Cast<UEnhancedInputComponent>(PC->InputComponent);;
inputComponent = Cast<UEnhancedInputComponent>(playerController->InputComponent);;
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
if(auto inputSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(playerController->GetLocalPlayer()))
{
if(auto GI = Cast<UCustomGameInstanceBase>(GetWorld()->GetGameInstance()))
{
@ -108,7 +111,7 @@ void APlayerBase::AttachToCamera(AActor* actor)
FVector APlayerBase::GetCameraDirection()
{
return camera->GetComponentRotation().Vector();
return camera->GetForwardVector();
}
FVector APlayerBase::GetCameraLocation()
{
@ -132,9 +135,9 @@ void APlayerBase::MoveCamera(FVector2D value)
return;
AddControllerYawInput(value.X);
rotationInput.Yaw = value.X;
AddControllerPitchInput(value.Y);
moved = true;
rotationInput.Pitch = value.Y;
}
void APlayerBase::MoveCharacter(FVector2D value)
@ -142,10 +145,10 @@ void APlayerBase::MoveCharacter(FVector2D value)
if(moveLocked)
return;
AddMovementInput(GetActorRightVector(), value.X);
AddMovementInput(GetActorForwardVector(), value.Y);
moved = true;
moveVector = GetActorRightVector() * value.X;
moveVector += GetActorForwardVector() * value.Y;
moveVector.Normalize(UE_KINDA_SMALL_NUMBER);
AddMovementInput(moveVector);
}
void APlayerBase::Jump()
@ -154,8 +157,6 @@ void APlayerBase::Jump()
return;
ACharacter::Jump();
moved = true;
}
void APlayerBase::SwitchRun(bool run)

View File

@ -26,9 +26,11 @@ public:
void AttachToCamera(AActor* actor);
FVector GetCameraLocation();
FVector GetCameraDirection();
bool IsMoving() { return isMoving; }
UPROPERTY(BlueprintAssignable)
FPlayerMovedDelegate OnPlayerMoved;
FVector moveVector;
class UEnhancedInputComponent* inputComponent;
UPROPERTY(EditAnywhere)
@ -53,6 +55,7 @@ protected:
UFUNCTION(BlueprintCallable, Category = Character)
void UpdatePitch(float min, float max);
class APlayerController* playerController;
UPROPERTY(EditAnywhere)
float moveSpeed = 200;
UPROPERTY(EditAnywhere)
@ -72,10 +75,14 @@ protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
float maxPitch = 65;
bool moved = false;
UPROPERTY(BlueprintReadOnly)
bool isMoving = false;
private:
void LoadInteractablesActivators();
void InteractableActivated(AInteractable* interactable, EActivatorType type);
void InteractableDeactivated(AInteractable* interactable, EActivatorType type);
FVector oldLocation;
FRotator rotationInput;
};

View File

@ -2,4 +2,3 @@
#include "InteractableHintWidget.h"

View File

@ -2,22 +2,36 @@
#pragma once
#include "Blueprint/UserWidget.h"
#include "CoreMinimal.h"
#include "ResolutionResponsiveUserWidget.h"
#include "InteractableHintWidget.generated.h"
UENUM(BlueprintType)
enum class EInteractableHintWidgetAnimation : uint8
{
Click,
Hold,
Unhold
};
UCLASS(Blueprintable)
class UInteractableHintWidget : public UUserWidget
class UInteractableHintWidget : public UResolutionResponsiveUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Show();
virtual void Show_Implementation() {}
UFUNCTION(BlueprintImplementableEvent)
void OnClick();
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Proceed();
virtual void Proceed_Implementation() {}
UFUNCTION(BlueprintImplementableEvent)
void OnHold();
UFUNCTION(BlueprintImplementableEvent)
void OnUnhold();
UPROPERTY(meta = (BindWidget))
class UTextBlock* keyText;
UPROPERTY(meta = (BindWidget))
class UTextBlock* descriptionText;
};

View File

@ -2,3 +2,92 @@
#include "InteractableHintWidgetManager.h"
#include "Blueprint/WidgetTree.h"
#include "Components/TextBlock.h"
#include "Components/VerticalBox.h"
#include "InputMappingContext.h"
#include "Interactable/Modificators/InteractableModificator.h"
#include "Widgets/InteractableHintWidget.h"
void UInteractableHintWidgetManager::Append(const class UInteractableModificator* modificator)
{
FScopeLock Lock(&hintsLock);
if(hintsMap.Contains(modificator))
return;
const auto& mappings = modificator->GetMappingContext()->GetMappings();
for(int32 i = hints->GetChildrenCount() - count - mappings.Num(); i < 0; ++i)
{
auto hint = WidgetTree->ConstructWidget<UInteractableHintWidget>(hintWidgetClass);
hint->SetVisibility(ESlateVisibility::Hidden);
hints->AddChild(hint);
}
int32 skipped = 0;
for(int32 i = 0; i < mappings.Num(); ++i)
{
if(mappings[i].Action->ActionDescription.ToString().Equals("!hide!", ESearchCase::IgnoreCase))
{
++skipped;
continue;
}
auto hint = Cast<UInteractableHintWidget>(hints->GetChildAt(count++));
hint->keyText->SetText(mappings[i].Key.GetDisplayName(false));
hint->descriptionText->SetText(mappings[i].Action->ActionDescription);
hint->SetVisibility(ESlateVisibility::Visible);
}
hintsMap.Add(modificator, { count - mappings.Num() + skipped, mappings.Num() - skipped });
}
void UInteractableHintWidgetManager::Remove(const class UInteractableModificator* modificator)
{
FScopeLock Lock(&hintsLock);
if(!hintsMap.Contains(modificator))
return;
auto& indexAndCount = hintsMap[modificator];
for(int32 i = 0; i < indexAndCount.Value; ++i)
{
auto hint = hints->GetChildAt(indexAndCount.Key);
hint->SetVisibility(ESlateVisibility::Hidden);
hints->RemoveChildAt(indexAndCount.Key);
hints->AddChild(hint);
--count;
}
hintsMap.Remove(modificator);
}
void UInteractableHintWidgetManager::AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index,
const EInteractableHintWidgetAnimation animation)
{
FScopeLock Lock(&hintsLock);
if(!hintsMap.Contains(modificator))
return;
auto& indexAndCount = hintsMap[modificator];
auto hint = Cast<UInteractableHintWidget>(hints->GetChildAt(indexAndCount.Key + index));
switch(animation)
{
case EInteractableHintWidgetAnimation::Click:
hint->OnClick();
break;
case EInteractableHintWidgetAnimation::Hold:
hint->OnHold();
break;
case EInteractableHintWidgetAnimation::Unhold:
hint->OnUnhold();
break;
default:
break;
}
}

View File

@ -3,33 +3,27 @@
#pragma once
#include "Blueprint/UserWidget.h"
#include "CoreMinimal.h"
#include "InteractableHintWidgetManager.generated.h"
enum class EActivatorType : uint8;
UCLASS(Blueprintable)
class UInteractableHintWidgetManager : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Append(const class UInteractableModificator* modificator);
virtual void Append_Implementation(const class UInteractableModificator* modificator) {}
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void Remove(EActivatorType type);
virtual void Remove_Implementation(EActivatorType type) {}
void Remove(const class UInteractableModificator* modificator);
void AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index, const EInteractableHintWidgetAnimation animation);
protected:
UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UInteractableHintWidget> interactableHintPressWidgetClass;
class UInteractableHintWidget* interactableHintPressWidget;
TSubclassOf<class UInteractableHintWidget> hintWidgetClass;
UPROPERTY(EditDefaultsOnly)
TSubclassOf<class UInteractableHintWidget> interactableHintHoldWidgetClass;
class UInteractableHintWidget* interactableHintHoldWidget;
UPROPERTY(meta = (BindWidget))
class UVerticalBox* hints;
int32 count = 0;
TMap<const class UInteractableModificator*, TPair<int32, int32>> hintsMap;
FCriticalSection hintsLock;
};

View File

@ -88,10 +88,15 @@ void UWidgetsManager::UpdateOverlayWidgetsOwner()
void UWidgetsManager::ShowInteractionHints(const UInteractableModificator* modificator)
{
if(interactableHintWidgetManager.IsValid())
interactableHintWidgetManager->Append_Implementation(modificator);
interactableHintWidgetManager->Append(modificator);
}
void UWidgetsManager::HideInteractionHints(const EActivatorType type)
void UWidgetsManager::HideInteractionHints(const UInteractableModificator* modificator)
{
if(interactableHintWidgetManager.IsValid())
interactableHintWidgetManager->Remove_Implementation(type);
interactableHintWidgetManager->Remove(modificator);
}
void UWidgetsManager::AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index, const EInteractableHintWidgetAnimation animation)
{
if(interactableHintWidgetManager.IsValid())
interactableHintWidgetManager->AnimateInteractionHint(modificator, index, animation);
}

View File

@ -7,7 +7,7 @@
#include "WidgetsManager.generated.h"
enum class EActivatorType : uint8;
enum class EInteractableHintWidgetAnimation : uint8;
UCLASS(Blueprintable)
class UWidgetsManager : public UObject
@ -22,7 +22,8 @@ public:
void UpdateOverlayWidgetsOwner();
void ShowInteractionHints(const class UInteractableModificator* modificator);
void HideInteractionHints(const EActivatorType type);
void HideInteractionHints(const class UInteractableModificator* modificator);
void AnimateInteractionHint(const class UInteractableModificator* modificator, const int32 index, const EInteractableHintWidgetAnimation animation);
protected:
UPROPERTY(EditDefaultsOnly)