2023-02-18 16:16:19 +01:00
|
|
|
|
2023-02-15 22:27:45 +01:00
|
|
|
import tkinter as tk
|
|
|
|
from source.packages import PackageManager
|
2023-02-18 16:16:19 +01:00
|
|
|
from source.packages.gui import *
|
2023-02-15 22:27:45 +01:00
|
|
|
from direct.showbase.ShowBase import ShowBase
|
2023-02-21 20:31:29 +01:00
|
|
|
from panda3d.core import VirtualFileSystem, Material, Vec3, CullFaceAttrib, WindowProperties
|
|
|
|
from direct.actor.Actor import Actor
|
2023-02-17 22:40:15 +01:00
|
|
|
|
|
|
|
class PackageExplorer:
|
|
|
|
def __init__(self, args):
|
|
|
|
self.gui = tk.Tk()
|
2023-02-21 20:31:29 +01:00
|
|
|
self.gui.title("Blackjack and Hookers: Package Explorer")
|
2023-02-17 22:40:15 +01:00
|
|
|
self.panda = ShowBase()
|
2023-02-21 20:31:29 +01:00
|
|
|
props = WindowProperties()
|
|
|
|
props.setTitle('Blackjack and Hookers: 3D Viewport')
|
|
|
|
self.panda.win.requestProperties(props)
|
2023-02-17 22:40:15 +01:00
|
|
|
self.package_manager = PackageManager(VirtualFileSystem.getGlobalPtr())
|
|
|
|
self.package_manager.set_main_package(args.main)
|
2023-02-18 11:11:37 +01:00
|
|
|
self.icons = get_icons()
|
|
|
|
self.prev = None
|
2023-02-17 22:40:15 +01:00
|
|
|
if args.package:
|
|
|
|
for include in args.package:
|
|
|
|
self.package_manager.include_package(include)
|
|
|
|
self.tree_packages = None
|
|
|
|
self.tree_scene = None
|
|
|
|
self.running = True
|
2023-02-21 20:31:29 +01:00
|
|
|
self.env_root = None
|
|
|
|
self.camera_root = None
|
|
|
|
self.camera_accel = 100
|
2023-02-18 16:16:19 +01:00
|
|
|
self.panda_keymap = {
|
|
|
|
'mouse1': False
|
|
|
|
}
|
2023-02-21 20:31:29 +01:00
|
|
|
self.mouse_previous = Vec3()
|
|
|
|
self.mouse_direction = Vec3()
|
2023-02-17 22:40:15 +01:00
|
|
|
init_gui(self, args)
|
2023-02-18 11:11:37 +01:00
|
|
|
init_packages_tree(self.tree_packages, self.package_manager, self.icons)
|
2023-02-18 16:16:19 +01:00
|
|
|
init_panda(self, args)
|
2023-02-17 22:40:15 +01:00
|
|
|
|
|
|
|
def on_tk_close(self):
|
|
|
|
self.running = False
|
|
|
|
|
|
|
|
def on_packagetree_doubleclick(self, event):
|
|
|
|
item = self.tree_packages.selection()[0]
|
|
|
|
if item.lower().endswith(('.glb', '.gltf', '.obj', '.egg')):
|
2023-02-18 11:11:37 +01:00
|
|
|
for child in self.scene_root.getChildren():
|
|
|
|
child.removeNode()
|
2023-02-17 22:40:15 +01:00
|
|
|
mat = Material()
|
|
|
|
mat.setAmbient((1, 0, 0, 1))
|
|
|
|
node = self.panda.loader.loadModel(item)
|
2023-02-21 20:31:29 +01:00
|
|
|
path = node.find('**/+Character')
|
|
|
|
if not path.isEmpty():
|
|
|
|
node = Actor(node)
|
2023-02-18 11:11:37 +01:00
|
|
|
node.reparentTo(self.scene_root)
|
|
|
|
node.setMaterial(mat)
|
2023-02-21 20:31:29 +01:00
|
|
|
node.setTwoSided(False)
|
|
|
|
node.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullClockwise))
|
2023-02-18 11:11:37 +01:00
|
|
|
self.display_scenegraph(node, item)
|
|
|
|
self.prev = node
|
|
|
|
|
|
|
|
def display_scenegraph(self, node, item):
|
|
|
|
self.tree_scene.delete(*self.tree_scene.get_children())
|
|
|
|
self.tree_scene.insert('', 'end', '/', text=f' {item}', open=True, image=self.icons.shape_square)
|
2023-02-21 20:31:29 +01:00
|
|
|
joints = node.getJoints() if getattr(node, 'getJoints', None) else []
|
|
|
|
if len(joints) > 0:
|
|
|
|
self.tree_scene.insert('/', 'end', 'joints', text=f' Joints ({len(joints)})', image=self.icons.chart_line_link)
|
|
|
|
for joint in joints:
|
|
|
|
self.tree_scene.insert('joints', 'end', f'joint_{joint.getName()}', text=f' {joint.getName()}', image=self.icons.anchor)
|
2023-02-18 11:11:37 +01:00
|
|
|
self.add_scene_nodes(node, '/')
|
|
|
|
|
|
|
|
def add_scene_nodes(self, node, parent):
|
|
|
|
pn = node.node()
|
|
|
|
tree_id = f'{pn.getType().getName()} {node.getName()}'
|
|
|
|
tree_name = tree_id
|
|
|
|
image = ''
|
|
|
|
match pn.getType().getName():
|
|
|
|
case 'ModelRoot':
|
|
|
|
image = self.icons.chart_organisation
|
|
|
|
case 'PandaNode':
|
|
|
|
image = self.icons.anchor
|
|
|
|
case 'GeomNode':
|
|
|
|
image = self.icons.shape_flip_horizontal
|
|
|
|
case 'AnimBundleNode':
|
|
|
|
bundle = pn.getBundle().getName()
|
2023-02-18 16:16:19 +01:00
|
|
|
tree_id = f'{tree_id}_{bundle}'
|
|
|
|
tree_name = f'{bundle}'
|
2023-02-18 11:11:37 +01:00
|
|
|
image = self.icons.film
|
|
|
|
case 'Character':
|
|
|
|
image = self.icons.user
|
|
|
|
self.tree_scene.insert(parent, 'end', tree_id, text=f' {tree_name}', open=True, image=image)
|
|
|
|
for child in node.getChildren():
|
|
|
|
self.add_scene_nodes(child, tree_id)
|
2023-02-15 22:27:45 +01:00
|
|
|
|
2023-02-18 16:16:19 +01:00
|
|
|
def mouse1_down(self):
|
|
|
|
self.panda_keymap['mouse1'] = True
|
|
|
|
|
|
|
|
def mouse1_up(self):
|
|
|
|
self.panda_keymap['mouse1'] = False
|
|
|
|
|
2023-02-21 20:31:29 +01:00
|
|
|
def wheel_up(self):
|
|
|
|
quat = self.panda.camera.getQuat(self.camera_root)
|
|
|
|
forward = quat.getForward()
|
|
|
|
self.panda.camera.setPos(self.panda.camera.getPos() + forward)
|
|
|
|
|
|
|
|
def wheel_down(self):
|
|
|
|
quat = self.panda.camera.getQuat(self.camera_root)
|
|
|
|
forward = quat.getForward()
|
|
|
|
self.panda.camera.setPos(self.panda.camera.getPos() - forward)
|
|
|
|
|
2023-02-18 16:16:19 +01:00
|
|
|
def update_input(self, task):
|
2023-02-21 20:31:29 +01:00
|
|
|
if self.panda.mouseWatcherNode.hasMouse():
|
|
|
|
mouse = self.panda.mouseWatcherNode.getMouse()
|
|
|
|
dt = self.panda.clock.getDt()
|
|
|
|
self.mouse_direction = Vec3(self.mouse_previous.getX() - mouse.getX(),
|
|
|
|
self.mouse_previous.getY() - mouse.getY(),
|
|
|
|
0)
|
|
|
|
self.mouse_previous = Vec3(mouse.getX(), mouse.getY(), 0)
|
|
|
|
|
2023-02-18 16:16:19 +01:00
|
|
|
if self.panda_keymap['mouse1']:
|
2023-02-21 20:31:29 +01:00
|
|
|
self.camera_root.setH(self.panda.render, self.camera_root.getH() + self.mouse_direction.getX() * self.camera_accel)
|
|
|
|
self.camera_root.setP(self.panda.render, self.camera_root.getP() + -self.mouse_direction.getY() * self.camera_accel)
|
2023-02-18 16:16:19 +01:00
|
|
|
|
|
|
|
return task.cont
|
|
|
|
|
2023-02-17 22:40:15 +01:00
|
|
|
def loop(self):
|
|
|
|
try:
|
|
|
|
while self.running:
|
|
|
|
self.gui.update_idletasks()
|
|
|
|
self.gui.update()
|
2023-02-18 11:11:37 +01:00
|
|
|
self.panda.taskMgr.step()
|
2023-02-17 22:40:15 +01:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
return
|
2023-02-15 22:27:45 +01:00
|
|
|
|
|
|
|
|
2023-02-17 22:40:15 +01:00
|
|
|
def start_explorer(args):
|
|
|
|
app = PackageExplorer(args)
|
|
|
|
app.loop()
|