diff --git a/materials_library_vx/__init__.py b/materials_library_vx/__init__.py index 01157def6da8069169cf70ef0aecb6fc19a206e2..17e3934e64860bd63820b0c01803984f6568c36d 100644 --- a/materials_library_vx/__init__.py +++ b/materials_library_vx/__init__.py @@ -19,16 +19,16 @@ # #####END GPL LICENSE BLOCK ##### bl_info = { - "name": "Material Library", - "author": "Mackraken (mackraken2023@hotmail.com)", - "version": (0, 5, 8), - "blender": (2, 80, 0), - "location": "Properties > Material", - "description": "Material Library VX", - "warning": "", - "wiki_url": "https://sites.google.com/site/aleonserra/home/scripts/matlib-vx", - "tracker_url": "", - "category": "Material"} + "name": "Material Library", + "author": "Mackraken (mackraken2023@hotmail.com)", + "version": (0, 5, 8), + "blender": (2, 80, 0), + "location": "Properties > Material", + "description": "Material Library VX", + "warning": "", + "wiki_url": "https://sites.google.com/site/aleonserra/home/scripts/matlib-vx", + "tracker_url": "", + "category": "Material"} import bpy @@ -52,100 +52,100 @@ dev = False matlib_path = os.path.dirname(__file__) if dev: - print (30*"-") - matlib_path = r"D:\Blender Foundation\Blender\2.72\scripts\addons\matlib" + print (30*"-") + matlib_path = r"D:\Blender Foundation\Blender\2.72\scripts\addons\matlib" ##debug print variables def dd(*args, dodir=False): - if dev: - if dodir: - print(dir(*args)) - print(*args) + if dev: + if dodir: + print(dir(*args)) + print(*args) #Regular Functions def winpath(path): - return path.replace("\\", "\\\\") + return path.replace("\\", "\\\\") def update_search_index(self, context): - search = self.search - for i, it in enumerate(self.materials): - if it.name==search: - self.mat_index = i - break + search = self.search + for i, it in enumerate(self.materials): + if it.name==search: + self.mat_index = i + break def check_path(path): - #isabs sometimes returns true on relpaths - if path and os.path.exists(path) and os.path.isfile(path) and os.path.isabs(path): - try: - if bpy.data.filepath and bpy.path.relpath(bpy.data.filepath) == bpy.path.relpath(path): - return False - except: - pass - #paths are on different drives. No problem then - return True - return False + #isabs sometimes returns true on relpaths + if path and os.path.exists(path) and os.path.isfile(path) and os.path.isabs(path): + try: + if bpy.data.filepath and bpy.path.relpath(bpy.data.filepath) == bpy.path.relpath(path): + return False + except: + pass + #paths are on different drives. No problem then + return True + return False def update_lib_index(self, context): - self.load_library() + self.load_library() def update_cat_index(self, context): - dd("cat index:", self.current_category, self.filter) + dd("cat index:", self.current_category, self.filter) - if self.filter: - self.filter = True + if self.filter: + self.filter = True def update_filter(self, context): - dd("filter:", self.filter, self.cat_index, self.current_category) -# index = self.cat_index -# -# if self.filter: -# cat = self.current_category -# else: -# cat = "" -# -# self.current_library.filter = cat - self.update_list() + dd("filter:", self.filter, self.cat_index, self.current_category) + # index = self.cat_index + # + # if self.filter: + # cat = self.current_category + # else: + # cat = "" + # + # self.current_library.filter = cat + self.update_list() def check_index(collection, index): - count = len(collection) - return count>0 and index<count and index>=0 + count = len(collection) + return count>0 and index<count and index>=0 def send_command(cmd, output="sendmat.py"): bin = winpath(bpy.app.binary_path) - scriptpath = winpath(os.path.join(matlib_path, output)) + scriptpath = winpath(os.path.join(bpy.app.tempdir, output)) with open(scriptpath, "w") as f: - f.write(cmd) + f.write(cmd) import subprocess if output == "createlib.py": - code = subprocess.call([bin, "-b", "-P", scriptpath]) + code = subprocess.call([bin, "-b", "-P", scriptpath]) else: - libpath = winpath(bpy.context.scene.matlib.current_library.path) - code = subprocess.call([bin, "-b", libpath, "-P", scriptpath]) + libpath = winpath(bpy.context.scene.matlib.current_library.path) + code = subprocess.call([bin, "-b", libpath, "-P", scriptpath]) #code returns 0 if ok, 1 if not return abs(code-1) def list_materials(path, sort=False): - list = [] - with bpy.data.libraries.load(path) as (data_from, data_to): - for mat in data_from.materials: - list.append(mat) + list = [] + with bpy.data.libraries.load(path) as (data_from, data_to): + for mat in data_from.materials: + list.append(mat) - if sort: list = sorted(list) - return list + if sort: list = sorted(list) + return list #category properties (none atm) class EmptyGroup(PropertyGroup): - pass + pass # bpy.utils.register_class(EmptyGroup) class matlibMaterials(PropertyGroup): - category: StringProperty() + category: StringProperty() # bpy.utils.register_class(matlibMaterials) #bpy.types.Scene.matlib_categories = CollectionProperty(type=EmptyGroup) @@ -153,17 +153,17 @@ class matlibMaterials(PropertyGroup): ### CATEGORIES class Categories(): - #cats = bpy.context.scene.matlib.categories + #cats = bpy.context.scene.matlib.categories - def __init__(self, cats): - self.cats = cats + def __init__(self, cats): + self.cats = cats - def save(self): - scn = bpy.context.scene - cats = set([cat.name for cat in self.cats]) - libpath = bpy.context.scene.matlib.current_library.path + def save(self): + scn = bpy.context.scene + cats = set([cat.name for cat in self.cats]) + libpath = bpy.context.scene.matlib.current_library.path - cmd = """ + cmd = """ print(30*"+") import bpy if not hasattr(bpy.context.scene, "matlib_categories"): @@ -175,19 +175,19 @@ cats = bpy.context.scene.matlib_categories for cat in cats: cats.remove(0) """ - for cat in cats: - cmd += """ + for cat in cats: + cmd += """ cat = cats.add() cat.name = "%s" """ % cat.capitalize() - cmd +=''' + cmd +=''' bpy.ops.wm.save_mainfile(filepath="%s", check_existing=False, compress=True)''' % winpath(libpath) - return send_command(cmd, "save_categories.py") + return send_command(cmd, "save_categories.py") - def read(self, pull=True): - #mandar a imprimir el listado - catfile = winpath(os.path.join(matlib_path, "categories.txt")) - cmd = """ + def read(self, pull=True): + #mandar a imprimir el listado + catfile = winpath(os.path.join(matlib_path, "categories.txt")) + cmd = """ import bpy, json class EmptyProps(bpy.types.PropertyGroup): pass @@ -203,61 +203,61 @@ for cat in bpy.context.scene.matlib_categories: with open("%s", "w") as f: f.write(json.dumps(cats, sort_keys=True, indent=4)) """ % catfile - if pull: send_command(cmd) + if pull: send_command(cmd) - #leer el fichero - with open(catfile, "r") as f: - cats = json.loads(f.read()) + #leer el fichero + with open(catfile, "r") as f: + cats = json.loads(f.read()) - dd(cats) + dd(cats) -# #refrescar categorias -# for cat in self.cats: -# self.cats.remove(0) -# -# for cat in cats: -# item = self.cats.add() -# item.name = cat -# - return cats - - def view(self): - for cat in self.cats: - dd(cat.name) - - def add(self, name): - if name and name not in [item.name for item in self.cats]: - name = name.strip().capitalize() - item = self.cats.add() - item.name = name - if self.save(): - dd(name, "added") - return True - else: - dd("duplicated?") + # #refrescar categorias + # for cat in self.cats: + # self.cats.remove(0) + # + # for cat in cats: + # item = self.cats.add() + # item.name = cat + # + return cats + + def view(self): + for cat in self.cats: + dd(cat.name) + + def add(self, name): + if name and name not in [item.name for item in self.cats]: + name = name.strip().capitalize() + item = self.cats.add() + item.name = name + if self.save(): + dd(name, "added") + return True + else: + dd("duplicated?") - def remove(self, index): - self.cats.remove(index) - self.save() + def remove(self, index): + self.cats.remove(index) + self.save() class Library(): - def __init__(self, matlib_path, name): - self.name = name - self.path = os.path.join(matlib_path, name) -# @property -# def default(self): -# return self.name == default_library + def __init__(self, matlib_path, name): + self.name = name + self.path = os.path.join(matlib_path, name) + # @property + # def default(self): + # return self.name == default_library - @property - def shortname(self): -# if self.default: -# return "Default Library" - return bpy.path.display_name(self.name).title() + @property + def shortname(self): + # if self.default: + # return "Default Library" + return bpy.path.display_name(self.name).title() - def __repr__(self): - return str(type(self).__name__) + "('" + self.name + "')" + def __repr__(self): + return str(type(self).__name__) + "('" + self.name + "')" #bpy.utils.register_class(Library) @@ -280,184 +280,184 @@ libraries = [] ### MATLIB CLASS class matlibProperties(PropertyGroup): - #MATLIB PROPERTIES - - #libraries are read from the xml - lib_index: IntProperty(min = -1, default = 2, update=update_lib_index) - all_materials: CollectionProperty(type = matlibMaterials) - materials: CollectionProperty(type = matlibMaterials) - mat_index: IntProperty(min = -1, default = -1) - categories: CollectionProperty(type = EmptyGroup) - cat_index: IntProperty(min = -1, default = -1, update=update_cat_index) - search: StringProperty(name="Search", description="Find By Name", update=update_search_index) - - #MATLIB OPTIONS - #link: import material linked - #force import: - # if disable it wont import a material if its present in the scene,(avoid duplicates) - # instead it will apply the scene material rather than importing the same one from the library - #filter: enable or disable category filter - #last selected: store the last selected object to regain focus when apply a material. - #hide_search: Hides Search Field - link: BoolProperty(name = "Linked", description="Link the material", default = False) - force_import: BoolProperty(name = "Force Import", description="Use Scene Materials by default", default = False) - filter: BoolProperty(name = "Filter",description="Filter Categories", default = False, update=update_filter) - show_prefs: BoolProperty(name = "show_prefs", description="Preferences", default = False) - last_selected: StringProperty(name="Last Selected") - hide_search: BoolProperty(name="Hide Search", description="Use Blender Search Only") - #import_file = StringProperty("Import File", subtype="FILE_PATH") - #path = os.path.dirname(path) - #Development only - - @property - def libraries(self): - global libraries - return libraries - - @property - def current_library(self): - if check_index(libraries, self.lib_index): - return libraries[self.lib_index] - @property - def active_material(self): - if check_index(self.materials, self.mat_index): - return self.materials[self.mat_index] - - def reload(self): - dd("loading libraries") - - if self.current_library: - self.load_library() - elif self.lib_index == -1 and len(libraries): - self.lib_index = 0 - - - def add_library(self, path, setEnabled = False): - #sanitize path - ext = os.path.extsep + "blend" - if not path.endswith(ext): - path += ext - - if check_path(path): -# if path == default_library: -# return 'ERROR', "Cannot add default library." - #if path in [lib.path for lib in self.libraries]: - return 'ERROR', "Library already exists." - else: - dd("Can't find " + path) - #create file - cmd = ''' + #MATLIB PROPERTIES + + #libraries are read from the xml + lib_index: IntProperty(min = -1, default = 2, update=update_lib_index) + all_materials: CollectionProperty(type = matlibMaterials) + materials: CollectionProperty(type = matlibMaterials) + mat_index: IntProperty(min = -1, default = -1) + categories: CollectionProperty(type = EmptyGroup) + cat_index: IntProperty(min = -1, default = -1, update=update_cat_index) + search: StringProperty(name="Search", description="Find By Name", update=update_search_index) + + #MATLIB OPTIONS + #link: import material linked + #force import: + # if disable it wont import a material if its present in the scene,(avoid duplicates) + # instead it will apply the scene material rather than importing the same one from the library + #filter: enable or disable category filter + #last selected: store the last selected object to regain focus when apply a material. + #hide_search: Hides Search Field + link: BoolProperty(name = "Linked", description="Link the material", default = False) + force_import: BoolProperty(name = "Force Import", description="Use Scene Materials by default", default = False) + filter: BoolProperty(name = "Filter",description="Filter Categories", default = False, update=update_filter) + show_prefs: BoolProperty(name = "show_prefs", description="Preferences", default = False) + last_selected: StringProperty(name="Last Selected") + hide_search: BoolProperty(name="Hide Search", description="Use Blender Search Only") + #import_file = StringProperty("Import File", subtype="FILE_PATH") + #path = os.path.dirname(path) + #Development only + + @property + def libraries(self): + global libraries + return libraries + + @property + def current_library(self): + if check_index(libraries, self.lib_index): + return libraries[self.lib_index] + + @property + def active_material(self): + if check_index(self.materials, self.mat_index): + return self.materials[self.mat_index] + + def reload(self): + dd("loading libraries") + if self.current_library: + self.load_library() + elif self.lib_index == -1 and len(libraries): + self.lib_index = 0 + + + def add_library(self, path, setEnabled = False): + #sanitize path + ext = os.path.extsep + "blend" + if not path.endswith(ext): + path += ext + + if check_path(path): + # if path == default_library: + # return 'ERROR', "Cannot add default library." + #if path in [lib.path for lib in self.libraries]: + return 'ERROR', "Library already exists." + else: + dd("Can't find " + path) + #create file + cmd = ''' import bpy bpy.ops.wm.save_mainfile(filepath="%s", check_existing=False, compress=True)''' % winpath(path) - if not (send_command(cmd, "createlib.py")): - return 'ERROR', "There was an error creating the file. Make sure you run Blender with admin rights." + if not (send_command(cmd, "createlib.py")): + return 'ERROR', "There was an error creating the file. Make sure you run Blender with admin rights." - #self.libraries = sorted(self.libraries, key=lambda lib: sortlibs(lib)) - dd("adding library", path) - global libraries - libraries = get_libraries() - return "INFO", "Library added" + #self.libraries = sorted(self.libraries, key=lambda lib: sortlibs(lib)) + dd("adding library", path) + global libraries + libraries = get_libraries() + return "INFO", "Library added" - def load_library(self): - self.empty_list(True) - if not self.current_library: - return 'ERROR', "Library not found!." + def load_library(self): + self.empty_list(True) + if not self.current_library: + return 'ERROR', "Library not found!." - path = self.current_library.path + path = self.current_library.path - dd("loading library", self.lib_index, path) + dd("loading library", self.lib_index, path) - if check_path(path): - self.filter = False - self.cat_index = -1 + if check_path(path): + self.filter = False + self.cat_index = -1 - categories = Categories(self.categories) - self.cats = categories.read(True) - self.load_categories() + categories = Categories(self.categories) + self.cats = categories.read(True) + self.load_categories() - for mat in self.all_materials: - self.all_materials.remove(0) + for mat in self.all_materials: + self.all_materials.remove(0) - for mat in list_materials(self.current_library.path, True): - item = self.all_materials.add() - item.name = mat - for cat in self.cats: - if mat in cat[1]: - item.category = cat[0] - break + for mat in list_materials(self.current_library.path, True): + item = self.all_materials.add() + item.name = mat + for cat in self.cats: + if mat in cat[1]: + item.category = cat[0] + break - self.update_list() - else: - return 'ERROR', "Library not found!." - - def update_list(self): - ### THIS HAS TO SORT - self.empty_list() - if self.current_library: - current_category = self.current_category - #sorteditems = sorted(self.all_materials, key=lambda x: x.name) - for mat in self.all_materials: - #print(current_category, mat.category) - if not self.filter or (self.filter and mat.category == current_category) or current_category == "": - item = self.materials.add() - item.name = mat.name - item.category = mat.category - - def empty_list(self, cats = False): - #self.mat_index = -1 - for it in self.materials: - self.materials.remove(0) - - if cats: - for c in self.categories: - self.categories.remove(0) - - ### CATEGORIES - @property - def current_category(self): - #print(self.mat_index) - if check_index(self.categories, self.cat_index): - return self.categories[self.cat_index].name - return "" - - def load_categories(self): - - for c in self.categories: - self.categories.remove(0) - - for c in self.cats: - cat = self.categories.add() - cat.name = c[0] - - def add_category(self, name): - if name: - name = name.strip().title() - dd("add category", name) - categories = Categories(self.categories) - - categories.add(name) - -# if lib: -# cat = xml.find("category", name, lib, create = True) -# self.load_categories() -# else: -# return 'ERROR', "Library not found" - def remove_category(self): - dd("removing category", self.current_category) - categories = Categories(self.categories) - categories.remove(self.cat_index) - - def set_category(self): - mat = self.active_material - #dd(lib, mat, self.current_category) - if mat: - #set mat to category - if self.cat_index>-1: - dd(self.current_category) - cat = self.current_category - if cat == self.all_materials[self.mat_index].category: - return - cmd = """ + self.update_list() + else: + return 'ERROR', "Library not found!." + + def update_list(self): + ### THIS HAS TO SORT + self.empty_list() + if self.current_library: + current_category = self.current_category + #sorteditems = sorted(self.all_materials, key=lambda x: x.name) + for mat in self.all_materials: + #print(current_category, mat.category) + if not self.filter or (self.filter and mat.category == current_category) or current_category == "": + item = self.materials.add() + item.name = mat.name + item.category = mat.category + + def empty_list(self, cats = False): + #self.mat_index = -1 + for it in self.materials: + self.materials.remove(0) + + if cats: + for c in self.categories: + self.categories.remove(0) + + ### CATEGORIES + @property + def current_category(self): + #print(self.mat_index) + if check_index(self.categories, self.cat_index): + return self.categories[self.cat_index].name + return "" + + def load_categories(self): + + for c in self.categories: + self.categories.remove(0) + + for c in self.cats: + cat = self.categories.add() + cat.name = c[0] + + def add_category(self, name): + if name: + name = name.strip().title() + dd("add category", name) + categories = Categories(self.categories) + + categories.add(name) + + # if lib: + # cat = xml.find("category", name, lib, create = True) + # self.load_categories() + # else: + # return 'ERROR', "Library not found" + def remove_category(self): + dd("removing category", self.current_category) + categories = Categories(self.categories) + categories.remove(self.cat_index) + + def set_category(self): + mat = self.active_material + #dd(lib, mat, self.current_category) + if mat: + #set mat to category + if self.cat_index>-1: + dd(self.current_category) + cat = self.current_category + if cat == self.all_materials[self.mat_index].category: + return + cmd = """ import bpy try: mat = bpy.data.materials['%s'] @@ -467,205 +467,205 @@ if mat: mat['category'] = "%s" bpy.ops.wm.save_mainfile(filepath="%s", check_existing=False, compress=True) """ % (mat.name, cat, winpath(self.current_library.path)) - if send_command(cmd): - self.all_materials[self.mat_index].category = cat - mat.category = cat + if send_command(cmd): + self.all_materials[self.mat_index].category = cat + mat.category = cat + else: + return "WARNING", "There was an error." + + # catnode = xml.find("category", self.current_category, lib, True) + # matnode = xml.find("material", mat.name, lib) + # if matnode: + # catnode.appendChild(matnode) + # else: + # matnode = xml.find("material", mat.name, catnode, True) + # xml.save() + # mat.category = cat + # self.current_library.materials[self.mat_index].category = cat + #remove mat from any category + else: + mat.category = "" + self.all_materials[self.mat_index].category = "" else: - return "WARNING", "There was an error." - -# catnode = xml.find("category", self.current_category, lib, True) -# matnode = xml.find("material", mat.name, lib) -# if matnode: -# catnode.appendChild(matnode) -# else: -# matnode = xml.find("material", mat.name, catnode, True) -# xml.save() -# mat.category = cat -# self.current_library.materials[self.mat_index].category = cat - #remove mat from any category - else: - mat.category = "" - self.all_materials[self.mat_index].category = "" - else: - return "WARNING", "Select a material" + return "WARNING", "Select a material" - def get_material(self, name, link=False): - with bpy.data.libraries.load(self.current_library.path, link, False) as (data_from, data_to): - data_to.materials = [name] - if link: - print(name + " linked.") - else: - print(name + " appended.") - - def apply(self, context, preview=False): - name = self.active_material.name - if not name: return "WARNING", "Select a material from the list." - - linked = self.link or preview - force = self.force_import or linked - - objects = [] - active = context.object - dummy = self.get_dummy(context) - - #setup objects - if preview: - if context.mode == "EDIT_MESH": - return "WARNING", "Can't preview on EDIT MODE" - if dummy!= active: - self.last_selected = context.object.name - context.view_layer.objects.active = dummy - objects.append(dummy) - #apply - else: - objects = [obj for obj in context.selected_objects if hasattr(obj.data, "materials")] - - if not objects: - return "INFO", "Please select an object" - - if dummy == context.object and not preview: - if (len(objects)==1 and dummy.select): - return "ERROR", "Apply is disabled for the Material Preview Object" - try: - last = context.scene.objects[self.last_selected] - if last in context.selected_objects: - context.view_layer.objects.active = last + def get_material(self, name, link=False): + with bpy.data.libraries.load(self.current_library.path, link, False) as (data_from, data_to): + data_to.materials = [name] + if link: + print(name + " linked.") else: - self.last_selected = "" - except: - context.view_layer.objects.active = None - dummy.select_set(False) - #objects = context.selected_objects - - material = None - - #mira si hay materiales linkados de la libreria actual - for mat in bpy.data.materials: - try: - samelib = bpy.path.relpath(mat.library.filepath) == bpy.path.relpath(self.current_library.path) - except: - samelib = False - - if mat.name == name and mat.library and samelib: - material = mat - dd("encontre linked", name, "no importo nada") - break - - if not force: - #busca materiales no linkados - for mat in bpy.data.materials: - if mat.name == name and not mat.library: - material = mat - dd("encontre no linkado", name, "no importo nada") - break - - if not material: - #go get it - dd("voy a buscarlo") - nmats = len(bpy.data.materials) - - self.get_material(name, linked) - - if not self.force_import: - try: - material = bpy.data.materials[name] - except: - pass - - if not material: - if nmats == len(bpy.data.materials) and not linked: - return "ERROR", name + " doesn't exists at library " + str(linked) + print(name + " appended.") + + def apply(self, context, preview=False): + name = self.active_material.name + if not name: return "WARNING", "Select a material from the list." + + linked = self.link or preview + force = self.force_import or linked + + objects = [] + active = context.object + dummy = self.get_dummy(context) + + #setup objects + if preview: + if context.mode == "EDIT_MESH": + return "WARNING", "Can't preview on EDIT MODE" + if dummy!= active: + self.last_selected = context.object.name + context.view_layer.objects.active = dummy + objects.append(dummy) + #apply else: - for mat in reversed(bpy.data.materials): - if mat.name[0:len(name)] == name: - #careful on how blender writes library paths - try: + objects = [obj for obj in context.selected_objects if hasattr(obj.data, "materials")] + + if not objects: + return "INFO", "Please select an object" + + if dummy == context.object and not preview: + if (len(objects)==1 and dummy.select): + return "ERROR", "Apply is disabled for the Material Preview Object" + try: + last = context.scene.objects[self.last_selected] + if last in context.selected_objects: + context.view_layer.objects.active = last + else: + self.last_selected = "" + except: + context.view_layer.objects.active = None + dummy.select_set(False) + #objects = context.selected_objects + + material = None + + #mira si hay materiales linkados de la libreria actual + for mat in bpy.data.materials: + try: samelib = bpy.path.relpath(mat.library.filepath) == bpy.path.relpath(self.current_library.path) - except: + except: samelib = False - if linked and mat.library and samelib: + if mat.name == name and mat.library and samelib: material = mat - dd(name, "importado con link") + dd("encontre linked", name, "no importo nada") break - else: - if not mat.library: - dd(name, "importado sin link") - material = mat - break - if material: - material.use_fake_user = False - material.user_clear() - - print ("Material", material, force) - - #if material: - #maybe some test cases doesn't return a material, gotta take care of that - #i cannot think of any case like that right now - #maybe import linked when the database isnt sync - if context.mode == "EDIT_MESH": - obj = context.object - dd(material) - index = -1 - for i, mat in enumerate(obj.data.materials): - if mat == material: - index = i - break - - if index == -1: - obj.data.materials.append(material) - index = len(obj.data.materials)-1 - dd(index) - import bmesh - bm = bmesh.from_edit_mesh(obj.data) - for f in bm.faces: - if f.select: - f.material_index = index - else: - for obj in objects: - index = obj.active_material_index - if index < len(obj.material_slots): - obj.material_slots[index].material = None - obj.material_slots[index].material = material + if not force: + #busca materiales no linkados + for mat in bpy.data.materials: + if mat.name == name and not mat.library: + material = mat + dd("encontre no linkado", name, "no importo nada") + break + + if not material: + #go get it + dd("voy a buscarlo") + nmats = len(bpy.data.materials) + + self.get_material(name, linked) + + if not self.force_import: + try: + material = bpy.data.materials[name] + except: + pass + + if not material: + if nmats == len(bpy.data.materials) and not linked: + return "ERROR", name + " doesn't exists at library " + str(linked) + else: + for mat in reversed(bpy.data.materials): + if mat.name[0:len(name)] == name: + #careful on how blender writes library paths + try: + samelib = bpy.path.relpath(mat.library.filepath) == bpy.path.relpath(self.current_library.path) + except: + samelib = False + + if linked and mat.library and samelib: + material = mat + dd(name, "importado con link") + break + else: + if not mat.library: + dd(name, "importado sin link") + material = mat + break + if material: + material.use_fake_user = False + material.user_clear() + + print ("Material", material, force) + + #if material: + #maybe some test cases doesn't return a material, gotta take care of that + #i cannot think of any case like that right now + #maybe import linked when the database isnt sync + if context.mode == "EDIT_MESH": + obj = context.object + dd(material) + index = -1 + for i, mat in enumerate(obj.data.materials): + if mat == material: + index = i + break + + if index == -1: + obj.data.materials.append(material) + index = len(obj.data.materials)-1 + dd(index) + import bmesh + bm = bmesh.from_edit_mesh(obj.data) + for f in bm.faces: + if f.select: + f.material_index = index + else: - obj.data.materials.append(material) + for obj in objects: + index = obj.active_material_index + if index < len(obj.material_slots): + obj.material_slots[index].material = None + obj.material_slots[index].material = material + else: + obj.data.materials.append(material) - if not linked: - bpy.ops.object.make_local(type="SELECT_OBDATA_MATERIAL") + if not linked: + bpy.ops.object.make_local(type="SELECT_OBDATA_MATERIAL") - def add_material(self, mat): + def add_material(self, mat): - if not mat: - return 'WARNING', "Select a material from the scene." + if not mat: + return 'WARNING', "Select a material from the scene." - name = mat.name - thispath = winpath(bpy.data.filepath) - libpath = winpath(self.current_library.path) + name = mat.name + thispath = winpath(bpy.data.filepath) + libpath = winpath(self.current_library.path) - if not thispath: - return 'WARNING', "Save this file before export." + if not thispath: + return 'WARNING', "Save this file before export." - if not libpath: - return 'WARNING', "Library not found!." + if not libpath: + return 'WARNING', "Library not found!." - elif bpy.data.is_dirty: - bpy.ops.wm.save_mainfile(check_existing=True) + elif bpy.data.is_dirty: + bpy.ops.wm.save_mainfile(check_existing=True) - if mat.library: - return 'WARNING', 'Cannot export linked materials.' + if mat.library: + return 'WARNING', 'Cannot export linked materials.' - dd("adding material", name, libpath) + dd("adding material", name, libpath) - overwrite = "" - if name in list_materials(libpath): - overwrite = ''' + overwrite = "" + if name in list_materials(libpath): + overwrite = ''' mat = bpy.data.materials["%s"] mat.name = "tmp" mat.use_fake_user = False mat.user_clear()''' % name - cmd = ''' + cmd = ''' import bpy{0} with bpy.data.libraries.load("{1}") as (data_from, data_to): data_to.materials = ["{2}"] @@ -675,88 +675,88 @@ bpy.ops.file.pack_all() bpy.ops.wm.save_mainfile(filepath="{3}", check_existing=False, compress=True) '''.format(overwrite, thispath, name, libpath) - if send_command(cmd): - #self.load_library() - if not overwrite: - item = self.all_materials.add() - item.name = name - if "category" in mat.keys(): - item.category = mat['category'] - #reorder all_materials - items = sorted([[item.name, item.category] for item in self.all_materials], key = lambda x: x[0]) - - self.all_materials.clear() - for it in items: - item = self.all_materials.add() - item.name = it[0] - item.category = it[1] - - self.update_list() - - return 'INFO', "Material added." - else: - print("Save Material Error: Run Blender with administrative privileges.") - return 'WARNING', "There was an error saving the material" - - def remove_material(self): - name = self.active_material.name - libpath = winpath(self.current_library.path) - if name and libpath and name in list_materials(libpath): - cmd = '''import bpy + if send_command(cmd): + #self.load_library() + if not overwrite: + item = self.all_materials.add() + item.name = name + if "category" in mat.keys(): + item.category = mat['category'] + #reorder all_materials + items = sorted([[item.name, item.category] for item in self.all_materials], key = lambda x: x[0]) + + self.all_materials.clear() + for it in items: + item = self.all_materials.add() + item.name = it[0] + item.category = it[1] + + self.update_list() + + return 'INFO', "Material added." + else: + print("Save Material Error: Run Blender with administrative privileges.") + return 'WARNING', "There was an error saving the material" + + def remove_material(self): + name = self.active_material.name + libpath = winpath(self.current_library.path) + if name and libpath and name in list_materials(libpath): + cmd = '''import bpy mat = bpy.data.materials["%s"] mat.use_fake_user = False mat.user_clear() bpy.ops.wm.save_mainfile(filepath="%s", check_existing=False, compress=True)''' % (name , libpath) - if send_command(cmd, "removemat.py"): - self.all_materials.remove(self.mat_index) - self.update_list() - else: - return 'ERROR', "There was an error." - return "INFO", name + " removed." - - def get_dummy(self, context): - dummy_name = "Material_Preview_Dummy" - dummy_mesh = "Material_Preview_Mesh" - scn = context.scene - try: - dummy = scn.objects[dummy_name] - except: - #create dummy - try: - me = bpy.data.meshes(dummy_mesh) - except: - me = bpy.data.meshes.new(dummy_mesh) - dummy = bpy.data.objects.new(dummy_name, me) - context.collection.objects.link(dummy) - - dummy.hide_set(True) - dummy.hide_render = True - dummy.hide_select = True - return dummy + if send_command(cmd, "removemat.py"): + self.all_materials.remove(self.mat_index) + self.update_list() + else: + return 'ERROR', "There was an error." + return "INFO", name + " removed." + + def get_dummy(self, context): + dummy_name = "Material_Preview_Dummy" + dummy_mesh = "Material_Preview_Mesh" + scn = context.scene + try: + dummy = scn.objects[dummy_name] + except: + #create dummy + try: + me = bpy.data.meshes(dummy_mesh) + except: + me = bpy.data.meshes.new(dummy_mesh) + dummy = bpy.data.objects.new(dummy_name, me) + context.collection.objects.link(dummy) + + dummy.hide_set(True) + dummy.hide_render = True + dummy.hide_select = True + return dummy # bpy.utils.register_class(matlibProperties) # Scene.matlib = PointerProperty(type = matlibProperties) ### MENUS class MATLIB_MT_LibsMenu(Menu): - bl_label = "Libraries Menu" + bl_label = "Libraries Menu" - def draw(self, context): - layout = self.layout - libs = libraries - #layout.operator("matlib.operator", text="Default Library").cmd="lib-1" - for i, lib in enumerate(libs): - layout.operator("matlib.operator", text=lib.shortname).cmd="lib"+str(i) + def draw(self, context): + layout = self.layout + libs = libraries + #layout.operator("matlib.operator", text="Default Library").cmd="lib-1" + for i, lib in enumerate(libs): + layout.operator("matlib.operator", text=lib.shortname).cmd="lib"+str(i) class MATLIB_MT_CatsMenu(Menu): - bl_label = "Categories Menu" + bl_label = "Categories Menu" - def draw(self, context): - layout = self.layout - cats = context.scene.matlib.categories - layout.operator("matlib.operator", text="All").cmd="cat-1" - for i, cat in enumerate(cats): - layout.operator("matlib.operator", text=cat.name).cmd="cat"+str(i) + def draw(self, context): + layout = self.layout + cats = context.scene.matlib.categories + layout.operator("matlib.operator", text="All").cmd="cat-1" + for i, cat in enumerate(cats): + layout.operator("matlib.operator", text=cat.name).cmd="cat"+str(i) ### OPERATORS #class MATLIB_OT_add(Operator): @@ -775,294 +775,294 @@ class MATLIB_MT_CatsMenu(Menu): class MATLIB_OT_add(Operator): - """Add active material to library""" - bl_idname = "matlib.add" - bl_label = "Add active material" - - @classmethod - def poll(cls, context): - obj = context.active_object - return obj is not None and obj.active_material is not None - - def execute(self, context): - matlib = context.scene.matlib - success = matlib.add_material(context.object.active_material) - if type(success).__name__ == "tuple": - print(success) - self.report({success[0]}, success[1]) - return {'FINISHED'} + """Add active material to library""" + bl_idname = "matlib.add" + bl_label = "Add active material" + + @classmethod + def poll(cls, context): + obj = context.active_object + return obj is not None and obj.active_material is not None + + def execute(self, context): + matlib = context.scene.matlib + success = matlib.add_material(context.object.active_material) + if type(success).__name__ == "tuple": + print(success) + self.report({success[0]}, success[1]) + return {'FINISHED'} class MATLIB_OT_remove(Operator): - """Remove material from library""" - bl_idname = "matlib.remove" - bl_label = "Remove material from library" - - @classmethod - def poll(cls, context): - matlib = context.scene.matlib - return check_index(matlib.materials, matlib.mat_index) - - def execute(self, context): - matlib = context.scene.matlib - success = matlib.remove_material() - if type(success).__name__ == "tuple": - print(success) - self.report({success[0]}, success[1]) - return {'FINISHED'} + """Remove material from library""" + bl_idname = "matlib.remove" + bl_label = "Remove material from library" + + @classmethod + def poll(cls, context): + matlib = context.scene.matlib + return check_index(matlib.materials, matlib.mat_index) + + def execute(self, context): + matlib = context.scene.matlib + success = matlib.remove_material() + if type(success).__name__ == "tuple": + print(success) + self.report({success[0]}, success[1]) + return {'FINISHED'} class MATLIB_OT_remove(Operator): - """Reload library""" - bl_idname = "matlib.reload" - bl_label = "Reload library" - -# @classmethod -# def poll(cls, context): -# matlib = context.scene.matlib -# index = matlib.mat_index -# l = len(matlib.materials) -# return l>0 and index >=0 and index < l - - def execute(self, context): - matlib = context.scene.matlib - success = matlib.reload() - if type(success).__name__ == "tuple": - print(success) - self.report({success[0]}, success[1]) - return {'FINISHED'} + """Reload library""" + bl_idname = "matlib.reload" + bl_label = "Reload library" + + # @classmethod + # def poll(cls, context): + # matlib = context.scene.matlib + # index = matlib.mat_index + # l = len(matlib.materials) + # return l>0 and index >=0 and index < l + + def execute(self, context): + matlib = context.scene.matlib + success = matlib.reload() + if type(success).__name__ == "tuple": + print(success) + self.report({success[0]}, success[1]) + return {'FINISHED'} class MATLIB_OT_apply(Operator): - """Apply selected material""" - bl_idname = "matlib.apply" - bl_label = "Apply material" - - @classmethod - def poll(cls, context): - matlib = context.scene.matlib - index = matlib.mat_index - l = len(matlib.materials) - obj = context.active_object - return l>0 and index >=0 and index < l and obj is not None - - def execute(self, context): - matlib = context.scene.matlib - success = matlib.apply(context, False) - if type(success).__name__ == "tuple": - print(success) - self.report({success[0]}, success[1]) - return {'FINISHED'} + """Apply selected material""" + bl_idname = "matlib.apply" + bl_label = "Apply material" + + @classmethod + def poll(cls, context): + matlib = context.scene.matlib + index = matlib.mat_index + l = len(matlib.materials) + obj = context.active_object + return l>0 and index >=0 and index < l and obj is not None + + def execute(self, context): + matlib = context.scene.matlib + success = matlib.apply(context, False) + if type(success).__name__ == "tuple": + print(success) + self.report({success[0]}, success[1]) + return {'FINISHED'} class MATLIB_OT_preview(Operator): - """Preview selected material""" - bl_idname = "matlib.preview" - bl_label = "Preview selected material" - - @classmethod - def poll(cls, context): - matlib = context.scene.matlib - index = matlib.mat_index - l = len(matlib.materials) - obj = context.active_object - return l>0 and index >=0 and index < l - - def execute(self, context): - matlib = context.scene.matlib - success = matlib.apply(context, True) - if type(success).__name__ == "tuple": - print(success) - self.report({success[0]}, success[1]) - return {'FINISHED'} + """Preview selected material""" + bl_idname = "matlib.preview" + bl_label = "Preview selected material" + + @classmethod + def poll(cls, context): + matlib = context.scene.matlib + index = matlib.mat_index + l = len(matlib.materials) + obj = context.active_object + return l>0 and index >=0 and index < l + + def execute(self, context): + matlib = context.scene.matlib + success = matlib.apply(context, True) + if type(success).__name__ == "tuple": + print(success) + self.report({success[0]}, success[1]) + return {'FINISHED'} class MATLIB_OT_flush(Operator): - """Flush unused materials""" - bl_idname = "matlib.flush" - bl_label = "Flush unused materials" - - @classmethod - def poll(cls, context): - matlib = context.scene.matlib - index = matlib.mat_index - l = len(matlib.materials) - obj = context.active_object - return l>0 and index >=0 and index < l - - def execute(self, context): - matlib = context.scene.matlib - dummy = matlib.get_dummy(context) - if dummy == context.object: - try: - context.view_layer.objects.active = context.scene.objects[matlib.last_selected] - except: - pass - - for slot in dummy.material_slots: - slot.material = None - i=0 - for mat in bpy.data.materials: - if mat.users==0: - i+=1 - print (mat.name, "removed.") - bpy.data.materials.remove(mat) - - plural = "" if i == 1 else "s" - self.report({'INFO'}, str(i) + " material"+plural+" removed.") - - return {'FINISHED'} + """Flush unused materials""" + bl_idname = "matlib.flush" + bl_label = "Flush unused materials" + + @classmethod + def poll(cls, context): + matlib = context.scene.matlib + index = matlib.mat_index + l = len(matlib.materials) + obj = context.active_object + return l>0 and index >=0 and index < l + + def execute(self, context): + matlib = context.scene.matlib + dummy = matlib.get_dummy(context) + if dummy == context.object: + try: + context.view_layer.objects.active = context.scene.objects[matlib.last_selected] + except: + pass + + for slot in dummy.material_slots: + slot.material = None + i=0 + for mat in bpy.data.materials: + if mat.users==0: + i+=1 + print (mat.name, "removed.") + bpy.data.materials.remove(mat) + + plural = "" if i == 1 else "s" + self.report({'INFO'}, str(i) + " material"+plural+" removed.") + + return {'FINISHED'} class MATLIB_OT_operator(Operator): - """Add, Remove, Reload, Apply, Preview, Clean Material""" - bl_label = "New" - bl_idname = "matlib.operator" - __doc__ = "Add, Remove, Reload, Apply, Preview, Clean Material" - - category: StringProperty(name="Category") - filepath: StringProperty(options={'HIDDEN'}) - cmd: bpy.props.StringProperty(name="Command", options={'HIDDEN'}) - filter_glob: StringProperty(default="*.blend", options={'HIDDEN'}) - @classmethod - def poll(cls, context): - return context.active_object is not None - - def draw(self, context): - layout = self.layout - #cmd = LIBRARY_ADD - if self.cmd == "LIBRARY_ADD": - #layout.label("Select a blend file as library or") - #layout.label("Type a name to create a new library.") - layout.prop(self, "category", text="Library") - elif self.cmd == "FILTER_ADD": - layout.prop(self, "category") - - def invoke(self, context, event): - - cmd = self.cmd - print("invoke", cmd) - - if cmd == "LIBRARY_ADD": - self.filepath = matlib_path + os.path.sep - dd("filepath", self.filepath, matlib_path) - #context.window_manager.fileselect_add(self) - context.window_manager.invoke_props_dialog(self) - return {'RUNNING_MODAL'} - elif cmd == "FILTER_ADD": - context.window_manager.invoke_props_dialog(self) - return {'RUNNING_MODAL'} - return self.execute(context) - - ### TODO: execute doesn't trigger remove - def execute(self, context): - - success = "" - matlib = context.scene.matlib - - if self.cmd == "init": - print("initialize") - return {'FINISHED'} - - #Library Commands - if self.cmd[0:3] == "lib": - index = int(self.cmd[3::]) - matlib.lib_index = index - #success = matlib.load_library() - elif self.cmd == "LIBRARY_ADD": - dd("execute lib add") - libname = self.category - if libname[-6::] != ".blend": libname+= ".blend" - libname = os.path.join(matlib_path, libname) - print(libname) - - success = matlib.add_library(libname, True) - for i, l in enumerate(libraries): - if l.name == self.category: - matlib.lib_index = i - break - - elif self.cmd == "RELOAD": - success = matlib.reload() - - if not matlib.current_library: - self.report({'ERROR'}, "Select a Library") - return {'CANCELLED'} - - if self.cmd == "FILTER_ADD": - success = matlib.add_category(self.category) - for i, cat in enumerate(matlib.categories): - if cat.name == self.category: - matlib.cat_index = i - break - - elif self.cmd == "FILTER_REMOVE": - matlib.remove_category() - - elif self.cmd == "FILTER_SET": - success = matlib.set_category() - - elif self.cmd[0:3] == "cat": - index = int(self.cmd[3::]) - matlib.cat_index = index - - #Common Commands - elif self.cmd == "ADD": - success = matlib.add_material(context.object.active_material) - - elif self.cmd == "REMOVE": - success = matlib.remove_material() - - - elif self.cmd == "APPLY": - success = matlib.apply(context) - - elif self.cmd == "PREVIEW": - success = matlib.apply(context, True) - - elif self.cmd=="FLUSH": - #release dummy materials - dummy = matlib.get_dummy(context) - if dummy == context.object: - try: - context.view_layer.objects.active = context.scene.objects[matlib.last_selected] - except: - pass - - for slot in dummy.material_slots: - slot.material = None - i=0 - for mat in bpy.data.materials: - if mat.users==0: - i+=1 - print (mat.name, "removed.") - bpy.data.materials.remove(mat) - - plural = "s" - if i==1: - plural = "" - - self.report({'INFO'}, str(i) + " material"+plural+" removed.") - - ### CONVERT - elif self.cmd == "CONVERT": - return {'FINISHED'} - lib = matlib.current_library - if lib: - - path = os.path.join(matlib_path, "www") - if not os.path.exists(path): - os.mkdir(path) - path = os.path.join(path, lib.shortname) - if not os.path.exists(path): - os.mkdir(path) - - path = winpath(path) - libpath = winpath(lib.name) - - print(path) - print(libpath) - - #decirle a la libreria que cree un fichero blend por cada material que tenga. - cmd = """ + """Add, Remove, Reload, Apply, Preview, Clean Material""" + bl_label = "New" + bl_idname = "matlib.operator" + __doc__ = "Add, Remove, Reload, Apply, Preview, Clean Material" + + category: StringProperty(name="Category") + filepath: StringProperty(options={'HIDDEN'}) + cmd: bpy.props.StringProperty(name="Command", options={'HIDDEN'}) + filter_glob: StringProperty(default="*.blend", options={'HIDDEN'}) + @classmethod + def poll(cls, context): + return context.active_object is not None + + def draw(self, context): + layout = self.layout + #cmd = LIBRARY_ADD + if self.cmd == "LIBRARY_ADD": + #layout.label("Select a blend file as library or") + #layout.label("Type a name to create a new library.") + layout.prop(self, "category", text="Library") + elif self.cmd == "FILTER_ADD": + layout.prop(self, "category") + + def invoke(self, context, event): + + cmd = self.cmd + print("invoke", cmd) + + if cmd == "LIBRARY_ADD": + self.filepath = matlib_path + os.path.sep + dd("filepath", self.filepath, matlib_path) + #context.window_manager.fileselect_add(self) + context.window_manager.invoke_props_dialog(self) + return {'RUNNING_MODAL'} + elif cmd == "FILTER_ADD": + context.window_manager.invoke_props_dialog(self) + return {'RUNNING_MODAL'} + return self.execute(context) + + ### TODO: execute doesn't trigger remove + def execute(self, context): + + success = "" + matlib = context.scene.matlib + + if self.cmd == "init": + print("initialize") + return {'FINISHED'} + + #Library Commands + if self.cmd[0:3] == "lib": + index = int(self.cmd[3::]) + matlib.lib_index = index + #success = matlib.load_library() + elif self.cmd == "LIBRARY_ADD": + dd("execute lib add") + libname = self.category + if libname[-6::] != ".blend": libname+= ".blend" + libname = os.path.join(matlib_path, libname) + print(libname) + + success = matlib.add_library(libname, True) + for i, l in enumerate(libraries): + if l.name == self.category: + matlib.lib_index = i + break + + elif self.cmd == "RELOAD": + success = matlib.reload() + + if not matlib.current_library: + self.report({'ERROR'}, "Select a Library") + return {'CANCELLED'} + + if self.cmd == "FILTER_ADD": + success = matlib.add_category(self.category) + for i, cat in enumerate(matlib.categories): + if cat.name == self.category: + matlib.cat_index = i + break + + elif self.cmd == "FILTER_REMOVE": + matlib.remove_category() + + elif self.cmd == "FILTER_SET": + success = matlib.set_category() + + elif self.cmd[0:3] == "cat": + index = int(self.cmd[3::]) + matlib.cat_index = index + + #Common Commands + elif self.cmd == "ADD": + success = matlib.add_material(context.object.active_material) + + elif self.cmd == "REMOVE": + success = matlib.remove_material() + + + elif self.cmd == "APPLY": + success = matlib.apply(context) + + elif self.cmd == "PREVIEW": + success = matlib.apply(context, True) + + elif self.cmd=="FLUSH": + #release dummy materials + dummy = matlib.get_dummy(context) + if dummy == context.object: + try: + context.view_layer.objects.active = context.scene.objects[matlib.last_selected] + except: + pass + + for slot in dummy.material_slots: + slot.material = None + i=0 + for mat in bpy.data.materials: + if mat.users==0: + i+=1 + print (mat.name, "removed.") + bpy.data.materials.remove(mat) + + plural = "s" + if i==1: + plural = "" + + self.report({'INFO'}, str(i) + " material"+plural+" removed.") + + ### CONVERT + elif self.cmd == "CONVERT": + return {'FINISHED'} + lib = matlib.current_library + if lib: + + path = os.path.join(matlib_path, "www") + if not os.path.exists(path): + os.mkdir(path) + path = os.path.join(path, lib.shortname) + if not os.path.exists(path): + os.mkdir(path) + + path = winpath(path) + libpath = winpath(lib.name) + + print(path) + print(libpath) + + #decirle a la libreria que cree un fichero blend por cada material que tenga. + cmd = """ print(30*"+") import bpy, os def list_materials(): @@ -1103,89 +1103,89 @@ for mat in mats: material.use_fake_user = True bpy.ops.wm.save_mainfile(filepath = matpath, compress=True, check_existing=False) """.format(libpath, path) - print(cmd) - send_command(cmd, "createlib.py") + print(cmd) + send_command(cmd, "createlib.py") - if type(success).__name__ == "tuple": - print(success) - self.report({success[0]}, success[1]) + if type(success).__name__ == "tuple": + print(success) + self.report({success[0]}, success[1]) - return {'FINISHED'} + return {'FINISHED'} class MATLIB_PT_vxPanel(Panel): - bl_label = "Material Library VX" - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "material" - - @classmethod - def poll(self, context): - return context.active_object.active_material!=None - - def draw(self, context): - layout = self.layout - matlib = context.scene.matlib - - #hyper ugly trick but i dont know how to init classes at register time -# if matlibProperties.init: -# matlibProperties.init = False -# matlib.__init__() - - #libraries - row = layout.row(align=True) - if matlib.current_library: - text = matlib.current_library.shortname - else: - text = "Select a Library" + bl_label = "Material Library VX" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "material" - row.menu("MATLIB_MT_LibsMenu",text=text) - row.operator("matlib.operator", icon="ADD", text="").cmd = "LIBRARY_ADD" - if matlib.active_material: - row.label(text = matlib.active_material.category) - else: - row.label(text="") -# -# #search - if not matlib.hide_search: - row = layout.row(align=True) - row.prop_search(matlib, "search", matlib, "materials", text="", icon="VIEWZOOM") - -# #list - row = layout.row() - row.template_list("UI_UL_list", " ", matlib, "materials", matlib, "mat_index", rows=6) - col = row.column(align=True) - row = layout.row() - - #operators - col.operator("matlib.operator", icon="ADD", text="").cmd="ADD" - col.operator("matlib.operator", icon="REMOVE", text="").cmd="REMOVE" - col.operator("matlib.operator", icon="FILE_REFRESH", text="").cmd="RELOAD" - col.operator("matlib.operator", icon="MATERIAL", text="").cmd="APPLY" - col.operator("matlib.operator", icon="COLOR", text="").cmd="PREVIEW" - col.operator("matlib.operator", icon="GHOST_DISABLED", text="").cmd="FLUSH" - col.prop(matlib, "show_prefs", icon="MODIFIER", text="") - - #categories - row = layout.row(align=True) - text = "All" - if matlib.current_category: text = matlib.current_category - row.menu("MATLIB_MT_CatsMenu",text=text) - row.prop(matlib, "filter", icon="FILTER", text="") - row.operator("matlib.operator", icon="FILE_PARENT", text="").cmd="FILTER_SET" - row.operator("matlib.operator", icon="ADD", text="").cmd="FILTER_ADD" - row.operator("matlib.operator", icon="REMOVE", text="").cmd="FILTER_REMOVE" - - #prefs - if matlib.show_prefs: - row = layout.row() - row.prop(matlib, "force_import") - row.prop(matlib, "link") - row = layout.row() - row.prop(matlib, "hide_search") + @classmethod + def poll(self, context): + return context.active_object.active_material!=None + + def draw(self, context): + layout = self.layout + matlib = context.scene.matlib + + #hyper ugly trick but i dont know how to init classes at register time + # if matlibProperties.init: + # matlibProperties.init = False + # matlib.__init__() + + #libraries + row = layout.row(align=True) + if matlib.current_library: + text = matlib.current_library.shortname + else: + text = "Select a Library" + + row.menu("MATLIB_MT_LibsMenu",text=text) + row.operator("matlib.operator", icon="ADD", text="").cmd = "LIBRARY_ADD" + if matlib.active_material: + row.label(text = matlib.active_material.category) + else: + row.label(text="") + # + # #search + if not matlib.hide_search: + row = layout.row(align=True) + row.prop_search(matlib, "search", matlib, "materials", text="", icon="VIEWZOOM") + + # #list + row = layout.row() + row.template_list("UI_UL_list", " ", matlib, "materials", matlib, "mat_index", rows=6) + col = row.column(align=True) + row = layout.row() + + #operators + col.operator("matlib.operator", icon="ADD", text="").cmd="ADD" + col.operator("matlib.operator", icon="REMOVE", text="").cmd="REMOVE" + col.operator("matlib.operator", icon="FILE_REFRESH", text="").cmd="RELOAD" + col.operator("matlib.operator", icon="MATERIAL", text="").cmd="APPLY" + col.operator("matlib.operator", icon="COLOR", text="").cmd="PREVIEW" + col.operator("matlib.operator", icon="GHOST_DISABLED", text="").cmd="FLUSH" + col.prop(matlib, "show_prefs", icon="MODIFIER", text="") + + #categories + row = layout.row(align=True) + text = "All" + if matlib.current_category: text = matlib.current_category + row.menu("MATLIB_MT_CatsMenu",text=text) + row.prop(matlib, "filter", icon="FILTER", text="") + row.operator("matlib.operator", icon="FILE_PARENT", text="").cmd="FILTER_SET" + row.operator("matlib.operator", icon="ADD", text="").cmd="FILTER_ADD" + row.operator("matlib.operator", icon="REMOVE", text="").cmd="FILTER_REMOVE" + + #prefs + if matlib.show_prefs: + row = layout.row() + row.prop(matlib, "force_import") + row.prop(matlib, "link") + row = layout.row() + row.prop(matlib, "hide_search") # row = layout.row(align=True) - #row = layout.row() - #row.operator("matlib.operator", icon="URL", text="Convert Library").cmd="CONVERT" +#row = layout.row() +#row.operator("matlib.operator", icon="URL", text="Convert Library").cmd="CONVERT" # row = layout.row() # if (matlib.current_library): @@ -1217,11 +1217,11 @@ def reload_library(self, context): class matlibvxPref(AddonPreferences): bl_idname = __name__ - matlib_path: StringProperty( name="Additional Path", description="User defined path to .blend libraries files", default="", + subtype="DIR_PATH", update=reload_library ) @@ -1230,15 +1230,16 @@ class matlibvxPref(AddonPreferences): layout.prop(self, "matlib_path") classes = [ -matlibMaterials, -EmptyGroup, -MATLIB_PT_vxPanel, -MATLIB_OT_operator, -MATLIB_MT_LibsMenu, -MATLIB_MT_CatsMenu, -matlibProperties, + matlibvxPref, + matlibMaterials, + EmptyGroup, + MATLIB_PT_vxPanel, + MATLIB_OT_operator, + MATLIB_MT_LibsMenu, + MATLIB_MT_CatsMenu, + matlibProperties, ] - + """ classes = [ matlibProperties, @@ -1282,7 +1283,7 @@ def unregister(): libraries.clear() bpy.app.handlers.load_post.remove(refresh_libs) for c in classes: - bpy.utils.unregister_class(c) + bpy.utils.unregister_class(c) if __name__ == "__main__":