Repro steps:
- Use a Dell XPS 13 laptop (or similar). Touch screen is not required.
- Install the latest binary version of Unreal 4.18.
- Create a new project. Choose C++ and Puzzle template. Choose mobile target, scalable graphics, no starter content.
- Without making any changes to the project, click “play” to play in the active level editor viewport.
- Notice that using the touchpad to “mouseover” correctly highlights the blocks.
- Notice that clicking does not register in the correct location. You will need to click significantly to the right of and below your intended target to actually activate the block.
- (Optional: Strangely, notice that running the game as a separate executable works as expected.)
Additional information:
Digging into the cause, I found that for the highlighting case, AMyProjectPawn::Tick calls APlayerController::DeprojectMousePositionToWorld. This function uses LocalPlayer->ViewportClient->GetMousePosition to get a correctly-scaled set of screen coordinates. (The place where the scale consideration actually happens is in FSceneViewport::GetMousePos, and the call is CachedGeometry.LocalToAbsolute(FVector2D(CachedMousePos.X / CachedGeometry.Scale, CachedMousePos.Y / CachedGeometry.Scale));
) Note that the function indicates we are ending up with absolute coordinates here.
For the OnTouch case (laptop touchpad generates touch events, not click events, but I suspect click events would have the same problem). The TouchLocation is pushed from calling code rather than pulled on a per-tick basis. This appears to come from FSceneViewport::OnTouchStarted, which calls MyGeometry.AbsoluteToLocal(TouchEvent.GetScreenSpacePosition()
). It appears that this code path is not making any specific consideration for the scale, and the code further indicates that this ending up with local coordinates–it seems a little strange to be different, but I’m not familiar enough with that code to say if it’s right or wrong.
Overriding the APlayerController::InputTouch function to discard the TouchLocation that is passed in and instead use coordinates obtained from LocalPlayer->ViewportClient->GetMousePosition causes the template to work correctly in both PIE and standalone, adding further evidence that code path is correct, and the TouchEvent is not handling scale correctly.