Page MenuHome

online_mat_lib.py

online_mat_lib.py

# ***** 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 3 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, see http://www.gnu.org/licenses/
# or write to the Free Software Foundation, Inc., 51 Franklin Street,
# Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2012 by Peter Cassetta ###
# All rights reserved.
#
# Contact: TODO ###
# Information: http://peter.cassetta.info/material-library/ ###
#
# The Original Code is: all of this file.
#
# Contributor(s): Peter Cassetta.
#
# ***** END GPL LICENSE BLOCK *****
bl_info = {
"name": "Online Material Library",
"author": "Peter Cassetta",
"version": (0, 3),
"blender": (2, 6, 3),
"location": "Properties > Material > Online Material Library",
"description": "Browse and download materials from a online CC0 library.",
"warning": "Alpha version",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Material/Online_Material_Library",
"tracker_url": "",
"category": "Material"}
import bpy
import os.path
import http.client
import xml.dom.minidom
library = "testing"
library_data = []
mat_lib_contents = "Please refresh."
mat_lib_category_filenames = []
mat_lib_category_types = []
mat_lib_category_names = []
mat_lib_categories = 0
category_contents = "None"
category_name = ""
category_filename = ""
category_materials = 0
category_type = "none"
parent_category_contents = "None"
parent_category_name = ""
parent_category_filename = ""
parent_category_categories = 0
parent_category_names = []
parent_category_filenames = []
material_names = []
material_filenames = []
material_contributors = []
material_ratings = []
material_file_contents = ""
current_material_number = -1
bpy.types.Scene.auto_download_previews = bpy.props.BoolProperty(name = "Auto-Preview", description = "Automatically download material previews", default = True, options = {'SKIP_SAVE'})
bpy.types.Scene.cache_previews = bpy.props.BoolProperty(name = "Cache Previews", description = "Store preview images locally for faster loading", default = True, options = {'SKIP_SAVE'})
bpy.types.Scene.bcm_datablock = bpy.props.StringProperty(name = "Text Datablock", description = "Name of text datablock to write .bcm data to", default="bcm_file", options = {'SKIP_SAVE'})
bpy.types.Scene.bcm_save_location = bpy.props.StringProperty(name = "Save location", description = "Directory to save .bcm files in", default=bpy.utils.user_resource('DATAFILES', path="material-library" + os.sep + "my-materials" + os.sep, create=True), options = {'SKIP_SAVE'}, subtype="DIR_PATH")
bpy.types.Scene.bcm_open_location = bpy.props.StringProperty(name = "Open location", description = "Location of .bcm file to open", default=bpy.utils.user_resource('DATAFILES', path="material-library" + os.sep + "my-materials" + os.sep, create=True), options = {'SKIP_SAVE'})
category_enum_items = [("None0", "None", "No category selected")]
bpy.types.Scene.material_category = bpy.props.EnumProperty(name = "", items = category_enum_items, description = "Choose a category", options = {'SKIP_SAVE'})
prev_category = "None0"
subcategory_enum_items = [("None0", "None", "No Subcategory Selected")]
bpy.types.Scene.material_subcategory = bpy.props.EnumProperty(name = "", items = subcategory_enum_items, description = "Choose a subcategory", options = {'SKIP_SAVE'})
class OnlineMaterialLibraryPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Online Material Library"
bl_idname = "OnlineMaterialLibraryPanel"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "material"
def draw(self, context):
global show_success_message
global show_success_message_timeout
global current_material_number
global prev_category
layout = self.layout
if str(context.scene.render.engine) == "CYCLES":
#Cycles is enabled!
if mat_lib_contents == "" or mat_lib_contents == "Please refresh.":
#Material Library Contents variable is empty -- ask user to refresh
row = layout.row()
#Main Indicator
row.label(text="Welcome to the online CC0 Material Library!", icon='INFO')
row = layout.row()
row.operator("material.libraryconnect", text="Connect", icon='WORLD')
else:
row = layout.row()
if mat_lib_contents[1:8] == "library":
#We have a valid material library
if category_type is not "info" and category_type is not "settings" and category_type is not "tools":
row = layout.row(align=True)
row.alignment = 'EXPAND'
row.prop(bpy.context.scene, "material_category")
#Here we check if the user has changed the category, if so, update.
if prev_category != bpy.context.scene.material_category:
prev_category = bpy.context.scene.material_category
libraryCategoryUpdate()
if category_type == "none":
#Not browsing category
row = layout.row()
row.label(text="%d categories." % mat_lib_categories)
row.operator("material.librarytools", text="Tools", icon='MODIFIER')
row = layout.row(align=True)
row.alignment = 'EXPAND'
row.operator("material.libraryinfo", text="Info", icon='INFO')
row.operator("material.librarysettings", text="Settings", icon='SETTINGS')
elif category_type == "info":
row.label(text="Add-on Info", icon='INFO')
row.operator("material.libraryhome", text="", icon='LOOP_BACK')
row = layout.row()
row.operator("wm.url_open", text="All materials are CC0 - learn more.", emboss=False).url = "http://creativecommons.org/publicdomain/zero/1.0/"
row = layout.row()
row.operator("wm.url_open", text="Material previews generated with B.M.P.S.", emboss=False).url = "https://svn.blender.org/svnroot/bf-blender/trunk/lib/tests/rendering/cycles/bmps.blend"
row = layout.row()
row.operator("wm.url_open", text="B.M.P.S. created by Robin \"tuqueque\" Marín", emboss=False).url = "http://blenderartists.org/forum/showthread.php?151903-b.m.p.s.-1.5!"
elif category_type == "settings":
row.label(text="Library Settings", icon='SETTINGS')
row.operator("material.libraryhome", text="", icon='LOOP_BACK')
row = layout.row()
row.prop(bpy.context.scene, "auto_download_previews")
row = layout.row()
row.prop(bpy.context.scene, "cache_previews")
row.operator("material.cacheclearpreviews", text="Clear Cache", icon='CANCEL')
elif category_type == "tools":
row.label(text="Material Tools", icon='MODIFIER')
row.operator("material.libraryhome", text="", icon='LOOP_BACK')
row = layout.row()
row.label(text="Save active material in .bcm format:")
row = layout.row(align=True)
row.alignment = 'EXPAND'
row.prop(bpy.context.scene, "bcm_datablock", text="", icon="TEXT")
row.operator("material.convertcycles", text="Convert to .bcm", icon='MATERIAL_DATA')
row = layout.row(align=True)
row.alignment = 'EXPAND'
row.prop(context.scene, "bcm_save_location", text="")
row.operator("material.convertcycles", text="Save as .bcm", icon='DISK_DRIVE').save_location = context.scene.bcm_save_location
row = layout.row()
row.label(text="Open a local .bcm file:")
row = layout.row()
col = row.column(align=True)
col.alignment = 'EXPAND'
colrow = col.row()
colrow.prop(context.scene, "bcm_open_location", text="")
colrow.operator("buttons.file_browse", text="", icon='FILESEL').relative_path = False
colrow = col.row(align=True)
colrow.alignment = 'EXPAND'
colrow.operator("material.libraryadd", text="Add to materials", icon='ZOOMIN').open_location = context.scene.bcm_open_location
colrow.operator("material.libraryapply", text="Apply to active", icon='PASTEDOWN').open_location = context.scene.bcm_open_location
elif category_type == "category":
#Browsing category - show materials
row = layout.row()
matwrap = row.box()
i = 0
while i < category_materials:
if (i == current_material_number):
matwraprow = matwrap.row()
matwrapbox = matwraprow.box()
matwrapboxrow = matwrapbox.row()
matwrapboxrow.operator("material.viewmaterial", text=material_names[i], icon='MATERIAL', emboss=False).material = i
matwrapboxrowcol = matwrapboxrow.column()
matwrapboxrowcolrow = matwrapboxrowcol.row()
matwrapboxrowcolrow.operator("material.viewmaterial", text="", icon='BLANK1', emboss=False).material = i
matwrapboxrowcolrow.operator("material.viewmaterial", text="", icon='BLANK1', emboss=False).material = i
matwrapboxrowcol = matwrapboxrow.column()
matwrapboxrowcolrow = matwrapboxrowcol.row()
matwrapboxrowcolrowsplit = matwrapboxrowcolrow.split(percentage=0.8)
matwrapboxrowcolrowsplitrow = matwrapboxrowcolrowsplit.row()
#Ratings
e = 0
while e < material_ratings[i]:
matwrapboxrowcolrowsplitrow.operator("material.viewmaterial", text="", icon='SOLO_ON', emboss=False).material = i
e = e + 1
if material_ratings[i] is not 5:
e = 0
while e < (5 - material_ratings[i]):
matwrapboxrowcolrowsplitrow.operator("material.viewmaterial", text="", icon='SOLO_OFF', emboss=False).material = i
e = e + 1
else:
matwraprow = matwrap.row()
matwrapcol = matwraprow.column()
matwrapcolrow = matwrapcol.row()
matwrapcolrow.operator("material.viewmaterial", text=material_names[i], icon='MATERIAL', emboss=False).material = i
matwrapcolrowcol = matwrapcolrow.column()
matwrapcolrowcolrow = matwrapcolrowcol.row()
matwrapcolrowcolrow.operator("material.viewmaterial", text="", icon='BLANK1', emboss=False).material = i
matwrapcolrowcolrow.operator("material.viewmaterial", text="", icon='BLANK1', emboss=False).material = i
matwrapcolrowcol = matwrapcolrow.column()
matwrapcolrowcolrow = matwrapcolrowcol.row()
matwrapcolrowcolrowsplit = matwrapcolrowcolrow.split(percentage=0.8)
matwrapcolrowcolrowsplitrow = matwrapcolrowcolrowsplit.row()
#Ratings
e = 0
while e < material_ratings[i]:
matwrapcolrowcolrowsplitrow.operator("material.viewmaterial", text="", icon='SOLO_ON', emboss=False).material = i
e = e + 1
if material_ratings[i] is not 5:
e = 0
while e < (5 - material_ratings[i]):
matwrapcolrowcolrowsplitrow.operator("material.viewmaterial", text="", icon='SOLO_OFF', emboss=False).material = i
e = e + 1
i = i + 1
if current_material_number is not -1:
#Display selected material's info
row = layout.row()
infobox = row.box()
inforow = infobox.row()
extra_info = ""
if bpy.context.object.active_material:
if material_names[current_material_number] == bpy.context.object.active_material.name:
if material_names[current_material_number] in bpy.data.materials:
extra_info = " Exists! Will be overwritten."
else:
if material_names[current_material_number] in bpy.data.materials:
extra_info = " Exists! Will be overwritten."
inforow.label(text=(material_names[current_material_number] + extra_info))
inforow.operator("material.viewmaterial", text="", icon='PANEL_CLOSE').material = -1
inforow = infobox.row()
#Display a preview
if bpy.data.textures.find("mat_lib_preview_texture") == -1:
bpy.data.textures.new("mat_lib_preview_texture", "IMAGE")
preview_texture = bpy.data.textures["mat_lib_preview_texture"]
inforowcol = inforow.column(align=True)
inforowcol.alignment = 'EXPAND'
if material_contributors[current_material_number] != "Unknown" and material_contributors[current_material_number] != "Anonymous":
inforowcolrow = inforowcol.row()
inforowcolrow.label(text="By %s." % material_contributors[current_material_number])
else:
inforowcolrow = inforowcol.row()
inforowcolrow.label(text="Contributor Unknown.")
inforowcolrow = inforowcol.row()
inforowcolrow.template_preview(preview_texture)
else:
preview_texture = bpy.data.textures['mat_lib_preview_texture']
inforowcol = inforow.column(align=True)
inforowcol.alignment = 'EXPAND'
if material_contributors[current_material_number] != "Unknown" and material_contributors[current_material_number] != "Anonymous":
inforowcolrow = inforowcol.row()
inforowcolrow.label(text="By %s." % material_contributors[current_material_number])
else:
inforowcolrow = inforowcol.row()
inforowcolrow.label(text="Author Unknown")
inforowcolrow = inforowcol.row()
inforowcolrow.template_preview(preview_texture)
inforowcol = inforow.column()
inforowcolrow = inforowcol.row()
inforowcolcol = inforowcol.column(align=True)
inforowcolcol.alignment = 'EXPAND'
if bpy.context.scene.auto_download_previews == False:
mat_button = inforowcolcol.operator("material.downloadpreview", text="Download Preview", icon='IMAGE_COL')
mat_button.name = material_names[current_material_number]
mat_button.filename = material_filenames[current_material_number]
mat_button.library = library
#Display "Add" or "Overwrite" button
mat_button = inforowcolcol.operator("material.libraryadd", text="Add to materials", icon='ZOOMIN')
mat_button.name = material_names[current_material_number]
mat_button.filename = material_filenames[current_material_number]
mat_button.library = library
#Display "Paste" button
mat_button = inforowcolcol.operator("material.libraryapply", text="Apply to active", icon='PASTEDOWN')
mat_button.name = material_names[current_material_number]
mat_button.filename = material_filenames[current_material_number]
mat_button.library = library
#Display "Save" button
mat_button = inforowcolcol.operator("material.librarysave", text="Save to disk", icon='DISK_DRIVE')
mat_button.name = material_names[current_material_number]
mat_button.filename = material_filenames[current_material_number]
mat_button.library = library
elif category_type == "subcategory":
#Browsing subcategory - show materials
row = layout.row()
matwrap = row.box()
i = 0
while i < category_materials:
if (i == current_material_number):
matwraprow = matwrap.row()
matwrapbox = matwraprow.box()
matwrapboxrow = matwrapbox.row()
matwrapboxrow.operator("material.viewmaterial", text=material_names[i], icon='MATERIAL', emboss=False).material = i
matwrapboxrowcol = matwrapboxrow.column()
matwrapboxrowcolrow = matwrapboxrowcol.row()
matwrapboxrowcolrow.operator("material.viewmaterial", text="", icon='BLANK1', emboss=False).material = i
matwrapboxrowcolrow.operator("material.viewmaterial", text="", icon='BLANK1', emboss=False).material = i
matwrapboxrowcol = matwrapboxrow.column()
matwrapboxrowcolrow = matwrapboxrowcol.row()
matwrapboxrowcolrowsplit = matwrapboxrowcolrow.split(percentage=0.8)
matwrapboxrowcolrowsplitrow = matwrapboxrowcolrowsplit.row()
#Ratings
e = 0
while e < material_ratings[i]:
matwrapboxrowcolrowsplitrow.operator("material.viewmaterial", text="", icon='SOLO_ON', emboss=False).material = i
e = e + 1
if material_ratings[i] is not 5:
e = 0
while e < (5 - material_ratings[i]):
matwrapboxrowcolrowsplitrow.operator("material.viewmaterial", text="", icon='SOLO_OFF', emboss=False).material = i
e = e + 1
else:
matwraprow = matwrap.row()
matwrapcol = matwraprow.column()
matwrapcolrow = matwrapcol.row()
matwrapcolrow.operator("material.viewmaterial", text=material_names[i], icon='MATERIAL', emboss=False).material = i
matwrapcolrowcol = matwrapcolrow.column()
matwrapcolrowcolrow = matwrapcolrowcol.row()
matwrapcolrowcolrow.operator("material.viewmaterial", text="", icon='BLANK1', emboss=False).material = i
matwrapcolrowcolrow.operator("material.viewmaterial", text="", icon='BLANK1', emboss=False).material = i
matwrapcolrowcol = matwrapcolrow.column()
matwrapcolrowcolrow = matwrapcolrowcol.row()
matwrapcolrowcolrowsplit = matwrapcolrowcolrow.split(percentage=0.8)
matwrapcolrowcolrowsplitrow = matwrapcolrowcolrowsplit.row()
#Ratings
e = 0
while e < material_ratings[i]:
matwrapcolrowcolrowsplitrow.operator("material.viewmaterial", text="", icon='SOLO_ON', emboss=False).material = i
e = e + 1
if material_ratings[i] is not 5:
e = 0
while e < (5 - material_ratings[i]):
matwrapcolrowcolrowsplitrow.operator("material.viewmaterial", text="", icon='SOLO_OFF', emboss=False).material = i
e = e + 1
i = i + 1
if current_material_number is not -1:
#Display selected material's info
row = layout.row()
infobox = row.box()
inforow = infobox.row()
inforow.label(text=material_names[current_material_number])
inforow.operator("material.viewmaterial", text="", icon='PANEL_CLOSE').material = -1
inforow = infobox.row()
##Display a preview
if bpy.data.textures.find("mat_lib_preview_texture") == -1:
bpy.data.textures.new("mat_lib_preview_texture", "IMAGE")
preview_texture = bpy.data.textures["mat_lib_preview_texture"]
inforowcol = inforow.column(align=True)
inforowcol.alignment = 'EXPAND'
inforowcolrow = inforowcol.row()
inforowcolrow.operator("material.downloadpreview", text="Download Preview", icon='IMAGE_COL')
inforowcolrow = inforowcol.row()
inforowcolrow.template_preview(preview_texture)
else:
preview_texture = bpy.data.textures['mat_lib_preview_texture']
inforowcol = inforow.column(align=True)
inforowcol.alignment = 'EXPAND'
inforowcolrow = inforowcol.row()
inforowcolrow.operator("material.downloadpreview", text="Download Preview", icon='IMAGE_COL')
inforowcolrow = inforowcol.row()
inforowcolrow.template_preview(preview_texture)
inforowcol = inforow.column()
inforowcolrow = inforowcol.row()
if bpy.data.materials.find(material_names[current_material_number]) is not -1:
inforowcolrow.label(text="Material exists", icon='ERROR')
if material_contributors[current_material_number] == "Unknown" or material_contributors[current_material_number] == "Anonymous":
inforowcolrow = inforowcol.row()
else:
inforowcolrow = inforowcol.row()
inforowcolrow.label(text="By %s." % material_contributors[current_material_number])
inforowcolrow = inforowcol.row()
if bpy.data.materials.find(material_names[current_material_number]) is not -1:
inforowcolrow.label(text="\"Add\" will overwrite.")
inforowcolcol = inforowcol.column(align=True)
inforowcolcol.alignment = 'EXPAND'
#Display "Add" or "Overwrite" button
mat_button = inforowcolcol.operator("material.libraryadd", text="Add to materials", icon='ZOOMIN')
mat_button.name = material_names[current_material_number]
mat_button.filename = material_filenames[current_material_number]
mat_button.library = library
#Display "Paste" button
mat_button = inforowcolcol.operator("material.libraryapply", text="Apply to active", icon='PASTEDOWN')
mat_button.name = bpy.context.object.active_material.name
mat_button.filename = material_filenames[current_material_number]
mat_button.library = library
#Display "Save" button
mat_button = inforowcolcol.operator("material.librarysave", text="Save to disk", icon='DISK_DRIVE')
mat_button.name = bpy.context.object.active_material.name
mat_button.filename = material_filenames[current_material_number]
mat_button.library = library
else:
#We do not have a valid material library. Bummer.
row.label(text="Could not retrieve material library.", icon='CANCEL')
row = layout.row()
row.label(text=mat_lib_contents)
row = layout.row()
row.operator("material.libraryconnect", text="Attempt Reconnect", icon='WORLD')
else:
#Dude, you gotta switch to Cycles to use this.
row = layout.row()
row.label(text="Sorry, Cycles only at the moment.",icon='ERROR')
class libraryCategory:
def __init__(self, title, folder):
self.title = title
self.folder = folder
self.materials = []
class libraryMaterial:
def __init__(self, name, href, contrib, stars):
self.name = name
self.href = href
self.contrib = contrib
self.stars = stars
def handleCategories(categories):
for index, category in enumerate(categories):
handleCategory(category, index)
def handleCategory(category, index):
print ('\n\n-Category "' + category.attributes['title'].value + '"; located in folder "/' + category.attributes['folder'].value + '/".')
library_data.append(libraryCategory(category.attributes['title'].value, category.attributes['folder'].value))
handleMaterials(category.getElementsByTagName("material"), index)
def handleMaterials(materials, index):
for material in materials:
handleMaterial(material, index)
def handleMaterial(material, index):
library_data[index].materials.append(libraryMaterial(material.attributes['name'].value, material.attributes['href'].value, material.attributes['contrib'].value, int(material.attributes['stars'].value)))
print ('\n -Material "' + material.attributes['name'].value + '"\n -Filename: "' + material.attributes['href'].value + '.bcm"\n -Rating: ' + material.attributes['stars'].value + ' stars\n -Contributed by "' + material.attributes['contrib'].value + '"')
class LibraryConnect(bpy.types.Operator):
'''Connect to the online material library'''
bl_idname = "material.libraryconnect"
bl_label = "Connect to the online material library"
def execute(self, context):
global library_data
global mat_lib_contents
global mat_lib_categories
global mat_lib_category_names
global mat_lib_category_types
global mat_lib_category_filenames
global category_enum_items
global subcategory_enum_items
global show_success_message
global show_success_message_timeout
global prev_category
#Pre-create file
if not os.path.exists(bpy.utils.user_resource('DATAFILES', path="material-library" + os.sep, create=True) + "mat_lib_preview_image.jpg"):
f = open(bpy.utils.user_resource('DATAFILES', path="material-library" + os.sep, create=True) + "mat_lib_preview_image.jpg", 'w+b')
f.close()
#Connect and download
connection = http.client.HTTPConnection("peter.cassetta.info")
if library == "release":
connection.request("GET", "/material-library/release/cycles/index.xml")
else:
connection.request("GET", "/material-library/testing/cycles/index.xml")
#Format nicely
mat_lib_contents = str(connection.getresponse().read())
mat_lib_contents = mat_lib_contents.replace("b'<?xml version=\"1.0\" encoding=\"UTF-8\"?>",'')
mat_lib_contents = mat_lib_contents.replace("\\r\\n",'')
mat_lib_contents = mat_lib_contents.replace("\\t",'')[:-1]
mat_lib_contents = mat_lib_contents.replace("\\",'')
dom = xml.dom.minidom.parseString(mat_lib_contents)
print ("\n\n---Material Library---")
categories = dom.getElementsByTagName("category")
handleCategories(categories)
mat_lib_category_names = []
mat_lib_category_filenames = []
for cat in library_data:
#Find category names
mat_lib_category_names.append(cat.title)
#Find category types
#NOTE: Will have to redo this.
#mat_lib_category_types = safeEval(mat_lib_contents[(mat_lib_contents.index('[types]') + 7):mat_lib_contents.index('[/types]')])
#Get category filenames
mat_lib_category_filenames.append(cat.folder)
#Find amount of categories
mat_lib_categories = len(mat_lib_category_names)
#Set enum items for category dropdown
category_enum_items = []
category_enum_items.append(("None0", "None", "No category selected"))
i = 0
while i < mat_lib_categories:
print (i)
category_enum_items.append(((mat_lib_category_names[i] + str(i + 1)), mat_lib_category_names[i], (mat_lib_category_names[i] + " category")))
i = i + 1
bpy.types.Scene.material_category = bpy.props.EnumProperty(name = "", items = category_enum_items, description = "Choose a category")
bpy.context.scene.material_category = "None0";
self.report({'INFO'}, "Retrieved library!")
return {'FINISHED'}
class LibraryInfo(bpy.types.Operator):
'''Display add-on info'''
bl_idname = "material.libraryinfo"
bl_label = "Display add-on info"
def execute(self, context):
global category_type
category_type = "info"
return {'FINISHED'}
class LibraryTools(bpy.types.Operator):
'''Display material tools'''
bl_idname = "material.librarytools"
bl_label = "Display material tools"
def execute(self, context):
global category_type
category_type = "tools"
return {'FINISHED'}
class LibrarySettings(bpy.types.Operator):
'''Display add-on settings'''
bl_idname = "material.librarysettings"
bl_label = "Display add-on settings"
def execute(self, context):
global category_type
category_type = "settings"
return {'FINISHED'}
class LibraryHome(bpy.types.Operator):
'''Go back'''
bl_idname = "material.libraryhome"
bl_label = "Go back"
def execute(self, context):
global category_type
category_type = "none"
return {'FINISHED'}
def libraryCategoryUpdate():
print("Updating Material Category.")
#Check if the category is None
if bpy.context.scene.material_category != "None0":
#Selected category is not None; select category.
global category_contents
global category_name
global category_filename
global category_materials
global parent_category_contents
global parent_category_name
global parent_category_filename
global parent_category_categories
global parent_category_names
global parent_category_filenames
global material_names
global material_filenames
global material_contributors
global material_ratings
global current_material_number
global category_type
i = 0
while i < len(category_enum_items):
if category_enum_items[i][0] == bpy.context.scene.material_category:
#Set category filename for refresh button
category_filename = mat_lib_category_filenames[i - 1]
#Set category name for header
category_name = mat_lib_category_names[i - 1]
category_index = i - 1
i = i + 1
if True:
current_material_number = -1
material_names = []
material_filenames = []
material_contributors = []
material_ratings = []
for mat in library_data[category_index].materials:
#Get material names
material_names.append(mat.name)
#Get material filenames
material_filenames.append(mat.href)
#Get material contributors
material_contributors.append(mat.contrib)
#Get material ratings
material_ratings.append(mat.stars)
#Set amount of materials in selected category
category_materials = len(material_names)
category_type = "category"
elif "parent" == "parent":
current_material_number = -1
#Find category names
parent_category_names = safeEval(parent_category_contents[(parent_category_contents.index('[names]') + 7):parent_category_contents.index('[/names]')])
#Get category filenames
parent_category_filenames = safeEval(parent_category_contents[(parent_category_contents.index('[filenames]') + 11):parent_category_contents.index('[/filenames]')])
#Set parent category name for header
parent_category_name = self.name
#Set parent category filename
parent_category_filename = self.filename
#Set amount of categories in parent category
parent_category_categories = len(parent_category_names)
category_type = "parent"
elif "subcategory" == "subcategory":
current_material_number = -1
#Get material names
material_names = safeEval(category_contents[(category_contents.index("[names]") + 7):category_contents.index("[/names]")])
#Get material filenames
material_filenames = safeEval(category_contents[(category_contents.index("[filenames]") + 11):category_contents.index("[/filenames]")])
#Get material contributors
material_contributors = safeEval(category_contents[(category_contents.index("[contributors]") + 14):category_contents.index("[/contributors]")])
#Get material ratings
material_ratings = safeEval(category_contents[(category_contents.index("[ratings]") + 9):category_contents.index("[/ratings]")])
#Set category name for header
category_name = self.name
#Set category filename for refresh button
category_filename = self.filename
#Set amount of materials in selected category
category_materials = len(material_names)
category_type = "subcategory"
else:
self.report({'ERROR'}, "Invalid category! See console for details.")
print ("Invalid category!")
print (category_contents)
else:
#Selected category is None
parent_category_contents = "None"
category_contents = "None"
current_material_number = -1
category_type = "none"
class ViewMaterial(bpy.types.Operator):
'''View material details'''
bl_idname = "material.viewmaterial"
bl_label = "view material details"
material = bpy.props.IntProperty()
def execute(self, context):
global current_material_number
current_material_number = self.material
if bpy.context.scene.auto_download_previews == True:
if self.material != -1:
print("Auto-download previews on.")
bpy.ops.material.downloadpreview(name=material_names[self.material], filename=material_filenames[self.material], library=library)
return {'FINISHED'}
class CacheClearPreviews(bpy.types.Operator):
'''Delete all cached previews'''
bl_idname = "material.cacheclearpreviews"
bl_label = "clear preview cache"
def execute(self, context):
for root, dirs, files in os.walk(bpy.utils.user_resource('DATAFILES') + "material-library" + os.sep + "testing" + os.sep + "cycles" + os.sep):
for name in files:
if ".jpg" in name:
print("Deleting \"" + os.path.join(root, name) + "\".")
os.remove(os.path.join(root, name))
self.report({'INFO'}, "Preview cache cleared.")
return {'FINISHED'}
class DownloadPreview(bpy.types.Operator):
'''Download Preview'''
bl_idname = "material.downloadpreview"
bl_label = "download preview from library"
name = bpy.props.StringProperty()
filename = bpy.props.StringProperty()
library = bpy.props.StringProperty()
def execute(self, context):
global parent_category_filename
global category_filename
#Check for a cached preview
if not os.path.exists(bpy.utils.user_resource('DATAFILES', path="material-library" + os.sep + self.library + os.sep + "cycles" + os.sep + category_filename + os.sep, create=True) + self.filename + ".jpg"):
#This preview doesn't exist yet; let's download it.
connection = http.client.HTTPConnection("peter.cassetta.info")
if category_type == "subcategory":
if self.library == "release":
connection.request("GET", "/material-library/release/cycles/" + parent_category_filename + "/" + category_filename + "/" + self.filename + ".jpg")
else:
connection.request("GET", "/material-library/testing/cycles/" + parent_category_filename + "/" + category_filename + "/" + self.filename + ".jpg")
else:
if self.library == "release":
connection.request("GET", "/material-library/release/cycles/" + category_filename + "/" + self.filename + ".jpg")
else:
connection.request("GET", "/material-library/testing/cycles/" + category_filename + "/" + self.filename + ".jpg")
response = connection.getresponse().read()
f = open(bpy.utils.user_resource('DATAFILES', path="material-library" + os.sep, create=True) + "mat_lib_preview_image.jpg", 'w+b')
f.write(response)
f.close()
if bpy.context.scene.cache_previews:
#We want to cache previews, so let's save the preview in the appropriate location.
#Also, we have to be sure that each folder exists
f = open(bpy.utils.user_resource('DATAFILES', path="material-library" + os.sep + self.library + os.sep + "cycles" + os.sep + category_filename + os.sep, create=True) + self.filename + ".jpg", 'w+b')
f.write(response)
f.close()
else:
cached_image = open(bpy.utils.user_resource('DATAFILES', path="material-library" + os.sep + self.library + os.sep + "cycles" + os.sep + category_filename + os.sep) + self.filename + ".jpg", 'r+b')
response = cached_image.read()
cached_image.close()
f = open(bpy.utils.user_resource('DATAFILES', path="material-library" + os.sep, create=True) + "mat_lib_preview_image.jpg", 'w+b')
f.write(response)
f.close()
#Check if has texture
if bpy.data.images.find("mat_lib_preview_image.jpg") == -1:
bpy.ops.image.open(filepath=bpy.utils.user_resource('DATAFILES') + "material-library" + os.sep + "mat_lib_preview_image.jpg")
if "mat_lib_preview_texture" not in bpy.data.textures:
bpy.data.textures.new("mat_lib_preview_texture", "IMAGE")
if bpy.data.textures["mat_lib_preview_texture"].image != bpy.data.images["mat_lib_preview_image.jpg"]:
bpy.data.textures["mat_lib_preview_texture"].image = bpy.data.images["mat_lib_preview_image.jpg"]
bpy.data.images["mat_lib_preview_image.jpg"].reload()
bpy.ops.wm.redraw_timer()
bpy.data.scenes[bpy.context.scene.name].update()
bpy.data.scenes[bpy.context.scene.name].frame_set(bpy.data.scenes[bpy.context.scene.name].frame_current)
self.report({'INFO'}, "Preview downloaded.")
return {'FINISHED'}
class AddLibraryMaterial(bpy.types.Operator):
'''Add material to scene'''
bl_idname = "material.libraryadd"
bl_label = "add material to scene"
name = bpy.props.StringProperty()
filename = bpy.props.StringProperty()
library = bpy.props.StringProperty()
open_location = bpy.props.StringProperty()
def execute(self, context):
global material_file_contents
if self.open_location is "":
connection = http.client.HTTPConnection("peter.cassetta.info")
if category_type == "subcategory":
if self.library == "release":
connection.request("GET", "/material-library/release/cycles/" + parent_category_filename + "/" + category_filename + "/" + self.filename + ".bcm")
else:
connection.request("GET", "/material-library/testing/cycles/" + parent_category_filename + "/" + category_filename + "/" + self.filename + ".bcm")
else:
if self.library == "release":
connection.request("GET", "/material-library/release/cycles/" + category_filename + "/" + self.filename + ".bcm")
else:
connection.request("GET", "/material-library/testing/cycles/" + category_filename + "/" + self.filename + ".bcm")
material_file_contents = str(connection.getresponse().read())
material_file_contents = material_file_contents[material_file_contents.index("cyclesmat"):-1]
print (material_file_contents)
name = self.name
else:
if ".bcm" in self.open_location:
bcm_file = open(self.open_location, mode="r", encoding="UTF-8")
material_file_contents = bcm_file.read()
bcm_file.close()
material_file_contents = material_file_contents[material_file_contents.index("cyclesmat"):]
name = ""
for word in self.open_location.split(os.sep)[-1][:-4].split("_"):
if name is not "":
name += " "
name += word.capitalize()
else:
self.report({'ERROR'}, "Not a .bcm file.")
return {'CANCELLED'}
#Check file for validitity
if material_file_contents[0:9] == "cyclesmat":
print ("Valid material file!")
#Create new material
if bpy.data.materials.find(name) == -1:
bpy.data.materials.new(name)
bpy.data.materials[name].use_nodes = True
bpy.data.materials[name].node_tree.nodes.clear()
#Determine node amount
node_amount = int(material_file_contents[(material_file_contents.index("[nodeamount]") + 12):material_file_contents.index('[/nodeamount]')])
#Add nodes
addNodes(node_amount, name)
#Below here adds the links.
link_amount = int(material_file_contents[(material_file_contents.index("[linkamount]") + 12):material_file_contents.index('[/linkamount]')])
i = 0
while i < link_amount:
link_data = safeEval(material_file_contents[(material_file_contents.index("[link" + str(i) + "]") + (6 + len(str(i)))):material_file_contents.index("[/link" + str(i) + "]")])
print (link_data)
bpy.data.materials[name].node_tree.links.new(bpy.data.materials[name].node_tree.nodes[link_data[0]].inputs[link_data[1]], bpy.data.materials[name].node_tree.nodes[link_data[2]].outputs[link_data[3]])
i = i + 1
#Set viewport color
if "[viewcolor]" in material_file_contents:
view_color = (material_file_contents[(material_file_contents.index("[viewcolor][") + 12):material_file_contents.index('][/viewcolor]')]).split(',')
bpy.data.materials[name].diffuse_color.r = float(view_color[0])
bpy.data.materials[name].diffuse_color.g = float(view_color[1])
bpy.data.materials[name].diffuse_color.b = float(view_color[2])
#Set sample-as-lamp-ness
if "[samplelamp]" in material_file_contents:
if "True" in material_file_contents[(material_file_contents.index("[samplelamp]") + 12):material_file_contents.index('[/samplelamp]')]:
sample_lamp = True
else:
sample_lamp = False
bpy.data.materials[name].cycles.sample_as_light = sample_lamp
self.report({'INFO'}, "Material added.")
else:
self.report({'ERROR'}, "Invalid material file.")
return {'FINISHED'}
class ApplyLibraryMaterial(bpy.types.Operator):
'''Apply to active material'''
bl_idname = "material.libraryapply"
bl_label = "Apply to active material"
name = bpy.props.StringProperty()
filename = bpy.props.StringProperty()
library = bpy.props.StringProperty()
open_location = bpy.props.StringProperty()
def execute(self, context):
global material_file_contents
if bpy.context.active_object:
if self.open_location is "":
connection = http.client.HTTPConnection("peter.cassetta.info")
if category_type == "subcategory":
if self.library == "release":
connection.request("GET", "/material-library/release/cycles/" + parent_category_filename + "/" + category_filename + "/" + self.filename + ".bcm")
else:
connection.request("GET", "/material-library/testing/cycles/" + parent_category_filename + "/" + category_filename + "/" + self.filename + ".bcm")
else:
if self.library == "release":
connection.request("GET", "/material-library/release/cycles/" + category_filename + "/" + self.filename + ".bcm")
else:
connection.request("GET", "/material-library/testing/cycles/" + category_filename + "/" + self.filename + ".bcm")
material_file_contents = str(connection.getresponse().read())
material_file_contents = material_file_contents[material_file_contents.index("cyclesmat"):-1]
print (material_file_contents)
name = self.name
else:
if ".bcm" in self.open_location:
bcm_file = open(self.open_location, mode="r", encoding="UTF-8")
material_file_contents = bcm_file.read()
bcm_file.close()
material_file_contents = material_file_contents[material_file_contents.index("cyclesmat"):]
name = ""
for word in self.open_location.split(os.sep)[-1][:-4].split("_"):
if name is not "":
name += " "
name += word.capitalize()
else:
self.report({'ERROR'}, "Not a .bcm file.")
return {'CANCELLED'}
if bpy.context.active_object.active_material:
if bpy.data.materials.find(name) == -1:
bpy.context.active_object.active_material.name = name
else:
bpy.context.active_object.material_slots[bpy.context.active_object.active_material_index].material = bpy.data.materials[name]
else:
if bpy.data.materials.find(name) == -1:
bpy.data.materials.new(name)
if len(bpy.context.active_object.material_slots.keys()) is 0:
bpy.ops.object.material_slot_add()
bpy.context.active_object.material_slots[bpy.context.active_object.active_material_index].material = bpy.data.materials[name]
bpy.data.materials[name].use_nodes = True
#Check file for validitity
if material_file_contents[0:9] == "cyclesmat":
print ("Valid material file!")
#Create new material
if bpy.data.materials.find(name) == -1:
bpy.data.materials.new(name)
bpy.data.materials[name].use_nodes = True
bpy.data.materials[name].node_tree.nodes.clear()
#Determine node amount
node_amount = int(material_file_contents[(material_file_contents.index("[nodeamount]") + 12):material_file_contents.index('[/nodeamount]')])
#Add nodes
addNodes(node_amount, name)
#Below here adds the links.
link_amount = int(material_file_contents[(material_file_contents.index("[linkamount]") + 12):material_file_contents.index('[/linkamount]')])
i = 0
while i < link_amount:
link_data = safeEval(material_file_contents[(material_file_contents.index("[link" + str(i) + "]") + (6 + len(str(i)))):material_file_contents.index("[/link" + str(i) + "]")])
print (link_data)
bpy.data.materials[name].node_tree.links.new(bpy.data.materials[name].node_tree.nodes[link_data[0]].inputs[link_data[1]], bpy.data.materials[name].node_tree.nodes[link_data[2]].outputs[link_data[3]])
i = i + 1
#Set viewport color
if "[viewcolor]" in material_file_contents:
view_color = (material_file_contents[(material_file_contents.index("[viewcolor][") + 12):material_file_contents.index('][/viewcolor]')]).split(',')
bpy.data.materials[name].diffuse_color.r = float(view_color[0])
bpy.data.materials[name].diffuse_color.g = float(view_color[1])
bpy.data.materials[name].diffuse_color.b = float(view_color[2])
#Set sample-as-lamp-ness
if "[samplelamp]" in material_file_contents:
if "True" in material_file_contents[(material_file_contents.index("[samplelamp]") + 12):material_file_contents.index('[/samplelamp]')]:
sample_lamp = True
else:
sample_lamp = False
bpy.data.materials[name].cycles.sample_as_light = sample_lamp
self.report({'INFO'}, "Material applied.")
else:
self.report({'ERROR'}, "Invalid material file.")
else:
self.report({'ERROR'}, "No object selected!")
return {'FINISHED'}
class SaveLibraryMaterial(bpy.types.Operator):
'''Save material to disk'''
bl_idname = "material.librarysave"
bl_label = "save material to disk"
name = bpy.props.StringProperty()
filename = bpy.props.StringProperty()
library = bpy.props.StringProperty()
def execute(self, context):
#global material_file_contents
#
#connection = http.client.HTTPConnection("peter.cassetta.info")
#if self.library == "release":
# if category_type == "subcategory":
# connection.request("GET", "/material-library/release/" + category_filename + "/" + subcategory_filename + "/" + self.filename + ".bcm")
# else:
# connection.request("GET", "/material-library/release/" + category_filename + "/" + self.filename + ".bcm")
#else:
# if category_type == "subcategory":
# connection.request("GET", "/material-library/testing/" + category_filename + "/" + subcategory_filename + "/" + self.filename + ".bcm")
# else:
# connection.request("GET", "/material-library/testing/" + category_filename + "/" + self.filename + ".bcm")
#
#material_file_contents = str(connection.getresponse().read())[14:-1]
self.report({'ERROR'}, "Not working yet!")
return {'FINISHED'}
def addNodes(node_amount, mat):
i = 0
while i < node_amount:
print (node_amount)
node_data = safeEval(material_file_contents[(material_file_contents.index("[node" + str(i) + "]") + (6 + len(str(i)))):material_file_contents.index("[/node" + str(i) + "]")])
print (node_data)
#Below here checks the type of the node and adds the correct type
#INPUT TYPES
#This is totally crafty, but some of these nodes actually
# store their values as their output's default value!
if node_data[0] == "ATTRIBUTE":
print ("ATTRIBUTE")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.attribute_name = node_data[1]
node.location = safeEval(node_data[2])
elif node_data[0] == "CAMERA":
print ("CAMERA")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.location = safeEval(node_data[1])
elif node_data[0] == "FRESNEL":
print ("FRESNEL")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[0].default_value = float(node_data[1])
node.location = safeEval(node_data[2])
elif node_data[0] == "LAYER_WEIGHT":
print ("LAYER_WEIGHT")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[0].default_value = float(node_data[1])
node.location = safeEval(node_data[2])
elif node_data[0] == "LIGHT_PATH":
print ("LIGHT_PATH")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.location = safeEval(node_data[1])
elif node_data[0] == "NEW_GEOMETRY":
print ("NEW_GEOMETRY")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.location = safeEval(node_data[1])
elif node_data[0] == "RGB":
print ("RGB")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.outputs[0].default_value = safeEval(node_data[1])
node.location = safeEval(node_data[2])
elif node_data[0] == "TEX_COORD":
print ("TEX_COORD")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.location = safeEval(node_data[1])
elif node_data[0] == "VALUE":
print ("VALUE")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.outputs[0].default_value = float(node_data[1])
node.location = safeEval(node_data[2])
#OUTPUT TYPES
elif node_data[0] == "OUTPUT_LAMP":
print ("OUTPUT_LAMP")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.location = safeEval(node_data[1])
elif node_data[0] == "OUTPUT_MATERIAL":
print ("OUTPUT_MATERIAL")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.location = safeEval(node_data[1])
elif node_data[0] == "OUTPUT_WORLD":
print ("OUTPUT_WORLD")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.location = safeEval(node_data[1])
#SHADER TYPES
elif node_data[0] == "ADD_SHADER":
print ("ADD_SHADER")
addShader(mat, node_data[0], "", "", "", "", node_data[1])
elif node_data[0] == "BACKGROUND":
print ("BACKGROUND")
addShader(mat, node_data[0], "", node_data[1], node_data[2], "", node_data[3])
elif node_data[0] == "BSDF_DIFFUSE":
print ("BSDF_DIFFUSE")
addShader(mat, node_data[0], "", node_data[1], node_data[2], "", node_data[3])
elif node_data[0] == "BSDF_GLASS":
print ("BSDF_GLASS")
addShader(mat, node_data[0], node_data[1], node_data[2], node_data[3], node_data[4], node_data[5])
elif node_data[0] == "BSDF_GLOSSY":
print ("BSDF_GLOSSY")
addShader(mat, node_data[0], node_data[1], node_data[2], node_data[3], "", node_data[4])
elif node_data[0] == "BSDF_TRANSLUCENT":
print ("BSDF_TRANSLUCENT")
addShader(mat, node_data[0], "", node_data[1], "", "", node_data[2])
elif node_data[0] == "BSDF_TRANSPARENT":
print ("BSDF_TRANSPARENT")
addShader(mat, node_data[0], "", node_data[1], "", "", node_data[2])
elif node_data[0] == "BSDF_VELVET":
print ("BSDF_VELVET")
addShader(mat, node_data[0], "", node_data[1], node_data[2], "", node_data[3])
elif node_data[0] == "EMISSION":
print ("EMISSION")
addShader(mat, node_data[0], "", node_data[1], node_data[2], "", node_data[3])
elif node_data[0] == "HOLDOUT":
print ("HOLDOUT")
addShader(mat, node_data[0], "", "", "", "", node_data[1])
elif node_data[0] == "MIX_SHADER":
print ("MIX_SHADER")
addShader(mat, node_data[0], "", "", node_data[1], "", node_data[2])
#TEXTURE TYPES
elif node_data[0] == "TEX_CHECKER":
print ("TEX_CHECKER")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[1].default_value = safeEval(node_data[1])
node.inputs[2].default_value = safeEval(node_data[2])
node.inputs[3].default_value = float(node_data[3])
node.location = safeEval(node_data[4])
elif node_data[0] == "TEX_GRADIENT":
print ("TEX_GRADIENT")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.gradient_type = node_data[1]
node.location = safeEval(node_data[2])
elif node_data[0] == "TEX_IMAGE":
print ("TEX_IMAGE")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
#Need to download image somehow...
#node.image = node_data[1]
node.color_space = node_data[2]
node.location = safeEval(node_data[3])
elif node_data[0] == "TEX_MAGIC":
print ("TEX_MAGIC")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.turbulence_depth = int(node_data[1])
node.inputs[1].default_value = float(node_data[2])
node.inputs[2].default_value = float(node_data[3])
node.location = safeEval(node_data[4])
elif node_data[0] == "TEX_MUSGRAVE":
print ("TEX_MUSGRAVE")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.musgrave_type = node_data[1]
node.inputs[1].default_value = float(node_data[2])
node.inputs[2].default_value = float(node_data[3])
node.inputs[3].default_value = float(node_data[4])
node.inputs[4].default_value = float(node_data[5])
node.inputs[5].default_value = float(node_data[6])
node.inputs[6].default_value = float(node_data[7])
node.location = safeEval(node_data[8])
elif node_data[0] == "TEX_NOISE":
print ("TEX_NOISE")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[1].default_value = float(node_data[1])
node.inputs[2].default_value = float(node_data[2])
node.inputs[3].default_value = float(node_data[3])
node.location = safeEval(node_data[4])
elif node_data[0] == "TEX_SKY":
print ("TEX_SKY")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.sun_direction = safeEval(node_data[1])
node.turbidity = float(node_data[2])
node.location = safeEval(node_data[3])
elif node_data[0] == "TEX_VORONOI":
print ("TEX_VORONOI")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.coloring = node_data[1]
node.inputs[1].default_value = float(node_data[2])
node.location = safeEval(node_data[3])
elif node_data[0] == "TEX_WAVE":
print ("TEX_WAVE")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.wave_type = node_data[1]
node.inputs[1].default_value = float(node_data[2])
node.inputs[2].default_value = float(node_data[3])
node.inputs[3].default_value = float(node_data[4])
node.inputs[4].default_value = float(node_data[5])
node.location = safeEval(node_data[6])
#COLOR TYPES
elif node_data[0] == "BRIGHTCONTRAST":
print ("BRIGHTCONTRAST")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[0].default_value = safeEval(node_data[1])
node.inputs[1].default_value = float(node_data[2])
node.inputs[2].default_value = float(node_data[3])
node.location = safeEval(node_data[4])
elif node_data[0] == "GAMMA":
print ("GAMMA")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[0].default_value = safeEval(node_data[1])
node.inputs[1].default_value = float(node_data[2])
node.location = safeEval(node_data[3])
elif node_data[0] == "HUE_SAT":
print ("HUE_SAT")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[0].default_value = float(node_data[1])
node.inputs[1].default_value = float(node_data[2])
node.inputs[2].default_value = float(node_data[3])
node.inputs[3].default_value = float(node_data[4])
node.inputs[4].default_value = safeEval(node_data[5])
node.location = safeEval(node_data[6])
elif node_data[0] == "INVERT":
print ("INVERT")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[0].default_value = float(node_data[1])
node.inputs[1].default_value = safeEval(node_data[2])
node.location = safeEval(node_data[3])
elif node_data[0] == "MIX_RGB":
print ("MIX_RGB")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.blend_type = node_data[1]
node.inputs[0].default_value = float(node_data[2])
node.inputs[1].default_value = safeEval(node_data[3])
node.inputs[2].default_value = safeEval(node_data[4])
node.location = safeEval(node_data[5])
#VECTOR TYPES
elif node_data[0] == "MAPPING":
print ("MAPPING")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.translation = safeEval(node_data[1])
node.rotation = safeEval(node_data[2])
node.scale = safeEval(node_data[3])
if node_data[4] == "True":
node.use_min = True
node.min = node_data[5]
if node_data[6] == "True":
node.use_max = True
node.max = node_data[7]
node.inputs[0].default_value = safeEval(node_data[8])
node.location = safeEval(node_data[9])
elif node_data[0] == "NORMAL":
print ("NORMAL")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.outputs[0].default_value = safeEval(node_data[1])
node.inputs[0].default_value = safeEval(node_data[2])
node.location = safeEval(node_data[3])
elif node_data[0] == "COMBRGB":
print ("COMBRGB")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[0].default_value = float(node_data[1])
node.inputs[1].default_value = float(node_data[2])
node.inputs[2].default_value = float(node_data[3])
node.location = safeEval(node_data[4])
elif node_data[0] == "MATH":
print ("MATH")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.operation = node_data[1]
node.inputs[0].default_value = float(node_data[2])
node.inputs[1].default_value = float(node_data[3])
node.location = safeEval(node_data[4])
elif node_data[0] == "RGBTOBW":
print ("RGBTOBW")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[0].default_value = safeEval(node_data[1])
node.location = safeEval(node_data[2])
elif node_data[0] == "SEPRGB":
print ("SEPRGB")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.inputs[0].default_value = safeEval(node_data[1])
node.location = safeEval(node_data[2])
elif node_data[0] == "VALTORGB":
print ("VALTORGB")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.color_ramp.interpolation = node_data[1]
node.inputs[0].default_value = float(node_data[2])
k = 0
while k < (int(node_data[3]) * 2):
#There are three array elements before the first colorramp one, so k will be offset by 3
element = node.color_ramp.elements.new(float(node_data[(k + 4)]))
element.color = eval(node_data[(k + 5)])
k = k + 2
node.location = eval(node_data[-1])
elif node_data[0] == "VECT_MATH":
print ("VECT_MATH")
node = bpy.data.materials[mat].node_tree.nodes.new(node_data[0])
node.operation = node_data[1]
node.inputs[0].default_value = safeEval(node_data[2])
node.inputs[1].default_value = safeEval(node_data[3])
node.location = safeEval(node_data[4])
else:
print ("The material file contains the node name \"%s\", which is not known. The material file may contain a typo, or you may need to check for updates to this addon." % node_data[0])
i = i + 1
def addShader(mat, type, distribution_type, color, fac, ior, location):
shader = bpy.data.materials[mat].node_tree.nodes.new(type)
shader.location = safeEval(location)
if distribution_type is not "":
shader.distribution = distribution_type
if color is not "":
shader.inputs[0].default_value = safeEval(color)
if type == "MIX_SHADER":
shader.inputs[0].default_value = float(fac)
else:
if fac is not "":
shader.inputs[1].default_value = float(fac)
if ior is not "":
shader.inputs[2].default_value = float(ior)
def safeEval(code_string):
if code_string.find("=") == -1:
if code_string.find("{") == -1:
if code_string.find("}") == -1:
return (eval(code_string))
else:
print("Downloaded file contains some invalid characters.")
print(code_string)
else:
print("Downloaded file contains some invalid characters.")
print(code_string)
else:
print("Downloaded file contains some invalid characters.")
print(code_string)
class MaterialConvertCycles(bpy.types.Operator):
'''Convert active material to the .bcm format'''
bl_idname = "material.convertcycles"
bl_label = "Convert Cycles Material to .bcm"
save_location = bpy.props.StringProperty()
def execute(self, context):
global material_file_contents
if not bpy.context.active_object:
if not bpy.context.active_object.get("active_material"):
self.report({'ERROR'}, "No material selected!")
return {'FINISHED'}
self.report({'ERROR'}, "No object selected!")
return {'FINISHED'}
mat = bpy.context.active_object.active_material.name
if self.save_location is "":
if bpy.context.scene.bcm_datablock is not "":
txt = bpy.context.scene.bcm_datablock
else:
txt = "bcm_file"
if txt not in bpy.data.texts:
bpy.data.texts.new(txt)
else:
filename = mat.replace("(", "")
filename = filename.replace(")", "")
filename = filename.replace("!", "")
filename = filename.replace("@", "")
filename = filename.replace("#", "")
filename = filename.replace("$", "")
filename = filename.replace("%", "")
filename = filename.replace("&", "")
filename = filename.replace("*", "")
filename = filename.replace("/", "")
filename = filename.replace("|", "")
filename = filename.replace("\\", "")
filename = filename.replace("'", "")
filename = filename.replace("\"", "")
filename = filename.replace("?", "")
filename = filename.replace(";", "")
filename = filename.replace(":", "")
filename = filename.replace("[", "")
filename = filename.replace("]", "")
filename = filename.replace("{", "")
filename = filename.replace("}", "")
filename = filename.replace("`", "")
filename = filename.replace("~", "")
filename = filename.replace("+", "")
filename = filename.replace("=", "")
filename = filename.replace(".", "")
filename = filename.replace(",", "")
filename = filename.replace("<", "")
filename = filename.replace(">", "")
filename = filename.replace(" ", "_")
filename = filename.replace("-", "_")
filename = filename.lower()
material_file_contents = ("cyclesmat")
material_file_contents += ("\n[nodeamount]" + str(len(bpy.data.materials[mat].node_tree.nodes)) + "[/nodeamount]")
i = 0
while i < len(bpy.data.materials[mat].node_tree.nodes):
if "NodeGroup" in str(bpy.data.materials[mat].node_tree.nodes[i].items):
node_type = "GROUP"
else:
node_type = bpy.data.materials[mat].node_tree.nodes[i].type
#Write node start tag
material_file_contents += ("\n[node" + str(i) + "][")
#Write node type
material_file_contents += ("\"" + node_type + "\"")
#Write node data
writeNodeData(i, bpy.data.materials[mat].node_tree)
#Write node end tag
material_file_contents += ("][/node" + str(i) + "]")
i = i + 1
material_file_contents += ("\n[linkamount]" + str(len(bpy.data.materials[mat].node_tree.links)) + "[/linkamount]")
writeNodeLinks(bpy.data.materials[mat].node_tree)
material_file_contents += ("\n[viewcolor]")
#Red
red = str(bpy.data.materials[mat].diffuse_color[0])
red = red[:(6 + red.index("."))]
material_file_contents += ("[" + red + ", ")
#Green
green = str(bpy.data.materials[mat].diffuse_color[1])
green = green[:(6 + green.index("."))]
material_file_contents += (green + ", ")
#Blue
blue = str(bpy.data.materials[mat].diffuse_color[2])
blue = blue[:(6 + blue.index("."))]
material_file_contents += (blue + "]")
material_file_contents += ("[/viewcolor]")
material_file_contents += ("\n[samplelamp]" + str(bpy.data.materials[mat].cycles.sample_as_light) + "[/samplelamp]")
if self.save_location is "":
bpy.data.texts[txt].clear()
bpy.data.texts[txt].write(material_file_contents)
self.report({'INFO'}, "Material \"" + mat + "\" written to Text \"" + txt + "\" as .bcm")
else:
bcm_file = open(context.scene.bcm_save_location + filename + ".bcm", mode="w", encoding="UTF-8")
bcm_file.write(material_file_contents)
bcm_file.close()
self.report({'INFO'}, "Material \"" + mat + "\" saved to \"" + filename + ".bcm\"")
return {'FINISHED'}
def writeNodeData(node, node_tree):
global material_file_contents
if "NodeGroup" in str(node_tree.nodes[node].items):
node_type = "GROUP"
else:
node_type = node_tree.nodes[node].type
if node_type == "GROUP":
material_file_contents += (", \"GROUP NODE!\"")
#INPUT TYPES
elif node_type == "ATTRIBUTE":
material_file_contents += (", \"" + node_tree.nodes[node].attribute_name + "\"")
writeLocation(node, node_tree)
elif node_type == "CAMERA":
writeLocation(node, node_tree)
elif node_type == "FRESNEL":
writeFloat(node_tree.nodes[node].inputs[0].default_value)
writeLocation(node, node_tree)
elif node_type == "LAYER_WEIGHT":
writeFloat(node_tree.nodes[node].inputs[0].default_value)
writeLocation(node, node_tree)
elif node_type == "LIGHT_PATH":
writeLocation(node, node_tree)
elif node_type == "NEW_GEOMETRY":
writeLocation(node, node_tree)
elif node_type == "RGB":
#Red
red = str(node_tree.nodes[node].outputs[0].default_value[0])
red = red[:(6 + red.index("."))]
material_file_contents += (", \"[" + red + ", ")
#Green
green = str(node_tree.nodes[node].outputs[0].default_value[1])
green = green[:(6 + green.index("."))]
material_file_contents += (green + ", ")
#Blue
blue = str(node_tree.nodes[node].outputs[0].default_value[2])
blue = blue[:(6 + blue.index("."))]
material_file_contents += (blue + ", ")
#Alpha
material_file_contents += (str(node_tree.nodes[node].outputs[0].default_value[3]) + "]\"")
writeLocation(node, node_tree)
elif node_type == "TEX_COORD":
writeLocation(node, node_tree)
elif node_type == "VALUE":
writeFloat(node_tree.nodes[node].outputs[0].default_value)
writeLocation(node, node_tree)
#OUTPUT TYPES
elif node_type == "OUTPUT_LAMP":
writeLocation(node, node_tree)
elif node_type == "OUTPUT_MATERIAL":
writeLocation(node, node_tree)
elif node_type == "OUTPUT_WORLD":
writeLocation(node, node_tree)
#SHADER TYPES
elif node_type == "ADD_SHADER":
writeShader(node, node_tree, False, False, False, False)
elif node_type == "BACKGROUND":
writeShader(node, node_tree, False, True, True, False)
elif node_type == "BSDF_DIFFUSE":
writeShader(node, node_tree, False, True, True, False)
elif node_type == "BSDF_GLASS":
writeShader(node, node_tree, True, True, True, True)
elif node_type == "BSDF_GLOSSY":
writeShader(node, node_tree, True, True, True, False)
elif node_type == "BSDF_TRANSLUCENT":
writeShader(node, node_tree, False, True, False, False)
elif node_type == "BSDF_TRANSPARENT":
writeShader(node, node_tree, False, True, False, False)
elif node_type == "BSDF_VELVET":
writeShader(node, node_tree, False, True, True, False)
elif node_type == "EMISSION":
writeShader(node, node_tree, False, True, True, False)
elif node_type == "HOLDOUT":
writeShader(node, node_tree, False, False, False, False)
elif node_type == "MIX_SHADER":
writeShader(node, node_tree, False, False, True, False)
#TEXTURE TYPES
elif node_type == "TEX_CHECKER":
writeColor(node, node_tree, 1)
writeColor(node, node_tree, 2)
writeFloat(node_tree.nodes[node].inputs[3].default_value)
writeLocation(node, node_tree)
elif node_type == "TEX_GRADIENT":
material_file_contents += (", \"" + node_tree.nodes[node].gradient_type + "\"")
writeLocation(node, node_tree)
elif node_type == "TEX_IMAGE":
material_file_contents += (", \"\"")
#Need to upload image somehow?
material_file_contents += (", \"" + node_tree.nodes[node].color_space + "\"")
writeLocation(node, node_tree)
elif node_type == "TEX_MAGIC":
material_file_contents += (", \"" + str(node_tree.nodes[node].turbulence_depth) + "\"")
writeFloat(node_tree.nodes[node].inputs[1].default_value)
writeFloat(node_tree.nodes[node].inputs[2].default_value)
writeLocation(node, node_tree)
elif node_type == "TEX_MUSGRAVE":
material_file_contents += (", \"" + str(node_tree.nodes[node].musgrave_type) + "\"")
writeFloat(node_tree.nodes[node].inputs[1].default_value)
writeFloat(node_tree.nodes[node].inputs[2].default_value)
writeFloat(node_tree.nodes[node].inputs[3].default_value)
writeFloat(node_tree.nodes[node].inputs[4].default_value)
writeFloat(node_tree.nodes[node].inputs[5].default_value)
writeFloat(node_tree.nodes[node].inputs[6].default_value)
writeLocation(node, node_tree)
elif node_type == "TEX_NOISE":
writeFloat(node_tree.nodes[node].inputs[1].default_value)
writeFloat(node_tree.nodes[node].inputs[2].default_value)
writeFloat(node_tree.nodes[node].inputs[3].default_value)
writeLocation(node, node_tree)
elif node_type == "TEX_SKY":
sun_direction = node_tree.nodes[node].sun_direction
material_file_contents += (", \"[" + str(sun_direction[0]) + ", " + str(sun_direction[1]) + ", " + str(sun_direction[2]) + "]\"")
material_file_contents += (", \"" + str(node_tree.nodes[node].turbidity) + "\"")
writeLocation(node, node_tree)
elif node_type == "TEX_VORONOI":
material_file_contents += (", \"" + str(node_tree.nodes[node].coloring) + "\"")
writeFloat(node_tree.nodes[node].inputs[1].default_value)
writeLocation(node, node_tree)
elif node_type == "TEX_WAVE":
material_file_contents += (", \"" + str(node_tree.nodes[node].wave_type) + "\"")
writeFloat(node_tree.nodes[node].inputs[1].default_value)
writeFloat(node_tree.nodes[node].inputs[2].default_value)
writeFloat(node_tree.nodes[node].inputs[3].default_value)
writeFloat(node_tree.nodes[node].inputs[4].default_value)
writeLocation(node, node_tree)
#COLOR TYPES
elif node_type == "BRIGHTCONTRAST":
writeColor(node, node_tree, 0)
writeFloat(node_tree.nodes[node].inputs[1].default_value)
writeFloat(node_tree.nodes[node].inputs[2].default_value)
writeLocation(node, node_tree)
elif node_type == "GAMMA":
writeColor(node, node_tree, 0)
writeFloat(node_tree.nodes[node].inputs[1].default_value)
writeLocation(node, node_tree)
elif node_type == "HUE_SAT":
writeFloat(node_tree.nodes[node].inputs[0].default_value)
writeFloat(node_tree.nodes[node].inputs[1].default_value)
writeFloat(node_tree.nodes[node].inputs[2].default_value)
writeFloat(node_tree.nodes[node].inputs[3].default_value)
writeColor(node, node_tree, 4)
writeLocation(node, node_tree)
elif node_type == "MIX_RGB":
material_file_contents += (", \"" + node_tree.nodes[node].blend_type + "\"")
writeFloat(node_tree.nodes[node].inputs[0].default_value)
writeColor(node, node_tree, 1)
writeColor(node, node_tree, 2)
writeLocation(node, node_tree)
elif node_type == "INVERT":
writeFloat(node_tree.nodes[node].inputs[0].default_value)
writeColor(node, node_tree, 1)
writeLocation(node, node_tree)
#VECTOR TYPES
elif node_type == "MAPPING":
translation = node_tree.nodes[node].translation
rotation = node_tree.nodes[node].rotation
scale = node_tree.nodes[node].scale
material_file_contents += (", \"[" + str(translation[0]) + ", " + str(translation[1]) + ", " + str(translation[2]) + "]\"")
material_file_contents += (", \"[" + str(rotation[0]) + ", " + str(rotation[1]) + ", " + str(rotation[2]) + "]\"")
material_file_contents += (", \"[" + str(scale[0]) + ", " + str(scale[1]) + ", " + str(scale[2]) + "]\"")
min = node_tree.nodes[node].min
max = node_tree.nodes[node].max
material_file_contents += (", \"" + str(node_tree.nodes[node].use_min) + "\"")
material_file_contents += (", \"[" + str(min[0]) + ", " + str(min[1]) + ", " + str(min[2]) + "]\"")
material_file_contents += (", \"" + str(node_tree.nodes[node].use_max) + "\"")
material_file_contents += (", \"[" + str(max[0]) + ", " + str(max[1]) + ", " + str(max[2]) + "]\"")
vec = node_tree.nodes[node].inputs[0].default_value
material_file_contents += (", \"[" + str(vec[0]) + ", " + str(vec[1]) + ", " + str(vec[2]) + "]\"")
writeLocation(node, node_tree)
elif node_type == "NORMAL":
output = node_tree.nodes[node].outputs[0].default_value
input = node_tree.nodes[node].inputs[0].default_value
material_file_contents += (", \"[" + str(output[0])[:(6 + str(output[0]).index("."))] + ", " + str(output[1])[:(6 + str(output[1]).index("."))] + ", " + str(output[2])[:(6 + str(output[2]).index("."))] + "]\"")
material_file_contents += (", \"[" + str(input[0])[:(6 + str(input[0]).index("."))] + ", " + str(input[1])[:(6 + str(input[1]).index("."))] + ", " + str(input[2])[:(6 + str(input[2]).index("."))] + "]\"")
writeLocation(node, node_tree)
#CONVERTER TYPES
elif node_type == "COMBRGB":
writeFloat(node_tree.nodes[node].inputs[0].default_value)
writeFloat(node_tree.nodes[node].inputs[1].default_value)
writeFloat(node_tree.nodes[node].inputs[2].default_value)
writeLocation(node, node_tree)
elif node_type == "MATH":
material_file_contents += (", \"" + str(node_tree.nodes[node].operation) + "\"")
writeFloat(node_tree.nodes[node].inputs[0].default_value)
writeFloat(node_tree.nodes[node].inputs[1].default_value)
writeLocation(node, node_tree)
elif node_type == "SEPRGB":
writeColor(node, node_tree, 0)
writeLocation(node, node_tree)
elif node_type == "VALTORGB":
material_file_contents += (", \"" + str(node_tree.nodes[node].color_ramp.interpolation) + "\"")
writeFloat(node_tree.nodes[node].inputs[0].default_value)
material_file_contents += (", \"" + str(len(node_tree.nodes[node].color_ramp.elements)) + "\"")
k = 0
while k < len(node_tree.nodes[node].color_ramp.elements):
writeFloat(node_tree.nodes[node].color_ramp.elements[k].position)
#Red
red = str(node_tree.nodes[node].color_ramp.elements[k].color[0])
red = red[:(6 + red.index("."))]
material_file_contents += (", \"[" + red + ", ")
#Green
green = str(node_tree.nodes[node].color_ramp.elements[k].color[1])
green = green[:(6 + green.index("."))]
material_file_contents += (green + ", ")
#Blue
blue = str(node_tree.nodes[node].color_ramp.elements[k].color[2])
blue = blue[:(6 + blue.index("."))]
material_file_contents += (blue + ", ")
#Alpha
alpha = str(node_tree.nodes[node].color_ramp.elements[k].color[3])
alpha = alpha[:(6 + alpha.index("."))]
material_file_contents += (alpha + "]\"")
k = k + 1
writeLocation(node, node_tree)
elif node_type == "VECT_MATH":
material_file_contents += (", \"" + str(node_tree.nodes[node].operation) + "\"")
vect = node_tree.nodes[node].inputs[0].default_value
material_file_contents += (", \"[" + str(vect[0])[:(6 + str(vect[0]).index("."))] + ", " + str(vect[1])[:(6 + str(vect[1]).index("."))] + ", " + str(vect[2])[:(6 + str(vect[2]).index("."))] + "]\"")
vect = node_tree.nodes[node].inputs[1].default_value
material_file_contents += (", \"[" + str(vect[0])[:(6 + str(vect[0]).index("."))] + ", " + str(vect[1])[:(6 + str(vect[1]).index("."))] + ", " + str(vect[2])[:(6 + str(vect[2]).index("."))] + "]\"")
writeLocation(node, node_tree)
else:
material_file_contents += (" Unsupported node type! ")
def writeShader(node, node_tree, use_dist, use_color, use_fac, use_ior):
global material_file_contents
#Write distribution type
if use_dist:
material_file_contents += (", \"" + node_tree.nodes[node].distribution + "\"")
#Write color
if use_color == True:
writeColor(node, node_tree, 0)
#Write fac (it's Roughness/Strength/Sigma)
if use_fac == True:
if node_tree.nodes[node].type == "MIX_SHADER":
fac = str(node_tree.nodes[node].inputs[0].default_value)
material_file_contents += (", \"" + fac[:(6 + fac.index("."))] + "\"")
else:
fac = str(node_tree.nodes[node].inputs[1].default_value)
material_file_contents += (", \"" + fac[:(6 + fac.index("."))] + "\"")
#Write IOR
if use_ior == True:
material_file_contents += (", \"" + str(node_tree.nodes[node].inputs[2].default_value) + "\"")
#Write Location
writeLocation(node, node_tree)
def writeColor(node, node_tree, input):
global material_file_contents
#Red
red = str(node_tree.nodes[node].inputs[input].default_value[0])
red = red[:(6 + red.index("."))]
material_file_contents += (", \"[" + red + ", ")
#Green
green = str(node_tree.nodes[node].inputs[input].default_value[1])
green = green[:(6 + green.index("."))]
material_file_contents += (green + ", ")
#Blue
blue = str(node_tree.nodes[node].inputs[input].default_value[2])
blue = blue[:(6 + blue.index("."))]
material_file_contents += (blue + ", ")
#Alpha
material_file_contents += (str(node_tree.nodes[node].inputs[input].default_value[3]) + "]\"")
def writeLocation(node, node_tree):
global material_file_contents
#X location
material_file_contents += (", \"" + str(int(node_tree.nodes[node].location.x)))
#Y location
material_file_contents += (", " + str(int(node_tree.nodes[node].location.y)) + "\"")
def writeFloat(number):
global material_file_contents
material_file_contents += (", \"" + str(number)[:(6 + str(number).index("."))] + "\"")
def writeNodeLinks(node_tree):
global material_file_contents
#Loop through the links
i = 0
while i < len(node_tree.links):
material_file_contents += ("\n[link" + str(i) + "][")
to_node_name = node_tree.links[i].to_node.name
#Loop through nodes to check name
e = 0
while e < len(node_tree.nodes):
#Write the index if name matches
if to_node_name == node_tree.nodes[e].name:
material_file_contents += (str(e))
#Set input socket's name
to_socket = node_tree.links[i].to_socket.path_from_id()
material_file_contents += (", " + to_socket[(to_socket.index("inputs[") + 7):-1])
e = len(node_tree.nodes)
e = e + 1
from_node_name = node_tree.links[i].from_node.name
#Loop through nodes to check name
e = 0
while e < len(node_tree.nodes):
#Write the index if name matches
if from_node_name == node_tree.nodes[e].name:
material_file_contents += (", " + str(e))
#Set input socket's name
from_socket = node_tree.links[i].from_socket.path_from_id()
material_file_contents += (", " + from_socket[(from_socket.index("outputs[") + 8):-1])
e = len(node_tree.nodes)
e = e + 1
material_file_contents += ("][/link" + str(i) + "]")
i = i + 1
def register():
bpy.utils.register_class(OnlineMaterialLibraryPanel)
bpy.utils.register_class(LibraryConnect)
bpy.utils.register_class(LibraryInfo)
bpy.utils.register_class(LibrarySettings)
bpy.utils.register_class(LibraryTools)
bpy.utils.register_class(LibraryHome)
bpy.utils.register_class(ViewMaterial)
bpy.utils.register_class(CacheClearPreviews)
bpy.utils.register_class(DownloadPreview)
bpy.utils.register_class(AddLibraryMaterial)
bpy.utils.register_class(ApplyLibraryMaterial)
bpy.utils.register_class(SaveLibraryMaterial)
bpy.utils.register_class(MaterialConvertCycles)
def unregister():
bpy.utils.unregister_class(OnlineMaterialLibraryPanel)
bpy.utils.unregister_class(LibraryConnect)
bpy.utils.unregister_class(LibraryInfo)
bpy.utils.unregister_class(LibrarySettings)
bpy.utils.unregister_class(LibraryTools)
bpy.utils.unregister_class(LibraryHome)
bpy.utils.unregister_class(ViewMaterial)
bpy.utils.unregister_class(CacheClearPreviews)
bpy.utils.unregister_class(DownloadPreview)
bpy.utils.unregister_class(AddLibraryMaterial)
bpy.utils.unregister_class(ApplyLibraryMaterial)
bpy.utils.unregister_class(SaveLibraryMaterial)
bpy.utils.unregister_class(MaterialConvertCycles)
if __name__ == "__main__":
register()

File Metadata

Mime Type
text/x-python
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
9f/40/b3569c0ff63ba13047991429561c

Event Timeline