Skip to content

Commit 46044aa

Browse files
New Extension Spec Compatibility and Usability Improvements (#36)
* improve recursive import by default it will now detect common prefixes and eliminate them. in the future it might be interesting to have an option to keep prefixes and simply use blenders naming to create a new one with an incremented name. * show hidden option that changes the relative root path * add blender manifest for 4.2 marketplace support * change to relative imports to not make blender angry from changing sys.path * update for new spec * change maintainer
1 parent d89c62d commit 46044aa

15 files changed

+147
-39
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ __pycache__/
22
.DS_Store
33
.vscode/
44
*.zip
5+
*.whl
56

67
# the following ignores are used to ignore the local softlink files
78
# the extern folder won't be affected by this
@@ -10,4 +11,4 @@ meshio
1011
future
1112
fileseq
1213

13-
docs/_build/*
14+
docs/_build/*

__init__.py

+14-25
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,24 @@
1-
bl_info = {
2-
"name": "Sequence Loader",
3-
"description": "Loader for meshio supported mesh files/ simulation sequences",
4-
"author": "Interactive Computer Graphics",
5-
"version": (0, 3, 2),
6-
"blender": (4, 0, 0),
7-
"warning": "",
8-
"support": "COMMUNITY",
9-
"category": "Import-Export",
10-
}
11-
121
import bpy
132
import os
143
import sys
154

16-
current_folder = os.path.dirname(os.path.abspath(__file__))
17-
if current_folder not in sys.path:
18-
sys.path.append(current_folder)
19-
# add paths of external libraries to sys.path
20-
if os.path.exists(os.path.join(current_folder, "extern")):
21-
external_libs = ["fileseq/src", "meshio/src", "python-future/src", "rich"]
22-
for lib in external_libs:
23-
lib_path = os.path.join(current_folder, "extern", lib)
24-
if lib_path not in sys.path:
25-
sys.path.append(lib_path)
5+
# current_folder = os.path.dirname(os.path.abspath(__file__))
6+
# if current_folder not in sys.path:
7+
# sys.path.append(current_folder)
8+
# # add paths of external libraries to sys.path
9+
# if os.path.exists(os.path.join(current_folder, "extern")):
10+
# external_libs = ["fileseq/src", "meshio/src", "python-future/src", "rich"]
11+
# for lib in external_libs:
12+
# lib_path = os.path.join(current_folder, "extern", lib)
13+
# if lib_path not in sys.path:
14+
# sys.path.append(lib_path)
2615

2716

28-
if bpy.context.preferences.filepaths.use_relative_paths == True:
29-
bpy.context.preferences.filepaths.use_relative_paths = False
17+
# if bpy.context.preferences.filepaths.use_relative_paths == True:
18+
# bpy.context.preferences.filepaths.use_relative_paths = False
3019

31-
from bseq import *
32-
from bseq.operators import menu_func_import, add_keymap, delete_keymap
20+
from .bseq import *
21+
from .bseq.operators import menu_func_import, add_keymap, delete_keymap
3322

3423
classes = [
3524
BSEQ_obj_property,

blender_manifest.toml

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
schema_version = "1.0.0"
2+
3+
# Example of manifest file for a Blender extension
4+
# Change the values according to your extension
5+
id = "sequence_loader"
6+
version = "0.3.3"
7+
name = "Blender Sequence Loader"
8+
tagline = "Just-in-time loader for meshio-supported mesh file sequences"
9+
maintainer = "Stefan Rhys Jeske <contact@srjeske.de>"
10+
# Supported types: "add-on", "theme"
11+
type = "add-on"
12+
13+
# # Optional: link to documentation, support, source files, etc
14+
website = "https://github.com/InteractiveComputerGraphics/blender-sequence-loader"
15+
16+
# # Optional: tag list defined by Blender and server, see:
17+
# # https://docs.blender.org/manual/en/dev/advanced/extensions/tags.html
18+
tags = ["Animation", "Object"]
19+
20+
blender_version_min = "4.2.0"
21+
# # Optional: Blender version that the extension does not support, earlier versions are supported.
22+
# # This can be omitted and defined later on the extensions platform if an issue is found.
23+
# blender_version_max = "5.1.0"
24+
25+
# License conforming to https://spdx.org/licenses/ (use "SPDX: prefix)
26+
# https://docs.blender.org/manual/en/dev/advanced/extensions/licenses.html
27+
license = [
28+
"SPDX:MIT",
29+
]
30+
# # Optional: required by some licenses.
31+
# copyright = [
32+
# "2002-2024 Developer Name",
33+
# "1998 Company Name",
34+
# ]
35+
36+
# # Optional: list of supported platforms. If omitted, the extension will be available in all operating systems.
37+
# platforms = ["windows-x64", "macos-arm64", "linux-x64"]
38+
# # Other supported platforms: "windows-arm64", "macos-x64"
39+
40+
# # Optional: bundle 3rd party Python modules.
41+
# # https://docs.blender.org/manual/en/dev/advanced/extensions/python_wheels.html
42+
wheels = [
43+
"./wheels/Fileseq-1.15.2-py3-none-any.whl",
44+
"./wheels/future-0.18.3-py3-none-any.whl",
45+
"./wheels/meshio-5.3.4-py3-none-any.whl",
46+
"./wheels/rich-13.7.0-py3-none-any.whl",
47+
]
48+
49+
# # Optional: add-ons can list which resources they will require:
50+
# # * files (for access of any filesystem operations)
51+
# # * network (for internet access)
52+
# # * clipboard (to read and/or write the system clipboard)
53+
# # * camera (to capture photos and videos)
54+
# # * microphone (to capture audio)
55+
# #
56+
# # If using network, remember to also check `bpy.app.online_access`
57+
# # https://docs.blender.org/manual/en/dev/advanced/extensions/addons.html#internet-access
58+
# #
59+
# # For each permission it is important to also specify the reason why it is required.
60+
# # Keep this a single short sentence without a period (.) at the end.
61+
# # For longer explanations use the documentation or detail page.
62+
#
63+
[permissions]
64+
files = "Core functionality to load files from disk"
65+
66+
# # Optional: advanced build settings.
67+
# # https://docs.blender.org/manual/en/dev/advanced/extensions/command_line_arguments.html#command-line-args-extension-build
68+
[build]
69+
# These are the default build excluded patterns.
70+
# You only need to edit them if you want different options.
71+
paths_exclude_pattern = [
72+
"__pycache__/",
73+
"/.git/",
74+
"/*.zip",
75+
"/extern/",
76+
"/docs/",
77+
"/images/",
78+
"build_addon.py",
79+
"download_wheels.sh"
80+
]

bseq/__init__.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
from bseq.utils import refresh_obj
1+
from .utils import refresh_obj
22
from .operators import BSEQ_OT_load, BSEQ_OT_edit, BSEQ_OT_resetpt, BSEQ_OT_resetmesh, BSEQ_OT_resetins, BSEQ_OT_set_as_split_norm, BSEQ_OT_remove_split_norm, BSEQ_OT_disable_selected, BSEQ_OT_enable_selected, BSEQ_OT_refresh_seq, BSEQ_OT_disable_all, BSEQ_OT_enable_all, BSEQ_OT_refresh_sequences, BSEQ_OT_set_start_end_frames, BSEQ_OT_batch_sequences, BSEQ_PT_batch_sequences_settings, BSEQ_OT_meshio_object, BSEQ_OT_import_zip, BSEQ_OT_delete_zips, BSEQ_addon_preferences, BSEQ_OT_load_all, BSEQ_OT_load_all_recursive
33
from .properties import BSEQ_scene_property, BSEQ_obj_property, BSEQ_mesh_property
44
from .panels import BSEQ_UL_Obj_List, BSEQ_List_Panel, BSEQ_Settings, BSEQ_PT_Import, BSEQ_PT_Import_Child1, BSEQ_PT_Import_Child2, BSEQ_Globals_Panel, BSEQ_Advanced_Panel, BSEQ_Templates, BSEQ_UL_Att_List, draw_template
55
from .messenger import subscribe_to_selected, unsubscribe_to_selected
6-
import bpy
7-
from bpy.app.handlers import persistent
86
from .importer import update_obj
97
from .globals import *
108

9+
import bpy
10+
from bpy.app.handlers import persistent
11+
1112

1213
@persistent
1314
def BSEQ_initialize(scene):
File renamed without changes.
File renamed without changes.

bseq/importer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from mathutils import Matrix
1010
import time
1111
# this import is not useless
12-
import additional_file_formats
12+
from .additional_file_formats import *
1313

1414
def extract_edges(cell: meshio.CellBlock):
1515
if cell.type == "line":

bseq/messenger.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ def selected_callback():
2020
bpy.context.scene.BSEQ.edit_obj = bpy.context.active_object
2121

2222
def subscribe_to_selected():
23-
import bseq
23+
# import bseq
24+
bseq = __loader__
2425

2526
# because current implementation may subscribe twice
2627
# so clear once to avoid duplication
@@ -37,5 +38,6 @@ def subscribe_to_selected():
3738

3839

3940
def unsubscribe_to_selected():
40-
import bseq
41+
# import bseq
42+
bseq = __loader__
4143
bpy.msgbus.clear_by_owner(bseq)

bseq/operators.py

+33-7
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ def draw(self, context):
440440
# layout.prop(importer_prop, "root_path", text="Root Directory")
441441

442442
class BSEQ_addon_preferences(bpy.types.AddonPreferences):
443-
bl_idname = addon_name
443+
bl_idname = __package__
444444

445445
zips_folder: bpy.props.StringProperty(
446446
name="Zips Folder",
@@ -556,6 +556,9 @@ def execute(self, context):
556556
return relative_path_error()
557557

558558
root_dir = importer_prop.path
559+
root_coll = bpy.context.scene.collection
560+
root_layer_collection = bpy.context.view_layer.layer_collection
561+
unlinked_collections = []
559562
# Recurse through subdirectories
560563
for root, dirs, files in os.walk(bpy.path.abspath(root_dir)):
561564
for dir in sorted(dirs):
@@ -570,14 +573,33 @@ def execute(self, context):
570573
coll_list = bpy.path.relpath(subdirectory, start=root_dir).strip("//").split("/")
571574

572575
# Get or create a nested collection starting from the root
573-
last_coll = bpy.context.scene.collection
574-
layer_collection = bpy.context.view_layer.layer_collection
576+
last_coll = root_coll
577+
layer_collection = root_layer_collection
575578
for coll in coll_list:
576-
cur_coll = bpy.data.collections.get(coll) if bpy.data.collections.get(coll) is not None else bpy.data.collections.new(coll)
577-
if last_coll is not None and cur_coll.name not in last_coll.children:
579+
# If it already exists and is not in the children of the last collection, then the prefix has changed
580+
cur_coll = bpy.data.collections.get(coll)
581+
if cur_coll is not None and last_coll is not None:
582+
if cur_coll.name not in last_coll.children:
583+
# Get the old parent of the existing collection and move the children to the old parent
584+
parent = [c for c in bpy.data.collections if bpy.context.scene.user_of_id(cur_coll) and cur_coll.name in c.children]
585+
if len(parent) > 0:
586+
for child in cur_coll.children:
587+
parent[0].children.link(child)
588+
for obj in cur_coll.objects:
589+
parent[0].objects.link(obj)
590+
parent[0].children.unlink(cur_coll)
591+
unlinked_collections.append(cur_coll)
592+
else:
593+
layer_collection = layer_collection.children[cur_coll.name]
594+
last_coll = cur_coll
595+
596+
597+
# If it was newly created, link it to the last collection
598+
if cur_coll is None and last_coll is not None:
599+
cur_coll = bpy.data.collections.new(coll)
578600
last_coll.children.link(cur_coll)
579-
layer_collection = layer_collection.children[cur_coll.name]
580-
last_coll = cur_coll
601+
layer_collection = layer_collection.children[cur_coll.name]
602+
last_coll = cur_coll
581603

582604
# Set the last collection as the active collection by recursing through the collections
583605
context.view_layer.active_layer_collection = layer_collection
@@ -587,6 +609,10 @@ def execute(self, context):
587609

588610
for s in seqs:
589611
create_obj_wrapper(s, importer_prop)
612+
613+
# Make sure unused datablocks are freed
614+
for coll in unlinked_collections:
615+
bpy.data.collections.remove(coll)
590616
return {'FINISHED'}
591617

592618

bseq/panels.py

+5
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,11 @@ def draw(self, context):
241241
col1.label(text="Relative Paths")
242242
col2.prop(importer_prop, "use_relative", text="")
243243

244+
if importer_prop.use_relative:
245+
col1.label(text="Relative Root")
246+
col2.prop(importer_prop, "root_path", text="")
247+
248+
244249
col1.label(text="Import Normals")
245250
col2.prop(importer_prop, "use_imported_normals", text="")
246251

download_wheels.sh

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pip wheel fileseq==1.15.2 -w ./wheels --no-deps
2+
pip wheel meshio==5.3.4 -w ./wheels --no-deps
3+
pip wheel future==0.18.3 -w ./wheels --no-deps
4+
pip wheel rich==13.7.0 -w ./wheels --no-deps

0 commit comments

Comments
 (0)