Skip to content

Commit 066c431

Browse files
authored
Updated GUI (#26)
* Added times of last load * obj files now load with meshio loader * create_meshio_obj now uses default blender obj importer * create_meshio_obj now only checks for the ending * Update (not working atm) * Current not wokring version (but mzd is now fixed) * Better (not working) obj loader * Some debugging lines * Added functionality to use from_pydata and objloader now works * Minor updates (with old mesh loading) * Updated submodule extern/fileseq * Updated submodule extern/meshio * Updated submodule extern/python-future * Updated submodule extern/rich * Renamed symbol * Added files of submodules * A lot of UI changes * Revert "Revert "A lot of UI changes"" This reverts commit 34d179c. * Fixed obj. loading duplicate bug * Purges all old meshes (during .obj sequences) * Changed class names to fix warnings * Uncommented seperate obj import * Uncommented seperate obj import * Update meshio * Small fix * Added compatibility for split vertex normals with objs * Added obj.py * Default normals now work with .obj and .vtk * Added import zip operator * Import + Delete Zips works now * Lowered number of shown seqs, because it's not the main function anymore * Imported extracted zip folders are stored in tmp_zips in a custom location and this whole folder is then deleted * Made addon ready for release * Updated submodule extern/fileseq * Updated submodule extern/meshio * Updated submodule extern/python-future * Updated submodule extern/rich * Minor GUI adjustments
1 parent 49514f9 commit 066c431

17 files changed

+849
-300
lines changed

__init__.py

+17-10
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"name": "Sequence Loader",
33
"description": "Loader for meshio supported mesh files/ simulation sequences",
44
"author": "Interactive Computer Graphics",
5-
"version": (0, 1, 5),
6-
"blender": (3, 4, 0),
5+
"version": (0, 2, 0),
6+
"blender": (3, 6, 0),
77
"warning": "",
88
"support": "COMMUNITY",
99
"category": "Import-Export",
@@ -21,7 +21,7 @@
2121
bpy.context.preferences.filepaths.use_relative_paths = False
2222

2323
from bseq import *
24-
from bseq.operators import menu_func_import
24+
from bseq.operators import menu_func_import, add_keymap, delete_keymap
2525

2626
classes = [
2727
BSEQ_obj_property,
@@ -32,10 +32,14 @@
3232
BSEQ_OT_resetpt,
3333
BSEQ_OT_resetins,
3434
BSEQ_OT_resetmesh,
35-
BSEQ_Import,
35+
BSEQ_PT_Import,
36+
BSEQ_PT_Import_Child1,
37+
BSEQ_PT_Import_Child2,
38+
BSEQ_Globals_Panel,
3639
BSEQ_List_Panel,
3740
BSEQ_UL_Obj_List,
3841
BSEQ_Settings,
42+
BSEQ_Advanced_Panel,
3943
BSEQ_Templates,
4044
BSEQ_UL_Att_List,
4145
BSEQ_OT_set_as_split_norm,
@@ -47,11 +51,15 @@
4751
BSEQ_OT_enable_all,
4852
BSEQ_OT_refresh_sequences,
4953
BSEQ_OT_set_start_end_frames,
50-
WM_OT_batchSequences,
51-
WM_OT_MeshioObject
54+
BSEQ_OT_batch_sequences,
55+
BSEQ_PT_batch_sequences_settings,
56+
BSEQ_OT_meshio_object,
57+
# BSEQ_OT_import_zip,
58+
# BSEQ_OT_delete_zips,
59+
# BSEQ_addon_preferences,
60+
BSEQ_OT_load_all
5261
]
5362

54-
5563
def register():
5664
bpy.app.handlers.load_post.append(BSEQ_initialize)
5765
for cls in classes:
@@ -60,8 +68,8 @@ def register():
6068
bpy.types.Scene.BSEQ = bpy.props.PointerProperty(type=BSEQ_scene_property)
6169
bpy.types.Object.BSEQ = bpy.props.PointerProperty(type=BSEQ_obj_property)
6270
bpy.types.Mesh.BSEQ = bpy.props.PointerProperty(type=BSEQ_mesh_property)
63-
6471
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
72+
add_keymap()
6573

6674
# manually call this function once
6775
# so when addon being installed, it can run correctly
@@ -76,10 +84,9 @@ def unregister():
7684
del bpy.types.Object.BSEQ
7785
bpy.app.handlers.load_post.remove(BSEQ_initialize)
7886
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
87+
delete_keymap()
7988
unsubscribe_to_selected()
8089

81-
8290
if __name__ == "__main__":
83-
8491
# unregister()
8592
register()

additional_file_formats/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from . import bgeo
2-
from . import mzd
2+
from . import mzd
3+
from . import obj

additional_file_formats/mzd.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def readMZD_to_meshio(filepath):
2222

2323
with open(filepath, 'rb') as file:
2424
byte = file.read(24)
25+
# check if mzd file is empty
2526
if byte != head:
2627
return -4
2728
while 1:
@@ -49,7 +50,7 @@ def readMZD_to_meshio(filepath):
4950
if out_numVertices < 0:
5051
return -127
5152
if out_numVertices == 0:
52-
break
53+
return meshio.Mesh(points=np.array([]), cells={})
5354

5455
byte = file.read(12 * out_numVertices)
5556
out_vertPositions = np.frombuffer(byte, dtype=np.float32)

additional_file_formats/obj.py

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
"""
2+
I/O for the Wavefront .obj file format, cf.
3+
<https://en.wikipedia.org/wiki/Wavefront_.obj_file>.
4+
"""
5+
import datetime
6+
7+
import numpy as np
8+
9+
# from .._files import open_file
10+
# from .._helpers import register_format
11+
# from .._mesh import CellBlock, Mesh
12+
13+
import meshio
14+
15+
16+
def read(filename):
17+
with open(filename, "r") as f:
18+
mesh = read_buffer(f)
19+
return mesh
20+
21+
22+
def read_buffer(f):
23+
points = []
24+
vertex_normals = []
25+
texture_coords = []
26+
face_groups = []
27+
face_normals = []
28+
face_texture_coords = []
29+
face_group_ids = []
30+
face_group_id = -1
31+
while True:
32+
line = f.readline()
33+
34+
if not line:
35+
# EOF
36+
break
37+
38+
strip = line.strip()
39+
40+
if len(strip) == 0 or strip[0] == "#":
41+
continue
42+
43+
split = strip.split()
44+
45+
if split[0] == "v":
46+
points.append([float(item) for item in split[1:]])
47+
elif split[0] == "vn":
48+
vertex_normals.append([float(item) for item in split[1:]])
49+
elif split[0] == "vt":
50+
texture_coords.append([float(item) for item in split[1:]])
51+
elif split[0] == "s":
52+
# "s 1" or "s off" controls smooth shading
53+
pass
54+
elif split[0] == "f":
55+
# old: dat = [int(item.split("/")[0]) for item in split[1:]]
56+
# A face in obj has one of the following formats: 1, 1/2, 1//3, 1/2/3
57+
# We want to support all formats now amd store the texture and normal indices in other arrays
58+
face_indices = []
59+
face_texture_indices = []
60+
face_normal_indices = []
61+
62+
for item in split[1:]:
63+
indices = item.split("/")
64+
face_indices.append(int(indices[0]))
65+
if len(indices) > 1 and indices[1] != "":
66+
face_texture_indices.append(int(indices[1]))
67+
if len(indices) > 2:
68+
face_normal_indices.append(int(indices[2]))
69+
70+
if len(face_groups) == 0 or (
71+
len(face_groups[-1]) > 0 and len(face_groups[-1][-1]) != len(face_indices)
72+
):
73+
face_groups.append([])
74+
face_group_ids.append([])
75+
face_texture_coords.append([])
76+
face_normals.append([])
77+
face_groups[-1].append(face_indices)
78+
face_group_ids[-1].append(face_group_id)
79+
if face_texture_indices:
80+
face_texture_coords[-1].append(face_texture_indices)
81+
if face_normal_indices:
82+
face_normals[-1].append(face_normal_indices)
83+
elif split[0] == "g":
84+
# new group
85+
face_groups.append([])
86+
face_group_ids.append([])
87+
face_texture_coords.append([])
88+
face_normals.append([])
89+
face_group_id += 1
90+
else:
91+
# who knows
92+
pass
93+
94+
# There may be empty groups, too. <https://github.com/nschloe/meshio/issues/770>
95+
# Remove them.
96+
face_groups = [f for f in face_groups if len(f) > 0]
97+
face_group_ids = [g for g in face_group_ids if len(g) > 0]
98+
face_normals = [n for n in face_normals if len(n) > 0]
99+
face_texture_coords = [t for t in face_texture_coords if len(t) > 0]
100+
101+
# convert to numpy arrays and remove
102+
points = np.array(points)
103+
face_groups = [np.array(f) for f in face_groups]
104+
texture_coords = [np.array(t) for t in texture_coords]
105+
vertex_normals = [np.array(n) for n in vertex_normals]
106+
point_data = {}
107+
cell_data = {}
108+
field_data = {}
109+
110+
if face_texture_coords and len(texture_coords) == max([max(max(face)) for face in face_texture_coords]):
111+
field_data["obj:vt"] = texture_coords
112+
cell_data["obj:vt_face_idx"] = face_texture_coords
113+
elif len(texture_coords) == len(points):
114+
point_data["obj:vt"] = texture_coords
115+
116+
if face_normals and len(vertex_normals) == max([max(max(face)) for face in face_normals]):
117+
field_data["obj:vn"] = vertex_normals
118+
cell_data["obj:vn_face_idx"] = face_normals
119+
elif len(vertex_normals) == len(points):
120+
point_data["obj:vn"] = vertex_normals
121+
122+
cell_data["obj:group_ids"] = []
123+
cells = []
124+
for f, gid in zip(face_groups, face_group_ids):
125+
if f.shape[1] == 3:
126+
cells.append(meshio.CellBlock("triangle", f - 1))
127+
elif f.shape[1] == 4:
128+
cells.append(meshio.CellBlock("quad", f - 1))
129+
else:
130+
cells.append(meshio.CellBlock("polygon", f - 1))
131+
cell_data["obj:group_ids"].append(gid)
132+
133+
return meshio.Mesh(points, cells, point_data=point_data, cell_data=cell_data, field_data=field_data)
134+
135+
meshio.register_format("obj", [".obj"], read, {"obj": None})

bseq/__init__.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
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, WM_OT_batchSequences, WM_OT_MeshioObject
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
4-
from .panels import BSEQ_UL_Obj_List, BSEQ_List_Panel, BSEQ_Settings, BSEQ_Import, BSEQ_Templates, BSEQ_UL_Att_List, draw_template
4+
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
66
import bpy
77
from bpy.app.handlers import persistent
@@ -12,7 +12,8 @@
1212
@persistent
1313
def BSEQ_initialize(scene):
1414
if update_obj not in bpy.app.handlers.frame_change_post:
15-
bpy.app.handlers.frame_change_post.append(auto_refresh)
15+
bpy.app.handlers.frame_change_post.append(auto_refresh_active)
16+
bpy.app.handlers.frame_change_post.append(auto_refresh_all)
1617
bpy.app.handlers.frame_change_post.append(update_obj)
1718
subscribe_to_selected()
1819
if print_information not in bpy.app.handlers.render_init:
@@ -24,12 +25,16 @@ def BSEQ_initialize(scene):
2425
"BSEQ_OT_load",
2526
"BSEQ_obj_property",
2627
"BSEQ_initialize",
27-
"BSEQ_Import",
28+
"BSEQ_PT_Import",
29+
"BSEQ_PT_Import_Child1",
30+
"BSEQ_PT_Import_Child2",
31+
"BSEQ_Globals_Panel",
2832
"BSEQ_List_Panel",
2933
"BSEQ_UL_Obj_List",
3034
"BSEQ_scene_property",
3135
"BSEQ_Templates",
3236
"BSEQ_Settings",
37+
"BSEQ_Advanced_Panel",
3338
"BSEQ_UL_Att_List",
3439
"subscribe_to_selected",
3540
"BSEQ_OT_resetpt",
@@ -47,6 +52,11 @@ def BSEQ_initialize(scene):
4752
"BSEQ_OT_enable_all",
4853
"BSEQ_OT_refresh_sequences",
4954
"BSEQ_OT_set_start_end_frames",
50-
"WM_OT_batchSequences",
51-
"WM_OT_MeshioObject"
55+
"BSEQ_OT_batch_sequences",
56+
"BSEQ_PT_batch_sequences_settings",
57+
"BSEQ_OT_meshio_object",
58+
"BSEQ_OT_import_zip",
59+
"BSEQ_OT_delete_zips",
60+
"BSEQ_addon_preferences",
61+
"BSEQ_OT_load_all"
5262
]

