diff --git a/io_scene_blam/__init__.py b/io_scene_blam/__init__.py index 6e981ed..c20df1b 100644 --- a/io_scene_blam/__init__.py +++ b/io_scene_blam/__init__.py @@ -50,7 +50,7 @@ PropertyGroup ) -from io_scene_blam import export_model +from io_scene_blam import export_jms_model # ------------------------------------------------------------ # Menu's and panels: @@ -215,7 +215,7 @@ class Blam_ObjectPropertiesGroup(PropertyGroup): # Register: classes = ( - export_model.Blam_ExportModel, + export_jms_model.Blam_ExportJmsModel, Blam_ScenePropertiesGroup, Blam_ObjectPropertiesGroup, Blam_SceneProps, @@ -227,7 +227,7 @@ def register(): for cls in classes: bpy.utils.register_class(cls) - bpy.types.TOPBAR_MT_file_export.append(export_model.menu_func_export) + bpy.types.TOPBAR_MT_file_export.append(export_jms_model.menu_func_export) bpy.types.Scene.blam = PointerProperty(type=Blam_ScenePropertiesGroup, name="Blam Properties", description="Blam Object properties") bpy.types.Object.blam = PointerProperty(type=Blam_ObjectPropertiesGroup, name="Blam Properties", description="Blam Object properties") @@ -238,7 +238,7 @@ def unregister(): for cls in reversed(classes): bpy.utils.unregister_class(cls) - bpy.types.TOPBAR_MT_file_export.remove(export_model.menu_func_export) + bpy.types.TOPBAR_MT_file_export.remove(export_jms_model.menu_func_export) del bpy.types.Scene.blam del bpy.types.Object.blam diff --git a/io_scene_blam/export_model.py b/io_scene_blam/export_jms_model.py similarity index 73% rename from io_scene_blam/export_model.py rename to io_scene_blam/export_jms_model.py index cd61446..e80a82f 100644 --- a/io_scene_blam/export_model.py +++ b/io_scene_blam/export_jms_model.py @@ -30,6 +30,10 @@ EnumProperty, ) from bpy.types import Operator +from .utils import ( + get_root_collection, + mesh_triangulate + ) JMS_CONSTANT = 8200 NODE_LIST_CHECKSUM = 3251 @@ -37,8 +41,8 @@ # ------------------------------------------------------------ # Menu's and panels: -class Blam_ExportModel(Operator, ExportHelper): - bl_idname = "blam.export_model" # important since its how bpy.ops.import_test.some_data is constructed +class Blam_ExportJmsModel(Operator, ExportHelper): + bl_idname = "blam.export_jms_model" # important since its how bpy.ops.import_test.some_data is constructed bl_label = "Export Halo model file" bl_options = {'PRESET'} @@ -49,16 +53,6 @@ class Blam_ExportModel(Operator, ExportHelper): options={'HIDDEN'}, maxlen=255, # Max internal buffer length, longer would be clamped. ) - - game: EnumProperty( - name="Example Enum", - description="Choose between exporting a Halo CE .jms file or a Halo 2 .ass file", - items=( - ('h1', "Halo CE (.jms)", ""), - ('h2', "Halo 2 (.ass)", ""), - ), - default='h1', - ) use_mesh_modifiers: BoolProperty( name="Apply Modifiers", @@ -81,10 +75,10 @@ def execute(self, context): ) def menu_func_export(self, context): - self.layout.operator(Blam_ExportModel.bl_idname, text='Halo Model (.jms/.ass)') + self.layout.operator(Blam_ExportJmsModel.bl_idname, text='Halo Model (.jms)') def write_jms_model(context, filepath, - EXPORT_TRI=False, + EXPORT_TRI=True, EXPORT_APPLY_MODIFIERS=True): root_collection = get_root_collection() @@ -107,7 +101,7 @@ def write_jms_model(context, filepath, regions.append(obj.data.name[:31]) # Materials - flags = get_object_shader_flags(obj, "h1") + flags = get_object_shader_flags(obj) material_indexs = [] for mat in obj.material_slots: matname = get_truncated_mat_name(mat.name, flags) @@ -213,58 +207,12 @@ def write_jms_model(context, filepath, return {'FINISHED'} -def write_ass_model(context, filepath): - root_collection = get_root_collection() - instancer_collection = get_instancer_collection() - - objects = [] - instanced_objects = [] - materials = [] - - # Get all objects and instanced objects - for obj in root_collection.all_objects: - if obj.is_from_instancer: - instanced_objects.append(obj) - else: - objects.append(obj) - - # Get all material names for each object - for obj in objects: - flags = get_object_shader_flags(obj, "h2") - for mat in obj.material_slots: - matname = get_truncated_mat_name(mat.name, flags) - if matname not in materials: - materials.append(matname) - for obj in instanced_objects: - flags = get_object_shader_flags(obj, "h2") - for mat in obj.material_slots: - matname = get_truncated_mat_name(mat.name, flags) - if matname not in materials: - materials.append(matname) - - # Start write - file = open(filepath, 'w',) - -def get_root_collection(): - try: - scene = bpy.context.scene - return bpy.data.collections[scene.blam.root_collection] - except: - print('Error: All geomotry must be parented too the collection \"' + bpy.context.blam.root_collection + '\".') - -def get_instancer_collection(): - try: - return bpy.data.collections[bpy.context.scene.blam.instancer_collection] - except: - print('Error: All geomotry must be parented too the collection \"' + bpy.context.blam.root_collection + '\".') - -def get_object_shader_flags(obj, game): +def get_object_shader_flags(obj): blam = obj.blam if blam.custom_flags != "": return blam.custom_flags - elif game == "h1": + else: flag_string = "" - if blam.double_sided: flag_string += '%' if blam.allow_transparency: @@ -287,8 +235,6 @@ def get_object_shader_flags(obj, game): flag_string += '.' return flag_string - else: - return "" def get_truncated_mat_name(matname, flags): combined_name = matname + flags @@ -298,11 +244,3 @@ def get_truncated_mat_name(matname, flags): return truncated_name else: return combined_name - -def mesh_triangulate(mesh): - import bmesh - bm = bmesh.new() - bm.from_mesh(mesh) - bmesh.ops.triangulate(bm, faces=bm.faces) - bm.to_mesh(mesh) - bm.free() diff --git a/io_scene_blam/utils.py b/io_scene_blam/utils.py new file mode 100644 index 0000000..24ae4db --- /dev/null +++ b/io_scene_blam/utils.py @@ -0,0 +1,42 @@ +# Copyright (c) 2019 Oliver Hitchcock ojhitchcock@gmail.com +# +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +import bpy + +def get_root_collection(): + try: + scene = bpy.context.scene + return bpy.data.collections[scene.blam.root_collection] + except: + print('Error: All geomotry must be parented too the collection \"' + bpy.context.blam.root_collection + '\".') + +def get_instancer_collection(): + try: + return bpy.data.collections[bpy.context.scene.blam.instancer_collection] + except: + print('Error: All geomotry must be parented too the collection \"' + bpy.context.blam.root_collection + '\".') + +def mesh_triangulate(mesh): + import bmesh + bm = bmesh.new() + bm.from_mesh(mesh) + bmesh.ops.triangulate(bm, faces=bm.faces) + bm.to_mesh(mesh) + bm.free()