Unity EmbeddedBrowser浏览器插件事件通讯

Unity EmbeddedBrowser浏览器插件事件通讯


Embedded Browser浏览器插件是一款基于Chrome内核的内嵌浏览器,被许多开发语言和框架内嵌,为开发者提供方便的浏览网页支持。
Embedded Browser浏览器的工作方式是在后台运行浏览器进程,通过后台浏览器通讯解析网址,合成Texture贴图帧,传递给Unity,同时Unity可以调用接口,与浏览器进程进行交互。

在这里插入图片描述
Embedded这种集成方式区别于移动端的WebView集成方式(WebView是将一块屏幕空间开辟出来给WebView使用,调用者和WebView之间没有太多关联),提供更自由的整合渠道,可以在三维空间和实体表面显示网页,使用更灵活。

模拟鼠标输入

通常,无论是Screen Canvas还是三维Mesh表面的Embedded页面,插件已经提供了无缝的输入方式,内部提供的MapPointerToBrowser已经帮助用户将三维坐标转换到Browser平面坐标。
如果我们要自定义输入,如远程控制,通过远程主机发送控制坐标和鼠标按键通讯,驱动非用户硬件输入,通常做法是引入Windows DLL,通过模拟鼠标可以达到要求

  #region DLLs
  [DllImport("user32.dll")]
  private static extern int SetCursorPos(int x, int y); //设置光标位置
  [DllImport("user32.dll")]
  private static extern bool GetCursorPos(ref int x, ref int y); //获取光标位置
  [DllImport("user32.dll")]
  static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, System.UIntPtr extraInfo); // 鼠标事件
                                                                                                      // 方法参数说明
                                                                                                      // VOID mouse_event(
                                                                                                      //     DWORD dwFlags,         // motion and click options
                                                                                                      //     DWORD dx,              // horizontal position or change
                                                                                                      //     DWORD dy,              // vertical position or change
                                                                                                      //     DWORD dwData,          // wheel movement
                                                                                                      //     ULONG_PTR dwExtraInfo  // application-defined information
                                                                                                      // );

  public enum MouseEventFlag : uint
  {
    
    
    Move = 0x0001,
    LeftDown = 0x0002,
    LeftUp = 0x0004,
    RightDown = 0x0008,
    RightUp = 0x0010,
    MiddleDown = 0x0020,
    MiddleUp = 0x0040,
    XDown = 0x0080,
    XUp = 0x0100,
    Wheel = 0x0800,
    VirtualDesk = 0x4000,
    Absolute = 0x8000
  }
  #endregion

调用代码

  IEnumerator MouseClick(int x, int y)
  {
    
    
    SetCursorPos(x, y);
    mouse_event(MouseEventFlag.LeftDown, 0, 0, 0, System.UIntPtr.Zero);
    yield return new WaitForSeconds(0.1f);
    mouse_event(MouseEventFlag.LeftUp, 0, 0, 0, System.UIntPtr.Zero);
  }

这种方法在调试和使用时,由于窗口分辨率不是1:1全屏导致坐标映射错误、窗口不在前台、干扰正常鼠操作等等问题,使用非常不友好。

调用Embedded接口直接输入

查看源代码BrowserInput.cs,可以看到插件处理输入事件代码

	private void HandleMouseInput() {
    
    
		var handler = browser.UIHandler;
		var mousePos = handler.MousePosition;
		var currentButtons = handler.MouseButtons;
		var mouseScroll = handler.MouseScroll;
		if (mousePos != prevPos) {
    
    
			BrowserNative.zfb_mouseMove(browser.browserId, mousePos.x, 1 - mousePos.y);
		}
		// ...
}

核心代码

BrowserNative.zfb_mouseMove(browser.browserId, mousePos.x, 1 - mousePos.y);

EmbeddedBrowser.Browser是虚拟给Unity使用的Browser对象,实际的浏览器对象是BrowserNative定义的一系列DLL接口。
browserId是一个数组索引,标记所有实际浏览器实例的列表
EmbeddedBrowser.Browser创建时加入allBrowsers列表

      unsafeBrowserId = newId;
      allBrowsers[unsafeBrowserId] = this;

按图索骥,BrowserNative包含了一系列浏览器接口,直接调用这些接口就可以扩展插件给我们定义的功能。
代码节选

	/**
	 * Reports the mouse's current location.
	 * x and y are in the range [0,1]. (0, 0) is top-left, (1, 1) is bottom-right
	 */
	public delegate void Calltype_zfb_mouseMove(int id, float x, float y);
	public static Calltype_zfb_mouseMove zfb_mouseMove;


	public delegate void Calltype_zfb_mouseButton(int id, MouseButton button, bool down, int clickCount);
	public static Calltype_zfb_mouseButton zfb_mouseButton;


	/** Reports a mouse scroll. One "tick" of a scroll wheel is generally around 120 units. */
	public delegate void Calltype_zfb_mouseScroll(int id, int deltaX, int deltaY);
	public static Calltype_zfb_mouseScroll zfb_mouseScroll;


	/**
	 * Report a key down/up event. Repeated "virtual" keystrokes are simulated by repeating the down event without
	 * an interveneing up event.
	 */
	public delegate void Calltype_zfb_keyEvent(int id, bool down, int windowsKeyCode);
	public static Calltype_zfb_keyEvent zfb_keyEvent;


	/**
	 * Report a typed character. This typically interleaves with calls to zfb_keyEvent
	 */
	public delegate void Calltype_zfb_characterEvent(int id, int character, int windowsKeyCode);
	public static Calltype_zfb_characterEvent zfb_characterEvent;


	/** Register a function to call when console.log etc. is called in the browser. */
	public delegate void Calltype_zfb_registerConsoleCallback(int id, ConsoleFunc callback);
	public static Calltype_zfb_registerConsoleCallback zfb_registerConsoleCallback;


	public delegate void Calltype_zfb_evalJS(int id, string script, string scriptURL);
	public static Calltype_zfb_evalJS zfb_evalJS;

调用BrowserNative接口,唯一需要标记是browserId,这个在EmbeddedBrowser.Browser中是一个保护变量

    /** Handle to the native browser. */
    [NonSerialized]
    internal protected int browserId;

我们给他增加一个公有属性

    /** Handle to the native browser. */
    [NonSerialized]
    internal protected int browserId;
    public int BrowserId {
    
     get {
    
     return browserId; } } // 增加公有属性暴露browserId

之后,我们就可以直接调用BrowserNative接口模拟鼠标输入了

  public void UpdateMouseEvent(EventType eventType, ViewRect rect)
  {
    
    
    float x = rect.x / rect.width;
    float y = rect.y / rect.height;
    Vector2 pos = MapPointerToBrowser(x, y, viewRect);
    if (eventType == EventType.MouseDown)
    {
    
    
      ZenFulcrum.EmbeddedBrowser.BrowserNative.zfb_mouseMove(browser.BrowserId, pos.x, pos.y); // 注意:x,y坐标为0-1范围
      ZenFulcrum.EmbeddedBrowser.BrowserNative.zfb_mouseButton(browser.BrowserId, ZenFulcrum.EmbeddedBrowser.BrowserNative.MouseButton.MBT_LEFT, true, 1);
    }
    else if (eventType == EventType.MouseUp)
    {
    
    
      ZenFulcrum.EmbeddedBrowser.BrowserNative.zfb_mouseButton(browser.BrowserId, ZenFulcrum.EmbeddedBrowser.BrowserNative.MouseButton.MBT_LEFT, false, 1);
    }
    else if (eventType == EventType.MouseMove)
    {
    
    
      ZenFulcrum.EmbeddedBrowser.BrowserNative.zfb_mouseMove(browser.BrowserId, pos.x, pos.y); // 注意:x,y坐标为0-1范围
    }
  }

猜你喜欢

转载自blog.csdn.net/qq_31042143/article/details/125551279