bseq/callback.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def update_path(self, context):
2525
return [("None", "No sequence detected", "", 1)]
2626

2727
file_sequences.clear()
28-
if len(f) >= 20:
28+
if len(f) >= 30:
2929
file_sequences.append(("None", "Too much sequence detected, could be false detection, please use pattern below", "", 1))
3030
else:
3131
count = 1

bseq/globals.py

+17-4
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,26 @@ 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(bseq_prop.use_relative))
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

31-
def auto_refresh(scene, depsgraph=None):
32-
if not bpy.context.scene.BSEQ.auto_refresh:
32+
def auto_refresh_all(scene, depsgraph=None):
33+
if not bpy.context.scene.BSEQ.auto_refresh_all:
34+
return
35+
for obj in bpy.data.objects:
36+
if obj.BSEQ.init == False:
37+
continue
38+
if obj.BSEQ.enabled == False:
39+
continue
40+
if obj.mode != "OBJECT":
41+
continue
42+
refresh_obj(obj, scene)
43+
44+
def auto_refresh_active(scene, depsgraph=None):
45+
if not bpy.context.scene.BSEQ.auto_refresh_active:
3346
return
3447
for obj in bpy.data.objects:
3548
if obj.BSEQ.init == False:

0 commit comments

Comments
 (0)