Skip to content

Instantly share code, notes, and snippets.

@tito
Last active March 1, 2020 19:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tito/8770e36845fd14f4df3c30b2031318cf to your computer and use it in GitHub Desktop.
Save tito/8770e36845fd14f4df3c30b2031318cf to your computer and use it in GitHub Desktop.
Panda3D with Kivy WRAPPER (Windows and Linux)
from pandawrapper import PandaApp
from kivy.base import runTouchApp
try:
from kaki.app import App
with_kaki = True
except ImportError:
from kivy.app import App
with_kaki = False
from kivy.factory import Factory as F
class OmanApp(App):
IDLE_DETECTION = True
AUTORELOADER_IGNORE_PATTERNS = [
"*__pycache__*",
"*.cache*",
"*.log"
]
AUTORELOADER_PATHS = [
(".", {"recursive": True})
]
def build_app(self):
# build your app here as usual
return F.Button(size_hint=(.5, .5), text="Hello")
if not with_kaki:
def build(self):
return self.build_app()
# pandawrapper support
def build_panda_app(self):
self.panda_app = base = PandaApp()
def run(self):
self.build_panda_app()
self.load_config()
self.load_kv(filename=self.kv_file)
root = self.build()
if root is not None:
self.root = root
runTouchApp(self.root, slave=True)
self.panda_app.run()
self.stop()
if __name__ == "__main__":
OmanApp().run()(oman)
import os
import sys
os.environ["KIVY_WINDOW"] = ""
if sys.platform == "linux":
os.environ["KIVY_GL_BACKEND"] = "gl"
import kivy.core
orig_core_select_lib = kivy.core.core_select_lib
def core_select_lib_hide_window(category, *largs, **kwargs):
if category == "window":
return
return orig_core_select_lib(category, *largs, **kwargs)
kivy.core.core_select_lib = core_select_lib_hide_window
import kivy.core.window
from kivy.app import App
from kivy.config import Config
from kivy.base import EventLoop, runTouchApp, stopTouchApp
from kivy.core.window import WindowBase
from kivy.graphics import opengl as gl
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.clock import Clock
from direct.showbase.ShowBase import ShowBase
from panda3d.core import (
CallbackNode, Camera, NodePath, MouseWatcher, loadPrcFileData)
from direct.showbase import DirectObject
base = None
class MouseWrapper(DirectObject.DirectObject):
def __init__(self, window):
super().__init__()
self.window = window
self.accept('mouse1', self.on_mouse_1)
self.accept('mouse1-up', self.on_mouse_up_1)
self.accept('mouse3', self.on_mouse_2)
self.accept('mouse3-up', self.on_mouse_up_2)
def on_mouse_1(self):
self.window.have_touch_down += 1
self.window.dispatch_mouse('on_mouse_down', 'left')
def on_mouse_up_1(self):
self.window.have_touch_down -= 1
self.window.dispatch_mouse('on_mouse_up', 'left')
def on_mouse_2(self):
self.window.have_touch_down += 1
self.window.dispatch_mouse('on_mouse_down', 'right')
def on_mouse_up_2(self):
self.window.have_touch_down -= 1
self.window.dispatch_mouse('on_mouse_up', 'right')
class KivyWindow(WindowBase):
_clearcolor = ObjectProperty()
def __init__(self, panda_app, display_region, **kwargs):
self.panda_app = panda_app
display_region.set_draw_callback(self.on_panda_draw)
self.mouse_wrapper = MouseWrapper(self)
self.have_touch_down = 0
super().__init__(**kwargs)
Clock.schedule_interval(lambda _: self.canvas.ask_update(), 0)
kivy.core.window.Window = self
def _prepare_gl_context(self, *largs):
self.reset_gl_context()
gl.glEnableVertexAttribArray(0)
gl.glEnableVertexAttribArray(1)
def _leave_gl_context(self, *largs):
gl.glDisableVertexAttribArray(0)
gl.glDisableVertexAttribArray(1)
def reset_gl_context(self):
gl.glEnable(gl.GL_BLEND)
gl.glDisable(gl.GL_DEPTH_TEST)
gl.glEnable(gl.GL_STENCIL_TEST)
gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
gl.glBlendFuncSeparate(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA, gl.GL_ONE, gl.GL_ONE)
gl.glActiveTexture(gl.GL_TEXTURE0)
gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
def on_panda_draw(self, data=None):
self.update_mouse()
if data:
self.size = list(self.panda_app.win.get_size())
self._prepare_gl_context()
EventLoop.idle()
self._leave_gl_context()
def update_mouse(self):
if self.have_touch_down:
x, y = self.get_mouse_position()
self.dispatch('on_mouse_move', x, y, [])
def dispatch_mouse(self, event_name, btn=None):
x, y = self.get_mouse_position()
self.dispatch(event_name, x, y, btn, [])
def get_mouse_position(self):
mw = base.mouseWatcherNode
if not mw.hasMouse():
return 0, 0
w, h = self.system_size
x, y = mw.getMouseX(), mw.getMouseY()
lx = (x + 1) / 2
ly = 1 - (y + 1) / 2
return lx * w, ly * h
class PandaApp(ShowBase):
def __init__(self):
global base
base = self
width = Config.getint("graphics", "width")
height = Config.getint("graphics", "height")
loadPrcFileData("", "load-file-type p3assimp")
loadPrcFileData("", "framebuffer-multisample 1")
loadPrcFileData("", "framebuffer-srgb true")
loadPrcFileData("", "multisamples 2")
loadPrcFileData("", f"win-size {width} {height}")
ShowBase.__init__(self)
self.display_region = self.win.make_display_region()
self.display_region.set_sort(30)
self.disable_mouse()
self.accept("escape", self.on_escape)
self.kivy_window = KivyWindow(
panda_app=self,
display_region=self.display_region,
)
def on_escape(self):
stopTouchApp()
self.userExit()
class PandaWrapperApp(App):
def build_panda_app(self):
self.panda_app = base = PandaApp()
def run(self):
self.build_panda_app()
self.load_config()
self.load_kv(filename=self.kv_file)
root = self.build()
if root is not None:
self.root = root
runTouchApp(self.root, slave=True)
self.panda_app.run()
self.stop()
if __name__ == "__main__":
from kivy.factory import Factory as F
class PandaTestApp(PandaWrapperApp):
def build(self):
btn = F.Button(
size_hint_y=None,
text="Hello world")
# build panda scene
scene = self.panda_app.loader.loadModel('models/environment')
scene.reparentTo(self.panda_app.render)
scene.setScale(0.25, 0.25, 0.25)
return btn
PandaTestApp().run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment