|
14 | 14 | # |
15 | 15 | # This will enable your copy of python to find the panda libraries. |
16 | 16 |
|
17 | | -# TODO: implement forwarding key/mouse events to the CEF browser. |
18 | | -# Browser object has following methods: SendKeyEvent(), |
19 | | -# SendMouseClickEvent(), SendMouseMoveEvent(), |
20 | | -# SendMouseWheelEvent(), SendFocusEvent(), |
21 | | -# SendCaptureLostEvent(). |
| 17 | +# TODO: fix the blurriness of the browser when window is resized. |
22 | 18 |
|
23 | 19 | import platform |
24 | 20 | if platform.architecture()[0] != "32bit": |
|
37 | 33 | from panda3d.core import * |
38 | 34 | from direct.showbase.DirectObject import DirectObject |
39 | 35 | from direct.task import Task |
40 | | -from math import pi, sin, cos |
| 36 | +from math import pi, sin, cos, floor, ceil |
| 37 | +import platform |
| 38 | +import ctypes |
41 | 39 |
|
42 | 40 | class World(DirectObject): |
43 | | - |
44 | 41 | browser = None |
45 | 42 | texture = None |
46 | 43 |
|
47 | 44 | def __init__(self): |
| 45 | + wp = WindowProperties() |
| 46 | + wp.setTitle('Panda3D example') |
| 47 | + base.win.requestProperties(wp) |
48 | 48 |
|
49 | 49 | environ = loader.loadModel("models/environment") |
50 | 50 | environ.reparentTo(render) |
51 | 51 | environ.setScale(0.25,0.25,0.25) |
52 | 52 | environ.setPos(-8,42,0) |
53 | 53 | taskMgr.add(self.spinCameraTask, "SpinCameraTask") |
54 | 54 |
|
55 | | - windowHandle = base.win.getWindowHandle().getIntHandle() |
56 | | - |
57 | 55 | self.texture = Texture() |
58 | | - self.texture.setXSize(400) |
59 | | - self.texture.setYSize(300) |
60 | 56 | self.texture.setCompression(Texture.CMOff) |
61 | 57 | self.texture.setComponentType(Texture.TUnsignedByte) |
62 | 58 | self.texture.setFormat(Texture.FRgba4) |
| 59 | + self.texture.setTexturesPower2(0) |
| 60 | + self.texture.setAutoTextureScale(0) |
63 | 61 |
|
64 | | - cardMaker = CardMaker("browser2d") |
65 | | - cardMaker.setFrame(-0.75,.75,-0.75,0.75) |
66 | | - card = render2d.attachNewNode(cardMaker.generate()) |
67 | | - card.setTexture(self.texture) |
68 | | - card.setHpr(0, 0, 5) |
| 62 | + self.cardMaker = CardMaker("browser2d") |
| 63 | + self.cardMaker.setFrame(-0.75, 0.75, -0.75, 0.75) |
| 64 | + node = self.cardMaker.generate() |
| 65 | + self.nodePath = render2d.attachNewNode(node) |
| 66 | + self.nodePath.setTexture(self.texture) |
| 67 | + self.nodePath.setHpr(0, 0, 5) |
69 | 68 |
|
| 69 | + windowHandle = base.win.getWindowHandle().getIntHandle() |
70 | 70 | windowInfo = cefpython.WindowInfo() |
71 | 71 | windowInfo.SetAsOffscreen(windowHandle) |
| 72 | + |
72 | 73 | self.browser = cefpython.CreateBrowserSync( |
73 | 74 | windowInfo, browserSettings={}, navigateURL="cefsimple.html") |
74 | 75 | self.browser.SetClientHandler( |
75 | 76 | ClientHandler(self.browser, self.texture)) |
76 | | - self.browser.SetSize(cefpython.PET_VIEW, 400, 300); |
| 77 | + |
| 78 | + # SetFocus needs to be called after browser creation. |
| 79 | + if platform.system() == "Windows": |
| 80 | + ctypes.windll.user32.SetFocus(windowHandle) |
| 81 | + |
| 82 | + self.setBrowserSize() |
| 83 | + self.accept("window-event", self.setBrowserSize) |
| 84 | + |
| 85 | + # Browser methods for sending mouse/keyboard/focus events: |
| 86 | + # SendKeyEvent(), SendMouseClickEvent(), SendMouseMoveEvent(), |
| 87 | + # SendMouseWheelEvent(), SendFocusEvent(), SendCaptureLostEvent(). |
| 88 | + |
| 89 | + self.initMouseHandlers() |
| 90 | + self.initKeyboardHandlers() |
77 | 91 |
|
78 | 92 | taskMgr.add(self.messageLoop, "CefMessageLoop") |
79 | 93 |
|
| 94 | + def setBrowserSize(self, window=None): |
| 95 | + width = int(round(base.win.getXSize() * 0.75)) |
| 96 | + height = int(round(base.win.getYSize() * 0.75)) |
| 97 | + self.texture.setXSize(width) |
| 98 | + self.texture.setYSize(height) |
| 99 | + self.browser.SetSize(cefpython.PET_VIEW, width, height) |
| 100 | + |
| 101 | + def initMouseHandlers(self): |
| 102 | + taskMgr.add(self.onMouseMove, "onMouseMove") |
| 103 | + self.accept("mouse1", self.onMouseDown) |
| 104 | + self.accept("mouse1-up", self.onMouseUp) |
| 105 | + self.accept("wheel_up", self.onMouseWheelUp) |
| 106 | + self.accept("wheel_down", self.onMouseWheelDown) |
| 107 | + |
| 108 | + def initKeyboardHandlers(self): |
| 109 | + pass |
| 110 | + |
| 111 | + def isMouseInsideBrowser(self, mouse): |
| 112 | + if mouse.getX() >= -0.75 and mouse.getX() <= 0.75 and ( |
| 113 | + mouse.getY() >= -0.75 and mouse.getY() <= 0.75): |
| 114 | + return True |
| 115 | + else: |
| 116 | + return False |
| 117 | + |
| 118 | + def getMousePixelCoordinates(self, mouse): |
| 119 | + # This calculation works only for the browser area. |
| 120 | + relX = mouse.getX() |
| 121 | + relY = mouse.getY() |
| 122 | + relX += 0.75 # 0 .. 1.5 |
| 123 | + relY += 0.75 # 0 .. 1.5 |
| 124 | + width = self.texture.getXSize() |
| 125 | + height = self.texture.getYSize() |
| 126 | + width /= 1.5 |
| 127 | + height /= 1.5 |
| 128 | + pixelX = relX * width |
| 129 | + pixelY = relY * height |
| 130 | + pixelY = abs(pixelY - self.texture.getYSize()) |
| 131 | + pixelX = int(round(pixelX)) |
| 132 | + pixelY = int(round(pixelY)) |
| 133 | + return (pixelX, pixelY) |
| 134 | + |
| 135 | + def onMouseMove(self, task): |
| 136 | + if base.mouseWatcherNode.hasMouse(): |
| 137 | + mouse = base.mouseWatcherNode.getMouse() |
| 138 | + if self.isMouseInsideBrowser(mouse): |
| 139 | + self.nodePath.setHpr(0, 0, 0) |
| 140 | + (x,y) = self.getMousePixelCoordinates(mouse) |
| 141 | + self.browser.SendMouseMoveEvent(x, y, mouseLeave=False) |
| 142 | + else: |
| 143 | + self.browser.SendMouseMoveEvent(-1, -1, mouseLeave=True) |
| 144 | + self.nodePath.setHpr(0, 0, 5) |
| 145 | + else: |
| 146 | + self.nodePath.setHpr(0, 0, 5) |
| 147 | + return Task.cont |
| 148 | + |
| 149 | + def onMouseDown(self): |
| 150 | + mouse = base.mouseWatcherNode.getMouse() |
| 151 | + (x,y) = self.getMousePixelCoordinates(mouse) |
| 152 | + self.browser.SendMouseClickEvent(x, y, cefpython.MOUSEBUTTON_LEFT, |
| 153 | + mouseUp=False, clickCount=1) |
| 154 | + |
| 155 | + def onMouseUp(self): |
| 156 | + mouse = base.mouseWatcherNode.getMouse() |
| 157 | + (x,y) = self.getMousePixelCoordinates(mouse) |
| 158 | + self.browser.SendMouseClickEvent(x, y, cefpython.MOUSEBUTTON_LEFT, |
| 159 | + mouseUp=True, clickCount=1) |
| 160 | + |
| 161 | + def onMouseWheelUp(self): |
| 162 | + if base.mouseWatcherNode.hasMouse(): |
| 163 | + mouse = base.mouseWatcherNode.getMouse() |
| 164 | + if self.isMouseInsideBrowser(mouse): |
| 165 | + (x,y) = self.getMousePixelCoordinates(mouse) |
| 166 | + self.browser.SendMouseWheelEvent(x, y, deltaX=0, deltaY=120) |
| 167 | + |
| 168 | + def onMouseWheelDown(self): |
| 169 | + if base.mouseWatcherNode.hasMouse(): |
| 170 | + mouse = base.mouseWatcherNode.getMouse() |
| 171 | + if self.isMouseInsideBrowser(mouse): |
| 172 | + (x,y) = self.getMousePixelCoordinates(mouse) |
| 173 | + self.browser.SendMouseWheelEvent(x, y, deltaX=0, deltaY=-120) |
| 174 | + |
80 | 175 | def messageLoop(self, task): |
81 | 176 | cefpython.SingleMessageLoop() |
82 | 177 | return Task.cont |
|
0 commit comments