From 527891f6cdc7d1135143c244b3b03e76dafea669 Mon Sep 17 00:00:00 2001 From: Simon Lusenc Date: Thu, 9 Jan 2020 15:39:05 +0100 Subject: [PATCH] Release - 2.0 Final --- addon/io_scs_tools/__init__.py | 10 +++++++-- .../internals/open_gl/primitive.py | 18 +++++++-------- .../internals/persistent/file_load.py | 14 +++++++----- .../internals/preview_models/__init__.py | 6 ++++- addon/io_scs_tools/operators/bases/export.py | 6 +++-- addon/io_scs_tools/operators/material.py | 14 +++++++++--- addon/io_scs_tools/utils/material.py | 22 +++++++++++-------- 7 files changed, 58 insertions(+), 32 deletions(-) diff --git a/addon/io_scs_tools/__init__.py b/addon/io_scs_tools/__init__.py index 3b6421a0..1ba452f1 100644 --- a/addon/io_scs_tools/__init__.py +++ b/addon/io_scs_tools/__init__.py @@ -22,7 +22,7 @@ "name": "SCS Tools", "description": "Setup models, Import-Export SCS data format", "author": "Simon Lusenc (50keda), Milos Zajic (4museman)", - "version": (2, 0, "c95d7ac"), + "version": (2, 0, "fae8eb4"), "blender": (2, 81, 0), "location": "File > Import-Export", "wiki_url": "http://modding.scssoft.com/wiki/Documentation/Tools/SCS_Blender_Tools", @@ -218,7 +218,13 @@ class SCS_TOOLS_OT_Export(bpy.types.Operator, _SCSExportHelper, ExportHelper): filter_glob: StringProperty(default=str("*" + filename_ext), options={'HIDDEN'}) def execute(self, context): - return self.execute_export(context, True) + # convert filepath to None if empty, so export will ignore given menu file path and try to export to other none menu set paths + if self.filepath == "": + filepath = None + else: + filepath = os.path.dirname(self.filepath) + + return self.execute_export(context, True, menu_filepath=filepath) def draw(self, context): from io_scs_tools.ui.shared import draw_export_panel diff --git a/addon/io_scs_tools/internals/open_gl/primitive.py b/addon/io_scs_tools/internals/open_gl/primitive.py index e3c55508..ac1d5cfd 100644 --- a/addon/io_scs_tools/internals/open_gl/primitive.py +++ b/addon/io_scs_tools/internals/open_gl/primitive.py @@ -151,15 +151,15 @@ class _ViewsBufferHandler: def __get_new_buffers__(): """Gets new instance for all buffers we currently use in one view. - :return: currently we have 3 buffers: 1 for lines and 2 for points of different size + :return: currently we have 5 buffers: 1 for trises, 1 for stipple lines, 1 for normal lines and 2 for points of different size :rtype: tuple[_Buffer] """ return ( - _Buffer(_Buffer.Types.LINES, 2, ShaderTypes.SMOOTH_COLOR_CLIPPED_3D, ("pos", "color")), # 0 + _Buffer(_Buffer.Types.TRIS, 0, ShaderTypes.SMOOTH_COLOR_CLIPPED_3D, ("pos", "color")), # 0 _Buffer(_Buffer.Types.LINES, 2, ShaderTypes.SMOOTH_COLOR_STIPPLE_CLIPPED_3D, ("pos", "color")), # 1 - _Buffer(_Buffer.Types.POINTS, 5, ShaderTypes.SMOOTH_COLOR_CLIPPED_3D, ("pos", "color")), # 2 - _Buffer(_Buffer.Types.POINTS, 12, ShaderTypes.SMOOTH_COLOR_CLIPPED_3D, ("pos", "color")), # 3 - _Buffer(_Buffer.Types.TRIS, 0, ShaderTypes.SMOOTH_COLOR_CLIPPED_3D, ("pos", "color")), # 4 + _Buffer(_Buffer.Types.LINES, 2, ShaderTypes.SMOOTH_COLOR_CLIPPED_3D, ("pos", "color")), # 2 + _Buffer(_Buffer.Types.POINTS, 5, ShaderTypes.SMOOTH_COLOR_CLIPPED_3D, ("pos", "color")), # 3 + _Buffer(_Buffer.Types.POINTS, 12, ShaderTypes.SMOOTH_COLOR_CLIPPED_3D, ("pos", "color")), # 4 ) def __init__(self): @@ -200,7 +200,7 @@ def append_tris_vertex(self, pos, color): :param color: color of the vertex, has to be of size 4 and fromat: (r, g, b, a) :type color: mathutils.Vector | bpy.types.bpy_prop_collection | tuple """ - buffer = self.__buffers[self.__current][4] + buffer = self.__buffers[self.__current][0] buffer.append_attr("pos", tuple(pos)) buffer.append_attr("color", tuple(color)) @@ -218,7 +218,7 @@ def append_line_vertex(self, pos, color, is_stipple=False): if is_stipple: buffer = self.__buffers[self.__current][1] else: - buffer = self.__buffers[self.__current][0] + buffer = self.__buffers[self.__current][2] buffer.append_attr("pos", tuple(pos)) buffer.append_attr("color", tuple(color)) @@ -234,9 +234,9 @@ def append_point_vertex(self, pos, color, size): :type size: float """ if size == 5.0: - buffer = self.__buffers[self.__current][2] - elif size == 12.0: buffer = self.__buffers[self.__current][3] + elif size == 12.0: + buffer = self.__buffers[self.__current][4] else: raise ValueError("Unsupported point size: %.2f. Only 5.0 or 12.0 are supported!" % size) diff --git a/addon/io_scs_tools/internals/persistent/file_load.py b/addon/io_scs_tools/internals/persistent/file_load.py index 8af30dab..3d2da9b0 100644 --- a/addon/io_scs_tools/internals/persistent/file_load.py +++ b/addon/io_scs_tools/internals/persistent/file_load.py @@ -124,11 +124,6 @@ def apply_fixes_for_0_6(): for scs_root in scs_roots: _looks.write_through(scs_root, material, texture_attr_str) - # 2. trigger update function for path reload and reload of possible missing textures - update_func = getattr(material.scs_props, "update_" + texture_attr_str, None) - if update_func: - update_func(material) - # ignore already properly set materials if _shader_presets.has_preset(material.scs_props.active_shader_preset_name): continue @@ -157,6 +152,11 @@ def apply_fixes_for_0_6(): for scs_root in scs_roots: _looks.write_through(scs_root, material, "active_shader_preset_name") + # 4. reload all materials once all corrections to materials has been done + override = bpy.context.copy() + override["window"] = bpy.data.window_managers[0].windows[0] + bpy.ops.material.scs_tools_reload_materials(override, 'INVOKE_DEFAULT') + def apply_fixes_for_1_4(): """ @@ -168,7 +168,9 @@ def apply_fixes_for_1_4(): print("INFO\t- Applying fixes for version <= 1.4") # 1. reload all materials - bpy.ops.material.scs_tools_reload_materials('INVOKE_DEFAULT') + override = bpy.context.copy() + override["window"] = bpy.data.window_managers[0].windows[0] + bpy.ops.material.scs_tools_reload_materials(override, 'INVOKE_DEFAULT') # 2. remove all obsolete ".scs_nmap_" + str(i) materials, as of 2.78 we are using new normal maps node i = 1 diff --git a/addon/io_scs_tools/internals/preview_models/__init__.py b/addon/io_scs_tools/internals/preview_models/__init__.py index a11bef0d..f08d803d 100644 --- a/addon/io_scs_tools/internals/preview_models/__init__.py +++ b/addon/io_scs_tools/internals/preview_models/__init__.py @@ -24,6 +24,7 @@ from io_scs_tools.internals.preview_models.cache import PrevModelsCache from io_scs_tools.consts import Material as _MAT_consts from io_scs_tools.consts import Colors as _COL_consts +from io_scs_tools.imp import pim as _pim_import from io_scs_tools.utils import path as _path_utils from io_scs_tools.utils.printout import lprint from io_scs_tools.utils import get_scs_globals as _get_scs_globals @@ -144,9 +145,11 @@ def load(locator, deep_reload=False): # we need to load preview model, if old mesh is not found or deep reload is requested if not old_mesh or deep_reload: - from io_scs_tools.imp import pim as _pim_import + scs_globals = _get_scs_globals() + scs_globals.import_in_progress = True obj = _pim_import.load_pim_file(bpy.context, abs_filepath, preview_model=True) + scs_globals.import_in_progress = False # in case used preview model doesn't have any mesh, abort loading, report error and reset path # Path has to be reset to prevent loading preview model over and over again @@ -193,6 +196,7 @@ def load(locator, deep_reload=False): prev_model_name = _cache.get_entry(locator.name) if prev_model_name and prev_model_name in bpy.data.objects: prev_model = bpy.data.objects[prev_model_name] + prev_model.data = old_mesh else: prev_model = bpy.data.objects.new(name=prem_name, object_data=old_mesh) diff --git a/addon/io_scs_tools/operators/bases/export.py b/addon/io_scs_tools/operators/bases/export.py index 2952ee3f..67e0c45c 100644 --- a/addon/io_scs_tools/operators/bases/export.py +++ b/addon/io_scs_tools/operators/bases/export.py @@ -127,13 +127,15 @@ def finish(self): bpy.data.scenes.remove(self.scene) self.scene = None - def execute_export(self, context, without_preview): + def execute_export(self, context, without_preview, menu_filepath=None): """Executes export. :param context: operator context :type context: bpy_struct :param without_preview: is export run without preview? :type without_preview: bool + :param menu_filepath: filepath used from menu export, if not provided export is done to none menu set path + :type menu_filepath: str :return: success of batch export :rtype: {'FINISHED'} | {'CANCELLED'} """ @@ -150,7 +152,7 @@ def execute_export(self, context, without_preview): ef_name_suffix = ".ef" try: - result = _export.batch_export(self, init_obj_list, name_suffix=ef_name_suffix) + result = _export.batch_export(self, init_obj_list, name_suffix=ef_name_suffix, menu_filepath=menu_filepath) except Exception as e: result = {"CANCELLED"} diff --git a/addon/io_scs_tools/operators/material.py b/addon/io_scs_tools/operators/material.py index 2279e27a..3ea1eceb 100644 --- a/addon/io_scs_tools/operators/material.py +++ b/addon/io_scs_tools/operators/material.py @@ -347,6 +347,7 @@ def merge_materials(self, mats_to_merge, base_mat_look_entries=None): if base_mat_look_entries: mat_look_entries = _looks.get_material_entries(root_obj, mat) if base_mat_look_entries[base_mat] != mat_look_entries: + lprint("W Looks of %r on object %r don't match with base material, material merge skipped!" % (mat.name, obj.name)) continue # ressign material @@ -482,22 +483,29 @@ def execute(self, context): for mat in unmergable_base_mats: del mats_to_merge[mat.name] + # take care of materials without linkage to objects, + # should be treated as mergable as no look entries for it exists. + for mat_name in mats_to_merge: + mat = bpy.data.materials[mat_name] + if mat not in mergable_base_mats: + mergable_base_mats[mat] = _looks.get_material_entries(None, mat) + # report unmergable if len(mats_to_merge) == 0 and len(unmergable_base_mats) > 0: - msg = ("No materials merging can be done. Found %i material candidates, " + msg = ("No materials merging can be done. Found %i base material candidates, " "however they are used on multiple SCS Root objects with different looks setup!") % len(unmergable_base_mats) self.report({'WARNING'}, msg) lprint("W " + msg, report_warnings=1) return {'CANCELLED'} elif len(unmergable_base_mats) > 0: - msg = "W Due to different looks settings on multiple SCS Root objects, following materials are unmergable:\n\t " + msg = "W Due to different looks settings on multiple SCS Root objects, following base materials are unmergable:\n\t " for i, mat in enumerate(unmergable_base_mats): msg += str(i + 1) + ". '" + mat.name + "'\n\t " lprint(msg.strip("\n\t ")) # now merge by name & effect & attributes and finish if self.merge_type == self.BY_NEA: - self.merge_materials(mats_to_merge, mergable_base_mats) + self.merge_materials(mats_to_merge, base_mat_look_entries=mergable_base_mats) lprint("", report_warnings=1) return {'FINISHED'} diff --git a/addon/io_scs_tools/utils/material.py b/addon/io_scs_tools/utils/material.py index 4cdfeb8d..a0b52150 100644 --- a/addon/io_scs_tools/utils/material.py +++ b/addon/io_scs_tools/utils/material.py @@ -188,7 +188,7 @@ def get_reflection_image(texture_path, report_invalid=False): abs_texture_filepaths = _path.get_texture_paths_from_tobj(abs_tobj_filepath) # should be a cubemap with six images - if len(abs_texture_filepaths) != 6: + if not abs_texture_filepaths or len(abs_texture_filepaths) != 6: return None # all six images have to exist @@ -784,27 +784,31 @@ def set_texture_settings_to_node(tex_node, settings): :type settings: str """ + # addr - repeating + if settings[2] == "1" and settings[3] == "1": + tex_node.extension = "REPEAT" + else: + tex_node.extension = "EXTEND" + image = tex_node.image + # image settings can't be done without image object thus end here + if not image: + return + # linear colorspace - if settings[0] == "1" and image: + if settings[0] == "1": image.colorspace_settings.name = "Linear" else: image.colorspace_settings.name = "sRGB" # tsnormal option - if settings[1] == "1" and image: + if settings[1] == "1": if image.filepath[-4:] in (".tga", ".dds"): image.colorspace_settings.name = "Non-Color" elif image.filepath[-4:] == ".png" and image.is_float: image.colorspace_settings.name = "Linear" - # addr - if settings[2] == "1" and settings[3] == "1": - tex_node.extension = "REPEAT" - else: - tex_node.extension = "EXTEND" - def has_valid_color_management(scene): """Gets validity of color management for rendering SCS object.