はじめに
先日、10月5日に開催された第1回 裏 OcuFes という Oculus Rift ユーザの開発者向けイベントへ参加してきました。参加者のほとんどの方が発表、色々な方面の濃い方々が集まるとても楽しいイベントでした。その場で私も発表してきたのでその資料をアップしました。
資料
内容
先日書きました Oculus Rift でミクさんに画面の中から出てきていただいた:解説 - 凹みTips と、PS Eye × 2個 を Unity 上で Oculus SDK と共に使ってみた - 凹みTips、Unity で Web をテクスチャとして表示して操作する方法について調べてみた - 凹みTips を組み合わせたネタを発表しました。ミクさんに来ていただく方は先日の記事をご参照いただくとして、ここではイベント中では話せなかったブラウザの方の解説をしたいと思います。
Awesomium がとても良く出来ているため、WebView に対して行いたい操作はおおよそ用意されており、UnityAwe の WebTexture.cs を参考にすれば簡単にやりたいことを実現出来ました。私はこれを参考に、カメラ前方へ Raycast して当たった点にマウス操作をインジェクションしているだけです。また、透過に関してはシェーダを Diffuse から Transparent に切り替えるだけで実現しています。
Crosshair.cs
using UnityEngine; using System.Collections; using AwesomiumMono; public class Crosshair : MonoBehaviour { private GameObject camera_; private GameObject image_; private WebTexture targetWebView_; private int cnt_ = 0; private int moveCnt_ = 0; private int clickCnt_ = 0; private bool clicking_ = false; private Vector2 lastPoint_ = Vector2.zero; public Texture normalTexture; public Texture clickTexture; public int clickCount = 60; public float distance = 5.0f; public float clickDistanceThreashold = 5.0f; void Start() { camera_ = GameObject.FindWithTag("MainCamera"); image_ = transform.GetChild(0).gameObject; image_.renderer.material.mainTexture = normalTexture; } void Update() { RaycastHit hit; Vector3 from = camera_.transform.position; Vector3 to = camera_.transform.forward; int layerMask = ~(1 << gameObject.layer); // Crosshair 自体を避けるため if ( Physics.Raycast(from, to, out hit, 10, layerMask) ) { WebTexture webtex = hit.transform.GetComponent<WebTexture>(); if (!webtex) return; int x = (int)(hit.textureCoord.x * webtex.width); int y = (int)(webtex.height - hit.textureCoord.y * webtex.height); webtex.getWebView().InjectMouseMove(x, y); Debug.Log ("x: " + x + ", y: " + y); // Click Vector2 point = new Vector2(x, y); if (lastPoint_ == Vector2.zero) { lastPoint_ = point; } if (Vector2.Distance(point, lastPoint_) < clickDistanceThreashold) { ++moveCnt_; } else { lastPoint_ = point; moveCnt_ = 0; } if (moveCnt_ > clickCount) { webtex.getWebView().InjectMouseDown(MouseButton.Left); webtex.getWebView().InjectMouseUp(MouseButton.Left); moveCnt_ = 0; clicking_ = true; image_.renderer.material.mainTexture = clickTexture; } if (clicking_) { if (clickCnt_ > 10) { clicking_ = false; clickCnt_ = 0; image_.renderer.material.mainTexture = normalTexture; } ++clickCnt_; } // Scroll if (x < webtex.width * 0.1 && cnt_ % 10 == 0) { WebKeyboardEvent keyEvent = new WebKeyboardEvent(); keyEvent.Type = WebKeyType.KeyDown; keyEvent.VirtualKeyCode = VirtualKey.LEFT; webtex.getWebView().InjectKeyboardEvent(keyEvent); keyEvent.Type = WebKeyType.KeyUp; webtex.getWebView().InjectKeyboardEvent(keyEvent); } else if (x > webtex.width * 0.9 && cnt_ % 10 == 0) { WebKeyboardEvent keyEvent = new WebKeyboardEvent(); keyEvent.Type = WebKeyType.KeyDown; keyEvent.VirtualKeyCode = VirtualKey.RIGHT; webtex.getWebView().InjectKeyboardEvent(keyEvent); keyEvent.Type = WebKeyType.KeyUp; webtex.getWebView().InjectKeyboardEvent(keyEvent); } if (y < webtex.height * 0.1) { webtex.getWebView().InjectMouseWheel(10); } else if (y < webtex.height * 0.2) { webtex.getWebView().InjectMouseWheel(5); } else if (y > webtex.height * 0.9) { webtex.getWebView().InjectMouseWheel(-10); } else if (y > webtex.height * 0.8) { webtex.getWebView().InjectMouseWheel(-5); } } ++cnt_; } void LateUpdate() { transform.position = camera_.transform.position + camera_.transform.forward * distance; transform.rotation = camera_.transform.rotation; } }
おわりに
とても面白い発表が多くてこの場でメモを貼りたいところですが、もろもろの事情により自粛させて頂きます。。。内容を知りたい方は是非次回の OcuFes にご参加頂き、直接発表者の方々へお尋ねください!