1
0
KF2-Dev-Scripts/UDKBase/classes/UDKMobileInputZone.uc
2020-12-13 18:01:13 +03:00

186 lines
6.1 KiB
Ucode

/**
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
*/
class UDKMobileInputZone extends MobileInputZone;
/** Range around player that is considered a player touch */
var const float HoldPlayerDistance;
/** touches that are still being pressed down */
struct ActivePress
{
var int Handle;
var vector2d TouchLocation;
var float TouchTime;
};
var array<ActivePress> CurrentPresses;
/** The location that was traced to when deprojecting the screen position to the world */
var transient Vector TraceHitLocation;
/** last thing we tapped (for detecting double tap) */
var transient Actor LastTappedActor;
/** The time in seconds of the last time we performed an untouch event */
var transient float TimeOfLastUntouch;
/** Amount of time that a touch has been held on the player pawn */
var transient float PlayerTouchStartTime;
/** Returns true if we are touching the player pawn */
function bool IsTouchingPlayerPawn()
{
// HACK to check if we've touched the player pawn
return (InputOwner.Outer.Pawn != None && VSize2D(TraceHitLocation - InputOwner.Outer.Pawn.Location) < HoldPlayerDistance);
}
/** Returns the actor that was traced to from projecting to the world */
function TraceFromScreenToWorld(Vector2D ScreenPos, out Actor outHitActor, out vector OutHitLocation, optional vector Extent = vect(32,32,32))
{
local Actor HitActor, TestHitActor;
local vector CameraLoc, CameraDir, HitLocation, TestHitLocation, HitNormal;
LocalPlayer(InputOwner.Outer.Player).DeProject(ScreenPos, CameraLoc, CameraDir);
// see what is underneath the tap location in the world
foreach InputOwner.Outer.TraceActors(class'Actor', TestHitActor, TestHitLocation, HitNormal, CameraLoc + CameraDir * 8000.0, CameraLoc, Extent)
{
if (((!TestHitActor.bWorldGeometry && BlockingVolume(TestHitActor) == None) || HitActor == None) &&
(TestHitActor.bBlockActors || TestHitActor.bProjTarget || TouchableElement3D(TestHitActor) != None) &&
(Trigger(TestHitActor) == None) &&
(Pawn(TestHitActor) == None || Pawn(TestHitActor).Health > 0))
{
HitActor = TestHitActor;
HitLocation = TestHitLocation;
if (!HitActor.bWorldGeometry && BlockingVolume(TestHitActor) == None)
{
break;
}
}
}
outHitActor = HitActor;
OutHitLocation = HitLocation;
}
/** Handler for touch input */
function bool ProcessGameplayInput(MobileInputZone Zone, float DeltaTime, int Handle, ETouchType EventType, Vector2D TouchLocation)
{
local Vector2D RelLocation, ViewportSize;
local Actor TraceHitActor;
local int PressIndex;
local bool bRedundantInput;
LocalPlayer(InputOwner.Outer.Player).ViewportClient.GetViewportSize(ViewportSize);
// Get the screen space in terms of 0 to 1
RelLocation.X = TouchLocation.X / ViewportSize.X;
RelLocation.Y = TouchLocation.Y / ViewportSize.Y;
// Project and trace to see what we hit
TraceFromScreenToWorld(RelLocation, TraceHitActor, TraceHitLocation);
// If this is a touch we don't want to do anything except do some bookkeeping
// for delayed movement or double tapping
if (EventType == Touch_Began)
{
PressIndex = CurrentPresses.Add(1);
CurrentPresses[PressIndex].Handle = Handle;
CurrentPresses[PressIndex].TouchLocation = TouchLocation;
CurrentPresses[PressIndex].TouchTime = InputOwner.Outer.WorldInfo.TimeSeconds;
if (CurrentPresses.length > 1)
{
PlayerTouchStartTime = -1.f;
}
else
{
// Check if we are touching the player pawn
if (IsTouchingPlayerPawn())
{
PlayerTouchStartTime = InputOwner.Outer.WorldInfo.TimeSeconds;
}
else
{
PlayerTouchStartTime = -1.f;
}
}
}
else if (EventType == Touch_Ended || EventType == Touch_Cancelled)
{
PressIndex = CurrentPresses.Find('Handle', Handle);
`Log(LastTappedActor @ TraceHitActor @ TimeOfLastUntouch @ InputOwner.MobileDoubleTapTime @ PressIndex);
if (PressIndex != INDEX_NONE)
{
CurrentPresses.Remove(PressIndex, 1);
// See if we tapped on something we can interact with
if ( TraceHitActor != None && (TraceHitActor.bBlockActors || TraceHitActor.bProjTarget || TouchableElement3D(TraceHitActor) != None) &&
Trigger(TraceHitActor) == None && (Pawn(TraceHitActor) == None || Pawn(TraceHitActor).Health > 0) )
{
// send double tap on world geometry for area skills but not single tap
if ( LastTappedActor == TraceHitActor &&
InputOwner.Outer.WorldInfo.TimeSeconds < TimeOfLastUntouch + InputOwner.MobileDoubleTapTime )
{
if (TouchableElement3D(TraceHitActor) != None)
{
TouchableElement3D(TraceHitActor).HandleDoubleClick();
}
}
else if (!TraceHitActor.bWorldGeometry && BlockingVolume(TraceHitActor) == None)
{
if (PlayerTouchStartTime < 0.f)
{
if (TouchableElement3D(TraceHitActor) != None)
{
TouchableElement3D(TraceHitActor).HandleClick();
}
}
}
}
PlayerTouchStartTime = -1.f;
}
TimeOfLastUntouch = InputOwner.Outer.WorldInfo.TimeSeconds;
}
else if (EventType == Touch_Moved || EventType == Touch_Stationary)
{
PressIndex = CurrentPresses.Find('Handle', Handle);
if (PressIndex != INDEX_NONE)
{
// if this is a duplicate input, ignore it
if (CurrentPresses[PressIndex].TouchLocation == TouchLocation && CurrentPresses[PressIndex].TouchTime == InputOwner.Outer.WorldInfo.TimeSeconds)
{
bRedundantInput = true;
}
else
{
CurrentPresses[PressIndex].TouchLocation = TouchLocation;
CurrentPresses[PressIndex].TouchTime = InputOwner.Outer.WorldInfo.TimeSeconds;
}
}
if (!bRedundantInput)
{
// Next see if we tapped on something we can interact with
if ( EventType == Touch_Moved && TouchableElement3D(TraceHitActor) != None )
{
TouchableElement3D(TraceHitActor).HandleDragOver();
}
}
}
LastTappedActor = TraceHitActor;
// If we aren't touching the player pawn, clear PlayerTouchStartTime
if ( !IsTouchingPlayerPawn() )
{
PlayerTouchStartTime = -1.f;
}
return false;
}
defaultproperties
{
OnProcessInputDelegate=ProcessGameplayInput
HoldPlayerDistance=150.f
}