2 # -*- coding: utf-8 -*-
4 """Registration info for Blender menus:
5 Name: 'LuxBlend v0.6 Exporter'
8 Tooltip: 'Export/Render to LuxRender v0.6 scene format (.lxs)'
11 __author__ = "radiance, zuegs, ideasman42, luxblender, dougal2"
14 "http://www.luxrender.net/",
15 "http://www.luxrender.net/forum/viewforum.php?f=11",
16 "http://www.luxrender.net/wiki/index.php/Tutorial_1:_Your_first_scene_%26_render"
19 LuxRender is an open-source rendering system for physically correct, unbiased image synthesis.
20 This is the Luxrender Blender Export Script.
23 - For updates: http://www.luxrender.net/forum/viewforum.php?f=11
24 - For Blender Tutorial: http://www.luxrender.net/wiki/index.php/Tutorial_1:_Your_first_scene_%26_render
27 - Run the script from the render menu.
28 - Set the default location of the Luxrender.exe.
30 Please check the lux tutorials & forums for more information.
34 # ***** BEGIN GPL LICENSE BLOCK *****
36 # --------------------------------------------------------------------------
37 # LuxBlend v0.6 exporter
38 # --------------------------------------------------------------------------
41 # radiance, zuegs, ideasman42, luxblender, dougal2
43 # This program is free software; you can redistribute it and/or
44 # modify it under the terms of the GNU General Public License
45 # as published by the Free Software Foundation; either version 2
46 # of the License, or (at your option) any later version.
48 # This program is distributed in the hope that it will be useful,
49 # but WITHOUT ANY WARRANTY; without even the implied warranty of
50 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51 # GNU General Public License for more details.
53 # You should have received a copy of the GNU General Public License
54 # along with this program; if not, write to the Free Software Foundation,
55 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
57 # ***** END GPL LICENCE BLOCK *****
58 # --------------------------------------------------------------------------
63 ######################################################
65 ######################################################
74 from Blender import Mesh, Scene, Object, Material, Texture, Window, sys, Draw, BGL, Mathutils, Lamp, Image
79 ######################################################
81 ######################################################
83 # New name based on old with a different extension
85 return Blender.Get('filename')[: -len(Blender.Get('filename').split('.', -1)[-1]) ] + ext
90 return str.replace("\\", "\\\\")
93 ### relpath ##########################
94 def relpath(base, target):
95 if target[0:2] == "\\\\" or target[0:2] == "//":
96 return target[2:len(target)]
97 if not os.path.isabs(base):
98 base = os.path.abspath(base)
99 if not os.path.isabs(target):
100 target = os.path.abspath(target)
102 base = os.path.normcase(base)
103 target = os.path.normcase(target)
106 baselist = base.split(os.sep)
107 if baselist[-1] == "":
108 baselist = baselist[:-1]
109 targetlist = target.split(os.sep)
111 top = min([len(baselist), len(targetlist)])
112 while i < top and baselist[i] == targetlist[i]:
115 return os.sep.join(targetlist)
116 if i == len(baselist):
117 return os.sep.join(targetlist[i:])
119 return ('..' + os.sep) * (len(baselist) - i) + os.sep.join(targetlist[i:])
121 ### luxFilePath #####################
124 def luxFilePath(filename):
125 global lxs_filename, previewing
126 scn = Scene.GetCurrent()
127 pm = luxProp(scn, "pathmode", "absolute").get()
128 if (pm=="absolute") or previewing: # absolute paths (the old / default mode)
130 elif pm=="relative": # relative paths
131 base = os.path.dirname(lxs_filename)
132 return relpath(base, filename)
133 elif pm=="flat": # flat mode - only filename
134 return os.path.basename(filename)
138 ###### RGC ##########################
140 scn = Scene.GetCurrent()
141 if luxProp(scn, "RGC", "true").get()=="true":
142 gamma = luxProp(scn, "film.gamma", 2.2).get()
146 if luxProp(scn, "colorclamp", "false").get()=="true":
155 scn = Scene.GetCurrent()
156 if luxProp(scn, "RGC", "true").get()=="true":
157 return luxProp(scn, "film.gamma", 2.2).get()
161 def exportMaterial(mat):
162 str = "# Material '%s'\n" %mat.name
163 return str+luxMaterial(mat)+"\n"
166 def exportMaterialGeomTag(mat):
167 return "%s\n"%(luxProp(mat, "link", "").get())
172 ################################################################
175 dummyMat = 2394723948 # random identifier for dummy material
178 #-------------------------------------------------
180 # helper function to get the material list of an object in respect of obj.colbits
181 #-------------------------------------------------
182 def getMaterials(obj, compress=False):
185 colbits = obj.colbits
186 objMats = obj.getMaterials(1)
187 data = obj.getData(mesh=1)
189 dataMats = data.materials
192 dataMats = data.getMaterials(1)
196 m = max(len(objMats), len(dataMats))
198 objMats.extend([None]*16)
199 dataMats.extend([None]*16)
201 if (colbits & (1<<i) > 0):
204 mats[i] = dataMats[i]
206 mats = [m for m in mats if m]
208 slots = [m for m in mats if m]
209 if m==0 or not slots:
210 print("Warning: object %s has no material assigned" % (obj.getName()))
213 if luxProp(Scene.GetCurrent(), "clay", "false").get()=="true":
214 if clayMat==None: clayMat = Material.New("lux_clayMat")
215 for i in range(len(mats)):
217 mattype = luxProp(mats[i], "type", "").get()
218 if (mattype not in ["portal","light","boundvolume"]): mats[i] = clayMat
223 ######################################################
225 ######################################################
228 #-------------------------------------------------
230 # initializes the exporter object
231 #-------------------------------------------------
232 def __init__(self, scene):
234 self.camera = scene.objects.camera
243 #-------------------------------------------------
244 # analyseObject(self, obj, matrix, name)
245 # called by analyseScene to build the lists before export
246 #-------------------------------------------------
247 def analyseObject(self, obj, matrix, name, isOriginal=True, isDupli=False):
250 obj_type = obj.getType()
251 if (obj.enableDupFrames and isOriginal):
252 for o, m in obj.DupObjects:
253 self.analyseObject(o, m, "%s.%s"%(name, o.getName()), False)
254 if (obj.enableDupGroup or obj.enableDupVerts or obj.enableDupFaces):
256 for o, m in obj.DupObjects:
257 self.analyseObject(o, m, "%s.%s"%(name, o.getName()), True, True)
258 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"))):
259 mats = getMaterials(obj)
260 if (len(mats)>0) and (mats[0]!=None) and ((mats[0].name=="PORTAL") or (luxProp(mats[0], "type", "").get()=="portal")):
261 self.portals.append([obj, matrix])
262 elif (len(mats)>0) and (luxProp(mats[0], "type", "").get()=="boundvolume"):
263 self.volumes.append([obj, matrix])
266 if (mat!=None) and (mat not in self.materials):
267 self.materials.append(mat)
268 if (mat!=None) and ((luxProp(mat, "type", "").get()=="light") or (luxProp(mat, "emission", "false").get()=="true")):
270 mesh_name = obj.getData(name_only=True)
272 self.meshes[mesh_name] += [obj]
274 self.meshes[mesh_name] = [obj]
275 self.objects.append([obj, matrix])
276 elif (obj_type == "Lamp"):
277 ltype = obj.getData(mesh=1).getType() # data
278 if (ltype == Lamp.Types["Lamp"]) or (ltype == Lamp.Types["Spot"]) or (ltype == Lamp.Types["Area"]):
279 self.lights.append([obj, matrix])
283 #-------------------------------------------------
285 # this function builds the lists of object, lights, meshes and materials before export
286 #-------------------------------------------------
287 def analyseScene(self):
289 for obj in self.scene.objects:
290 if ((obj.Layers & self.scene.Layers) > 0):
291 if self.analyseObject(obj, obj.getMatrix(), obj.getName()): light = True
294 #-------------------------------------------------
295 # exportMaterialLink(self, file, mat)
296 # exports material link. LuxRender "Material"
297 #-------------------------------------------------
298 def exportMaterialLink(self, file, mat):
300 file.write("\tMaterial \"matte\" # dummy material\n")
302 file.write("\t%s"%exportMaterialGeomTag(mat)) # use original methode
304 #-------------------------------------------------
305 # exportMaterial(self, file, mat)
306 # exports material. LuxRender "Texture"
307 #-------------------------------------------------
308 def exportMaterial(self, file, mat):
309 print("material %s"%(mat.getName()))
310 file.write("\t%s"%exportMaterial(mat)) # use original methode
312 #-------------------------------------------------
313 # exportMaterials(self, file)
314 # exports materials to the file
315 #-------------------------------------------------
316 def exportMaterials(self, file):
317 for mat in self.materials:
319 self.exportMaterial(file, mat)
321 #-------------------------------------------------
322 # getMeshType(self, vertcount, mat)
323 # returns type of mesh as string to use depending on thresholds
324 #-------------------------------------------------
325 def getMeshType(self, vertcount, mat):
326 scn = Scene.GetCurrent()
328 usesubdiv = luxProp(mat, "subdiv", "false")
329 usedisp = luxProp(mat, "dispmap", "false")
330 sharpbound = luxProp(mat, "sharpbound", "false")
331 nsmooth = luxProp(mat, "nsmooth", "true")
332 sdoffset = luxProp(mat, "sdoffset", 0.0)
334 if usesubdiv.get() == "true":
335 nlevels = luxProp(mat, "sublevels", 1)
336 dstr += "\"loopsubdiv\" \"integer nlevels\" [%i] \"bool dmnormalsmooth\" [\"%s\"] \"bool dmsharpboundary\" [\"%s\"]"% (nlevels.get(), nsmooth.get(), sharpbound.get())
338 if usedisp.get() == "true":
339 dstr += " \"string displacementmap\" [\"%s::dispmap.scale\"] \"float dmscale\" [-1.0] \"float dmoffset\" [%f]"%(mat.getName(), sdoffset.get()) # scale is scaled in texture
341 if dstr != "": return dstr
343 return "\"trianglemesh\""
345 #-------------------------------------------------
346 # exportMesh(self, file, mesh, mats, name, portal)
347 # exports mesh to the file without any optimization
348 #-------------------------------------------------
349 def exportMesh(self, file, mesh, mats, name, portal=False):
352 for matIndex in range(len(mats)):
353 if (mats[matIndex] != None):
354 mesh_str = getMeshType(len(mesh.verts), mats[matIndex])
356 file.write("\tShape %s \"integer indices\" [\n"% mesh_str)
358 self.exportMaterialLink(file, mats[matIndex])
359 file.write("\tPortalShape %s \"integer indices\" [\n"% mesh_str)
361 ffaces = [f for f in mesh.faces if f.mat == matIndex]
363 file.write("%d %d %d\n"%(index, index+1, index+2))
365 file.write("%d %d %d\n"%(index, index+2, index+3))
366 index += len(face.verts)
367 file.write("\t] \"point P\" [\n")
370 file.write("%f %f %f\n"% tuple(vertex.co))
371 file.write("\t] \"normal N\" [\n")
377 file.write("%f %f %f\n"% tuple(normal))
379 file.write("\t] \"float uv\" [\n")
382 file.write("%f %f\n"% tuple(uv))
385 #-------------------------------------------------
386 # exportMeshOpt(self, file, mesh, mats, name, portal, optNormals)
387 # exports mesh to the file with optimization.
388 # portal: export without normals and UVs
389 # optNormals: speed and filesize optimization, flat faces get exported without normals
390 #-------------------------------------------------
391 def exportMeshOpt(self, file, mesh, mats, name, portal=False, optNormals=True):
392 shapeList, smoothFltr, shapeText = [0], [[0,1]], [""]
394 normalFltr, uvFltr, shapeText = [0], [0], ["portal"] # portal, no normals, no UVs
396 uvFltr, normalFltr, shapeText = [1], [1], ["mixed with normals"] # normals and UVs
397 if optNormals: # one pass for flat faces without normals and another pass for smoothed faces with normals, all with UVs
398 shapeList, smoothFltr, normalFltr, uvFltr, shapeText = [0,1], [[0],[1]], [0,1], [1,1], ["flat w/o normals", "smoothed with normals"]
401 usedmats = [f.mat for f in mesh.faces]
402 for matIndex in range(len(mats)):
403 if not matIndex in usedmats:
409 self.exportMaterialLink(file, mat)
410 for shape in shapeList:
411 blenderExportVertexMap = []
414 ffaces = [f for f in mesh.faces if (f.mat == matIndex) and (f.smooth in smoothFltr[shape])]
419 # v = [vertex.co[0], vertex.co[1], vertex.co[2]]
421 if normalFltr[shape]:
423 # v.extend(vertex.no)
428 if (uvFltr[shape]) and (mesh.faceUV):
429 # v.extend(face.uv[index])
430 v.append(face.uv[index])
431 blenderVIndex = vertex.index
434 if (blenderVIndex < len(blenderExportVertexMap)):
435 for exportVIndex in blenderExportVertexMap[blenderVIndex]:
436 v2 = exportVerts[exportVIndex]
437 if (length==len(v2)) and (v == v2):
438 newExportVIndex = exportVIndex
440 if (newExportVIndex < 0):
441 newExportVIndex = len(exportVerts)
442 exportVerts.append(v)
443 while blenderVIndex >= len(blenderExportVertexMap):
444 blenderExportVertexMap.append([])
445 blenderExportVertexMap[blenderVIndex].append(newExportVIndex)
446 exportVIndices.append(newExportVIndex)
448 exportFaces.append(exportVIndices)
449 if (len(exportVerts)>0):
450 mesh_str = self.getMeshType(len(exportVerts), mats[matIndex])
452 file.write("\tPortalShape %s \"integer indices\" [\n"% mesh_str)
454 file.write("\tShape %s \"integer indices\" [\n"% mesh_str)
455 for face in exportFaces:
456 file.write("%d %d %d\n"%(face[0], face[1], face[2]))
458 file.write("%d %d %d\n"%(face[0], face[2], face[3]))
459 file.write("\t] \"point P\" [\n")
460 # for vertex in exportVerts:
461 # file.write("%f %f %f\n"%(vertex[0], vertex[1], vertex[2]))
462 file.write("".join(["%f %f %f\n"%tuple(vertex[0]) for vertex in exportVerts]))
463 if normalFltr[shape]:
464 file.write("\t] \"normal N\" [\n")
465 # for vertex in exportVerts:
466 # file.write("%f %f %f\n"%(vertex[3], vertex[4], vertex[5]))
467 file.write("".join(["%f %f %f\n"%tuple(vertex[1]) for vertex in exportVerts]))
468 if (uvFltr[shape]) and (mesh.faceUV):
469 file.write("\t] \"float uv\" [\n")
470 # for vertex in exportVerts:
471 # file.write("%f %f\n"%(vertex[6], vertex[7]))
472 file.write("".join(["%f %f\n"%tuple(vertex[2]) for vertex in exportVerts]))
474 if (uvFltr[shape]) and (mesh.faceUV):
475 file.write("\t] \"float uv\" [\n")
476 # for vertex in exportVerts:
477 # file.write("%f %f\n"%(vertex[3], vertex[4]))
478 file.write("".join(["%f %f\n"%tuple(vertex[1]) for vertex in exportVerts]))
480 print(" shape(%s): %d vertices, %d faces"%(shapeText[shape], len(exportVerts), len(exportFaces)))
482 #-------------------------------------------------
483 # exportMeshes(self, file)
484 # exports meshes that uses instancing (meshes that are used by at least "instancing_threshold" objects)
485 #-------------------------------------------------
486 def exportMeshes(self, file):
487 scn = Scene.GetCurrent()
488 instancing_threshold = luxProp(scn, "instancing_threshold", 2).get()
489 mesh_optimizing = luxProp(scn, "mesh_optimizing", True).get()
491 for (mesh_name, objs) in self.meshes.items():
492 allow_instancing = True
493 mats = getMaterials(objs[0]) # mats = obj.getData().getMaterials()
494 for mat in mats: # don't instance if one of the materials is emissive
495 if (mat!=None) and (luxProp(mat, "type", "").get()=="light"):
496 allow_instancing = False
497 for obj in objs: # don't instance if the objects with same mesh uses different materials
498 ms = getMaterials(obj)
500 allow_instancing = False
501 if obj.modifiers.__len__() > 0:
502 allow_instancing = False
503 if allow_instancing and (len(objs) > instancing_threshold):
504 del self.meshes[mesh_name]
505 mesh.getFromObject(objs[0], 0, 1)
506 print("blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces)))
507 file.write("ObjectBegin \"%s\"\n"%mesh_name)
509 if (mesh_optimizing):
510 self.exportMeshOpt(file, mesh, mats, mesh_name)
512 self.exportMesh(file, mesh, mats, mesh_name)
513 file.write("ObjectEnd # %s\n\n"%mesh_name)
516 #-------------------------------------------------
517 # exportObjects(self, file)
518 # exports objects to the file
519 #-------------------------------------------------
520 def exportObjects(self, file):
521 scn = Scene.GetCurrent()
522 cam = scn.getCurrentCamera().data
523 objectmblur = luxProp(cam, "objectmblur", "true")
524 usemblur = luxProp(cam, "usemblur", "false")
525 mesh_optimizing = luxProp(scn, "mesh_optimizing", True).get()
527 for [obj, matrix] in self.objects:
528 print("object: %s"%(obj.getName()))
529 mesh_name = obj.getData(name_only=True)
532 if(objectmblur.get() == "true" and usemblur.get() == "true"):
534 frame = Blender.Get('curframe')
535 Blender.Set('curframe', frame+1)
536 m1 = 1.0*matrix # multiply by 1.0 to get a copy of orignal matrix (will be frame-independant)
537 Blender.Set('curframe', frame)
539 print(" motion blur")
542 if motion: # motion-blur only works with instances, so ensure mesh is exported as instance first
543 if mesh_name in self.meshes:
544 del self.meshes[mesh_name]
545 mesh.getFromObject(obj, 0, 1)
546 mats = getMaterials(obj)
547 print(" blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces)))
548 file.write("ObjectBegin \"%s\"\n"%mesh_name)
549 if (mesh_optimizing):
550 self.exportMeshOpt(file, mesh, mats, mesh_name)
552 self.exportMesh(file, mesh, mats, mesh_name)
553 file.write("ObjectEnd # %s\n\n"%mesh_name)
555 file.write("AttributeBegin # %s\n"%obj.getName())
556 file.write("\tTransform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
557 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
558 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
559 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
560 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
562 file.write("\tTransformBegin\n")
563 file.write("\t\tIdentity\n")
564 file.write("\t\tTransform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
565 %(motion[0][0], motion[0][1], motion[0][2], motion[0][3],\
566 motion[1][0], motion[1][1], motion[1][2], motion[1][3],\
567 motion[2][0], motion[2][1], motion[2][2], motion[2][3],\
568 motion[3][0], motion[3][1], motion[3][2], motion[3][3]))
569 file.write("\t\tCoordinateSystem \"%s\"\n"%(obj.getName()+"_motion"))
570 file.write("\tTransformEnd\n")
571 if mesh_name in self.meshes:
572 mesh.getFromObject(obj, 0, 1)
573 mats = getMaterials(obj)
574 print(" blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces)))
575 if (mesh_optimizing):
576 self.exportMeshOpt(file, mesh, mats, mesh_name)
578 self.exportMesh(file, mesh, mats, mesh_name)
580 print(" instance %s"%(mesh_name))
582 file.write("\tMotionInstance \"%s\" 0.0 1.0 \"%s\"\n"%(mesh_name, obj.getName()+"_motion"))
584 file.write("\tObjectInstance \"%s\"\n"%mesh_name)
585 file.write("AttributeEnd\n\n")
588 #-------------------------------------------------
589 # exportPortals(self, file)
590 # exports portals objects to the file
591 #-------------------------------------------------
592 def exportPortals(self, file):
593 scn = Scene.GetCurrent()
594 mesh_optimizing = luxProp(scn, "mesh_optimizing", True).get()
596 for [obj, matrix] in self.portals:
597 print("portal: %s"%(obj.getName()))
598 file.write("\tTransform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
599 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
600 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
601 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
602 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
603 mesh_name = obj.getData(name_only=True)
604 mesh.getFromObject(obj, 0, 1)
605 mats = getMaterials(obj) # mats = obj.getData().getMaterials()
606 if (mesh_optimizing):
607 self.exportMeshOpt(file, mesh, mats, mesh_name, True)
609 self.exportMesh(file, mesh, mats, mesh_name, True)
612 #-------------------------------------------------
613 # exportLights(self, file)
614 # exports lights to the file
615 #-------------------------------------------------
616 def exportLights(self, file):
617 for [obj, matrix] in self.lights:
618 ltype = obj.getData(mesh=1).getType() # data
619 if (ltype == Lamp.Types["Lamp"]) or (ltype == Lamp.Types["Spot"]) or (ltype == Lamp.Types["Area"]):
620 print("light: %s"%(obj.getName()))
621 if ltype == Lamp.Types["Area"]:
622 (str, link) = luxLight("", "", obj, None, 0)
624 if ltype == Lamp.Types["Area"]: file.write("AttributeBegin # %s\n"%obj.getName())
625 else: file.write("TransformBegin # %s\n"%obj.getName())
626 file.write("\tTransform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
627 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
628 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
629 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
630 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
631 col = obj.getData(mesh=1).col # data
632 energy = obj.getData(mesh=1).energy # data
633 if ltype == Lamp.Types["Lamp"]:
634 lightgroup = luxProp(obj, "light.lightgroup", "default")
635 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
636 file.write("LightGroup \"%s\"\n"%lightgroup.get())
637 (str, link) = luxLamp("", "", obj, None, 0)
638 file.write(str+"LightSource \"point\""+link+"\n")
639 if ltype == Lamp.Types["Spot"]:
640 (str, link) = luxSpot("", "", obj, None, 0)
642 proj = luxProp(obj, "light.usetexproj", "false")
643 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
644 lightgroup = luxProp(obj, "light.lightgroup", "default")
645 file.write("LightGroup \"%s\"\n"%lightgroup.get())
646 if(proj.get() == "true"):
647 file.write("Rotate 180 0 1 0\n")
648 file.write("LightSource \"projection\" \"float fov\" [%f]"%(obj.getData(mesh=1).spotSize))
650 file.write("LightSource \"spot\" \"point from\" [0 0 0] \"point to\" [0 0 -1] \"float coneangle\" [%f] \"float conedeltaangle\" [%f]"\
651 %(obj.getData(mesh=1).spotSize*0.5, obj.getData(mesh=1).spotSize*0.5*obj.getData(mesh=1).spotBlend)) # data
652 file.write(link+"\n")
653 if ltype == Lamp.Types["Area"]:
654 lightgroup = luxProp(obj, "light.lightgroup", "default")
655 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
656 file.write("LightGroup \"%s\"\n"%lightgroup.get())
657 file.write("\tAreaLightSource \"area\"")
659 # file.write(luxLight("", "", obj, None, 0))
661 areax = obj.getData(mesh=1).getAreaSizeX()
662 # lamps "getAreaShape()" not implemented yet - so we can't detect shape! Using square as default
664 if (True): areay = areax
665 else: areay = obj.getData(mesh=1).getAreaSizeY()
666 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})
667 if ltype == Lamp.Types["Area"]: file.write("AttributeEnd # %s\n"%obj.getName())
668 else: file.write("TransformEnd # %s\n"%obj.getName())
672 #-------------------------------------------------
673 # exportVolumes(self, file)
674 # exports volumes to the file
675 #-------------------------------------------------
676 def exportVolumes(self, file):
677 for [obj, matrix] in self.volumes:
678 print("volume: %s"%(obj.getName()))
679 file.write("# Volume: %s\n"%(obj.getName()))
681 # trickery to obtain objectspace boundingbox AABB
682 mat = obj.matrixWorld.copy().invert()
683 bb = [vec * mat for vec in obj.getBoundBox()]
684 minx = miny = minz = 100000000000000.0
685 maxx = maxy = maxz = -100000000000000.0
687 if (vec[0] < minx): minx = vec[0]
688 if (vec[1] < miny): miny = vec[1]
689 if (vec[2] < minz): minz = vec[2]
690 if (vec[0] > maxx): maxx = vec[0]
691 if (vec[1] > maxy): maxy = vec[1]
692 if (vec[2] > maxz): maxz = vec[2]
694 file.write("Transform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
695 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
696 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
697 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
698 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
700 str_opt = (" \"point p0\" [%f %f %f] \"point p1\" [%f %f %f]"%(minx, miny, minz, maxx, maxy, maxz))
701 mats = getMaterials(obj)
702 if (len(mats)>0) and (mats[0]!=None) and (luxProp(mats[0], "type", "").get()=="boundvolume"):
704 (str, link) = luxMaterialBlock("", "", "", mat, None, 0, str_opt)
705 file.write("%s"%link)
709 # Note - radiance - this is a work in progress
710 def luxFlashBlock(camObj):
712 str += "CoordSysTransform \"camera\"\n"
714 str += "Texture \"camflashtex\" \"color\" \"blackbody\" \"float temperature\" [5500.0]"
715 str += "AreaLightSource \"area\" \"texture L\" [\"camflashtex\"] \"float power\" [100.000000] \"float efficacy\" [17.000000] \"float gain\" [1.000000]\n"
719 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"
724 ######################################################
726 ######################################################
728 def save_lux(filename, unindexedname):
730 export_total_steps = 12.0
732 global meshlist, matnames, lxs_filename, geom_filename, geom_pfilename, mat_filename, mat_pfilename, vol_filename, vol_pfilename, LuxIsGUI
734 global render_status_text
736 render_status_text = 'Exporting...'
739 print("Lux Render Export started...\n")
740 time1 = Blender.sys.time()
741 scn = Scene.GetCurrent()
743 filepath = os.path.dirname(filename)
744 filebase = os.path.splitext(os.path.basename(filename))[0]
746 lxs_filename = filename
748 geom_filename = os.path.join(filepath, filebase + "-geom.lxo")
749 geom_pfilename = filebase + "-geom.lxo"
751 mat_filename = os.path.join(filepath, filebase + "-mat.lxm")
752 mat_pfilename = filebase + "-mat.lxm"
754 vol_filename = os.path.join(filepath, filebase + "-vol.lxv")
755 vol_pfilename = filebase + "-vol.lxv"
757 ### Zuegs: initialization for export class
758 export = luxExport(Blender.Scene.GetCurrent())
760 # check if a light is present
761 envtype = luxProp(scn, "env.type", "infinite").get()
762 if envtype == "sunsky":
764 for obj in scn.objects:
765 if (obj.getType() == "Lamp") and ((obj.Layers & scn.Layers) > 0):
766 if obj.getData(mesh=1).getType() == 1: # sun object # data
768 if not(export.analyseScene()) and not(envtype == "infinite") and not((envtype == "sunsky") and (sun != None)):
769 print("ERROR: No light source found")
770 Draw.PupMenu("ERROR: No light source found%t|OK%x1")
771 render_status_text = ''
772 render_status = False
773 Blender.Window.QRedrawAll()
777 if LuxIsGUI: DrawProgressBar(0.0/export_total_steps,'Setting up Scene file')
779 class output_proxy():
781 combine_all_output = False
784 if self.f is not None: self.f.close()
785 def write(self, str):
786 if self.f is not None:
790 class file_output(output_proxy):
791 def __init__(self,filename):
792 self.f = open(filename, "w")
794 from threading import Thread
795 class pipe_output(output_proxy, Thread):
796 combine_all_output = True
798 def __init__(self, xr,yr, haltspp, filename):
799 Thread.__init__(self)
801 self.filename = filename
802 self.haltspp = haltspp
807 bintype = "luxconsole"
808 self.load_result = True
810 bintype = "luxrender"
812 print("pipe: using %s" % bintype)
814 self.p = get_lux_pipe(scn, 1, bintype)
815 self.f = self.p.stdin
817 global render_status_text
820 render_status_text = "Rendering ..."
821 Blender.Window.QRedrawAll()
825 if self.load_result: self.data = self.p.communicate()[0]
827 if self.load_result: # self.load_image()
829 print("LuxRender process finished")
832 def load_image(self):
833 i = Blender.Image.Load(self.filename)
838 print("processing %i image bytes" % len(self.data))
839 i = Blender.Image.New('luxrender', self.xr, self.yr, 32)
842 raw_image.append(ord(j))
845 for y in range(self.yr-1, -1, -1):
846 for x in range(0, self.xr):
847 i.setPixelI(x,y, raw_image[bi:bi+3]+[0])
851 def update_status(self):
852 global render_status_text
854 render_status = False
855 render_status_text = "Rendering complete"
856 if self.haltspp>0: render_status_text += ", check Image Editor window"
857 Blender.Window.QRedrawAll()
859 use_pipe_output = luxProp(scn, "pipe", "false").get() == "true" and luxProp(scn, "run", "true").get() == "true"
861 file = output_proxy()
863 if luxProp(scn, "lxs", "true").get()=="true" or use_pipe_output:
864 ##### Determine/open files
866 print("using pipe output")
867 print("Exporting scene to pipe")
868 xr,yr = get_render_resolution(scn)
869 file = pipe_output(xr, yr,
870 luxProp(scn, "haltspp", 0).get(),
871 os.path.join(filepath, filebase + ".png")
874 print("using file output")
875 print("Exporting scene to '" + filename + "'...\n")
876 file = file_output(filename)
878 ##### Write Header ######
879 file.write("# Lux Render v0.6 Scene File\n")
880 file.write("# Exported by LuxBlend Blender Exporter\n")
883 ##### Write camera ######
884 camObj = scn.getCurrentCamera()
886 if LuxIsGUI: DrawProgressBar(1.0/export_total_steps,'Exporting Camera')
888 print("processing Camera...")
890 cammblur = luxProp(cam, "cammblur", "true")
891 usemblur = luxProp(cam, "usemblur", "false")
893 matrix = camObj.getMatrix()
896 if(cammblur.get() == "true" and usemblur.get() == "true"):
898 frame = Blender.Get('curframe')
899 Blender.Set('curframe', frame+1)
900 m1 = 1.0*matrix # multiply by 1.0 to get a copy of original matrix (will be frame-independant)
901 Blender.Set('curframe', frame)
903 # Motion detected, write endtransform
904 print(" motion blur")
908 target = pos + forwards
910 file.write("TransformBegin\n")
911 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] ))
912 file.write(" CoordinateSystem \"CameraEndTransform\"\n")
913 file.write("TransformEnd\n\n")
915 # Write original lookat transform
917 forwards = -matrix[2]
918 target = pos + forwards
920 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] ))
921 file.write(luxCamera(camObj.data, scn.getRenderingContext()))
923 file.write("\n \"string endtransform\" [\"CameraEndTransform\"]")
927 if LuxIsGUI: DrawProgressBar(2.0/export_total_steps,'Exporting Film Settings')
928 ##### Write film ######
929 file.write(luxFilm(scn))
932 if LuxIsGUI: DrawProgressBar(3.0/export_total_steps,'Exporting Pixel Filter')
933 ##### Write Pixel Filter ######
934 file.write(luxPixelFilter(scn))
937 if LuxIsGUI: DrawProgressBar(4.0/export_total_steps,'Exporting Sampler')
938 ##### Write Sampler ######
939 file.write(luxSampler(scn))
942 if LuxIsGUI: DrawProgressBar(5.0/export_total_steps,'Exporting Surface Integrator')
943 ##### Write Surface Integrator ######
944 file.write(luxSurfaceIntegrator(scn))
947 if LuxIsGUI: DrawProgressBar(6.0/export_total_steps,'Exporting Volume Integrator')
948 ##### Write Volume Integrator ######
949 file.write(luxVolumeIntegrator(scn))
952 if LuxIsGUI: DrawProgressBar(7.0/export_total_steps,'Exporting Accelerator')
953 ##### Write Acceleration ######
954 file.write(luxAccelerator(scn))
957 ########## BEGIN World
959 file.write("WorldBegin\n")
962 ########## World scale
963 #scale = luxProp(scn, "global.scale", 1.0).get()
965 # # TODO: not working yet !!!
966 # # TODO: propabily scale needs to be applyed on camera coords too
967 # 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))
970 if LuxIsGUI: DrawProgressBar(8.0/export_total_steps,'Exporting Environment')
971 ##### Write World Background, Sunsky or Env map ######
972 env = luxEnvironment(scn)
974 file.write("AttributeBegin\n")
976 export.exportPortals(file)
977 file.write("AttributeEnd\n")
980 # Note - radiance - this is a work in progress
981 # flash = luxFlashBlock(camObj)
983 # file.write("# Camera flash lamp\n")
984 # file.write("AttributeBegin\n")
985 # #file.write("CoordSysTransform \"camera\"\n")
987 # file.write("AttributeEnd\n\n")
989 #### Write material & geometry file includes in scene file
990 if not file.combine_all_output: file.write("Include \"%s\"\n\n" %(mat_pfilename))
991 if not file.combine_all_output: file.write("Include \"%s\"\n\n" %(geom_pfilename))
992 if not file.combine_all_output: file.write("Include \"%s\"\n\n" %(vol_pfilename))
994 if luxProp(scn, "lxm", "true").get()=="true" or use_pipe_output:
995 if LuxIsGUI: DrawProgressBar(9.0/export_total_steps,'Exporting Materials')
996 ##### Write Material file #####
997 if not file.combine_all_output: print("Exporting materials to '" + mat_filename + "'...\n")
998 mat_file = open(mat_filename, 'w') if not file.combine_all_output else file
1000 export.exportMaterials(mat_file)
1002 if not file.combine_all_output: mat_file.close()
1004 if luxProp(scn, "lxo", "true").get()=="true" or use_pipe_output:
1005 if LuxIsGUI: DrawProgressBar(10.0/export_total_steps,'Exporting Geometry')
1006 ##### Write Geometry file #####
1007 if not file.combine_all_output: print("Exporting geometry to '" + geom_filename + "'...\n")
1008 geom_file = open(geom_filename, 'w') if not file.combine_all_output else file
1011 export.exportLights(geom_file)
1012 export.exportMeshes(geom_file)
1013 export.exportObjects(geom_file)
1015 if not file.combine_all_output: geom_file.close()
1017 if luxProp(scn, "lxv", "true").get()=="true" or use_pipe_output:
1018 if LuxIsGUI: DrawProgressBar(11.0/export_total_steps,'Exporting Volumes')
1019 ##### Write Volume file #####
1020 if not file.combine_all_output: print("Exporting volumes to '" + vol_filename + "'...\n")
1021 vol_file = open(vol_filename, 'w') if not file.combine_all_output else file
1024 export.exportVolumes(vol_file)
1026 if not file.combine_all_output: vol_file.close()
1028 render_status_text = ''
1029 render_status = False
1030 Blender.Window.QRedrawAll()
1032 if luxProp(scn, "lxs", "true").get()=="true" or use_pipe_output:
1034 file.write("WorldEnd\n\n")
1037 if LuxIsGUI: DrawProgressBar(12.0/export_total_steps,'Export Finished')
1038 print("Finished.\n")
1041 time2 = Blender.sys.time()
1042 print("Processing time: %f\n" %(time2-time1))
1045 #if luxProp(scn, "haltspp", 0).get() > 0:
1046 # Wait for piped luxconsole render thread to end
1049 # Don't launch it again as a piped scene is started implicitly
1054 ########################################################################
1055 #### Construct server string argument
1056 ########################################################################
1058 def networkstring(scn):
1060 if (luxProp(scn,"network","false").get() == "true"):
1061 if (luxProp(scn,"network_use_file","false").get() == "true"):
1062 print("read network servers from file: "+ luxProp(scn,"network_file_path","false").get())
1063 f = open(luxProp(scn,"network_file_path","false").get())
1066 print("add server :" + s)
1067 servers_string=servers_string+" -u "+ s
1070 if luxProp(scn,"network_servers","").get():
1071 for server in luxProp(scn,"network_servers","").get().split(","):
1072 servers_string=servers_string+" -u "+ server
1073 return servers_string
1076 #########################################################################
1077 ### LAUNCH LuxRender AND RENDER CURRENT SCENE
1078 #########################################################################
1080 def get_lux_exec(scn, type="luxrender"):
1082 #get blenders 'bpydata' directory
1083 datadir=Blender.Get("datadir")
1085 ic = luxProp(scn, "lux", "").get()
1086 ic = Blender.sys.dirname(ic) + os.sep + type
1088 if osys.platform == "win32": ic = ic + ".exe"
1090 if type=="luxrender" and osys.platform == "darwin": ic = ic + ".app/Contents/MacOS/luxrender"
1094 def get_lux_args(filename, extra_args=[], anim=False):
1095 ostype = osys.platform
1096 scn = Scene.GetCurrent()
1098 ic = get_lux_exec(scn, type=(anim and 'luxconsole' or 'luxrender'))
1100 servers_string = networkstring(scn)
1101 update_int=luxProp(scn,"newtork_interval",180).get()
1103 checkluxpath = luxProp(scn, "checkluxpath", True).get()
1105 if sys.exists(ic) != 1:
1106 Draw.PupMenu("Error: Lux renderer not found. Please set path on System page.%t|OK")
1108 autothreads = luxProp(scn, "autothreads", "true").get()
1109 threads = luxProp(scn, "threads", 1).get()
1110 luxnice = luxProp(scn, "luxnice", 0).get()
1111 noopengl = luxProp(scn, "noopengl", "false").get()
1113 if noopengl == "true":
1114 extra_args.append("--noopengl")
1116 lux_args = "\"%s\" " % ic
1118 extra_args.append('%s'%servers_string)
1119 extra_args.append("-i %d " % update_int)
1121 if autothreads != "true":
1122 extra_args.append("--threads=%d " % threads)
1124 lux_args2 = ' '.join(extra_args)
1127 lux_args2 = " - " + lux_args2
1129 filename = "\"%s\"" % filename
1130 lux_args2 = lux_args2 + filename
1132 lux_args += lux_args2
1134 if ostype == "win32":
1136 if luxnice > 15: prio = "/low"
1137 elif luxnice > 5: prio = "/belownormal"
1138 elif luxnice > -5: prio = "/normal"
1139 elif luxnice > -15: prio = "/abovenormal"
1140 else: prio = "/high"
1143 cmd = "start /b %s \"\" %s" % (prio, lux_args)
1145 cmd = "start /WAIT %s \"\" %s" % (prio, lux_args)
1147 # if ostype == "linux2" or ostype == "darwin":
1150 cmd = "(nice -n %d %s)&"%(luxnice, lux_args)
1152 cmd = "(nice -n %d %s)"%(luxnice, lux_args)
1154 return cmd, lux_args2
1156 def get_lux_pipe(scn, buf = 1024, type="luxconsole"):
1157 bin = "\"%s\"" % get_lux_exec(scn, type)
1159 print("piping to lux binary: " + bin)
1161 PIPE = subprocess.PIPE
1163 cmd, raw_args = get_lux_args('-',
1164 extra_args=['-b'] if type=="luxconsole" else []
1167 return subprocess.Popen(bin + raw_args, shell=True, bufsize=buf, stdin=PIPE, stdout=PIPE, stderr=PIPE)
1169 def launchLux(filename):
1170 cmd, raw_args = get_lux_args(filename, extra_args=[])
1171 print("Running Luxrender:\n"+cmd)
1174 def launchLuxWait(filename, anim=False):
1175 ostype = osys.platform
1176 cmd, raw_args = get_lux_args(filename, extra_args=[], anim=anim)
1178 if ostype == "win32":
1181 # if ostype == "linux2" or ostype == "darwin":
1183 subprocess.call(cmd,shell=True)
1185 #### SAVE ANIMATION ####
1188 #def save_anim(filename):
1190 # scn = Scene.GetCurrent()
1191 # to = luxProp(scn, 'export.threaded', 'true').get()
1192 # run = luxProp(scn, "run", "true").get()
1193 # deflt = luxProp(scn, "default", "true").get()
1194 # if to == 'true' and run == 'true' and deflt == 'false':
1196 # anim_thread = threading.Thread(target=save_anim_real, args=(filename,True))
1197 # anim_thread.start()
1199 # save_anim_real(filename)
1201 def save_anim(filename, as_thread=False):
1202 if as_thread: print('SAR thread started')
1203 global MatSaved, LuxIsGUI
1206 startF = Blender.Get('staframe')
1207 endF = Blender.Get('endframe')
1208 scn = Scene.GetCurrent()
1210 Run = luxProp(scn, "run", "true").get()
1213 haltspp = luxProp(scn, "haltspp", 0).get()
1215 Draw.PupMenu("ERROR: You must set a limit for spp (Output->halt) when doing animation and the 'run' flag is switched on")
1220 print("\n\nRendering animation (frame %i to %i)\n\n"%(startF, endF))
1222 v_frame = Blender.Get('curframe')
1224 for i in range (startF, endF+1):
1225 # Seems to get stuck unless we redraw the UI
1227 # Window.QRedrawAll()
1228 Blender.Set('curframe', i)
1229 print("Rendering frame %i"%(i))
1231 frameindex = ("-%05d" % (i)) + ".lxs"
1232 indexedname = sys.makename(filename, frameindex)
1233 unindexedname = filename
1234 luxProp(scn, "filename", Blender.Get("filename")).set(sys.makename(filename, "-%05d" % (Blender.Get('curframe'))))
1237 if save_lux(filename, unindexedname):
1238 launchLuxWait(filename, anim=True)
1240 save_lux(indexedname, unindexedname)
1243 # Seems to get stuck unless we redraw the UI
1245 # Window.QRedrawAll()
1247 Blender.Set('curframe', v_frame)
1249 print("\n\nFinished Rendering animation\n")
1250 if as_thread: print('SAR thread finished')
1252 #### SAVE STILL (hackish...) ####
1255 #def save_still(filename):
1257 # scn = Scene.GetCurrent()
1258 # to = luxProp(scn, 'export.threaded', 'true').get()
1259 # if to == 'true' and luxProp(scn, "run", "true").get() == "true":
1261 # still_thread = threading.Thread(target=save_still_real, args=(filename,))
1262 # still_thread.start()
1264 # save_still_real(filename)
1266 def save_still(filename):
1267 global MatSaved, runRenderAfterExport
1268 scn = Scene.GetCurrent()
1269 luxProp(scn, "filename", Blender.Get("filename")).set(sys.makename(filename, ""))
1271 unindexedname = filename
1272 # Seems to get stuck unless we redraw the UI
1274 # Window.QRedrawAll()
1275 if save_lux(filename, unindexedname):
1276 if runRenderAfterExport and luxProp(scn, "pipe", "false").get() == "false": #(run == None and luxProp(scn, "run", "true").get() == "true") or run:
1279 # Seems to get stuck unless we redraw the UI
1281 # Window.QRedrawAll()
1284 ######################################################
1286 ######################################################
1288 def base64value(char):
1289 if 64 < ord(char) < 91: return ord(char)-65
1290 if 96 < ord(char) < 123: return ord(char)-97+26
1291 if 47 < ord(char) < 58: return ord(char)-48+52
1292 if char == '+': return 62
1295 def decodeIconStr(s):
1296 buf = BGL.Buffer(BGL.GL_BYTE, [16,16,4])
1301 buf[y][x][c] = int(base64value(s[offset])*4.048)
1305 def decodeLogoStr(s):
1306 buf = BGL.Buffer(BGL.GL_BYTE, [18,118,4])
1309 for x in range(118):
1311 buf[y][x][c] = int(base64value(s[offset])*4.048)
1315 def decodeArrowStr(s):
1316 buf = BGL.Buffer(BGL.GL_BYTE, [22,22,4])
1321 buf[y][x][c] = int(base64value(s[offset])*4.048)
1325 def decodeBarStr(s):
1326 buf = BGL.Buffer(BGL.GL_BYTE, [17,138,4])
1329 for x in range(138):
1331 buf[y][x][c] = int(base64value(s[offset])*4.048)
1335 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")
1337 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")
1339 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")
1342 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")
1343 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")
1344 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")
1345 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")
1346 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")
1347 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")
1348 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")
1349 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")
1350 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")
1351 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")
1352 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")
1353 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")
1354 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")
1356 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")
1358 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")
1360 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")
1362 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")
1364 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")
1366 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")
1368 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")
1370 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")
1372 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")
1375 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")
1377 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//")
1379 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")
1381 def drawIcon(icon, x, y):
1382 BGL.glEnable(BGL.GL_BLEND)
1383 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1384 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1385 BGL.glDrawPixels(16, 16, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1386 BGL.glDisable(BGL.GL_BLEND)
1388 def drawArrow(icon, x, y):
1389 BGL.glEnable(BGL.GL_BLEND)
1390 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1391 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1392 BGL.glDrawPixels(22, 22, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1393 BGL.glDisable(BGL.GL_BLEND)
1395 def drawLogo(icon, x, y):
1396 BGL.glEnable(BGL.GL_BLEND)
1397 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1398 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1399 BGL.glDrawPixels(118, 18, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1400 BGL.glDisable(BGL.GL_BLEND)
1402 def drawBar(icon, x, y):
1403 BGL.glEnable(BGL.GL_BLEND)
1404 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1405 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1406 BGL.glDrawPixels(138, 17, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1407 BGL.glDisable(BGL.GL_BLEND)
1411 #-------------------------------------------------
1413 # helper class to handle images and icons for the GUI
1414 #-------------------------------------------------
1417 def resize(self, width, height):
1419 self.height = height
1420 self.buf = BGL.Buffer(BGL.GL_BYTE, [width,height,4]) # GL buffer
1421 def __init__(self, width=0, height=0):
1422 self.resize(width, height)
1423 def draw(self, x, y):
1424 BGL.glEnable(BGL.GL_BLEND)
1425 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1426 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1427 BGL.glDrawPixels(self.width, self.height, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, self.buf)
1428 BGL.glDisable(BGL.GL_BLEND)
1429 def decodeStr(self, width, height, s):
1430 self.resize(width, height)
1432 for y in range(self.height):
1433 for x in range(self.width):
1435 self.buf[y][x][c] = int(base64value(s[offset])*4.048)
1438 def decodeLuxConsole(self, width, height, data):
1439 self.resize(width, height)
1441 for y in range(self.height-1,-1,-1):
1442 for x in range(self.width):
1444 self.buf[y][x][c] = ord(data[offset])
1446 self.buf[y][x][3] = 255
1449 previewCache = {} # dictionary that will hold all preview images
1452 ######################################################
1454 ######################################################
1460 evtDeletePreset = 97
1461 evtSaveMaterial = 96
1462 evtLoadMaterial = 95
1463 evtDeleteMaterial = 94
1464 evtConvertMaterial = 92
1465 evtSaveMaterial2 = 91
1466 evtLoadMaterial2 = 90
1470 defaultsExclude = ['preset','filename','page','link']
1472 luxdefaults = Blender.Registry.GetKey('luxblend', True)
1473 if not(type(luxdefaults) is DictType):
1477 newluxdefaults = luxdefaults.copy()
1480 def saveluxdefaults():
1481 try: del newluxdefaults['page']
1483 try: Blender.Registry.SetKey('luxblend', newluxdefaults, True)
1490 # *** PRESETS **************************************
1491 presetsExclude = ['preset','lux','datadir','threads','filename','page','RGC','film.gamma','colorclamp','link']
1492 def getPresets(key):
1493 presets = Blender.Registry.GetKey(key, True)
1494 if not(type(presets) is DictType):
1497 def getScenePresets():
1498 presets = getPresets('luxblend_presets').copy()
1500 # radiance's hardcoded render presets:
1502 presets['0 Preview - Direct Lighting'] = {
1503 'film.displayinterval': 4,
1505 'useparamkeys': 'false',
1506 'sampler.showadvanced': 'false',
1507 'sintegrator.showadvanced': 'false',
1508 'pixelfilter.showadvanced': 'false',
1510 'sampler.type': 'lowdiscrepancy',
1511 'sampler.lowdisc.pixelsamples': 1,
1512 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
1514 'sintegrator.type': 'directlighting',
1515 'sintegrator.dlighting.maxdepth': 5,
1517 'pixelfilter.type': 'mitchell',
1518 'pixelfilter.mitchell.sharp': 0.250,
1519 'pixelfilter.mitchell.xwidth': 2.0,
1520 'pixelfilter.mitchell.ywidth': 2.0,
1521 'pixelfilter.mitchell.optmode': "slider" }
1523 presets['1 Final - MLT/Bidir Path Tracing (interior) (recommended)'] = {
1524 'film.displayinterval': 8,
1526 'useparamkeys': 'false',
1527 'sampler.showadvanced': 'false',
1528 'sintegrator.showadvanced': 'false',
1529 'pixelfilter.showadvanced': 'false',
1531 'sampler.type': 'metropolis',
1532 'sampler.metro.strength': 0.6,
1533 'sampler.metro.lmprob': 0.4,
1534 'sampler.metro.maxrejects': 512,
1535 #'sampler.metro.initsamples': 262144,
1536 'sampler.metro.usevariance': "false",
1538 'sintegrator.type': 'bidirectional',
1539 'sintegrator.bidir.bounces': 16,
1540 'sintegrator.bidir.eyedepth': 16,
1541 'sintegrator.bidir.lightdepth': 16,
1543 'pixelfilter.type': 'mitchell',
1544 'pixelfilter.mitchell.sharp': 0.250,
1545 'pixelfilter.mitchell.xwidth': 2.0,
1546 'pixelfilter.mitchell.ywidth': 2.0,
1547 'pixelfilter.mitchell.optmode': "slider" }
1549 presets['2 Final - MLT/Path Tracing (exterior)'] = {
1550 'film.displayinterval': 8,
1552 'useparamkeys': 'false',
1553 'sampler.showadvanced': 'false',
1554 'sintegrator.showadvanced': 'false',
1555 'pixelfilter.showadvanced': 'false',
1557 'sampler.type': 'metropolis',
1558 'sampler.metro.strength': 0.6,
1559 'sampler.metro.lmprob': 0.4,
1560 'sampler.metro.maxrejects': 512,
1561 #'sampler.metro.initsamples': 262144,
1562 'sampler.metro.usevariance': "false",
1564 'sintegrator.type': 'path',
1565 'sintegrator.bidir.bounces': 10,
1566 'sintegrator.bidir.maxdepth': 10,
1568 'pixelfilter.type': 'mitchell',
1569 'pixelfilter.mitchell.sharp': 0.250,
1570 'pixelfilter.mitchell.xwidth': 2.0,
1571 'pixelfilter.mitchell.ywidth': 2.0,
1572 'pixelfilter.mitchell.optmode': "slider" }
1576 presets['5 Progressive - Bidir Path Tracing (interior)'] = {
1577 'film.displayinterval': 8,
1579 'useparamkeys': 'false',
1580 'sampler.showadvanced': 'false',
1581 'sintegrator.showadvanced': 'false',
1582 'pixelfilter.showadvanced': 'false',
1584 'sampler.type': 'lowdiscrepancy',
1585 'sampler.lowdisc.pixelsamples': 1,
1586 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
1588 'sintegrator.type': 'bidirectional',
1589 'sintegrator.bidir.bounces': 16,
1590 'sintegrator.bidir.eyedepth': 16,
1591 'sintegrator.bidir.lightdepth': 16,
1593 'pixelfilter.type': 'mitchell',
1594 'pixelfilter.mitchell.sharp': 0.250,
1595 'pixelfilter.mitchell.xwidth': 2.0,
1596 'pixelfilter.mitchell.ywidth': 2.0,
1597 'pixelfilter.mitchell.optmode': "slider" }
1599 presets['6 Progressive - Path Tracing (exterior)'] = {
1600 'film.displayinterval': 8,
1602 'useparamkeys': 'false',
1603 'sampler.showadvanced': 'false',
1604 'sintegrator.showadvanced': 'false',
1605 'pixelfilter.showadvanced': 'false',
1607 'sampler.type': 'lowdiscrepancy',
1608 'sampler.lowdisc.pixelsamples': 1,
1609 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
1611 'sintegrator.type': 'path',
1612 'sintegrator.bidir.bounces': 10,
1613 'sintegrator.bidir.maxdepth': 10,
1615 'pixelfilter.type': 'mitchell',
1616 'pixelfilter.mitchell.sharp': 0.250,
1617 'pixelfilter.mitchell.xwidth': 2.0,
1618 'pixelfilter.mitchell.ywidth': 2.0,
1619 'pixelfilter.mitchell.optmode': "slider" }
1623 presets['8 Bucket - Bidir Path Tracing (interior)'] = {
1624 'film.displayinterval': 8,
1626 'useparamkeys': 'false',
1627 'sampler.showadvanced': 'false',
1628 'sintegrator.showadvanced': 'false',
1629 'pixelfilter.showadvanced': 'false',
1631 'sampler.type': 'lowdiscrepancy',
1632 'sampler.lowdisc.pixelsamples': 64,
1633 'sampler.lowdisc.pixelsampler': 'hilbert',
1635 'sintegrator.type': 'bidirectional',
1636 'sintegrator.bidir.bounces': 8,
1637 'sintegrator.bidir.eyedepth': 8,
1638 'sintegrator.bidir.lightdepth': 10,
1640 'pixelfilter.type': 'mitchell',
1641 'pixelfilter.mitchell.sharp': 0.250,
1642 'pixelfilter.mitchell.xwidth': 2.0,
1643 'pixelfilter.mitchell.ywidth': 2.0,
1644 'pixelfilter.mitchell.optmode': "slider" }
1646 presets['9 Bucket - Path Tracing (exterior)'] = {
1647 'film.displayinterval': 8,
1649 'useparamkeys': 'false',
1650 'sampler.showadvanced': 'false',
1651 'sintegrator.showadvanced': 'false',
1652 'pixelfilter.showadvanced': 'false',
1654 'sampler.type': 'lowdiscrepancy',
1655 'sampler.lowdisc.pixelsamples': 64,
1656 'sampler.lowdisc.pixelsampler': 'hilbert',
1658 'sintegrator.type': 'path',
1659 'sintegrator.bidir.bounces': 8,
1660 'sintegrator.bidir.maxdepth': 8,
1662 'pixelfilter.type': 'mitchell',
1663 'pixelfilter.mitchell.sharp': 0.333,
1664 'pixelfilter.mitchell.xwidth': 2.0,
1665 'pixelfilter.mitchell.ywidth': 2.0,
1666 'pixelfilter.mitchell.optmode': "slider" }
1670 presets['B Anim - Distributed/GI low Q'] = {
1671 'film.displayinterval': 8,
1673 'useparamkeys': 'false',
1674 'sampler.showadvanced': 'false',
1675 'sintegrator.showadvanced': 'false',
1676 'pixelfilter.showadvanced': 'false',
1678 'sampler.type': 'lowdiscrepancy',
1679 'sampler.lowdisc.pixelsamples': 16,
1680 'sampler.lowdisc.pixelsampler': 'hilbert',
1682 'sintegrator.type': 'distributedpath',
1683 'sintegrator.distributedpath.causticsonglossy': 'true',
1684 'sintegrator.distributedpath.diffuserefractdepth': 5,
1685 'sintegrator.distributedpath.indirectglossy': 'true',
1686 'sintegrator.distributedpath.directsamples': 1,
1687 'sintegrator.distributedpath.diffuserefractsamples': 1,
1688 'sintegrator.distributedpath.glossyreflectdepth': 2,
1689 'sintegrator.distributedpath.causticsondiffuse': 'false',
1690 'sintegrator.distributedpath.directsampleall': 'true',
1691 'sintegrator.distributedpath.indirectdiffuse': 'true',
1692 'sintegrator.distributedpath.specularreflectdepth': 3,
1693 'sintegrator.distributedpath.diffusereflectsamples': 1,
1694 'sintegrator.distributedpath.glossyreflectsamples': 1,
1695 'sintegrator.distributedpath.glossyrefractdepth': 5,
1696 'sintegrator.distributedpath.diffusereflectdepth': '2',
1697 'sintegrator.distributedpath.indirectsamples': 1,
1698 'sintegrator.distributedpath.indirectsampleall': 'false',
1699 'sintegrator.distributedpath.glossyrefractsamples': 1,
1700 'sintegrator.distributedpath.directdiffuse': 'true',
1701 'sintegrator.distributedpath.directglossy': 'true',
1702 'sintegrator.distributedpath.strategy': 'auto',
1703 'sintegrator.distributedpath.specularrefractdepth': 5,
1705 'pixelfilter.type': 'mitchell',
1706 'pixelfilter.mitchell.sharp': 0.333,
1707 'pixelfilter.mitchell.xwidth': 2.0,
1708 'pixelfilter.mitchell.ywidth': 2.0,
1709 'pixelfilter.mitchell.optmode': "slider" }
1711 presets['C Anim - Distributed/GI medium Q'] = {
1712 'film.displayinterval': 8,
1714 'useparamkeys': 'false',
1715 'sampler.showadvanced': 'false',
1716 'sintegrator.showadvanced': 'false',
1717 'pixelfilter.showadvanced': 'false',
1719 'sampler.type': 'lowdiscrepancy',
1720 'sampler.lowdisc.pixelsamples': 64,
1721 'sampler.lowdisc.pixelsampler': 'hilbert',
1723 'sintegrator.type': 'distributedpath',
1724 'sintegrator.distributedpath.causticsonglossy': 'true',
1725 'sintegrator.distributedpath.diffuserefractdepth': 5,
1726 'sintegrator.distributedpath.indirectglossy': 'true',
1727 'sintegrator.distributedpath.directsamples': 1,
1728 'sintegrator.distributedpath.diffuserefractsamples': 1,
1729 'sintegrator.distributedpath.glossyreflectdepth': 2,
1730 'sintegrator.distributedpath.causticsondiffuse': 'false',
1731 'sintegrator.distributedpath.directsampleall': 'true',
1732 'sintegrator.distributedpath.indirectdiffuse': 'true',
1733 'sintegrator.distributedpath.specularreflectdepth': 3,
1734 'sintegrator.distributedpath.diffusereflectsamples': 1,
1735 'sintegrator.distributedpath.glossyreflectsamples': 1,
1736 'sintegrator.distributedpath.glossyrefractdepth': 5,
1737 'sintegrator.distributedpath.diffusereflectdepth': '2',
1738 'sintegrator.distributedpath.indirectsamples': 1,
1739 'sintegrator.distributedpath.indirectsampleall': 'false',
1740 'sintegrator.distributedpath.glossyrefractsamples': 1,
1741 'sintegrator.distributedpath.directdiffuse': 'true',
1742 'sintegrator.distributedpath.directglossy': 'true',
1743 'sintegrator.distributedpath.strategy': 'auto',
1744 'sintegrator.distributedpath.specularrefractdepth': 5,
1746 'pixelfilter.type': 'mitchell',
1747 'pixelfilter.mitchell.sharp': 0.333,
1748 'pixelfilter.mitchell.xwidth': 2.0,
1749 'pixelfilter.mitchell.ywidth': 2.0,
1750 'pixelfilter.mitchell.optmode': "slider" }
1752 presets['D Anim - Distributed/GI high Q'] = {
1753 'film.displayinterval': 8,
1755 'useparamkeys': 'false',
1756 'sampler.showadvanced': 'false',
1757 'sintegrator.showadvanced': 'false',
1758 'pixelfilter.showadvanced': 'false',
1760 'sampler.type': 'lowdiscrepancy',
1761 'sampler.lowdisc.pixelsamples': 256,
1762 'sampler.lowdisc.pixelsampler': 'hilbert',
1764 'sintegrator.type': 'distributedpath',
1765 'sintegrator.distributedpath.causticsonglossy': 'true',
1766 'sintegrator.distributedpath.diffuserefractdepth': 5,
1767 'sintegrator.distributedpath.indirectglossy': 'true',
1768 'sintegrator.distributedpath.directsamples': 1,
1769 'sintegrator.distributedpath.diffuserefractsamples': 1,
1770 'sintegrator.distributedpath.glossyreflectdepth': 2,
1771 'sintegrator.distributedpath.causticsondiffuse': 'false',
1772 'sintegrator.distributedpath.directsampleall': 'true',
1773 'sintegrator.distributedpath.indirectdiffuse': 'true',
1774 'sintegrator.distributedpath.specularreflectdepth': 3,
1775 'sintegrator.distributedpath.diffusereflectsamples': 1,
1776 'sintegrator.distributedpath.glossyreflectsamples': 1,
1777 'sintegrator.distributedpath.glossyrefractdepth': 5,
1778 'sintegrator.distributedpath.diffusereflectdepth': '2',
1779 'sintegrator.distributedpath.indirectsamples': 1,
1780 'sintegrator.distributedpath.indirectsampleall': 'false',
1781 'sintegrator.distributedpath.glossyrefractsamples': 1,
1782 'sintegrator.distributedpath.directdiffuse': 'true',
1783 'sintegrator.distributedpath.directglossy': 'true',
1784 'sintegrator.distributedpath.strategy': 'auto',
1785 'sintegrator.distributedpath.specularrefractdepth': 5,
1787 'pixelfilter.type': 'mitchell',
1788 'pixelfilter.mitchell.sharp': 0.333,
1789 'pixelfilter.mitchell.xwidth': 2.0,
1790 'pixelfilter.mitchell.ywidth': 2.0,
1791 'pixelfilter.mitchell.optmode': "slider" }
1793 presets['E Anim - Distributed/GI very high Q'] = {
1794 'film.displayinterval': 8,
1796 'useparamkeys': 'false',
1797 'sampler.showadvanced': 'false',
1798 'sintegrator.showadvanced': 'false',
1799 'pixelfilter.showadvanced': 'false',
1801 'sampler.type': 'lowdiscrepancy',
1802 'sampler.lowdisc.pixelsamples': 512,
1803 'sampler.lowdisc.pixelsampler': 'hilbert',
1805 'sintegrator.type': 'distributedpath',
1806 'sintegrator.distributedpath.causticsonglossy': 'true',
1807 'sintegrator.distributedpath.diffuserefractdepth': 5,
1808 'sintegrator.distributedpath.indirectglossy': 'true',
1809 'sintegrator.distributedpath.directsamples': 1,
1810 'sintegrator.distributedpath.diffuserefractsamples': 1,
1811 'sintegrator.distributedpath.glossyreflectdepth': 2,
1812 'sintegrator.distributedpath.causticsondiffuse': 'false',
1813 'sintegrator.distributedpath.directsampleall': 'true',
1814 'sintegrator.distributedpath.indirectdiffuse': 'true',
1815 'sintegrator.distributedpath.specularreflectdepth': 3,
1816 'sintegrator.distributedpath.diffusereflectsamples': 1,
1817 'sintegrator.distributedpath.glossyreflectsamples': 1,
1818 'sintegrator.distributedpath.glossyrefractdepth': 5,
1819 'sintegrator.distributedpath.diffusereflectdepth': '2',
1820 'sintegrator.distributedpath.indirectsamples': 1,
1821 'sintegrator.distributedpath.indirectsampleall': 'false',
1822 'sintegrator.distributedpath.glossyrefractsamples': 1,
1823 'sintegrator.distributedpath.directdiffuse': 'true',
1824 'sintegrator.distributedpath.directglossy': 'true',
1825 'sintegrator.distributedpath.strategy': 'auto',
1826 'sintegrator.distributedpath.specularrefractdepth': 5,
1828 'pixelfilter.type': 'mitchell',
1829 'pixelfilter.mitchell.sharp': 0.333,
1830 'pixelfilter.mitchell.xwidth': 2.0,
1831 'pixelfilter.mitchell.ywidth': 2.0,
1832 'pixelfilter.mitchell.optmode': "slider" }
1836 def getMaterialPresets():
1837 return getPresets('luxblend_materials')
1839 def savePreset(key, name, d):
1841 presets = getPresets(key)
1843 presets[name] = d.copy()
1846 Blender.Registry.SetKey(key, presets, True)
1848 def saveScenePreset(name, d):
1850 for n in presetsExclude:
1853 savePreset('luxblend_presets', name, d)
1855 def saveMaterialPreset(name, d):
1857 for n in presetsExclude:
1860 savePreset('luxblend_materials', name, d)
1864 # **************************************************
1870 usedproperties = {} # global variable to collect used properties for storing presets
1871 usedpropertiesfilterobj = None # assign a object to only collect the properties that are assigned to this object
1873 # class to access properties (for lux settings)
1875 def __init__(self, obj, name, default):
1878 # if len(name)>31: print("Warning: property-name \"%s\" has more than 31 chars."%(name))
1879 self.hashmode = len(name)>31 # activate hash mode for keynames longer 31 chars (limited by blenders ID-prop)
1880 self.hashname = "__hash:%x"%(name.__hash__())
1881 self.default = default
1882 def parseassignment(self, s, name):
1884 if l[0] != name: print("Warning: property-name \"%s\" has hash-collide with \"%s\"."%(name, l[0]))
1886 def createassignment(self, name, value):
1887 return "%s = %s"%(name, value)
1889 global usedproperties, usedpropertiesfilterobj, luxdefaults
1892 value = self.obj.properties['luxblend'][self.name]
1893 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
1894 usedproperties[self.name] = value
1898 value = self.parseassignment(self.obj.properties['luxblend'][self.hashname], self.name)
1899 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
1900 usedproperties[self.name] = value
1903 if self.obj.__class__.__name__ == "Scene": # luxdefaults only for global setting
1905 value = luxdefaults[self.name]
1906 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
1907 usedproperties[self.name] = value
1910 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
1911 usedproperties[self.name] = self.default
1913 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
1914 usedproperties[self.name] = self.default
1927 def set(self, value):
1928 global newluxdefaults
1930 if self.hashmode: n, v = self.hashname, self.createassignment(self.name, value)
1931 else: n, v = self.name, value
1932 if value is not None:
1933 try: self.obj.properties['luxblend'][n] = v
1934 except (KeyError, TypeError):
1935 self.obj.properties['luxblend'] = {}
1936 self.obj.properties['luxblend'][n] = v
1938 try: del self.obj.properties['luxblend'][n]
1940 if self.obj.__class__.__name__ == "Scene": # luxdefaults only for global setting
1941 # value has changed, so this are user settings, remove preset reference
1942 if not(self.name in defaultsExclude):
1943 newluxdefaults[self.name] = value
1944 try: self.obj.properties['luxblend']['preset']=""
1948 try: del self.obj.properties['luxblend'][self.name]
1950 try: del self.obj.properties['luxblend'][self.hashname]
1954 if type(v) == types.FloatType: return float(v)
1956 if type(v) == types.StringType: return float(v.split(" ")[0])
1959 if type(v) == types.FloatType: return float(v)
1961 if type(v) == types.StringType: return float(v.split(" ")[0])
1965 try: return int(self.get())
1966 except: return int(self.default)
1968 return self.getVector()
1969 def getVector(self):
1971 if type(v) in [types.FloatType, types.IntType]: return (float(v), float(v), float(v))
1974 if type(v) == types.StringType: l = self.get().split(" ")
1977 if (l==None) or (len(l) != 3): l = self.default.split(" ")
1978 return (float(l[0]), float(l[1]), float(l[2]))
1979 except AttributeError:
1980 return (float(l[0]), float(l[0]), float(l[0]))
1982 def getVectorStr(self):
1983 return "%f %f %f"%self.getVector()
1985 return type(self.get()) == types.FloatType
1988 return "%f %f %f"%(rg(col[0]), rg(col[1]),rg(col[2]))
1989 def setRGB(self, value):
1990 self.set("%f %f %f"%(value[0], value[1], value[2]))
1991 def setVector(self, value):
1992 self.set("%f %f %f"%(value[0], value[1], value[2]))
1995 # class to access blender attributes (for lux settings)
1997 def __init__(self, obj, name):
2002 return getattr(self.obj, self.name)
2006 return float(self.get())
2008 return int(self.get())
2019 def set(self, value):
2021 setattr(self.obj, self.name, value)
2025 # class for dynamic gui
2027 def __init__(self, y=200):
2028 self.x = 110 # left start position after captions
2029 self.xmax = 110+2*(140+4)
2031 self.w = 140 # default element width in pixels
2032 self.h = 18 # default element height in pixels
2036 self.resethmax = False
2037 def getRect(self, wu, hu):
2038 w = int(self.w * wu + self.xgap * (wu-1))
2039 h = int(self.h * hu + self.ygap * (hu-1))
2040 if self.x + w > self.xmax: self.newline()
2041 if self.resethmax: self.hmax = 0; self.resethmax = False
2042 rect = [int(self.x), int(self.y-h), int(w), int(h)]
2043 self.x += int(w + self.xgap)
2044 if h+self.ygap > self.hmax: self.hmax = int(h+self.ygap)
2046 def newline(self, title="", distance=0, level=0, icon=None, color=None):
2048 if not(self.resethmax): self.y -= int(self.hmax + distance)
2049 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)
2050 if icon!=None: drawIcon(icon, 2+level*10, self.y-16)
2051 self.resethmax = True
2054 BGL.glColor3f(0.9,0.9,0.9); BGL.glRasterPos2i(20+level*10,self.y-self.h+5); Draw.Text(title)
2056 def luxHelp(name, lux, caption, hint, gui, width=1.0):
2058 r = gui.getRect(width, 1)
2059 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)]))
2060 drawIcon(icon_help, r[0], r[1])
2062 return "\n \"bool %s\" [\"%s\"]"%(name, lux.get())
2064 # lux parameter types
2065 def luxOption(name, lux, options, caption, hint, gui, width=1.0):
2067 menustr = caption+": %t"
2068 for i, v in enumerate(options): menustr = "%s %%x%d|%s"%(v, i, menustr)
2070 i = options.index(lux.get())
2073 lux.set(lux.default) # not found, so try default value
2074 i = options.index(lux.get())
2076 print("value %s not found in options list"%(lux.get()))
2078 r = gui.getRect(width, 1)
2079 Draw.Menu(menustr, evtLuxGui, r[0], r[1], r[2], r[3], i, hint, lambda e,v: lux.set(options[v]))
2080 return "\n \"string %s\" [\"%s\"]"%(name, lux.get())
2082 def luxOptionRect(name, lux, options, caption, hint, gui, x, y, xx, yy):
2084 menustr = caption+": %t"
2085 for i, v in enumerate(options): menustr = "%s %%x%d|%s"%(v, i, menustr)
2087 i = options.index(lux.get())
2090 lux.set(lux.default) # not found, so try default value
2091 i = options.index(lux.get())
2093 print ("value %s not found in options list"%(lux.get()))
2095 Draw.Menu(menustr, evtLuxGui, x, y, xx, yy, i, hint, lambda e,v: lux.set(options[v]))
2096 return "\n \"string %s\" [\"%s\"]"%(name, lux.get())
2098 def luxIdentifier(name, lux, options, caption, hint, gui, icon=None, width=1.0):
2099 if gui: gui.newline(caption+":", 8, 0, icon, [0.75,0.5,0.25])
2100 luxOption(name, lux, options, caption, hint, gui, width)
2101 return "\n%s \"%s\""%(name, lux.get())
2103 def luxFloat(name, lux, min, max, caption, hint, gui, width=1.0, useslider=0):
2105 if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
2106 r = gui.getRect(width-0.12, 1)
2108 r = gui.getRect(width, 1)
2112 Draw.Slider(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, 0, hint, lambda e,v: lux.set(v))
2114 Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, hint, lambda e,v: lux.set(v))
2115 if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
2118 keyname = lux.getname()
2120 useipo = luxProp(obj, keyname+".IPOuse", "false")
2121 i = gui.getRect(0.12, 1)
2122 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)]))
2124 if useipo.get() == "true":
2125 if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
2126 curve = luxProp(obj, keyname+".IPOCurveName", "")
2127 if curve.get() == "":
2128 c = gui.getRect(2.0, 1)
2130 c = gui.getRect(1.1, 1)
2132 Draw.String("Ipo:", evtLuxGui, c[0], c[1], c[2], c[3], curve.get(), 250, "Set IPO Name", lambda e,v: curve.set(v))
2134 usemapping = luxProp(obj, keyname+".IPOmap", "false")
2137 # Apply IPO to value
2138 if curve.get() != "":
2140 ipoob = Blender.Ipo.Get(curve.get())
2144 if curve.get() != "":
2145 names = list([x[0] for x in ipoob.curveConsts.items()])
2146 ipotype = luxProp(obj, keyname+".IPOCurveType", "OB_LOCZ")
2147 luxOption("ipocurve", ipotype, names, "IPO Curve", "Set IPO Curve", gui, 0.6)
2149 icu = ipoob[eval("Blender.Ipo.%s" % (ipotype.get()))]
2150 icu_value = icu[Blender.Get('curframe')]
2151 if usemapping.get() == "false": # if true is set during mapping below
2155 m = gui.getRect(0.3, 1)
2156 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)]))
2157 if usemapping.get() == "true":
2158 if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
2159 fmin = luxProp(obj, keyname+".IPOCurvefmin", 0.0)
2160 luxFloatNoIPO("ipofmin", fmin, -100, 100, "fmin", "Map minimum value from Curve", gui, 0.5)
2161 fmax = luxProp(obj, keyname+".IPOCurvefmax", 1.0)
2162 luxFloatNoIPO("ipofmax", fmax, -100, 100, "fmax", "Map maximum value from Curve", gui, 0.5)
2163 tmin = luxProp(obj, keyname+".IPOCurvetmin", min)
2164 luxFloatNoIPO("ipotmin", tmin, min, max, "tmin", "Map miminum value to", gui, 0.5)
2165 tmax = luxProp(obj, keyname+".IPOCurvetmax", max)
2166 luxFloatNoIPO("ipotmax", tmax, min, max, "tmax", "Map maximum value to", gui, 0.5)
2168 sval = (icu_value - fmin.getFloat()) / (fmax.getFloat() - fmin.getFloat())
2169 lux.set(tmin.getFloat() + (sval * (tmax.getFloat() - tmin.getFloat())))
2172 #v = gui.getRect(0.5, 1)
2173 #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)]))
2175 if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
2177 keyname = lux.getname()
2178 useipo = luxProp(obj, keyname+".IPOuse", "false")
2179 if useipo.get() == "true":
2180 curve = luxProp(obj, keyname+".IPOCurveName", "")
2182 ipoob = Blender.Ipo.Get(curve.get())
2186 usemapping = luxProp(obj, keyname+".IPOmap", "false")
2188 if curve.get() != "":
2189 names = list([x[0] for x in ipoob.curveConsts.items()])
2190 ipotype = luxProp(obj, keyname+".IPOCurveType", "OB_LOCZ")
2192 icu = ipoob[eval("Blender.Ipo.%s" % (ipotype.get()))]
2193 icu_value = icu[Blender.Get('curframe')]
2194 if usemapping.get() == "false": # if true is set during mapping below
2197 if usemapping.get() == "true":
2198 if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
2199 fmin = luxProp(obj, keyname+".IPOCurvefmin", 0.0)
2200 fmax = luxProp(obj, keyname+".IPOCurvefmax", 1.0)
2201 tmin = luxProp(obj, keyname+".IPOCurvetmin", min)
2202 tmax = luxProp(obj, keyname+".IPOCurvetmax", max)
2203 sval = (icu_value - fmin.getFloat()) / (fmax.getFloat() - fmin.getFloat())
2204 lux.set(tmin.getFloat() + (sval * (tmax.getFloat() - tmin.getFloat())))
2206 return "\n \"float %s\" [%f]"%(name, lux.getFloat())
2208 def luxFloatNoIPO(name, lux, min, max, caption, hint, gui, width=1.0, useslider=0):
2210 r = gui.getRect(width, 1)
2212 Draw.Slider(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, 0, hint, lambda e,v: lux.set(v))
2214 Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, hint, lambda e,v: lux.set(v))
2215 return "\n \"float %s\" [%f]"%(name, lux.getFloat())
2219 def luxInt(name, lux, min, max, caption, hint, gui, width=1.0):
2221 r = gui.getRect(width, 1)
2222 Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getInt(), min, max, hint, lambda e,v: lux.set(v))
2223 return "\n \"integer %s\" [%d]"%(name, lux.getInt())
2225 def luxBool(name, lux, caption, hint, gui, width=1.0):
2227 r = gui.getRect(width, 1)
2228 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)]))
2229 return "\n \"bool %s\" [\"%s\"]"%(name, lux.get())
2231 def luxLabel(caption, gui):
2233 r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5)
2236 def luxCollapse(name, lux, caption, hint, gui, width=1.0):
2238 r = gui.getRect(width, 1)
2239 if lux.get() == "true":
2240 drawArrow(arrow_down, r[0]-22, r[1]-2)
2242 drawArrow(arrow_right, r[0]-22, r[1]-2)
2243 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)]))
2244 return "\n \"bool %s\" [\"%s\"]"%(name, lux.get())
2246 def luxString(name, lux, caption, hint, gui, width=1.0):
2248 r = gui.getRect(width, 1)
2249 Draw.String(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.get(), 250, hint, lambda e,v: lux.set(v))
2250 if lux.get()==lux.default: return ""
2251 else: return "\n \"string %s\" [\"%s\"]"%(name, luxstr(lux.get()))
2253 def luxFile(name, lux, caption, hint, gui, width=1.0):
2255 r = gui.getRect(width, 1)
2256 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))
2257 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()))
2258 return "\n \"string %s\" [\"%s\"]"%(name, luxstr(luxFilePath(lux.get())))
2260 def luxPath(name, lux, caption, hint, gui, width=1.0):
2262 r = gui.getRect(width, 1)
2263 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))
2264 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()))
2265 return "\n \"string %s\" [\"%s\"]"%(name, luxstr(lux.get()))
2267 def luxRGB(name, lux, max, caption, hint, gui, width=2.0):
2269 r = gui.getRect(width, 1)
2274 if rgb[i] > scale: scale = rgb[i]
2275 rgb = (rgb[0]/scale, rgb[1]/scale, rgb[2]/scale)
2276 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)))
2277 w = int((r[2]-r[3])/3); m = max
2279 w = int((r[2]-r[3])/4); m = 1.0
2280 drawR, drawG, drawB, drawS = Draw.Create(rgb[0]), Draw.Create(rgb[1]), Draw.Create(rgb[2]), Draw.Create(scale)
2281 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)))
2282 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)))
2283 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)))
2285 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)))
2287 return "\n \"color %s\" [%s]"%(name, lux.getRGC())
2288 return "\n \"color %s\" [%s]"%(name, lux.get())
2290 def luxVector(name, lux, min, max, caption, hint, gui, width=2.0):
2292 r = gui.getRect(width, 1)
2293 vec = lux.getVector()
2295 drawX, drawY, drawZ = Draw.Create(vec[0]), Draw.Create(vec[1]), Draw.Create(vec[2])
2296 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)))
2297 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)))
2298 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)))
2299 return "\n \"vector %s\" [%s]"%(name, lux.get())
2301 def luxVectorUniform(name, lux, min, max, caption, hint, gui, width=2.0):
2302 def setUniform(lux, value):
2303 if value: lux.set(lux.getFloat())
2304 else: lux.setVector(lux.getVector())
2306 r = gui.getRect(width, 1)
2307 vec = lux.getVector()
2308 Draw.Toggle("U", evtLuxGui, r[0], r[1], gui.h, gui.h, lux.isFloat(), "uniform", lambda e,v: setUniform(lux, v))
2310 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))
2312 w = int((r[2]-gui.h)/3)
2313 drawX, drawY, drawZ = Draw.Create(vec[0]), Draw.Create(vec[1]), Draw.Create(vec[2])
2314 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)))
2315 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)))
2316 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)))
2317 return "\n \"vector %s\" [%s]"%(name, lux.getVectorStr())
2320 # lux individual identifiers
2321 def luxCamera(cam, context, gui=None):
2322 global icon_c_camera
2325 camtype = luxProp(cam, "camera.type", "perspective")
2326 # Radiance - remarked 'realistic' for v0.6 release
2327 #str = luxIdentifier("Camera", camtype, ["perspective","orthographic","environment","realistic"], "CAMERA", "select camera type", gui, icon_c_camera)
2328 str = luxIdentifier("Camera", camtype, ["perspective","orthographic","environment"], "CAMERA", "select camera type", gui, icon_c_camera)
2330 if camtype.get() == "perspective":
2331 if gui: gui.newline(" View:")
2332 str += luxFloat("fov", luxAttr(cam, "angle"), 8.0, 170.0, "fov", "camera field-of-view angle", gui)
2333 fl = luxAttr(cam, "lens")
2335 luxFloat("lens", fl, 1.0, 250.0, "focallength", "camera focal length", gui)
2337 if camtype.get() == "orthographic" :
2338 str += luxFloat("scale", luxAttr(cam, "scale"), 0.01, 1000.0, "scale", "orthographic camera scale", gui)
2339 scale = cam.scale / 2
2340 if camtype.get() == "realistic":
2342 if gui: gui.newline(" View:")
2343 fov = luxAttr(cam, "angle")
2344 str += luxFloat("fov", fov, 8.0, 170.0, "fov", "camera field-of-view angle", gui)
2345 if gui: luxFloat("lens", luxAttr(cam, "lens"), 1.0, 250.0, "focallength", "camera focal length", gui)
2348 if gui: gui.newline()
2349 str += luxFile("specfile", luxProp(cam, "camera.realistic.specfile", ""), "spec-file", "", gui, 1.0)
2350 # if gui: gui.newline()
2351 # auto calc str += luxFloat("filmdistance", luxProp(cam, "camera.realistic.filmdistance", 70.0), 0.1, 1000.0, "film-dist", "film-distance [mm]", gui)
2352 filmdiag = luxProp(cam, "camera.realistic.filmdiag", 35.0)
2353 str += luxFloat("filmdiag", filmdiag, 0.1, 1000.0, "film-diag", "[mm]", gui)
2354 if gui: gui.newline()
2355 fstop = luxProp(cam, "camera.realistic.fstop", 1.0)
2356 luxFloat("aperture_diameter", fstop, 0.1, 100.0, "f-stop", "", gui)
2357 dofdist = luxAttr(cam, "dofDist")
2358 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)
2360 Draw.Button("S", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, "focus selected object", lambda e,v:setFocus("S"))
2361 Draw.Button("C", evtLuxGui, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "focus cursor", lambda e,v:setFocus("C"))
2362 focal = filmdiag.get()*0.001 / math.tan(fov.get() * math.pi / 360.0) / 2.0
2363 print("calculated focal length: %f mm"%(focal * 1000.0))
2364 aperture_diameter = focal / fstop.get()
2365 print("calculated aperture diameter: %f mm"%(aperture_diameter * 1000.0))
2366 str += "\n \"float aperture_diameter\" [%f]"%(aperture_diameter*1000.0)
2367 filmdistance = dofdist.get() * focal / (dofdist.get() - focal)
2368 print("calculated film distance: %f mm"%(filmdistance * 1000.0))
2369 str += "\n \"float filmdistance\" [%f]"%(filmdistance*1000.0)
2372 useclip = luxProp(cam, "useclip", "false")
2373 luxCollapse("useclip", useclip, "Near & Far Clipping", "Enable Camera near and far clipping options", gui, 2.0)
2374 if(useclip.get() == "true"):
2375 if gui: gui.newline(" Clipping:")
2376 str += luxFloat("hither", luxAttr(cam, "clipStart"), 0.0, 100.0, "start", "near clip distance", gui)
2377 str += luxFloat("yon", luxAttr(cam, "clipEnd"), 1.0, 10000.0, "end", "far clip distance", gui)
2380 usedof = luxProp(cam, "usedof", "false")
2382 if camtype.get() in ["perspective", "orthographic"]:
2383 luxCollapse("usedof", usedof, "Depth of Field & Bokeh", "Enable Depth of Field & Aperture options", gui, 2.0)
2386 if usedof.get() == "true":
2388 if gui: gui.newline(" DOF:")
2390 lr = luxProp(cam, "camera.lensradius", 0.01)
2391 fs = luxProp(cam, "camera.fstop", 2.8)
2393 if camtype.get() == "perspective":
2395 usefstop = luxProp(cam, "usefstop", "false")
2396 luxBool("usefstop", usefstop, "Use f/stop", "Use f/stop to define DOF effect", gui, 1.0)
2398 LR_SCALE = 1000.0 # lr in metres -> mm
2399 FL_SCALE = 1.0 # fl in mm -> mm
2401 def lr_2_fs(fl, lr):
2403 return fl / ( 2.0 * lr )
2405 def fs_2_lr(fl, fs):
2406 return fl / ( 2.0 * fs )
2408 if usefstop.get() == 'true':
2409 lr.set(fs_2_lr(fl.get() * FL_SCALE, fs.get()) / LR_SCALE)
2410 luxFloat("fstop", fs, 0.9, 64.0, "fstop", "Defines the lens aperture.", gui)
2411 str += luxFloat("lensradius", lr, 0.0, 1.0, "", "", None)
2413 fs.set(lr_2_fs(fl.get() * FL_SCALE, lr.get() * LR_SCALE))
2414 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)
2416 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)
2418 focustype = luxProp(cam, "camera.focustype", "autofocus")
2419 luxOption("focustype", focustype, ["autofocus", "manual", "object"], "Focus Type", "Choose the focus behaviour", gui)
2422 if focustype.get() == "autofocus":
2423 str += luxBool("autofocus",luxProp(cam, "camera.autofocus", "true"), "autofocus", "Enable automatic focus", gui)
2424 if focustype.get() == "object":
2425 objectfocus = luxProp(cam, "camera.objectfocus", "")
2426 luxString("objectfocus", objectfocus, "object", "Always focus camera on named object", gui, 1.0)
2427 dofdist = luxAttr(cam, "dofDist")
2428 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)
2429 if objectfocus.get() != "":
2431 setFocus(objectfocus.get())
2433 luxProp(cam, "camera.objectfocus", "").set("")
2434 Draw.PupMenu("WARNING: focus-object does not match existing object-name")
2435 if LuxIsGUI: Draw.Redraw()
2437 if focustype.get() == "manual":
2438 dofdist = luxAttr(cam, "dofDist")
2439 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)
2441 Draw.Button("S", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, "focus selected object", lambda e,v:setFocus("S"))
2442 Draw.Button("C", evtLuxGui, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "focus cursor", lambda e,v:setFocus("C"))
2444 if camtype.get() == "perspective" and usedof.get() == "true":
2445 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)
2446 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)
2447 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)
2449 useaspect = luxProp(cam, "useaspectratio", "false")
2450 aspectratio = luxProp(cam, "ratio", 1.3333)
2451 if camtype.get() in ["perspective", "orthographic"]:
2452 useshift = luxProp(cam, "camera.useshift", "false")
2453 luxCollapse("useshift", useshift, "Architectural (Lens Shift) & Aspect Ratio", "Enable Lens Shift and Aspect Ratio options", gui, 2.0)
2454 if(useshift.get() == "true"):
2455 if gui: gui.newline(" Shift:")
2456 luxFloat("X", luxAttr(cam, "shiftX"), -2.0, 2.0, "X", "horizontal lens shift", gui)
2457 luxFloat("Y", luxAttr(cam, "shiftY"), -2.0, 2.0, "Y", "vertical lens shift", gui)
2459 if gui: gui.newline(" AspectRatio:")
2460 luxBool("useaspectratio", useaspect, "Custom", "Define a custom frame aspect ratio", gui)
2461 if useaspect.get() == "true":
2462 str += luxFloat("frameaspectratio", aspectratio, 0.0001, 3.0, "aspectratio", "Frame aspect ratio", gui)
2464 if useaspect.get() == "true":
2465 ratio = 1./aspectratio.get()
2467 ratio = float(context.sizeY)/float(context.sizeX)
2469 screenwindow = [(2*cam.shiftX-1)*scale, (2*cam.shiftX+1)*scale, (2*cam.shiftY-ratio)*scale, (2*cam.shiftY+ratio)*scale]
2471 screenwindow = [(2*cam.shiftX-1/ratio)*scale, (2*cam.shiftX+1/ratio)*scale, (2*cam.shiftY-1)*scale, (2*cam.shiftY+1)*scale]
2472 # render region option
2473 if context.borderRender:
2474 (x1,y1,x2,y2) = context.border
2475 screenwindow = [screenwindow[0]*(1-x1)+screenwindow[1]*x1, screenwindow[0]*(1-x2)+screenwindow[1]*x2,\
2476 screenwindow[2]*(1-y1)+screenwindow[3]*y1, screenwindow[2]*(1-y2)+screenwindow[3]*y2]
2477 str += "\n \"float screenwindow\" [%f %f %f %f]"%(screenwindow[0], screenwindow[1], screenwindow[2], screenwindow[3])
2479 # Note - radiance - this is a work in progress
2480 # Flash lamp option for perspective and ortho cams
2481 # if camtype.get() in ["perspective", "orthographic"]:
2482 # useflash = luxProp(cam, "useflash", "false")
2483 # luxBool("useflash", useflash, "Flash Lamp", "Enable Camera mounted flash lamp options", gui, 2.0)
2485 # Motion Blur Options (common to all cameras)
2486 usemblur = luxProp(cam, "usemblur", "false")
2487 luxCollapse("usemblur", usemblur, "Motion Blur", "Enable Motion Blur", gui, 2.0)
2488 if(usemblur.get() == "true"):
2489 if gui: gui.newline(" Shutter:")
2490 mblurpreset = luxProp(cam, "mblurpreset", "true")
2491 luxBool("mblurpreset", mblurpreset, "Preset", "Enable use of Shutter Presets", gui, 0.4)
2492 if(mblurpreset.get() == "true"):
2493 shutterpresets = ["full frame", "half frame", "quarter frame", "1/25", "1/30", "1/45", "1/60", "1/85", "1/125", "1/250", "1/500"]
2494 shutterpreset = luxProp(cam, "camera.shutterspeedpreset", "full frame")
2495 luxOption("shutterpreset", shutterpreset, shutterpresets, "shutterspeed", "Choose the Shutter speed preset.", gui, 1.0)
2497 fpspresets = ["10 FPS", "12 FPS", "20 FPS", "25 FPS", "29.99 FPS", "30 FPS", "50 FPS", "60 FPS"]
2498 shutfps = luxProp(cam, "camera.shutfps", "25 FPS")
2499 luxOption("shutfps", shutfps, fpspresets, "@", "Choose the number of frames per second as the time base.", gui, 0.6)
2501 sfps = shutfps.get()
2503 if sfps == "10 FPS": fps = 10
2504 elif sfps == "12 FPS": fps = 12
2505 elif sfps == "20 FPS": fps = 20
2506 elif sfps == "25 FPS": fps = 25
2507 elif sfps == "29.99 FPS": fps = 29.99
2508 elif sfps == "30 FPS": fps = 30
2509 elif sfps == "50 FPS": fps = 50
2510 elif sfps == "60 FPS": fps = 60
2512 spre = shutterpreset.get()
2515 if spre == "full frame": close = 1.0
2516 elif spre == "half frame": close = 0.5
2517 elif spre == "quarter frame": close = 0.25
2518 elif spre == "1/25": close = 1.0 / 25.0 * fps
2519 elif spre == "1/30": close = 1.0 / 30.0 * fps
2520 elif spre == "1/45": close = 1.0 / 45.0 * fps
2521 elif spre == "1/60": close = 1.0 / 60.0 * fps
2522 elif spre == "1/85": close = 1.0 / 85.0 * fps
2523 elif spre == "1/125": close = 1.0 / 125.0 * fps
2524 elif spre == "1/250": close = 1.0 / 250.0 * fps
2525 elif spre == "1/500": close = 1.0 / 500.0 * fps
2527 str += "\n \"float shutteropen\" [%f]\n \"float shutterclose\" [%f] "%(open,close)
2530 str += luxFloat("shutteropen", luxProp(cam, "camera.shutteropen", 0.0), 0.0, 100.0, "open", "time in seconds when shutter opens", gui, 0.8)
2531 str += luxFloat("shutterclose", luxProp(cam, "camera.shutterclose", 1.0), 0.0, 100.0, "close", "time in seconds when shutter closes", gui, 0.8)
2533 str += luxOption("shutterdistribution", luxProp(cam, "camera.shutterdistribution", "uniform"), ["uniform", "gaussian"], "distribution", "Choose the shutter sampling distribution.", gui, 2.0)
2534 objectmblur = luxProp(cam, "objectmblur", "true")
2535 luxBool("objectmblur", objectmblur, "Object", "Enable Motion Blur for scene object motions", gui, 1.0)
2536 cammblur = luxProp(cam, "cammblur", "true")
2537 luxBool("cammblur", cammblur, "Camera", "Enable Motion Blur for Camera motion", gui, 1.0)
2541 def get_render_resolution(scn, gui = None):
2542 context = scn.getRenderingContext()
2543 scale = luxProp(scn, "film.scale", "100 %")
2544 scale = int(scale.get()[:-1])
2545 xr = luxAttr(context, "sizeX").get()*scale/100
2546 yr = luxAttr(context, "sizeY").get()*scale/100
2550 def luxFilm(scn, gui=None):
2553 filmtype = luxProp(scn, "film.type", "fleximage")
2554 str = luxIdentifier("Film", filmtype, ["fleximage"], "FILM", "select film type", gui)
2555 if filmtype.get() == "fleximage":
2556 context = scn.getRenderingContext()
2558 if gui: gui.newline(" Resolution:")
2560 xr,yr = get_render_resolution(scn, gui)
2562 luxInt("xresolution", luxAttr(context, "sizeX"), 0, 8192, "X", "width of the render", gui, 0.666)
2563 luxInt("yresolution", luxAttr(context, "sizeY"), 0, 8192, "Y", "height of the render", gui, 0.666)
2564 scale = luxProp(scn, "film.scale", "100 %")
2565 luxOption("", scale, ["400 %", "200 %", "100 %", "75 %", "50 %", "25 %"], "scale", "scale resolution", gui, 0.666)
2567 # render region option
2568 if context.borderRender:
2569 (x1,y1,x2,y2) = context.border
2570 if (x1==x2) and (y1==y2): print("WARNING: empty render-region, use SHIFT-B to set render region in Blender.")
2571 str += "\n \"integer xresolution\" [%d] \n \"integer yresolution\" [%d]"%(xr*(x2-x1), yr*(y2-y1))
2573 str += "\n \"integer xresolution\" [%d] \n \"integer yresolution\" [%d]"%(xr, yr)
2575 if gui: gui.newline(" Halt:")
2576 str += luxInt("haltspp", luxProp(scn, "haltspp", 0), 0, 32768, "haltspp", "Stop rendering after specified amount of samples per pixel / 0 = never halt", gui)
2577 palpha = luxProp(scn, "film.premultiplyalpha", "false")
2578 str += luxBool("premultiplyalpha", palpha, "premultiplyalpha", "Pre multiply film alpha channel during normalization", gui)
2580 if gui: gui.newline(" Tonemap:")
2581 tonemapkernel = luxProp(scn, "film.tonemapkernel", "reinhard")
2582 str += luxOption("tonemapkernel", tonemapkernel, ["reinhard", "linear", "contrast", "maxwhite"], "Tonemapping Kernel", "Select the tonemapping kernel to use", gui, 2.0)
2583 if tonemapkernel.get() == "reinhard":
2584 autoywa = luxProp(scn, "film.reinhard.autoywa", "true")
2585 #str += luxBool("reinhard_autoywa", autoywa, "auto Ywa", "Automatically determine World Adaption Luminance", gui)
2586 if autoywa.get() == "false":
2587 str += luxFloat("reinhard_ywa", luxProp(scn, "film.reinhard.ywa", 0.1), 0.001, 1.0, "Ywa", "Display/World Adaption Luminance", gui)
2588 str += luxFloat("reinhard_prescale", luxProp(scn, "film.reinhard.prescale", 1.0), 0.0, 10.0, "preScale", "Image scale before tonemap operator", gui)
2589 str += luxFloat("reinhard_postscale", luxProp(scn, "film.reinhard.postscale", 1.2), 0.0, 10.0, "postScale", "Image scale after tonemap operator", gui)
2590 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)
2591 elif tonemapkernel.get() == "linear":
2592 str += luxFloat("linear_sensitivity", luxProp(scn, "film.linear.sensitivity", 50.0), 0.0, 1000.0, "sensitivity", "Adaption/Sensitivity", gui)
2593 str += luxFloat("linear_exposure", luxProp(scn, "film.linear.exposure", 1.0), 0.001, 1.0, "exposure", "Exposure duration in seconds", gui)
2594 str += luxFloat("linear_fstop", luxProp(scn, "film.linear.fstop", 2.8), 0.1, 64.0, "Fstop", "F-Stop", gui)
2595 str += luxFloat("linear_gamma", luxProp(scn, "film.linear.gamma", 1.0), 0.0, 8.0, "gamma", "Tonemap operator gamma correction", gui)
2596 elif tonemapkernel.get() == "contrast":
2597 str += luxFloat("contrast_ywa", luxProp(scn, "film.contrast.ywa", 0.1), 0.001, 1.0, "Ywa", "Display/World Adaption Luminance", gui)
2599 if gui: gui.newline(" Display:")
2600 str += luxInt("displayinterval", luxProp(scn, "film.displayinterval", 12), 4, 3600, "interval", "Set display Interval (seconds)", gui)
2602 if gui: gui.newline(" Write:")
2603 str += luxInt("writeinterval", luxProp(scn, "film.writeinterval", 120), 12, 3600, "interval", "Set display Interval (seconds)", gui)
2605 # Image File Outputs
2607 # LDR clamping method
2608 if gui: gui.newline(" Clamping:")
2609 ldrclampmethod = luxProp(scn, "film.ldr_clamp_method", "lum")
2610 str += luxOption("ldr_clamp_method", ldrclampmethod, ["lum", "hue", "cut"], "LDR clamping", "Method to clamp high luminance values for LDR output", gui, 0.5)
2611 if gui: gui.newline()
2614 saveexr = luxProp(scn, "film.write_exr", "false")
2615 str += luxCollapse("write_exr", saveexr, "OpenEXR Output", "Enable OpenEXR output", gui, 2.0)
2617 if saveexr.get() == "true":
2618 if gui: gui.newline(" OpenEXR:")
2620 exrchannels = luxProp(scn, "film.write_exr_channels", "RGBA")
2621 str += luxOption("write_exr_channels", exrchannels, ["Y", "YA", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
2622 exrres = luxProp(scn, "film.write_exr_halftype", "true")
2623 str += luxBool("write_exr_halftype", exrres, "16bit Half", "Enable 16bit Half resolution output, otherwise 32bit float", gui, 0.5)
2624 exrcompression = luxProp(scn, "film.write_exr_compression", "PIZ (lossless)")
2625 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)
2627 exrimaging = luxProp(scn, "film.write_exr_imaging", "true")
2628 str += luxBool("write_exr_applyimaging", exrimaging, "Apply Imaging/Tonemapping", "Apply Imaging and Tonemapping pipeline", gui, 1.2)
2630 if exrimaging.get()=="true":
2631 exrgamutclamp = luxProp(scn, "film.write_exr_gamutclamp", "true")
2632 str += luxBool("write_exr_gamutclamp", exrgamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 0.8)
2634 if gui: gui.newline()
2636 exrZ = luxProp(scn, "film.write_exr_Z", "true")
2637 str += luxBool("write_exr_ZBuf", exrZ, "ZBuf", "Enable Z Depth Buffer channel", gui, 0.8)
2638 if exrZ.get() == "true":
2639 exrZNormalize = luxProp(scn, "film.write_exr_ZNorm", "None")
2640 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)
2643 savepng = luxProp(scn, "film.write_png", "true")
2644 str += luxCollapse("write_png", savepng, "PNG Output", "Enable PNG (Portable Network Graphics) output", gui, 2.0)
2646 if savepng.get() == "true":
2647 if gui: gui.newline(" PNG:")
2648 pngchannels = luxProp(scn, "film.write_png_channels", "RGB")
2649 str += luxOption("write_png_channels", pngchannels, ["Y", "YA", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
2650 png16bit = luxProp(scn, "film.write_png_16bit", "false")
2651 str += luxBool("write_png_16bit", png16bit, "16bit", "Enable 16bits per channel resolution PNG output", gui, 0.5)
2652 pnggamutclamp = luxProp(scn, "film.write_png_gamutclamp", "true")
2653 str += luxBool("write_png_gamutclamp", pnggamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 1.0)
2656 #pngZ = luxProp(scn, "film.write_png_ZBuf", "false")
2657 #str += luxBool("write_png_ZBuf", pngZ, "ZBuf (Separate)", "Enable Z Depth Buffer channel", gui, 0.8)
2658 #if pngZ.get() == "true":
2659 # pngZNormalize = luxProp(scn, "film.write_png_ZNorm", "Min/Max")
2660 # 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)
2663 savetga = luxProp(scn, "film.write_tga", "false")
2664 str += luxCollapse("write_tga", savetga, "TGA Output", "Enable TGA output", gui, 2.0)
2666 if savetga.get() == "true":
2667 if gui: gui.newline(" TGA:")
2668 tgachannels = luxProp(scn, "film.write_tga_channels", "RGB")
2669 str += luxOption("write_tga_channels", tgachannels, ["Y", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
2670 tgagamutclamp = luxProp(scn, "film.write_tga_gamutclamp", "true")
2671 str += luxBool("write_tga_gamutclamp", tgagamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 1.5)
2674 #tgaZ = luxProp(scn, "film.write_tga_ZBuf", "false")
2675 #str += luxBool("write_tga_ZBuf", tgaZ, "ZBuf (Separate)", "Enable Z Depth Buffer channel", gui, 0.8)
2676 #if tgaZ.get() == "true":
2677 # tgaZNormalize = luxProp(scn, "film.write_tga_ZNorm", "Min/Max")
2678 # 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)
2681 # override output image dir in case of command line batch mode
2682 overrideop = luxProp(scn, "overrideoutputpath", "")
2683 if overrideop.get() != "":
2684 filebase = os.path.splitext(os.path.basename(Blender.Get('filename')))[0]
2685 filename = overrideop.get() + "/" + filebase + "-%05d" % (Blender.Get('curframe'))
2686 str += "\n \"string filename\" [\"%s\"]"%(filename)
2688 fn = luxProp(scn, "filename", "default-%05d" % (Blender.Get('curframe')))
2689 str += luxString("filename", fn, "File name", "save file name", None)
2691 if gui: gui.newline(" Resume:")
2692 resumeflm = luxProp(scn, "film.write_resume_flm", "false")
2693 str += luxBool("write_resume_flm", resumeflm, "Write/Use FLM", "Write a resume fleximage .flm file, or resume rendering if it already exists", gui)
2694 restartflm = luxProp(scn, "film.restart_resume_flm", "true")
2695 str += luxBool("restart_resume_flm", restartflm, "Restart/Erase", "Restart with a black flm, even it a previous flm exists", gui)
2696 if gui: gui.newline(" Reject:")
2697 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)
2698 debugmode = luxProp(scn, "film.debug", "false")
2699 str += luxBool("debug", debugmode, "debug", "Turn on debug reporting and switch off reject", gui)
2702 if gui: gui.newline(" Colorspace:")
2704 cspaceusepreset = luxProp(scn, "film.colorspaceusepreset", "true")
2705 luxBool("colorspaceusepreset", cspaceusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
2707 # Default values for 'sRGB - HDTV (ITU-R BT.709-5)'
2708 cspacewhiteX = luxProp(scn, "film.cspacewhiteX", 0.314275)
2709 cspacewhiteY = luxProp(scn, "film.cspacewhiteY", 0.329411)
2710 cspaceredX = luxProp(scn, "film.cspaceredX", 0.63)
2711 cspaceredY = luxProp(scn, "film.cspaceredY", 0.34)
2712 cspacegreenX = luxProp(scn, "film.cspacegreenX", 0.31)
2713 cspacegreenY = luxProp(scn, "film.cspacegreenY", 0.595)
2714 cspaceblueX = luxProp(scn, "film.cspaceblueX", 0.155)
2715 cspaceblueY = luxProp(scn, "film.cspaceblueY", 0.07)
2716 gamma = luxProp(scn, "film.gamma", 2.2)
2718 if(cspaceusepreset.get() == "true"):
2720 cspace = luxProp(scn, "film.colorspace", "sRGB - HDTV (ITU-R BT.709-5)")
2721 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"]
2722 luxOption("colorspace", cspace, cspaces, "Colorspace", "select output working colorspace", gui, 1.6)
2724 if cspace.get()=="ROMM RGB":
2725 cspacewhiteX.set(0.346); cspacewhiteY.set(0.359) # D50
2726 cspaceredX.set(0.7347); cspaceredY.set(0.2653)
2727 cspacegreenX.set(0.1596); cspacegreenY.set(0.8404)
2728 cspaceblueX.set(0.0366); cspaceblueY.set(0.0001)
2729 elif cspace.get()=="Adobe RGB 98":
2730 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
2731 cspaceredX.set(0.64); cspaceredY.set(0.34)
2732 cspacegreenX.set(0.21); cspacegreenY.set(0.71)
2733 cspaceblueX.set(0.15); cspaceblueY.set(0.06)
2734 elif cspace.get()=="Apple RGB":
2735 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
2736 cspaceredX.set(0.625); cspaceredY.set(0.34)
2737 cspacegreenX.set(0.28); cspacegreenY.set(0.595)
2738 cspaceblueX.set(0.155); cspaceblueY.set(0.07)
2739 elif cspace.get()=="NTSC (FCC 1953, ITU-R BT.470-2 System M)":
2740 cspacewhiteX.set(0.310); cspacewhiteY.set(0.316) # C
2741 cspaceredX.set(0.67); cspaceredY.set(0.33)
2742 cspacegreenX.set(0.21); cspacegreenY.set(0.71)
2743 cspaceblueX.set(0.14); cspaceblueY.set(0.08)
2744 elif cspace.get()=="NTSC (1979) (SMPTE C, SMPTE-RP 145)":
2745 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
2746 cspaceredX.set(0.63); cspaceredY.set(0.34)
2747 cspacegreenX.set(0.31); cspacegreenY.set(0.595)
2748 cspaceblueX.set(0.155); cspaceblueY.set(0.07)
2749 elif cspace.get()=="PAL/SECAM (EBU 3213, ITU-R BT.470-6)":
2750 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
2751 cspaceredX.set(0.64); cspaceredY.set(0.33)
2752 cspacegreenX.set(0.29); cspacegreenY.set(0.60)
2753 cspaceblueX.set(0.15); cspaceblueY.set(0.06)
2754 elif cspace.get()=="CIE (1931) E":
2755 cspacewhiteX.set(0.333); cspacewhiteY.set(0.333) # E
2756 cspaceredX.set(0.7347); cspaceredY.set(0.2653)
2757 cspacegreenX.set(0.2738); cspacegreenY.set(0.7174)
2758 cspaceblueX.set(0.1666); cspaceblueY.set(0.0089)
2760 whitepointusecspace = luxProp(scn, "film.whitepointusecolorspace", "true")
2761 luxBool("whitepointusecolorspace", whitepointusecspace, "Colorspace Whitepoint", "Use default whitepoint for selected colorspace", gui, 1.0)
2762 gammausecspace = luxProp(scn, "film.gammausecolorspace", "true")
2763 luxBool("gammausecolorspace", gammausecspace, "Colorspace Gamma", "Use default output gamma for selected colorspace", gui, 1.0)
2765 if(whitepointusecspace.get() == "false"):
2766 if gui: gui.newline(" Whitepoint:")
2767 whitepointusepreset = luxProp(scn, "film.whitepointusepreset", "true")
2768 luxBool("whitepointusepreset", whitepointusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
2770 if(whitepointusepreset.get() == "true"):
2771 whitepointpresets = ["E", "D50", "D55", "D65", "D75", "A", "B", "C", "9300", "F2", "F7", "F11"]
2772 whitepointpreset = luxProp(scn, "film.whitepointpreset", "D65")
2773 luxOption("whitepointpreset", whitepointpreset, whitepointpresets, " PRESET", "select Whitepoint preset", gui, 1.6)
2775 if whitepointpreset.get()=="E": cspacewhiteX.set(0.333); cspacewhiteY.set(0.333)
2776 elif whitepointpreset.get()=="D50": cspacewhiteX.set(0.346); cspacewhiteY.set(0.359)
2777 elif whitepointpreset.get()=="D55": cspacewhiteX.set(0.332); cspacewhiteY.set(0.347)
2778 elif whitepointpreset.get()=="D65": cspacewhiteX.set(0.313); cspacewhiteY.set(0.329)
2779 elif whitepointpreset.get()=="D75": cspacewhiteX.set(0.299); cspacewhiteY.set(0.315)
2780 elif whitepointpreset.get()=="A": cspacewhiteX.set(0.448); cspacewhiteY.set(0.407)
2781 elif whitepointpreset.get()=="B": cspacewhiteX.set(0.348); cspacewhiteY.set(0.352)
2782 elif whitepointpreset.get()=="C": cspacewhiteX.set(0.310); cspacewhiteY.set(0.316)
2783 elif whitepointpreset.get()=="9300": cspacewhiteX.set(0.285); cspacewhiteY.set(0.293)
2784 elif whitepointpreset.get()=="F2": cspacewhiteX.set(0.372); cspacewhiteY.set(0.375)
2785 elif whitepointpreset.get()=="F7": cspacewhiteX.set(0.313); cspacewhiteY.set(0.329)
2786 elif whitepointpreset.get()=="F11": cspacewhiteX.set(0.381); cspacewhiteY.set(0.377)
2788 luxFloat("white X", cspacewhiteX, 0.0, 1.0, "white X", "Whitepoint X weight", gui, 0.8)
2789 luxFloat("white Y", cspacewhiteY, 0.0, 1.0, "white Y", "Whitepoint Y weight", gui, 0.8)
2791 if(gammausecspace.get() == "false"):
2792 if gui: gui.newline(" Gamma:")
2793 luxFloat("gamma", gamma, 0.1, 6.0, "gamma", "Output and RGC Gamma", gui, 2.0)
2796 luxFloat("white X", cspacewhiteX, 0.0, 1.0, "white X", "Whitepoint X weight", gui, 0.8)
2797 luxFloat("white Y", cspacewhiteY, 0.0, 1.0, "white Y", "Whitepoint Y weight", gui, 0.8)
2798 luxFloat("red X", cspaceredX, 0.0, 1.0, "red X", "Red component X weight", gui, 1.0)
2799 luxFloat("red Y", cspaceredY, 0.0, 1.0, "red Y", "Red component Y weight", gui, 1.0)
2800 luxFloat("green X", cspacegreenX, 0.0, 1.0, "green X", "Green component X weight", gui, 1.0)
2801 luxFloat("green Y", cspacegreenY, 0.0, 1.0, "green Y", "Green component Y weight", gui, 1.0)
2802 luxFloat("blue X", cspaceblueX, 0.0, 1.0, "blue X", "Blue component X weight", gui, 1.0)
2803 luxFloat("blue Y", cspaceblueY, 0.0, 1.0, "blue Y", "Blue component Y weight", gui, 1.0)
2804 if gui: gui.newline(" Gamma:")
2805 luxFloat("gamma", gamma, 0.1, 6.0, "gamma", "Output and RGC Gamma", gui, 2.0)
2807 str += "\n \"float colorspace_white\" [%f %f]"%(cspacewhiteX.get(), cspacewhiteY.get())
2808 str += "\n \"float colorspace_red\" [%f %f]"%(cspaceredX.get(), cspaceredY.get())
2809 str += "\n \"float colorspace_green\" [%f %f]"%(cspacegreenX.get(), cspacegreenY.get())
2810 str += "\n \"float colorspace_blue\" [%f %f]"%(cspaceblueX.get(), cspaceblueY.get())
2811 str += "\n \"float gamma\" [%f]"%(gamma.get())
2816 def luxPixelFilter(scn, gui=None):
2817 global icon_c_filter
2820 filtertype = luxProp(scn, "pixelfilter.type", "mitchell")
2821 str = luxIdentifier("PixelFilter", filtertype, ["box", "gaussian", "mitchell", "sinc", "triangle"], "FILTER", "select pixel filter type", gui, icon_c_filter)
2824 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
2825 showadvanced = luxProp(scn, "pixelfilter.showadvanced", parammodeadvanced.get())
2826 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
2828 showhelp = luxProp(scn, "pixelfilter.showhelp", "false")
2829 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
2831 if filtertype.get() == "box":
2832 if showadvanced.get()=="true":
2833 # Advanced parameters
2834 if gui: gui.newline()
2835 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)
2836 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)
2837 if filtertype.get() == "gaussian":
2838 if showadvanced.get()=="true":
2839 # Advanced parameters
2840 if gui: gui.newline()
2841 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)
2842 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)
2843 if gui: gui.newline()
2844 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)
2845 if filtertype.get() == "mitchell":
2846 if showadvanced.get()=="false":
2847 # Default parameters
2848 if gui: gui.newline("", 8, 0, None, [0.4,0.4,0.4])
2849 slidval = luxProp(scn, "pixelfilter.mitchell.sharp", 0.25)
2850 luxFloat("sharpness", slidval, 0.0, 1.0, "sharpness", "Specify amount between blurred (left) and sharp/ringed (right)", gui, 2.0, 1)
2851 # rule: B + 2*c = 1.0
2852 C = slidval.getFloat() * 0.5
2853 B = 1.0 - slidval.getFloat()
2854 str += "\n \"float B\" [%f]"%(B)
2855 str += "\n \"float C\" [%f]"%(C)
2857 if showadvanced.get()=="true":
2858 # Advanced parameters
2859 if gui: gui.newline()
2860 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)
2861 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)
2862 if gui: gui.newline()
2864 optmode = luxProp(scn, "pixelfilter.mitchell.optmode", "slider")
2865 luxOption("optmode", optmode, ["slider", "preset", "manual"], "Mode", "Mode of configuration", gui, 0.5)
2867 if(optmode.get() == "slider"):
2868 slidval = luxProp(scn, "pixelfilter.mitchell.sharp", 0.33)
2869 luxFloat("sharpness", slidval, 0.0, 1.0, "sharpness", "Specify amount between blurred (left) and sharp/ringed (right)", gui, 1.5, 1)
2870 # rule: B + 2*c = 1.0
2871 C = slidval.getFloat() * 0.5
2872 B = 1.0 - slidval.getFloat()
2873 str += "\n \"float B\" [%f]"%(B)
2874 str += "\n \"float C\" [%f]"%(C)
2875 elif(optmode.get() == "preset"):
2876 print("not implemented")
2878 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)
2879 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)
2881 if filtertype.get() == "sinc":
2882 if showadvanced.get()=="true":
2883 # Advanced parameters
2884 if gui: gui.newline()
2885 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)
2886 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)
2887 if gui: gui.newline()
2888 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)
2889 if filtertype.get() == "triangle":
2890 if showadvanced.get()=="true":
2891 # Advanced parameters
2892 if gui: gui.newline()
2893 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)
2894 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)
2897 def luxSampler(scn, gui=None):
2898 global icon_c_sampler, icon_help
2901 samplertype = luxProp(scn, "sampler.type", "metropolis")
2902 str = luxIdentifier("Sampler", samplertype, ["metropolis", "erpt", "lowdiscrepancy", "random"], "SAMPLER", "select sampler type", gui, icon_c_sampler)
2905 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
2906 showadvanced = luxProp(scn, "sampler.showadvanced", parammodeadvanced.get())
2907 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
2909 showhelp = luxProp(scn, "sampler.showhelp", "false")
2910 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
2912 if samplertype.get() == "metropolis":
2913 if showadvanced.get()=="false":
2914 # Default parameters
2915 if gui: gui.newline(" Mutation:", 8, 0, None, [0.4,0.4,0.4])
2916 strength = luxProp(scn, "sampler.metro.strength", 0.6)
2917 luxFloat("strength", strength, 0.0, 1.0, "strength", "Mutation Strength (lmprob = 1.0-strength)", gui, 2.0, 1)
2918 v = 1.0 - strength.get()
2919 str += "\n \"float largemutationprob\" [%f]"%v
2920 if showadvanced.get()=="true":
2921 # Advanced parameters
2922 if gui: gui.newline(" Mutation:")
2923 str += luxFloat("largemutationprob", luxProp(scn, "sampler.metro.lmprob", 0.4), 0.0, 1.0, "LM.prob.", "Probability of generating a large sample (mutation)", gui)
2924 str += luxInt("maxconsecrejects", luxProp(scn, "sampler.metro.maxrejects", 512), 0, 32768, "max.rejects", "number of consecutive rejects before a new mutation is forced", gui)
2925 if gui: gui.newline(" Screen:")
2926 #str += luxInt("initsamples", luxProp(scn, "sampler.metro.initsamples", 262144), 1, 1000000, "initsamples", "", gui)
2927 str += luxBool("usevariance",luxProp(scn, "sampler.metro.usevariance", "false"), "usevariance", "Accept based on variance", gui, 1.0)
2929 if showhelp.get()=="true":
2930 if gui: gui.newline(" Description:", 8, 0, icon_help, [0.4,0.5,0.56])
2931 r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5)
2932 Draw.Text("A Metropolis-Hastings mutating sampler which implements MLT", 'small')
2934 if samplertype.get() == "erpt":
2935 #str += luxInt("initsamples", luxProp(scn, "sampler.erpt.initsamples", 100000), 1, 1000000, "initsamples", "", gui)
2936 if gui: gui.newline(" Mutation:")
2937 str += luxInt("chainlength", luxProp(scn, "sampler.erpt.chainlength", 512), 1, 32768, "chainlength", "The number of mutations from a given seed", gui)
2938 if gui: gui.newline()
2939 str += luxInt("stratawidth", luxProp(scn, "sampler.erpt.stratawidth", 256), 1, 32768, "stratawidth", "The number of x/y strata for stratified sampling of seeds", gui)
2941 if samplertype.get() == "lowdiscrepancy":
2942 if gui: gui.newline(" PixelSampler:")
2943 str += luxOption("pixelsampler", luxProp(scn, "sampler.lowdisc.pixelsampler", "lowdiscrepancy"), ["linear", "tile", "random", "vegas","lowdiscrepancy","hilbert"], "pixel-sampler", "select pixel-sampler", gui)
2944 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)
2946 if samplertype.get() == "random":
2947 if gui: gui.newline(" PixelSampler:")
2948 str += luxOption("pixelsampler", luxProp(scn, "sampler.random.pixelsampler", "vegas"), ["linear", "tile", "random", "vegas","lowdiscrepancy","hilbert"], "pixel-sampler", "select pixel-sampler", gui)
2949 if gui: gui.newline()
2950 str += luxInt("pixelsamples", luxProp(scn, "sampler.random.pixelsamples", 4), 1, 512, "pixelsamples", "Allows you to specify how many samples per pixel are computed", gui)
2953 def luxSurfaceIntegrator(scn, gui=None):
2954 global icon_c_integrator
2957 integratortype = luxProp(scn, "sintegrator.type", "bidirectional")
2959 str = luxIdentifier("SurfaceIntegrator", integratortype, ["directlighting", "path", "bidirectional", "exphotonmap", "distributedpath", "igi" ], "INTEGRATOR", "select surface integrator type", gui, icon_c_integrator)
2962 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
2963 showadvanced = luxProp(scn, "sintegrator.showadvanced", parammodeadvanced.get())
2964 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
2966 showhelp = luxProp(scn, "sintegrator.showhelp", "false")
2967 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
2969 if integratortype.get() == "directlighting":
2970 if showadvanced.get()=="false":
2971 # Default parameters
2972 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
2973 str += luxInt("maxdepth", luxProp(scn, "sintegrator.dlighting.maxdepth", 8), 0, 2048, "bounces", "The maximum recursion depth for ray casting", gui, 2.0)
2975 if showadvanced.get()=="true":
2976 # Advanced parameters
2977 str += luxOption("strategy", luxProp(scn, "sintegrator.dlighting.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
2978 if gui: gui.newline(" Depth:")
2979 str += luxInt("maxdepth", luxProp(scn, "sintegrator.dlighting.maxdepth", 8), 0, 2048, "max-depth", "The maximum recursion depth for ray casting", gui)
2980 if gui: gui.newline()
2982 if integratortype.get() == "path":
2983 if showadvanced.get()=="false":
2984 # Default parameters
2985 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
2986 str += luxInt("maxdepth", luxProp(scn, "sintegrator.path.maxdepth", 10), 0, 2048, "bounces", "The maximum recursion depth for ray casting", gui, 1.0)
2987 ienv = luxProp(scn, "sintegrator.path.ienvironment", "true")
2988 str += luxBool("includeenvironment", ienv, "Include Environment", "Enable/Disable rendering of environment lightsources", gui)
2990 if showadvanced.get()=="true":
2991 # Advanced parameters
2992 if gui: gui.newline(" Depth:")
2993 str += luxInt("maxdepth", luxProp(scn, "sintegrator.path.maxdepth", 10), 0, 2048, "maxdepth", "The maximum recursion depth for ray casting", gui)
2994 str += luxOption("strategy", luxProp(scn, "sintegrator.path.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
2995 if gui: gui.newline(" RR:")
2996 rrstrat = luxProp(scn, "sintegrator.path.rrstrategy", "efficiency")
2997 str += luxOption("rrstrategy", rrstrat, ["efficiency", "probability", "none"], "RR strategy", "select Russian Roulette path termination strategy", gui)
2998 if rrstrat.get() == "probability":
2999 str += luxFloat("rrcontinueprob", luxProp(scn, "sintegrator.path.rrcontinueprob", 0.65), 0.0, 1.0, "rrprob", "Russian roulette continue probability", gui)
3000 ienv = luxProp(scn, "sintegrator.path.ienvironment", "true")
3001 str += luxBool("includeenvironment", ienv, "Include Environment", "Enable/Disable rendering of environment lightsources", gui)
3003 if integratortype.get() == "bidirectional":
3004 if showadvanced.get()=="false":
3005 # Default parameters
3006 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
3007 bounces = luxProp(scn, "sintegrator.bidir.bounces", 16)
3008 luxInt("bounces", bounces, 5, 32, "bounces", "The maximum recursion depth for ray casting (in both directions)", gui, 2.0)
3009 str += "\n \"integer eyedepth\" [%i]\n"%bounces.get()
3010 str += " \"integer lightdepth\" [%i]"%bounces.get()
3012 if showadvanced.get()=="true":
3013 # Advanced parameters
3014 if gui: gui.newline(" Depth:")
3015 str += luxInt("eyedepth", luxProp(scn, "sintegrator.bidir.eyedepth", 16), 0, 2048, "eyedepth", "The maximum recursion depth for ray casting", gui)
3016 str += luxInt("lightdepth", luxProp(scn, "sintegrator.bidir.lightdepth", 16), 0, 2048, "lightdepth", "The maximum recursion depth for light ray casting", gui)
3017 str += luxOption("strategy", luxProp(scn, "sintegrator.bidir.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
3019 str += luxFloat('eyerrthreshold', luxProp(scn, "sintegrator.bidir.eyerrthreshold", 0), 0, 1, "eyerrthreshold", "The minimum probability for russian roulette eye subpath termination ", gui)
3020 str += luxFloat('lightrrthreshold', luxProp(scn, "sintegrator.bidir.lightrrthreshold", 0), 0, 1, "lightrrthreshold", "The minimum probability for russian roulette light subpath termination ", gui)
3022 if integratortype.get() == "exphotonmap":
3023 if gui: gui.newline(" Render:")
3024 str += luxOption("renderingmode", luxProp(scn, "sintegrator.photonmap.renderingmode", "directlighting"), ["directlighting", "path"], "renderingmode", "select rendering mode", gui)
3025 str += luxOption("strategy", luxProp(scn, "sintegrator.photonmap.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
3026 str += luxInt("maxphotondepth", luxProp(scn, "sintegrator.photonmap.maxphotondepth", 10), 1, 1024, "maxphotondepth", "The maximum recursion depth of photon tracing", gui)
3027 str += luxInt("maxdepth", luxProp(scn, "sintegrator.photonmap.maxdepth", 6), 1, 1024, "maxdepth", "The maximum recursion depth of specular reflection and refraction", gui)
3028 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)
3029 str += luxInt("nused", luxProp(scn, "sintegrator.photonmap.nused", 50), 0, 1000000, "nused", "The number of photons to use in density estimation", gui)
3031 if gui: gui.newline(" Photons:")
3032 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)
3033 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)
3034 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)
3035 if gui: gui.newline(" FinalGather:")
3036 fg = luxProp(scn, "sintegrator.photonmap.fgather", "true")
3037 str += luxBool("finalgather", fg, "finalgather", "Enable use of final gather during rendering", gui)
3038 if fg.get() == "true":
3039 rrstrat = luxProp(scn, "sintegrator.photonmap.gatherrrstrategy", "efficiency")
3040 str += luxOption("gatherrrstrategy", rrstrat, ["efficiency", "probability", "none"], "RR strategy", "select Russian Roulette gather termination strategy", gui)
3041 str += luxInt("finalgathersamples", luxProp(scn, "sintegrator.photonmap.fgathers", 32), 1, 1024, "samples", "The number of finalgather samples to take per pixel during rendering", gui)
3042 str += luxFloat("gatherangle", luxProp(scn, "sintegrator.photonmap.gangle", 10.0), 0.0, 360.0, "gatherangle", "Angle for final gather", gui)
3043 if rrstrat.get() == "probability":
3044 str += luxFloat("gatherrrcontinueprob", luxProp(scn, "sintegrator.photonmap.gatherrrcontinueprob", 0.65), 0.0, 1.0, "rrcontinueprob", "Probability for russian roulette particle tracing termination", gui)
3046 if integratortype.get() == "distributedpath":
3047 str += luxOption("strategy", luxProp(scn, "sintegrator.distributedpath.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
3048 if gui: gui.newline(" Direct:")
3049 str += luxBool("directsampleall",luxProp(scn, "sintegrator.distributedpath.directsampleall", "true"), "Direct ALL", "Include diffuse direct light sample at first vertex", gui, 0.7)
3050 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.3)
3051 str += luxBool("indirectsampleall",luxProp(scn, "sintegrator.distributedpath.indirectsampleall", "false"), "Indirect ALL", "Include diffuse direct light sample at first vertex", gui, 0.7)
3052 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.3)
3053 if gui: gui.newline(" Diffuse:")
3054 str += luxInt("diffusereflectdepth", luxProp(scn, "sintegrator.distributedpath.diffusereflectdepth", 3), 0, 2048, "Reflect", "The maximum recursion depth for diffuse reflection ray casting", gui, 0.5)
3055 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.3)
3056 str += luxInt("diffuserefractdepth", luxProp(scn, "sintegrator.distributedpath.diffuserefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for diffuse refraction ray casting", gui, 0.5)
3057 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.3)
3058 str += luxBool("directdiffuse",luxProp(scn, "sintegrator.distributedpath.directdiffuse", "true"), "DL", "Include diffuse direct light sample at first vertex", gui, 0.20)
3059 str += luxBool("indirectdiffuse",luxProp(scn, "sintegrator.distributedpath.indirectdiffuse", "true"), "IDL", "Include diffuse indirect light sample at first vertex", gui, 0.20)
3060 if gui: gui.newline(" Glossy:")
3061 str += luxInt("glossyreflectdepth", luxProp(scn, "sintegrator.distributedpath.glossyreflectdepth", 2), 0, 2048, "Reflect", "The maximum recursion depth for glossy reflection ray casting", gui, 0.50)
3062 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.3)
3063 str += luxInt("glossyrefractdepth", luxProp(scn, "sintegrator.distributedpath.glossyrefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for glossy refraction ray casting", gui, 0.50)
3064 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.3)
3065 str += luxBool("directglossy",luxProp(scn, "sintegrator.distributedpath.directglossy", "true"), "DL", "Include glossy direct light sample at first vertex", gui, 0.20)
3066 str += luxBool("indirectglossy",luxProp(scn, "sintegrator.distributedpath.indirectglossy", "true"), "IDL", "Include glossy indirect light sample at first vertex", gui, 0.20)
3067 if gui: gui.newline(" Specular:")
3068 str += luxInt("specularreflectdepth", luxProp(scn, "sintegrator.distributedpath.specularreflectdepth", 3), 0, 2048, "Reflect", "The maximum recursion depth for specular reflection ray casting", gui, 1.0)
3069 str += luxInt("specularrefractdepth", luxProp(scn, "sintegrator.distributedpath.specularrefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for specular refraction ray casting", gui, 1.0)
3070 #if gui: gui.newline(" Caustics:")
3071 #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)
3072 #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)
3074 usereject = luxProp(scn, "sintegrator.distributedpath.usereject", "false")
3075 luxCollapse("usereject", usereject, "Rejection", "Enable Rejection system to eliminate bright contributions", gui, 2.0)
3077 if usereject.get()=="true":
3078 if gui: gui.newline(" Diffuse:")
3080 diffusereflectreject = luxProp(scn, "sintegrator.distributedpath.difreflreject", "false")
3081 str += luxBool("diffusereflectreject", diffusereflectreject, "Reflect", "Enable Rejection for Diffuse Reflection", gui, 0.4)
3082 if diffusereflectreject.get()=="true":
3083 str += luxFloat("diffusereflectreject_threshold", luxProp(scn, "sintegrator.distributedpath.difreflrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3085 diffuserefractreject = luxProp(scn, "sintegrator.distributedpath.difrefrreject", "false")
3086 str += luxBool("diffuserefractreject", diffuserefractreject, "Refract", "Enable Rejection for Diffuse Refraction", gui, 0.4)
3087 if diffuserefractreject.get()=="true":
3088 str += luxFloat("diffuserefractreject_threshold", luxProp(scn, "sintegrator.distributedpath.difrefrrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3090 if gui: gui.newline(" Glossy:")
3092 glossyreflectreject = luxProp(scn, "sintegrator.distributedpath.glosreflreject", "false")
3093 str += luxBool("glossyreflectreject", glossyreflectreject, "Reflect", "Enable Rejection for Glossy Reflection", gui, 0.4)
3094 if glossyreflectreject.get()=="true":
3095 str += luxFloat("glossyreflectreject_threshold", luxProp(scn, "sintegrator.distributedpath.glosreflrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3097 glossyrefractreject = luxProp(scn, "sintegrator.distributedpath.glosrefrreject", "false")
3098 str += luxBool("glossyrefractreject", glossyrefractreject, "Refract", "Enable Rejection for Glossy Refraction", gui, 0.4)
3099 if glossyrefractreject.get()=="true":
3100 str += luxFloat("glossyrefractreject_threshold", luxProp(scn, "sintegrator.distributedpath.glosrefrrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3102 if integratortype.get() == "igi":
3103 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
3104 depth = luxProp(scn, "sintegrator.igi.maxdepth", 5)
3105 luxInt("maxdepth", depth, 1, 32, "maxdepth", "The maximum recursion depth for ray casting", gui, 2.0)
3106 if showadvanced.get()=="true":
3107 # Advanced parameters
3108 if gui: gui.newline(" VLights:")
3109 str += luxInt("nsets", luxProp(scn, "sintegrator.igi.nsets", 4), 1, 100, "nsets", "The number of virtual lights sets", gui)
3110 str += luxInt("nlights", luxProp(scn, "sintegrator.igi.nlights", 64), 1, 1000, "nlights", "The number of light paths per light set", gui)
3111 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)
3116 def luxVolumeIntegrator(scn, gui=None):
3117 global icon_c_volumeintegrator
3120 integratortype = luxProp(scn, "vintegrator.type", "single")
3121 str = luxIdentifier("VolumeIntegrator", integratortype, ["emission", "single"], "VOLUME INT", "select volume integrator type", gui, icon_c_volumeintegrator)
3122 if integratortype.get() == "emission":
3123 str += luxFloat("stepsize", luxProp(scn, "vintegrator.emission.stepsize", 1.0), 0.0, 100.0, "stepsize", "Stepsize for volumes", gui)
3124 if integratortype.get() == "single":
3125 str += luxFloat("stepsize", luxProp(scn, "vintegrator.emission.stepsize", 1.0), 0.0, 100.0, "stepsize", "Stepsize for volumes", gui)
3128 def luxEnvironment(scn, gui=None):
3129 global icon_c_environment
3132 envtype = luxProp(scn, "env.type", "infinite")
3133 lsstr = luxIdentifier("LightSource", envtype, ["none", "infinite", "sunsky"], "ENVIRONMENT", "select environment light type", gui, icon_c_environment)
3134 if gui: gui.newline()
3137 if envtype.get() != "none":
3139 if envtype.get() in ["infinite", "sunsky"]:
3140 env_lg = luxProp(scn, "env.lightgroup", "default")
3141 luxString("env.lightgroup", env_lg, "lightgroup", "Environment light group", gui)
3142 if luxProp(scn, "nolg", "false").get()!="true":
3143 lsstr = '\nLightGroup "' + env_lg.get() + '"' + lsstr
3144 rotZ = luxProp(scn, "env.rotation", 0.0)
3145 rotY = luxProp(scn, "env.rotationY", 0.0)
3146 rotX = luxProp(scn, "env.rotationX", 0.0)
3147 if gui: gui.newline()
3148 luxFloat("rotation", rotX, 0.0, 360.0, "rot X", "environment rotation X", gui, 0.66)
3149 luxFloat("rotation", rotY, 0.0, 360.0, "rot Y", "environment rotation Y", gui, 0.66)
3150 luxFloat("rotation", rotZ, 0.0, 360.0, "rot Z", "environment rotation Z", gui, 0.66)
3151 if rotZ.get() != 0 or rotY.get() != 0 or rotX.get() != 0:
3152 str += "\tRotate %d 1 0 0\n"%(rotX.get())
3153 str += "\tRotate %d 0 1 0\n"%(rotY.get())
3154 str += "\tRotate %d 0 0 1\n"%(rotZ.get())
3158 if envtype.get() == "infinite":
3159 mapping = luxProp(scn, "env.infinite.mapping", "latlong")
3160 mappings = ["latlong","angular","vcross"]
3161 mapstr = luxOption("mapping", mapping, mappings, "mapping", "Select mapping type", gui, 0.5)
3162 map = luxProp(scn, "env.infinite.mapname", "")
3163 mapstr += luxFile("mapname", map, "map-file", "filename of the environment map", gui, 1.5)
3164 mapstr += luxFloat("gamma", luxProp(scn, "env.infinite.gamma", 1.0), 0.0, 6.0, "gamma", "", gui, 1.0)
3170 worldcolor = Blender.World.Get('World').getHor()
3171 str += "\n \"color L\" [%g %g %g]" %(worldcolor[0], worldcolor[1], worldcolor[2])
3174 str += luxFloat("gain", luxProp(scn, "env.infinite.gain", 1.0), 0.0001, 100.0, "gain", "Infinite Env Gain", gui, 1.0)
3176 infinitesun = luxProp(scn, "env.infinite.hassun", "false")
3177 luxCollapse("infinitesun", infinitesun, "Sun Component", "Add Sunlight Component", gui, 2.0)
3178 if(infinitesun.get() == "true"):
3179 sun_lg = luxProp(scn, "env.sun_lightgroup", "default")
3180 luxString("env.lightgroup", sun_lg, "lightgroup", "Sun component light group", gui)
3181 if luxProp(scn, "nolg", "false").get()!="true":
3182 str += '\nLightGroup "' + sun_lg.get() + '"'
3183 str += "\nLightSource \"sun\" "
3187 if envtype.get() == "sunsky" or infinitehassun == 1:
3191 for obj in scn.objects:
3192 if (obj.getType() == "Lamp") and ((obj.Layers & scn.Layers) > 0):
3193 if obj.getData(mesh=1).getType() == 1: # sun object # data
3196 str += luxFloat("gain", luxProp(scn, "env.sunsky.gain", 1.0), 0.0001, 100.0, "gain", "Sky gain", gui)
3198 invmatrix = Mathutils.Matrix(sun.getInverseMatrix())
3199 str += "\n \"vector sundir\" [%f %f %f]\n" %(invmatrix[0][2], invmatrix[1][2], invmatrix[2][2])
3200 str += luxFloat("relsize", luxProp(scn, "env.sunsky.relsize", 1.0), 0.0, 100.0, "rel.size", "relative sun size", gui)
3201 str += luxFloat("turbidity", luxProp(scn, "env.sunsky.turbidity", 2.2), 2.0, 50.0, "turbidity", "Sky turbidity", gui)
3203 showGeo = luxProp(sun, 'sc.show', 'false')
3205 luxCollapse("sc.show", showGeo, "Geographic Sun", "Set sun position by world location, date and time", gui, 2.0)
3206 if gui and showGeo.get() == 'true':
3207 gui.newline("Geographic:")
3208 sc = sun_calculator(sun)
3210 luxInt("sc.day", luxProp(sun, "sc.day", 1), 1, 31, "day", "Local date: day", gui, 0.66)
3211 luxInt("sc.month", luxProp(sun, "sc.month", 1), 1, 12, "month", "Local date: month", gui, 0.67)
3212 luxInt("sc.year", luxProp(sun, "sc.year", 2009), 1800, 2100, "year", "Local date: year", gui, 0.66)
3214 luxInt("sc.hour", luxProp(sun, "sc.hour", 0), 0, 23, "hour", "Local time: hour", gui, 0.72)
3215 luxInt("sc.minute", luxProp(sun, "sc.minute", 0), 0, 59, "minute", "Local time: minute", gui, 0.72)
3216 luxBool("sc.dst", luxProp(sun, "sc.dst", 'false'), "DST", "DST", gui, 0.28)
3217 r = gui.getRect(0.28,1)
3218 Draw.Button("NOW", 0, r[0], r[1], r[2], r[3], "Set to current time", lambda e,v: sc.now())
3220 r = gui.getRect(0.3,1)
3221 Draw.Button("Preset", 0, r[0], r[1], r[2], r[3], "Choose a preset location", lambda e,v: sc.set_location(
3222 Draw.PupTreeMenu(sun_calculator.location_list)
3225 luxFloat("sc.lat", luxProp(sun, "sc.lat", 0.0), -90.0, 90.0, "lat", "Location: latitude", gui, 0.56)
3226 luxFloat("sc.long", luxProp(sun, "sc.long", 0.0), -180.0, 180.0, "long", "Location: longitude", gui, 0.56)
3227 luxInt("sc.tz", luxProp(sun, "sc.tz", 0), -12, 12, "timezone", "Local time: timezone offset from GMT", gui, 0.56)
3229 r = gui.getRect(2,1)
3230 Draw.Button("Calculate", 0, r[0], r[1], r[2], r[3], "Calculate sun's position", lambda e,v: sc.compute())
3234 gui.newline(); r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5)
3235 Draw.Text("create a blender Sun Lamp")
3239 #if gui: gui.newline("GLOBAL:", 8, 0, None, [0.75,0.5,0.25])
3240 #luxFloat("scale", luxProp(scn, "global.scale", 1.0), 0.0, 10.0, "scale", "global world scale", gui)
3244 class sun_calculator:
3245 #Based on SunLight v1.0 by Miguel Kabantsov (miguelkab@gmail.com)
3246 #Replaces the faulty sun position calculation algorythm with a precise calculation (Source for algorythm: http://de.wikipedia.org/wiki/Sonnenstand),
3247 #Co-Ordinates: http://www.bcca.org/misc/qiblih/latlong.html
3248 #Author: Nils-Peter Fischer (Nils-Peter.Fischer@web.de)
3266 ("Antwerp, Belgium", 67),
3267 ("Berlin, Germany", 1),
3268 ("Bratislava, Slovak Republic", 70),
3269 ("Brno, Czech Republic", 72),
3270 ("Brussles, Belgium", 68),
3271 ("Geneva, Switzerland", 65),
3272 ("Helsinki, Finland", 7),
3273 ("Innsbruck, Austria", 62),
3274 ("Kyiv, Ukraine", 64),
3275 ("London, England", 10),
3276 ("Lyon, France", 66),
3277 ("Nitra, Slovak Republic", 69),
3278 ("Oslo, Norway", 58),
3279 ("Paris, France", 15),
3280 ("Praha, Czech Republic", 71),
3281 ("Rome, Italy", 18),
3282 ("Telfs, Austria", 63),
3283 ("Warsaw, Poland", 74),
3284 ("Wroclaw, Poland", 73),
3285 ("Zurich, Switzerland", 21),
3289 ("Beijing, China", 0),
3290 ("Bombay, India", 2),
3291 ("Buenos Aires, Argentina", 3),
3292 ("Cairo, Egypt", 4),
3293 ("Cape Town, South Africa", 5),
3294 ("Caracas, Venezuela", 6),
3295 ("Curitiba, Brazil", 60),
3296 ("Hong Kong, China", 8),
3297 ("Jerusalem, Israel", 9),
3298 ("Joinville, Brazil", 61),
3299 ("Mexico City, Mexico", 11),
3300 ("Moscow, Russia", 12),
3301 ("New Delhi, India", 13),
3302 ("Ottawa, Canada", 14),
3303 ("Rio de Janeiro, Brazil", 16),
3304 ("Riyadh, Saudi Arabia", 17),
3305 ("Sao Paulo, Brazil", 59),
3306 ("Sydney, Australia", 19),
3307 ("Tokyo, Japan", 20),
3311 ("Albuquerque, NM", 22),
3312 ("Anchorage, AK", 23),
3313 ("Atlanta, GA", 24),
3315 ("Birmingham, AL", 26),
3316 ("Bismarck, ND", 27),
3318 ("Boulder, CO", 29),
3319 ("Chicago, IL", 30),
3322 ("Detroit, MI", 33),
3323 ("Honolulu, HI", 34),
3324 ("Houston, TX", 35),
3325 ("Indianapolis, IN", 36),
3326 ("Jackson, MS", 37),
3327 ("Kansas City, MO", 38),
3328 ("Los Angeles, CA", 39),
3329 ("Menomonee Falls, WI", 40),
3331 ("Minneapolis, MN", 42),
3332 ("New Orleans, LA", 43),
3333 ("New York City, NY", 44),
3334 ("Oklahoma City, OK", 45),
3335 ("Philadelphia, PA", 46),
3336 ("Phoenix, AZ", 47),
3337 ("Pittsburgh, PA", 48),
3338 ("Portland, ME", 49),
3339 ("Portland, OR", 50),
3340 ("Raleigh, NC", 51),
3341 ("Richmond, VA", 52),
3342 ("Saint Louis, MO", 53),
3343 ("San Diego, CA", 54),
3344 ("San Francisco, CA", 55),
3345 ("Seattle, WA", 56),
3346 ("Washington DC", 57),
3352 67: ( 51.2167, 4.4, 1),
3353 1: ( 52.33, 13.30, 1),
3354 70: ( 48.17, 17.17, 1),
3355 72: ( 49.2, 16.63, 1),
3356 68: ( 58.8467, 4.3525, 1),
3357 65: ( 46.217, 6.150, 1),
3358 7: ( 60.1667, 24.9667,2),
3359 62: ( 47.2672, 11.3928, 1),
3360 64: ( 50.75, 30.0833, 2),
3361 10: ( 51.50, 0.0, 0),
3362 66: ( 45.767, 4.833, 1),
3363 69: ( 48.32, 18.07, 1),
3364 58: ( 59.56, 10.41, 1),
3365 15: ( 48.8667, 2.667, 1),
3366 71: ( 50.08, 14.46, 1),
3367 18: ( 41.90, 12.4833, 1),
3368 63: ( 47.3, 11.0667, 1),
3369 74: ( 52.232, 21.008, 1),
3370 73: ( 51.108, 17.038, 1),
3371 21: ( 47.3833, 8.5333, 1),
3374 0: ( 39.9167, 116.4167, 8),
3375 2: ( 18.9333, 72.8333, 5.5),
3376 3: (-34.60, -58.45, -3),
3377 4: ( 30.10, 31.3667, 2),
3378 5: (-33.9167, 18.3667, 2),
3379 6: ( 10.50, -66.9333, -4),
3380 60: (-25.4278, -49.2731, -3),
3381 8: ( 22.25, 114.1667, 8),
3382 9: ( 31.7833, 35.2333, 2),
3383 61: (-29.3044, -48.8456, -3),
3384 11: ( 19.4, -99.15, -6),
3385 12: ( 55.75, 37.5833, 3),
3386 13: ( 28.6, 77.2, 5.5),
3387 14: ( 45.41667, -75.7, -5),
3388 16: (-22.90, -43.2333, -3),
3389 17: ( 24.633, 46.71667, 3),
3390 59: ( -23.5475, -46.6361, -3),
3391 19: (-33.8667,151.2167,10),
3392 20: ( 35.70, 139.7667, 9),
3395 22: ( 35.0833, -106.65, -7),
3396 23: ( 61.217, -149.90, -9),
3397 24: ( 33.733, -84.383, -5),
3398 25: ( 30.283, -97.733, -6),
3399 26: ( 33.521, -86.8025, -6),
3400 27: ( 46.817, -100.783, -6),
3401 28: ( 42.35, -71.05, -5),
3402 29: ( 40.125, -105.237, -7),
3403 30: ( 41.85, -87.65, -6),
3404 31: ( 32.46, -96.47, -6),
3405 32: ( 39.733, -104.983, -7),
3406 33: ( 42.333, -83.05, -5),
3407 34: ( 21.30, -157.85, -10),
3408 35: ( 29.75, -95.35, -6),
3409 36: ( 39.767, -86.15, -5),
3410 37: ( 32.283, -90.183, -6),
3411 38: ( 39.083, -94.567, -6),
3412 39: ( 34.05, -118.233, -8),
3413 40: ( 43.11, -88.10, -6),
3414 41: ( 25.767, -80.183, -5),
3415 42: ( 44.967, -93.25, -6),
3416 43: ( 29.95, -90.067, -6),
3417 44: ( 40.7167, -74.0167, -5),
3418 45: ( 35.483, -97.533, -6),
3419 46: ( 39.95, -75.15, -5),
3420 47: ( 33.433, -112.067,-7),
3421 48: ( 40.433, -79.9833, -5),
3422 49: ( 43.666, -70.283, -5),
3423 50: ( 45.517, -122.65, -8),
3424 51: ( 35.783, -78.65, -5),
3425 52: ( 37.5667, -77.450, -5),
3426 53: ( 38.6167, -90.1833, -6),
3427 54: ( 32.7667, -117.2167, -8),
3428 55: ( 37.7667, -122.4167, -8),
3429 56: ( 47.60, -122.3167, -8),
3430 57: ( 38.8833, -77.0333, -5),
3433 def __init__(self, sun):
3437 ct = time.localtime()
3444 luxProp(self.sun, 'sc.day', 0).set(ct[2])
3445 luxProp(self.sun, 'sc.month', 0).set(ct[1])
3446 luxProp(self.sun, 'sc.year', 0).set(ct[0])
3447 luxProp(self.sun, 'sc.hour', 0).set(ct[3])
3448 luxProp(self.sun, 'sc.minute', 0).set(ct[4])
3449 luxProp(self.sun, 'sc.dst', 0).set(dst)
3453 def set_location(self, location):
3454 if location < 0: return
3456 lat, long, tz = self.location_data[location]
3457 luxProp(self.sun, "sc.lat", 0).set(lat)
3458 luxProp(self.sun, "sc.long", 0).set(long)
3459 luxProp(self.sun, "sc.tz", 0).set(tz)
3465 self.lat = luxProp(self.sun, "sc.lat", 0).get()
3466 self.long = luxProp(self.sun, "sc.long", 0).get()
3467 self.tz = luxProp(self.sun, "sc.tz", 0).get()
3469 self.hour = luxProp(self.sun, "sc.hour", 0).get()
3470 self.min = luxProp(self.sun, "sc.minute", 0).get()
3471 self.dst = luxProp(self.sun, "sc.dst", 'false').get()
3472 if self.dst == 'true':
3477 self.day = luxProp(self.sun, "sc.day", 0).get()
3478 self.month = luxProp(self.sun, "sc.month", 0).get()
3479 self.year = luxProp(self.sun, "sc.year", 0).get()
3482 az,el = self.geoSunData(
3488 self.hour + self.min/60.0,
3492 self.sun.rot = math.radians(90-el), 0, math.radians(-az)
3497 # --- THE FOLLOWING METHODS ARE ADAPTED FROM LUXMAYA ---
3499 # mathematical helpers
3500 def sind(self, deg):
3501 return math.sin(math.radians(deg))
3503 def cosd(self, deg):
3504 return math.cos(math.radians(deg))
3506 def tand(self, deg):
3507 return math.tan(math.radians(deg))
3509 def asind(self, deg):
3510 return math.degrees(math.asin(deg))
3512 def atand(self, deg):
3513 return math.degrees(math.atan(deg))
3516 def geo_sun_astronomicJulianDate(self, Year, Month, Day, LocalTime, Timezone):
3518 See quoted source in class header for explanation
3528 UT = LocalTime - Timezone
3531 B = 2.0 - A+int(A/4.0)
3533 JD = math.floor(365.25*(Y+4716.0)) + math.floor(30.6001*(M+1.0)) + Day + hour + B - 1524.4
3537 def geoSunData(self, Latitude, Longitude, Year, Month, Day, LocalTime, Timezone):
3539 See quoted source in class header for explanation
3542 JD = self.geo_sun_astronomicJulianDate(Year, Month, Day, LocalTime, Timezone)
3548 LDeg = (280.460 + 0.9856474*n) - (math.floor((280.460 + 0.9856474*n)/360.0) * 360.0)
3549 gDeg = (357.528 + 0.9856003*n) - (math.floor((357.528 + 0.9856003*n)/360.0) * 360.0)
3550 LambdaDeg = LDeg + 1.915 * self.sind(gDeg) + 0.02 * self.sind(2.0*gDeg)
3552 epsilonDeg = 23.439 - 0.0000004*n
3554 alphaDeg = self.atand( (self.cosd(epsilonDeg) * self.sind(LambdaDeg)) / self.cosd(LambdaDeg) )
3555 if self.cosd(LambdaDeg) < 0.0:
3558 deltaDeg = self.asind( self.sind(epsilonDeg) * self.sind(LambdaDeg) )
3560 JDNull = self.geo_sun_astronomicJulianDate(Year, Month, Day, 0.0, 0.0)
3562 TNull = (JDNull - 2451545.0) / 36525.0
3563 T = LocalTime - Timezone
3565 thetaGh = 6.697376 + 2400.05134*TNull + 1.002738*T
3566 thetaGh -= math.floor(thetaGh/24.0) * 24.0
3568 thetaG = thetaGh * 15.0
3569 theta = thetaG + llambda
3571 tau = theta - alphaDeg
3573 a = self.atand( self.sind(tau) / ( self.cosd(tau)*self.sind(phi) - self.tand(deltaDeg)*self.cosd(phi)) )
3574 if self.cosd(tau)*self.sind(phi) - self.tand(deltaDeg)*self.cosd(phi) < 0.0:
3577 h = self.asind( self.cosd(deltaDeg)*self.cosd(tau)*self.cosd(phi) + self.sind(deltaDeg)*self.sind(phi) )
3579 R = 1.02 / (self.tand (h+(10.3/(h+5.11))))
3585 return azimuth, elevation
3587 def luxAccelerator(scn, gui=None):
3590 acceltype = luxProp(scn, "accelerator.type", "tabreckdtree")
3591 str = luxIdentifier("Accelerator", acceltype, ["none", "tabreckdtree", "grid", "bvh", "qbvh"], "ACCEL", "select accelerator type", gui)
3592 if acceltype.get() == "tabreckdtree":
3593 if gui: gui.newline()
3594 str += luxInt("intersectcost", luxProp(scn, "accelerator.kdtree.interscost", 80), 0, 1000, "inters.cost", "specifies how expensive ray-object intersections are", gui)
3595 str += luxInt("traversalcost", luxProp(scn, "accelerator.kdtree.travcost", 1), 0, 1000, "trav.cost", "specifies how expensive traversing a ray through the kdtree is", gui)
3596 if gui: gui.newline()
3597 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)
3598 if gui: gui.newline()
3599 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)
3600 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)
3601 if acceltype.get() == "unsafekdtree":
3602 if gui: gui.newline()
3603 str += luxInt("intersectcost", luxProp(scn, "accelerator.kdtree.interscost", 80), 0, 1000, "inters.cost", "specifies how expensive ray-object intersections are", gui)
3604 str += luxInt("traversalcost", luxProp(scn, "accelerator.kdtree.travcost", 1), 0, 1000, "trav.cost", "specifies how expensive traversing a ray through the kdtree is", gui)
3605 if gui: gui.newline()
3606 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)
3607 if gui: gui.newline()
3608 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)
3609 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)
3610 if acceltype.get() == "grid":
3611 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)
3612 if acceltype.get() == "qbvh":
3613 if gui: gui.newline()
3614 str += luxInt("maxprimsperleaf", luxProp(scn, "accelerator.qbvh.maxprimsperleaf", 4), 1, 64, "maxprimsperleaf", "Maximum number of primitives to leave in one leaf node", gui)
3617 def luxSystem(scn, gui=None):
3619 if gui: gui.newline("PATHS:", 10)
3620 lp = luxProp(scn, "lux", "")
3621 lp.set(Blender.sys.dirname(lp.get())+os.sep)
3622 luxPath("LUX dir", lp, "lux binary dir", "Lux installation path", gui, 2.0)
3624 # luxFile("GUI filename", luxProp(scn, "lux", ""), "lux-file", "filename and path of the lux GUI executable", gui, 2.0)
3625 # luxFile("Console filename", luxProp(scn, "luxconsole", ""), "lux-file-console", "filename and path of the lux console executable", gui, 2.0)
3626 if gui: gui.newline()
3627 luxFile("datadir", luxProp(scn, "datadir", ""), "default out dir", "default.lxs save path", gui, 2.0)
3629 if gui: gui.newline()
3630 pm = ["absolute","relative","flat"]
3631 luxOption("pathmode", luxProp(scn, "pathmode", "absolute"), pm, "path-mode", "select format for paths on export", gui, 2.0)
3633 if gui: gui.newline("PRIORITY:", 10)
3634 luxnice = luxProp(scn, "luxnice", 10)
3635 if osys.platform=="win32":
3636 r = gui.getRect(2, 1)
3637 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))
3638 else: luxInt("nice", luxnice, -20, 19, "nice", "nice value. Range goes from -20 (highest priority) to 19 (lowest)", gui)
3640 luxBool("noopengl", luxProp(scn, "noopengl", "false"), "Disable OpenGL", "(workaround for some buggy display drivers)", gui, 1.0)
3643 if gui: gui.newline("THREADS:", 10)
3644 autothreads = luxProp(scn, "autothreads", "true")
3645 luxBool("autothreads", autothreads, "Auto Detect", "Automatically use all available processors", gui, 1.0)
3646 if autothreads.get()=="false":
3647 luxInt("threads", luxProp(scn, "threads", 1), 1, 100, "threads", "number of threads used for rendering", gui, 1.0)
3648 # luxBool('export.threaded', luxProp(scn, 'export.threaded', 'true'), 'Pipe in background', 'When using pipe export, do not block Blender UI', gui, 1.0)
3650 if gui: gui.newline("ANIM:", 10)
3651 useparamkeys = luxProp(scn, "useparamkeys", "false")
3652 luxBool("useparamkeys", useparamkeys, "Enable Parameter IPO Keyframing", "Enables keyframing of luxblend parameters", gui, 2.0)
3654 if gui: gui.newline("PARAMS:", 10)
3655 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
3656 luxBool("parammodeadvanced", parammodeadvanced, "Default Advanced Parameters", "Always use advanced parameters by default", gui, 2.0)
3658 if gui: gui.newline("PREVIEW:", 10)
3659 qs = ["low","medium","high","very high"]
3660 defprevmat = luxProp(scn, "defprevmat", "high")
3661 luxOption("defprevmat", defprevmat, qs, "Materials", "Select default preview quality in material editor for materials", gui, 1.0)
3663 if gui: gui.newline("GAMMA:", 10)
3664 luxBool("RGC", luxProp(scn, "RGC", "true"), "RGC", "use reverse gamma correction", gui)
3665 luxBool("ColClamp", luxProp(scn, "colorclamp", "false"), "ColClamp", "clamp all colors to 0.0-0.9", gui)
3666 if gui: gui.newline("MESH:", 10)
3667 luxBool("mesh_optimizing", luxProp(scn, "mesh_optimizing", "true"), "optimize meshes", "Optimize meshes during export", gui, 2.0)
3668 #luxInt("trianglemesh thr", luxProp(scn, "trianglemesh_thr", 0), 0, 10000000, "trianglemesh threshold", "Vertex threshold for exporting (wald) trianglemesh object(s)", gui, 2.0)
3669 #if gui: gui.newline()
3670 #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)
3671 if gui: gui.newline("INSTANCING:", 10)
3672 luxInt("instancing_threshold", luxProp(scn, "instancing_threshold", 2), 0, 1000000, "object instancing threshold", "Threshold to created instanced objects", gui, 2.0)
3674 # dougal2 packed images, enable this when implemented in Lux itself
3675 #if gui: gui.newline('TEXTURES:',10)
3676 #impack = luxProp(scn, 'packtextures', 'false')
3677 #luxBool('impack', impack, 'Pack All Images', '', gui, 2.0)
3680 network=luxProp(scn,"network","false")
3681 gui.newline("NETWORK:", 10)
3682 luxCollapse("network",network, "network", "enable network option", gui, 2.0)
3683 if(network.get() == "true"):
3684 network_use_file=luxProp(scn,"network_use_file","false")
3685 luxBool ("use file",network_use_file,"use file", "get list of servers from file; one per line",gui,2.0)
3686 if (network_use_file.get() == "true"):
3687 luxFile("file", luxProp(scn, "network_file_path", ""), "file", "file where servers are defined", gui, 1.0)
3690 luxString("Servers",luxProp(scn,"network_servers",""),"servers","coma separated list of servers",gui,1.0)
3692 luxInt("network_interval",luxProp(scn,"newtork_interval",180),0,300,"update interval","interval between network refresh",gui)
3695 def scalelist(list, factor):
3696 for i in range(len(list)): list[i] = list[i] * factor
3700 def luxMapping(key, mat, gui, level=0):
3701 global icon_map2d, icon_map2dparam
3702 if gui: gui.newline("2Dmap:", -2, level, icon_map2d)
3703 mapping = luxProp(mat, key+".mapping", "uv")
3704 mappings = ["uv","spherical","cylindrical","planar"]
3705 str = luxOption("mapping", mapping, mappings, "mapping", "", gui, 0.5)
3706 if mapping.get() == "uv":
3707 if gui: gui.newline()
3708 str += luxFloat("uscale", luxProp(mat, key+".uscale", 1.0), -100.0, 100.0, "Us", "u-scale", gui, 0.5)
3709 str += luxFloat("vscale", luxProp(mat, key+".vscale", -1.0), -100.0, 100.0, "Vs", "v-scale", gui, 0.5)
3710 str += luxFloat("udelta", luxProp(mat, key+".udelta", 0.0), -100.0, 100.0, "Ud", "u-delta", gui, 0.5)
3711 str += luxFloat("vdelta", luxProp(mat, key+".vdelta", 0.0), -100.0, 100.0, "Vd", "v-delta", gui, 0.5)
3712 if mapping.get() == "planar":
3713 str += luxFloat("udelta", luxProp(mat, key+".udelta", 0.0), -100.0, 100.0, "Ud", "u-delta", gui, 0.75)
3714 str += luxFloat("vdelta", luxProp(mat, key+".vdelta", 0.0), -100.0, 100.0, "Vd", "v-delta", gui, 0.75)
3715 if gui: gui.newline("v1:", -2, level+1, icon_map2dparam)
3716 str += luxVector("v1", luxProp(mat, key+".v1", "1 0 0"), -100.0, 100.0, "v1", "v1-vector", gui, 2.0)
3717 if gui: gui.newline("v2:", -2, level+1, icon_map2dparam)
3718 str += luxVector("v2", luxProp(mat, key+".v2", "0 1 0"), -100.0, 100.0, "v2", "v2-vector", gui, 2.0)
3721 def lux3DMapping(key, mat, gui, level=0):
3722 global icon_map3dparam
3724 if gui: gui.newline("scale:", -2, level, icon_map3dparam)
3725 str += luxVectorUniform("scale", luxProp(mat, key+".3dscale", 1.0), 0.001, 1000.0, "scale", "scale-vector", gui, 2.0)
3726 if gui: gui.newline("rot:", -2, level, icon_map3dparam)
3727 str += luxVector("rotate", luxProp(mat, key+".3drotate", "0 0 0"), -360.0, 360.0, "rotate", "rotate-vector", gui, 2.0)
3728 if gui: gui.newline("move:", -2, level, icon_map3dparam)
3729 str += luxVector("translate", luxProp(mat, key+".3dtranslate", "0 0 0"), -1000.0, 1000.0, "move", "translate-vector", gui, 2.0)
3732 def getTreeNameById(tree, i): # helper function to retrive name of the selected treemenu-item
3734 if type(t)==types.TupleType:
3735 if type(t[1])==types.ListType:
3736 n=getTreeNameById(t[1], i)
3738 elif t[1]==i: return t[0]
3741 def luxTexture(name, parentkey, type, default, min, max, caption, hint, mat, gui, matlevel, texlevel=0, lightsource=0, overrideicon=""):
3742 global icon_tex, icon_texcol, icon_texmix, icon_texmixcol, icon_texparam, icon_spectex
3744 return (t1[0]+t2[0], t1[1]+t2[1])
3745 def alternativedefault(type, default):
3746 if type=="float": return 0.0
3747 else: return "0.0 0.0 0.0"
3748 level = matlevel + texlevel
3749 keyname = "%s:%s"%(parentkey, name)
3750 texname = "%s:%s"%(mat.getName(), keyname)
3751 # if gui: gui.newline(caption+":", 0, level)
3752 if(lightsource == 0):
3753 if texlevel == 0: texture = luxProp(mat, keyname+".texture", "imagemap")
3754 else: texture = luxProp(mat, keyname+".texture", "constant")
3756 texture = luxProp(mat, keyname+".texture", "blackbody")
3758 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"]
3761 if(overrideicon != ""):
3765 if texture.get() in ["mix", "scale", "checkerboard", "dots"]:
3766 if type=="color": icon = icon_texmixcol
3767 else: icon = icon_texmix
3768 elif texture.get() in ["constant", "blackbody", "equalenergy", "frequency", "gaussian", "regulardata", "irregulardata"]:
3771 if type=="color": icon = icon_texcol
3772 else: icon = icon_tex
3773 if (texlevel > 0): gui.newline(caption+":", -2, level, icon, scalelist([0.5,0.5,0.5],2.0/(level+2)))
3774 else: gui.newline("texture:", -2, level, icon, scalelist([0.5,0.5,0.5],2.0/(level+2)))
3775 luxOption("texture", texture, textures, "texture", "", gui, 2)
3776 str = "Texture \"%s\" \"%s\" \"%s\""%(texname, type, texture.get())
3778 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))
3779 if gui: # Draw Texture level Material preview
3780 luxPreview(mat, parentkey, 1, False, False, name, gui, texlevel, [0.5, 0.5, 0.5])
3781 # Add an offset for next controls
3782 #r = gui.getRect(1.0, 1)
3785 if texture.get() == "constant":
3786 value = luxProp(mat, keyname+".value", default)
3787 if type == "float": luxFloat("value", value, min, max, "", "", gui, 1.1)
3788 elif type == "color": luxRGB("value", value, max, "", "", gui, 2)
3790 if type == "color": return ("", " \"%s %s\" [%s]"%(type, name, value.getRGC()))
3791 return ("", " \"%s %s\" [%s]"%(type, name, value.get()))
3793 # if type == "color": str += " \"%s value\" [%s]"%(type, value.getRGC())
3794 # else: str += " \"%s value\" [%s]"%(type, value.get())
3796 if texture.get() == "blackbody":
3798 if gui.xmax-gui.x < gui.w: gui.newline()
3799 r = gui.getRect(1.0, 1)
3801 drawBar(bar_blackbody, gui.xmax-gui.w-7, r[1])
3802 str += luxFloat("temperature", luxProp(mat, keyname+".bbtemp", 6500.0), 1000.0, 10000.0, "temperature", "Black Body temperature in degrees Kelvin", gui, 2.0, 1)
3804 if texture.get() == "lampspectrum":
3805 lampstring = luxProp(mat, keyname+".lampstring", "Incandescent2")
3806 lamppreset = luxProp(mat, keyname+".lampspectrum", "PHILIPS [Argenta] 200W Incandescent Lamp")
3808 def setLamp(i, value, preset, tree, dict): # callback function to set ior value after selection
3811 preset.set(getTreeNameById(tree, i))
3813 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) ] ) ]
3815 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" }
3817 r = gui.getRect(2.0, 1)
3818 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))
3819 str += luxString("name", lampstring, "Lamp", "Choose measured Lamp Spectrum", None, 2.0)
3821 if texture.get() == "equalenergy":
3823 if gui.xmax-gui.x < gui.w: gui.newline()
3824 r = gui.getRect(1.0, 1)
3826 drawBar(bar_equalenergy, gui.xmax-gui.w-7, r[1])
3827 str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Energy of each spectral band", gui, 2.0, 1)
3829 if texture.get() == "frequency":
3830 str += luxFloat("freq", luxProp(mat, keyname+".freq", 0.01), 0.01, 100.0, "frequency", "Frequency in nm", gui, 2.0, 1)
3831 str += luxFloat("phase", luxProp(mat, keyname+".phase", 0.5), 0.0, 1.0, "phase", "Phase", gui, 1.1, 1)
3832 str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Amount of mean energy", gui, 0.9, 1)
3834 if texture.get() == "gaussian":
3836 if gui.xmax-gui.x < gui.w: gui.newline()
3837 r = gui.getRect(1.0, 1)
3839 drawBar(bar_spectrum, gui.xmax-gui.w-7, r[1])
3840 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)
3841 str += luxFloat("width", luxProp(mat, keyname+".width", 50.0), 20.0, 300.0, "width", "Width of gaussian distribution in nm", gui, 1.1, 1)
3842 str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Amount of mean energy", gui, 0.9, 1)
3844 if texture.get() == "imagemap":
3845 if gui: gui.newline("IM-clip:", -2, level)
3846 str += luxOption("wrap", luxProp(mat, keyname+".wrap", "repeat"), ["repeat","black","clamp"], "repeat", "", gui, 1.0)
3848 if gui: gui.newline("IM-source:", -2, level)
3851 texturefilename = luxProp(mat, keyname+".filename", "")
3852 extimage = luxProp(mat, keyname+'.externalimage', "true")
3853 luxBool("External Image", extimage, "External Image", "External Image", gui, 1.0)
3854 if gui: gui.newline("IM-path:", -2, level)
3855 if extimage.get() == "true":
3856 luxFile("filename", texturefilename, "file", "texture file path", gui, 2.0)
3858 bil = [i.filename for i in Image.Get() if '.' in i.filename]
3860 uti = [i.filename for i in Image.Get() if '.' not in i.filename]
3862 luxLabel("INFO: Images not listed here must be saved first", gui)
3865 luxOption("Image", texturefilename, bil, "Blender Images", "Blender Image", gui, 2.0)
3867 luxLabel("No Blender Images - Load Image in the Image Editor", gui)
3868 # dougal2 image file packing
3869 impack = luxProp(Scene.GetCurrent(), 'packtextures', 'false')
3871 if impack.get() == 'false':
3872 str += luxFile("filename", texturefilename, "file", "texture file path", None, 2.0)
3875 def get_image_data(filename):
3877 f=open(filename,'rb')
3881 print('Error reading image data from %s' % filename)
3883 return base64.b64encode(zlib.compress(d))
3884 imdata = get_image_data(texturefilename.get())
3885 str += '\r\n "string imagedata" ["%s"]' % imdata
3887 useseq = luxProp(mat, keyname+".useseq", "false")
3888 luxCollapse("usesew", useseq, "Sequence", "", gui, 2.0)
3890 if useseq.get() == "true":
3891 seqframes = luxProp(mat, keyname+".seqframes", 100)
3892 luxInt("frames", seqframes, 1, 100000, "Frames", "", gui, 0.5)
3893 seqoffset = luxProp(mat, keyname+".seqoffset", 0)
3894 luxInt("offset", seqoffset, 0, 100000, "Offset", "", gui, 0.5)
3895 seqstartframe = luxProp(mat, keyname+".seqsframe", 1)
3896 luxInt("startframe", seqstartframe, 1, 100000, "StartFr", "", gui, 0.5)
3897 seqcyclic = luxProp(mat, keyname+".seqcycl", "false")
3898 luxBool("cyclic", seqcyclic, "Cyclic", "", gui, 0.5)
3901 totalframes = seqframes.get()
3902 currentframe = Blender.Get('curframe')
3904 if(currentframe < seqstartframe.get()):
3905 fnumber = 1 + seqoffset.get()
3907 fnumber = (currentframe - (seqstartframe.get()-1)) + seqoffset.get()
3909 if(fnumber > seqframes.get()):
3910 if(seqcyclic.get() == "false"):
3911 fnumber = seqframes.get()
3913 fnumber = currentframe % seqframes.get()
3916 def get_seq_filename(number, filename):
3917 m = re.findall(r'(\d+)', filename)
3919 return "ERR: Can't find pattern"
3921 rightmost_number = m[len(m)-1]
3922 seq_length = len(rightmost_number)
3925 new_seq_number = nstr.zfill(seq_length)
3927 return filename.replace(rightmost_number, new_seq_number)
3929 texturefilename.set(get_seq_filename(fnumber, texturefilename.get()))
3930 if gui: gui.newline()
3932 str += luxFloat("gamma", luxProp(mat, keyname+".gamma", texturegamma()), 0.0, 6.0, "gamma", "", gui, 0.75)
3933 str += luxFloat("gain", luxProp(mat, keyname+".gain", 1.0), 0.0, 10.0, "gain", "", gui, 0.5)
3934 filttype = luxProp(mat, keyname+".filtertype", "bilinear")
3935 filttypes = ["mipmap_ewa","mipmap_trilinear","bilinear","nearest"]
3936 str += luxOption("filtertype", filttype, filttypes, "filtertype", "Choose the filtering method to use for the image texture", gui, 0.75)
3938 if filttype.get() == "mipmap_ewa" or filttype.get() == "mipmap_trilinear":
3939 str += luxFloat("maxanisotropy", luxProp(mat, keyname+".maxanisotropy", 8.0), 1.0, 512.0, "maxaniso", "", gui, 1.0)
3940 str += luxInt("discardmipmaps", luxProp(mat, keyname+".discardmipmaps", 0), 0, 1, "discardmips", "", gui, 1.0)
3942 str += luxMapping(keyname, mat, gui, level+1)
3944 if texture.get() == "mix":
3945 (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))
3946 (s, l) = c((s, l), 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))
3950 if texture.get() == "scale":
3951 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
3952 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
3955 if texture.get() == "bilerp":
3957 str += luxFloat("v00", luxProp(mat, keyname+".v00", 0.0), min, max, "v00", "", gui, 1.0)
3958 str += luxFloat("v01", luxProp(mat, keyname+".v01", 1.0), min, max, "v01", "", gui, 1.0)
3959 if gui: gui.newline("", -2)
3960 str += luxFloat("v10", luxProp(mat, keyname+".v10", 0.0), min, max, "v10", "", gui, 1.0)
3961 str += luxFloat("v11", luxProp(mat, keyname+".v11", 1.0), min, max, "v11", "", gui, 1.0)
3962 elif type == "color":
3963 if gui: gui.newline(" v00:", -2)
3964 str += luxRGB("v00", luxProp(mat, keyname+".v00", "0.0 0.0 0.0"), max, "v00", "", gui, 2.0)
3965 if gui: gui.newline(" v01:", -2)
3966 str += luxRGB("v01", luxProp(mat, keyname+".v01", "1.0 1.0 1.0"), max, "v01", "", gui, 2.0)
3967 if gui: gui.newline(" v10:", -2)
3968 str += luxRGB("v10", luxProp(mat, keyname+".v10", "0.0 0.0 0.0"), max, "v10", "", gui, 2.0)
3969 if gui: gui.newline(" v11:", -2)
3970 str += luxRGB("v11", luxProp(mat, keyname+".v11", "1.0 1.0 1.0"), max, "v11", "", gui, 2.0)
3971 str += luxMapping(keyname, mat, gui, level+1)
3973 if texture.get() == "windy":
3974 str += lux3DMapping(keyname, mat, gui, level+1)
3975 # this texture has no options
3977 if texture.get() == "checkerboard":
3978 dim = luxProp(mat, keyname+".dim", 2)
3979 str += luxInt("dimension", dim, 2, 3, "dim", "", gui, 1)
3980 if dim.get() == 2: str += luxOption("aamode", luxProp(mat, keyname+".aamode", "closedform"), ["closedform","supersample","none"], "aamode", "antialiasing mode", gui, 0.6)
3981 if gui: gui.newline("", -2)
3982 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
3983 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
3985 if dim.get() == 2: str += luxMapping(keyname, mat, gui, level+1)
3986 if dim.get() == 3: str += lux3DMapping(keyname, mat, gui, level+1)
3988 if texture.get() == "dots":
3989 (s, l) = c(("", ""), luxTexture("inside", keyname, type, default, min, max, "inside", "", mat, gui, matlevel, texlevel+1, lightsource))
3990 (s, l) = c((s, l), luxTexture("outside", keyname, type, alternativedefault(type, default), min, max, "outside", "", mat, gui, matlevel, texlevel+1, lightsource))
3992 str += luxMapping(keyname, mat, gui, level+1)
3994 if texture.get() == "fbm":
3995 str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1)
3996 # if gui: gui.newline("", -2)
3997 str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 1, 1)
3998 if gui: gui.newline("", -2)
3999 str += lux3DMapping(keyname, mat, gui, level+1)
4001 if texture.get() == "marble":
4002 str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1)
4003 # if gui: gui.newline("", -2)
4004 str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 1, 1)
4005 if gui: gui.newline("", -2)
4006 str += luxFloat("nscale", luxProp(mat, keyname+".nscale", 1.0), 0.0, 100.0, "nscale", "Scaling factor for the noise input", gui, 1.0)
4007 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)
4008 if gui: gui.newline("", -2)
4009 str += lux3DMapping(keyname, mat, gui, level+1)
4011 if texture.get() == "wrinkled":
4012 str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1)
4013 # if gui: gui.newline("", -2)
4014 str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 1, 1)
4015 if gui: gui.newline("", -2)
4016 str += lux3DMapping(keyname, mat, gui, level+1)
4018 if texture.get() == "brick":
4019 if gui: gui.newline("brick:", -2, level+1, icon_texparam)
4021 str += luxFloat("brickwidth", luxProp(mat, keyname+".brickwidth", 0.3), 0.0, 10.0, "brickwidth (X)", "", gui, 1.0)
4022 str += luxFloat("brickheight", luxProp(mat, keyname+".brickheight", 0.1), 0.0, 10.0, "brickheight (Z)", "", gui, 1.0)
4023 str += luxFloat("brickdepth", luxProp(mat, keyname+".brickdepth", 0.15), 0.0, 10.0, "brickdepth (Y)", "", gui, 1.0)
4025 if gui: gui.newline("mortar:", -2, level+1, icon_texparam)
4027 str += luxFloat("mortarsize", luxProp(mat, keyname+".mortarsize", 0.01), 0.0, 1.0, "mortarsize", "", gui, 1.0)
4029 (s, l) = c(("", ""), luxTexture("bricktex", keyname, type, default, min, max, "bricktex", "", mat, gui, matlevel, texlevel+1, lightsource))
4030 (s, l) = c((s, l), luxTexture("mortartex", keyname, type, alternativedefault(type, default), min, max, "mortartex", "", mat, gui, matlevel, texlevel+1, lightsource))
4033 str += lux3DMapping(keyname, mat, gui, level+1)
4035 if texture.get() == "blender_marble":
4036 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4038 mtype = luxProp(mat, keyname+".mtype", "soft")
4039 mtypes = ["soft","sharp","sharper"]
4040 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
4042 noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
4043 noisetypes = ["soft_noise","hard_noise"]
4044 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
4046 str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0, 6, "noisedepth", "", gui, 0.75)
4048 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4049 str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 200.0, "turbulance", "", gui, 1.0)
4051 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
4052 noisebasis2 = luxProp(mat, keyname+".noisebasis2", "sin")
4053 noisebasises2 = ["sin","saw","tri"]
4054 str += luxOption("noisebasis2", noisebasis2, noisebasises2, "noisebasis2", "", gui, 0.7)
4056 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4057 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4058 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
4060 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4061 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4062 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4064 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4065 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4068 str += lux3DMapping(keyname, mat, gui, level+1)
4070 if texture.get() == "blender_musgrave":
4071 if gui: gui.newline("type:", -2, level+1, icon_texparam)
4072 mtype = luxProp(mat, keyname+".mtype", "multifractal")
4073 mtypes = ["multifractal","ridged_multifractal", "hybrid_multifractal", "hetero_terrain", "fbm"]
4074 str += luxOption("type", mtype, mtypes, "type", "", gui, 2.0)
4076 str += luxFloat("h", luxProp(mat, keyname+".h", 1.0), 0.0, 2.0, "h", "", gui, 0.5)
4077 str += luxFloat("lacu", luxProp(mat, keyname+".lacu", 2.0), 0.0, 6.0, "lacu", "", gui, 0.75)
4078 str += luxFloat("octs", luxProp(mat, keyname+".octs", 2.0), 0.0, 8.0, "octs", "", gui, 0.75)
4080 if mtype.get() == "hetero_terrain":
4081 str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 2.0)
4082 if mtype.get() == "ridged_multifractal":
4083 str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 1.25)
4084 str += luxFloat("gain", luxProp(mat, keyname+".gain", 2.0), 0.0, 6.0, "gain", "", gui, 0.75)
4085 if mtype.get() == "hybrid_multifractal":
4086 str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 1.25)
4087 str += luxFloat("gain", luxProp(mat, keyname+".gain", 2.0), 0.0, 6.0, "gain", "", gui, 0.75)
4089 str += luxFloat("outscale", luxProp(mat, keyname+".outscale", 1.0), 0.0, 10.0, "iscale", "", gui, 1.0)
4090 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4092 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
4093 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4094 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4095 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 2.0)
4097 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4098 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4099 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4101 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4102 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4105 str += lux3DMapping(keyname, mat, gui, level+1)
4107 if texture.get() == "blender_wood":
4108 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4110 mtype = luxProp(mat, keyname+".mtype", "bands")
4111 mtypes = ["bands","rings","bandnoise", "ringnoise"]
4112 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
4114 noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
4115 noisetypes = ["soft_noise","hard_noise"]
4116 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
4118 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4119 str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 200.0, "turbulance", "", gui, 1.0)
4121 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
4122 noisebasis2 = luxProp(mat, keyname+".noisebasis2", "sin")
4123 noisebasises2 = ["sin","saw","tri"]
4124 str += luxOption("noisebasis2", noisebasis2, noisebasises2, "noisebasis2", "", gui, 0.7)
4126 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4127 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4128 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
4130 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4131 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4132 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4134 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4135 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4138 str += lux3DMapping(keyname, mat, gui, level+1)
4140 if texture.get() == "blender_clouds":
4141 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4143 mtype = luxProp(mat, keyname+".mtype", "default")
4144 mtypes = ["default","color"]
4145 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
4147 noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
4148 noisetypes = ["soft_noise","hard_noise"]
4149 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
4151 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4152 str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0, 6, "noisedepth", "", gui, 1.0)
4154 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
4155 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4156 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4157 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
4159 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4160 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4161 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4163 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4164 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4167 str += lux3DMapping(keyname, mat, gui, level+1)
4169 if texture.get() == "blender_blend":
4170 if gui: gui.newline("type:", -2, level+1, icon_texparam)
4172 mtype = luxProp(mat, keyname+".mtype", "lin")
4173 mtypes = ["lin","quad","ease","diag","sphere","halo","radial"]
4174 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
4176 mflag = luxProp(mat, keyname+".flag", "false")
4177 str += luxBool("flipxy", mflag, "flipXY", "", gui, 0.5)
4179 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4180 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4181 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4183 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4184 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4187 str += lux3DMapping(keyname, mat, gui, level+1)
4189 if texture.get() == "blender_distortednoise":
4190 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4192 str += luxFloat("distamount", luxProp(mat, keyname+".distamount", 1.0), 0.0, 10.0, "distamount", "", gui, 1.0)
4193 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4194 str += luxFloat("nabla", luxProp(mat, keyname+".nabla", 0.025), 0.000, 2.0, "nabla", "", gui, 1.0)
4196 if gui: gui.newline("distortion:", -2, level+1, icon_texparam)
4197 ntype = luxProp(mat, keyname+".type", "blender_original")
4198 ntypes = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4199 str += luxOption("type", ntype, ntypes, "type", "", gui, 1.3)
4201 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
4202 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4203 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4204 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
4206 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4207 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4208 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4210 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4211 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4214 str += lux3DMapping(keyname, mat, gui, level+1)
4216 if texture.get() == "blender_noise":
4217 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4218 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4219 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4221 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4222 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4225 str += lux3DMapping(keyname, mat, gui, level+1)
4227 if texture.get() == "blender_magic":
4228 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4230 str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0.0, 10.0, "noisedepth", "", gui, 1.0)
4231 str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 2.0, "turbulance", "", gui, 1.0)
4233 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4234 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4235 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4237 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4238 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4241 str += lux3DMapping(keyname, mat, gui, level+1)
4243 if texture.get() == "blender_stucci":
4244 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4245 mtype = luxProp(mat, keyname+".mtype", "Plastic")
4246 mtypes = ["Plastic","Wall In","Wall Out"]
4247 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
4249 noisetype = luxProp(mat, keyname+".noisetype", "soft_noise")
4250 noisetypes = ["soft_noise","hard_noise"]
4251 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
4253 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 10.0, "noisesize", "", gui, 1.0)
4254 str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 200.0, "turbulance", "", gui, 1.0)
4256 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4257 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4258 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
4260 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4261 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4262 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4264 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4265 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4268 str += lux3DMapping(keyname, mat, gui, level+1)
4270 if texture.get() == "blender_voronoi":
4271 #if gui: gui.newline("distmetric:", -2, level+1, icon_texparam)
4272 mtype = luxProp(mat, keyname+".distmetric", "actual_distance")
4273 mtypes = ["actual_distance","distance_squared","manhattan", "chebychev", "minkovsky_half", "minkovsky_four", "minkovsky"]
4274 str += luxOption("distmetric", mtype, mtypes, "distmetric", "", gui, 1.1)
4276 if gui: gui.newline("param:", -2, level+1, icon_texparam)
4277 str += luxFloat("minkovsky_exp", luxProp(mat, keyname+".minkovsky_exp", 2.5), 0.001, 10.0, "minkovsky_exp", "", gui, 1.0)
4278 str += luxFloat("outscale", luxProp(mat, keyname+".outscale", 1.0), 0.01, 10.0, "outscale", "", gui, 1.0)
4279 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4280 str += luxFloat("nabla", luxProp(mat, keyname+".nabla", 0.025), 0.001, 0.1, "nabla", "", gui, 1.0)
4281 if gui: gui.newline("wparam:", -2, level+1, icon_texparam)
4282 str += luxFloat("w1", luxProp(mat, keyname+".w1", 1.0), -2.0, 2.0, "w1", "", gui, 1.0)
4283 str += luxFloat("w2", luxProp(mat, keyname+".w2", 0.0), -2.0, 2.0, "w2", "", gui, 1.0)
4284 str += luxFloat("w3", luxProp(mat, keyname+".w3", 0.0), -2.0, 2.0, "w3", "", gui, 1.0)
4285 str += luxFloat("w4", luxProp(mat, keyname+".w4", 0.0), -2.0, 2.0, "w4", "", gui, 1.0)
4287 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4288 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4289 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4291 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4292 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4295 str += lux3DMapping(keyname, mat, gui, level+1)
4299 return (str+"\n", " \"texture %s\" [\"%s\"]"%(name, texname))
4302 def luxSpectrumTexture(name, key, default, max, caption, hint, mat, gui, level=0):
4304 if gui: gui.newline(caption, 4, level, icon_col, scalelist([0.5,0.6,0.5],2.0/(level+2)))
4306 keyname = "%s:%s"%(key, name)
4307 texname = "%s:%s"%(mat.getName(), keyname)
4308 value = luxProp(mat, keyname, default)
4309 link = luxRGB(name, value, max, "", hint, gui, 2.0)
4310 tex = luxProp(mat, keyname+".textured", False)
4311 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)]))
4312 if tex.get()=="true":
4313 if gui: gui.newline("", -2)
4314 (str, link) = luxTexture(name, key, "color", default, 0, max, caption, hint, mat, gui, level+1)
4315 if value.getRGB() != (1.0, 1.0, 1.0):
4316 if str == "": # handle special case if texture is a just a constant
4317 str += "Texture \"%s\" \"color\" \"scale\" \"color tex1\" [%s] \"color tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
4318 else: str += "Texture \"%s\" \"color\" \"scale\" \"texture tex1\" [\"%s\"] \"color tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4319 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4322 def luxLightSpectrumTexture(name, key, default, max, caption, hint, mat, gui, level=0):
4323 #if gui: gui.newline(caption, 4, level, icon_emission, scalelist([0.6,0.5,0.5],2.0/(level+2)))
4325 keyname = "%s:%s"%(key, name)
4326 texname = "%s:%s"%(mat.getName(), keyname)
4327 (str, link) = luxTexture(name, key, "color", default, 0, max, caption, hint, mat, gui, level+1, 0, 1)
4330 def luxFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4332 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4334 keyname = "%s:%s"%(key, name)
4335 texname = "%s:%s"%(mat.getName(), keyname)
4336 value = luxProp(mat, keyname, default)
4337 link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
4338 tex = luxProp(mat, keyname+".textured", False)
4339 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)]))
4340 if tex.get()=="true":
4341 if gui: gui.newline("", -2)
4342 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4343 if value.get() != 1.0:
4344 if str == "": # handle special case if texture is a just a constant
4345 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
4346 else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4347 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4350 def luxFloatSliderTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4352 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4354 keyname = "%s:%s"%(key, name)
4355 texname = "%s:%s"%(mat.getName(), keyname)
4356 value = luxProp(mat, keyname, default)
4357 link = luxFloat(name, value, min, max, caption, hint, gui, 2.0, 1)
4358 tex = luxProp(mat, keyname+".textured", False)
4359 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)]))
4360 if tex.get()=="true":
4361 if gui: gui.newline("", -2)
4362 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4363 if value.get() != 1.0:
4364 if str == "": # handle special case if texture is a just a constant
4365 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
4366 else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4367 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4371 def luxExponentTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4373 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4375 keyname = "%s:%s"%(key, name)
4376 texname = "%s:%s"%(mat.getName(), keyname)
4377 value = luxProp(mat, keyname, default)
4379 if(value.get() == None): value.set(0.002)
4381 # link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
4383 r = gui.getRect(2.0, 1)
4384 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))
4385 link = " \"float %s\" [%f]"%(name, value.getFloat())
4387 tex = luxProp(mat, keyname+".textured", False)
4388 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)]))
4389 if tex.get()=="true":
4390 if gui: gui.newline("", -2)
4391 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4392 if value.get() != 1.0:
4393 if str == "": # handle special case if texture is a just a constant
4394 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
4395 else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4396 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4400 def luxDispFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4402 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4404 keyname = "%s:%s"%(key, name)
4405 texname = "%s:%s"%(mat.getName(), keyname)
4406 value = luxProp(mat, keyname, default)
4407 link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
4408 tex = luxProp(mat, keyname+".textured", False)
4409 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)]))
4410 if tex.get()=="true":
4411 if gui: gui.newline("", -2)
4412 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4413 str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4414 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4417 def luxIORFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4419 iornames = ["0Z *** Gases @ 0 C ***", "01 - Vacuum", "02 - Air @ STP", "03 - Air", "04 - Helium", "05 - Hydrogen", "06 - Carbon dioxide",
4420 "1Z *** LIQUIDS @ 20 C ***", "11 - Benzene", "12 - Water", "13 - Ethyl alcohol", "14 - Carbon tetrachloride", "15 - Carbon disulfide",
4421 "2Z *** SOLIDS at room temperature ***", "21 - Diamond", "22 - Strontium titanate", "23 - Amber", "24 - Fused silica glass", "25 - sodium chloride",
4422 "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"]
4423 iorvals = [1.0, 1.0, 1.0002926, 1.000293, 1.000036, 1.000132, 1.00045,
4424 1.501, 1.501, 1.333, 1.361, 1.461, 1.628,
4425 2.419, 2.419, 2.41, 1.55, 1.458, 1.50,
4426 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]
4429 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4431 keyname = "%s:%s"%(key, name)
4432 texname = "%s:%s"%(mat.getName(), keyname)
4433 value = luxProp(mat, keyname, default)
4435 iorusepreset = luxProp(mat, keyname+".iorusepreset", "true")
4436 luxBool("iorusepreset", iorusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
4438 if(iorusepreset.get() == "true"):
4439 iorpreset = luxProp(mat, keyname+".iorpreset", "24 - Fused silica glass")
4441 def setIor(i, value, preset, tree, dict): # callback function to set ior value after selection
4444 preset.set(getTreeNameById(tree, i))
4445 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", [("Vacuum", 101), ("Air @ STP", 102), ("Air", 103), ("Helium", 104), ("Hydrogen", 105), ("Carbon dioxide", 106) ]), ("Transparent\x20", [("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) ] ) ]
4446 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}
4447 r = gui.getRect(1.6, 1)
4448 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))
4449 link = luxFloat(name, value, min, max, "IOR", hint, None, 1.6)
4451 link = luxFloat(name, value, min, max, "IOR", hint, gui, 1.6, 1)
4453 tex = luxProp(mat, keyname+".textured", False)
4454 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)]))
4455 if tex.get()=="true":
4456 if gui: gui.newline("", -2)
4457 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4458 if value.get() != 1.0:
4459 str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4460 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4463 def luxCauchyBFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4465 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" ]
4466 cauchybvals = [ 0.00354, 0.00420, 0.00459, 0.00531, 0.00743, 0.01342 ]
4469 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4471 keyname = "%s:%s"%(key, name)
4472 texname = "%s:%s"%(mat.getName(), keyname)
4473 value = luxProp(mat, keyname, default)
4475 cauchybusepreset = luxProp(mat, keyname+".cauchybusepreset", "true")
4476 luxBool("cauchybusepreset", cauchybusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
4478 if(cauchybusepreset.get() == "true"):
4479 cauchybpreset = luxProp(mat, keyname+".cauchybpreset", "01 - Fused silica glass")
4480 luxOption("cauchybpreset", cauchybpreset, cauchybnames, " PRESET", "select CauchyB preset", gui, 1.6)
4481 idx = cauchybnames.index(cauchybpreset.get())
4482 value.set(cauchybvals[idx])
4483 link = luxFloat(name, value, min, max, "cauchyb", hint, None, 1.6)
4485 link = luxFloat(name, value, min, max, "cauchyb", hint, gui, 1.6, 1)
4487 tex = luxProp(mat, keyname+".textured", False)
4488 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)]))
4489 if tex.get()=="true":
4490 if gui: gui.newline("", -2)
4491 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4492 if value.get() != 1.0:
4493 str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4494 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4497 def luxLight(name, kn, mat, gui, level):
4499 if name != "": gui.newline(name+":", 10, level)
4500 else: gui.newline("color:", 0, level+1)
4501 (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
4502 if gui: gui.newline("")
4503 link += luxFloat("power", luxProp(mat, kn+"light.power", 100.0), 0.0, 10000.0, "Power(W)", "AreaLight Power in Watts", gui)
4504 link += luxFloat("efficacy", luxProp(mat, kn+"light.efficacy", 17.0), 0.0, 100.0, "Efficacy(lm/W)", "Efficacy Luminous flux/watt", gui)
4505 if gui: gui.newline("")
4506 link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
4507 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
4508 luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 1.0)
4510 if gui: gui.newline("Photometric")
4511 pm = luxProp(mat, kn+"light.usepm", "false")
4512 luxCollapse("photometric", pm, "Photometric Diagram", "Enable Photometric Diagram options", gui, 2.0)
4514 if(pm.get()=="true"):
4515 pmtype = luxProp(mat, kn+"light.pmtype", "IESna")
4516 pmtypes = ["IESna", "imagemap"]
4517 luxOption("type", pmtype, pmtypes, "type", "Choose Photometric data type to use", gui, 0.6)
4518 if(pmtype.get() == "imagemap"):
4519 map = luxProp(mat, kn+"light.pmmapname", "")
4520 link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 1.4)
4521 if(pmtype.get() == "IESna"):
4522 map = luxProp(mat, kn+"light.pmiesname", "")
4523 link += luxFile("iesname", map, "ies-file", "filename of the IES photometric data file", gui, 1.4)
4525 has_bump_options = 0
4526 has_object_options = 1
4529 def luxLamp(name, kn, mat, gui, level):
4531 if name != "": gui.newline(name+":", 10, level)
4532 else: gui.newline("color:", 0, level+1)
4533 # if gui: gui.newline("", 10, level)
4534 (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
4535 if gui: gui.newline("")
4536 link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
4537 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
4538 luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 1.0)
4540 if gui: gui.newline("Photometric")
4541 pm = luxProp(mat, kn+"light.usepm", "false")
4542 luxBool("photometric", pm, "Photometric Diagram", "Enable Photometric Diagram options", gui, 2.0)
4544 if(pm.get()=="true"):
4545 pmtype = luxProp(mat, kn+"light.pmtype", "IESna")
4546 pmtypes = ["IESna", "imagemap"]
4547 luxOption("type", pmtype, pmtypes, "type", "Choose Photometric data type to use", gui, 0.6)
4548 if(pmtype.get() == "imagemap"):
4549 map = luxProp(mat, kn+"light.pmmapname", "")
4550 link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 1.4)
4551 if(pmtype.get() == "IESna"):
4552 map = luxProp(mat, kn+"light.pmiesname", "")
4553 link += luxFile("iesname", map, "ies-file", "filename of the IES photometric data file", gui, 1.4)
4555 link += luxBool("flipz", luxProp(mat, kn+"light.flipZ", "true"), "Flip Z", "Flip Z direction in mapping", gui, 2.0)
4559 def luxSpot(name, kn, mat, gui, level):
4561 if name != "": gui.newline(name+":", 10, level)
4562 else: gui.newline("color:", 0, level+1)
4563 # if gui: gui.newline("", 10, level)
4564 (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
4565 if gui: gui.newline("")
4566 link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
4567 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
4568 luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 1.0)
4570 if gui: gui.newline("Projection")
4571 proj = luxProp(mat, kn+"light.usetexproj", "false")
4572 luxBool("projection", proj, "Texture Projection", "Enable imagemap texture projection", gui, 2.0)
4574 if(proj.get() == "true"):
4575 map = luxProp(mat, kn+"light.pmmapname", "")
4576 link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 2.0)
4581 def Preview_Sphereset(mat, kn, state):
4583 luxProp(mat, kn+"prev_sphere", "true").set("true")
4584 luxProp(mat, kn+"prev_plane", "false").set("false")
4585 luxProp(mat, kn+"prev_torus", "false").set("false")
4586 def Preview_Planeset(mat, kn, state):
4588 luxProp(mat, kn+"prev_sphere", "true").set("false")
4589 luxProp(mat, kn+"prev_plane", "false").set("true")
4590 luxProp(mat, kn+"prev_torus", "false").set("false")
4591 def Preview_Torusset(mat, kn, state):
4593 luxProp(mat, kn+"prev_sphere", "true").set("false")
4594 luxProp(mat, kn+"prev_plane", "false").set("false")
4595 luxProp(mat, kn+"prev_torus", "false").set("true")
4600 def Preview_Update(mat, kn, defLarge, defType, texName, name, level):
4601 #print("%s %s %s %s %s %s %s" % (mat, kn, defLarge, defType, texName, name, level))
4606 Blender.Window.WaitCursor(True)
4607 scn = Scene.GetCurrent()
4609 # set path mode to absolute for preview
4610 pm_prop = luxProp(scn, "pathmode", "absolute")
4612 pm_prop.set('absolute')
4615 # Size of preview thumbnail
4616 thumbres = 110 # default 110x110
4618 large = luxProp(mat, kn+"prev_large", "true")
4620 large = luxProp(mat, kn+"prev_large", "false")
4621 if(large.get() == "true"):
4622 thumbres = 140 # small 140x140
4624 thumbbuf = thumbres*thumbres*3
4626 # consolebin = luxProp(scn, "luxconsole", "").get()
4628 p = get_lux_pipe(scn, buf=thumbbuf, type="luxconsole")
4630 # Unremark to write debugging output to file
4631 # p.stdin = open('c:\preview.lxs', 'w')
4634 prev_sphere = luxProp(mat, kn+"prev_sphere", "true")
4635 prev_plane = luxProp(mat, kn+"prev_plane", "false")
4636 prev_torus = luxProp(mat, kn+"prev_torus", "false")
4638 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
4639 prev_plane = luxProp(mat, kn+"prev_plane", "true")
4640 prev_torus = luxProp(mat, kn+"prev_torus", "false")
4642 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
4643 prev_plane = luxProp(mat, kn+"prev_plane", "false")
4644 prev_torus = luxProp(mat, kn+"prev_torus", "true")
4647 if luxProp(mat, kn+"prev_zoom", "false").get() == "true":
4648 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')
4650 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')
4652 p.stdin.write('Film "fleximage" "integer xresolution" [%i] "integer yresolution" [%i] "integer displayinterval" [3] "integer ldr_writeinterval" [3600] "string tonemapkernel" ["linear"] "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))
4653 p.stdin.write('PixelFilter "sinc"\n')
4655 scn = Scene.GetCurrent()
4656 defprevmat = luxProp(scn, "defprevmat", "high")
4657 quality = luxProp(mat, kn+"prev_quality", defprevmat.get())
4658 if quality.get()=="low":
4659 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [2]\n')
4660 elif quality.get()=="medium":
4661 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [4]\n')
4662 elif quality.get()=="high":
4663 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [8]\n')
4665 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [32]\n')
4667 if(prev_plane.get()=="false"):
4668 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')
4670 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')
4672 p.stdin.write('WorldBegin\n')
4673 if(prev_sphere.get()=="true"):
4674 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')
4675 elif (prev_plane.get()=="true"):
4676 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')
4678 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')
4679 obwidth = luxProp(mat, kn+"prev_obwidth", 1.0)
4681 p.stdin.write('TransformBegin\n')
4682 p.stdin.write('Scale %f %f %f\n'%(obw,obw,obw))
4684 print("texture "+texName+" "+name)
4685 (str, link) = luxTexture(texName, name, "color", "1.0 1.0 1.0", None, None, "", "", mat, None, 0, level)
4686 link = link.replace(" "+texName+"\"", " Kd\"") # swap texture name to "Kd"
4687 p.stdin.write(str+"\n")
4688 p.stdin.write("Material \"matte\" "+link+"\n")
4691 p.stdin.write(luxMaterial(mat))
4692 link = luxProp(mat,"link","").get()
4693 if kn!="": link = link.rstrip("\"")+":"+kn.strip(".:")+"\""
4694 p.stdin.write(link+'\n')
4695 p.stdin.write('TransformEnd\n')
4697 if(prev_sphere.get()=="true"):
4698 p.stdin.write('Shape "sphere" "float radius" [1.0]\n')
4699 elif (prev_plane.get()=="true"):
4700 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')
4701 elif (prev_torus.get()=="true"):
4702 p.stdin.write('Shape "torus" "float radius" [1.0]\n')
4703 p.stdin.write('AttributeEnd\n')
4704 # Checkerboard floor
4705 if(prev_plane.get()=="false"):
4706 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')
4707 p.stdin.write('Texture "checks" "color" "checkerboard"')
4708 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]')
4709 p.stdin.write('"string mapping" ["uv"] "float uscale" [36.8] "float vscale" [36.0]\n')
4710 p.stdin.write('Material "matte" "texture Kd" ["checks"]\n')
4711 p.stdin.write('Shape "loopsubdiv" "integer nlevels" [3] "bool dmnormalsmooth" ["true"] "bool dmsharpboundary" ["false"] ')
4712 p.stdin.write('"integer indices" [ 0 1 2 0 2 3 1 0 4 1 4 5 5 4 6 5 6 7 ]')
4713 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')
4714 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')
4715 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')
4716 p.stdin.write('AttributeEnd\n')
4718 if(prev_plane.get()=="false"):
4719 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')
4721 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')
4722 area = luxProp(mat, kn+"prev_arealight", "false")
4723 if(area.get() == "false"):
4724 p.stdin.write('Texture "pL" "color" "blackbody" "float temperature" [6500.0]\n')
4725 p.stdin.write('LightSource "point" "texture L" ["pL"] "float gain" [0.002]')
4727 p.stdin.write('ReverseOrientation\n')
4728 p.stdin.write('AreaLightSource "area" "color L" [1.0 1.0 1.0]\n')
4729 if(prev_plane.get()=="false"):
4730 p.stdin.write(' "float gain" [0.3]\n')
4731 p.stdin.write('Shape "disk" "float radius" [1.0]\nAttributeEnd\n')
4732 p.stdin.write('WorldEnd\n')
4736 data = p.communicate()[0]
4743 if(datalen < thumbbuf):
4744 print("error on preview: got %i bytes, expected %i" % (datalen, thumbbuf))
4748 image.decodeLuxConsole(thumbres, thumbres, data)
4749 previewCache[(mat.name+":"+kn).__hash__()] = image
4751 Blender.Window.WaitCursor(False)
4753 def luxPreview(mat, name, defType=0, defEnabled=False, defLarge=False, texName=None, gui=None, level=0, color=None):
4758 if texName: kn += ":"+texName
4759 if kn != "": kn += "."
4760 if(defEnabled == True):
4761 showpreview = luxProp(mat, kn+"prev_show", "true")
4763 showpreview = luxProp(mat, kn+"prev_show", "false")
4764 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)]))
4765 if showpreview.get()=="true":
4767 large = luxProp(mat, kn+"prev_large", "true")
4769 large = luxProp(mat, kn+"prev_large", "false")
4772 if(large.get() == "true"):
4776 r = gui.getRect(1.1, rr)
4778 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)
4779 try: previewCache[(mat.name+":"+kn).__hash__()].draw(r[0]-82, r[1]+4)
4782 prev_sphere = luxProp(mat, kn+"prev_sphere", "true")
4783 prev_plane = luxProp(mat, kn+"prev_plane", "false")
4784 prev_torus = luxProp(mat, kn+"prev_torus", "false")
4786 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
4787 prev_plane = luxProp(mat, kn+"prev_plane", "true")
4788 prev_torus = luxProp(mat, kn+"prev_torus", "false")
4790 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
4791 prev_plane = luxProp(mat, kn+"prev_plane", "false")
4792 prev_torus = luxProp(mat, kn+"prev_torus", "true")
4794 # preview mode toggle buttons
4795 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)]))
4796 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)]))
4797 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)]))
4800 zoom = luxProp(mat, kn+"prev_zoom", "false")
4801 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)]))
4803 area = luxProp(mat, kn+"prev_arealight", "false")
4804 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)]))
4807 obwidth = luxProp(mat, kn+"prev_obwidth", 1.0)
4808 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))
4811 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)]))
4814 qs = ["low","medium","high","very high"]
4815 scn = Scene.GetCurrent()
4816 defprevmat = luxProp(scn, "defprevmat", "high")
4817 quality = luxProp(mat, kn+"prev_quality", defprevmat.get())
4818 luxOptionRect("quality", quality, qs, " Quality", "select preview quality", gui, r[0]+200, r[1]+100+voffset, 88, 18)
4821 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))
4823 # Reset depths after getRect()
4828 def luxMaterialBlock(name, luxname, key, mat, gui=None, level=0, str_opt=""):
4829 global icon_mat, icon_matmix, icon_map3dparam
4831 return (t1[0]+t2[0], t1[1]+t2[1])
4833 if key == "": keyname = kn = name
4834 else: keyname = kn = "%s:%s"%(key, name)
4835 if kn != "": kn += "."
4836 if keyname == "": matname = mat.getName()
4837 else: matname = "%s:%s"%(mat.getName(), keyname)
4840 mattype = luxProp(mat, kn+"type", "matte")
4841 # Set backwards compatibility of glossy material from plastic and substrate
4842 if(mattype.get() == "substrate" or mattype.get() == "plastic"):
4843 mattype.set("glossy")
4845 # this is reverse order than in shown in the dropdown list
4846 materials = ["null","mix","mirror","shinymetal","metal","mattetranslucent","matte","glossy","roughglass","glass","carpaint"]
4848 if level == 0: materials = ["portal","light","boundvolume"]+materials
4851 if mattype.get() == "mix": icon = icon_matmix
4852 if level == 0: gui.newline("Material type:", 12, level, icon, [0.75,0.5,0.25])
4853 else: gui.newline(name+":", 12, level, icon, scalelist([0.75,0.6,0.25],2.0/(level+2)))
4856 link = luxOption("type", mattype, materials, " TYPE", "select material type", gui)
4857 showadvanced = luxProp(mat, kn+"showadvanced", "false")
4858 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
4859 showhelp = luxProp(mat, kn+"showhelp", "false")
4860 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
4862 # show copy/paste menu button
4863 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))
4865 # Draw Material preview option
4869 if gui: luxPreview(mat, keyname, 0, showmatprev, True, None, gui, level, [0.746, 0.625, 0.5])
4872 if gui: gui.newline()
4873 has_object_options = 0 # disable object options by default
4874 has_bump_options = 0 # disable bump mapping options by default
4875 has_emission_options = 0 # disable emission options by default
4876 has_compositing_options = 0 # disable compositing options by default
4878 if mattype.get() == "mix":
4879 (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))
4880 (str,link) = c((str,link), luxMaterialBlock("mat1", "namedmaterial1", keyname, mat, gui, level+1))
4881 (str,link) = c((str,link), luxMaterialBlock("mat2", "namedmaterial2", keyname, mat, gui, level+1))
4882 has_bump_options = 0
4883 has_object_options = 1
4884 has_emission_options = 1
4885 has_compositing_options = 0
4887 if mattype.get() == "light":
4888 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
4889 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
4890 link = "LightGroup \"%s\"\n"%lightgroup.get()
4893 link += "AreaLightSource \"area\""
4894 (str,link) = c((str,link), luxLight("", kn, mat, gui, level))
4895 has_bump_options = 0
4896 has_object_options = 1
4897 has_emission_options = 0
4898 has_compositing_options = 1
4900 if mattype.get() == "boundvolume":
4902 voltype = luxProp(mat, kn+"vol.type", "homogeneous")
4903 vols = ["homogeneous", "exponential", "cloud"]
4904 vollink = luxOption("type", voltype, vols, "type", "", gui)
4905 if voltype.get() == "homogeneous":
4906 link = "Volume \"homogeneous\""
4907 if voltype.get() == "exponential":
4908 link = "Volume \"exponential\""
4909 if voltype.get() == "cloud":
4910 link = "Volume \"cloud\""
4912 if gui: gui.newline("absorption:", 0, level+1)
4913 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)
4914 if gui: gui.newline("scattering:", 0, level+1)
4915 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)
4916 if gui: gui.newline("emission:", 0, level+1)
4917 link += luxRGB("Le", luxProp(mat, kn+"vol.le", "0.0 0.0 0.0"), 1.0, "Le", "The volume's emission spectrum", gui)
4918 if gui: gui.newline("assymetry:", 0, level+1)
4919 link += luxFloat("g", luxProp(mat, kn+"vol.g", 0.0), 0.0, 100.0, "g", "The phase function asymmetry parameter", gui)
4921 if voltype.get() == "exponential":
4922 if gui: gui.newline("form:", 0, level+1)
4923 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)
4924 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)
4925 if gui: gui.newline("updir:", 0, level+1)
4926 link += luxVector("updir", luxProp(mat, kn+"vol.updir", "0 0 1"), -1.0, 1.0, "updir", "Up direction vector", gui, 2.0)
4928 if voltype.get() == "cloud":
4929 if gui: gui.newline("cloud:", 0, level+1)
4930 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)
4931 link += luxFloat("noisescale", luxProp(mat, kn+"vol.noisescale", 0.3), 0.1, 2.0, "noisesize", "Size of cloud noise", gui)
4932 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)
4933 link += luxFloat("noiseoffset", luxProp(mat, kn+"vol.noiseoffset", 0.0), 0.0, 1000.0, "noiseoffset", "Useful for creating unique clouds", gui )
4934 link += luxInt("octaves", luxProp(mat, kn+"vol.octaves", 3), 1, 8, "octaves", "Sets the amount of detail for the noise", gui )
4935 link += luxFloat("omega", luxProp(mat, kn+"vol.omega", 0.75), 0.1, 1.0, "omega", "Sets the scale difference of each successive octave", gui )
4936 link += luxFloat("sharpness", luxProp(mat, kn+"vol.sharpness", 6.0), 0.2, 10.0, "sharpness", "Sets the sharpness of the noise", gui)
4937 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)
4938 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)
4939 link += luxInt("spheres", luxProp(mat, kn+"vol.spheres", 2000), 0, 10000, "spheres", "Number of small spheres for cumulus shape. 0 is non-cumulus.", gui )
4940 link += luxFloat("spheresize", luxProp(mat, kn+"vol.spheresize", 0.15), 0.05, 0.55, "spheresize", "Size of cumulus spheres", gui)
4944 has_bump_options = 0
4945 has_object_options = 0
4946 has_emission_options = 0
4950 if mattype.get() == "carpaint":
4951 if gui: gui.newline("Preset:", 0, level+1)
4952 carname = luxProp(mat, kn+"carpaint.name", "Custom")
4953 cars = ["Custom","ford f8","polaris silber","opel titan","bmw339","2k acrylack","white","blue","blue matte"]
4954 carlink = luxOption("name", carname, cars, "name", "", gui)
4955 if carname.get() == "Custom":
4956 (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
4957 (str,link) = c((str,link), luxSpectrumTexture("Ks1", keyname, "1.0 1.0 1.0", 1.0, "specular1", "", mat, gui, level+1))
4958 (str,link) = c((str,link), luxSpectrumTexture("Ks2", keyname, "1.0 1.0 1.0", 1.0, "specular2", "", mat, gui, level+1))
4959 (str,link) = c((str,link), luxSpectrumTexture("Ks3", keyname, "1.0 1.0 1.0", 1.0, "specular3", "", mat, gui, level+1))
4960 (str,link) = c((str,link), luxFloatTexture("R1", keyname, 1.0, 0.0, 1.0, "R1", "", mat, gui, level+1))
4961 (str,link) = c((str,link), luxFloatTexture("R2", keyname, 1.0, 0.0, 1.0, "R2", "", mat, gui, level+1))
4962 (str,link) = c((str,link), luxFloatTexture("R3", keyname, 1.0, 0.0, 1.0, "R3", "", mat, gui, level+1))
4963 (str,link) = c((str,link), luxFloatTexture("M1", keyname, 1.0, 0.0, 1.0, "M1", "", mat, gui, level+1))
4964 (str,link) = c((str,link), luxFloatTexture("M2", keyname, 1.0, 0.0, 1.0, "M2", "", mat, gui, level+1))
4965 (str,link) = c((str,link), luxFloatTexture("M3", keyname, 1.0, 0.0, 1.0, "M3", "", mat, gui, level+1))
4966 else: link += carlink
4967 absorption = luxProp(mat, keyname+".useabsorption", "false")
4968 luxCollapse("absorption", absorption, "Absorption", "Enable Coating Absorption", gui, 2.0)
4969 if absorption.get() == "true":
4970 (str,link) = c((str,link), luxSpectrumTexture("Ka", keyname, "0.2 0.2 0.2", 1.0, "absorption", "", mat, gui, level+1))
4971 (str,link) = c((str,link), luxFloatTexture("d", keyname, 5.0, 0.0, 15.0, "depth", "", mat, gui, level+1))
4972 has_bump_options = 1
4973 has_object_options = 1
4974 has_emission_options = 1
4975 has_compositing_options = 1
4977 if mattype.get() == "glass":
4978 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
4979 (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
4980 (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 6.0, "IOR", "", mat, gui, level+1))
4981 architectural = luxProp(mat, keyname+".architectural", "false")
4982 link += luxBool("architectural", architectural, "architectural", "Enable architectural glass", gui, 2.0)
4983 if architectural.get() == "false":
4984 chromadisp = luxProp(mat, keyname+".chromadisp", "false")
4985 luxCollapse("chromadisp", chromadisp, "Dispersive Refraction", "Enable Chromatic Dispersion", gui, 2.0)
4986 if chromadisp.get() == "true":
4987 (str,link) = c((str,link), luxCauchyBFloatTexture("cauchyb", keyname, 0.0, 0.0, 1.0, "cauchyb", "", mat, gui, level+1))
4988 thinfilm = luxProp(mat, keyname+".thinfilm", "false")
4989 luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
4990 if thinfilm.get() == "true":
4991 (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))
4992 (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))
4993 has_bump_options = 1
4994 has_object_options = 1
4995 has_emission_options = 1
4996 has_compositing_options = 1
4998 if mattype.get() == "matte":
4999 orennayar = luxProp(mat, keyname+".orennayar", "false")
5000 (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
5001 luxCollapse("orennayar", orennayar, "Oren-Nayar", "Enable Oren-Nayar BRDF", gui, 2.0)
5002 if orennayar.get() == "true":
5003 (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))
5004 has_bump_options = 1
5005 has_object_options = 1
5006 has_emission_options = 1
5007 has_compositing_options = 1
5009 if mattype.get() == "mattetranslucent":
5010 orennayar = luxProp(mat, keyname+".orennayar", "false")
5011 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
5012 (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
5013 luxCollapse("orennayar", orennayar, "Oren-Nayar", "Enable Oren-Nayar BRDF", gui, 2.0)
5014 if orennayar.get() == "true":
5015 (str,link) = c((str,link), luxFloatTexture("sigma", keyname, 0.0, 0.0, 100.0, "sigma", "", mat, gui, level+1))
5016 has_bump_options = 1
5017 has_object_options = 1
5018 has_emission_options = 1
5019 has_compositing_options = 1
5021 if mattype.get() == "metal":
5022 if gui: gui.newline("name:", 0, level+1)
5023 metalname = luxProp(mat, kn+"metal.name", "")
5024 metals = ["aluminium","amorphous carbon","silver","gold","copper"]
5026 if not(metalname.get() in metals):
5027 metals.append(metalname.get())
5028 metallink = luxOption("name", metalname, metals, "name", "", gui, 1.88)
5029 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"))
5030 link += luxstr(metallink)
5031 anisotropic = luxProp(mat, kn+"metal.anisotropic", "false")
5034 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)]))
5035 if anisotropic.get()=="true":
5036 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
5037 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
5039 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
5040 (str,link) = c((str,link), (s, l))
5041 link += l.replace("uroughness", "vroughness", 1)
5043 has_bump_options = 1
5044 has_object_options = 1
5045 has_emission_options = 1
5046 has_compositing_options = 1
5048 if mattype.get() == "mirror":
5049 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
5050 thinfilm = luxProp(mat, keyname+".thinfilm", "false")
5051 luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
5052 if thinfilm.get() == "true":
5053 (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))
5054 (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))
5056 has_bump_options = 1
5057 has_object_options = 1
5058 has_emission_options = 1
5059 has_compositing_options = 1
5061 if mattype.get() == "roughglass":
5062 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
5063 (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
5064 anisotropic = luxProp(mat, kn+"roughglass.anisotropic", "false")
5067 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)]))
5068 if anisotropic.get()=="true":
5069 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
5070 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
5072 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
5073 (str,link) = c((str,link), (s, l))
5074 link += l.replace("uroughness", "vroughness", 1)
5075 (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 6.0, "IOR", "", mat, gui, level+1))
5076 chromadisp = luxProp(mat, keyname+".chromadisp", "false")
5077 luxCollapse("chromadisp", chromadisp, "Dispersive Refraction", "Enable Chromatic Dispersion", gui, 2.0)
5078 if chromadisp.get() == "true":
5079 (str,link) = c((str,link), luxCauchyBFloatTexture("cauchyb", keyname, 0.0, 0.0, 1.0, "cauchyb", "", mat, gui, level+1))
5080 has_bump_options = 1
5081 has_object_options = 1
5082 has_emission_options = 1
5083 has_compositing_options = 1
5085 if mattype.get() == "shinymetal":
5086 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
5087 (str,link) = c((str,link), luxSpectrumTexture("Ks", keyname, "1.0 1.0 1.0", 1.0, "specular", "", mat, gui, level+1))
5088 anisotropic = luxProp(mat, kn+"shinymetal.anisotropic", "false")
5091 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)]))
5092 if anisotropic.get()=="true":
5093 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
5094 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
5096 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
5097 (str,link) = c((str,link), (s, l))
5098 link += l.replace("uroughness", "vroughness", 1)
5100 thinfilm = luxProp(mat, keyname+".thinfilm", "false")
5101 luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
5102 if thinfilm.get() == "true":
5103 (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))
5104 (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))
5106 has_bump_options = 1
5107 has_object_options = 1
5108 has_emission_options = 1
5109 has_compositing_options = 1
5111 if mattype.get() == "glossy":
5112 (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
5113 useior = luxProp(mat, keyname+".useior", "false")
5116 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)]))
5117 if useior.get() == "true":
5118 (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 50.0, "IOR", "", mat, gui, level+1))
5119 link += " \"color Ks\" [1.0 1.0 1.0]"
5121 (str,link) = c((str,link), luxSpectrumTexture("Ks", keyname, "1.0 1.0 1.0", 1.0, "specular", "", mat, gui, level+1))
5122 link += " \"float index\" [0.0]"
5123 anisotropic = luxProp(mat, kn+"glossy.anisotropic", "false")
5126 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)]))
5127 if anisotropic.get()=="true":
5128 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
5129 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
5131 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
5132 (str,link) = c((str,link), (s, l))
5133 link += l.replace("uroughness", "vroughness", 1)
5135 absorption = luxProp(mat, keyname+".useabsorption", "false")
5136 luxCollapse("absorption", absorption, "Absorption", "Enable Coating Absorption", gui, 2.0)
5137 if absorption.get() == "true":
5138 (str,link) = c((str,link), luxSpectrumTexture("Ka", keyname, "0.2 0.2 0.2", 1.0, "absorption", "", mat, gui, level+1))
5139 (str,link) = c((str,link), luxFloatTexture("d", keyname, 0.15, 0.0, 15.0, "depth", "", mat, gui, level+1))
5140 has_bump_options = 1
5141 has_object_options = 1
5142 has_emission_options = 1
5143 has_compositing_options = 1
5145 if mattype.get() == 'null':
5146 has_emission_options = 1
5148 # Bump mapping options (common)
5149 if (has_bump_options == 1):
5150 usebump = luxProp(mat, keyname+".usebump", "false")
5151 luxCollapse("usebump", usebump, "Bump Map", "Enable Bump Mapping options", gui, 2.0)
5152 if usebump.get() == "true":
5153 (str,link) = c((str,link), luxFloatTexture("bumpmap", keyname, 0.0, -1.0, 1.0, "bumpmap", "bumpmap scale in meters - i.e. 0.01 = 1 cm", mat, gui, level+1))
5155 # emission options (common)
5157 if (has_emission_options == 1):
5158 if gui: gui.newline("", 2, level, None, [0.6,0.6,0.4])
5159 useemission = luxProp(mat, "emission", "false")
5160 luxCollapse("useemission", useemission, "Emission", "Enable emission options", gui, 2.0)
5161 if useemission.get() == "true":
5162 # emission GUI is here but lux export will be done later
5163 luxLight("", "", mat, gui, level)
5164 else: luxProp(mat, "emission", "false").set("false") # prevent from exporting later
5167 # Compositing options (common)
5168 # Note - currently only display options when using distributedpath integrator
5169 integratortype = luxProp(Scene.GetCurrent(), "sintegrator.type", "bidirectional")
5170 if (integratortype.get() == "distributedpath" and level == 0):
5171 if (has_compositing_options == 1):
5172 if gui: gui.newline("", 2, level, None, [0.4,0.4,0.6])
5173 usecompo = luxProp(mat, "compo", "false")
5174 luxCollapse("compo", usecompo, "Compositing", "Enable Compositing options", gui, 2.0)
5175 if usecompo.get() == "true":
5176 if gui: gui.newline("", 2, level, None, [0.35,0.35,0.55])
5177 usecompoviz = luxProp(mat, "compo_viz", "false")
5178 luxCollapse("compo_viz", usecompoviz, "Visibility", "Enable Visibility Compositing options", gui, 2.0)
5179 if usecompoviz.get() == "true":
5180 if gui: gui.newline("View", 2, level, None, [0.35,0.35,0.55])
5181 compovizmat = luxProp(mat, "compo_viz_mat", "true")
5182 link += luxBool("compo_visible_material", compovizmat, "Material", "Enable View Visibility of Material", gui, 1.0)
5183 compovizemi = luxProp(mat, "compo_viz_emi", "true")
5184 link += luxBool("compo_visible_emission", compovizemi, "Emission", "Enable View Visibility of Emission", gui, 1.0)
5186 if gui: gui.newline("Indirect", 2, level, None, [0.35,0.35,0.55])
5187 compovizmati = luxProp(mat, "compo_viz_mati", "true")
5188 link += luxBool("compo_visible_indirect_material", compovizmati, "Material", "Enable InDirect Visibility of Material", gui, 1.0)
5189 compovizemii = luxProp(mat, "compo_viz_emii", "true")
5190 link += luxBool("compo_visible_indirect_emission", compovizemii, "Emission", "Enable InDirect Visibility of Emission", gui, 1.0)
5192 if gui: gui.newline("", 2, level, None, [0.4,0.4,0.6])
5193 overridealpha = luxProp(mat, "compo_o_alpha", "false")
5194 link += luxCollapse("compo_override_alpha", overridealpha, "Override Alpha", "Enable Manual control of alpha value", gui, 2.0)
5195 if overridealpha.get() == "true":
5196 if gui: gui.newline("Alpha", 2, level, None, [0.4,0.4,0.6])
5197 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)
5198 usecolorkey = luxProp(mat, "compo_usekey", "false")
5199 if gui: gui.newline("", 2, level, None, [0.35,0.35,0.55])
5200 link += luxCollapse("compo_use_key", usecolorkey, "Chroma Key", "Enable Chroma Object key", gui, 2.0)
5201 if usecolorkey.get() == "true":
5202 if gui: gui.newline("Key", 2, level, None, [0.35,0.35,0.55])
5203 link += luxRGB("compo_key_color", luxProp(mat, "compo_key_color", "0.0 0.0 1.0"), 1.0, "key", "", gui, 2.0)
5205 # transformation options (common)
5206 if (level == 0) and mattype.get() not in ['portal', 'null']:
5207 if gui: gui.newline("", 2, level, None, [0.6,0.6,0.4])
5208 usetransformation = luxProp(mat, "transformation", "false")
5209 luxCollapse("usetransformation", usetransformation, "Texture Transformation", "Enable transformation option", gui, 2.0)
5210 if usetransformation.get() == "true":
5211 scale = luxProp(mat, "3dscale", 1.0)
5212 rotate = luxProp(mat, "3drotate", "0 0 0")
5213 translate = luxProp(mat, "3dtranslate", "0 0 0")
5215 gui.newline("scale:", -2, level, icon_map3dparam)
5216 luxVectorUniform("scale", scale, 0.001, 1000.0, "scale", "scale-vector", gui, 2.0)
5217 gui.newline("rot:", -2, level, icon_map3dparam)
5218 luxVector("rotate", rotate, -360.0, 360.0, "rotate", "rotate-vector", gui, 2.0)
5219 gui.newline("move:", -2, level, icon_map3dparam)
5220 luxVector("translate", translate, -1000.0, 1000.0, "move", "translate-vector", gui, 2.0)
5221 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"
5223 # Object options (common)
5224 if (level == 0) and (has_object_options == 1):
5225 if gui: gui.newline("Mesh:", 2, level, icon, [0.6,0.6,0.4])
5226 usesubdiv = luxProp(mat, "subdiv", "false")
5227 luxBool("usesubdiv", usesubdiv, "Subdivision", "Enable Loop Subdivision options", gui, 1.0)
5228 usedisp = luxProp(mat, "dispmap", "false")
5229 luxBool("usedisp", usedisp, "Displacement Map", "Enable Displacement mapping options", gui, 1.0)
5230 if usesubdiv.get() == "true" or usedisp.get() == "true":
5231 luxInt("sublevels", luxProp(mat, "sublevels", 2), 0, 12, "sublevels", "The number of levels of object subdivision", gui, 2.0)
5232 sharpbound = luxProp(mat, "sharpbound", "false")
5233 luxBool("sharpbound", sharpbound, "Sharpen Bounds", "Sharpen boundaries during subdivision", gui, 1.0)
5234 nsmooth = luxProp(mat, "nsmooth", "true")
5235 luxBool("nsmooth", nsmooth, "Smooth", "Smooth faces during subdivision", gui, 1.0)
5236 if usedisp.get() == "true":
5237 (str,ll) = c((str,link), luxDispFloatTexture("dispmap", keyname, 0.1, -10, 10.0, "dispmap", "Displacement Mapping amount", mat, gui, level+1))
5238 luxFloat("sdoffset", luxProp(mat, "sdoffset", 0.0), 0.0, 1.0, "Offset", "Offset for displacement map", gui, 2.0)
5239 usesubdiv.set("true")
5241 if mattype.get() == "light":
5244 str += "MakeNamedMaterial \"%s\"%s\n"%(matname, link)
5245 return (str, " \"string %s\" [\"%s\"]"%(luxname, matname))
5248 def luxMaterial(mat, gui=None):
5251 if luxProp(mat, "type", "").get()=="": # lux material not defined yet
5252 print("Blender material \"%s\" has no lux material definition, converting..."%(mat.getName()))
5254 convertMaterial(mat) # try converting the blender material to a lux material
5256 (str, link) = luxMaterialBlock("", "", "", mat, gui, 0)
5257 if luxProp(mat, "type", "matte").get() != "light":
5258 link = "NamedMaterial \"%s\""%(mat.getName())
5259 # export emission options (no gui)
5260 useemission = luxProp(mat, "emission", "false")
5261 if useemission.get() == "true":
5262 lightgroup = luxProp(mat, "light.lightgroup", "default")
5263 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
5264 link += "\n\tLightGroup \"%s\"\n"%lightgroup.get()
5266 (estr, elink) = luxLight("", "", mat, None, 0)
5268 link += "\n\tAreaLightSource \"area\" "+elink
5270 luxProp(mat, "link", "").set("".join(link))
5275 def luxVolume(mat, gui=None):
5278 (str, link) = luxMaterialBlock("", "", "", mat, gui, 0)
5279 luxProp(mat, "link", "").set("".join(link))
5282 runRenderAfterExport = None
5283 def CBluxExport(default, run):
5284 global runRenderAfterExport
5285 runRenderAfterExport = run
5287 datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
5288 if datadir=="": datadir = Blender.Get("datadir")
5290 if not os.path.exists(datadir):
5291 Draw.PupMenu("ERROR: output directory does not exist!")
5295 filename = datadir + os.sep + "default.lxs"
5296 save_still(filename)
5298 Window.FileSelector(save_still, "Export", sys.makename(Blender.Get("filename"), ".lxs"))
5301 def CBluxAnimExport(default, run, fileselect=True):
5303 datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
5304 if datadir=="": datadir = Blender.Get("datadir")
5306 if not os.path.exists(datadir):
5307 Draw.PupMenu("ERROR: output directory does not exist!")
5311 filename = datadir + os.sep + "default.lxs"
5315 Window.FileSelector(save_anim, "Export", sys.makename(Blender.Get("filename"), ".lxs"))
5317 datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
5318 if datadir=="": datadir = Blender.Get("datadir")
5319 filename = sys.makename(Blender.Get("filename") , ".lxs")
5323 # convert a Blender material to lux material
5324 def convertMaterial(mat):
5326 if str != "": return str+"."
5329 if str != "": return str+":"
5331 def mapConstDict(value, constant_dict, lux_dict, default=None):
5332 for k,v in constant_dict.items():
5333 if (v == value) and (lux_dict.has_key(k)):
5337 def convertMapping(name, tex):
5338 if tex.texco == Texture.TexCo["UV"]:
5339 luxProp(mat, dot(name)+"mapping","").set("uv")
5340 luxProp(mat, dot(name)+"uscale", 1.0).set(tex.size[0])
5341 luxProp(mat, dot(name)+"vscale", 1.0).set(-tex.size[1])
5342 luxProp(mat, dot(name)+"udelta", 0.0).set(tex.ofs[0]+0.5*(1.0-tex.size[0]))
5343 luxProp(mat, dot(name)+"vdelta", 0.0).set(-tex.ofs[1]-0.5*(1.0-tex.size[1]))
5344 if tex.mapping != Texture.Mappings["FLAT"]:
5345 print("Material Conversion Warning: for UV-texture-input only FLAT mapping is supported\n")
5347 if tex.mapping == Texture.Mappings["FLAT"]:
5348 luxProp(mat, dot(name)+"mapping","").set("planar") # make planar-mapping convert correctly from blender(WYSIWYG)- jens
5349 luxProp(mat, dot(name)+"v1", "1.0 1.0 1.0").setVector((0.5*tex.size[0], 0.0, 0.0))
5350 luxProp(mat, dot(name)+"v2", "0.0 0.0 0.0").setVector((0.0, -0.5*tex.size[1], -0.0))
5351 luxProp(mat, dot(name)+"udelta", 0.0).set(tex.ofs[0]+0.5)
5352 luxProp(mat, dot(name)+"vdelta", 0.0).set(-tex.ofs[1]-0.5)
5353 elif tex.mapping == Texture.Mappings["TUBE"]:
5354 luxProp(mat, dot(name)+"mapping","").set("cylindrical")
5355 elif tex.mapping == Texture.Mappings["SPHERE"]:
5356 luxProp(mat, dot(name)+"mapping","").set("spherical")
5357 else: luxProp(mat, dot(name)+"mapping","").set("planar")
5359 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]))
5360 luxProp(mat, dot(name)+"3dtranslate", "0.0 0.0 0.0").setVector((-tex.ofs[0], -tex.ofs[1], -tex.ofs[2]))
5362 def convertColorband(colorband):
5363 # colorbands are not supported in lux - so lets extract a average low-side and high-side color
5364 cb = [colorband[0]] + colorband[:] + [colorband[-1]]
5365 cb[0][4], cb[-1][4] = 0.0, 1.0
5366 low, high = [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]
5367 for i in range(1, len(cb)):
5369 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])
5370 high[c] += (cb[i-1][c]*cb[i-1][4] + cb[i][c]*cb[i][4]) * (cb[i][4]-cb[i-1][4])
5373 def createLuxTexture(name, tex):
5375 convertMapping(name, tex)
5376 if (texture.type == Texture.Types["IMAGE"]) and (texture.image) and (texture.image.filename!=""):
5377 luxProp(mat, dot(name)+"texture", "").set("imagemap")
5378 luxProp(mat, dot(name)+"filename", "").set(texture.image.filename)
5379 luxProp(mat, dot(name)+"wrap", "").set(mapConstDict(texture.extend, Texture.ExtendModes, {"REPEAT":"repeat", "EXTEND":"clamp", "CLIP":"black"}, ""))
5381 if tex.texco != Texture.TexCo["GLOB"]:
5382 print("Material Conversion Warning: procedural textures supports global mapping only\n")
5383 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"}
5384 luxProp(mat, dot(name)+"bright", 1.0).set(texture.brightness)
5385 luxProp(mat, dot(name)+"contrast", 1.0).set(texture.contrast)
5386 if texture.type == Texture.Types["CLOUDS"]:
5387 luxProp(mat, dot(name)+"texture", "").set("blender_clouds")
5388 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"CLD_DEFAULT":"default", "CLD_COLOR":"color"}, ""))
5389 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
5390 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5391 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
5392 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5393 elif texture.type == Texture.Types["WOOD"]:
5394 luxProp(mat, dot(name)+"texture", "").set("blender_wood")
5395 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"WOD_BANDS":"bands", "WOD_RINGS":"rings", "WOD_BANDNOISE":"bandnoise", "WOD_RINGNOISE":"ringnoise"}, ""))
5396 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, {"SINE":"sin", "SAW":"saw", "TRI":"tri"}, ""))
5397 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5398 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
5399 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5400 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
5401 elif texture.type == Texture.Types["MUSGRAVE"]:
5402 luxProp(mat, dot(name)+"texture", "").set("blender_musgrave")
5403 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"}, ""))
5404 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5405 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5406 # 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)
5407 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
5408 else: luxProp(mat, dot(name)+"h", 1.0).set(0.5) # use a default value
5409 # bug in blender python API: values "offset" and "gain" are missing in Python-API (reported to Ideasman42 - will be fixed after Blender 2.47)
5411 luxProp(mat, dot(name)+"offset", 1.0).set(texture.offset)
5412 luxProp(mat, dot(name)+"gain", 1.0).set(texture.gain)
5413 except AttributeError: pass
5414 luxProp(mat, dot(name)+"lacu", 2.0).set(texture.lacunarity)
5415 luxProp(mat, dot(name)+"octs", 2.0).set(texture.octs)
5416 luxProp(mat, dot(name)+"outscale", 1.0).set(texture.iScale)
5417 elif texture.type == Texture.Types["MARBLE"]:
5418 luxProp(mat, dot(name)+"texture", "").set("blender_marble")
5419 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"MBL_SOFT":"soft", "MBL_SHARP":"sharp", "MBL_SHARPER":"sharper"}, ""))
5420 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
5421 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
5422 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
5423 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5424 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, {"SINE":"sin", "SAW":"saw", "TRI":"tri"}, ""))
5425 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5426 elif texture.type == Texture.Types["VORONOI"]:
5427 luxProp(mat, dot(name)+"texture", "").set("blender_voronoi")
5428 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])
5429 luxProp(mat, dot(name)+"outscale", 1.0).set(texture.iScale)
5430 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5431 luxProp(mat, dot(name)+"minkosky_exp", 2.5).set(texture.exp)
5432 luxProp(mat, dot(name)+"w1", 1.0).set(texture.weight1)
5433 luxProp(mat, dot(name)+"w2", 0.0).set(texture.weight2)
5434 luxProp(mat, dot(name)+"w3", 0.0).set(texture.weight3)
5435 luxProp(mat, dot(name)+"w4", 0.0).set(texture.weight4)
5436 elif texture.type == Texture.Types["NOISE"]:
5437 luxProp(mat, dot(name)+"texture", "").set("blender_noise")
5438 elif texture.type == Texture.Types["DISTNOISE"]:
5439 luxProp(mat, dot(name)+"texture", "").set("blender_distortednoise")
5440 luxProp(mat, dot(name)+"distamount", 1.0).set(texture.distAmnt)
5441 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5442 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5443 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, noiseDict, ""))
5444 elif texture.type == Texture.Types["MAGIC"]:
5445 luxProp(mat, dot(name)+"texture", "").set("blender_magic")
5446 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
5447 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
5448 elif texture.type == Texture.Types["STUCCI"]:
5449 luxProp(mat, dot(name)+"texture", "").set("blender_stucci")
5450 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"STC_PLASTIC":"Plastic", "MSTC_WALLIN":"Wall In", "STC_WALLOUT":"Wall Out"}, ""))
5451 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
5452 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5453 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
5454 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5455 elif texture.type == Texture.Types["BLEND"]:
5456 luxProp(mat, dot(name)+"texture", "").set("blender_blend")
5457 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"}, ""))
5458 luxProp(mat, dot(name)+"flipXY", "false").set({0:"false", 1:"true"}[texture.rot90])
5460 print("Material Conversion Warning: SORRY, this procedural texture isn\'t implemented in conversion\n")
5462 def convertTextures(basename, texs, type="float", channel="col", val=1.0):
5465 isImagemap = (texture.type == Texture.Types["IMAGE"]) and (texture.image) and (texture.image.filename!="")
5466 if channel == "col":
5467 if texture.flags & Texture.Flags["COLORBAND"] > 0:
5468 cbLow, cbHigh = convertColorband(texture.colorband)
5469 val1, alpha1, val2, alpha2 = (cbLow[0],cbLow[1],cbLow[2]), cbLow[3]*tex.colfac, (cbHigh[0], cbHigh[1], cbHigh[2]), cbHigh[3]*tex.colfac
5471 lum1, lum2 = (val1[0]+val1[1]+val1[2])/3.0, (val2[0]+val2[1]+val2[2])/3.0
5472 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)
5473 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
5474 else: val1, alpha1, val2, alpha2 = tex.col, 0.0, tex.col, tex.colfac
5475 elif channel == "nor": val1, alpha1, val2, alpha2 = tex.norfac * 0.01, 0.0, tex.norfac * 0.01, 1.0
5476 else: val1, alpha1, val2, alpha2 = 1.0, 0.0, 1.0, tex.varfac
5477 if (tex.neg)^((channel=="nor") and (tex.mtNor<0)): val1, alpha1, val2, alpha2 = val2, alpha2, val1, alpha1
5478 luxProp(mat, dot(basename)+"textured", "").set("true")
5481 if (alpha1 < 1.0) or (alpha2 < 1.0): # texture with transparency
5482 luxProp(mat, dot(basename)+"texture", "").set("mix")
5483 if alpha1 == alpha2: # constant alpha
5484 luxProp(mat, ddot(basename)+"amount.value", 1.0).set(alpha1)
5486 createLuxTexture(ddot(basename)+"amount", tex)
5487 luxProp(mat, ddot(basename)+"amount:tex1.value", 1.0).set(alpha1)
5488 luxProp(mat, ddot(basename)+"amount:tex2.value", 1.0).set(alpha2)
5489 # transparent to next texture
5490 name = ddot(basename)+"tex1"
5492 convertTextures(ddot(basename)+"tex1", texs, type, channel, val)
5494 if type=="float": luxProp(mat, ddot(basename)+"tex1.value", 1.0).set(val)
5495 else: luxProp(mat, ddot(basename)+"tex1.value", "1.0 1.0 1.0").setRGB((val[0], val[1], val[2]))
5496 name = ddot(basename)+"tex2"
5497 if val1 == val2: # texture with different colors / value
5498 if type == "col": luxProp(mat, dot(name)+"value", "1.0 1.0 1.0").setRGB(val1)
5499 else: luxProp(mat, dot(name)+"value", 1.0).set(val1)
5501 createLuxTexture(name, tex)
5502 if type == "col": luxProp(mat, ddot(name)+"tex1.value", "1.0 1.0 1.0").setRGB(val1)
5503 else: luxProp(mat, ddot(name)+"tex1.value", 1.0).set(val1)
5504 if type == "col": luxProp(mat, ddot(name)+"tex2.value", "1.0 1.0 1.0").setRGB(val2)
5505 else: luxProp(mat, ddot(name)+"tex2.value", 1.0).set(val2)
5508 def convertDiffuseTexture(name):
5510 for tex in mat.getTextures():
5511 if tex and (tex.mapto & Texture.MapTo["COL"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
5513 luxProp(mat, name, "").setRGB((mat.ref, mat.ref, mat.ref))
5514 convertTextures(name, texs, "col", "col", (mat.R, mat.G, mat.B))
5515 def convertSpecularTexture(name):
5517 for tex in mat.getTextures():
5518 if tex and (tex.mapto & Texture.MapTo["CSP"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
5520 luxProp(mat, name, "").setRGB((mat.ref*mat.spec, mat.ref*mat.spec, mat.ref*mat.spec))
5521 convertTextures(name, texs, "col", "col", (mat.specR, mat.specG, mat.specB))
5522 def convertMirrorTexture(name):
5524 for tex in mat.getTextures():
5525 if tex and (tex.mapto & Texture.MapTo["CMIR"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
5527 luxProp(mat, name, "").setRGB((mat.ref, mat.ref, mat.ref))
5528 convertTextures(name, texs, "col", "col", (mat.mirR, mat.mirG, mat.mirB))
5529 def convertBumpTexture(basename):
5531 for tex in mat.getTextures():
5532 if tex and (tex.mapto & Texture.MapTo["NOR"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
5534 name = basename+":bumpmap"
5535 luxProp(mat, basename+".usebump", "").set("true")
5536 luxProp(mat, dot(name)+"textured", "").set("true")
5537 luxProp(mat, name, "").set(1.0)
5538 convertTextures(name, texs, "float", "nor", 0.0)
5540 def makeMatte(name):
5541 luxProp(mat, dot(name)+"type", "").set("matte")
5542 luxProp(mat, name+":Kd", "").setRGB((mat.R*mat.ref, mat.G*mat.ref, mat.B*mat.ref))
5543 convertDiffuseTexture(name+":Kd")
5544 convertBumpTexture(name)
5545 def makeGlossy(name, roughness):
5546 luxProp(mat, dot(name)+"type", "").set("glossy")
5547 luxProp(mat, name+":Kd", "").setRGB((mat.R*mat.ref, mat.G*mat.ref, mat.B*mat.ref))
5548 luxProp(mat, name+":Ks", "").setRGB((mat.specR*mat.spec*0.5, mat.specG*mat.spec*0.5, mat.specB*mat.spec*0.5))
5549 luxProp(mat, name+":uroughness", 0.0).set(roughness)
5550 luxProp(mat, name+":vroughness", 0.0).set(roughness)
5551 convertDiffuseTexture(name+":Kd")
5552 convertSpecularTexture(name+":Ks")
5553 convertBumpTexture(name)
5554 def makeMirror(name):
5555 luxProp(mat, dot(name)+"type", "").set("mirror")
5556 luxProp(mat, name+":Kr", "").setRGB((mat.mirR, mat.mirG, mat.mirB))
5557 convertMirrorTexture(name+":Kr")
5558 convertBumpTexture(name)
5559 def makeGlass(name):
5560 luxProp(mat, dot(name)+"type", "").set("glass")
5561 luxProp(mat, name+":Kr", "").setRGB((0.0, 0.0, 0.0))
5562 luxProp(mat, name+":Kt", "").setRGB((mat.R, mat.G, mat.B))
5563 luxProp(mat, name+":index.iorusepreset", "").set("false")
5564 luxProp(mat, name+":index", 0.0).set(mat.getIOR())
5565 convertMirrorTexture(name+":Kr")
5566 convertDiffuseTexture(name+":Kt")
5567 convertBumpTexture(name)
5568 def makeRoughglass(name, roughness):
5569 luxProp(mat, dot(name)+"type", "").set("roughglass")
5570 luxProp(mat, name+":Kr", "").setRGB((0.0, 0.0, 0.0))
5571 luxProp(mat, name+":Kt", "").setRGB((mat.R, mat.G, mat.B))
5572 luxProp(mat, name+":index.iorusepreset", "").set("false")
5573 luxProp(mat, name+":index", 0.0).set(mat.getIOR())
5574 luxProp(mat, name+":uroughness", 0.0).set(roughness)
5575 luxProp(mat, name+":vroughness", 0.0).set(roughness)
5576 convertMirrorTexture(name+":Kr")
5577 convertDiffuseTexture(name+":Kt")
5578 convertBumpTexture(name)
5579 print("convert Blender material \"%s\" to lux material"%(mat.name))
5580 mat.properties['luxblend'] = {}
5581 if mat.emit > 0.0001:
5582 luxProp(mat, "type", "").set("light")
5583 luxProp(mat, "light.l", "").setRGB((mat.R, mat.G, mat.B))
5584 luxProp(mat, "light.gain", 1.0).set(mat.emit)
5587 if not(mat.mode & Material.Modes.RAYTRANSP): alpha = 1.0
5588 alpha0name, alpha1name = "", ""
5589 if (alpha > 0.0) and (alpha < 1.0):
5590 luxProp(mat, "type", "").set("mix")
5591 luxProp(mat, ":amount", 0.0).set(alpha)
5592 alpha0name, alpha1name = "mat2", "mat1"
5594 mirror = mat.rayMirr
5595 if not(mat.mode & Material.Modes.RAYMIRROR): mirror = 0.0
5596 mirror0name, mirror1name = alpha1name, alpha1name
5597 if (mirror > 0.0) and (mirror < 1.0):
5598 luxProp(mat, dot(alpha1name)+"type", "").set("mix")
5599 luxProp(mat, alpha1name+":amount", 0.0).set(1.0 - mirror)
5600 mirror0name, mirror1name = ddot(alpha1name)+"mat1", ddot(alpha1name)+"mat2"
5602 if mat.glossMir < 1.0: makeGlossy(mirror1name, 1.0-mat.glossMir**2)
5603 else: makeMirror(mirror1name)
5605 if mat.spec > 0.0: makeGlossy(mirror0name, 1.0/mat.hard)
5606 else: makeMatte(mirror0name)
5608 if mat.glossTra < 1.0: makeRoughnessGlass(alpha0name, 1.0-mat.glossTra**2)
5609 else: makeGlass(alpha0name)
5611 def convertAllMaterials():
5612 for mat in Material.Get(): convertMaterial(mat)
5617 ### Connect LRMDB ###
5618 ConnectLrmdb = False
5620 import socket # try import of socket library
5622 def downloadLRMDB(mat, id):
5624 DrawProgressBar(0.0,'Getting Material #'+id)
5626 HOST = 'www.luxrender.net'
5627 GET = '/lrmdb/en/material/download/'+id
5629 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
5630 sock.connect((HOST, PORT))
5631 sock.send("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (GET, HOST))
5632 data = sock.recv(1024)
5636 data = sock.recv(1024)
5638 if str.split("\n", 1)[0].find("200") < 0:
5639 print("ERROR: server error: %s"%(str.split("\n",1)[0]))
5641 str = (str.split("\r\n\r\n")[1]).strip()
5642 if (str[0]=="{") and (str[-1]=="}"):
5643 return str2MatTex(str)
5644 print("ERROR: downloaded data is not a material or texture")
5646 print("ERROR: download failed")
5648 DrawProgressBar(1.0,'')
5650 print("ERROR: material id is not valid")
5654 #===========================================================================
5656 #===========================================================================
5658 #---------------------------------------------------------------------------
5660 import cookielib, urllib2, xmlrpclib
5662 #---------------------------------------------------------------------------
5664 # https://fedorahosted.org/python-bugzilla/browser/bugzilla.py?rev=e6f699f06e92b1e49b1b8d2c8fbe89d9425a4a9a
5665 class CookieTransport(xmlrpclib.Transport):
5667 A subclass of xmlrpclib.Transport that supports cookies.
5674 # Cribbed from xmlrpclib.Transport.send_user_agent
5675 def send_cookies(self, connection, cookie_request):
5677 Send all the cookie data that we have received
5680 if self.cookiejar is None:
5681 self.cookiejar = cookielib.CookieJar()
5682 elif self.cookiejar:
5683 # Let the cookiejar figure out what cookies are appropriate
5684 self.cookiejar.add_cookie_header(cookie_request)
5685 # Pull the cookie headers out of the request object...
5687 for header, value in cookie_request.header_items():
5688 if header.startswith('Cookie'):
5689 cookielist.append([header, value])
5690 # ...and put them over the connection
5691 for header, value in cookielist:
5692 connection.putheader(header, value)
5694 # This is the same request() method from xmlrpclib.Transport,
5695 # with a couple additions noted below
5696 def request(self, host, handler, request_body, verbose=0):
5701 host_connection = self.make_connection(host)
5703 host_connection.set_debuglevel(1)
5705 # ADDED: construct the URL and Request object for proper cookie handling
5706 request_url = "%s://%s/" % (self.scheme, host)
5707 cookie_request = urllib2.Request(request_url)
5709 self.send_request(host_connection, handler, request_body)
5710 self.send_host(host_connection, host)
5712 # ADDED. creates cookiejar if None.
5713 self.send_cookies(host_connection, cookie_request)
5714 self.send_user_agent(host_connection)
5715 self.send_content(host_connection, request_body)
5717 errcode, errmsg, headers = host_connection.getreply()
5719 # ADDED: parse headers and get cookies here
5720 class CookieResponse:
5722 fake a response object that we can fill with the headers above
5725 def __init__(self, headers):
5726 self.headers = headers
5731 cookie_response = CookieResponse(headers)
5733 # Okay, extract the cookies from the headers
5734 self.cookiejar.extract_cookies(cookie_response, cookie_request)
5736 # And write back any changes
5737 # DH THIS DOESN'T WORK
5738 # self.cookiejar.save(self.cookiejar.filename)
5741 raise xmlrpclib.ProtocolError(
5747 self.verbose = verbose
5750 sock = host_connection._conn.sock
5751 except AttributeError:
5754 return self._parse_response(host_connection.getfile(), sock)
5757 #===========================================================================
5759 #===========================================================================
5761 host = 'http://www.luxrender.net/lrmdb/ixr'
5769 last_error_str = None
5771 def last_error(self):
5772 return self.last_error_str #'LRMDB Connector: %s' %
5776 result = self.SERVER.user.login(
5783 self.logged_in = True
5786 self.last_error_str = 'Login Failed'
5787 self.logged_in = False
5790 def submit_object(self, mat, basekey, tex):
5791 if not self.check_creds(): return False
5794 result = 'Unknown Error'
5797 name = Draw.PupStrInput('Name: ', '', 32)
5801 result = self.SERVER.object.submit(
5803 MatTex2dict( getMatTex(mat, basekey, tex), tex )
5805 if result is not True:
5810 self.last_error_str = 'Submit failed: %s' % result
5813 def check_creds(self):
5814 if self.SERVER is None:
5816 self.SERVER = xmlrpclib.ServerProxy(self.host, transport=CookieTransport())
5818 self.last_error_str = 'ServerProxy init failed'
5822 if not self.logged_in:
5823 #if self.username is "":
5824 self.request_username()
5826 #if self.password is "":
5827 self.request_password()
5833 def request_username(self):
5834 self.username = Draw.PupStrInput("Username:", self.username, 32)
5836 def request_password(self):
5837 self.password = Draw.PupStrInput("Password:", self.password, 32)
5839 lrmdb_connector = lrmdb()
5842 except: print("WARNING: LRMDB support not available")
5846 ### MatTex functions ###
5847 ### MatTex : is a dictionary of material or texture properties
5849 def getMatTex(mat, basekey='', tex=False):
5850 global usedproperties, usedpropertiesfilterobj
5852 usedpropertiesfilterobj = mat
5855 for k,v in usedproperties.items():
5856 if k[:len(basekey)]==basekey:
5857 if k[-9:] != '.textured':
5858 name = k[len(basekey):]
5859 if name == ".type": name = "type"
5861 dict["__type__"] = ["material","texture"][bool(tex)]
5864 def putMatTex(mat, dict, basekey='', tex=None):
5865 if dict and (tex!=None) and (tex ^ (dict.has_key("__type__") and (dict["__type__"]=="texture"))):
5866 print("ERROR: Can't apply %s as %s"%(["texture","material"][bool(tex)],["material","texture"][bool(tex)]))
5869 # remove all current properties in mat that starts with basekey
5871 d = mat.properties['luxblend']
5872 for k,v in d.convert_to_pyobject().items():
5874 if k[:7]=="__hash:": # decode if entry is hashed (cause of 32chars limit)
5877 if kn[:len(basekey)]==basekey:
5878 del mat.properties['luxblend'][k]
5879 except: print("error") # pass
5880 # assign loaded properties
5881 for k,v in dict.items():
5883 if (basekey!="") and (k=="type"): k = ".type"
5884 # zuegs: following two lines should fix issue http://www.luxrender.net/forum/viewtopic.php?f=16&t=1618&p=14512#p14512
5885 if (basekey!="") and ((k[0]!=".") and (k[0]!=":")): k = ":"+k
5886 if (basekey=="") and (k[0:4]==":mat"): k = k[1:]
5887 luxProp(mat, basekey+k, None).set(v)
5888 if k[-8:] == '.texture':
5889 luxProp(mat, basekey+k[:-8]+'.textured', 'false').set('true')
5895 def MatTex2dict(d, tex = None):
5898 if LBX_VERSION == '0.6':
5900 if tex is not None and tex == True:
5901 d['LUX_DATA'] = 'TEXTURE'
5903 d['LUX_DATA'] = 'MATERIAL'
5905 d['LUX_VERSION'] = '0.6'
5909 elif LBX_VERSION == '0.7':
5912 if type(d[k]) == types.IntType:
5914 if type(d[k]) == types.FloatType:
5916 if type(d[k]) == types.BooleanType:
5918 if type(d[k]) == types.StringType:
5923 if l==None or len(l)!=3:
5928 definition.append([ t, k, d[k] ])
5932 'type': d['__type__'],
5934 'definition': definition,
5936 ['string', 'generator', 'luxblend'],
5942 def format_dictStr(dictStr):
5948 for char in dictStr:
5949 if char in ['}', ']']:
5952 for j in range(0,pos):
5957 if char in [',', '{', '[']:
5959 if char in ['{', '[']:
5961 for j in range(0,pos):
5967 def MatTex2str(d, tex = None):
5970 if LBX_VERSION == '0.6':
5971 return format_dictStr(str( MatTex2dict(d, tex) )) #.replace(", \'", ",\n\'")
5973 elif LBX_VERSION == '0.7':
5974 return format_dictStr(str( MatTex2dict(d, tex) )) #.replace("], \'", "],\r\n\'").replace("[","\r\n\t[")
5977 def str2MatTex(s, tex = None): # todo: this is not absolutely save from attacks!!!
5981 if (s[0]=='{') and (s[-1]=='}'):
5982 d = eval(s, dict(__builtins__=None))
5983 if type(d)==types.DictType:
5986 if LBX_VERSION == '0.6':
5988 if tex is not None and tex == True:
5989 test_str = 'TEXTURE'
5991 test_str = 'MATERIAL'
5993 if ('LUX_DATA' in d.keys() and d['LUX_DATA'] == test_str) \
5994 and ('LUX_VERSION' in d.keys() and (d['LUX_VERSION'] == '0.6' or d['LUX_VERSION'] == 0.6)):
5997 reason = 'Missing/incorrect metadata'
5999 elif LBX_VERSION == '0.7':
6001 def lb_list_to_dict(list):
6003 for t, k, v in list:
6010 if ('version' in d.keys() and d['version'] in ['0.6', '0.7']) \
6011 and ('type' in d.keys() and d['type'] in ['material', 'texture']) \
6012 and ('definition' in d.keys()):
6016 definition = lb_list_to_dict(d['definition'])
6018 if 'metadata' in d.keys():
6019 definition.update( lb_list_to_dict(d['metadata']) )
6023 reason = 'Incorrect LBX definition data'
6025 reason = 'Missing/incorrect metadata'
6027 reason = 'Unknown LBX version'
6029 reason = 'Not a parsed dict'
6031 reason = 'Not a stored dict'
6034 print("ERROR: string to material/texture conversion failed: %s" % reason)
6038 luxclipboard = None # global variable for copy/paste content
6039 def showMatTexMenu(mat, basekey='', tex=False):
6040 global luxclipboard, ConnectLrmdb
6041 if tex: menu="Texture menu:%t"
6042 else: menu="Material menu:%t"
6045 if luxclipboard and (not(tex) ^ (luxclipboard["__type__"]=="texture")): menu +="|Paste%x2"
6048 menu += "|Load LBT%x3|Save LBT%x4"
6050 menu += "|Load LBM%x3|Save LBM%x4"
6052 menu += "|Download from DB%x5" #not(tex) and
6053 menu += "|Upload to DB%x6"
6055 # menu += "|%l|dump material%x99|dump clipboard%x98"
6056 r = Draw.PupMenu(menu)
6058 luxclipboard = getMatTex(mat, basekey, tex)
6059 elif r==2: putMatTex(mat, luxclipboard, basekey, tex)
6061 scn = Scene.GetCurrent()
6063 Window.FileSelector(lambda fn:loadMatTex(mat, fn, basekey, tex), "load texture", luxProp(scn, "lux", "").get()+os.sep+".lbt")
6065 Window.FileSelector(lambda fn:loadMatTex(mat, fn, basekey, tex), "load material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
6067 scn = Scene.GetCurrent()
6069 Window.FileSelector(lambda fn:saveMatTex(mat, fn, basekey, tex), "save texture", luxProp(scn, "lux", "").get()+os.sep+".lbt")
6071 Window.FileSelector(lambda fn:saveMatTex(mat, fn, basekey, tex), "save material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
6074 id = Draw.PupStrInput("Material ID:", "", 32)
6076 id = Draw.PupStrInput("Texture ID:", "", 32)
6077 if id: putMatTex(mat, downloadLRMDB(mat, id), basekey, tex)
6079 global lrmdb_connector
6080 if not lrmdb_connector.submit_object(mat, basekey, tex):
6081 msg = lrmdb_connector.last_error()
6085 Draw.PupMenu("Upload: "+msg+".%t|OK")
6087 # for k,v in mat.properties['luxblend'].convert_to_pyobject().items(): print(k+"="+repr(v))
6089 # for k,v in luxclipboard.items(): print(k+"="+repr(v))
6094 def saveMatTex(mat, fn, basekey='', tex=False):
6096 d = getMatTex(mat, basekey, tex)
6097 file = open(fn, 'w')
6098 file.write(MatTex2str(d, tex))
6100 if LuxIsGUI: Draw.Redraw()
6103 def loadMatTex(mat, fn, basekey='', tex=None):
6105 file = open(fn, 'r')
6108 data = str2MatTex(data, tex)
6109 putMatTex(mat, data, basekey, tex)
6110 if LuxIsGUI: Draw.Redraw()
6114 def setactivemat(mat):
6122 self.position = 0 # current position at top (inside 0..height-viewHeight)
6123 self.height = 0 # total height of the content
6124 self.viewHeight = 0 # height of window
6125 self.x = 0 # horizontal position of the scrollbar
6126 self.scrolling = self.over = False # start without scrolling ;)
6127 def calcRects(self):
6128 # Blender doesn't give us direct access to the window size yet, but it does set the
6129 # GL scissor box for it, so we can get the size from that. (thx to Daniel Dunbar)
6130 size = BGL.Buffer(BGL.GL_FLOAT, 4)
6131 BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, size)
6132 size = size.list # [winx, winy, width, height]
6133 self.winrect = size[:]
6134 self.viewHeight = size[3]
6135 size[0], size[1] = size[2]-20, 0 # [scrollx1, scrolly1, scrollx2, scrolly2]
6137 if self.position < 0: self.position = 0
6138 if self.height < self.viewHeight: self.height = self.viewHeight
6139 if self.position > self.height-self.viewHeight: self.position = self.height-self.viewHeight
6140 self.factor = (size[3]-size[1]-4)/self.height
6141 self.sliderRect = [size[0]+2, size[3]-2-(self.position+self.viewHeight)*self.factor, size[2]-2, size[3]-2-self.position*self.factor]
6144 BGL.glColor3f(0.5,0.5,0.5); BGL.glRectf(self.rect[0],self.rect[1],self.rect[2],self.rect[3])
6145 if self.over or self.scrolling: BGL.glColor3f(1.0,1.0,0.7)
6146 else: BGL.glColor3f(0.7,0.7,0.7)
6147 BGL.glRectf(self.sliderRect[0],self.sliderRect[1],self.sliderRect[2],self.sliderRect[3])
6149 return self.viewHeight+self.position
6150 def scroll(self, delta):
6151 self.position = self.position + delta
6156 coord, buttons = Window.GetMouseCoords(), Window.GetMouseButtons()
6157 over = (coord[0]>=self.winrect[0]+self.rect[0]) and (coord[0]<=self.winrect[0]+self.rect[2]) and \
6158 (coord[1]>=self.winrect[1]+self.rect[1]) and (coord[1]<=self.winrect[1]+self.rect[3])
6159 if Window.MButs.L and buttons > 0:
6161 if self.factor > 0: self.scroll((self.lastcoord[1]-coord[1])/self.factor)
6164 self.scrolling = True
6165 self.lastcoord = coord
6166 elif self.scrolling:
6167 self.scrolling = False
6169 if self.over != over: Draw.Redraw()
6172 scrollbar = scrollbar()
6177 global icon_luxblend
6179 BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
6181 y = int(scrollbar.getTop()) # 420
6182 BGL.glColor3f(0.1,0.1,0.1); BGL.glRectf(0,0,440,y)
6183 BGL.glColor3f(1.0,0.5,0.0); BGL.glRasterPos2i(130,y-21); Draw.Text("v0.6")
6184 BGL.glColor3f(0.9,0.9,0.9)
6186 drawLogo(icon_luxblend, 6, y-25)
6188 scn = Scene.GetCurrent()
6190 luxpage = luxProp(scn, "page", 0)
6194 BGL.glRasterPos2i(10,y-45); Draw.Text("Render presets:")
6195 luxpreset = luxProp(scn, "preset", "1C - Final - medium MLT/Path Tracing (indoor) (recommended)")
6196 presets = getScenePresets()
6197 presetskeys = presets.keys()
6199 presetskeys.insert(0, "")
6200 presetsstr = "presets: %t"
6201 for i, v in enumerate(presetskeys): presetsstr = "%s %%x%d|%s"%(v, i, presetsstr)
6202 try: i = presetskeys.index(luxpreset.get())
6203 except ValueError: i = 0
6204 Draw.Menu(presetsstr, evtLuxGui, 110, y-50, 220, 18, i, "", lambda e,v: luxpreset.set(presetskeys[v]))
6205 Draw.Button("save", evtSavePreset, 330, y-50, 40, 18, "create a render-settings preset")
6206 Draw.Button("del", evtDeletePreset, 370, y-50, 40, 18, "delete a render-settings preset")
6208 # if preset is selected load values
6209 if luxpreset.get() != "":
6211 d = presets[luxpreset.get()]
6212 for k,v in d.items(): scn.properties['luxblend'][k] = v
6215 Draw.Button("Material", evtLuxGui, 10, y-70, 80, 16, "", lambda e,v:luxpage.set(0))
6216 Draw.Button("Cam/Env", evtLuxGui, 90, y-70, 80, 16, "", lambda e,v:luxpage.set(1))
6217 Draw.Button("Render", evtLuxGui, 170, y-70, 80, 16, "", lambda e,v:luxpage.set(2))
6218 Draw.Button("Output", evtLuxGui, 250, y-70, 80, 16, "", lambda e,v:luxpage.set(3))
6219 Draw.Button("System", evtLuxGui, 330, y-70, 80, 16, "", lambda e,v:luxpage.set(4))
6220 if luxpage.get() == 0:
6221 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(10,y-74,90,y-70);BGL.glColor3f(0.9,0.9,0.9)
6222 obj = scn.objects.active
6224 if (obj.getType() == "Lamp"):
6225 ltype = obj.getData(mesh=1).getType() # data
6226 if (ltype == Lamp.Types["Area"]): luxLight("Area LIGHT", "", obj, gui, 0)
6227 elif (ltype == Lamp.Types["Spot"]): luxSpot("Spot LIGHT", "", obj, gui, 0)
6228 elif (ltype == Lamp.Types["Lamp"]): luxLamp("Point LIGHT", "", obj, gui, 0)
6230 matfilter = luxProp(scn, "matlistfilter", "false")
6231 mats = getMaterials(obj, True)
6232 if (activemat == None) and (len(mats) > 0):
6233 setactivemat(mats[0])
6234 if matfilter.get() == "false":
6235 mats = Material.Get()
6237 for i, v in enumerate(mats):
6238 if v==activemat: matindex = i
6239 matnames = [m.getName() for m in mats]
6240 menustr = "Material: %t"
6241 for i, v in enumerate(matnames): menustr = "%s %%x%d|%s"%(v, i, menustr)
6242 gui.newline("MATERIAL:", 8)
6243 r = gui.getRect(1.1, 1)
6244 Draw.Button("C", evtConvertMaterial, r[0]-gui.h, gui.y-gui.h, gui.h, gui.h, "convert blender material to lux material")
6245 Draw.Menu(menustr, evtLuxGui, r[0], r[1], r[2], r[3], matindex, "", lambda e,v: setactivemat(mats[v]))
6246 luxBool("", matfilter, "filter", "only show active object materials", gui, 0.5)
6248 Draw.Button("L", evtLoadMaterial, gui.x, gui.y-gui.h, gui.h, gui.h, "load a material preset")
6249 Draw.Button("S", evtSaveMaterial, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "save a material preset")
6250 Draw.Button("D", evtDeleteMaterial, gui.x+gui.h*2, gui.y-gui.h, gui.h, gui.h, "delete a material preset")
6252 setactivemat(mats[matindex])
6253 luxMaterial(activemat, gui)
6254 if luxpage.get() == 1:
6255 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(90,y-74,170,y-70);BGL.glColor3f(0.9,0.9,0.9)
6256 cam = scn.getCurrentCamera()
6258 r = gui.getRect(1.1, 1)
6259 luxCamera(cam.data, scn.getRenderingContext(), gui)
6261 luxEnvironment(scn, gui)
6262 if luxpage.get() == 2:
6263 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(170,y-74,250,y-70);BGL.glColor3f(0.9,0.9,0.9)
6264 r = gui.getRect(1.1, 1)
6265 luxSampler(scn, gui)
6267 luxSurfaceIntegrator(scn, gui)
6269 luxVolumeIntegrator(scn, gui)
6271 luxPixelFilter(scn, gui)
6272 if luxpage.get() == 3:
6273 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(250,y-74,330,y-70);BGL.glColor3f(0.9,0.9,0.9)
6274 r = gui.getRect(1.1, 1)
6276 if luxpage.get() == 4:
6277 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(330,y-74,410,y-70);BGL.glColor3f(0.9,0.9,0.9)
6280 luxAccelerator(scn, gui)
6281 gui.newline("MATERIALS:", 10)
6282 r = gui.getRect(2,1)
6283 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())
6284 gui.newline("SETTINGS:", 10)
6285 r = gui.getRect(2,1)
6286 Draw.Button("save defaults", 0, r[0], r[1], r[2], r[3], "save current settings as defaults", lambda e,v:saveluxdefaults())
6288 if y > 0: y = 0 # bottom align of render button
6289 run = luxProp(scn, "run", "true")
6290 dlt = luxProp(scn, "default", "true")
6291 pipe = luxProp(scn, "pipe", "false")
6292 clay = luxProp(scn, "clay", "false")
6293 nolg = luxProp(scn, "nolg", "false")
6294 lxs = luxProp(scn, "lxs", "true")
6295 lxo = luxProp(scn, "lxo", "true")
6296 lxm = luxProp(scn, "lxm", "true")
6297 lxv = luxProp(scn, "lxv", "true")
6298 net = luxProp(scn, "netrenderctl", "false")
6299 donet = luxProp(scn, "donetrender", "true")
6301 global render_status_text
6302 global render_status
6304 if render_status == True:
6305 BGL.glRasterPos2i(10,y+20)
6306 Draw.Text(render_status_text)
6308 BGL.glRasterPos2i(10,y+5)
6309 Draw.Text(render_status_text, "tiny")
6311 def check_pipe_def_exclusion(m, v):
6313 dlt.set(["false","true"][bool(v)])
6315 if dlt.get() == 'true':
6318 pipe.set(["false","true"][bool(v)])
6320 if pipe.get() == 'true':
6323 if (run.get()=="true"):
6324 Draw.Button("Render", 0, 10, y+20, 100, 36, "Render with Lux", lambda e,v:CBluxExport(dlt.get()=="true" or pipe.get()=="true", True))
6325 Draw.Button("Render Anim", 0, 110, y+20, 100, 36, "Render animation with Lux", lambda e,v:CBluxAnimExport(dlt.get()=="true" or pipe.get()=="true", True))
6327 Draw.Button("Export", 0, 10, y+20, 100, 36, "Export", lambda e,v:CBluxExport(dlt.get()=="true" or pipe.get()=="true", False))
6328 Draw.Button("Export Anim", 0, 110, y+20, 100, 36, "Export animation", lambda e,v:CBluxAnimExport(dlt.get()=="true" or pipe.get()=="true", False))
6330 Draw.Toggle("run", evtLuxGui, 265, y+40, 30, 16, run.get()=="true", "start Lux after export", lambda e,v: run.set(["false","true"][bool(v)]))
6332 if (pipe.get() == 'false' and dlt.get() == 'true') or run.get()=='false':
6333 Draw.Toggle("def", evtLuxGui, 295, y+40, 55, 16, dlt.get()=="true", "write to default lxs file", lambda e,v: check_pipe_def_exclusion('d',v))
6334 elif pipe.get() == 'true' and dlt.get() == 'false':
6335 Draw.Toggle("pipe", evtLuxGui, 295, y+40, 55, 16, pipe.get()=="true", "do not write any lxs file", lambda e,v: check_pipe_def_exclusion('p',v))
6337 Draw.Toggle("def", evtLuxGui, 295, y+40, 25, 16, dlt.get()=="true", "write to default lxs file", lambda e,v: check_pipe_def_exclusion('d',v))
6338 Draw.Toggle("pipe", evtLuxGui, 320, y+40, 30, 16, pipe.get()=="true", "do not write any lxs file", lambda e,v: check_pipe_def_exclusion('p',v))
6340 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)]))
6341 Draw.Toggle("noLG", evtLuxGui, 380, y+40, 35, 16, nolg.get()=="true", "disables all light groups", lambda e,v: nolg.set(["false","true"][bool(v)]))
6343 if pipe.get() == "false":
6344 Draw.Toggle(".lxs", 0, 265, y+20, 37, 16, lxs.get()=="true", "export .lxs scene file", lambda e,v: lxs.set(["false","true"][bool(v)]))
6345 Draw.Toggle(".lxo", 0, 302, y+20, 38, 16, lxo.get()=="true", "export .lxo geometry file", lambda e,v: lxo.set(["false","true"][bool(v)]))
6346 Draw.Toggle(".lxm", 0, 340, y+20, 37, 16, lxm.get()=="true", "export .lxm material file", lambda e,v: lxm.set(["false","true"][bool(v)]))
6347 Draw.Toggle(".lxv", 0, 377, y+20, 38, 16, lxv.get()=="true", "export .lxv volume file", lambda e,v: lxv.set(["false","true"][bool(v)]))
6349 BGL.glColor3f(0.9, 0.9, 0.9)
6351 BGL.glRasterPos2i(330,y+5) ; Draw.Text("Press Q or ESC to quit.", "tiny")
6352 scrollbar.height = scrollbar.getTop() - y
6355 render_status_text = ''
6356 render_status = False
6371 def luxEvent(evt, val): # function that handles keyboard and mouse events
6372 global activeObject, activemat, activeEvent, lastEventTime, key_tabs
6373 if evt == Draw.ESCKEY or evt == Draw.QKEY:
6374 stop = Draw.PupMenu("OK?%t|Cancel export %x1")
6378 scn = Scene.GetCurrent()
6380 if scn.objects.active != activeObject:
6381 activeObject = scn.objects.active
6384 if (evt == Draw.MOUSEX) or (evt == Draw.MOUSEY): scrollbar.Mouse()
6385 if evt == Draw.WHEELUPMOUSE: scrollbar.scroll(-16)
6386 if evt == Draw.WHEELDOWNMOUSE: scrollbar.scroll(16)
6387 if evt == Draw.PAGEUPKEY: scrollbar.scroll(-50)
6388 if evt == Draw.PAGEDOWNKEY: scrollbar.scroll(50)
6390 # scroll to [T]op and [B]ottom
6391 if evt == Draw.TKEY:
6392 scrollbar.scroll(-scrollbar.position)
6393 if evt == Draw.BKEY:
6394 scrollbar.scroll(100000) # Some large number should be enough ?!
6396 # R key shortcut to launch render
6397 # E key shortcut to export current scene (not render)
6398 # P key shortcut to preview current material
6399 # These keys need time and process-complete locks
6400 if evt in [Draw.RKEY, Draw.EKEY, Draw.PKEY]:
6401 if activeEvent == None and (sys.time() - lastEventTime) > 5:
6402 lastEventTime = sys.time()
6403 if evt == Draw.RKEY:
6404 activeEvent = 'RKEY'
6405 CBluxExport(luxProp(scn, "default", "true").get() == "true" or luxProp(scn, "pipe", "false").get() == "true", True)
6407 if evt == Draw.EKEY:
6408 activeEvent = 'EKEY'
6409 CBluxExport(luxProp(scn, "default", "true").get() == "true" or luxProp(scn, "pipe", "false").get() == "true", False)
6411 if evt == Draw.PKEY:
6412 activeEvent = 'PKEY'
6413 if activemat != None:
6414 Preview_Update(activemat, '', True, 0, None, None, None)
6417 # Switch GUI tabs with number keys
6418 if evt in key_tabs.keys():
6419 luxProp(scn, "page", 0).set(key_tabs[evt])
6424 # Handle icon button events - note - radiance - this is a work in progress! :)
6425 # if evt == Draw.LEFTMOUSE and not val:
6426 # size=BGL.Buffer(BGL.GL_FLOAT, 4)
6427 # BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, size)
6428 # size= [int(s) for s in size]
6429 # mx, my = Window.GetMouseCoords()
6430 # mousex = mx - size[0]
6431 # print("mousex = %i"%mousex)
6432 # #if((mousex > 2) and (mousex < 25)):
6433 # # Mouse clicked in left button bar
6434 # if((mousex > 399) and (mousex < 418)):
6435 # # Mouse clicked in right button bar
6436 # mousey = my - size[1] - scrollbar.position
6437 # print("mousey = %i"%mousey)
6440 def luxButtonEvt(evt): # function that handles button events
6441 global usedproperties, usedpropertiesfilterobj
6442 if evt == evtLuxGui:
6444 if evt == evtSavePreset:
6445 scn = Scene.GetCurrent()
6447 name = Draw.PupStrInput("preset name: ", "")
6450 usedpropertiesfilterobj = None
6451 luxSurfaceIntegrator(scn)
6456 # luxEnvironment(scn)
6457 saveScenePreset(name, usedproperties.copy())
6458 luxProp(scn, "preset", "").set(name)
6460 if evt == evtDeletePreset:
6461 presets = getScenePresets().keys()
6463 presetsstr = "delete preset: %t"
6464 for i, v in enumerate(presets): presetsstr += "|%s %%x%d"%(v, i)
6465 r = Draw.PupMenu(presetsstr, 20)
6467 saveScenePreset(presets[r], None)
6470 if evt == evtLoadMaterial:
6472 mats = getMaterialPresets()
6473 matskeys = mats.keys()
6475 matsstr = "load preset: %t"
6476 for i, v in enumerate(matskeys): matsstr += "|%s %%x%d"%(v, i)
6477 r = Draw.PupMenu(matsstr, 20)
6481 # for k,v in mats[name].items(): activemat.properties['luxblend'][k] = v
6482 for k,v in mats[name].items(): luxProp(activemat, k, None).set(v)
6485 if evt == evtSaveMaterial:
6487 name = Draw.PupStrInput("preset name: ", "")
6490 usedpropertiesfilterobj = activemat
6491 luxMaterial(activemat)
6492 saveMaterialPreset(name, usedproperties.copy())
6494 if evt == evtDeleteMaterial:
6495 matskeys = getMaterialPresets().keys()
6497 matsstr = "delete preset: %t"
6498 for i, v in enumerate(matskeys): matsstr += "|%s %%x%d"%(v, i)
6499 r = Draw.PupMenu(matsstr, 20)
6501 saveMaterialPreset(matskeys[r], None)
6503 if evt == evtConvertMaterial:
6504 if activemat: convertMaterial(activemat)
6506 if evt == evtLoadMaterial2:
6508 scn = Scene.GetCurrent()
6509 Window.FileSelector(lambda fn:loadMatTex(activemat, fn), "load material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
6510 if evt == evtSaveMaterial2:
6512 scn = Scene.GetCurrent()
6513 Window.FileSelector(lambda fn:saveMaterial(activemat, fn), "save material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
6516 def setFocus(target):
6517 currentscene = Scene.GetCurrent()
6518 camObj = currentscene.objects.camera # currentscene.getCurrentCamera()
6521 refLoc = (Object.GetSelected()[0]).getLocation()
6523 print("select an object to focus\n")
6525 refLoc = Window.GetCursorPos()
6527 refLoc = (Object.Get(target)).getLocation()
6528 dist = Mathutils.Vector(refLoc) - Mathutils.Vector(camObj.getLocation())
6529 camDir = camObj.getMatrix()[2]*(-1.0)
6530 camObj.getData(mesh=1).dofDist = (camDir[0]*dist[0]+camDir[1]*dist[1]+camDir[2]*dist[2])/camDir.length # data
6533 # Parse command line arguments for batch mode rendering if supplied
6536 batchindex = osys.argv.index('--batch')
6537 pyargs = osys.argv[osys.argv.index('--batch')+1:]
6540 if (pyargs != []) and (batchindex != 0):
6541 print("\n\nLuxBlend v0.6 - BATCH mode\n")
6544 scene = Scene.GetCurrent()
6545 context = scene.getRenderingContext()
6549 o, a = getopt.getopt(pyargs, 's:e:o:t:l:',["scale=","haltspp=","run=", "lbm=", "lbt="])
6555 if (opts.has_key('--run')) and (opts['--run'] == 'false'):
6557 luxProp(scene, "run", "true").set("false")
6559 luxProp(scene, "run", "true").set("true")
6561 if opts.has_key('--scale'):
6562 print("Zoom: %s" %opts['--scale'])
6563 luxProp(scene, "film.scale", "100 %").set(opts['--scale'])
6565 if opts.has_key('--haltspp'):
6566 print("haltspp: %s" %opts['--haltspp'])
6567 luxProp(scene, "haltspp", 0).set(int(opts['--haltspp']))
6569 if opts.has_key('-s'):
6570 print("Start frame: %s" %opts['-s'])
6571 context.startFrame(int(opts['-s']))
6573 print("Error: Start frame not supplied (-s)"); osys.exit(1)
6574 if opts.has_key('-e'):
6575 print("End frame: %s" %opts['-e'])
6576 context.endFrame(int(opts['-e']))
6578 print("Error: End frame not supplied (-e)"); osys.exit(1)
6579 if opts.has_key('-l'):
6580 print("Path to lux binary: %s" %opts['-l'])
6581 luxbatchconsolemode = luxProp(scene, "luxbatchc", "false")
6582 luxbatchconsolemode.set("true")
6583 luxpathprop = luxProp(scene, "lux", "")
6584 luxpathprop.set(opts['-l'])
6586 print("Error: path to lux binary not supplied (-l)"); osys.exit(1)
6587 if opts.has_key('-o'):
6588 print("Image output path: %s" %opts['-o'])
6589 luxProp(scene, "overrideoutputpath", "").set(opts['-o'])
6591 print("Error: image output path not supplied (-o)"); osys.exit(1)
6592 if opts.has_key('-t'):
6593 print("Temporary export path: %s" %opts['-t'])
6594 luxProp(scene, "datadir", "").set(opts['-t'])
6596 print("Error: Temporary export path not supplied (-t)"); osys.exit(1)
6598 if opts.has_key('--lbm'):
6599 print("Load material: %s" %opts['--lbm'])
6600 mat = Material.Get("Material")
6601 if mat: loadMatTex(mat, opts['--lbm'])
6603 print("Error: No material with name \"Material\" found (--lbm)"); osys.exit(1)
6605 if opts.has_key('--lbt'):
6606 print("Load material: %s" %opts['--lbt'])
6607 mat = Material.Get("Material")
6608 if mat: loadMatTex(mat, opts['--lbt'], ':Kd')
6610 print("Error: No material with name \"Material\" found (--lbt)"); osys.exit(1)
6612 # CBluxAnimExport(True, True)
6613 CBluxAnimExport(True, True, False) # as by zukazuka (http://www.luxrender.net/forum/viewtopic.php?f=11&t=1288)
6617 print("\n\nLuxBlend v0.6 - UI mode\n")
6618 from Blender.Window import DrawProgressBar
6621 Draw.Register(luxDraw, luxEvent, luxButtonEvt) # init GUI
6623 luxpathprop = luxProp(Scene.GetCurrent(), "lux", "")
6624 luxpath = luxpathprop.get()
6625 luxrun = luxProp(Scene.GetCurrent(), "run", True).get()
6626 checkluxpath = luxProp(Scene.GetCurrent(), "checkluxpath", True).get()
6628 if checkluxpath and luxrun:
6629 if (luxpath is None) or (sys.exists(luxpath)<=0):
6630 # luxpath not valid, so delete entry from .blend scene file
6631 luxpathprop.delete()
6632 # and re-get luxpath, so we get the path from default-settings
6633 luxpath = luxpathprop.get()
6635 LUXRENDER_ROOT = os.getenv('LUXRENDER_ROOT')
6636 if LUXRENDER_ROOT is not None:
6637 LUXRENDER_ROOT = LUXRENDER_ROOT + os.sep
6638 luxpathprop.set(LUXRENDER_ROOT)
6639 luxpath = LUXRENDER_ROOT
6640 if sys.exists(luxpath)>0:
6641 print('LuxRender path set from LUXRENDER_ROOT environment variable')
6644 if (luxpath is None) or (sys.exists(luxpath)<=0):
6645 print("WARNING: LuxPath \"%s\" is not valid\n"%(luxpath))
6646 scn = Scene.GetCurrent()
6648 r = Draw.PupMenu("Installation: Set path to the lux render software?%t|Yes%x1|No%x0|Never%x2")
6650 Window.FileSelector(lambda s:luxProp(scn, "lux", "").set(Blender.sys.dirname(s)+os.sep), "Select file in Lux path")
6653 newluxdefaults["checkluxpath"] = False
6656 print("Lux path check disabled\n")