LuxBlend_0.1.py
author jensverwiebe
Sat Aug 08 00:48:19 2009 +0200 (2009-08-08)
changeset 338 a9ae8f25904a
parent 337 7754d0c5fc29
child 340 54697ccabb6f
permissions -rw-r--r--
changed all other RC-flags to RC5 too
     1 #!BPY
     2 # coding=utf-8
     3 """Registration info for Blender menus:
     4 Name: 'LuxBlend v0.6RC5 Exporter'
     5 Blender: 248
     6 Group: 'Render'
     7 Tooltip: 'Export/Render to LuxRender v0.6RC5 scene format (.lxs)'
     8 """
     9 #
    10 # ***** BEGIN GPL LICENSE BLOCK *****
    11 #
    12 # --------------------------------------------------------------------------
    13 # LuxBlend v0.6RC5 exporter
    14 # --------------------------------------------------------------------------
    15 #
    16 # Authors:
    17 # radiance, zuegs, ideasman42, luxblender, dougal2
    18 #
    19 # This program is free software; you can redistribute it and/or
    20 # modify it under the terms of the GNU General Public License
    21 # as published by the Free Software Foundation; either version 2
    22 # of the License, or (at your option) any later version.
    23 #
    24 # This program is distributed in the hope that it will be useful,
    25 # but WITHOUT ANY WARRANTY; without even the implied warranty of
    26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    27 # GNU General Public License for more details.
    28 #
    29 # You should have received a copy of the GNU General Public License
    30 # along with this program; if not, write to the Free Software Foundation,
    31 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    32 #
    33 # ***** END GPL LICENCE BLOCK *****
    34 # --------------------------------------------------------------------------
    35 
    36 
    37 
    38 
    39 ######################################################
    40 # Importing modules
    41 ######################################################
    42 
    43 import math
    44 import time
    45 import os
    46 import sys as osys
    47 import types
    48 import subprocess
    49 import Blender
    50 from Blender import Mesh, Scene, Object, Material, Texture, Window, sys, Draw, BGL, Mathutils, Lamp, Image
    51 
    52 
    53 
    54 
    55 ######################################################
    56 # Functions
    57 ######################################################
    58 
    59 # New name based on old with a different extension
    60 def newFName(ext):
    61     return Blender.Get('filename')[: -len(Blender.Get('filename').split('.', -1)[-1]) ] + ext
    62 
    63 
    64 # some helpers
    65 def luxstr(str):
    66     return str.replace("\\", "\\\\")
    67 
    68 
    69 ### relpath ##########################
    70 def relpath(base, target):
    71     if target[0:2] == "\\\\" or target[0:2] == "//":
    72         return target[2:len(target)]
    73     if not os.path.isabs(base):
    74         base = os.path.abspath(base)
    75     if not os.path.isabs(target):
    76         target = os.path.abspath(target)
    77     if os.sep == "\\":
    78         base = os.path.normcase(base)
    79         target = os.path.normcase(target)
    80     if base == os.sep:
    81         return '.' + target
    82     baselist = base.split(os.sep)
    83     if baselist[-1] == "":
    84         baselist = baselist[:-1]
    85     targetlist = target.split(os.sep)
    86     i = 0
    87     top = min([len(baselist), len(targetlist)])
    88     while i < top and baselist[i] == targetlist[i]:
    89         i+=1
    90     if i == 0:
    91         return os.sep.join(targetlist)
    92     if i == len(baselist):
    93         return os.sep.join(targetlist[i:])
    94     else:
    95         return ('..' + os.sep) * (len(baselist) - i) + os.sep.join(targetlist[i:])
    96 
    97 ### luxFilePath #####################
    98 lxs_filename = ""
    99 previewing = False
   100 def luxFilePath(filename):
   101     global lxs_filename, previewing
   102     scn = Scene.GetCurrent()
   103     pm = luxProp(scn, "pathmode", "absolute").get()
   104     if (pm=="absolute") or previewing: # absolute paths (the old / default mode)
   105         return filename
   106     elif pm=="relative": # relative paths
   107         base = os.path.dirname(lxs_filename)
   108         return relpath(base, filename)
   109     elif pm=="flat": # flat mode - only filename
   110         return os.path.basename(filename)
   111 
   112 
   113 
   114 ###### RGC ##########################
   115 def rg(col):
   116     scn = Scene.GetCurrent()
   117     if luxProp(scn, "RGC", "true").get()=="true":
   118         gamma = luxProp(scn, "film.gamma", 2.2).get()
   119     else:
   120         gamma = 1.0
   121     ncol = col**gamma
   122     if luxProp(scn, "colorclamp", "false").get()=="true":
   123         ncol = ncol * 0.9
   124         if ncol > 0.9:
   125             ncol = 0.9
   126         if ncol < 0.0:
   127             ncol = 0.0
   128     return ncol
   129 
   130 def texturegamma():
   131     scn = Scene.GetCurrent()
   132     if luxProp(scn, "RGC", "true").get()=="true":
   133         return luxProp(scn, "film.gamma", 2.2).get()
   134     else:
   135         return 1.0
   136 
   137 def exportMaterial(mat):
   138     str = "# Material '%s'\n" %mat.name
   139     return str+luxMaterial(mat)+"\n"
   140 
   141 
   142 def exportMaterialGeomTag(mat):
   143     return "%s\n"%(luxProp(mat, "link", "").get())
   144 
   145 
   146 
   147 
   148 ################################################################
   149 
   150 
   151 dummyMat = 2394723948 # random identifier for dummy material
   152 clayMat = None
   153 
   154 #-------------------------------------------------
   155 # getMaterials(obj)
   156 # helper function to get the material list of an object in respect of obj.colbits
   157 #-------------------------------------------------
   158 def getMaterials(obj, compress=False):
   159     global clayMat
   160     mats = [None]*16
   161     colbits = obj.colbits
   162     objMats = obj.getMaterials(1)
   163     data = obj.getData(mesh=1)
   164     try:
   165         dataMats = data.materials
   166     except:
   167         try:
   168             dataMats = data.getMaterials(1)
   169         except:
   170             dataMats = []
   171             colbits = 0xffff
   172     m = max(len(objMats), len(dataMats))
   173     if m>0:
   174         objMats.extend([None]*16)
   175         dataMats.extend([None]*16)
   176         for i in range(m):
   177             if (colbits & (1<<i) > 0):
   178                 mats[i] = objMats[i]
   179             else:
   180                 mats[i] = dataMats[i]
   181         if compress:
   182             mats = [m for m in mats if m]
   183     else:
   184         print "Warning: object %s has no material assigned"%(obj.getName())
   185         mats = []
   186     # clay option
   187     if luxProp(Scene.GetCurrent(), "clay", "false").get()=="true":
   188         if clayMat==None: clayMat = Material.New("lux_clayMat")
   189         for i in range(len(mats)):
   190             if mats[i]:
   191                 mattype = luxProp(mats[i], "type", "").get()
   192                 if (mattype not in ["portal","light","boundvolume"]): mats[i] = clayMat
   193     return mats
   194 
   195 
   196 
   197 ######################################################
   198 # luxExport class
   199 ######################################################
   200 
   201 class luxExport:
   202     #-------------------------------------------------
   203     # __init__
   204     # initializes the exporter object
   205     #-------------------------------------------------
   206     def __init__(self, scene):
   207         self.scene = scene
   208         self.camera = scene.objects.camera
   209         self.objects = []
   210         self.portals = []
   211         self.volumes = []
   212         self.meshes = {}
   213         self.materials = []
   214         self.lights = []
   215         self.duplis = set()
   216 
   217     #-------------------------------------------------
   218     # analyseObject(self, obj, matrix, name)
   219     # called by analyseScene to build the lists before export
   220     #-------------------------------------------------
   221     def analyseObject(self, obj, matrix, name, isOriginal=True, isDupli=False):
   222         light = False
   223         if (obj.users > 0):
   224             obj_type = obj.getType()
   225             if (obj.enableDupFrames and isOriginal):
   226                 for o, m in obj.DupObjects:
   227                     self.analyseObject(o, m, "%s.%s"%(name, o.getName()), False)    
   228             if (obj.enableDupGroup or obj.enableDupVerts or obj.enableDupFaces):
   229                 self.duplis.add(obj)
   230                 for o, m in obj.DupObjects:
   231                     self.analyseObject(o, m, "%s.%s"%(name, o.getName()), True, True)    
   232             elif ((isDupli or (not obj.getParent() in self.duplis)) and ((obj_type == "Mesh") or (obj_type == "Surf") or (obj_type == "Curve") or (obj_type == "Text"))):
   233                 mats = getMaterials(obj)
   234                 if (len(mats)>0) and (mats[0]!=None) and ((mats[0].name=="PORTAL") or (luxProp(mats[0], "type", "").get()=="portal")):
   235                     self.portals.append([obj, matrix])
   236                 elif (len(mats)>0) and (luxProp(mats[0], "type", "").get()=="boundvolume"):
   237                     self.volumes.append([obj, matrix])
   238                 else:
   239                     for mat in mats:
   240                         if (mat!=None) and (mat not in self.materials):
   241                             self.materials.append(mat)
   242                         if (mat!=None) and ((luxProp(mat, "type", "").get()=="light") or (luxProp(mat, "emission", "false").get()=="true")):
   243                             light = True
   244                     mesh_name = obj.getData(name_only=True)
   245                     try:
   246                         self.meshes[mesh_name] += [obj]
   247                     except KeyError:
   248                         self.meshes[mesh_name] = [obj]                
   249                     self.objects.append([obj, matrix])
   250             elif (obj_type == "Lamp"):
   251                 ltype = obj.getData(mesh=1).getType() # data
   252                 if (ltype == Lamp.Types["Lamp"]) or (ltype == Lamp.Types["Spot"]) or (ltype == Lamp.Types["Area"]):
   253                     self.lights.append([obj, matrix])
   254                     light = True
   255         return light
   256 
   257     #-------------------------------------------------
   258     # analyseScene(self)
   259     # this function builds the lists of object, lights, meshes and materials before export
   260     #-------------------------------------------------
   261     def analyseScene(self):
   262         light = False
   263         for obj in self.scene.objects:
   264             if ((obj.Layers & self.scene.Layers) > 0):
   265                 if self.analyseObject(obj, obj.getMatrix(), obj.getName()): light = True
   266         return light
   267 
   268     #-------------------------------------------------
   269     # exportMaterialLink(self, file, mat)
   270     # exports material link. LuxRender "Material" 
   271     #-------------------------------------------------
   272     def exportMaterialLink(self, file, mat):
   273         if mat == dummyMat:
   274             file.write("\tMaterial \"matte\" # dummy material\n")
   275         else:
   276             file.write("\t%s"%exportMaterialGeomTag(mat)) # use original methode
   277 
   278     #-------------------------------------------------
   279     # exportMaterial(self, file, mat)
   280     # exports material. LuxRender "Texture" 
   281     #-------------------------------------------------
   282     def exportMaterial(self, file, mat):
   283         print "material %s"%(mat.getName())
   284         file.write("\t%s"%exportMaterial(mat)) # use original methode        
   285     
   286     #-------------------------------------------------
   287     # exportMaterials(self, file)
   288     # exports materials to the file
   289     #-------------------------------------------------
   290     def exportMaterials(self, file):
   291         for mat in self.materials:
   292             
   293             self.exportMaterial(file, mat)
   294 
   295     #-------------------------------------------------
   296     # getMeshType(self, vertcount, mat)
   297     # returns type of mesh as string to use depending on thresholds
   298     #-------------------------------------------------
   299     def getMeshType(self, vertcount, mat):
   300         scn = Scene.GetCurrent()
   301         if mat != dummyMat:
   302             usesubdiv = luxProp(mat, "subdiv", "false")
   303             usedisp = luxProp(mat, "dispmap", "false")
   304             sharpbound = luxProp(mat, "sharpbound", "false")
   305             nsmooth = luxProp(mat, "nsmooth", "true")
   306             sdoffset = luxProp(mat, "sdoffset", 0.0)
   307             dstr = ""
   308             if usesubdiv.get() == "true":
   309                 nlevels = luxProp(mat, "sublevels", 1)
   310                 dstr += "\"loopsubdiv\" \"integer nlevels\" [%i] \"bool dmnormalsmooth\" [\"%s\"] \"bool dmsharpboundary\" [\"%s\"]"% (nlevels.get(), nsmooth.get(), sharpbound.get())
   311             
   312             if usedisp.get() == "true":
   313                 dstr += " \"string displacementmap\" [\"%s::dispmap.scale\"] \"float dmscale\" [-1.0] \"float dmoffset\" [%f]"%(mat.getName(), sdoffset.get()) # scale is scaled in texture
   314 
   315             if dstr != "": return dstr
   316 
   317         return "\"trianglemesh\""
   318 
   319     #-------------------------------------------------
   320     # exportMesh(self, file, mesh, mats, name, portal)
   321     # exports mesh to the file without any optimization
   322     #-------------------------------------------------
   323     def exportMesh(self, file, mesh, mats, name, portal=False):
   324         if mats == []:
   325             mats = [dummyMat]
   326         for matIndex in range(len(mats)):
   327             if (mats[matIndex] != None):
   328                 mesh_str = getMeshType(len(mesh.verts), mats[matIndex])
   329                 if (portal):
   330                     file.write("\tShape %s \"integer indices\" [\n"% mesh_str)
   331                 else:
   332                     self.exportMaterialLink(file, mats[matIndex])
   333                     file.write("\tPortalShape %s \"integer indices\" [\n"% mesh_str)
   334                 index = 0
   335                 ffaces = [f for f in mesh.faces if f.mat == matIndex]
   336                 for face in ffaces:
   337                     file.write("%d %d %d\n"%(index, index+1, index+2))
   338                     if (len(face)==4):
   339                         file.write("%d %d %d\n"%(index, index+2, index+3))
   340                     index += len(face.verts)
   341                 file.write("\t] \"point P\" [\n");
   342                 for face in ffaces:
   343                     for vertex in face:
   344                         file.write("%f %f %f\n"% tuple(vertex.co))
   345                 file.write("\t] \"normal N\" [\n")
   346                 for face in ffaces:
   347                     normal = face.no
   348                     for vertex in face:
   349                         if (face.smooth):
   350                             normal = vertex.no
   351                         file.write("%f %f %f\n"% tuple(normal))
   352                 if (mesh.faceUV):
   353                     file.write("\t] \"float uv\" [\n")
   354                     for face in ffaces:
   355                         for uv in face.uv:
   356                             file.write("%f %f\n"% tuple(uv))
   357                 file.write("\t]\n")
   358 
   359     #-------------------------------------------------
   360     # exportMeshOpt(self, file, mesh, mats, name, portal, optNormals)
   361     # exports mesh to the file with optimization.
   362     # portal: export without normals and UVs
   363     # optNormals: speed and filesize optimization, flat faces get exported without normals
   364     #-------------------------------------------------
   365     def exportMeshOpt(self, file, mesh, mats, name, portal=False, optNormals=True):
   366         shapeList, smoothFltr, shapeText = [0], [[0,1]], [""]
   367         if portal:
   368             normalFltr, uvFltr, shapeText = [0], [0], ["portal"] # portal, no normals, no UVs
   369         else:
   370             uvFltr, normalFltr, shapeText = [1], [1], ["mixed with normals"] # normals and UVs
   371             if optNormals: # one pass for flat faces without normals and another pass for smoothed faces with normals, all with UVs
   372                 shapeList, smoothFltr, normalFltr, uvFltr, shapeText = [0,1], [[0],[1]], [0,1], [1,1], ["flat w/o normals", "smoothed with normals"]
   373         if mats == []:
   374             mats = [dummyMat]
   375         for matIndex in range(len(mats)):
   376             if (mats[matIndex] != None):
   377                 if not(portal):
   378                     self.exportMaterialLink(file, mats[matIndex])
   379                 for shape in shapeList:
   380                     blenderExportVertexMap = []
   381                     exportVerts = []
   382                     exportFaces = []
   383                     ffaces = [f for f in mesh.faces if (f.mat == matIndex) and (f.smooth in smoothFltr[shape])]
   384                     for face in ffaces:
   385                         exportVIndices = []
   386                         index = 0
   387                         for vertex in face:
   388 #                            v = [vertex.co[0], vertex.co[1], vertex.co[2]]
   389                             v = [vertex.co]
   390                             if normalFltr[shape]:
   391                                 if (face.smooth):
   392 #                                    v.extend(vertex.no)
   393                                     v.append(vertex.no)
   394                                 else:
   395 #                                    v.extend(face.no)
   396                                     v.append(face.no)
   397                             if (uvFltr[shape]) and (mesh.faceUV):
   398 #                                v.extend(face.uv[index])
   399                                 v.append(face.uv[index])
   400                             blenderVIndex = vertex.index
   401                             newExportVIndex = -1
   402                             length = len(v)
   403                             if (blenderVIndex < len(blenderExportVertexMap)):
   404                                 for exportVIndex in blenderExportVertexMap[blenderVIndex]:
   405                                     v2 = exportVerts[exportVIndex]
   406                                     if (length==len(v2)) and (v == v2):
   407                                         newExportVIndex = exportVIndex
   408                                         break
   409                             if (newExportVIndex < 0):
   410                                 newExportVIndex = len(exportVerts)
   411                                 exportVerts.append(v)
   412                                 while blenderVIndex >= len(blenderExportVertexMap):
   413                                     blenderExportVertexMap.append([])
   414                                 blenderExportVertexMap[blenderVIndex].append(newExportVIndex)
   415                             exportVIndices.append(newExportVIndex)
   416                             index += 1
   417                         exportFaces.append(exportVIndices)
   418                     if (len(exportVerts)>0):
   419                         mesh_str = self.getMeshType(len(exportVerts), mats[matIndex])
   420                         if (portal):
   421                             file.write("\tPortalShape %s \"integer indices\" [\n"% mesh_str)
   422                         else:
   423                             file.write("\tShape %s \"integer indices\" [\n"% mesh_str)
   424                         for face in exportFaces:
   425                             file.write("%d %d %d\n"%(face[0], face[1], face[2]))
   426                             if (len(face)==4):
   427                                 file.write("%d %d %d\n"%(face[0], face[2], face[3]))
   428                         file.write("\t] \"point P\" [\n");
   429 #                        for vertex in exportVerts:
   430 #                            file.write("%f %f %f\n"%(vertex[0], vertex[1], vertex[2]))
   431                         file.write("".join(["%f %f %f\n"%tuple(vertex[0]) for vertex in exportVerts]))
   432                         if normalFltr[shape]:
   433                             file.write("\t] \"normal N\" [\n")
   434 #                            for vertex in exportVerts:
   435 #                                file.write("%f %f %f\n"%(vertex[3], vertex[4], vertex[5]))
   436                             file.write("".join(["%f %f %f\n"%tuple(vertex[1]) for vertex in exportVerts])) 
   437                             if (uvFltr[shape]) and (mesh.faceUV):
   438                                 file.write("\t] \"float uv\" [\n")
   439 #                                for vertex in exportVerts:
   440 #                                    file.write("%f %f\n"%(vertex[6], vertex[7]))
   441                                 file.write("".join(["%f %f\n"%tuple(vertex[2]) for vertex in exportVerts])) 
   442                         else:            
   443                             if (uvFltr[shape]) and (mesh.faceUV):
   444                                 file.write("\t] \"float uv\" [\n")
   445 #                                for vertex in exportVerts:
   446 #                                    file.write("%f %f\n"%(vertex[3], vertex[4]))
   447                                 file.write("".join(["%f %f\n"%tuple(vertex[1]) for vertex in exportVerts])) 
   448                         file.write("\t]\n")
   449                         print "  shape(%s): %d vertices, %d faces"%(shapeText[shape], len(exportVerts), len(exportFaces))
   450     
   451     #-------------------------------------------------
   452     # exportMeshes(self, file)
   453     # exports meshes that uses instancing (meshes that are used by at least "instancing_threshold" objects)
   454     #-------------------------------------------------
   455     def exportMeshes(self, file):
   456         scn = Scene.GetCurrent()
   457         instancing_threshold = luxProp(scn, "instancing_threshold", 2).get()
   458         mesh_optimizing = luxProp(scn, "mesh_optimizing", True).get()
   459         mesh = Mesh.New('')
   460         for (mesh_name, objs) in self.meshes.items():
   461             allow_instancing = True
   462             mats = getMaterials(objs[0]) # mats = obj.getData().getMaterials()
   463             for mat in mats: # don't instance if one of the materials is emissive
   464                 if (mat!=None) and (luxProp(mat, "type", "").get()=="light"):
   465                     allow_instancing = False
   466             for obj in objs: # don't instance if the objects with same mesh uses different materials
   467                 ms = getMaterials(obj)
   468                 if ms <> mats:
   469                     allow_instancing = False
   470             if obj.modifiers.__len__() > 0:
   471                 allow_instancing = False
   472             if allow_instancing and (len(objs) > instancing_threshold):
   473                 del self.meshes[mesh_name]
   474                 mesh.getFromObject(objs[0], 0, 1)
   475                 print "blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces))
   476                 file.write("ObjectBegin \"%s\"\n"%mesh_name)
   477                 if (mesh_optimizing):
   478                     self.exportMeshOpt(file, mesh, mats, mesh_name)
   479                 else:
   480                     self.exportMesh(file, mesh, mats, mesh_name)
   481                 file.write("ObjectEnd # %s\n\n"%mesh_name)
   482         mesh.verts = None
   483 
   484     #-------------------------------------------------
   485     # exportObjects(self, file)
   486     # exports objects to the file
   487     #-------------------------------------------------
   488     def exportObjects(self, file):
   489         scn = Scene.GetCurrent()
   490         cam = scn.getCurrentCamera().data
   491         objectmblur = luxProp(cam, "objectmblur", "true")
   492         usemblur = luxProp(cam, "usemblur", "false")
   493         mesh_optimizing = luxProp(scn, "mesh_optimizing", True).get()
   494         mesh = Mesh.New('')
   495         for [obj, matrix] in self.objects:
   496             print "object: %s"%(obj.getName())
   497             mesh_name = obj.getData(name_only=True)
   498 
   499             motion = None
   500             if(objectmblur.get() == "true" and usemblur.get() == "true"):
   501                 # motion blur
   502                 frame = Blender.Get('curframe')
   503                 Blender.Set('curframe', frame+1)
   504                 m1 = 1.0*matrix # multiply by 1.0 to get a copy of orignal matrix (will be frame-independant) 
   505                 Blender.Set('curframe', frame)
   506                 if m1 != matrix:
   507                     print "  motion blur"
   508                     motion = m1
   509     
   510             if motion: # motion-blur only works with instances, so ensure mesh is exported as instance first
   511                 if mesh_name in self.meshes:
   512                     del self.meshes[mesh_name]
   513                     mesh.getFromObject(obj, 0, 1)
   514                     mats = getMaterials(obj)
   515                     print "  blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces))
   516                     file.write("ObjectBegin \"%s\"\n"%mesh_name)
   517                     if (mesh_optimizing):
   518                         self.exportMeshOpt(file, mesh, mats, mesh_name)
   519                     else:
   520                         self.exportMesh(file, mesh, mats, mesh_name)
   521                     file.write("ObjectEnd # %s\n\n"%mesh_name)
   522 
   523             file.write("AttributeBegin # %s\n"%obj.getName())
   524             file.write("\tTransform [%s %s %s %s  %s %s %s %s  %s %s %s %s  %s %s %s %s]\n"\
   525                 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
   526                   matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
   527                   matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
   528                     matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
   529             if motion:
   530                 file.write("\tTransformBegin\n")
   531                 file.write("\t\tIdentity\n")
   532                 file.write("\t\tTransform [%s %s %s %s  %s %s %s %s  %s %s %s %s  %s %s %s %s]\n"\
   533                     %(motion[0][0], motion[0][1], motion[0][2], motion[0][3],\
   534                       motion[1][0], motion[1][1], motion[1][2], motion[1][3],\
   535                       motion[2][0], motion[2][1], motion[2][2], motion[2][3],\
   536                         motion[3][0], motion[3][1], motion[3][2], motion[3][3]))
   537                 file.write("\t\tCoordinateSystem \"%s\"\n"%(obj.getName()+"_motion"))
   538                 file.write("\tTransformEnd\n")
   539             if mesh_name in self.meshes:
   540                 mesh.getFromObject(obj, 0, 1)
   541                 mats = getMaterials(obj)
   542                 print "  blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces))
   543                 if (mesh_optimizing):
   544                     self.exportMeshOpt(file, mesh, mats, mesh_name)
   545                 else:
   546                     self.exportMesh(file, mesh, mats, mesh_name)
   547             else:
   548                 print "  instance %s"%(mesh_name)
   549                 if motion:
   550                     file.write("\tMotionInstance \"%s\" 0.0 1.0 \"%s\"\n"%(mesh_name, obj.getName()+"_motion"))
   551                 else:
   552                     file.write("\tObjectInstance \"%s\"\n"%mesh_name)
   553             file.write("AttributeEnd\n\n")
   554         mesh.verts = None
   555 
   556     #-------------------------------------------------
   557     # exportPortals(self, file)
   558     # exports portals objects to the file
   559     #-------------------------------------------------
   560     def exportPortals(self, file):
   561         scn = Scene.GetCurrent()
   562         mesh_optimizing = luxProp(scn, "mesh_optimizing", True).get()
   563         mesh = Mesh.New('')
   564         for [obj, matrix] in self.portals:
   565             print "portal: %s"%(obj.getName())
   566             file.write("\tTransform [%s %s %s %s  %s %s %s %s  %s %s %s %s  %s %s %s %s]\n"\
   567                 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
   568                   matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
   569                   matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
   570                     matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
   571             mesh_name = obj.getData(name_only=True)
   572             mesh.getFromObject(obj, 0, 1)
   573             mats = getMaterials(obj) # mats = obj.getData().getMaterials()
   574             if (mesh_optimizing):
   575                 self.exportMeshOpt(file, mesh, mats, mesh_name, True)
   576             else:
   577                 self.exportMesh(file, mesh, mats, mesh_name, True)
   578         mesh.verts = None
   579 
   580     #-------------------------------------------------
   581     # exportLights(self, file)
   582     # exports lights to the file
   583     #-------------------------------------------------
   584     def exportLights(self, file):
   585         for [obj, matrix] in self.lights:
   586             ltype = obj.getData(mesh=1).getType() # data
   587             if (ltype == Lamp.Types["Lamp"]) or (ltype == Lamp.Types["Spot"]) or (ltype == Lamp.Types["Area"]):
   588                 print "light: %s"%(obj.getName())
   589                 if ltype == Lamp.Types["Area"]:
   590                     (str, link) = luxLight("", "", obj, None, 0)
   591                     file.write(str)
   592                 if ltype == Lamp.Types["Area"]: file.write("AttributeBegin # %s\n"%obj.getName())
   593                 else: file.write("TransformBegin # %s\n"%obj.getName())
   594                 file.write("\tTransform [%s %s %s %s  %s %s %s %s  %s %s %s %s  %s %s %s %s]\n"\
   595                     %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
   596                       matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
   597                       matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
   598                         matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
   599                 col = obj.getData(mesh=1).col # data
   600                 energy = obj.getData(mesh=1).energy # data
   601                 if ltype == Lamp.Types["Lamp"]:
   602                     lightgroup = luxProp(obj, "light.lightgroup", "default")
   603                     if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
   604                         file.write("LightGroup \"%s\"\n"%lightgroup.get())
   605                     (str, link) = luxLamp("", "", obj, None, 0)
   606                     file.write(str+"LightSource \"point\""+link+"\n")
   607                 if ltype == Lamp.Types["Spot"]:
   608                     (str, link) = luxSpot("", "", obj, None, 0)
   609                     file.write(str)
   610                     proj = luxProp(obj, "light.usetexproj", "false")
   611                     if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
   612                         lightgroup = luxProp(obj, "light.lightgroup", "default")
   613                     file.write("LightGroup \"%s\"\n"%lightgroup.get())
   614                     if(proj.get() == "true"):
   615                         file.write("Rotate 180 0 1 0\n")
   616                         file.write("LightSource \"projection\" \"float fov\" [%f]"%(obj.getData(mesh=1).spotSize))
   617                     else:
   618                         file.write("LightSource \"spot\" \"point from\" [0 0 0] \"point to\" [0 0 -1] \"float coneangle\" [%f] \"float conedeltaangle\" [%f]"\
   619                             %(obj.getData(mesh=1).spotSize*0.5, obj.getData(mesh=1).spotSize*0.5*obj.getData(mesh=1).spotBlend)) # data
   620                     file.write(link+"\n")
   621                 if ltype == Lamp.Types["Area"]:
   622                     lightgroup = luxProp(obj, "light.lightgroup", "default")
   623                     if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
   624                         file.write("LightGroup \"%s\"\n"%lightgroup.get())
   625                     file.write("\tAreaLightSource \"area\"")
   626                     file.write(link)
   627 #                    file.write(luxLight("", "", obj, None, 0))
   628                     file.write("\n")
   629                     areax = obj.getData(mesh=1).getAreaSizeX()
   630                     # lamps "getAreaShape()" not implemented yet - so we can't detect shape! Using square as default
   631                     # todo: ideasman42
   632                     if (True): areay = areax
   633                     else: areay = obj.getData(mesh=1).getAreaSizeY()
   634                     file.write('\tShape "trianglemesh" "integer indices" [0 1 2 0 2 3] "point P" [-%(x)f %(y)f 0.0 %(x)f %(y)f 0.0 %(x)f -%(y)f 0.0 -%(x)f -%(y)f 0.0]\n'%{"x":areax/2, "y":areay/2})
   635                 if ltype == Lamp.Types["Area"]: file.write("AttributeEnd # %s\n"%obj.getName())
   636                 else: file.write("TransformEnd # %s\n"%obj.getName())
   637                 file.write("\n")
   638 
   639 
   640     #-------------------------------------------------
   641     # exportVolumes(self, file)
   642     # exports volumes to the file
   643     #-------------------------------------------------
   644     def exportVolumes(self, file):
   645         for [obj, matrix] in self.volumes:
   646             print "volume: %s"%(obj.getName())
   647             file.write("# Volume: %s\n"%(obj.getName()))
   648 
   649             # trickery to obtain objectspace boundingbox AABB
   650             mat = obj.matrixWorld.copy().invert()
   651             bb = [vec * mat for vec in obj.getBoundBox()]
   652             minx = miny = minz = 100000000000000.0
   653             maxx = maxy = maxz = -100000000000000.0
   654             for vec in bb:
   655                 if (vec[0] < minx): minx = vec[0]
   656                 if (vec[1] < miny): miny = vec[1]
   657                 if (vec[2] < minz): minz = vec[2]
   658                 if (vec[0] > maxx): maxx = vec[0]
   659                 if (vec[1] > maxy): maxy = vec[1]
   660                 if (vec[2] > maxz): maxz = vec[2]
   661 
   662             file.write("Transform [%s %s %s %s  %s %s %s %s  %s %s %s %s  %s %s %s %s]\n"\
   663                 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
   664                   matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
   665                   matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
   666                     matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
   667 
   668             str_opt = (" \"point p0\" [%f %f %f] \"point p1\" [%f %f %f]"%(minx, miny, minz, maxx, maxy, maxz))
   669             mats = getMaterials(obj)
   670             if (len(mats)>0) and (mats[0]!=None) and (luxProp(mats[0], "type", "").get()=="boundvolume"):
   671                 mat = mats[0]
   672                 (str, link) = luxMaterialBlock("", "", "", mat, None, 0, str_opt)
   673                 file.write("%s"%link)
   674                 file.write("\n\n")
   675 
   676 
   677 # Note - radiance - this is a work in progress
   678 def luxFlashBlock(camObj):
   679     str = ""
   680     str += "CoordSysTransform \"camera\"\n"
   681 
   682     str += "Texture \"camflashtex\" \"color\" \"blackbody\" \"float temperature\" [5500.0]"
   683     str += "AreaLightSource \"area\" \"texture L\" [\"camflashtex\"] \"float power\" [100.000000] \"float efficacy\" [17.000000] \"float gain\" [1.000000]\n"
   684 
   685     up = 10.0
   686 
   687     str += "Shape \"trianglemesh\" \"integer indices\" [ 0 1 2 0 2 3 ] \"point P\" [ 0.014 0.012 0.0   0.006 0.012 0.0   0.006 0.008 0.0   0.014 0.008 0.0 ]\n"
   688 
   689     return str
   690 
   691 
   692 ######################################################
   693 # EXPORT
   694 ######################################################
   695 
   696 def save_lux(filename, unindexedname):
   697     
   698     export_total_steps = 12.0
   699     
   700     global meshlist, matnames, lxs_filename, geom_filename, geom_pfilename, mat_filename, mat_pfilename, vol_filename, vol_pfilename, LuxIsGUI
   701 
   702     print("Lux Render Export started...\n")
   703     time1 = Blender.sys.time()
   704     scn = Scene.GetCurrent()
   705 
   706     filepath = os.path.dirname(filename)
   707     filebase = os.path.splitext(os.path.basename(filename))[0]
   708 
   709     lxs_filename = filename
   710 
   711     geom_filename = os.path.join(filepath, filebase + "-geom.lxo")
   712     geom_pfilename = filebase + "-geom.lxo"
   713 
   714     mat_filename = os.path.join(filepath, filebase + "-mat.lxm")
   715     mat_pfilename = filebase + "-mat.lxm"
   716     
   717     vol_filename = os.path.join(filepath, filebase + "-vol.lxv")
   718     vol_pfilename = filebase + "-vol.lxv"
   719 
   720     ### Zuegs: initialization for export class
   721     export = luxExport(Blender.Scene.GetCurrent())
   722 
   723     # check if a light is present
   724     envtype = luxProp(scn, "env.type", "infinite").get()
   725     if envtype == "sunsky":
   726         sun = None
   727         for obj in scn.objects:
   728             if (obj.getType() == "Lamp") and ((obj.Layers & scn.Layers) > 0):
   729                 if obj.getData(mesh=1).getType() == 1: # sun object # data
   730                     sun = obj
   731     if not(export.analyseScene()) and not(envtype == "infinite") and not((envtype == "sunsky") and (sun != None)):
   732         print("ERROR: No light source found")
   733         Draw.PupMenu("ERROR: No light source found%t|OK%x1")
   734         return False
   735 
   736     if LuxIsGUI: DrawProgressBar(0.0/export_total_steps,'Setting up Scene file')
   737     if luxProp(scn, "lxs", "true").get()=="true":
   738         ##### Determine/open files
   739         print("Exporting scene to '" + filename + "'...\n")
   740         file = open(filename, 'w')
   741 
   742         ##### Write Header ######
   743         file.write("# Lux Render v0.6RC5 Scene File\n")
   744         file.write("# Exported by LuxBlend Blender Exporter\n")
   745         file.write("\n")
   746     
   747         ##### Write camera ######
   748         camObj = scn.getCurrentCamera()
   749 
   750         if LuxIsGUI: DrawProgressBar(1.0/export_total_steps,'Exporting Camera')
   751         if camObj:
   752             print "processing Camera..."
   753             cam = camObj.data
   754             cammblur = luxProp(cam, "cammblur", "true")
   755             usemblur = luxProp(cam, "usemblur", "false")
   756 
   757             matrix = camObj.getMatrix()
   758 
   759             motion = None
   760             if(cammblur.get() == "true" and usemblur.get() == "true"):
   761                 # motion blur
   762                 frame = Blender.Get('curframe')
   763                 Blender.Set('curframe', frame+1)
   764                 m1 = 1.0*matrix # multiply by 1.0 to get a copy of original matrix (will be frame-independant) 
   765                 Blender.Set('curframe', frame)
   766                 if m1 != matrix:
   767                     # Motion detected, write endtransform
   768                     print "  motion blur"
   769                     motion = m1
   770                     pos = m1[3]
   771                     forwards = -m1[2]
   772                     target = pos + forwards
   773                     up = m1[1]
   774                     file.write("TransformBegin\n")
   775                     file.write("   LookAt %f %f %f \n       %f %f %f \n       %f %f %f\n" % ( pos[0], pos[1], pos[2], target[0], target[1], target[2], up[0], up[1], up[2] ))
   776                     file.write("   CoordinateSystem \"CameraEndTransform\"\n")
   777                     file.write("TransformEnd\n\n")
   778 
   779             # Write original lookat transform
   780             pos = matrix[3]
   781             forwards = -matrix[2]
   782             target = pos + forwards
   783             up = matrix[1]
   784             file.write("LookAt %f %f %f \n       %f %f %f \n       %f %f %f\n\n" % ( pos[0], pos[1], pos[2], target[0], target[1], target[2], up[0], up[1], up[2] ))
   785             file.write(luxCamera(camObj.data, scn.getRenderingContext()))
   786             if motion:
   787                 file.write("\n   \"string endtransform\" [\"CameraEndTransform\"]")
   788             file.write("\n")
   789         file.write("\n")
   790     
   791         if LuxIsGUI: DrawProgressBar(2.0/export_total_steps,'Exporting Film Settings')
   792         ##### Write film ######
   793         file.write(luxFilm(scn))
   794         file.write("\n")
   795 
   796         if LuxIsGUI: DrawProgressBar(3.0/export_total_steps,'Exporting Pixel Filter')
   797         ##### Write Pixel Filter ######
   798         file.write(luxPixelFilter(scn))
   799         file.write("\n")
   800     
   801         if LuxIsGUI: DrawProgressBar(4.0/export_total_steps,'Exporting Sampler')
   802         ##### Write Sampler ######
   803         file.write(luxSampler(scn))
   804         file.write("\n")
   805     
   806         if LuxIsGUI: DrawProgressBar(5.0/export_total_steps,'Exporting Surface Integrator')
   807         ##### Write Surface Integrator ######
   808         file.write(luxSurfaceIntegrator(scn))
   809         file.write("\n")
   810         
   811         if LuxIsGUI: DrawProgressBar(6.0/export_total_steps,'Exporting Volume Integrator')
   812         ##### Write Volume Integrator ######
   813         file.write(luxVolumeIntegrator(scn))
   814         file.write("\n")
   815         
   816         if LuxIsGUI: DrawProgressBar(7.0/export_total_steps,'Exporting Accelerator')
   817         ##### Write Acceleration ######
   818         file.write(luxAccelerator(scn))
   819         file.write("\n")    
   820     
   821         ########## BEGIN World
   822         file.write("\n")
   823         file.write("WorldBegin\n")
   824         file.write("\n")
   825 
   826         ########## World scale
   827         #scale = luxProp(scn, "global.scale", 1.0).get()
   828         #if scale != 1.0:
   829         #    # TODO: not working yet !!!
   830         #    # TODO: propabily scale needs to be applyed on camera coords too 
   831         #    file.write("Transform [%s 0.0 0.0 0.0  0.0 %s 0.0 0.0  0.0 0.0 %s 0.0  0.0 0.0 0 1.0]\n"%(scale, scale, scale))
   832         #    file.write("\n")
   833         
   834         if LuxIsGUI: DrawProgressBar(8.0/export_total_steps,'Exporting Environment')
   835         ##### Write World Background, Sunsky or Env map ######
   836         env = luxEnvironment(scn)
   837         if env != "":
   838             file.write("AttributeBegin\n")
   839             file.write(env)
   840             export.exportPortals(file)
   841             file.write("AttributeEnd\n")
   842             file.write("\n")    
   843 
   844     # Note - radiance - this is a work in progress
   845 #        flash = luxFlashBlock(camObj)
   846 #        if flash != "":
   847 #            file.write("# Camera flash lamp\n")
   848 #            file.write("AttributeBegin\n")
   849 #            #file.write("CoordSysTransform \"camera\"\n")
   850 #            file.write(flash)
   851 #            file.write("AttributeEnd\n\n")
   852 
   853         #### Write material & geometry file includes in scene file
   854         file.write("Include \"%s\"\n\n" %(mat_pfilename))
   855         file.write("Include \"%s\"\n\n" %(geom_pfilename))
   856         file.write("Include \"%s\"\n\n" %(vol_pfilename))
   857         
   858         #### Write End Tag
   859         file.write("WorldEnd\n\n")
   860         file.close()
   861         
   862     if luxProp(scn, "lxm", "true").get()=="true":
   863         if LuxIsGUI: DrawProgressBar(9.0/export_total_steps,'Exporting Materials')
   864         ##### Write Material file #####
   865         print("Exporting materials to '" + mat_filename + "'...\n")
   866         mat_file = open(mat_filename, 'w')
   867         mat_file.write("")
   868         export.exportMaterials(mat_file)
   869         mat_file.write("")
   870         mat_file.close()
   871     
   872     if luxProp(scn, "lxo", "true").get()=="true":
   873         if LuxIsGUI: DrawProgressBar(10.0/export_total_steps,'Exporting Geometry')
   874         ##### Write Geometry file #####
   875         print("Exporting geometry to '" + geom_filename + "'...\n")
   876         geom_file = open(geom_filename, 'w')
   877         meshlist = []
   878         geom_file.write("")
   879         export.exportLights(geom_file)
   880         export.exportMeshes(geom_file)
   881         export.exportObjects(geom_file)
   882         geom_file.write("")
   883         geom_file.close()
   884 
   885     if luxProp(scn, "lxv", "true").get()=="true":
   886         if LuxIsGUI: DrawProgressBar(11.0/export_total_steps,'Exporting Volumes')
   887         ##### Write Volume file #####
   888         print("Exporting volumes to '" + vol_filename + "'...\n")
   889         vol_file = open(vol_filename, 'w')
   890         meshlist = []
   891         vol_file.write("")
   892         export.exportVolumes(vol_file)
   893         vol_file.write("")
   894         vol_file.close()
   895 
   896 
   897     if LuxIsGUI: DrawProgressBar(12.0/export_total_steps,'Export Finished')
   898     print("Finished.\n")
   899     del export
   900 
   901     time2 = Blender.sys.time()
   902     print("Processing time: %f\n" %(time2-time1))
   903     return True
   904 
   905 ########################################################################
   906 ####  Construct server string argument
   907 ########################################################################
   908 
   909 def networkstring(scn):
   910     servers_string = ""
   911     if  (luxProp(scn,"network","false").get() == "true"):
   912         if (luxProp(scn,"network_use_file","false").get() == "true"):
   913             print "read network servers from file: "+ luxProp(scn,"network_file_path","false").get()
   914             f = open(luxProp(scn,"network_file_path","false").get())
   915             for s in f:
   916                 s = s.strip("\n")
   917                 print "add server :" + s
   918                 servers_string=servers_string+" -u "+ s
   919             f.close
   920         else : 
   921              if  luxProp(scn,"network_servers","").get():
   922                  for server in luxProp(scn,"network_servers","").get().split(","):
   923                     servers_string=servers_string+" -u "+ server
   924     return servers_string
   925 
   926 
   927 #########################################################################
   928 ###     LAUNCH LuxRender AND RENDER CURRENT SCENE
   929 #########################################################################
   930 
   931 def launchLux(filename):
   932     ostype = osys.platform
   933     #get blenders 'bpydata' directory
   934     datadir=Blender.Get("datadir")
   935     
   936     scn = Scene.GetCurrent()
   937     ic = luxProp(scn, "lux", "").get()
   938     ic = Blender.sys.dirname(ic) + os.sep + "luxrender"
   939 
   940     servers_string = networkstring(scn)
   941     update_int=luxProp(scn,"newtork_interval",180).get()
   942 
   943     if ostype == "win32": ic = ic + ".exe"
   944     if ostype == "darwin": ic = ic + ".app/Contents/MacOS/luxrender"
   945     checkluxpath = luxProp(scn, "checkluxpath", True).get()
   946     if checkluxpath:
   947         if sys.exists(ic) != 1:
   948             Draw.PupMenu("Error: Lux renderer not found. Please set path on System page.%t|OK")
   949             return        
   950     autothreads = luxProp(scn, "autothreads", "true").get()
   951     threads = luxProp(scn, "threads", 1).get()
   952     luxnice = luxProp(scn, "luxnice", 0).get()
   953     noopengl = luxProp(scn, "noopengl", "false").get()
   954     if noopengl == "true":
   955         noopengl_str = " --noopengl"
   956     else:
   957         noopengl_str = ""
   958     
   959     if ostype == "win32":
   960         prio = ""
   961         if luxnice > 15: prio = "/low"
   962         elif luxnice > 5: prio = "/belownormal"
   963         elif luxnice > -5: prio = "/normal"
   964         elif luxnice > -15: prio = "/abovenormal"
   965         else: prio = "/high"
   966         if(autothreads=="true"):
   967             cmd = "start /b %s \"\" \"%s\" %s %s -i %d \"%s\" "%(prio, ic, noopengl_str, servers_string ,update_int, filename)        
   968         else:
   969             cmd = "start /b %s \"\" \"%s\" %s %s -i %d \"%s\" --threads=%d"%(prio, ic, noopengl_str, servers_string ,update_int ,filename, threads)        
   970 
   971     if ostype == "linux2" or ostype == "darwin":
   972         if(autothreads=="true"):
   973             cmd = "(nice -n %d \"%s\" %s %s -i %d \"%s\")&"%(luxnice, ic, noopengl_str, servers_string ,update_int, filename)
   974 
   975         else:
   976             cmd = "(nice -n %d \"%s\" --threads=%d %s %s -i %d \"%s\")&"%(luxnice, ic, threads, noopengl_str, servers_string ,update_int, filename)
   977 
   978     # call external shell script to start Lux    
   979     print("Running Luxrender:\n"+cmd)
   980     os.system(cmd)
   981 
   982 def launchLuxPiped():
   983     ostype = osys.platform
   984     #get blenders 'bpydata' directory
   985     datadir=Blender.Get("datadir")
   986     
   987     scn = Scene.GetCurrent()
   988 
   989     servers_string = networkstring(scn)
   990     update_int=luxProp(scn,"newtork_interval",180).get()
   991 
   992     ic = luxProp(scn, "lux", "").get()
   993     ic = Blender.sys.dirname(ic) + os.sep + "luxrender"
   994     if ostype == "win32": ic = ic + ".exe"
   995     if ostype == "darwin": ic = ic + ".app/Contents/MacOS/luxrender"
   996     checkluxpath = luxProp(scn, "checkluxpath", True).get()
   997     if checkluxpath:
   998         if sys.exists(ic) != 1:
   999             Draw.PupMenu("Error: Lux renderer not found. Please set path on System page.%t|OK")
  1000             return        
  1001     autothreads = luxProp(scn, "autothreads", "true").get()
  1002     threads = luxProp(scn, "threads", 1).get()
  1003 
  1004     if ostype == "win32":
  1005         if(autothreads=="true"):
  1006             cmd = "\"%s\" - %s -i %d "%(ic,servers_string,update_int)        
  1007         else:
  1008             cmd = "\"%s\" - %s -i %d --threads=%d"%(ic, threads)        
  1009 
  1010     if ostype == "linux2" or ostype == "darwin":
  1011         if(autothreads=="true"):
  1012             cmd = "(\"%s -u %s -i %d\" \"%s\")&"%(ic,servers_string,update_int, filename)
  1013         else:
  1014             cmd = "(\"%s\" --threads=%d -u %s -i %d \"%s\")&"%(ic, threads,servers_string,update_int, filename)
  1015 
  1016     # call external shell script to start Lux    
  1017     print("Running Luxrender:\n"+cmd)
  1018 
  1019     import subprocess, os
  1020 
  1021     PIPE = subprocess.PIPE
  1022     p = subprocess.Popen(cmd, stdin=PIPE)
  1023     
  1024     return p.stdin
  1025 
  1026 def launchLuxWait(filename):
  1027     ostype = osys.platform
  1028     #get blenders 'bpydata' directory
  1029     datadir=Blender.Get("datadir")
  1030 
  1031     scn = Scene.GetCurrent()
  1032     luxbatchconsolemode = luxProp(scn, "luxbatchc", "false")
  1033 
  1034     servers_string = networkstring(scn)
  1035     update_int=luxProp(scn,"newtork_interval",180).get()
  1036 
  1037     ic = luxProp(scn, "lux", "").get()
  1038     if luxbatchconsolemode.get() == "false":
  1039         ic = Blender.sys.dirname(ic) + os.sep + "luxconsole"
  1040     if ostype == "win32": ic = ic + ".exe"
  1041     # radiance - comment out app install for luxconsole on OSX for jensverwiebe
  1042     #if ostype == "darwin": ic = ic + ".app/Contents/MacOS/luxconsole"
  1043     checkluxpath = luxProp(scn, "checkluxpath", True).get()
  1044     if checkluxpath:
  1045         if sys.exists(ic) != 1:
  1046             Draw.PupMenu("Error: Lux renderer not found. Please set path on System page.%t|OK")
  1047             return        
  1048     autothreads = luxProp(scn, "autothreads", "true").get()
  1049     threads = luxProp(scn, "threads", 1).get()
  1050 
  1051     if ostype == "win32":
  1052         if(autothreads=="true"):
  1053             cmd = "start /b /WAIT \"\" \"%s\" %s -i %d -f \"%s\" "%(ic,servers_string,update_int, filename)        
  1054         else:
  1055             cmd = "start /b /WAIT \"\" \"%s\"  %s -i %d -f \"%s\" --threads=%d"%(ic,servers_string,update_int, filename, threads)        
  1056         # call external shell script to start Lux    
  1057         #print("Running Luxrender:\n"+cmd)
  1058         #os.spawnv(os.P_WAIT, cmd, 0)
  1059         os.system(cmd)
  1060 
  1061     if ostype == "linux2" or ostype == "darwin":
  1062         if(autothreads=="true"):
  1063             cmd = "\"%s\" %s -i %d -f \"%s\""%(ic,servers_string,update_int, filename)
  1064         else:
  1065             cmd = "\"%s\" %s -i %d -f --threads=%d \"%s\""%(ic,servers_string,update_int,  threads, filename)
  1066         subprocess.call(cmd,shell=True)
  1067 
  1068 #### SAVE ANIMATION ####    
  1069 def save_anim(filename):
  1070     global MatSaved
  1071     
  1072     MatSaved = 0
  1073     startF = Blender.Get('staframe')
  1074     endF = Blender.Get('endframe')
  1075     scn = Scene.GetCurrent()
  1076 
  1077     Run = luxProp(scn, "run", "true").get()
  1078 
  1079     print("\n\nRendering animation (frame %i to %i)\n\n"%(startF, endF))
  1080 
  1081     for i in range (startF, endF+1):
  1082         Blender.Set('curframe', i)
  1083         print("Rendering frame %i"%(i))
  1084         Blender.Redraw()
  1085         frameindex = ("-%05d" % (i)) + ".lxs"
  1086         indexedname = sys.makename(filename, frameindex)
  1087         unindexedname = filename
  1088         luxProp(scn, "filename", Blender.Get("filename")).set(sys.makename(filename, "-%05d" %  (Blender.Get('curframe'))))
  1089 
  1090         if Run == "true":
  1091             if save_lux(filename, unindexedname):
  1092                 launchLuxWait(filename)
  1093         else:
  1094             save_lux(indexedname, unindexedname)
  1095 
  1096         MatSaved = 1
  1097 
  1098     print("\n\nFinished Rendering animation\n")
  1099 
  1100 #### SAVE STILL (hackish...) ####
  1101 def save_still(filename):
  1102     global MatSaved
  1103     scn = Scene.GetCurrent()
  1104     luxProp(scn, "filename", Blender.Get("filename")).set(sys.makename(filename, ""))
  1105     MatSaved = 0
  1106     unindexedname = filename
  1107     if save_lux(filename, unindexedname):
  1108         if runRenderAfterExport: #(run == None and luxProp(scn, "run", "true").get() == "true") or run:
  1109             launchLux(filename)
  1110 
  1111 
  1112 ######################################################
  1113 # Icons
  1114 ######################################################
  1115 
  1116 def base64value(char):
  1117     if 64 < ord(char) < 91: return ord(char)-65
  1118     if 96 < ord(char) < 123: return ord(char)-97+26
  1119     if 47 < ord(char) < 58: return ord(char)-48+52
  1120     if char == '+': return 62
  1121     return 63
  1122 
  1123 def decodeIconStr(s):
  1124     buf = BGL.Buffer(BGL.GL_BYTE, [16,16,4])
  1125     offset = 0
  1126     for y in range(16):
  1127         for x in range(16):
  1128             for c in range(4):
  1129                 buf[y][x][c] = int(base64value(s[offset])*4.048)
  1130                 offset += 1
  1131     return buf
  1132 
  1133 def decodeLogoStr(s):
  1134     buf = BGL.Buffer(BGL.GL_BYTE, [18,118,4])
  1135     offset = 0
  1136     for y in range(18):
  1137         for x in range(118):
  1138             for c in range(4):
  1139                 buf[y][x][c] = int(base64value(s[offset])*4.048)
  1140                 offset += 1
  1141     return buf
  1142 
  1143 def decodeArrowStr(s):
  1144     buf = BGL.Buffer(BGL.GL_BYTE, [22,22,4])
  1145     offset = 0
  1146     for y in range(22):
  1147         for x in range(22):
  1148             for c in range(4):
  1149                 buf[y][x][c] = int(base64value(s[offset])*4.048)
  1150                 offset += 1
  1151     return buf
  1152 
  1153 def decodeBarStr(s):
  1154     buf = BGL.Buffer(BGL.GL_BYTE, [17,138,4])
  1155     offset = 0
  1156     for y in range(17):
  1157         for x in range(138):
  1158             for c in range(4):
  1159                 buf[y][x][c] = int(base64value(s[offset])*4.048)
  1160                 offset += 1
  1161     return buf
  1162 
  1163 arrow_down = decodeArrowStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///Q///G///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///3///e///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///V///////7///D///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///1///////////e///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///a///////////////7///C///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///B///5///////////////////c///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///f///////////////////////7///C///A///A///A///A///A///A///A///A///A///A///A///A///A///C///6///////////////////////////c///A///A///A///A///A///A///A///A///A///A///A///A///A///i///////////////////////////////6///C///A///A///A///A///A///A///A///A///A///A///A///G///9///////////////////////////////////e///A///A///A///A///A///A///A///A///A///A///I///n///////////////////////////////////////6///N///A///A///A///A///A///A///A///A///A///L///b///e///e///e///e///e///e///e///e///e///g///O///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1164 
  1165 arrow_right = decodeArrowStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///L///I///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///b///n///G///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///e///////9///i///C///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///e///////////////6///f///B///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///e///////////////////////5///a///A///A///A///A///A///A///A///A///A///A///A///A///A///A///e///////////////////////////////1///V///A///A///A///A///A///A///A///A///A///A///A///A///e///////////////////////////////////////3///Q///A///A///A///A///A///A///A///A///A///A///e///////////////////////////////////7///e///G///A///A///A///A///A///A///A///A///A///A///e///////////////////////////7///e///D///A///A///A///A///A///A///A///A///A///A///A///A///e///////////////////7///c///C///A///A///A///A///A///A///A///A///A///A///A///A///A///A///e///////////6///c///C///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///g///6///e///C///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///O///N///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1166 
  1167 icon_luxblend = decodeLogoStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A/gAA/gAA/gAA/gAA/gAA/gAA/gAa/gA5/gAZ/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A/gAA/gAA/gAA/gAA/gAA/gAA/gAj/gA//gAh/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A/gAA/gAA/gAA/gAA/gAA/gAA/gAC/gAO/gAC/gAB/gAS/gAQ/gAA/gAA/gAA/gAA/gAA///A///A///A/gAA/gAZ/gAu/gA7/gA//gA//gA//gA//gA//gA//gA//gAd/gAA/gAZ/gAu/gA//gA//gA//gA//gA//gA//gA3/gAm/gAI/gAE/gAz/gA//gA//gAZ/gAA/gAA/gAA/gAZ/gA//gA//gAm/gAR/gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gAz/gAd/gAE/gAA/gA//gA//gAd/gAA/gAI/gAm/gA3/gA//gA//gA//gAR/gAA/gAA/gAA/gAA/gAA/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA//gAA/gAE/gAd/gAz/gA//gA//gA//gA//gA//gA7/gAq/gAV/gAA///A///A///A///A///A///A/gAA/gAA/gAA/gAI/gAK/gAA/gAA/gAA/gAA/gAn/gA//gA//gAc/gAA/gAA/gAA/gAA///A///A///A/gAi/gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gAd/gAZ/gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gA7/gAE/gAE/gAz/gA//gA//gAR/gAA/gAZ/gA//gA//gAm/gAA/gAR/gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gAz/gAA/gA//gA//gAd/gAI/gA7/gA//gA//gA//gA//gA//gAR/gAA/gAA/gAA/gAA/gAA/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA//gAA/gAu/gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gAi///A///A///A///A///A///A/gAA/gAA/gAA/gAv/gA4/gAA/gAA/gAA/gAD/gA9/gA//gA//gAz/gAA/gAA/gAA/gAA///A///A///A/gA//gA//gAq/gAI/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAu/gA//gA3/gAI/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA//gAR/gAA/gAM/gA7/gA//gA7/gAZ/gA//gA//gAz/gAA/gAA/gAR/gA//gA//gAR/gAA/gAA/gAA/gAA/gAA/gAA/gAE/gAd/gA//gA//gAM/gA//gA//gAd/gAd/gA//gA//gAd/gAI/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA//gAA/gA//gA//gAq/gAA/gAA/gAA/gAA/gAA/gAE/gAq/gA//gA////A///A///A///A///A///A/gAA/gAA/gAA/gAN/gAQ/gAA/gAA/gAA/gAA/gAs/gA//gA//gA+/gAs/gAp/gAZ/gAA///A///A///A/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAR/gA//gA//gAR/gAA/gAA/gAM/gA7/gA//gA//gA//gAz/gAE/gAA/gAA/gAR/gA//gA//gAR/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAR/gA//gA//gAR/gA//gA//gAd/gAd/gA//gA//gAu/gAu/gAu/gAu/gAu/gAu/gAu/gAu/gAu/gAM/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA//gAA/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA////A///A///A///A///A///A/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAI/gAA/gAE/gAZ/gAw/gA//gA//gA//gA//gAh///A///A///A/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAR/gA//gA//gAR/gAA/gAA/gAA/gAR/gA//gA//gA//gAI/gAA/gAA/gAA/gAR/gA//gA//gAm/gAd/gAd/gAd/gAd/gAd/gAd/gAd/gA3/gA//gA3/gAA/gA//gA//gAd/gAd/gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gAR/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA//gAA/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA////A///A///A///A///A///A/gAl/gAL/gAA/gAA/gAA/gAA/gAf/gA+/gAd/gAA/gAA/gAT/gA//gA//gA//gA//gA6///A///A///A/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAR/gA//gA//gAR/gAA/gAA/gAE/gAz/gA//gA//gA//gAz/gAE/gAA/gAA/gAR/gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gAd/gAA/gA//gA//gAd/gAd/gA//gA//gAR/gAR/gAR/gAR/gAR/gAR/gAd/gA//gA//gAR/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA//gAA/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA////A///A///A///A///A///A/gAl/gAK/gAA/gAA/gAA/gAA/gAf/gA+/gAd/gAA/gAA/gAT/gA//gA//gA//gA//gA6///A///A///A/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAR/gA//gA//gAR/gAA/gAA/gAz/gA//gA7/gAd/gA//gA//gAm/gAA/gAA/gAR/gA//gA//gAm/gAd/gAd/gAd/gAd/gAd/gAd/gAd/gAu/gA//gA//gAI/gA//gA//gAd/gAd/gA//gA//gAd/gAR/gAR/gAR/gAR/gAR/gAq/gA//gA//gAR/gAu/gA//gA7/gAZ/gAR/gAR/gAR/gAR/gAV/gAz/gA//gA//gAA/gA3/gA//gA7/gAi/gAd/gAd/gAd/gAd/gAd/gAu/gA//gA////A///A///A///A///A///A/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAI/gAA/gAE/gAa/gAw/gA//gA//gA//gA//gAg///A///A///A/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAu/gA//gAu/gAA/gAA/gAA/gAA/gAA/gAA/gAR/gA//gA//gAR/gAA/gAm/gA//gA7/gAM/gAA/gAZ/gA//gA//gAm/gAA/gAR/gA//gA//gAR/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAR/gA//gA//gAR/gA//gA//gAd/gAE/gAz/gA//gA//gA//gA//gA//gA//gA//gA//gA//gAz/gAA/gAV/gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gAi/gAA/gAV/gA7/gA//gA//gA//gA//gA//gA//gA//gA//gA//gA////A///A///A///A///A///A/gAA/gAA/gAA/gAO/gAR/gAA/gAA/gAA/gAA/gAt/gA//gA//gA+/gAs/gAq/gAZ/gAA///A///A///A/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAi/gAu/gAi/gAA/gAA/gAA/gAA/gAA/gAA/gAM/gAu/gAu/gAM/gAm/gA//gA7/gAM/gAA/gAA/gAA/gAm/gA//gA//gAd/gAR/gA//gA//gAd/gAR/gAR/gAR/gAR/gAR/gAR/gAR/gAq/gA//gA//gAM/gA//gA//gAd/gAA/gAA/gAZ/gAm/gAu/gAu/gAu/gAu/gAu/gAq/gAZ/gAA/gAA/gAA/gAI/gAd/gAu/gAu/gAu/gAu/gAu/gAu/gAi/gAV/gAA/gAA/gAA/gAE/gAV/gAd/gAd/gAd/gAd/gAd/gAd/gAu/gA//gA////A///A///A///A///A///A/gAA/gAA/gAA/gAv/gA4/gAA/gAA/gAA/gAD/gA9/gA//gA//gAz/gAA/gAA/gAA/gAA///A///A///A/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAR/gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gA//gAm/gAA/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA////A///A///A///A///A///A/gAA/gAA/gAA/gAI/gAK/gAA/gAA/gAA/gAA/gAn/gA//gA//gAc/gAA/gAA/gAA/gAA///A///A///A/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAM/gAu/gAu/gAu/gAu/gAu/gAu/gAu/gAu/gAu/gAu/gAm/gAR/gAA/gAA/gA//gA//gAd/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAd/gA//gA////A///A///A///A///A///A/gAA/gAA/gAA/gAA/gAA/gAA/gAC/gAO/gAC/gAB/gAS/gAP/gAA/gAA/gAA/gAA/gAA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A/gAA/gAA/gAA/gAA/gAA/gAA/gAj/gA//gAh/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A/gAA/gAA/gAA/gAA/gAA/gAA/gAa/gA5/gAY/gAA/gAA/gAA/gAA/gAA/gAA/gAA/gAA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1168 
  1169 
  1170 icon_blender = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wA27wA27wA27wAFFFGIIIsNNN5IIIsFFFG27wA27wA27wA27wA27wA///A27wA27wA27wA27wA27wAFFFmnnn9sss/kkk9FFFm27wA27wA27wA27wA27wA///A27wA27wA27wA27wA27wAEEEvwww/AAA/sss/EEEv27wA27wA27wA27wA27wA///A27wA27wA27wA27wA27wAFFFxzzz/xxx/vvv/FFFx27wA27wA27wA27wA27wA///A27wAGGGRLLLtKKK7KKK9JJJ/111/ppp/xxx/III/JJJ9JJJ7LLLtGGGR27wA///AGGGQPPP8xxx/444/vvv/555/333/999/zzz/xxx/jjj/nnn/nnn/OOO8GGGQ///ALLL2222/zzz/lll/+++/888/666/444/222/000/yyy/aaa/nnn/vvv/LLL2///AMMMxqqq/+++/ttt/////AAA/888/666/444/AAA/000/iii/zzz/nnn/MMMx///AGGGKLLLqKKK7ZZZ/yyy/yyy/yyy/888/vvv/ttt/rrr/VVV/JJJ7LLLqGGGK///A27wA27wA27wAJJJ1999+////sss5UUU8qqq5777/333+III127wA27wA27wA///A27wA27wA27wAHHHJMMMzUUU7GGGpHHHIGGGpSSS7MMMzHHHJ27wA27wA27wA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1171 icon_col = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wA27wA27wAVIAPXKB5VIAS27wA27wA27wA27wA///A///A///A///A///A27wA27wA27wAVIAPXKB8shU/XLC9VIAS27wA27wA27wA///A///A///A///A///A27wA27wAVIAPXKB8ymU/7xd/0qb/XLC9VIAS27wA27wA///A///A///A///A///A27wAVIAPXKA8xkO/7uW/7wa/7xd/0qb/XLC9VIAS27wA///A///A///A///A///AVIAPXKA8xiJ/6rO/6sS/7uW/7wZ/7xd/0qa/XLC9VIAS///A///A///A///A///AXKA1ypd/+6z/6rO/6rO/6sS/7uW/7vZ/7xd/shT/XKB5///A///A///A///A///AVJAMYMC873w/+6z/6rO/6rO/6sS/7uV/ymT/XKB8VIAP///A///A///A///A///A27wAVJAMYMC873w/+6z/6rO/6rO/xkN/XKB8VIAP27wA///A///A///A///A///A27wA27wAVJAMYMC873w/+6z/xiJ/XKA8VIAP27wA27wA///A///A///A///A///A27wA27wA27wAVJAMYMC8xpc/XKA8VIAP27wA27wA27wA///A///A///A///A///A27wA27wA27wA27wAVJAMXKA1VIAP27wA27wA27wA27wA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1172 icon_float = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wA27wA27wAMMMSOOO5MMMP27wA27wA27wA27wA///A///A///A///A///A27wA27wA27wAMMMSPPP9nnn/PPP8MMMP27wA27wA27wA///A///A///A///A///A27wA27wAMMMSPPP9ttt/333/vvv/PPP8MMMP27wA27wA///A///A///A///A///A27wAMMMSOOO9ppp/zzz/111/333/vvv/PPP8MMMP27wA///A///A///A///A///AMMMSOOO9lll/uuu/www/zzz/111/333/vvv/PPP8MMMP///A///A///A///A///AOOO5sss/666/sss/uuu/www/zzz/111/333/kkk/PPP1///A///A///A///A///AMMMPQQQ8444/666/ttt/uuu/www/zzz/ppp/OOO8MMMM///A///A///A///A///A27wAMMMPQQQ8444/666/ttt/uuu/mmm/OOO8MMMM27wA///A///A///A///A///A27wA27wAMMMPQQQ8444/555/jjj/OOO8MMMM27wA27wA///A///A///A///A///A27wA27wA27wAMMMPQQQ8ppp/OOO8MMMM27wA27wA27wA///A///A///A///A///A27wA27wA27wA27wAMMMPOOO1MMMM27wA27wA27wA27wA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1173 icon_map2d = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wA27wA27wA27wAMMMUMMMzMMMzMMMU27wA27wA27wA27wA27wA///A///A27wA27wA27wANNNPMMMyYVQ/wnV/bbb/RRR/MMMyNNNP27wA27wA27wA///A///A27wAMMMLMMMtWUQ/vnZ/7vY/6rP/aaa/eee/ZZZ/PPP/MMMtMMML27wA///A///AMMMfTSQ/tnc/7yg/7uV/6qN/6qM/YYY/ZZZ/ddd/fff/YYY/OOO/MMMf///A///AMMM/71o/7wb/6sQ/rgK/dVG/6qM/YYY/ZZZ/bbb/ccc/fff/ggg/MMM////A///AMMM/92q/AAA/6rP/dVH/AAA/6qM/YYY/ZZZ/bbb/ccc/eee/iii/MMM////A///AMMM/93r/dWI/6rP/dVH/AAA/6qM/XXX/ZZZ/bbb/ccc/eee/iii/MMM////A///AMMM/94t/6sR/6rQ/6rO/6qN/6qM/XXX/ZZZ/bbb/ccc/eee/jjj/MMM////A///AMMM/94u/dWI/dVI/6rP/6rN/6qM/XXX/ZZZ/bbb/ccc/eee/kkk/MMM////A///AMMM/+5v/AAA/AAA/6rP/7vX/94t/xxx/ggg/bbb/ccc/eee/lll/MMM////A///AMMM/+5x/6sR/7xd/+6y/////////////////111/mmm/eee/mmm/MMM////A///AMMM/+72//96/////////////////////////////////666/vvv/MMM////A///AMMMiTTS/wuq/986/////////////////////////555/ppp/SSS/MMMi///A///A27wAMMMHMMMdMMM0aZX/0yu/+97/888/uuu/XXX/MMM0MMMdMMMH27wA///A///A27wA27wA27wA27wANNNLMMMhMMM3MMM3MMMhNNNL27wA27wA27wA27wA///A")
  1174 icon_map2dparam = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wAQQQB27wA27wA27wA27wA27wA27wA27wA27wA27wA27wA27wA27wA///A///A27wAUUUwMMM9EEE3AAAvAAAlAAAbAAAI27wA27wA27wA27wA27wA27wA///A///A27wAeeeOVVV9OOO/MMM/CCC/AAA+AAA9AAAg27wA27wA27wA27wA27wA///A///A27wA27wAfffKWWW9ggg/mmm/TTT/AAA/AAA9AAAS27wA27wA27wA27wA///A///A27wA27wA27wAeeeXVVV9hhh/lll/TTT/BBB/BBB6AAAN27wA27wA27wA///A///A27wAAAAK27wA27wAdddgTTT8NNN/NNN/JJJ/VVV9EEE8AAAoAAAG27wA///A///A27wAAAAXAAAA27wA27wAeeeaVVV2QQQ/nnn+222/mmm/PPP9JGF8KGCX///A///A27wAAAAkAAAA27wA27wA27wA27wAVVVXYYY8+++/333/gec+ZPL+XOJq///A///A27wAAAAxAAAB27wA27wA27wA27wA27wAXXXiiii83219ofY8eUO/aQL2///A///A27wAAAA9AAAC27wA27wA27wA27wA27wAgggAWWVwmgc84yt/oeW/gWP1///A///ACCC6AAA/AAA/CCC627wA27wA27wA27wA27wAKFFDKGDzxsm52wq/peW2///A///AAAA/////////AAA/AAABAAAAAAAAAAAA27wA27wALFCFMHE31wr61uo5///A///AAAA/////////AAA/AAA+AAAzAAAmAAAZAAAM27wA27wAKFDJPLH6umez///A///ACCC6AAA/AAA/CCC627wA27wA27wA27wA27wA27wA27wA27wAKFCOOJFf///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1175 icon_map3dparam = decodeIconStr("27wA27wA27wA27wA27wA27wA3nIC6pMJ6pMJ3nIC27wA27wA27wA27wA27wA27wA27wA27wA27wA27wA27wA3nIC6qMj6qM/6qM/6qMj3nIC27wA27wA27wA27wA27wA27wA27wA27wA27wA27wA6pMJ6qM/////////6qM/6pMJ27wA27wA27wA27wA27wA27wA27wA27wA27wANNNOSQMz5qM/////////5qM/SQMzNNNO27wA27wA27wA27wA27wA27wAMMMIMMMrXXX/www/5wg/6qM/5qM/vnX/bbb/PPP/MMMrMMMI27wA27wA27wA27wAMMM1xxx/777/222/yyy/zxu/caY/bbb/ggg/iii/YYY/MMM127wA27wA27wA27wAMMM/+++/zzz/yyy/yyy/yyy/ZZZ/bbb/ddd/fff/kkk/MMM/27wA27wA27wA27wAMMM/////yyy/yyy/yyy/yyy/ZZZ/bbb/ddd/eee/lll/MMM/27wA27wA27wA27wAMMM/////yyy/yyy/yyy/yyy/ZZZ/bbb/ddd/eee/nnn/MMM/27wA27wA27wA3nICRPM//97/yyy/yyy/yyy/yyy/ZZZ/bbb/ddd/eee/rpm/RPM/3nIC27wA3nIC6qMj5qM/6qM/2ue/zzz/444/999/666/rrr/fff/tkU/5qM/5qM/6qMj3nIC6pMJ6qM/////////6qM/+96/////////////////985/6qM/////////6qM/6pMJ6pMJ6qM/////////6qM/+86/////////////////974/6qM/////////6qM/6pMJ3nIC6qMj6qM/6qM/pfM2PPP+mmm/555/000/hhh/PPP+pfM26qM/6qM/6qMj3nIC27wA3nIC6pMJ6pMJ3nICMMMEMMMaMMMwMMMwMMMaMMME3nIC6pMJ6pMJ3nIC27wA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1176 icon_mat = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wA27wAVJAMXKBnXLB1WJA9XLB1XKBnVJAM27wA27wA27wA///A///A///A27wAVAAAWJBgYMD9ukW/1sc/5we/0qY/sgQ/XLB9WJBgVAAA27wA///A///A///A27wAWJBghXM96zk/8yf/7wa/7vY/7vZ/YUN/TQM/aPF9WJBg27wA///A///A///AVIALZNE970o/7wb/QNG/QNG/7vX/7vX/JHD/DDD/bXP/XKB9VIAL///A///A///AXKBpype/8zj/7vX/QNG/QNG/7vX/7vX/sjR/IGD/keS/rfQ/XKBp///A///A///AXLB36zp/7xc/7vX/7vX/7vX/7vX/7vX/7vX/7vX/7vZ/0qZ/XLB3///A///A///AVJA+95x/2rX/fYM/zoU/7vX/7vX/7vX/7vX/7vX/7vY/6wf/VJA+///A///A///AXKB361s/VTO/AAA/NKF/7vX/7vX/meP/IGD/JHD/tkU/1rc/XKB3///A///A///AXKBq0tj/cba/AAA/HGD/7vX/7vX/IGD/AAA/AAA/VTQ/ujW/XKBq///A///A///AVIAMaPG920w/RPN/meP/7vX/7vX/gaM/BAA/HHH/njd/YMD9VIAM///A///A///A27wAWKBilbS995y/91n/8xd/7vZ/7xc/4wh/4yn/iXM9WKBi27wA///A///A///A27wAQQABWKBiaOF9zsj/61s/95x/5zp/xpe/ZNE9WKBiQQAB27wA///A///A///A27wA27wA27wAVIAMXKBqXKB3VJA+XKB3XKBqVIAM27wA27wA27wA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1177 icon_matmix = decodeIconStr("27wA27wA27wA27wA27wA27wA27wAMIFdUMG7WNF+WNF+SLG5LHFS27wA27wA///A27wA27wA27wA27wA27wASLGAOJGziYN/xmV/wmT/pgQ/jaN/YPH/NJGm27wA///A27wA27wA27wA27wA27wAMIFjlbR/9ye/6sQ/zlJ/sgJ/ofM/ngT/YPH/MIGT///A27wA27wA27wA27wA27wAXQJ/6xk/9xZ/6sQ/5qM/zlK/sfI/ofM/jaN/SLG5///A27wA27wA27wA27wAHHHGgXQ//4r/8xc/7vX/7tR/5pM/zlK/sgJ/pgQ/WMF+///A27wA27wA27wA27wAJOVVYbf/58//y27/wz3/7vY/7tS/4pM/ykJ/vmU/WMF////A27wAAAAALIGkTMG+NQU/Qcu/Sfz/Sfz/Wi1/wz4/7vZ/7sR/6sR/wmW/UMH8///ASLGAOJG1iYN/xmV/kns/Rfz/99+/++//Rfz/z27/8ye/9yc/9zg/iYN/LIFh///AMHFilbR/9ye/6sQ/jns/Rfz/////////Rfz/57///4q/6xk/lbR/NJG227wA///AYQJ96xk/9xZ/6sQ/orw/Tgz/Rfz/Rez/Qdw/Xaf/gXP/XPI/MIGoAAAA27wA///AgXQ//4r/8xc/7vX/7tR/nrw/jms/dhn/ein/WNG/GGGRAAAA27wA27wA27wA///AhYR//7x/91m/8xe/7vY/7tS/4pM/ykJ/vmU/WMF/GGGH27wA27wA27wA27wA///AbTM995x//+6/80k/8ye/7vZ/7sR/6sR/wmW/TMG+27wA27wA27wA27wA27wA///APIEitld///7//+6/91n/8ye/9yc/9zg/iYN/LIGk27wA27wA27wA27wA27wA///ARKGCRKFyskc/94v//7w//4q/6xk/lbR/OJG0AAAA27wA27wA27wA27wA27wA///A27wAQJECPIEibTL9hYQ/gXP/YQJ9MHEi27wA27wA27wA27wA27wA27wA27wA///A")
  1178 icon_tex = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///AOOO6MMM/MMM/MMM/MMM/MMM/MMM/MMM/MMM/MMM/MMM/MMM/OOO6///A///A///AMMM/444/555/555/555/555/666/666/777/777/888/888/MMM////A///A///AMMM/555/mmm/TTT/aaa/xxx/111/222/222/QQQ/ZZZ/777/MMM////A///A///AMMM/333/DDD/AAA/AAA/YYY/zzz/111/xxx/AAA/AAA/nnn/MMM////A///A///AMMM/222/DDD/AAA/AAA/bbb/yyy/zzz/111/RRR/AAA/iii/MMM////A///A///AMMM/666/jjj/TTT/ddd/vvv/xxx/yyy/zzz/000/rrr/555/MMM////A///A///AMMM/666/rrr/sss/uuu/vvv/www/xxx/yyy/zzz/000/666/MMM////A///A///AMMM/666/qqq/iii/qqq/uuu/vvv/ppp/nnn/yyy/zzz/555/MMM////A///A///AMMM/777/jjj/AAA/RRR/sss/bbb/AAA/AAA/SSS/yyy/555/MMM////A///A///AMMM/888/mmm/LLL/ccc/rrr/QQQ/AAA/AAA/AAA/www/555/MMM////A///A///AMMM/888/nnn/ooo/ppp/qqq/jjj/HHH/DDD/XXX/www/555/MMM////A///A///AMMM/666/888/888/777/666/666/555/555/555/444/333/MMM////A///A///ANNN4NNN+NNN+NNN+NNN+NNN+NNN+NNN+NNN+NNN+NNN+NNN+OOO4///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1179 icon_texcol = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///AWKA4VJA+VJA+VJA+VJA+VJA+VJA+VJA+VJA+VJA+VJA+VJA+WKA4///A///A///AVIA/82p/93r/93r/93s/93s/93s/93t/94u/94u/94w/95w/VIA////A///A///AVIA/93s/xoV/ZVM/icR/6wf/8zi/80k/80l/USN/daU/94v/VIA////A///A///AVIA/72r/FDC/AAA/AAA/eZP/8yf/8zh/3vg/AAA/AAA/olf/VIA////A///A///AVIA/50p/DCB/AAA/AAA/faO/8xd/8yf/8zh/SPK/AAA/jga/VIA////A///A///AVIA/94t/rhO/WRI/haN/5uY/7wb/8xd/8yf/7yg/tma/72r/VIA////A///A///AVIA/94u/6sQ/6tT/7uV/7uX/7vY/7wa/7xc/8ye/8yg/93s/VIA////A///A///AVIA/94u/6rO/ylO/5sS/7uU/7uW/1qV/yoW/7xc/8ye/93s/VIA////A///A///AVIA/+5w/zlL/DDD/bVK/6tS/mdN/AAA/AAA/YTK/7xc/93r/VIA////A///A///AVIA/+5x/3oL/NKD/mcK/6sQ/WQG/AAA/AAA/BAA/5uZ/93r/VIA////A///A///AVIA/+6z/6qM/6qM/6qM/6rO/ujM/IGC/BBA/aUJ/7vX/93r/VIA////A///A///AVIA/+5w/+6y/+5w/+4v/94t/93s/82r/93r/93r/93r/92p/VIA////A///A///AWJA6VJA/WJB/WJB/WJB/WJB/WJB/WJB/WJB/WJB/WJB/VJA/WJA6///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1180 icon_texmix = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///APPP7ccc/ddd/ccc/bbb/bbb/ddd/eee/RRR9///A///A///A///A///A///A///AYYY+yyy/fff/qqq/000/111/jjj/sss/eee////A///A///A///A///A///A///Aaaa9XXX/AAA/III/rrr/xxx/LLL/GGG/VVV////A///A///A///A///A///A///AZZZ9hhh/JJJ/XXX/rrr/uuu/kkk/eee/YYY////A///A///A///A///A///A///AVYd/sv0/imq/nqu/rrr/ttt/vvv/000/bbb////A///APPP7ccc/ddd/ccc/Ycg/Qcu/Sfz/Sfz/Wi1/fin/RRR/bbb/yyy/bbb////A///AYYY+yyy/fff/qqq/x05/Rfz/99+/++//Rfz/PSX/AAA/AAA/uuu/bbb////A///Aaaa9XXX/AAA/III/orw/Rfz/////////Rfz/lpu/XXX/eee/000/ccc////A///AZZZ9hhh/JJJ/XXX/osw/Tgz/Rfz/Rez/Qdw/Wae/bbb9aaa9YYY9PPP7///A///AYYY9vvv/lll/ppp/rrr/pty/sw1/w06/Ych////A///A///A///A///A///A///AZZZ9sss/SSS/iii/hhh/RRR/bbb/yyy/bbb////A///A///A///A///A///A///AZZZ9rrr/JJJ/eee/SSS/AAA/AAA/uuu/bbb////A///A///A///A///A///A///AZZZ+111/ttt/uuu/ooo/XXX/eee/000/ccc////A///A///A///A///A///A///AOOO4aaa9aaa9ZZZ9ZZZ9bbb9aaa9YYY9PPP7///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1181 icon_texmixcol = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///AaOE7mcS/ndT/mcS/lbS/kbS/ndU/neV/bQH9///A///A///A///A///A///A///AiYP+92o/niY/0tg//4p//6s/pme/wun/neV////A///A///A///A///A///A///AkZP9aYT/AAA/LJF/5vd//2j/OMH/GHH/eVN////A///A///A///A///A///A///AjYP9qlZ/OKE/haO/7wb/+zf/voZ/jgY/hYP////A///A///A///A///A///A///AXae/z27/qty/ux2/9wZ/+yc//1f//5o/lbS////A///AaOE7mcS/ndT/mcS/adh/Qcu/Sfz/Sfz/Wi1/lot/ZUK/leQ//3l/kbR////A///AiYP+92o/niY/0tg/25+/Rfz/99+/++//Rfz/TXc/AAA/BAA/9zg/lbS////A///AkZP9aYT/AAA/LJF/tx2/Rfz/////////Rfz/quz/bZU/lhX//6o/lcS////A///AjYP9qlZ/OKE/haO/uy3/Tgz/Rfz/Rez/Qdw/Ybg/laQ9laQ9iYP9aOE7///A///AhXP9/1f/6sQ/8vW/9wZ/wz4/y28/26//aej////A///A///A///A///A///A///AhXQ98xd/eWH/znR/xmR/ZUK/leQ//3l/kbR////A///A///A///A///A///A///AhYR97xb/TMA/xkL/dVG/AAA/BAA/9zg/lbS////A///A///A///A///A///A///AiYR+/7q//zb//0d/1tb/bZU/lhX//6o/lcS////A///A///A///A///A///A///AZNE4iZS9iZS9iYR9jZQ9laQ9laQ9iYP9aOE7///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1182 icon_texparam = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wAOOO5GGG/BBB9AAA5AAAwAAAnAAAO27wA27wA27wA27wA27wA27wA///A875F27wAYYYZPPP/KKK/III/BBB/AAA/AAA/AAAxAAAB27wA27wA27wA27wA///AoooO875K27wAaaaTRRR/eee/lll/SSS/AAA/AAA/AAAk27wA27wA27wA27wA///AeeeX222V876J27wAbbbkSSS/iii/mmm/TTT/AAA/AAA/CCCW27wA27wA27wA///AXXXfxxxftttW887I27wAcccwSSS/OOO/PPP/III/RRR/CCC/CCC3CCCL27wA///ATTTmtttsQQQvbbbd887H27wAdddrVVV/PPP/hhh/222/lll/NNN/HFE/KFCo///APPPssss3HHH6NNNwZZZd988G27wA27wAXXXlXXX/999/333/jhg/ZPK/WOJ5///AMMMvsss/jjj1XXXxrrrf333R998F27xA27wAYYYvggg/554/meX/eUO/ZQL////AJJJyvvv/jjj/oooztttoyyyc444Q999E27xAfffAYXW7jeZ/4yt/pfX/gWP////AHHH0zzz/iii/jjj+oooytttnlllggggX+99D27xALFAFKGD9wql/2wr/peW////AFFF3333/HHH/QQQ/jjj9mmmyDDD8KKKxTTTe555D26xAIFDKMHE+0vq/1uo////ADDD6666/HHH/QQQ/jjj/kkk8DDD+BBB+JJJyrrrR+++C26xAKFDROKG/wog+///ABBB9555/777/333/000/www/rrr9bbb6fffv000Y555M///B26xAKFCYOKF0///ABBB5BBB9DDD6EEE4GGG1IIIzKKKxNNNtPPPmSSSfUUUXUUUODDDE26xA27wA///A")
  1183 
  1184 icon_emission = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wA27wAAAAgAAA/AAAg27wA27wA27wA///A///A///A///A///A///A///A27wAAAAFAAAxAAA/AAA/AAA/AAAxAAAF27wA///A///A///A///A///A///A///A27wAAAAZooo5////444/nnn/KKK2AAAZ27wA///A///A///A///A///A///A///A27wAAAALSSS/ggg/bbb/AAA/AAA/AAAL27wA///A///A///A///A///A///A///A27wAAAAYrrr/////777/nnn/KKJ+AAAZ27wA///A///A///A///A///A///A///A27wAPNBRTRI+kiX8ebQ+ebN8NLA+PNCP27wA///A///A///A///A///A///A///AQQABVRB1qlQ483g2qlR+81Z2pkO6VRB0QQAB///A///A///A///A///A///A///ATQBlieP685t361ezjcD+5ySx61c0dYG6TQBl///A///A///A///A///A///A///AVRA453x650gwhbB93vRthbB+4yXvwrX0VRA4///A///A///A///A///A///A///AVRA+++8941ow2xbs0tRp0tRp1vUr2yiyVRA+///A///A///A///A///A///A///AUQA48868/++999772yiszuYo2yhsvsdxVRA5///A///A///A///A///A///A///ATPBlqof6//////++64yy64yy7611cYK4TPBl///A///A///A///A///A///A///AKKABUQA1qnf59989//++6525ifT4UQA1KKAB///A///A///A///A///A///A///A27wAKKABSPBkUQA4VQA+UQA4SPBkKKAB27wA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1185 
  1186 icon_spectex = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///AAAATGGGzAAAiAAAA27wA27wA27wA27wA27wA27wA27wAAAADAAAjGGGxAAAT///AFFFy555/SBx/MA5+ASx9AhZ9ArC9AwA9WvA9xnA9/WA97AA/xBB/555/FFFz///AAAAUccc/ka1/MA6/ASx/AhZ/ArC/AwA/WvA/xnA//WA/9AA/1ff/SSS+AAAZ///A27wAMMM6ph2/MA6/Xi0/AhZ/ArC/AwA/WvA/xnA//WA/1bb/jjj/AAAY27wA///A27wABBBnpmv/ni6/lr1/AhZ/ArC/AwA/WvA/xnA//WA/6vv/SSS/AAAE27wA///A27wAAAAEGGG1PPP/SUY/Zsn/ArC/AwA/hyS/xnA//WA/5uu/DDDw27wA27wA///A27wA27wAAAABAAAEIII3oyw/ArC/WvW/syn/31u/3vr/nll/AAAa27wA27wA///A27wA27wA///A///AAAAnlus/BrE/v4v/TTT/kkk/444/PPP+AAAE27wA27wA///A27wA27wA27wA27wAAAAZnnn/444/555/GGG3AAAdEEExAAAM27wA27wA27wA///A27wA27wA27wA27wAAAAKaaa/555/zzz/AAAn27wA27wA27wA27wA27wA27wA///A27wA27wA27wA27wAAAAALLL8555/iii/AAAX27wA27wA27wA27wA27wA27wA///A27wA27wA27wA27wA27wAAAAPKKK6AAArAAAB27wA27wA27wA27wA27wA27wA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1187 
  1188 icon_c_filter = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///AAAASGGG1BBBsAAAW27wA27wA27wA27wA27wA27wA27wAAAAWBBBsGGGyAAAU///AHHHx555/333/ddd/AAAl27wA27wA27wA27wA27wAAAAlddd/333/555/FFFz///AAAAUMMM8eee/555/ccc/AAAT27wA27wA27wAAAATccc/555/eee/MMM8AAAV///A27wAAAAAAAAbfff/222/GGG1AAAA27wAAAAAGGG1222/fff/AAAbAAAA27wA///A27wA27wAAAAAFFFz222/hhh/AAAW27wAAAAWhhh/222/FFFzAAAA27wA27wA///A27wA27wA27wAAAAQccc/333/EEEz27wAEEEz333/ccc/AAAQ27wA27wA27wA///A27wA27wA27wA27wAGGG1444/aaa/AAAdaaa/444/GGG127wA27wA27wA27wA///A27wA27wA27wA27wAAAAakkk/000/UUU/000/kkk/AAAa27wA27wA27wA27wA///A27wA27wA27wA27wAAAACGGG1xxx/555/xxx/GGG1AAAC27wA27wA27wA27wA///A27wA27wA27wA27wA27wAAAAFAAAoJJJ1AAAoAAAF27wA27wA27wA27wA27wA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1189 
  1190 icon_c_camera = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wA27wA27wAAAAAAAABAAABAAABAAABAAAA27wA27wA27wA27wA///A///ANNN6MMM/MMM/JJJ/MMM/LLL/LLL/LLL/LLL/MMM/MMM/MMM/MMM/OOO6///A///AMMM/vvv/ttt/ccc/mmm/jjj/ggg/hhh/jjj/ooo/sss/www/iii/MMM////A///AMMM/uuu/eee/RRR/XXX/ZZZ/mmm/xxx/ppp/ggg/jjj/ppp/eee/MMM////A///AMMM/ttt/aaa/OOO/WWW/rrr/aaa/TTT/jjj/zzz/hhh/lll/ccc/MMM////A///AMMM/sss/XXX/LLL/ggg/QQQ/HHH/KKK/QQQ/hhh/rrr/ggg/bbb/MMM////A///AMMM/rrr/VVV/JJJ/ooo/QQQ/TTT/III/JJJ/RRR/yyy/ddd/ZZZ/MMM////A///AMMM/sss/UUU/JJJ/eee/eee/www/RRR/EEE/VVV/ooo/ccc/ZZZ/MMM////A///AMMM/uuu/VVV/KKK/RRR/kkk/fff/QQQ/OOO/ooo/bbb/eee/ZZZ/MMM////A///AMMM/xxx/WWW/LLL/NNN/SSS/eee/ooo/hhh/YYY/YYY/ggg/ZZZ/MMM////A///AMMM/zzz/vvv/aaa/fff/VVV/OOO/PPP/RRR/bbb/mmm/sss/fff/NNN9///A///ANNN6MLJ/MJE/IHG/OOO+ggg/bbb/ccc/eee/jjj/NNN+MMM/NNN9MMMP///A///A27wAMHAl9jA/NIApMMMmWWW/888/////888/bbb/NNNmAAAA27wA27wA///A///A27wALGAPMHAoMHASMMMGSSS/777/////888/WWW/NNNF27wA27wA27wA///A///A27wA27wA27wA27wA27wARRRiPPP+QQQ/RRR+VVVi27wA27wA27wA27wA///A")
  1191 
  1192 icon_c_environment = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///AGMV1HNV7HNV7HNV7HNV7HNV7HNV7HNV7HNV7HNV7HNV7GMV1///A///A///A///AHNV7y0u/z0u/y0t/xzs/wyr/wyq/vxp/uxo/twn/svm/HNV7///A///A///A///AIOW8341/tvm/qtj/qtj/qtj/qtj/qtj/qtj/qtj/two/HNV7///A///A///A///AINV8sts/cdc/qrp/uxp/qtj/qtj/qtj/qtj/qtj/tvo/HNU7///A///A///A///AGMV7svy/Ubh/VZb/ZZZ/xyt/ruk/qtj/qtj/rul/bcb/GLU7///A///A///A///AGMV7twz/Uci/Uci/Tbg/TUU/ssq/y0u/vxr/TVT/fko/GMV7///A///A///A///AGMV7vy0/Vdj/Zgl/Xfk/Uci/RWZ/TVV/PSU/Tag/hnr/GMV7///A///A///A///AGMV7wz1/gmq/023/txz/Xfk/Uci/Uci/Uci/Uci/jos/GMV7///A///A///A///AGMV7y02/jos/////023/Zgl/Uci/Uci/Uci/Uci/kpt/GMV7///A///A///A///AGMV7z23/ahm/jos/gmq/Vdj/Uci/Uci/Uci/Uci/mru/GMV7///A///A///A///AGMV7x02/023/y02/wz1/vy0/uxz/swy/rux/ptw/lqu/GMV7///A///A///A///AGMV1GMV7GMV7GMV7GMV7GMV7GMV7GMV7GMV7GMV7GMV7GMV1///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1193 
  1194 icon_c_sampler = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wA27wAMMMXSSS3MMMg27wA27wA27wA27wAMMMdTTT2MMMc27wA27wA27wA27wA27wAMMMSggg/////XXX+MMMB27wA27wA27wAUUU8////jjj/MMMT27wA27wA27wAMMMIYYY8+++/xxx/NNNuMMMCMMMCMMMCMMMCNNNqwww/////ZZZ9MMMJ27wAMMMASSS0666/+++/fff/bbb/bbb/eee/eee/bbb/bbb/ddd/999/777/SSS327wAMMMGjjj/////////////////////////////////////////////////lll/MMMI27wARRRz555/999/ccc/YYY/YYY+aaa+bbb+YYY+YYY+bbb/999/666/RRR2MMMB27wAMMMHWWW7999/yyy/NNNu27wA27wA27wA27wANNNtxxx/+++/YYY8MMMI27wAVVqARfzGOTZZeee/////WWW+QctHRfzLRfzLRfzGUUU8////hhh/OSYaRfzGVVqARfzGRezcRfz5PXj8STV5NPSiRezcRfz5Rfz5RezcNQThRST6PYk7Rfz5RezcRfzGRfzLRfz5////////Rfz5RfzMRfz5////////Rfz5RfzMRfz5////////Rfz5RfzLRfzLRfz5////////Rfz5RfzMRfz5////////Rfz5RfzMRfz5////////Rfz5RfzLRfzGRezcRfz5Rfz5RezcRfzKRezcRfz5Rfz5RezcRfzKRezcRfz5Rfz5RezcRfzGVVqARfzGRfzLRfzLRfzGVVqARfzGRfzLRfzLRfzGVVqARfzGRfzLRfzLRfzGVVqA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1195 
  1196 icon_c_integrator = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wAAAAAEJPYHMT0MRY+GLS0EJPYAAAA27wA27wA27wA27wA27wA27wA27wA27wAAAVAEJPoVai/lr0/elv/Xeo/LRZ/EIPnDHOEAAVA27wA27wA27wA27wA27wA27wAEIPcZel/rw5/cir/NTb/SYi/PWh/MSb/QVd/KPW6EJPfAJSB27wA27wA27wAAAAAHMT4ty7/hmv/FKQyDGMXEJP7bhq/nt2/pv4/sy6/diq/EJQuIIQC27wA27wAFIQGRWd/u08/TYf/CFKQDGLfUai/flv/Zfp/SZj/bgp/rx6/fks/EJQuAJSB27wAAJSBINT7uz8/glt/EIOqGKQ4Xeo/SYi/KQY/SZk/IOW/Ydl/ty7/diq/EJPg27wA27wAEJPhflt/u08/Yel/JOW/QXi/HNV/TZi/Yfp/GLS6EJPuejr/tz8/HMT6AMMB27wAGGMCFLRxiow/u08/ciq/SZk/Yeo/gnw/Vaj/DINhDGJQQVd/u08/SXe/FIQG27wA27wAFJODFKRyhmu/u08/sy7/pv4/cir/FJQ7CGLTEIPudir/uz8/JOU6AMMB27wA27wA27wAFJODEJPjKPW8UZh/RXg/RYj/QXg/MSa/Zfo/pv4/diq/EJPg27wA27wA27wA27wA27wA27wAFKQDEIPLEJPtPVe/ahr/flv/jpz/diq/FJQtAJSB27wA27wA27wA27wA27wA27wA27wA27wAAMMBEJPeGLS5OUb/INU5EJPeAMMB27wA27wA27wA27wA27wA27wA27wA27wA27wA27wA27wAAAAAEIQEAAVA27wA27wA27wA27wA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1197 
  1198 icon_c_volumeintegrator = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wA27wA27wAMMMAMMMWNNN8NNN9MMMWMMMA27wA27wA27wA27wA///A27wA27wAAAAAEJPYIMS3MRY/KOU/gik/ggg/TTT/MMMzMMMR27wA27wA27wA27wA27wAAAVAFJPtVai/lr0/elv/Xeo/LRZ/NQU/ggh/ddd/RRR/MMMvMMMN27wA27wA27wAHKOvZel/rw5/cir/NTb/SYi/PWh/MSb/QVd/LQW/TWZ/aaa/PPP/MMMh27wAAAAAIMS/ty7/hmv/OSX/gik/HMS/bhq/nt2/pv4/sy6/diq/MQV/hhh/MMM/27wAFIQGRWd/u08/TYf/lmn/bdf/Uai/flv/Zfp/SZj/bgp/rx6/fks/NRV/MMN/27wAAJSBINT/uz8/glt/TWa/LPU/Xeo/SYi/KQY/SZk/IOW/Ydl/ty7/diq/IKO/27wA27wAIKO/flt/u08/Yel/JOW/QXi/HNV/TZi/Yfp/INT/LOT/ejr/tz8/IMT/AMMB27wAMMM/SWb/iow/u08/ciq/SZk/Yeo/gnw/Vaj/PRU/XXY/QVd/u08/SXe/FIQG27wAMMM/899/PTY/hmu/u08/sy7/pv4/cir/HLR/UVX/KOT/dir/uz8/JOU/AMMB27wAMMM/////vww/WZd/MRX/UZh/RXg/RYj/QXg/MSa/Zfo/pv4/diq/IKO/27wA27wAMMM/////999/////999/123/VZd/PVe/ahr/flv/jpz/diq/RUa/MMN/27wA27wAMMMxRRR/rrr/888/////////+++/jmp/MRX/OUb/NRX/WYb/PQQ/MMMx27wA27wA27wANNNEMMMaMMMxWWW/www/+++/999/uuu/UUV/MMMxMMMaNNNE27wA27wA///A27wA27wA27wA27wANNNIMMMfMMM1MMM1MMMfNNNI27wA27wA27wA27wA///A")
  1199 
  1200 icon_help = decodeIconStr("///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A27wA27wA27wAAAAOGGGtFFF4HHH6GGG3GGGqAAAK27wA27wA27wA///A///A///A27wAAAABEEEnNNN7vvv/666/888/888/vvv/III7EEEgAAAA27wA///A///A///A27wAEEEmfff+333/333/333/lll/999/999/999/WWW8EEEd27wA///A///A///AAAAPSSS7333/zzz/111/xxx/III/+++/777/999/999/JJJ6AAAJ///A///A///AFFFtxxx/yyy/xxx/zzz/444/999/777/666/777/999/ppp/FFFh///A///A///AEEE4555/uuu/vvv/xxx/ttt/MMM/yyy/666/666/777/111/GGGy///A///A///AJJJ7666/sss/ttt/vvv/yyy/ttt/HHH/yyy/666/555/777/FFF5///A///A///ADDD3777/sss/qqq/lll/vvv/yyy/sss/EEE/777/444/xxx/GGGv///A///A///ADDDq000/xxx/iii/FFF/kkk/lll/hhh/HHH/555/333/kkk/DDDe///A///A///AAAAJNNN8999/rrr/iii/DDD/DDD/GGG/000/000/000/GGG6AAAE///A///A///A27wACCCcccc9999/yyy/ttt/sss/www/000/000/QQQ8CCCT27wA///A///A///A27wA27wACCCXMMM7www/444/777/000/ooo+III5BBBR27wA27wA///A///A///A27wA27wA27wAAAAFBBBbEEEsEEE1FFFqBBBZAAAD27wA27wA27wA///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A///A")
  1201 
  1202 
  1203 bar_spectrum = decodeBarStr("AAA/AAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAA/AAA/AAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAA/AAA/AAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAA/AAA/AAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAA/AAA/AAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAA/AAA/AAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAA/AAA/AAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAA/AAA/AAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAA/AAA/AAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAA/AAA4AAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAA4AAAsAAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAAsAAAcAAA/AAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAA/CAAcAAAKAAAzAAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAAzCAAK///AAAAaAAB/AAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAA/CAAa///A///A///AAABfAAC/AAD/BAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAA/DAA/CAAf///A///A///A///A///AAACaAADzBAF/CAH/DAK/EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA/FAA/EAA/DAAzDAAa///A///A///A///A///A///A///AAADKBAFcCAHsDAK4EAN/GAQ/HAU/JAX/LAb/MAf/OAj/PAm/QAq/RAt/SAv/SAx/SAz/SA1/SA3/SA4/SA5/RA6/PA6/OA6/MA6/IA5/CA4/AA3/AD2/AJ1/AN0/AQy/ATw/AVu/AYr/AZo/Abl/Adj/Aeg/Agd/Ahb/AiY/AjW/AlT/AmR/AnO/AoL/AqI/AqE/ArA/AsA/AtA/AuA/AvA/AvA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/AwA/CwA/OvA/UvA/ZuA/euA/htA/lsA/orA/rqA/tpA/woA/ymA/0lA/2jA/4hA/5fA/7eA/8cA/9aA/+YA//VA//TA//QA//NA//KA//FA/+AA/+AA/8AA/7AA/6AA/5AA/3AA/2AA/0AA/yAA/wAA/uAA/sAA/qAA/oAA/lAA/jAA/hAA/fAA/dAA/bAA/ZAA/YAA/WAA/UAA/SAA/RAA/QAA/OAA/NAA/MAA/LAA/KAA/JAA/IAA/HAA/GAA/FAA4FAAsEAAcDAAK///A///A///A///A")
  1204 
  1205 bar_blackbody = decodeBarStr("+LA/+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/+aA//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ//sK//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////+///++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LA/+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/QQQ//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ/QQQ//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////QQQ/++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LA/+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/QQQ//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ/QQQ//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////QQQ/++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LA/+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/QQQ//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ/QQQ//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////QQQ/++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LA/+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/QQQ//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ/QQQ//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////QQQ/++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LA/+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/+aA//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ//sK//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////+///++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LA/+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/QQQ/QQQ/QQQ//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ/QQQ//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////QQQ/QQQ/QQQ/++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LA/+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/QQQ//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ/QQQ//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////QQQ/++//QQQ/++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LA/+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/QQQ//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ/QQQ//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////QQQ/++//QQQ/++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LA4+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/+aA/QQQ/QQQ//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ/QQQ//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////QQQ/QQQ/++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LAs+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/+aA//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ//sK//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////+///++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LAc+LA/+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/+aA//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ//sK//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////+///++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LAK+LAz+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/+aA//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ//sK//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////+///++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LAA+LAa+MA/+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/+aA//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ//sK//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////+///++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LAA+LAA+MAf+NA/+OA/+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/+aA//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ//sK//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////+///++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LAA+LAA+MAA+NAa+OAz+QA/+RA/+SA/+TA/+VA/+WA/+XA/+ZA/+aA//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ//sK//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////+///++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//+LAA+LAA+MAA+NAA+OAK+QAc+RAs+SA4+TA/+VA/+WA/+XA/+ZA/+aA//bA//cA//eA//fA//gA//hA//iA//kA//lA//mA//nA//oA//oB//pD//pE//qF//qG//qH//rI//rJ//sK//sM//sN//tO//tP//uQ//uR//vS//vT//vU//wW//wX//xY//xZ//xa//yb//yc//zd//ze//zg//0h//0i//1j//1k//1l//2m//2n//3p//3q//4r//4s//4t//5u//5v//6w//6y//6y//70//71//82//83//84//95//96//+7//+9///9/////////////////+///++//++//++//++//9+//9+//99//99//89//89//89//88//88//78//78//78//78//67//67//67//67//57//57//56//56//56//46//46//46//45//35//35//35//35//24//24//24//24//24//13//13//13//13//03//03//03//02//z2//z2//z2//z2//02//")
  1206 
  1207 bar_equalenergy = decodeBarStr("AAA/AAA/AAA/AAA/BBB/BBB/BBB/BBB/CCC/CCC/CDC/DDD/DDD/DDD/EEE/EEE/EFF/FFF/FFF/GGG/GGG/HGG/HHH/HHH/III/III/JJJ/JJJ/KJK/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QQQ/RRR/RRR/SSS/TSS/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/XXY/YYY/ZZZ/ZZZ/aaa/aaa/bbb/cbb/ccc/ddd/ddd/eee/eee/fff/ffg/ggg/hhh/hhh/iii/iii/jjj/kkk/kkk/lll/lll/mmm/mnm/nnn/ono/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/sss/ttt/utu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/122/222/222/333/333/444/444/545/555/555/666/666/667/777/777/788/888/888/999/999/999/9++/+++/+++/+++/////////////AAA/AAA/AAA/AAA/BBB/BBB/BBB/BBB/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/EEF/FFF/FFF/GGG/GGG/GGH/HHH/HHH/III/III/JJJ/JJJ/KJJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QQQ/RRR/RSR/SSS/TTT/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/YXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/cbb/ccc/ddd/ddd/eee/eee/fff/ffg/ggg/hhh/hhh/iii/iii/jjj/kkj/kkk/lll/lll/mmm/mmn/nnn/ono/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/stt/ttt/tuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/111/222/222/333/333/444/444/554/555/555/666/666/766/777/777/777/888/888/999/999/999/9++/+++/+++/+++/////////////AAA/AAA/AAA/AAA/BBB/BBB/BBB/BCC/CCC/CCC/DCC/DDD/DDD/DDD/EEE/EEE/FEF/FFF/FFF/GGG/GGG/GGG/HHH/HHH/III/III/JJJ/JJJ/KJJ/KKK/KLK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/RQQ/RRR/SRR/SSS/STT/TTT/UTU/UUU/VVV/VVV/WWW/WWW/XXX/XXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/cbb/ccc/ddd/ddd/eee/eee/fff/ggg/ggg/hhh/hhh/iii/iii/jjj/jjk/kkk/lll/lll/mmm/mmm/nnn/ooo/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/tst/ttt/utt/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/122/222/222/333/333/444/444/555/555/555/666/666/667/777/777/888/888/888/999/999/999/++9/+++/+++/+++/////////////AAA/AAA/AAA/AAA/BBB/BBB/BBB/BBB/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/FEE/FFF/FFF/GGG/GGG/HGG/HHH/HHH/III/III/JJJ/JJJ/JKJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QRQ/RRR/RRS/SSS/TST/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/XYY/YYY/ZZZ/ZZZ/aaa/aaa/bbb/bcc/ccc/ddd/ddd/eee/eee/fff/gfg/ggg/hhh/hhh/iii/iii/jjj/jjk/kkk/lll/lll/mmm/mmm/nnn/onn/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/tst/ttt/uuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/211/222/222/333/333/444/444/455/555/555/666/666/776/777/777/887/888/888/899/999/999/999/+++/+++/+++/////////////AAA/AAA/AAA/AAA/BBB/BBB/BBB/CBC/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/EEF/FFF/FFF/GGG/GGG/HHG/HHH/HHH/III/III/JJJ/JJJ/KKJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QQR/RRR/RRR/SSS/STT/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/XXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/bcb/ccc/ddd/ddd/eee/eee/fff/gff/ggg/hhh/hhh/iii/iii/jjj/jkk/kkk/lll/lll/mmm/mmm/nnn/noo/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/sss/ttt/uuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/211/222/322/333/333/444/444/554/555/555/666/666/766/777/777/878/888/888/999/999/999/+9+/+++/+++/+++/////////////AAA/AAA/AAA/AAA/BBB/BBB/BBB/BBB/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/EEF/FFF/FFF/GGG/GGG/GGH/HHH/HHH/III/III/JJJ/JJJ/KJJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QQQ/RRR/RSR/SSS/TTT/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/YXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/cbb/ccc/ddd/ddd/eee/eee/fff/ffg/ggg/hhh/hhh/iii/iii/jjj/kkj/kkk/lll/lll/mmm/mmn/nnn/ono/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/stt/ttt/tuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/111/222/222/333/333/444/444/554/555/555/666/666/766/777/777/777/888/888/999/999/999/9++/+++/+++/+++/////////////AAA/AAA/AAA/AAA/BBB/BBB/BBB/BCC/CCC/CCC/DCC/DDD/DDD/DDD/EEE/EEE/FEF/FFF/FFF/GGG/GGG/GGG/HHH/HHH/III/III/JJJ/JJJ/KJJ/KKK/KLK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/RQQ/RRR/SRR/SSS/STT/TTT/UTU/UUU/VVV/VVV/WWW/WWW/XXX/XXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/cbb/ccc/ddd/ddd/eee/eee/fff/ggg/ggg/hhh/hhh/iii/iii/jjj/jjk/kkk/lll/lll/mmm/mmm/nnn/ooo/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/tst/ttt/utt/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/122/222/222/333/333/444/444/555/555/555/666/666/667/777/777/888/888/888/999/999/999/++9/+++/+++/+++/////////////AAA/AAA/AAA/AAA/BBB/BBB/BBB/BBB/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/FEE/FFF/FFF/GGG/GGG/HGG/HHH/HHH/III/III/JJJ/JJJ/JKJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QRQ/RRR/RRS/SSS/TST/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/XYY/YYY/ZZZ/ZZZ/aaa/aaa/bbb/bcc/ccc/ddd/ddd/eee/eee/fff/gfg/ggg/hhh/hhh/iii/iii/jjj/jjk/kkk/lll/lll/mmm/mmm/nnn/onn/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/tst/ttt/uuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/211/222/222/333/333/444/444/455/555/555/666/666/776/777/777/887/888/888/899/999/999/999/+++/+++/+++/////////////AAA/AAA/AAA/AAA/BBB/BBB/BBB/CBC/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/EEF/FFF/FFF/GGG/GGG/HHG/HHH/HHH/III/III/JJJ/JJJ/KKJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QQR/RRR/RRR/SSS/STT/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/XXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/bcb/ccc/ddd/ddd/eee/eee/fff/gff/ggg/hhh/hhh/iii/iii/jjj/jkk/kkk/lll/lll/mmm/mmm/nnn/noo/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/sss/ttt/uuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/211/222/322/333/333/444/444/554/555/555/666/666/766/777/777/878/888/888/999/999/999/+9+/+++/+++/+++/////////////GBA+AAA/AAA/AAA/BBB/BBB/BBB/BBB/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/EEF/FFF/FFF/GGG/GGG/GGH/HHH/HHH/III/III/JJJ/JJJ/KJJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QQQ/RRR/RSR/SSS/TTT/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/YXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/cbb/ccc/ddd/ddd/eee/eee/fff/ffg/ggg/hhh/hhh/iii/iii/jjj/kkj/kkk/lll/lll/mmm/mmn/nnn/ono/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/stt/ttt/tuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/111/222/222/333/333/444/444/554/555/555/666/666/766/777/777/777/888/888/999/999/999/9++/+++/+++/+++/////////++/+OCA5AAA/AAA/AAA/BBB/BBB/BBB/BCC/CCC/CCC/DCC/DDD/DDD/DDD/EEE/EEE/FEF/FFF/FFF/GGG/GGG/GGG/HHH/HHH/III/III/JJJ/JJJ/KJJ/KKK/KLK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/RQQ/RRR/SRR/SSS/STT/TTT/UTU/UUU/VVV/VVV/WWW/WWW/XXX/XXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/cbb/ccc/ddd/ddd/eee/eee/fff/ggg/ggg/hhh/hhh/iii/iii/jjj/jjk/kkk/lll/lll/mmm/mmm/nnn/ooo/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/tst/ttt/utt/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/122/222/222/333/333/444/444/555/555/555/666/666/667/777/777/888/888/888/999/999/999/++9/+++/+++/+++/////////89/5WEAsAAA/AAA/AAA/BBB/BBB/BBB/BBB/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/FEE/FFF/FFF/GGG/GGG/HGG/HHH/HHH/III/III/JJJ/JJJ/JKJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QRQ/RRR/RRS/SSS/TST/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/XYY/YYY/ZZZ/ZZZ/aaa/aaa/bbb/bcc/ccc/ddd/ddd/eee/eee/fff/gfg/ggg/hhh/hhh/iii/iii/jjj/jjk/kkk/lll/lll/mmm/mmm/nnn/onn/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/tst/ttt/uuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/211/222/222/333/333/444/444/455/555/555/666/666/776/777/777/887/888/888/899/999/999/999/+++/+++/+++/////////78/scFASKCA9AAA/AAA/BBB/BBB/BBB/CBC/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/EEF/FFF/FFF/GGG/GGG/HHG/HHH/HHH/III/III/JJJ/JJJ/KKJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QQR/RRR/RRR/SSS/STT/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/XXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/bcb/ccc/ddd/ddd/eee/eee/fff/gff/ggg/hhh/hhh/iii/iii/jjj/jkk/kkk/lll/lll/mmm/mmm/nnn/noo/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/sss/ttt/uuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/211/222/322/333/333/444/444/554/555/555/666/666/766/777/777/878/888/888/999/999/999/+9+/+++/+++/+++/////99/967/S///AXEApBAA/AAA/BBB/BBB/BBB/BBB/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/EEF/FFF/FFF/GGG/GGG/GGH/HHH/HHH/III/III/JJJ/JJJ/KJJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QQQ/RRR/RSR/SSS/TTT/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/YXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/cbb/ccc/ddd/ddd/eee/eee/fff/ffg/ggg/hhh/hhh/iii/iii/jjj/kkj/kkk/lll/lll/mmm/mmn/nnn/ono/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/stt/ttt/tuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/111/222/222/333/333/444/444/554/555/555/666/666/766/777/777/777/888/888/999/999/999/9++/+++/+++/+++/////67/p///A///A///AVEAvBAA/BBB/BBB/BBB/BCC/CCC/CCC/DCC/DDD/DDD/DDD/EEE/EEE/FEF/FFF/FFF/GGG/GGG/GGG/HHH/HHH/III/III/JJJ/JJJ/KJJ/KKK/KLK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/RQQ/RRR/SRR/SSS/STT/TTT/UTU/UUU/VVV/VVV/WWW/WWW/XXX/XXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/cbb/ccc/ddd/ddd/eee/eee/fff/ggg/ggg/hhh/hhh/iii/iii/jjj/jjk/kkk/lll/lll/mmm/mmm/nnn/ooo/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/tst/ttt/utt/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/122/222/222/333/333/444/444/555/555/555/666/666/667/777/777/888/888/888/999/999/999/++9/+++/+++/+++/78/v///A///A///A///A///AXFApKDA9BBB/BBB/BBB/CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/FEE/FFF/FFF/GGG/GGG/HGG/HHH/HHH/III/III/JJJ/JJJ/JKJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QRQ/RRR/RRS/SSS/TST/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/XYY/YYY/ZZZ/ZZZ/aaa/aaa/bbb/bcc/ccc/ddd/ddd/eee/eee/fff/gfg/ggg/hhh/hhh/iii/iii/jjj/jjk/kkk/lll/lll/mmm/mmm/nnn/onn/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/tst/ttt/uuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/211/222/222/333/333/444/444/455/555/555/666/666/776/777/777/887/888/888/899/999/999/999/+++/89+967/p///A///A///A///A///A///A///AdHASXGAsQFB5IDB+CCC/CCC/CCC/DDD/DDD/DDD/EEE/EEE/EEF/FFF/FFF/GGG/GGG/HHG/HHH/HHH/III/III/JJJ/JJJ/KKJ/KKK/KKK/LLL/LLL/MMM/MMM/NNN/NNN/OOO/OOO/PPP/PPP/QQQ/QQR/RRR/RRR/SSS/STT/TTT/UUU/UUU/VVV/VVV/WWW/WWW/XXX/XXX/YYY/ZZZ/ZZZ/aaa/aaa/bbb/bcb/ccc/ddd/ddd/eee/eee/fff/gff/ggg/hhh/hhh/iii/iii/jjj/jkk/kkk/lll/lll/mmm/mmm/nnn/noo/ooo/ppp/ppp/qqq/qqq/rrr/rrr/sss/sss/ttt/uuu/uuu/vvv/vvv/www/www/xxx/xxx/yyy/yyy/zzz/zzz/000/000/111/111/211/222/322/333/333/444/444/554/555/555/666/666/766/777/777/878/888/888/999/999/88++78+567+s56/S///A///A///A///A") 
  1208 
  1209 def drawIcon(icon, x, y):
  1210     BGL.glEnable(BGL.GL_BLEND)
  1211     BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA) 
  1212     BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
  1213     BGL.glDrawPixels(16, 16, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
  1214     BGL.glDisable(BGL.GL_BLEND)
  1215 
  1216 def drawArrow(icon, x, y):
  1217     BGL.glEnable(BGL.GL_BLEND)
  1218     BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA) 
  1219     BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
  1220     BGL.glDrawPixels(22, 22, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
  1221     BGL.glDisable(BGL.GL_BLEND)
  1222 
  1223 def drawLogo(icon, x, y):
  1224     BGL.glEnable(BGL.GL_BLEND)
  1225     BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA) 
  1226     BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
  1227     BGL.glDrawPixels(118, 18, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
  1228     BGL.glDisable(BGL.GL_BLEND)
  1229 
  1230 def drawBar(icon, x, y):
  1231     BGL.glEnable(BGL.GL_BLEND)
  1232     BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA) 
  1233     BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
  1234     BGL.glDrawPixels(138, 17, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
  1235     BGL.glDisable(BGL.GL_BLEND)
  1236 
  1237 
  1238 
  1239 #-------------------------------------------------
  1240 # luxImage()
  1241 # helper class to handle images and icons for the GUI
  1242 #-------------------------------------------------
  1243 
  1244 class luxImage:
  1245     def resize(self, width, height):
  1246         self.width = width
  1247         self.height = height
  1248         self.buf = BGL.Buffer(BGL.GL_BYTE, [width,height,4]) # GL buffer
  1249     def __init__(self, width=0, height=0):
  1250         self.resize(width, height)
  1251     def draw(self, x, y):
  1252         BGL.glEnable(BGL.GL_BLEND)
  1253         BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA) 
  1254         BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
  1255         BGL.glDrawPixels(self.width, self.height, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, self.buf)
  1256         BGL.glDisable(BGL.GL_BLEND)        
  1257     def decodeStr(self, width, height, s):
  1258         self.resize(width, height)
  1259         offset = 0
  1260         for y in range(self.height):
  1261             for x in range(self.width):
  1262                 for c in range(4):
  1263                     self.buf[y][x][c] = int(base64value(s[offset])*4.048)
  1264                     offset += 1
  1265 
  1266     def decodeLuxConsole(self, width, height, data):
  1267         self.resize(width, height)
  1268         offset = 0
  1269         for y in range(self.height-1,-1,-1):
  1270             for x in range(self.width):
  1271                 for c in range(3):
  1272                     self.buf[y][x][c] = ord(data[offset])
  1273                     offset += 1
  1274                 self.buf[y][x][3] = 255
  1275 
  1276 
  1277 previewCache = {}  # dictionary that will hold all preview images
  1278 
  1279 
  1280 ######################################################
  1281 # New GUI by Zuegs
  1282 ######################################################
  1283 
  1284 from types import *
  1285 
  1286 evtLuxGui = 99
  1287 evtSavePreset = 98
  1288 evtDeletePreset = 97
  1289 evtSaveMaterial = 96
  1290 evtLoadMaterial = 95
  1291 evtDeleteMaterial = 94
  1292 evtConvertMaterial = 92
  1293 evtSaveMaterial2 = 91
  1294 evtLoadMaterial2 = 90
  1295 
  1296 
  1297 # default settings
  1298 defaultsExclude = ['preset','filename','page','link']
  1299 try:
  1300     luxdefaults = Blender.Registry.GetKey('luxblend', True)
  1301     if not(type(luxdefaults) is DictType):
  1302         luxdefaults = {}
  1303 except:
  1304     luxdefaults = {}
  1305 newluxdefaults = luxdefaults.copy()
  1306 
  1307 
  1308 def saveluxdefaults():
  1309     try: del newluxdefaults['page']
  1310     except: pass
  1311     try: Blender.Registry.SetKey('luxblend', newluxdefaults, True)
  1312     except: pass
  1313 
  1314 
  1315 
  1316 
  1317 
  1318 # *** PRESETS **************************************
  1319 presetsExclude = ['preset','lux','datadir','threads','filename','page','RGC','film.gamma','colorclamp','link']
  1320 def getPresets(key):
  1321     presets = Blender.Registry.GetKey(key, True)
  1322     if not(type(presets) is DictType):
  1323         presets = {}
  1324     return presets
  1325 def getScenePresets():
  1326     presets = getPresets('luxblend_presets').copy()
  1327 
  1328     # radiance's hardcoded render presets:
  1329 
  1330     presets['0 Preview - Direct Lighting'] = {
  1331     'film.displayinterval': 4,
  1332     'haltspp': 0,
  1333     'useparamkeys': 'false',
  1334     'sampler.showadvanced': 'false',
  1335     'sintegrator.showadvanced': 'false',
  1336     'pixelfilter.showadvanced': 'false',
  1337 
  1338     'sampler.type': 'lowdiscrepancy',
  1339     'sampler.lowdisc.pixelsamples': 1,
  1340     'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
  1341 
  1342     'sintegrator.type': 'directlighting',
  1343     'sintegrator.dlighting.maxdepth': 5,
  1344 
  1345     'pixelfilter.type': 'mitchell',
  1346     'pixelfilter.mitchell.sharp': 0.250, 
  1347     'pixelfilter.mitchell.xwidth': 2.0, 
  1348     'pixelfilter.mitchell.ywidth': 2.0, 
  1349     'pixelfilter.mitchell.optmode': "slider" }
  1350 
  1351     presets['1 Final - MLT/Bidir Path Tracing (interior) (recommended)'] =  {
  1352     'film.displayinterval': 8,
  1353     'haltspp': 0,
  1354     'useparamkeys': 'false',
  1355     'sampler.showadvanced': 'false',
  1356     'sintegrator.showadvanced': 'false',
  1357     'pixelfilter.showadvanced': 'false',
  1358 
  1359     'sampler.type': 'metropolis',
  1360     'sampler.metro.strength': 0.6,
  1361     'sampler.metro.lmprob': 0.4,
  1362     'sampler.metro.maxrejects': 512,
  1363     'sampler.metro.initsamples': 262144,
  1364     'sampler.metro.usevariance': "false",
  1365 
  1366     'sintegrator.type': 'bidirectional',
  1367     'sintegrator.bidir.bounces': 16,
  1368     'sintegrator.bidir.eyedepth': 16,
  1369     'sintegrator.bidir.lightdepth': 16,
  1370 
  1371     'pixelfilter.type': 'mitchell',
  1372     'pixelfilter.mitchell.sharp': 0.250, 
  1373     'pixelfilter.mitchell.xwidth': 2.0, 
  1374     'pixelfilter.mitchell.ywidth': 2.0, 
  1375     'pixelfilter.mitchell.optmode': "slider" }
  1376 
  1377     presets['2 Final - MLT/Path Tracing (exterior)'] =  {
  1378     'film.displayinterval': 8,
  1379     'haltspp': 0,
  1380     'useparamkeys': 'false',
  1381     'sampler.showadvanced': 'false',
  1382     'sintegrator.showadvanced': 'false',
  1383     'pixelfilter.showadvanced': 'false',
  1384 
  1385     'sampler.type': 'metropolis',
  1386     'sampler.metro.strength': 0.6,
  1387     'sampler.metro.lmprob': 0.4,
  1388     'sampler.metro.maxrejects': 512,
  1389     'sampler.metro.initsamples': 262144,
  1390     'sampler.metro.usevariance': "false",
  1391 
  1392     'sintegrator.type': 'path',
  1393     'sintegrator.bidir.bounces': 10,
  1394     'sintegrator.bidir.maxdepth': 10,
  1395 
  1396     'pixelfilter.type': 'mitchell',
  1397     'pixelfilter.mitchell.sharp': 0.250, 
  1398     'pixelfilter.mitchell.xwidth': 2.0, 
  1399     'pixelfilter.mitchell.ywidth': 2.0, 
  1400     'pixelfilter.mitchell.optmode': "slider" }
  1401     
  1402     presets['4 '] = { }
  1403 
  1404     presets['5 Progressive - Bidir Path Tracing (interior)'] =  {
  1405     'film.displayinterval': 8,
  1406     'haltspp': 0,
  1407     'useparamkeys': 'false',
  1408     'sampler.showadvanced': 'false',
  1409     'sintegrator.showadvanced': 'false',
  1410     'pixelfilter.showadvanced': 'false',
  1411 
  1412     'sampler.type': 'lowdiscrepancy',
  1413     'sampler.lowdisc.pixelsamples': 1,
  1414     'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
  1415 
  1416     'sintegrator.type': 'bidirectional',
  1417     'sintegrator.bidir.bounces': 16,
  1418     'sintegrator.bidir.eyedepth': 16,
  1419     'sintegrator.bidir.lightdepth': 16,
  1420 
  1421     'pixelfilter.type': 'mitchell',
  1422     'pixelfilter.mitchell.sharp': 0.250, 
  1423     'pixelfilter.mitchell.xwidth': 2.0, 
  1424     'pixelfilter.mitchell.ywidth': 2.0, 
  1425     'pixelfilter.mitchell.optmode': "slider" }
  1426 
  1427     presets['6 Progressive - Path Tracing (exterior)'] =  {
  1428     'film.displayinterval': 8,
  1429     'haltspp': 0,
  1430     'useparamkeys': 'false',
  1431     'sampler.showadvanced': 'false',
  1432     'sintegrator.showadvanced': 'false',
  1433     'pixelfilter.showadvanced': 'false',
  1434 
  1435     'sampler.type': 'lowdiscrepancy',
  1436     'sampler.lowdisc.pixelsamples': 1,
  1437     'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
  1438 
  1439     'sintegrator.type': 'path',
  1440     'sintegrator.bidir.bounces': 10,
  1441     'sintegrator.bidir.maxdepth': 10,
  1442 
  1443     'pixelfilter.type': 'mitchell',
  1444     'pixelfilter.mitchell.sharp': 0.250, 
  1445     'pixelfilter.mitchell.xwidth': 2.0, 
  1446     'pixelfilter.mitchell.ywidth': 2.0, 
  1447     'pixelfilter.mitchell.optmode': "slider" }
  1448 
  1449     presets['7 '] = { }
  1450 
  1451     presets['8 Bucket - Bidir Path Tracing (interior)'] =  {
  1452     'film.displayinterval': 8,
  1453     'haltspp': 0,
  1454     'useparamkeys': 'false',
  1455     'sampler.showadvanced': 'false',
  1456     'sintegrator.showadvanced': 'false',
  1457     'pixelfilter.showadvanced': 'false',
  1458 
  1459     'sampler.type': 'lowdiscrepancy',
  1460     'sampler.lowdisc.pixelsamples': 64,
  1461     'sampler.lowdisc.pixelsampler': 'hilbert',
  1462 
  1463     'sintegrator.type': 'bidirectional',
  1464     'sintegrator.bidir.bounces': 8,
  1465     'sintegrator.bidir.eyedepth': 8,
  1466     'sintegrator.bidir.lightdepth': 10,
  1467 
  1468     'pixelfilter.type': 'mitchell',
  1469     'pixelfilter.mitchell.sharp': 0.250, 
  1470     'pixelfilter.mitchell.xwidth': 2.0, 
  1471     'pixelfilter.mitchell.ywidth': 2.0, 
  1472     'pixelfilter.mitchell.optmode': "slider" }
  1473 
  1474     presets['9 Bucket - Path Tracing (exterior)'] =  {
  1475     'film.displayinterval': 8,
  1476     'haltspp': 0,
  1477     'useparamkeys': 'false',
  1478     'sampler.showadvanced': 'false',
  1479     'sintegrator.showadvanced': 'false',
  1480     'pixelfilter.showadvanced': 'false',
  1481 
  1482     'sampler.type': 'lowdiscrepancy',
  1483     'sampler.lowdisc.pixelsamples': 64,
  1484     'sampler.lowdisc.pixelsampler': 'hilbert',
  1485 
  1486     'sintegrator.type': 'path',
  1487     'sintegrator.bidir.bounces': 8,
  1488     'sintegrator.bidir.maxdepth': 8,
  1489 
  1490     'pixelfilter.type': 'mitchell',
  1491     'pixelfilter.mitchell.sharp': 0.333, 
  1492     'pixelfilter.mitchell.xwidth': 2.0, 
  1493     'pixelfilter.mitchell.ywidth': 2.0, 
  1494     'pixelfilter.mitchell.optmode': "slider" }
  1495 
  1496     presets['A '] = { }
  1497 
  1498     presets['B Anim - Distributed/GI low Q'] =  {
  1499     'film.displayinterval': 8,
  1500     'haltspp': 1,
  1501     'useparamkeys': 'false',
  1502     'sampler.showadvanced': 'false',
  1503     'sintegrator.showadvanced': 'false',
  1504     'pixelfilter.showadvanced': 'false',
  1505 
  1506     'sampler.type': 'lowdiscrepancy',
  1507     'sampler.lowdisc.pixelsamples': 16,
  1508     'sampler.lowdisc.pixelsampler': 'hilbert',
  1509 
  1510     'sintegrator.type': 'distributedpath',
  1511     'sintegrator.distributedpath.causticsonglossy': 'true',
  1512     'sintegrator.distributedpath.diffuserefractdepth': 5,
  1513     'sintegrator.distributedpath.indirectglossy': 'true',
  1514     'sintegrator.distributedpath.directsamples': 1,
  1515     'sintegrator.distributedpath.diffuserefractsamples': 1,
  1516     'sintegrator.distributedpath.glossyreflectdepth': 2,
  1517     'sintegrator.distributedpath.causticsondiffuse': 'false',
  1518     'sintegrator.distributedpath.directsampleall': 'true',
  1519     'sintegrator.distributedpath.indirectdiffuse': 'true',
  1520     'sintegrator.distributedpath.specularreflectdepth': 3,
  1521     'sintegrator.distributedpath.diffusereflectsamples': 1,
  1522     'sintegrator.distributedpath.glossyreflectsamples': 1,
  1523     'sintegrator.distributedpath.glossyrefractdepth': 5,
  1524     'sintegrator.distributedpath.diffusereflectdepth': '2',
  1525     'sintegrator.distributedpath.indirectsamples': 1,
  1526     'sintegrator.distributedpath.indirectsampleall': 'false',
  1527     'sintegrator.distributedpath.glossyrefractsamples': 1,
  1528     'sintegrator.distributedpath.directdiffuse': 'true',
  1529     'sintegrator.distributedpath.directglossy': 'true',
  1530     'sintegrator.distributedpath.strategy': 'auto',
  1531     'sintegrator.distributedpath.specularrefractdepth': 5,
  1532 
  1533     'pixelfilter.type': 'mitchell',
  1534     'pixelfilter.mitchell.sharp': 0.333, 
  1535     'pixelfilter.mitchell.xwidth': 2.0, 
  1536     'pixelfilter.mitchell.ywidth': 2.0, 
  1537     'pixelfilter.mitchell.optmode': "slider" }
  1538 
  1539     presets['C Anim - Distributed/GI medium Q'] =  {
  1540     'film.displayinterval': 8,
  1541     'haltspp': 1,
  1542     'useparamkeys': 'false',
  1543     'sampler.showadvanced': 'false',
  1544     'sintegrator.showadvanced': 'false',
  1545     'pixelfilter.showadvanced': 'false',
  1546 
  1547     'sampler.type': 'lowdiscrepancy',
  1548     'sampler.lowdisc.pixelsamples': 64,
  1549     'sampler.lowdisc.pixelsampler': 'hilbert',
  1550 
  1551     'sintegrator.type': 'distributedpath',
  1552     'sintegrator.distributedpath.causticsonglossy': 'true',
  1553     'sintegrator.distributedpath.diffuserefractdepth': 5,
  1554     'sintegrator.distributedpath.indirectglossy': 'true',
  1555     'sintegrator.distributedpath.directsamples': 1,
  1556     'sintegrator.distributedpath.diffuserefractsamples': 1,
  1557     'sintegrator.distributedpath.glossyreflectdepth': 2,
  1558     'sintegrator.distributedpath.causticsondiffuse': 'false',
  1559     'sintegrator.distributedpath.directsampleall': 'true',
  1560     'sintegrator.distributedpath.indirectdiffuse': 'true',
  1561     'sintegrator.distributedpath.specularreflectdepth': 3,
  1562     'sintegrator.distributedpath.diffusereflectsamples': 1,
  1563     'sintegrator.distributedpath.glossyreflectsamples': 1,
  1564     'sintegrator.distributedpath.glossyrefractdepth': 5,
  1565     'sintegrator.distributedpath.diffusereflectdepth': '2',
  1566     'sintegrator.distributedpath.indirectsamples': 1,
  1567     'sintegrator.distributedpath.indirectsampleall': 'false',
  1568     'sintegrator.distributedpath.glossyrefractsamples': 1,
  1569     'sintegrator.distributedpath.directdiffuse': 'true',
  1570     'sintegrator.distributedpath.directglossy': 'true',
  1571     'sintegrator.distributedpath.strategy': 'auto',
  1572     'sintegrator.distributedpath.specularrefractdepth': 5,
  1573 
  1574     'pixelfilter.type': 'mitchell',
  1575     'pixelfilter.mitchell.sharp': 0.333, 
  1576     'pixelfilter.mitchell.xwidth': 2.0, 
  1577     'pixelfilter.mitchell.ywidth': 2.0, 
  1578     'pixelfilter.mitchell.optmode': "slider" }
  1579     
  1580     presets['D Anim - Distributed/GI high Q'] =  {
  1581     'film.displayinterval': 8,
  1582     'haltspp': 1,
  1583     'useparamkeys': 'false',
  1584     'sampler.showadvanced': 'false',
  1585     'sintegrator.showadvanced': 'false',
  1586     'pixelfilter.showadvanced': 'false',
  1587 
  1588     'sampler.type': 'lowdiscrepancy',
  1589     'sampler.lowdisc.pixelsamples': 256,
  1590     'sampler.lowdisc.pixelsampler': 'hilbert',
  1591 
  1592     'sintegrator.type': 'distributedpath',
  1593     'sintegrator.distributedpath.causticsonglossy': 'true',
  1594     'sintegrator.distributedpath.diffuserefractdepth': 5,
  1595     'sintegrator.distributedpath.indirectglossy': 'true',
  1596     'sintegrator.distributedpath.directsamples': 1,
  1597     'sintegrator.distributedpath.diffuserefractsamples': 1,
  1598     'sintegrator.distributedpath.glossyreflectdepth': 2,
  1599     'sintegrator.distributedpath.causticsondiffuse': 'false',
  1600     'sintegrator.distributedpath.directsampleall': 'true',
  1601     'sintegrator.distributedpath.indirectdiffuse': 'true',
  1602     'sintegrator.distributedpath.specularreflectdepth': 3,
  1603     'sintegrator.distributedpath.diffusereflectsamples': 1,
  1604     'sintegrator.distributedpath.glossyreflectsamples': 1,
  1605     'sintegrator.distributedpath.glossyrefractdepth': 5,
  1606     'sintegrator.distributedpath.diffusereflectdepth': '2',
  1607     'sintegrator.distributedpath.indirectsamples': 1,
  1608     'sintegrator.distributedpath.indirectsampleall': 'false',
  1609     'sintegrator.distributedpath.glossyrefractsamples': 1,
  1610     'sintegrator.distributedpath.directdiffuse': 'true',
  1611     'sintegrator.distributedpath.directglossy': 'true',
  1612     'sintegrator.distributedpath.strategy': 'auto',
  1613     'sintegrator.distributedpath.specularrefractdepth': 5,
  1614 
  1615     'pixelfilter.type': 'mitchell',
  1616     'pixelfilter.mitchell.sharp': 0.333, 
  1617     'pixelfilter.mitchell.xwidth': 2.0, 
  1618     'pixelfilter.mitchell.ywidth': 2.0, 
  1619     'pixelfilter.mitchell.optmode': "slider" }
  1620 
  1621     presets['E Anim - Distributed/GI very high Q'] =  {
  1622     'film.displayinterval': 8,
  1623     'haltspp': 1,
  1624     'useparamkeys': 'false',
  1625     'sampler.showadvanced': 'false',
  1626     'sintegrator.showadvanced': 'false',
  1627     'pixelfilter.showadvanced': 'false',
  1628 
  1629     'sampler.type': 'lowdiscrepancy',
  1630     'sampler.lowdisc.pixelsamples': 512,
  1631     'sampler.lowdisc.pixelsampler': 'hilbert',
  1632 
  1633     'sintegrator.type': 'distributedpath',
  1634     'sintegrator.distributedpath.causticsonglossy': 'true',
  1635     'sintegrator.distributedpath.diffuserefractdepth': 5,
  1636     'sintegrator.distributedpath.indirectglossy': 'true',
  1637     'sintegrator.distributedpath.directsamples': 1,
  1638     'sintegrator.distributedpath.diffuserefractsamples': 1,
  1639     'sintegrator.distributedpath.glossyreflectdepth': 2,
  1640     'sintegrator.distributedpath.causticsondiffuse': 'false',
  1641     'sintegrator.distributedpath.directsampleall': 'true',
  1642     'sintegrator.distributedpath.indirectdiffuse': 'true',
  1643     'sintegrator.distributedpath.specularreflectdepth': 3,
  1644     'sintegrator.distributedpath.diffusereflectsamples': 1,
  1645     'sintegrator.distributedpath.glossyreflectsamples': 1,
  1646     'sintegrator.distributedpath.glossyrefractdepth': 5,
  1647     'sintegrator.distributedpath.diffusereflectdepth': '2',
  1648     'sintegrator.distributedpath.indirectsamples': 1,
  1649     'sintegrator.distributedpath.indirectsampleall': 'false',
  1650     'sintegrator.distributedpath.glossyrefractsamples': 1,
  1651     'sintegrator.distributedpath.directdiffuse': 'true',
  1652     'sintegrator.distributedpath.directglossy': 'true',
  1653     'sintegrator.distributedpath.strategy': 'auto',
  1654     'sintegrator.distributedpath.specularrefractdepth': 5,
  1655 
  1656     'pixelfilter.type': 'mitchell',
  1657     'pixelfilter.mitchell.sharp': 0.333, 
  1658     'pixelfilter.mitchell.xwidth': 2.0, 
  1659     'pixelfilter.mitchell.ywidth': 2.0, 
  1660     'pixelfilter.mitchell.optmode': "slider" }
  1661 
  1662     return presets
  1663 
  1664 def getMaterialPresets():
  1665     return getPresets('luxblend_materials')
  1666 
  1667 def savePreset(key, name, d):
  1668     try:
  1669         presets = getPresets(key)
  1670         if d:
  1671             presets[name] = d.copy()
  1672         else:
  1673             del presets[name]
  1674         Blender.Registry.SetKey(key, presets, True)
  1675     except: pass    
  1676 def saveScenePreset(name, d):
  1677     try:
  1678         for n in presetsExclude:
  1679             try: del d[n];
  1680             except: pass
  1681         savePreset('luxblend_presets', name, d)
  1682     except: pass
  1683 def saveMaterialPreset(name, d):
  1684     try:
  1685         for n in presetsExclude:
  1686             try: del d[n];
  1687             except: pass
  1688         savePreset('luxblend_materials', name, d)
  1689     except: pass
  1690 
  1691 
  1692 # **************************************************
  1693 
  1694 
  1695 
  1696 
  1697 
  1698 usedproperties = {} # global variable to collect used properties for storing presets
  1699 usedpropertiesfilterobj = None # assign a object to only collect the properties that are assigned to this object
  1700 
  1701 # class to access properties (for lux settings)
  1702 class luxProp:
  1703     def __init__(self, obj, name, default):
  1704         self.obj = obj
  1705         self.name = name
  1706 #        if len(name)>31: print "Warning: property-name \"%s\" has more than 31 chars."%(name)
  1707         self.hashmode = len(name)>31   # activate hash mode for keynames longer 31 chars (limited by blenders ID-prop)
  1708         self.hashname = "__hash:%x"%(name.__hash__())
  1709         self.default = default
  1710     def parseassignment(self, s, name):
  1711         l = s.split(" = ")
  1712         if l[0] != name: print "Warning: property-name \"%s\" has hash-collide with \"%s\"."%(name, l[0])
  1713         return l[1]
  1714     def createassignment(self, name, value):
  1715         return "%s = %s"%(name, value)
  1716     def get(self):
  1717         global usedproperties, usedpropertiesfilterobj, luxdefaults
  1718         if self.obj:
  1719             try:
  1720                 value = self.obj.properties['luxblend'][self.name]
  1721                 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
  1722                     usedproperties[self.name] = value
  1723                 return value
  1724             except KeyError:
  1725                 try:
  1726                     value = self.parseassignment(self.obj.properties['luxblend'][self.hashname], self.name)
  1727                     if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
  1728                         usedproperties[self.name] = value
  1729                     return value
  1730                 except KeyError:
  1731                     if self.obj.__class__.__name__ == "Scene": # luxdefaults only for global setting
  1732                         try:
  1733                             value = luxdefaults[self.name]
  1734                             if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
  1735                                 usedproperties[self.name] = value
  1736                             return value
  1737                         except KeyError:
  1738                             if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
  1739                                 usedproperties[self.name] = self.default
  1740                             return self.default
  1741                     if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
  1742                         usedproperties[self.name] = self.default
  1743                     return self.default
  1744         return None
  1745     def getobj(self):
  1746         if self.obj:
  1747             return self.obj
  1748         else:
  1749             return None
  1750     def getname(self):
  1751         if self.name:
  1752             return self.name
  1753         else:
  1754             return None
  1755     def set(self, value):
  1756         global newluxdefaults
  1757         if self.obj:
  1758             if self.hashmode: n, v = self.hashname, self.createassignment(self.name, value)
  1759             else: n, v = self.name, value
  1760             if value is not None:
  1761                 try: self.obj.properties['luxblend'][n] = v
  1762                 except (KeyError, TypeError):
  1763                     self.obj.properties['luxblend'] = {}
  1764                     self.obj.properties['luxblend'][n] = v
  1765             else:
  1766                 try: del self.obj.properties['luxblend'][n]
  1767                 except:    pass
  1768             if self.obj.__class__.__name__ == "Scene": # luxdefaults only for global setting
  1769                 # value has changed, so this are user settings, remove preset reference
  1770                 if not(self.name in defaultsExclude):
  1771                     newluxdefaults[self.name] = value
  1772                     try: self.obj.properties['luxblend']['preset']=""
  1773                     except: pass
  1774     def delete(self):
  1775         if self.obj:
  1776             try: del self.obj.properties['luxblend'][self.name]
  1777             except:    pass
  1778             try: del self.obj.properties['luxblend'][self.hashname]
  1779             except:    pass
  1780     def getFloat(self):
  1781         v = self.get()
  1782         if type(v) == types.FloatType: return float(v)
  1783         try:
  1784             if type(v) == types.StringType: return float(v.split(" ")[0])
  1785         except: pass
  1786         v = self.default
  1787         if type(v) == types.FloatType: return float(v)
  1788         try:
  1789             if type(v) == types.StringType: return float(v.split(" ")[0])
  1790         except: pass
  1791         return 0.0
  1792     def getInt(self):
  1793         try: return int(self.get())
  1794         except: return int(self.default)
  1795     def getRGB(self):
  1796         return self.getVector()
  1797     def getVector(self):
  1798         v = self.get()
  1799         if type(v) in [types.FloatType, types.IntType]: return (float(v), float(v), float(v))
  1800         l = None
  1801         try:
  1802             if type(v) == types.StringType: l = self.get().split(" ")
  1803         except: pass
  1804         try:
  1805             if (l==None) or (len(l) != 3): l = self.default.split(" ")
  1806             return (float(l[0]), float(l[1]), float(l[2]))
  1807         except AttributeError:
  1808             return (float(l[0]), float(l[0]), float(l[0]))
  1809         
  1810     def getVectorStr(self):
  1811         return "%f %f %f"%self.getVector()
  1812     def isFloat(self):
  1813         return type(self.get()) == types.FloatType
  1814     def getRGC(self):
  1815         col = self.getRGB()
  1816         return "%f %f %f"%(rg(col[0]), rg(col[1]),rg(col[2]))
  1817     def setRGB(self, value):
  1818         self.set("%f %f %f"%(value[0], value[1], value[2]))
  1819     def setVector(self, value):
  1820         self.set("%f %f %f"%(value[0], value[1], value[2]))
  1821 
  1822 
  1823 # class to access blender attributes (for lux settings)
  1824 class luxAttr:
  1825     def __init__(self, obj, name):
  1826         self.obj = obj
  1827         self.name = name
  1828     def get(self):
  1829         if self.obj:
  1830             return getattr(self.obj, self.name)
  1831         else:
  1832             return None
  1833     def getFloat(self):
  1834         return float(self.get())
  1835     def getInt(self):
  1836         return int(self.get())
  1837     def getobj(self):
  1838         if self.obj:
  1839             return self.obj
  1840         else:
  1841             return None
  1842     def getname(self):
  1843         if self.name:
  1844             return self.name
  1845         else:
  1846             return None
  1847     def set(self, value):
  1848         if self.obj:
  1849             setattr(self.obj, self.name, value)
  1850             Window.QRedrawAll()
  1851 
  1852 
  1853 # class for dynamic gui
  1854 class luxGui:
  1855     def __init__(self, y=200):
  1856         self.x = 110 # left start position after captions
  1857         self.xmax = 110+2*(140+4)
  1858         self.y = y
  1859         self.w = 140 # default element width in pixels
  1860         self.h = 18  # default element height in pixels
  1861         self.hmax = 0
  1862         self.xgap = 4
  1863         self.ygap = 4
  1864         self.resethmax = False
  1865     def getRect(self, wu, hu):
  1866         w = int(self.w * wu + self.xgap * (wu-1))
  1867         h = int(self.h * hu + self.ygap * (hu-1))
  1868         if self.x + w > self.xmax: self.newline()
  1869         if self.resethmax: self.hmax = 0; self.resethmax = False
  1870         rect = [int(self.x), int(self.y-h), int(w), int(h)]
  1871         self.x += int(w + self.xgap)
  1872         if h+self.ygap > self.hmax: self.hmax = int(h+self.ygap)
  1873         return rect
  1874     def newline(self, title="", distance=0, level=0, icon=None, color=None):
  1875         self.x = 110
  1876         if not(self.resethmax): self.y -= int(self.hmax + distance)
  1877         if color!=None:    BGL.glColor3f(color[0],color[1],color[2]); BGL.glRectf(0,self.y-self.hmax,self.xmax,self.y+distance); BGL.glColor3f(0.9, 0.9, 0.9)
  1878         if icon!=None: drawIcon(icon, 2+level*10, self.y-16)
  1879         self.resethmax = True
  1880         if title!="":
  1881             self.getRect(0, 1)
  1882             BGL.glColor3f(0.9,0.9,0.9); BGL.glRasterPos2i(20+level*10,self.y-self.h+5); Draw.Text(title)
  1883     
  1884 def luxHelp(name, lux, caption, hint, gui, width=1.0):
  1885     if gui:
  1886         r = gui.getRect(width, 1)
  1887         Draw.Toggle(caption, evtLuxGui, r[0], r[1], r[2], r[3], lux.get()=="true", hint, lambda e,v: lux.set(["false","true"][bool(v)]))
  1888         drawIcon(icon_help, r[0], r[1])
  1889 
  1890     return "\n   \"bool %s\" [\"%s\"]"%(name, lux.get())
  1891 
  1892 # lux parameter types
  1893 def luxOption(name, lux, options, caption, hint, gui, width=1.0):
  1894     if gui:
  1895         menustr = caption+": %t"
  1896         for i, v in enumerate(options): menustr = "%s %%x%d|%s"%(v, i, menustr)
  1897         try:
  1898             i = options.index(lux.get())
  1899         except ValueError:
  1900             try:
  1901                 lux.set(lux.default) # not found, so try default value
  1902                 i = options.index(lux.get())
  1903             except ValueError:
  1904                 print "value %s not found in options list"%(lux.get())
  1905                 i = 0
  1906         r = gui.getRect(width, 1)
  1907         Draw.Menu(menustr, evtLuxGui, r[0], r[1], r[2], r[3], i, hint, lambda e,v: lux.set(options[v]))
  1908     return "\n   \"string %s\" [\"%s\"]"%(name, lux.get())
  1909 
  1910 def luxOptionRect(name, lux, options, caption, hint, gui, x, y, xx, yy):
  1911     if gui:
  1912         menustr = caption+": %t"
  1913         for i, v in enumerate(options): menustr = "%s %%x%d|%s"%(v, i, menustr)
  1914         try:
  1915             i = options.index(lux.get())
  1916         except ValueError:
  1917             try:
  1918                 lux.set(lux.default) # not found, so try default value
  1919                 i = options.index(lux.get())
  1920             except ValueError:
  1921                 print "value %s not found in options list"%(lux.get())
  1922                 i = 0
  1923         Draw.Menu(menustr, evtLuxGui, x, y, xx, yy, i, hint, lambda e,v: lux.set(options[v]))
  1924     return "\n   \"string %s\" [\"%s\"]"%(name, lux.get())
  1925 
  1926 def luxIdentifier(name, lux, options, caption, hint, gui, icon=None, width=1.0):
  1927     if gui: gui.newline(caption+":", 8, 0, icon, [0.75,0.5,0.25])
  1928     luxOption(name, lux, options, caption, hint, gui, width)
  1929     return "\n%s \"%s\""%(name, lux.get())
  1930 
  1931 def luxFloat(name, lux, min, max, caption, hint, gui, width=1.0, useslider=0):
  1932     if gui:
  1933         if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
  1934             r = gui.getRect(width-0.12, 1)
  1935         else:
  1936             r = gui.getRect(width, 1)
  1937 
  1938         # Value
  1939         if(useslider==1):
  1940             Draw.Slider(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, 0, hint, lambda e,v: lux.set(v))
  1941         else:
  1942             Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, hint, lambda e,v: lux.set(v))
  1943         if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
  1944             # IPO Curve
  1945             obj = lux.getobj()
  1946             keyname = lux.getname()
  1947     
  1948             useipo = luxProp(obj, keyname+".IPOuse", "false")
  1949             i = gui.getRect(0.12, 1)
  1950             Draw.Toggle("I", evtLuxGui, i[0], i[1], i[2], i[3], useipo.get()=="true", "Use IPO Curve", lambda e,v: useipo.set(["false","true"][bool(v)]))
  1951             
  1952             if useipo.get() == "true":
  1953                 if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
  1954                 curve = luxProp(obj, keyname+".IPOCurveName", "") 
  1955                 if curve.get() == "":
  1956                     c = gui.getRect(2.0, 1)
  1957                 else:
  1958                     c = gui.getRect(1.1, 1)
  1959                 
  1960                 Draw.String("Ipo:", evtLuxGui, c[0], c[1], c[2], c[3], curve.get(), 250, "Set IPO Name", lambda e,v: curve.set(v))
  1961                 
  1962                 usemapping = luxProp(obj, keyname+".IPOmap", "false")
  1963                 icu_value = 0
  1964     
  1965                 # Apply IPO to value
  1966                 if curve.get() != "":
  1967                     try:
  1968                         ipoob = Blender.Ipo.Get(curve.get())
  1969                     except: 
  1970                         curve.set("")
  1971                     pass
  1972                     if curve.get() != "":
  1973                         names = list([x[0] for x in ipoob.curveConsts.items()])
  1974                         ipotype = luxProp(obj, keyname+".IPOCurveType", "OB_LOCZ")
  1975                         luxOption("ipocurve", ipotype, names, "IPO Curve", "Set IPO Curve", gui, 0.6)
  1976     
  1977                         icu = ipoob[eval("Blender.Ipo.%s" % (ipotype.get()))]
  1978                         icu_value = icu[Blender.Get('curframe')]
  1979                         if usemapping.get() == "false": # if true is set during mapping below
  1980                             lux.set(icu_value)    
  1981     
  1982                         # Mapping options
  1983                         m = gui.getRect(0.3, 1)
  1984                         Draw.Toggle("Map", evtLuxGui, m[0], m[1], m[2], m[3], usemapping.get()=="true", "Edit Curve mapping", lambda e,v: usemapping.set(["false","true"][bool(v)]))
  1985                         if usemapping.get() == "true":
  1986                             if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
  1987                             fmin = luxProp(obj, keyname+".IPOCurvefmin", 0.0)
  1988                             luxFloatNoIPO("ipofmin", fmin, -100, 100, "fmin", "Map minimum value from Curve", gui, 0.5)
  1989                             fmax = luxProp(obj, keyname+".IPOCurvefmax", 1.0)
  1990                             luxFloatNoIPO("ipofmax", fmax, -100, 100, "fmax", "Map maximum value from Curve", gui, 0.5)
  1991                             tmin = luxProp(obj, keyname+".IPOCurvetmin", min)
  1992                             luxFloatNoIPO("ipotmin", tmin, min, max, "tmin", "Map miminum value to", gui, 0.5)
  1993                             tmax = luxProp(obj, keyname+".IPOCurvetmax", max)
  1994                             luxFloatNoIPO("ipotmax", tmax, min, max, "tmax", "Map maximum value to", gui, 0.5)
  1995     
  1996                             sval = (icu_value - fmin.getFloat()) / (fmax.getFloat() - fmin.getFloat())
  1997                             lux.set(tmin.getFloat() + (sval * (tmax.getFloat() - tmin.getFloat())))
  1998 
  1999                             # invert
  2000                             #v = gui.getRect(0.5, 1)
  2001                             #Draw.Toggle("Invert", evtLuxGui, v[0], v[1], v[2], v[3], useipo.get()=="true", "Invert Curve values", lambda e,v: useipo.set(["false","true"][bool(v)]))
  2002     else:
  2003         if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
  2004             obj = lux.getobj()
  2005             keyname = lux.getname()
  2006             useipo = luxProp(obj, keyname+".IPOuse", "false")
  2007             if useipo.get() == "true":
  2008                 curve = luxProp(obj, keyname+".IPOCurveName", "") 
  2009                 try:
  2010                     ipoob = Blender.Ipo.Get(curve.get())
  2011                 except: 
  2012                     curve.set("")
  2013                 pass
  2014                 usemapping = luxProp(obj, keyname+".IPOmap", "false")
  2015                 icu_value = 0
  2016                 if curve.get() != "":
  2017                     names = list([x[0] for x in ipoob.curveConsts.items()])
  2018                     ipotype = luxProp(obj, keyname+".IPOCurveType", "OB_LOCZ")
  2019     
  2020                     icu = ipoob[eval("Blender.Ipo.%s" % (ipotype.get()))]
  2021                     icu_value = icu[Blender.Get('curframe')]
  2022                     if usemapping.get() == "false": # if true is set during mapping below
  2023                         lux.set(icu_value)    
  2024     
  2025                 if usemapping.get() == "true":
  2026                     if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
  2027                     fmin = luxProp(obj, keyname+".IPOCurvefmin", 0.0)
  2028                     fmax = luxProp(obj, keyname+".IPOCurvefmax", 1.0)
  2029                     tmin = luxProp(obj, keyname+".IPOCurvetmin", min)
  2030                     tmax = luxProp(obj, keyname+".IPOCurvetmax", max)
  2031                     sval = (icu_value - fmin.getFloat()) / (fmax.getFloat() - fmin.getFloat())
  2032                     lux.set(tmin.getFloat() + (sval * (tmax.getFloat() - tmin.getFloat())))
  2033 
  2034     return "\n   \"float %s\" [%f]"%(name, lux.getFloat())
  2035 
  2036 def luxFloatNoIPO(name, lux, min, max, caption, hint, gui, width=1.0, useslider=0):
  2037     if gui:
  2038         r = gui.getRect(width, 1)
  2039         if(useslider==1):
  2040             Draw.Slider(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, 0, hint, lambda e,v: lux.set(v))
  2041         else:
  2042             Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, hint, lambda e,v: lux.set(v))
  2043     return "\n   \"float %s\" [%f]"%(name, lux.getFloat())
  2044 
  2045 
  2046 
  2047 def luxInt(name, lux, min, max, caption, hint, gui, width=1.0):
  2048     if gui:
  2049         r = gui.getRect(width, 1)
  2050         Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getInt(), min, max, hint, lambda e,v: lux.set(v))
  2051     return "\n   \"integer %s\" [%d]"%(name, lux.getInt())
  2052 
  2053 def luxBool(name, lux, caption, hint, gui, width=1.0):
  2054     if gui:
  2055         r = gui.getRect(width, 1)
  2056         Draw.Toggle(caption, evtLuxGui, r[0], r[1], r[2], r[3], lux.get()=="true", hint, lambda e,v: lux.set(["false","true"][bool(v)]))
  2057     return "\n   \"bool %s\" [\"%s\"]"%(name, lux.get())
  2058 
  2059 def luxCollapse(name, lux, caption, hint, gui, width=1.0):
  2060     if gui:
  2061         r = gui.getRect(width, 1)
  2062         if lux.get() == "true":
  2063             drawArrow(arrow_down, r[0]-22, r[1]-2)
  2064         else:
  2065             drawArrow(arrow_right, r[0]-22, r[1]-2)
  2066         Draw.Toggle(caption, evtLuxGui, r[0], r[1], r[2], r[3], lux.get()=="true", hint, lambda e,v: lux.set(["false","true"][bool(v)]))
  2067     return "\n   \"bool %s\" [\"%s\"]"%(name, lux.get())
  2068 
  2069 def luxString(name, lux, caption, hint, gui, width=1.0):
  2070     if gui:
  2071         r = gui.getRect(width, 1)
  2072         Draw.String(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.get(), 250, hint, lambda e,v: lux.set(v))
  2073     if lux.get()==lux.default: return ""
  2074     else: return "\n   \"string %s\" [\"%s\"]"%(name, luxstr(lux.get()))
  2075 
  2076 def luxFile(name, lux, caption, hint, gui, width=1.0):
  2077     if gui:
  2078         r = gui.getRect(width, 1)
  2079         Draw.String(caption+": ", evtLuxGui, r[0], r[1], r[2]-r[3]-2, r[3], lux.get(), 250, hint, lambda e,v: lux.set(v))
  2080         Draw.Button("...", 0, r[0]+r[2]-r[3], r[1], r[3], r[3], "click to open file selector", lambda e,v:Window.FileSelector(lambda s:lux.set(s), "Select %s"%(caption), lux.get()))
  2081     return "\n   \"string %s\" [\"%s\"]"%(name, luxstr(luxFilePath(lux.get())))
  2082 
  2083 def luxPath(name, lux, caption, hint, gui, width=1.0):
  2084     if gui:
  2085         r = gui.getRect(width, 1)
  2086         Draw.String(caption+": ", evtLuxGui, r[0], r[1], r[2]-r[3]-2, r[3], lux.get(), 250, hint, lambda e,v: lux.set(Blender.sys.dirname(v)+os.sep))
  2087         Draw.Button("...", 0, r[0]+r[2]-r[3], r[1], r[3], r[3], "click to open file selector", lambda e,v:Window.FileSelector(lambda s:lux.set(s), "Select %s"%(caption), lux.get()))
  2088     return "\n   \"string %s\" [\"%s\"]"%(name, luxstr(lux.get()))
  2089 
  2090 def luxRGB(name, lux, max, caption, hint, gui, width=2.0):
  2091     if gui:
  2092         r = gui.getRect(width, 1)
  2093         scale = 1.0
  2094         rgb = lux.getRGB()
  2095         if max > 1.0:
  2096             for i in range(3):
  2097                 if rgb[i] > scale: scale = rgb[i]
  2098             rgb = (rgb[0]/scale, rgb[1]/scale, rgb[2]/scale)
  2099         Draw.ColorPicker(evtLuxGui, r[0], r[1], r[3], r[3], rgb, "click to select color", lambda e,v: lux.setRGB((v[0]*scale,v[1]*scale,v[2]*scale)))
  2100         w = int((r[2]-r[3])/3); m = max
  2101         if max > 1.0:
  2102             w = int((r[2]-r[3])/4); m = 1.0
  2103         drawR, drawG, drawB, drawS = Draw.Create(rgb[0]), Draw.Create(rgb[1]), Draw.Create(rgb[2]), Draw.Create(scale)
  2104         drawR = Draw.Number("R:", evtLuxGui, r[0]+r[3], r[1], w, r[3], drawR.val, 0.0, m, "red", lambda e,v: lux.setRGB((v*scale,drawG.val*scale,drawB.val*scale)))
  2105         drawG = Draw.Number("G:", evtLuxGui, r[0]+r[3]+w, r[1], w, r[3], drawG.val, 0.0, m, "green", lambda e,v: lux.setRGB((drawR.val*scale,v*scale,drawB.val*scale)))
  2106         drawB = Draw.Number("B:", evtLuxGui, r[0]+r[3]+2*w, r[1], w, r[3], drawB.val, 0.0, m, "blue", lambda e,v: lux.setRGB((drawR.val*scale,drawG.val*scale,v*scale)))
  2107         if max > 1.0:
  2108             Draw.Number("s:", evtLuxGui, r[0]+r[3]+3*w, r[1], w, r[3], drawS.val, 0.0, max, "color scale", lambda e,v: lux.setRGB((drawR.val*v,drawG.val*v,drawB.val*v)))
  2109     if max <= 1.0:
  2110         return "\n   \"color %s\" [%s]"%(name, lux.getRGC())
  2111     return "\n   \"color %s\" [%s]"%(name, lux.get())
  2112 
  2113 def luxVector(name, lux, min, max, caption, hint, gui, width=2.0):
  2114     if gui:
  2115         r = gui.getRect(width, 1)
  2116         vec = lux.getVector()
  2117         w = int(r[2]/3)
  2118         drawX, drawY, drawZ = Draw.Create(vec[0]), Draw.Create(vec[1]), Draw.Create(vec[2])
  2119         drawX = Draw.Number("x:", evtLuxGui, r[0], r[1], w, r[3], drawX.val, min, max, "", lambda e,v: lux.setVector((v,drawY.val,drawZ.val)))
  2120         drawY = Draw.Number("y:", evtLuxGui, r[0]+w, r[1], w, r[3], drawY.val, min, max, "", lambda e,v: lux.setVector((drawX.val,v,drawZ.val)))
  2121         drawZ = Draw.Number("z:", evtLuxGui, r[0]+2*w, r[1], w, r[3], drawZ.val, min, max, "", lambda e,v: lux.setVector((drawX.val,drawY.val,v)))
  2122     return "\n   \"vector %s\" [%s]"%(name, lux.get())
  2123 
  2124 def luxVectorUniform(name, lux, min, max, caption, hint, gui, width=2.0):
  2125     def setUniform(lux, value):
  2126         if value: lux.set(lux.getFloat())
  2127         else: lux.setVector(lux.getVector())
  2128     if gui:
  2129         r = gui.getRect(width, 1)
  2130         vec = lux.getVector()
  2131         Draw.Toggle("U", evtLuxGui, r[0], r[1], gui.h, gui.h, lux.isFloat(), "uniform", lambda e,v: setUniform(lux, v))
  2132         if lux.isFloat():
  2133             Draw.Number("v:", evtLuxGui, r[0]+gui.h, r[1], r[2]-gui.h, r[3], lux.getFloat(), min, max, "", lambda e,v: lux.set(v))
  2134         else:
  2135             w = int((r[2]-gui.h)/3)
  2136             drawX, drawY, drawZ = Draw.Create(vec[0]), Draw.Create(vec[1]), Draw.Create(vec[2])
  2137             drawX = Draw.Number("x:", evtLuxGui, r[0]+gui.h, r[1], w, r[3], drawX.val, min, max, "", lambda e,v: lux.setVector((v,drawY.val,drawZ.val)))
  2138             drawY = Draw.Number("y:", evtLuxGui, r[0]+w+gui.h, r[1], w, r[3], drawY.val, min, max, "", lambda e,v: lux.setVector((drawX.val,v,drawZ.val)))
  2139             drawZ = Draw.Number("z:", evtLuxGui, r[0]+2*w+gui.h, r[1], w, r[3], drawZ.val, min, max, "", lambda e,v: lux.setVector((drawX.val,drawY.val,v)))
  2140     return "\n   \"vector %s\" [%s]"%(name, lux.getVectorStr())
  2141 
  2142 
  2143 # lux individual identifiers
  2144 def luxCamera(cam, context, gui=None):
  2145     global icon_c_camera
  2146     str = ""
  2147     if cam:
  2148         camtype = luxProp(cam, "camera.type", "perspective")
  2149         # Radiance - remarked 'realistic' for v0.6 release
  2150         #str = luxIdentifier("Camera", camtype, ["perspective","orthographic","environment","realistic"], "CAMERA", "select camera type", gui, icon_c_camera)
  2151         str = luxIdentifier("Camera", camtype, ["perspective","orthographic","environment"], "CAMERA", "select camera type", gui, icon_c_camera)
  2152         scale = 1.0
  2153         if camtype.get() == "perspective":
  2154             if gui: gui.newline("  View:")
  2155             str += luxFloat("fov", luxAttr(cam, "angle"), 8.0, 170.0, "fov", "camera field-of-view angle", gui)
  2156             fl = luxAttr(cam, "lens")
  2157             if gui:
  2158                 luxFloat("lens", fl, 1.0, 250.0, "focallength", "camera focal length", gui)
  2159             
  2160         if camtype.get() == "orthographic" :
  2161             str += luxFloat("scale", luxAttr(cam, "scale"), 0.01, 1000.0, "scale", "orthographic camera scale", gui)
  2162             scale = cam.scale / 2
  2163         if camtype.get() == "realistic":
  2164             
  2165             if gui: gui.newline("  View:")
  2166             fov = luxAttr(cam, "angle")
  2167             str += luxFloat("fov", fov, 8.0, 170.0, "fov", "camera field-of-view angle", gui)
  2168             if gui: luxFloat("lens", luxAttr(cam, "lens"), 1.0, 250.0, "focallength", "camera focal length", gui)
  2169             
  2170             
  2171             if gui: gui.newline()
  2172             str += luxFile("specfile", luxProp(cam, "camera.realistic.specfile", ""), "spec-file", "", gui, 1.0)
  2173 #            if gui: gui.newline()
  2174 # auto calc        str += luxFloat("filmdistance", luxProp(cam, "camera.realistic.filmdistance", 70.0), 0.1, 1000.0, "film-dist", "film-distance [mm]", gui)
  2175             filmdiag = luxProp(cam, "camera.realistic.filmdiag", 35.0)
  2176             str += luxFloat("filmdiag", filmdiag, 0.1, 1000.0, "film-diag", "[mm]", gui)
  2177             if gui: gui.newline()
  2178             fstop = luxProp(cam, "camera.realistic.fstop", 1.0)
  2179             luxFloat("aperture_diameter", fstop, 0.1, 100.0, "f-stop", "", gui)
  2180             dofdist = luxAttr(cam, "dofDist")
  2181             luxFloat("focaldistance", dofdist, 0.0, 10000.0, "distance", "Distance from the camera at which objects will be in focus. Has no effect if Lens Radius is 0", gui)
  2182             if gui:
  2183                 Draw.Button("S", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, "focus selected object", lambda e,v:setFocus("S"))
  2184                 Draw.Button("C", evtLuxGui, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "focus cursor", lambda e,v:setFocus("C"))
  2185             focal = filmdiag.get()*0.001 / math.tan(fov.get() * math.pi / 360.0) / 2.0
  2186             print "calculated focal length: %f mm"%(focal * 1000.0)
  2187             aperture_diameter = focal / fstop.get()
  2188             print "calculated aperture diameter: %f mm"%(aperture_diameter * 1000.0)
  2189             str += "\n   \"float aperture_diameter\" [%f]"%(aperture_diameter*1000.0)
  2190             filmdistance = dofdist.get() * focal / (dofdist.get() - focal)
  2191             print "calculated film distance: %f mm"%(filmdistance * 1000.0)
  2192             str += "\n   \"float filmdistance\" [%f]"%(filmdistance*1000.0)
  2193 
  2194         # Clipping
  2195         useclip = luxProp(cam, "useclip", "false")
  2196         luxCollapse("useclip", useclip, "Near & Far Clipping", "Enable Camera near and far clipping options", gui, 2.0)
  2197         if(useclip.get() == "true"):
  2198             if gui: gui.newline("  Clipping:")
  2199             str += luxFloat("hither", luxAttr(cam, "clipStart"), 0.0, 100.0, "start", "near clip distance", gui)
  2200             str += luxFloat("yon", luxAttr(cam, "clipEnd"), 1.0, 10000.0, "end", "far clip distance", gui)
  2201 
  2202         # Depth of Field
  2203         usedof = luxProp(cam, "usedof", "false")
  2204         
  2205         if camtype.get() in ["perspective", "orthographic"]:
  2206             luxCollapse("usedof", usedof, "Depth of Field & Bokeh", "Enable Depth of Field & Aperture options", gui, 2.0)
  2207             
  2208             
  2209             if usedof.get() == "true":
  2210                 
  2211                 if gui: gui.newline("  DOF:")
  2212                 
  2213                 lr = luxProp(cam, "camera.lensradius", 0.01)
  2214                 fs = luxProp(cam, "camera.fstop", 2.8)
  2215                 
  2216                 if camtype.get() == "perspective":
  2217                     
  2218                     usefstop = luxProp(cam, "usefstop", "false")
  2219                     luxBool("usefstop", usefstop, "Use f/stop", "Use f/stop to define DOF effect", gui, 1.0)
  2220                     
  2221                     LR_SCALE = 1000.0       # lr in metres -> mm
  2222                     FL_SCALE = 1.0          # fl in mm -> mm
  2223                     
  2224                     def lr_2_fs(fl, lr):
  2225                         lr += 0.00000001
  2226                         return fl / ( 2.0 * lr )
  2227                     
  2228                     def fs_2_lr(fl, fs):
  2229                         return fl / ( 2.0 * fs )
  2230                     
  2231                     if usefstop.get() == 'true':
  2232                         lr.set(fs_2_lr(fl.get() * FL_SCALE, fs.get()) / LR_SCALE)
  2233                         luxFloat("fstop", fs, 0.9, 64.0, "fstop", "Defines the lens aperture.", gui)
  2234                         str += luxFloat("lensradius", lr, 0.0, 1.0, "", "", None)
  2235                     else:
  2236                         fs.set(lr_2_fs(fl.get() * FL_SCALE, lr.get() * LR_SCALE))
  2237                         str += luxFloat("lensradius", lr, 0.0, 1.0, "lens-radius", "Defines the lens radius. Values higher than 0. enable DOF and control the amount", gui)
  2238                 else:
  2239                     str += luxFloat("lensradius", lr, 0.0, 1.0, "lens-radius", "Defines the lens radius. Values higher than 0. enable DOF and control the amount", gui)
  2240                 
  2241                 focustype = luxProp(cam, "camera.focustype", "autofocus")
  2242                 luxOption("focustype", focustype, ["autofocus", "manual", "object"], "Focus Type", "Choose the focus behaviour", gui)
  2243                 
  2244     
  2245                 if focustype.get() == "autofocus":
  2246                     str += luxBool("autofocus",luxProp(cam, "camera.autofocus", "true"), "autofocus", "Enable automatic focus", gui)
  2247                 if focustype.get() == "object":
  2248                     objectfocus = luxProp(cam, "camera.objectfocus", "")
  2249                     luxString("objectfocus", objectfocus, "object", "Always focus camera on named object", gui, 1.0)
  2250                     dofdist = luxAttr(cam, "dofDist")
  2251                     str += luxFloat("focaldistance", dofdist, 0.0, 100.0, "distance", "Distance from the camera at which objects will be in focus. Has no effect if Lens Radius is 0", gui)
  2252                     if objectfocus.get() != "":
  2253                         setFocus(objectfocus.get())
  2254                 if focustype.get() == "manual":
  2255                     dofdist = luxAttr(cam, "dofDist")
  2256                     str += luxFloat("focaldistance", dofdist, 0.0, 100.0, "distance", "Distance from the camera at which objects will be in focus. Has no effect if Lens Radius is 0", gui)
  2257                     if gui:
  2258                         Draw.Button("S", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, "focus selected object", lambda e,v:setFocus("S"))
  2259                         Draw.Button("C", evtLuxGui, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "focus cursor", lambda e,v:setFocus("C"))
  2260 
  2261         if camtype.get() == "perspective" and usedof.get() == "true":
  2262             str += luxInt("blades", luxProp(cam, "camera.blades", 6), 0, 16, "aperture blades", "Number of blade edges of the aperture, values 0 to 2 defaults to a circle", gui)
  2263             str += luxOption("distribution", luxProp(cam, "camera.distribution", "uniform"), ["uniform", "exponential", "inverse exponential", "gaussian", "inverse gaussian"], "distribution", "Choose the lens sampling distribution. Non-uniform distributions allow for ring effects.", gui)
  2264             str += luxInt("power", luxProp(cam, "camera.power", 1), 0, 512, "power", "Exponent for the expression in exponential distribution. Higher value gives a more pronounced ring effect.", gui)
  2265 
  2266         useaspect = luxProp(cam, "useaspectratio", "false")
  2267         aspectratio = luxProp(cam, "ratio", 1.3333)
  2268         if camtype.get() in ["perspective", "orthographic"]:
  2269             useshift = luxProp(cam, "camera.useshift", "false")
  2270             luxCollapse("useshift", useshift, "Architectural (Lens Shift) & Aspect Ratio", "Enable Lens Shift and Aspect Ratio options", gui, 2.0)
  2271             if(useshift.get() == "true"):
  2272                 if gui: gui.newline("  Shift:")
  2273                 luxFloat("X", luxAttr(cam, "shiftX"), -2.0, 2.0, "X", "horizontal lens shift", gui)
  2274                 luxFloat("Y", luxAttr(cam, "shiftY"), -2.0, 2.0, "Y", "vertical lens shift", gui)
  2275 
  2276                 if gui: gui.newline("  AspectRatio:")
  2277                 luxBool("useaspectratio", useaspect, "Custom", "Define a custom frame aspect ratio", gui)
  2278                 if useaspect.get() == "true":
  2279                     str += luxFloat("frameaspectratio", aspectratio, 0.0001, 3.0, "aspectratio", "Frame aspect ratio", gui)
  2280             if context:
  2281                 if useaspect.get() == "true":
  2282                     ratio = 1./aspectratio.get()
  2283                 else:
  2284                         ratio = float(context.sizeY)/float(context.sizeX)
  2285                 if ratio < 1.0:
  2286                     screenwindow = [(2*cam.shiftX-1)*scale, (2*cam.shiftX+1)*scale, (2*cam.shiftY-ratio)*scale, (2*cam.shiftY+ratio)*scale]
  2287                 else:
  2288                     screenwindow = [(2*cam.shiftX-1/ratio)*scale, (2*cam.shiftX+1/ratio)*scale, (2*cam.shiftY-1)*scale, (2*cam.shiftY+1)*scale]
  2289                 # render region option
  2290                 if context.borderRender:
  2291                     (x1,y1,x2,y2) = context.border
  2292                     screenwindow = [screenwindow[0]*(1-x1)+screenwindow[1]*x1, screenwindow[0]*(1-x2)+screenwindow[1]*x2,\
  2293                             screenwindow[2]*(1-y1)+screenwindow[3]*y1, screenwindow[2]*(1-y2)+screenwindow[3]*y2]
  2294                 str += "\n   \"float screenwindow\" [%f %f %f %f]"%(screenwindow[0], screenwindow[1], screenwindow[2], screenwindow[3])
  2295 
  2296         # Note - radiance - this is a work in progress
  2297         # Flash lamp option for perspective and ortho cams
  2298 #        if camtype.get() in ["perspective", "orthographic"]:
  2299 #            useflash = luxProp(cam, "useflash", "false")
  2300 #            luxBool("useflash", useflash, "Flash Lamp", "Enable Camera mounted flash lamp options", gui, 2.0)
  2301 
  2302         # Motion Blur Options (common to all cameras)
  2303         usemblur = luxProp(cam, "usemblur", "false")
  2304         luxCollapse("usemblur", usemblur, "Motion Blur", "Enable Motion Blur", gui, 2.0)
  2305         if(usemblur.get() == "true"):    
  2306             if gui: gui.newline("  Shutter:")
  2307             mblurpreset = luxProp(cam, "mblurpreset", "true")
  2308             luxBool("mblurpreset", mblurpreset, "Preset", "Enable use of Shutter Presets", gui, 0.4)
  2309             if(mblurpreset.get() == "true"):
  2310                 shutterpresets = ["full frame", "half frame", "quarter frame", "1/25", "1/30", "1/45", "1/60", "1/85", "1/125", "1/250", "1/500"]        
  2311                 shutterpreset = luxProp(cam, "camera.shutterspeedpreset", "full frame")
  2312                 luxOption("shutterpreset", shutterpreset, shutterpresets, "shutterspeed", "Choose the Shutter speed preset.", gui, 1.0)
  2313 
  2314                 fpspresets = ["10 FPS", "12 FPS", "20 FPS", "25 FPS", "29.99 FPS", "30 FPS", "50 FPS", "60 FPS"]
  2315                 shutfps = luxProp(cam, "camera.shutfps", "25 FPS")
  2316                 luxOption("shutfps", shutfps, fpspresets, "@", "Choose the number of frames per second as the time base.", gui, 0.6)
  2317 
  2318                 sfps = shutfps.get()
  2319                 fps = 25
  2320                 if sfps == "10 FPS": fps = 10
  2321                 elif sfps == "12 FPS": fps = 12
  2322                 elif sfps == "20 FPS": fps = 20
  2323                 elif sfps == "25 FPS": fps = 25
  2324                 elif sfps == "29.99 FPS": fps = 29.99
  2325                 elif sfps == "30 FPS": fps = 30
  2326                 elif sfps == "50 FPS": fps = 50
  2327                 elif sfps == "60 FPS": fps = 60
  2328 
  2329                 spre = shutterpreset.get()
  2330                 open = 0.0
  2331                 close = 1.0
  2332                 if spre == "full frame": close = 1.0
  2333                 elif spre == "half frame": close = 0.5
  2334                 elif spre == "quarter frame": close = 0.25
  2335                 elif spre == "1/25": close = 1.0 / 25.0 * fps
  2336                 elif spre == "1/30": close = 1.0 / 30.0 * fps
  2337                 elif spre == "1/45": close = 1.0 / 45.0 * fps
  2338                 elif spre == "1/60": close = 1.0 / 60.0 * fps
  2339                 elif spre == "1/85": close = 1.0 / 85.0 * fps
  2340                 elif spre == "1/125": close = 1.0 / 125.0 * fps
  2341                 elif spre == "1/250": close = 1.0 / 250.0 * fps
  2342                 elif spre == "1/500": close = 1.0 / 500.0 * fps
  2343 
  2344                 str += "\n   \"float shutteropen\" [%f]\n   \"float shutterclose\" [%f] "%(open,close)
  2345 
  2346             else:
  2347                 str += luxFloat("shutteropen", luxProp(cam, "camera.shutteropen", 0.0), 0.0, 100.0, "open", "time in seconds when shutter opens", gui, 0.8)
  2348                 str += luxFloat("shutterclose", luxProp(cam, "camera.shutterclose", 1.0), 0.0, 100.0, "close", "time in seconds when shutter closes", gui, 0.8)
  2349 
  2350             str += luxOption("shutterdistribution", luxProp(cam, "camera.shutterdistribution", "uniform"), ["uniform", "gaussian"], "distribution", "Choose the shutter sampling distribution.", gui, 2.0)
  2351             objectmblur = luxProp(cam, "objectmblur", "true")
  2352             luxBool("objectmblur", objectmblur, "Object", "Enable Motion Blur for scene object motions", gui, 1.0)
  2353             cammblur = luxProp(cam, "cammblur", "true")
  2354             luxBool("cammblur", cammblur, "Camera", "Enable Motion Blur for Camera motion", gui, 1.0)
  2355     return str
  2356 
  2357 
  2358 def luxFilm(scn, gui=None):
  2359     str = ""
  2360     if scn:
  2361         filmtype = luxProp(scn, "film.type", "fleximage")
  2362         str = luxIdentifier("Film", filmtype, ["fleximage"], "FILM", "select film type", gui)
  2363         if filmtype.get() == "fleximage":
  2364             context = scn.getRenderingContext()
  2365             if context:
  2366                 if gui: gui.newline("  Resolution:")
  2367                 luxInt("xresolution", luxAttr(context, "sizeX"), 0, 8192, "X", "width of the render", gui, 0.666)
  2368                 luxInt("yresolution", luxAttr(context, "sizeY"), 0, 8192, "Y", "height of the render", gui, 0.666)
  2369                 scale = luxProp(scn, "film.scale", "100 %")
  2370                 luxOption("", scale, ["400 %", "200 %", "100 %", "75 %", "50 %", "25 %"], "scale", "scale resolution", gui, 0.666)
  2371                 scale = int(scale.get()[:-1])
  2372                 # render region option
  2373                 if context.borderRender:
  2374                     (x1,y1,x2,y2) = context.border
  2375                     if (x1==x2) and (y1==y2): print "WARNING: empty render-region, use SHIFT-B to set render region in Blender."
  2376                     str += "\n   \"integer xresolution\" [%d] \n   \"integer yresolution\" [%d]"%(luxAttr(context, "sizeX").get()*scale/100*(x2-x1), luxAttr(context, "sizeY").get()*scale/100*(y2-y1))
  2377                 else:
  2378                     str += "\n   \"integer xresolution\" [%d] \n   \"integer yresolution\" [%d]"%(luxAttr(context, "sizeX").get()*scale/100, luxAttr(context, "sizeY").get()*scale/100)
  2379 
  2380             if gui: gui.newline("  Halt:")
  2381             str += luxInt("haltspp", luxProp(scn, "haltspp", 0), 0, 32768, "haltspp", "Stop rendering after specified amount of samples per pixel / 0 = never halt", gui)
  2382             palpha = luxProp(scn, "film.premultiplyalpha", "false")
  2383             str += luxBool("premultiplyalpha", palpha, "premultiplyalpha", "Pre multiply film alpha channel during normalization", gui)
  2384     
  2385             if gui: gui.newline("  Tonemap:")
  2386             tonemapkernel =    luxProp(scn, "film.tonemapkernel", "reinhard")
  2387             str += luxOption("tonemapkernel", tonemapkernel, ["reinhard", "linear", "contrast", "maxwhite"], "Tonemapping Kernel", "Select the tonemapping kernel to use", gui, 2.0)
  2388             if tonemapkernel.get() == "reinhard":
  2389                 autoywa = luxProp(scn, "film.reinhard.autoywa", "true")
  2390                 #str += luxBool("reinhard_autoywa", autoywa, "auto Ywa", "Automatically determine World Adaption Luminance", gui)
  2391                 if autoywa.get() == "false":
  2392                     str += luxFloat("reinhard_ywa", luxProp(scn, "film.reinhard.ywa", 0.1), 0.001, 1.0, "Ywa", "Display/World Adaption Luminance", gui)
  2393                 str += luxFloat("reinhard_prescale", luxProp(scn, "film.reinhard.prescale", 1.0), 0.0, 10.0, "preScale", "Image scale before tonemap operator", gui)
  2394                 str += luxFloat("reinhard_postscale", luxProp(scn, "film.reinhard.postscale", 1.2), 0.0, 10.0, "postScale", "Image scale after tonemap operator", gui)
  2395                 str += luxFloat("reinhard_burn", luxProp(scn, "film.reinhard.burn", 6.0), 0.1, 12.0, "burn", "12.0: no burn out, 0.1 lot of burn out", gui)
  2396             elif tonemapkernel.get() == "linear":
  2397                 str += luxFloat("linear_sensitivity", luxProp(scn, "film.linear.sensitivity", 50.0), 0.0, 1000.0, "sensitivity", "Adaption/Sensitivity", gui)
  2398                 str += luxFloat("linear_exposure", luxProp(scn, "film.linear.exposure", 1.0), 0.001, 1.0, "exposure", "Exposure duration in seconds", gui)
  2399                 str += luxFloat("linear_fstop", luxProp(scn, "film.linear.fstop", 2.8), 0.1, 64.0, "Fstop", "F-Stop", gui)
  2400                 str += luxFloat("linear_gamma", luxProp(scn, "film.linear.gamma", 1.0), 0.0, 8.0, "gamma", "Tonemap operator gamma correction", gui)
  2401             elif tonemapkernel.get() == "contrast":
  2402                 str += luxFloat("contrast_ywa", luxProp(scn, "film.contrast.ywa", 0.1), 0.001, 1.0, "Ywa", "Display/World Adaption Luminance", gui)
  2403 
  2404             if gui: gui.newline("  Display:")
  2405             str += luxInt("displayinterval", luxProp(scn, "film.displayinterval", 12), 4, 3600, "interval", "Set display Interval (seconds)", gui)
  2406             
  2407             if gui: gui.newline("  Write:")
  2408             str += luxInt("writeinterval", luxProp(scn, "film.writeinterval", 120), 12, 3600, "interval", "Set display Interval (seconds)", gui)
  2409 
  2410         # Image File Outputs
  2411 
  2412         # LDR clamping method
  2413         if gui: gui.newline("  Clamping:")
  2414         ldrclampmethod = luxProp(scn, "film.ldr_clamp_method", "lum")
  2415         str += luxOption("ldr_clamp_method", ldrclampmethod, ["lum", "hue", "cut"], "LDR clamping", "Method to clamp high luminance values for LDR output", gui, 0.5)
  2416         if gui: gui.newline()
  2417 
  2418         # OpenEXR Output
  2419         saveexr = luxProp(scn, "film.write_exr", "false")
  2420         str += luxCollapse("write_exr", saveexr, "OpenEXR Output", "Enable OpenEXR output", gui, 2.0)
  2421 
  2422         if saveexr.get() == "true":
  2423             if gui: gui.newline("  OpenEXR:")
  2424 
  2425             exrchannels = luxProp(scn, "film.write_exr_channels", "RGBA")
  2426             str += luxOption("write_exr_channels", exrchannels, ["Y", "YA", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
  2427             exrres = luxProp(scn, "film.write_exr_halftype", "true")
  2428             str += luxBool("write_exr_halftype", exrres, "16bit Half", "Enable 16bit Half resolution output, otherwise 32bit float", gui, 0.5)
  2429             exrcompression = luxProp(scn, "film.write_exr_compression", "PIZ (lossless)")
  2430             str += luxOption("write_exr_compressiontype", exrcompression, ["RLE (lossless)", "PIZ (lossless)", "ZIP (lossless)", "Pxr24 (lossy)", "None"], "Compression", "Select OpenEXR Compression algorithm to use", gui, 1.0)
  2431 
  2432             exrimaging = luxProp(scn, "film.write_exr_imaging", "true")
  2433             str += luxBool("write_exr_applyimaging", exrimaging, "Apply Imaging/Tonemapping", "Apply Imaging and Tonemapping pipeline", gui, 1.2)
  2434         
  2435             if exrimaging.get()=="true":
  2436                 exrgamutclamp = luxProp(scn, "film.write_exr_gamutclamp", "true")
  2437                 str += luxBool("write_exr_gamutclamp", exrgamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 0.8)
  2438 
  2439             if gui: gui.newline()
  2440             # Zbuf output
  2441             exrZ = luxProp(scn, "film.write_exr_Z", "true")
  2442             str += luxBool("write_exr_ZBuf", exrZ, "ZBuf", "Enable Z Depth Buffer channel", gui, 0.8)
  2443             if exrZ.get() == "true":
  2444                 exrZNormalize = luxProp(scn, "film.write_exr_ZNorm", "None")
  2445                 str += luxOption("write_exr_zbuf_normalizationtype", exrZNormalize, ["Camera Start/End clip", "Min/Max", "None"], "ZBuf Normalization", "Select type of normalization to use for Zbuf Depth Map", gui, 1.2)
  2446 
  2447         # PNG Output
  2448         savepng = luxProp(scn, "film.write_png", "true")
  2449         str += luxCollapse("write_png", savepng, "PNG Output", "Enable PNG (Portable Network Graphics) output", gui, 2.0)
  2450 
  2451         if savepng.get() == "true":
  2452             if gui: gui.newline("  PNG:")
  2453             pngchannels = luxProp(scn, "film.write_png_channels", "RGB")
  2454             str += luxOption("write_png_channels", pngchannels, ["Y", "YA", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
  2455             png16bit = luxProp(scn, "film.write_png_16bit", "false")
  2456             str += luxBool("write_png_16bit", png16bit, "16bit", "Enable 16bits per channel resolution PNG output", gui, 0.5)
  2457             pnggamutclamp = luxProp(scn, "film.write_png_gamutclamp", "true")
  2458             str += luxBool("write_png_gamutclamp", pnggamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 1.0)
  2459 
  2460         # Zbuf output
  2461         #pngZ = luxProp(scn, "film.write_png_ZBuf", "false")
  2462         #str += luxBool("write_png_ZBuf", pngZ, "ZBuf (Separate)", "Enable Z Depth Buffer channel", gui, 0.8)
  2463         #if pngZ.get() == "true":
  2464         #    pngZNormalize = luxProp(scn, "film.write_png_ZNorm", "Min/Max")
  2465         #    str += luxOption("write_png_zbuf_normalizationtype", pngZNormalize, ["Camera Start/End clip", "Min/Max", "None"], "ZBuf Normalization", "Select type of normalization to use for Zbuf Depth Map", gui, 1.2)
  2466 
  2467         # TGA Output
  2468         savetga = luxProp(scn, "film.write_tga", "false")
  2469         str += luxCollapse("write_tga", savetga, "TGA Output", "Enable TGA output", gui, 2.0)
  2470 
  2471         if savetga.get() == "true":
  2472             if gui: gui.newline("  TGA:")
  2473             tgachannels = luxProp(scn, "film.write_tga_channels", "RGB")
  2474             str += luxOption("write_tga_channels", tgachannels, ["Y", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
  2475             tgagamutclamp = luxProp(scn, "film.write_tga_gamutclamp", "true")
  2476             str += luxBool("write_tga_gamutclamp", tgagamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 1.5)
  2477 
  2478         # Zbuf output
  2479         #tgaZ = luxProp(scn, "film.write_tga_ZBuf", "false")
  2480         #str += luxBool("write_tga_ZBuf", tgaZ, "ZBuf (Separate)", "Enable Z Depth Buffer channel", gui, 0.8)
  2481         #if tgaZ.get() == "true":
  2482         #    tgaZNormalize = luxProp(scn, "film.write_tga_ZNorm", "Min/Max")
  2483         #    str += luxOption("write_tga_zbuf_normalizationtype", tgaZNormalize, ["Camera Start/End clip", "Min/Max", "None"], "ZBuf Normalization", "Select type of normalization to use for Zbuf Depth Map", gui, 1.2)
  2484 
  2485 
  2486         # override output image dir in case of command line batch mode 
  2487         overrideop = luxProp(scn, "overrideoutputpath", "")
  2488         if overrideop.get() != "":
  2489             filebase = os.path.splitext(os.path.basename(Blender.Get('filename')))[0]
  2490             filename = overrideop.get() + "/" + filebase + "-%05d" %  (Blender.Get('curframe'))
  2491             str += "\n   \"string filename\" [\"%s\"]"%(filename)
  2492         else:
  2493             fn = luxProp(scn, "filename", "default-%05d" %  (Blender.Get('curframe')))
  2494             str += luxString("filename", fn, "File name", "save file name", None)
  2495     
  2496         if gui: gui.newline("  Resume:")
  2497         resumeflm = luxProp(scn, "film.write_resume_flm", "false")
  2498         str += luxBool("write_resume_flm", resumeflm, "Write/Use FLM", "Write a resume fleximage .flm file, or resume rendering if it already exists", gui)
  2499         restartflm = luxProp(scn, "film.restart_resume_flm", "true")
  2500         str += luxBool("restart_resume_flm", restartflm, "Restart/Erase", "Restart with a black flm, even it a previous flm exists", gui)
  2501         if gui: gui.newline("  Reject:")
  2502         str += luxInt("reject_warmup", luxProp(scn, "film.reject_warmup", 128), 0, 32768, "warmup_spp", "Specify amount of samples per pixel for high intensity rejection", gui)
  2503         debugmode = luxProp(scn, "film.debug", "false")
  2504         str += luxBool("debug", debugmode, "debug", "Turn on debug reporting and switch off reject", gui)
  2505     
  2506         # Colorspace
  2507         if gui: gui.newline("  Colorspace:")
  2508     
  2509         cspaceusepreset = luxProp(scn, "film.colorspaceusepreset", "true")
  2510         luxBool("colorspaceusepreset", cspaceusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
  2511     
  2512         # Default values for 'sRGB - HDTV (ITU-R BT.709-5)'
  2513         cspacewhiteX = luxProp(scn, "film.cspacewhiteX", 0.314275)
  2514         cspacewhiteY = luxProp(scn, "film.cspacewhiteY", 0.329411)
  2515         cspaceredX = luxProp(scn, "film.cspaceredX", 0.63)
  2516         cspaceredY = luxProp(scn, "film.cspaceredY", 0.34)
  2517         cspacegreenX = luxProp(scn, "film.cspacegreenX", 0.31)
  2518         cspacegreenY = luxProp(scn, "film.cspacegreenY", 0.595)
  2519         cspaceblueX = luxProp(scn, "film.cspaceblueX", 0.155)
  2520         cspaceblueY = luxProp(scn, "film.cspaceblueY", 0.07)
  2521         gamma = luxProp(scn, "film.gamma", 2.2)
  2522     
  2523         if(cspaceusepreset.get() == "true"):
  2524             # preset controls
  2525             cspace = luxProp(scn, "film.colorspace", "sRGB - HDTV (ITU-R BT.709-5)")
  2526             cspaces = ["sRGB - HDTV (ITU-R BT.709-5)", "ROMM RGB", "Adobe RGB 98", "Apple RGB", "NTSC (FCC 1953, ITU-R BT.470-2 System M)", "NTSC (1979) (SMPTE C, SMPTE-RP 145)", "PAL/SECAM (EBU 3213, ITU-R BT.470-6)", "CIE (1931) E"]
  2527             luxOption("colorspace", cspace, cspaces, "Colorspace", "select output working colorspace", gui, 1.6)
  2528     
  2529             if cspace.get()=="ROMM RGB":
  2530                 cspacewhiteX.set(0.346); cspacewhiteY.set(0.359) # D50
  2531                 cspaceredX.set(0.7347); cspaceredY.set(0.2653)
  2532                 cspacegreenX.set(0.1596); cspacegreenY.set(0.8404)
  2533                 cspaceblueX.set(0.0366); cspaceblueY.set(0.0001)
  2534             elif cspace.get()=="Adobe RGB 98":
  2535                 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
  2536                 cspaceredX.set(0.64); cspaceredY.set(0.34)
  2537                 cspacegreenX.set(0.21); cspacegreenY.set(0.71)
  2538                 cspaceblueX.set(0.15); cspaceblueY.set(0.06)
  2539             elif cspace.get()=="Apple RGB":
  2540                 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
  2541                 cspaceredX.set(0.625); cspaceredY.set(0.34)
  2542                 cspacegreenX.set(0.28); cspacegreenY.set(0.595)
  2543                 cspaceblueX.set(0.155); cspaceblueY.set(0.07)
  2544             elif cspace.get()=="NTSC (FCC 1953, ITU-R BT.470-2 System M)":
  2545                 cspacewhiteX.set(0.310); cspacewhiteY.set(0.316) # C
  2546                 cspaceredX.set(0.67); cspaceredY.set(0.33)
  2547                 cspacegreenX.set(0.21); cspacegreenY.set(0.71)
  2548                 cspaceblueX.set(0.14); cspaceblueY.set(0.08)
  2549             elif cspace.get()=="NTSC (1979) (SMPTE C, SMPTE-RP 145)":
  2550                 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
  2551                 cspaceredX.set(0.63); cspaceredY.set(0.34)
  2552                 cspacegreenX.set(0.31); cspacegreenY.set(0.595)
  2553                 cspaceblueX.set(0.155); cspaceblueY.set(0.07)
  2554             elif cspace.get()=="PAL/SECAM (EBU 3213, ITU-R BT.470-6)":
  2555                 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
  2556                 cspaceredX.set(0.64); cspaceredY.set(0.33)
  2557                 cspacegreenX.set(0.29); cspacegreenY.set(0.60)
  2558                 cspaceblueX.set(0.15); cspaceblueY.set(0.06)
  2559             elif cspace.get()=="CIE (1931) E":
  2560                 cspacewhiteX.set(0.333); cspacewhiteY.set(0.333) # E
  2561                 cspaceredX.set(0.7347); cspaceredY.set(0.2653)
  2562                 cspacegreenX.set(0.2738); cspacegreenY.set(0.7174)
  2563                 cspaceblueX.set(0.1666); cspaceblueY.set(0.0089)
  2564     
  2565             whitepointusecspace = luxProp(scn, "film.whitepointusecolorspace", "true")
  2566             luxBool("whitepointusecolorspace", whitepointusecspace, "Colorspace Whitepoint", "Use default whitepoint for selected colorspace", gui, 1.0)
  2567             gammausecspace = luxProp(scn, "film.gammausecolorspace", "true")
  2568             luxBool("gammausecolorspace", gammausecspace, "Colorspace Gamma", "Use default output gamma for selected colorspace", gui, 1.0)
  2569     
  2570             if(whitepointusecspace.get() == "false"):
  2571                 if gui: gui.newline("  Whitepoint:")
  2572                 whitepointusepreset = luxProp(scn, "film.whitepointusepreset", "true")
  2573                 luxBool("whitepointusepreset", whitepointusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
  2574     
  2575                 if(whitepointusepreset.get() == "true"):
  2576                     whitepointpresets = ["E", "D50", "D55", "D65", "D75", "A", "B", "C", "9300", "F2", "F7", "F11"]
  2577                     whitepointpreset = luxProp(scn, "film.whitepointpreset", "D65")
  2578                     luxOption("whitepointpreset", whitepointpreset, whitepointpresets, "  PRESET", "select Whitepoint preset", gui, 1.6)
  2579     
  2580                     if whitepointpreset.get()=="E": cspacewhiteX.set(0.333); cspacewhiteY.set(0.333)
  2581                     elif whitepointpreset.get()=="D50": cspacewhiteX.set(0.346); cspacewhiteY.set(0.359)
  2582                     elif whitepointpreset.get()=="D55": cspacewhiteX.set(0.332); cspacewhiteY.set(0.347)
  2583                     elif whitepointpreset.get()=="D65": cspacewhiteX.set(0.313); cspacewhiteY.set(0.329)
  2584                     elif whitepointpreset.get()=="D75": cspacewhiteX.set(0.299); cspacewhiteY.set(0.315)
  2585                     elif whitepointpreset.get()=="A": cspacewhiteX.set(0.448); cspacewhiteY.set(0.407)
  2586                     elif whitepointpreset.get()=="B": cspacewhiteX.set(0.348); cspacewhiteY.set(0.352)
  2587                     elif whitepointpreset.get()=="C": cspacewhiteX.set(0.310); cspacewhiteY.set(0.316)
  2588                     elif whitepointpreset.get()=="9300": cspacewhiteX.set(0.285); cspacewhiteY.set(0.293)
  2589                     elif whitepointpreset.get()=="F2": cspacewhiteX.set(0.372); cspacewhiteY.set(0.375)
  2590                     elif whitepointpreset.get()=="F7": cspacewhiteX.set(0.313); cspacewhiteY.set(0.329)
  2591                     elif whitepointpreset.get()=="F11": cspacewhiteX.set(0.381); cspacewhiteY.set(0.377)
  2592                 else:
  2593                     luxFloat("white X", cspacewhiteX, 0.0, 1.0, "white X", "Whitepoint X weight", gui, 0.8)
  2594                     luxFloat("white Y", cspacewhiteY, 0.0, 1.0, "white Y", "Whitepoint Y weight", gui, 0.8)
  2595     
  2596             if(gammausecspace.get() == "false"):
  2597                 if gui: gui.newline("  Gamma:")
  2598                 luxFloat("gamma", gamma, 0.1, 6.0, "gamma", "Output and RGC Gamma", gui, 2.0)
  2599         else:
  2600             # manual controls
  2601             luxFloat("white X", cspacewhiteX, 0.0, 1.0, "white X", "Whitepoint X weight", gui, 0.8)
  2602             luxFloat("white Y", cspacewhiteY, 0.0, 1.0, "white Y", "Whitepoint Y weight", gui, 0.8)
  2603             luxFloat("red X", cspaceredX, 0.0, 1.0, "red X", "Red component X weight", gui, 1.0)
  2604             luxFloat("red Y", cspaceredY, 0.0, 1.0, "red Y", "Red component Y weight", gui, 1.0)
  2605             luxFloat("green X", cspacegreenX, 0.0, 1.0, "green X", "Green component X weight", gui, 1.0)
  2606             luxFloat("green Y", cspacegreenY, 0.0, 1.0, "green Y", "Green component Y weight", gui, 1.0)
  2607             luxFloat("blue X", cspaceblueX, 0.0, 1.0, "blue X", "Blue component X weight", gui, 1.0)
  2608             luxFloat("blue Y", cspaceblueY, 0.0, 1.0, "blue Y", "Blue component Y weight", gui, 1.0)
  2609             if gui: gui.newline("  Gamma:")
  2610             luxFloat("gamma", gamma, 0.1, 6.0, "gamma", "Output and RGC Gamma", gui, 2.0)
  2611             
  2612         str += "\n   \"float colorspace_white\" [%f %f]"%(cspacewhiteX.get(), cspacewhiteY.get())
  2613         str += "\n   \"float colorspace_red\" [%f %f]"%(cspaceredX.get(), cspaceredY.get())
  2614         str += "\n   \"float colorspace_green\" [%f %f]"%(cspacegreenX.get(), cspacegreenY.get())
  2615         str += "\n   \"float colorspace_blue\" [%f %f]"%(cspaceblueX.get(), cspaceblueY.get())
  2616         str += "\n   \"float gamma\" [%f]"%(gamma.get())
  2617 
  2618     return str
  2619 
  2620 
  2621 def luxPixelFilter(scn, gui=None):
  2622     global icon_c_filter
  2623     str = ""
  2624     if scn:
  2625         filtertype = luxProp(scn, "pixelfilter.type", "mitchell")
  2626         str = luxIdentifier("PixelFilter", filtertype, ["box", "gaussian", "mitchell", "sinc", "triangle"], "FILTER", "select pixel filter type", gui, icon_c_filter)
  2627 
  2628         # Advanced toggle
  2629         parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
  2630         showadvanced = luxProp(scn, "pixelfilter.showadvanced", parammodeadvanced.get())
  2631         luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
  2632         # Help toggle
  2633         showhelp = luxProp(scn, "pixelfilter.showhelp", "false")
  2634         luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
  2635 
  2636         if filtertype.get() == "box":
  2637             if showadvanced.get()=="true":
  2638                 # Advanced parameters
  2639                 if gui: gui.newline()
  2640                 str += luxFloat("xwidth", luxProp(scn, "pixelfilter.box.xwidth", 0.5), 0.0, 10.0, "x-width", "Width of the filter in the x direction", gui)
  2641                 str += luxFloat("ywidth", luxProp(scn, "pixelfilter.box.ywidth", 0.5), 0.0, 10.0, "y-width", "Width of the filter in the y direction", gui)
  2642         if filtertype.get() == "gaussian":
  2643             if showadvanced.get()=="true":
  2644                 # Advanced parameters
  2645                 if gui: gui.newline()
  2646                 str += luxFloat("xwidth", luxProp(scn, "pixelfilter.gaussian.xwidth", 2.0), 0.0, 10.0, "x-width", "Width of the filter in the x direction", gui)
  2647                 str += luxFloat("ywidth", luxProp(scn, "pixelfilter.gaussian.ywidth", 2.0), 0.0, 10.0, "y-width", "Width of the filter in the y direction", gui)
  2648                 if gui: gui.newline()
  2649                 str += luxFloat("alpha", luxProp(scn, "pixelfilter.gaussian.alpha", 2.0), 0.0, 10.0, "alpha", "Gaussian rate of falloff. Lower values give blurrier images", gui)
  2650         if filtertype.get() == "mitchell":
  2651             if showadvanced.get()=="false":
  2652                 # Default parameters
  2653                 if gui: gui.newline("", 8, 0, None, [0.4,0.4,0.4])
  2654                 slidval = luxProp(scn, "pixelfilter.mitchell.sharp", 0.25)
  2655                 luxFloat("sharpness", slidval, 0.0, 1.0, "sharpness", "Specify amount between blurred (left) and sharp/ringed (right)", gui, 2.0, 1)
  2656                 # rule: B + 2*c = 1.0
  2657                 C = slidval.getFloat() * 0.5
  2658                 B = 1.0 - slidval.getFloat()
  2659                 str += "\n   \"float B\" [%f]"%(B)
  2660                 str += "\n   \"float C\" [%f]"%(C)
  2661 
  2662             if showadvanced.get()=="true":
  2663                 # Advanced parameters
  2664                 if gui: gui.newline()
  2665                 str += luxFloat("xwidth", luxProp(scn, "pixelfilter.mitchell.xwidth", 2.0), 0.0, 10.0, "x-width", "Width of the filter in the x direction", gui)
  2666                 str += luxFloat("ywidth", luxProp(scn, "pixelfilter.mitchell.ywidth", 2.0), 0.0, 10.0, "y-width", "Width of the filter in the y direction", gui)
  2667                 if gui: gui.newline()
  2668     
  2669                 optmode = luxProp(scn, "pixelfilter.mitchell.optmode", "slider")
  2670                 luxOption("optmode", optmode, ["slider", "preset", "manual"], "Mode", "Mode of configuration", gui, 0.5)
  2671     
  2672                 if(optmode.get() == "slider"):
  2673                     slidval = luxProp(scn, "pixelfilter.mitchell.sharp", 0.33)
  2674                     luxFloat("sharpness", slidval, 0.0, 1.0, "sharpness", "Specify amount between blurred (left) and sharp/ringed (right)", gui, 1.5, 1)
  2675                     # rule: B + 2*c = 1.0
  2676                     C = slidval.getFloat() * 0.5
  2677                     B = 1.0 - slidval.getFloat()
  2678                     str += "\n   \"float B\" [%f]"%(B)
  2679                     str += "\n   \"float C\" [%f]"%(C)
  2680                 elif(optmode.get() == "preset"):
  2681                     print "not implemented"
  2682                 else:
  2683                     str += luxFloat("B", luxProp(scn, "pixelfilter.mitchell.B", 0.3333), 0.0, 1.0, "B", "Specify the shape of the Mitchell filter. Often best result is when B + 2C = 1", gui, 0.75)
  2684                     str += luxFloat("C", luxProp(scn, "pixelfilter.mitchell.C", 0.3333), 0.0, 1.0, "C", "Specify the shape of the Mitchell filter. Often best result is when B + 2C = 1", gui, 0.75)
  2685 
  2686         if filtertype.get() == "sinc":
  2687             if showadvanced.get()=="true":
  2688                 # Advanced parameters
  2689                 if gui: gui.newline()
  2690                 str += luxFloat("xwidth", luxProp(scn, "pixelfilter.sinc.xwidth", 4.0), 0.0, 10.0, "x-width", "Width of the filter in the x direction", gui)
  2691                 str += luxFloat("ywidth", luxProp(scn, "pixelfilter.sinc.ywidth", 4.0), 0.0, 10.0, "y-width", "Width of the filter in the y direction", gui)
  2692                 if gui: gui.newline()
  2693                 str += luxFloat("tau", luxProp(scn, "pixelfilter.sinc.tau", 3.0), 0.0, 10.0, "tau", "Permitted number of cycles of the sinc function before it is clamped to zero", gui)
  2694         if filtertype.get() == "triangle":
  2695             if showadvanced.get()=="true":
  2696                 # Advanced parameters
  2697                 if gui: gui.newline()
  2698                 str += luxFloat("xwidth", luxProp(scn, "pixelfilter.triangle.xwidth", 2.0), 0.0, 10.0, "x-width", "Width of the filter in the x direction", gui)
  2699                 str += luxFloat("ywidth", luxProp(scn, "pixelfilter.triangle.ywidth", 2.0), 0.0, 10.0, "y-width", "Width of the filter in the y direction", gui)
  2700     return str            
  2701 
  2702 def luxSampler(scn, gui=None):
  2703     global icon_c_sampler, icon_help
  2704     str = ""
  2705     if scn:
  2706         samplertype = luxProp(scn, "sampler.type", "metropolis")
  2707         str = luxIdentifier("Sampler", samplertype, ["metropolis", "erpt", "lowdiscrepancy", "random"], "SAMPLER", "select sampler type", gui, icon_c_sampler)
  2708 
  2709         # Advanced toggle
  2710         parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
  2711         showadvanced = luxProp(scn, "sampler.showadvanced", parammodeadvanced.get())
  2712         luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
  2713         # Help toggle
  2714         showhelp = luxProp(scn, "sampler.showhelp", "false")
  2715         luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
  2716 
  2717         if samplertype.get() == "metropolis":
  2718             if showadvanced.get()=="false":
  2719                 # Default parameters
  2720                 if gui: gui.newline("  Mutation:", 8, 0, None, [0.4,0.4,0.4])
  2721                 strength = luxProp(scn, "sampler.metro.strength", 0.6)
  2722                 luxFloat("strength", strength, 0.0, 1.0, "strength", "Mutation Strength (lmprob = 1.0-strength)", gui, 2.0, 1)
  2723                 v = 1.0 - strength.get()
  2724                 str += "\n   \"float largemutationprob\" [%f]"%v
  2725             if showadvanced.get()=="true":
  2726                 # Advanced parameters
  2727                 if gui: gui.newline("  Mutation:")
  2728                 str += luxFloat("largemutationprob", luxProp(scn, "sampler.metro.lmprob", 0.4), 0.0, 1.0, "LM.prob.", "Probability of generating a large sample (mutation)", gui)
  2729                 str += luxInt("maxconsecrejects", luxProp(scn, "sampler.metro.maxrejects", 512), 0, 32768, "max.rejects", "number of consecutive rejects before a new mutation is forced", gui)
  2730                 if gui: gui.newline("  Screen:")
  2731                 str += luxInt("initsamples", luxProp(scn, "sampler.metro.initsamples", 262144), 1, 1000000, "initsamples", "", gui)
  2732                 str += luxBool("usevariance",luxProp(scn, "sampler.metro.usevariance", "false"), "usevariance", "Accept based on variance", gui, 1.0)
  2733 
  2734             if showhelp.get()=="true":
  2735                 if gui: gui.newline("  Description:", 8, 0, icon_help, [0.4,0.5,0.56])
  2736                 r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5) 
  2737                 Draw.Text("A Metropolis-Hastings mutating sampler which implements MLT", 'small')    
  2738 
  2739         if samplertype.get() == "erpt":
  2740             str += luxInt("initsamples", luxProp(scn, "sampler.erpt.initsamples", 100000), 1, 1000000, "initsamples", "", gui)
  2741             if gui: gui.newline("  Mutation:")
  2742             str += luxInt("chainlength", luxProp(scn, "sampler.erpt.chainlength", 512), 1, 32768, "chainlength", "The number of mutations from a given seed", gui)
  2743             if gui: gui.newline()
  2744             str += luxInt("stratawidth", luxProp(scn, "sampler.erpt.stratawidth", 256), 1, 32768, "stratawidth", "The number of x/y strata for stratified sampling of seeds", gui)
  2745 
  2746         if samplertype.get() == "lowdiscrepancy":
  2747             if gui: gui.newline("  PixelSampler:")
  2748             str += luxOption("pixelsampler", luxProp(scn, "sampler.lowdisc.pixelsampler", "lowdiscrepancy"), ["linear", "tile", "random", "vegas","lowdiscrepancy","hilbert"], "pixel-sampler", "select pixel-sampler", gui)
  2749             str += luxInt("pixelsamples", luxProp(scn, "sampler.lowdisc.pixelsamples", 4), 1, 2048, "samples", "Average number of samples taken per pixel. More samples create a higher quality image at the cost of render time", gui)
  2750 
  2751         if samplertype.get() == "random":
  2752             if gui: gui.newline("  PixelSampler:")
  2753             str += luxOption("pixelsampler", luxProp(scn, "sampler.random.pixelsampler", "vegas"), ["linear", "tile", "random", "vegas","lowdiscrepancy","hilbert"], "pixel-sampler", "select pixel-sampler", gui)
  2754             if gui: gui.newline()
  2755             str += luxInt("xsamples", luxProp(scn, "sampler.random.xsamples", 2), 1, 512, "xsamples", "Allows you to specify how many samples per pixel are taking in the x direction", gui)
  2756             str += luxInt("ysamples", luxProp(scn, "sampler.random.ysamples", 2), 1, 512, "ysamples", "Allows you to specify how many samples per pixel are taking in the y direction", gui)
  2757     return str            
  2758 
  2759 def luxSurfaceIntegrator(scn, gui=None):
  2760     global icon_c_integrator
  2761     str = ""
  2762     if scn:
  2763         integratortype = luxProp(scn, "sintegrator.type", "bidirectional")
  2764         
  2765         str = luxIdentifier("SurfaceIntegrator", integratortype, ["directlighting", "path", "bidirectional", "exphotonmap", "distributedpath", "igi" ], "INTEGRATOR", "select surface integrator type", gui, icon_c_integrator)
  2766 
  2767         # Advanced toggle
  2768         parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
  2769         showadvanced = luxProp(scn, "sintegrator.showadvanced", parammodeadvanced.get())
  2770         luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
  2771         # Help toggle
  2772         showhelp = luxProp(scn, "sintegrator.showhelp", "false")
  2773         luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
  2774 
  2775         if integratortype.get() == "directlighting":
  2776             if showadvanced.get()=="false":
  2777                 # Default parameters
  2778                 if gui: gui.newline("  Depth:", 8, 0, None, [0.4,0.4,0.4])
  2779                 str += luxInt("maxdepth", luxProp(scn, "sintegrator.dlighting.maxdepth", 8), 0, 2048, "bounces", "The maximum recursion depth for ray casting", gui, 2.0)
  2780 
  2781             if showadvanced.get()=="true":
  2782                 # Advanced parameters
  2783                 str += luxOption("strategy", luxProp(scn, "sintegrator.dlighting.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
  2784                 if gui: gui.newline("  Depth:")
  2785                 str += luxInt("maxdepth", luxProp(scn, "sintegrator.dlighting.maxdepth", 8), 0, 2048, "max-depth", "The maximum recursion depth for ray casting", gui)
  2786                 if gui: gui.newline()
  2787 
  2788         if integratortype.get() == "path":
  2789             if showadvanced.get()=="false":
  2790                 # Default parameters
  2791                 if gui: gui.newline("  Depth:", 8, 0, None, [0.4,0.4,0.4])
  2792                 str += luxInt("maxdepth", luxProp(scn, "sintegrator.path.maxdepth", 10), 0, 2048, "bounces", "The maximum recursion depth for ray casting", gui, 1.0)
  2793                 ienv = luxProp(scn, "sintegrator.path.ienvironment", "true")
  2794                 str += luxBool("includeenvironment", ienv, "Include Environment", "Enable/Disable rendering of environment lightsources", gui)
  2795 
  2796             if showadvanced.get()=="true":
  2797                 # Advanced parameters
  2798                 if gui: gui.newline("  Depth:")
  2799                 str += luxInt("maxdepth", luxProp(scn, "sintegrator.path.maxdepth", 10), 0, 2048, "maxdepth", "The maximum recursion depth for ray casting", gui)
  2800                 str += luxOption("strategy", luxProp(scn, "sintegrator.path.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
  2801                 if gui: gui.newline("  RR:")
  2802                 rrstrat = luxProp(scn, "sintegrator.path.rrstrategy", "efficiency")
  2803                 str += luxOption("rrstrategy", rrstrat, ["efficiency", "probability", "none"], "RR strategy", "select Russian Roulette path termination strategy", gui)
  2804                 if rrstrat.get() == "probability":
  2805                     str += luxFloat("rrcontinueprob", luxProp(scn, "sintegrator.path.rrcontinueprob", 0.65), 0.0, 1.0, "rrprob", "Russian roulette continue probability", gui)
  2806                 ienv = luxProp(scn, "sintegrator.path.ienvironment", "true")
  2807                 str += luxBool("includeenvironment", ienv, "Include Environment", "Enable/Disable rendering of environment lightsources", gui)
  2808 
  2809         if integratortype.get() == "bidirectional":
  2810             if showadvanced.get()=="false":
  2811                 # Default parameters
  2812                 if gui: gui.newline("  Depth:", 8, 0, None, [0.4,0.4,0.4])
  2813                 bounces = luxProp(scn, "sintegrator.bidir.bounces", 16)
  2814                 luxInt("bounces", bounces, 5, 32, "bounces", "The maximum recursion depth for ray casting (in both directions)", gui, 2.0)
  2815                 str += "\n   \"integer eyedepth\" [%i]\n"%bounces.get()
  2816                 str += "   \"integer lightdepth\" [%i]"%bounces.get()
  2817 
  2818             if showadvanced.get()=="true":
  2819                 # Advanced parameters
  2820                 if gui: gui.newline("  Depth:")
  2821                 str += luxInt("eyedepth", luxProp(scn, "sintegrator.bidir.eyedepth", 16), 0, 2048, "eyedepth", "The maximum recursion depth for ray casting", gui)
  2822                 str += luxInt("lightdepth", luxProp(scn, "sintegrator.bidir.lightdepth", 16), 0, 2048, "lightdepth", "The maximum recursion depth for light ray casting", gui)
  2823                 str += luxOption("strategy", luxProp(scn, "sintegrator.bidir.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
  2824 
  2825         if integratortype.get() == "exphotonmap":
  2826             if gui: gui.newline("  Render:")
  2827             str += luxOption("renderingmode", luxProp(scn, "sintegrator.photonmap.renderingmode", "directlighting"), ["directlighting", "path"], "renderingmode", "select rendering mode", gui)
  2828             str += luxOption("strategy", luxProp(scn, "sintegrator.photonmap.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
  2829             str += luxInt("maxphotondepth", luxProp(scn, "sintegrator.photonmap.maxphotondepth", 10), 1, 1024, "maxphotondepth", "The maximum recursion depth of photon tracing", gui)
  2830             str += luxInt("maxdepth", luxProp(scn, "sintegrator.photonmap.maxdepth", 6), 1, 1024, "maxdepth", "The maximum recursion depth of specular reflection and refraction", gui)
  2831             str += luxFloat("maxdist", luxProp(scn, "sintegrator.photonmap.maxdist", 0.1), 0.0, 10.0, "maxdist", "The maximum distance between a point being shaded and a photon that can contribute to that point", gui)
  2832             str += luxInt("nused", luxProp(scn, "sintegrator.photonmap.nused", 50), 0, 1000000, "nused", "The number of photons to use in density estimation", gui)
  2833 
  2834             if gui: gui.newline("  Photons:")
  2835             str += luxInt("indirectphotons", luxProp(scn, "sintegrator.photonmap.idphotons", 200000), 0, 10000000, "indirect", "The number of photons to shoot for indirect lighting during preprocessing of the photon map", gui)
  2836             str += luxInt("maxdirectphotons", luxProp(scn, "sintegrator.photonmap.maxdphotons", 1000000), 0, 10000000, "maxdirect", "The maximum number of photons to shoot for direct lighting during preprocessing of the photon map", gui)
  2837             str += luxInt("causticphotons", luxProp(scn, "sintegrator.photonmap.cphotons", 20000), 0, 10000000, "caustic", "The number of photons to shoot for caustics during preprocessing of the photon map", gui)
  2838             if gui: gui.newline("  FinalGather:")
  2839             fg = luxProp(scn, "sintegrator.photonmap.fgather", "true")
  2840             str += luxBool("finalgather", fg, "finalgather", "Enable use of final gather during rendering", gui)
  2841             if fg.get() == "true":
  2842                 rrstrat = luxProp(scn, "sintegrator.photonmap.gatherrrstrategy", "efficiency")
  2843                 str += luxOption("gatherrrstrategy", rrstrat, ["efficiency", "probability", "none"], "RR strategy", "select Russian Roulette gather termination strategy", gui)
  2844                 str += luxInt("finalgathersamples", luxProp(scn, "sintegrator.photonmap.fgathers", 32), 1, 1024, "samples", "The number of finalgather samples to take per pixel during rendering", gui)
  2845                 str += luxFloat("gatherangle", luxProp(scn, "sintegrator.photonmap.gangle", 10.0), 0.0, 360.0, "gatherangle", "Angle for final gather", gui)
  2846                 if rrstrat.get() == "probability":
  2847                     str += luxFloat("gatherrrcontinueprob", luxProp(scn, "sintegrator.photonmap.gatherrrcontinueprob", 0.65), 0.0, 1.0, "rrcontinueprob", "Probability for russian roulette particle tracing termination", gui)
  2848 
  2849         if integratortype.get() == "distributedpath":
  2850             str += luxOption("strategy", luxProp(scn, "sintegrator.distributedpath.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
  2851             if gui: gui.newline("  Direct:")
  2852             str += luxBool("directsampleall",luxProp(scn, "sintegrator.distributedpath.directsampleall", "true"), "Direct ALL", "Include diffuse direct light sample at first vertex", gui, 0.75)
  2853             str += luxInt("directsamples", luxProp(scn, "sintegrator.distributedpath.directsamples", 1), 0, 1024, "s", "The number of direct light samples to take at the eye vertex", gui, 0.25)
  2854             str += luxBool("indirectsampleall",luxProp(scn, "sintegrator.distributedpath.indirectsampleall", "false"), "Indirect ALL", "Include diffuse direct light sample at first vertex", gui, 0.75)
  2855             str += luxInt("indirectsamples", luxProp(scn, "sintegrator.distributedpath.indirectsamples", 1), 0, 1024, "s", "The number of direct light samples to take at the remaining vertices", gui, 0.25)
  2856             if gui: gui.newline("  Diffuse:")
  2857             str += luxInt("diffusereflectdepth", luxProp(scn, "sintegrator.distributedpath.diffusereflectdepth", 3), 0, 2048, "Reflect", "The maximum recursion depth for diffuse reflection ray casting", gui, 0.5)
  2858             str += luxInt("diffusereflectsamples", luxProp(scn, "sintegrator.distributedpath.diffusereflectsamples", 1), 0, 1024, "s", "The number of diffuse reflection samples to take at the eye vertex", gui, 0.25)
  2859             str += luxInt("diffuserefractdepth", luxProp(scn, "sintegrator.distributedpath.diffuserefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for diffuse refraction ray casting", gui, 0.5)
  2860             str += luxInt("diffuserefractsamples", luxProp(scn, "sintegrator.distributedpath.diffuserefractsamples", 1), 0, 1024, "s", "The number of diffuse refraction samples to take at the eye vertex", gui, 0.25)
  2861             str += luxBool("directdiffuse",luxProp(scn, "sintegrator.distributedpath.directdiffuse", "true"), "DL", "Include diffuse direct light sample at first vertex", gui, 0.25)
  2862             str += luxBool("indirectdiffuse",luxProp(scn, "sintegrator.distributedpath.indirectdiffuse", "true"), "IDL", "Include diffuse indirect light sample at first vertex", gui, 0.25)
  2863             if gui: gui.newline("  Glossy:")
  2864             str += luxInt("glossyreflectdepth", luxProp(scn, "sintegrator.distributedpath.glossyreflectdepth", 2), 0, 2048, "Reflect", "The maximum recursion depth for glossy reflection ray casting", gui, 0.5)
  2865             str += luxInt("glossyreflectsamples", luxProp(scn, "sintegrator.distributedpath.glossyreflectsamples", 1), 0, 1024, "s", "The number of glossy reflection samples to take at the eye vertex", gui, 0.25)
  2866             str += luxInt("glossyrefractdepth", luxProp(scn, "sintegrator.distributedpath.glossyrefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for glossy refraction ray casting", gui, 0.5)
  2867             str += luxInt("glossyrefractsamples", luxProp(scn, "sintegrator.distributedpath.glossyrefractsamples", 1), 0, 1024, "s", "The number of glossy refraction samples to take at the eye vertex", gui, 0.25)
  2868             str += luxBool("directglossy",luxProp(scn, "sintegrator.distributedpath.directglossy", "true"), "DL", "Include glossy direct light sample at first vertex", gui, 0.25)
  2869             str += luxBool("indirectglossy",luxProp(scn, "sintegrator.distributedpath.indirectglossy", "true"), "IDL", "Include glossy indirect light sample at first vertex", gui, 0.25)
  2870             if gui: gui.newline("  Specular:")
  2871             str += luxInt("specularreflectdepth", luxProp(scn, "sintegrator.distributedpath.specularreflectdepth", 3), 0, 2048, "Reflect", "The maximum recursion depth for specular reflection ray casting", gui, 1.0)
  2872             str += luxInt("specularrefractdepth", luxProp(scn, "sintegrator.distributedpath.specularrefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for specular refraction ray casting", gui, 1.0)
  2873             #if gui: gui.newline("  Caustics:")
  2874             #str += luxBool("causticsondiffuse",luxProp(scn, "sintegrator.distributedpath.causticsondiffuse", "false"), "Caustics on Diffuse", "Enable caustics on diffuse surfaces (warning: might generate bright pixels)", gui, 1.0)
  2875             #str += luxBool("causticsonglossy",luxProp(scn, "sintegrator.distributedpath.causticsonglossy", "true"), "Caustics on Glossy", "Enable caustics on glossy surfaces (warning: might generate bright pixels)", gui, 1.0)
  2876 
  2877             usereject = luxProp(scn, "sintegrator.distributedpath.usereject", "false")
  2878             luxCollapse("usereject", usereject, "Rejection", "Enable Rejection system to eliminate bright contributions", gui, 2.0)
  2879 
  2880             if usereject.get()=="true":
  2881                 if gui: gui.newline("  Diffuse:")
  2882                 
  2883                 diffusereflectreject = luxProp(scn, "sintegrator.distributedpath.difreflreject", "false")
  2884                 str += luxBool("diffusereflectreject", diffusereflectreject, "Reflect", "Enable Rejection for Diffuse Reflection", gui, 0.4)
  2885                 if diffusereflectreject.get()=="true":
  2886                     str += luxFloat("diffusereflectreject_threshold", luxProp(scn, "sintegrator.distributedpath.difreflrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
  2887             
  2888                 diffuserefractreject = luxProp(scn, "sintegrator.distributedpath.difrefrreject", "false")
  2889                 str += luxBool("diffuserefractreject", diffuserefractreject, "Refract", "Enable Rejection for Diffuse Refraction", gui, 0.4)
  2890                 if diffuserefractreject.get()=="true":
  2891                     str += luxFloat("diffuserefractreject_threshold", luxProp(scn, "sintegrator.distributedpath.difrefrrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
  2892             
  2893                 if gui: gui.newline("  Glossy:")
  2894                 
  2895                 glossyreflectreject = luxProp(scn, "sintegrator.distributedpath.glosreflreject", "false")
  2896                 str += luxBool("glossyreflectreject", glossyreflectreject, "Reflect", "Enable Rejection for Glossy Reflection", gui, 0.4)
  2897                 if glossyreflectreject.get()=="true":
  2898                     str += luxFloat("glossyreflectreject_threshold", luxProp(scn, "sintegrator.distributedpath.glosreflrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
  2899             
  2900                 glossyrefractreject = luxProp(scn, "sintegrator.distributedpath.glosrefrreject", "false")
  2901                 str += luxBool("glossyrefractreject", glossyrefractreject, "Refract", "Enable Rejection for Glossy Refraction", gui, 0.4)
  2902                 if glossyrefractreject.get()=="true":
  2903                     str += luxFloat("glossyrefractreject_threshold", luxProp(scn, "sintegrator.distributedpath.glosrefrrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
  2904     
  2905         if integratortype.get() == "igi":
  2906             if gui: gui.newline("  Depth:", 8, 0, None, [0.4,0.4,0.4])
  2907             depth = luxProp(scn, "sintegrator.igi.maxdepth", 5)
  2908             luxInt("maxdepth", depth, 1, 32, "maxdepth", "The maximum recursion depth for ray casting", gui, 2.0)
  2909             if showadvanced.get()=="true":
  2910                 # Advanced parameters
  2911                 if gui: gui.newline("  VLights:")
  2912                 str += luxInt("nsets", luxProp(scn, "sintegrator.igi.nsets", 4), 1, 100, "nsets", "The number of virtual lights sets", gui)
  2913                 str += luxInt("nlights", luxProp(scn, "sintegrator.igi.nlights", 64), 1, 1000, "nlights", "The number of light paths per light set", gui)
  2914                 str += luxFloat("strategy", luxProp(scn, "sintegrator.igi.mindist", 0.1), 0.01, 10.0, "mindist", "The minimal distance to a virtual light to take it into account", gui)
  2915 
  2916     
  2917     return str
  2918 
  2919 def luxVolumeIntegrator(scn, gui=None):
  2920     global icon_c_volumeintegrator
  2921     str = ""
  2922     if scn:
  2923         integratortype = luxProp(scn, "vintegrator.type", "single")
  2924         str = luxIdentifier("VolumeIntegrator", integratortype, ["emission", "single"], "VOLUME INT", "select volume integrator type", gui, icon_c_volumeintegrator)
  2925         if integratortype.get() == "emission":
  2926             str += luxFloat("stepsize", luxProp(scn, "vintegrator.emission.stepsize", 1.0), 0.0, 100.0, "stepsize", "Stepsize for volumes", gui)
  2927         if integratortype.get() == "single":
  2928             str += luxFloat("stepsize", luxProp(scn, "vintegrator.emission.stepsize", 1.0), 0.0, 100.0, "stepsize", "Stepsize for volumes", gui)
  2929     return str
  2930 
  2931 def luxEnvironment(scn, gui=None):
  2932     global icon_c_environment
  2933     str = ""
  2934     if scn:
  2935         envtype = luxProp(scn, "env.type", "infinite")
  2936         lsstr = luxIdentifier("LightSource", envtype, ["none", "infinite", "sunsky"], "ENVIRONMENT", "select environment light type", gui, icon_c_environment)
  2937         if gui: gui.newline()
  2938         str = ""
  2939         
  2940         if envtype.get() != "none":
  2941             
  2942             if envtype.get() in ["infinite", "sunsky"]:
  2943                 env_lg = luxProp(scn, "env.lightgroup", "default")
  2944                 luxString("env.lightgroup", env_lg, "lightgroup", "Environment light group", gui)
  2945                 if luxProp(scn, "nolg", "false").get()!="true":
  2946                     lsstr = '\nLightGroup "' + env_lg.get() + '"' + lsstr
  2947                 rotZ = luxProp(scn, "env.rotation", 0.0)
  2948                 rotY = luxProp(scn, "env.rotationY", 0.0)
  2949                 rotX = luxProp(scn, "env.rotationX", 0.0)
  2950                 if gui: gui.newline()
  2951                 luxFloat("rotation", rotX, 0.0, 360.0, "rot X", "environment rotation X", gui, 0.66)
  2952                 luxFloat("rotation", rotY, 0.0, 360.0, "rot Y", "environment rotation Y", gui, 0.66)
  2953                 luxFloat("rotation", rotZ, 0.0, 360.0, "rot Z", "environment rotation Z", gui, 0.66)
  2954                 if rotZ.get() != 0 or rotY.get() != 0 or rotX.get() != 0:
  2955                     str += "\tRotate %d 1 0 0\n"%(rotX.get())
  2956                     str += "\tRotate %d 0 1 0\n"%(rotY.get())
  2957                     str += "\tRotate %d 0 0 1\n"%(rotZ.get())
  2958             str += "\t"+lsstr
  2959 
  2960             infinitehassun = 0
  2961             if envtype.get() == "infinite":
  2962                 mapping = luxProp(scn, "env.infinite.mapping", "latlong")
  2963                 mappings = ["latlong","angular","vcross"]
  2964                 mapstr = luxOption("mapping", mapping, mappings, "mapping", "Select mapping type", gui, 0.5)
  2965                 map = luxProp(scn, "env.infinite.mapname", "")
  2966                 mapstr += luxFile("mapname", map, "map-file", "filename of the environment map", gui, 1.5)
  2967                 mapstr += luxFloat("gamma", luxProp(scn, "env.infinite.gamma", 1.0), 0.0, 6.0, "gamma", "", gui, 1.0)
  2968                 
  2969                 if map.get() != "":
  2970                     str += mapstr
  2971                 else:
  2972                     try:
  2973                         worldcolor = Blender.World.Get('World').getHor()
  2974                         str += "\n   \"color L\" [%g %g %g]" %(worldcolor[0], worldcolor[1], worldcolor[2])
  2975                     except: pass
  2976 
  2977                 str += luxFloat("gain", luxProp(scn, "env.infinite.gain", 1.0), 0.0001, 100.0, "gain", "", gui, 1.0)
  2978 
  2979                 infinitesun = luxProp(scn, "env.infinite.hassun", "false")
  2980                 luxCollapse("infinitesun", infinitesun, "Sun Component", "Add Sunlight Component", gui, 2.0)
  2981                 if(infinitesun.get() == "true"):
  2982                     sun_lg = luxProp(scn, "env.sun_lightgroup", "default")
  2983                     luxString("env.lightgroup", sun_lg, "lightgroup", "Sun component light group", gui)
  2984                     if luxProp(scn, "nolg", "false").get()!="true":
  2985                         str += '\nLightGroup "' + sun_lg.get() + '"'
  2986                     str += "\nLightSource \"sun\" "
  2987                     infinitehassun = 1
  2988 
  2989 
  2990             if envtype.get() == "sunsky" or infinitehassun == 1:
  2991                 
  2992                 
  2993                 sun = None
  2994                 for obj in scn.objects:
  2995                     if (obj.getType() == "Lamp") and ((obj.Layers & scn.Layers) > 0):
  2996                         if obj.getData(mesh=1).getType() == 1: # sun object # data
  2997                             sun = obj
  2998                 if sun:
  2999                     str += luxFloat("gain", luxProp(scn, "env.sunsky.gain", 1.0), 0.0, 1000.0, "gain", "Sky gain", gui)
  3000                     
  3001                     invmatrix = Mathutils.Matrix(sun.getInverseMatrix())
  3002                     str += "\n   \"vector sundir\" [%f %f %f]\n" %(invmatrix[0][2], invmatrix[1][2], invmatrix[2][2])
  3003                     str += luxFloat("relsize", luxProp(scn, "env.sunsky.relsize", 1.0), 0.0, 100.0, "rel.size", "relative sun size", gui)
  3004                     str += luxFloat("turbidity", luxProp(scn, "env.sunsky.turbidity", 2.2), 2.0, 50.0, "turbidity", "Sky turbidity", gui)
  3005                     
  3006                     showGeo = luxProp(sun, 'sc.show', 'false')
  3007                     if gui:
  3008                         luxCollapse("sc.show", showGeo, "Geographic Sun", "Set sun position by world location, date and time", gui, 2.0)
  3009                     if gui and showGeo.get() == 'true':
  3010                         gui.newline("Geographic:")
  3011                         sc = sun_calculator(sun)
  3012                         
  3013                         luxInt("sc.day", luxProp(sun, "sc.day", 1), 1, 31, "day", "Local date: day", gui, 0.66)
  3014                         luxInt("sc.month", luxProp(sun, "sc.month", 1), 1, 12, "month", "Local date: month", gui, 0.67)
  3015                         luxInt("sc.year", luxProp(sun, "sc.year", 2009), 1800, 2100, "year", "Local date: year", gui, 0.66)
  3016                         
  3017                         luxInt("sc.hour", luxProp(sun, "sc.hour", 0), 0, 23, "hour", "Local time: hour", gui, 0.72)
  3018                         luxInt("sc.minute", luxProp(sun, "sc.minute", 0), 0, 59, "minute", "Local time: minute", gui, 0.72)
  3019                         luxBool("sc.dst", luxProp(sun, "sc.dst", 'false'), "DST", "DST", gui, 0.28)
  3020                         r = gui.getRect(0.28,1)
  3021                         Draw.Button("NOW", 0, r[0], r[1], r[2], r[3], "Set to current time", lambda e,v: sc.now())
  3022                         
  3023                         r = gui.getRect(0.3,1)
  3024                         Draw.Button("Preset", 0, r[0], r[1], r[2], r[3], "Choose a preset location", lambda e,v: sc.set_location(
  3025                             Draw.PupTreeMenu(sun_calculator.location_list)
  3026                         ))
  3027                         
  3028                         luxFloat("sc.lat", luxProp(sun, "sc.lat", 0.0), -90.0, 90.0, "lat", "Location: latitude", gui, 0.56)
  3029                         luxFloat("sc.long", luxProp(sun, "sc.long", 0.0), -180.0, 180.0, "long", "Location: longitude", gui, 0.56)
  3030                         luxInt("sc.tz", luxProp(sun, "sc.tz", 0), -12, 12, "timezone", "Local time: timezone offset from GMT", gui, 0.56)
  3031                         
  3032                         r = gui.getRect(2,1)
  3033                         Draw.Button("Calculate", 0, r[0], r[1], r[2], r[3], "Calculate sun's position", lambda e,v: sc.compute())
  3034                     
  3035                 else:
  3036                     if gui:
  3037                         gui.newline(); r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5) 
  3038                         Draw.Text("create a blender Sun Lamp")
  3039 
  3040 
  3041             str += "\n"
  3042         #if gui: gui.newline("GLOBAL:", 8, 0, None, [0.75,0.5,0.25])
  3043         #luxFloat("scale", luxProp(scn, "global.scale", 1.0), 0.0, 10.0, "scale", "global world scale", gui)
  3044         
  3045     return str
  3046 
  3047 class sun_calculator:
  3048     #Based on SunLight v1.0 by Miguel Kabantsov (miguelkab@gmail.com)
  3049     #Replaces the faulty sun position calculation algorythm with a precise calculation (Source for algorythm: http://de.wikipedia.org/wiki/Sonnenstand),
  3050     #Co-Ordinates: http://www.bcca.org/misc/qiblih/latlong.html
  3051     #Author: Nils-Peter Fischer (Nils-Peter.Fischer@web.de)
  3052     
  3053     sun = None
  3054     
  3055     lat = 0
  3056     long = 0
  3057     
  3058     hour = 0
  3059     min = 0
  3060     tz = 0
  3061     dst = 'false'
  3062     
  3063     day = 0
  3064     month = 0
  3065     year = 0
  3066     
  3067     location_list = [
  3068         ("EUROPE",[
  3069             ("Antwerp, Belgium",          67),
  3070             ("Berlin, Germany",            1),
  3071             ("Bratislava, Slovak Republic", 70),
  3072             ("Brno, Czech Republic",      72),
  3073             ("Brussles, Belgium",         68),
  3074             ("Geneva, Switzerland",       65),
  3075             ("Helsinki, Finland",          7),
  3076             ("Innsbruck, Austria",        62),
  3077             ("Kyiv, Ukraine",             64),
  3078             ("London, England",           10),
  3079             ("Lyon, France",              66),
  3080             ("Nitra, Slovak Republic",    69),
  3081             ("Oslo, Norway",              58),
  3082             ("Paris, France",             15),
  3083             ("Praha, Czech Republic",     71),
  3084             ("Rome, Italy",               18),
  3085             ("Telfs, Austria",            63),
  3086             ("Warsaw, Poland",            74),
  3087             ("Wroclaw, Poland",           73),
  3088             ("Zurich, Switzerland",       21),
  3089         ]),
  3090     
  3091         ("WORLD CITIES", [
  3092             ("Beijing, China",             0),
  3093             ("Bombay, India",              2),
  3094             ("Buenos Aires, Argentina",    3),
  3095             ("Cairo, Egypt",               4),
  3096             ("Cape Town, South Africa",    5),
  3097             ("Caracas, Venezuela",         6),
  3098             ("Curitiba, Brazil",          60),
  3099             ("Hong Kong, China",           8),
  3100             ("Jerusalem, Israel",          9),
  3101             ("Joinville, Brazil",         61),
  3102             ("Mexico City, Mexico",       11),
  3103             ("Moscow, Russia",            12),
  3104             ("New Delhi, India",          13),
  3105             ("Ottawa, Canada",            14),
  3106             ("Rio de Janeiro, Brazil",    16),
  3107             ("Riyadh, Saudi Arabia",      17),
  3108             ("Sao Paulo, Brazil",         59),
  3109             ("Sydney, Australia",         19),
  3110             ("Tokyo, Japan",              20), 
  3111         ]),
  3112         
  3113         ("US CITIES", [
  3114             ("Albuquerque, NM",           22),
  3115             ("Anchorage, AK",             23),
  3116             ("Atlanta, GA",               24),
  3117             ("Austin, TX",                25),
  3118             ("Birmingham, AL",            26),
  3119             ("Bismarck, ND",              27),
  3120             ("Boston, MA",                28),
  3121             ("Boulder, CO",               29),
  3122             ("Chicago, IL",               30),
  3123             ("Dallas, TX",                31),
  3124             ("Denver, CO",                32),
  3125             ("Detroit, MI",               33),
  3126             ("Honolulu, HI",              34),
  3127             ("Houston, TX",               35),
  3128             ("Indianapolis, IN",          36),
  3129             ("Jackson, MS",               37),
  3130             ("Kansas City, MO",           38),
  3131             ("Los Angeles, CA",           39),
  3132             ("Menomonee Falls, WI",       40),
  3133             ("Miami, FL",                 41),
  3134             ("Minneapolis, MN",           42),
  3135             ("New Orleans, LA",           43),
  3136             ("New York City, NY",         44),
  3137             ("Oklahoma City, OK",         45),
  3138             ("Philadelphia, PA",          46),
  3139             ("Phoenix, AZ",               47),
  3140             ("Pittsburgh, PA",            48),
  3141             ("Portland, ME",              49),
  3142             ("Portland, OR",              50),
  3143             ("Raleigh, NC",               51),
  3144             ("Richmond, VA",              52),
  3145             ("Saint Louis, MO",           53),
  3146             ("San Diego, CA",             54),
  3147             ("San Francisco, CA",         55),
  3148             ("Seattle, WA",               56),
  3149             ("Washington DC",             57),
  3150         ])
  3151     ]
  3152 
  3153     location_data = {
  3154         # Europe
  3155         67:   ( 51.2167, 4.4, 1),
  3156         1:    ( 52.33, 13.30, 1),
  3157         70:   ( 48.17, 17.17, 1),
  3158         72:   ( 49.2, 16.63, 1),
  3159         68:   ( 58.8467, 4.3525, 1),
  3160         65:   ( 46.217, 6.150, 1),
  3161         7:    ( 60.1667, 24.9667,2),
  3162         62:   ( 47.2672, 11.3928, 1),
  3163         64:   ( 50.75, 30.0833, 2),
  3164         10:   ( 51.50, 0.0, 0),
  3165         66:   ( 45.767, 4.833, 1),
  3166         69:   ( 48.32, 18.07, 1),
  3167         58:   ( 59.56, 10.41, 1),
  3168         15:   ( 48.8667, 2.667, 1),
  3169         71:   ( 50.08, 14.46, 1),
  3170         18:   ( 41.90, 12.4833, 1),
  3171         63:   ( 47.3, 11.0667, 1),
  3172         74:   ( 52.232, 21.008, 1),
  3173         73:   ( 51.108, 17.038, 1),
  3174         21:   ( 47.3833, 8.5333, 1),
  3175     
  3176         # World Cities
  3177         0:    ( 39.9167, 116.4167, 8),
  3178         2:    ( 18.9333, 72.8333, 5.5),
  3179         3:    (-34.60, -58.45, -3),
  3180         4:    ( 30.10, 31.3667, 2),
  3181         5:    (-33.9167, 18.3667, 2),
  3182         6:    ( 10.50, -66.9333, -4),
  3183         60:   (-25.4278, -49.2731, -3),
  3184         8:    ( 22.25, 114.1667, 8),
  3185         9:    ( 31.7833, 35.2333, 2),
  3186         61:   (-29.3044, -48.8456, -3),
  3187         11:   ( 19.4, -99.15, -6),
  3188         12:   ( 55.75, 37.5833, 3),
  3189         13:   ( 28.6, 77.2, 5.5),
  3190         14:   ( 45.41667, -75.7, -5),
  3191         16:   (-22.90, -43.2333, -3),
  3192         17:   ( 24.633, 46.71667, 3),
  3193         59:   ( -23.5475, -46.6361, -3),
  3194         19:   (-33.8667,151.2167,10),
  3195         20:   ( 35.70, 139.7667, 9), 
  3196     
  3197         # US Cities
  3198         22:   ( 35.0833, -106.65, -7),
  3199         23:   ( 61.217, -149.90, -9),
  3200         24:   ( 33.733, -84.383, -5),
  3201         25:   ( 30.283, -97.733, -6),
  3202         26:   ( 33.521, -86.8025, -6),
  3203         27:   ( 46.817, -100.783, -6),
  3204         28:   ( 42.35, -71.05, -5),
  3205         29:   ( 40.125, -105.237, -7),
  3206         30:   ( 41.85, -87.65, -6),
  3207         31:   ( 32.46, -96.47, -6),
  3208         32:   ( 39.733, -104.983, -7),
  3209         33:   ( 42.333, -83.05, -5),
  3210         34:   ( 21.30, -157.85, -10),
  3211         35:   ( 29.75, -95.35, -6),
  3212         36:   ( 39.767, -86.15, -5),
  3213         37:   ( 32.283, -90.183, -6),
  3214         38:   ( 39.083, -94.567, -6),
  3215         39:   ( 34.05, -118.233, -8),
  3216         40:   ( 43.11, -88.10, -6),
  3217         41:   ( 25.767, -80.183, -5),
  3218         42:   ( 44.967, -93.25, -6),
  3219         43:   ( 29.95, -90.067, -6),
  3220         44:   ( 40.7167, -74.0167, -5),
  3221         45:   ( 35.483, -97.533, -6),
  3222         46:   ( 39.95, -75.15, -5),
  3223         47:   ( 33.433, -112.067,-7),
  3224         48:   ( 40.433, -79.9833, -5),
  3225         49:   ( 43.666, -70.283, -5),
  3226         50:   ( 45.517, -122.65, -8),
  3227         51:   ( 35.783, -78.65, -5),
  3228         52:   ( 37.5667, -77.450, -5),
  3229         53:   ( 38.6167, -90.1833, -6),
  3230         54:   ( 32.7667, -117.2167, -8),
  3231         55:   ( 37.7667, -122.4167, -8),
  3232         56:   ( 47.60, -122.3167, -8),
  3233         57:   ( 38.8833, -77.0333, -5),
  3234     }
  3235 
  3236     def __init__(self, sun):
  3237         self.sun = sun
  3238     
  3239     def now(self):
  3240         ct = time.localtime()
  3241         
  3242         if ct[8] == 0:
  3243             dst = 'false'
  3244         else:
  3245             dst = 'true'
  3246         
  3247         luxProp(self.sun, 'sc.day', 0).set(ct[2])
  3248         luxProp(self.sun, 'sc.month', 0).set(ct[1])
  3249         luxProp(self.sun, 'sc.year', 0).set(ct[0])
  3250         luxProp(self.sun, 'sc.hour', 0).set(ct[3])
  3251         luxProp(self.sun, 'sc.minute', 0).set(ct[4])
  3252         luxProp(self.sun, 'sc.dst', 0).set(dst)
  3253         
  3254         self.compute()
  3255         
  3256     def set_location(self, location):
  3257         if location < 0: return
  3258         
  3259         lat, long, tz = self.location_data[location]
  3260         luxProp(self.sun, "sc.lat", 0).set(lat)
  3261         luxProp(self.sun, "sc.long", 0).set(long)
  3262         luxProp(self.sun, "sc.tz", 0).set(tz)
  3263         
  3264         self.compute()
  3265     
  3266     def compute(self):
  3267         
  3268         self.lat  = luxProp(self.sun, "sc.lat", 0).get()
  3269         self.long = luxProp(self.sun, "sc.long", 0).get()
  3270         self.tz   = luxProp(self.sun, "sc.tz", 0).get()
  3271         
  3272         self.hour = luxProp(self.sun, "sc.hour", 0).get()
  3273         self.min  = luxProp(self.sun, "sc.minute", 0).get()
  3274         self.dst  = luxProp(self.sun, "sc.dst", 'false').get()
  3275         if self.dst == 'true':
  3276             self.dst = 1
  3277         else:
  3278             self.dst = 0
  3279         
  3280         self.day   = luxProp(self.sun, "sc.day", 0).get()
  3281         self.month = luxProp(self.sun, "sc.month", 0).get()
  3282         self.year  = luxProp(self.sun, "sc.year", 0).get()
  3283         
  3284         
  3285         az,el = self.geoSunData(
  3286             self.lat,
  3287             self.long,
  3288             self.year,
  3289             self.month,
  3290             self.day,
  3291             self.hour + self.min/60.0,
  3292             -self.tz + self.dst
  3293         )
  3294         
  3295         self.sun.rot = math.radians(90-el), 0, math.radians(-az)
  3296         
  3297         Window.Redraw()
  3298         
  3299         
  3300     # --- THE FOLLOWING METHODS ARE ADAPTED FROM LUXMAYA ---
  3301     
  3302     # mathematical helpers
  3303     def sind(self, deg):
  3304         return math.sin(math.radians(deg))
  3305     
  3306     def cosd(self, deg):
  3307         return math.cos(math.radians(deg))
  3308     
  3309     def tand(self, deg):
  3310         return math.tan(math.radians(deg))
  3311     
  3312     def asind(self, deg):
  3313         return math.degrees(math.asin(deg))
  3314     
  3315     def atand(self, deg):
  3316         return math.degrees(math.atan(deg))
  3317     
  3318     
  3319     def geo_sun_astronomicJulianDate(self, Year, Month, Day, LocalTime, Timezone):
  3320         """
  3321         See quoted source in class header for explanation
  3322         """
  3323         
  3324         if Month > 2.0:
  3325             Y = Year
  3326             M = Month
  3327         else:
  3328             Y = Year - 1.0
  3329             M = Month + 12.0
  3330             
  3331         UT = LocalTime - Timezone
  3332         hour = UT / 24.0
  3333         A = int(Y/100.0)
  3334         B = 2.0 - A+int(A/4.0)
  3335         
  3336         JD = math.floor(365.25*(Y+4716.0)) + math.floor(30.6001*(M+1.0)) + Day + hour + B - 1524.4
  3337         
  3338         return JD
  3339     
  3340     def geoSunData(self, Latitude, Longitude, Year, Month, Day, LocalTime, Timezone):
  3341         """
  3342         See quoted source in class header for explanation
  3343         """
  3344         
  3345         JD = self.geo_sun_astronomicJulianDate(Year, Month, Day, LocalTime, Timezone)
  3346         
  3347         phi = Latitude
  3348         llambda = Longitude
  3349                 
  3350         n = JD - 2451545.0
  3351         LDeg = (280.460 + 0.9856474*n) - (math.floor((280.460 + 0.9856474*n)/360.0) * 360.0)
  3352         gDeg = (357.528 + 0.9856003*n) - (math.floor((357.528 + 0.9856003*n)/360.0) * 360.0)
  3353         LambdaDeg = LDeg + 1.915 * self.sind(gDeg) + 0.02 * self.sind(2.0*gDeg)
  3354         
  3355         epsilonDeg = 23.439 - 0.0000004*n
  3356         
  3357         alphaDeg = self.atand( (self.cosd(epsilonDeg) * self.sind(LambdaDeg)) / self.cosd(LambdaDeg) )
  3358         if self.cosd(LambdaDeg) < 0.0:
  3359             alphaDeg += 180.0
  3360             
  3361         deltaDeg = self.asind( self.sind(epsilonDeg) * self.sind(LambdaDeg) )
  3362         
  3363         JDNull = self.geo_sun_astronomicJulianDate(Year, Month, Day, 0.0, 0.0)
  3364         
  3365         TNull = (JDNull - 2451545.0) / 36525.0
  3366         T = LocalTime - Timezone
  3367         
  3368         thetaGh = 6.697376 + 2400.05134*TNull + 1.002738*T
  3369         thetaGh -= math.floor(thetaGh/24.0) * 24.0
  3370         
  3371         thetaG = thetaGh * 15.0
  3372         theta = thetaG + llambda
  3373         
  3374         tau = theta - alphaDeg
  3375         
  3376         a = self.atand( self.sind(tau) / ( self.cosd(tau)*self.sind(phi) - self.tand(deltaDeg)*self.cosd(phi)) )
  3377         if self.cosd(tau)*self.sind(phi) - self.tand(deltaDeg)*self.cosd(phi) < 0.0:
  3378             a += 180.0
  3379         
  3380         h = self.asind( self.cosd(deltaDeg)*self.cosd(tau)*self.cosd(phi) + self.sind(deltaDeg)*self.sind(phi) )
  3381         
  3382         R = 1.02 / (self.tand (h+(10.3/(h+5.11))))
  3383         hR = h + R/60.0
  3384         
  3385         azimuth = a
  3386         elevation = hR
  3387         
  3388         return azimuth, elevation
  3389 
  3390 def luxAccelerator(scn, gui=None):
  3391     str = ""
  3392     if scn:
  3393         acceltype = luxProp(scn, "accelerator.type", "tabreckdtree")
  3394         str = luxIdentifier("Accelerator", acceltype, ["none", "tabreckdtree", "grid", "bvh", "qbvh"], "ACCEL", "select accelerator type", gui)
  3395         if acceltype.get() == "tabreckdtree":
  3396             if gui: gui.newline()
  3397             str += luxInt("intersectcost", luxProp(scn, "accelerator.kdtree.interscost", 80), 0, 1000, "inters.cost", "specifies how expensive ray-object intersections are", gui)
  3398             str += luxInt("traversalcost", luxProp(scn, "accelerator.kdtree.travcost", 1), 0, 1000, "trav.cost", "specifies how expensive traversing a ray through the kdtree is", gui)
  3399             if gui: gui.newline()
  3400             str += luxFloat("emptybonus", luxProp(scn, "accelerator.kdtree.emptybonus", 0.2), 0.0, 100.0, "empty.b", "promotes kd-tree nodes that represent empty space", gui)
  3401             if gui: gui.newline()
  3402             str += luxInt("maxprims", luxProp(scn, "accelerator.kdtree.maxprims", 1), 0, 1000, "maxprims", "maximum number of primitives in a kdtree volume before further splitting of the volume occurs", gui)
  3403             str += luxInt("maxdepth", luxProp(scn, "accelerator.kdtree.maxdepth", -1), -1, 100, "maxdepth", "If positive, the maximum depth of the tree. If negative this value is set automatically", gui)
  3404         if acceltype.get() == "unsafekdtree":
  3405             if gui: gui.newline()
  3406             str += luxInt("intersectcost", luxProp(scn, "accelerator.kdtree.interscost", 80), 0, 1000, "inters.cost", "specifies how expensive ray-object intersections are", gui)
  3407             str += luxInt("traversalcost", luxProp(scn, "accelerator.kdtree.travcost", 1), 0, 1000, "trav.cost", "specifies how expensive traversing a ray through the kdtree is", gui)
  3408             if gui: gui.newline()
  3409             str += luxFloat("emptybonus", luxProp(scn, "accelerator.kdtree.emptybonus", 0.2), 0.0, 100.0, "empty.b", "promotes kd-tree nodes that represent empty space", gui)
  3410             if gui: gui.newline()
  3411             str += luxInt("maxprims", luxProp(scn, "accelerator.kdtree.maxprims", 1), 0, 1000, "maxprims", "maximum number of primitives in a kdtree volume before further splitting of the volume occurs", gui)
  3412             str += luxInt("maxdepth", luxProp(scn, "accelerator.kdtree.maxdepth", -1), -1, 100, "maxdepth", "If positive, the maximum depth of the tree. If negative this value is set automatically", gui)
  3413         if acceltype.get() == "grid":
  3414             str += luxBool("refineimmediately", luxProp(scn, "accelerator.grid.refine", "false"), "refine immediately", "Makes the primitive intersectable as soon as it is added to the grid", gui)
  3415         if acceltype.get() == "qbvh":
  3416             if gui: gui.newline()
  3417             str += luxInt("maxprimsperleaf", luxProp(scn, "accelerator.qbvh.maxprimsperleaf", 4), 1, 64, "maxprimsperleaf", "Maximum number of primitives to leave in one leaf node", gui)
  3418     return str
  3419 
  3420 def luxSystem(scn, gui=None):
  3421     if scn:
  3422         if gui: gui.newline("PATHS:", 10)
  3423         lp = luxProp(scn, "lux", "")
  3424         lp.set(Blender.sys.dirname(lp.get())+os.sep)
  3425         luxPath("LUX dir", lp, "lux binary dir", "Lux installation path", gui, 2.0)
  3426 
  3427 #        luxFile("GUI filename", luxProp(scn, "lux", ""), "lux-file", "filename and path of the lux GUI executable", gui, 2.0)
  3428 #        luxFile("Console filename", luxProp(scn, "luxconsole", ""), "lux-file-console", "filename and path of the lux console executable", gui, 2.0)
  3429         if gui: gui.newline()
  3430         luxFile("datadir", luxProp(scn, "datadir", ""), "default out dir", "default.lxs save path", gui, 2.0)
  3431 
  3432         if gui: gui.newline()
  3433         pm = ["absolute","relative","flat"]
  3434         luxOption("pathmode", luxProp(scn, "pathmode", "absolute"), pm, "path-mode", "select format for paths on export", gui, 2.0)
  3435 
  3436         if gui: gui.newline("PRIORITY:", 10)
  3437         luxnice = luxProp(scn, "luxnice", 10)
  3438         if osys.platform=="win32":
  3439             r = gui.getRect(2, 1)
  3440             Draw.Menu("priority%t|abovenormal%x-10|normal%x0|belownormal%x10|low%x19", evtLuxGui, r[0], r[1], r[2], r[3], luxnice.get(), "", lambda e,v: luxnice.set(v))
  3441         else: luxInt("nice", luxnice, -20, 19, "nice", "nice value. Range goes from -20 (highest priority) to 19 (lowest)", gui)
  3442 
  3443         luxBool("noopengl", luxProp(scn, "noopengl", "false"), "Disable OpenGL", "(workaround for some buggy display drivers)", gui, 1.0)
  3444 
  3445 
  3446         if gui: gui.newline("THREADS:", 10)
  3447         autothreads = luxProp(scn, "autothreads", "true")
  3448         luxBool("autothreads", autothreads, "Auto Detect", "Automatically use all available processors", gui, 1.0)
  3449         if autothreads.get()=="false":
  3450             luxInt("threads", luxProp(scn, "threads", 1), 1, 100, "threads", "number of threads used for rendering", gui, 1.0)
  3451 
  3452         if gui: gui.newline("ANIM:", 10)
  3453         useparamkeys = luxProp(scn, "useparamkeys", "false")
  3454         luxBool("useparamkeys", useparamkeys, "Enable Parameter IPO Keyframing", "Enables keyframing of luxblend parameters", gui, 2.0)
  3455 
  3456         if gui: gui.newline("PARAMS:", 10)
  3457         parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
  3458         luxBool("parammodeadvanced", parammodeadvanced, "Default Advanced Parameters", "Always use advanced parameters by default", gui, 2.0)
  3459 
  3460         if gui: gui.newline("PREVIEW:", 10)
  3461         qs = ["low","medium","high","very high"]
  3462         defprevmat = luxProp(scn, "defprevmat", "high")
  3463         luxOption("defprevmat", defprevmat, qs, "Materials", "Select default preview quality in material editor for materials", gui, 1.0)
  3464 
  3465         if gui: gui.newline("GAMMA:", 10)
  3466         luxBool("RGC", luxProp(scn, "RGC", "true"), "RGC", "use reverse gamma correction", gui)
  3467         luxBool("ColClamp", luxProp(scn, "colorclamp", "false"), "ColClamp", "clamp all colors to 0.0-0.9", gui)
  3468         if gui: gui.newline("MESH:", 10)
  3469         luxBool("mesh_optimizing", luxProp(scn, "mesh_optimizing", "true"), "optimize meshes", "Optimize meshes during export", gui, 2.0)
  3470         #luxInt("trianglemesh thr", luxProp(scn, "trianglemesh_thr", 0), 0, 10000000, "trianglemesh threshold", "Vertex threshold for exporting (wald) trianglemesh object(s)", gui, 2.0)
  3471         #if gui: gui.newline()
  3472         #luxInt("barytrianglemesh thr", luxProp(scn, "barytrianglemesh_thr", 300000), 0, 100000000, "barytrianglemesh threshold", "Vertex threshold for exporting barytrianglemesh object(s) (slower but uses less memory)", gui, 2.0)
  3473         if gui: gui.newline("INSTANCING:", 10)
  3474         luxInt("instancing_threshold", luxProp(scn, "instancing_threshold", 2), 0, 1000000, "object instancing threshold", "Threshold to created instanced objects", gui, 2.0)
  3475         
  3476         # dougal2 packed images, enable this when implemented in Lux itself
  3477         #if gui: gui.newline('TEXTURES:',10)
  3478         #impack = luxProp(scn, 'packtextures', 'false')
  3479         #luxBool('impack', impack, 'Pack All Images', '', gui, 2.0)
  3480         
  3481         if gui: 
  3482             network=luxProp(scn,"network","false")
  3483             gui.newline("NETWORK:", 10)
  3484             luxCollapse("network",network, "network", "enable network option", gui, 2.0)
  3485             if(network.get() == "true"):
  3486                 network_use_file=luxProp(scn,"network_use_file","false")
  3487                 luxBool ("use file",network_use_file,"use file", "get list of servers from file; one per line",gui,2.0)
  3488                 if (network_use_file.get() == "true"):
  3489                     luxFile("file", luxProp(scn, "network_file_path", ""), "file", "file where servers are defined", gui, 1.0)         
  3490                 else :     
  3491                     #gui.newline("")
  3492                     luxString("Servers",luxProp(scn,"network_servers",""),"servers","coma separated list of servers",gui,1.0)
  3493                 #gui.newline("")
  3494                 luxInt("network_interval",luxProp(scn,"newtork_interval",180),0,300,"update interval","interval between network refresh",gui)
  3495 
  3496 
  3497 def scalelist(list, factor):
  3498     for i in range(len(list)): list[i] = list[i] * factor
  3499     return list
  3500 
  3501 
  3502 def luxMapping(key, mat, gui, level=0):
  3503     global icon_map2d, icon_map2dparam
  3504     if gui: gui.newline("2Dmap:", -2, level, icon_map2d)
  3505     mapping = luxProp(mat, key+".mapping", "uv")
  3506     mappings = ["uv","spherical","cylindrical","planar"]
  3507     str = luxOption("mapping", mapping, mappings, "mapping", "", gui, 0.5)
  3508     if mapping.get() == "uv":
  3509         str += luxFloat("uscale", luxProp(mat, key+".uscale", 1.0), -100.0, 100.0, "Us", "u-scale", gui, 0.375)
  3510         str += luxFloat("vscale", luxProp(mat, key+".vscale", -1.0), -100.0, 100.0, "Vs", "v-scale", gui, 0.375)
  3511         str += luxFloat("udelta", luxProp(mat, key+".udelta", 0.0), -100.0, 100.0, "Ud", "u-delta", gui, 0.375)
  3512         str += luxFloat("vdelta", luxProp(mat, key+".vdelta", 0.0), -100.0, 100.0, "Vd", "v-delta", gui, 0.375)
  3513     if mapping.get() == "planar":
  3514         str += luxFloat("udelta", luxProp(mat, key+".udelta", 0.0), -100.0, 100.0, "Ud", "u-delta", gui, 0.75)
  3515         str += luxFloat("vdelta", luxProp(mat, key+".vdelta", 0.0), -100.0, 100.0, "Vd", "v-delta", gui, 0.75)
  3516         if gui: gui.newline("v1:", -2, level+1, icon_map2dparam)
  3517         str += luxVector("v1", luxProp(mat, key+".v1", "1 0 0"), -100.0, 100.0, "v1", "v1-vector", gui, 2.0)
  3518         if gui: gui.newline("v2:", -2, level+1, icon_map2dparam)
  3519         str += luxVector("v2", luxProp(mat, key+".v2", "0 1 0"), -100.0, 100.0, "v2", "v2-vector", gui, 2.0)
  3520     return str
  3521 
  3522 def lux3DMapping(key, mat, gui, level=0):
  3523     global icon_map3dparam
  3524     str = ""
  3525     if gui: gui.newline("scale:", -2, level, icon_map3dparam)
  3526     str += luxVectorUniform("scale", luxProp(mat, key+".3dscale", 1.0), 0.001, 1000.0, "scale", "scale-vector", gui, 2.0)
  3527     if gui: gui.newline("rot:", -2, level, icon_map3dparam)
  3528     str += luxVector("rotate", luxProp(mat, key+".3drotate", "0 0 0"), -360.0, 360.0, "rotate", "rotate-vector", gui, 2.0)
  3529     if gui: gui.newline("move:", -2, level, icon_map3dparam)
  3530     str += luxVector("translate", luxProp(mat, key+".3dtranslate", "0 0 0"), -1000.0, 1000.0, "move", "translate-vector", gui, 2.0)
  3531     return str
  3532     
  3533 def getTreeNameById(tree, i): # helper function to retrive name of the selected treemenu-item
  3534     for t in tree:
  3535         if type(t)==types.TupleType:
  3536             if type(t[1])==types.ListType: 
  3537                 n=getTreeNameById(t[1], i)
  3538                 if n: return n
  3539             elif t[1]==i: return t[0]
  3540     return None    
  3541 
  3542 def luxTexture(name, parentkey, type, default, min, max, caption, hint, mat, gui, matlevel, texlevel=0, lightsource=0, overrideicon=""):
  3543     global icon_tex, icon_texcol, icon_texmix, icon_texmixcol, icon_texparam, icon_spectex
  3544     def c(t1, t2):
  3545         return (t1[0]+t2[0], t1[1]+t2[1])
  3546     def alternativedefault(type, default):
  3547         if type=="float": return 0.0
  3548         else: return "0.0 0.0 0.0"
  3549     level = matlevel + texlevel
  3550     keyname = "%s:%s"%(parentkey, name)
  3551     texname = "%s:%s"%(mat.getName(), keyname)
  3552 #    if gui: gui.newline(caption+":", 0, level)
  3553     if(lightsource == 0):
  3554         if texlevel == 0: texture = luxProp(mat, keyname+".texture", "imagemap")
  3555         else: texture = luxProp(mat, keyname+".texture", "constant")
  3556     else:
  3557         texture = luxProp(mat, keyname+".texture", "blackbody")
  3558 
  3559     textures = ["constant","blackbody", "lampspectrum", "equalenergy", "frequency", "gaussian", "regulardata", "irregulardata", "imagemap","mix","scale","bilerp","uv", "checkerboard","brick","dots","fbm","marble","wrinkled", "windy", "blender_marble", "blender_musgrave", "blender_wood", "blender_clouds", "blender_blend", "blender_distortednoise", "blender_noise", "blender_magic", "blender_stucci", "blender_voronoi", "harlequin"]
  3560 
  3561     if gui:
  3562         if(overrideicon != ""):
  3563             icon = overrideicon
  3564         else:
  3565             icon = icon_tex
  3566             if texture.get() in ["mix", "scale", "checkerboard", "dots"]:
  3567                 if type=="color": icon = icon_texmixcol
  3568                 else: icon = icon_texmix
  3569             elif texture.get() in ["constant", "blackbody", "equalenergy", "frequency", "gaussian", "regulardata", "irregulardata"]:
  3570                 icon = icon_spectex
  3571             else:
  3572                 if type=="color": icon = icon_texcol
  3573                 else: icon = icon_tex
  3574         if (texlevel > 0): gui.newline(caption+":", -2, level, icon, scalelist([0.5,0.5,0.5],2.0/(level+2)))
  3575         else: gui.newline("texture:", -2, level, icon, scalelist([0.5,0.5,0.5],2.0/(level+2)))
  3576     luxOption("texture", texture, textures, "texture", "", gui, 0.9)
  3577     str = "Texture \"%s\" \"%s\" \"%s\""%(texname, type, texture.get())
  3578 
  3579     if gui: Draw.PushButton(">", evtLuxGui, gui.xmax+gui.h, gui.y-gui.h, gui.h, gui.h, "Menu", lambda e,v: showMatTexMenu(mat,keyname,True))
  3580     if gui: # Draw Texture level Material preview
  3581         luxPreview(mat, parentkey, 1, False, False, name, gui, texlevel, [0.5, 0.5, 0.5])
  3582         # Add an offset for next controls
  3583         #r = gui.getRect(1.0, 1)
  3584         #gui.x += 140
  3585 
  3586     if texture.get() == "constant":
  3587         value = luxProp(mat, keyname+".value", default)
  3588         if type == "float": luxFloat("value", value, min, max, "", "", gui, 1.1)
  3589         elif type == "color": luxRGB("value", value, max, "", "", gui, 1.1)
  3590 # direct version
  3591         if type == "color": return ("", " \"%s %s\" [%s]"%(type, name, value.getRGC()))
  3592         return ("", " \"%s %s\" [%s]"%(type, name, value.get()))
  3593 # indirect version
  3594 #        if type == "color": str += " \"%s value\" [%s]"%(type, value.getRGC())
  3595 #        else: str += " \"%s value\" [%s]"%(type, value.get())
  3596 
  3597     if texture.get() == "blackbody":
  3598         if gui:
  3599             if gui.xmax-gui.x < gui.w: gui.newline()
  3600             r = gui.getRect(1.0, 1)
  3601             gui.newline()
  3602             drawBar(bar_blackbody, gui.xmax-gui.w-7, r[1])
  3603         str += luxFloat("temperature", luxProp(mat, keyname+".bbtemp", 6500.0), 1000.0, 10000.0, "temperature", "Black Body temperature in degrees Kelvin", gui, 2.0, 1)
  3604 
  3605     if texture.get() == "lampspectrum":
  3606         lampstring = luxProp(mat, keyname+".lampstring", "Incandescent2")
  3607         lamppreset = luxProp(mat, keyname+".lampspectrum", "PHILIPS [Argenta] 200W Incandescent Lamp")
  3608         if gui:
  3609             def setLamp(i, value, preset, tree, dict): # callback function to set ior value after selection
  3610                 if i >= 0:
  3611                     value.set(dict[i])
  3612                     preset.set(getTreeNameById(tree, i))
  3613 
  3614             measuredtree = [ 	("Natural Daylight", 	[ ("Natural Daylight", 1) ] ), ("Incandescent", 	[ ("Paraffin Candle Flame", 2), ("Generic 7W Incandescent Lamp", 3), ("PHILIPS [Argenta] 200W Incandescent Lamp", 4), ("Welsbach Gas Mantle (modern, without Thorium)", 5), ("Incandescent Anti-Insect Lamp", 6) ] ), ("Fluorescent/Compact Fluorescent",	[ ("PHILIPS [TL-D 30W/55] Regular Daylight Fluorescent", 7), ("Sylvania [F4T5 4W] Regular Warm White Fluorescent", 8), ("OSRAM [DULUXSTAR 21W/827] Regular Compact Triphosphor Fluorescent", 9), ("Cold Cathode Warm White CFL Triphosphor Fluorescent.", 10), ("NARVA [COLOURLUX plus daylight 20W/860] Daylight CFL Triphosphor Fluorescent", 11), ("Sylvania [GroLux] Fluorescent Aquarium/Plant Lamp", 12), ("Laptop LCD Screen", 13), ("PHILIPS [ActiViva] \"Natural\" Triphosphor Fluorescent", 14), ("PHILIPS [ActiViva] \"Active\" Triphosphor Fluorescent", 16) ] ), ("High Pressure Mercury",		[ ("OSRAM [HQA 80W] Clear HPM Lamp", 17), ("PHILIPS [HPL 125W] HPM Lamp with improved color", 18), ("OSRAM [HQL 80W] HPM Lamp with improved warm deluxe color", 19), ("PHILIPS [ML 160W] Self-Ballasted HPM Vapor Lamp", 20), ("NARVA [160W] Self-ballasted HPM Vapor Lamp", 21) ] ), ("Low/High Pressure Sodium",		[ ("Regular High Pressure Sodium Lamp, warmup after 5-7 sec", 22), ("Regular High Pressure Sodium Lamp, warmup after 10-12 sec", 23), ("SOX Low Pressure Sodium Discharge Lamp", 24), ("Medium Pressure Sodium Discharge Lamp, warmup after ~35 sec", 25), ("GE [Lucalox 35W] High Pressure Sodium Lamp", 26), ("PHILIPS [SDW-T 100W] Super High Pressure White Sodium Lamp", 27) ] ), ("Metal Halide",		[ ("PHILIPS [HPI-T 400W] MH Lamp with Mercury, Sodium, Thallium and Indium iodides", 28), ("OSRAM [HQI-TS 75W/WDL] Metal Halide lamp with Mercury, sodium, thallium, indium and tin iodides, from ", 29), ("GE [MVR325IUWM 325 Watt I-Line Multi-Vapor® Metal Halide - Clear Watt Miser®] MH Lamp with Mercury, Sodium and Scandium iodides", 30), ("OSRAM [HQI-T 400W/D] MH Lamp with Mercury, Thallium, Dysprosium, Holmium, Thulium and Caesium iodides", 31), ("PHILIPS Diazo MH Lamp with Mercury, iron and cobalt iodides", 32), ("Sylvania Diazo MH Lamp with Mercury, gallium and lead iodides", 33), ("OSRAM [HQI-T 400W/Blau] Blue colored MH Lamp with Mercury and indium iodides", 34), ("RADIUM [HRI-T 400W/Planta] Plant growing MH Lamp with Mercury, indium and sodium iodides", 35), ("OSRAM [HQI-T 400W/Grun] Green colored MH Lamp with Mercury and thallium iodides", 36) ] ), ("Diode",		[ ("Regular High Brightness Blue LED", 37), ("Monochromatic emission from a Red Laser diode", 38), ("Monochromatic emission from a Green Laser diode.", 39) ] ), ("Spectral",		[ ("PHILIPS Spectral Xenon Lamp - Continuous Xenon low pressure thermionic discharge", 40), ("PHILIPS spectral Rubidium Lamp - Continuous Rubidium low pressure thermionic discharge", 41), ("PHILIPS spectral Cadmium Lamp - Continuous Cadmium low pressure thermionic discharge", 42), ("PHILIPS spectral zinc Lamp - Continuous Zinc low pressure thermionic discharge", 43) ] ), ("Glow Discharge",		[ ("Neon glow discharge", 44), ("Neon and Krypton glow discharge and green phosphor (night-lights/indicators)", 45), ("Neon and Xenon glow discharge and green phosphor (night-lights/indicators)", 46), ("Neon and Xenon glow discharge and blue phosphor (night-lights/indicators)", 48), ("Argon glow discharge", 49), ("Self-ballasted High Pressure Mercury Vapor Lamp, with yttrium vanadate phosphate fluorescent phosphors, in glow discharge mode", 50) ] ), ("Molecular",		[ ("Butane Gas Flame", 51), ("Alcohol Flame", 52) ] ), ("General Fluorescence",		[ ("Print quality A4 Xerox paper wrapped around a blacklight Lamp", 53), ("Neon green dye, bombarded with black light", 54), ("Regular Modern Color TV CRT", 55) ] ), ("Various",		[ ("Stroboscopic flash. Xenon I, likely II and perhaps III", 56), ("Carbon Arc Spectrum", 57), ("OSRAM [XBO 75W/2] Short Arc Xenon Lamp", 58) ] ), ("Blacklight/Ultraviolet",		[ ("Sylvania [G8T5 8W] Germicidal lamp", 59), ("Sylvania [F6T5/BLB 8W] Black light blue fluorescent", 60), ("PHILIPS [HPW 125W] High Pressure Mercury Black Light", 61), ("Sylvania [Blacklite 350 F8W/BL350] Black Light fluorescent", 62) ] ), ("Mercury UV Spectrum",		[ ("The near visible UVA emissions from a high pressure Mercury clear lamp", 63) ] ), ("Absorption/Mixed Spectra",		[ ("High Pressure Mercury Warm Deluxe light ([1.4.3]) absorbed through blue Cobalt glass", 64), ("Incandescent light ([1.2.3]) absorbed through blue Cobalt glass", 65), ("High Pressure Mercury Warm Deluxe light ([1.4.3]) absorbed through ciel dye #42053", 66), ("Incandescent light ([1.2.3]) absorbed through ciel dye #42053", 67), ("High Pressure Mercury Warm Deluxe light ([1.4.3]) absorbed through red glass", 68), ("Incandescent light ([1.2.3]) absorbed through red glass.m", 69), ("Incandescent light ([1.2.3]) absorbed through olive oil. ", 70) ] ) ] 
  3615 
  3616             measureddict  = {1:"Daylight", 2:"Candle", 3:"Incandescent1", 4:"Incandescent2", 5:"Welsbach", 6:"AntiInsect", 7:"FLD2", 8:"FL37K", 9:"CFL27K", 10:"CFL4K", 11:"CFL6K", 12:"GroLux", 13:"LCDS", 14:"FLAV8K", 15:"none", 16:"FLAV17K", 17:"HPM2", 18:"HPMFL1", 19:"HPMFL2", 20:"HPMSB", 21:"HPMSBFL", 22:"SS1", 23:"SS2", 24:"LPS", 25:"MPS", 26:"HPS", 27:"SHPS", 28:"MHN", 29:"MHWWD", 30:"MHSc", 31:"MHD", 32:"FeCo", 33:"GaPb", 34:"BLAU", 35:"PLANTA", 36:"GRUN", 37:"LEDB", 38:"RedLaser", 39:"GreenLaser", 40:"XeI", 41:"Rb", 42:"Cd", 43:"Zn", 44:"Ne", 45:"NeKrFL", 46:"NeXeFL1", 47:"none", 48:"NeXeFL2", 49:"Ar", 50:"HPMFL2Glow", 51:"Butane", 52:"Alcohol", 53:"BLP", 54:"BLNG", 55:"TV", 56:"Xe", 57:"CarbonArc", 58:"HPX", 59:"LPM2", 60:"FLBLB", 61:"HPMBL", 62:"FLBL", 63:"UVA", 64:"HPMFLCobaltGlass", 65:"CobaltGlass", 66:"HPMFLCL42053", 67:"CL42053", 68:"HPMFLRedGlass", 69:"RedGlass", 70:"OliveOil" }
  3617 
  3618             r = gui.getRect(2.0, 1)
  3619             Draw.Button(lamppreset.get(), evtLuxGui, r[0], r[1], r[2], r[3], "select lamp spectrum", lambda e,v: setLamp(Draw.PupTreeMenu(measuredtree), lampstring, lamppreset, measuredtree, measureddict))
  3620         str += luxString("name", lampstring, "Lamp", "Choose measured Lamp Spectrum", None, 2.0)
  3621 
  3622     if texture.get() == "equalenergy":
  3623         if gui:
  3624             if gui.xmax-gui.x < gui.w: gui.newline()
  3625             r = gui.getRect(1.0, 1)
  3626             gui.newline()
  3627             drawBar(bar_equalenergy, gui.xmax-gui.w-7, r[1])
  3628         str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Energy of each spectral band", gui, 2.0, 1)
  3629 
  3630     if texture.get() == "frequency":
  3631         str += luxFloat("freq", luxProp(mat, keyname+".freq", 0.01), 0.01, 100.0, "frequency", "Frequency in nm", gui, 2.0, 1)
  3632         str += luxFloat("phase", luxProp(mat, keyname+".phase", 0.5), 0.0, 1.0, "phase", "Phase", gui, 1.1, 1)
  3633         str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Amount of mean energy", gui, 0.9, 1)
  3634 
  3635     if texture.get() == "gaussian":
  3636         if gui:
  3637             if gui.xmax-gui.x < gui.w: gui.newline()
  3638             r = gui.getRect(1.0, 1)
  3639             gui.newline()
  3640             drawBar(bar_spectrum, gui.xmax-gui.w-7, r[1])
  3641         str += luxFloat("wavelength", luxProp(mat, keyname+".wavelength", 550.0), 380.0, 720.0, "wavelength", "Mean Wavelength in visible spectrum in nm", gui, 2.0, 1)
  3642         str += luxFloat("width", luxProp(mat, keyname+".width", 50.0), 20.0, 300.0, "width", "Width of gaussian distribution in nm", gui, 1.1, 1)
  3643         str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Amount of mean energy", gui, 0.9, 1)
  3644 
  3645     if texture.get() == "imagemap":
  3646         str += luxOption("wrap", luxProp(mat, keyname+".wrap", "repeat"), ["repeat","black","clamp"], "repeat", "", gui, 1.1)
  3647 
  3648         # ZANQDO
  3649         texturefilename = luxProp(mat, keyname+".filename", "")
  3650         luxFile("filename", texturefilename, "file", "texture file path", gui, 2.0)
  3651         # dougal2 image file packing
  3652         impack = luxProp(Scene.GetCurrent(), 'packtextures', 'false')
  3653         
  3654         if impack.get() == 'false':
  3655             str += luxFile("filename", texturefilename, "file", "texture file path", None, 2.0)
  3656         else:
  3657             import zlib, base64
  3658             def get_image_data(filename):
  3659                 try:
  3660                     f=open(filename,'rb')
  3661                     d=f.read()
  3662                     f.close()
  3663                 except:
  3664                     print 'Error reading image data from %s' % filename
  3665                     d = ''
  3666                 return base64.b64encode(zlib.compress(d))
  3667             imdata = get_image_data(texturefilename.get())
  3668             str += '\r\n   "string imagedata" ["%s"]' % imdata
  3669         
  3670         useseq = luxProp(mat, keyname+".useseq", "false")
  3671         luxCollapse("usesew", useseq, "Sequence", "", gui, 2.0)
  3672     
  3673         if useseq.get() == "true":
  3674             seqframes = luxProp(mat, keyname+".seqframes", 100)
  3675             luxInt("frames", seqframes, 1, 100000, "Frames", "", gui, 0.5)
  3676             seqoffset = luxProp(mat, keyname+".seqoffset", 0)
  3677             luxInt("offset", seqoffset, 0, 100000, "Offset", "", gui, 0.5)
  3678             seqstartframe = luxProp(mat, keyname+".seqsframe", 1)
  3679             luxInt("startframe", seqstartframe, 1, 100000, "StartFr", "", gui, 0.5)
  3680             seqcyclic = luxProp(mat, keyname+".seqcycl", "false")
  3681             luxBool("cyclic", seqcyclic, "Cyclic", "", gui, 0.5)
  3682     
  3683             
  3684             totalframes = seqframes.get()
  3685             currentframe = Blender.Get('curframe')
  3686     
  3687             if(currentframe < seqstartframe.get()):
  3688                 fnumber = 1 + seqoffset.get()
  3689             else:
  3690                 fnumber = (currentframe - (seqstartframe.get()-1)) + seqoffset.get()
  3691     
  3692             if(fnumber > seqframes.get()):
  3693                 if(seqcyclic.get() == "false"):
  3694                     fnumber = seqframes.get()
  3695                 else:
  3696                     fnumber = currentframe % seqframes.get()
  3697     
  3698             import re
  3699             def get_seq_filename(number, filename):
  3700                 m = re.findall(r'(\d+)', filename)
  3701                 if len(m) == 0:
  3702                     return "ERR: Can't find pattern"
  3703     
  3704                 rightmost_number = m[len(m)-1]
  3705                 seq_length = len(rightmost_number)
  3706     
  3707                 nstr = "%i" %number
  3708                 new_seq_number = nstr.zfill(seq_length)
  3709      
  3710                 return filename.replace(rightmost_number, new_seq_number)
  3711      
  3712             texturefilename.set(get_seq_filename(fnumber, texturefilename.get()))
  3713             if gui: gui.newline()
  3714     
  3715         str += luxFloat("gamma", luxProp(mat, keyname+".gamma", texturegamma()), 0.0, 6.0, "gamma", "", gui, 0.75)
  3716         str += luxFloat("gain", luxProp(mat, keyname+".gain", 1.0), 0.0, 10.0, "gain", "", gui, 0.5)
  3717         filttype = luxProp(mat, keyname+".filtertype", "bilinear")
  3718         filttypes = ["mipmap_ewa","mipmap_trilinear","bilinear","nearest"]
  3719         str += luxOption("filtertype", filttype, filttypes, "filtertype", "Choose the filtering method to use for the image texture", gui, 0.75)
  3720         
  3721         if filttype.get() == "mipmap_ewa" or filttype.get() == "mipmap_trilinear":    
  3722             str += luxFloat("maxanisotropy", luxProp(mat, keyname+".maxanisotropy", 8.0), 1.0, 512.0, "maxaniso", "", gui, 1.0)
  3723             str += luxInt("discardmipmaps", luxProp(mat, keyname+".discardmipmaps", 0), 0, 1, "discardmips", "", gui, 1.0)
  3724     
  3725         str += luxMapping(keyname, mat, gui, level+1)
  3726 
  3727     if texture.get() == "mix":
  3728         (s, l) = c(("", ""), luxTexture("amount", keyname, "float", 0.5, 0.0, 1.0, "amount", "The degree of mix between the two textures", mat, gui, matlevel, texlevel+1, lightsource))
  3729         (s, l) = c((s, l), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  3730         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  3731         str = s + str + l
  3732 
  3733     if texture.get() == "scale":
  3734         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  3735         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  3736         str = s + str + l
  3737 
  3738     if texture.get() == "bilerp":
  3739         if type == "float":
  3740             str += luxFloat("v00", luxProp(mat, keyname+".v00", 0.0), min, max, "v00", "", gui, 1.0)
  3741             str += luxFloat("v01", luxProp(mat, keyname+".v01", 1.0), min, max, "v01", "", gui, 1.0)
  3742             if gui: gui.newline("", -2)
  3743             str += luxFloat("v10", luxProp(mat, keyname+".v10", 0.0), min, max, "v10", "", gui, 1.0)
  3744             str += luxFloat("v11", luxProp(mat, keyname+".v11", 1.0), min, max, "v11", "", gui, 1.0)
  3745         elif type == "color":
  3746             if gui: gui.newline("          v00:", -2)
  3747             str += luxRGB("v00", luxProp(mat, keyname+".v00", "0.0 0.0 0.0"), max, "v00", "", gui, 2.0)
  3748             if gui: gui.newline("          v01:", -2)
  3749             str += luxRGB("v01", luxProp(mat, keyname+".v01", "1.0 1.0 1.0"), max, "v01", "", gui, 2.0)
  3750             if gui: gui.newline("          v10:", -2)
  3751             str += luxRGB("v10", luxProp(mat, keyname+".v10", "0.0 0.0 0.0"), max, "v10", "", gui, 2.0)
  3752             if gui: gui.newline("          v11:", -2)
  3753             str += luxRGB("v11", luxProp(mat, keyname+".v11", "1.0 1.0 1.0"), max, "v11", "", gui, 2.0)
  3754         str += luxMapping(keyname, mat, gui, level+1)
  3755 
  3756     if texture.get() == "windy":
  3757         str += lux3DMapping(keyname, mat, gui, level+1)
  3758         # this texture has no options 
  3759 
  3760     if texture.get() == "checkerboard":
  3761         dim = luxProp(mat, keyname+".dim", 2)
  3762         str += luxInt("dimension", dim, 2, 3, "dim", "", gui, 0.5)
  3763         if dim.get() == 2: str += luxOption("aamode", luxProp(mat, keyname+".aamode", "closedform"), ["closedform","supersample","none"], "aamode", "antialiasing mode", gui, 0.6)
  3764         if gui: gui.newline("", -2)
  3765         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  3766         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  3767         str = s + str + l
  3768         if dim.get() == 2: str += luxMapping(keyname, mat, gui, level+1) 
  3769         if dim.get() == 3: str += lux3DMapping(keyname, mat, gui, level+1)
  3770 
  3771     if texture.get() == "dots":
  3772         (s, l) = c(("", ""), luxTexture("inside", keyname, type, default, min, max, "inside", "", mat, gui, matlevel, texlevel+1, lightsource))
  3773         (s, l) = c((s, l), luxTexture("outside", keyname, type, alternativedefault(type, default), min, max, "outside", "", mat, gui, matlevel, texlevel+1, lightsource))
  3774         str = s + str + l
  3775         str += luxMapping(keyname, mat, gui, level+1)
  3776 
  3777     if texture.get() == "fbm":
  3778         str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1.1)
  3779         if gui: gui.newline("", -2)
  3780         str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 2.0, 1)
  3781         if gui: gui.newline("", -2)
  3782         str += lux3DMapping(keyname, mat, gui, level+1)
  3783 
  3784     if texture.get() == "marble":
  3785         str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1.1)
  3786         if gui: gui.newline("", -2)
  3787         str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 2.0, 1)
  3788         if gui: gui.newline("", -2)
  3789         str += luxFloat("nscale", luxProp(mat, keyname+".nscale", 1.0), 0.0, 100.0, "nscale", "Scaling factor for the noise input", gui, 1.0)
  3790         str += luxFloat("variation", luxProp(mat, keyname+".variation", 0.2), 0.0, 100.0, "variation", "A scaling factor for the noise input function", gui, 1.0)
  3791         if gui: gui.newline("", -2)
  3792         str += lux3DMapping(keyname, mat, gui, level+1)
  3793 
  3794     if texture.get() == "wrinkled":
  3795         str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1.1)
  3796         if gui: gui.newline("", -2)
  3797         str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 2.0, 1)
  3798         if gui: gui.newline("", -2)
  3799         str += lux3DMapping(keyname, mat, gui, level+1)
  3800 
  3801     if texture.get() == "brick":
  3802         if gui: gui.newline("brick:", -2, level+1, icon_texparam)
  3803 
  3804         str += luxFloat("brickwidth", luxProp(mat, keyname+".brickwidth", 0.3), 0.0, 10.0, "brickwidth (X)", "", gui, 1.0)
  3805         str += luxFloat("brickheight", luxProp(mat, keyname+".brickheight", 0.1), 0.0, 10.0, "brickheight (Z)", "", gui, 1.0)
  3806         str += luxFloat("brickdepth", luxProp(mat, keyname+".brickdepth", 0.15), 0.0, 10.0, "brickdepth (Y)", "", gui, 1.0)
  3807 
  3808         if gui: gui.newline("mortar:", -2, level+1, icon_texparam)
  3809 
  3810         str += luxFloat("mortarsize", luxProp(mat, keyname+".mortarsize", 0.01), 0.0, 1.0, "mortarsize", "", gui, 1.0)
  3811 
  3812         (s, l) = c(("", ""), luxTexture("bricktex", keyname, type, default, min, max, "bricktex", "", mat, gui, matlevel, texlevel+1, lightsource))
  3813         (s, l) = c((s, l), luxTexture("mortartex", keyname, type, alternativedefault(type, default), min, max, "mortartex", "", mat, gui, matlevel, texlevel+1, lightsource))
  3814         str = s + str + l
  3815 
  3816         str += lux3DMapping(keyname, mat, gui, level+1)
  3817 
  3818     if texture.get() == "blender_marble":
  3819         if gui: gui.newline("noise:", -2, level+1, icon_texparam)
  3820 
  3821         mtype = luxProp(mat, keyname+".mtype", "soft")
  3822         mtypes = ["soft","sharp","sharper"]
  3823         str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
  3824 
  3825         noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
  3826         noisetypes = ["soft_noise","hard_noise"]
  3827         str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
  3828 
  3829         str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0, 6, "noisedepth", "", gui, 0.75)
  3830 
  3831         str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
  3832         str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 200.0, "turbulance", "", gui, 1.0)
  3833 
  3834         if gui: gui.newline("basis:", -2, level+1, icon_texparam)
  3835         noisebasis2 = luxProp(mat, keyname+".noisebasis2", "sin")
  3836         noisebasises2 = ["sin","saw","tri"]
  3837         str += luxOption("noisebasis2", noisebasis2, noisebasises2, "noisebasis2", "", gui, 0.7)
  3838 
  3839         noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
  3840         noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
  3841         str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
  3842 
  3843         if gui: gui.newline("level:", -2, level+1, icon_texparam)
  3844         str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
  3845         str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
  3846 
  3847         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  3848         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  3849         str = s + str + l
  3850 
  3851         str += lux3DMapping(keyname, mat, gui, level+1)
  3852 
  3853     if texture.get() == "blender_musgrave":
  3854         if gui: gui.newline("type:", -2, level+1, icon_texparam)
  3855         mtype = luxProp(mat, keyname+".mtype", "multifractal")
  3856         mtypes = ["multifractal","ridged_multifractal", "hybrid_multifractal", "hetero_terrain", "fbm"]
  3857         str += luxOption("type", mtype, mtypes, "type", "", gui, 2.0)
  3858 
  3859         str += luxFloat("h", luxProp(mat, keyname+".h", 1.0), 0.0, 2.0, "h", "", gui, 0.5)
  3860         str += luxFloat("lacu", luxProp(mat, keyname+".lacu", 2.0), 0.0, 6.0, "lacu", "", gui, 0.75)
  3861         str += luxFloat("octs", luxProp(mat, keyname+".octs", 2.0), 0.0, 8.0, "octs", "", gui, 0.75)
  3862 
  3863         if mtype.get() == "hetero_terrain":
  3864             str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 2.0)
  3865         if mtype.get() == "ridged_multifractal":
  3866             str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 1.25)
  3867             str += luxFloat("gain", luxProp(mat, keyname+".gain", 2.0), 0.0, 6.0, "gain", "", gui, 0.75)
  3868         if mtype.get() == "hybrid_multifractal":
  3869             str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 1.25)
  3870             str += luxFloat("gain", luxProp(mat, keyname+".gain", 2.0), 0.0, 6.0, "gain", "", gui, 0.75)
  3871 
  3872         str += luxFloat("outscale", luxProp(mat, keyname+".outscale", 1.0), 0.0, 10.0, "iscale", "", gui, 1.0)
  3873         str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
  3874 
  3875         if gui: gui.newline("basis:", -2, level+1, icon_texparam)
  3876         noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
  3877         noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
  3878         str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 2.0)
  3879 
  3880         if gui: gui.newline("level:", -2, level+1, icon_texparam)
  3881         str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
  3882         str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
  3883 
  3884         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  3885         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  3886         str = s + str + l
  3887 
  3888         str += lux3DMapping(keyname, mat, gui, level+1)
  3889 
  3890     if texture.get() == "blender_wood":
  3891         if gui: gui.newline("noise:", -2, level+1, icon_texparam)
  3892 
  3893         mtype = luxProp(mat, keyname+".mtype", "bands")
  3894         mtypes = ["bands","rings","bandnoise", "ringnoise"]
  3895         str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
  3896 
  3897         noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
  3898         noisetypes = ["soft_noise","hard_noise"]
  3899         str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
  3900 
  3901         str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
  3902         str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 200.0, "turbulance", "", gui, 1.0)
  3903 
  3904         if gui: gui.newline("basis:", -2, level+1, icon_texparam)
  3905         noisebasis2 = luxProp(mat, keyname+".noisebasis2", "sin")
  3906         noisebasises2 = ["sin","saw","tri"]
  3907         str += luxOption("noisebasis2", noisebasis2, noisebasises2, "noisebasis2", "", gui, 0.7)
  3908 
  3909         noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
  3910         noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
  3911         str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
  3912 
  3913         if gui: gui.newline("level:", -2, level+1, icon_texparam)
  3914         str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
  3915         str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
  3916 
  3917         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  3918         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  3919         str = s + str + l
  3920     
  3921         str += lux3DMapping(keyname, mat, gui, level+1)
  3922 
  3923     if texture.get() == "blender_clouds":
  3924         if gui: gui.newline("noise:", -2, level+1, icon_texparam)
  3925 
  3926         mtype = luxProp(mat, keyname+".mtype", "default")
  3927         mtypes = ["default","color"]
  3928         str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
  3929 
  3930         noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
  3931         noisetypes = ["soft_noise","hard_noise"]
  3932         str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
  3933 
  3934         str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
  3935         str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0, 6, "noisedepth", "", gui, 1.0)
  3936 
  3937         if gui: gui.newline("basis:", -2, level+1, icon_texparam)
  3938         noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
  3939         noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
  3940         str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
  3941 
  3942         if gui: gui.newline("level:", -2, level+1, icon_texparam)
  3943         str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
  3944         str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
  3945 
  3946         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  3947         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  3948         str = s + str + l
  3949     
  3950         str += lux3DMapping(keyname, mat, gui, level+1)
  3951 
  3952     if texture.get() == "blender_blend":
  3953         if gui: gui.newline("type:", -2, level+1, icon_texparam)
  3954 
  3955         mtype = luxProp(mat, keyname+".mtype", "lin")
  3956         mtypes = ["lin","quad","ease","diag","sphere","halo","radial"]
  3957         str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
  3958         
  3959         mflag = luxProp(mat, keyname+".flag", "false")
  3960         str += luxBool("flipxy", mflag, "flipXY", "", gui, 0.5)
  3961 
  3962         if gui: gui.newline("level:", -2, level+1, icon_texparam)
  3963         str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
  3964         str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
  3965 
  3966         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  3967         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  3968         str = s + str + l
  3969         
  3970         str += lux3DMapping(keyname, mat, gui, level+1)
  3971 
  3972     if texture.get() == "blender_distortednoise":
  3973         if gui: gui.newline("noise:", -2, level+1, icon_texparam)
  3974         
  3975         str += luxFloat("distamount", luxProp(mat, keyname+".distamount", 1.0), 0.0, 10.0, "distamount", "", gui, 1.0)
  3976         str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
  3977         str += luxFloat("nabla", luxProp(mat, keyname+".nabla", 0.025), 0.000, 2.0, "nabla", "", gui, 1.0)
  3978         
  3979         if gui: gui.newline("distortion:", -2, level+1, icon_texparam)
  3980         ntype = luxProp(mat, keyname+".type", "blender_original")
  3981         ntypes = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
  3982         str += luxOption("type", ntype, ntypes, "type", "", gui, 1.3)
  3983         
  3984         if gui: gui.newline("basis:", -2, level+1, icon_texparam)
  3985         noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
  3986         noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
  3987         str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
  3988 
  3989         if gui: gui.newline("level:", -2, level+1, icon_texparam)
  3990         str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
  3991         str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
  3992 
  3993         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  3994         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  3995         str = s + str + l
  3996         
  3997         str += lux3DMapping(keyname, mat, gui, level+1)
  3998 
  3999     if texture.get() == "blender_noise":        
  4000         if gui: gui.newline("level:", -2, level+1, icon_texparam)
  4001         str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
  4002         str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
  4003 
  4004         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  4005         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  4006         str = s + str + l
  4007         
  4008         str += lux3DMapping(keyname, mat, gui, level+1)
  4009         
  4010     if texture.get() == "blender_magic":
  4011         if gui: gui.newline("noise:", -2, level+1, icon_texparam)
  4012         
  4013         str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0.0, 10.0, "noisedepth", "", gui, 1.0)
  4014         str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 2.0, "turbulance", "", gui, 1.0)
  4015 
  4016         if gui: gui.newline("level:", -2, level+1, icon_texparam)
  4017         str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
  4018         str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
  4019 
  4020         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  4021         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  4022         str = s + str + l
  4023         
  4024         str += lux3DMapping(keyname, mat, gui, level+1)
  4025         
  4026     if texture.get() == "blender_stucci":
  4027         if gui: gui.newline("noise:", -2, level+1, icon_texparam)
  4028         mtype = luxProp(mat, keyname+".mtype", "Plastic")
  4029         mtypes = ["Plastic","Wall In","Wall Out"]
  4030         str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
  4031 
  4032         noisetype = luxProp(mat, keyname+".noisetype", "soft_noise")
  4033         noisetypes = ["soft_noise","hard_noise"]
  4034         str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
  4035         
  4036         str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 10.0, "noisesize", "", gui, 1.0)
  4037         str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 200.0, "turbulance", "", gui, 1.0)
  4038 
  4039         noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
  4040         noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
  4041         str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
  4042 
  4043         if gui: gui.newline("level:", -2, level+1, icon_texparam)
  4044         str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
  4045         str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
  4046 
  4047         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  4048         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  4049         str = s + str + l
  4050 
  4051         str += lux3DMapping(keyname, mat, gui, level+1)
  4052 
  4053     if texture.get() == "blender_voronoi":
  4054         #if gui: gui.newline("distmetric:", -2, level+1, icon_texparam)
  4055         mtype = luxProp(mat, keyname+".distmetric", "actual_distance")
  4056         mtypes = ["actual_distance","distance_squared","manhattan", "chebychev", "minkovsky_half", "minkovsky_four", "minkovsky"]
  4057         str += luxOption("distmetric", mtype, mtypes, "distmetric", "", gui, 1.1)
  4058 
  4059         if gui: gui.newline("param:", -2, level+1, icon_texparam)
  4060         str += luxFloat("minkovsky_exp", luxProp(mat, keyname+".minkovsky_exp", 2.5), 0.001, 10.0, "minkovsky_exp", "", gui, 1.0)
  4061         str += luxFloat("outscale", luxProp(mat, keyname+".outscale", 1.0), 0.01, 10.0, "outscale", "", gui, 1.0)
  4062         str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
  4063         str += luxFloat("nabla", luxProp(mat, keyname+".nabla", 0.025), 0.001, 0.1, "nabla", "", gui, 1.0)
  4064         if gui: gui.newline("wparam:", -2, level+1, icon_texparam)
  4065         str += luxFloat("w1", luxProp(mat, keyname+".w1", 1.0), -2.0, 2.0, "w1", "", gui, 1.0)
  4066         str += luxFloat("w2", luxProp(mat, keyname+".w2", 0.0), -2.0, 2.0, "w2", "", gui, 1.0)
  4067         str += luxFloat("w3", luxProp(mat, keyname+".w3", 0.0), -2.0, 2.0, "w3", "", gui, 1.0)
  4068         str += luxFloat("w4", luxProp(mat, keyname+".w4", 0.0), -2.0, 2.0, "w4", "", gui, 1.0)
  4069 
  4070         if gui: gui.newline("level:", -2, level+1, icon_texparam)
  4071         str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
  4072         str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
  4073 
  4074         (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
  4075         (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
  4076         str = s + str + l
  4077 
  4078         str += lux3DMapping(keyname, mat, gui, level+1)
  4079 
  4080 
  4081 
  4082     return (str+"\n", " \"texture %s\" [\"%s\"]"%(name, texname))
  4083 
  4084 
  4085 def luxSpectrumTexture(name, key, default, max, caption, hint, mat, gui, level=0):
  4086     global icon_col
  4087     if gui: gui.newline(caption, 4, level, icon_col, scalelist([0.5,0.6,0.5],2.0/(level+2)))
  4088     str = ""
  4089     keyname = "%s:%s"%(key, name)
  4090     texname = "%s:%s"%(mat.getName(), keyname)
  4091     value = luxProp(mat, keyname, default)
  4092     link = luxRGB(name, value, max, "", hint, gui, 2.0)
  4093     tex = luxProp(mat, keyname+".textured", False)
  4094     if gui: Draw.Toggle("T", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, tex.get()=="true", "use texture", lambda e,v:tex.set(["false","true"][bool(v)]))
  4095     if tex.get()=="true":
  4096         if gui: gui.newline("", -2)
  4097         (str, link) = luxTexture(name, key, "color", default, 0, max, caption, hint, mat, gui, level+1)
  4098         if value.getRGB() != (1.0, 1.0, 1.0):
  4099             if str == "": # handle special case if texture is a just a constant
  4100                 str += "Texture \"%s\" \"color\" \"scale\" \"color tex1\" [%s] \"color tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
  4101             else: str += "Texture \"%s\" \"color\" \"scale\" \"texture tex1\" [\"%s\"] \"color tex2\" [%s]\n"%(texname+".scale", texname, value.get())
  4102             link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
  4103     return (str, link)
  4104 
  4105 def luxLightSpectrumTexture(name, key, default, max, caption, hint, mat, gui, level=0):
  4106     #if gui: gui.newline(caption, 4, level, icon_emission, scalelist([0.6,0.5,0.5],2.0/(level+2)))
  4107     str = ""
  4108     keyname = "%s:%s"%(key, name)
  4109     texname = "%s:%s"%(mat.getName(), keyname)
  4110     (str, link) = luxTexture(name, key, "color", default, 0, max, caption, hint, mat, gui, level+1, 0, 1)
  4111     return (str, link)
  4112 
  4113 def luxFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
  4114     global icon_float
  4115     if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
  4116     str = ""
  4117     keyname = "%s:%s"%(key, name)
  4118     texname = "%s:%s"%(mat.getName(), keyname)
  4119     value = luxProp(mat, keyname, default)
  4120     link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
  4121     tex = luxProp(mat, keyname+".textured", False)
  4122     if gui: Draw.Toggle("T", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, tex.get()=="true", "use texture", lambda e,v:tex.set(["false","true"][bool(v)]))
  4123     if tex.get()=="true":
  4124         if gui: gui.newline("", -2)
  4125         (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
  4126         if value.get() != 1.0:
  4127             if str == "": # handle special case if texture is a just a constant
  4128                 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
  4129             else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
  4130             link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
  4131     return (str, link)
  4132 
  4133 def luxFloatSliderTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
  4134         global icon_float
  4135         if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
  4136         str = ""
  4137         keyname = "%s:%s"%(key, name)
  4138         texname = "%s:%s"%(mat.getName(), keyname)
  4139         value = luxProp(mat, keyname, default)
  4140         link = luxFloat(name, value, min, max, caption, hint, gui, 2.0, 1)
  4141         tex = luxProp(mat, keyname+".textured", False)
  4142         if gui: Draw.Toggle("T", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, tex.get()=="true", "use texture", lambda e,v:tex.set(["false","true"][bool(v)]))
  4143         if tex.get()=="true":
  4144                 if gui: gui.newline("", -2)
  4145                 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
  4146                 if value.get() != 1.0:
  4147                         if str == "": # handle special case if texture is a just a constant
  4148                                 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
  4149                         else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
  4150                         link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
  4151         return (str, link)
  4152 
  4153 
  4154 def luxExponentTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
  4155     global icon_float
  4156     if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
  4157     str = ""
  4158     keyname = "%s:%s"%(key, name)
  4159     texname = "%s:%s"%(mat.getName(), keyname)
  4160     value = luxProp(mat, keyname, default)
  4161 
  4162     if(value.get() == None): value.set(0.002)
  4163 
  4164 #    link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
  4165     if gui:
  4166         r = gui.getRect(2.0, 1)
  4167         Draw.Number("", evtLuxGui, r[0], r[1], r[2], r[3], float(1.0/value.getFloat()), 1.0, 1000000.0, hint, lambda e,v: value.set(1.0/v))
  4168     link = " \"float %s\" [%f]"%(name, value.getFloat())
  4169 
  4170     tex = luxProp(mat, keyname+".textured", False)
  4171     if gui: Draw.Toggle("T", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, tex.get()=="true", "use texture", lambda e,v:tex.set(["false","true"][bool(v)]))
  4172     if tex.get()=="true":
  4173         if gui: gui.newline("", -2)
  4174         (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
  4175         if value.get() != 1.0:
  4176             if str == "": # handle special case if texture is a just a constant
  4177                 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
  4178             else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
  4179             link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
  4180     return (str, link)
  4181 
  4182 
  4183 def luxDispFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
  4184     global icon_float
  4185     if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
  4186     str = ""
  4187     keyname = "%s:%s"%(key, name)
  4188     texname = "%s:%s"%(mat.getName(), keyname)
  4189     value = luxProp(mat, keyname, default)
  4190     link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
  4191     tex = luxProp(mat, keyname+".textured", False)
  4192     if gui: Draw.Toggle("T", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, tex.get()=="true", "use texture", lambda e,v:tex.set(["false","true"][bool(v)]))
  4193     if tex.get()=="true":
  4194         if gui: gui.newline("", -2)
  4195         (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
  4196         str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
  4197         link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
  4198     return (str, link)
  4199 
  4200 def luxIORFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
  4201     # IOR preset data
  4202     iornames = ["0Z *** Gases @ 0 C ***", "01 - Vacuum", "02 - Air @ STP", "03 - Air", "04 - Helium", "05 - Hydrogen", "06 - Carbon dioxide",
  4203     "1Z *** LIQUIDS @ 20 C ***", "11 - Benzene", "12 - Water", "13 - Ethyl alcohol", "14 - Carbon tetrachloride", "15 - Carbon disulfide", 
  4204     "2Z *** SOLIDS at room temperature ***", "21 - Diamond", "22 - Strontium titanate", "23 - Amber", "24 - Fused silica glass", "25 - sodium chloride", 
  4205     "3Z *** OTHER Materials ***", "31 - Pyrex (Borosilicate glass)", "32 - Ruby", "33 - Water ice", "34 - Cryolite", "35 - Acetone", "36 - Ethanol", "37 - Teflon", "38 - Glycerol", "39 - Acrylic glass", "40 - Rock salt", "41 - Crown glass (pure)", "42 - Salt (NaCl)", "43 - Polycarbonate", "44 - PMMA", "45 - PETg", "46 - PET", "47 - Flint glass (pure)", "48 - Crown glass (impure)", "49 - Fused Quartz", "50 - Bromine", "51 - Flint glass (impure)", "52 - Cubic zirconia", "53 - Moissanite", "54 - Cinnabar (Mercury sulfide)", "55 - Gallium(III) prosphide", "56 - Gallium(III) arsenide", "57 - Silicon"]
  4206     iorvals = [1.0, 1.0, 1.0002926, 1.000293, 1.000036, 1.000132, 1.00045,
  4207     1.501, 1.501, 1.333, 1.361, 1.461, 1.628,
  4208     2.419, 2.419, 2.41, 1.55, 1.458, 1.50,
  4209     1.470, 1.470, 1.760, 1.31, 1.388, 1.36, 1.36, 1.35, 1.4729, 1.490, 1.516, 1.50, 1.544, 1.584, 1.4893, 1.57, 1.575, 1.60, 1.485, 1.46, 1.661, 1.523, 2.15, 2.419, 2.65, 3.02, 3.5, 3.927, 4.01]
  4210 
  4211     global icon_float
  4212     if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
  4213     str = ""
  4214     keyname = "%s:%s"%(key, name)
  4215     texname = "%s:%s"%(mat.getName(), keyname)
  4216     value = luxProp(mat, keyname, default)
  4217 
  4218     iorusepreset = luxProp(mat, keyname+".iorusepreset", "true")
  4219     luxBool("iorusepreset", iorusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
  4220 
  4221     if(iorusepreset.get() == "true"):
  4222         iorpreset = luxProp(mat, keyname+".iorpreset", "24 - Fused silica glass")
  4223         if gui:
  4224             def setIor(i, value, preset, tree, dict): # callback function to set ior value after selection                
  4225                 if i >= 0:
  4226                     value.set(dict[i])
  4227                     preset.set(getTreeNameById(tree, i))
  4228             iortree = [ ("LIQUIDS", [("Acetone", 1), ("Alcohol, Ethyl (grain)", 2), ("Alcohol, Methyl (wood)", 3), ("Beer", 4), ("Benzene", 5), ("Carbon tetrachloride", 6), ("Carbon disulfide", 7), ("Carbonated Beverages", 8), ("Chlorine (liq)", 9), ("Cranberry Juice (25%)", 10), ("Glycerin", 11), ("Honey, 13% water content", 12), ("Honey, 17% water content", 13), ("Honey, 21% water content", 14), ("Ice", 15), ("Milk", 16), ("Oil, Clove", 17), ("Oil, Lemon", 18), ("Oil, Neroli", 19), ("Oil, Orange", 20), ("Oil, Safflower", 21), ("Oil, vegetable (50 C)", 22), ("Oil of Wintergreen", 23), ("Rum, White", 24), ("Shampoo", 25), ("Sugar Solution 30%", 26), ("Sugar Solution 80%", 27), ("Turpentine", 28), ("Vodka", 29), ("Water (0 C)", 30), ("Water (100 C)", 31), ("Water (20 C)", 32), ("Whisky", 33) ] ), ("GASES(0C)", [("Vacuum", 101), ("Air @ STP", 102), ("Air", 103), ("Helium", 104), ("Hydrogen", 105), ("Carbon dioxide", 106) ]), ("TRANSPARENT", [("Eye, Aqueous humor", 201), ("Eye, Cornea", 202), ("Eye, Lens", 203), ("Eye, Vitreous humor", 204), ("Glass, Arsenic Trisulfide", 205), ("Glass, Crown (common)", 206), ("Glass, Flint, 29% lead", 207), ("Glass, Flint, 55% lead", 208), ("Glass, Flint, 71% lead", 209), ("Glass, Fused Silica", 210), ("Glass, Pyrex", 211), ("Lucite", 212), ("Nylon", 213), ("Obsidian", 214), ("Plastic", 215), ("Plexiglas", 216), ("Salt", 217)  ]), ("GEMSTONES", [("Agate", 301), ("Alexandrite", 302), ("Almandine", 303), ("Amber", 304), ("Amethyst", 305), ("Ammolite", 306), ("Andalusite", 307), ("Apatite", 308), ("Aquamarine", 309), ("Axenite", 310), ("Beryl", 311), ("Beryl, Red", 312), ("Chalcedony", 313), ("Chrome Tourmaline", 314), ("Citrine", 315), ("Clinohumite", 316), ("Coral", 317), ("Crystal", 318), ("Crysoberyl, Catseye", 319), ("Danburite", 320), ("Diamond", 321), ("Emerald", 322), ("Emerald Catseye", 323), ("Flourite", 324), ("Garnet, Grossular", 325), ("Garnet, Andradite", 326), ("Garnet, Demantiod", 327), ("Garnet, Mandarin", 328), ("Garnet, Pyrope", 329), ("Garnet, Rhodolite", 330), ("Garnet, Tsavorite", 331), ("Garnet, Uvarovite", 332), ("Hauyn", 333), ("Iolite", 334), ("Jade, Jadeite", 335), ("Jade, Nephrite", 336), ("Jet", 337), ("Kunzite", 338), ("Labradorite", 339), ("Lapis Lazuli", 340), ("Moonstone", 341), ("Morganite", 342), ("Obsidian", 343), ("Opal, Black", 344), ("Opal, Fire", 345), ("Opal, White", 346), ("Oregon Sunstone", 347), ("Padparadja", 348), ("Pearl", 349), ("Peridot", 350), ("Quartz", 351), ("Ruby", 352), ("Sapphire", 353), ("Sapphire, Star", 354), ("Spessarite", 355), ("Spinel", 356), ("Spinel, Blue", 357), ("Spinel, Red", 358), ("Star Ruby", 359), ("Tanzanite", 360), ("Topaz", 361), ("Topaz, Imperial", 362), ("Tourmaline", 363), ("Tourmaline, Blue", 364), ("Tourmaline, Catseye", 365), ("Tourmaline, Green", 366), ("Tourmaline, Paraiba", 367), ("Tourmaline, Red", 368), ("Zircon", 369), ("Zirconia, Cubic", 370) ] ), ("OTHER", [("Pyrex (Borosilicate glass)", 401), ("Ruby", 402), ("Water ice", 403), ("Cryolite", 404), ("Acetone", 405), ("Ethanol", 406), ("Teflon", 407), ("Glycerol", 408), ("Acrylic glass", 409), ("Rock salt", 410), ("Crown glass (pure)", 411), ("Salt (NaCl)", 412), ("Polycarbonate", 413), ("PMMA", 414), ("PETg", 415), ("PET", 416), ("Flint glass (pure)", 417), ("Crown glass (impure)", 418), ("Fused Quartz", 419), ("Bromine", 420), ("Flint glass (impure)", 421), ("Cubic zirconia", 422), ("Moissanite", 423), ("Cinnabar (Mercury sulfide)", 424), ("Gallium(III) prosphide", 425), ("Gallium(III) arsenide", 426), ("Silicon", 427) ] ) ]
  4229             iordict = {1:1.36, 2:1.36, 3:1.329, 4:1.345, 5:1.501, 6:1.000132, 7:1.00045, 8:1.34, 9:1.385, 10:1.351, 11:1.473, 12:1.504, 13:1.494, 14:1.484, 15:1.309, 16:1.35, 17:1.535, 18:1.481, 19:1.482, 20:1.473, 21:1.466, 22:1.47, 23:1.536, 24:1.361, 25:1.362, 26:1.38, 27:1.49, 28:1.472, 29:1.363, 30:1.33346, 31:1.31766, 32:1.33283, 33:1.356, 101:1.0, 102:1.0002926, 103:1.000293, 104:1.000036, 105:1.000132, 106:1.00045, 201:1.33, 202:1.38, 203:1.41, 204:1.34, 205:2.04, 206:1.52, 207:1.569, 208:1.669, 209:1.805, 210:1.459, 211:1.474, 212:1.495, 213:1.53, 214:1.50, 215:1.460, 216:1.488, 217:1.516, 301:1.544, 302:1.746, 303:1.75, 304:1.539, 305:1.532, 306:1.52, 307:1.629, 308:1.632, 309:1.567, 310:1.674, 311:1.57, 312:1.570, 313:1.544, 314:1.61, 315:1.532, 316:1.625, 317:1.486, 318:2.000, 319:1.746, 320:1.627, 321:2.417, 322:1.560, 323:1.560, 324:1.434, 325:1.72, 326:1.88, 327:1.880, 328:1.790, 329:1.73, 330:1.740, 331:1.739, 332:1.74, 333:1.490, 334:1.522, 335:1.64, 336:1.600, 337:1.660, 338:1.660, 339:1.560, 340:1.50, 341:1.518, 342:1.585, 343:1.50, 344:1.440, 345:1.430, 346:1.440, 347:1.560, 348:1.760, 349:1.53, 350:1.635, 351:1.544, 352:1.757, 353:1.757, 354:1.760, 355:1.79, 356:1.712, 357:1.712, 358:1.708, 359:1.76, 360:1.690, 361:1.607, 362:1.605, 363:1.603, 364:1.61, 365:1.61, 366:1.61, 367:1.61, 368:1.61, 369:1.777, 370:2.173, 401:1.47, 402:1.76, 403:1.31, 404:1.388, 405:1.36, 406:1.36, 407:1.35, 408:1.4729, 409:1.49, 410:1.516, 411:1.5, 412:1.544, 413:1.584, 414:1.4893, 415:1.57, 416:1.575, 417:1.6, 418:1.485, 419:1.46, 420:1.661, 421:1.523, 422:2.15, 423:2.419, 424:2.65, 425:3.02, 426:3.5, 427:3.927}
  4230             r = gui.getRect(1.6, 1)
  4231             Draw.Button(iorpreset.get(), evtLuxGui, r[0], r[1], r[2], r[3], "select IOR preset", lambda e,v: setIor(Draw.PupTreeMenu(iortree), value, iorpreset, iortree, iordict))
  4232         link = luxFloat(name, value, min, max, "IOR", hint, None, 1.6)
  4233     else:
  4234         link = luxFloat(name, value, min, max, "IOR", hint, gui, 1.6, 1)
  4235 
  4236     tex = luxProp(mat, keyname+".textured", False)
  4237     if gui: Draw.Toggle("T", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, tex.get()=="true", "use texture", lambda e,v:tex.set(["false","true"][bool(v)]))
  4238     if tex.get()=="true":
  4239         if gui: gui.newline("", -2)
  4240         (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
  4241         if value.get() != 1.0:
  4242             str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
  4243             link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
  4244     return (str, link)
  4245 
  4246 def luxCauchyBFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
  4247     # IOR preset data
  4248     cauchybnames = ["01 - Fused silica glass", "02 - Borosilicate glass BK7", "03 - Hard crown glass K5", "04 - Barium crown glass BaK4", "05 - Barium flint glass BaF10", "06 - Dense flint glass SF10" ]
  4249     cauchybvals = [ 0.00354, 0.00420, 0.00459, 0.00531, 0.00743, 0.01342 ]
  4250 
  4251     global icon_float
  4252     if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
  4253     str = ""
  4254     keyname = "%s:%s"%(key, name)
  4255     texname = "%s:%s"%(mat.getName(), keyname)
  4256     value = luxProp(mat, keyname, default)
  4257 
  4258     cauchybusepreset = luxProp(mat, keyname+".cauchybusepreset", "true")
  4259     luxBool("cauchybusepreset", cauchybusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
  4260 
  4261     if(cauchybusepreset.get() == "true"):
  4262         cauchybpreset = luxProp(mat, keyname+".cauchybpreset", "01 - Fused silica glass")
  4263         luxOption("cauchybpreset", cauchybpreset, cauchybnames, "  PRESET", "select CauchyB preset", gui, 1.6)
  4264         idx = cauchybnames.index(cauchybpreset.get())
  4265         value.set(cauchybvals[idx])
  4266         link = luxFloat(name, value, min, max, "cauchyb", hint, None, 1.6)
  4267     else:
  4268         link = luxFloat(name, value, min, max, "cauchyb", hint, gui, 1.6, 1)
  4269 
  4270     tex = luxProp(mat, keyname+".textured", False)
  4271     if gui: Draw.Toggle("T", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, tex.get()=="true", "use texture", lambda e,v:tex.set(["false","true"][bool(v)]))
  4272     if tex.get()=="true":
  4273         if gui: gui.newline("", -2)
  4274         (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
  4275         if value.get() != 1.0:
  4276             str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
  4277             link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
  4278     return (str, link)
  4279 
  4280 def luxLight(name, kn, mat, gui, level):
  4281     if gui:
  4282         if name != "": gui.newline(name+":", 10, level)
  4283         else: gui.newline("color:", 0, level+1)
  4284     (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
  4285     if gui: gui.newline("")
  4286     link += luxFloat("power", luxProp(mat, kn+"light.power", 100.0), 0.0, 10000.0, "Power(W)", "AreaLight Power in Watts", gui)
  4287     link += luxFloat("efficacy", luxProp(mat, kn+"light.efficacy", 17.0), 0.0, 100.0, "Efficacy(lm/W)", "Efficacy Luminous flux/watt", gui)
  4288     if gui: gui.newline("")
  4289     link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
  4290     lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
  4291     luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 1.0)
  4292 
  4293     if gui: gui.newline("Photometric")
  4294     pm = luxProp(mat, kn+"light.usepm", "false")
  4295     luxCollapse("photometric", pm, "Photometric Diagram", "Enable Photometric Diagram options", gui, 2.0)
  4296 
  4297     if(pm.get()=="true"):
  4298         pmtype = luxProp(mat, kn+"light.pmtype", "IESna")
  4299         pmtypes = ["IESna", "imagemap"]
  4300         luxOption("type", pmtype, pmtypes, "type", "Choose Photometric data type to use", gui, 0.6)
  4301         if(pmtype.get() == "imagemap"):
  4302             map = luxProp(mat, kn+"light.pmmapname", "")
  4303             link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 1.4)
  4304         if(pmtype.get() == "IESna"):
  4305             map = luxProp(mat, kn+"light.pmiesname", "")
  4306             link += luxFile("iesname", map, "ies-file", "filename of the IES photometric data file", gui, 1.4)
  4307 
  4308     has_bump_options = 0
  4309     has_object_options = 1
  4310     return (str, link)
  4311 
  4312 def luxLamp(name, kn, mat, gui, level):
  4313     if gui:
  4314         if name != "": gui.newline(name+":", 10, level)
  4315         else: gui.newline("color:", 0, level+1)
  4316 #    if gui: gui.newline("", 10, level)
  4317     (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
  4318     if gui: gui.newline("")
  4319     link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
  4320     lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
  4321     luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 1.0)
  4322 
  4323     if gui: gui.newline("Photometric")
  4324     pm = luxProp(mat, kn+"light.usepm", "false")
  4325     luxBool("photometric", pm, "Photometric Diagram", "Enable Photometric Diagram options", gui, 2.0)
  4326 
  4327     if(pm.get()=="true"):
  4328         pmtype = luxProp(mat, kn+"light.pmtype", "IESna")
  4329         pmtypes = ["IESna", "imagemap"]
  4330         luxOption("type", pmtype, pmtypes, "type", "Choose Photometric data type to use", gui, 0.6)
  4331         if(pmtype.get() == "imagemap"):
  4332             map = luxProp(mat, kn+"light.pmmapname", "")
  4333             link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 1.4)
  4334         if(pmtype.get() == "IESna"):
  4335             map = luxProp(mat, kn+"light.pmiesname", "")
  4336             link += luxFile("iesname", map, "ies-file", "filename of the IES photometric data file", gui, 1.4)
  4337 
  4338         link += luxBool("flipz", luxProp(mat, kn+"light.flipZ", "true"), "Flip Z", "Flip Z direction in mapping", gui, 2.0)
  4339 
  4340     return (str, link)
  4341 
  4342 def luxSpot(name, kn, mat, gui, level):
  4343     if gui:
  4344         if name != "": gui.newline(name+":", 10, level)
  4345         else: gui.newline("color:", 0, level+1)
  4346 #    if gui: gui.newline("", 10, level)
  4347     (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
  4348     if gui: gui.newline("")
  4349     link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
  4350     lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
  4351     luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 1.0)
  4352 
  4353     if gui: gui.newline("Projection")
  4354     proj = luxProp(mat, kn+"light.usetexproj", "false")
  4355     luxBool("projection", proj, "Texture Projection", "Enable imagemap texture projection", gui, 2.0)
  4356 
  4357     if(proj.get() == "true"):
  4358         map = luxProp(mat, kn+"light.pmmapname", "")
  4359         link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 2.0)
  4360 
  4361     return (str, link)
  4362 
  4363 
  4364 def Preview_Sphereset(mat, kn, state):
  4365     if state=="true":
  4366         luxProp(mat, kn+"prev_sphere", "true").set("true")
  4367         luxProp(mat, kn+"prev_plane", "false").set("false")
  4368         luxProp(mat, kn+"prev_torus", "false").set("false")
  4369 def Preview_Planeset(mat, kn, state):
  4370     if state=="true":
  4371         luxProp(mat, kn+"prev_sphere", "true").set("false")
  4372         luxProp(mat, kn+"prev_plane", "false").set("true")
  4373         luxProp(mat, kn+"prev_torus", "false").set("false")
  4374 def Preview_Torusset(mat, kn, state):
  4375     if state=="true":
  4376         luxProp(mat, kn+"prev_sphere", "true").set("false")
  4377         luxProp(mat, kn+"prev_plane", "false").set("false")
  4378         luxProp(mat, kn+"prev_torus", "false").set("true")
  4379 
  4380 def Preview_Update(mat, kn, defLarge, defType, texName, name, level):
  4381     #print "%s %s %s %s %s %s %s" % (mat, kn, defLarge, defType, texName, name, level)
  4382 
  4383     global previewing
  4384     previewing = True
  4385     
  4386     Blender.Window.WaitCursor(True)
  4387     scn = Scene.GetCurrent()
  4388 
  4389     # Size of preview thumbnail
  4390     thumbres = 110 # default 110x110
  4391     if(defLarge):
  4392         large = luxProp(mat, kn+"prev_large", "true")
  4393     else:
  4394         large = luxProp(mat, kn+"prev_large", "false")
  4395     if(large.get() == "true"):
  4396         thumbres = 140 # small 140x140
  4397 
  4398     thumbbuf = thumbres*thumbres*3
  4399 
  4400 #        consolebin = luxProp(scn, "luxconsole", "").get()
  4401     consolebin = Blender.sys.dirname(luxProp(scn, "lux", "").get()) + os.sep + "luxconsole"
  4402     if osys.platform == "win32": consolebin = consolebin + ".exe"
  4403 
  4404     PIPE = subprocess.PIPE
  4405     p = subprocess.Popen((consolebin, '-b', '-'), bufsize=thumbbuf, stdin=PIPE, stdout=PIPE, stderr=PIPE)
  4406 
  4407     # Unremark to write debugging output to file
  4408     # p.stdin = open('c:\preview.lxs', 'w')
  4409 
  4410     if defType == 0:    
  4411         prev_sphere = luxProp(mat, kn+"prev_sphere", "true")
  4412         prev_plane = luxProp(mat, kn+"prev_plane", "false")
  4413         prev_torus = luxProp(mat, kn+"prev_torus", "false")
  4414     elif defType == 1:
  4415         prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
  4416         prev_plane = luxProp(mat, kn+"prev_plane", "true")
  4417         prev_torus = luxProp(mat, kn+"prev_torus", "false")
  4418     else:
  4419         prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
  4420         prev_plane = luxProp(mat, kn+"prev_plane", "false")
  4421         prev_torus = luxProp(mat, kn+"prev_torus", "true")
  4422 
  4423     # Zoom
  4424     if luxProp(mat, kn+"prev_zoom", "false").get() == "true":
  4425         p.stdin.write('LookAt 0.250000 -1.500000 0.750000 0.250000 -0.500000 0.750000 0.000000 0.000000 1.000000\nCamera "perspective" "float fov" [22.5]\n')
  4426     else:
  4427         p.stdin.write('LookAt 0.0 -3.0 0.5 0.0 -2.0 0.5 0.0 0.0 1.0\nCamera "perspective" "float fov" [22.5]\n')
  4428     # Fleximage
  4429     p.stdin.write('Film "fleximage" "integer xresolution" [%i] "integer yresolution" [%i] "integer displayinterval" [3] "integer ldr_writeinterval" [3600] "string tonemapper" ["reinhard"] "integer haltspp" [1] "integer reject_warmup" [64] "bool write_tonemapped_tga" ["false"] "bool write_untonemapped_exr" ["false"] "bool write_tonemapped_exr" ["false"] "bool write_untonemapped_igi" ["false"] "bool write_tonemapped_igi" ["false"] "bool write_png" ["false"] "string filename" ["luxblend-preview"] \n'%(thumbres, thumbres))
  4430     p.stdin.write('PixelFilter "sinc"\n')
  4431     # Quality
  4432     scn = Scene.GetCurrent()
  4433     defprevmat = luxProp(scn, "defprevmat", "high")
  4434     quality = luxProp(mat, kn+"prev_quality", defprevmat.get())
  4435     if quality.get()=="low":
  4436         p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [2]\n')
  4437     elif quality.get()=="medium":
  4438         p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [4]\n')
  4439     elif quality.get()=="high":
  4440         p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [8]\n')
  4441     else: 
  4442         p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [32]\n')
  4443     # SurfaceIntegrator
  4444     if(prev_plane.get()=="false"):
  4445         p.stdin.write('SurfaceIntegrator "distributedpath" "integer directsamples" [1] "integer diffusereflectdepth" [1] "integer diffusereflectsamples" [4] "integer diffuserefractdepth" [4] "integer diffuserefractsamples" [1] "integer glossyreflectdepth" [1] "integer glossyreflectsamples" [2] "integer glossyrefractdepth" [4] "integer glossyrefractsamples" [1] "integer specularreflectdepth" [2] "integer specularrefractdepth" [4]\n')
  4446     else:
  4447         p.stdin.write('SurfaceIntegrator "distributedpath" "integer directsamples" [1] "integer diffusereflectdepth" [0] "integer diffusereflectsamples" [0] "integer diffuserefractdepth" [0] "integer diffuserefractsamples" [0] "integer glossyreflectdepth" [0] "integer glossyreflectsamples" [0] "integer glossyrefractdepth" [0] "integer glossyrefractsamples" [0] "integer specularreflectdepth" [1] "integer specularrefractdepth" [1]\n')
  4448     # World
  4449     p.stdin.write('WorldBegin\n')
  4450     if(prev_sphere.get()=="true"):
  4451         p.stdin.write('AttributeBegin\nTransform [0.5 0.0 0.0 0.0  0.0 0.5 0.0 0.0  0.0 0.0 0.5 0.0  0.0 0.0 0.5 1.0]\n')
  4452     elif (prev_plane.get()=="true"):
  4453         p.stdin.write('AttributeBegin\nTransform [0.649999976158 0.0 0.0 0.0  0.0 4.90736340453e-008 0.649999976158 0.0  0.0 -0.649999976158 4.90736340453e-008 0.0  0.0 0.0 0.5 1.0]\n')
  4454     else:
  4455         p.stdin.write('AttributeBegin\nTransform [0.35 -0.35 0.0 0.0  0.25 0.25 0.35 0.0  -0.25 -0.25 0.35 0.0  0.0 0.0 0.5 1.0]\n')
  4456     obwidth = luxProp(mat, kn+"prev_obwidth", 1.0)
  4457     obw = obwidth.get()
  4458     p.stdin.write('TransformBegin\n')
  4459     p.stdin.write('Scale %f %f %f\n'%(obw,obw,obw))
  4460     if texName:
  4461         print "texture "+texName+"  "+name
  4462         (str, link) = luxTexture(texName, name, "color", "1.0 1.0 1.0", None, None, "", "", mat, None, 0, level)
  4463         link = link.replace(" "+texName+"\"", " Kd\"") # swap texture name to "Kd"
  4464         p.stdin.write(str+"\n")
  4465         p.stdin.write("Material \"matte\" "+link+"\n") 
  4466     else:
  4467         # Material
  4468         p.stdin.write(luxMaterial(mat))
  4469         link = luxProp(mat,"link","").get()
  4470         if kn!="": link = link.rstrip("\"")+":"+kn.strip(".:")+"\""
  4471         p.stdin.write(link+'\n')
  4472     p.stdin.write('TransformEnd\n')
  4473     # Shape
  4474     if(prev_sphere.get()=="true"):
  4475         p.stdin.write('Shape "sphere" "float radius" [1.0]\n')
  4476     elif (prev_plane.get()=="true"):
  4477         p.stdin.write('    Shape "trianglemesh" "integer indices" [ 0 1 2 0 2 3 ] "point P" [ 1.0 1.0 0.0 -1.0 1.0 0.0 -1.0 -1.0 -0.0 1.0 -1.0 -0.0 ] "float uv" [ 1.0 1.0     0.0 1.0     0.0 0.0       1.0 0.0 ]\n')
  4478     elif (prev_torus.get()=="true"):
  4479         p.stdin.write('Shape "torus" "float radius" [1.0]\n')
  4480     p.stdin.write('AttributeEnd\n')
  4481     # Checkerboard floor
  4482     if(prev_plane.get()=="false"):
  4483         p.stdin.write('AttributeBegin\nTransform [5.0 0.0 0.0 0.0  0.0 5.0 0.0 0.0  0.0 0.0 5.0 0.0  0.0 0.0 0.0 1.0]\n')
  4484         p.stdin.write('Texture "checks" "color" "checkerboard"')
  4485         p.stdin.write('"integer dimension" [2] "string aamode" ["supersample"] "color tex1" [0.9 0.9 0.9] "color tex2" [0.0 0.0 0.0]')
  4486         p.stdin.write('"string mapping" ["uv"] "float uscale" [36.8] "float vscale" [36.0]\n')
  4487         p.stdin.write('Material "matte" "texture Kd" ["checks"]\n')
  4488         p.stdin.write('Shape "loopsubdiv" "integer nlevels" [3] "bool dmnormalsmooth" ["true"] "bool dmsharpboundary" ["false"] ')
  4489         p.stdin.write('"integer indices" [ 0 1 2 0 2 3 1 0 4 1 4 5 5 4 6 5 6 7 ]')
  4490         p.stdin.write('"point P" [ 1.000000 1.000000 0.000000 -1.000000 1.000000 0.000000 -1.000000 -1.000000 0.000000 1.000000 -1.000000 0.000000 1.000000 3.000000 0.000000 -1.000000 3.000000 0.000000 1.000000 3.000000 2.000000 -1.000000 3.000000 2.000000')
  4491         p.stdin.write('] "normal N" [ 0.000000 0.000000 1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 1.000000 0.000000 -0.707083 0.707083 0.000000 -0.707083 0.707083 0.000000 -1.000000 0.000000 0.000000 -1.000000 0.000000')
  4492         p.stdin.write('] "float uv" [ 0.333334 0.000000 0.333334 0.333334 0.000000 0.333334 0.000000 0.000000 0.666667 0.000000 0.666667 0.333333 1.000000 0.000000 1.000000 0.333333 ]\n')
  4493         p.stdin.write('AttributeEnd\n')
  4494     # Lightsource
  4495     if(prev_plane.get()=="false"):
  4496         p.stdin.write('AttributeBegin\nTransform [1.0 0.0 0.0 0.0  0.0 1.0 0.0 0.0  0.0 0.0 1.0 0.0  1.0 -1.0 4.0 1.0]\n')
  4497     else:
  4498         p.stdin.write('AttributeBegin\nTransform [1.0 0.0 0.0 0.0  0.0 1.0 0.0 0.0  0.0 0.0 1.0 0.0  1.0 -4.0 1.0 1.0]\n')
  4499     area = luxProp(mat, kn+"prev_arealight", "false")
  4500     if(area.get() == "false"):
  4501         p.stdin.write('Texture "pL" "color" "blackbody" "float temperature" [6500.0]\n')
  4502         p.stdin.write('LightSource "point" "texture L" ["pL"]')
  4503     else:
  4504         p.stdin.write('ReverseOrientation\n')
  4505         p.stdin.write('AreaLightSource "area" "color L" [1.0 1.0 1.0]\n')
  4506         p.stdin.write('Shape "disk" "float radius" [1.0]\nAttributeEnd\n')
  4507     p.stdin.write('WorldEnd\n')
  4508     previewing = False
  4509 
  4510     data = p.communicate()[0]
  4511     p.stdin.close()
  4512     if(len(data) < thumbbuf): 
  4513         print "error on preview"
  4514         return
  4515     global previewCache
  4516     image = luxImage()
  4517     image.decodeLuxConsole(thumbres, thumbres, data)
  4518     previewCache[(mat.name+":"+kn).__hash__()] = image
  4519     Draw.Redraw()
  4520     Blender.Window.WaitCursor(False)
  4521 
  4522 def luxPreview(mat, name, defType=0, defEnabled=False, defLarge=False, texName=None, gui=None, level=0, color=None):
  4523     
  4524 
  4525     if gui:
  4526         kn = name
  4527         if texName: kn += ":"+texName
  4528         if kn != "": kn += "."
  4529         if(defEnabled == True):
  4530             showpreview = luxProp(mat, kn+"prev_show", "true")
  4531         else:
  4532             showpreview = luxProp(mat, kn+"prev_show", "false")
  4533         Draw.Toggle("P", evtLuxGui, gui.xmax, gui.y-gui.h, gui.h, gui.h, showpreview.get()=="true", "Preview", lambda e,v: showpreview.set(["false","true"][bool(v)]))
  4534         if showpreview.get()=="true": 
  4535             if(defLarge):
  4536                 large = luxProp(mat, kn+"prev_large", "true")
  4537             else:
  4538                 large = luxProp(mat, kn+"prev_large", "false")
  4539             voffset = -8
  4540             rr = 5.65 
  4541             if(large.get() == "true"):
  4542                 rr = 7
  4543                 voffset = 22
  4544             gui.newline()
  4545             r = gui.getRect(1.1, rr)
  4546             if(color != None):
  4547                 BGL.glColor3f(color[0],color[1],color[2]); BGL.glRectf(r[0]-110, r[1], 418, r[1]+128+voffset); BGL.glColor3f(0.9, 0.9, 0.9)
  4548             try: previewCache[(mat.name+":"+kn).__hash__()].draw(r[0]-82, r[1]+4)
  4549             except: pass
  4550 
  4551             prev_sphere = luxProp(mat, kn+"prev_sphere", "true")
  4552             prev_plane = luxProp(mat, kn+"prev_plane", "false")
  4553             prev_torus = luxProp(mat, kn+"prev_torus", "false")
  4554             if defType == 1:
  4555                 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
  4556                 prev_plane = luxProp(mat, kn+"prev_plane", "true")
  4557                 prev_torus = luxProp(mat, kn+"prev_torus", "false")
  4558             elif defType == 2:
  4559                 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
  4560                 prev_plane = luxProp(mat, kn+"prev_plane", "false")
  4561                 prev_torus = luxProp(mat, kn+"prev_torus", "true")
  4562 
  4563             # preview mode toggle buttons
  4564             Draw.Toggle("S", evtLuxGui, r[0]-108, r[1]+100+voffset, 22, 22, prev_sphere.get()=="true", "Draw Sphere", lambda e,v: Preview_Sphereset(mat, kn, ["false","true"][bool(v)]))
  4565             Draw.Toggle("P", evtLuxGui, r[0]-108, r[1]+74+voffset, 22, 22, prev_plane.get()=="true", "Draw 2D Plane", lambda e,v: Preview_Planeset(mat, kn, ["false","true"][bool(v)]))
  4566             Draw.Toggle("T", evtLuxGui, r[0]-108, r[1]+48+voffset, 22, 22, prev_torus.get()=="true", "Draw Torus", lambda e,v: Preview_Torusset(mat, kn, ["false","true"][bool(v)]))
  4567 
  4568             # Zoom toggle
  4569             zoom = luxProp(mat, kn+"prev_zoom", "false")
  4570             Draw.Toggle("Zoom", evtLuxGui, r[0]+66, r[1]+100+voffset, 50, 18, zoom.get()=="true", "Zoom", lambda e,v: zoom.set(["false","true"][bool(v)]))
  4571 
  4572             area = luxProp(mat, kn+"prev_arealight", "false")
  4573             Draw.Toggle("Area", evtLuxGui, r[0]+66, r[1]+5, 50, 18, area.get()=="true", "Area", lambda e,v: area.set(["false","true"][bool(v)]))
  4574 
  4575             # Object width
  4576             obwidth = luxProp(mat, kn+"prev_obwidth", 1.0)
  4577             Draw.Number("Width:", evtLuxGui, r[0]+66, r[1]+78+voffset, 129, 18, obwidth.get(), 0.001, 10, "The width of the preview object in blender/lux 1m units", lambda e,v: obwidth.set(v))
  4578 
  4579             # large/small size
  4580             Draw.Toggle("large", evtLuxGui, r[0]+200, r[1]+78+voffset, 88, 18, large.get()=="true", "Large", lambda e,v: large.set(["false","true"][bool(v)]))
  4581 
  4582             # Preview Quality
  4583             qs = ["low","medium","high","very high"]
  4584             scn = Scene.GetCurrent()
  4585             defprevmat = luxProp(scn, "defprevmat", "high")
  4586             quality = luxProp(mat, kn+"prev_quality", defprevmat.get())
  4587             luxOptionRect("quality", quality, qs, "  Quality", "select preview quality", gui, r[0]+200, r[1]+100+voffset, 88, 18)
  4588 
  4589             # Update preview
  4590             Draw.Button("Update Preview", evtLuxGui, r[0]+120, r[1]+5, 167, 18, "Update Material Preview", lambda e,v: Preview_Update(mat, kn, defLarge, defType, texName, name, level))
  4591 
  4592             # Reset depths after getRect()
  4593             gui.y -= 92+voffset
  4594             gui.y -= gui.h
  4595             gui.hmax = 18 + 4
  4596 
  4597 def luxMaterialBlock(name, luxname, key, mat, gui=None, level=0, str_opt=""):
  4598     global icon_mat, icon_matmix, icon_map3dparam
  4599     def c(t1, t2):
  4600         return (t1[0]+t2[0], t1[1]+t2[1])
  4601     str = ""
  4602     if key == "": keyname = kn = name
  4603     else: keyname = kn = "%s:%s"%(key, name)
  4604     if kn != "": kn += "."
  4605     if keyname == "": matname = mat.getName()
  4606     else: matname = "%s:%s"%(mat.getName(), keyname)
  4607 
  4608     if mat:
  4609         mattype = luxProp(mat, kn+"type", "matte")
  4610         # Set backwards compatibility of glossy material from plastic and substrate
  4611         if(mattype.get() == "substrate" or mattype.get() == "plastic"):
  4612             mattype.set("glossy")
  4613 
  4614         # this is reverse order than in shown in the dropdown list
  4615         materials = ["null","mix","mirror","shinymetal","metal","mattetranslucent","matte","glossy","roughglass","glass","carpaint"]
  4616         
  4617         if level == 0: materials = ["portal","light","boundvolume"]+materials
  4618         if gui:
  4619             icon = icon_mat
  4620             if mattype.get() == "mix": icon = icon_matmix
  4621             if level == 0: gui.newline("Material type:", 12, level, icon, [0.75,0.5,0.25])
  4622             else: gui.newline(name+":", 12, level, icon, scalelist([0.75,0.6,0.25],2.0/(level+2)))
  4623 
  4624 
  4625         link = luxOption("type", mattype, materials, "  TYPE", "select material type", gui)
  4626         showadvanced = luxProp(mat, kn+"showadvanced", "false")
  4627         luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
  4628         showhelp = luxProp(mat, kn+"showhelp", "false")
  4629         luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
  4630 
  4631         # show copy/paste menu button
  4632         if gui: Draw.PushButton(">", evtLuxGui, gui.xmax+gui.h, gui.y-gui.h, gui.h, gui.h, "Menu", lambda e,v: showMatTexMenu(mat,keyname,False))
  4633 
  4634         # Draw Material preview option
  4635         showmatprev = False
  4636         if level == 0:
  4637             showmatprev = True
  4638         if gui: luxPreview(mat, keyname, 0, showmatprev, True, None, gui, level, [0.746, 0.625, 0.5])
  4639 
  4640 
  4641         if gui: gui.newline()
  4642         has_object_options   = 0 # disable object options by default
  4643         has_bump_options     = 0 # disable bump mapping options by default
  4644         has_emission_options = 0 # disable emission options by default
  4645         has_compositing_options = 0 # disable compositing options by default
  4646 
  4647         if mattype.get() == "mix":
  4648             (str,link) = c((str,link), luxFloatTexture("amount", keyname, 0.5, 0.0, 1.0, "amount", "The degree of mix between the two materials", mat, gui, level+1))
  4649             (str,link) = c((str,link), luxMaterialBlock("mat1", "namedmaterial1", keyname, mat, gui, level+1))
  4650             (str,link) = c((str,link), luxMaterialBlock("mat2", "namedmaterial2", keyname, mat, gui, level+1))
  4651             has_bump_options = 0
  4652             has_object_options = 1
  4653             has_emission_options = 1
  4654             has_compositing_options = 0
  4655 
  4656         if mattype.get() == "light":
  4657             lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
  4658             if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
  4659                 link = "LightGroup \"%s\"\n"%lightgroup.get()
  4660             link += "AreaLightSource \"area\""
  4661             (str,link) = c((str,link), luxLight("", kn, mat, gui, level))
  4662             has_bump_options = 0
  4663             has_object_options = 1
  4664             has_emission_options = 0
  4665             has_compositing_options = 1
  4666 
  4667         if mattype.get() == "boundvolume":
  4668             link = ""
  4669             voltype = luxProp(mat, kn+"vol.type", "homogeneous")
  4670             vols = ["homogeneous", "exponential", "cloud"]
  4671             vollink = luxOption("type", voltype, vols, "type", "", gui)
  4672             if voltype.get() == "homogeneous":
  4673                 link = "Volume \"homogeneous\""
  4674             if voltype.get() == "exponential":
  4675                 link = "Volume \"exponential\""
  4676             if voltype.get() == "cloud":
  4677                 link = "Volume \"cloud\""
  4678 
  4679             if gui: gui.newline("absorption:", 0, level+1)
  4680             link += luxRGB("sigma_a", luxProp(mat, kn+"vol.sig_a", "1.0 1.0 1.0"), 1.0, "sigma_a", "The absorption cross section", gui)
  4681             if gui: gui.newline("scattering:", 0, level+1)
  4682             link += luxRGB("sigma_s", luxProp(mat, kn+"vol.sig_b", "0.0 0.0 0.0"), 1.0, "sigma_b", "The scattering cross section", gui)
  4683             if gui: gui.newline("emission:", 0, level+1)
  4684             link += luxRGB("Le", luxProp(mat, kn+"vol.le", "0.0 0.0 0.0"), 1.0, "Le", "The volume's emission spectrum", gui)
  4685             if gui: gui.newline("assymetry:", 0, level+1)
  4686             link += luxFloat("g", luxProp(mat, kn+"vol.g", 0.0), 0.0, 100.0, "g", "The phase function asymmetry parameter", gui)
  4687 
  4688             if voltype.get() == "exponential":
  4689                 if gui: gui.newline("form:", 0, level+1)
  4690                 link += luxFloat("a", luxProp(mat, kn+"vol.a", 1.0), 0.0, 100.0, "a/scale", "exponential::a parameter in the ae^{-bh} formula", gui)
  4691                 link += luxFloat("b", luxProp(mat, kn+"vol.b", 2.0), 0.0, 100.0, "b/falloff", "exponential::b parameter in the ae^{-bh} formula", gui)
  4692                 if gui: gui.newline("updir:", 0, level+1)
  4693                 link += luxVector("updir", luxProp(mat, kn+"vol.updir", "0 0 1"), -1.0, 1.0, "updir", "Up direction vector", gui, 2.0)
  4694 
  4695             if voltype.get() == "cloud":
  4696                 if gui: gui.newline("cloud:", 0, level+1)
  4697                 link += luxFloat("radius", luxProp(mat, kn+"vol.radius", 0.5), 0.01, 2.0, "radius", "Radius of hemisphere used as basis for cloud shape", gui)
  4698                 link += luxFloat("noisescale", luxProp(mat, kn+"vol.noisescale", 0.3), 0.1, 2.0, "noisesize", "Size of cloud noise", gui)
  4699                 link += luxFloat("turbulence", luxProp(mat, kn+"vol.turbulence", 0.5), 0.0, 3.0, "turbulence", "Extent to which the noise effects the cloud shape", gui)
  4700                 link += luxFloat("noiseoffset", luxProp(mat, kn+"vol.noiseoffset", 0.0), 0.0, 1000.0, "noiseoffset", "Useful for creating unique clouds", gui )
  4701                 link += luxInt("octaves", luxProp(mat, kn+"vol.octaves", 3), 1, 8, "octaves", "Sets the amount of detail for the noise", gui )
  4702                 link += luxFloat("omega", luxProp(mat, kn+"vol.omega", 0.75), 0.1, 1.0, "omega", "Sets the scale difference of each successive octave", gui )
  4703                 link += luxFloat("sharpness", luxProp(mat, kn+"vol.sharpness", 6.0), 0.2, 10.0, "sharpness", "Sets the sharpness of the noise", gui)
  4704                 link += luxFloat("variability", luxProp(mat, kn+"vol.variability", 0.9), 0.0, 1.0, "mask amount", "Noise mask amount. 0 means noise everywhere, 1 means only some spots have noise.", gui)
  4705                 link += luxFloat("baseflatness", luxProp(mat, kn+"vol.baseflatness", 0.8), 0.0, 1.0, "baseflatness", "Flatness of the cloud's base. (0.0 makes a round cloud.)", gui)
  4706                 link += luxInt("spheres", luxProp(mat, kn+"vol.spheres", 2000), 0, 10000, "spheres", "Number of small spheres for cumulus shape. 0 is non-cumulus.", gui )
  4707                 link += luxFloat("spheresize", luxProp(mat, kn+"vol.spheresize", 0.15), 0.05, 0.55, "spheresize", "Size of cumulus spheres", gui)
  4708  
  4709             link += str_opt
  4710 
  4711             has_bump_options = 0
  4712             has_object_options = 0
  4713             has_emission_options = 0
  4714 
  4715             return (str, link)
  4716 
  4717         if mattype.get() == "carpaint":
  4718             if gui: gui.newline("Preset:", 0, level+1)
  4719             carname = luxProp(mat, kn+"carpaint.name", "Custom")
  4720             cars = ["Custom","ford f8","polaris silber","opel titan","bmw339","2k acrylack","white","blue","blue matte"]
  4721             carlink = luxOption("name", carname, cars, "name", "", gui)
  4722             if carname.get() == "Custom":
  4723                 (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
  4724                 (str,link) = c((str,link), luxSpectrumTexture("Ks1", keyname, "1.0 1.0 1.0", 1.0, "specular1", "", mat, gui, level+1))
  4725                 (str,link) = c((str,link), luxSpectrumTexture("Ks2", keyname, "1.0 1.0 1.0", 1.0, "specular2", "", mat, gui, level+1))
  4726                 (str,link) = c((str,link), luxSpectrumTexture("Ks3", keyname, "1.0 1.0 1.0", 1.0, "specular3", "", mat, gui, level+1))
  4727                 (str,link) = c((str,link), luxFloatTexture("R1", keyname, 1.0, 0.0, 1.0, "R1", "", mat, gui, level+1))
  4728                 (str,link) = c((str,link), luxFloatTexture("R2", keyname, 1.0, 0.0, 1.0, "R2", "", mat, gui, level+1))
  4729                 (str,link) = c((str,link), luxFloatTexture("R3", keyname, 1.0, 0.0, 1.0, "R3", "", mat, gui, level+1))
  4730                 (str,link) = c((str,link), luxFloatTexture("M1", keyname, 1.0, 0.0, 1.0, "M1", "", mat, gui, level+1))
  4731                 (str,link) = c((str,link), luxFloatTexture("M2", keyname, 1.0, 0.0, 1.0, "M2", "", mat, gui, level+1))
  4732                 (str,link) = c((str,link), luxFloatTexture("M3", keyname, 1.0, 0.0, 1.0, "M3", "", mat, gui, level+1))
  4733             else: link += carlink
  4734             absorption = luxProp(mat, keyname+".useabsorption", "false")
  4735             luxCollapse("absorption", absorption, "Absorption", "Enable Coating Absorption", gui, 2.0)
  4736             if absorption.get() == "true":
  4737                 (str,link) = c((str,link), luxSpectrumTexture("Ka", keyname, "0.2 0.2 0.2", 1.0, "absorption", "", mat, gui, level+1))
  4738                 (str,link) = c((str,link), luxFloatTexture("d", keyname, 5.0, 0.0, 15.0, "depth", "", mat, gui, level+1))
  4739             has_bump_options = 1
  4740             has_object_options = 1
  4741             has_emission_options = 1
  4742             has_compositing_options = 1
  4743         
  4744         if mattype.get() == "glass":
  4745             (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
  4746             (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
  4747             (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 6.0, "IOR", "", mat, gui, level+1))
  4748             architectural = luxProp(mat, keyname+".architectural", "false")
  4749             link += luxBool("architectural", architectural, "architectural", "Enable architectural glass", gui, 2.0)
  4750             if architectural.get() == "false":
  4751                 chromadisp = luxProp(mat, keyname+".chromadisp", "false")
  4752                 luxCollapse("chromadisp", chromadisp, "Dispersive Refraction", "Enable Chromatic Dispersion", gui, 2.0)
  4753                 if chromadisp.get() == "true":
  4754                     (str,link) = c((str,link), luxCauchyBFloatTexture("cauchyb", keyname, 0.0, 0.0, 1.0, "cauchyb", "", mat, gui, level+1))
  4755                 thinfilm = luxProp(mat, keyname+".thinfilm", "false")
  4756                 luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
  4757                 if thinfilm.get() == "true":
  4758                     (str,link) = c((str,link), luxFloatSliderTexture("film", keyname, 200.0, 1.0, 1500.0, "film", "thickness of film coating in nanometers", mat, gui, level+1))
  4759                     (str,link) = c((str,link), luxIORFloatTexture("filmindex", keyname, 1.5, 1.0, 6.0, "film IOR", "film coating index of refraction", mat, gui, level+1))
  4760             has_bump_options = 1
  4761             has_object_options = 1
  4762             has_emission_options = 1
  4763             has_compositing_options = 1
  4764             
  4765         if mattype.get() == "matte":
  4766             orennayar = luxProp(mat, keyname+".orennayar", "false")
  4767             (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
  4768             luxCollapse("orennayar", orennayar, "Oren-Nayar", "Enable Oren-Nayar BRDF", gui, 2.0)
  4769             if orennayar.get() == "true":
  4770                 (str,link) = c((str,link), luxFloatTexture("sigma", keyname, 0.0, 0.0, 100.0, "sigma", "sigma value for Oren-Nayar BRDF", mat, gui, level+1))
  4771             has_bump_options = 1
  4772             has_object_options = 1
  4773             has_emission_options = 1
  4774             has_compositing_options = 1
  4775         
  4776         if mattype.get() == "mattetranslucent":
  4777             orennayar = luxProp(mat, keyname+".orennayar", "false")
  4778             (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
  4779             (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
  4780             luxCollapse("orennayar", orennayar, "Oren-Nayar", "Enable Oren-Nayar BRDF", gui, 2.0)
  4781             if orennayar.get() == "true":
  4782                 (str,link) = c((str,link), luxFloatTexture("sigma", keyname, 0.0, 0.0, 100.0, "sigma", "", mat, gui, level+1))
  4783             has_bump_options = 1
  4784             has_object_options = 1
  4785             has_emission_options = 1
  4786             has_compositing_options = 1
  4787         
  4788         if mattype.get() == "metal":
  4789             if gui: gui.newline("name:", 0, level+1)
  4790             metalname = luxProp(mat, kn+"metal.name", "")
  4791             metals = ["aluminium","amorphous carbon","silver","gold","copper"]
  4792 
  4793             if not(metalname.get() in metals):
  4794                 metals.append(metalname.get())
  4795             metallink = luxOption("name", metalname, metals, "name", "", gui, 1.88)
  4796             if gui: Draw.Button("...", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, "click to select a nk file",lambda e,v:Window.FileSelector(lambda s:metalname.set(s), "Select nk file"))
  4797             link += luxstr(metallink)
  4798             anisotropic = luxProp(mat, kn+"metal.anisotropic", "false")
  4799             if gui:
  4800                 gui.newline("")
  4801                 Draw.Toggle("A", evtLuxGui, gui.x-gui.h, gui.y-gui.h, gui.h, gui.h, anisotropic.get()=="true", "anisotropic roughness", lambda e,v:anisotropic.set(["false","true"][bool(v)]))
  4802             if anisotropic.get()=="true":
  4803                 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
  4804                 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
  4805             else:
  4806                 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
  4807                 (str,link) = c((str,link), (s, l))
  4808                 link += l.replace("uroughness", "vroughness", 1)
  4809                 
  4810             has_bump_options = 1
  4811             has_object_options = 1
  4812             has_emission_options = 1
  4813             has_compositing_options = 1
  4814             
  4815         if mattype.get() == "mirror":
  4816             (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
  4817             thinfilm = luxProp(mat, keyname+".thinfilm", "false")
  4818             luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
  4819             if thinfilm.get() == "true":
  4820                 (str,link) = c((str,link), luxFloatSliderTexture("film", keyname, 200.0, 1.0, 1500.0, "film", "thickness of film coating in nanometers", mat, gui, level+1))
  4821                 (str,link) = c((str,link), luxIORFloatTexture("filmindex", keyname, 1.5, 1.0, 6.0, "film IOR", "film coating index of refraction", mat, gui, level+1))
  4822 
  4823             has_bump_options = 1
  4824             has_object_options = 1
  4825             has_emission_options = 1
  4826             has_compositing_options = 1
  4827             
  4828         if mattype.get() == "roughglass":
  4829             (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
  4830             (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
  4831             anisotropic = luxProp(mat, kn+"roughglass.anisotropic", "false")
  4832             if gui:
  4833                 gui.newline("")
  4834                 Draw.Toggle("A", evtLuxGui, gui.x-gui.h, gui.y-gui.h, gui.h, gui.h, anisotropic.get()=="true", "anisotropic roughness", lambda e,v:anisotropic.set(["false","true"][bool(v)]))
  4835             if anisotropic.get()=="true":
  4836                 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
  4837                 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
  4838             else:
  4839                 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
  4840                 (str,link) = c((str,link), (s, l))
  4841                 link += l.replace("uroughness", "vroughness", 1)
  4842             (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 6.0, "IOR", "", mat, gui, level+1))
  4843             chromadisp = luxProp(mat, keyname+".chromadisp", "false")
  4844             luxCollapse("chromadisp", chromadisp, "Dispersive Refraction", "Enable Chromatic Dispersion", gui, 2.0)
  4845             if chromadisp.get() == "true":
  4846                 (str,link) = c((str,link), luxCauchyBFloatTexture("cauchyb", keyname, 0.0, 0.0, 1.0, "cauchyb", "", mat, gui, level+1))
  4847             has_bump_options = 1
  4848             has_object_options = 1
  4849             has_emission_options = 1
  4850             has_compositing_options = 1
  4851             
  4852         if mattype.get() == "shinymetal":
  4853             (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
  4854             (str,link) = c((str,link), luxSpectrumTexture("Ks", keyname, "1.0 1.0 1.0", 1.0, "specular", "", mat, gui, level+1))
  4855             anisotropic = luxProp(mat, kn+"shinymetal.anisotropic", "false")
  4856             if gui:
  4857                 gui.newline("")
  4858                 Draw.Toggle("A", evtLuxGui, gui.x-gui.h, gui.y-gui.h, gui.h, gui.h, anisotropic.get()=="true", "anisotropic roughness", lambda e,v:anisotropic.set(["false","true"][bool(v)]))
  4859             if anisotropic.get()=="true":
  4860                 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
  4861                 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
  4862             else:
  4863                 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
  4864                 (str,link) = c((str,link), (s, l))
  4865                 link += l.replace("uroughness", "vroughness", 1)
  4866 
  4867             thinfilm = luxProp(mat, keyname+".thinfilm", "false")
  4868             luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
  4869             if thinfilm.get() == "true":
  4870                 (str,link) = c((str,link), luxFloatSliderTexture("film", keyname, 200.0, 1.0, 1500.0, "film", "thickness of film coating in nanometers", mat, gui, level+1))
  4871                 (str,link) = c((str,link), luxIORFloatTexture("filmindex", keyname, 1.5, 1.0, 6.0, "film IOR", "film coating index of refraction", mat, gui, level+1))
  4872 
  4873             has_bump_options = 1
  4874             has_object_options = 1
  4875             has_emission_options = 1
  4876             has_compositing_options = 1
  4877             
  4878         if mattype.get() == "glossy":
  4879             (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
  4880             useior = luxProp(mat, keyname+".useior", "false")
  4881             if gui:
  4882                 gui.newline("")
  4883                 Draw.Toggle("I", evtLuxGui, gui.x-gui.h, gui.y-gui.h, gui.h, gui.h, useior.get()=="true", "Use IOR/Reflective index input", lambda e,v:useior.set(["false","true"][bool(v)]))
  4884             if useior.get() == "true":
  4885                 (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 50.0, "IOR", "", mat, gui, level+1))
  4886                 link += " \"color Ks\" [1.0 1.0 1.0]"    
  4887             else:
  4888                 (str,link) = c((str,link), luxSpectrumTexture("Ks", keyname, "1.0 1.0 1.0", 1.0, "specular", "", mat, gui, level+1))
  4889                 link += " \"float index\" [0.0]"    
  4890             anisotropic = luxProp(mat, kn+"glossy.anisotropic", "false")
  4891             if gui:
  4892                 gui.newline("")
  4893                 Draw.Toggle("A", evtLuxGui, gui.x-gui.h, gui.y-gui.h, gui.h, gui.h, anisotropic.get()=="true", "anisotropic roughness", lambda e,v:anisotropic.set(["false","true"][bool(v)]))
  4894             if anisotropic.get()=="true":
  4895                 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
  4896                 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
  4897             else:
  4898                 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
  4899                 (str,link) = c((str,link), (s, l))
  4900                 link += l.replace("uroughness", "vroughness", 1)
  4901 
  4902             absorption = luxProp(mat, keyname+".useabsorption", "false")
  4903             luxCollapse("absorption", absorption, "Absorption", "Enable Coating Absorption", gui, 2.0)
  4904             if absorption.get() == "true":
  4905                 (str,link) = c((str,link), luxSpectrumTexture("Ka", keyname, "0.2 0.2 0.2", 1.0, "absorption", "", mat, gui, level+1))
  4906                 (str,link) = c((str,link), luxFloatTexture("d", keyname, 0.15, 0.0, 15.0, "depth", "", mat, gui, level+1))
  4907             has_bump_options = 1
  4908             has_object_options = 1
  4909             has_emission_options = 1
  4910             has_compositing_options = 1
  4911             
  4912         if mattype.get() == 'null':
  4913         	has_emission_options = 1
  4914 
  4915         # Bump mapping options (common)
  4916         if (has_bump_options == 1):
  4917             usebump = luxProp(mat, keyname+".usebump", "false")
  4918             luxCollapse("usebump", usebump, "Bump Map", "Enable Bump Mapping options", gui, 2.0)
  4919             if usebump.get() == "true":
  4920                 (str,link) = c((str,link), luxFloatTexture("bumpmap", keyname, 0.0, -1.0, 1.0, "bumpmap", "", mat, gui, level+1))
  4921 
  4922         # emission options (common)
  4923         if (level == 0):
  4924             if (has_emission_options == 1):
  4925                 if gui: gui.newline("", 2, level, None, [0.6,0.6,0.4])
  4926                 useemission = luxProp(mat, "emission", "false")
  4927                 luxCollapse("useemission", useemission, "Emission", "Enable emission options", gui, 2.0)
  4928                 if useemission.get() == "true":
  4929                     # emission GUI is here but lux export will be done later 
  4930                     luxLight("", "", mat, gui, level)
  4931             else: luxProp(mat, "emission", "false").set("false") # prevent from exporting later
  4932 
  4933 
  4934         # Compositing options (common)
  4935         # Note - currently only display options when using distributedpath integrator
  4936         integratortype = luxProp(Scene.GetCurrent(), "sintegrator.type", "bidirectional")
  4937         if (integratortype.get() == "distributedpath" and level == 0):
  4938             if (has_compositing_options == 1):
  4939                 if gui: gui.newline("", 2, level, None, [0.4,0.4,0.6])
  4940                 usecompo = luxProp(mat, "compo", "false")
  4941                 luxCollapse("compo", usecompo, "Compositing", "Enable Compositing options", gui, 2.0)
  4942                 if usecompo.get() == "true":
  4943                     if gui: gui.newline("", 2, level, None, [0.35,0.35,0.55])
  4944                     usecompoviz = luxProp(mat, "compo_viz", "false")
  4945                     luxCollapse("compo_viz", usecompoviz, "Visibility", "Enable Visibility Compositing options", gui, 2.0)
  4946                     if usecompoviz.get() == "true":
  4947                         if gui: gui.newline("View", 2, level, None, [0.35,0.35,0.55])
  4948                         compovizmat = luxProp(mat, "compo_viz_mat", "true")
  4949                         link += luxBool("compo_visible_material", compovizmat, "Material", "Enable View Visibility of Material", gui, 1.0)
  4950                         compovizemi = luxProp(mat, "compo_viz_emi", "true")
  4951                         link += luxBool("compo_visible_emission", compovizemi, "Emission", "Enable View Visibility of Emission", gui, 1.0)
  4952                         
  4953                         if gui: gui.newline("Indirect", 2, level, None, [0.35,0.35,0.55])
  4954                         compovizmati = luxProp(mat, "compo_viz_mati", "true")
  4955                         link += luxBool("compo_visible_indirect_material", compovizmati, "Material", "Enable InDirect Visibility of Material", gui, 1.0)
  4956                         compovizemii = luxProp(mat, "compo_viz_emii", "true")
  4957                         link += luxBool("compo_visible_indirect_emission", compovizemii, "Emission", "Enable InDirect Visibility of Emission", gui, 1.0)
  4958                     
  4959                     if gui: gui.newline("", 2, level, None, [0.4,0.4,0.6])
  4960                     overridealpha = luxProp(mat, "compo_o_alpha", "false")
  4961                     link += luxCollapse("compo_override_alpha", overridealpha, "Override Alpha", "Enable Manual control of alpha value", gui, 2.0)
  4962                     if overridealpha.get() == "true":
  4963                         if gui: gui.newline("Alpha", 2, level, None, [0.4,0.4,0.6])
  4964                         link += luxFloat("compo_override_alpha_value", luxProp(mat, "compo_o_alpha_v", 0.0), 0.0, 1.0, "Alpha", "Alpha Value", gui, 2.0, 1)
  4965                     usecolorkey = luxProp(mat, "compo_usekey", "false")
  4966                     if gui: gui.newline("", 2, level, None, [0.35,0.35,0.55])
  4967                     link += luxCollapse("compo_use_key", usecolorkey, "Chroma Key", "Enable Chroma Object key", gui, 2.0)
  4968                     if usecolorkey.get() == "true":
  4969                         if gui: gui.newline("Key", 2, level, None, [0.35,0.35,0.55])
  4970                         link += luxRGB("compo_key_color", luxProp(mat, "compo_key_color", "0.0 0.0 1.0"), 1.0, "key", "", gui, 2.0)
  4971 
  4972         # transformation options (common)
  4973         if (level == 0) and mattype.get() not in ['portal', 'null']:
  4974             if gui: gui.newline("", 2, level, None, [0.6,0.6,0.4])
  4975             usetransformation = luxProp(mat, "transformation", "false")
  4976             luxCollapse("usetransformation", usetransformation, "Texture Transformation", "Enable transformation option", gui, 2.0)
  4977             if usetransformation.get() == "true":
  4978                 scale = luxProp(mat, "3dscale", 1.0)
  4979                 rotate = luxProp(mat, "3drotate", "0 0 0")
  4980                 translate = luxProp(mat, "3dtranslate", "0 0 0")
  4981                 if gui:
  4982                     gui.newline("scale:", -2, level, icon_map3dparam)
  4983                     luxVectorUniform("scale", scale, 0.001, 1000.0, "scale", "scale-vector", gui, 2.0)
  4984                     gui.newline("rot:", -2, level, icon_map3dparam)
  4985                     luxVector("rotate", rotate, -360.0, 360.0, "rotate", "rotate-vector", gui, 2.0)
  4986                     gui.newline("move:", -2, level, icon_map3dparam)
  4987                     luxVector("translate", translate, -1000.0, 1000.0, "move", "translate-vector", gui, 2.0)
  4988                 str = ("TransformBegin\n\tScale %f %f %f\n"%( 1.0/scale.getVector()[0],1.0/scale.getVector()[1],1.0/scale.getVector()[2] ))+("\tRotate %f 1 0 0\n\tRotate %f 0 1 0\n\tRotate %f 0 0 1\n"%rotate.getVector())+("\tTranslate %f %f %f\n"%translate.getVector()) + str + "TransformEnd\n"
  4989 
  4990         # Object options (common)
  4991         if (level == 0) and (has_object_options == 1):
  4992             if gui: gui.newline("Mesh:", 2, level, icon, [0.6,0.6,0.4])
  4993             usesubdiv = luxProp(mat, "subdiv", "false")
  4994             luxBool("usesubdiv", usesubdiv, "Subdivision", "Enable Loop Subdivision options", gui, 1.0)
  4995             usedisp = luxProp(mat, "dispmap", "false")
  4996             luxBool("usedisp", usedisp, "Displacement Map", "Enable Displacement mapping options", gui, 1.0)
  4997             if usesubdiv.get() == "true" or usedisp.get() == "true":
  4998                 luxInt("sublevels", luxProp(mat, "sublevels", 2), 0, 12, "sublevels", "The number of levels of object subdivision", gui, 2.0)
  4999                 sharpbound = luxProp(mat, "sharpbound", "false")
  5000                 luxBool("sharpbound", sharpbound, "Sharpen Bounds", "Sharpen boundaries during subdivision", gui, 1.0)
  5001                 nsmooth = luxProp(mat, "nsmooth", "true")
  5002                 luxBool("nsmooth", nsmooth, "Smooth", "Smooth faces during subdivision", gui, 1.0)
  5003             if usedisp.get() == "true":
  5004                 (str,ll) = c((str,link), luxDispFloatTexture("dispmap", keyname, 0.1, -10, 10.0, "dispmap", "Displacement Mapping amount", mat, gui, level+1))
  5005                 luxFloat("sdoffset",  luxProp(mat, "sdoffset", 0.0), 0.0, 1.0, "Offset", "Offset for displacement map", gui, 2.0)
  5006                 usesubdiv.set("true");
  5007 
  5008         if mattype.get() == "light":
  5009             return (str, link)
  5010 
  5011         str += "MakeNamedMaterial \"%s\"%s\n"%(matname, link)
  5012     return (str, " \"string %s\" [\"%s\"]"%(luxname, matname))
  5013 
  5014 
  5015 def luxMaterial(mat, gui=None):
  5016     str = ""
  5017     if mat:
  5018         if luxProp(mat, "type", "").get()=="": # lux material not defined yet
  5019             print "Blender material \"%s\" has no lux material definition, converting..."%(mat.getName())
  5020             try:
  5021                 convertMaterial(mat) # try converting the blender material to a lux material
  5022             except: pass
  5023         (str, link) = luxMaterialBlock("", "", "", mat, gui, 0)
  5024         if luxProp(mat, "type", "matte").get() != "light":
  5025             link = "NamedMaterial \"%s\""%(mat.getName())
  5026         # export emission options (no gui)
  5027         useemission = luxProp(mat, "emission", "false")
  5028         if useemission.get() == "true":
  5029             lightgroup = luxProp(mat, "light.lightgroup", "default")
  5030             if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
  5031                 link += "\n\tLightGroup \"%s\"\n"%lightgroup.get()
  5032             
  5033             (estr, elink) = luxLight("", "", mat, None, 0)
  5034             str += estr
  5035             link += "\n\tAreaLightSource \"area\" "+elink 
  5036             
  5037         luxProp(mat, "link", "").set("".join(link))
  5038         
  5039     return str
  5040         
  5041 
  5042 def luxVolume(mat, gui=None):
  5043     str = ""
  5044     if mat:
  5045         (str, link) = luxMaterialBlock("", "", "", mat, gui, 0)
  5046         luxProp(mat, "link", "").set("".join(link))
  5047     return str
  5048 
  5049 runRenderAfterExport = None
  5050 def CBluxExport(default, run):
  5051     global runRenderAfterExport
  5052     runRenderAfterExport = run
  5053     if default:
  5054         datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
  5055         if datadir=="": datadir = Blender.Get("datadir")
  5056         filename = datadir + os.sep + "default.lxs"
  5057         save_still(filename)
  5058     else:
  5059         Window.FileSelector(save_still, "Export", sys.makename(Blender.Get("filename"), ".lxs"))
  5060 
  5061 
  5062 def CBluxAnimExport(default, run, fileselect=True):
  5063     if default:
  5064         datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
  5065         if datadir=="": datadir = Blender.Get("datadir")
  5066         filename = datadir + os.sep + "default.lxs"
  5067         save_anim(filename)
  5068     else:
  5069         if fileselect:
  5070             Window.FileSelector(save_anim, "Export", sys.makename(Blender.Get("filename"), ".lxs"))
  5071         else:
  5072             datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
  5073             if datadir=="": datadir = Blender.Get("datadir")
  5074             filename = sys.makename(Blender.Get("filename") , ".lxs")
  5075             save_anim(filename)
  5076 
  5077 
  5078 # convert a Blender material to lux material
  5079 def convertMaterial(mat):
  5080     def dot(str):
  5081         if str != "": return str+"."
  5082         return str
  5083     def ddot(str):
  5084         if str != "": return str+":"
  5085         return str
  5086     def mapConstDict(value, constant_dict, lux_dict, default=None):
  5087         for k,v in constant_dict.items():
  5088             if (v == value) and (lux_dict.has_key(k)):
  5089                 return lux_dict[k]
  5090         return default
  5091 
  5092     def convertMapping(name, tex):
  5093         if tex.texco == Texture.TexCo["UV"]:
  5094             luxProp(mat, dot(name)+"mapping","").set("uv")
  5095             luxProp(mat, dot(name)+"uscale", 1.0).set(tex.size[0])
  5096             luxProp(mat, dot(name)+"vscale", 1.0).set(-tex.size[1])
  5097             luxProp(mat, dot(name)+"udelta", 0.0).set(tex.ofs[0]+0.5*(1.0-tex.size[0]))
  5098             luxProp(mat, dot(name)+"vdelta", 0.0).set(-tex.ofs[1]-0.5*(1.0-tex.size[1]))
  5099             if tex.mapping != Texture.Mappings["FLAT"]:
  5100                 print "Material Conversion Warning: for UV-texture-input only FLAT mapping is supported\n" 
  5101         else:
  5102             if tex.mapping == Texture.Mappings["FLAT"]:
  5103                 luxProp(mat, dot(name)+"mapping","").set("planar")
  5104             elif tex.mapping == Texture.Mappings["TUBE"]:
  5105                 luxProp(mat, dot(name)+"mapping","").set("cylindrical")
  5106             elif tex.mapping == Texture.Mappings["SPHERE"]:
  5107                 luxProp(mat, dot(name)+"mapping","").set("spherical")
  5108             else: luxProp(mat, dot(name)+"mapping","").set("planar")
  5109         luxProp(mat, dot(name)+"3dscale", "1.0 1.0 1.0").setVector((1.0/tex.size[0], 1.0/tex.size[1], 1.0/tex.size[2]))
  5110         luxProp(mat, dot(name)+"3dtranslate", "0.0 0.0 0.0").setVector((-tex.ofs[0], -tex.ofs[1], -tex.ofs[2]))
  5111 
  5112     def convertColorband(colorband):
  5113         # colorbands are not supported in lux - so lets extract a average low-side and high-side color
  5114         cb = [colorband[0]] + colorband[:] + [colorband[-1]]
  5115         cb[0][4], cb[-1][4] = 0.0, 1.0
  5116         low, high = [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]
  5117         for i in range(1, len(cb)):
  5118             for c in range(4):
  5119                 low[c] += (cb[i-1][c]*(1.0-cb[i-1][4]) + cb[i][c]*(1.0-cb[i][4])) * (cb[i][4]-cb[i-1][4])
  5120                 high[c] += (cb[i-1][c]*cb[i-1][4] + cb[i][c]*cb[i][4]) * (cb[i][4]-cb[i-1][4])
  5121         return low, high
  5122 
  5123     def createLuxTexture(name, tex):
  5124         texture = tex.tex
  5125         convertMapping(name, tex)
  5126         if (texture.type == Texture.Types["IMAGE"]) and (texture.image) and (texture.image.filename!=""):
  5127             luxProp(mat, dot(name)+"texture", "").set("imagemap")
  5128             luxProp(mat, dot(name)+"filename", "").set(texture.image.filename)
  5129             luxProp(mat, dot(name)+"wrap", "").set(mapConstDict(texture.extend, Texture.ExtendModes, {"REPEAT":"repeat", "EXTEND":"clamp", "CLIP":"black"}, ""))
  5130         else:
  5131             if tex.texco != Texture.TexCo["GLOB"]:
  5132                 print "Material Conversion Warning: procedural textures supports global mapping only\n"
  5133             noiseDict = {"BLENDER":"blender_original", "CELLNOISE":"cell_noise", "IMPROVEDPERLIN":"improved_perlin", "PERLIN":"original_perlin", "VORONOICRACKLE":"voronoi_crackle", "VORONOIF1":"voronoi_f1", "VORONOIF2":"voronoi_f2", "VORONOIF2F1":"voronoi_f2f1", "VORONOIF3":"voronoi_f3", "VORONOIF4":"voronoi_f4"}
  5134             luxProp(mat, dot(name)+"bright", 1.0).set(texture.brightness)
  5135             luxProp(mat, dot(name)+"contrast", 1.0).set(texture.contrast)
  5136             if texture.type == Texture.Types["CLOUDS"]:
  5137                 luxProp(mat, dot(name)+"texture", "").set("blender_clouds")
  5138                 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"CLD_DEFAULT":"default", "CLD_COLOR":"color"}, ""))
  5139                 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
  5140                 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
  5141                 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
  5142                 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
  5143             elif texture.type == Texture.Types["WOOD"]:
  5144                 luxProp(mat, dot(name)+"texture", "").set("blender_wood")
  5145                 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"WOD_BANDS":"bands", "WOD_RINGS":"rings", "WOD_BANDNOISE":"bandnoise", "WOD_RINGNOISE":"ringnoise"}, ""))
  5146                 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, {"SINE":"sin", "SAW":"saw", "TRI":"tri"}, ""))
  5147                 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
  5148                 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
  5149                 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
  5150                 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
  5151             elif texture.type == Texture.Types["MUSGRAVE"]:
  5152                 luxProp(mat, dot(name)+"texture", "").set("blender_musgrave")
  5153                 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"MUS_MFRACTAL":"multifractal", "MUS_RIDGEDMF":"ridged_multifractal", "MUS_HYBRIDMF":"hybrid_multifractal", "MUS_HTERRAIN":"hetero_terrain", "MUS_FBM":"fbm"}, ""))
  5154                 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
  5155                 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
  5156                 # bug in blender python API: value of "hFracDim" is casted to Integer instead of Float (reported to Ideasman42 - will be fixed after Blender 2.47)
  5157                 if texture.hFracDim != 0.0: luxProp(mat, dot(name)+"h", 1.0).set(texture.hFracDim) # bug in blender API, "texture.hFracDim" returns a Int instead of a Float
  5158                 else: luxProp(mat, dot(name)+"h", 1.0).set(0.5) # use a default value
  5159                 # bug in blender python API: values "offset" and "gain" are missing in Python-API (reported to Ideasman42 - will be fixed after Blender 2.47)
  5160                 try:
  5161                     luxProp(mat, dot(name)+"offset", 1.0).set(texture.offset)
  5162                     luxProp(mat, dot(name)+"gain", 1.0).set(texture.gain)
  5163                 except AttributeError: pass
  5164                 luxProp(mat, dot(name)+"lacu", 2.0).set(texture.lacunarity)
  5165                 luxProp(mat, dot(name)+"octs", 2.0).set(texture.octs)
  5166                 luxProp(mat, dot(name)+"outscale", 1.0).set(texture.iScale)
  5167             elif texture.type == Texture.Types["MARBLE"]:
  5168                 luxProp(mat, dot(name)+"texture", "").set("blender_marble")
  5169                 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"MBL_SOFT":"soft", "MBL_SHARP":"sharp", "MBL_SHARPER":"sharper"}, ""))
  5170                 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
  5171                 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
  5172                 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
  5173                 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
  5174                 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, {"SINE":"sin", "SAW":"saw", "TRI":"tri"}, ""))
  5175                 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
  5176             elif texture.type == Texture.Types["VORONOI"]:
  5177                 luxProp(mat, dot(name)+"texture", "").set("blender_voronoi")
  5178                 luxProp(mat, dot(name)+"distmetric", "").set({0:"actual_distance", 1:"distance_squared", 2:"manhattan", 3:"chebychev", 4:"minkovsky_half", 5:"minkovsky_four", 6:"minkovsky"}[texture.distMetric])
  5179                 luxProp(mat, dot(name)+"outscale", 1.0).set(texture.iScale)
  5180                 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
  5181                 luxProp(mat, dot(name)+"minkosky_exp", 2.5).set(texture.exp)
  5182                 luxProp(mat, dot(name)+"w1", 1.0).set(texture.weight1)
  5183                 luxProp(mat, dot(name)+"w2", 0.0).set(texture.weight2)
  5184                 luxProp(mat, dot(name)+"w3", 0.0).set(texture.weight3)
  5185                 luxProp(mat, dot(name)+"w4", 0.0).set(texture.weight4)
  5186             elif texture.type == Texture.Types["NOISE"]:
  5187                 luxProp(mat, dot(name)+"texture", "").set("blender_noise")
  5188             elif texture.type == Texture.Types["DISTNOISE"]:
  5189                 luxProp(mat, dot(name)+"texture", "").set("blender_distortednoise")
  5190                 luxProp(mat, dot(name)+"distamount", 1.0).set(texture.distAmnt)
  5191                 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
  5192                 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
  5193                 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, noiseDict, ""))
  5194             elif texture.type == Texture.Types["MAGIC"]:
  5195                 luxProp(mat, dot(name)+"texture", "").set("blender_magic")
  5196                 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
  5197                 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
  5198             elif texture.type == Texture.Types["STUCCI"]:
  5199                 luxProp(mat, dot(name)+"texture", "").set("blender_stucci")
  5200                 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"STC_PLASTIC":"Plastic", "MSTC_WALLIN":"Wall In", "STC_WALLOUT":"Wall Out"}, ""))
  5201                 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
  5202                 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
  5203                 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
  5204                 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
  5205             elif texture.type == Texture.Types["BLEND"]:
  5206                 luxProp(mat, dot(name)+"texture", "").set("blender_blend")
  5207                 luxProp(mat, dot(name)+"type", "").set(mapConstDict(texture.stype, Texture.STypes, {"BLN_LIN":"lin", "BLN_QUAD":"quad", "BLN_EASE":"ease", "BLN_DIAG":"diag", "BLN_SPHERE":"sphere", "BLN_HALO":"halo", "BLN_RADIAL":"radial"}, ""))
  5208                 luxProp(mat, dot(name)+"flipXY", "false").set({0:"false", 1:"true"}[texture.rot90])
  5209             else:
  5210                 print "Material Conversion Warning: SORRY, this procedural texture isn\'t implemented in conversion\n"
  5211 
  5212     def convertTextures(basename, texs, type="float", channel="col", val=1.0):
  5213         tex = texs.pop()
  5214         texture = tex.tex
  5215         isImagemap = (texture.type == Texture.Types["IMAGE"]) and (texture.image) and (texture.image.filename!="")
  5216         if channel == "col":
  5217             if texture.flags & Texture.Flags["COLORBAND"] > 0:
  5218                 cbLow, cbHigh = convertColorband(texture.colorband)
  5219                 val1, alpha1, val2, alpha2 = (cbLow[0],cbLow[1],cbLow[2]), cbLow[3]*tex.colfac, (cbHigh[0], cbHigh[1], cbHigh[2]), cbHigh[3]*tex.colfac
  5220                 if tex.noRGB:
  5221                     lum1, lum2 = (val1[0]+val1[1]+val1[2])/3.0, (val2[0]+val2[1]+val2[2])/3.0
  5222                     val1, val2 = (tex.col[0]*lum1,tex.col[1]*lum1,tex.col[2]*lum1), (tex.col[0]*lum2,tex.col[1]*lum2,tex.col[2]*lum2)
  5223             elif isImagemap and not(tex.noRGB): val1, alpha1, val2, alpha2 = (0.0,0.0,0.0), tex.colfac, (1.0,1.0,1.0), tex.colfac
  5224             else: val1, alpha1, val2, alpha2 = tex.col, 0.0, tex.col, tex.colfac
  5225         elif channel == "nor": val1, alpha1, val2, alpha2 = tex.norfac * 0.01, 0.0, tex.norfac * 0.01, 1.0
  5226         else: val1, alpha1, val2, alpha2 = 1.0, 0.0, 1.0, tex.varfac
  5227         if (tex.neg)^((channel=="nor") and (tex.mtNor<0)): val1, alpha1, val2, alpha2 = val2, alpha2, val1, alpha1
  5228         luxProp(mat, dot(basename)+"textured", "").set("true")
  5229 
  5230         name = basename
  5231         if (alpha1 < 1.0) or (alpha2 < 1.0): # texture with transparency
  5232             luxProp(mat, dot(basename)+"texture", "").set("mix")
  5233             if alpha1 == alpha2: # constant alpha
  5234                 luxProp(mat, ddot(basename)+"amount.value", 1.0).set(alpha1)
  5235             else:
  5236                 createLuxTexture(ddot(basename)+"amount", tex)
  5237                 luxProp(mat, ddot(basename)+"amount:tex1.value", 1.0).set(alpha1)
  5238                 luxProp(mat, ddot(basename)+"amount:tex2.value", 1.0).set(alpha2)
  5239             # transparent to next texture
  5240             name = ddot(basename)+"tex1"
  5241             if len(texs) > 0:
  5242                 convertTextures(ddot(basename)+"tex1", texs, type, channel, val)
  5243             else:
  5244                 if type=="float": luxProp(mat, ddot(basename)+"tex1.value", 1.0).set(val);
  5245                 else: luxProp(mat, ddot(basename)+"tex1.value", "1.0 1.0 1.0").setRGB((val[0], val[1], val[2]))
  5246             name = ddot(basename)+"tex2"
  5247         if val1 == val2: # texture with different colors / value
  5248             if type == "col": luxProp(mat, dot(name)+"value", "1.0 1.0 1.0").setRGB(val1)
  5249             else: luxProp(mat, dot(name)+"value", 1.0).set(val1)
  5250         else:
  5251             createLuxTexture(name, tex)
  5252             if type == "col": luxProp(mat, ddot(name)+"tex1.value", "1.0 1.0 1.0").setRGB(val1)
  5253             else: luxProp(mat, ddot(name)+"tex1.value", 1.0).set(val1)
  5254             if type == "col": luxProp(mat, ddot(name)+"tex2.value", "1.0 1.0 1.0").setRGB(val2)
  5255             else: luxProp(mat, ddot(name)+"tex2.value", 1.0).set(val2)
  5256 
  5257 
  5258     def convertDiffuseTexture(name):
  5259         texs = []
  5260         for tex in mat.getTextures():
  5261             if tex and (tex.mapto & Texture.MapTo["COL"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
  5262         if len(texs) > 0:
  5263             luxProp(mat, name, "").setRGB((mat.ref, mat.ref, mat.ref))
  5264             convertTextures(name, texs, "col", "col", (mat.R, mat.G, mat.B))
  5265     def convertSpecularTexture(name):
  5266         texs = []
  5267         for tex in mat.getTextures():
  5268             if tex and (tex.mapto & Texture.MapTo["CSP"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
  5269         if len(texs) > 0:
  5270             luxProp(mat, name, "").setRGB((mat.ref*mat.spec, mat.ref*mat.spec, mat.ref*mat.spec))
  5271             convertTextures(name, texs, "col", "col", (mat.specR, mat.specG, mat.specB))
  5272     def convertMirrorTexture(name):
  5273         texs = []
  5274         for tex in mat.getTextures():
  5275             if tex and (tex.mapto & Texture.MapTo["CMIR"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
  5276         if len(texs) > 0:
  5277             luxProp(mat, name, "").setRGB((mat.ref, mat.ref, mat.ref))
  5278             convertTextures(name, texs, "col", "col", (mat.mirR, mat.mirG, mat.mirB))
  5279     def convertBumpTexture(basename):
  5280         texs = []
  5281         for tex in mat.getTextures():
  5282             if tex and (tex.mapto & Texture.MapTo["NOR"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
  5283         if len(texs) > 0:
  5284             name = basename+":bumpmap"
  5285             luxProp(mat, basename+".usebump", "").set("true")
  5286             luxProp(mat, dot(name)+"textured", "").set("true")
  5287             luxProp(mat, name, "").set(1.0)
  5288             convertTextures(name, texs, "float", "nor", 0.0)
  5289 
  5290     def makeMatte(name):
  5291         luxProp(mat, dot(name)+"type", "").set("matte")
  5292         luxProp(mat, name+":Kd", "").setRGB((mat.R*mat.ref, mat.G*mat.ref, mat.B*mat.ref))
  5293         convertDiffuseTexture(name+":Kd")
  5294         convertBumpTexture(name)
  5295     def makeGlossy(name, roughness):
  5296         luxProp(mat, dot(name)+"type", "").set("glossy")
  5297         luxProp(mat, name+":Kd", "").setRGB((mat.R*mat.ref, mat.G*mat.ref, mat.B*mat.ref))
  5298         luxProp(mat, name+":Ks", "").setRGB((mat.specR*mat.spec*0.5, mat.specG*mat.spec*0.5, mat.specB*mat.spec*0.5))
  5299         luxProp(mat, name+":uroughness", 0.0).set(roughness)
  5300         luxProp(mat, name+":vroughness", 0.0).set(roughness)
  5301         convertDiffuseTexture(name+":Kd")
  5302         convertSpecularTexture(name+":Ks")
  5303         convertBumpTexture(name)
  5304     def makeMirror(name):
  5305         luxProp(mat, dot(name)+"type", "").set("mirror")
  5306         luxProp(mat, name+":Kr", "").setRGB((mat.mirR, mat.mirG, mat.mirB))
  5307         convertMirrorTexture(name+":Kr")
  5308         convertBumpTexture(name)
  5309     def makeGlass(name):
  5310         luxProp(mat, dot(name)+"type", "").set("glass")
  5311         luxProp(mat, name+":Kr", "").setRGB((0.0, 0.0, 0.0))
  5312         luxProp(mat, name+":Kt", "").setRGB((mat.R, mat.G, mat.B))
  5313         luxProp(mat, name+":index.iorusepreset", "").set("false")
  5314         luxProp(mat, name+":index", 0.0).set(mat.getIOR())
  5315         convertMirrorTexture(name+":Kr")
  5316         convertDiffuseTexture(name+":Kt")
  5317         convertBumpTexture(name)
  5318     def makeRoughglass(name, roughness):
  5319         luxProp(mat, dot(name)+"type", "").set("roughglass")
  5320         luxProp(mat, name+":Kr", "").setRGB((0.0, 0.0, 0.0))
  5321         luxProp(mat, name+":Kt", "").setRGB((mat.R, mat.G, mat.B))
  5322         luxProp(mat, name+":index.iorusepreset", "").set("false")
  5323         luxProp(mat, name+":index", 0.0).set(mat.getIOR())
  5324         luxProp(mat, name+":uroughness", 0.0).set(roughness)
  5325         luxProp(mat, name+":vroughness", 0.0).set(roughness)
  5326         convertMirrorTexture(name+":Kr")
  5327         convertDiffuseTexture(name+":Kt")
  5328         convertBumpTexture(name)
  5329     print "convert Blender material \"%s\" to lux material"%(mat.name)
  5330     mat.properties['luxblend'] = {}
  5331     if mat.emit > 0.0001:
  5332         luxProp(mat, "type", "").set("light")
  5333         luxProp(mat, "light.l", "").setRGB((mat.R, mat.G, mat.B))
  5334         luxProp(mat, "light.gain", 1.0).set(mat.emit)
  5335         return
  5336     alpha = mat.alpha
  5337     if not(mat.mode & Material.Modes.RAYTRANSP): alpha = 1.0
  5338     alpha0name, alpha1name = "", ""
  5339     if (alpha > 0.0) and (alpha < 1.0):
  5340         luxProp(mat, "type", "").set("mix")
  5341         luxProp(mat, ":amount", 0.0).set(alpha)
  5342         alpha0name, alpha1name = "mat2", "mat1"
  5343     if alpha > 0.0:
  5344         mirror = mat.rayMirr
  5345         if not(mat.mode & Material.Modes.RAYMIRROR): mirror = 0.0
  5346         mirror0name, mirror1name = alpha1name, alpha1name
  5347         if (mirror > 0.0) and (mirror < 1.0):
  5348             luxProp(mat, dot(alpha1name)+"type", "").set("mix")
  5349             luxProp(mat, alpha1name+":amount", 0.0).set(1.0 - mirror)
  5350             mirror0name, mirror1name = ddot(alpha1name)+"mat1", ddot(alpha1name)+"mat2"
  5351         if mirror > 0.0:
  5352             if mat.glossMir < 1.0: makeGlossy(mirror1name, 1.0-mat.glossMir**2)
  5353             else: makeMirror(mirror1name)
  5354         if mirror < 1.0:
  5355             if mat.spec > 0.0: makeGlossy(mirror0name, 1.0/mat.hard)
  5356             else: makeMatte(mirror0name)
  5357     if alpha < 1.0:
  5358         if mat.glossTra < 1.0: makeRoughnessGlass(alpha0name, 1.0-mat.glossTra**2)
  5359         else: makeGlass(alpha0name)
  5360 
  5361 def convertAllMaterials():
  5362     for mat in Material.Get(): convertMaterial(mat)
  5363 
  5364 
  5365 
  5366 
  5367 ### Connect LRMDB ###
  5368 ConnectLrmdb = False
  5369 try:
  5370     import socket  # try import of socket library
  5371     ConnectLrmdb = True
  5372     def downloadLRMDB(mat, id):
  5373         if id.isalnum():
  5374             DrawProgressBar(0.0,'Getting Material #'+id)
  5375             try:
  5376                 HOST = 'www.luxrender.net'
  5377                 GET = '/lrmdb/en/material/download/'+id
  5378                 PORT = 80
  5379                 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  5380                 sock.connect((HOST, PORT))
  5381                 sock.send("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (GET, HOST))
  5382                 data = sock.recv(1024)
  5383                 str = ""
  5384                 while len(data):
  5385                     str += data
  5386                     data = sock.recv(1024)
  5387                 sock.close()
  5388                 if str.split("\n", 1)[0].find("200") < 0:
  5389                     print "ERROR: server error: %s"%(str.split("\n",1)[0])
  5390                     return None
  5391                 str = (str.split("\r\n\r\n")[1]).strip()
  5392                 if (str[0]=="{") and (str[-1]=="}"):
  5393                     return str2MatTex(str)
  5394                 print "ERROR: downloaded data is not a material or texture"
  5395             except:
  5396                 print "ERROR: download failed"
  5397                 
  5398             DrawProgressBar(1.0,'')
  5399         else:
  5400             print "ERROR: material id is not valid"
  5401         return None
  5402     
  5403         
  5404     #===========================================================================
  5405     # COOKIETRANSPORT
  5406     #===========================================================================
  5407     
  5408     #--------------------------------------------------------------------------- 
  5409     # IMPORTS
  5410     import cookielib, urllib2, xmlrpclib
  5411     
  5412     #---------------------------------------------------------------------------
  5413     # pilfered from
  5414     # https://fedorahosted.org/python-bugzilla/browser/bugzilla.py?rev=e6f699f06e92b1e49b1b8d2c8fbe89d9425a4a9a
  5415     class CookieTransport(xmlrpclib.Transport):
  5416         '''
  5417         A subclass of xmlrpclib.Transport that supports cookies.
  5418         '''
  5419         
  5420         cookiejar = None
  5421         scheme = 'http'
  5422         verbose = None
  5423     
  5424         # Cribbed from xmlrpclib.Transport.send_user_agent 
  5425         def send_cookies(self, connection, cookie_request):
  5426             '''
  5427             Send all the cookie data that we have received
  5428             '''
  5429             
  5430             if self.cookiejar is None:
  5431                 self.cookiejar = cookielib.CookieJar()
  5432             elif self.cookiejar:
  5433                 # Let the cookiejar figure out what cookies are appropriate
  5434                 self.cookiejar.add_cookie_header(cookie_request)
  5435                 # Pull the cookie headers out of the request object...
  5436                 cookielist = list()
  5437                 for header, value in cookie_request.header_items():
  5438                     if header.startswith('Cookie'):
  5439                         cookielist.append([header, value])
  5440                 # ...and put them over the connection
  5441                 for header, value in cookielist:
  5442                     connection.putheader(header, value)
  5443     
  5444         # This is the same request() method from xmlrpclib.Transport,
  5445         # with a couple additions noted below
  5446         def request(self, host, handler, request_body, verbose=0):
  5447             '''
  5448             Handle the request
  5449             '''
  5450             
  5451             host_connection = self.make_connection(host)
  5452             if verbose:
  5453                 host_connection.set_debuglevel(1)
  5454     
  5455             # ADDED: construct the URL and Request object for proper cookie handling
  5456             request_url = "%s://%s/" % (self.scheme, host)
  5457             cookie_request  = urllib2.Request(request_url) 
  5458     
  5459             self.send_request(host_connection, handler, request_body)
  5460             self.send_host(host_connection, host) 
  5461             
  5462             # ADDED. creates cookiejar if None.
  5463             self.send_cookies(host_connection, cookie_request)
  5464             self.send_user_agent(host_connection)
  5465             self.send_content(host_connection, request_body)
  5466     
  5467             errcode, errmsg, headers = host_connection.getreply()
  5468     
  5469             # ADDED: parse headers and get cookies here
  5470             class CookieResponse:
  5471                 '''
  5472                 fake a response object that we can fill with the headers above
  5473                 '''
  5474                 
  5475                 def __init__(self, headers):
  5476                     self.headers = headers
  5477                     
  5478                 def info(self):
  5479                     return self.headers
  5480                 
  5481             cookie_response = CookieResponse(headers)
  5482             
  5483             # Okay, extract the cookies from the headers
  5484             self.cookiejar.extract_cookies(cookie_response, cookie_request)
  5485             
  5486             # And write back any changes
  5487             # DH THIS DOESN'T WORK
  5488             # self.cookiejar.save(self.cookiejar.filename)
  5489     
  5490             if errcode != 200:
  5491                 raise xmlrpclib.ProtocolError(
  5492                     host + handler,
  5493                     errcode, errmsg,
  5494                     headers
  5495                 )
  5496     
  5497             self.verbose = verbose
  5498     
  5499             try:
  5500                 sock = host_connection._conn.sock
  5501             except AttributeError:
  5502                 sock = None
  5503     
  5504             return self._parse_response(host_connection.getfile(), sock)
  5505     
  5506 
  5507     #===========================================================================
  5508     # LRMDB Integration
  5509     #===========================================================================
  5510     class lrmdb:
  5511         host              = 'http://www.luxrender.net/lrmdb/ixr'
  5512         
  5513         username          = ""
  5514         password          = ""
  5515         logged_in         = False
  5516         
  5517         SERVER            = None
  5518         
  5519         last_error_str    = None
  5520         
  5521         def last_error(self):
  5522             return self.last_error_str #'LRMDB Connector: %s' %
  5523         
  5524         def login(self):
  5525             try:
  5526                 result = self.SERVER.user.login(
  5527                     self.username,
  5528                     self.password
  5529                 )
  5530                 if not result:
  5531                     raise
  5532                 else:
  5533                     self.logged_in = True
  5534                     return True
  5535             except:
  5536                 self.last_error_str = 'Login Failed'
  5537                 self.logged_in = False
  5538                 return False
  5539             
  5540         def submit_object(self, mat, basekey, tex):
  5541             if not self.check_creds(): return False
  5542             
  5543             try:
  5544                 result = 'Unknown Error'
  5545                 
  5546                 if tex:
  5547                     name = Draw.PupStrInput('Name: ', '', 32)
  5548                 else:
  5549                     name = mat.name
  5550                 
  5551                 result = self.SERVER.object.submit(
  5552                     name,
  5553                     MatTex2dict( getMatTex(mat, basekey, tex), tex )
  5554                 )
  5555                 if result is not True:
  5556                     raise
  5557                 else:
  5558                     return True
  5559             except:
  5560                 self.last_error_str = 'Submit failed: %s' % result
  5561                 return False
  5562         
  5563         def check_creds(self):
  5564             if self.SERVER is None:
  5565                 try:
  5566                     self.SERVER = xmlrpclib.ServerProxy(self.host, transport=CookieTransport())
  5567                 except:
  5568                     self.last_error_str = 'ServerProxy init failed'
  5569                     return False
  5570             
  5571             
  5572             if not self.logged_in:
  5573                 #if self.username is "":
  5574                 self.request_username()
  5575                 
  5576                 #if self.password is "":
  5577                 self.request_password()
  5578                     
  5579                 return self.login()
  5580             else:
  5581                 return True
  5582                 
  5583         def request_username(self):
  5584             self.username = Draw.PupStrInput("Username:", self.username, 32)
  5585             
  5586         def request_password(self):
  5587             self.password = Draw.PupStrInput("Password:", self.password, 32)
  5588 
  5589     lrmdb_connector = lrmdb()
  5590         
  5591     
  5592 except: print "WARNING: LRMDB support not available"
  5593 
  5594 
  5595 
  5596 ### MatTex functions ###
  5597 ### MatTex : is a dictionary of material or texture properties
  5598 
  5599 def getMatTex(mat, basekey='', tex=False):
  5600     global usedproperties, usedpropertiesfilterobj
  5601     usedproperties = {}
  5602     usedpropertiesfilterobj = mat
  5603     luxMaterial(mat)
  5604     dict = {}
  5605     for k,v in usedproperties.items():
  5606         if k[:len(basekey)]==basekey:
  5607             if k[-9:] != '.textured':
  5608                 name = k[len(basekey):]
  5609                 if name == ".type": name = "type"
  5610                 dict[name] = v
  5611     dict["__type__"] = ["material","texture"][bool(tex)]
  5612     return dict
  5613 
  5614 def putMatTex(mat, dict, basekey='', tex=None):
  5615     if dict and (tex!=None) and (tex ^ (dict.has_key("__type__") and (dict["__type__"]=="texture"))):
  5616         print "ERROR: Can't apply %s as %s"%(["texture","material"][bool(tex)],["material","texture"][bool(tex)])
  5617         return
  5618     if dict:
  5619         # remove all current properties in mat that starts with basekey
  5620         try:
  5621             d = mat.properties['luxblend']
  5622             for k,v in d.convert_to_pyobject().items():
  5623                 kn = k
  5624                 if k[:7]=="__hash:":    # decode if entry is hashed (cause of 32chars limit)
  5625                     l = v.split(" = ")
  5626                     kn = l[0]
  5627                 if kn[:len(basekey)]==basekey:
  5628                     del mat.properties['luxblend'][k]
  5629         except: print "error" # pass
  5630         # assign loaded properties
  5631         for k,v in dict.items():
  5632             try:
  5633                 if (basekey!="") and (k=="type"): k = ".type"
  5634                 # zuegs: following two lines should fix issue http://www.luxrender.net/forum/viewtopic.php?f=16&t=1618&p=14512#p14512
  5635                 if (basekey!="") and ((k[0]!=".") and (k[0]!=":")): k = ":"+k
  5636                 if (basekey=="") and (k[0:4]==":mat"): k = k[1:]
  5637                 luxProp(mat, basekey+k, None).set(v)
  5638                 if k[-8:] == '.texture':
  5639                     luxProp(mat, basekey+k[:-8]+'.textured', 'false').set('true')
  5640             except: pass
  5641 
  5642 
  5643 LBX_VERSION = '0.7'
  5644 
  5645 def MatTex2dict(d, tex = None):
  5646     global LBX_VERSION
  5647     
  5648     if LBX_VERSION == '0.6':
  5649     
  5650         if tex is not None and tex == True:
  5651             d['LUX_DATA'] = 'TEXTURE'
  5652         else:
  5653             d['LUX_DATA'] = 'MATERIAL'
  5654         
  5655         d['LUX_VERSION'] = '0.6'
  5656         
  5657         return d
  5658     
  5659     elif LBX_VERSION == '0.7':
  5660         definition = []
  5661         for k in d.keys():
  5662             if type(d[k]) == types.IntType:
  5663                 t = 'integer'
  5664             if type(d[k]) == types.FloatType:
  5665                 t = 'float'
  5666             if type(d[k]) == types.BooleanType:
  5667                 t = 'bool'
  5668             if type(d[k]) == types.StringType:
  5669                 l=None
  5670                 try:
  5671                     l = d[k].split(" ")
  5672                 except: pass
  5673                 if l==None or len(l)!=3:
  5674                     t = 'string'
  5675                 else:
  5676                     t = 'vector'
  5677                 
  5678             definition.append([ t, k, d[k] ])
  5679         
  5680         
  5681         lbx = {
  5682             'type': d['__type__'],
  5683             'version': '0.7',
  5684             'definition': definition,
  5685             'metadata': [
  5686                 ['string', 'generator', 'luxblend'],
  5687             ]
  5688         }
  5689         
  5690         return lbx
  5691 
  5692 def format_dictStr(dictStr):
  5693     result = ''
  5694     pos = 0
  5695     indentStr = '  '
  5696     newLine = '\n'
  5697     
  5698     for char in dictStr:
  5699         if char in ['}', ']']:
  5700             result += newLine
  5701             pos -= 1
  5702             for j in range(0,pos):
  5703                 result += indentStr
  5704                 
  5705         result += char
  5706         
  5707         if char in [',', '{', '[']:
  5708             result += newLine
  5709             if char in ['{', '[']:
  5710                 pos += 1
  5711             for j in range(0,pos):
  5712                 result += indentStr
  5713             
  5714     return result
  5715 
  5716 
  5717 def MatTex2str(d, tex = None):
  5718     global LBX_VERSION
  5719     
  5720     if LBX_VERSION == '0.6':
  5721         return format_dictStr(str( MatTex2dict(d, tex) )) #.replace(", \'", ",\n\'")
  5722     
  5723     elif LBX_VERSION == '0.7':
  5724         return format_dictStr(str( MatTex2dict(d, tex) )) #.replace("], \'", "],\r\n\'").replace("[","\r\n\t[")
  5725         
  5726 
  5727 def str2MatTex(s, tex = None):    # todo: this is not absolutely save from attacks!!!
  5728     global LBX_VERSION
  5729     
  5730     s = s.strip()
  5731     if (s[0]=='{') and (s[-1]=='}'):
  5732         d = eval(s, dict(__builtins__=None,True=True,False=False))
  5733         if type(d)==types.DictType:
  5734             
  5735             
  5736             if LBX_VERSION == '0.6':
  5737             
  5738                 if tex is not None and tex == True:
  5739                     test_str = 'TEXTURE'
  5740                 else:
  5741                     test_str = 'MATERIAL'
  5742                     
  5743                 if   ('LUX_DATA' in d.keys() and d['LUX_DATA'] == test_str) \
  5744                 and  ('LUX_VERSION' in d.keys() and (d['LUX_VERSION'] == '0.6' or d['LUX_VERSION'] == 0.6)):
  5745                     return d
  5746                 else:
  5747                     reason = 'Missing/incorrect metadata'
  5748                     
  5749             elif LBX_VERSION == '0.7':
  5750                 
  5751                 def lb_list_to_dict(list):
  5752                     d = {}
  5753                     for t, k, v in list:
  5754                         if t == 'float':
  5755                             v = float(v)
  5756                             
  5757                         d[k] = v
  5758                     return d
  5759                 
  5760                 if   ('version' in d.keys() and d['version'] in ['0.6', '0.7']) \
  5761                 and  ('type' in d.keys() and d['type'] in ['material', 'texture']) \
  5762                 and  ('definition' in d.keys()):
  5763                     
  5764                     
  5765                     try:
  5766                         definition = lb_list_to_dict(d['definition'])
  5767                         
  5768                         if 'metadata' in d.keys():
  5769                             definition.update( lb_list_to_dict(d['metadata']) )
  5770                         
  5771                         return definition
  5772                     except:
  5773                         reason = 'Incorrect LBX definition data'
  5774                 else: 
  5775                     reason = 'Missing/incorrect metadata'
  5776             else:
  5777                 reason = 'Unknown LBX version'
  5778         else:
  5779             reason = 'Not a parsed dict'
  5780     else:
  5781         reason = 'Not a stored dict'
  5782             
  5783             
  5784     print "ERROR: string to material/texture conversion failed: %s" % reason
  5785     return None
  5786 
  5787 
  5788 luxclipboard = None # global variable for copy/paste content
  5789 def showMatTexMenu(mat, basekey='', tex=False):
  5790     global luxclipboard, ConnectLrmdb
  5791     if tex: menu="Texture menu:%t"
  5792     else: menu="Material menu:%t"
  5793     menu += "|Copy%x1"
  5794     try:
  5795         if luxclipboard and (not(tex) ^ (luxclipboard["__type__"]=="texture")): menu +="|Paste%x2"
  5796     except: pass
  5797     if (tex):
  5798         menu += "|Load LBT%x3|Save LBT%x4"
  5799     else:
  5800         menu += "|Load LBM%x3|Save LBM%x4"
  5801     if  ConnectLrmdb:
  5802         menu += "|Download from DB%x5" #not(tex) and
  5803         menu += "|Upload to DB%x6"
  5804 
  5805 #    menu += "|%l|dump material%x99|dump clipboard%x98"
  5806     r = Draw.PupMenu(menu)
  5807     if r==1:
  5808         luxclipboard = getMatTex(mat, basekey, tex)
  5809     elif r==2: putMatTex(mat, luxclipboard, basekey, tex)
  5810     elif r==3: 
  5811         scn = Scene.GetCurrent()
  5812         if (tex):
  5813             Window.FileSelector(lambda fn:loadMatTex(mat, fn, basekey, tex), "load texture", luxProp(scn, "lux", "").get()+os.sep+".lbt")
  5814         else:
  5815             Window.FileSelector(lambda fn:loadMatTex(mat, fn, basekey, tex), "load material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
  5816     elif r==4:
  5817         scn = Scene.GetCurrent()
  5818         if (tex):
  5819             Window.FileSelector(lambda fn:saveMatTex(mat, fn, basekey, tex), "save texture", luxProp(scn, "lux", "").get()+os.sep+".lbt")
  5820         else:
  5821             Window.FileSelector(lambda fn:saveMatTex(mat, fn, basekey, tex), "save material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
  5822     elif r==5:
  5823         if not tex:
  5824             id = Draw.PupStrInput("Material ID:", "", 32)
  5825         else:
  5826             id = Draw.PupStrInput("Texture ID:", "", 32)
  5827         if id: putMatTex(mat, downloadLRMDB(mat, id), basekey, tex)
  5828     elif r==6:
  5829         global lrmdb_connector
  5830         if not lrmdb_connector.submit_object(mat, basekey, tex):
  5831             msg = lrmdb_connector.last_error()
  5832         else:
  5833             msg = 'OK'
  5834             
  5835         Draw.PupMenu("Upload: "+msg+".%t|OK")
  5836 #    elif r==99:
  5837 #        for k,v in mat.properties['luxblend'].convert_to_pyobject().items(): print k+"="+repr(v)
  5838 #    elif r==98:
  5839 #        for k,v in luxclipboard.items(): print k+"="+repr(v)
  5840 #    print ""
  5841     Draw.Redraw()
  5842 
  5843 
  5844 def saveMatTex(mat, fn, basekey='', tex=False):
  5845     global LuxIsGUI
  5846     d = getMatTex(mat, basekey, tex)
  5847     file = open(fn, 'w')
  5848     file.write(MatTex2str(d, tex))
  5849     file.close()
  5850     if LuxIsGUI: Draw.Redraw()
  5851 
  5852 
  5853 def loadMatTex(mat, fn, basekey='', tex=None):
  5854     global LuxIsGUI
  5855     file = open(fn, 'r')
  5856     data = file.read()
  5857     file.close()
  5858     data = str2MatTex(data, tex)
  5859     putMatTex(mat, data, basekey, tex) 
  5860     if LuxIsGUI: Draw.Redraw()
  5861 
  5862 
  5863 activemat = None
  5864 def setactivemat(mat):
  5865     global activemat
  5866     activemat = mat
  5867 
  5868 
  5869 # scrollbar
  5870 class scrollbar:
  5871     def __init__(self):
  5872         self.position = 0 # current position at top (inside 0..height-viewHeight)
  5873         self.height = 0 # total height of the content
  5874         self.viewHeight = 0 # height of window
  5875         self.x = 0 # horizontal position of the scrollbar
  5876         self.scrolling = self.over = False # start without scrolling ;)
  5877     def calcRects(self):
  5878         # Blender doesn't give us direct access to the window size yet, but it does set the
  5879         # GL scissor box for it, so we can get the size from that. (thx to Daniel Dunbar)
  5880         size = BGL.Buffer(BGL.GL_FLOAT, 4)
  5881         BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, size)
  5882         size = size.list # [winx, winy, width, height]
  5883         self.winrect = size[:]
  5884         self.viewHeight = size[3]
  5885         size[0], size[1] = size[2]-20, 0 # [scrollx1, scrolly1, scrollx2, scrolly2]
  5886         self.rect = size[:]
  5887         if self.position < 0: self.position = 0
  5888         if self.height < self.viewHeight: self.height = self.viewHeight
  5889         if self.position > self.height-self.viewHeight: self.position = self.height-self.viewHeight
  5890         self.factor = (size[3]-size[1]-4)/self.height
  5891         self.sliderRect = [size[0]+2, size[3]-2-(self.position+self.viewHeight)*self.factor, size[2]-2, size[3]-2-self.position*self.factor]
  5892     def draw(self):
  5893         self.calcRects()
  5894         BGL.glColor3f(0.5,0.5,0.5); BGL.glRectf(self.rect[0],self.rect[1],self.rect[2],self.rect[3])
  5895         if self.over or self.scrolling: BGL.glColor3f(1.0,1.0,0.7)
  5896         else: BGL.glColor3f(0.7,0.7,0.7)
  5897         BGL.glRectf(self.sliderRect[0],self.sliderRect[1],self.sliderRect[2],self.sliderRect[3])
  5898     def getTop(self):
  5899         return self.viewHeight+self.position
  5900     def scroll(self, delta):
  5901         self.position = self.position + delta
  5902         self.calcRects()
  5903         Draw.Redraw()
  5904     def Mouse(self):
  5905         self.calcRects()
  5906         coord, buttons = Window.GetMouseCoords(), Window.GetMouseButtons()
  5907         over = (coord[0]>=self.winrect[0]+self.rect[0]) and (coord[0]<=self.winrect[0]+self.rect[2]) and \
  5908                (coord[1]>=self.winrect[1]+self.rect[1]) and (coord[1]<=self.winrect[1]+self.rect[3])
  5909         if Window.MButs.L and buttons > 0:
  5910             if self.scrolling:
  5911                 if self.factor > 0: self.scroll((self.lastcoord[1]-coord[1])/self.factor)
  5912                 Draw.Redraw()
  5913             elif self.over:
  5914                 self.scrolling = True
  5915             self.lastcoord = coord
  5916         elif self.scrolling:
  5917             self.scrolling = False
  5918             Draw.Redraw()
  5919         if self.over != over: Draw.Redraw()
  5920         self.over = over
  5921 
  5922 scrollbar = scrollbar()
  5923 
  5924 
  5925 # gui main draw
  5926 def luxDraw():
  5927     global icon_luxblend
  5928 
  5929     BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
  5930 
  5931     y = int(scrollbar.getTop()) # 420
  5932     BGL.glColor3f(0.1,0.1,0.1); BGL.glRectf(0,0,440,y)
  5933     BGL.glColor3f(1.0,0.5,0.0); BGL.glRasterPos2i(130,y-21); Draw.Text("v0.6RC5")
  5934     BGL.glColor3f(0.9,0.9,0.9);
  5935 
  5936     drawLogo(icon_luxblend, 6, y-25);
  5937 
  5938     scn = Scene.GetCurrent()
  5939     if scn:
  5940         luxpage = luxProp(scn, "page", 0)
  5941         gui = luxGui(y-70)
  5942 
  5943         # render presets
  5944         BGL.glRasterPos2i(10,y-45); Draw.Text("Render presets:")
  5945         luxpreset = luxProp(scn, "preset", "1C - Final - medium MLT/Path Tracing (indoor) (recommended)")
  5946         presets = getScenePresets()
  5947         presetskeys = presets.keys()
  5948         presetskeys.sort()
  5949         presetskeys.insert(0, "")
  5950         presetsstr = "presets: %t"
  5951         for i, v in enumerate(presetskeys): presetsstr = "%s %%x%d|%s"%(v, i, presetsstr)
  5952         try: i = presetskeys.index(luxpreset.get())
  5953         except ValueError: i = 0
  5954         Draw.Menu(presetsstr, evtLuxGui, 110, y-50, 220, 18, i, "", lambda e,v: luxpreset.set(presetskeys[v]))
  5955         Draw.Button("save", evtSavePreset, 330, y-50, 40, 18, "create a render-settings preset")
  5956         Draw.Button("del", evtDeletePreset, 370, y-50, 40, 18, "delete a render-settings preset")
  5957 
  5958         # if preset is selected load values
  5959         if luxpreset.get() != "":
  5960             try:
  5961                 d = presets[luxpreset.get()]
  5962                 for k,v in d.items(): scn.properties['luxblend'][k] = v
  5963             except: pass
  5964 
  5965         Draw.Button("Material", evtLuxGui, 10, y-70, 80, 16, "", lambda e,v:luxpage.set(0))
  5966         Draw.Button("Cam/Env", evtLuxGui, 90, y-70, 80, 16, "", lambda e,v:luxpage.set(1))
  5967         Draw.Button("Render", evtLuxGui, 170, y-70, 80, 16, "", lambda e,v:luxpage.set(2))
  5968         Draw.Button("Output", evtLuxGui, 250, y-70, 80, 16, "", lambda e,v:luxpage.set(3))
  5969         Draw.Button("System", evtLuxGui, 330, y-70, 80, 16, "", lambda e,v:luxpage.set(4))
  5970         if luxpage.get() == 0:
  5971             BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(10,y-74,90,y-70);BGL.glColor3f(0.9,0.9,0.9)
  5972             obj = scn.objects.active
  5973             if obj:
  5974                 if (obj.getType() == "Lamp"):
  5975                     ltype = obj.getData(mesh=1).getType() # data
  5976                     if (ltype == Lamp.Types["Area"]): luxLight("Area LIGHT", "", obj, gui, 0)
  5977                     elif (ltype == Lamp.Types["Spot"]): luxSpot("Spot LIGHT", "", obj, gui, 0)
  5978                     elif (ltype == Lamp.Types["Lamp"]): luxLamp("Point LIGHT", "", obj, gui, 0)
  5979                 else:
  5980                     matfilter = luxProp(scn, "matlistfilter", "false")
  5981                     mats = getMaterials(obj, True)
  5982                     if (activemat == None) and (len(mats) > 0):
  5983                         setactivemat(mats[0])
  5984                     if matfilter.get() == "false":
  5985                         mats = Material.Get()
  5986                     matindex = 0
  5987                     for i, v in enumerate(mats):
  5988                         if v==activemat: matindex = i
  5989                     matnames = [m.getName() for m in mats]
  5990                     menustr = "Material: %t"
  5991                     for i, v in enumerate(matnames): menustr = "%s %%x%d|%s"%(v, i, menustr)
  5992                     gui.newline("MATERIAL:", 8) 
  5993                     r = gui.getRect(1.1, 1)
  5994                     Draw.Button("C", evtConvertMaterial, r[0]-gui.h, gui.y-gui.h, gui.h, gui.h, "convert blender material to lux material")
  5995                     Draw.Menu(menustr, evtLuxGui, r[0], r[1], r[2], r[3], matindex, "", lambda e,v: setactivemat(mats[v]))
  5996                     luxBool("", matfilter, "filter", "only show active object materials", gui, 0.5)
  5997 
  5998                     Draw.Button("L", evtLoadMaterial, gui.x, gui.y-gui.h, gui.h, gui.h, "load a material preset")
  5999                     Draw.Button("S", evtSaveMaterial, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "save a material preset")
  6000                     Draw.Button("D", evtDeleteMaterial, gui.x+gui.h*2, gui.y-gui.h, gui.h, gui.h, "delete a material preset")
  6001                     if len(mats) > 0:
  6002                         setactivemat(mats[matindex])
  6003                         luxMaterial(activemat, gui)
  6004         if luxpage.get() == 1:
  6005             BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(90,y-74,170,y-70);BGL.glColor3f(0.9,0.9,0.9)
  6006             cam = scn.getCurrentCamera()
  6007             if cam:
  6008                 r = gui.getRect(1.1, 1)
  6009                 luxCamera(cam.data, scn.getRenderingContext(), gui)
  6010             gui.newline("", 10)
  6011             luxEnvironment(scn, gui)
  6012         if luxpage.get() == 2:
  6013             BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(170,y-74,250,y-70);BGL.glColor3f(0.9,0.9,0.9)
  6014             r = gui.getRect(1.1, 1)
  6015             luxSampler(scn, gui)
  6016             gui.newline("", 10)
  6017             luxSurfaceIntegrator(scn, gui)
  6018             gui.newline("", 10)
  6019             luxVolumeIntegrator(scn, gui)
  6020             gui.newline("", 10)
  6021             luxPixelFilter(scn, gui)
  6022         if luxpage.get() == 3:
  6023             BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(250,y-74,330,y-70);BGL.glColor3f(0.9,0.9,0.9)
  6024             r = gui.getRect(1.1, 1)
  6025             luxFilm(scn, gui)
  6026         if luxpage.get() == 4:
  6027             BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(330,y-74,410,y-70);BGL.glColor3f(0.9,0.9,0.9)
  6028             luxSystem(scn, gui)
  6029             gui.newline("", 10)
  6030             luxAccelerator(scn, gui)
  6031             gui.newline("MATERIALS:", 10)
  6032             r = gui.getRect(2,1)
  6033             Draw.Button("convert all blender materials", 0, r[0], r[1], r[2], r[3], "convert all blender-materials to lux-materials", lambda e,v:convertAllMaterials())
  6034             gui.newline("SETTINGS:", 10)
  6035             r = gui.getRect(2,1)
  6036             Draw.Button("save defaults", 0, r[0], r[1], r[2], r[3], "save current settings as defaults", lambda e,v:saveluxdefaults())
  6037         y = gui.y - 80
  6038         if y > 0: y = 0 # bottom align of render button
  6039         run = luxProp(scn, "run", "true")
  6040         dlt = luxProp(scn, "default", "true")
  6041         clay = luxProp(scn, "clay", "false")
  6042         nolg = luxProp(scn, "nolg", "false")
  6043         lxs = luxProp(scn, "lxs", "true")
  6044         lxo = luxProp(scn, "lxo", "true")
  6045         lxm = luxProp(scn, "lxm", "true")
  6046         lxv = luxProp(scn, "lxv", "true")
  6047         net = luxProp(scn, "netrenderctl", "false")
  6048         donet = luxProp(scn, "donetrender", "true")
  6049         if (run.get()=="true"):
  6050             Draw.Button("Render", 0, 10, y+20, 100, 36, "Render with Lux", lambda e,v:CBluxExport(dlt.get()=="true", True))
  6051             Draw.Button("Render Anim", 0, 110, y+20, 100, 36, "Render animation with Lux", lambda e,v:CBluxAnimExport(dlt.get()=="true", True))
  6052         else:
  6053             Draw.Button("Export", 0, 10, y+20, 100, 36, "Export", lambda e,v:CBluxExport(dlt.get()=="true", False))
  6054             Draw.Button("Export Anim", 0, 110, y+20, 100, 36, "Export animation", lambda e,v:CBluxAnimExport(dlt.get()=="true", False))
  6055 
  6056         Draw.Toggle("run", evtLuxGui, 290, y+40, 30, 16, run.get()=="true", "start Lux after export", lambda e,v: run.set(["false","true"][bool(v)]))
  6057         Draw.Toggle("def", evtLuxGui, 320, y+40, 30, 16, dlt.get()=="true", "save to default.lxs", lambda e,v: dlt.set(["false","true"][bool(v)]))
  6058         Draw.Toggle("clay", evtLuxGui, 350, y+40, 30, 16, clay.get()=="true", "all materials are rendered as white-matte", lambda e,v: clay.set(["false","true"][bool(v)]))
  6059         Draw.Toggle("nolg", evtLuxGui, 380, y+40, 30, 16, nolg.get()=="true", "disables all light groups", lambda e,v: nolg.set(["false","true"][bool(v)]))
  6060         Draw.Toggle(".lxs", 0, 290, y+20, 30, 16, lxs.get()=="true", "export .lxs scene file", lambda e,v: lxs.set(["false","true"][bool(v)]))
  6061         Draw.Toggle(".lxo", 0, 320, y+20, 30, 16, lxo.get()=="true", "export .lxo geometry file", lambda e,v: lxo.set(["false","true"][bool(v)]))
  6062         Draw.Toggle(".lxm", 0, 350, y+20, 30, 16, lxm.get()=="true", "export .lxm material file", lambda e,v: lxm.set(["false","true"][bool(v)]))
  6063         Draw.Toggle(".lxv", 0, 380, y+20, 30, 16, lxm.get()=="true", "export .lxv volume file", lambda e,v: lxm.set(["false","true"][bool(v)]))
  6064     BGL.glColor3f(0.9, 0.9, 0.9) ; BGL.glRasterPos2i(340,y+5) ; Draw.Text("Press Q or ESC to quit.", "tiny")
  6065     scrollbar.height = scrollbar.getTop() - y
  6066     scrollbar.draw()
  6067 
  6068 mouse_xr=1 
  6069 mouse_yr=1 
  6070 
  6071 activeObject = None
  6072 activeEvent = None
  6073 lastEventTime = 0
  6074 key_tabs = {
  6075     Draw.ONEKEY:     0,
  6076     Draw.TWOKEY:     1,
  6077     Draw.THREEKEY:   2,
  6078     Draw.FOURKEY:    3,
  6079     Draw.FIVEKEY:    4,
  6080 }
  6081 def luxEvent(evt, val):  # function that handles keyboard and mouse events
  6082     global activeObject, activemat, activeEvent, lastEventTime, key_tabs
  6083     if evt == Draw.ESCKEY or evt == Draw.QKEY:
  6084         stop = Draw.PupMenu("OK?%t|Cancel export %x1")
  6085         if stop == 1:
  6086             Draw.Exit()
  6087             return
  6088     scn = Scene.GetCurrent()
  6089     if scn:
  6090         if scn.objects.active != activeObject:
  6091             activeObject = scn.objects.active
  6092             activemat = None
  6093             Window.QRedrawAll()
  6094     if (evt == Draw.MOUSEX) or (evt == Draw.MOUSEY): scrollbar.Mouse()
  6095     if evt == Draw.WHEELUPMOUSE: scrollbar.scroll(-16)
  6096     if evt == Draw.WHEELDOWNMOUSE: scrollbar.scroll(16)
  6097     if evt == Draw.PAGEUPKEY: scrollbar.scroll(-50)
  6098     if evt == Draw.PAGEDOWNKEY: scrollbar.scroll(50)
  6099 
  6100     # scroll to [T]op and [B]ottom
  6101     if evt == Draw.TKEY:
  6102         scrollbar.scroll(-scrollbar.position)
  6103     if evt == Draw.BKEY:
  6104         scrollbar.scroll(100000)   # Some large number should be enough ?!
  6105 
  6106     # R key shortcut to launch render
  6107     # E key shortcut to export current scene (not render)
  6108     # P key shortcut to preview current material
  6109     # These keys need time and process-complete locks
  6110     if evt in [Draw.RKEY, Draw.EKEY, Draw.PKEY]:
  6111         if activeEvent == None and (sys.time() - lastEventTime) > 5:
  6112             lastEventTime = sys.time()
  6113             if evt == Draw.RKEY:
  6114                 activeEvent = 'RKEY'
  6115                 CBluxExport(luxProp(scn, "default", "true").get() == "true", True)
  6116                 activeEvent = None
  6117             if evt == Draw.EKEY:
  6118                 activeEvent = 'EKEY'
  6119                 CBluxExport(luxProp(scn, "default", "true").get() == "true", False)
  6120                 activeEvent = None
  6121             if evt == Draw.PKEY:
  6122                 activeEvent = 'PKEY'
  6123                 if activemat != None:
  6124                     Preview_Update(activemat, '', True, 0, None, None, None)
  6125                 activeEvent = None
  6126         
  6127     # Switch GUI tabs with number keys
  6128     if evt in key_tabs.keys():
  6129         luxProp(scn, "page", 0).set(key_tabs[evt])        
  6130         luxDraw()
  6131         Window.QRedrawAll()
  6132           
  6133 
  6134     # Handle icon button events - note - radiance - this is a work in progress! :)
  6135 #    if evt == Draw.LEFTMOUSE and not val: 
  6136 #           size=BGL.Buffer(BGL.GL_FLOAT, 4) 
  6137 #           BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, size) 
  6138 #            size= [int(s) for s in size] 
  6139 #        mx, my = Window.GetMouseCoords()
  6140 #        mousex = mx - size[0]
  6141 #        print "mousex = %i"%mousex
  6142 #        #if((mousex > 2) and (mousex < 25)):
  6143 #            # Mouse clicked in left button bar
  6144 #        if((mousex > 399) and (mousex < 418)):
  6145 #            # Mouse clicked in right button bar
  6146 #            mousey = my - size[1] - scrollbar.position
  6147 #            print "mousey = %i"%mousey
  6148             
  6149     
  6150 def luxButtonEvt(evt):  # function that handles button events
  6151     global usedproperties, usedpropertiesfilterobj
  6152     if evt == evtLuxGui:
  6153         Draw.Redraw()
  6154     if evt == evtSavePreset:
  6155         scn = Scene.GetCurrent()
  6156         if scn:
  6157             name = Draw.PupStrInput("preset name: ", "")
  6158             if name != "":
  6159                 usedproperties = {}
  6160                 usedpropertiesfilterobj = None
  6161                 luxSurfaceIntegrator(scn)
  6162                 luxSampler(scn)
  6163                 luxPixelFilter(scn)
  6164                 # luxFilm(scn)
  6165                 luxAccelerator(scn)
  6166                 # luxEnvironment(scn)
  6167                 saveScenePreset(name, usedproperties.copy())
  6168                 luxProp(scn, "preset", "").set(name)
  6169                 Draw.Redraw()
  6170     if evt == evtDeletePreset:
  6171         presets = getScenePresets().keys()
  6172         presets.sort()
  6173         presetsstr = "delete preset: %t"
  6174         for i, v in enumerate(presets): presetsstr += "|%s %%x%d"%(v, i)
  6175         r = Draw.PupMenu(presetsstr, 20)
  6176         if r >= 0:
  6177             saveScenePreset(presets[r], None)
  6178             Draw.Redraw()
  6179 
  6180     if evt == evtLoadMaterial:
  6181         if activemat:
  6182             mats = getMaterialPresets()
  6183             matskeys = mats.keys()
  6184             matskeys.sort()
  6185             matsstr = "load preset: %t"
  6186             for i, v in enumerate(matskeys): matsstr += "|%s %%x%d"%(v, i)
  6187             r = Draw.PupMenu(matsstr, 20)
  6188             if r >= 0:
  6189                 name = matskeys[r]
  6190                 try:
  6191 #                    for k,v in mats[name].items(): activemat.properties['luxblend'][k] = v
  6192                     for k,v in mats[name].items(): luxProp(activemat, k, None).set(v)
  6193                 except: pass
  6194                 Draw.Redraw()
  6195     if evt == evtSaveMaterial:
  6196         if activemat:
  6197             name = Draw.PupStrInput("preset name: ", "")
  6198             if name != "":
  6199                 usedproperties = {}
  6200                 usedpropertiesfilterobj = activemat
  6201                 luxMaterial(activemat)
  6202                 saveMaterialPreset(name, usedproperties.copy())
  6203                 Draw.Redraw()
  6204     if evt == evtDeleteMaterial:
  6205         matskeys = getMaterialPresets().keys()
  6206         matskeys.sort()
  6207         matsstr = "delete preset: %t"
  6208         for i, v in enumerate(matskeys): matsstr += "|%s %%x%d"%(v, i)
  6209         r = Draw.PupMenu(matsstr, 20)
  6210         if r >= 0:
  6211             saveMaterialPreset(matskeys[r], None)
  6212             Draw.Redraw()
  6213     if evt == evtConvertMaterial:
  6214         if activemat: convertMaterial(activemat)
  6215         Draw.Redraw()
  6216     if evt == evtLoadMaterial2:
  6217         if activemat:
  6218             scn = Scene.GetCurrent()
  6219             Window.FileSelector(lambda fn:loadMatTex(activemat, fn), "load material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
  6220     if evt == evtSaveMaterial2:
  6221         if activemat:
  6222             scn = Scene.GetCurrent()
  6223             Window.FileSelector(lambda fn:saveMaterial(activemat, fn), "save material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
  6224     
  6225 
  6226 def setFocus(target):
  6227     currentscene = Scene.GetCurrent()
  6228     camObj = currentscene.objects.camera # currentscene.getCurrentCamera()
  6229     if target == "S":
  6230         try:
  6231             refLoc = (Object.GetSelected()[0]).getLocation()
  6232         except:
  6233             print "select an object to focus\n"
  6234     elif target == "C":
  6235         refLoc = Window.GetCursorPos()
  6236     else:
  6237         refLoc = (Object.Get(target)).getLocation()
  6238     dist = Mathutils.Vector(refLoc) - Mathutils.Vector(camObj.getLocation())
  6239     camDir = camObj.getMatrix()[2]*(-1.0)
  6240     camObj.getData(mesh=1).dofDist = (camDir[0]*dist[0]+camDir[1]*dist[1]+camDir[2]*dist[2])/camDir.length # data
  6241 
  6242 
  6243 # Parse command line arguments for batch mode rendering if supplied
  6244 
  6245 try:
  6246     batchindex = osys.argv.index('--batch')
  6247     pyargs = osys.argv[osys.argv.index('--batch')+1:]
  6248 except: pyargs = []
  6249 
  6250 if (pyargs != []) and (batchindex != 0):
  6251     print "\n\nLuxBlend v0.6RC5 - BATCH mode\n"
  6252     LuxIsGUI = False
  6253 
  6254     scene = Scene.GetCurrent()
  6255     context = scene.getRenderingContext()
  6256 
  6257     luxpath = ""
  6258     import getopt
  6259     o, a = getopt.getopt(pyargs, 's:e:o:t:l:',["scale=","haltspp=","run=", "lbm=", "lbt="])
  6260 
  6261     opts = {}
  6262     for k,v in o:
  6263         opts[k] = v
  6264 
  6265     if (opts.has_key('--run')) and (opts['--run'] == 'false'):
  6266         print "Run: false"
  6267         luxProp(scene, "run", "true").set("false")
  6268     else:
  6269         luxProp(scene, "run", "true").set("true")
  6270 
  6271     if opts.has_key('--scale'):
  6272         print "Zoom: %s" %opts['--scale']
  6273         luxProp(scene, "film.scale", "100 %").set(opts['--scale'])
  6274 
  6275     if opts.has_key('--haltspp'):
  6276         print "haltspp: %s" %opts['--haltspp']
  6277         luxProp(scene, "haltspp", 0).set(int(opts['--haltspp']))
  6278 
  6279     if opts.has_key('-s'):
  6280         print "Start frame: %s" %opts['-s']
  6281         context.startFrame(int(opts['-s']))
  6282     else:
  6283         print "Error: Start frame not supplied (-s)"; osys.exit(1)
  6284     if opts.has_key('-e'):
  6285         print "End frame: %s" %opts['-e']
  6286         context.endFrame(int(opts['-e']))
  6287     else:
  6288         print "Error: End frame not supplied (-e)"; osys.exit(1)
  6289     if opts.has_key('-l'):
  6290         print "Path to lux binary: %s" %opts['-l']
  6291         luxbatchconsolemode = luxProp(scene, "luxbatchc", "false")
  6292         luxbatchconsolemode.set("true")
  6293         luxpathprop = luxProp(scene, "lux", "")
  6294         luxpathprop.set(opts['-l'])
  6295     else:
  6296         print "Error: path to lux binary not supplied (-l)"; osys.exit(1)    
  6297     if opts.has_key('-o'):
  6298         print "Image output path: %s" %opts['-o']
  6299         luxProp(scene, "overrideoutputpath", "").set(opts['-o'])
  6300     else:
  6301         print "Error: image output path not supplied (-o)"; osys.exit(1)    
  6302     if opts.has_key('-t'):
  6303         print "Temporary export path: %s" %opts['-t']
  6304         luxProp(scene, "datadir", "").set(opts['-t'])
  6305     else:
  6306         print "Error: Temporary export path not supplied (-t)"; osys.exit(1)            
  6307     
  6308     if opts.has_key('--lbm'):
  6309         print "Load material: %s" %opts['--lbm']
  6310         mat = Material.Get("Material")
  6311         if mat: loadMatTex(mat, opts['--lbm'])
  6312         else:
  6313             print "Error: No material with name \"Material\" found (--lbm)"; osys.exit(1)
  6314             
  6315     if opts.has_key('--lbt'):
  6316         print "Load material: %s" %opts['--lbt']
  6317         mat = Material.Get("Material")
  6318         if mat: loadMatTex(mat, opts['--lbt'], ':Kd')
  6319         else:
  6320             print "Error: No material with name \"Material\" found (--lbt)"; osys.exit(1)
  6321 
  6322 #    CBluxAnimExport(True, True)
  6323     CBluxAnimExport(True, True, False) # as by zukazuka (http://www.luxrender.net/forum/viewtopic.php?f=11&t=1288)
  6324     osys.exit(0)
  6325 
  6326 else:
  6327     print "\n\nLuxBlend v0.6RC5 - UI mode\n"
  6328     from Blender.Window import DrawProgressBar
  6329     LuxIsGUI = True
  6330     
  6331     Draw.Register(luxDraw, luxEvent, luxButtonEvt) # init GUI
  6332 
  6333     luxpathprop = luxProp(Scene.GetCurrent(), "lux", "")
  6334     luxpath = luxpathprop.get()
  6335     luxrun = luxProp(Scene.GetCurrent(), "run", True).get()
  6336     checkluxpath = luxProp(Scene.GetCurrent(), "checkluxpath", True).get()
  6337 
  6338     if checkluxpath and luxrun:
  6339         if (luxpath is None) or (sys.exists(luxpath)<=0):
  6340             # luxpath not valid, so delete entry from .blend scene file ...
  6341             luxpathprop.delete()
  6342             # and re-get luxpath, so we get the path from default-settings
  6343             luxpath = luxpathprop.get()
  6344             if (luxpath is None) or (sys.exists(luxpath)<=0):
  6345                 print "WARNING: LuxPath \"%s\" is not valid\n"%(luxpath)
  6346                 scn = Scene.GetCurrent()
  6347                 if scn:
  6348                     r = Draw.PupMenu("Installation: Set path to the lux render software?%t|Yes%x1|No%x0|Never%x2")
  6349                     if r == 1:
  6350                         Window.FileSelector(lambda s:luxProp(scn, "lux", "").set(Blender.sys.dirname(s)+os.sep), "Select file in Lux path")
  6351                         saveluxdefaults()
  6352                     if r == 2:
  6353                         newluxdefaults["checkluxpath"] = False
  6354                         saveluxdefaults()
  6355     else    :
  6356         print "Lux path check disabled\n"