186 lines
6.1 KiB
Ucode
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
|
||
|
}
|