using bessw.Unity.WebView.ChromeDevTools; using bessw.Unity.WebView.ChromeDevTools.Protocol.Input; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace bessw.Unity.WebView { [RequireComponent(typeof(RawImage))] public class WebViewComponent : MonoBehaviour, IPointerDownHandler, IPointerMoveHandler, IPointerUpHandler, IPointerEnterHandler, IDropHandler, IPointerExitHandler { #region json serializer /// <summary> /// Json serializer settings for the user space objects (e.g. transfering objects that have been droped on the BrowserView) /// Users are allowed to change serializer settings to their liking. /// </summary> public static JsonSerializerSettings serializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver(), Converters = new List<JsonConverter>() { new ColorConverter(), new Vector2Converter(), new Vector3Converter(), new Vector4Converter() } }; /// <summary> /// JsonSerializer for the user space objects (e.g. transfering objects that have been droped on the BrowserView) /// Users are allowed to change serializer settings to their liking. /// </summary> public static JsonSerializer serializer = JsonSerializer.Create(serializerSettings); #endregion json serializer private Browser browser; protected BrowserTab tab; private RawImage rawImage; private RectTransform rectTransform; public bool headlessBrowser = true; //TODO: handle changed targetUrl public string targetUrl = "https://google.de"; // Start is called before the first frame update private void Start() { Debug.LogWarning("start Webview"); rawImage = this.gameObject.GetComponent<RawImage>(); rectTransform = this.gameObject.GetComponent<RectTransform>(); } private void OnEnable() { Debug.LogWarning("enable Webview"); Browser.headless = headlessBrowser; browser = Browser.getInstance(); //StartCoroutine(GetOpenTabs()); var c = StartCoroutine(browser.OpenNewTab(targetUrl, (BrowserTab bt) => { tab = bt; StartCoroutine(tab.Update()); //StartCoroutine(createScreenshots()); StartCoroutine(tab.StartStream(900, 560, (frame) => { Debug.LogWarning("stream"); rawImage.texture = frame; rawImage.SetNativeSize(); })); })); } public IEnumerator createScreenshots () { yield return tab.CreateScreenshot(900, 560, (screenshot) => { rawImage.texture = screenshot; StartCoroutine(createScreenshots()); }); } private IEnumerator getDropzoneState () { Debug.LogWarning($"dropzone pre"); DomNodeWrapper doc = null; yield return DomNodeWrapper.getDocument(tab, (document) => { Debug.LogWarning($"dropzone 1: '{document}'"); doc = document; StartCoroutine(document.querySelectorAll("[dropzone='copy']", (dropzones) => { foreach (var dropzone in dropzones) { Debug.LogWarning($"dropzone 2: Node is Null?: '{dropzone.Node == null}'"); StartCoroutine(dropzone.getAttributes((attributes) => { Debug.LogWarning($"dropzone 3 getAttributes: '{string.Join(", ", attributes.Values)}'"); })); } })); }); Debug.LogWarning($"dropzone post: '{doc}'"); // alternative way to get the dropzone state } // Update is called once per frame private void Update() { } #region pointer event handlers public void OnPointerDown(PointerEventData eventData) { Vector2Int pos = toBrowserCoordinates(eventData.position); tab.OnPointerDown(pos, eventData); } public void OnPointerMove(PointerEventData eventData) { // TODO: transform eventData delta vector to browser coordinates Vector2Int pos = toBrowserCoordinates(eventData.position); tab.OnPointerMove(pos, eventData); // On drag over if (eventData.dragging) { Debug.LogWarning($"OnDragOver: {eventData.position}"); createDragEvent(DragEventType.dragOver, eventData); } } public void OnPointerUp(PointerEventData eventData) { Vector2Int pos = toBrowserCoordinates(eventData.position); tab.OnPointerUp(pos, eventData); } #endregion pointer event handlers #region drag event handlers public void OnPointerEnter(PointerEventData eventData) { if (eventData.dragging) { Debug.LogWarning($"OnDragEnter: {eventData.position}"); createDragEvent(DragEventType.dragEnter, eventData); } } public void OnDrop(PointerEventData eventData) { Debug.LogWarning($"OnDrop: {eventData.position}"); createDragEvent(DragEventType.drop, eventData); // TODO: remove debug code StartCoroutine(getDropzoneState()); } public void OnPointerExit(PointerEventData eventData) { if (eventData.dragging) { Debug.LogWarning($"OnDragLeave: {eventData.position}"); //createDragEvent(DragEventType.dragCancel, eventData); tab.CancelDragging(); // TODO: drag cancel seems to be ignored by the browser } } private void createDragEvent(DragEventType dragEventType, PointerEventData eventData) { if (eventData.pointerDrag.TryGetComponent(out BrowserDropable dropable)) { var position = toBrowserCoordinates(eventData.position); var dragEvent = new dispatchDragEvent { type = dragEventType, data = new DragData { items = new DragDataItem[] { new DragDataItem { mimeType = "application/json", data = JsonConvert.SerializeObject(dropable, serializerSettings) } }, dragOperationsMask = DragOperationsMask.Copy }, x = position.x, y = position.y, }; Debug.LogWarning($"DragEvent: {dragEvent.type}, {eventData.position}, '{dragEvent.data.items[0].data}'"); // send the DragEvent as drag event to the browser tab.OnDragNDrop(dragEvent); } } #endregion drag event handlers private Vector2Int toBrowserCoordinates(Vector2 eventPos) { Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventPos, null, out localPoint); // invert y because the browser has y=0 on the top Vector2 invertedLocalPos = new Vector2(localPoint.x, rectTransform.rect.size.y - localPoint.y); Vector2 browserCoorinate = tab.size / rectTransform.rect.size * invertedLocalPos; Debug.Log($"eventPos: {eventPos}, invertedLocalPos: {invertedLocalPos}, browserCoordinate: {browserCoorinate}"); return new Vector2Int((int) browserCoorinate.x, (int) browserCoorinate.y); } private void OnDisable() { // TODO: do we want to close the browser when not in use? // close browser when recompiling tab.Close(); browser.Close(); } private void OnDestroy() { tab.Close(); browser.Close(); } /** * Close all browser windows. */ private void OnApplicationQuit() { tab.Close(); browser.Close(); } } public interface BrowserDropable { } }