输入处理

鼠标/触摸输入

FairyGUI使用内置的机制进行鼠标和触摸事件的处理,不使用射线。如果确实要使用射线,可以将UIPanel的“HitTest Mode”设置为“Raycast”。无论哪种点击检测模式,下面的事件处理机制都一样。

如果要区分点击UI还是点击场景里的对象,可以使用下面的方法:

if(Stage.isTouchOnUI) //点在了UI上
{
}
else //没有点在UI上
{
}

这种检测不仅适用于点击,也适用于悬停。例如,如果鼠标悬停在UI上,这个判断也是真。如果你觉得屏幕上都没有UI了这个还是返回真,那就真的是有UI,特别是全屏界面,没设置穿透时,它的空白区域也是接受输入的。你可以通过打印GRoot.inst.touchTarget检查。

和鼠标/触摸相关的事件有:

在任何事件(即不只是鼠标/触摸相关的事件)回调中都可以获得当前鼠标或手指位置,以及点击的对象,例如:

void AnyEventHandler(EventContext context)
{
//点击位置,注意是屏幕坐标,要转换本地坐标要使用GlobalToLocal
Debug.Log(context.inputEvent.x + ", " + context.inputEvent.y);

//获取点击的对象(在鼠标/触摸事件中)
Debug.Log((GObject)context.sender);
//如果事件是冒泡的,可以获得最底层的对象。但要注意,这里的对象类型是DisplayObject,不是GObject。
Debug.Log((DisplayObject)context.initiator);
}

如果不在事件中,需要获得当前鼠标或者手指的位置,可以用:

//这是鼠标的位置,或者最后一个手指的位置
Vector2 pos1 = Stage.inst.touchPosition;

//获取指定手指的位置,参数是手指id
Vector2 pos2 = Stage.inst.GetTouchPosition(1);

在任何时候,如果需要获得当前点击的对象,或者鼠标下的对象,都可以通过以下的方式获得:

GObject obj = GRoot.inst.touchTarget;

//判断是不是在某个组件内
Debug.Log(testComponent==obj || testComponent.IsAncestorOf(obj));

多点触摸

FairyGUI支持多点触摸的处理。每个手指都会按照TouchBegin->TouchMove->TouchEnd流程派发事件,可以使用EventContext.inputEvent.touchId区分不同的手指。一般来说,普通的点击事件无需关心手指id,只有需要用到整个触摸流程的才需要处理。

//这是当前按下的手指的数量
int touchCount = Stage.inst.touchCount;

//获得当前所有按下的手指id
int[] touchIDs = Stage.inst.GetAllTouch(null);

如果你不想使用多点触摸功能,可以使用Unity的API:Input.multiTouchEnabled = false关闭。

VR输入处理

VR里输入一般使用凝视输入,或者手柄输入,针对这些新的输入方式,FairyGUI提供了封装支持,也就是说,在VR应用里,你仍然可以像处理鼠标或者触摸输入一样处理VR的输入,无任何区别,也就是说UI逻辑不需要做任何修改。

首先,需要把这些外部输入传入FairyGUI。在Stage类里提供了这些API:

public void SetCustomInput(ref RaycastHit hit, bool buttonDown);
public void SetCustomInput(ref RaycastHit hit, bool buttonDown, bool buttonUp);

SetCustomInput可以放在Update里调用,而且必须每帧调用。如果使用了SetCustomInput,则FairyGUI不再处理鼠标或者触摸输入。

使用示例:


SteamVR_TrackedObject controller;
SteamVR_Controller.Device controllerDevice;

void Start()
{
controller = ...
controllerDevice = ...
}

void Update()
{
Vector3 pos = controller.transform.position;
Vector3 dir = controller.transform.forward;
bool trigger_down = controllerDevice.GetPress(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger);

RaycastHit rh;
if (Physics.Raycast(pos, dir, out rh))
{
Stage.inst.SetCustomInput(rh, trigger_down);
}
}

键盘输入

侦听键盘输入的方法是:

Stage.inst.onKeyDown.Add(OnKeyDown);

void OnKeyDown(EventContext context)
{
Debug.Log(context.inputEvent.keyCode);
}

在手机上是通过原生的键盘输入。键盘弹出时,派发GTextInput.onFocusIn事件,键盘收回时,派发GTextInput.onFocusOut事件。

Unity在键盘输入时自带了一个额外的输入框,如果你不需要这个输入框,希望像微信那样弹出自己的输入框,你需要自行编写原生代码,FairyGUI这边提供的支持有:

//定义自己的键盘
KeyBoard yourKeyboard;

Stage.inst.keyboard = yourKeyboard;

复制粘贴问题

当使用DLL形式的插件时,因为DLL默认是为移动平台编译的,所以不支持复制粘贴(如果要支持,需要自己写原生代码支持)。如果是在PC平台上使用时,需要将CopyPastePatch.cs放到工程里,并在游戏启动时调用CopyPastePatch.Apply(),就可以在PC平台激活复制粘贴功能。如果你是使用源码形式的插件,不需要进行这个处理。

手势

FairyGUI提供了手势的支持。使用手势的方式是:

LongPressGesture gesture = new LongPressGesture(targetObject);
gesture.onAction.Add(OnGestureAction);

targetObject是接收手势的元件,注意一定要是可触摸的。图片是不可触摸的,一般建议用组件,或者装载器。如果你需要全屏幕监测手势,那么可以直接用GRoot.inst作为targetObject(需1.9.0 SDK或更高版本支持)

常用的手势有:

LongPressGesture 长按手势。可以设定长按触发的时间,还可以控制长按触发后继续触发通知的时间间隔。

SwipeGesture 手指划动手势。

PinchGesture两指缩放手势。

RotationGesture 两指旋转手势。

手势的使用方法可以参考Gesture这个Demo。手势与FairyGUI SDK是非耦合的,也就是说,如果你觉得手势不符合你的要求,你可以复制一个出来自己改自己用。