From e93499db2ffc93f41d7374004f002b5b0813e1ad Mon Sep 17 00:00:00 2001 From: lijenstina Date: Sat, 15 Jul 2017 08:55:54 +0200 Subject: Fix T51618: Add a warning message override, poll check Bumped version to 1.0.2 Add a poll for the bpy.app.path is not an empty string that can happen if the file is not saved Add and override to the warning_messages that will allow to show up the message no matter what the setting is Small UI fixes --- materials_utils/__init__.py | 196 ++++++++++++-------------- materials_utils/material_converter.py | 77 +++++----- materials_utils/materials_cycles_converter.py | 47 +++--- materials_utils/texture_rename.py | 16 +-- materials_utils/warning_messages_utils.py | 19 ++- 5 files changed, 181 insertions(+), 174 deletions(-) (limited to 'materials_utils') diff --git a/materials_utils/__init__.py b/materials_utils/__init__.py index 09342408..c001a882 100644 --- a/materials_utils/__init__.py +++ b/materials_utils/__init__.py @@ -15,24 +15,24 @@ # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # ##### END GPL LICENSE BLOCK ##### + # (c) 2016 meta-androcto, parts based on work by Saidenka, lijenstina -# Materials Utils: by MichaleW, lijenstina, -# (some code thanks to: CoDEmanX, SynaGl0w, -# ideasman42) -# Materials Conversion: Silvio Falcinelli, johnzero7#, -# fixes by angavrilov and others -# Link to base names: Sybren, Texture renamer: Yadoob +# Materials Utils: by MichaleW, lijenstina, +# (some code thanks to: CoDEmanX, SynaGl0w, ideasman42) +# Materials Conversion: Silvio Falcinelli, johnzero7#, +# fixes by angavrilov and others +# Link to base names: Sybren, Texture renamer: Yadoob bl_info = { "name": "Materials Utils Specials", "author": "Community", - "version": (1, 0, 1), + "version": (1, 0, 2), "blender": (2, 77, 0), - "location": "Materials Properties Specials/Shift Q", - "description": "Materials Utils & Convertors", + "location": "Materials Properties Specials > Shift Q", + "description": "Materials Utils and Convertors", "warning": "", - "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/3D_interaction/Materials_Utils", - "tracker_url": "", + "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/" + "Scripts/3D_interaction/Materials_Utils", "category": "Material" } @@ -51,29 +51,30 @@ else: import bpy import os from os import ( - path as os_path, - access as os_access, - remove as os_remove, - ) + path as os_path, + access as os_access, + remove as os_remove, + ) from bpy.props import ( - StringProperty, - BoolProperty, - EnumProperty, - ) + StringProperty, + BoolProperty, + EnumProperty, + PointerProperty, + ) from bpy.types import ( - Menu, - Operator, - Panel, - AddonPreferences, - PropertyGroup, - ) + Menu, + Operator, + Panel, + AddonPreferences, + PropertyGroup, + ) from .warning_messages_utils import ( - warning_messages, - c_data_has_materials, - ) + warning_messages, + c_data_has_materials, + ) -# Functions # +# Functions def fake_user_set(fake_user='ON', materials='UNUSED', operator=None): warn_mesg, w_mesg = '', "" @@ -420,8 +421,7 @@ def cleanmatslots(operator=None): bpy.ops.object.mode_set(mode='EDIT') -# separate edit mode mesh function -# (faster than iterating through all faces) +# separate edit mode mesh function (faster than iterating through all faces) def assign_mat_mesh_edit(matname="Default", operator=None): actob = bpy.context.active_object @@ -733,8 +733,7 @@ def remove_materials_all(operator=None): class VIEW3D_OT_show_mat_preview(Operator): bl_label = "Preview Active Material" bl_idname = "view3d.show_mat_preview" - bl_description = ("Show the preview of Active Material \n" - "and context related settings") + bl_description = "Show the preview of Active Material and context related settings" bl_options = {'REGISTER', 'UNDO'} is_not_undo = False # prevent drawing props on undo @@ -1193,9 +1192,8 @@ class VIEW3D_OT_fake_user_set(Operator): class MATERIAL_OT_set_transparent_back_side(Operator): bl_idname = "material.set_transparent_back_side" bl_label = "Transparent back (BI)" - bl_description = ("Creates BI nodes with Alpha output connected to" - "Front/Back Geometry node \n" - "on Object's Active Material Slot") + bl_description = ("Creates BI nodes with Alpha output connected to Front/Back\n" + "Geometry node on Object's Active Material Slot") bl_options = {'REGISTER', 'UNDO'} @classmethod @@ -1346,8 +1344,7 @@ class MATERIAL_OT_link_to_base_names(Operator): return context.window_manager.invoke_props_dialog(self) def replace_name(self): - # use the chosen material as a base one - # check if there is a name + # use the chosen material as a base one, check if there is a name self.check_no_name = (False if self.mat_keep in {""} else True) if self.check_no_name is True: @@ -1356,7 +1353,7 @@ class MATERIAL_OT_link_to_base_names(Operator): if name == self.mat_keep: try: base, suffix = name.rsplit('.', 1) - # trigger the except + # trigger the exception num = int(suffix, 10) self.mat_keep = base mat.name = self.mat_keep @@ -1376,7 +1373,7 @@ class MATERIAL_OT_link_to_base_names(Operator): base, suffix = name.rsplit('.', 1) try: - # trigger the except + # trigger the exception num = int(suffix, 10) except ValueError: # Not a numeric suffix @@ -1442,18 +1439,17 @@ class MATERIAL_OT_link_to_base_names(Operator): class MATERIAL_OT_check_converter_path(Operator): bl_idname = "material.check_converter_path" bl_label = "Check Converters images/data save path" - bl_description = ("Checks if the given path is writeable \n" - "(has OS writing privileges)") + bl_description = "Check if the given path is writeable (has OS writing privileges)" bl_options = {'REGISTER', 'INTERNAL'} - @classmethod - def poll(cls, context): - return True - def check_valid_path(self, context): sc = context.scene paths = bpy.path.abspath(sc.mat_specials.conv_path) + if bpy.data.filepath == "": + warning_messages(self, "DIR_PATH_EMPTY", override=True) + return False + if os_path.exists(paths): if os_access(paths, os.W_OK | os.X_OK): try: @@ -1463,13 +1459,13 @@ class MATERIAL_OT_check_converter_path(Operator): os_remove(path_test) return True except (OSError, IOError): - warning_messages(self, 'DIR_PATH_W_ERROR') + warning_messages(self, 'DIR_PATH_W_ERROR', override=True) return False else: - warning_messages(self, 'DIR_PATH_A_ERROR') + warning_messages(self, 'DIR_PATH_A_ERROR', override=True) return False else: - warning_messages(self, 'DIR_PATH_N_ERROR') + warning_messages(self, 'DIR_PATH_N_ERROR', override=True) return False return True @@ -1477,13 +1473,13 @@ class MATERIAL_OT_check_converter_path(Operator): def execute(self, context): if not self.check_valid_path(context): return {'CANCELLED'} - else: - warning_messages(self, 'DIR_PATH_W_OK') + + warning_messages(self, 'DIR_PATH_W_OK', override=True) return {'FINISHED'} -# Menu classes # +# Menu classes class VIEW3D_MT_assign_material(Menu): bl_label = "Assign Material" @@ -1759,19 +1755,17 @@ class MATERIAL_PT_scenemassive(Panel): text="Convert All to Cycles", icon='MATERIAL') split.operator("ml.refresh_active", text="Convert Active to Cycles", icon='MATERIAL') - box = box.box() - ml_restore = box.operator("ml.restore", - text="To BI Nodes Off", + row = box.row() + ml_restore = row.operator("ml.restore", text="To BI Nodes Off", icon='MATERIAL') ml_restore.switcher = False ml_restore.renderer = "BI" - row = layout.row() - box = row.box() - box.menu("scenemassive.opt", text="Advanced Options", icon='SCRIPTWIN') - box = row.box() - box.menu("help.biconvert", - text="Usage Information Guide", icon='MOD_EXPLODE') + box = layout.box() + row = box.row() + row.menu("scenemassive.opt", text="Advanced Options", icon='SCRIPTWIN') + row.menu("help.biconvert", + text="Usage Information Guide", icon="INFO") box = layout.box() box.label("Save Directory") @@ -1804,18 +1798,15 @@ class MATERIAL_PT_xps_convert(Panel): split.operator("xps_tools.convert_to_cycles_selected", text="Convert Selected to Nodes", icon="TEXTURE") - col = layout.column() - row = col.row() - box = row.box() - ml_restore = box.operator("ml.restore", - text="To BI Nodes ON", + box = layout.box() + row = box.row() + ml_restore = row.operator("ml.restore", text="To BI Nodes ON", icon='MATERIAL') ml_restore.switcher = True ml_restore.renderer = "BI" - box = row.box() - box.menu("help.nodeconvert", - text="Usage Information Guide", icon="MOD_EXPLODE") + row.menu("help.nodeconvert", + text="Usage Information Guide", icon="INFO") # Converters Help # @@ -1891,7 +1882,7 @@ class MATERIAL_MT_nodeconv_help(Menu): layout.label(text="Convert Materials/Image Textures from Imports:", icon="INFO") -# Make Report # +# Make Report class material_converter_report(Operator): bl_idname = "mat_converter.reports" bl_label = "Material Converter Report" @@ -1902,14 +1893,12 @@ class material_converter_report(Operator): def draw(self, context): layout = self.layout - box = layout.box() - - box.label(text="Converter Report", icon='INFO') + layout.label(text="Information:", icon='INFO') if self.message and type(self.message) is str: list_string = self.message.split("*") for line in range(len(list_string)): - box.label(text=str(list_string[line])) + layout.label(text=str(list_string[line])) def invoke(self, context, event): return context.window_manager.invoke_props_dialog(self, width=500) @@ -1919,7 +1908,6 @@ class material_converter_report(Operator): # Scene Properties - class material_specials_scene_props(PropertyGroup): conv_path = StringProperty( name="Save Directory", @@ -1990,7 +1978,6 @@ class material_specials_scene_props(PropertyGroup): # Addon Preferences - class VIEW3D_MT_material_utils_pref(AddonPreferences): bl_idname = __name__ @@ -2004,10 +1991,9 @@ class VIEW3D_MT_material_utils_pref(AddonPreferences): show_remove_mat = BoolProperty( name="Enable Remove all Materials", default=False, - description="Enable Remove all Materials \n" - "for all Selected Objects \n \n" - "Use with care - if you want to keep materials after \n" - "closing \ reloading Blender Set Fake User for them", + description="Enable Remove all Materials for all Selected Objects\n\n" + "Use with care - if you want to keep materials after\n" + "closing or reloading Blender, Set Fake User for them", ) show_mat_preview = BoolProperty( name="Enable Material Preview", @@ -2034,7 +2020,7 @@ class VIEW3D_MT_material_utils_pref(AddonPreferences): ) show_converters = BoolProperty( name="Enable Converters", - default=True, + default=False, description="Enable Material Converters", ) set_preview_size = EnumProperty( @@ -2056,13 +2042,12 @@ class VIEW3D_MT_material_utils_pref(AddonPreferences): name="Preview Menu Type", description="Set the the Preview menu type", items=(('LIST', "Classic", - "Display as a Classic List like in Blender Propreties. \n \n" - "Preview of Active Material not available"), + "Display as a Classic List like in Blender Propreties.\n" + "Preview of Active Material is not available"), ('PREVIEW', "Preview Display", - "Display as a preview of Thumbnails \n" - "It can have some performance issues with \n" - "scenes containing a lot of materials \n \n" - "Preview of Active Material available")), + "Display as a preview of Thumbnails\n" + "It can have some performance issues with scenes containing a lot of materials\n" + "Preview of Active Material is available")), default='PREVIEW', ) set_experimental_type = EnumProperty( @@ -2101,21 +2086,22 @@ class VIEW3D_MT_material_utils_pref(AddonPreferences): col.prop(self, "show_separators") boxie = box.box() - row = boxie.row() - row.prop(self, "show_mat_preview") - rowsy = row.split(align=True) - rowsy.enabled = True if self.show_mat_preview else False - rowsy.prop(self, "set_preview_type", expand=True) - rowsa = boxie.row(align=True) - rowsa.enabled = True if self.set_preview_type in {'PREVIEW'} else False - rowsa.prop(self, "set_preview_size", expand=True) + split = boxie.split(percentage=0.3) + split.prop(self, "show_mat_preview") + if self.show_mat_preview: + rowsy = split.row(align=True) + rowsy.enabled = True if self.show_mat_preview else False + rowsy.prop(self, "set_preview_type", expand=True) + rowsa = boxie.row(align=True) + rowsa.enabled = True if self.set_preview_type in {'PREVIEW'} else False + rowsa.prop(self, "set_preview_size", expand=True) boxif = box.box() - rowf = boxif.row() - rowf.prop(self, "show_converters") - rowsf = rowf.split() - rowsf.enabled = True if self.show_converters else False - rowsf.prop(self, "set_experimental_type", expand=True) + split = boxif.split(percentage=0.3) + split.prop(self, "show_converters") + if self.show_converters: + rowe = split.row(align=True) + rowe.prop(self, "set_experimental_type", expand=True) # utility functions: @@ -2224,7 +2210,7 @@ def c_need_of_viewport_colors(): return False -# Draw Separator # +# Draw Separator def use_separator(operator, context): # pass the preferences show_separators bool to enable/disable them pref = return_preferences() @@ -2233,7 +2219,7 @@ def use_separator(operator, context): operator.layout.separator() -# preferences utilities # +# preferences utilities def return_preferences(): return bpy.context.user_preferences.addons[__name__].preferences @@ -2299,9 +2285,9 @@ def register(): warning_messages_utils.MAT_SPEC_NAME = __name__ # Register Scene Properties - bpy.types.Scene.mat_specials = bpy.props.PointerProperty( - type=material_specials_scene_props - ) + bpy.types.Scene.mat_specials = PointerProperty( + type=material_specials_scene_props + ) kc = bpy.context.window_manager.keyconfigs.addon if kc: diff --git a/materials_utils/material_converter.py b/materials_utils/material_converter.py index 86e6ada7..dfde5c50 100644 --- a/materials_utils/material_converter.py +++ b/materials_utils/material_converter.py @@ -1,18 +1,17 @@ # -*- coding: utf-8 -*- import bpy -import mathutils from mathutils import Vector from bpy.types import Operator from .warning_messages_utils import ( - warning_messages, - c_is_cycles_addon_enabled, - c_data_has_materials, - collect_report, - ) + warning_messages, + c_is_cycles_addon_enabled, + c_data_has_materials, + collect_report, + ) # ----------------------------------------------------------------------------- -# Globals # +# Globals nodesDictionary = None @@ -39,7 +38,7 @@ textureNodeSizeY = 350 # ----------------------------------------------------------------------------- -# Functions # +# Functions def makeTextureNodeDict(cmat): global nodesDictionary @@ -155,11 +154,11 @@ def replaceNode(oldNode, newNode): newNode.location = oldNode.location try: for link in oldNode.outputs['BSDF'].links: - links.new(newNode.outputs['BSDF'], link.to_socket) + link.new(newNode.outputs['BSDF'], link.to_socket) for link in oldNode.inputs['Color'].links: - links.new(newNode.inputs['Color'], link.from_socket) + link.new(newNode.inputs['Color'], link.from_socket) for link in oldNode.inputs['Normal'].links: - links.new(newNode.inputs['Normal'], link.from_socket) + link.new(newNode.inputs['Normal'], link.from_socket) except: collect_report("ERROR: Failure to replace node") @@ -252,8 +251,10 @@ def createDiffuseNodes(cmat, texCoordNode, mainShader, materialOutput): mixRgbNode.parent = diffuseFrame addRGBMixNode(TreeNodes, textureSlot, mixRgbNode, texNode, latestNode, '{}'.format(groupName), textureIdx) - mixRgbNode.location = Vector((max(texNode.location.x, latestNode.location.x), - (texNode.location.y + latestNode.location.y) / 2)) + Vector((200, 0)) + mixRgbNode.location = Vector( + (max(texNode.location.x, latestNode.location.x), + (texNode.location.y + latestNode.location.y) / 2)) + Vector((200, 0) + ) latestNode = mixRgbNode except: continue @@ -325,7 +326,8 @@ def createNormalNodes(cmat, texCoordNode, mainShader, materialOutput): tex_node_name = getattr(texNode.image, "name", "") collect_report("INFO: Generating Normal Nodes for: " + tex_node_name) texNode.parent = normalFrame - placeNode(texNode, -500 - ((texCount) * 200), currPosY, textureNodeSizeX, textureNodeSizeY, 0, textureIdx) + placeNode(texNode, -500 - ((texCount) * 200), currPosY, + textureNodeSizeX, textureNodeSizeY, 0, textureIdx) # Add mapping node normalMapping = TreeNodes.nodes.new(MAPPING_NODE) @@ -364,8 +366,10 @@ def createNormalNodes(cmat, texCoordNode, mainShader, materialOutput): mixRgbNode.parent = normalFrame addRGBMixNode(TreeNodes, textureSlot, mixRgbNode, texNode, latestNode, '{}'.format(groupName), textureIdx) - mixRgbNode.location = Vector((max(texNode.location.x, latestNode.location.x), - (texNode.location.y + latestNode.location.y) / 2)) + Vector((200, 0)) + mixRgbNode.location = Vector( + (max(texNode.location.x, latestNode.location.x), + (texNode.location.y + latestNode.location.y) / 2)) + Vector((200, 0) + ) latestNode = mixRgbNode except: continue @@ -401,7 +405,8 @@ def createSpecularNodes(cmat, texCoordNode, mainShader, mainDiffuse, materialOut tex_node_name = getattr(texNode.image, "name", "") collect_report("INFO: Generating {} Nodes for: ".format(groupName) + tex_node_name) texNode.parent = specularFrame - placeNode(texNode, -500 - ((texCount) * 200), currPosY, textureNodeSizeX, textureNodeSizeY, 0, textureIdx) + placeNode(texNode, -500 - ((texCount) * 200), + currPosY, textureNodeSizeX, textureNodeSizeY, 0, textureIdx) # Add mapping node specularMapping = TreeNodes.nodes.new(MAPPING_NODE) @@ -439,8 +444,10 @@ def createSpecularNodes(cmat, texCoordNode, mainShader, mainDiffuse, materialOut mixRgbNode.parent = specularFrame addRGBMixNode(TreeNodes, textureSlot, mixRgbNode, texNode, latestNode, '{}'.format(groupName), textureIdx) - mixRgbNode.location = Vector((max(texNode.location.x, latestNode.location.x), - (texNode.location.y + latestNode.location.y) / 2)) + Vector((200, 0)) + mixRgbNode.location = Vector( + (max(texNode.location.x, latestNode.location.x), + (texNode.location.y + latestNode.location.y) / 2)) + Vector((200, 0) + ) latestNode = mixRgbNode except: continue @@ -505,7 +512,8 @@ def createEmissionNodes(cmat, texCoordNode, mainShader, materialOutput): tex_node_name = getattr(texNode.image, "name", "") collect_report("INFO: Generating {} Nodes for: ".format(groupName) + tex_node_name) texNode.parent = emissionFrame - placeNode(texNode, -500 - ((texCount) * 200), currPosY, textureNodeSizeX, textureNodeSizeY, 0, textureIdx) + placeNode(texNode, -500 - ((texCount) * 200), currPosY, + textureNodeSizeX, textureNodeSizeY, 0, textureIdx) # Add mapping node emissionMapping = TreeNodes.nodes.new(MAPPING_NODE) @@ -544,8 +552,10 @@ def createEmissionNodes(cmat, texCoordNode, mainShader, materialOutput): mixRgbNode.parent = emissionFrame addRGBMixNode(TreeNodes, textureSlot, mixRgbNode, texNode, latestNode, '{}'.format(groupName), textureIdx) - mixRgbNode.location = Vector((max(texNode.location.x, latestNode.location.x), - (texNode.location.y + latestNode.location.y) / 2)) + Vector((200, 0)) + mixRgbNode.location = Vector( + (max(texNode.location.x, latestNode.location.x), + (texNode.location.y + latestNode.location.y) / 2)) + Vector((200, 0) + ) latestNode = mixRgbNode except: continue @@ -604,9 +614,9 @@ def AutoNode(active=False, operator=None): if not materials: if operator: if active: - warning_messages(operator, 'CONV_NO_SEL_MAT') + warning_messages(operator, 'CONV_NO_SEL_MAT', override=True) else: - warning_messages(operator, 'CONV_NO_SC_MAT') + warning_messages(operator, 'CONV_NO_SC_MAT', override=True) return for cmat in materials: @@ -649,7 +659,6 @@ def makeCyclesFromBI(cmat): cmat_mirror = cmat.raytrace_mirror.use cmat_mirror_fac = cmat.raytrace_mirror.reflect_factor - # -------------------------------------- # Material Shaders # Diffuse nodes # -------------------------------------- @@ -727,17 +736,19 @@ def makeCyclesFromBI(cmat): # ----------------------------------------------------------------------------- -# Operator Classes # +# Operator Classes class material_convert_all(Operator): bl_idname = "xps_tools.convert_to_cycles_all" bl_label = "Convert All Materials" - bl_description = "Convert All Materials to BI and Cycles Nodes" + bl_description = ("Convert All Materials to BI and Cycles Nodes\n" + "Needs saving the .blend file first") bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): - return (c_is_cycles_addon_enabled() and c_data_has_materials()) + return (bpy.data.filepath != "" and c_is_cycles_addon_enabled() and + c_data_has_materials()) def execute(self, context): AutoNode(False, self) @@ -747,14 +758,15 @@ class material_convert_all(Operator): class material_convert_selected(Operator): bl_idname = "xps_tools.convert_to_cycles_selected" bl_label = "Convert All Materials From Selected Objects" - bl_description = "Convert All Materials on Selected Objects to BI and Cycles Nodes" + bl_description = ("Convert All Materials on Selected Objects to BI and Cycles Nodes\n" + "Needs saving the .blend file first") bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): - return (c_data_has_materials() and c_is_cycles_addon_enabled() and - bool( - next((obj for obj in context.selected_objects if obj.type == 'MESH'), + return (bpy.data.filepath != "" and c_data_has_materials() and + c_is_cycles_addon_enabled() and + bool(next((obj for obj in context.selected_objects if obj.type == 'MESH'), None) ) ) @@ -773,5 +785,6 @@ def unregister(): bpy.utils.unregister_module(__name__) pass + if __name__ == "__main__": register() diff --git a/materials_utils/materials_cycles_converter.py b/materials_utils/materials_cycles_converter.py index 55c57ba7..c9dd994d 100644 --- a/materials_utils/materials_cycles_converter.py +++ b/materials_utils/materials_cycles_converter.py @@ -5,22 +5,22 @@ import bpy from os import path as os_path from bpy.types import Operator -from math import (log2, - ceil, - ) +from math import ( + log2, ceil, + ) from bpy.props import ( - BoolProperty, - EnumProperty, - ) + BoolProperty, + EnumProperty, + ) from .warning_messages_utils import ( - warning_messages, - c_is_cycles_addon_enabled, - c_data_has_materials, - collect_report, - ) + warning_messages, + c_is_cycles_addon_enabled, + c_data_has_materials, + collect_report, + ) # ----------------------------------------------------------------------------- -# Globals # +# Globals # switch for operator's function called after AutoNodeInitiate CHECK_AUTONODE = False @@ -37,7 +37,7 @@ PAINT_SC_COLOR = (0.80, 0.75, 0.54, 0.9) CLAY_GLOSSY = (0.38, 0.032, 0.023, 1) # ----------------------------------------------------------------------------- -# Functions # +# Functions def AutoNodeSwitch(renderer="CYCLES", switch="OFF", operator=None): @@ -130,8 +130,7 @@ def BakingText(tex, mode, tex_type=None): img = bpy.data.images.get("TMP_BAKING") img.file_format = ("JPEG" if not mode == "ALPHA" else "PNG") - # switch temporarly to 'IMAGE EDITOR' - # other approaches are not reliable + # switch temporarly to 'IMAGE EDITOR', other approaches are not reliable check_area = False store_area = bpy.context.area.type collect_report("INFO: Temporarly switching context to Image Editor") @@ -211,7 +210,7 @@ def AutoNodeInitiate(active=False, operator=None): if sc.mat_specials.SET_FAKE_USER: SetFakeUserTex() else: - warning_messages(operator, 'DIR_PATH_CONVERT') + warning_messages(operator, 'DIR_PATH_CONVERT', override=True) def AutoNode(active=False, operator=None): @@ -850,7 +849,7 @@ def create_mix_node(TreeNodes, links, nodes, loc, start, median_point, row, fram # ----------------------------------------------------------------------------- -# Operator Classes # +# Operator Classes class mllock(Operator): bl_idname = "ml.lock" @@ -877,12 +876,14 @@ class mllock(Operator): class mlrefresh(Operator): bl_idname = "ml.refresh" bl_label = "Convert All Materials" - bl_description = "Convert All Materials in the scene from non-nodes to Cycles" + bl_description = ("Convert All Materials in the scene from non-nodes to Cycles\n" + "Needs saving the .blend file first") bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): - return (c_is_cycles_addon_enabled() and c_data_has_materials()) + return (bpy.data.filepath != ""and c_is_cycles_addon_enabled() and + c_data_has_materials()) def execute(self, context): AutoNodeInitiate(False, self) @@ -909,13 +910,14 @@ class mlrefresh(Operator): class mlrefresh_active(Operator): bl_idname = "ml.refresh_active" bl_label = "Convert All Materials From Active Object" - bl_description = "Convert all Active Object's Materials from non-nodes to Cycles" + bl_description = ("Convert all Active Object's Materials from non-nodes to Cycles\n" + "Needs saving the .blend file first") bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): - return (c_is_cycles_addon_enabled() and c_data_has_materials() and - context.active_object is not None) + return (bpy.data.filepath != "" and c_is_cycles_addon_enabled() and + c_data_has_materials() and context.active_object is not None) def execute(self, context): AutoNodeInitiate(True, self) @@ -978,5 +980,6 @@ def unregister(): bpy.utils.unregister_module(__name__) pass + if __name__ == "__main__": register() diff --git a/materials_utils/texture_rename.py b/materials_utils/texture_rename.py index ddea43cc..ac728b70 100644 --- a/materials_utils/texture_rename.py +++ b/materials_utils/texture_rename.py @@ -3,21 +3,20 @@ import bpy from bpy.types import ( - Operator, - Panel, - ) + Operator, + Panel, + ) from bpy.props import StringProperty from .warning_messages_utils import ( - warning_messages, - c_data_has_images, - ) + warning_messages, + c_data_has_images, + ) class TEXTURE_OT_patern_rename(Operator): bl_idname = "texture.patern_rename" bl_label = "Texture Renamer" - bl_description = ("Replace the Texture names pattern with \n" - "the attached Image ones. \n" + bl_description = ("Replace the Texture names pattern with the attached Image ones\n" "Works on all Textures (Including Brushes) \n \n" "The First field - the name pattern to replace \n" "The Second - searches for existing names \n") @@ -108,5 +107,6 @@ def unregister(): bpy.utils.unregister_module(__name__) pass + if __name__ == "__main__": register() diff --git a/materials_utils/warning_messages_utils.py b/materials_utils/warning_messages_utils.py index 7a7ab0de..2e5f3b69 100644 --- a/materials_utils/warning_messages_utils.py +++ b/materials_utils/warning_messages_utils.py @@ -12,19 +12,22 @@ MAT_SPEC_NAME = "materials_specials" COLLECT_REPORT = [] -# Functions # +# Functions -def warning_messages(operator=None, warn='DEFAULT', object_name="", is_mat=None, fake=""): +def warning_messages(operator=None, warn='DEFAULT', object_name="", is_mat=None, + fake="", override=False): # Enter warning messages to the message dictionary # warn - if nothing passed falls back to DEFAULT # a list of strings can be passed and concatenated in obj_name too # is_mat a switch to change to materials or textures for obj_name('MAT','TEX', 'FILE', None) # fake - optional string that can be passed # MAX_COUNT - max members of an list to be displayed + # override - important messages that should be enabled, no matter the setting # pass the show_warnings bool to enable/disable them addon = bpy.context.user_preferences.addons[MAT_SPEC_NAME] - show_warn = (addon.preferences.show_warnings if addon else False) + get_warn = addon.preferences.show_warnings if addon else False + show_warn = get_warn if override is False else override if show_warn and operator: obj_name = "" @@ -102,6 +105,7 @@ def warning_messages(operator=None, warn='DEFAULT', object_name="", is_mat=None, 'DIR_PATH_A_ERROR': "ERROR: Directory not accessible", 'DIR_PATH_W_OK': "Directory has writing privileges", 'DIR_PATH_CONVERT': "Conversion Cancelled. Problem with chosen Directory, check System Console", + 'DIR_PATH_EMPTY': "File Path is empty. Please save the .blend file first", 'MAT_LINK_ERROR': "{}{}".format(obj_name, "not be renamed or set as Base(s)"), 'MAT_LINK_NO_NAME': "No Base name given, No changes applied", 'MOVE_SLOT_UP': "{}{}".format(obj_name, "been moved on top of the stack"), @@ -122,6 +126,10 @@ def warning_messages(operator=None, warn='DEFAULT', object_name="", is_mat=None, print("\n** MATERIAL SPECIALS **: \n Full list for the Info message is: \n", ", ".join(object_name), "\n") + # restore settings if overriden + if override: + addon.preferences.show_warnings = get_warn + def collect_report(collection="", is_start=False, is_final=False): # collection passes a string for appending to COLLECT_REPORT global @@ -146,11 +154,8 @@ def collect_report(collection="", is_start=False, is_final=False): COLLECT_REPORT = [] -# utility functions: - def c_is_cycles_addon_enabled(): - # checks if Cycles is enabled - # thanks to ideasman42 + # checks if Cycles is enabled thanks to ideasman42 return ('cycles' in bpy.context.user_preferences.addons.keys()) -- cgit v1.2.3