当前位置:网站首页>Unity EmbeddedBrowser浏览器插件事件通讯
Unity EmbeddedBrowser浏览器插件事件通讯
2022-07-03 12:59:00 【foenix66】
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范围
}
}
边栏推荐
- untiy世界边缘的物体阴影闪动,靠近远点的物体阴影正常
- The reasons why there are so many programming languages in programming internal skills
- PowerPoint 教程,如何在 PowerPoint 中將演示文稿另存為視頻?
- Flink SQL knows why (7): haven't you even seen the ETL and group AGG scenarios that are most suitable for Flink SQL?
- Kivy教程之 盒子布局 BoxLayout将子项排列在垂直或水平框中(教程含源码)
- Internet of things completion -- (stm32f407 connects to cloud platform detection data)
- The 35 required questions in MySQL interview are illustrated, which is too easy to understand
- R语言使用data函数获取当前R环境可用的示例数据集:获取datasets包中的所有示例数据集、获取所有包的数据集、获取特定包的数据集
- MapReduce implements matrix multiplication - implementation code
- 已解决TypeError: Argument ‘parser‘ has incorrect type (expected lxml.etree._BaseParser, got type)
猜你喜欢
Road construction issues
(first) the most complete way to become God of Flink SQL in history (full text 180000 words, 138 cases, 42 pictures)
Flink SQL knows why (7): haven't you even seen the ETL and group AGG scenarios that are most suitable for Flink SQL?
File uploading and email sending
[Database Principle and Application Tutorial (4th Edition | wechat Edition) Chen Zhibo] [Chapter IV exercises]
rxjs Observable filter Operator 的实现原理介绍
Logseq 评测:优点、缺点、评价、学习教程
Elk note 24 -- replace logstash consumption log with gohangout
MySQL constraints
The principle of human voice transformer
随机推荐
Comprehensive evaluation of double chain notes remnote: fast input, PDF reading, interval repetition / memory
R语言gt包和gtExtras包优雅地、漂亮地显示表格数据:nflreadr包以及gtExtras包的gt_plt_winloss函数可视化多个分组的输赢值以及内联图(inline plot)
User and group command exercises
Kivy教程之 盒子布局 BoxLayout将子项排列在垂直或水平框中(教程含源码)
Sword finger offer 14- ii Cut rope II
Anan's doubts
Cadre de logback
Setting up remote links to MySQL on Linux
用户和组命令练习
DQL basic query
服务器硬盘冷迁移后网卡无法启动问题
Servlet
开始报名丨CCF C³[email protected]奇安信:透视俄乌网络战 —— 网络空间基础设施面临的安全对抗与制裁博弈...
Flink code is written like this. It's strange that the window can be triggered (bad programming habits)
Detailed explanation of multithreading
Elk note 24 -- replace logstash consumption log with gohangout
使用tensorflow进行完整的DNN深度神经网络CNN训练完成图片识别案例
双链笔记 RemNote 综合评测:快速输入、PDF 阅读、间隔重复/记忆
正则表达式
106. How to improve the readability of SAP ui5 application routing URL