diff --git a/assets/models/debugplane.glb b/assets/models/debugplane.glb new file mode 100644 index 0000000..a48ca4b Binary files /dev/null and b/assets/models/debugplane.glb differ diff --git a/icons/anchor.png b/icons/anchor.png new file mode 100644 index 0000000..9b3422c Binary files /dev/null and b/icons/anchor.png differ diff --git a/icons/chart_organisation.png b/icons/chart_organisation.png new file mode 100644 index 0000000..505a707 Binary files /dev/null and b/icons/chart_organisation.png differ diff --git a/icons/film.png b/icons/film.png new file mode 100644 index 0000000..b0ce7bb Binary files /dev/null and b/icons/film.png differ diff --git a/icons/link.png b/icons/link.png new file mode 100644 index 0000000..25eacb7 Binary files /dev/null and b/icons/link.png differ diff --git a/icons/shape_flip_horizontal.png b/icons/shape_flip_horizontal.png new file mode 100644 index 0000000..8667c81 Binary files /dev/null and b/icons/shape_flip_horizontal.png differ diff --git a/icons/sound.png b/icons/sound.png new file mode 100644 index 0000000..6056d23 Binary files /dev/null and b/icons/sound.png differ diff --git a/icons/user.png b/icons/user.png new file mode 100644 index 0000000..79f35cc Binary files /dev/null and b/icons/user.png differ diff --git a/source/packages/manager.py b/source/packages/manager.py index a6c684b..3edd651 100644 --- a/source/packages/manager.py +++ b/source/packages/manager.py @@ -1,5 +1,6 @@ import os, json +import posixpath from .package import Package from .errors import * @@ -38,4 +39,15 @@ class PackageManager: self.vfs.mount(filepath, vfs_path, 0) new_package = Package(type('', (object,), meta), vfs_path, self.vfs) self.package_map[meta['name']] = new_package - self.package_list.insert(0, new_package) \ No newline at end of file + self.package_list.insert(0, new_package) + + def get_model_path(self, name): + for imported_package in reversed(self.package_list): + target_path = posixpath.join(imported_package.mount_dir, 'models', name) + print(target_path) + if self.vfs.exists(target_path): + return target_path + main_path = posixpath.join(self.main_package.mount_dir, 'models', name) + if (self.vfs.exists(main_path)): + return main_path + return None diff --git a/source/pkgexplore.py b/source/pkgexplore.py index 1ab8da9..9f68a81 100644 --- a/source/pkgexplore.py +++ b/source/pkgexplore.py @@ -3,7 +3,7 @@ import tkinter as tk import tkinter.ttk as ttk from source.packages import PackageManager from direct.showbase.ShowBase import ShowBase -from panda3d.core import VirtualFileSystem, Material, WindowProperties +from panda3d.core import VirtualFileSystem, Material, NodePath from direct.stdpy.file import walk import simplepbr @@ -22,7 +22,14 @@ def get_icons(): "page_red": tk.PhotoImage(file='icons/page_red.png'), 'shape_square': tk.PhotoImage(file='icons/shape_square.png'), 'color_wheel': tk.PhotoImage(file='icons/color_wheel.png'), - 'color_swatch': tk.PhotoImage(file='icons/color_swatch.png') + 'color_swatch': tk.PhotoImage(file='icons/color_swatch.png'), + 'link': tk.PhotoImage(file='icons/link.png'), + 'sound': tk.PhotoImage(file='icons/sound.png'), + 'chart_organisation': tk.PhotoImage(file='icons/chart_organisation.png'), + 'anchor': tk.PhotoImage(file='icons/anchor.png'), + 'shape_flip_horizontal': tk.PhotoImage(file='icons/shape_flip_horizontal.png'), + 'film': tk.PhotoImage(file='icons/film.png'), + 'user': tk.PhotoImage(file='icons/user.png') })() def add_package_contents_to_tree(tree, package, type, name, extensions, icon_folder, icon_group, icon_item): @@ -47,10 +54,14 @@ def add_package_textures_to_tree(tree, package, icons): def add_package_materials_to_tree(tree, package, icons): add_package_contents_to_tree(tree, package, 'materials/', 'Materials', ('.json'), icons.folder, icons.color_wheel, icons.color_swatch) +def add_package_sounds_to_tree(tree, package, icons): + add_package_contents_to_tree(tree, package, 'sounds/', 'Sounds', ('.ogg', '.wav'), icons.folder, icons.sound, icons.sound) + def add_package_to_tree(tree, package, icons): add_package_models_to_tree(tree, package, icons) add_package_textures_to_tree(tree, package, icons) add_package_materials_to_tree(tree, package, icons) + add_package_sounds_to_tree(tree, package, icons) def init_packages_tree(tree, packages, icons): tree.insert('', 'end', '/', text=' /', open=True, image=icons.app) @@ -65,7 +76,7 @@ def init_packages_tree(tree, packages, icons): def init_gui(app, args): app.gui.geometry("700x500") app.gui.grid_rowconfigure(0, weight=10) - app.gui.grid_rowconfigure(0, weight=1) + app.gui.grid_rowconfigure(1, weight=5) app.gui.grid_columnconfigure(0, weight=1) package_frame = tk.Frame(app.gui, padx=4, pady=4) package_frame.grid(column=0, row=0, sticky="news") @@ -108,6 +119,8 @@ class PackageExplorer: self.panda = ShowBase() self.package_manager = PackageManager(VirtualFileSystem.getGlobalPtr()) self.package_manager.set_main_package(args.main) + self.icons = get_icons() + self.prev = None if args.package: for include in args.package: self.package_manager.include_package(include) @@ -117,7 +130,21 @@ class PackageExplorer: simplepbr.init() gltf.patch_loader(self.panda.loader) init_gui(self, args) - init_packages_tree(self.tree_packages, self.package_manager, get_icons()) + init_packages_tree(self.tree_packages, self.package_manager, self.icons) + + env_root = NodePath('env_root') + env_root.reparentTo(self.panda.render) + + axis = self.panda.loader.loadModel(self.package_manager.get_model_path('axis.glb')) + axis.reparentTo(env_root) + + plane = self.panda.loader.loadModel(self.package_manager.get_model_path('debugplane.glb')) + plane.reparentTo(env_root) + + self.scene_root = NodePath('scene_root') + self.scene_root.reparentTo(self.panda.render) + + self.gui.protocol("WM_DELETE_WINDOW", self.on_tk_close) def on_tk_close(self): @@ -126,18 +153,51 @@ class PackageExplorer: def on_packagetree_doubleclick(self, event): item = self.tree_packages.selection()[0] if item.lower().endswith(('.glb', '.gltf', '.obj', '.egg')): + for child in self.scene_root.getChildren(): + child.removeNode() mat = Material() mat.setAmbient((1, 0, 0, 1)) node = self.panda.loader.loadModel(item) - node.reparentTo(self.panda.render) - node.setMaterial(mat) + node.reparentTo(self.scene_root) + node.setMaterial(mat) + 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) + 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() + tree_id = f'{tree_id}_"{bundle}"' + tree_name = f'"{bundle}"' + 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) def loop(self): try: while self.running: - self.panda.taskMgr.step() self.gui.update_idletasks() self.gui.update() + self.panda.taskMgr.step() except KeyboardInterrupt: return