Skip to content

Instantly share code, notes, and snippets.

@croxis
Last active February 4, 2021 15:41
Show Gist options
  • Select an option

  • Save croxis/9789973 to your computer and use it in GitHub Desktop.

Select an option

Save croxis/9789973 to your computer and use it in GitHub Desktop.
CEFPython for Panda3D
from cefpython3 import cefpython
import os
import sys
from panda3d.core import loadPrcFileData
loadPrcFileData("", "Panda3D example")
loadPrcFileData("", "fullscreen 0")
loadPrcFileData("", "win-size 1024 768")
import direct.directbase.DirectStart
from panda3d.core import CardMaker, Texture
settings = {
"log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE
#"log_file": GetApplicationPath("debug.log"), # Set to "" to disable.
"release_dcheck_enabled": True, # Enable only when debugging.
# This directories must be set on Linux
"locales_dir_path": cefpython.GetModuleDirectory()+"/locales",
"resources_dir_path": cefpython.GetModuleDirectory(),
"browser_subprocess_path": "%s/%s" % (
cefpython.GetModuleDirectory(), "subprocess")
}
class ClientHandler:
"""A client handler is required for the browser to do built in callbacks back into the application."""
browser = None
texture = None
def __init__(self, browser, texture):
self.browser = browser
self.texture = texture
def OnPaint(self, browser, paintElementType, dirtyRects, buffer, width, height):
img = self.texture.modifyRamImage()
if paintElementType == cefpython.PET_POPUP:
print("width=%s, height=%s" % (width, height))
elif paintElementType == cefpython.PET_VIEW:
img.setData(buffer.GetString(mode="rgba", origin="bottom-left"))
else:
raise Exception("Unknown paintElementType: %s" % paintElementType)
def GetViewRect(self, browser, rect):
width = self.texture.getXSize()
height = self.texture.getYSize()
rect.append(0)
rect.append(0)
rect.append(width)
rect.append(height)
return True
def GetScreenPoint(self, browser, viewX, viewY, screenCoordinates):
print("GetScreenPoint()")
return False
def OnLoadEnd(self, browser, frame, httpStatusCode):
return
self._saveImage()
def OnLoadError(self, browser, frame, errorCode, errorText, failedURL):
print("load error", browser, frame, errorCode, errorText, failedURL)
'''def setBrowserSize(window=None):
"""Use something like this to set a full screen UI. Texture and browser size should equal window size. Also remember to set panda textures to ignore power of 2"""
width = int(round(base.win.getXSize() * 0.75))
height = int(round(base.win.getYSize() * 0.75))
texture.setXSize(width)
texture.setYSize(height)
browser.WasResized()
#browser.SetSize(cefpython.PET_VIEW, width, height)'''
def messageLoop(task):
cefpython.MessageLoopWork()
return task.cont
cefpython.g_debug = True
cefpython.Initialize(settings)
texture = Texture()
texture.setXSize(1024)
texture.setYSize(1024)
texture.setCompression(Texture.CMOff)
texture.setComponentType(Texture.TUnsignedByte)
texture.setFormat(Texture.FRgba4)
cardMaker = CardMaker("browser2d")
cardMaker.setFrame(-0.75, 0.75, -0.75, 0.75)
node = cardMaker.generate()
#For UI attach to render2d
nodePath = render.attachNewNode(node)
nodePath.setTexture(texture)
windowHandle = base.win.getWindowHandle().getIntHandle()
windowInfo = cefpython.WindowInfo()
#You can pass 0 to parentWindowHandle, but then some things like context menus and plugins may not display correctly.
windowInfo.SetAsOffscreen(windowHandle)
#windowInfo.SetAsOffscreen(0)
# By default window rendering is 30 fps, let's change
# it to 60 for better user experience when scrolling.
browserSettings = {}
# Using non about:blank in constructor results in error before render handler callback is set.
# Either set it before/during construction, or set it after then call LoadURL after it is set.
browser = cefpython.CreateBrowserSync(
windowInfo, browserSettings,
navigateUrl="http://www.panda3d.org")
browser.SendFocusEvent(True)
browser.SetClientHandler(ClientHandler(browser, texture))
def on_load_end(*args, **kwargs): return # Example of one kind of call back
browser.SetClientCallback("OnLoadEnd", on_load_end)
browser.WasResized()
''' IMPORTANT: there is a bug in CEF 3 that causes js bindings to be removed when LoadUrl() is called (see http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=11009). A temporary fix to this bug is to do the navigation through javascript by calling: GetMainFrame().ExecuteJavascript('window.location="http://google.com/"'). '''
#browser.GetMainFrame().ExecuteJavascript('window.location="http://www.panda3d.org"')
#browser.GetMainFrame().LoadUrl("http://wwww.panda3d.org")
#base.accept("window-event", setBrowserSize)
taskMgr.add(messageLoop, "CefMessageLoop")
run()
cefpython.Shutdown()
"""Putting data into a frame"""
from cefpython3 import cefpython
import os
import sys
from panda3d.core import loadPrcFileData
loadPrcFileData("", "Panda3D example -- Set Javascript")
loadPrcFileData("", "fullscreen 0")
loadPrcFileData("", "win-size 1024 768")
import direct.directbase.DirectStart
from panda3d.core import CardMaker, Texture
settings = {
"log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE
#"log_file": GetApplicationPath("debug.log"), # Set to "" to disable.
"release_dcheck_enabled": True, # Enable only when debugging.
# This directories must be set on Linux
"locales_dir_path": cefpython.GetModuleDirectory()+"/locales",
"resources_dir_path": cefpython.GetModuleDirectory(),
"browser_subprocess_path": "%s/%s" % (
cefpython.GetModuleDirectory(), "subprocess")
}
html = """<html>
<body>
<script language="JavaScript">
function setFrameCount(counter){
document.getElementById("framecount").innerHTML=counter;
}
</script>
<h1>""" + sys.version + """</h1><br />
Message:
<script>
document.write(window.sometext);
</script><br />
Number of Frames: <span id="framecount"></span>
</body>
</html>"""
class ClientHandler:
"""A client handler is required for the browser to do built in callbacks back into the application."""
browser = None
texture = None
def __init__(self, browser, texture):
self.browser = browser
self.texture = texture
def OnPaint(self, browser, paintElementType, dirtyRects, buffer, width, height):
img = self.texture.modifyRamImage()
if paintElementType == cefpython.PET_POPUP:
print("width=%s, height=%s" % (width, height))
elif paintElementType == cefpython.PET_VIEW:
img.setData(buffer.GetString(mode="rgba", origin="bottom-left"))
else:
raise Exception("Unknown paintElementType: %s" % paintElementType)
def GetViewRect(self, browser, rect):
width = self.texture.getXSize()
height = self.texture.getYSize()
rect.append(0)
rect.append(0)
rect.append(width)
rect.append(height)
return True
def GetScreenPoint(self, browser, viewX, viewY, screenCoordinates):
print("GetScreenPoint()")
return False
def OnLoadEnd(self, browser, frame, httpStatusCode):
return
self._saveImage()
def OnLoadError(self, browser, frame, errorCode, errorText, failedURL):
print("load error", browser, frame, errorCode, errorText, failedURL)
def messageLoop(task):
cefpython.MessageLoopWork()
"""Call a specific javascript function and pass any parameters to it."""
browser.GetMainFrame().CallFunction("setFrameCount", task.frame)
return task.cont
def setVariable(name, value):
"""Sets a javascript value in the main frame"""
jsBindings.SetProperty(name, value)
cefpython.g_debug = True
cefpython.Initialize(settings)
texture = Texture()
texture.setXSize(1024)
texture.setYSize(1024)
texture.setCompression(Texture.CMOff)
texture.setComponentType(Texture.TUnsignedByte)
texture.setFormat(Texture.FRgba4)
cardMaker = CardMaker("browser2d")
cardMaker.setFrame(-0.75, 0.75, -0.75, 0.75)
node = cardMaker.generate()
#For UI attach to render2d
nodePath = render.attachNewNode(node)
nodePath.setTexture(texture)
windowHandle = base.win.getWindowHandle().getIntHandle()
windowInfo = cefpython.WindowInfo()
#You can pass 0 to parentWindowHandle, but then some things like context menus and plugins may not display correctly.
windowInfo.SetAsOffscreen(windowHandle)
#windowInfo.SetAsOffscreen(0)
browserSettings = {}
# Using non about:blank in constructor results in error before render handler callback is set.
# Either set it before/during construction, or set it after then call LoadURL after it is set.
browser = cefpython.CreateBrowserSync(
windowInfo, browserSettings,
navigateUrl="http://www.panda3d.org")
browser.SendFocusEvent(True)
browser.SetClientHandler(ClientHandler(browser, texture))
def on_load_end(*args, **kwargs): return # Example of one kind of call back
browser.SetClientCallback("OnLoadEnd", on_load_end)
browser.GetMainFrame().LoadString(html, "http://fake")
browser.WasResized()
''' IMPORTANT: there is a bug in CEF 3 that causes js bindings to be removed when LoadUrl() is called (see http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=11009). A temporary fix to this bug is to do the navigation through javascript by calling: GetMainFrame().ExecuteJavascript('window.location="http://google.com/"'). '''
#browser.GetMainFrame().ExecuteJavascript('window.location="http://www.panda3d.org"')
#browser.GetMainFrame().LoadUrl("http://wwww.panda3d.org")
#base.accept("window-event", setBrowserSize)
"""Sets up bindings to access javascript variabels and functions. Also is used for calling back into python."""
jsBindings = cefpython.JavascriptBindings(bindToFrames=False, bindToPopups=True)
jsBindings.SetProperty("sometext", "A message from python land! Hello!")
browser.SetJavascriptBindings(jsBindings)
taskMgr.add(messageLoop, "CefMessageLoop")
run()
cefpython.Shutdown()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment