diff --git a/.travis.yml b/.travis.yml index c853e72..eaf3044 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,8 @@ env: - "PYTHONPATH=." matrix: include: - - python: "3.5" - env: "BLENDER_TAR=http://download.blender.org/release/Blender2.79/blender-2.79-linux-glibc219-x86_64.tar.bz2" - - python: "3.4" - env: "BLENDER_TAR=http://download.blender.org/release/Blender2.72/blender-2.72-linux-glibc211-x86_64.tar.bz2" + - python: "3.7" + env: "BLENDER_TAR=https://builder.blender.org/download/blender-2.80-16639c6f1a31-linux-glibc224-x86_64.tar.bz2" before_install: - wget -O - ${BLENDER_TAR} | tar -jxf - - mv blender-* blender diff --git a/README.md b/README.md index e1abe36..093cf50 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # .MD3 support for Blender -Up-to-date addon (Blender ≥ 2.7.2 supported!) for working with Quake 3 model format, written from scratch. +Up-to-date addon (Blender 2.8x supported!) for working with Quake 3 model format, written from scratch. Can deal with animation (via the Shape Keys), textures and md3 tags (added as Empty objects). @@ -12,6 +12,4 @@ Used [this](http://www.icculus.org/homepages/phaethon/q3a/formats/md3format.html ## Supported versions -2.6.9 very likely will work, though it becomes increasingly complex to test & maintain -python 3.3 builds due to lack of features present in newer versions of python and -significant API mismatches in bunch of supporting software. +Blender 2.80 and above. diff --git a/io_scene_md3/__init__.py b/io_scene_md3/__init__.py index bb33e8e..2e3027b 100644 --- a/io_scene_md3/__init__.py +++ b/io_scene_md3/__init__.py @@ -1,8 +1,8 @@ bl_info = { "name": "Quake 3 Model (.md3)", "author": "Vitaly Verhovodov", - "version": (0, 2, 1), - "blender": (2, 72, 0), + "version": (0, 3, 1), + "blender": (2, 80, 0), "location": "File > Import-Export > Quake 3 Model", "description": "Quake 3 Model format (.md3)", "warning": "", @@ -57,17 +57,23 @@ def menu_func_import(self, context): def menu_func_export(self, context): self.layout.operator(ExportMD3.bl_idname, text="Quake 3 Model (.md3)") +classes = ( + ExportMD3, + ImportMD3 +) def register(): - bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + for cls in classes: + bpy.utils.register_class(cls) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): - bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + for cls in classes: + bpy.utils.unregister_class(cls) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) if __name__ == "__main__": diff --git a/io_scene_md3/export_md3.py b/io_scene_md3/export_md3.py index 1e3c09b..98a162d 100644 --- a/io_scene_md3/export_md3.py +++ b/io_scene_md3/export_md3.py @@ -25,6 +25,7 @@ def prepare_name(name): def gather_shader_info(mesh): 'Returning uvmap name, texture name list' uv_maps = {} + ''' for material in mesh.materials: for texture_slot in material.texture_slots: if ( @@ -40,6 +41,10 @@ def gather_shader_info(mesh): uv_maps[uv_map_name] = [] # one UV map can be used by many textures uv_maps[uv_map_name].append(prepare_name(texture_slot.texture.name)) + ''' + uv_maps["UVMap"] = [] + uv_maps["UVMap"].append("placeholder") + uv_maps = [(k, v) for k, v in uv_maps.items()] if len(uv_maps) <= 0: print('Warning: No UV maps found, zero filling will be used') @@ -140,7 +145,7 @@ def get_evaluated_vertex_co(self, frame, i): a, b, t = self.mesh_sk_abs co = interp(kbs[a].data[i].co, kbs[b].data[i].co, t) - co = self.mesh_matrix * co + co = self.mesh_matrix @ co self.mesh_vco[frame].append(co) return co @@ -165,9 +170,9 @@ def switch_frame(self, i): def surface_start_frame(self, i): self.switch_frame(i) - obj = self.scene.objects.active + obj = bpy.context.view_layer.objects.active self.mesh_matrix = obj.matrix_world - self.mesh = obj.to_mesh(self.scene, True, 'PREVIEW') + self.mesh = obj.to_mesh(preserve_all_data_layers=True) self.mesh.calc_normals_split() self.mesh_sk_rel = None @@ -190,14 +195,16 @@ def surface_start_frame(self, i): def pack_surface(self, surf_name): obj = self.scene.objects[surf_name] - self.scene.objects.active = obj + bpy.context.view_layer.objects.active = obj bpy.ops.object.modifier_add(type='TRIANGULATE') # no 4-gons or n-gons - self.mesh = obj.to_mesh(self.scene, True, 'PREVIEW') + #self.mesh = obj.to_mesh(bpy.context.depsgraph, True) + self.mesh = obj.to_mesh(preserve_all_data_layers=True) self.mesh.calc_normals_split() self.mesh_uvmap_name, self.mesh_shader_list = gather_shader_info(self.mesh) self.mesh_md3vert_to_loop, self.mesh_loop_to_md3vert = gather_vertices( self.mesh, + #None if self.mesh_uvmap_name is None else self.mesh.uv_layers[self.mesh_uvmap_name].data) None if self.mesh_uvmap_name is None else self.mesh.uv_layers[self.mesh_uvmap_name].data) nShaders = len(self.mesh_shader_list) @@ -283,7 +290,7 @@ def __call__(self, filename): self.surfNames = [] self.tagNames = [] for o in self.scene.objects: - if o.hide: # skip hidden objects + if o.hide_viewport: # skip hidden objects continue if o.type == 'MESH': self.surfNames.append(o.name) diff --git a/io_scene_md3/import_md3.py b/io_scene_md3/import_md3.py index fa68662..0b11313 100644 --- a/io_scene_md3/import_md3.py +++ b/io_scene_md3/import_md3.py @@ -61,7 +61,7 @@ def create_tag(self, i): bpy.ops.object.add(type='EMPTY') tag = bpy.context.object tag.name = data.name - tag.empty_draw_type = 'ARROWS' + #tag.empty_draw_type = 'ARROWS' tag.rotation_mode = 'QUATERNION' tag.matrix_basis = get_tag_matrix_basis(data) return tag @@ -104,7 +104,7 @@ def read_mesh_animation(self, obj, data, start_pos): data.nVerts, start_pos + data.offVerts + frame * fmt.Vertex.size * data.nVerts, self.read_surface_vert) - self.scene.objects.active = obj + bpy.context.view_layer.objects.active = obj self.context.object.active_shape_key_index = 0 bpy.ops.object.shape_key_retime() for frame in range(data.nFrames): @@ -123,7 +123,14 @@ def make_surface_UV_map(self, uv, uvdata): def read_surface_shader(self, i): data = self.unpack(fmt.Shader) - + ''' + # trying to use nodes: + self.material.use_nodes = True + bsdf = self.material.node_tree.nodes["Principled BSDF"] + texture = self.material.node_tree.nodes.new('ShaderNodeTexImage') + self.material.node_tree.links.new(bsdf.inputs['Base Color'], texture.outputs['Color']) + ''' + ''' texture = bpy.data.textures.new(data.name, 'IMAGE') texture_slot = self.material.texture_slots.create(i) texture_slot.uv_layer = 'UVMap' @@ -138,6 +145,7 @@ def read_surface_shader(self, i): image = bpy.data.images.load(fname) texture.image = image break + ''' def read_surface(self, i): start_pos = self.file.tell() @@ -166,7 +174,7 @@ def read_surface(self, i): self.material = bpy.data.materials.new('Main') self.mesh.materials.append(self.material) - self.mesh.uv_textures.new('UVMap') + self.mesh.uv_layers.new(name='UVMap') self.make_surface_UV_map( self.read_n_items(data.nVerts, start_pos + data.offST, self.read_surface_ST), self.mesh.uv_layers['UVMap'].data) @@ -174,7 +182,7 @@ def read_surface(self, i): self.read_n_items(data.nShaders, start_pos + data.offShaders, self.read_surface_shader) obj = bpy.data.objects.new(data.name, self.mesh) - self.scene.objects.link(obj) + self.scene.collection.objects.link(obj) if data.nFrames > 1: self.read_mesh_animation(obj, data, start_pos) @@ -183,8 +191,8 @@ def read_surface(self, i): def post_settings(self): self.scene.frame_set(0) - self.scene.game_settings.material_mode = 'GLSL' # TODO: questionable - bpy.ops.object.lamp_add(type='SUN') # TODO: questionable + #self.scene.game_settings.material_mode = 'GLSL' # TODO: questionable + #bpy.ops.object.lamp_add(type='SUN') # TODO: questionable def __call__(self, filename): self.filename = filename