Fixes for placeable objects and inventory tabs
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/Prefabs/Tree2.uasset
LFS
BIN
Content/Prefabs/Tree2.uasset
LFS
Binary file not shown.
BIN
Content/Prefabs/Tree3.uasset
LFS
BIN
Content/Prefabs/Tree3.uasset
LFS
Binary file not shown.
BIN
Content/Prefabs/Tree4.uasset
LFS
BIN
Content/Prefabs/Tree4.uasset
LFS
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -11,6 +11,7 @@
|
||||
#include "../Public/EleriPlayerController.h"
|
||||
#include "../Public/MyCharacter.h"
|
||||
#include "Engine/OverlapResult.h"
|
||||
#include "LandscapeProxy.h"
|
||||
|
||||
// Sets default values for this component's properties
|
||||
UMoveActorsComponent::UMoveActorsComponent()
|
||||
@@ -18,8 +19,6 @@ UMoveActorsComponent::UMoveActorsComponent()
|
||||
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
|
||||
// off to improve performance if you don't need them.
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +30,19 @@ void UMoveActorsComponent::BeginPlay()
|
||||
PlayerController = Cast<AEleriPlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0));
|
||||
PlayerCharacter = Cast<AMyCharacter>(GetOwner());
|
||||
|
||||
if (!PlayerCharacter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<AActor*> OutActors;
|
||||
PlayerCharacter->GetOverlappingActors(OutActors);
|
||||
for (auto Actor : OutActors)
|
||||
for (const AActor* Actor : OutActors)
|
||||
{
|
||||
if(PlantableAreaActorClass == Actor->GetClass())
|
||||
if (Actor && PlantableAreaActorClass == Actor->GetClass())
|
||||
{
|
||||
bRemovalModePossible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,114 +53,121 @@ void UMoveActorsComponent::TickComponent(float DeltaTime, ELevelTick TickType, F
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
if (!PlayerCharacter || !MovingActor) return;
|
||||
if (!PlayerCharacter || !IsValid(MovingActor) || MovingActor->bPlaced) return;
|
||||
|
||||
if (!MovingActor->bPlaced)
|
||||
FVector ForwardVec = PlayerCharacter->GetActorForwardVector();
|
||||
if (PlayerController && PlayerController->PlayerCameraManager)
|
||||
{
|
||||
FVector ForwardVec;
|
||||
if (APlayerCameraManager* CameraManager = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0))
|
||||
ForwardVec = PlayerController->PlayerCameraManager->GetCameraRotation().Vector();
|
||||
ForwardVec.Z = 0.f;
|
||||
}
|
||||
|
||||
// Prefer the per-actor tuning values, falling back to the component defaults.
|
||||
const float Distance = MovingActor->DistanceFromActor > 0.f ? MovingActor->DistanceFromActor : PlacementDistance;
|
||||
const float GridSnap = MovingActor->GridScale > 0.f ? MovingActor->GridScale : GridSnapSize;
|
||||
|
||||
FVector PosVector = PlayerCharacter->GetActorLocation() + (ForwardVec * Distance) + FVector(0.f, 0.f, PlacementHeightOffset);
|
||||
|
||||
if (bGridMovementActive)
|
||||
{
|
||||
PosVector = UKismetMathLibrary::Vector_SnappedToGrid(PosVector, GridSnap);
|
||||
}
|
||||
|
||||
const FVector TargetScale = (MovingActor->ScaleOverride != FVector::ZeroVector) ? MovingActor->ScaleOverride : MovingActor->GetActorScale();
|
||||
MovingActor->SetActorTransform(FTransform(MovingActor->GetActorRotation(), PosVector, TargetScale));
|
||||
|
||||
// Snap the object down onto the ground beneath it.
|
||||
FCollisionObjectQueryParams QueryParams;
|
||||
QueryParams.AddObjectTypesToQuery(ECC_WorldStatic);
|
||||
|
||||
const FVector TraceEnd = MovingActor->GetActorLocation() + FVector(0.f, 0.f, -GroundTraceLength);
|
||||
TArray<FHitResult> OutHits;
|
||||
GetWorld()->LineTraceMultiByObjectType(OutHits, MovingActor->GetActorLocation(), TraceEnd, QueryParams);
|
||||
|
||||
MovingActor->bPlaceable = true;
|
||||
MovingActor->IntersectingActors.Empty();
|
||||
for (const FHitResult& HitResult : OutHits)
|
||||
{
|
||||
AActor* HitActor = HitResult.GetActor();
|
||||
if (!HitActor || HitActor == MovingActor) continue;
|
||||
|
||||
MovingActor->IntersectingActors.Add(HitActor);
|
||||
|
||||
if (HitActor->IsA(ALandscapeProxy::StaticClass()))
|
||||
{
|
||||
ForwardVec = CameraManager->GetCameraRotation().Vector();
|
||||
ForwardVec.Z = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ForwardVec = PlayerCharacter->GetActorForwardVector();
|
||||
}
|
||||
//FVector PosVector = UKismetMathLibrary::Vector_SnappedToGrid(PlayerCharacter->GetActorLocation() + ((ForwardVec * MovingActor->DistanceFromActor) + FVector(0.f, 0.f, 100.f)), MovingActor->GridScale);
|
||||
|
||||
FVector PosVector = PlayerCharacter->GetActorLocation() + ((ForwardVec * 800.f) + FVector(0.f, 0.f, 100.f));
|
||||
|
||||
if (bGridMovementActive)
|
||||
{
|
||||
PosVector = UKismetMathLibrary::Vector_SnappedToGrid(PosVector, 250.f);
|
||||
}
|
||||
|
||||
FTransform NewTransform = FTransform(MovingActor->GetActorRotation(), PosVector, (MovingActor->ScaleOverride != FVector::ZeroVector) ? MovingActor->ScaleOverride : MovingActor->GetActorScale());
|
||||
MovingActor->SetActorTransform(NewTransform);
|
||||
|
||||
|
||||
TArray<FHitResult> OutHits;
|
||||
FCollisionObjectQueryParams QueryParams;
|
||||
QueryParams.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldStatic);
|
||||
FVector TraceEnd = (MovingActor->GetActorLocation() + FVector(0.f, 0.f, -1000.f));
|
||||
GetWorld()->LineTraceMultiByObjectType(OutHits, MovingActor->GetActorLocation(), TraceEnd, QueryParams);
|
||||
|
||||
MovingActor->bPlaceable = true;
|
||||
MovingActor->IntersectingActors.Empty();
|
||||
for (const FHitResult& HitResult : OutHits)
|
||||
{
|
||||
if (HitResult.GetActor() == MovingActor) continue;
|
||||
|
||||
MovingActor->IntersectingActors.Add(HitResult.GetActor());
|
||||
|
||||
if (HitResult.GetActor()->GetClass()->GetName() == FString("Landscape"))
|
||||
{
|
||||
MovingActor->SetActorLocation(HitResult.ImpactPoint);
|
||||
}
|
||||
}
|
||||
|
||||
//Check if moving object is overlapping
|
||||
TArray<AActor*> OverlappingActors;
|
||||
FVector Center, BoxExtent;
|
||||
MovingActor->GetActorBounds(false, Center, BoxExtent);
|
||||
BoxExtent *= 0.9f;
|
||||
if (!MovingActor->BoxExtentOverride.IsNearlyZero())
|
||||
{
|
||||
BoxExtent = MovingActor->BoxExtentOverride;
|
||||
}
|
||||
|
||||
TArray<FOverlapResult> OverlapResults;
|
||||
FCollisionQueryParams QueryParams1;
|
||||
QueryParams1.bTraceComplex = true;
|
||||
QueryParams1.AddIgnoredActor(MovingActor);
|
||||
QueryParams1.AddIgnoredActor(PlayerCharacter);
|
||||
FCollisionObjectQueryParams ObjectQueryParams;
|
||||
ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldStatic);
|
||||
ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldDynamic);
|
||||
ObjectQueryParams.AddObjectTypesToQuery(ECC_GameTraceChannel1);
|
||||
ObjectQueryParams.AddObjectTypesToQuery(ECC_GameTraceChannel2);
|
||||
|
||||
bool bHit = GetWorld()->OverlapMultiByObjectType(
|
||||
OverlapResults,
|
||||
MovingActor->GetActorLocation(),
|
||||
FQuat::Identity,
|
||||
ObjectQueryParams,
|
||||
FCollisionShape::MakeBox(BoxExtent), // Or MakeSphere, MakeCapsule
|
||||
QueryParams1
|
||||
);
|
||||
for (const FOverlapResult& OverlapResult : OverlapResults)
|
||||
{
|
||||
if (OverlapResult.GetActor())
|
||||
OverlappingActors.Add(OverlapResult.GetActor());
|
||||
}
|
||||
//DrawDebugBox(GetWorld(), MovingActor->GetActorLocation(), BoxExtent, FColor::Red);
|
||||
bool PlantableAreaFound = false;
|
||||
for (auto OverlappingActor : OverlappingActors)
|
||||
{
|
||||
if (OverlappingActor->GetClass() == PlantableAreaActorClass)
|
||||
{
|
||||
PlantableAreaFound = true;
|
||||
}
|
||||
|
||||
if (OverlappingActor->GetClass()->GetName() == FString("Landscape") ||
|
||||
!OverlappingActor->GetClass()->IsChildOf(AStaticMeshActor::StaticClass())) continue;
|
||||
|
||||
if (!ActorsToIgnore.FindByPredicate([&OverlappingActor](const TSubclassOf<AActor>& ActorClass) { return OverlappingActor->GetClass() == ActorClass; }))
|
||||
{
|
||||
MovingActor->bPlaceable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!PlantableAreaFound)
|
||||
MovingActor->bPlaceable = false;
|
||||
|
||||
if (MovingActor)
|
||||
{
|
||||
MovingActor->GetStaticMeshComponent()->SetOverlayMaterial((!MovingActor->bPlaceable) ? MovingActor->CantPlaceMaterial : MovingActor->CanPlaceMaterial);
|
||||
MovingActor->K2_TogglePlaceableEffects(MovingActor->bPlaceable);
|
||||
MovingActor->SetActorLocation(HitResult.ImpactPoint);
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the object overlaps anything that should block placement.
|
||||
FVector Center, BoxExtent;
|
||||
MovingActor->GetActorBounds(false, Center, BoxExtent);
|
||||
BoxExtent *= OverlapBoxExtentMultiplier;
|
||||
if (!MovingActor->BoxExtentOverride.IsNearlyZero())
|
||||
{
|
||||
BoxExtent = MovingActor->BoxExtentOverride;
|
||||
}
|
||||
|
||||
FCollisionQueryParams OverlapQueryParams;
|
||||
OverlapQueryParams.bTraceComplex = true;
|
||||
OverlapQueryParams.AddIgnoredActor(MovingActor);
|
||||
OverlapQueryParams.AddIgnoredActor(PlayerCharacter);
|
||||
|
||||
FCollisionObjectQueryParams ObjectQueryParams;
|
||||
ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldStatic);
|
||||
ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldDynamic);
|
||||
ObjectQueryParams.AddObjectTypesToQuery(ECC_GameTraceChannel1);
|
||||
ObjectQueryParams.AddObjectTypesToQuery(ECC_GameTraceChannel2);
|
||||
|
||||
TArray<FOverlapResult> OverlapResults;
|
||||
GetWorld()->OverlapMultiByObjectType(
|
||||
OverlapResults,
|
||||
MovingActor->GetActorLocation(),
|
||||
MovingActor->GetActorQuat(),
|
||||
ObjectQueryParams,
|
||||
FCollisionShape::MakeBox(BoxExtent),
|
||||
OverlapQueryParams
|
||||
);
|
||||
|
||||
bool PlantableAreaFound = false;
|
||||
for (const FOverlapResult& OverlapResult : OverlapResults)
|
||||
{
|
||||
AActor* OverlappingActor = OverlapResult.GetActor();
|
||||
if (!OverlappingActor) continue;
|
||||
|
||||
if (PlantableAreaActorClass == OverlappingActor->GetClass())
|
||||
{
|
||||
PlantableAreaFound = true;
|
||||
}
|
||||
|
||||
// Landscape and non-static-mesh actors don't block placement.
|
||||
if (OverlappingActor->IsA(ALandscapeProxy::StaticClass()) || !OverlappingActor->GetClass()->IsChildOf(AStaticMeshActor::StaticClass()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool bIsIgnored = ActorsToIgnore.ContainsByPredicate([&OverlappingActor](const TSubclassOf<AActor>& ActorClass)
|
||||
{
|
||||
return OverlappingActor->GetClass() == ActorClass;
|
||||
});
|
||||
|
||||
if (!bIsIgnored)
|
||||
{
|
||||
MovingActor->bPlaceable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PlantableAreaFound)
|
||||
{
|
||||
MovingActor->bPlaceable = false;
|
||||
}
|
||||
|
||||
if (UStaticMeshComponent* MeshComponent = MovingActor->GetStaticMeshComponent())
|
||||
{
|
||||
MeshComponent->SetOverlayMaterial((!MovingActor->bPlaceable) ? MovingActor->CantPlaceMaterial : MovingActor->CanPlaceMaterial);
|
||||
}
|
||||
MovingActor->K2_TogglePlaceableEffects(MovingActor->bPlaceable);
|
||||
}
|
||||
|
||||
void UMoveActorsComponent::ToggleGridMovement()
|
||||
@@ -172,20 +184,21 @@ bool UMoveActorsComponent::PlaceableActionUsed(ERemovalAction ActionUsed)
|
||||
switch (ActionUsed)
|
||||
{
|
||||
case ERemovalAction::NONE:
|
||||
case ERemovalAction::MAX:
|
||||
default:
|
||||
break;
|
||||
|
||||
case ERemovalAction::START_MOVE:
|
||||
if (AEleriPlayerController* PC = Cast<AEleriPlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0)))
|
||||
{
|
||||
PickUpObjectForPlacing(HighligtedMovingActor);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
return PickUpObjectForPlacing(HighligtedMovingActor);
|
||||
|
||||
case ERemovalAction::PLACE:
|
||||
if (PlayerController && MovingActor && MovingActor->IsPlaceable())
|
||||
if (PlayerController && MovingActor->IsPlaceable())
|
||||
{
|
||||
FPrimaryAssetId ItemId = MovingActor->ItemStack.ItemId;
|
||||
if (!ItemId.IsValid())
|
||||
{
|
||||
ItemId = MovingActor->DataAssetId;
|
||||
}
|
||||
if (ItemId.IsValid())
|
||||
{
|
||||
if (UInventoryComponent* Inventory = UMainBlueprintFunctionLibrary::GetPlayerInventory(GetWorld()))
|
||||
@@ -197,52 +210,50 @@ bool UMoveActorsComponent::PlaceableActionUsed(ERemovalAction ActionUsed)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
//Will place it in inventory
|
||||
|
||||
case ERemovalAction::REMOVE:
|
||||
case ERemovalAction::EXIT:
|
||||
if (UGameInstance* GI = UGameplayStatics::GetGameInstance(GetWorld()))
|
||||
{
|
||||
// A world object is returned to the player's inventory before it is removed.
|
||||
if (MovingActor->DataAssetId.IsValid() && !MovingActor->bFromInventory)
|
||||
{
|
||||
if (UObjectPersistenceSubsystem* ObjectPersistenceSubsystem = GI->GetSubsystem<UObjectPersistenceSubsystem>())
|
||||
if (UInventoryComponent* Inventory = UMainBlueprintFunctionLibrary::GetPlayerInventory(GetWorld()))
|
||||
{
|
||||
Inventory->AddItemToInventory(MovingActor->DataAssetId, 1, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(GetWorld()))
|
||||
{
|
||||
if (UObjectPersistenceSubsystem* ObjectPersistenceSubsystem = GameInstance->GetSubsystem<UObjectPersistenceSubsystem>())
|
||||
{
|
||||
if (MovingActor)
|
||||
{
|
||||
if (MovingActor->DataAssetId.IsValid() && !MovingActor->bFromInventory)
|
||||
{
|
||||
if (UInventoryComponent* Inventory = UMainBlueprintFunctionLibrary::GetPlayerInventory(GetWorld()))
|
||||
{
|
||||
Inventory->AddItemToInventory(MovingActor->DataAssetId, 1, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectPersistenceSubsystem->RemoveActorFromLevel(MovingActor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*if (MovingActor->InventoryRef)
|
||||
|
||||
// Fallback if the persistence subsystem is unavailable.
|
||||
MovingActor->Destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
case ERemovalAction::EXIT:
|
||||
{
|
||||
// Cancel the current placement/move without committing it.
|
||||
if (MovingActor->bFromInventory)
|
||||
{
|
||||
PlaceableActionUsed(ERemovalAction::REMOVE);
|
||||
// A preview spawned from the inventory: return the item and destroy the preview.
|
||||
MovingActor->ReturnToInventory();
|
||||
MovingActor->Destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
// An existing world object: put it back where it was picked up from.
|
||||
MovingActor->SetActorTransform(MovingActor->CurrentMemorizedTransform);
|
||||
for (int32 i = 0; i < MovingActor->MeshMaterials.Num(); i++)
|
||||
{
|
||||
MovingActor->GetStaticMeshComponent()->SetMaterial(i, MovingActor->MeshMaterials[i]);
|
||||
}
|
||||
MovingActor->GetStaticMeshComponent()->SetOverlayMaterial(nullptr);
|
||||
if (PlayerController)
|
||||
{
|
||||
PlaceObjectForPlacing();
|
||||
}
|
||||
return true;
|
||||
}*/
|
||||
break;
|
||||
case ERemovalAction::MAX:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -253,7 +264,7 @@ void UMoveActorsComponent::ToggleRemovalModeOption(bool bNewRemoveModePossible)
|
||||
|
||||
bool UMoveActorsComponent::PickUpObjectForPlacing(ARemovableStaticMeshActor* Placable)
|
||||
{
|
||||
if (MovingActor || !Placable || !PlayerController) return false;
|
||||
if (MovingActor || !IsValid(Placable) || !PlayerController) return false;
|
||||
|
||||
// Get the Enhanced Input Local Player Subsystem from the Local Player related to our Player Controller.
|
||||
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
|
||||
@@ -268,16 +279,14 @@ bool UMoveActorsComponent::PickUpObjectForPlacing(ARemovableStaticMeshActor* Pla
|
||||
|
||||
bool UMoveActorsComponent::PlaceObjectForPlacing()
|
||||
{
|
||||
if (!MovingActor) return false;
|
||||
if (!IsValid(MovingActor)) return false;
|
||||
|
||||
if (MovingActor)
|
||||
if (UStaticMeshComponent* MeshComponent = MovingActor->GetStaticMeshComponent())
|
||||
{
|
||||
if (MovingActor->GetStaticMeshComponent())
|
||||
{
|
||||
MovingActor->GetStaticMeshComponent()->SetOverlayMaterial(nullptr);
|
||||
}
|
||||
MovingActor->Place();
|
||||
MeshComponent->SetOverlayMaterial(nullptr);
|
||||
}
|
||||
MovingActor->Place();
|
||||
|
||||
RemovalModePlacingStack--;
|
||||
return RemoveObjectForPlacing();
|
||||
}
|
||||
@@ -290,9 +299,11 @@ bool UMoveActorsComponent::RemoveObjectForPlacing()
|
||||
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
|
||||
{
|
||||
if (RemovalModePlacingStack <= 0)
|
||||
{
|
||||
Subsystem->RemoveMappingContext(PlayerController->RemoveModeContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MovingActor = nullptr;
|
||||
return true;
|
||||
}
|
||||
@@ -300,9 +311,11 @@ bool UMoveActorsComponent::RemoveObjectForPlacing()
|
||||
|
||||
void UMoveActorsComponent::StartObjectRemoval(bool bStart, int32 Stack)
|
||||
{
|
||||
if (!PlayerCharacter) return;
|
||||
|
||||
if (!bStart)
|
||||
{
|
||||
PlayerCharacter->bAlreadyInteracting = bStart;
|
||||
PlayerCharacter->bAlreadyInteracting = false;
|
||||
}
|
||||
PlayerCharacter->CurrentlyDoing = bStart ? ECurrentlyDoing::OBJECT_PLACING : ECurrentlyDoing::NOTHING;
|
||||
|
||||
@@ -312,29 +325,33 @@ void UMoveActorsComponent::StartObjectRemoval(bool bStart, int32 Stack)
|
||||
if (!bStart)
|
||||
{
|
||||
PlayerCharacter->ZoomBack(0.5f);
|
||||
|
||||
}
|
||||
else if (bStart)
|
||||
else
|
||||
{
|
||||
PlayerCharacter->ZoomCamera(-500.f, 0.5f);
|
||||
PlayerCharacter->ZoomCamera(500.f, 0.5f);
|
||||
}
|
||||
|
||||
bRemovalMode = bStart;
|
||||
OnRemovalModeToggled.Broadcast(bRemovalMode);
|
||||
|
||||
PlayerCharacter->SetNewCameraPitches(
|
||||
bStart? PlayerCharacter->CameraPitchMin - 50 : PlayerCharacter->CameraPitchMin,
|
||||
bStart? PlayerCharacter->CameraPitchMax + 5 : PlayerCharacter->CameraPitchMax);
|
||||
bStart ? PlayerCharacter->CameraPitchMin - 50 : PlayerCharacter->CameraPitchMin,
|
||||
bStart ? PlayerCharacter->CameraPitchMax + 5 : PlayerCharacter->CameraPitchMax);
|
||||
|
||||
if (PlayerController->GetMainGameWidget())
|
||||
if (PlayerController && PlayerController->GetMainGameWidget())
|
||||
{
|
||||
PlayerController->GetMainGameWidget()->SwitchKeybindsDisplay(bRemovalMode ? 4 : 1);
|
||||
}
|
||||
|
||||
// Get the Enhanced Input Local Player Subsystem from the Local Player related to our Player Controller.
|
||||
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
|
||||
if (PlayerController)
|
||||
{
|
||||
if (!bStart)
|
||||
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
|
||||
{
|
||||
Subsystem->RemoveMappingContext(PlayerController->RemoveModeContext);
|
||||
if (!bStart)
|
||||
{
|
||||
Subsystem->RemoveMappingContext(PlayerController->RemoveModeContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,38 +360,21 @@ void UMoveActorsComponent::StartObjectRemoval(bool bStart, int32 Stack)
|
||||
|
||||
bool UMoveActorsComponent::HighlightRemovableObject(ARemovableStaticMeshActor* Placable)
|
||||
{
|
||||
if (!bRemovalModePossible || !bRemovalMode) return false;
|
||||
if (!bRemovalModePossible || !bRemovalMode || !IsValid(Placable)) return false;
|
||||
|
||||
if (!HighligtedMovingActor)
|
||||
if (HighligtedMovingActor == Placable)
|
||||
{
|
||||
HighligtedMovingActor = Placable;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HighligtedMovingActor != Placable)
|
||||
{
|
||||
if (HighligtedMovingActor)
|
||||
{
|
||||
HighligtedMovingActor = Placable;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
HighligtedMovingActor = Placable;
|
||||
return true;
|
||||
}
|
||||
|
||||
void UMoveActorsComponent::UnhighlightRemovableObject(ARemovableStaticMeshActor* Placable)
|
||||
{
|
||||
if (Placable)
|
||||
if (Placable && HighligtedMovingActor == Placable)
|
||||
{
|
||||
if (HighligtedMovingActor == Placable)
|
||||
{
|
||||
HighligtedMovingActor = nullptr;
|
||||
}
|
||||
HighligtedMovingActor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,21 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TSubclassOf<AActor> PlantableAreaActorClass;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Placement")
|
||||
float PlacementDistance = 800.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Placement")
|
||||
float PlacementHeightOffset = 100.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Placement")
|
||||
float GridSnapSize = 250.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Placement")
|
||||
float GroundTraceLength = 1000.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Placement", meta = (ClampMin = "0.0", ClampMax = "1.0"))
|
||||
float OverlapBoxExtentMultiplier = 0.9f;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnRemovalModeToggled OnRemovalModeToggled;
|
||||
|
||||
@@ -84,9 +99,9 @@ public:
|
||||
FORCEINLINE bool IsGridMovementActive() const { return bGridMovementActive; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure)
|
||||
inline bool IsRemovingModePossible() { return bRemovalModePossible; }
|
||||
bool IsRemovingModePossible() const { return bRemovalModePossible; }
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure)
|
||||
inline bool IsRemovingMode() { return bRemovalMode; }
|
||||
bool IsRemovingMode() const { return bRemovalMode; }
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
|
||||
@@ -13,18 +13,61 @@
|
||||
ARemovableStaticMeshActor::ARemovableStaticMeshActor()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
||||
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
|
||||
SetRootComponent(RootComponent);
|
||||
|
||||
|
||||
WidgetComponent = CreateDefaultSubobject<UInteractionWidgetComponent>(TEXT("WidgetComponent"));
|
||||
WidgetComponent->SetupAttachment(RootComponent);
|
||||
|
||||
OverlapBoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("OverlapBoxComponent"));
|
||||
OverlapBoxComponent->SetupAttachment(RootComponent);
|
||||
// Detection only: the box never blocks anything, it only reports overlaps.
|
||||
OverlapBoxComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
||||
OverlapBoxComponent->SetCollisionObjectType(OverlapBoxObjectType);
|
||||
OverlapBoxComponent->SetCollisionResponseToAllChannels(ECR_Overlap);
|
||||
OverlapBoxComponent->SetCollisionResponseToChannel(ECC_Visibility, ECR_Ignore);
|
||||
OverlapBoxComponent->SetGenerateOverlapEvents(true);
|
||||
OverlapBoxComponent->SetCanEverAffectNavigation(false);
|
||||
}
|
||||
|
||||
void ARemovableStaticMeshActor::OnConstruction(const FTransform& Transform)
|
||||
{
|
||||
Super::OnConstruction(Transform);
|
||||
|
||||
UpdateOverlapBoxExtent();
|
||||
}
|
||||
|
||||
void ARemovableStaticMeshActor::UpdateOverlapBoxExtent()
|
||||
{
|
||||
if (!OverlapBoxComponent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OverlapBoxComponent->SetCollisionObjectType(OverlapBoxObjectType);
|
||||
|
||||
UStaticMeshComponent* MeshComponent = GetStaticMeshComponent();
|
||||
if (!MeshComponent || !MeshComponent->GetStaticMesh())
|
||||
{
|
||||
OverlapBoxComponent->SetBoxExtent(FVector::ZeroVector);
|
||||
return;
|
||||
}
|
||||
|
||||
// GetLocalBounds returns the mesh' bounding box in its own local space.
|
||||
FVector BoundsMin, BoundsMax;
|
||||
MeshComponent->GetLocalBounds(BoundsMin, BoundsMax);
|
||||
|
||||
OverlapBoxComponent->SetRelativeLocation((BoundsMin + BoundsMax) * 0.5f);
|
||||
OverlapBoxComponent->SetBoxExtent(!BoxExtentOverride.IsNearlyZero()
|
||||
? BoxExtentOverride
|
||||
: (BoundsMax - BoundsMin) * 0.5f);
|
||||
}
|
||||
|
||||
void ARemovableStaticMeshActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
// Keep the detection box in sync with the mesh that is actually assigned at runtime.
|
||||
UpdateOverlapBoxExtent();
|
||||
|
||||
PlayerRef = UGameplayStatics::GetActorOfClass(GetWorld(), AMyCharacter::StaticClass());
|
||||
if (PlayerRef) {
|
||||
MoveableComponent = PlayerRef->GetComponentByClass<UMoveActorsComponent>();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "Engine/StaticMeshActor.h"
|
||||
#include "../Public/InventoryComponent.h"
|
||||
#include "Components/InteractionWidgetComponent.h"
|
||||
#include "Components/BoxComponent.h"
|
||||
#include "Interface/InteractableActorInterface.h"
|
||||
|
||||
#include "RemovableStaticMeshActor.generated.h"
|
||||
@@ -28,6 +29,8 @@ public:
|
||||
ARemovableStaticMeshActor();
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void OnConstruction(const FTransform& Transform) override;
|
||||
|
||||
virtual void ToggleInteractableUI_Implementation(bool bActive) override;
|
||||
virtual bool IsInteractable_Implementation() const override;
|
||||
@@ -76,11 +79,24 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Removable Object")
|
||||
FPrimaryAssetId DataAssetId;
|
||||
|
||||
/** Overlap only collision box that always fits the static mesh' bounding box.
|
||||
* It never blocks anything, it only reports what the object currently overlaps. */
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Removable Object")
|
||||
UBoxComponent* OverlapBoxComponent;
|
||||
|
||||
/** Collision object type of OverlapBoxComponent. Defaults to the project's "RemovableStaticMEsh" channel. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Removable Object")
|
||||
TEnumAsByte<ECollisionChannel> OverlapBoxObjectType = ECC_GameTraceChannel2;
|
||||
|
||||
/** Resizes OverlapBoxComponent so it fits the mesh' bounding box (or BoxExtentOverride when that one is set). */
|
||||
UFUNCTION(BlueprintCallable, Category = "Removable Object")
|
||||
void UpdateOverlapBoxExtent();
|
||||
|
||||
//Used for movable actors to override their box extent for checking collision
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Removable Object")
|
||||
FVector BoxExtentOverride = FVector::ZeroVector;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BLueprintPure)
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure)
|
||||
FORCEINLINE bool IsPlaceable() const { return bPlaceable; }
|
||||
UFUNCTION(BlueprintCallable, BLueprintPure)
|
||||
FORCEINLINE bool FromInventory() const { return InventoryRef != nullptr; }
|
||||
|
||||
@@ -33,7 +33,7 @@ public class ProjectEleri : ModuleRules
|
||||
"InteractionSystem"
|
||||
});
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(new string[] { "OnlineSubsystem", "OnlineSubsystemUtils" });
|
||||
PrivateDependencyModuleNames.AddRange(new string[] { "OnlineSubsystem", "OnlineSubsystemUtils", "Landscape" });
|
||||
|
||||
// Uncomment if you are using Slate UI
|
||||
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "ObjectPersistenceSubsystem.h"
|
||||
#include "Interface/RemovableActorInterface.h"
|
||||
#include "../../Components/PlacableActorComponent.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "../../Public/EleriSaveGame.h"
|
||||
#include "../GameObjects/RemovableStaticMeshActor.h"
|
||||
@@ -27,16 +26,10 @@ void UObjectPersistenceSubsystem::RemoveActorFromLevel(AActor* ActorToRemove)
|
||||
|
||||
//Check if actor existed meaning we're placing it for the first time
|
||||
int32 ActorIndex = ActorExistsInList(ActorToRemove);
|
||||
if (ActorIndex == -1)
|
||||
{
|
||||
if (UPlacableActorComponent* Placeable = ActorToRemove->GetComponentByClass<UPlacableActorComponent>())
|
||||
{
|
||||
//Placeable->ReturnToInventory();
|
||||
}
|
||||
}
|
||||
else
|
||||
if (ActorIndex != INDEX_NONE)
|
||||
{
|
||||
PlacedActors.RemoveAt(ActorIndex);
|
||||
|
||||
}
|
||||
|
||||
ActorToRemove->Destroy();
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "ObjectPersistenceSubsystem.generated.h"
|
||||
|
||||
class UPlacableActorComponent;
|
||||
class UEleriSaveGame;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
|
||||
Reference in New Issue
Block a user