Created
November 27, 2017 16:38
-
-
Save hon454/3ae400b2943ee01043de55804aaf005f to your computer and use it in GitHub Desktop.
Android VR Webview Texture for Unity (more information at: https://jerome.gangneux.net/projects/2017-02-android-vr-webview/)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.EventSystems; | |
using System; | |
using System.Collections; | |
using System.Runtime.InteropServices; | |
[RequireComponent(typeof(Renderer))] | |
public class AndroidWebview : MonoBehaviour, IPointerExitHandler, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler { | |
// Public values | |
/** | |
* Default URL to load, you can load a new URL with LoadUrl(String url) | |
*/ | |
public string url = "https://www.google.com/"; | |
/** | |
* Default Texture size | |
*/ | |
public int textureWidth = 640; | |
public int textureHeight = 640; | |
/** | |
* This is only to show that delegation and events works | |
* You can remove this :) | |
*/ | |
public TextMesh statusText = null; | |
public TextMesh eventText = null; | |
/** | |
* Get more debug message in the Android logcat | |
*/ | |
public bool isDebug = false; | |
// Internals objects | |
protected Texture2D nativeTexture = null; | |
protected IntPtr nativeTexId = IntPtr.Zero; | |
protected AndroidJavaObject view = null; | |
/** | |
* You need a Renderer with a texture (best result with unlit texture) | |
*/ | |
protected Renderer mainRenderer = null; | |
public enum ActionEvent { | |
Down = 1, | |
Up = 2, | |
Move = 3, | |
Max | |
} | |
protected enum SurfaceEvent { | |
Init = 0, | |
Stop = 1, | |
Update = 2, | |
Max | |
}; | |
// Configuration | |
/** | |
* Set to true if you want to send event to the Native Webview | |
* Related to PositionInformation(Vector2, ActionEvent) | |
*/ | |
protected bool propagateHitEvent = true; | |
// State | |
protected bool isClickedDown = false; | |
protected bool isScrolling = false; | |
protected Vector2 lastPosition = Vector2.zero; | |
// Unity life cycle | |
/** | |
* Used to configure the renderer and the external texture | |
*/ | |
void Awake () { | |
JRMGX_Android_View_Init (); | |
mainRenderer = GetComponent<Renderer> (); | |
if (mainRenderer.material == null) { | |
Debug.LogError ("No material for surface"); | |
} else if (mainRenderer.material.mainTexture == null) { | |
Debug.LogError ("No material.mainTexture for surface"); | |
} | |
nativeTexture = Texture2D.CreateExternalTexture (textureWidth, textureHeight, TextureFormat.RGBA32, true, false, IntPtr.Zero); | |
IssuePluginEvent (SurfaceEvent.Init); | |
} | |
/** | |
* Start the rendering of the Webview | |
*/ | |
void Start() { | |
StartCoroutine (DelayedStart()); | |
} | |
/** | |
* Check each frame if the Webview has a new update | |
*/ | |
void Update () { | |
IntPtr currTexId = JRMGX_Android_View_GetTexture (); | |
if (currTexId != nativeTexId) { | |
nativeTexId = currTexId; | |
nativeTexture.UpdateExternalTexture (currTexId); | |
Debug.Log ("AndroidView - texture size is " + nativeTexture.width + " x " + nativeTexture.height); | |
} | |
IssuePluginEvent (SurfaceEvent.Update); | |
} | |
/** | |
* Ask the Webview to consume waiting event | |
*/ | |
void LateUpdate () { | |
if (propagateHitEvent == false) return; | |
if (view != null) { | |
view.Call ("eventPoll"); | |
} | |
} | |
void OnApplicationQuit () { | |
IssuePluginEvent (SurfaceEvent.Stop); | |
} | |
// Public interface | |
/** | |
* Webview method goBack | |
* Load the previous page if possible | |
*/ | |
public void GoBack () { | |
view.Call ("goBack"); | |
} | |
/** | |
* Webview method goForward | |
* Load the next page if possible | |
*/ | |
public void GoForward () { | |
view.Call ("goForward"); | |
} | |
/** | |
* Webview method loadUrl | |
* Load a new Url in the webview | |
*/ | |
public void LoadUrl (String newUrl) { | |
url = newUrl; | |
view.Call ("loadUrl", newUrl); | |
} | |
// Delegation | |
/** | |
* The Webview will give you delegate messages for specific events | |
* message: | |
* - onPageStarted:string <-- when a new url is about to be loaded | |
* - onPageFinished:string <-- when a new url has finished to load | |
* - onReceivedError:string <-- when an error happen | |
* you need to parse these messages and handle it as you wish | |
*/ | |
protected void Delegation (string message) { | |
// Do something here with `message` | |
if (statusText != null) { | |
statusText.text = message; | |
} | |
} | |
/** | |
* Debug method, can be removed | |
*/ | |
protected void PrintEvent (string message) { | |
if (eventText == null) return; | |
eventText.text = message; | |
} | |
// Sending event | |
/** | |
* This is how you can send `Move` action to the Webview | |
* position is the final pointer position on the underlying 2D Webview | |
* It is android coordinate system: top,left = 0,0 / bottom,right = textureHeight,textureWidth | |
* See the `Event system` section below for an example | |
*/ | |
public void PositionInformation (Vector2 position, ActionEvent actionType) { | |
if (propagateHitEvent == false) return; | |
if (view != null) { | |
// This is for debugging only you should remove it | |
PrintEvent ("event " + actionType.ToString () + " sent: " + position.ToString ()); | |
view.Call ("eventAdd", (int) position.x, (int) position.y, (int) actionType); | |
} | |
} | |
// Event system | |
/** | |
* Convert an Unity `PointerEventData` position to the webview coordinate position | |
* This needs to be adapted for you scene | |
*/ | |
public void UpdateLastPosition (PointerEventData eventData) { | |
// This needs to be adapted for you scene | |
// It depends on how you transformed your GameObject | |
// You will have try to adapt +/- and choose from x/y/z on position | |
Vector3 position = transform.InverseTransformPoint (eventData.pointerCurrentRaycast.worldPosition); | |
//Debug.Log (position); // Use debug.log and adb logcat to find out | |
float x = ((position.x + 5) / 10) * textureWidth; | |
float y = ((position.z - 5) / -10) * textureHeight; | |
lastPosition = new Vector2 (x, y); | |
} | |
#region IPointerExitHandler implementation | |
/** | |
* When the pointer get out of the GameObject we considerate that the user did an ActionEvent.Up | |
*/ | |
public void OnPointerExit (PointerEventData eventData) { | |
isClickedDown = false; | |
UpdateLastPosition (eventData); | |
PositionInformation (lastPosition, ActionEvent.Up); | |
} | |
#endregion | |
#region IPointerClickHandler implementation | |
/** | |
* Example of event system implementation | |
*/ | |
public void OnPointerClick (PointerEventData eventData) { | |
if (isScrolling) return; // Skip the click event if we are scrolling | |
UpdateLastPosition (eventData); | |
PositionInformation (lastPosition, ActionEvent.Down); | |
PositionInformation (lastPosition, ActionEvent.Up); | |
} | |
#endregion | |
#region IEndDragHandler implementation | |
public void OnEndDrag (PointerEventData eventData) { | |
UpdateLastPosition (eventData); | |
PositionInformation (lastPosition, ActionEvent.Up); | |
isScrolling = false; | |
} | |
#endregion | |
#region IDragHandler implementation | |
public void OnDrag (PointerEventData eventData) { | |
isScrolling = true; | |
UpdateLastPosition (eventData); | |
PositionInformation (lastPosition, ActionEvent.Move); | |
} | |
#endregion | |
#region IBeginDragHandler implementation | |
public void OnBeginDrag (PointerEventData eventData) { | |
isScrolling = true; | |
UpdateLastPosition (eventData); | |
PositionInformation (lastPosition, ActionEvent.Down); | |
} | |
#endregion | |
#region IGvrPointerHoverHandler implementation | |
/** | |
* Example of event system implementation for Google Daydream | |
* This will conflict with Unity event handle above, please remove them. | |
* | |
* This method is an example and works only with the Google Daydream asset installed (IGvrPointerHoverHandler) | |
* if you don't use Google Daydream you may achieve the same result with classic Unity event handler (above) | |
*/ | |
public void OnGvrPointerHover (PointerEventData eventData) { | |
/* | |
UpdateLastPosition (eventData); | |
// If you use the Google Daydream asset, you could do something like that | |
if (GvrController.ClickButtonDown) { | |
isClickedDown = true; | |
PositionInformation (lastPosition, ActionEvent.Down); | |
} | |
else if (GvrController.ClickButtonUp) { | |
isClickedDown = false; | |
PositionInformation (lastPosition, ActionEvent.Up); | |
} | |
if (isClickedDown) { | |
PositionInformation (lastPosition, ActionEvent.Move); | |
} | |
*/ | |
} | |
#endregion | |
// Internal to plugin | |
// ... | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment