From 3f088f486c10098c1d7b43d9135add3e12f74bef Mon Sep 17 00:00:00 2001 From: Steven Garcia Date: Sun, 7 Jul 2024 08:47:11 -0500 Subject: [PATCH] Actually runs on 4.0 now --- io_scene_halo/file_ass/__init__.py | 105 ++++++----- io_scene_halo/file_jma/__init__.py | 286 +++++++++++++++++++---------- io_scene_halo/file_jms/__init__.py | 284 +++++++++++++++++----------- io_scene_halo/file_qua/__init__.py | 149 +++++++++------ io_scene_halo/file_tag/__init__.py | 254 +++++++++++++++---------- 5 files changed, 671 insertions(+), 407 deletions(-) diff --git a/io_scene_halo/file_ass/__init__.py b/io_scene_halo/file_ass/__init__.py index 396855f81..76e01643b 100644 --- a/io_scene_halo/file_ass/__init__.py +++ b/io_scene_halo/file_ass/__init__.py @@ -46,16 +46,6 @@ StringProperty ) -try: - from bpy.types import ( - FileHandler, - OperatorFileListElement - ) -except ImportError: - print("Blender is out of date. Drag and drop will not function") - FileHandler = None - OperatorFileListElement = None - def version_settings_callback(self, context): items=[ ('1', "1", "H2/H3"), ('2', "2", "H2/H3"), @@ -504,42 +494,69 @@ def draw(self, context): row.enabled = is_enabled row.prop(self, "scale_float") -class ImportASS(Operator, ImportHelper): - """Import an ASS file""" - bl_idname = "import_scene.ass" - bl_label = "Import ASS" - filename_ext = '.ASS' +try: + from bpy.types import FileHandler - filter_glob: StringProperty( - default="*.ass", - options={'HIDDEN'}, - ) + class ImportASS(Operator, ImportHelper): + """Import an ASS file""" + bl_idname = "import_scene.ass" + bl_label = "Import ASS" + filename_ext = '.ASS' - filepath: StringProperty( - subtype='FILE_PATH', - options={'SKIP_SAVE'} - ) + filter_glob: StringProperty( + default="*.ass", + options={'HIDDEN'}, + ) - def execute(self, context): - from ..file_ass import import_ass + filepath: StringProperty( + subtype='FILE_PATH', + options={'SKIP_SAVE'} + ) - return global_functions.run_code("import_ass.load_file(context, self.filepath, self.report)") + def execute(self, context): + from ..file_ass import import_ass - def invoke(self, context, event): - if self.filepath: - return self.execute(context) - context.window_manager.fileselect_add(self) - return {'RUNNING_MODAL'} + return global_functions.run_code("import_ass.load_file(context, self.filepath, self.report)") -class ImportASS_FileHandler(FileHandler): - bl_idname = "ASS_FH_import" - bl_label = "File handler for ASS import" - bl_import_operator = "import_scene.ass" - bl_file_extensions = ".ASS" + def invoke(self, context, event): + if self.filepath: + return self.execute(context) + context.window_manager.fileselect_add(self) + return {'RUNNING_MODAL'} - @classmethod - def poll_drop(cls, context): - return (context.area and context.area.type == 'VIEW_3D') + class ImportASS_FileHandler(FileHandler): + bl_idname = "ASS_FH_import" + bl_label = "File handler for ASS import" + bl_import_operator = "import_scene.ass" + bl_file_extensions = ".ASS" + + @classmethod + def poll_drop(cls, context): + return (context.area and context.area.type == 'VIEW_3D') + +except ImportError: + print("Blender is out of date. Drag and drop will not function") + FileHandler = None + class ImportASS(Operator, ImportHelper): + """Import an ASS file""" + bl_idname = "import_scene.ass" + bl_label = "Import ASS" + filename_ext = '.ASS' + + filter_glob: StringProperty( + default="*.ass", + options={'HIDDEN'}, + ) + + filepath: StringProperty( + subtype='FILE_PATH', + options={'SKIP_SAVE'} + ) + + def execute(self, context): + from ..file_ass import import_ass + + return global_functions.run_code("import_ass.load_file(context, self.filepath, self.report)") def menu_func_export(self, context): self.layout.operator(ExportASS.bl_idname, text='Halo Amalgam Scene Specification (.ass)') @@ -547,13 +564,15 @@ def menu_func_export(self, context): def menu_func_import(self, context): self.layout.operator(ImportASS.bl_idname, text="Halo Amalgam Scene Specification (.ass)") -classeshalo = ( +classeshalo = [ ASS_ScenePropertiesGroup, ASS_SceneProps, ImportASS, - ImportASS_FileHandler, - ExportASS, -) + ExportASS +] + +if not FileHandler == None: + classeshalo.append(ImportASS_FileHandler) def register(): for clshalo in classeshalo: diff --git a/io_scene_halo/file_jma/__init__.py b/io_scene_halo/file_jma/__init__.py index cadd01c10..757981a8e 100644 --- a/io_scene_halo/file_jma/__init__.py +++ b/io_scene_halo/file_jma/__init__.py @@ -47,17 +47,6 @@ StringProperty ) -try: - from bpy.types import ( - FileHandler, - OperatorFileListElement - ) -except ImportError: - print("Blender is out of date. Drag and drop will not function") - FileHandler = None - OperatorFileListElement = None - - class JMS_RestPositionsADialog(Operator): """Set rest positions from a JMS file""" bl_idname = "import_scene.jms_rest_a" @@ -532,116 +521,207 @@ def draw(self, context): row.enabled = is_enabled row.prop(self, "scale_float") -class ImportJMA(Operator, ImportHelper): - """Import a JMA file""" - bl_idname = "import_scene.jma" - bl_label = "Import JMA" - filename_ext = '.JMA' +try: + from bpy.types import FileHandler + + class ImportJMA(Operator, ImportHelper): + """Import a JMA file""" + bl_idname = "import_scene.jma" + bl_label = "Import JMA" + filename_ext = '.JMA' + + game_title: EnumProperty( + name="Game Title:", + description="What game was the model file made for", + default="auto", + items=[ ('auto', "Auto", "Attempt to guess the game this animation was intended for. Will default to Halo CE if this fails."), + ('halo1', "Halo 1", "Import an animation intended for Halo 1"), + ('halo2', "Halo 2", "Import an animation intended for Halo 2"), + ('halo3', "Halo 3", "Import an animation intended for Halo 3"), + ] + ) - game_title: EnumProperty( - name="Game Title:", - description="What game was the model file made for", - default="auto", - items=[ ('auto', "Auto", "Attempt to guess the game this animation was intended for. Will default to Halo CE if this fails."), - ('halo1', "Halo 1", "Import an animation intended for Halo 1"), - ('halo2', "Halo 2", "Import an animation intended for Halo 2"), - ('halo3', "Halo 3", "Import an animation intended for Halo 3"), - ] - ) + fix_parents: BoolProperty( + name ="Force node parents", + description = "Force thigh bones to use pelvis and clavicles to use spine1. Used to match node import behavior used by Halo 2, Halo 3, and Halo 3 ODST", + default = True, + ) - fix_parents: BoolProperty( - name ="Force node parents", - description = "Force thigh bones to use pelvis and clavicles to use spine1. Used to match node import behavior used by Halo 2, Halo 3, and Halo 3 ODST", - default = True, - ) + fix_rotations: BoolProperty( + name ="Fix Rotations", + description = "Set rotations to match what you would visually see in 3DS Max. Rotates bones by 90 degrees on a local Z axis to match how Blender handles rotations", + default = False, + ) - fix_rotations: BoolProperty( - name ="Fix Rotations", - description = "Set rotations to match what you would visually see in 3DS Max. Rotates bones by 90 degrees on a local Z axis to match how Blender handles rotations", - default = False, - ) + jms_path_a: StringProperty( + name="Primary JMS", + description="Select a path to a JMS containing the primary skeleton. Will be used for rest position", + ) - jms_path_a: StringProperty( - name="Primary JMS", - description="Select a path to a JMS containing the primary skeleton. Will be used for rest position", - ) + jms_path_b: StringProperty( + name="Secondary JMS", + description="Select a path to a JMS containing the secondary skeleton. Will be used for rest position", + ) - jms_path_b: StringProperty( - name="Secondary JMS", - description="Select a path to a JMS containing the secondary skeleton. Will be used for rest position", - ) + filter_glob: StringProperty( + default="*.jma;*.jmm;*.jmt;*.jmo;*.jmr;*.jmrx;*.jmh;*.jmz;*.jmw", + options={'HIDDEN'}, + ) - filter_glob: StringProperty( - default="*.jma;*.jmm;*.jmt;*.jmo;*.jmr;*.jmrx;*.jmh;*.jmz;*.jmw", - options={'HIDDEN'}, - ) + filepath: StringProperty( + subtype='FILE_PATH', + options={'SKIP_SAVE'} + ) - filepath: StringProperty( - subtype='FILE_PATH', - options={'SKIP_SAVE'} - ) + def execute(self, context): + from ..file_jma import import_jma - def execute(self, context): - from ..file_jma import import_jma + return global_functions.run_code("import_jma.load_file(context, self.filepath, self.game_title, self.fix_parents, self.fix_rotations, self.jms_path_a, self.jms_path_b, self.report)") - return global_functions.run_code("import_jma.load_file(context, self.filepath, self.game_title, self.fix_parents, self.fix_rotations, self.jms_path_a, self.jms_path_b, self.report)") + def invoke(self, context, event): + if self.filepath: + return self.execute(context) + context.window_manager.fileselect_add(self) + return {'RUNNING_MODAL'} - def invoke(self, context, event): - if self.filepath: - return self.execute(context) - context.window_manager.fileselect_add(self) - return {'RUNNING_MODAL'} + def draw(self, context): + scene = context.scene + scene_jma = scene.jma + self.jms_path_a = scene_jma.jms_path_a + self.jms_path_b = scene_jma.jms_path_b + layout = self.layout - def draw(self, context): - scene = context.scene - scene_jma = scene.jma - self.jms_path_a = scene_jma.jms_path_a - self.jms_path_b = scene_jma.jms_path_b - layout = self.layout + box = layout.box() + box.label(text="Version:") + col = box.column(align=True) + row = col.row() + row.label(text='Game Title:') + row.prop(self, "game_title", text='') + if not self.game_title == "halo1": + box = layout.box() + box.label(text="Import Options:") + col = box.column(align=True) + row = col.row() + row.label(text='Force node parents:') + row.prop(self, "fix_parents", text='') - box = layout.box() - box.label(text="Version:") - col = box.column(align=True) - row = col.row() - row.label(text='Game Title:') - row.prop(self, "game_title", text='') - if self.game_title == "halo1" or self.game_title == 'auto': row = col.row() - row.label(text='Game Version:') - row.prop(self, "game_version", text='') + row.label(text='Fix Rotations:') + row.prop(self, "fix_rotations", text='') - if not self.game_title == "halo1": box = layout.box() - box.label(text="Import Options:") + box.label(text="Import:") col = box.column(align=True) row = col.row() - row.label(text='Force node parents:') - row.prop(self, "fix_parents", text='') + row.label(text='Primary JMS:') + row.prop(self, "jms_path_a", text='') + if ".jms" in self.jms_path_a.lower(): + row = col.row() + row.label(text='Secondary JMS:') + row.prop(self, "jms_path_b", text='') + + class ImportJMA_FileHandler(FileHandler): + bl_idname = "JMA_FH_import" + bl_label = "File handler for JMA import" + bl_import_operator = "import_scene.jma" + bl_file_extensions = ".JMA;.JMM;.JMT;.JMO;.JMR;.JMRX;.JMH;.JMZ;.JMW" + + @classmethod + def poll_drop(cls, context): + return (context.area and context.area.type == 'VIEW_3D') - row = col.row() - row.label(text='Fix Rotations:') - row.prop(self, "fix_rotations", text='') +except ImportError: + print("Blender is out of date. Drag and drop will not function") + FileHandler = None + class ImportJMA(Operator, ImportHelper): + """Import a JMA file""" + bl_idname = "import_scene.jma" + bl_label = "Import JMA" + filename_ext = '.JMA' + + game_title: EnumProperty( + name="Game Title:", + description="What game was the model file made for", + default="auto", + items=[ ('auto', "Auto", "Attempt to guess the game this animation was intended for. Will default to Halo CE if this fails."), + ('halo1', "Halo 1", "Import an animation intended for Halo 1"), + ('halo2', "Halo 2", "Import an animation intended for Halo 2"), + ('halo3', "Halo 3", "Import an animation intended for Halo 3"), + ] + ) - box = layout.box() - box.label(text="Import:") - col = box.column(align=True) - row = col.row() - row.label(text='Primary JMS:') - row.prop(self, "jms_path_a", text='') - if ".jms" in self.jms_path_a.lower(): + fix_parents: BoolProperty( + name ="Force node parents", + description = "Force thigh bones to use pelvis and clavicles to use spine1. Used to match node import behavior used by Halo 2, Halo 3, and Halo 3 ODST", + default = True, + ) + + fix_rotations: BoolProperty( + name ="Fix Rotations", + description = "Set rotations to match what you would visually see in 3DS Max. Rotates bones by 90 degrees on a local Z axis to match how Blender handles rotations", + default = False, + ) + + jms_path_a: StringProperty( + name="Primary JMS", + description="Select a path to a JMS containing the primary skeleton. Will be used for rest position", + ) + + jms_path_b: StringProperty( + name="Secondary JMS", + description="Select a path to a JMS containing the secondary skeleton. Will be used for rest position", + ) + + filter_glob: StringProperty( + default="*.jma;*.jmm;*.jmt;*.jmo;*.jmr;*.jmrx;*.jmh;*.jmz;*.jmw", + options={'HIDDEN'}, + ) + + filepath: StringProperty( + subtype='FILE_PATH', + options={'SKIP_SAVE'} + ) + + def execute(self, context): + from ..file_jma import import_jma + + return global_functions.run_code("import_jma.load_file(context, self.filepath, self.game_title, self.fix_parents, self.fix_rotations, self.jms_path_a, self.jms_path_b, self.report)") + + def draw(self, context): + scene = context.scene + scene_jma = scene.jma + self.jms_path_a = scene_jma.jms_path_a + self.jms_path_b = scene_jma.jms_path_b + layout = self.layout + + box = layout.box() + box.label(text="Version:") + col = box.column(align=True) row = col.row() - row.label(text='Secondary JMS:') - row.prop(self, "jms_path_b", text='') + row.label(text='Game Title:') + row.prop(self, "game_title", text='') + if not self.game_title == "halo1": + box = layout.box() + box.label(text="Import Options:") + col = box.column(align=True) + row = col.row() + row.label(text='Force node parents:') + row.prop(self, "fix_parents", text='') -class ImportJMA_FileHandler(FileHandler): - bl_idname = "JMA_FH_import" - bl_label = "File handler for JMA import" - bl_import_operator = "import_scene.jma" - bl_file_extensions = ".JMA;.JMM;.JMT;.JMO;.JMR;.JMRX;.JMH;.JMZ;.JMW" + row = col.row() + row.label(text='Fix Rotations:') + row.prop(self, "fix_rotations", text='') - @classmethod - def poll_drop(cls, context): - return (context.area and context.area.type == 'VIEW_3D') + box = layout.box() + box.label(text="Import:") + col = box.column(align=True) + row = col.row() + row.label(text='Primary JMS:') + row.prop(self, "jms_path_a", text='') + if ".jms" in self.jms_path_a.lower(): + row = col.row() + row.label(text='Secondary JMS:') + row.prop(self, "jms_path_b", text='') def menu_func_export(self, context): self.layout.operator(ExportJMA.bl_idname, text="Halo Jointed Model Animation (.jma)") @@ -649,15 +729,17 @@ def menu_func_export(self, context): def menu_func_import(self, context): self.layout.operator(ImportJMA.bl_idname, text="Halo Jointed Model Animation (.jma)") -classeshalo = ( +classeshalo = [ JMA_ScenePropertiesGroup, JMA_SceneProps, ImportJMA, - ImportJMA_FileHandler, ExportJMA, JMS_RestPositionsADialog, JMS_RestPositionsBDialog, -) +] + +if not FileHandler == None: + classeshalo.append(ImportJMA_FileHandler) def register(): for clshalo in classeshalo: diff --git a/io_scene_halo/file_jms/__init__.py b/io_scene_halo/file_jms/__init__.py index b516aa8e7..1fe8f0410 100644 --- a/io_scene_halo/file_jms/__init__.py +++ b/io_scene_halo/file_jms/__init__.py @@ -48,16 +48,6 @@ CollectionProperty ) -try: - from bpy.types import ( - FileHandler, - OperatorFileListElement - ) -except ImportError: - print("Blender is out of date. Drag and drop will not function") - FileHandler = None - OperatorFileListElement = None - class JMS_PhysicsPropertiesGroup(PropertyGroup): jms_spring_type: EnumProperty( name="Spring Type", @@ -816,114 +806,197 @@ def draw(self, context): row.enabled = is_enabled row.prop(self, "scale_float") -class ImportJMS(Operator, ImportHelper): - """Import a JMS file""" - bl_idname = "import_scene.jms" - bl_label = "Import JMS" - filename_ext = '.JMS' - game_title: EnumProperty( - name="Game Title:", - description="What game was the model file made for", - default="auto", - items=[ ('auto', "Auto", "Attempt to guess the game this JMS was intended for. Will default to Halo CE if this fails"), - ('halo1', "Halo 1", "Import a JMS intended for Halo 1"), - ('halo2', "Halo 2", "Import a JMS intended for Halo 2"), - ('halo3', "Halo 3", "Import a JMS intended for Halo 3"), - ] +try: + from bpy.types import ( + FileHandler, + OperatorFileListElement ) - reuse_armature: BoolProperty( - name ="Reuse Armature", - description = "Reuse a preexisting armature in the scene if it matches what is in the JMS file", - default = True, - ) + class ImportJMS(Operator, ImportHelper): + """Import a JMS file""" + bl_idname = "import_scene.jms" + bl_label = "Import JMS" + filename_ext = '.JMS' + game_title: EnumProperty( + name="Game Title:", + description="What game was the model file made for", + default="auto", + items=[ ('auto', "Auto", "Attempt to guess the game this JMS was intended for. Will default to Halo CE if this fails"), + ('halo1', "Halo 1", "Import a JMS intended for Halo Custom Edition or Halo 1 MCC"), + ('halo2', "Halo 2", "Import a JMS intended for Halo 2 Vista or Halo 2 MCC"), + ('halo3', "Halo 3", "Import a JMS intended for Halo 3 MCC"), + ] + ) - fix_parents: BoolProperty( - name ="Force node parents", - description = "Force thigh bones to use pelvis and clavicles to use spine1. Used to match node import behavior used by Halo 2, Halo 3, and Halo 3 ODST", - default = True, - ) + reuse_armature: BoolProperty( + name ="Reuse Armature", + description = "Reuse a preexisting armature in the scene if it matches what is in the JMS file", + default = True, + ) - fix_rotations: BoolProperty( - name ="Fix Rotations", - description = "Set rotations to match what you would visually see in 3DS Max. Rotates bones by 90 degrees on a local Z axis to match how Blender handles rotations", - default = False, - ) + fix_parents: BoolProperty( + name ="Force node parents", + description = "Force thigh bones to use pelvis and clavicles to use spine1. Used to match node import behavior used by Halo 2, Halo 3, and Halo 3 ODST", + default = True, + ) - empty_markers: BoolProperty( - name ="Generate Empty Markers", - description = "Generate empty markers instead of UV spheres", - default = True, - ) + fix_rotations: BoolProperty( + name ="Fix Rotations", + description = "Set rotations to match what you would visually see in 3DS Max. Rotates bones by 90 degrees on a local Z axis to match how Blender handles rotations", + default = False, + ) - filter_glob: StringProperty( - default="*.jms;*.jmp", - options={'HIDDEN'}, - ) + empty_markers: BoolProperty( + name ="Generate Empty Markers", + description = "Generate empty markers instead of UV spheres", + default = True, + ) - directory: StringProperty( - subtype='FILE_PATH', - options={'SKIP_SAVE'} - ) - files: CollectionProperty( - type=OperatorFileListElement, - options={'SKIP_SAVE'} - ) + filter_glob: StringProperty( + default="*.jms;*.jmp", + options={'HIDDEN'}, + ) - def execute(self, context): - from . import import_jms + directory: StringProperty( + subtype='FILE_PATH', + options={'SKIP_SAVE'} + ) - if not self.directory: - return {'CANCELLED'} - - for file in self.files: - filepath = os.path.join(self.directory, file.name) - global_functions.run_code("import_jms.load_file(context, filepath, self.game_title, self.reuse_armature, self.fix_parents, self.fix_rotations, self.empty_markers, self.report)") + files: CollectionProperty( + type=OperatorFileListElement, + options={'SKIP_SAVE'} + ) - return {'FINISHED'} + def execute(self, context): + from . import import_jms - def invoke(self, context, event): - if self.directory: - return self.execute(context) - context.window_manager.fileselect_add(self) - return {'RUNNING_MODAL'} + if not self.directory: + return {'CANCELLED'} + + for file in self.files: + filepath = os.path.join(self.directory, file.name) + global_functions.run_code("import_jms.load_file(context, filepath, self.game_title, self.reuse_armature, self.fix_parents, self.fix_rotations, self.empty_markers, self.report)") - def draw(self, context): - layout = self.layout - box = layout.box() - box.label(text="Version:") - col = box.column(align=True) - row = col.row() - box.label(text="Game Version:") - row.prop(self, "game_title", text='') - box = layout.box() - box.label(text="Import Options:") - col = box.column(align=True) + return {'FINISHED'} - row = col.row() - row.label(text='Reuse Armature:') - row.prop(self, "reuse_armature", text='') - if self.game_title == 'auto' or self.game_title == "halo2" or self.game_title == "halo3": + def draw(self, context): + layout = self.layout + box = layout.box() + box.label(text="Version:") + col = box.column(align=True) row = col.row() - row.label(text='Force node parents:') - row.prop(self, "fix_parents", text='') + box.label(text="Game Version:") + row.prop(self, "game_title", text='') + box = layout.box() + box.label(text="Import Options:") + col = box.column(align=True) - row = col.row() - row.label(text='Fix Rotations:') - row.prop(self, "fix_rotations", text='') - row = col.row() - row.label(text='Use Empties For Markers:') - row.prop(self, "empty_markers", text='') + row = col.row() + row.label(text='Reuse Armature:') + row.prop(self, "reuse_armature", text='') + if self.game_title == 'auto' or self.game_title == "halo2" or self.game_title == "halo3": + row = col.row() + row.label(text='Force node parents:') + row.prop(self, "fix_parents", text='') -class ImportJMS_FileHandler(FileHandler): - bl_idname = "JMS_FH_import" - bl_label = "File handler for JMS import" - bl_import_operator = "import_scene.jms" - bl_file_extensions = ".JMS" + row = col.row() + row.label(text='Fix Rotations:') + row.prop(self, "fix_rotations", text='') + row = col.row() + row.label(text='Use Empties For Markers:') + row.prop(self, "empty_markers", text='') - @classmethod - def poll_drop(cls, context): - return (context.area and context.area.type == 'VIEW_3D') + class ImportJMS_FileHandler(FileHandler): + bl_idname = "JMS_FH_import" + bl_label = "File handler for JMS import" + bl_import_operator = "import_scene.jms" + bl_file_extensions = ".JMS" + + @classmethod + def poll_drop(cls, context): + return (context.area and context.area.type == 'VIEW_3D') + +except ImportError: + FileHandler = None + print("Blender is out of date. Drag and drop will not function") + class ImportJMS(Operator, ImportHelper): + """Import a JMS file""" + bl_idname = "import_scene.jms" + bl_label = "Import JMS" + filename_ext = '.JMS' + game_title: EnumProperty( + name="Game Title:", + description="What game was the model file made for", + default="auto", + items=[ ('auto', "Auto", "Attempt to guess the game this JMS was intended for. Will default to Halo CE if this fails"), + ('halo1', "Halo 1", "Import a JMS intended for Halo Custom Edition or Halo 1 MCC"), + ('halo2', "Halo 2", "Import a JMS intended for Halo 2 Vista or Halo 2 MCC"), + ('halo3', "Halo 3", "Import a JMS intended for Halo 3 MCC"), + ] + ) + + reuse_armature: BoolProperty( + name ="Reuse Armature", + description = "Reuse a preexisting armature in the scene if it matches what is in the JMS file", + default = True, + ) + + fix_parents: BoolProperty( + name ="Force node parents", + description = "Force thigh bones to use pelvis and clavicles to use spine1. Used to match node import behavior used by Halo 2, Halo 3, and Halo 3 ODST", + default = True, + ) + + fix_rotations: BoolProperty( + name ="Fix Rotations", + description = "Set rotations to match what you would visually see in 3DS Max. Rotates bones by 90 degrees on a local Z axis to match how Blender handles rotations", + default = False, + ) + + empty_markers: BoolProperty( + name ="Generate Empty Markers", + description = "Generate empty markers instead of UV spheres", + default = True, + ) + + filter_glob: StringProperty( + default="*.jms;*.jmp", + options={'HIDDEN'}, + ) + + def execute(self, context): + from . import import_jms + + global_functions.run_code("import_jms.load_file(context, self.filepath, self.game_title, self.reuse_armature, self.fix_parents, self.fix_rotations, self.empty_markers, self.report)") + + return {'FINISHED'} + + def draw(self, context): + layout = self.layout + box = layout.box() + box.label(text="Version:") + col = box.column(align=True) + row = col.row() + box.label(text="Game Version:") + row.prop(self, "game_title", text='') + box = layout.box() + box.label(text="Import Options:") + col = box.column(align=True) + + row = col.row() + row.label(text='Reuse Armature:') + row.prop(self, "reuse_armature", text='') + if self.game_title == 'auto' or self.game_title == "halo2" or self.game_title == "halo3": + row = col.row() + row.label(text='Force node parents:') + row.prop(self, "fix_parents", text='') + + row = col.row() + row.label(text='Fix Rotations:') + row.prop(self, "fix_rotations", text='') + row = col.row() + row.label(text='Use Empties For Markers:') + row.prop(self, "empty_markers", text='') def menu_func_export(self, context): self.layout.operator(ExportJMS.bl_idname, text="Halo Jointed Model Skeleton (.jms)") @@ -931,15 +1004,18 @@ def menu_func_export(self, context): def menu_func_import(self, context): self.layout.operator(ImportJMS.bl_idname, text="Halo Jointed Model Skeleton (.jms)") -classeshalo = ( +classeshalo = [ + JMA_TransformsDialog, JMS_ScenePropertiesGroup, JMS_SceneProps, JMS_PhysicsPropertiesGroup, JMS_PhysicsProps, ImportJMS, - ImportJMS_FileHandler, ExportJMS -) +] + +if not FileHandler == None: + classeshalo.append(ImportJMS_FileHandler) def register(): for clshalo in classeshalo: diff --git a/io_scene_halo/file_qua/__init__.py b/io_scene_halo/file_qua/__init__.py index 07a8be3d1..fe67c899a 100644 --- a/io_scene_halo/file_qua/__init__.py +++ b/io_scene_halo/file_qua/__init__.py @@ -38,17 +38,6 @@ ExportHelper ) -try: - from bpy.types import ( - FileHandler, - OperatorFileListElement - ) -except ImportError: - print("Blender is out of date. Drag and drop will not function") - FileHandler = None - OperatorFileListElement = None - - class ExportQUA(Operator, ExportHelper): """Write a QUA file""" bl_idname = 'export_scene.qua' @@ -115,53 +104,91 @@ def draw(self, context): row.label(text='Strip Identifier:') row.prop(self, "strip_identifier", text='') -class ImportQUA(Operator, ImportHelper): - """Import a QUA file""" - bl_idname = "import_scene.qua" - bl_label = "Import QUA" - filename_ext = '.QUA' - - game_title: EnumProperty( - name="Game Title:", - description="What game was the cinematic file made for", - default="auto", - items=[ ('auto', "Auto", "Attempt to guess the game this animation was intended for. Will default to Halo CE if this fails."), - ('halo1', "Halo 1", "Import an animation intended for Halo 1"), - ('halo2', "Halo 2", "Import an animation intended for Halo 2"), - ('halo3', "Halo 3", "Import an animation intended for Halo 3"), - ] - ) - - filter_glob: StringProperty( - default="*.qua", - options={'HIDDEN'}, - ) - - filepath: StringProperty( - subtype='FILE_PATH', - options={'SKIP_SAVE'} - ) - - def execute(self, context): - from ..file_qua import import_qua - - return global_functions.run_code("import_qua.load_file(context, self.filepath, self.report)") - - def invoke(self, context, event): - if self.filepath: - return self.execute(context) - context.window_manager.fileselect_add(self) - return {'RUNNING_MODAL'} - -class ImportQUA_FileHandler(FileHandler): - bl_idname = "QUA_FH_import" - bl_label = "File handler for QUA import" - bl_import_operator = "import_scene.qua" - bl_file_extensions = ".QUA" +try: + from bpy.types import FileHandler + + class ImportQUA(Operator, ImportHelper): + """Import a QUA file""" + bl_idname = "import_scene.qua" + bl_label = "Import QUA" + filename_ext = '.QUA' + + game_title: EnumProperty( + name="Game Title:", + description="What game was the cinematic file made for", + default="auto", + items=[ ('auto', "Auto", "Attempt to guess the game this animation was intended for. Will default to Halo CE if this fails."), + ('halo1', "Halo 1", "Import an animation intended for Halo 1"), + ('halo2', "Halo 2", "Import an animation intended for Halo 2"), + ('halo3', "Halo 3", "Import an animation intended for Halo 3"), + ] + ) + + filter_glob: StringProperty( + default="*.qua", + options={'HIDDEN'}, + ) + + filepath: StringProperty( + subtype='FILE_PATH', + options={'SKIP_SAVE'} + ) + + def execute(self, context): + from ..file_qua import import_qua + + return global_functions.run_code("import_qua.load_file(context, self.filepath, self.report)") + + def invoke(self, context, event): + if self.filepath: + return self.execute(context) + context.window_manager.fileselect_add(self) + return {'RUNNING_MODAL'} + + class ImportQUA_FileHandler(FileHandler): + bl_idname = "QUA_FH_import" + bl_label = "File handler for QUA import" + bl_import_operator = "import_scene.qua" + bl_file_extensions = ".QUA" + + @classmethod + def poll_drop(cls, context): + return (context.area and context.area.type == 'VIEW_3D') - @classmethod - def poll_drop(cls, context): - return (context.area and context.area.type == 'VIEW_3D') +except ImportError: + print("Blender is out of date. Drag and drop will not function") + FileHandler = None + class ImportQUA(Operator, ImportHelper): + """Import a QUA file""" + bl_idname = "import_scene.qua" + bl_label = "Import QUA" + filename_ext = '.QUA' + + game_title: EnumProperty( + name="Game Title:", + description="What game was the cinematic file made for", + default="auto", + items=[ ('auto', "Auto", "Attempt to guess the game this animation was intended for. Will default to Halo CE if this fails."), + ('halo1', "Halo 1", "Import an animation intended for Halo 1"), + ('halo2', "Halo 2", "Import an animation intended for Halo 2"), + ('halo3', "Halo 3", "Import an animation intended for Halo 3"), + ] + ) + + filter_glob: StringProperty( + default="*.qua", + options={'HIDDEN'}, + ) + + filepath: StringProperty( + subtype='FILE_PATH', + options={'SKIP_SAVE'} + ) + + def execute(self, context): + from ..file_qua import import_qua + + return global_functions.run_code("import_qua.load_file(context, self.filepath, self.report)") def menu_func_export(self, context): self.layout.operator(ExportQUA.bl_idname, text='Halo Ubercam Animation (.qua)') @@ -169,11 +196,13 @@ def menu_func_export(self, context): def menu_func_import(self, context): self.layout.operator(ImportQUA.bl_idname, text="Halo Ubercam Animation (.qua)") -classeshalo = ( +classeshalo = [ ImportQUA, - ImportQUA_FileHandler, ExportQUA -) +] + +if not FileHandler == None: + classeshalo.append(ImportQUA_FileHandler) def register(): for clshalo in classeshalo: diff --git a/io_scene_halo/file_tag/__init__.py b/io_scene_halo/file_tag/__init__.py index be0b23351..7c497542c 100644 --- a/io_scene_halo/file_tag/__init__.py +++ b/io_scene_halo/file_tag/__init__.py @@ -43,101 +43,6 @@ from ..global_functions import global_functions -try: - from bpy.types import ( - FileHandler, - OperatorFileListElement - ) -except ImportError: - print("Blender is out of date. Drag and drop will not function") - FileHandler = None - OperatorFileListElement = None - -class ImportTag(Operator, ImportHelper): - """Import a tag for various Halo titles""" - bl_idname = "import_scene.tag" - bl_label = "Import Tag" - - game_title: EnumProperty( - name="Game:", - description="What game does the tag group belong to", - items=[ ('auto', "Auto", "Attempt to get the game title automatically. Defaults to Halo 1 if it fails."), - ('halo1', "Halo 1", "Use tag data from Halo 1"), - ('halo2', "Halo 2", "Use tag data from Halo 2"), - ('halo3', "Halo 3", "Use tag data from Halo 3"), - ] - ) - - fix_rotations: BoolProperty( - name ="Fix Rotations", - description = "Set rotations to match what you would visually see in 3DS Max. Rotates bones by 90 degrees on a local Z axis to match how Blender handles rotations", - default = False, - ) - - empty_markers: BoolProperty( - name ="Generate Empty Markers", - description = "Generate empty markers instead of UV spheres", - default = True, - ) - - directory: StringProperty( - subtype='FILE_PATH', - options={'SKIP_SAVE'} - ) - files: CollectionProperty( - type=OperatorFileListElement, - options={'SKIP_SAVE'} - ) - - def execute(self, context): - from ..file_tag import import_tag - - if not self.directory: - return {'CANCELLED'} - - for file in self.files: - filepath = os.path.join(self.directory, file.name) - global_functions.run_code("import_tag.load_file(context, filepath, self.game_title, self.fix_rotations, self.empty_markers, self.report)") - - return {'FINISHED'} - - def invoke(self, context, event): - if self.directory: - return self.execute(context) - context.window_manager.fileselect_add(self) - return {'RUNNING_MODAL'} - - def draw(self, context): - layout = self.layout - - box = layout.box() - box.label(text="Game Title:") - col = box.column(align=True) - row = col.row() - row.prop(self, "game_title", text='') - col = box.column(align=True) - - box = layout.box() - box.label(text="Import Options:") - col = box.column(align=True) - - row = col.row() - row.label(text='Fix Rotations:') - row.prop(self, "fix_rotations", text='') - row = col.row() - row.label(text='Use Empties For Markers:') - row.prop(self, "empty_markers", text='') - -class ImportTag_FileHandler(FileHandler): - bl_idname = "TAG_FH_import" - bl_label = "File handler for tag import" - bl_import_operator = "import_scene.tag" - bl_file_extensions = ".model;.gbxmodel;.model_collision_geometry;.model_animations;.physics;.scenario_structure_bsp;.scenario;.camera_track;.render_model;.shader_environment;.shader_model;.shader_transparent_meter;.shader_transparent_glass" - - @classmethod - def poll_drop(cls, context): - return (context.area and context.area.type == 'VIEW_3D') - class ExportSCNR(Operator, ExportHelper): """Write a scenario tag file""" bl_idname = "export_scene.scnr" @@ -154,11 +59,164 @@ def execute(self, context): return global_functions.run_code("export_tag.write_file(context, self.filepath, self.report)") -classeshalo = ( +try: + from bpy.types import ( + FileHandler, + OperatorFileListElement + ) + + class ImportTag(Operator, ImportHelper): + """Import a tag for various Halo titles""" + bl_idname = "import_scene.tag" + bl_label = "Import Tag" + + game_title: EnumProperty( + name="Game:", + description="What game does the tag group belong to", + items=[ ('auto', "Auto", "Attempt to get the game title automatically. Defaults to Halo 1 if it fails."), + ('halo1', "Halo 1", "Use tag data from Halo 1"), + ('halo2', "Halo 2", "Use tag data from Halo 2"), + ('halo3', "Halo 3", "Use tag data from Halo 3"), + ] + ) + + fix_rotations: BoolProperty( + name ="Fix Rotations", + description = "Set rotations to match what you would visually see in 3DS Max. Rotates bones by 90 degrees on a local Z axis to match how Blender handles rotations", + default = False, + ) + + empty_markers: BoolProperty( + name ="Generate Empty Markers", + description = "Generate empty markers instead of UV spheres", + default = True, + ) + + directory: StringProperty( + subtype='FILE_PATH', + options={'SKIP_SAVE'} + ) + + files: CollectionProperty( + type=OperatorFileListElement, + options={'SKIP_SAVE'} + ) + + def execute(self, context): + from ..file_tag import import_tag + + if not self.directory: + return {'CANCELLED'} + + for file in self.files: + filepath = os.path.join(self.directory, file.name) + print(filepath) + global_functions.run_code("import_tag.load_file(context, filepath, self.game_title, self.fix_rotations, self.empty_markers, self.report)") + + return {'FINISHED'} + + def invoke(self, context, event): + if self.directory: + return self.execute(context) + context.window_manager.fileselect_add(self) + return {'RUNNING_MODAL'} + + def draw(self, context): + layout = self.layout + + box = layout.box() + box.label(text="Game Title:") + col = box.column(align=True) + row = col.row() + row.prop(self, "game_title", text='') + col = box.column(align=True) + + box = layout.box() + box.label(text="Import Options:") + col = box.column(align=True) + + row = col.row() + row.label(text='Fix Rotations:') + row.prop(self, "fix_rotations", text='') + row = col.row() + row.label(text='Use Empties For Markers:') + row.prop(self, "empty_markers", text='') + + class ImportTag_FileHandler(FileHandler): + bl_idname = "TAG_FH_import" + bl_label = "File handler for tag import" + bl_import_operator = "import_scene.tag" + bl_file_extensions = ".model;.gbxmodel;.model_collision_geometry;.model_animations;.physics;.scenario_structure_bsp;.scenario;.camera_track;.render_model;.shader_environment;.shader_model;.shader_transparent_meter;.shader_transparent_glass" + + @classmethod + def poll_drop(cls, context): + return (context.area and context.area.type == 'VIEW_3D') + +except ImportError: + print("Blender is out of date. Drag and drop will not function") + FileHandler = None + class ImportTag(Operator, ImportHelper): + """Import a tag for various Halo titles""" + bl_idname = "import_scene.tag" + bl_label = "Import Tag" + + game_title: EnumProperty( + name="Game:", + description="What game does the tag group belong to", + items=[ ('auto', "Auto", "Attempt to get the game title automatically. Defaults to Halo 1 if it fails."), + ('halo1', "Halo 1", "Use tag data from Halo 1"), + ('halo2', "Halo 2", "Use tag data from Halo 2"), + ('halo3', "Halo 3", "Use tag data from Halo 3"), + ] + ) + + fix_rotations: BoolProperty( + name ="Fix Rotations", + description = "Set rotations to match what you would visually see in 3DS Max. Rotates bones by 90 degrees on a local Z axis to match how Blender handles rotations", + default = False, + ) + + empty_markers: BoolProperty( + name ="Generate Empty Markers", + description = "Generate empty markers instead of UV spheres", + default = True, + ) + + def execute(self, context): + from ..file_tag import import_tag + + global_functions.run_code("import_tag.load_file(context, self.filepath, self.game_title, self.fix_rotations, self.empty_markers, self.report)") + + return {'FINISHED'} + + def draw(self, context): + layout = self.layout + + box = layout.box() + box.label(text="Game Title:") + col = box.column(align=True) + row = col.row() + row.prop(self, "game_title", text='') + col = box.column(align=True) + + box = layout.box() + box.label(text="Import Options:") + col = box.column(align=True) + + row = col.row() + row.label(text='Fix Rotations:') + row.prop(self, "fix_rotations", text='') + row = col.row() + row.label(text='Use Empties For Markers:') + row.prop(self, "empty_markers", text='') + +classeshalo = [ ImportTag, - ImportTag_FileHandler, ExportSCNR -) +] + +if not FileHandler == None: + classeshalo.append(ImportTag_FileHandler) def menu_func_export(self, context): self.layout.operator(ExportSCNR.bl_idname, text="Halo Scenario (.scenario)")