Files

1074 lines
38 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "Rover.h"
#include "InputAction.h"
#include "InputActionValue.h"
#include "InputMappingContext.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "RoverController.h"
#include "Kismet/GameplayStatics.h"
#include "CesiumGlobeAnchorComponent.h"
#include "Kismet/KismetMathLibrary.h"
#include "CesiumGeoreference.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "DrawDebugHelpers.h"
#include "Blueprint/UserWidget.h"
#include "CesiumFlyToComponent.h"
#include "GameFramework/PawnMovementComponent.h"
#include "Blueprint/WidgetLayoutLibrary.h"
#include "Engine/StaticMeshActor.h"
#include "Components/SceneCaptureComponent2D.h"
#include "ConvexVolume.h"
ARover* ARover::PlayerPawn = nullptr;
ARover::ARover():
bPressMouseMiddleKey(false),
SelfBaseTurnRate(10),
SelfBaseLookUpRate(10),
ZoomRollSpeed(5.f),
RotateAngle(0.1f),
bPressMouseRightKey(false),
bPressMouseLeftKey(false),
BaseMouseLeftMoveRate(50.f),
MoveToLocation(FVector(0)),
MaxDistance(1.f),
bMoveForward(false),
bMoveRight(false),
bLimitViewport(false),
bAllowMouseLeftMove(true),
ControlHeightMulitiplier(0.1f),
LongitudeLatitudeControlHeightMulitiplier(0.01),
MouseMoveOffsetMulitiplier(0.01),
bAllowUpdataMove(false),
SlowStopMoveSpeed(0),
TotalSlowStopMoveOffsetTime(0),
CurrentSlowStopMoveOffsetTime(0),
ChangeHeightThreshold(100000),
bFlying(false),
ZoomOffsetMulitiplier(0.1f),
ZoomOffsetHeightValue(1000000),
bFollowSportTrace(false),
CurrentMoveDistance(0),
MoveSpeedMultiplier(1.5f),
bAllowInertialMove(false),
CheckMoveCollisionChannel(ECollisionChannel::ECC_Visibility),
SelecteItemMode(ESelecteItemMode::ESM_Default),
LastSelecteItemMode(ESelecteItemMode::ESM_Default),
bTempStopAutoRotate(false)
{
PlayerPawn = this;
FlyComp = CreateDefaultSubobject<UCesiumFlyToComponent>(TEXT("FlyComp"));
FlyComp->RotationToUse = ECesiumFlyToRotation::ControlRotationInUnreal;
FlyComp->Duration = 3.f;
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComp"));
SpringArm->SetupAttachment(RootComponent);
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComp"));
Camera->SetupAttachment(SpringArm);
AutoPossessPlayer = EAutoReceiveInput::Player0;
}
void ARover::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
PlayerLongitudeLatitudeHeight = GlobeAnchor->GetLongitudeLatitudeHeight();
LastMousePosition = MousePosition;
PlayerController->GetMousePosition(MousePosition.X, MousePosition.Y);
UpdataMoveToLocation(DeltaTime);
if (GlobeAnchor->GetHeight() > 100000) {
if (PlayerController) {
//PlayerController->GetMainHUD()->CloseWeatherSystem();
}
}
UpdateSlideRotation(DeltaTime);
InertialMove(DeltaTime);
//GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::White, TEXT("Tick正在执行"));
}
void ARover::BeginPlay()
{
Super::BeginPlay();
PlayerController = Cast<ARoverController>(UGameplayStatics::GetPlayerController(GetWorld(), 0));
if (Georeference) {
FVector Location = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(FVector(106.405113, 29.720642, 7000000.0));
CurrentHeight = 7000000.0;
SetActorLocation(Location);
PlayerController->SetControlRotation(FRotator(-88.f, -90, 0));
Georeference->SetOriginLongitudeLatitudeHeight(FVector(106, 30, 1000.0));
}
}
void ARover::SetupPlayerInputComponent(UInputComponent* InInputComponent)
{
if (APlayerController* ThePlayerController = Cast<APlayerController>(GetController())) {
if (UEnhancedInputLocalPlayerSubsystem* LocalPlayerSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(ThePlayerController->GetLocalPlayer())) {
LocalPlayerSubsystem->AddMappingContext(BaseInputAction, 0);
}
}
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(InInputComponent)) {
if (MouseMiddleAxisAsset) {
EnhancedInputComponent->BindAction(MouseMiddleAxisAsset, ETriggerEvent::Started, this, &ARover::PressMouseMiddleButton);
EnhancedInputComponent->BindAction(MouseMiddleAxisAsset, ETriggerEvent::Completed, this, &ARover::ReleaseMouseMiddleButton);
}
if (MouseLeftAsset) {
EnhancedInputComponent->BindAction(MouseLeftAsset, ETriggerEvent::Started, this, &ARover::PressMouseLeftButton);
EnhancedInputComponent->BindAction(MouseLeftAsset, ETriggerEvent::Completed, this, &ARover::ReleaseMouseLeftButton);
EnhancedInputComponent->BindAction(MouseLeftAsset, ETriggerEvent::Triggered, this, &ARover::MouseLeftMovePawn);
}
if (TurnAsset) {
EnhancedInputComponent->BindAction(TurnAsset, ETriggerEvent::Triggered, this, &ARover::_TurnAtRate);
}
if (LookUpAsset) {
EnhancedInputComponent->BindAction(LookUpAsset, ETriggerEvent::Triggered, this, &ARover::_LookUpAtRate);
}
if (GamePadTurnAsset) {
EnhancedInputComponent->BindAction(GamePadTurnAsset, ETriggerEvent::Triggered, this, &ARover::GamePadTurnAtRate);
}
if (GamePadLookUPAsset) {
EnhancedInputComponent->BindAction(GamePadLookUPAsset, ETriggerEvent::Triggered, this, &ARover::GamePadLookUpAtRate);
}
if (MouseRollAxisAsset) {
EnhancedInputComponent->BindAction(MouseRollAxisAsset, ETriggerEvent::Triggered, this, &ARover::MouseRollDistance);
}
if (MouseRightAsset) {
EnhancedInputComponent->BindAction(MouseRightAsset, ETriggerEvent::Started, this, &ARover::PressMouseRightButton);
EnhancedInputComponent->BindAction(MouseRightAsset, ETriggerEvent::Completed, this, &ARover::ReleaseMouseRightButton);
}
if (MoveForwardAsset) {
EnhancedInputComponent->BindAction(MoveForwardAsset, ETriggerEvent::Triggered, this, &ARover::_MoveForward);
EnhancedInputComponent->BindAction(MoveForwardAsset, ETriggerEvent::Completed, this, &ARover::ReleaseMoveButton);
}
if (MoveRightAsset) {
EnhancedInputComponent->BindAction(MoveRightAsset, ETriggerEvent::Triggered, this, &ARover::_MoveRight);
EnhancedInputComponent->BindAction(MoveRightAsset, ETriggerEvent::Completed, this, &ARover::ReleaseMoveButton);
}
if (TS_TwoTouchAsset) {
EnhancedInputComponent->BindAction(TS_TwoTouchAsset, ETriggerEvent::Triggered, this, &ARover::TS_TriggeredTwoTouch);
EnhancedInputComponent->BindAction(TS_TwoTouchAsset, ETriggerEvent::Started, this, &ARover::TS_PressTwoTouch);
EnhancedInputComponent->BindAction(TS_TwoTouchAsset, ETriggerEvent::Completed, this, &ARover::TS_ReleaseTwoTouch);
}
}
}
void ARover::PressMouseMiddleButton()
{
if (bPressMouseLeftKey || bPressMouseRightKey)return;
bPressMouseMiddleKey = true;
}
void ARover::ReleaseMouseMiddleButton()
{
bPressMouseMiddleKey = false;
}
void ARover::PressMouseLeftButton()
{
FHitResult _ClickObject;
if ( bPressMouseMiddleKey)return;
if (bCurrentLookingup) {
ReleaseMouseMiddleButton();
bCurrentLookingup = false;
}
if (bHDRIMode) {
PressMouseMiddleButton();
return;
}
PlayerController->GetMousePosition(TestMousePosition.X, TestMousePosition.Y);
FHitResult _HitResult;
if (PlayerController->GetUnderMouseHitPosition(_HitResult)) {
MouseClickLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(_HitResult.Location);
if (GlobeAnchor->GetHeight() < 20000) {
AssistMouseLeftMoveActor->SetActorLocation(_HitResult.Location);
float _Distance = (AssistMouseLeftMoveActor->GetActorLocation() - GetActorLocation()).Length() * 0.1;
AssistMouseLeftMoveActor->SetActorScale3D(FVector(_Distance));
CheckMoveCollisionChannel = ECollisionChannel::ECC_GameTraceChannel1;
}
else {
CheckMoveCollisionChannel = ECollisionChannel::ECC_Visibility;
}
}
bPressMouseLeftKey = true;
}
void ARover::ReleaseMouseLeftButton()
{
if (bHDRIMode) {
ReleaseMouseMiddleButton();
return;
}
bPressMouseLeftKey = false;
if (!bAllowUpdataMove)bAllowInertialMove = true;
}
void ARover::PressMouseRightButton()
{
if (bPressMouseLeftKey || bPressMouseMiddleKey)return;
if (bHDRIMode) {
PressMouseMiddleButton();
return;
}
bTempStopAutoRotate = true;
bPressMouseRightKey = true;
// 用于判断当前右键是拖动还是点击
//FTimerHandle ClearSelectedResourceItemTimer;
//GetWorldTimerManager().SetTimer(ClearSelectedResourceItemTimer, this, &ARover::ClearSelectedResourceItemSets, 0.2f, false);
StopMouseLeftMove();
UpdatascreenCenterPointLocation();
}
void ARover::ReleaseMouseRightButton()
{
bTempStopAutoRotate = false;
bPressMouseRightKey = false;
//PlayerController->SetMouseShowStatus(true);
bLimitViewport = false;
AdjustSpeedByHeight();
if (LastMousePosition != MousePosition) {
SlideTime = (MousePosition - LastMousePosition).Length() * MouseMoveOffsetMulitiplier * 0.1;;
TotalSlideTime = SlideTime;
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::SanitizeFloat(SlideTime));
}
}
void ARover::_TurnAtRate(const FInputActionValue& Value)
{
if (bPressMouseRightKey) {
AroundPointRotation(Value.GetMagnitude(), EAxis::X);
}
if (!bPressMouseMiddleKey)return;
AddControllerYawInput(Value.GetMagnitude() * GetWorld()->GetDeltaSeconds() * SelfBaseTurnRate * -0.15 * Camera->FieldOfView / 80);
}
void ARover::GamePadTurnAtRate(const FInputActionValue& Value)
{
if (bFollowSportTrace)return;
AddControllerYawInput(Value.GetMagnitude() * GetWorld()->GetDeltaSeconds() * SelfBaseTurnRate * -0.15 * Camera->FieldOfView / 80);
}
void ARover::_LookUpAtRate(const FInputActionValue& Value)
{
if (bPressMouseRightKey) {
AroundPointRotation(Value.GetMagnitude(), EAxis::Y);
}
if (!bPressMouseMiddleKey)return;
AddControllerPitchInput(Value.GetMagnitude() * GetWorld()->GetDeltaSeconds() * SelfBaseLookUpRate * 0.15 * Camera->FieldOfView / 80);
}
void ARover::GamePadLookUpAtRate(const FInputActionValue& Value)
{
AddControllerPitchInput(Value.GetMagnitude() * GetWorld()->GetDeltaSeconds() * SelfBaseLookUpRate * 0.15 * Camera->FieldOfView / 80);
}
void ARover::MouseRollDistance(const FInputActionValue& Value)
{
if (!bHDRIMode)
{
AssistMouseRollDistance(Value.GetMagnitude());
}
else
{
//输出鼠标滚轮值
MiddleKeyValue = Value.GetMagnitude();
}
}
void ARover::TS_TriggeredTwoTouch(const FInputActionValue& Value)
{
if (!bTS_StartAction)return;
LastTouch1 = Touch1;
LastTouch2 = Touch2;
PlayerController->GetInputTouchState(ETouchIndex::Touch1, Touch1.X, Touch1.Y, bPressTouch1);
PlayerController->GetInputTouchState(ETouchIndex::Touch2, Touch2.X, Touch2.Y, bPressTouch2);
if (LastTouch1 == Touch1 && LastTouch2 == Touch2)return;
FVector2D CurTwoTouchDirection = (Touch1 - LastTouch1).GetSafeNormal();
FVector2D LastTwoTouchDirection = (Touch2 - LastTouch2).GetSafeNormal();
double Delta = UKismetMathLibrary::DotProduct2D(CurTwoTouchDirection, LastTwoTouchDirection);
if (Delta <= 0) {
TS_MouseRollDistance(Value);
TS_FOVRotation(Value);
}
else if (Delta > 0) {
TS_UpDownPitch(Value);
}
}
void ARover::TS_MouseRollDistance(const FInputActionValue& Value)
{
if (!bPressTouch1 || !bPressTouch1)return;
float TheValue = ((Touch1 - Touch2).Length() - ((LastTouch1 - LastTouch2).Length())) * 0.05;
AssistMouseRollDistance(TheValue, TS_ZoomHitResult);
}
void ARover::TS_PressTwoTouch()
{
if (GetWorldTimerManager().IsTimerActive(TS_DelayReleaseTimer)) {
GetWorldTimerManager().ClearTimer(TS_DelayReleaseTimer);
}
bTS_PressTwoTouch = true;
PlayerController->GetInputTouchState(ETouchIndex::Touch1, Touch1.X, Touch1.Y, bPressTouch1);
PlayerController->GetInputTouchState(ETouchIndex::Touch2, Touch2.X, Touch2.Y, bPressTouch2);
if (TS_ZoomHitResult == std::nullopt) {
FVector2D TS_ZoomPoint = (Touch1 + Touch2) * 0.5f;
FHitResult HitResult;
PlayerController->GetUnderScreenHitPosition(TS_ZoomPoint, HitResult);
TS_ZoomHitResult = HitResult;
}
GetWorldTimerManager().SetTimer(TS_ActionTimer, this, &ARover::TS_StartAction, TS_DelayTime, false);
}
void ARover::TS_ReleaseTwoTouch()
{
if (GetWorldTimerManager().IsTimerActive(TS_DelayReleaseTimer)) {
GetWorldTimerManager().ClearTimer(TS_DelayReleaseTimer);
}
FTimerDelegate _TimerDelegate;
_TimerDelegate.BindLambda([this]() {
this->bTS_PressTwoTouch = false;
this->bLimitViewport = false;
this->bTS_StartAction = false;
this->TS_ZoomHitResult = std::nullopt;
this->TS_ActionStatus = ETSAction::ETS_Default;
});
GetWorldTimerManager().SetTimer(TS_DelayReleaseTimer, _TimerDelegate, 0.05f, false);
}
void ARover::TS_FOVRotation(const FInputActionValue& Value)
{
FVector2D CurTwoTouchDirection = (Touch2 - Touch1).GetSafeNormal();
FVector2D LastTwoTouchDirection = (LastTouch2 - LastTouch1).GetSafeNormal();
if (LastTouch1 == Touch1 && LastTouch2 == Touch2)return;
if (!bPressTouch1 || !bPressTouch2)return;
float Angle = FMath::RadiansToDegrees(FMath::Acos(UKismetMathLibrary::DotProduct2D(CurTwoTouchDirection, LastTwoTouchDirection) / (CurTwoTouchDirection.Length() * LastTwoTouchDirection.Length())));
float Alpha = SelfBaseTurnRate * 0.5 * Angle;
if (UKismetMathLibrary::CrossProduct2D(CurTwoTouchDirection, LastTwoTouchDirection) <= 0) {
Alpha *= -1;
}
AroundPointRotation(Alpha, EAxis::X, TS_ZoomHitResult->Location);
}
void ARover::TS_UpDownPitch(const FInputActionValue& Value)
{
if (LastTouch1 == Touch1 && LastTouch2 == Touch2)return;
if (!bPressTouch1 || !bPressTouch2)return;
FVector2D CurTwoTouchDirection = (Touch2 - Touch1).GetSafeNormal();
FVector2D LastTwoTouchDirection = (LastTouch2 - LastTouch1).GetSafeNormal();
float Alpha = Value.GetMagnitude() * GetWorld()->GetDeltaSeconds() * 0.4;
if (LastTouch1.Y - Touch1.Y <= 0) {
Alpha *= -1;
}
AroundPointRotation(Alpha, EAxis::Y, TS_ZoomHitResult->Location);
}
void ARover::ModifyMaxRollCoefficient(float Coefficient)
{
MaxRollCoefficient = Coefficient;
AssistMouseRollDistance(1);
}
void ARover::_MoveRight(const FInputActionValue& TheValue)
{
float Value = TheValue.GetMagnitude();
if (Value && GetController()) {
StopMouseLeftMove();
AdjustSpeedByHeight();
FRotator ControlRotation = GetControlRotation();
FRotator Rotation(ControlRotation.Pitch, ControlRotation.Yaw, 0);
FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::Y);
float Height = GlobeAnchor->GetHeight();
if (Height < 50)Height = 50;
AddMovementInput(Direction, Value * Height * 0.000001);
UpdateOrignLongitudeLatitude();
bPressMoveButton = true;
UpdateCurrentHeight();
}
}
void ARover::UpdateCurrentHeight()
{
this->CurrentHeight = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(this->GetActorLocation()).Z;
}
void ARover::ResetPlayerProperty()
{
bPressMoveButton = false;
}
void ARover::MoveToLongitudeLatitudeHeight(const FVector& LongitudeLatitudeHeight)
{
if (bFlying)return;
GlobeAnchor->MoveToLongitudeLatitudeHeight(LongitudeLatitudeHeight);
UpdateOrignLongitudeLatitude();
UpdateCurrentHeight();
}
void ARover::EnableCameraLag(bool bOpen)
{
if (bOpen) {
SpringArm->bEnableCameraLag = true;
SpringArm->bEnableCameraRotationLag = true;
}
else {
SpringArm->bEnableCameraLag = false;
SpringArm->bEnableCameraRotationLag = false;
}
}
void ARover::SetMaxRollDistance(float _MaxDistance)
{
CurrentMaxRollDistance = _MaxDistance;
FVector SelfLocation = GetActorLocation();
if (SelfLocation.Z < CurrentMaxRollDistance)return;
FHitResult HitResult;
if (ARoverController::PlayerController->GetUnderscreenCenterHitPosition(HitResult)) {
FVector Direction = (SelfLocation - HitResult.Location).GetSafeNormal();
SelfLocation = HitResult.Location + Direction * CurrentMaxRollDistance;
SetActorLocation(SelfLocation);
UpdateCurrentHeight();
}
}
FConvexVolume ARover::GetViewFrustum()
{
FMinimalViewInfo CameraViewInfo;
Camera->GetCameraView(GetWorld()->GetDeltaSeconds(), CameraViewInfo);
FMatrix ProjectionMatrix;
FMatrix ViewMatrix;
FMatrix ViewProjectionMatrix;
UGameplayStatics::GetViewProjectionMatrix(CameraViewInfo, ViewMatrix, ProjectionMatrix, ViewProjectionMatrix);
FConvexVolume ViewFrustum;
GetViewFrustumBounds(ViewFrustum, ViewProjectionMatrix, true, true);
return ViewFrustum;
}
bool ARover::CheckPointInViewFrustum(const FVector& Point)
{
FConvexVolume ViewFrustum = GetViewFrustum();
TArray<FVector> Vertices;
return ViewFrustum.IntersectPoint(Point);
}
void ARover::StopKeyMove()
{
bKeyMove = false;
}
void ARover::StartKeyMove()
{
bKeyMove = true;
}
void ARover::ClearCurrentSlowStopMoveOffsetTime()
{
CurrentSlowStopMoveOffsetTime = 0;
MoveToLocation = FVector(0);
}
void ARover::TS_StartAction()
{
UpdatascreenCenterPointLocation();
bTS_StartAction = true;
}
void ARover::MouseLeftMovePawn(const FInputActionValue& Value)
{
if (!bPressMouseLeftKey || !bAllowMouseLeftMove || bFollowSportTrace || bTS_PressTwoTouch)return;
if (LastMousePosition == MousePosition)return;
if (!bCurrentLookingup) {
float MouseOffset = (MousePosition - LastMousePosition).Length();
FVector MouseDirection;
FVector MousePositionWorldLocation;
FVector LastMouseDirection;
FVector LastMousePositionWorldLocation;
PlayerController->DeprojectScreenPositionToWorld(MousePosition.X, MousePosition.Y, MousePositionWorldLocation, MouseDirection);
PlayerController->DeprojectScreenPositionToWorld(LastMousePosition.X, LastMousePosition.Y, LastMousePositionWorldLocation, LastMouseDirection);
FVector Location = GetActorLocation();
float Height = FMath::Abs(GlobeAnchor->GetHeight());
if (Height < 200)Height = 200;
FHitResult _MouseHitResult;
GetWorld()->LineTraceSingleByChannel(_MouseHitResult, MousePositionWorldLocation, MousePositionWorldLocation + MouseDirection * 100000000000, CheckMoveCollisionChannel);
if (_MouseHitResult.bBlockingHit) {
if (bAllowUpdateSlide) {
MouseClickLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(_MouseHitResult.Location);
bAllowUpdateSlide = false;
bAllowSlowStopMove = false;
return;
}
bAllowUpdataMove = false;
FVector _MouseLocation = _MouseHitResult.Location;
FVector _FirstMouseClickPosition = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(MouseClickLongitudeLatitude);
FVector2D _MousescreenPosition;
FVector2D _FirstMousescreenPosition;
PlayerController->ProjectWorldLocationToScreen(_MouseLocation, _MousescreenPosition);
PlayerController->ProjectWorldLocationToScreen(_FirstMouseClickPosition, _FirstMousescreenPosition);
_MouseLocation.Z = 0;
_FirstMouseClickPosition.Z = 0;
MoveDirectionLast = (_MouseLocation - _FirstMouseClickPosition).GetSafeNormal() * -1;
CurrentMoveDistance = (_MouseLocation - _FirstMouseClickPosition).Length();
FVector MoveToDistance = MoveDirectionLast * CurrentMoveDistance;
MoveToDistance.Z = 0;
MoveToLocation = Location + MoveToDistance;
FVector TargetLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(MoveToLocation);
float Latitude = TargetLongitudeLatitude.Y;
if (Latitude > MaxCrossingLatitude || Latitude < -MaxCrossingLatitude) {
FInputActionValue InputActionValue(-10.f);
_MoveRight(InputActionValue);
}
else {
TargetLongitudeLatitude.Z = CurrentHeight;
MoveToLocation = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(TargetLongitudeLatitude);
GlobeAnchor->MoveToLongitudeLatitudeHeight(TargetLongitudeLatitude);
}
UpdateOrignLongitudeLatitude();
TotalSlowStopMoveOffsetTime = MouseOffset * MouseMoveOffsetMulitiplier * 0.1;
}
else if (GlobeAnchor->GetHeight() > LimitValueOfRotateAroundPoint) {
bAllowSlowStopMove = true;
bAllowUpdateSlide = true;
MoveDirectionLast = (MousePositionWorldLocation - LastMousePositionWorldLocation).GetSafeNormal() * -1;
FVector MoveToDistance = MoveDirectionLast * (MousePositionWorldLocation - LastMousePositionWorldLocation).Length() * Height * BaseMouseLeftMoveRate * 10;
Location += MoveToDistance;
FVector MoveToLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(Location);
MoveToLongitudeLatitude.Z = Height;
MoveToLocation = MoveToLongitudeLatitude;
TotalSlowStopMoveOffsetTime = FMath::Clamp(MouseOffset * MouseMoveOffsetMulitiplier, 0.f, 1.f);
if (GetWorldTimerManager().IsTimerActive(SlowStopMoveTimer))GetWorldTimerManager().ClearTimer(SlowStopMoveTimer);
GetWorld()->GetTimerManager().SetTimer(SlowStopMoveTimer, this, &ARover::StartSlowStopMove, CurrentSlowStopMoveOffsetTime, false);
bAllowUpdataMove = true;
}
else {
bCurrentLookingup = true;
PressMouseMiddleButton();
}
if (!bCurrentLookingup) {
CurrentSlowStopMoveOffsetTime = TotalSlowStopMoveOffsetTime;
}
}
}
void ARover::TouchMovePawn(FVector2D CurScreenPosition, FVector2D LastScreenPosition)
{
if (CurScreenPosition == LastScreenPosition)return;
MousePosition = CurScreenPosition;
LastMousePosition = LastScreenPosition;
float MouseOffset = (CurScreenPosition - LastScreenPosition).Length();
FVector MouseDirection;
FVector MousePositionWorldLocation;
FVector LastMouseDirection;
FVector LastMousePositionWorldLocation;
PlayerController->DeprojectScreenPositionToWorld(CurScreenPosition.X, CurScreenPosition.Y, MousePositionWorldLocation, MouseDirection);
PlayerController->DeprojectScreenPositionToWorld(LastScreenPosition.X, LastScreenPosition.Y, LastMousePositionWorldLocation, LastMouseDirection);
FVector Location = GetActorLocation();
float Height = FMath::Abs(GlobeAnchor->GetHeight());
if (Height < 200)Height = 200;
FHitResult _MouseHitResult;
GetWorld()->LineTraceSingleByChannel(_MouseHitResult, MousePositionWorldLocation, MousePositionWorldLocation + MouseDirection * 100000000000, CheckMoveCollisionChannel);
if (_MouseHitResult.bBlockingHit) {
if (bAllowUpdateSlide) {
MouseClickLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(_MouseHitResult.Location);
bAllowUpdateSlide = false;
bAllowSlowStopMove = false;
return;
}
bAllowUpdataMove = false;
FVector _MouseLocation = _MouseHitResult.Location;
FVector _FirstMouseClickPosition = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(MouseClickLongitudeLatitude);
FVector2D _MousescreenPosition;
FVector2D _FirstMousescreenPosition;
PlayerController->ProjectWorldLocationToScreen(_MouseLocation, _MousescreenPosition);
PlayerController->ProjectWorldLocationToScreen(_FirstMouseClickPosition, _FirstMousescreenPosition);
_MouseLocation.Z = 0;
_FirstMouseClickPosition.Z = 0;
MoveDirectionLast = (_MouseLocation - _FirstMouseClickPosition).GetSafeNormal() * -1;
CurrentMoveDistance = (_MouseLocation - _FirstMouseClickPosition).Length();
FVector MoveToDistance = MoveDirectionLast * CurrentMoveDistance;
MoveToDistance.Z = 0;
MoveToLocation = Location + MoveToDistance;
FVector TargetLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(MoveToLocation);
float Latitude = TargetLongitudeLatitude.Y;
if (Latitude > MaxCrossingLatitude || Latitude < -MaxCrossingLatitude) {
FInputActionValue InputActionValue(-10.f);
_MoveRight(InputActionValue);
}
else {
TargetLongitudeLatitude.Z = CurrentHeight;
MoveToLocation = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(TargetLongitudeLatitude);
GlobeAnchor->MoveToLongitudeLatitudeHeight(TargetLongitudeLatitude);
}
UpdateOrignLongitudeLatitude();
TotalSlowStopMoveOffsetTime = MouseOffset * MouseMoveOffsetMulitiplier * 0.1;
}
else if (GlobeAnchor->GetHeight() > LimitValueOfRotateAroundPoint) {
bAllowSlowStopMove = true;
bAllowUpdateSlide = true;
MoveDirectionLast = (MousePositionWorldLocation - LastMousePositionWorldLocation).GetSafeNormal() * -1;
FVector MoveToDistance = MoveDirectionLast * (MousePositionWorldLocation - LastMousePositionWorldLocation).Length() * Height * BaseMouseLeftMoveRate * 10;
Location += MoveToDistance;
FVector MoveToLongitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(Location);
MoveToLongitudeLatitude.Z = Height;
MoveToLocation = MoveToLongitudeLatitude;
TotalSlowStopMoveOffsetTime = FMath::Clamp(MouseOffset * MouseMoveOffsetMulitiplier, 0.f, 1.f);
if (GetWorldTimerManager().IsTimerActive(SlowStopMoveTimer))GetWorldTimerManager().ClearTimer(SlowStopMoveTimer);
GetWorld()->GetTimerManager().SetTimer(SlowStopMoveTimer, this, &ARover::StartSlowStopMove, CurrentSlowStopMoveOffsetTime, false);
bAllowUpdataMove = true;
}
else {
bCurrentLookingup = true;
PressMouseMiddleButton();
}
if (!bCurrentLookingup) {
CurrentSlowStopMoveOffsetTime = TotalSlowStopMoveOffsetTime;
}
}
void ARover::UpdataMoveToLocation(float DeltaTime)
{
static FVector LastTargetLocation = FVector(0);
if (MoveToLocation == FVector(0))return;
if (bAllowUpdataMove) {
FVector TargetLocation = FVector(0);
if (!bAllowInertialMove) {
FVector Location = GlobeAnchor->GetLongitudeLatitudeHeight();
if (Location.X > 90) {
if (MoveToLocation.X < 0) {
MoveToLocation.X = 180 + (180 + MoveToLocation.X);
}
}
else if (Location.X < -90) {
if (MoveToLocation.X > 0) {
MoveToLocation.X = MoveToLocation.X - 360;
}
}
TargetLocation = UKismetMathLibrary::VInterpTo(Location, MoveToLocation, DeltaTime, 3.f);
/*if (TargetLocation.X > 180) {
TargetLocation.X = TargetLocation.X - 360;
}
else if (TargetLocation.X < -180) {
TargetLocation.X = 180 + (TargetLocation.X + 180);
}*/
TargetLocation.Z = CurrentHeight;
GlobeAnchor->MoveToLongitudeLatitudeHeight(TargetLocation);
if (LastTargetLocation != FVector(0)) {
MoveDirectionLast = (TargetLocation - LastTargetLocation).GetSafeNormal();
}
if (!GetWorldTimerManager().IsTimerActive(UpdateOriginLongitudeLatitdeTimer)) {
DelayUpdateOrigin();
}
SlowStopMoveSpeed = (TargetLocation - LastTargetLocation).Length();
}
LastTargetLocation = TargetLocation;
}
else if (!bAllowInertialMove && bAllowSlowStopMove) {
//return;
if (CurrentSlowStopMoveOffsetTime <= 0) {
MoveToLocation = FVector(0);
SlowStopMoveSpeed = 0;
MoveDirectionLast = FVector(0);
LastTargetLocation = FVector(0);
bAllowSlowStopMove = false;
return;
}
float SpeedMulityplier = UKismetMathLibrary::NormalizeToRange(CurrentSlowStopMoveOffsetTime, 0, TotalSlowStopMoveOffsetTime);
CurrentSlowStopMoveOffsetTime -= DeltaTime;
FVector Location = GlobeAnchor->GetLongitudeLatitudeHeight();
FVector TargetLocation = Location + MoveDirectionLast * SlowStopMoveSpeed * SpeedMulityplier;
/*if (TargetLocation.X > 180) {
TargetLocation.X = TargetLocation.X - 360;
}
else if (TargetLocation.X < -180) {
TargetLocation.X = TargetLocation.X + 360;
}*/
/*if (TargetLocation.Y > 90) {
TargetLocation.Y = TargetLocation.Y - 180;
}
else if (TargetLocation.Y < -90) {
TargetLocation.Y = TargetLocation.Y + 180;
}*/
TargetLocation.Z = CurrentHeight;
GlobeAnchor->MoveToLongitudeLatitudeHeight(TargetLocation);
if (!GetWorldTimerManager().IsTimerActive(UpdateOriginLongitudeLatitdeTimer)) {
DelayUpdateOrigin();
}
}
}
void ARover::_MoveForward(const FInputActionValue& TheValue)
{
float Value = TheValue.GetMagnitude();
if (Value && GetController()) {
StopMouseLeftMove();
AdjustSpeedByHeight();
FRotator ControlRotation = GetControlRotation();
FRotator Rotation(ControlRotation.Pitch, ControlRotation.Yaw, 0);
FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::X);
float Height = GlobeAnchor->GetHeight();
if (Height < 50)Height = 50;
else if (Height > 10001620 && Value < 0)Height = 0;
AddMovementInput(Direction, Value * Height * 0.000001);
if ((GetActorLocation() - screenMiddleLocation).Length() > 8000000)return;
UpdateOrignLongitudeLatitude();
bPressMoveButton = true;
UpdateCurrentHeight();
}
}
void ARover::ReleaseMoveButton()
{
bPressMoveButton = false;
}
void ARover::StopMoveForward()
{
bMoveForward = false;
ForwardDirection = FVector(0);
}
void ARover::StopMoveRight()
{
bMoveRight = false;
RightDirection = FVector(0);
}
void ARover::AllowLeftMouseMovePlayer(bool bAllow)
{
bAllowMouseLeftMove = bAllow;
if (!bAllowMouseLeftMove)MoveToLocation = FVector(0);
}
bool ARover::GetKeyMoveState()
{
return bKeyMove;
}
void ARover::UpdateSlideRotation(float DeltaTime)
{
if (bPressMouseRightKey) return;
if (SlideTime <= 0)return;
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::White, TEXT("正在Tick旋转"));
SlideTime -= DeltaTime;
float ScaleValue = UKismetMathLibrary::NormalizeToRange(SlideTime, 0, TotalSlideTime);
float _SlideSpeed = SlideSpeed * ScaleValue;
AroundPointRotation(_SlideSpeed, EAxis::X);
}
void ARover::UpdateOrignLongitudeLatitude(float Time)
{
CheckUpdateOrignLongitudeLatitude();
}
void ARover::FlyTo(const FVector& LongitudeLatitude, double YawAtDestination, double PitchAtDestination)
{
if (bFlying) {
FlyComp->InterruptFlight();
}
StopMouseLeftMove();
OnFlyStart(LongitudeLatitude, YawAtDestination, PitchAtDestination);
FlyComp->FlyToLocationLongitudeLatitudeHeight(LongitudeLatitude, YawAtDestination, PitchAtDestination, true);
//CheckUpdateOrignLongitudeLatitude();
if (GetWorldTimerManager().IsTimerActive(UpdateFlyOriginTimer))GetWorldTimerManager().ClearTimer(UpdateFlyOriginTimer);
GetWorldTimerManager().SetTimer(UpdateFlyOriginTimer, this, &ARover::CheckUpdateOrignLongitudeLatitude, 0.01f, true);
bFlying = true;
}
void ARover::AssistMouseRollDistance(float Value, const FVector2D& ZoomScreenPosition)
{
std::optional< FVector2D> _ZoomScreenPosition;
if (ZoomScreenPosition != FVector2D(-1)) {
_ZoomScreenPosition = ZoomScreenPosition;
}
AssistMouseRollDistance(Value, std::nullopt, _ZoomScreenPosition);
}
void ARover::AssistMouseRollDistance(float Value, std::optional<FHitResult> _TS_ZoomHitResult, std::optional<FVector2D> ZoomScreenPosition)
{
StopMouseLeftMove();
FVector2D ZoomRollPosition;
if (ZoomScreenPosition.has_value()) {
ZoomRollPosition = ZoomScreenPosition.value();
}
else {
PlayerController->GetMousePosition(ZoomRollPosition.X, ZoomRollPosition.Y);
}
FVector ActorLocation = GetActorLocation();
float Height = GlobeAnchor->GetHeight();
FVector WorldLocation;
FVector WorldDirection;
if (bFollowSportTrace) {
FVector2D screenCenter = ARoverController::GetScreenCenterPosition();
PlayerController->DeprojectScreenPositionToWorld(screenCenter.X, screenCenter.Y, WorldLocation, WorldDirection);
}
else {
if (_TS_ZoomHitResult == std::nullopt) {
PlayerController->DeprojectScreenPositionToWorld(ZoomRollPosition.X, ZoomRollPosition.Y, WorldLocation, WorldDirection);
}
else if (_TS_ZoomHitResult->bBlockingHit) {
WorldDirection = (_TS_ZoomHitResult->Location - GetActorLocation()).GetSafeNormal();
}
}
if (Value < 0) {
if (ActorLocation.Z >= CurrentMaxRollDistance * MaxRollCoefficient)return;
WorldDirection *= -1;
}
float Speed = 0;
FHitResult UnderMouseHitResult;
if (_TS_ZoomHitResult == std::nullopt) {
PlayerController->GetHitResultAtScreenPosition(ZoomRollPosition, ECollisionChannel::ECC_Visibility, true, UnderMouseHitResult);
}
else {
UnderMouseHitResult.bBlockingHit = _TS_ZoomHitResult->bBlockingHit;
UnderMouseHitResult.Location = _TS_ZoomHitResult->Location;
}
if (UnderMouseHitResult.bBlockingHit) {
float TargetPointWithSelfDistance = (UnderMouseHitResult.Location - GetActorLocation()).Length();
Speed = TargetPointWithSelfDistance * ZoomRollSpeed * 0.01;
if (Value > 0 && (UnderMouseHitResult.Location - GetActorLocation()).Length() < 50)return;
}
else {
Speed = Height * ZoomRollSpeed;
}
ActorLocation += WorldDirection * Speed * FMath::Abs(Value);
if (ActorLocation.Z > CurrentMaxRollDistance * MaxRollCoefficient) {
ActorLocation.Z = CurrentMaxRollDistance * MaxRollCoefficient;
}
if (Value > 0) {
FVector2D screenCenterPosition = ARoverController::GetScreenCenterPosition();
if ((screenCenterPosition - ZoomRollPosition).Length() > 300) {
if (Height > ZoomOffsetHeightValue) {
FHitResult MouseHitResult;
if (PlayerController->GetUnderScreenHitPosition(ZoomRollPosition, MouseHitResult)) {
FHitResult screenHitResult;
if (PlayerController->GetUnderscreenCenterHitPosition(screenHitResult)) {
float Distance = (MouseHitResult.Location - screenHitResult.Location).Length();
FVector Direction = (MouseHitResult.Location - screenHitResult.Location).GetSafeNormal();
ActorLocation += Direction * Distance * ZoomOffsetMulitiplier;
}
}
}
}
}
if (GetWorldTimerManager().IsTimerActive(PlayerController->RotateCameraTimer)) {
if ((ActorLocation - screenMiddleLocation).Length() > 5000000 && Value < 0)return;
}
SetActorLocation(ActorLocation);
CurrentHeight = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(ActorLocation).Z;
AdjustSpeedByHeight();
UpdateOrignLongitudeLatitude();
}
FVector ARover::GetCurrentLongitudeLatitude()
{
return FVector();
}
void ARover::CheckUpdateOrignLongitudeLatitude()
{
if (!IsUpdateOrignLongitudeLatitude)return;
if (GetWorldTimerManager().IsTimerActive(PlayerController->RotateCameraTimer) || Georeference == nullptr)return;
FVector OriginLongitudeLatitude = Georeference->GetOriginLongitudeLatitudeHeight();
FVector SelfLongitudeLatitude = GlobeAnchor->GetLongitudeLatitudeHeight();
SelfLongitudeLatitude.Z = OriginLongitudeLatitude.Z;
if (FMath::FloorToInt32(OriginLongitudeLatitude.X) != FMath::FloorToInt32(SelfLongitudeLatitude.X) ||
FMath::FloorToInt32(OriginLongitudeLatitude.Y) != FMath::FloorToInt32(SelfLongitudeLatitude.Y)) {
int32 Lon = FMath::FloorToInt32(SelfLongitudeLatitude.X / 1.f);
int32 Lat = FMath::FloorToInt32(SelfLongitudeLatitude.Y / 1.f);
Georeference->SetOriginLongitudeLatitudeHeight(FVector(Lon * 1, Lat * 1, SelfLongitudeLatitude.Z));
UpdateOriginCoordinate();
}
}
float ARover::GetHeight() const
{
return GlobeAnchor->GetHeight();
}
void ARover::AroundPointRotation(float TheValue, EAxis::Type AxisType, FVector _RotationPoint)
{
if (!IsEnabledAroundPointRotation)return;
if (GlobeAnchor->GetHeight() > LimitValueOfRotateAroundPoint || bPressMoveButton) {
if (bPressMoveButton) {
if (GetWorldTimerManager().IsTimerActive(ReleaseMoveButtonTimer)) {
GetWorldTimerManager().ClearTimer(ReleaseMoveButtonTimer);
}
FTimerDelegate Delegate;
Delegate.BindLambda([this]() {
bPressMoveButton = false;
});
GetWorldTimerManager().SetTimer(ReleaseMoveButtonTimer, Delegate, 0.1f, false);
}
return;
}
// 停止移动
MoveToLocation = FVector(0);
FVector MovePoint = FVector(0);
FRotator ViewRotation(0);
FVector RotationPointLocation =
_RotationPoint != FVector(-1) ?
_RotationPoint :
screenMiddleLocation;
if (AxisType == EAxis::X) {
FVector Vector = GetActorLocation() - RotationPointLocation;
float Angle = RotateAngle * TheValue;
FVector p = Vector.RotateAngleAxis(Angle, FVector::UpVector);
MovePoint = (p + RotationPointLocation);
ViewRotation = GetControlRotation();
ViewRotation.Pitch = FMath::UnwindDegrees(ViewRotation.Pitch);
ViewRotation.Yaw += Angle;
//PlayerController->SetControlRotation(Rotation);
}
else {
FVector ActorLocation = GetActorLocation();
FVector CurrentMoveAixs = ActorLocation - RotationPointLocation;
ActorLocation.Z = RotationPointLocation.Z;
FVector BaseAxis = ActorLocation - RotationPointLocation;
FVector RotateAxis = BaseAxis.RotateAngleAxis(90.f, FVector::UpVector);
float Angle = RotateAngle * TheValue;
FVector FinishAxis = CurrentMoveAixs.RotateAngleAxis(Angle, RotateAxis.GetSafeNormal());
FVector FinishDirectionAixs = FinishAxis.GetSafeNormal();
// 判断是否是同方向
float SameDirection = UKismetMathLibrary::Dot_VectorVector(FinishDirectionAixs, RotationPointLocation.UpVector);
if (SameDirection >= 0.999 && SameDirection <= 1.f) {
if (bLimitViewport) {
return;
}
}
else {
bLimitViewport = true;
}
MovePoint = FinishAxis + RotationPointLocation;
ViewRotation = (RotationPointLocation - MovePoint).Rotation();
if (FMath::Abs(ViewRotation.Pitch) > FMath::Abs(GetControlRotation().Pitch)) {
if (FMath::Abs(ViewRotation.Pitch) >= 89)return;
}
}
FVector SelfActorLocation = GetActorLocation();
FHitResult HitResult;
FCollisionQueryParams QueryParam;
QueryParam.AddIgnoredActor(this);
if (GetWorld()->LineTraceSingleByChannel(HitResult, SelfActorLocation, MovePoint, ECollisionChannel::ECC_Visibility, QueryParam)) {
return;
//MovePoint =HitResult.Location + HitResult.Location.UpVector.GetSafeNormal() * 100;
}
if (ViewRotation.Pitch > 0)return;
SetActorLocation(MovePoint);
PlayerController->SetControlRotation(ViewRotation);
UpdateCurrentHeight();
}
void ARover::UpdatascreenCenterPointLocation()
{
FHitResult HitResult;
FVector ScreenCenterLocation;
FVector ScreenCenterDirection;
FVector2D ScreenCenterPosition = ARoverController::GetScreenCenterPosition();
PlayerController->DeprojectScreenPositionToWorld(ScreenCenterPosition.X, ScreenCenterPosition.Y, ScreenCenterLocation, ScreenCenterDirection);
FVector End = ScreenCenterLocation + ScreenCenterDirection * 100000000;
if (GetWorld()->LineTraceSingleByChannel(HitResult, ScreenCenterLocation, End, ECollisionChannel::ECC_Visibility)) {
screenMiddleLocation = HitResult.Location;
}
}
void ARover::AdjustSpeedByHeight()
{
UpdateCurrentHeight();
BaseMouseLeftMoveRate = GlobeAnchor->GetHeight() * LongitudeLatitudeControlHeightMulitiplier;
BaseMouseLeftMoveRate = FMath::Clamp(BaseMouseLeftMoveRate, 200, 3000);
}
void ARover::StartSlowStopMove()
{
bAllowUpdataMove = false;
}
void ARover::StopMouseLeftMove()
{
bAllowUpdataMove = false;
CurrentSlowStopMoveOffsetTime = 0;
bAllowInertialMove = false;
}
void ARover::DelayUpdateOrigin(float DelayTime)
{
if (!GetWorldTimerManager().IsTimerActive(UpdateOriginLongitudeLatitdeTimer)) {
FTimerDelegate TimerDelegate;
TimerDelegate.BindUFunction(this, TEXT("UpdateOrignLongitudeLatitude"), 0.01f);
GetWorld()->GetTimerManager().SetTimer(UpdateOriginLongitudeLatitdeTimer, TimerDelegate, DelayTime, false);
}
}
void ARover::InertialMove(float DeltaTime)
{
if (!bAllowInertialMove || GlobeAnchor->GetHeight() > ChangeHeightThreshold)return;
if (CurrentSlowStopMoveOffsetTime <= 0) {
CurrentSlowStopMoveOffsetTime = 0;
bAllowInertialMove = false;
return;
}
CurrentSlowStopMoveOffsetTime -= DeltaTime;
float SpeedMulityplier = UKismetMathLibrary::NormalizeToRange(CurrentSlowStopMoveOffsetTime, 0, TotalSlowStopMoveOffsetTime);
FVector Location = GetActorLocation();
FVector TargetLocation = Location + MoveDirectionLast * CurrentMoveDistance * 0.3 * SpeedMulityplier;
FVector TargetLontitudeLatitude = Georeference->TransformUnrealPositionToLongitudeLatitudeHeight(TargetLocation);
float Latitude = TargetLontitudeLatitude.Y;
if (!(Latitude > MaxCrossingLatitude || Latitude < -MaxCrossingLatitude)) {
TargetLontitudeLatitude.Z = CurrentHeight;
TargetLocation = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(TargetLontitudeLatitude);
SetActorLocation(TargetLocation);
}
UpdateOrignLongitudeLatitude();
}