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.

Revisions

  1. croxis revised this gist Jun 26, 2014. 1 changed file with 361 additions and 0 deletions.
    361 changes: 361 additions & 0 deletions clicking.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,361 @@
    """Demos clicking on screen elements vs clicking on the environment."""

    from cefpython3 import cefpython

    import math
    import os
    import sys


    from panda3d.core import loadPrcFileData
    loadPrcFileData("", "Panda3D example -- Transparent window")
    loadPrcFileData("", "fullscreen 0")
    loadPrcFileData("", "win-size 1024 768")
    loadPrcFileData("", "textures-power-2 none")

    import direct.directbase.DirectStart
    from panda3d.core import CardMaker
    from panda3d.core import PNMImage, Point3, Texture, TransparencyAttrib, VBase4
    # For 3d picker
    from panda3d.core import CollisionHandlerQueue, CollisionNode, CollisionRay, CollisionTraverser, GeomNode

    from direct.actor.Actor import Actor
    from direct.interval.IntervalGlobal import Sequence


    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>
    <head>
    <!-- Bootstrap - Now making generic looking UI too! -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">
    <!-- Override premade style. CSS background has to be transparent for the texture to be transparent. -->
    <style>
    body {background-color: rgba(0,0,0,0.0);}
    .vbtm {
    display: inline-block;
    vertical-align: bottom;
    float: none;
    }
    </style>
    </head>
    <body>
    <script language="JavaScript">
    $('.pull-down').each(function() {
    $(this).css('margin-top', $(this).parent().height()-$(this).height())
    });
    function setFrameCount(counter){
    document.getElementById("framecount").innerHTML=counter;
    };
    function setOtherMessage(text){
    document.getElementById("othermessage").innerHTML=text;
    };
    </script>
    <row>
    <div class="col-md-6">
    <div class="well"><h2>""" + sys.version + """</h2></div>
    </div>
    </row>
    <row>
    <div class="col-md-6 pull-down">
    <div class="well"><h3>Message: <small><script>
    document.write(window.sometext);
    </script></small></h3></div>
    </div>
    <div class="col-md-6 pull-down">
    <div class="well"><h3>Number of Frames: <small><span id="framecount"></span></small></h3></div>
    </div>
    <div class="col-md-6 pull-down">
    <div class="well"><h3>Other Message: <small><span id="othermessage"></span></small></h3></div>
    </div>
    </row>
    <br />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
    </body>
    </html>"""


    class ClientHandler(object):
    """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()", browser, viewX, viewY, screenCoordinates)
    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)


    def setBrowserSize(window=None):
    """Set the off screen browser to the same resolution of the panda window.
    Best I can find is creating a new texture on resize.
    """
    texture = make_texture()
    nodePath.setTexture(texture)
    handler.texture = texture
    browser.WasResized()


    def make_texture():
    texture = Texture()
    texture.setCompression(Texture.CMOff)
    texture.setComponentType(Texture.TUnsignedByte)
    texture.setFormat(Texture.FRgba4)
    texture.setXSize(base.win.getXSize())
    texture.setYSize(base.win.getYSize())
    return texture



    cefpython.g_debug = True
    cefpython.Initialize(settings)


    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)
    windowInfo.SetTransparentPainting(True)
    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)
    handler = ClientHandler(browser, make_texture())
    browser.SetClientHandler(handler)

    cardMaker = CardMaker("browser2d")
    cardMaker.setFrameFullscreenQuad()
    node = cardMaker.generate()
    #For UI attach to render2d
    nodePath = render2d.attachNewNode(node)
    nodePath.setTransparency(TransparencyAttrib.MAlpha)
    nodePath.setTexture(handler.texture)

    #setBrowserSize()

    base.accept("window-event", setBrowserSize)


    # Example of one kind of call back
    def on_load_end(*args, **kwargs):
    print "I loaded!"


    browser.SetClientCallback("OnLoadEnd", on_load_end)

    browser.GetMainFrame().LoadString(html, "http://fake")

    '''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")


    """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")


    """This section sets up the hello world grass scene."""
    def spinCameraTask(task):
    angleDegrees = task.time * 6.0
    angleRadians = angleDegrees * (math.pi / 180.0)
    camera.setPos(20 * math.sin(angleRadians), -20.0 * math.cos(angleRadians), 3)
    camera.setHpr(angleDegrees, 0, 0)
    return task.cont


    environ = loader.loadModel("models/environment")
    environ.reparentTo(render)
    environ.setScale(0.25, 0.25, 0.25)
    environ.setPos(-8, 42, 0)
    taskMgr.add(spinCameraTask, "SpinCameraTask")
    pandaActor = Actor("models/panda-model",
    {"walk": "models/panda-walk4"})
    pandaActor.setScale(0.005, 0.005, 0.005)
    pandaActor.reparentTo(render)
    pandaActor.loop("walk")
    pandaPosInterval1 = pandaActor.posInterval(13,
    Point3(0, -10, 0),
    startPos=Point3(0, 10, 0))
    pandaPosInterval2 = pandaActor.posInterval(13,
    Point3(0, 10, 0),
    startPos=Point3(0, -10, 0))
    pandaHprInterval1 = pandaActor.hprInterval(3,
    Point3(180, 0, 0),
    startHpr=Point3(0, 0, 0))
    pandaHprInterval2 = pandaActor.hprInterval(3,
    Point3(0, 0, 0),
    startHpr=Point3(180, 0, 0))
    pandaPace = Sequence(pandaPosInterval1,
    pandaHprInterval1,
    pandaPosInterval2,
    pandaHprInterval2,
    name="pandaPace")
    pandaPace.loop()
    """End default scene setup"""


    """Set up 'generic' picker from Clicking on 3D objects manual"""
    myTraverser = CollisionTraverser('mousePicker')
    base.cTrav = myTraverser
    myHandler = CollisionHandlerQueue()

    pickerNode = CollisionNode('mouseRay')
    pickerNP = camera.attachNewNode(pickerNode)
    pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
    pickerRay = CollisionRay()
    pickerNode.addSolid(pickerRay)
    myTraverser.addCollider(pickerNP, myHandler)


    def click_object():
    # First we check that the mouse is not outside the screen.
    if base.mouseWatcherNode.hasMouse():
    # This gives up the screen coordinates of the mouse.
    mpos = base.mouseWatcherNode.getMouse()
    # This makes the ray's origin the camera and makes the ray point
    # to the screen coordinates of the mouse.
    pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
    myTraverser.traverse(render)
    # Assume for simplicity's sake that myHandler is a CollisionHandlerQueue.
    if myHandler.getNumEntries() > 0:
    # This is so we get the closest object
    myHandler.sortEntries()
    pickedObj = myHandler.getEntry(0).getIntoNodePath()
    if not pickedObj.isEmpty():
    handlePickedObject(pickedObj)


    def handlePickedObject(picked_object):
    browser.GetMainFrame().CallFunction("setOtherMessage", "You poked " + str(picked_object))
    """End set up 'generic' picker from Clicking on 3D objects manual"""


    def onMouseDown():
    '''This logic is set up for an ui where the mouse will be interacting with
    both ui elements and in world elements, such as an rts, tbs, or simulation
    game. This requires checking if the pixel the mouse clicked on is ui or
    not.
    We do this by checking the alpha level of the ui texture. If there is
    no alpha we hand off to the other parts of the mouse ui logic. If there
    is alpha the mouse click is passed to the browser instead.
    It is advised to create another mouse click event that is fired when
    alpha = 0 and have the additional logic listen for that. Otherwise
    anything listening to mouse1 and mouse1-up will fire reguardless of
    the position of the mouse.'''

    if base.win.has_pointer(0):
    x = int(base.win.get_pointer(0).get_x())
    y = int(base.win.get_pointer(0).get_y())
    '''# This is probably a more memory efficent, but does not work
    peek = handler.texture.peek()
    color = VBase4(1, 0, 1, 0)
    peek.lookup(color, int(x), int(y))
    print color, x, y'''
    # So this way instead!
    image = PNMImage()
    handler.texture.store(image)
    if image.get_alpha(x, y):
    browser.SendMouseClickEvent(x, y, cefpython.MOUSEBUTTON_LEFT,
    mouseUp=False, clickCount=1)
    else:
    print("Screen picking logic here!")
    click_object()
    image.clear()


    def onMouseUp():
    '''You may wish to pass all mouse-up events to both the browser
    and the game logic, depending on your needs.'''
    if base.win.has_pointer(0):
    x = int(base.win.get_pointer(0).get_x())
    y = int(base.win.get_pointer(0).get_y())
    '''# This is probably a more memory efficent, but does not work
    peek = handler.texture.peek()
    color = VBase4(1, 0, 1, 0)
    peek.lookup(color, int(x), int(y))
    print color, x, y'''

    image = PNMImage()
    handler.texture.store(image)
    if image.get_alpha(x, y):
    browser.SendMouseClickEvent(x, y, cefpython.MOUSEBUTTON_LEFT,
    mouseUp=True, clickCount=1)
    else:
    print("Screen picking logic here!")
    image.clear()


    base.accept("mouse1", onMouseDown)
    base.accept("mouse1-up", onMouseUp)
    #base.accept("wheel_up", onMouseWheelUp)
    #base.accept("wheel_down", onMouseWheelDown)


    run()
    cefpython.Shutdown()
  2. croxis revised this gist Apr 3, 2014. 1 changed file with 217 additions and 0 deletions.
    217 changes: 217 additions & 0 deletions render2d.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,217 @@
    """Demonstrates transparent window parented to the ui layer."""

    from cefpython3 import cefpython

    import math
    import os
    import sys


    from panda3d.core import loadPrcFileData
    loadPrcFileData("", "Panda3D example -- Transparent window")
    loadPrcFileData("", "fullscreen 0")
    loadPrcFileData("", "win-size 1024 768")
    loadPrcFileData("", "textures-power-2 none")

    import direct.directbase.DirectStart
    from panda3d.core import CardMaker, Point3, Texture, TransparencyAttrib
    from direct.actor.Actor import Actor
    from direct.interval.IntervalGlobal import Sequence


    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)


    def setBrowserSize(window=None):
    """Set the off screen browser to the same resolution of the panda window.
    Best I can find is creating a new texture on resize.
    """
    width = base.win.getXSize()
    height = base.win.getYSize()
    texture = make_texture()
    texture.setXSize(width)
    texture.setYSize(height)
    nodePath.setTexture(texture)
    handler.texture = texture
    browser.WasResized()


    def make_texture():
    texture = Texture()
    texture.setCompression(Texture.CMOff)
    texture.setComponentType(Texture.TUnsignedByte)
    texture.setFormat(Texture.FRgba4)
    return texture



    cefpython.g_debug = True
    cefpython.Initialize(settings)

    # Set up the texture for the off screen browser to render to.
    texture = make_texture()

    cardMaker = CardMaker("browser2d")
    cardMaker.setFrameFullscreenQuad()
    node = cardMaker.generate()
    #For UI attach to render2d
    nodePath = render2d.attachNewNode(node)
    nodePath.setTransparency(TransparencyAttrib.MAlpha)
    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)
    windowInfo.SetTransparentPainting(True)
    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)
    handler = ClientHandler(browser, texture)
    browser.SetClientHandler(handler)
    setBrowserSize()
    base.accept("window-event", setBrowserSize)

    # Example of one kind of call back
    def on_load_end(*args, **kwargs): return
    browser.SetClientCallback("OnLoadEnd", on_load_end)

    browser.GetMainFrame().LoadString(html, "http://fake")

    '''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")


    """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")


    """This section sets up the hello world grass scene."""
    def spinCameraTask(task):
    angleDegrees = task.time * 6.0
    angleRadians = angleDegrees * (math.pi / 180.0)
    camera.setPos(20 * math.sin(angleRadians), -20.0 * math.cos(angleRadians), 3)
    camera.setHpr(angleDegrees, 0, 0)
    return task.cont

    environ = loader.loadModel("models/environment")
    environ.reparentTo(render)
    environ.setScale(0.25, 0.25, 0.25)
    environ.setPos(-8, 42, 0)
    taskMgr.add(spinCameraTask, "SpinCameraTask")
    pandaActor = Actor("models/panda-model",
    {"walk": "models/panda-walk4"})
    pandaActor.setScale(0.005, 0.005, 0.005)
    pandaActor.reparentTo(render)
    pandaActor.loop("walk")
    pandaPosInterval1 = pandaActor.posInterval(13,
    Point3(0, -10, 0),
    startPos=Point3(0, 10, 0))
    pandaPosInterval2 = pandaActor.posInterval(13,
    Point3(0, 10, 0),
    startPos=Point3(0, -10, 0))
    pandaHprInterval1 = pandaActor.hprInterval(3,
    Point3(180, 0, 0),
    startHpr=Point3(0, 0, 0))
    pandaHprInterval2 = pandaActor.hprInterval(3,
    Point3(0, 0, 0),
    startHpr=Point3(180, 0, 0))
    pandaPace = Sequence(pandaPosInterval1,
    pandaHprInterval1,
    pandaPosInterval2,
    pandaHprInterval2,
    name="pandaPace")
    pandaPace.loop()
    """End default scene setup"""


    run()
    cefpython.Shutdown()
  3. croxis revised this gist Mar 31, 2014. 1 changed file with 150 additions and 0 deletions.
    150 changes: 150 additions & 0 deletions pythontojs.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,150 @@
    """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()
  4. croxis created this gist Mar 26, 2014.
    130 changes: 130 additions & 0 deletions basic.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,130 @@
    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()