Skip to content

Commit 468fbe7

Browse files
committed
Made addon ready for release
1 parent 62fcd62 commit 468fbe7

File tree

9 files changed

+160
-96
lines changed

9 files changed

+160
-96
lines changed

__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@
5454
BSEQ_OT_batch_sequences,
5555
BSEQ_PT_batch_sequences_settings,
5656
BSEQ_OT_meshio_object,
57-
BSEQ_OT_import_zip,
58-
BSEQ_OT_delete_zips,
59-
BSEQ_addon_preferences
57+
# BSEQ_OT_import_zip,
58+
# BSEQ_OT_delete_zips,
59+
# BSEQ_addon_preferences,
60+
BSEQ_OT_load_all
6061
]
6162

6263
def register():

bseq/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from bseq.utils import refresh_obj
2-
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
2+
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
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
@@ -57,5 +57,6 @@ def BSEQ_initialize(scene):
5757
"BSEQ_OT_meshio_object",
5858
"BSEQ_OT_import_zip",
5959
"BSEQ_OT_delete_zips",
60-
"BSEQ_addon_preferences"
60+
"BSEQ_addon_preferences",
61+
"BSEQ_OT_load_all"
6162
]

bseq/globals.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ def print_information(scene):
2323
if bseq_prop.init:
2424
file.write("Object name: {}\n".format(obj.name))
2525
file.write("Is it being animated: {}\n".format(bseq_prop.enabled))
26-
file.write("Filepath: {}\n".format(bseq_prop.pattern))
27-
file.write("Is it relative path: {}\n".format(bpy.path.is_subdir(obj.BSEQ.pattern, bpy.path.abspath("//"))))
26+
file.write("Filepath: {}\n".format(bseq_prop.path))
27+
file.write("Pattern: {}\n".format(bseq_prop.pattern))
28+
file.write("Current file: {}\n".format(bseq_prop.current_file))
2829
file.write("\n\n")
2930

3031

bseq/importer.py

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import traceback
55
import fileseq
66
import os
7-
from .utils import show_message_box
7+
from .utils import show_message_box, get_relative_path, get_absolute_path
88
import numpy as np
99
from mathutils import Matrix
1010
import time
@@ -221,7 +221,7 @@ def create_meshio_obj(filepath):
221221
bpy.ops.object.select_all(action="DESELECT")
222222
bpy.context.view_layer.objects.active = object
223223

224-
def create_obj(fileseq, root_path, transform_matrix=Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])):
224+
def create_obj(fileseq, use_relative, root_path, transform_matrix=Matrix.Identity(4)):
225225

226226
current_frame = bpy.context.scene.frame_current
227227
filepath = fileseq[current_frame % len(fileseq)]
@@ -241,13 +241,14 @@ def create_obj(fileseq, root_path, transform_matrix=Matrix([[1, 0, 0, 0], [0, 1,
241241
object = bpy.data.objects.new(name, mesh)
242242

243243
# create the object
244-
if bpy.path.is_subdir(filepath, bpy.path.abspath("//")):
245-
if root_path != "":
246-
object.BSEQ.pattern = bpy.path.relpath(str(fileseq), start=root_path)
247-
else:
248-
object.BSEQ.pattern = bpy.path.relpath(str(fileseq))
244+
if use_relative:
245+
full_path = get_relative_path(str(fileseq), root_path)
249246
else:
250-
object.BSEQ.pattern = str(fileseq)
247+
full_path = str(fileseq)
248+
# path is only the directory in which the file is located
249+
object.BSEQ.path = os.path.dirname(full_path)
250+
object.BSEQ.pattern = os.path.basename(full_path)
251+
object.BSEQ.current_file = filepath
251252
object.BSEQ.init = True
252253
object.BSEQ.enabled = enabled
253254
object.BSEQ.start_end_frame = (fileseq.start(), fileseq.end())
@@ -261,7 +262,6 @@ def create_obj(fileseq, root_path, transform_matrix=Matrix([[1, 0, 0, 0], [0, 1,
261262
bpy.context.view_layer.objects.active = object
262263

263264
def update_obj(scene, depsgraph=None):
264-
265265
for obj in bpy.data.objects:
266266
start_time = time.perf_counter()
267267

@@ -278,17 +278,11 @@ def update_obj(scene, depsgraph=None):
278278
show_message_box("Warning: Might not be able load the correct frame because the dependency graph is not available.", "BSEQ Warning")
279279
current_frame = obj.BSEQ.frame
280280
meshio_mesh = None
281-
pattern = obj.BSEQ.pattern
282-
# check if the path is relative
283-
if bpy.path.is_subdir(pattern, bpy.path.abspath("//")):
284-
if scene.BSEQ.root_path != "":
285-
pattern = bpy.path.abspath(pattern, start=scene.BSEQ.root_path)
286-
else:
287-
pattern = bpy.path.abspath(pattern)
288-
281+
289282
# in case the blender file was created on windows system, but opened in linux system
290-
pattern = bpy.path.native_pathsep(pattern)
291-
fs = fileseq.FileSequence(pattern)
283+
full_path = get_absolute_path(obj, scene)
284+
285+
fs = fileseq.FileSequence(full_path)
292286

293287
if obj.BSEQ.use_advance and obj.BSEQ.script_name:
294288
script = bpy.data.texts[obj.BSEQ.script_name]
@@ -303,6 +297,7 @@ def update_obj(scene, depsgraph=None):
303297
user_process = locals()['process']
304298
try:
305299
user_process(fs, current_frame, obj.data)
300+
obj.BSEQ.current_file = "Controlled by user process"
306301
except Exception as e:
307302
show_message_box("Error when calling user process: " + traceback.format_exc(), icon="ERROR")
308303
del locals()['process']
@@ -313,6 +308,7 @@ def update_obj(scene, depsgraph=None):
313308
user_preprocess = locals()['preprocess']
314309
try:
315310
meshio_mesh = user_preprocess(fs, current_frame)
311+
obj.BSEQ.current_file = "Controlled by user preprocess"
316312
except Exception as e:
317313
show_message_box("Error when calling user preprocess: " + traceback.format_exc(), icon="ERROR")
318314
# this continue means only if error occures, then goes to next bpy.object
@@ -321,8 +317,10 @@ def update_obj(scene, depsgraph=None):
321317
del locals()['preprocess']
322318
else:
323319
filepath = fs[current_frame % len(fs)]
320+
filepath = os.path.normpath(filepath)
324321
try:
325322
meshio_mesh = meshio.read(filepath)
323+
obj.BSEQ.current_file = filepath
326324
except Exception as e:
327325
show_message_box("Error when reading: " + filepath + ",\n" + traceback.format_exc(),
328326
"Meshio Loading Error" + str(e),

bseq/operators.py

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,25 @@
33
import fileseq
44
from .messenger import *
55
import traceback
6-
from .utils import refresh_obj, show_message_box
6+
from .utils import refresh_obj, show_message_box, get_relative_path
77
from .importer import create_obj, create_meshio_obj
88
import numpy as np
99

1010
addon_name = "blendersequenceloader"
1111

12+
def relative_path_error():
13+
show_message_box("When using relative path, please save file before using it", icon="ERROR")
14+
return {"CANCELLED"}
15+
16+
def get_transform_matrix(importer_prop):
17+
if importer_prop.use_custom_transform:
18+
return Matrix.LocRotScale(importer_prop.custom_location, importer_prop.custom_rotation, importer_prop.custom_scale)
19+
else:
20+
return Matrix.Identity(4)
21+
22+
def create_obj_wrapper(seq, importer_prop):
23+
create_obj(seq, importer_prop.use_relative, importer_prop.root_path, transform_matrix=get_transform_matrix(importer_prop))
24+
1225
# Here are load and delete operations
1326
class BSEQ_OT_load(bpy.types.Operator):
1427
'''This operator loads a sequence'''
@@ -20,10 +33,8 @@ def execute(self, context):
2033
scene = context.scene
2134
importer_prop = scene.BSEQ
2235

23-
if importer_prop.relative and not bpy.data.is_saved:
24-
# use relative but file not saved
25-
show_message_box("When using relative path, please save file before using it", icon="ERROR")
26-
return {"CANCELLED"}
36+
if importer_prop.use_relative and not bpy.data.is_saved:
37+
return relative_path_error()
2738

2839
fs = importer_prop.fileseq
2940
use_pattern = importer_prop.use_pattern
@@ -43,13 +54,7 @@ def execute(self, context):
4354
show_message_box(traceback.format_exc(), "Can't find sequence: " + str(fs), "ERROR")
4455
return {"CANCELLED"}
4556

46-
transform_matrix = (Matrix.LocRotScale(
47-
importer_prop.custom_location,
48-
importer_prop.custom_rotation,
49-
importer_prop.custom_scale)
50-
if importer_prop.use_custom_transform else Matrix.Identity(4))
51-
52-
create_obj(fs, importer_prop.root_path, transform_matrix=transform_matrix)
57+
create_obj_wrapper(fs, importer_prop)
5358
return {"FINISHED"}
5459

5560

@@ -63,10 +68,9 @@ def execute(self, context):
6368
scene = context.scene
6469
importer_prop = scene.BSEQ
6570

66-
if importer_prop.relative and not bpy.data.is_saved:
71+
if importer_prop.use_relative and not bpy.data.is_saved:
6772
# use relative but file not saved
68-
show_message_box("When using relative path, please save file before using it", icon="ERROR")
69-
return {"CANCELLED"}
73+
return relative_path_error()
7074

7175
fs = importer_prop.fileseq
7276
use_pattern = importer_prop.use_pattern
@@ -93,7 +97,7 @@ def execute(self, context):
9397
obj = sim_loader.edit_obj
9498
if not obj:
9599
return {"CANCELLED"}
96-
if importer_prop.relative:
100+
if importer_prop.use_relative:
97101
if importer_prop.root_path != "":
98102
object.BSEQ.pattern = bpy.path.relpath(str(fileseq), start=importer_prop.root_path)
99103
else:
@@ -379,10 +383,8 @@ def execute(self, context):
379383
scene = context.scene
380384
importer_prop = scene.BSEQ
381385

382-
if importer_prop.relative and not bpy.data.is_saved:
383-
# use relative but file not saved
384-
show_message_box("When using relative path, please save file before using it", icon="ERROR")
385-
return {"CANCELLED"}
386+
if importer_prop.use_relative and not bpy.data.is_saved:
387+
return relative_path_error()
386388

387389
self.filter_glob = '*'
388390

@@ -393,13 +395,13 @@ def execute(self, context):
393395
# Check if there exists a matching file sequence for every selection
394396
fp = str(Path(folder.parent, selection.name))
395397
seqs = fileseq.findSequencesOnDisk(str(folder.parent))
396-
matching_seqs = [s for s in seqs if fp in list(s) and s not in used_seqs]
397-
398-
if matching_seqs:
399-
transform_matrix = (Matrix.LocRotScale(importer_prop.custom_location, importer_prop.custom_rotation, importer_prop.custom_scale)
400-
if importer_prop.use_custom_transform else Matrix.Identity(4))
401-
create_obj(matching_seqs[0], importer_prop.root_path, transform_matrix=transform_matrix)
402-
used_seqs.add(matching_seqs[0])
398+
matching_seq = [s for s in seqs if fp in list(s) and str(s) not in used_seqs]
399+
400+
if matching_seq:
401+
matching_seq = matching_seq[0]
402+
used_seqs.add(str(matching_seq))
403+
404+
create_obj_wrapper(matching_seq, importer_prop)
403405
return {'FINISHED'}
404406

405407
def draw(self, context):
@@ -425,15 +427,15 @@ def draw(self, context):
425427
layout.use_property_split = True
426428
layout.use_property_decorate = False # No animation.
427429

428-
# sfile = context.space_data
429-
# operator = sfile.active_operator
430+
# # sfile = context.space_data
431+
# # operator = sfile.active_operator
430432

431-
layout.prop(importer_prop, 'filter_string')
433+
# layout.prop(importer_prop, 'filter_string')
432434

433-
layout.alignment = 'LEFT'
434-
layout.prop(importer_prop, "relative", text="Relative Path")
435-
if importer_prop.relative:
436-
layout.prop(importer_prop, "root_path", text="Root Directory")
435+
# layout.alignment = 'LEFT'
436+
# layout.prop(importer_prop, "relative", text="Relative Path")
437+
# if importer_prop.use_relative:
438+
# layout.prop(importer_prop, "root_path", text="Root Directory")
437439

438440
class BSEQ_addon_preferences(bpy.types.AddonPreferences):
439441
bl_idname = addon_name
@@ -444,9 +446,10 @@ class BSEQ_addon_preferences(bpy.types.AddonPreferences):
444446
)
445447

446448
def draw(self, context):
447-
layout = self.layout
448-
layout.label(text="Please set a folder to store the extracted zip files")
449-
layout.prop(self, "zips_folder", text="Zips Folder")
449+
# layout = self.layout
450+
# layout.label(text="Please set a folder to store the extracted zip files")
451+
# layout.prop(self, "zips_folder", text="Zips Folder")
452+
pass
450453

451454
zip_folder_name = '/tmp_zips'
452455

@@ -465,6 +468,8 @@ class BSEQ_OT_import_zip(bpy.types.Operator, ImportHelper):
465468
files: bpy.props.CollectionProperty(type=bpy.types.PropertyGroup)
466469

467470
def execute(self, context):
471+
importer_prop = context.scene.BSEQ
472+
468473
import zipfile
469474
zip_file = zipfile.ZipFile(self.filepath)
470475

@@ -477,14 +482,19 @@ def execute(self, context):
477482

478483
valid_files = [info.filename for info in zip_file.infolist() if not info.filename.startswith('__MACOSX/')]
479484
zip_file.extractall(zips_folder, members=valid_files)
480-
zip_file.close()
485+
zip_file.close()
481486

482487
folder = str(zips_folder) + '/' + str(Path(self.filepath).name)[:-4]
483488
print(folder)
484489

485490
seqs = fileseq.findSequencesOnDisk(str(folder))
491+
if not seqs:
492+
show_message_box("No sequences found in the zip file", icon="ERROR")
493+
return {"CANCELLED"}
494+
486495
for s in seqs:
487-
create_obj(s, folder, transform_matrix=Matrix.Identity(4))
496+
# Import it with absolute paths
497+
create_obj(s, False, folder, transform_matrix=get_transform_matrix(importer_prop))
488498

489499
# created_folder = context.scene.BSEQ.imported_zips.add()
490500
# created_folder.path = folder
@@ -509,6 +519,28 @@ def execute(self, context):
509519

510520
return {'FINISHED'}
511521

522+
class BSEQ_OT_load_all(bpy.types.Operator):
523+
"""Load all sequences"""
524+
bl_idname = "bseq.load_all"
525+
bl_label = "Load All"
526+
bl_options = {'PRESET', 'UNDO'}
527+
528+
def execute(self, context):
529+
importer_prop = context.scene.BSEQ
530+
531+
if importer_prop.use_relative and not bpy.data.is_saved:
532+
return relative_path_error()
533+
534+
dir = importer_prop.path
535+
seqs = fileseq.findSequencesOnDisk(str(dir))
536+
537+
for s in seqs:
538+
print(s)
539+
540+
for s in seqs:
541+
create_obj_wrapper(s, importer_prop)
542+
return {'FINISHED'}
543+
512544

513545
class BSEQ_OT_meshio_object(bpy.types.Operator, ImportHelper):
514546
"""Batch Import Meshio Objects"""

0 commit comments

Comments
 (0)