Skip to content

Commit

Permalink
Updated GUI (#26)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
justo46 authored Nov 23, 2023
1 parent 49514f9 commit 066c431
Show file tree
Hide file tree
Showing 17 changed files with 849 additions and 300 deletions.
27 changes: 17 additions & 10 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"name": "Sequence Loader",
"description": "Loader for meshio supported mesh files/ simulation sequences",
"author": "Interactive Computer Graphics",
"version": (0, 1, 5),
"blender": (3, 4, 0),
"version": (0, 2, 0),
"blender": (3, 6, 0),
"warning": "",
"support": "COMMUNITY",
"category": "Import-Export",
Expand All @@ -21,7 +21,7 @@
bpy.context.preferences.filepaths.use_relative_paths = False

from bseq import *
from bseq.operators import menu_func_import
from bseq.operators import menu_func_import, add_keymap, delete_keymap

classes = [
BSEQ_obj_property,
Expand All @@ -32,10 +32,14 @@
BSEQ_OT_resetpt,
BSEQ_OT_resetins,
BSEQ_OT_resetmesh,
BSEQ_Import,
BSEQ_PT_Import,
BSEQ_PT_Import_Child1,
BSEQ_PT_Import_Child2,
BSEQ_Globals_Panel,
BSEQ_List_Panel,
BSEQ_UL_Obj_List,
BSEQ_Settings,
BSEQ_Advanced_Panel,
BSEQ_Templates,
BSEQ_UL_Att_List,
BSEQ_OT_set_as_split_norm,
Expand All @@ -47,11 +51,15 @@
BSEQ_OT_enable_all,
BSEQ_OT_refresh_sequences,
BSEQ_OT_set_start_end_frames,
WM_OT_batchSequences,
WM_OT_MeshioObject
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
]


def register():
bpy.app.handlers.load_post.append(BSEQ_initialize)
for cls in classes:
Expand All @@ -60,8 +68,8 @@ def register():
bpy.types.Scene.BSEQ = bpy.props.PointerProperty(type=BSEQ_scene_property)
bpy.types.Object.BSEQ = bpy.props.PointerProperty(type=BSEQ_obj_property)
bpy.types.Mesh.BSEQ = bpy.props.PointerProperty(type=BSEQ_mesh_property)

bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
add_keymap()

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


if __name__ == "__main__":

# unregister()
register()
3 changes: 2 additions & 1 deletion additional_file_formats/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from . import bgeo
from . import mzd
from . import mzd
from . import obj
3 changes: 2 additions & 1 deletion additional_file_formats/mzd.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def readMZD_to_meshio(filepath):

with open(filepath, 'rb') as file:
byte = file.read(24)
# check if mzd file is empty
if byte != head:
return -4
while 1:
Expand Down Expand Up @@ -49,7 +50,7 @@ def readMZD_to_meshio(filepath):
if out_numVertices < 0:
return -127
if out_numVertices == 0:
break
return meshio.Mesh(points=np.array([]), cells={})

byte = file.read(12 * out_numVertices)
out_vertPositions = np.frombuffer(byte, dtype=np.float32)
Expand Down
135 changes: 135 additions & 0 deletions additional_file_formats/obj.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
"""
I/O for the Wavefront .obj file format, cf.
<https://en.wikipedia.org/wiki/Wavefront_.obj_file>.
"""
import datetime

import numpy as np

# from .._files import open_file
# from .._helpers import register_format
# from .._mesh import CellBlock, Mesh

import meshio


def read(filename):
with open(filename, "r") as f:
mesh = read_buffer(f)
return mesh


def read_buffer(f):
points = []
vertex_normals = []
texture_coords = []
face_groups = []
face_normals = []
face_texture_coords = []
face_group_ids = []
face_group_id = -1
while True:
line = f.readline()

if not line:
# EOF
break

strip = line.strip()

if len(strip) == 0 or strip[0] == "#":
continue

split = strip.split()

if split[0] == "v":
points.append([float(item) for item in split[1:]])
elif split[0] == "vn":
vertex_normals.append([float(item) for item in split[1:]])
elif split[0] == "vt":
texture_coords.append([float(item) for item in split[1:]])
elif split[0] == "s":
# "s 1" or "s off" controls smooth shading
pass
elif split[0] == "f":
# old: dat = [int(item.split("/")[0]) for item in split[1:]]
# A face in obj has one of the following formats: 1, 1/2, 1//3, 1/2/3
# We want to support all formats now amd store the texture and normal indices in other arrays
face_indices = []
face_texture_indices = []
face_normal_indices = []

for item in split[1:]:
indices = item.split("/")
face_indices.append(int(indices[0]))
if len(indices) > 1 and indices[1] != "":
face_texture_indices.append(int(indices[1]))
if len(indices) > 2:
face_normal_indices.append(int(indices[2]))

if len(face_groups) == 0 or (
len(face_groups[-1]) > 0 and len(face_groups[-1][-1]) != len(face_indices)
):
face_groups.append([])
face_group_ids.append([])
face_texture_coords.append([])
face_normals.append([])
face_groups[-1].append(face_indices)
face_group_ids[-1].append(face_group_id)
if face_texture_indices:
face_texture_coords[-1].append(face_texture_indices)
if face_normal_indices:
face_normals[-1].append(face_normal_indices)
elif split[0] == "g":
# new group
face_groups.append([])
face_group_ids.append([])
face_texture_coords.append([])
face_normals.append([])
face_group_id += 1
else:
# who knows
pass

# There may be empty groups, too. <https://github.com/nschloe/meshio/issues/770>
# Remove them.
face_groups = [f for f in face_groups if len(f) > 0]
face_group_ids = [g for g in face_group_ids if len(g) > 0]
face_normals = [n for n in face_normals if len(n) > 0]
face_texture_coords = [t for t in face_texture_coords if len(t) > 0]

# convert to numpy arrays and remove
points = np.array(points)
face_groups = [np.array(f) for f in face_groups]
texture_coords = [np.array(t) for t in texture_coords]
vertex_normals = [np.array(n) for n in vertex_normals]
point_data = {}
cell_data = {}
field_data = {}

if face_texture_coords and len(texture_coords) == max([max(max(face)) for face in face_texture_coords]):
field_data["obj:vt"] = texture_coords
cell_data["obj:vt_face_idx"] = face_texture_coords
elif len(texture_coords) == len(points):
point_data["obj:vt"] = texture_coords

if face_normals and len(vertex_normals) == max([max(max(face)) for face in face_normals]):
field_data["obj:vn"] = vertex_normals
cell_data["obj:vn_face_idx"] = face_normals
elif len(vertex_normals) == len(points):
point_data["obj:vn"] = vertex_normals

cell_data["obj:group_ids"] = []
cells = []
for f, gid in zip(face_groups, face_group_ids):
if f.shape[1] == 3:
cells.append(meshio.CellBlock("triangle", f - 1))
elif f.shape[1] == 4:
cells.append(meshio.CellBlock("quad", f - 1))
else:
cells.append(meshio.CellBlock("polygon", f - 1))
cell_data["obj:group_ids"].append(gid)

return meshio.Mesh(points, cells, point_data=point_data, cell_data=cell_data, field_data=field_data)

meshio.register_format("obj", [".obj"], read, {"obj": None})
22 changes: 16 additions & 6 deletions bseq/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from bseq.utils import refresh_obj
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
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
from .properties import BSEQ_scene_property, BSEQ_obj_property, BSEQ_mesh_property
from .panels import BSEQ_UL_Obj_List, BSEQ_List_Panel, BSEQ_Settings, BSEQ_Import, BSEQ_Templates, BSEQ_UL_Att_List, draw_template
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
from .messenger import subscribe_to_selected, unsubscribe_to_selected
import bpy
from bpy.app.handlers import persistent
Expand All @@ -12,7 +12,8 @@
@persistent
def BSEQ_initialize(scene):
if update_obj not in bpy.app.handlers.frame_change_post:
bpy.app.handlers.frame_change_post.append(auto_refresh)
bpy.app.handlers.frame_change_post.append(auto_refresh_active)
bpy.app.handlers.frame_change_post.append(auto_refresh_all)
bpy.app.handlers.frame_change_post.append(update_obj)
subscribe_to_selected()
if print_information not in bpy.app.handlers.render_init:
Expand All @@ -24,12 +25,16 @@ def BSEQ_initialize(scene):
"BSEQ_OT_load",
"BSEQ_obj_property",
"BSEQ_initialize",
"BSEQ_Import",
"BSEQ_PT_Import",
"BSEQ_PT_Import_Child1",
"BSEQ_PT_Import_Child2",
"BSEQ_Globals_Panel",
"BSEQ_List_Panel",
"BSEQ_UL_Obj_List",
"BSEQ_scene_property",
"BSEQ_Templates",
"BSEQ_Settings",
"BSEQ_Advanced_Panel",
"BSEQ_UL_Att_List",
"subscribe_to_selected",
"BSEQ_OT_resetpt",
Expand All @@ -47,6 +52,11 @@ def BSEQ_initialize(scene):
"BSEQ_OT_enable_all",
"BSEQ_OT_refresh_sequences",
"BSEQ_OT_set_start_end_frames",
"WM_OT_batchSequences",
"WM_OT_MeshioObject"
"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"
]
2 changes: 1 addition & 1 deletion bseq/callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def update_path(self, context):
return [("None", "No sequence detected", "", 1)]

