void UTangoARCamera::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	if (UTangoDevice::Get().GetCurrentConfig().AreaDescription.UUID.Len() > 0)
	{
		FrameOfReference = FTangoCoordinateFramePair(ETangoCoordinateFrameType::AREA_DESCRIPTION, ETangoCoordinateFrameType::CAMERA_COLOR);
	}
	else
	{
		FrameOfReference = FTangoCoordinateFramePair(ETangoCoordinateFrameType::START_OF_SERVICE, ETangoCoordinateFrameType::CAMERA_COLOR);
	}

	if (ARScreen == nullptr && TangoARHelpers::DataIsReady())
	{
		ARScreen = NewObject<UTangoARScreenComponent>(this, TEXT("TangoCameraARScreen"));
		if (ARScreen)
		{
			ARScreen->RegisterComponent();
            ARScreen->AttachToComponent(this, FAttachmentTransformRules::KeepWorldTransform, NAME_None);

			FVector2D LowerLeft, UpperRight, NearFar;
			TangoARHelpers::GetNearPlane(LowerLeft, UpperRight, NearFar);
			FVector2D UVShift = TangoARHelpers::GetARUVShift();

			NearFar.Y *= 0.99f;
			FVector LL = FVector(NearFar.Y, LowerLeft.X*(NearFar.Y / NearFar.X), LowerLeft.Y*(NearFar.Y / NearFar.X));
			FVector UR = FVector(NearFar.Y, UpperRight.X*(NearFar.Y / NearFar.X), UpperRight.Y*(NearFar.Y / NearFar.X));

			ARScreen->SetRelativeLocation((LL + UR)*0.5f);
			ARScreen->SetRelativeRotation(FQuat::Identity);
			ARScreen->SetRelativeScale3D(FVector(1, FMath::Abs(UR.Y - LL.Y) / (100.0f*(1.0f - 2.0f*UVShift.X)), FMath::Abs(LL.Z - UR.Z) / (100.0f*(1.0f - 2.0f*UVShift.Y))));
		}
		else
		{
			UE_LOG(ProjectTangoPlugin, Error, TEXT("UTangoARCamera::TickComponent: Could not instantiate TangoARScreen for TangoARCamera. There will be no camera passthrough."));
		}
	}
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	if (UTangoDevice::Get().getTangoDeviceMotionPointer())
	{
		FTangoPoseData LatestPose = UTangoDevice::Get().getTangoDeviceMotionPointer()->GetPoseAtTime(FrameOfReference, 0);
		//Only move the component if the pose status is valid.
		if (LatestPose.StatusCode == ETangoPoseStatus::VALID)
		{
			SetRelativeLocation(LatestPose.Position);
			SetRelativeRotation(FRotator(LatestPose.QuatRotation));
		}
	}
	else
	{
		UE_LOG(ProjectTangoPlugin, Warning, TEXT("UTangoARCamera::TickComponent: Could not update transfrom because Tango Service is not connect or has motion tracking disabled!"));
	}

	if (!ViewExtension.IsValid() && GEngine)
	{
		TSharedPtr< FTangoViewExtension, ESPMode::ThreadSafe > NewViewExtension(new FTangoViewExtension(Cast<ITangoARInterface>(this)));
		ViewExtension = NewViewExtension;
		GEngine->ViewExtensions.Add(ViewExtension);
	}
}
void UGripMotionControllerComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// Moved this here instead of in the polling function, it was ticking once per frame anyway so no loss of perf
	// It doesn't need to be there and now I can pre-check
	// Also epics implementation in the polling function didn't work anyway as it was based off of playercontroller which is not the owner of this controller
	
	// Cache state from the game thread for use on the render thread
	// No need to check if in game thread here as tick always is
	bHasAuthority = IsLocallyControlled();
	bIsServer = IsServer();

	// Server/remote clients don't set the controller position in VR
	// Don't call positional checks and don't create the late update scene view
	if (bHasAuthority)
	{
		if (!ViewExtension.IsValid() && GEngine)
		{
			TSharedPtr< FViewExtension, ESPMode::ThreadSafe > NewViewExtension(new FViewExtension(this));
			ViewExtension = NewViewExtension;
			GEngine->ViewExtensions.Add(ViewExtension);
		}

		// This is the owning player, now you can get the controller's location and rotation from the correct source
		FVector Position;
		FRotator Orientation;
		bTracked = PollControllerState(Position, Orientation);

		if (bTracked)
		{
			SetRelativeLocationAndRotation(Position, Orientation);
		}

		if (!bTracked && !bUseWithoutTracking)
			return; // Don't update anything including location

		// Don't bother with any of this if not replicating transform
		if (bReplicates && bTracked)
		{
			ReplicatedControllerTransform.Position = Position;
			ReplicatedControllerTransform.Orientation = Orientation;

			if (GetNetMode() == NM_Client)//bReplicateControllerTransform)
			{
				ControllerNetUpdateCount += DeltaTime;
				if (ControllerNetUpdateCount >= (1.0f / ControllerNetUpdateRate))
				{
					ControllerNetUpdateCount = 0.0f;
					Server_SendControllerTransform(ReplicatedControllerTransform);
				}
			}
		}
	}

	// Process the gripped actors
	TickGrip();

}
//=============================================================================
void UMotionControllerComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	if (bIsActive)
	{
		FVector Position;
		FRotator Orientation;
		bTracked = PollControllerState(Position, Orientation);
		if (bTracked)
		{
			SetRelativeLocationAndRotation(Position, Orientation);
		}

		if (!ViewExtension.IsValid() && GEngine)
		{
			TSharedPtr< FViewExtension, ESPMode::ThreadSafe > NewViewExtension(new FViewExtension(this));
			ViewExtension = NewViewExtension;
			GEngine->ViewExtensions.Add(ViewExtension);
		}
	}
}