Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormeta-androcto <meta.androcto1@gmail.com>2017-04-24 03:33:31 +0300
committermeta-androcto <meta.androcto1@gmail.com>2017-04-24 03:33:31 +0300
commit8b7a78110f4a702018e23672361f228d15d2e6f5 (patch)
tree39c69af0c076a2d340d45fea9394c9bf1393c851 /materials_library_vx
parent7fc71a4856f65c42f5c0711d440d2e2136df0de3 (diff)
Initial Commit materials library: T51230 T50357
Diffstat (limited to 'materials_library_vx')
-rw-r--r--materials_library_vx/__init__.py1203
-rw-r--r--materials_library_vx/cycles_templates.blendbin0 -> 174321 bytes
-rw-r--r--materials_library_vx/materials.blendbin0 -> 98014 bytes
3 files changed, 1203 insertions, 0 deletions
diff --git a/materials_library_vx/__init__.py b/materials_library_vx/__init__.py
new file mode 100644
index 00000000..39bb55d2
--- /dev/null
+++ b/materials_library_vx/__init__.py
@@ -0,0 +1,1203 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+# contributed to by meta-androcto
+
+bl_info = {
+ "name": "Material Library VX",
+ "author": "Mackraken",
+ "version": (1, 0, 1),
+ "blender": (2, 77, 0),
+ "location": "Properties > Material",
+ "description": "Material Library VX",
+ "warning": "",
+ "wiki_url": "https://sites.google.com/site/aleonserra/home/scripts/matlib-vx-5-6",
+ "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
+ "category": "Material"}
+
+# TODO: translate comments, cleanup imports, remove dead code, fix xml set fiter crash
+
+import bpy
+import json
+import zipfile
+import urllib.request
+import os
+import sys
+import re
+import csv
+import codecs
+import collections
+import subprocess
+import webbrowser
+from bpy.types import (
+ Operator,
+ Menu,
+ Panel,
+ PropertyGroup,
+ AddonPreferences,
+ )
+from bpy.props import (
+ BoolProperty,
+ CollectionProperty,
+ EnumProperty,
+ IntProperty,
+ StringProperty,
+ PointerProperty,
+ )
+
+
+dev = False
+matlib_path = os.path.dirname(__file__)
+
+if dev:
+ 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)
+
+
+# add-on settings
+def addon_settings():
+ # separate function just for more convience
+ addon = bpy.context.user_preferences.addons[__name__]
+ compact = addon.preferences.use_brushes_menu_type
+
+ return compact
+
+
+# Regular Functions
+def winpath(path):
+ 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
+
+
+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
+
+
+def update_lib_index(self, context):
+ self.load_library()
+
+
+def update_cat_index(self, context):
+ dd("cat index:", self.current_category, self.filters)
+
+ if self.filters:
+ self.filters = True
+
+
+def update_filter(self, context):
+
+ dd("filter:", self.filters, self.cat_index, self.current_category)
+ """
+ index = self.cat_index
+
+ if self.filters:
+ cat = self.current_category
+ else:
+ cat = ""
+
+ self.current_library.filters = cat
+ """
+ self.update_list()
+
+
+def check_index(collection, index):
+ 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))
+
+ with open(scriptpath, "w") as f:
+ f.write(cmd)
+
+ if output == "createlib.py":
+ 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])
+
+ # 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)
+
+ if sort:
+ list = sorted(list)
+ return list
+
+
+# category properties (none atm)
+class EmptyGroup(PropertyGroup):
+ pass
+
+
+bpy.utils.register_class(EmptyGroup)
+
+
+class matlibMaterials(PropertyGroup):
+ category = StringProperty()
+
+
+bpy.utils.register_class(matlibMaterials)
+
+
+# bpy.types.Scene.matlib_categories = CollectionProperty(type=EmptyGroup)
+
+
+# CATEGORIES
+class Categories():
+
+ # cats = bpy.context.scene.matlib.categories
+
+ 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
+
+ cmd = """
+print(30*"+")
+import bpy
+if not hasattr(bpy.context.scene, "matlib_categories"):
+ class EmptyProps(bpy.types.PropertyGroup):
+ pass
+ bpy.utils.register_class(EmptyProps)
+ bpy.types.Scene.matlib_categories = bpy.props.CollectionProperty(type=EmptyProps)
+cats = bpy.context.scene.matlib_categories
+for cat in cats:
+ cats.remove(0)
+"""
+ for cat in cats:
+ cmd += """
+cat = cats.add()
+cat.name = "%s" """ % cat.capitalize()
+ cmd += '''
+bpy.ops.wm.save_mainfile(filepath="%s", check_existing=False, compress=True)''' % winpath(libpath)
+
+ 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 = """
+import bpy, json
+class EmptyProps(bpy.types.PropertyGroup):
+ pass
+bpy.utils.register_class(EmptyProps)
+bpy.types.Scene.matlib_categories = bpy.props.CollectionProperty(type=EmptyProps)
+cats = []
+for cat in bpy.context.scene.matlib_categories:
+ materials = []
+ for mat in bpy.data.materials:
+ if "category" in mat.keys() and mat['category'] == cat.name:
+ materials.append(mat.name)
+ cats.append([cat.name, materials])
+with open("%s", "w") as f:
+ f.write(json.dumps(cats, sort_keys=True, indent=4))
+""" % catfile
+ if pull:
+ send_command(cmd)
+
+ # leer el fichero
+ with open(catfile, "r") as f:
+ cats = json.loads(f.read())
+
+ 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?")
+
+ def remove(self, index):
+ self.cats.remove(index)
+ self.save()
+
+
+class Library():
+
+ def __init__(self, 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()
+
+ def __repr__(self):
+ return str(type(self).__name__) + "('" + self.name + "')"
+
+
+# bpy.utils.register_class(Library)
+
+def get_libraries():
+ libs = [Library(f) for f in os.listdir(matlib_path) if f[-5::] == "blend"]
+ return sorted(libs, key=lambda x: bpy.path.display_name(x.name))
+
+
+libraries = get_libraries()
+
+
+# MATLIB CLASS
+class matlibProperties(PropertyGroup):
+
+ # MATLIB PROPERTIES
+
+ # libraries are read from the xml
+ lib_index = IntProperty(
+ min=-1,
+ default=-1,
+ 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
+ # filters: 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
+ )
+ filters = 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."
+
+ # 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!."
+
+ path = self.current_library.path
+
+ dd("loading library", self.lib_index, path)
+
+ if check_path(path):
+ self.filters = False
+ self.cat_index = -1
+
+ 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 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.filters or (self.filters 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']
+except:
+ mat = None
+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
+ 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:
+ """
+ matnode = xml.find("material", mat.name, lib)
+ if matnode:
+ xml.deleteNode(matnode)
+ """
+ mat.category = ""
+ self.current_library.materials[self.mat_index].category = ""
+ else:
+ 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.scene.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.scene.objects.active = last
+ else:
+ self.last_selected = ""
+ except:
+ context.scene.objects.active = None
+ dummy.select = 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 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)
+
+ # if material:
+ # maybe some test cases doesnt 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
+ else:
+ obj.data.materials.append(material)
+
+ if not linked:
+ bpy.ops.object.make_local(type="SELECT_OBDATA_MATERIAL")
+
+ def add_material(self, mat):
+
+ 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)
+
+ if not thispath:
+ return 'WARNING', "Save this file before export."
+
+ if not libpath:
+ return 'WARNING', "Library not found!."
+
+ elif bpy.data.is_dirty:
+ bpy.ops.wm.save_mainfile(check_existing=True)
+
+ if mat.library:
+ return 'WARNING', 'Cannot export linked materials.'
+
+ dd("adding material", name, libpath)
+
+ 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 = '''
+import bpy{0}
+with bpy.data.libraries.load("{1}") as (data_from, data_to):
+ data_to.materials = ["{2}"]
+mat = bpy.data.materials["{2}"]
+mat.use_fake_user=True
+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 priviledges.")
+ 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)
+ scn.objects.link(dummy)
+
+ dummy.hide = True
+ dummy.hide_render = True
+ dummy.hide_select = True
+ return dummy
+
+
+bpy.utils.register_class(matlibProperties)
+bpy.types.Scene.matlib = PointerProperty(type=matlibProperties)
+
+
+# MENUS
+class matlibLibsMenu(Menu):
+ bl_idname = "matlib.libs_menu"
+ bl_label = "Libraries Menu"
+ bl_description = "Main Categories 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)
+
+
+class matlibCatsMenu(Menu):
+ bl_idname = "matlib.cats_menu"
+ bl_label = "Categories Menu"
+ bl_description = "Sub 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)
+
+
+# OPERATORS
+
+class matlibOperator(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 = 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)
+
+ def execute(self, context):
+ # TODO: execute doesnt trigger remove
+ 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.scene.objects.active = scn.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():
+ list = []
+ with bpy.data.libraries.load("{0}") as (data_from, data_to):
+ for mat in data_from.materials:
+ list.append(mat)
+ return sorted(list)
+
+def get_material(name, link=False):
+ with bpy.data.libraries.load("{0}", link, False) as (data_from, data_to):
+ data_to.materials = [name]
+ if link:
+ print(name + " linked.")
+ else:
+ print(name + " appended.")
+
+for scn in bpy.data.scenes:
+ for obj in scn.objects:
+ scn.objects.unlink(obj)
+ obj.user_clear()
+ bpy.data.objects.remove(obj)
+
+def clean_materials():
+ for mat in bpy.data.materials:
+ mat.user_clear()
+ bpy.data.materials.remove(mat)
+
+bin = bpy.app.binary_path
+mats = list_materials()
+bpy.context.user_preferences.filepaths.save_version = 0
+for mat in mats:
+ clean_materials()
+ matpath = os.path.join("{1}", mat + ".blend")
+ print(matpath)
+ get_material(mat)
+ material = bpy.data.materials[0]
+ 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")
+
+ if type(success).__name__ == "tuple":
+ print(success)
+ self.report({success[0]}, success[1])
+
+ return {'FINISHED'}
+
+
+class matlibvxPanel(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 is not 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__()
+ """
+ # libaries
+ row = layout.row(align=True)
+ if matlib.current_library:
+ text = matlib.current_library.shortname
+ else:
+ text = "Select Library"
+ row.menu("matlib.libs_menu", text=text)
+ if matlib.active_material:
+ row.label(matlib.active_material.category)
+ else:
+ row.label("")
+
+ # search
+ if not matlib.hide_search:
+ row = layout.row()
+ row.prop_search(matlib, "search", matlib, "materials", text="", icon="VIEWZOOM")
+
+ # list
+ col = self.layout.column(align=True)
+ row = col.row(align=True)
+ row.template_list("UI_UL_list", " ", matlib, "materials", matlib, "mat_index", rows=6)
+
+ col = self.layout.column(align=True)
+ row = col.row(align=True)
+ # operators
+ row.operator("matlib.operator", icon="MATERIAL", text="Apply").cmd = "APPLY"
+ row.operator("matlib.operator", icon="COLOR", text="Preview").cmd = "PREVIEW"
+
+ col = self.layout.column(align=True)
+ row = col.row(align=True)
+ row.operator("matlib.operator", icon="ZOOMIN", text="Add Mat").cmd = "ADD"
+ row.operator("matlib.operator", icon="ZOOMOUT", text="Remove Mat").cmd = "REMOVE"
+
+ col = self.layout.column(align=True)
+ row = col.row(align=True)
+ row.operator("matlib.operator", icon="FILE_REFRESH", text="Reload").cmd = "RELOAD"
+ row.operator("matlib.operator", icon="GHOST_DISABLED", text="Flush Unused").cmd = "FLUSH"
+
+ col = self.layout.column(align=True)
+ row = col.row(align=True)
+ col.prop(matlib, "show_prefs", icon="MODIFIER", text="Advanced")
+
+ # 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"
+ # categories
+ row = layout.row()
+ row.operator("matlib.operator", icon="ZOOMIN", text="Add library").cmd = "LIBRARY_ADD"
+ row = layout.row(align=True)
+ text = "All"
+ if matlib.current_category:
+ text = matlib.current_category
+
+ if addon_settings() == "normal":
+ col = self.layout.column(align=True)
+ row = col.row(align=True)
+ row.menu("matlib.cats_menu", text=text)
+ col = self.layout.column(align=True)
+ row = col.row(align=True)
+ row.prop(matlib, "filters", icon="FILTER", text="Filter Category")
+ row.operator("matlib.operator", icon="FILE_PARENT", text="Set Filter").cmd = "FILTER_SET"
+ col = self.layout.column(align=True)
+ row = col.row(align=True)
+ row.operator("matlib.operator", icon="ZOOMIN", text="Add Filter").cmd = "FILTER_ADD"
+ row.operator("matlib.operator", icon="ZOOMOUT", text="Remove Filter").cmd = "FILTER_REMOVE"
+ else:
+ row.menu("matlib.cats_menu", text=text)
+ row.prop(matlib, "filters", icon="FILTER", text="")
+ row.operator("matlib.operator", icon="FILE_PARENT", text="").cmd = "FILTER_SET"
+ row.operator("matlib.operator", icon="ZOOMIN", text="").cmd = "FILTER_ADD"
+ row.operator("matlib.operator", icon="ZOOMOUT", text="").cmd = "FILTER_REMOVE"
+
+
+class matlibvxPref(AddonPreferences):
+ bl_idname = __name__
+
+ use_brushes_menu_type = EnumProperty(
+ name="Choose Panel layout",
+ description="",
+ items=[('compact', "Icon only panels",
+ "Use more compact layout"),
+ ('normal', "Icon and text panels",
+ "Use an usually spaced layout")
+ ],
+ default='normal'
+ )
+
+ def draw(self, context):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ row.prop(self, "use_brushes_menu_type", expand=True)
+
+
+classes = (
+ matlibvxPanel,
+ matlibOperator,
+ matlibLibsMenu,
+ matlibCatsMenu,
+ matlibvxPref,
+ )
+
+
+def register():
+ for cls in classes:
+ bpy.utils.register_class(cls)
+
+
+def unregister():
+ for cls in classes:
+ bpy.utils.unregister_class(cls)
+
+
+if __name__ == "__main__":
+ register() \ No newline at end of file
diff --git a/materials_library_vx/cycles_templates.blend b/materials_library_vx/cycles_templates.blend
new file mode 100644
index 00000000..ce97446a
--- /dev/null
+++ b/materials_library_vx/cycles_templates.blend
Binary files differ
diff --git a/materials_library_vx/materials.blend b/materials_library_vx/materials.blend
new file mode 100644
index 00000000..abd0bb00
--- /dev/null
+++ b/materials_library_vx/materials.blend
Binary files differ