file_sequences.clear()
if len(f) >= 20:
if len(f) >= 30:
file_sequences.append(("None", "Too much sequence detected, could be false detection, please use pattern below", "", 1))
else:
count = 1
Expand Down
21 changes: 17 additions & 4 deletions bseq/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,26 @@ def print_information(scene):
if bseq_prop.init:
file.write("Object name: {}\n".format(obj.name))
file.write("Is it being animated: {}\n".format(bseq_prop.enabled))
file.write("Filepath: {}\n".format(bseq_prop.pattern))
file.write("Is it relative path: {}\n".format(bseq_prop.use_relative))
file.write("Filepath: {}\n".format(bseq_prop.path))
file.write("Pattern: {}\n".format(bseq_prop.pattern))
file.write("Current file: {}\n".format(bseq_prop.current_file))
file.write("\n\n")


def auto_refresh(scene, depsgraph=None):
if not bpy.context.scene.BSEQ.auto_refresh:
def auto_refresh_all(scene, depsgraph=None):
if not bpy.context.scene.BSEQ.auto_refresh_all:
return
for obj in bpy.data.objects:
if obj.BSEQ.init == False:
continue
if obj.BSEQ.enabled == False:
continue
if obj.mode != "OBJECT":
continue
refresh_obj(obj, scene)

def auto_refresh_active(scene, depsgraph=None):
if not bpy.context.scene.BSEQ.auto_refresh_active:
return
for obj in bpy.data.objects:
if obj.BSEQ.init == False:
Expand Down
Loading

0 comments on commit 066c431

Please sign in to comment.