1074 lines
38 KiB
C++
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();
|
|
}
|