Skip to content

Instantly share code, notes, and snippets.

@JCxYIS
Created May 2, 2022 16:13
Show Gist options
  • Save JCxYIS/d3a7aa93df617a0391f8e4d9a08b28fc to your computer and use it in GitHub Desktop.
Save JCxYIS/d3a7aa93df617a0391f8e4d9a08b28fc to your computer and use it in GitHub Desktop.
PicoVR 鍵盤工具插件:使其支援 Input Field (見 https://hackmd.io/@jcxyisncu1102/steamvr-to-pico/%2FUyRsBE57Sw-JtpjEBhz_6g )
/// Modded by JCxYIS
/// 20220328
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using UnityEngine.EventSystems;
using Pvr_UnitySDKAPI;
public class ImeDelegateImpl : ImeDelegateBase
{
public class TextComponent
{
public string text
{
get { return TextGetter.Invoke(); }
set { TextSetter.Invoke(value); }
}
private Func<string> TextGetter;
private Action<string> TextSetter;
public static explicit operator TextComponent(InputField inputField)
{
TextComponent tc = new TextComponent();
tc.TextGetter = () => inputField.text;
tc.TextSetter = str => inputField.text = str;
return tc;
}
public static explicit operator TextComponent(Text text)
{
TextComponent tc = new TextComponent();
tc.TextGetter = () => text.text;
tc.TextSetter = str => text.text = str;
return tc;
}
}
public TextComponent mText;
public GameObject[] mKbdViews;
public SGViewGather mKbdView;
public ImeManager mManager;
private Texture2D mTexture;
private Vector2 mTextureSize = new Vector2(780,390);
private Vector2 mPtKbd = new Vector2();
private SGClickTracker mTracker = new SGClickTracker();
//ImeDelegateBase
public override void OnIMEShow(Vector2 vSize)
{
Debug.Log("sogou DelegateImpl OnIMEShow");
mTextureSize = vSize;
Debug.Log("sogou DelegateImpl OnIMEShow, size = " + mTextureSize[0] + ":" + mTextureSize[1]);
CreateTexture(vSize);
mManager.Draw(mTexture);
mKbdView.SetActive(true);
}
public override void OnIMEHide()
{
Debug.Log("sogou DelegateImpl OnIMEHide");
mKbdView.SetActive(false);
}
public override void OnIMECommit(string strCommit)
{
mText.text += strCommit;
}
public override void OnIMEKey(SGImeKey key)
{
switch (key)
{
case SGImeKey.KEYCODE_DEL:
String strText = mText.text;
mText.text = strText.Remove(strText.Length - 1);
break;
case SGImeKey.KEYCODE_ENTER:
mText.text = "";
break;
}
}
public override void OnIMEError(SGImeError nType, string strErr)
{
}
//MonoBehaviour
void Start()
{
mKbdView = new SGViewGather(mKbdViews);
CreateTexture(mTextureSize);
#if UNITY_EDITOR
#else
mKbdView.SetActive(false);
#endif
}
void Update()
{
//Debug.Log("panel update");
CheckMouseEvent();
mManager.Draw(mTexture);
}
//other
private void CreateTexture(Vector2 vSize)
{
if (mTexture)
{
return;
}
#if UNITY_EDITOR
#else
// Create a texture
mTexture = new Texture2D((int)vSize.x, (int)vSize.y, TextureFormat.RGBA32, false);
// Set point filtering just so we can see the pixels clearly
mTexture.filterMode = FilterMode.Trilinear;
// Call Apply() so it's actually uploaded to the GPU
mTexture.Apply();
Debug.Log(" sogou DelegateImpl_kbd CreateTexture: texture created");
// Set texture onto cube
//GameObject cube = GameObject.Find("Cube");
//cube.GetComponent<Renderer>().material.mainTexture = mTexture;
// Set texture onto kbdview
mKbdView.SetTexture(mTexture);
#endif
}
private void DispatchMessageToAndroid(SGImeMotionEventType type, Vector2 pt)
{
if (null != mManager)
{
mManager.OnTouch(pt.x, pt.y, type);
}
}
private void LogEvent(string prefix, PointerEventData eventData)
{
Debug.Log(prefix + ": " + eventData.pointerCurrentRaycast.gameObject.name + " x=" + eventData.position.x + ",y=" + eventData.position.y);
}
private void CheckMouseEvent()
{
if (Point2UV(mRay, ref mPtKbd))
{
if (mTracker.Track(mPtKbd, Input.GetKeyDown(KeyCode.JoystickButton0) ||
Controller.UPvr_GetKeyClick(0, Pvr_KeyCode.TOUCHPAD) || Controller.UPvr_GetKeyClick(0, Pvr_KeyCode.TRIGGER) || Controller.UPvr_GetKeyClick(0, Pvr_KeyCode.X) ||
Controller.UPvr_GetKeyClick(1, Pvr_KeyCode.TOUCHPAD) || Controller.UPvr_GetKeyClick(1, Pvr_KeyCode.TRIGGER) || Controller.UPvr_GetKeyClick(1, Pvr_KeyCode.A)))
{
DispatchMessageToAndroid(mTracker.GetEvent(), mTracker.GetPoint());
}
else if (mTracker.Track(mPtKbd, Controller.UPvr_GetKeyClick(0, Pvr_KeyCode.Y) || Controller.UPvr_GetKeyClick(1, Pvr_KeyCode.B) ||
Controller.UPvr_GetKeyClick(0, Pvr_KeyCode.APP) || Controller.UPvr_GetKeyClick(1, Pvr_KeyCode.APP)))
{
mManager.Hide();
}
} else if (mTracker.TrackOuter() )
{
DispatchMessageToAndroid(mTracker.GetEvent(), mTracker.GetPoint());
}
}
public Pvr_ControllerDemo_VRInput controller;
private Ray mRay => controller ? controller.ray : PicoVRcontroller.Instance?.Ray ?? new Ray();
private bool Point2UV(Ray ray, ref Vector2 ptUV)
{
RaycastHit hitInfo;
bool bRes = false;
if (Physics.Raycast(ray, out hitInfo))
{
string name = hitInfo.collider.gameObject.name;
if (mKbdView.FindName(name))
{
GameObject kbd = hitInfo.collider.gameObject;
Vector3 vecKbd = kbd.transform.InverseTransformPoint(hitInfo.point);
Vector2 pixelUV = hitInfo.textureCoord;
Renderer rend = hitInfo.transform.GetComponent<Renderer>();
ptUV.x = pixelUV.x * mTextureSize.x;
ptUV.y = (1 - pixelUV.y) * mTextureSize.y;
//Debug.Log("ray click " + name + ": 3d point=" + vecKbd.ToString() + " uv=(" + pixelUV.x + "," + pixelUV.y + ") org=(" + ptUV.ToString() + ")" + " w=" + texSize.x + ",h=" + texSize.y);
bRes = true;
}
}
return bRes;
}
}
public class SGViewGather
{
private GameObject[] mViews;
public SGViewGather(GameObject[] param)
{
mViews = param;
}
public void SetActive(bool bActive)
{
foreach (GameObject view in mViews)
{
view.SetActive(bActive);
}
}
public bool FindName(string name)
{
foreach (GameObject view in mViews)
{
if (view.name == name)
{
return true;
}
}
return false;
}
public void SetTexture(Texture2D tex)
{
foreach (GameObject view in mViews)
{
Renderer rend = view.GetComponent<Renderer>();
rend.material.mainTexture = tex;
}
}
}
public class SGClickTracker
{
private bool mDownOld = false;
private Vector2 mPtOld = new Vector2();
private SGImeMotionEventType mEvent;
private const float mTrackRadius = 10.0f;
private long mTimeDown;
private bool mLongPressed = false;
private long mIntervelLongPress = 100;
public bool Track(Vector2 pt, bool bDown)
{
bool bRes = false;
if (bDown)
{
if (mDownOld)
{
mEvent = SGImeMotionEventType.ACTION_MOVE;
if (!mLongPressed)
{
long timeDiff = DateTime.Now.Ticks - mTimeDown;
if (timeDiff > mIntervelLongPress)
{
mLongPressed = true;
mEvent = SGImeMotionEventType.ACTION_LONGPRESS;
bRes = true; //force sendmessage
}
}
}
else
{
mEvent = SGImeMotionEventType.ACTION_DOWN;
mTimeDown = DateTime.Now.Ticks;
mLongPressed = false;
}
}
else
{
if (mDownOld)
{
mEvent = SGImeMotionEventType.ACTION_UP;
}
else
{
//mEvent = SGImeMotionEventType.ACTION_HOVER_MOVE;
mEvent = SGImeMotionEventType.ACTION_MOVE; //c++代码只识别move事件
}
}
if (mDownOld != bDown)
{
bRes = true;
}
else if (PointDist(mPtOld, pt) > mTrackRadius)
{
bRes = true;
}
mDownOld = bDown;
if (bRes)
{
mPtOld = pt;
}
return bRes;
}
public bool TrackOuter()
{
bool bRes = false;
if (mEvent != SGImeMotionEventType.ACTION_OUTSIDE)
{
SGImeMotionEventType eventOld = mEvent;
mEvent = SGImeMotionEventType.ACTION_OUTSIDE;
}
return bRes;
}
public Vector2 GetPoint()
{
return mPtOld;
}
public SGImeMotionEventType GetEvent()
{
return mEvent;
}
private float PointDist(Vector2 ptNew, Vector2 ptOld)
{
return Math.Abs(ptNew[0] - ptOld[0]) + Math.Abs(ptNew[1] - ptOld[1]);
}
}
/// Modded by JCxYIS
/// 20220328
using Pvr_UnitySDKAPI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class TextHandler : MonoBehaviour,IPointerEnterHandler,IPointerExitHandler
{
public ImeManager mManager;
public SGImeInputType mInputType;
public SGImeTextType mTextType;
private bool isSelect;
ImeDelegateImpl.TextComponent inputComponent = null;
// Start is called before the first frame update
void Start()
{
if (GetComponent<Text>())
inputComponent = (ImeDelegateImpl.TextComponent)GetComponent<Text>();
else if(GetComponent<InputField>())
inputComponent = (ImeDelegateImpl.TextComponent)GetComponent<InputField>();
}
// Update is called once per frame
void Update()
{
if (isSelect)
{
if (Input.GetKeyDown(KeyCode.JoystickButton0) || Input.GetMouseButtonDown(0) ||
Controller.UPvr_GetKeyClick(0, Pvr_KeyCode.TOUCHPAD) || Controller.UPvr_GetKeyClick(0, Pvr_KeyCode.TRIGGER) || Controller.UPvr_GetKeyClick(0, Pvr_KeyCode.X) ||
Controller.UPvr_GetKeyClick(1, Pvr_KeyCode.TOUCHPAD) || Controller.UPvr_GetKeyClick(1, Pvr_KeyCode.TRIGGER) || Controller.UPvr_GetKeyClick(1, Pvr_KeyCode.A))
{
mManager.Show(mInputType, mTextType);
if(inputComponent == null)
Debug.LogError("[TextHandler] 此物件沒有可輸入的文字組件");
else
FindObjectOfType<ImeDelegateImpl>().mText = inputComponent;
// inputComponent.text = "Test48763";
}
}
}
public void OnPointerEnter(PointerEventData eventData)
{
// Debug.Log("TextHandler OnPointerEnter");
isSelect = true;
}
public void OnPointerExit(PointerEventData eventData)
{
// Debug.Log("TextHandler OnPointerExit");
isSelect = false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment