Backported the fix for max. value of network_interval
2 # -*- coding: utf-8 -*-
4 """Registration info for Blender menus:
5 Name: 'LuxBlend v0.6.1 Exporter'
8 Tooltip: 'Export/Render to LuxRender v0.6.1 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.1 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):
350 print(" exporting mesh")
353 usedmats = [f.mat for f in mesh.faces]
354 for matIndex in range(len(mats)):
355 if not matIndex in usedmats:
361 self.exportMaterialLink(file, mat)
362 mesh_str = self.getMeshType(len(mesh.verts), mats[matIndex])
364 file.write("\tShape %s \"integer indices\" [\n"% mesh_str)
366 self.exportMaterialLink(file, mats[matIndex])
367 file.write("\tPortalShape %s \"integer indices\" [\n"% mesh_str)
369 ffaces = [f for f in mesh.faces if f.mat == matIndex]
371 file.write("%d %d %d\n"%(index, index+1, index+2))
373 file.write("%d %d %d\n"%(index, index+2, index+3))
374 index += len(face.verts)
375 file.write("\t] \"point P\" [\n")
378 file.write("%f %f %f\n"% tuple(vertex.co))
379 file.write("\t] \"normal N\" [\n")
385 file.write("%f %f %f\n"% tuple(normal))
387 file.write("\t] \"float uv\" [\n")
390 file.write("%f %f\n"% tuple(uv))
393 #-------------------------------------------------
394 # exportMeshOpt(self, file, mesh, mats, name, portal, optNormals)
395 # exports mesh to the file with optimization.
396 # portal: export without normals and UVs
397 # optNormals: speed and filesize optimization, flat faces get exported without normals
398 #-------------------------------------------------
399 def exportMeshOpt(self, file, mesh, mats, name, portal=False, optNormals=True):
400 print(" exporting optimized mesh")
401 shapeList, smoothFltr, shapeText = [0], [[0,1]], [""]
403 normalFltr, uvFltr, shapeText = [0], [0], ["portal"] # portal, no normals, no UVs
405 uvFltr, normalFltr, shapeText = [1], [1], ["mixed with normals"] # normals and UVs
406 if optNormals: # one pass for flat faces without normals and another pass for smoothed faces with normals, all with UVs
407 shapeList, smoothFltr, normalFltr, uvFltr, shapeText = [0,1], [[0],[1]], [0,1], [1,1], ["flat w/o normals", "smoothed with normals"]
410 usedmats = [f.mat for f in mesh.faces]
411 for matIndex in range(len(mats)):
412 if not matIndex in usedmats:
418 self.exportMaterialLink(file, mat)
419 for shape in shapeList:
420 blenderExportVertexMap = []
423 ffaces = [f for f in mesh.faces if (f.mat == matIndex) and (f.smooth in smoothFltr[shape])]
428 # v = [vertex.co[0], vertex.co[1], vertex.co[2]]
430 if normalFltr[shape]:
432 # v.extend(vertex.no)
437 if (uvFltr[shape]) and (mesh.faceUV):
438 # v.extend(face.uv[index])
439 v.append(face.uv[index])
440 blenderVIndex = vertex.index
443 if (blenderVIndex < len(blenderExportVertexMap)):
444 for exportVIndex in blenderExportVertexMap[blenderVIndex]:
445 v2 = exportVerts[exportVIndex]
446 if (length==len(v2)) and (v == v2):
447 newExportVIndex = exportVIndex
449 if (newExportVIndex < 0):
450 newExportVIndex = len(exportVerts)
451 exportVerts.append(v)
452 while blenderVIndex >= len(blenderExportVertexMap):
453 blenderExportVertexMap.append([])
454 blenderExportVertexMap[blenderVIndex].append(newExportVIndex)
455 exportVIndices.append(newExportVIndex)
457 exportFaces.append(exportVIndices)
458 if (len(exportVerts)>0):
459 mesh_str = self.getMeshType(len(exportVerts), mats[matIndex])
461 file.write("\tPortalShape %s \"integer indices\" [\n"% mesh_str)
463 file.write("\tShape %s \"integer indices\" [\n"% mesh_str)
464 for face in exportFaces:
465 file.write("%d %d %d\n"%(face[0], face[1], face[2]))
467 file.write("%d %d %d\n"%(face[0], face[2], face[3]))
468 file.write("\t] \"point P\" [\n")
469 # for vertex in exportVerts:
470 # file.write("%f %f %f\n"%(vertex[0], vertex[1], vertex[2]))
471 file.write("".join(["%f %f %f\n"%tuple(vertex[0]) for vertex in exportVerts]))
472 if normalFltr[shape]:
473 file.write("\t] \"normal N\" [\n")
474 # for vertex in exportVerts:
475 # file.write("%f %f %f\n"%(vertex[3], vertex[4], vertex[5]))
476 file.write("".join(["%f %f %f\n"%tuple(vertex[1]) for vertex in exportVerts]))
477 if (uvFltr[shape]) and (mesh.faceUV):
478 file.write("\t] \"float uv\" [\n")
479 # for vertex in exportVerts:
480 # file.write("%f %f\n"%(vertex[6], vertex[7]))
481 file.write("".join(["%f %f\n"%tuple(vertex[2]) for vertex in exportVerts]))
483 if (uvFltr[shape]) and (mesh.faceUV):
484 file.write("\t] \"float uv\" [\n")
485 # for vertex in exportVerts:
486 # file.write("%f %f\n"%(vertex[3], vertex[4]))
487 file.write("".join(["%f %f\n"%tuple(vertex[1]) for vertex in exportVerts]))
489 print(" shape(%s): %d vertices, %d faces"%(shapeText[shape], len(exportVerts), len(exportFaces)))
491 #-------------------------------------------------
492 # exportMeshes(self, file)
493 # exports meshes that uses instancing (meshes that are used by at least "instancing_threshold" objects)
494 #-------------------------------------------------
495 def exportMeshes(self, file):
496 scn = Scene.GetCurrent()
497 instancing_threshold = luxProp(scn, "instancing_threshold", 2).get()
498 mesh_optimizing = luxProp(scn, "mesh_optimizing", "true")
500 for (mesh_name, objs) in self.meshes.items():
501 allow_instancing = True
502 mats = getMaterials(objs[0]) # mats = obj.getData().getMaterials()
503 for mat in mats: # don't instance if one of the materials is emissive
504 if (mat!=None) and (luxProp(mat, "type", "").get()=="light"):
505 allow_instancing = False
506 for obj in objs: # don't instance if the objects with same mesh uses different materials
507 ms = getMaterials(obj)
509 allow_instancing = False
510 if obj.modifiers.__len__() > 0:
511 allow_instancing = False
512 if allow_instancing and (len(objs) > instancing_threshold):
513 del self.meshes[mesh_name]
514 mesh.getFromObject(objs[0], 0, 1)
515 print("blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces)))
516 file.write("ObjectBegin \"%s\"\n"%mesh_name)
518 if (mesh_optimizing.get() == "true"):
519 self.exportMeshOpt(file, mesh, mats, mesh_name)
521 self.exportMesh(file, mesh, mats, mesh_name)
522 file.write("ObjectEnd # %s\n\n"%mesh_name)
525 #-------------------------------------------------
526 # exportObjects(self, file)
527 # exports objects to the file
528 #-------------------------------------------------
529 def exportObjects(self, file):
530 scn = Scene.GetCurrent()
531 cam = scn.getCurrentCamera().data
532 objectmblur = luxProp(cam, "objectmblur", "true")
533 usemblur = luxProp(cam, "usemblur", "false")
534 mesh_optimizing = luxProp(scn, "mesh_optimizing", "true")
536 for [obj, matrix] in self.objects:
537 print("object: %s"%(obj.getName()))
538 mesh_name = obj.getData(name_only=True)
541 if(objectmblur.get() == "true" and usemblur.get() == "true"):
543 frame = Blender.Get('curframe')
544 Blender.Set('curframe', frame+1)
545 m1 = 1.0*matrix # multiply by 1.0 to get a copy of orignal matrix (will be frame-independant)
546 Blender.Set('curframe', frame)
548 print(" motion blur")
551 if motion: # motion-blur only works with instances, so ensure mesh is exported as instance first
552 if mesh_name in self.meshes:
553 del self.meshes[mesh_name]
554 mesh.getFromObject(obj, 0, 1)
555 mats = getMaterials(obj)
556 print(" blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces)))
557 file.write("ObjectBegin \"%s\"\n"%mesh_name)
558 if (mesh_optimizing.get() == "true"):
559 self.exportMeshOpt(file, mesh, mats, mesh_name)
561 self.exportMesh(file, mesh, mats, mesh_name)
562 file.write("ObjectEnd # %s\n\n"%mesh_name)
564 file.write("AttributeBegin # %s\n"%obj.getName())
565 file.write("\tTransform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
566 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
567 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
568 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
569 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
571 file.write("\tTransformBegin\n")
572 file.write("\t\tIdentity\n")
573 file.write("\t\tTransform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
574 %(motion[0][0], motion[0][1], motion[0][2], motion[0][3],\
575 motion[1][0], motion[1][1], motion[1][2], motion[1][3],\
576 motion[2][0], motion[2][1], motion[2][2], motion[2][3],\
577 motion[3][0], motion[3][1], motion[3][2], motion[3][3]))
578 file.write("\t\tCoordinateSystem \"%s\"\n"%(obj.getName()+"_motion"))
579 file.write("\tTransformEnd\n")
580 if mesh_name in self.meshes:
581 mesh.getFromObject(obj, 0, 1)
582 mats = getMaterials(obj)
583 print(" blender-mesh: %s (%d vertices, %d faces)"%(mesh_name, len(mesh.verts), len(mesh.faces)))
584 if (mesh_optimizing.get() == "true"):
585 self.exportMeshOpt(file, mesh, mats, mesh_name)
587 self.exportMesh(file, mesh, mats, mesh_name)
589 print(" instance %s"%(mesh_name))
591 file.write("\tMotionInstance \"%s\" 0.0 1.0 \"%s\"\n"%(mesh_name, obj.getName()+"_motion"))
593 file.write("\tObjectInstance \"%s\"\n"%mesh_name)
594 file.write("AttributeEnd\n\n")
597 #-------------------------------------------------
598 # exportPortals(self, file)
599 # exports portals objects to the file
600 #-------------------------------------------------
601 def exportPortals(self, file):
602 scn = Scene.GetCurrent()
603 mesh_optimizing = luxProp(scn, "mesh_optimizing", "true")
605 for [obj, matrix] in self.portals:
606 print("portal: %s"%(obj.getName()))
607 file.write("\tTransform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
608 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
609 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
610 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
611 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
612 mesh_name = obj.getData(name_only=True)
613 mesh.getFromObject(obj, 0, 1)
614 mats = getMaterials(obj) # mats = obj.getData().getMaterials()
615 if (mesh_optimizing.get() == "true"):
616 self.exportMeshOpt(file, mesh, mats, mesh_name, True)
618 self.exportMesh(file, mesh, mats, mesh_name, True)
621 #-------------------------------------------------
622 # exportLights(self, file)
623 # exports lights to the file
624 #-------------------------------------------------
625 def exportLights(self, file):
626 for [obj, matrix] in self.lights:
627 ltype = obj.getData(mesh=1).getType() # data
628 if (ltype == Lamp.Types["Lamp"]) or (ltype == Lamp.Types["Spot"]) or (ltype == Lamp.Types["Area"]):
629 print("light: %s"%(obj.getName()))
630 if ltype == Lamp.Types["Area"]:
631 (str, link) = luxLight("", "", obj, None, 0)
633 if ltype == Lamp.Types["Area"]: file.write("AttributeBegin # %s\n"%obj.getName())
634 else: file.write("TransformBegin # %s\n"%obj.getName())
635 file.write("\tTransform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
636 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
637 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
638 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
639 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
640 col = obj.getData(mesh=1).col # data
641 energy = obj.getData(mesh=1).energy # data
642 if ltype == Lamp.Types["Lamp"]:
643 lightgroup = luxProp(obj, "light.lightgroup", "default")
644 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
645 file.write("LightGroup \"%s\"\n"%lightgroup.get())
646 (str, link) = luxLamp("", "", obj, None, 0)
647 file.write(str+"LightSource \"point\""+link+"\n")
648 if ltype == Lamp.Types["Spot"]:
649 (str, link) = luxSpot("", "", obj, None, 0)
651 proj = luxProp(obj, "light.usetexproj", "false")
652 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
653 lightgroup = luxProp(obj, "light.lightgroup", "default")
654 file.write("LightGroup \"%s\"\n"%lightgroup.get())
655 if(proj.get() == "true"):
656 file.write("Rotate 180 0 1 0\n")
657 file.write("LightSource \"projection\" \"float fov\" [%f]"%(obj.getData(mesh=1).spotSize))
659 file.write("LightSource \"spot\" \"point from\" [0 0 0] \"point to\" [0 0 -1] \"float coneangle\" [%f] \"float conedeltaangle\" [%f]"\
660 %(obj.getData(mesh=1).spotSize*0.5, obj.getData(mesh=1).spotSize*0.5*obj.getData(mesh=1).spotBlend)) # data
661 file.write(link+"\n")
662 if ltype == Lamp.Types["Area"]:
663 lightgroup = luxProp(obj, "light.lightgroup", "default")
664 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
665 file.write("LightGroup \"%s\"\n"%lightgroup.get())
666 file.write("\tAreaLightSource \"area\"")
668 # file.write(luxLight("", "", obj, None, 0))
670 areax = obj.getData(mesh=1).getAreaSizeX()
671 # lamps "getAreaShape()" not implemented yet - so we can't detect shape! Using square as default
673 if (True): areay = areax
674 else: areay = obj.getData(mesh=1).getAreaSizeY()
675 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})
676 if ltype == Lamp.Types["Area"]: file.write("AttributeEnd # %s\n"%obj.getName())
677 else: file.write("TransformEnd # %s\n"%obj.getName())
681 #-------------------------------------------------
682 # exportVolumes(self, file)
683 # exports volumes to the file
684 #-------------------------------------------------
685 def exportVolumes(self, file):
686 for [obj, matrix] in self.volumes:
687 print("volume: %s"%(obj.getName()))
688 file.write("# Volume: %s\n"%(obj.getName()))
690 # trickery to obtain objectspace boundingbox AABB
691 mat = obj.matrixWorld.copy().invert()
692 bb = [vec * mat for vec in obj.getBoundBox()]
693 minx = miny = minz = 100000000000000.0
694 maxx = maxy = maxz = -100000000000000.0
696 if (vec[0] < minx): minx = vec[0]
697 if (vec[1] < miny): miny = vec[1]
698 if (vec[2] < minz): minz = vec[2]
699 if (vec[0] > maxx): maxx = vec[0]
700 if (vec[1] > maxy): maxy = vec[1]
701 if (vec[2] > maxz): maxz = vec[2]
703 file.write("Transform [%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]\n"\
704 %(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],\
705 matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],\
706 matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],\
707 matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]))
709 str_opt = (" \"point p0\" [%f %f %f] \"point p1\" [%f %f %f]"%(minx, miny, minz, maxx, maxy, maxz))
710 mats = getMaterials(obj)
711 if (len(mats)>0) and (mats[0]!=None) and (luxProp(mats[0], "type", "").get()=="boundvolume"):
713 (str, link) = luxMaterialBlock("", "", "", mat, None, 0, str_opt)
714 file.write("%s"%link)
718 # Note - radiance - this is a work in progress
719 def luxFlashBlock(camObj):
721 str += "CoordSysTransform \"camera\"\n"
723 str += "Texture \"camflashtex\" \"color\" \"blackbody\" \"float temperature\" [5500.0]"
724 str += "AreaLightSource \"area\" \"texture L\" [\"camflashtex\"] \"float power\" [100.000000] \"float efficacy\" [17.000000] \"float gain\" [1.000000]\n"
728 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"
733 ######################################################
735 ######################################################
737 def save_lux(filename, unindexedname):
739 export_total_steps = 12.0
741 global meshlist, matnames, lxs_filename, geom_filename, geom_pfilename, mat_filename, mat_pfilename, vol_filename, vol_pfilename, LuxIsGUI
743 global render_status_text
745 render_status_text = 'Exporting...'
748 print("Lux Render Export started...\n")
749 time1 = Blender.sys.time()
750 scn = Scene.GetCurrent()
752 filepath = os.path.dirname(filename)
753 filebase = os.path.splitext(os.path.basename(filename))[0]
755 lxs_filename = filename
757 geom_filename = os.path.join(filepath, filebase + "-geom.lxo")
758 geom_pfilename = filebase + "-geom.lxo"
760 mat_filename = os.path.join(filepath, filebase + "-mat.lxm")
761 mat_pfilename = filebase + "-mat.lxm"
763 vol_filename = os.path.join(filepath, filebase + "-vol.lxv")
764 vol_pfilename = filebase + "-vol.lxv"
766 ### Zuegs: initialization for export class
767 export = luxExport(Blender.Scene.GetCurrent())
769 # check if a light is present
770 envtype = luxProp(scn, "env.type", "infinite").get()
771 if envtype == "sunsky":
773 for obj in scn.objects:
774 if (obj.getType() == "Lamp") and ((obj.Layers & scn.Layers) > 0):
775 if obj.getData(mesh=1).getType() == 1: # sun object # data
777 if not(export.analyseScene()) and not(envtype == "infinite") and not((envtype == "sunsky") and (sun != None)):
778 print("ERROR: No light source found")
779 Draw.PupMenu("ERROR: No light source found%t|OK%x1")
780 render_status_text = ''
781 render_status = False
782 Blender.Window.QRedrawAll()
786 if LuxIsGUI: DrawProgressBar(0.0/export_total_steps,'Setting up Scene file')
788 class output_proxy():
790 combine_all_output = False
793 if self.f is not None: self.f.close()
794 def write(self, str):
795 if self.f is not None:
799 class file_output(output_proxy):
800 def __init__(self,filename):
801 self.f = open(filename, "w")
803 from threading import Thread
804 class pipe_output(output_proxy, Thread):
805 combine_all_output = True
807 def __init__(self, xr,yr, haltspp, halttime, filename):
808 Thread.__init__(self)
810 self.filename = filename
811 self.haltspp = haltspp
812 self.halttime = halttime
816 if self.haltspp > 0 or self.halttime > 0:
817 bintype = "luxconsole"
818 self.load_result = True
820 bintype = "luxrender"
822 print("pipe: using %s" % bintype)
824 self.p = get_lux_pipe(scn, 1, bintype)
825 self.f = self.p.stdin
827 global render_status_text
830 render_status_text = "Rendering ..."
831 Blender.Window.QRedrawAll()
835 if self.load_result: self.data = self.p.communicate()[0]
837 if self.load_result: # self.load_image()
839 print("LuxRender process finished")
842 def load_image(self):
843 i = Blender.Image.Load(self.filename)
848 print("processing %i image bytes" % len(self.data))
849 i = Blender.Image.New('luxrender', self.xr, self.yr, 32)
852 raw_image.append(ord(j))
855 for y in range(self.yr-1, -1, -1):
856 for x in range(0, self.xr):
857 i.setPixelI(x,y, raw_image[bi:bi+3]+[0])
861 def update_status(self):
862 global render_status_text
864 render_status = False
865 render_status_text = "Rendering complete"
866 if self.haltspp > 0 or self.halttime > 0: render_status_text += ", check Image Editor window"
867 Blender.Window.QRedrawAll()
869 use_pipe_output = luxProp(scn, "pipe", "false").get() == "true" and luxProp(scn, "run", "true").get() == "true"
871 file = output_proxy()
873 if luxProp(scn, "lxs", "true").get()=="true" or use_pipe_output:
874 ##### Determine/open files
876 print("using pipe output")
877 print("Exporting scene to pipe")
878 xr,yr = get_render_resolution(scn)
879 file = pipe_output(xr, yr,
880 luxProp(scn, "haltspp", 0).get(),
881 luxProp(scn, "halttime", 0).get(),
882 os.path.join(filepath, filebase + ".png")
885 print("using file output")
886 print("Exporting scene to '" + filename + "'...\n")
887 file = file_output(filename)
889 ##### Write Header ######
890 file.write("# Lux Render v%s Scene File\n"%__version__)
891 file.write("# Exported by LuxBlend Blender Exporter\n")
894 ##### Write camera ######
895 camObj = scn.getCurrentCamera()
897 if LuxIsGUI: DrawProgressBar(1.0/export_total_steps,'Exporting Camera')
899 print("processing Camera...")
901 cammblur = luxProp(cam, "cammblur", "true")
902 usemblur = luxProp(cam, "usemblur", "false")
904 matrix = camObj.getMatrix()
907 if(cammblur.get() == "true" and usemblur.get() == "true"):
909 frame = Blender.Get('curframe')
910 Blender.Set('curframe', frame+1)
911 m1 = 1.0*matrix # multiply by 1.0 to get a copy of original matrix (will be frame-independant)
912 Blender.Set('curframe', frame)
914 # Motion detected, write endtransform
915 print(" motion blur")
919 target = pos + forwards
921 file.write("TransformBegin\n")
922 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] ))
923 file.write(" CoordinateSystem \"CameraEndTransform\"\n")
924 file.write("TransformEnd\n\n")
926 # Write original lookat transform
928 forwards = -matrix[2]
929 target = pos + forwards
931 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] ))
932 file.write(luxCamera(camObj.data, scn.getRenderingContext()))
934 file.write("\n \"string endtransform\" [\"CameraEndTransform\"]")
938 if LuxIsGUI: DrawProgressBar(2.0/export_total_steps,'Exporting Film Settings')
939 ##### Write film ######
940 file.write(luxFilm(scn))
943 if LuxIsGUI: DrawProgressBar(3.0/export_total_steps,'Exporting Pixel Filter')
944 ##### Write Pixel Filter ######
945 file.write(luxPixelFilter(scn))
948 if LuxIsGUI: DrawProgressBar(4.0/export_total_steps,'Exporting Sampler')
949 ##### Write Sampler ######
950 file.write(luxSampler(scn))
953 if LuxIsGUI: DrawProgressBar(5.0/export_total_steps,'Exporting Surface Integrator')
954 ##### Write Surface Integrator ######
955 file.write(luxSurfaceIntegrator(scn))
958 if LuxIsGUI: DrawProgressBar(6.0/export_total_steps,'Exporting Volume Integrator')
959 ##### Write Volume Integrator ######
960 file.write(luxVolumeIntegrator(scn))
963 if LuxIsGUI: DrawProgressBar(7.0/export_total_steps,'Exporting Accelerator')
964 ##### Write Acceleration ######
965 file.write(luxAccelerator(scn))
968 ########## BEGIN World
970 file.write("WorldBegin\n")
973 ########## World scale
974 #scale = luxProp(scn, "global.scale", 1.0).get()
976 # # TODO: not working yet !!!
977 # # TODO: propabily scale needs to be applyed on camera coords too
978 # 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))
981 if LuxIsGUI: DrawProgressBar(8.0/export_total_steps,'Exporting Environment')
982 ##### Write World Background, Sunsky or Env map ######
983 env = luxEnvironment(scn)
985 file.write("AttributeBegin\n")
987 export.exportPortals(file)
988 file.write("AttributeEnd\n")
991 # Note - radiance - this is a work in progress
992 # flash = luxFlashBlock(camObj)
994 # file.write("# Camera flash lamp\n")
995 # file.write("AttributeBegin\n")
996 # #file.write("CoordSysTransform \"camera\"\n")
998 # file.write("AttributeEnd\n\n")
1000 #### Write material & geometry file includes in scene file
1001 if not file.combine_all_output: file.write("Include \"%s\"\n\n" %(mat_pfilename))
1002 if not file.combine_all_output: file.write("Include \"%s\"\n\n" %(geom_pfilename))
1003 if not file.combine_all_output: file.write("Include \"%s\"\n\n" %(vol_pfilename))
1005 if luxProp(scn, "lxm", "true").get()=="true" or use_pipe_output:
1006 if LuxIsGUI: DrawProgressBar(9.0/export_total_steps,'Exporting Materials')
1007 ##### Write Material file #####
1008 if not file.combine_all_output: print("Exporting materials to '" + mat_filename + "'...\n")
1009 mat_file = open(mat_filename, 'w') if not file.combine_all_output else file
1011 export.exportMaterials(mat_file)
1013 if not file.combine_all_output: mat_file.close()
1015 if luxProp(scn, "lxo", "true").get()=="true" or use_pipe_output:
1016 if LuxIsGUI: DrawProgressBar(10.0/export_total_steps,'Exporting Geometry')
1017 ##### Write Geometry file #####
1018 if not file.combine_all_output: print("Exporting geometry to '" + geom_filename + "'...\n")
1019 geom_file = open(geom_filename, 'w') if not file.combine_all_output else file
1022 export.exportLights(geom_file)
1023 export.exportMeshes(geom_file)
1024 export.exportObjects(geom_file)
1026 if not file.combine_all_output: geom_file.close()
1028 if luxProp(scn, "lxv", "true").get()=="true" or use_pipe_output:
1029 if LuxIsGUI: DrawProgressBar(11.0/export_total_steps,'Exporting Volumes')
1030 ##### Write Volume file #####
1031 if not file.combine_all_output: print("Exporting volumes to '" + vol_filename + "'...\n")
1032 vol_file = open(vol_filename, 'w') if not file.combine_all_output else file
1035 export.exportVolumes(vol_file)
1037 if not file.combine_all_output: vol_file.close()
1039 render_status_text = ''
1040 render_status = False
1041 Blender.Window.QRedrawAll()
1043 if luxProp(scn, "lxs", "true").get()=="true" or use_pipe_output:
1045 file.write("WorldEnd\n\n")
1048 if LuxIsGUI: DrawProgressBar(12.0/export_total_steps,'Export Finished')
1049 print("Finished.\n")
1052 time2 = Blender.sys.time()
1053 print("Processing time: %f\n" %(time2-time1))
1056 #if luxProp(scn, "haltspp", 0).get() > 0:
1057 # Wait for piped luxconsole render thread to end
1060 # Don't launch it again as a piped scene is started implicitly
1065 ########################################################################
1066 #### Construct server string argument
1067 ########################################################################
1069 def networkstring(scn):
1071 if (luxProp(scn,"network","false").get() == "true"):
1072 if (luxProp(scn,"network_use_file","false").get() == "true"):
1073 print("read network servers from file: "+ luxProp(scn,"network_file_path","false").get())
1074 f = open(luxProp(scn,"network_file_path","false").get())
1077 print("add server :" + s)
1078 servers_string=servers_string+" -u "+ s
1081 if luxProp(scn,"network_servers","").get():
1082 for server in luxProp(scn,"network_servers","").get().split(","):
1083 servers_string=servers_string+" -u "+ server
1084 return servers_string
1087 #########################################################################
1088 ### LAUNCH LuxRender AND RENDER CURRENT SCENE
1089 #########################################################################
1091 def get_lux_exec(scn, type="luxrender"):
1093 #get blenders 'bpydata' directory
1094 datadir=Blender.Get("datadir")
1096 ic = luxProp(scn, "lux", "").get()
1097 ic = Blender.sys.dirname(ic) + os.sep + type
1099 if osys.platform == "win32": ic = ic + ".exe"
1101 if type=="luxrender" and osys.platform == "darwin": ic = ic + ".app/Contents/MacOS/luxrender"
1105 def get_lux_args(filename, extra_args=[], anim=False):
1106 ostype = osys.platform
1107 scn = Scene.GetCurrent()
1109 ic = get_lux_exec(scn, type=(anim and 'luxconsole' or 'luxrender'))
1111 servers_string = networkstring(scn)
1112 update_int=luxProp(scn,"newtork_interval",180).get()
1114 checkluxpath = luxProp(scn, "checkluxpath", True).get()
1116 if sys.exists(ic) != 1:
1117 Draw.PupMenu("Error: Lux renderer not found. Please set path on System page.%t|OK")
1119 autothreads = luxProp(scn, "autothreads", "true").get()
1120 threads = luxProp(scn, "threads", 1).get()
1121 luxnice = luxProp(scn, "luxnice", 0).get()
1122 noopengl = luxProp(scn, "noopengl", "false").get()
1124 if noopengl == "true" and not anim:
1125 extra_args.append("--noopengl")
1127 lux_args = "\"%s\" " % ic
1129 extra_args.append('%s'%servers_string)
1130 extra_args.append("-i %d " % update_int)
1132 if autothreads != "true":
1133 extra_args.append("--threads=%d " % threads)
1135 lux_args2 = ' '.join(extra_args)
1138 lux_args2 = " - " + lux_args2
1140 filename = "\"%s\"" % filename
1141 lux_args2 = lux_args2 + filename
1143 lux_args += lux_args2
1145 if ostype == "win32":
1147 if luxnice > 15: prio = "/low"
1148 elif luxnice > 5: prio = "/belownormal"
1149 elif luxnice > -5: prio = "/normal"
1150 elif luxnice > -15: prio = "/abovenormal"
1151 else: prio = "/high"
1154 cmd = "start /b %s \"\" %s" % (prio, lux_args)
1156 cmd = "start /WAIT %s \"\" %s" % (prio, lux_args)
1158 # if ostype == "linux2" or ostype == "darwin":
1161 cmd = "(nice -n %d %s)&"%(luxnice, lux_args)
1163 cmd = "(nice -n %d %s)"%(luxnice, lux_args)
1165 return cmd, lux_args2
1167 def get_lux_pipe(scn, buf = 1024, type="luxconsole"):
1168 bin = "\"%s\"" % get_lux_exec(scn, type)
1170 print("piping to lux binary: " + bin)
1172 PIPE = subprocess.PIPE
1174 cmd, raw_args = get_lux_args('-',
1175 extra_args=['-b'] if type=="luxconsole" else []
1178 # dirty hack to filter "noopengl" option from luxconsole args
1179 raw_args = raw_args.replace('--noopengl', '')
1181 return subprocess.Popen(bin + raw_args, shell=True, bufsize=buf, stdin=PIPE, stdout=PIPE, stderr=PIPE)
1183 def launchLux(filename):
1184 cmd, raw_args = get_lux_args(filename, extra_args=[])
1185 print("Running Luxrender:\n"+cmd)
1188 def launchLuxWait(filename, anim=False):
1189 ostype = osys.platform
1190 cmd, raw_args = get_lux_args(filename, extra_args=[], anim=anim)
1192 if ostype == "win32":
1195 # if ostype == "linux2" or ostype == "darwin":
1197 subprocess.call(cmd,shell=True)
1199 #### SAVE ANIMATION ####
1202 #def save_anim(filename):
1204 # scn = Scene.GetCurrent()
1205 # to = luxProp(scn, 'export.threaded', 'true').get()
1206 # run = luxProp(scn, "run", "true").get()
1207 # deflt = luxProp(scn, "default", "true").get()
1208 # if to == 'true' and run == 'true' and deflt == 'false':
1210 # anim_thread = threading.Thread(target=save_anim_real, args=(filename,True))
1211 # anim_thread.start()
1213 # save_anim_real(filename)
1215 def save_anim(filename, as_thread=False):
1216 if as_thread: print('SAR thread started')
1217 global MatSaved, LuxIsGUI
1220 startF = Blender.Get('staframe')
1221 endF = Blender.Get('endframe')
1222 scn = Scene.GetCurrent()
1224 Run = luxProp(scn, "run", "true").get()
1227 haltspp = luxProp(scn, "haltspp", 0).get()
1228 halttime = luxProp(scn, "halttime", 0).get()
1229 if haltspp == 0 and halttime == 0:
1230 Draw.PupMenu("ERROR: You must set a limit for spp (Output->halt) or for time (Output->time) when doing animation and the 'run' flag is switched on")
1235 print("\n\nRendering animation (frame %i to %i)\n\n"%(startF, endF))
1237 v_frame = Blender.Get('curframe')
1239 for i in range (startF, endF+1):
1240 # Seems to get stuck unless we redraw the UI
1242 # Window.QRedrawAll()
1243 Blender.Set('curframe', i)
1244 print("Rendering frame %i"%(i))
1246 frameindex = ("-%05d" % (i)) + ".lxs"
1247 indexedname = sys.makename(filename, frameindex)
1248 unindexedname = filename
1249 luxProp(scn, "filename", Blender.Get("filename")).set(sys.makename(filename, "-%05d" % (Blender.Get('curframe'))))
1252 if save_lux(filename, unindexedname):
1253 launchLuxWait(filename, anim=True)
1255 save_lux(indexedname, unindexedname)
1258 # Seems to get stuck unless we redraw the UI
1260 # Window.QRedrawAll()
1262 Blender.Set('curframe', v_frame)
1264 print("\n\nFinished Rendering animation\n")
1265 if as_thread: print('SAR thread finished')
1267 #### SAVE STILL (hackish...) ####
1270 #def save_still(filename):
1272 # scn = Scene.GetCurrent()
1273 # to = luxProp(scn, 'export.threaded', 'true').get()
1274 # if to == 'true' and luxProp(scn, "run", "true").get() == "true":
1276 # still_thread = threading.Thread(target=save_still_real, args=(filename,))
1277 # still_thread.start()
1279 # save_still_real(filename)
1281 def save_still(filename):
1282 global MatSaved, runRenderAfterExport
1283 scn = Scene.GetCurrent()
1284 luxProp(scn, "filename", Blender.Get("filename")).set(sys.makename(filename, ""))
1286 unindexedname = filename
1287 # Seems to get stuck unless we redraw the UI
1289 # Window.QRedrawAll()
1290 if save_lux(filename, unindexedname):
1291 if runRenderAfterExport and luxProp(scn, "pipe", "false").get() == "false": #(run == None and luxProp(scn, "run", "true").get() == "true") or run:
1294 # Seems to get stuck unless we redraw the UI
1296 # Window.QRedrawAll()
1299 ######################################################
1301 ######################################################
1303 def base64value(char):
1304 if 64 < ord(char) < 91: return ord(char)-65
1305 if 96 < ord(char) < 123: return ord(char)-97+26
1306 if 47 < ord(char) < 58: return ord(char)-48+52
1307 if char == '+': return 62
1310 def decodeIconStr(s):
1311 buf = BGL.Buffer(BGL.GL_BYTE, [16,16,4])
1316 buf[y][x][c] = int(base64value(s[offset])*4.048)
1320 def decodeLogoStr(s):
1321 buf = BGL.Buffer(BGL.GL_BYTE, [18,118,4])
1324 for x in range(118):
1326 buf[y][x][c] = int(base64value(s[offset])*4.048)
1330 def decodeArrowStr(s):
1331 buf = BGL.Buffer(BGL.GL_BYTE, [22,22,4])
1336 buf[y][x][c] = int(base64value(s[offset])*4.048)
1340 def decodeBarStr(s):
1341 buf = BGL.Buffer(BGL.GL_BYTE, [17,138,4])
1344 for x in range(138):
1346 buf[y][x][c] = int(base64value(s[offset])*4.048)
1350 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")
1352 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")
1354 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")
1357 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")
1358 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")
1359 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")
1360 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")
1361 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")
1362 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")
1363 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")
1364 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")
1365 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")
1366 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")
1367 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")
1368 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")
1369 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")
1371 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")
1373 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")
1375 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")
1377 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")
1379 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")
1381 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")
1383 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")
1385 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")
1387 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")
1390 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")
1392 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//")
1394 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")
1396 def drawIcon(icon, x, y):
1397 BGL.glEnable(BGL.GL_BLEND)
1398 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1399 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1400 BGL.glDrawPixels(16, 16, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1401 BGL.glDisable(BGL.GL_BLEND)
1403 def drawArrow(icon, x, y):
1404 BGL.glEnable(BGL.GL_BLEND)
1405 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1406 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1407 BGL.glDrawPixels(22, 22, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1408 BGL.glDisable(BGL.GL_BLEND)
1410 def drawLogo(icon, x, y):
1411 BGL.glEnable(BGL.GL_BLEND)
1412 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1413 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1414 BGL.glDrawPixels(118, 18, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1415 BGL.glDisable(BGL.GL_BLEND)
1417 def drawBar(icon, x, y):
1418 BGL.glEnable(BGL.GL_BLEND)
1419 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1420 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1421 BGL.glDrawPixels(138, 17, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, icon)
1422 BGL.glDisable(BGL.GL_BLEND)
1426 #-------------------------------------------------
1428 # helper class to handle images and icons for the GUI
1429 #-------------------------------------------------
1432 def resize(self, width, height):
1434 self.height = height
1435 self.buf = BGL.Buffer(BGL.GL_BYTE, [width,height,4]) # GL buffer
1436 def __init__(self, width=0, height=0):
1437 self.resize(width, height)
1438 def draw(self, x, y):
1439 BGL.glEnable(BGL.GL_BLEND)
1440 BGL.glBlendFunc(BGL.GL_SRC_ALPHA, BGL.GL_ONE_MINUS_SRC_ALPHA)
1441 BGL.glRasterPos2f(int(x)+0.5, int(y)+0.5)
1442 BGL.glDrawPixels(self.width, self.height, BGL.GL_RGBA, BGL.GL_UNSIGNED_BYTE, self.buf)
1443 BGL.glDisable(BGL.GL_BLEND)
1444 def decodeStr(self, width, height, s):
1445 self.resize(width, height)
1447 for y in range(self.height):
1448 for x in range(self.width):
1450 self.buf[y][x][c] = int(base64value(s[offset])*4.048)
1453 def decodeLuxConsole(self, width, height, data):
1454 self.resize(width, height)
1456 for y in range(self.height-1,-1,-1):
1457 for x in range(self.width):
1459 self.buf[y][x][c] = ord(data[offset])
1461 self.buf[y][x][3] = 255
1464 previewCache = {} # dictionary that will hold all preview images
1467 ######################################################
1469 ######################################################
1475 evtDeletePreset = 97
1476 evtSaveMaterial = 96
1477 evtLoadMaterial = 95
1478 evtDeleteMaterial = 94
1479 evtConvertMaterial = 92
1480 evtSaveMaterial2 = 91
1481 evtLoadMaterial2 = 90
1485 defaultsExclude = ['preset','filename','page','link']
1487 luxdefaults = Blender.Registry.GetKey('luxblend', True)
1488 if not(type(luxdefaults) is DictType):
1492 newluxdefaults = luxdefaults.copy()
1495 def saveluxdefaults():
1496 try: del newluxdefaults['page']
1498 try: Blender.Registry.SetKey('luxblend', newluxdefaults, True)
1505 # *** PRESETS **************************************
1506 presetsExclude = ['preset','lux','datadir','threads','filename','page','RGC','film.gamma','colorclamp','link']
1507 def getPresets(key):
1508 presets = Blender.Registry.GetKey(key, True)
1509 if not(type(presets) is DictType):
1512 def getScenePresets():
1513 presets = getPresets('luxblend_presets').copy()
1515 # radiance's hardcoded render presets:
1517 presets['0 Preview - Global Illumination'] = {
1518 'film.displayinterval': 4,
1521 'useparamkeys': 'false',
1522 'sampler.showadvanced': 'false',
1523 'sintegrator.showadvanced': 'false',
1524 'pixelfilter.showadvanced': 'false',
1526 'sampler.type': 'lowdiscrepancy',
1527 'sampler.lowdisc.pixelsamples': 1,
1528 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
1530 'sintegrator.type': 'distributedpath',
1531 'sintegrator.distributedpath.directsampleall': 'true',
1532 'sintegrator.distributedpath.directsamples': 1,
1533 'sintegrator.distributedpath.directdiffuse': 'true',
1534 'sintegrator.distributedpath.directglossy': 'true',
1535 'sintegrator.distributedpath.indirectsampleall': 'false',
1536 'sintegrator.distributedpath.indirectsamples': 1,
1537 'sintegrator.distributedpath.indirectdiffuse': 'true',
1538 'sintegrator.distributedpath.indirectglossy': 'true',
1539 'sintegrator.distributedpath.diffusereflectdepth': 1,
1540 'sintegrator.distributedpath.diffusereflectsamples': 4,
1541 'sintegrator.distributedpath.diffuserefractdepth': 4,
1542 'sintegrator.distributedpath.diffuserefractsamples': 1,
1543 'sintegrator.distributedpath.glossyreflectdepth': 1,
1544 'sintegrator.distributedpath.glossyreflectsamples': 2,
1545 'sintegrator.distributedpath.glossyrefractdepth': 4,
1546 'sintegrator.distributedpath.glossyrefractsamples': 1,
1547 'sintegrator.distributedpath.specularreflectdepth': 2,
1548 'sintegrator.distributedpath.specularrefractdepth': 4,
1549 'sintegrator.distributedpath.causticsonglossy': 'true',
1550 'sintegrator.distributedpath.causticsondiffuse': 'false',
1551 'sintegrator.distributedpath.strategy': 'auto',
1553 'pixelfilter.type': 'mitchell',
1554 'pixelfilter.mitchell.sharp': 0.250,
1555 'pixelfilter.mitchell.xwidth': 2.0,
1556 'pixelfilter.mitchell.ywidth': 2.0,
1557 'pixelfilter.mitchell.optmode': "slider" }
1559 presets['0b Preview - Direct Lighting'] = {
1560 'film.displayinterval': 4,
1563 'useparamkeys': 'false',
1564 'sampler.showadvanced': 'false',
1565 'sintegrator.showadvanced': 'false',
1566 'pixelfilter.showadvanced': 'false',
1568 'sampler.type': 'lowdiscrepancy',
1569 'sampler.lowdisc.pixelsamples': 1,
1570 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
1572 'sintegrator.type': 'directlighting',
1573 'sintegrator.dlighting.maxdepth': 5,
1575 'pixelfilter.type': 'mitchell',
1576 'pixelfilter.mitchell.sharp': 0.250,
1577 'pixelfilter.mitchell.xwidth': 2.0,
1578 'pixelfilter.mitchell.ywidth': 2.0,
1579 'pixelfilter.mitchell.optmode': "slider" }
1581 presets['1 Final - MLT/Bidir Path Tracing (interior) (recommended)'] = {
1582 'film.displayinterval': 8,
1585 'useparamkeys': 'false',
1586 'sampler.showadvanced': 'false',
1587 'sintegrator.showadvanced': 'false',
1588 'pixelfilter.showadvanced': 'false',
1590 'sampler.type': 'metropolis',
1591 'sampler.metro.strength': 0.6,
1592 'sampler.metro.lmprob': 0.4,
1593 'sampler.metro.maxrejects': 512,
1594 #'sampler.metro.initsamples': 262144,
1595 'sampler.metro.usevariance': "false",
1597 'sintegrator.type': 'bidirectional',
1598 'sintegrator.bidir.bounces': 16,
1599 'sintegrator.bidir.eyedepth': 16,
1600 'sintegrator.bidir.lightdepth': 16,
1602 'pixelfilter.type': 'mitchell',
1603 'pixelfilter.mitchell.sharp': 0.250,
1604 'pixelfilter.mitchell.xwidth': 2.0,
1605 'pixelfilter.mitchell.ywidth': 2.0,
1606 'pixelfilter.mitchell.optmode': "slider" }
1608 presets['2 Final - MLT/Path Tracing (exterior)'] = {
1609 'film.displayinterval': 8,
1612 'useparamkeys': 'false',
1613 'sampler.showadvanced': 'false',
1614 'sintegrator.showadvanced': 'false',
1615 'pixelfilter.showadvanced': 'false',
1617 'sampler.type': 'metropolis',
1618 'sampler.metro.strength': 0.6,
1619 'sampler.metro.lmprob': 0.4,
1620 'sampler.metro.maxrejects': 512,
1621 #'sampler.metro.initsamples': 262144,
1622 'sampler.metro.usevariance': "false",
1624 'sintegrator.type': 'path',
1625 'sintegrator.bidir.bounces': 10,
1626 'sintegrator.bidir.maxdepth': 10,
1628 'pixelfilter.type': 'mitchell',
1629 'pixelfilter.mitchell.sharp': 0.250,
1630 'pixelfilter.mitchell.xwidth': 2.0,
1631 'pixelfilter.mitchell.ywidth': 2.0,
1632 'pixelfilter.mitchell.optmode': "slider" }
1636 presets['5 Progressive - Bidir Path Tracing (interior)'] = {
1637 'film.displayinterval': 8,
1640 'useparamkeys': 'false',
1641 'sampler.showadvanced': 'false',
1642 'sintegrator.showadvanced': 'false',
1643 'pixelfilter.showadvanced': 'false',
1645 'sampler.type': 'lowdiscrepancy',
1646 'sampler.lowdisc.pixelsamples': 1,
1647 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
1649 'sintegrator.type': 'bidirectional',
1650 'sintegrator.bidir.bounces': 16,
1651 'sintegrator.bidir.eyedepth': 16,
1652 'sintegrator.bidir.lightdepth': 16,
1654 'pixelfilter.type': 'mitchell',
1655 'pixelfilter.mitchell.sharp': 0.250,
1656 'pixelfilter.mitchell.xwidth': 2.0,
1657 'pixelfilter.mitchell.ywidth': 2.0,
1658 'pixelfilter.mitchell.optmode': "slider" }
1660 presets['6 Progressive - Path Tracing (exterior)'] = {
1661 'film.displayinterval': 8,
1664 'useparamkeys': 'false',
1665 'sampler.showadvanced': 'false',
1666 'sintegrator.showadvanced': 'false',
1667 'pixelfilter.showadvanced': 'false',
1669 'sampler.type': 'lowdiscrepancy',
1670 'sampler.lowdisc.pixelsamples': 1,
1671 'sampler.lowdisc.pixelsampler': 'lowdiscrepancy',
1673 'sintegrator.type': 'path',
1674 'sintegrator.bidir.bounces': 10,
1675 'sintegrator.bidir.maxdepth': 10,
1677 'pixelfilter.type': 'mitchell',
1678 'pixelfilter.mitchell.sharp': 0.250,
1679 'pixelfilter.mitchell.xwidth': 2.0,
1680 'pixelfilter.mitchell.ywidth': 2.0,
1681 'pixelfilter.mitchell.optmode': "slider" }
1685 presets['8 Bucket - Bidir Path Tracing (interior)'] = {
1686 'film.displayinterval': 8,
1689 'useparamkeys': 'false',
1690 'sampler.showadvanced': 'false',
1691 'sintegrator.showadvanced': 'false',
1692 'pixelfilter.showadvanced': 'false',
1694 'sampler.type': 'lowdiscrepancy',
1695 'sampler.lowdisc.pixelsamples': 64,
1696 'sampler.lowdisc.pixelsampler': 'hilbert',
1698 'sintegrator.type': 'bidirectional',
1699 'sintegrator.bidir.bounces': 8,
1700 'sintegrator.bidir.eyedepth': 8,
1701 'sintegrator.bidir.lightdepth': 10,
1703 'pixelfilter.type': 'mitchell',
1704 'pixelfilter.mitchell.sharp': 0.250,
1705 'pixelfilter.mitchell.xwidth': 2.0,
1706 'pixelfilter.mitchell.ywidth': 2.0,
1707 'pixelfilter.mitchell.optmode': "slider" }
1709 presets['9 Bucket - Path Tracing (exterior)'] = {
1710 'film.displayinterval': 8,
1713 'useparamkeys': 'false',
1714 'sampler.showadvanced': 'false',
1715 'sintegrator.showadvanced': 'false',
1716 'pixelfilter.showadvanced': 'false',
1718 'sampler.type': 'lowdiscrepancy',
1719 'sampler.lowdisc.pixelsamples': 64,
1720 'sampler.lowdisc.pixelsampler': 'hilbert',
1722 'sintegrator.type': 'path',
1723 'sintegrator.bidir.bounces': 8,
1724 'sintegrator.bidir.maxdepth': 8,
1726 'pixelfilter.type': 'mitchell',
1727 'pixelfilter.mitchell.sharp': 0.333,
1728 'pixelfilter.mitchell.xwidth': 2.0,
1729 'pixelfilter.mitchell.ywidth': 2.0,
1730 'pixelfilter.mitchell.optmode': "slider" }
1734 presets['B Anim - Distributed/GI low Q'] = {
1735 'film.displayinterval': 8,
1738 'useparamkeys': 'false',
1739 'sampler.showadvanced': 'false',
1740 'sintegrator.showadvanced': 'false',
1741 'pixelfilter.showadvanced': 'false',
1743 'sampler.type': 'lowdiscrepancy',
1744 'sampler.lowdisc.pixelsamples': 16,
1745 'sampler.lowdisc.pixelsampler': 'hilbert',
1747 'sintegrator.type': 'distributedpath',
1748 'sintegrator.distributedpath.causticsonglossy': 'true',
1749 'sintegrator.distributedpath.diffuserefractdepth': 5,
1750 'sintegrator.distributedpath.indirectglossy': 'true',
1751 'sintegrator.distributedpath.directsamples': 1,
1752 'sintegrator.distributedpath.diffuserefractsamples': 1,
1753 'sintegrator.distributedpath.glossyreflectdepth': 2,
1754 'sintegrator.distributedpath.causticsondiffuse': 'false',
1755 'sintegrator.distributedpath.directsampleall': 'true',
1756 'sintegrator.distributedpath.indirectdiffuse': 'true',
1757 'sintegrator.distributedpath.specularreflectdepth': 3,
1758 'sintegrator.distributedpath.diffusereflectsamples': 1,
1759 'sintegrator.distributedpath.glossyreflectsamples': 1,
1760 'sintegrator.distributedpath.glossyrefractdepth': 5,
1761 'sintegrator.distributedpath.diffusereflectdepth': '2',
1762 'sintegrator.distributedpath.indirectsamples': 1,
1763 'sintegrator.distributedpath.indirectsampleall': 'false',
1764 'sintegrator.distributedpath.glossyrefractsamples': 1,
1765 'sintegrator.distributedpath.directdiffuse': 'true',
1766 'sintegrator.distributedpath.directglossy': 'true',
1767 'sintegrator.distributedpath.strategy': 'auto',
1768 'sintegrator.distributedpath.specularrefractdepth': 5,
1770 'pixelfilter.type': 'mitchell',
1771 'pixelfilter.mitchell.sharp': 0.333,
1772 'pixelfilter.mitchell.xwidth': 2.0,
1773 'pixelfilter.mitchell.ywidth': 2.0,
1774 'pixelfilter.mitchell.optmode': "slider" }
1776 presets['C Anim - Distributed/GI medium Q'] = {
1777 'film.displayinterval': 8,
1780 'useparamkeys': 'false',
1781 'sampler.showadvanced': 'false',
1782 'sintegrator.showadvanced': 'false',
1783 'pixelfilter.showadvanced': 'false',
1785 'sampler.type': 'lowdiscrepancy',
1786 'sampler.lowdisc.pixelsamples': 64,
1787 'sampler.lowdisc.pixelsampler': 'hilbert',
1789 'sintegrator.type': 'distributedpath',
1790 'sintegrator.distributedpath.causticsonglossy': 'true',
1791 'sintegrator.distributedpath.diffuserefractdepth': 5,
1792 'sintegrator.distributedpath.indirectglossy': 'true',
1793 'sintegrator.distributedpath.directsamples': 1,
1794 'sintegrator.distributedpath.diffuserefractsamples': 1,
1795 'sintegrator.distributedpath.glossyreflectdepth': 2,
1796 'sintegrator.distributedpath.causticsondiffuse': 'false',
1797 'sintegrator.distributedpath.directsampleall': 'true',
1798 'sintegrator.distributedpath.indirectdiffuse': 'true',
1799 'sintegrator.distributedpath.specularreflectdepth': 3,
1800 'sintegrator.distributedpath.diffusereflectsamples': 1,
1801 'sintegrator.distributedpath.glossyreflectsamples': 1,
1802 'sintegrator.distributedpath.glossyrefractdepth': 5,
1803 'sintegrator.distributedpath.diffusereflectdepth': '2',
1804 'sintegrator.distributedpath.indirectsamples': 1,
1805 'sintegrator.distributedpath.indirectsampleall': 'false',
1806 'sintegrator.distributedpath.glossyrefractsamples': 1,
1807 'sintegrator.distributedpath.directdiffuse': 'true',
1808 'sintegrator.distributedpath.directglossy': 'true',
1809 'sintegrator.distributedpath.strategy': 'auto',
1810 'sintegrator.distributedpath.specularrefractdepth': 5,
1812 'pixelfilter.type': 'mitchell',
1813 'pixelfilter.mitchell.sharp': 0.333,
1814 'pixelfilter.mitchell.xwidth': 2.0,
1815 'pixelfilter.mitchell.ywidth': 2.0,
1816 'pixelfilter.mitchell.optmode': "slider" }
1818 presets['D Anim - Distributed/GI high Q'] = {
1819 'film.displayinterval': 8,
1822 'useparamkeys': 'false',
1823 'sampler.showadvanced': 'false',
1824 'sintegrator.showadvanced': 'false',
1825 'pixelfilter.showadvanced': 'false',
1827 'sampler.type': 'lowdiscrepancy',
1828 'sampler.lowdisc.pixelsamples': 256,
1829 'sampler.lowdisc.pixelsampler': 'hilbert',
1831 'sintegrator.type': 'distributedpath',
1832 'sintegrator.distributedpath.causticsonglossy': 'true',
1833 'sintegrator.distributedpath.diffuserefractdepth': 5,
1834 'sintegrator.distributedpath.indirectglossy': 'true',
1835 'sintegrator.distributedpath.directsamples': 1,
1836 'sintegrator.distributedpath.diffuserefractsamples': 1,
1837 'sintegrator.distributedpath.glossyreflectdepth': 2,
1838 'sintegrator.distributedpath.causticsondiffuse': 'false',
1839 'sintegrator.distributedpath.directsampleall': 'true',
1840 'sintegrator.distributedpath.indirectdiffuse': 'true',
1841 'sintegrator.distributedpath.specularreflectdepth': 3,
1842 'sintegrator.distributedpath.diffusereflectsamples': 1,
1843 'sintegrator.distributedpath.glossyreflectsamples': 1,
1844 'sintegrator.distributedpath.glossyrefractdepth': 5,
1845 'sintegrator.distributedpath.diffusereflectdepth': '2',
1846 'sintegrator.distributedpath.indirectsamples': 1,
1847 'sintegrator.distributedpath.indirectsampleall': 'false',
1848 'sintegrator.distributedpath.glossyrefractsamples': 1,
1849 'sintegrator.distributedpath.directdiffuse': 'true',
1850 'sintegrator.distributedpath.directglossy': 'true',
1851 'sintegrator.distributedpath.strategy': 'auto',
1852 'sintegrator.distributedpath.specularrefractdepth': 5,
1854 'pixelfilter.type': 'mitchell',
1855 'pixelfilter.mitchell.sharp': 0.333,
1856 'pixelfilter.mitchell.xwidth': 2.0,
1857 'pixelfilter.mitchell.ywidth': 2.0,
1858 'pixelfilter.mitchell.optmode': "slider" }
1860 presets['E Anim - Distributed/GI very high Q'] = {
1861 'film.displayinterval': 8,
1864 'useparamkeys': 'false',
1865 'sampler.showadvanced': 'false',
1866 'sintegrator.showadvanced': 'false',
1867 'pixelfilter.showadvanced': 'false',
1869 'sampler.type': 'lowdiscrepancy',
1870 'sampler.lowdisc.pixelsamples': 512,
1871 'sampler.lowdisc.pixelsampler': 'hilbert',
1873 'sintegrator.type': 'distributedpath',
1874 'sintegrator.distributedpath.causticsonglossy': 'true',
1875 'sintegrator.distributedpath.diffuserefractdepth': 5,
1876 'sintegrator.distributedpath.indirectglossy': 'true',
1877 'sintegrator.distributedpath.directsamples': 1,
1878 'sintegrator.distributedpath.diffuserefractsamples': 1,
1879 'sintegrator.distributedpath.glossyreflectdepth': 2,
1880 'sintegrator.distributedpath.causticsondiffuse': 'false',
1881 'sintegrator.distributedpath.directsampleall': 'true',
1882 'sintegrator.distributedpath.indirectdiffuse': 'true',
1883 'sintegrator.distributedpath.specularreflectdepth': 3,
1884 'sintegrator.distributedpath.diffusereflectsamples': 1,
1885 'sintegrator.distributedpath.glossyreflectsamples': 1,
1886 'sintegrator.distributedpath.glossyrefractdepth': 5,
1887 'sintegrator.distributedpath.diffusereflectdepth': '2',
1888 'sintegrator.distributedpath.indirectsamples': 1,
1889 'sintegrator.distributedpath.indirectsampleall': 'false',
1890 'sintegrator.distributedpath.glossyrefractsamples': 1,
1891 'sintegrator.distributedpath.directdiffuse': 'true',
1892 'sintegrator.distributedpath.directglossy': 'true',
1893 'sintegrator.distributedpath.strategy': 'auto',
1894 'sintegrator.distributedpath.specularrefractdepth': 5,
1896 'pixelfilter.type': 'mitchell',
1897 'pixelfilter.mitchell.sharp': 0.333,
1898 'pixelfilter.mitchell.xwidth': 2.0,
1899 'pixelfilter.mitchell.ywidth': 2.0,
1900 'pixelfilter.mitchell.optmode': "slider" }
1904 def getMaterialPresets():
1905 return getPresets('luxblend_materials')
1907 def savePreset(key, name, d):
1909 presets = getPresets(key)
1911 presets[name] = d.copy()
1914 Blender.Registry.SetKey(key, presets, True)
1916 def saveScenePreset(name, d):
1918 for n in presetsExclude:
1921 savePreset('luxblend_presets', name, d)
1923 def saveMaterialPreset(name, d):
1925 for n in presetsExclude:
1928 savePreset('luxblend_materials', name, d)
1932 # **************************************************
1938 usedproperties = {} # global variable to collect used properties for storing presets
1939 usedpropertiesfilterobj = None # assign a object to only collect the properties that are assigned to this object
1941 # class to access properties (for lux settings)
1943 def __init__(self, obj, name, default):
1946 # if len(name)>31: print("Warning: property-name \"%s\" has more than 31 chars."%(name))
1947 self.hashmode = len(name)>31 # activate hash mode for keynames longer 31 chars (limited by blenders ID-prop)
1948 self.hashname = "__hash:%x"%(name.__hash__())
1949 self.default = default
1950 def parseassignment(self, s, name):
1952 if l[0] != name: print("Warning: property-name \"%s\" has hash-collide with \"%s\"."%(name, l[0]))
1954 def createassignment(self, name, value):
1955 return "%s = %s"%(name, value)
1957 global usedproperties, usedpropertiesfilterobj, luxdefaults
1960 value = self.obj.properties['luxblend'][self.name]
1961 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
1962 usedproperties[self.name] = value
1966 value = self.parseassignment(self.obj.properties['luxblend'][self.hashname], self.name)
1967 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
1968 usedproperties[self.name] = value
1971 if self.obj.__class__.__name__ == "Scene": # luxdefaults only for global setting
1973 value = luxdefaults[self.name]
1974 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
1975 usedproperties[self.name] = value
1978 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
1979 usedproperties[self.name] = self.default
1981 if not(usedpropertiesfilterobj) or (usedpropertiesfilterobj == self.obj):
1982 usedproperties[self.name] = self.default
1995 def set(self, value):
1996 global newluxdefaults
1998 if self.hashmode: n, v = self.hashname, self.createassignment(self.name, value)
1999 else: n, v = self.name, value
2000 if value is not None:
2001 try: self.obj.properties['luxblend'][n] = v
2002 except (KeyError, TypeError):
2003 self.obj.properties['luxblend'] = {}
2004 self.obj.properties['luxblend'][n] = v
2006 try: del self.obj.properties['luxblend'][n]
2008 if self.obj.__class__.__name__ == "Scene": # luxdefaults only for global setting
2009 # value has changed, so this are user settings, remove preset reference
2010 if not(self.name in defaultsExclude):
2011 newluxdefaults[self.name] = value
2012 try: self.obj.properties['luxblend']['preset']=""
2016 try: del self.obj.properties['luxblend'][self.name]
2018 try: del self.obj.properties['luxblend'][self.hashname]
2022 if type(v) == types.FloatType: return float(v)
2024 if type(v) == types.StringType: return float(v.split(" ")[0])
2027 if type(v) == types.FloatType: return float(v)
2029 if type(v) == types.StringType: return float(v.split(" ")[0])
2033 try: return int(self.get())
2034 except: return int(self.default)
2036 return self.getVector()
2037 def getVector(self):
2039 if type(v) in [types.FloatType, types.IntType]: return (float(v), float(v), float(v))
2042 if type(v) == types.StringType: l = self.get().split(" ")
2045 if (l==None) or (len(l) != 3): l = self.default.split(" ")
2046 return (float(l[0]), float(l[1]), float(l[2]))
2047 except AttributeError:
2048 return (float(l[0]), float(l[0]), float(l[0]))
2050 def getVectorStr(self):
2051 return "%f %f %f"%self.getVector()
2053 return type(self.get()) == types.FloatType
2056 return "%f %f %f"%(rg(col[0]), rg(col[1]),rg(col[2]))
2057 def setRGB(self, value):
2058 self.set("%f %f %f"%(value[0], value[1], value[2]))
2059 def setVector(self, value):
2060 self.set("%f %f %f"%(value[0], value[1], value[2]))
2063 # class to access blender attributes (for lux settings)
2065 def __init__(self, obj, name):
2070 return getattr(self.obj, self.name)
2074 return float(self.get())
2076 return int(self.get())
2087 def set(self, value):
2089 setattr(self.obj, self.name, value)
2093 # class for dynamic gui
2095 def __init__(self, y=200):
2096 self.x = 110 # left start position after captions
2097 self.xmax = 110+2*(140+4)
2099 self.w = 140 # default element width in pixels
2100 self.h = 18 # default element height in pixels
2104 self.resethmax = False
2105 def getRect(self, wu, hu):
2106 w = int(self.w * wu + self.xgap * (wu-1))
2107 h = int(self.h * hu + self.ygap * (hu-1))
2108 if self.x + w > self.xmax: self.newline()
2109 if self.resethmax: self.hmax = 0; self.resethmax = False
2110 rect = [int(self.x), int(self.y-h), int(w), int(h)]
2111 self.x += int(w + self.xgap)
2112 if h+self.ygap > self.hmax: self.hmax = int(h+self.ygap)
2114 def newline(self, title="", distance=0, level=0, icon=None, color=None):
2116 if not(self.resethmax): self.y -= int(self.hmax + distance)
2117 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)
2118 if icon!=None: drawIcon(icon, 2+level*10, self.y-16)
2119 self.resethmax = True
2122 BGL.glColor3f(0.9,0.9,0.9); BGL.glRasterPos2i(20+level*10,self.y-self.h+5); Draw.Text(title)
2124 def luxHelp(name, lux, caption, hint, gui, width=1.0):
2126 r = gui.getRect(width, 1)
2127 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)]))
2128 drawIcon(icon_help, r[0], r[1])
2130 return "\n \"bool %s\" [\"%s\"]"%(name, lux.get())
2132 # lux parameter types
2133 def luxOption(name, lux, options, caption, hint, gui, width=1.0):
2135 menustr = caption+": %t"
2136 for i, v in enumerate(options): menustr = "%s %%x%d|%s"%(v, i, menustr)
2138 i = options.index(lux.get())
2141 lux.set(lux.default) # not found, so try default value
2142 i = options.index(lux.get())
2144 print("value %s not found in options list"%(lux.get()))
2146 r = gui.getRect(width, 1)
2147 Draw.Menu(menustr, evtLuxGui, r[0], r[1], r[2], r[3], i, hint, lambda e,v: lux.set(options[v]))
2148 return "\n \"string %s\" [\"%s\"]"%(name, lux.get())
2150 def luxOptionRect(name, lux, options, caption, hint, gui, x, y, xx, yy):
2152 menustr = caption+": %t"
2153 for i, v in enumerate(options): menustr = "%s %%x%d|%s"%(v, i, menustr)
2155 i = options.index(lux.get())
2158 lux.set(lux.default) # not found, so try default value
2159 i = options.index(lux.get())
2161 print ("value %s not found in options list"%(lux.get()))
2163 Draw.Menu(menustr, evtLuxGui, x, y, xx, yy, i, hint, lambda e,v: lux.set(options[v]))
2164 return "\n \"string %s\" [\"%s\"]"%(name, lux.get())
2166 def luxIdentifier(name, lux, options, caption, hint, gui, icon=None, width=1.0):
2167 if gui: gui.newline(caption+":", 8, 0, icon, [0.75,0.5,0.25])
2168 luxOption(name, lux, options, caption, hint, gui, width)
2169 return "\n%s \"%s\""%(name, lux.get())
2171 def luxFloat(name, lux, min, max, caption, hint, gui, width=1.0, useslider=0):
2173 if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
2174 r = gui.getRect(width-0.12, 1)
2176 r = gui.getRect(width, 1)
2180 Draw.Slider(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, 0, hint, lambda e,v: lux.set(v))
2182 Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, hint, lambda e,v: lux.set(v))
2183 if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
2186 keyname = lux.getname()
2188 useipo = luxProp(obj, keyname+".IPOuse", "false")
2189 i = gui.getRect(0.12, 1)
2190 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)]))
2192 if useipo.get() == "true":
2193 if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
2194 curve = luxProp(obj, keyname+".IPOCurveName", "")
2195 if curve.get() == "":
2196 c = gui.getRect(2.0, 1)
2198 c = gui.getRect(1.1, 1)
2200 Draw.String("Ipo:", evtLuxGui, c[0], c[1], c[2], c[3], curve.get(), 250, "Set IPO Name", lambda e,v: curve.set(v))
2202 usemapping = luxProp(obj, keyname+".IPOmap", "false")
2205 # Apply IPO to value
2206 if curve.get() != "":
2208 ipoob = Blender.Ipo.Get(curve.get())
2212 if curve.get() != "":
2213 names = list([x[0] for x in ipoob.curveConsts.items()])
2214 ipotype = luxProp(obj, keyname+".IPOCurveType", "OB_LOCZ")
2215 luxOption("ipocurve", ipotype, names, "IPO Curve", "Set IPO Curve", gui, 0.6)
2217 icu = ipoob[eval("Blender.Ipo.%s" % (ipotype.get()))]
2218 icu_value = icu[Blender.Get('curframe')]
2219 if usemapping.get() == "false": # if true is set during mapping below
2223 m = gui.getRect(0.3, 1)
2224 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)]))
2225 if usemapping.get() == "true":
2226 if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
2227 fmin = luxProp(obj, keyname+".IPOCurvefmin", 0.0)
2228 luxFloatNoIPO("ipofmin", fmin, -100, 100, "fmin", "Map minimum value from Curve", gui, 0.5)
2229 fmax = luxProp(obj, keyname+".IPOCurvefmax", 1.0)
2230 luxFloatNoIPO("ipofmax", fmax, -100, 100, "fmax", "Map maximum value from Curve", gui, 0.5)
2231 tmin = luxProp(obj, keyname+".IPOCurvetmin", min)
2232 luxFloatNoIPO("ipotmin", tmin, min, max, "tmin", "Map miminum value to", gui, 0.5)
2233 tmax = luxProp(obj, keyname+".IPOCurvetmax", max)
2234 luxFloatNoIPO("ipotmax", tmax, min, max, "tmax", "Map maximum value to", gui, 0.5)
2236 sval = (icu_value - fmin.getFloat()) / (fmax.getFloat() - fmin.getFloat())
2237 lux.set(tmin.getFloat() + (sval * (tmax.getFloat() - tmin.getFloat())))
2240 #v = gui.getRect(0.5, 1)
2241 #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)]))
2243 if (luxProp(Scene.GetCurrent(), "useparamkeys", "false").get()=="true"):
2245 keyname = lux.getname()
2246 useipo = luxProp(obj, keyname+".IPOuse", "false")
2247 if useipo.get() == "true":
2248 curve = luxProp(obj, keyname+".IPOCurveName", "")
2250 ipoob = Blender.Ipo.Get(curve.get())
2254 usemapping = luxProp(obj, keyname+".IPOmap", "false")
2256 if curve.get() != "":
2257 names = list([x[0] for x in ipoob.curveConsts.items()])
2258 ipotype = luxProp(obj, keyname+".IPOCurveType", "OB_LOCZ")
2260 icu = ipoob[eval("Blender.Ipo.%s" % (ipotype.get()))]
2261 icu_value = icu[Blender.Get('curframe')]
2262 if usemapping.get() == "false": # if true is set during mapping below
2265 if usemapping.get() == "true":
2266 if gui: gui.newline(caption+"IPO:", 8, 0, None, [0.5,0.45,0.35])
2267 fmin = luxProp(obj, keyname+".IPOCurvefmin", 0.0)
2268 fmax = luxProp(obj, keyname+".IPOCurvefmax", 1.0)
2269 tmin = luxProp(obj, keyname+".IPOCurvetmin", min)
2270 tmax = luxProp(obj, keyname+".IPOCurvetmax", max)
2271 sval = (icu_value - fmin.getFloat()) / (fmax.getFloat() - fmin.getFloat())
2272 lux.set(tmin.getFloat() + (sval * (tmax.getFloat() - tmin.getFloat())))
2274 return "\n \"float %s\" [%f]"%(name, lux.getFloat())
2276 def luxFloatNoIPO(name, lux, min, max, caption, hint, gui, width=1.0, useslider=0):
2278 r = gui.getRect(width, 1)
2280 Draw.Slider(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, 0, hint, lambda e,v: lux.set(v))
2282 Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getFloat(), min, max, hint, lambda e,v: lux.set(v))
2283 return "\n \"float %s\" [%f]"%(name, lux.getFloat())
2287 def luxInt(name, lux, min, max, caption, hint, gui, width=1.0):
2289 r = gui.getRect(width, 1)
2290 Draw.Number(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.getInt(), min, max, hint, lambda e,v: lux.set(v))
2291 return "\n \"integer %s\" [%d]"%(name, lux.getInt())
2293 def luxBool(name, lux, caption, hint, gui, width=1.0):
2295 r = gui.getRect(width, 1)
2296 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)]))
2297 return "\n \"bool %s\" [\"%s\"]"%(name, lux.get())
2299 def luxLabel(caption, gui):
2301 r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5)
2304 def luxCollapse(name, lux, caption, hint, gui, width=1.0):
2306 r = gui.getRect(width, 1)
2307 if lux.get() == "true":
2308 drawArrow(arrow_down, r[0]-22, r[1]-2)
2310 drawArrow(arrow_right, r[0]-22, r[1]-2)
2311 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)]))
2312 return "\n \"bool %s\" [\"%s\"]"%(name, lux.get())
2314 def luxString(name, lux, caption, hint, gui, width=1.0):
2316 r = gui.getRect(width, 1)
2317 Draw.String(caption+": ", evtLuxGui, r[0], r[1], r[2], r[3], lux.get(), 250, hint, lambda e,v: lux.set(v))
2318 if lux.get()==lux.default: return ""
2319 else: return "\n \"string %s\" [\"%s\"]"%(name, luxstr(lux.get()))
2321 def luxFile(name, lux, caption, hint, gui, width=1.0):
2323 r = gui.getRect(width, 1)
2324 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))
2325 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()))
2326 return "\n \"string %s\" [\"%s\"]"%(name, luxstr(luxFilePath(lux.get())))
2328 def luxPath(name, lux, caption, hint, gui, width=1.0):
2330 r = gui.getRect(width, 1)
2331 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))
2332 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()))
2333 return "\n \"string %s\" [\"%s\"]"%(name, luxstr(lux.get()))
2335 def luxRGB(name, lux, max, caption, hint, gui, width=2.0):
2337 r = gui.getRect(width, 1)
2342 if rgb[i] > scale: scale = rgb[i]
2343 rgb = (rgb[0]/scale, rgb[1]/scale, rgb[2]/scale)
2344 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)))
2345 w = int((r[2]-r[3])/3); m = max
2347 w = int((r[2]-r[3])/4); m = 1.0
2348 drawR, drawG, drawB, drawS = Draw.Create(rgb[0]), Draw.Create(rgb[1]), Draw.Create(rgb[2]), Draw.Create(scale)
2349 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)))
2350 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)))
2351 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)))
2353 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)))
2355 return "\n \"color %s\" [%s]"%(name, lux.getRGC())
2356 return "\n \"color %s\" [%s]"%(name, lux.get())
2358 def luxVector(name, lux, min, max, caption, hint, gui, width=2.0):
2360 r = gui.getRect(width, 1)
2361 vec = lux.getVector()
2363 drawX, drawY, drawZ = Draw.Create(vec[0]), Draw.Create(vec[1]), Draw.Create(vec[2])
2364 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)))
2365 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)))
2366 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)))
2367 return "\n \"vector %s\" [%s]"%(name, lux.get())
2369 def luxVectorUniform(name, lux, min, max, caption, hint, gui, width=2.0):
2370 def setUniform(lux, value):
2371 if value: lux.set(lux.getFloat())
2372 else: lux.setVector(lux.getVector())
2374 r = gui.getRect(width, 1)
2375 vec = lux.getVector()
2376 Draw.Toggle("U", evtLuxGui, r[0], r[1], gui.h, gui.h, lux.isFloat(), "uniform", lambda e,v: setUniform(lux, v))
2378 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))
2380 w = int((r[2]-gui.h)/3)
2381 drawX, drawY, drawZ = Draw.Create(vec[0]), Draw.Create(vec[1]), Draw.Create(vec[2])
2382 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)))
2383 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)))
2384 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)))
2385 return "\n \"vector %s\" [%s]"%(name, lux.getVectorStr())
2388 # lux individual identifiers
2389 def luxCamera(cam, context, gui=None):
2390 global icon_c_camera
2393 camtype = luxProp(cam, "camera.type", "perspective")
2394 # Radiance - remarked 'realistic' for v0.6 release
2395 #str = luxIdentifier("Camera", camtype, ["perspective","orthographic","environment","realistic"], "CAMERA", "select camera type", gui, icon_c_camera)
2396 str = luxIdentifier("Camera", camtype, ["perspective","orthographic","environment"], "CAMERA", "select camera type", gui, icon_c_camera)
2398 if camtype.get() == "perspective":
2399 if gui: gui.newline(" View:")
2400 str += luxFloat("fov", luxAttr(cam, "angle"), 8.0, 170.0, "fov", "camera field-of-view angle", gui)
2401 fl = luxAttr(cam, "lens")
2403 luxFloat("lens", fl, 1.0, 250.0, "focallength", "camera focal length", gui)
2405 if camtype.get() == "orthographic" :
2406 str += luxFloat("scale", luxAttr(cam, "scale"), 0.01, 1000.0, "scale", "orthographic camera scale", gui)
2407 scale = cam.scale / 2
2408 if camtype.get() == "realistic":
2410 if gui: gui.newline(" View:")
2411 fov = luxAttr(cam, "angle")
2412 str += luxFloat("fov", fov, 8.0, 170.0, "fov", "camera field-of-view angle", gui)
2413 if gui: luxFloat("lens", luxAttr(cam, "lens"), 1.0, 250.0, "focallength", "camera focal length", gui)
2416 if gui: gui.newline()
2417 str += luxFile("specfile", luxProp(cam, "camera.realistic.specfile", ""), "spec-file", "", gui, 1.0)
2418 # if gui: gui.newline()
2419 # auto calc str += luxFloat("filmdistance", luxProp(cam, "camera.realistic.filmdistance", 70.0), 0.1, 1000.0, "film-dist", "film-distance [mm]", gui)
2420 filmdiag = luxProp(cam, "camera.realistic.filmdiag", 35.0)
2421 str += luxFloat("filmdiag", filmdiag, 0.1, 1000.0, "film-diag", "[mm]", gui)
2422 if gui: gui.newline()
2423 fstop = luxProp(cam, "camera.realistic.fstop", 1.0)
2424 luxFloat("aperture_diameter", fstop, 0.1, 100.0, "f-stop", "", gui)
2425 dofdist = luxAttr(cam, "dofDist")
2426 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)
2428 Draw.Button("S", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, "focus selected object", lambda e,v:setFocus("S"))
2429 Draw.Button("C", evtLuxGui, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "focus cursor", lambda e,v:setFocus("C"))
2430 focal = filmdiag.get()*0.001 / math.tan(fov.get() * math.pi / 360.0) / 2.0
2431 print("calculated focal length: %f mm"%(focal * 1000.0))
2432 aperture_diameter = focal / fstop.get()
2433 print("calculated aperture diameter: %f mm"%(aperture_diameter * 1000.0))
2434 str += "\n \"float aperture_diameter\" [%f]"%(aperture_diameter*1000.0)
2435 filmdistance = dofdist.get() * focal / (dofdist.get() - focal)
2436 print("calculated film distance: %f mm"%(filmdistance * 1000.0))
2437 str += "\n \"float filmdistance\" [%f]"%(filmdistance*1000.0)
2440 useclip = luxProp(cam, "useclip", "false")
2441 luxCollapse("useclip", useclip, "Near & Far Clipping", "Enable Camera near and far clipping options", gui, 2.0)
2442 if(useclip.get() == "true"):
2443 if gui: gui.newline(" Clipping:")
2444 str += luxFloat("hither", luxAttr(cam, "clipStart"), 0.0, 100.0, "start", "near clip distance", gui)
2445 str += luxFloat("yon", luxAttr(cam, "clipEnd"), 1.0, 10000.0, "end", "far clip distance", gui)
2448 usedof = luxProp(cam, "usedof", "false")
2450 if camtype.get() in ["perspective", "orthographic"]:
2451 luxCollapse("usedof", usedof, "Depth of Field & Bokeh", "Enable Depth of Field & Aperture options", gui, 2.0)
2454 if usedof.get() == "true":
2456 if gui: gui.newline(" DOF:")
2458 lr = luxProp(cam, "camera.lensradius", 0.01)
2459 fs = luxProp(cam, "camera.fstop", 2.8)
2461 if camtype.get() == "perspective":
2463 usefstop = luxProp(cam, "usefstop", "false")
2464 luxBool("usefstop", usefstop, "Use f/stop", "Use f/stop to define DOF effect", gui, 1.0)
2466 LR_SCALE = 1000.0 # lr in metres -> mm
2467 FL_SCALE = 1.0 # fl in mm -> mm
2469 def lr_2_fs(fl, lr):
2471 return fl / ( 2.0 * lr )
2473 def fs_2_lr(fl, fs):
2474 return fl / ( 2.0 * fs )
2476 if usefstop.get() == 'true':
2477 lr.set(fs_2_lr(fl.get() * FL_SCALE, fs.get()) / LR_SCALE)
2478 luxFloat("fstop", fs, 0.9, 64.0, "fstop", "Defines the lens aperture.", gui)
2479 str += luxFloat("lensradius", lr, 0.0, 1.0, "", "", None)
2481 fs.set(lr_2_fs(fl.get() * FL_SCALE, lr.get() * LR_SCALE))
2482 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)
2484 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)
2486 focustype = luxProp(cam, "camera.focustype", "autofocus")
2487 luxOption("focustype", focustype, ["autofocus", "manual", "object"], "Focus Type", "Choose the focus behaviour", gui)
2490 if focustype.get() == "autofocus":
2491 str += luxBool("autofocus",luxProp(cam, "camera.autofocus", "true"), "autofocus", "Enable automatic focus", gui)
2492 if focustype.get() == "object":
2493 objectfocus = luxProp(cam, "camera.objectfocus", "")
2494 luxString("objectfocus", objectfocus, "object", "Always focus camera on named object", gui, 1.0)
2495 dofdist = luxAttr(cam, "dofDist")
2496 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)
2497 if objectfocus.get() != "":
2499 setFocus(objectfocus.get())
2501 luxProp(cam, "camera.objectfocus", "").set("")
2502 Draw.PupMenu("WARNING: focus-object does not match existing object-name")
2503 if LuxIsGUI: Draw.Redraw()
2505 if focustype.get() == "manual":
2506 dofdist = luxAttr(cam, "dofDist")
2507 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)
2509 Draw.Button("S", evtLuxGui, gui.x, gui.y-gui.h, gui.h, gui.h, "focus selected object", lambda e,v:setFocus("S"))
2510 Draw.Button("C", evtLuxGui, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "focus cursor", lambda e,v:setFocus("C"))
2512 if camtype.get() == "perspective" and usedof.get() == "true":
2513 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)
2514 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)
2515 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)
2517 useaspect = luxProp(cam, "useaspectratio", "false")
2518 aspectratio = luxProp(cam, "ratio", 1.3333)
2519 if camtype.get() in ["perspective", "orthographic"]:
2520 useshift = luxProp(cam, "camera.useshift", "false")
2521 luxCollapse("useshift", useshift, "Architectural (Lens Shift) & Aspect Ratio", "Enable Lens Shift and Aspect Ratio options", gui, 2.0)
2522 if(useshift.get() == "true"):
2523 if gui: gui.newline(" Shift:")
2524 luxFloat("X", luxAttr(cam, "shiftX"), -2.0, 2.0, "X", "horizontal lens shift", gui)
2525 luxFloat("Y", luxAttr(cam, "shiftY"), -2.0, 2.0, "Y", "vertical lens shift", gui)
2527 if gui: gui.newline(" AspectRatio:")
2528 luxBool("useaspectratio", useaspect, "Custom", "Define a custom frame aspect ratio", gui)
2529 if useaspect.get() == "true":
2530 str += luxFloat("frameaspectratio", aspectratio, 0.0001, 3.0, "aspectratio", "Frame aspect ratio", gui)
2532 if useaspect.get() == "true":
2533 ratio = 1./aspectratio.get()
2535 ratio = float(context.sizeY)/float(context.sizeX)
2537 screenwindow = [(2*cam.shiftX-1)*scale, (2*cam.shiftX+1)*scale, (2*cam.shiftY-ratio)*scale, (2*cam.shiftY+ratio)*scale]
2539 screenwindow = [(2*cam.shiftX-1/ratio)*scale, (2*cam.shiftX+1/ratio)*scale, (2*cam.shiftY-1)*scale, (2*cam.shiftY+1)*scale]
2540 # render region option
2541 if context.borderRender:
2542 (x1,y1,x2,y2) = context.border
2543 screenwindow = [screenwindow[0]*(1-x1)+screenwindow[1]*x1, screenwindow[0]*(1-x2)+screenwindow[1]*x2,\
2544 screenwindow[2]*(1-y1)+screenwindow[3]*y1, screenwindow[2]*(1-y2)+screenwindow[3]*y2]
2545 str += "\n \"float screenwindow\" [%f %f %f %f]"%(screenwindow[0], screenwindow[1], screenwindow[2], screenwindow[3])
2547 # Note - radiance - this is a work in progress
2548 # Flash lamp option for perspective and ortho cams
2549 # if camtype.get() in ["perspective", "orthographic"]:
2550 # useflash = luxProp(cam, "useflash", "false")
2551 # luxBool("useflash", useflash, "Flash Lamp", "Enable Camera mounted flash lamp options", gui, 2.0)
2553 # Motion Blur Options (common to all cameras)
2554 usemblur = luxProp(cam, "usemblur", "false")
2555 luxCollapse("usemblur", usemblur, "Motion Blur", "Enable Motion Blur", gui, 2.0)
2556 if(usemblur.get() == "true"):
2557 if gui: gui.newline(" Shutter:")
2558 mblurpreset = luxProp(cam, "mblurpreset", "true")
2559 luxBool("mblurpreset", mblurpreset, "Preset", "Enable use of Shutter Presets", gui, 0.4)
2560 if(mblurpreset.get() == "true"):
2561 shutterpresets = ["full frame", "half frame", "quarter frame", "1/25", "1/30", "1/45", "1/60", "1/85", "1/125", "1/250", "1/500"]
2562 shutterpreset = luxProp(cam, "camera.shutterspeedpreset", "full frame")
2563 luxOption("shutterpreset", shutterpreset, shutterpresets, "shutterspeed", "Choose the Shutter speed preset.", gui, 1.0)
2565 fpspresets = ["10 FPS", "12 FPS", "20 FPS", "25 FPS", "29.99 FPS", "30 FPS", "50 FPS", "60 FPS"]
2566 shutfps = luxProp(cam, "camera.shutfps", "25 FPS")
2567 luxOption("shutfps", shutfps, fpspresets, "@", "Choose the number of frames per second as the time base.", gui, 0.6)
2569 sfps = shutfps.get()
2571 if sfps == "10 FPS": fps = 10
2572 elif sfps == "12 FPS": fps = 12
2573 elif sfps == "20 FPS": fps = 20
2574 elif sfps == "25 FPS": fps = 25
2575 elif sfps == "29.99 FPS": fps = 29.99
2576 elif sfps == "30 FPS": fps = 30
2577 elif sfps == "50 FPS": fps = 50
2578 elif sfps == "60 FPS": fps = 60
2580 spre = shutterpreset.get()
2583 if spre == "full frame": close = 1.0
2584 elif spre == "half frame": close = 0.5
2585 elif spre == "quarter frame": close = 0.25
2586 elif spre == "1/25": close = 1.0 / 25.0 * fps
2587 elif spre == "1/30": close = 1.0 / 30.0 * fps
2588 elif spre == "1/45": close = 1.0 / 45.0 * fps
2589 elif spre == "1/60": close = 1.0 / 60.0 * fps
2590 elif spre == "1/85": close = 1.0 / 85.0 * fps
2591 elif spre == "1/125": close = 1.0 / 125.0 * fps
2592 elif spre == "1/250": close = 1.0 / 250.0 * fps
2593 elif spre == "1/500": close = 1.0 / 500.0 * fps
2595 str += "\n \"float shutteropen\" [%f]\n \"float shutterclose\" [%f] "%(open,close)
2598 str += luxFloat("shutteropen", luxProp(cam, "camera.shutteropen", 0.0), 0.0, 100.0, "open", "time in seconds when shutter opens", gui, 0.8)
2599 str += luxFloat("shutterclose", luxProp(cam, "camera.shutterclose", 1.0), 0.0, 100.0, "close", "time in seconds when shutter closes", gui, 0.8)
2601 str += luxOption("shutterdistribution", luxProp(cam, "camera.shutterdistribution", "uniform"), ["uniform", "gaussian"], "distribution", "Choose the shutter sampling distribution.", gui, 2.0)
2602 objectmblur = luxProp(cam, "objectmblur", "true")
2603 luxBool("objectmblur", objectmblur, "Object", "Enable Motion Blur for scene object motions", gui, 1.0)
2604 cammblur = luxProp(cam, "cammblur", "true")
2605 luxBool("cammblur", cammblur, "Camera", "Enable Motion Blur for Camera motion", gui, 1.0)
2609 def get_render_resolution(scn, gui = None):
2610 context = scn.getRenderingContext()
2611 scale = luxProp(scn, "film.scale", "100 %")
2612 scale = int(scale.get()[:-1])
2613 xr = luxAttr(context, "sizeX").get()*scale/100
2614 yr = luxAttr(context, "sizeY").get()*scale/100
2618 def luxFilm(scn, gui=None):
2621 filmtype = luxProp(scn, "film.type", "fleximage")
2622 str = luxIdentifier("Film", filmtype, ["fleximage"], "FILM", "select film type", gui)
2623 if filmtype.get() == "fleximage":
2624 context = scn.getRenderingContext()
2626 if gui: gui.newline(" Resolution:")
2628 xr,yr = get_render_resolution(scn, gui)
2630 luxInt("xresolution", luxAttr(context, "sizeX"), 0, 8192, "X", "width of the render", gui, 0.666)
2631 luxInt("yresolution", luxAttr(context, "sizeY"), 0, 8192, "Y", "height of the render", gui, 0.666)
2632 scale = luxProp(scn, "film.scale", "100 %")
2633 luxOption("", scale, ["400 %", "200 %", "100 %", "75 %", "50 %", "25 %"], "scale", "scale resolution", gui, 0.666)
2635 # render region option
2636 if context.borderRender:
2637 (x1,y1,x2,y2) = context.border
2638 if (x1==x2) and (y1==y2): print("WARNING: empty render-region, use SHIFT-B to set render region in Blender.")
2639 str += "\n \"integer xresolution\" [%d] \n \"integer yresolution\" [%d]"%(xr*(x2-x1), yr*(y2-y1))
2641 str += "\n \"integer xresolution\" [%d] \n \"integer yresolution\" [%d]"%(xr, yr)
2643 if gui: gui.newline(" Halt:")
2644 str += luxInt("haltspp", luxProp(scn, "haltspp", 0), 0, 32768, "haltspp", "Stop rendering after specified amount of samples per pixel / 0 = never halt", gui)
2645 str += luxInt("halttime", luxProp(scn, "halttime", 0), 0, 86400, "halttime", "Stop rendering after specified number of seconds / 0 = never halt", gui)
2646 palpha = luxProp(scn, "film.premultiplyalpha", "false")
2647 str += luxBool("premultiplyalpha", palpha, "premultiplyalpha", "Pre multiply film alpha channel during normalization", gui)
2649 if gui: gui.newline(" Tonemap:")
2650 tonemapkernel = luxProp(scn, "film.tonemapkernel", "reinhard")
2651 str += luxOption("tonemapkernel", tonemapkernel, ["reinhard", "linear", "contrast", "maxwhite"], "Tonemapping Kernel", "Select the tonemapping kernel to use", gui, 2.0)
2652 if tonemapkernel.get() == "reinhard":
2653 autoywa = luxProp(scn, "film.reinhard.autoywa", "true")
2654 #str += luxBool("reinhard_autoywa", autoywa, "auto Ywa", "Automatically determine World Adaption Luminance", gui)
2655 if autoywa.get() == "false":
2656 str += luxFloat("reinhard_ywa", luxProp(scn, "film.reinhard.ywa", 0.1), 0.001, 1.0, "Ywa", "Display/World Adaption Luminance", gui)
2657 str += luxFloat("reinhard_prescale", luxProp(scn, "film.reinhard.prescale", 1.0), 0.0, 10.0, "preScale", "Image scale before tonemap operator", gui)
2658 str += luxFloat("reinhard_postscale", luxProp(scn, "film.reinhard.postscale", 1.2), 0.0, 10.0, "postScale", "Image scale after tonemap operator", gui)
2659 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)
2660 elif tonemapkernel.get() == "linear":
2661 str += luxFloat("linear_sensitivity", luxProp(scn, "film.linear.sensitivity", 50.0), 0.0, 1000.0, "sensitivity", "Adaption/Sensitivity", gui)
2662 str += luxFloat("linear_exposure", luxProp(scn, "film.linear.exposure", 1.0), 0.001, 1.0, "exposure", "Exposure duration in seconds", gui)
2663 str += luxFloat("linear_fstop", luxProp(scn, "film.linear.fstop", 2.8), 0.1, 64.0, "Fstop", "F-Stop", gui)
2664 str += luxFloat("linear_gamma", luxProp(scn, "film.linear.gamma", 1.0), 0.0, 8.0, "gamma", "Tonemap operator gamma correction", gui)
2665 elif tonemapkernel.get() == "contrast":
2666 str += luxFloat("contrast_ywa", luxProp(scn, "film.contrast.ywa", 0.1), 0.001, 1.0, "Ywa", "Display/World Adaption Luminance", gui)
2668 if gui: gui.newline(" Display:")
2669 str += luxInt("displayinterval", luxProp(scn, "film.displayinterval", 12), 4, 3600, "interval", "Set display Interval (seconds)", gui)
2671 if gui: gui.newline(" Write:")
2672 str += luxInt("writeinterval", luxProp(scn, "film.writeinterval", 120), 12, 3600, "interval", "Set display Interval (seconds)", gui)
2674 # Image File Outputs
2676 # LDR clamping method
2677 if gui: gui.newline(" Clamping:")
2678 ldrclampmethod = luxProp(scn, "film.ldr_clamp_method", "lum")
2679 str += luxOption("ldr_clamp_method", ldrclampmethod, ["lum", "hue", "cut"], "LDR clamping", "Method to clamp high luminance values for LDR output", gui, 0.5)
2680 if gui: gui.newline()
2683 saveexr = luxProp(scn, "film.write_exr", "false")
2684 str += luxCollapse("write_exr", saveexr, "OpenEXR Output", "Enable OpenEXR output", gui, 2.0)
2686 if saveexr.get() == "true":
2687 if gui: gui.newline(" OpenEXR:")
2689 exrchannels = luxProp(scn, "film.write_exr_channels", "RGBA")
2690 str += luxOption("write_exr_channels", exrchannels, ["Y", "YA", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
2691 exrres = luxProp(scn, "film.write_exr_halftype", "true")
2692 str += luxBool("write_exr_halftype", exrres, "16bit Half", "Enable 16bit Half resolution output, otherwise 32bit float", gui, 0.5)
2693 exrcompression = luxProp(scn, "film.write_exr_compression", "PIZ (lossless)")
2694 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)
2696 exrimaging = luxProp(scn, "film.write_exr_imaging", "true")
2697 str += luxBool("write_exr_applyimaging", exrimaging, "Apply Imaging/Tonemapping", "Apply Imaging and Tonemapping pipeline", gui, 1.2)
2699 if exrimaging.get()=="true":
2700 exrgamutclamp = luxProp(scn, "film.write_exr_gamutclamp", "true")
2701 str += luxBool("write_exr_gamutclamp", exrgamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 0.8)
2703 if gui: gui.newline()
2705 exrZ = luxProp(scn, "film.write_exr_Z", "true")
2706 str += luxBool("write_exr_ZBuf", exrZ, "ZBuf", "Enable Z Depth Buffer channel", gui, 0.8)
2707 if exrZ.get() == "true":
2708 exrZNormalize = luxProp(scn, "film.write_exr_ZNorm", "None")
2709 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)
2712 savepng = luxProp(scn, "film.write_png", "true")
2713 str += luxCollapse("write_png", savepng, "PNG Output", "Enable PNG (Portable Network Graphics) output", gui, 2.0)
2715 if savepng.get() == "true":
2716 if gui: gui.newline(" PNG:")
2717 pngchannels = luxProp(scn, "film.write_png_channels", "RGB")
2718 str += luxOption("write_png_channels", pngchannels, ["Y", "YA", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
2719 png16bit = luxProp(scn, "film.write_png_16bit", "false")
2720 str += luxBool("write_png_16bit", png16bit, "16bit", "Enable 16bits per channel resolution PNG output", gui, 0.5)
2721 pnggamutclamp = luxProp(scn, "film.write_png_gamutclamp", "true")
2722 str += luxBool("write_png_gamutclamp", pnggamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 1.0)
2725 #pngZ = luxProp(scn, "film.write_png_ZBuf", "false")
2726 #str += luxBool("write_png_ZBuf", pngZ, "ZBuf (Separate)", "Enable Z Depth Buffer channel", gui, 0.8)
2727 #if pngZ.get() == "true":
2728 # pngZNormalize = luxProp(scn, "film.write_png_ZNorm", "Min/Max")
2729 # 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)
2732 savetga = luxProp(scn, "film.write_tga", "false")
2733 str += luxCollapse("write_tga", savetga, "TGA Output", "Enable TGA output", gui, 2.0)
2735 if savetga.get() == "true":
2736 if gui: gui.newline(" TGA:")
2737 tgachannels = luxProp(scn, "film.write_tga_channels", "RGB")
2738 str += luxOption("write_tga_channels", tgachannels, ["Y", "RGB", "RGBA"], "Channels", "Select channels type to write", gui, 0.5)
2739 tgagamutclamp = luxProp(scn, "film.write_tga_gamutclamp", "true")
2740 str += luxBool("write_tga_gamutclamp", tgagamutclamp, "Gamut Clamp", "Clamp out of gamut (bright) pixel values", gui, 1.5)
2743 #tgaZ = luxProp(scn, "film.write_tga_ZBuf", "false")
2744 #str += luxBool("write_tga_ZBuf", tgaZ, "ZBuf (Separate)", "Enable Z Depth Buffer channel", gui, 0.8)
2745 #if tgaZ.get() == "true":
2746 # tgaZNormalize = luxProp(scn, "film.write_tga_ZNorm", "Min/Max")
2747 # 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)
2750 # override output image dir in case of command line batch mode
2751 overrideop = luxProp(scn, "overrideoutputpath", "")
2752 if overrideop.get() != "":
2753 filebase = os.path.splitext(os.path.basename(Blender.Get('filename')))[0]
2754 filename = overrideop.get() + "/" + filebase + "-%05d" % (Blender.Get('curframe'))
2755 str += "\n \"string filename\" [\"%s\"]"%(filename)
2757 fn = luxProp(scn, "filename", "default-%05d" % (Blender.Get('curframe')))
2758 str += luxString("filename", fn, "File name", "save file name", None)
2760 if gui: gui.newline(" Resume:")
2761 resumeflm = luxProp(scn, "film.write_resume_flm", "false")
2762 str += luxBool("write_resume_flm", resumeflm, "Write/Use FLM", "Write a resume fleximage .flm file, or resume rendering if it already exists", gui)
2763 restartflm = luxProp(scn, "film.restart_resume_flm", "true")
2764 str += luxBool("restart_resume_flm", restartflm, "Restart/Erase", "Restart with a black flm, even it a previous flm exists", gui)
2765 if gui: gui.newline(" Reject:")
2766 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)
2767 debugmode = luxProp(scn, "film.debug", "false")
2768 str += luxBool("debug", debugmode, "debug", "Turn on debug reporting and switch off reject", gui)
2771 if gui: gui.newline(" Colorspace:")
2773 cspaceusepreset = luxProp(scn, "film.colorspaceusepreset", "true")
2774 luxBool("colorspaceusepreset", cspaceusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
2776 # Default values for 'sRGB - HDTV (ITU-R BT.709-5)'
2777 cspacewhiteX = luxProp(scn, "film.cspacewhiteX", 0.314275)
2778 cspacewhiteY = luxProp(scn, "film.cspacewhiteY", 0.329411)
2779 cspaceredX = luxProp(scn, "film.cspaceredX", 0.63)
2780 cspaceredY = luxProp(scn, "film.cspaceredY", 0.34)
2781 cspacegreenX = luxProp(scn, "film.cspacegreenX", 0.31)
2782 cspacegreenY = luxProp(scn, "film.cspacegreenY", 0.595)
2783 cspaceblueX = luxProp(scn, "film.cspaceblueX", 0.155)
2784 cspaceblueY = luxProp(scn, "film.cspaceblueY", 0.07)
2785 gamma = luxProp(scn, "film.gamma", 2.2)
2787 if(cspaceusepreset.get() == "true"):
2789 cspace = luxProp(scn, "film.colorspace", "sRGB - HDTV (ITU-R BT.709-5)")
2790 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"]
2791 luxOption("colorspace", cspace, cspaces, "Colorspace", "select output working colorspace", gui, 1.6)
2793 if cspace.get()=="ROMM RGB":
2794 cspacewhiteX.set(0.346); cspacewhiteY.set(0.359) # D50
2795 cspaceredX.set(0.7347); cspaceredY.set(0.2653)
2796 cspacegreenX.set(0.1596); cspacegreenY.set(0.8404)
2797 cspaceblueX.set(0.0366); cspaceblueY.set(0.0001)
2798 elif cspace.get()=="Adobe RGB 98":
2799 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
2800 cspaceredX.set(0.64); cspaceredY.set(0.34)
2801 cspacegreenX.set(0.21); cspacegreenY.set(0.71)
2802 cspaceblueX.set(0.15); cspaceblueY.set(0.06)
2803 elif cspace.get()=="Apple RGB":
2804 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
2805 cspaceredX.set(0.625); cspaceredY.set(0.34)
2806 cspacegreenX.set(0.28); cspacegreenY.set(0.595)
2807 cspaceblueX.set(0.155); cspaceblueY.set(0.07)
2808 elif cspace.get()=="NTSC (FCC 1953, ITU-R BT.470-2 System M)":
2809 cspacewhiteX.set(0.310); cspacewhiteY.set(0.316) # C
2810 cspaceredX.set(0.67); cspaceredY.set(0.33)
2811 cspacegreenX.set(0.21); cspacegreenY.set(0.71)
2812 cspaceblueX.set(0.14); cspaceblueY.set(0.08)
2813 elif cspace.get()=="NTSC (1979) (SMPTE C, SMPTE-RP 145)":
2814 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
2815 cspaceredX.set(0.63); cspaceredY.set(0.34)
2816 cspacegreenX.set(0.31); cspacegreenY.set(0.595)
2817 cspaceblueX.set(0.155); cspaceblueY.set(0.07)
2818 elif cspace.get()=="PAL/SECAM (EBU 3213, ITU-R BT.470-6)":
2819 cspacewhiteX.set(0.313); cspacewhiteY.set(0.329) # D65
2820 cspaceredX.set(0.64); cspaceredY.set(0.33)
2821 cspacegreenX.set(0.29); cspacegreenY.set(0.60)
2822 cspaceblueX.set(0.15); cspaceblueY.set(0.06)
2823 elif cspace.get()=="CIE (1931) E":
2824 cspacewhiteX.set(0.333); cspacewhiteY.set(0.333) # E
2825 cspaceredX.set(0.7347); cspaceredY.set(0.2653)
2826 cspacegreenX.set(0.2738); cspacegreenY.set(0.7174)
2827 cspaceblueX.set(0.1666); cspaceblueY.set(0.0089)
2829 whitepointusecspace = luxProp(scn, "film.whitepointusecolorspace", "true")
2830 luxBool("whitepointusecolorspace", whitepointusecspace, "Colorspace Whitepoint", "Use default whitepoint for selected colorspace", gui, 1.0)
2831 gammausecspace = luxProp(scn, "film.gammausecolorspace", "true")
2832 luxBool("gammausecolorspace", gammausecspace, "Colorspace Gamma", "Use default output gamma for selected colorspace", gui, 1.0)
2834 if(whitepointusecspace.get() == "false"):
2835 if gui: gui.newline(" Whitepoint:")
2836 whitepointusepreset = luxProp(scn, "film.whitepointusepreset", "true")
2837 luxBool("whitepointusepreset", whitepointusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
2839 if(whitepointusepreset.get() == "true"):
2840 whitepointpresets = ["E", "D50", "D55", "D65", "D75", "A", "B", "C", "9300", "F2", "F7", "F11"]
2841 whitepointpreset = luxProp(scn, "film.whitepointpreset", "D65")
2842 luxOption("whitepointpreset", whitepointpreset, whitepointpresets, " PRESET", "select Whitepoint preset", gui, 1.6)
2844 if whitepointpreset.get()=="E": cspacewhiteX.set(0.333); cspacewhiteY.set(0.333)
2845 elif whitepointpreset.get()=="D50": cspacewhiteX.set(0.346); cspacewhiteY.set(0.359)
2846 elif whitepointpreset.get()=="D55": cspacewhiteX.set(0.332); cspacewhiteY.set(0.347)
2847 elif whitepointpreset.get()=="D65": cspacewhiteX.set(0.313); cspacewhiteY.set(0.329)
2848 elif whitepointpreset.get()=="D75": cspacewhiteX.set(0.299); cspacewhiteY.set(0.315)
2849 elif whitepointpreset.get()=="A": cspacewhiteX.set(0.448); cspacewhiteY.set(0.407)
2850 elif whitepointpreset.get()=="B": cspacewhiteX.set(0.348); cspacewhiteY.set(0.352)
2851 elif whitepointpreset.get()=="C": cspacewhiteX.set(0.310); cspacewhiteY.set(0.316)
2852 elif whitepointpreset.get()=="9300": cspacewhiteX.set(0.285); cspacewhiteY.set(0.293)
2853 elif whitepointpreset.get()=="F2": cspacewhiteX.set(0.372); cspacewhiteY.set(0.375)
2854 elif whitepointpreset.get()=="F7": cspacewhiteX.set(0.313); cspacewhiteY.set(0.329)
2855 elif whitepointpreset.get()=="F11": cspacewhiteX.set(0.381); cspacewhiteY.set(0.377)
2857 luxFloat("white X", cspacewhiteX, 0.0, 1.0, "white X", "Whitepoint X weight", gui, 0.8)
2858 luxFloat("white Y", cspacewhiteY, 0.0, 1.0, "white Y", "Whitepoint Y weight", gui, 0.8)
2860 if(gammausecspace.get() == "false"):
2861 if gui: gui.newline(" Gamma:")
2862 luxFloat("gamma", gamma, 0.1, 6.0, "gamma", "Output and RGC Gamma", gui, 2.0)
2865 luxFloat("white X", cspacewhiteX, 0.0, 1.0, "white X", "Whitepoint X weight", gui, 0.8)
2866 luxFloat("white Y", cspacewhiteY, 0.0, 1.0, "white Y", "Whitepoint Y weight", gui, 0.8)
2867 luxFloat("red X", cspaceredX, 0.0, 1.0, "red X", "Red component X weight", gui, 1.0)
2868 luxFloat("red Y", cspaceredY, 0.0, 1.0, "red Y", "Red component Y weight", gui, 1.0)
2869 luxFloat("green X", cspacegreenX, 0.0, 1.0, "green X", "Green component X weight", gui, 1.0)
2870 luxFloat("green Y", cspacegreenY, 0.0, 1.0, "green Y", "Green component Y weight", gui, 1.0)
2871 luxFloat("blue X", cspaceblueX, 0.0, 1.0, "blue X", "Blue component X weight", gui, 1.0)
2872 luxFloat("blue Y", cspaceblueY, 0.0, 1.0, "blue Y", "Blue component Y weight", gui, 1.0)
2873 if gui: gui.newline(" Gamma:")
2874 luxFloat("gamma", gamma, 0.1, 6.0, "gamma", "Output and RGC Gamma", gui, 2.0)
2876 str += "\n \"float colorspace_white\" [%f %f]"%(cspacewhiteX.get(), cspacewhiteY.get())
2877 str += "\n \"float colorspace_red\" [%f %f]"%(cspaceredX.get(), cspaceredY.get())
2878 str += "\n \"float colorspace_green\" [%f %f]"%(cspacegreenX.get(), cspacegreenY.get())
2879 str += "\n \"float colorspace_blue\" [%f %f]"%(cspaceblueX.get(), cspaceblueY.get())
2880 str += "\n \"float gamma\" [%f]"%(gamma.get())
2885 def luxPixelFilter(scn, gui=None):
2886 global icon_c_filter
2889 filtertype = luxProp(scn, "pixelfilter.type", "mitchell")
2890 str = luxIdentifier("PixelFilter", filtertype, ["box", "gaussian", "mitchell", "sinc", "triangle"], "FILTER", "select pixel filter type", gui, icon_c_filter)
2893 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
2894 showadvanced = luxProp(scn, "pixelfilter.showadvanced", parammodeadvanced.get())
2895 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
2897 showhelp = luxProp(scn, "pixelfilter.showhelp", "false")
2898 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
2900 if filtertype.get() == "box":
2901 if showadvanced.get()=="true":
2902 # Advanced parameters
2903 if gui: gui.newline()
2904 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)
2905 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)
2906 if filtertype.get() == "gaussian":
2907 if showadvanced.get()=="true":
2908 # Advanced parameters
2909 if gui: gui.newline()
2910 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)
2911 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)
2912 if gui: gui.newline()
2913 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)
2914 if filtertype.get() == "mitchell":
2915 if showadvanced.get()=="false":
2916 # Default parameters
2917 if gui: gui.newline("", 8, 0, None, [0.4,0.4,0.4])
2918 slidval = luxProp(scn, "pixelfilter.mitchell.sharp", 0.25)
2919 luxFloat("sharpness", slidval, 0.0, 1.0, "sharpness", "Specify amount between blurred (left) and sharp/ringed (right)", gui, 2.0, 1)
2920 # rule: B + 2*c = 1.0
2921 C = slidval.getFloat() * 0.5
2922 B = 1.0 - slidval.getFloat()
2923 str += "\n \"float B\" [%f]"%(B)
2924 str += "\n \"float C\" [%f]"%(C)
2926 if showadvanced.get()=="true":
2927 # Advanced parameters
2928 if gui: gui.newline()
2929 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)
2930 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)
2931 if gui: gui.newline()
2933 optmode = luxProp(scn, "pixelfilter.mitchell.optmode", "slider")
2934 luxOption("optmode", optmode, ["slider", "preset", "manual"], "Mode", "Mode of configuration", gui, 0.5)
2936 if(optmode.get() == "slider"):
2937 slidval = luxProp(scn, "pixelfilter.mitchell.sharp", 0.33)
2938 luxFloat("sharpness", slidval, 0.0, 1.0, "sharpness", "Specify amount between blurred (left) and sharp/ringed (right)", gui, 1.5, 1)
2939 # rule: B + 2*c = 1.0
2940 C = slidval.getFloat() * 0.5
2941 B = 1.0 - slidval.getFloat()
2942 str += "\n \"float B\" [%f]"%(B)
2943 str += "\n \"float C\" [%f]"%(C)
2944 elif(optmode.get() == "preset"):
2945 print("not implemented")
2947 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)
2948 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)
2950 if filtertype.get() == "sinc":
2951 if showadvanced.get()=="true":
2952 # Advanced parameters
2953 if gui: gui.newline()
2954 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)
2955 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)
2956 if gui: gui.newline()
2957 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)
2958 if filtertype.get() == "triangle":
2959 if showadvanced.get()=="true":
2960 # Advanced parameters
2961 if gui: gui.newline()
2962 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)
2963 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)
2966 def luxSampler(scn, gui=None):
2967 global icon_c_sampler, icon_help
2970 samplertype = luxProp(scn, "sampler.type", "metropolis")
2971 str = luxIdentifier("Sampler", samplertype, ["metropolis", "erpt", "lowdiscrepancy", "random"], "SAMPLER", "select sampler type", gui, icon_c_sampler)
2974 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
2975 showadvanced = luxProp(scn, "sampler.showadvanced", parammodeadvanced.get())
2976 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
2978 showhelp = luxProp(scn, "sampler.showhelp", "false")
2979 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
2981 if samplertype.get() == "metropolis":
2982 if showadvanced.get()=="false":
2983 # Default parameters
2984 if gui: gui.newline(" Mutation:", 8, 0, None, [0.4,0.4,0.4])
2985 strength = luxProp(scn, "sampler.metro.strength", 0.6)
2986 luxFloat("strength", strength, 0.0, 1.0, "strength", "Mutation Strength (lmprob = 1.0-strength)", gui, 2.0, 1)
2987 v = 1.0 - strength.get()
2988 str += "\n \"float largemutationprob\" [%f]"%v
2989 if showadvanced.get()=="true":
2990 # Advanced parameters
2991 if gui: gui.newline(" Mutation:")
2992 str += luxFloat("largemutationprob", luxProp(scn, "sampler.metro.lmprob", 0.4), 0.0, 1.0, "LM.prob.", "Probability of generating a large sample (mutation)", gui)
2993 str += luxInt("maxconsecrejects", luxProp(scn, "sampler.metro.maxrejects", 512), 0, 32768, "max.rejects", "number of consecutive rejects before a new mutation is forced", gui)
2994 if gui: gui.newline(" Screen:")
2995 #str += luxInt("initsamples", luxProp(scn, "sampler.metro.initsamples", 262144), 1, 1000000, "initsamples", "", gui)
2996 str += luxBool("usevariance",luxProp(scn, "sampler.metro.usevariance", "false"), "usevariance", "Accept based on variance", gui, 1.0)
2998 if showhelp.get()=="true":
2999 if gui: gui.newline(" Description:", 8, 0, icon_help, [0.4,0.5,0.56])
3000 r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5)
3001 Draw.Text("A Metropolis-Hastings mutating sampler which implements MLT", 'small')
3003 if samplertype.get() == "erpt":
3004 #str += luxInt("initsamples", luxProp(scn, "sampler.erpt.initsamples", 100000), 1, 1000000, "initsamples", "", gui)
3005 if gui: gui.newline(" Mutation:")
3006 str += luxInt("chainlength", luxProp(scn, "sampler.erpt.chainlength", 512), 1, 32768, "chainlength", "The number of mutations from a given seed", gui)
3007 if gui: gui.newline()
3008 str += luxInt("stratawidth", luxProp(scn, "sampler.erpt.stratawidth", 256), 1, 32768, "stratawidth", "The number of x/y strata for stratified sampling of seeds", gui)
3010 if samplertype.get() == "lowdiscrepancy":
3011 if gui: gui.newline(" PixelSampler:")
3012 str += luxOption("pixelsampler", luxProp(scn, "sampler.lowdisc.pixelsampler", "lowdiscrepancy"), ["linear", "tile", "random", "vegas","lowdiscrepancy","hilbert"], "pixel-sampler", "select pixel-sampler", gui)
3013 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)
3015 if samplertype.get() == "random":
3016 if gui: gui.newline(" PixelSampler:")
3017 str += luxOption("pixelsampler", luxProp(scn, "sampler.random.pixelsampler", "vegas"), ["linear", "tile", "random", "vegas","lowdiscrepancy","hilbert"], "pixel-sampler", "select pixel-sampler", gui)
3018 if gui: gui.newline()
3019 str += luxInt("pixelsamples", luxProp(scn, "sampler.random.pixelsamples", 4), 1, 512, "pixelsamples", "Allows you to specify how many samples per pixel are computed", gui)
3022 def luxSurfaceIntegrator(scn, gui=None):
3023 global icon_c_integrator
3026 integratortype = luxProp(scn, "sintegrator.type", "bidirectional")
3028 str = luxIdentifier("SurfaceIntegrator", integratortype, ["directlighting", "path", "bidirectional", "exphotonmap", "distributedpath", "igi" ], "INTEGRATOR", "select surface integrator type", gui, icon_c_integrator)
3031 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
3032 showadvanced = luxProp(scn, "sintegrator.showadvanced", parammodeadvanced.get())
3033 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
3035 showhelp = luxProp(scn, "sintegrator.showhelp", "false")
3036 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
3038 if integratortype.get() == "directlighting":
3039 if showadvanced.get()=="false":
3040 # Default parameters
3041 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
3042 str += luxInt("maxdepth", luxProp(scn, "sintegrator.dlighting.maxdepth", 8), 0, 2048, "bounces", "The maximum recursion depth for ray casting", gui, 2.0)
3044 if showadvanced.get()=="true":
3045 # Advanced parameters
3046 str += luxOption("strategy", luxProp(scn, "sintegrator.dlighting.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
3047 if gui: gui.newline(" Depth:")
3048 str += luxInt("maxdepth", luxProp(scn, "sintegrator.dlighting.maxdepth", 8), 0, 2048, "max-depth", "The maximum recursion depth for ray casting", gui)
3049 if gui: gui.newline()
3051 if integratortype.get() == "path":
3052 if showadvanced.get()=="false":
3053 # Default parameters
3054 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
3055 str += luxInt("maxdepth", luxProp(scn, "sintegrator.path.maxdepth", 10), 0, 2048, "bounces", "The maximum recursion depth for ray casting", gui, 1.0)
3056 ienv = luxProp(scn, "sintegrator.path.ienvironment", "true")
3057 str += luxBool("includeenvironment", ienv, "Include Environment", "Enable/Disable rendering of environment lightsources", gui)
3059 if showadvanced.get()=="true":
3060 # Advanced parameters
3061 if gui: gui.newline(" Depth:")
3062 str += luxInt("maxdepth", luxProp(scn, "sintegrator.path.maxdepth", 10), 0, 2048, "maxdepth", "The maximum recursion depth for ray casting", gui)
3063 str += luxOption("strategy", luxProp(scn, "sintegrator.path.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
3064 if gui: gui.newline(" RR:")
3065 rrstrat = luxProp(scn, "sintegrator.path.rrstrategy", "efficiency")
3066 str += luxOption("rrstrategy", rrstrat, ["efficiency", "probability", "none"], "RR strategy", "select Russian Roulette path termination strategy", gui)
3067 if rrstrat.get() == "probability":
3068 str += luxFloat("rrcontinueprob", luxProp(scn, "sintegrator.path.rrcontinueprob", 0.65), 0.0, 1.0, "rrprob", "Russian roulette continue probability", gui)
3069 ienv = luxProp(scn, "sintegrator.path.ienvironment", "true")
3070 str += luxBool("includeenvironment", ienv, "Include Environment", "Enable/Disable rendering of environment lightsources", gui)
3072 if integratortype.get() == "bidirectional":
3073 if showadvanced.get()=="false":
3074 # Default parameters
3075 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
3076 bounces = luxProp(scn, "sintegrator.bidir.bounces", 16)
3077 luxInt("bounces", bounces, 5, 32, "bounces", "The maximum recursion depth for ray casting (in both directions)", gui, 2.0)
3078 str += "\n \"integer eyedepth\" [%i]\n"%bounces.get()
3079 str += " \"integer lightdepth\" [%i]"%bounces.get()
3081 if showadvanced.get()=="true":
3082 # Advanced parameters
3083 if gui: gui.newline(" Depth:")
3084 str += luxInt("eyedepth", luxProp(scn, "sintegrator.bidir.eyedepth", 16), 0, 2048, "eyedepth", "The maximum recursion depth for ray casting", gui)
3085 str += luxInt("lightdepth", luxProp(scn, "sintegrator.bidir.lightdepth", 16), 0, 2048, "lightdepth", "The maximum recursion depth for light ray casting", gui)
3086 str += luxOption("strategy", luxProp(scn, "sintegrator.bidir.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
3088 str += luxFloat('eyerrthreshold', luxProp(scn, "sintegrator.bidir.eyerrthreshold", 0), 0, 1, "eyerrthreshold", "The minimum probability for russian roulette eye subpath termination ", gui)
3089 str += luxFloat('lightrrthreshold', luxProp(scn, "sintegrator.bidir.lightrrthreshold", 0), 0, 1, "lightrrthreshold", "The minimum probability for russian roulette light subpath termination ", gui)
3091 if integratortype.get() == "exphotonmap":
3092 if gui: gui.newline(" Render:")
3093 str += luxOption("renderingmode", luxProp(scn, "sintegrator.photonmap.renderingmode", "directlighting"), ["directlighting", "path"], "renderingmode", "select rendering mode", gui)
3094 str += luxOption("strategy", luxProp(scn, "sintegrator.photonmap.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
3095 str += luxInt("maxphotondepth", luxProp(scn, "sintegrator.photonmap.maxphotondepth", 10), 1, 1024, "maxphotondepth", "The maximum recursion depth of photon tracing", gui)
3096 str += luxInt("maxdepth", luxProp(scn, "sintegrator.photonmap.maxdepth", 6), 1, 1024, "maxdepth", "The maximum recursion depth of specular reflection and refraction", gui)
3097 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)
3098 str += luxInt("nused", luxProp(scn, "sintegrator.photonmap.nused", 50), 0, 1000000, "nused", "The number of photons to use in density estimation", gui)
3100 if gui: gui.newline(" Photons:")
3101 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)
3102 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)
3103 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)
3104 if gui: gui.newline(" FinalGather:")
3105 fg = luxProp(scn, "sintegrator.photonmap.fgather", "true")
3106 str += luxBool("finalgather", fg, "finalgather", "Enable use of final gather during rendering", gui)
3107 if fg.get() == "true":
3108 rrstrat = luxProp(scn, "sintegrator.photonmap.gatherrrstrategy", "efficiency")
3109 str += luxOption("gatherrrstrategy", rrstrat, ["efficiency", "probability", "none"], "RR strategy", "select Russian Roulette gather termination strategy", gui)
3110 str += luxInt("finalgathersamples", luxProp(scn, "sintegrator.photonmap.fgathers", 32), 1, 1024, "samples", "The number of finalgather samples to take per pixel during rendering", gui)
3111 str += luxFloat("gatherangle", luxProp(scn, "sintegrator.photonmap.gangle", 10.0), 0.0, 360.0, "gatherangle", "Angle for final gather", gui)
3112 if rrstrat.get() == "probability":
3113 str += luxFloat("gatherrrcontinueprob", luxProp(scn, "sintegrator.photonmap.gatherrrcontinueprob", 0.65), 0.0, 1.0, "rrcontinueprob", "Probability for russian roulette particle tracing termination", gui)
3115 if integratortype.get() == "distributedpath":
3116 str += luxOption("strategy", luxProp(scn, "sintegrator.distributedpath.strategy", "auto"), ["one", "all", "auto"], "strategy", "select directlighting strategy", gui)
3117 if gui: gui.newline(" Direct:")
3118 str += luxBool("directsampleall",luxProp(scn, "sintegrator.distributedpath.directsampleall", "true"), "Direct ALL", "Include diffuse direct light sample at first vertex", gui, 0.7)
3119 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)
3120 str += luxBool("indirectsampleall",luxProp(scn, "sintegrator.distributedpath.indirectsampleall", "false"), "Indirect ALL", "Include diffuse direct light sample at first vertex", gui, 0.7)
3121 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)
3122 if gui: gui.newline(" Diffuse:")
3123 str += luxInt("diffusereflectdepth", luxProp(scn, "sintegrator.distributedpath.diffusereflectdepth", 3), 0, 2048, "Reflect", "The maximum recursion depth for diffuse reflection ray casting", gui, 0.5)
3124 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)
3125 str += luxInt("diffuserefractdepth", luxProp(scn, "sintegrator.distributedpath.diffuserefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for diffuse refraction ray casting", gui, 0.5)
3126 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)
3127 str += luxBool("directdiffuse",luxProp(scn, "sintegrator.distributedpath.directdiffuse", "true"), "DL", "Include diffuse direct light sample at first vertex", gui, 0.20)
3128 str += luxBool("indirectdiffuse",luxProp(scn, "sintegrator.distributedpath.indirectdiffuse", "true"), "IDL", "Include diffuse indirect light sample at first vertex", gui, 0.20)
3129 if gui: gui.newline(" Glossy:")
3130 str += luxInt("glossyreflectdepth", luxProp(scn, "sintegrator.distributedpath.glossyreflectdepth", 2), 0, 2048, "Reflect", "The maximum recursion depth for glossy reflection ray casting", gui, 0.50)
3131 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)
3132 str += luxInt("glossyrefractdepth", luxProp(scn, "sintegrator.distributedpath.glossyrefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for glossy refraction ray casting", gui, 0.50)
3133 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)
3134 str += luxBool("directglossy",luxProp(scn, "sintegrator.distributedpath.directglossy", "true"), "DL", "Include glossy direct light sample at first vertex", gui, 0.20)
3135 str += luxBool("indirectglossy",luxProp(scn, "sintegrator.distributedpath.indirectglossy", "true"), "IDL", "Include glossy indirect light sample at first vertex", gui, 0.20)
3136 if gui: gui.newline(" Specular:")
3137 str += luxInt("specularreflectdepth", luxProp(scn, "sintegrator.distributedpath.specularreflectdepth", 3), 0, 2048, "Reflect", "The maximum recursion depth for specular reflection ray casting", gui, 1.0)
3138 str += luxInt("specularrefractdepth", luxProp(scn, "sintegrator.distributedpath.specularrefractdepth", 5), 0, 2048, "Refract", "The maximum recursion depth for specular refraction ray casting", gui, 1.0)
3139 #if gui: gui.newline(" Caustics:")
3140 #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)
3141 #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)
3143 usereject = luxProp(scn, "sintegrator.distributedpath.usereject", "false")
3144 luxCollapse("usereject", usereject, "Rejection", "Enable Rejection system to eliminate bright contributions", gui, 2.0)
3146 if usereject.get()=="true":
3147 if gui: gui.newline(" Diffuse:")
3149 diffusereflectreject = luxProp(scn, "sintegrator.distributedpath.difreflreject", "false")
3150 str += luxBool("diffusereflectreject", diffusereflectreject, "Reflect", "Enable Rejection for Diffuse Reflection", gui, 0.4)
3151 if diffusereflectreject.get()=="true":
3152 str += luxFloat("diffusereflectreject_threshold", luxProp(scn, "sintegrator.distributedpath.difreflrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3154 diffuserefractreject = luxProp(scn, "sintegrator.distributedpath.difrefrreject", "false")
3155 str += luxBool("diffuserefractreject", diffuserefractreject, "Refract", "Enable Rejection for Diffuse Refraction", gui, 0.4)
3156 if diffuserefractreject.get()=="true":
3157 str += luxFloat("diffuserefractreject_threshold", luxProp(scn, "sintegrator.distributedpath.difrefrrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3159 if gui: gui.newline(" Glossy:")
3161 glossyreflectreject = luxProp(scn, "sintegrator.distributedpath.glosreflreject", "false")
3162 str += luxBool("glossyreflectreject", glossyreflectreject, "Reflect", "Enable Rejection for Glossy Reflection", gui, 0.4)
3163 if glossyreflectreject.get()=="true":
3164 str += luxFloat("glossyreflectreject_threshold", luxProp(scn, "sintegrator.distributedpath.glosreflrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3166 glossyrefractreject = luxProp(scn, "sintegrator.distributedpath.glosrefrreject", "false")
3167 str += luxBool("glossyrefractreject", glossyrefractreject, "Refract", "Enable Rejection for Glossy Refraction", gui, 0.4)
3168 if glossyrefractreject.get()=="true":
3169 str += luxFloat("glossyrefractreject_threshold", luxProp(scn, "sintegrator.distributedpath.glosrefrrejectthr", 10.0), 0.01, 10.0, "Thr", "The Average Threshold to reject", gui, 0.6)
3171 if integratortype.get() == "igi":
3172 if gui: gui.newline(" Depth:", 8, 0, None, [0.4,0.4,0.4])
3173 depth = luxProp(scn, "sintegrator.igi.maxdepth", 5)
3174 luxInt("maxdepth", depth, 1, 32, "maxdepth", "The maximum recursion depth for ray casting", gui, 2.0)
3175 if showadvanced.get()=="true":
3176 # Advanced parameters
3177 if gui: gui.newline(" VLights:")
3178 str += luxInt("nsets", luxProp(scn, "sintegrator.igi.nsets", 4), 1, 100, "nsets", "The number of virtual lights sets", gui)
3179 str += luxInt("nlights", luxProp(scn, "sintegrator.igi.nlights", 64), 1, 1000, "nlights", "The number of light paths per light set", gui)
3180 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)
3185 def luxVolumeIntegrator(scn, gui=None):
3186 global icon_c_volumeintegrator
3189 integratortype = luxProp(scn, "vintegrator.type", "single")
3190 str = luxIdentifier("VolumeIntegrator", integratortype, ["emission", "single"], "VOLUME INT", "select volume integrator type", gui, icon_c_volumeintegrator)
3191 if integratortype.get() == "emission":
3192 str += luxFloat("stepsize", luxProp(scn, "vintegrator.emission.stepsize", 1.0), 0.0, 100.0, "stepsize", "Stepsize for volumes", gui)
3193 if integratortype.get() == "single":
3194 str += luxFloat("stepsize", luxProp(scn, "vintegrator.emission.stepsize", 1.0), 0.0, 100.0, "stepsize", "Stepsize for volumes", gui)
3197 def luxEnvironment(scn, gui=None):
3198 global icon_c_environment
3201 envtype = luxProp(scn, "env.type", "infinite")
3202 lsstr = luxIdentifier("LightSource", envtype, ["none", "infinite", "sunsky"], "ENVIRONMENT", "select environment light type", gui, icon_c_environment)
3203 if gui: gui.newline()
3206 if envtype.get() != "none":
3208 if envtype.get() in ["infinite", "sunsky"]:
3209 env_lg = luxProp(scn, "env.lightgroup", "default")
3210 luxString("env.lightgroup", env_lg, "lightgroup", "Environment light group", gui)
3211 if luxProp(scn, "nolg", "false").get()!="true":
3212 lsstr = '\nLightGroup "' + env_lg.get() + '"' + lsstr
3213 rotZ = luxProp(scn, "env.rotation", 0.0)
3214 rotY = luxProp(scn, "env.rotationY", 0.0)
3215 rotX = luxProp(scn, "env.rotationX", 0.0)
3216 if gui: gui.newline()
3217 luxFloat("rotation", rotX, 0.0, 360.0, "rot X", "environment rotation X", gui, 0.66)
3218 luxFloat("rotation", rotY, 0.0, 360.0, "rot Y", "environment rotation Y", gui, 0.66)
3219 luxFloat("rotation", rotZ, 0.0, 360.0, "rot Z", "environment rotation Z", gui, 0.66)
3220 if rotZ.get() != 0 or rotY.get() != 0 or rotX.get() != 0:
3221 str += "\tRotate %d 1 0 0\n"%(rotX.get())
3222 str += "\tRotate %d 0 1 0\n"%(rotY.get())
3223 str += "\tRotate %d 0 0 1\n"%(rotZ.get())
3227 if envtype.get() == "infinite":
3228 mapping = luxProp(scn, "env.infinite.mapping", "latlong")
3229 mappings = ["latlong","angular","vcross"]
3230 mapstr = luxOption("mapping", mapping, mappings, "mapping", "Select mapping type", gui, 0.5)
3231 map = luxProp(scn, "env.infinite.mapname", "")
3232 mapstr += luxFile("mapname", map, "map-file", "filename of the environment map", gui, 1.5)
3233 mapstr += luxFloat("gamma", luxProp(scn, "env.infinite.gamma", 1.0), 0.0, 6.0, "gamma", "", gui, 1.0)
3239 worldcolor = Blender.World.Get('World').getHor()
3240 str += "\n \"color L\" [%g %g %g]" %(worldcolor[0], worldcolor[1], worldcolor[2])
3243 str += luxFloat("gain", luxProp(scn, "env.infinite.gain", 1.0), 0.0001, 100.0, "gain", "Infinite Env Gain", gui, 1.0)
3245 infinitesun = luxProp(scn, "env.infinite.hassun", "false")
3246 luxCollapse("infinitesun", infinitesun, "Sun Component", "Add Sunlight Component", gui, 2.0)
3247 if(infinitesun.get() == "true"):
3248 sun_lg = luxProp(scn, "env.sun_lightgroup", "default")
3249 luxString("env.lightgroup", sun_lg, "lightgroup", "Sun component light group", gui)
3250 if luxProp(scn, "nolg", "false").get()!="true":
3251 str += '\nLightGroup "' + sun_lg.get() + '"'
3252 str += "\nLightSource \"sun\" "
3256 if envtype.get() == "sunsky" or infinitehassun == 1:
3260 for obj in scn.objects:
3261 if (obj.getType() == "Lamp") and ((obj.Layers & scn.Layers) > 0):
3262 if obj.getData(mesh=1).getType() == 1: # sun object # data
3265 str += luxFloat("gain", luxProp(scn, "env.sunsky.gain", 1.0), 0.0001, 100.0, "gain", "Sky gain", gui)
3267 invmatrix = Mathutils.Matrix(sun.getInverseMatrix())
3268 str += "\n \"vector sundir\" [%f %f %f]\n" %(invmatrix[0][2], invmatrix[1][2], invmatrix[2][2])
3269 str += luxFloat("relsize", luxProp(scn, "env.sunsky.relsize", 1.0), 0.0, 100.0, "rel.size", "relative sun size", gui)
3270 str += luxFloat("turbidity", luxProp(scn, "env.sunsky.turbidity", 2.2), 2.0, 50.0, "turbidity", "Sky turbidity", gui)
3272 showGeo = luxProp(sun, 'sc.show', 'false')
3274 luxCollapse("sc.show", showGeo, "Geographic Sun", "Set sun position by world location, date and time", gui, 2.0)
3275 if gui and showGeo.get() == 'true':
3276 gui.newline("Geographic:")
3277 sc = sun_calculator(sun)
3279 luxInt("sc.day", luxProp(sun, "sc.day", 1), 1, 31, "day", "Local date: day", gui, 0.66)
3280 luxInt("sc.month", luxProp(sun, "sc.month", 1), 1, 12, "month", "Local date: month", gui, 0.67)
3281 luxInt("sc.year", luxProp(sun, "sc.year", 2009), 1800, 2100, "year", "Local date: year", gui, 0.66)
3283 luxInt("sc.hour", luxProp(sun, "sc.hour", 0), 0, 23, "hour", "Local time: hour", gui, 0.72)
3284 luxInt("sc.minute", luxProp(sun, "sc.minute", 0), 0, 59, "minute", "Local time: minute", gui, 0.72)
3285 luxBool("sc.dst", luxProp(sun, "sc.dst", 'false'), "DST", "DST", gui, 0.28)
3286 r = gui.getRect(0.28,1)
3287 Draw.Button("NOW", 0, r[0], r[1], r[2], r[3], "Set to current time", lambda e,v: sc.now())
3289 r = gui.getRect(0.3,1)
3290 Draw.Button("Preset", 0, r[0], r[1], r[2], r[3], "Choose a preset location", lambda e,v: sc.set_location(
3291 Draw.PupTreeMenu(sun_calculator.location_list)
3294 luxFloat("sc.lat", luxProp(sun, "sc.lat", 0.0), -90.0, 90.0, "lat", "Location: latitude", gui, 0.56)
3295 luxFloat("sc.long", luxProp(sun, "sc.long", 0.0), -180.0, 180.0, "long", "Location: longitude", gui, 0.56)
3296 luxInt("sc.tz", luxProp(sun, "sc.tz", 0), -12, 12, "timezone", "Local time: timezone offset from GMT", gui, 0.56)
3298 r = gui.getRect(2,1)
3299 Draw.Button("Calculate", 0, r[0], r[1], r[2], r[3], "Calculate sun's position", lambda e,v: sc.compute())
3303 gui.newline(); r = gui.getRect(2,1); BGL.glRasterPos2i(r[0],r[1]+5)
3304 Draw.Text("create a blender Sun Lamp")
3308 #if gui: gui.newline("GLOBAL:", 8, 0, None, [0.75,0.5,0.25])
3309 #luxFloat("scale", luxProp(scn, "global.scale", 1.0), 0.0, 10.0, "scale", "global world scale", gui)
3313 class sun_calculator:
3314 #Based on SunLight v1.0 by Miguel Kabantsov (miguelkab@gmail.com)
3315 #Replaces the faulty sun position calculation algorythm with a precise calculation (Source for algorythm: http://de.wikipedia.org/wiki/Sonnenstand),
3316 #Co-Ordinates: http://www.bcca.org/misc/qiblih/latlong.html
3317 #Author: Nils-Peter Fischer (Nils-Peter.Fischer@web.de)
3335 ("Antwerp, Belgium", 67),
3336 ("Berlin, Germany", 1),
3337 ("Bratislava, Slovak Republic", 70),
3338 ("Brno, Czech Republic", 72),
3339 ("Brussles, Belgium", 68),
3340 ("Geneva, Switzerland", 65),
3341 ("Helsinki, Finland", 7),
3342 ("Innsbruck, Austria", 62),
3343 ("Kyiv, Ukraine", 64),
3344 ("London, England", 10),
3345 ("Lyon, France", 66),
3346 ("Nitra, Slovak Republic", 69),
3347 ("Oslo, Norway", 58),
3348 ("Paris, France", 15),
3349 ("Praha, Czech Republic", 71),
3350 ("Rome, Italy", 18),
3351 ("Telfs, Austria", 63),
3352 ("Warsaw, Poland", 74),
3353 ("Wroclaw, Poland", 73),
3354 ("Zurich, Switzerland", 21),
3358 ("Beijing, China", 0),
3359 ("Bombay, India", 2),
3360 ("Buenos Aires, Argentina", 3),
3361 ("Cairo, Egypt", 4),
3362 ("Cape Town, South Africa", 5),
3363 ("Caracas, Venezuela", 6),
3364 ("Curitiba, Brazil", 60),
3365 ("Hong Kong, China", 8),
3366 ("Jerusalem, Israel", 9),
3367 ("Joinville, Brazil", 61),
3368 ("Mexico City, Mexico", 11),
3369 ("Moscow, Russia", 12),
3370 ("New Delhi, India", 13),
3371 ("Ottawa, Canada", 14),
3372 ("Rio de Janeiro, Brazil", 16),
3373 ("Riyadh, Saudi Arabia", 17),
3374 ("Sao Paulo, Brazil", 59),
3375 ("Sydney, Australia", 19),
3376 ("Tokyo, Japan", 20),
3380 ("Albuquerque, NM", 22),
3381 ("Anchorage, AK", 23),
3382 ("Atlanta, GA", 24),
3384 ("Birmingham, AL", 26),
3385 ("Bismarck, ND", 27),
3387 ("Boulder, CO", 29),
3388 ("Chicago, IL", 30),
3391 ("Detroit, MI", 33),
3392 ("Honolulu, HI", 34),
3393 ("Houston, TX", 35),
3394 ("Indianapolis, IN", 36),
3395 ("Jackson, MS", 37),
3396 ("Kansas City, MO", 38),
3397 ("Los Angeles, CA", 39),
3398 ("Menomonee Falls, WI", 40),
3400 ("Minneapolis, MN", 42),
3401 ("New Orleans, LA", 43),
3402 ("New York City, NY", 44),
3403 ("Oklahoma City, OK", 45),
3404 ("Philadelphia, PA", 46),
3405 ("Phoenix, AZ", 47),
3406 ("Pittsburgh, PA", 48),
3407 ("Portland, ME", 49),
3408 ("Portland, OR", 50),
3409 ("Raleigh, NC", 51),
3410 ("Richmond, VA", 52),
3411 ("Saint Louis, MO", 53),
3412 ("San Diego, CA", 54),
3413 ("San Francisco, CA", 55),
3414 ("Seattle, WA", 56),
3415 ("Washington DC", 57),
3421 67: ( 51.2167, 4.4, 1),
3422 1: ( 52.33, 13.30, 1),
3423 70: ( 48.17, 17.17, 1),
3424 72: ( 49.2, 16.63, 1),
3425 68: ( 58.8467, 4.3525, 1),
3426 65: ( 46.217, 6.150, 1),
3427 7: ( 60.1667, 24.9667,2),
3428 62: ( 47.2672, 11.3928, 1),
3429 64: ( 50.75, 30.0833, 2),
3430 10: ( 51.50, 0.0, 0),
3431 66: ( 45.767, 4.833, 1),
3432 69: ( 48.32, 18.07, 1),
3433 58: ( 59.56, 10.41, 1),
3434 15: ( 48.8667, 2.667, 1),
3435 71: ( 50.08, 14.46, 1),
3436 18: ( 41.90, 12.4833, 1),
3437 63: ( 47.3, 11.0667, 1),
3438 74: ( 52.232, 21.008, 1),
3439 73: ( 51.108, 17.038, 1),
3440 21: ( 47.3833, 8.5333, 1),
3443 0: ( 39.9167, 116.4167, 8),
3444 2: ( 18.9333, 72.8333, 5.5),
3445 3: (-34.60, -58.45, -3),
3446 4: ( 30.10, 31.3667, 2),
3447 5: (-33.9167, 18.3667, 2),
3448 6: ( 10.50, -66.9333, -4),
3449 60: (-25.4278, -49.2731, -3),
3450 8: ( 22.25, 114.1667, 8),
3451 9: ( 31.7833, 35.2333, 2),
3452 61: (-29.3044, -48.8456, -3),
3453 11: ( 19.4, -99.15, -6),
3454 12: ( 55.75, 37.5833, 3),
3455 13: ( 28.6, 77.2, 5.5),
3456 14: ( 45.41667, -75.7, -5),
3457 16: (-22.90, -43.2333, -3),
3458 17: ( 24.633, 46.71667, 3),
3459 59: ( -23.5475, -46.6361, -3),
3460 19: (-33.8667,151.2167,10),
3461 20: ( 35.70, 139.7667, 9),
3464 22: ( 35.0833, -106.65, -7),
3465 23: ( 61.217, -149.90, -9),
3466 24: ( 33.733, -84.383, -5),
3467 25: ( 30.283, -97.733, -6),
3468 26: ( 33.521, -86.8025, -6),
3469 27: ( 46.817, -100.783, -6),
3470 28: ( 42.35, -71.05, -5),
3471 29: ( 40.125, -105.237, -7),
3472 30: ( 41.85, -87.65, -6),
3473 31: ( 32.46, -96.47, -6),
3474 32: ( 39.733, -104.983, -7),
3475 33: ( 42.333, -83.05, -5),
3476 34: ( 21.30, -157.85, -10),
3477 35: ( 29.75, -95.35, -6),
3478 36: ( 39.767, -86.15, -5),
3479 37: ( 32.283, -90.183, -6),
3480 38: ( 39.083, -94.567, -6),
3481 39: ( 34.05, -118.233, -8),
3482 40: ( 43.11, -88.10, -6),
3483 41: ( 25.767, -80.183, -5),
3484 42: ( 44.967, -93.25, -6),
3485 43: ( 29.95, -90.067, -6),
3486 44: ( 40.7167, -74.0167, -5),
3487 45: ( 35.483, -97.533, -6),
3488 46: ( 39.95, -75.15, -5),
3489 47: ( 33.433, -112.067,-7),
3490 48: ( 40.433, -79.9833, -5),
3491 49: ( 43.666, -70.283, -5),
3492 50: ( 45.517, -122.65, -8),
3493 51: ( 35.783, -78.65, -5),
3494 52: ( 37.5667, -77.450, -5),
3495 53: ( 38.6167, -90.1833, -6),
3496 54: ( 32.7667, -117.2167, -8),
3497 55: ( 37.7667, -122.4167, -8),
3498 56: ( 47.60, -122.3167, -8),
3499 57: ( 38.8833, -77.0333, -5),
3502 def __init__(self, sun):
3506 ct = time.localtime()
3513 luxProp(self.sun, 'sc.day', 0).set(ct[2])
3514 luxProp(self.sun, 'sc.month', 0).set(ct[1])
3515 luxProp(self.sun, 'sc.year', 0).set(ct[0])
3516 luxProp(self.sun, 'sc.hour', 0).set(ct[3])
3517 luxProp(self.sun, 'sc.minute', 0).set(ct[4])
3518 luxProp(self.sun, 'sc.dst', 0).set(dst)
3522 def set_location(self, location):
3523 if location < 0: return
3525 lat, long, tz = self.location_data[location]
3526 luxProp(self.sun, "sc.lat", 0).set(lat)
3527 luxProp(self.sun, "sc.long", 0).set(long)
3528 luxProp(self.sun, "sc.tz", 0).set(tz)
3534 self.lat = luxProp(self.sun, "sc.lat", 0).get()
3535 self.long = luxProp(self.sun, "sc.long", 0).get()
3536 self.tz = luxProp(self.sun, "sc.tz", 0).get()
3538 self.hour = luxProp(self.sun, "sc.hour", 0).get()
3539 self.min = luxProp(self.sun, "sc.minute", 0).get()
3540 self.dst = luxProp(self.sun, "sc.dst", 'false').get()
3541 if self.dst == 'true':
3546 self.day = luxProp(self.sun, "sc.day", 0).get()
3547 self.month = luxProp(self.sun, "sc.month", 0).get()
3548 self.year = luxProp(self.sun, "sc.year", 0).get()
3551 az,el = self.geoSunData(
3557 self.hour + self.min/60.0,
3561 self.sun.rot = math.radians(90-el), 0, math.radians(-az)
3566 # --- THE FOLLOWING METHODS ARE ADAPTED FROM LUXMAYA ---
3568 # mathematical helpers
3569 def sind(self, deg):
3570 return math.sin(math.radians(deg))
3572 def cosd(self, deg):
3573 return math.cos(math.radians(deg))
3575 def tand(self, deg):
3576 return math.tan(math.radians(deg))
3578 def asind(self, deg):
3579 return math.degrees(math.asin(deg))
3581 def atand(self, deg):
3582 return math.degrees(math.atan(deg))
3585 def geo_sun_astronomicJulianDate(self, Year, Month, Day, LocalTime, Timezone):
3587 See quoted source in class header for explanation
3597 UT = LocalTime - Timezone
3600 B = 2.0 - A+int(A/4.0)
3602 JD = math.floor(365.25*(Y+4716.0)) + math.floor(30.6001*(M+1.0)) + Day + hour + B - 1524.4
3606 def geoSunData(self, Latitude, Longitude, Year, Month, Day, LocalTime, Timezone):
3608 See quoted source in class header for explanation
3611 JD = self.geo_sun_astronomicJulianDate(Year, Month, Day, LocalTime, Timezone)
3617 LDeg = (280.460 + 0.9856474*n) - (math.floor((280.460 + 0.9856474*n)/360.0) * 360.0)
3618 gDeg = (357.528 + 0.9856003*n) - (math.floor((357.528 + 0.9856003*n)/360.0) * 360.0)
3619 LambdaDeg = LDeg + 1.915 * self.sind(gDeg) + 0.02 * self.sind(2.0*gDeg)
3621 epsilonDeg = 23.439 - 0.0000004*n
3623 alphaDeg = self.atand( (self.cosd(epsilonDeg) * self.sind(LambdaDeg)) / self.cosd(LambdaDeg) )
3624 if self.cosd(LambdaDeg) < 0.0:
3627 deltaDeg = self.asind( self.sind(epsilonDeg) * self.sind(LambdaDeg) )
3629 JDNull = self.geo_sun_astronomicJulianDate(Year, Month, Day, 0.0, 0.0)
3631 TNull = (JDNull - 2451545.0) / 36525.0
3632 T = LocalTime - Timezone
3634 thetaGh = 6.697376 + 2400.05134*TNull + 1.002738*T
3635 thetaGh -= math.floor(thetaGh/24.0) * 24.0
3637 thetaG = thetaGh * 15.0
3638 theta = thetaG + llambda
3640 tau = theta - alphaDeg
3642 a = self.atand( self.sind(tau) / ( self.cosd(tau)*self.sind(phi) - self.tand(deltaDeg)*self.cosd(phi)) )
3643 if self.cosd(tau)*self.sind(phi) - self.tand(deltaDeg)*self.cosd(phi) < 0.0:
3646 h = self.asind( self.cosd(deltaDeg)*self.cosd(tau)*self.cosd(phi) + self.sind(deltaDeg)*self.sind(phi) )
3648 R = 1.02 / (self.tand (h+(10.3/(h+5.11))))
3654 return azimuth, elevation
3656 def luxAccelerator(scn, gui=None):
3659 acceltype = luxProp(scn, "accelerator.type", "tabreckdtree")
3660 str = luxIdentifier("Accelerator", acceltype, ["none", "tabreckdtree", "grid", "bvh", "qbvh"], "ACCEL", "select accelerator type", gui)
3661 if acceltype.get() == "tabreckdtree":
3662 if gui: gui.newline()
3663 str += luxInt("intersectcost", luxProp(scn, "accelerator.kdtree.interscost", 80), 0, 1000, "inters.cost", "specifies how expensive ray-object intersections are", gui)
3664 str += luxInt("traversalcost", luxProp(scn, "accelerator.kdtree.travcost", 1), 0, 1000, "trav.cost", "specifies how expensive traversing a ray through the kdtree is", gui)
3665 if gui: gui.newline()
3666 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)
3667 if gui: gui.newline()
3668 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)
3669 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)
3670 if acceltype.get() == "unsafekdtree":
3671 if gui: gui.newline()
3672 str += luxInt("intersectcost", luxProp(scn, "accelerator.kdtree.interscost", 80), 0, 1000, "inters.cost", "specifies how expensive ray-object intersections are", gui)
3673 str += luxInt("traversalcost", luxProp(scn, "accelerator.kdtree.travcost", 1), 0, 1000, "trav.cost", "specifies how expensive traversing a ray through the kdtree is", gui)
3674 if gui: gui.newline()
3675 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)
3676 if gui: gui.newline()
3677 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)
3678 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)
3679 if acceltype.get() == "grid":
3680 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)
3681 if acceltype.get() == "qbvh":
3682 if gui: gui.newline()
3683 str += luxInt("maxprimsperleaf", luxProp(scn, "accelerator.qbvh.maxprimsperleaf", 4), 1, 64, "maxprimsperleaf", "Maximum number of primitives to leave in one leaf node", gui)
3686 def luxSystem(scn, gui=None):
3688 if gui: gui.newline("PATHS:", 10)
3689 lp = luxProp(scn, "lux", "")
3690 lp.set(Blender.sys.dirname(lp.get())+os.sep)
3691 luxPath("LUX dir", lp, "lux binary dir", "Lux installation path", gui, 2.0)
3693 # luxFile("GUI filename", luxProp(scn, "lux", ""), "lux-file", "filename and path of the lux GUI executable", gui, 2.0)
3694 # luxFile("Console filename", luxProp(scn, "luxconsole", ""), "lux-file-console", "filename and path of the lux console executable", gui, 2.0)
3695 if gui: gui.newline()
3696 luxFile("datadir", luxProp(scn, "datadir", ""), "default out dir", "default.lxs save path", gui, 2.0)
3698 if gui: gui.newline()
3699 pm = ["absolute","relative","flat"]
3700 luxOption("pathmode", luxProp(scn, "pathmode", "absolute"), pm, "path-mode", "select format for paths on export", gui, 2.0)
3702 if gui: gui.newline("PRIORITY:", 10)
3703 luxnice = luxProp(scn, "luxnice", 10)
3704 if osys.platform=="win32":
3705 r = gui.getRect(2, 1)
3706 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))
3707 else: luxInt("nice", luxnice, -20, 19, "nice", "nice value. Range goes from -20 (highest priority) to 19 (lowest)", gui)
3709 luxBool("noopengl", luxProp(scn, "noopengl", "false"), "Disable OpenGL", "(workaround for some buggy display drivers)", gui, 1.0)
3712 if gui: gui.newline("THREADS:", 10)
3713 autothreads = luxProp(scn, "autothreads", "true")
3714 luxBool("autothreads", autothreads, "Auto Detect", "Automatically use all available processors", gui, 1.0)
3715 if autothreads.get()=="false":
3716 luxInt("threads", luxProp(scn, "threads", 1), 1, 100, "threads", "number of threads used for rendering", gui, 1.0)
3717 # luxBool('export.threaded', luxProp(scn, 'export.threaded', 'true'), 'Pipe in background', 'When using pipe export, do not block Blender UI', gui, 1.0)
3719 if gui: gui.newline("ANIM:", 10)
3720 useparamkeys = luxProp(scn, "useparamkeys", "false")
3721 luxBool("useparamkeys", useparamkeys, "Enable Parameter IPO Keyframing", "Enables keyframing of luxblend parameters", gui, 2.0)
3723 if gui: gui.newline("PARAMS:", 10)
3724 parammodeadvanced = luxProp(scn, "parammodeadvanced", "false")
3725 luxBool("parammodeadvanced", parammodeadvanced, "Default Advanced Parameters", "Always use advanced parameters by default", gui, 2.0)
3727 if gui: gui.newline("PREVIEW:", 10)
3728 qs = ["low","medium","high","very high"]
3729 defprevmat = luxProp(scn, "defprevmat", "high")
3730 luxOption("defprevmat", defprevmat, qs, "Materials", "Select default preview quality in material editor for materials", gui, 1.0)
3732 if gui: gui.newline("GAMMA:", 10)
3733 luxBool("RGC", luxProp(scn, "RGC", "true"), "RGC", "use reverse gamma correction", gui)
3734 luxBool("ColClamp", luxProp(scn, "colorclamp", "false"), "ColClamp", "clamp all colors to 0.0-0.9", gui)
3735 if gui: gui.newline("MESH:", 10)
3736 luxBool("mesh_optimizing", luxProp(scn, "mesh_optimizing", "true"), "optimize meshes", "Optimize meshes during export", gui, 2.0)
3737 #luxInt("trianglemesh thr", luxProp(scn, "trianglemesh_thr", 0), 0, 10000000, "trianglemesh threshold", "Vertex threshold for exporting (wald) trianglemesh object(s)", gui, 2.0)
3738 #if gui: gui.newline()
3739 #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)
3740 if gui: gui.newline("INSTANCING:", 10)
3741 luxInt("instancing_threshold", luxProp(scn, "instancing_threshold", 2), 0, 1000000, "object instancing threshold", "Threshold to created instanced objects", gui, 2.0)
3743 # dougal2 packed images, enable this when implemented in Lux itself
3744 #if gui: gui.newline('TEXTURES:',10)
3745 #impack = luxProp(scn, 'packtextures', 'false')
3746 #luxBool('impack', impack, 'Pack All Images', '', gui, 2.0)
3749 network=luxProp(scn,"network","false")
3750 gui.newline("NETWORK:", 10)
3751 luxCollapse("network",network, "network", "enable network option", gui, 2.0)
3752 if(network.get() == "true"):
3753 network_use_file=luxProp(scn,"network_use_file","false")
3754 luxBool ("use file",network_use_file,"use file", "get list of servers from file; one per line",gui,2.0)
3755 if (network_use_file.get() == "true"):
3756 luxFile("file", luxProp(scn, "network_file_path", ""), "file", "file where servers are defined", gui, 1.0)
3759 luxString("Servers",luxProp(scn,"network_servers",""),"servers","coma separated list of servers",gui,1.0)
3761 luxInt("network_interval",luxProp(scn,"newtork_interval",180),0,9999,"update interval","interval between network refresh",gui)
3764 def scalelist(list, factor):
3765 for i in range(len(list)): list[i] = list[i] * factor
3769 def luxMapping(key, mat, gui, level=0):
3770 global icon_map2d, icon_map2dparam
3771 if gui: gui.newline("2Dmap:", -2, level, icon_map2d)
3772 mapping = luxProp(mat, key+".mapping", "uv")
3773 mappings = ["uv","spherical","cylindrical","planar"]
3774 str = luxOption("mapping", mapping, mappings, "mapping", "", gui, 0.5)
3775 if mapping.get() == "uv":
3776 if gui: gui.newline()
3777 str += luxFloat("uscale", luxProp(mat, key+".uscale", 1.0), -100.0, 100.0, "Us", "u-scale", gui, 0.5)
3778 str += luxFloat("vscale", luxProp(mat, key+".vscale", -1.0), -100.0, 100.0, "Vs", "v-scale", gui, 0.5)
3779 str += luxFloat("udelta", luxProp(mat, key+".udelta", 0.0), -100.0, 100.0, "Ud", "u-delta", gui, 0.5)
3780 str += luxFloat("vdelta", luxProp(mat, key+".vdelta", 0.0), -100.0, 100.0, "Vd", "v-delta", gui, 0.5)
3781 if mapping.get() == "planar":
3782 str += luxFloat("udelta", luxProp(mat, key+".udelta", 0.0), -100.0, 100.0, "Ud", "u-delta", gui, 0.75)
3783 str += luxFloat("vdelta", luxProp(mat, key+".vdelta", 0.0), -100.0, 100.0, "Vd", "v-delta", gui, 0.75)
3784 if gui: gui.newline("v1:", -2, level+1, icon_map2dparam)
3785 str += luxVector("v1", luxProp(mat, key+".v1", "1 0 0"), -100.0, 100.0, "v1", "v1-vector", gui, 2.0)
3786 if gui: gui.newline("v2:", -2, level+1, icon_map2dparam)
3787 str += luxVector("v2", luxProp(mat, key+".v2", "0 1 0"), -100.0, 100.0, "v2", "v2-vector", gui, 2.0)
3790 def lux3DMapping(key, mat, gui, level=0):
3791 global icon_map3dparam
3793 if gui: gui.newline("scale:", -2, level, icon_map3dparam)
3794 str += luxVectorUniform("scale", luxProp(mat, key+".3dscale", 1.0), 0.001, 1000.0, "scale", "scale-vector", gui, 2.0)
3795 if gui: gui.newline("rot:", -2, level, icon_map3dparam)
3796 str += luxVector("rotate", luxProp(mat, key+".3drotate", "0 0 0"), -360.0, 360.0, "rotate", "rotate-vector", gui, 2.0)
3797 if gui: gui.newline("move:", -2, level, icon_map3dparam)
3798 str += luxVector("translate", luxProp(mat, key+".3dtranslate", "0 0 0"), -1000.0, 1000.0, "move", "translate-vector", gui, 2.0)
3801 def getTreeNameById(tree, i): # helper function to retrive name of the selected treemenu-item
3803 if type(t)==types.TupleType:
3804 if type(t[1])==types.ListType:
3805 n=getTreeNameById(t[1], i)
3807 elif t[1]==i: return t[0]
3810 def luxTexture(name, parentkey, type, default, min, max, caption, hint, mat, gui, matlevel, texlevel=0, lightsource=0, overrideicon=""):
3811 global icon_tex, icon_texcol, icon_texmix, icon_texmixcol, icon_texparam, icon_spectex
3813 return (t1[0]+t2[0], t1[1]+t2[1])
3814 def alternativedefault(type, default):
3815 if type=="float": return 0.0
3816 else: return "0.0 0.0 0.0"
3817 level = matlevel + texlevel
3818 keyname = "%s:%s"%(parentkey, name)
3819 texname = "%s:%s"%(mat.getName(), keyname)
3820 # if gui: gui.newline(caption+":", 0, level)
3821 if(lightsource == 0):
3822 if texlevel == 0: texture = luxProp(mat, keyname+".texture", "imagemap")
3823 else: texture = luxProp(mat, keyname+".texture", "constant")
3825 texture = luxProp(mat, keyname+".texture", "blackbody")
3827 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"]
3830 if(overrideicon != ""):
3834 if texture.get() in ["mix", "scale", "checkerboard", "dots"]:
3835 if type=="color": icon = icon_texmixcol
3836 else: icon = icon_texmix
3837 elif texture.get() in ["constant", "blackbody", "equalenergy", "frequency", "gaussian", "regulardata", "irregulardata"]:
3840 if type=="color": icon = icon_texcol
3841 else: icon = icon_tex
3842 if (texlevel > 0): gui.newline(caption+":", -2, level, icon, scalelist([0.5,0.5,0.5],2.0/(level+2)))
3843 else: gui.newline("texture:", -2, level, icon, scalelist([0.5,0.5,0.5],2.0/(level+2)))
3844 luxOption("texture", texture, textures, "texture", "", gui, 2)
3845 str = "Texture \"%s\" \"%s\" \"%s\""%(texname, type, texture.get())
3847 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))
3848 if gui: # Draw Texture level Material preview
3849 luxPreview(mat, parentkey, 1, False, False, name, gui, texlevel, [0.5, 0.5, 0.5])
3850 # Add an offset for next controls
3851 #r = gui.getRect(1.0, 1)
3854 if texture.get() == "constant":
3855 value = luxProp(mat, keyname+".value", default)
3856 if type == "float": luxFloat("value", value, min, max, "", "", gui, 1.1)
3857 elif type == "color": luxRGB("value", value, max, "", "", gui, 2)
3859 if type == "color": return ("", " \"%s %s\" [%s]"%(type, name, value.getRGC()))
3860 return ("", " \"%s %s\" [%s]"%(type, name, value.get()))
3862 # if type == "color": str += " \"%s value\" [%s]"%(type, value.getRGC())
3863 # else: str += " \"%s value\" [%s]"%(type, value.get())
3865 if texture.get() == "blackbody":
3867 if gui.xmax-gui.x < gui.w: gui.newline()
3868 r = gui.getRect(1.0, 1)
3870 drawBar(bar_blackbody, gui.xmax-gui.w-7, r[1])
3871 str += luxFloat("temperature", luxProp(mat, keyname+".bbtemp", 6500.0), 1000.0, 10000.0, "temperature", "Black Body temperature in degrees Kelvin", gui, 2.0, 1)
3873 if texture.get() == "lampspectrum":
3874 lampstring = luxProp(mat, keyname+".lampstring", "Incandescent2")
3875 lamppreset = luxProp(mat, keyname+".lampspectrum", "PHILIPS [Argenta] 200W Incandescent Lamp")
3877 def setLamp(i, value, preset, tree, dict): # callback function to set ior value after selection
3880 preset.set(getTreeNameById(tree, i))
3882 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) ] ) ]
3884 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" }
3886 r = gui.getRect(2.0, 1)
3887 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))
3888 str += luxString("name", lampstring, "Lamp", "Choose measured Lamp Spectrum", None, 2.0)
3890 if texture.get() == "equalenergy":
3892 if gui.xmax-gui.x < gui.w: gui.newline()
3893 r = gui.getRect(1.0, 1)
3895 drawBar(bar_equalenergy, gui.xmax-gui.w-7, r[1])
3896 str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Energy of each spectral band", gui, 2.0, 1)
3898 if texture.get() == "frequency":
3899 str += luxFloat("freq", luxProp(mat, keyname+".freq", 0.01), 0.01, 100.0, "frequency", "Frequency in nm", gui, 2.0, 1)
3900 str += luxFloat("phase", luxProp(mat, keyname+".phase", 0.5), 0.0, 1.0, "phase", "Phase", gui, 1.1, 1)
3901 str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Amount of mean energy", gui, 0.9, 1)
3903 if texture.get() == "gaussian":
3905 if gui.xmax-gui.x < gui.w: gui.newline()
3906 r = gui.getRect(1.0, 1)
3908 drawBar(bar_spectrum, gui.xmax-gui.w-7, r[1])
3909 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)
3910 str += luxFloat("width", luxProp(mat, keyname+".width", 50.0), 20.0, 300.0, "width", "Width of gaussian distribution in nm", gui, 1.1, 1)
3911 str += luxFloat("energy", luxProp(mat, keyname+".energy", 1.0), 0.0, 1.0, "energy", "Amount of mean energy", gui, 0.9, 1)
3913 if texture.get() == "imagemap":
3914 if gui: gui.newline("IM-clip:", -2, level)
3915 str += luxOption("wrap", luxProp(mat, keyname+".wrap", "repeat"), ["repeat","black","clamp"], "repeat", "", gui, 1.0)
3917 if gui: gui.newline("IM-source:", -2, level)
3920 texturefilename = luxProp(mat, keyname+".filename", "")
3921 extimage = luxProp(mat, keyname+'.externalimage', "true")
3922 luxBool("External Image", extimage, "External Image", "External Image", gui, 1.0)
3923 if gui: gui.newline("IM-path:", -2, level)
3924 if extimage.get() == "true":
3925 luxFile("filename", texturefilename, "file", "texture file path", gui, 2.0)
3927 bil = [i.filename for i in Image.Get() if '.' in i.filename]
3929 uti = [i.filename for i in Image.Get() if '.' not in i.filename]
3931 luxLabel("INFO: Images not listed here must be saved first", gui)
3934 luxOption("Image", texturefilename, bil, "Blender Images", "Blender Image", gui, 2.0)
3936 luxLabel("No Blender Images - Load Image in the Image Editor", gui)
3937 # dougal2 image file packing
3938 impack = luxProp(Scene.GetCurrent(), 'packtextures', 'false')
3940 if impack.get() == 'false':
3941 str += luxFile("filename", texturefilename, "file", "texture file path", None, 2.0)
3944 def get_image_data(filename):
3946 f=open(filename,'rb')
3950 print('Error reading image data from %s' % filename)
3952 return base64.b64encode(zlib.compress(d))
3953 imdata = get_image_data(texturefilename.get())
3954 str += '\r\n "string imagedata" ["%s"]' % imdata
3956 useseq = luxProp(mat, keyname+".useseq", "false")
3957 luxCollapse("usesew", useseq, "Sequence", "", gui, 2.0)
3959 if useseq.get() == "true":
3960 seqframes = luxProp(mat, keyname+".seqframes", 100)
3961 luxInt("frames", seqframes, 1, 100000, "Frames", "", gui, 0.5)
3962 seqoffset = luxProp(mat, keyname+".seqoffset", 0)
3963 luxInt("offset", seqoffset, 0, 100000, "Offset", "", gui, 0.5)
3964 seqstartframe = luxProp(mat, keyname+".seqsframe", 1)
3965 luxInt("startframe", seqstartframe, 1, 100000, "StartFr", "", gui, 0.5)
3966 seqcyclic = luxProp(mat, keyname+".seqcycl", "false")
3967 luxBool("cyclic", seqcyclic, "Cyclic", "", gui, 0.5)
3970 totalframes = seqframes.get()
3971 currentframe = Blender.Get('curframe')
3973 if(currentframe < seqstartframe.get()):
3974 fnumber = 1 + seqoffset.get()
3976 fnumber = (currentframe - (seqstartframe.get()-1)) + seqoffset.get()
3978 if(fnumber > seqframes.get()):
3979 if(seqcyclic.get() == "false"):
3980 fnumber = seqframes.get()
3982 fnumber = currentframe % seqframes.get()
3985 def get_seq_filename(number, filename):
3986 m = re.findall(r'(\d+)', filename)
3988 return "ERR: Can't find pattern"
3990 rightmost_number = m[len(m)-1]
3991 seq_length = len(rightmost_number)
3994 new_seq_number = nstr.zfill(seq_length)
3996 return filename.replace(rightmost_number, new_seq_number)
3998 texturefilename.set(get_seq_filename(fnumber, texturefilename.get()))
3999 if gui: gui.newline()
4001 str += luxFloat("gamma", luxProp(mat, keyname+".gamma", texturegamma()), 0.0, 6.0, "gamma", "", gui, 0.75)
4002 str += luxFloat("gain", luxProp(mat, keyname+".gain", 1.0), 0.0, 10.0, "gain", "", gui, 0.5)
4003 filttype = luxProp(mat, keyname+".filtertype", "bilinear")
4004 filttypes = ["mipmap_ewa","mipmap_trilinear","bilinear","nearest"]
4005 str += luxOption("filtertype", filttype, filttypes, "filtertype", "Choose the filtering method to use for the image texture", gui, 0.75)
4007 if filttype.get() == "mipmap_ewa" or filttype.get() == "mipmap_trilinear":
4008 str += luxFloat("maxanisotropy", luxProp(mat, keyname+".maxanisotropy", 8.0), 1.0, 512.0, "maxaniso", "", gui, 1.0)
4009 str += luxInt("discardmipmaps", luxProp(mat, keyname+".discardmipmaps", 0), 0, 1, "discardmips", "", gui, 1.0)
4011 str += luxMapping(keyname, mat, gui, level+1)
4013 if texture.get() == "mix":
4014 (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))
4015 (s, l) = c((s, l), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4016 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4019 if texture.get() == "scale":
4020 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4021 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4024 if texture.get() == "bilerp":
4026 str += luxFloat("v00", luxProp(mat, keyname+".v00", 0.0), min, max, "v00", "", gui, 1.0)
4027 str += luxFloat("v01", luxProp(mat, keyname+".v01", 1.0), min, max, "v01", "", gui, 1.0)
4028 if gui: gui.newline("", -2)
4029 str += luxFloat("v10", luxProp(mat, keyname+".v10", 0.0), min, max, "v10", "", gui, 1.0)
4030 str += luxFloat("v11", luxProp(mat, keyname+".v11", 1.0), min, max, "v11", "", gui, 1.0)
4031 elif type == "color":
4032 if gui: gui.newline(" v00:", -2)
4033 str += luxRGB("v00", luxProp(mat, keyname+".v00", "0.0 0.0 0.0"), max, "v00", "", gui, 2.0)
4034 if gui: gui.newline(" v01:", -2)
4035 str += luxRGB("v01", luxProp(mat, keyname+".v01", "1.0 1.0 1.0"), max, "v01", "", gui, 2.0)
4036 if gui: gui.newline(" v10:", -2)
4037 str += luxRGB("v10", luxProp(mat, keyname+".v10", "0.0 0.0 0.0"), max, "v10", "", gui, 2.0)
4038 if gui: gui.newline(" v11:", -2)
4039 str += luxRGB("v11", luxProp(mat, keyname+".v11", "1.0 1.0 1.0"), max, "v11", "", gui, 2.0)
4040 str += luxMapping(keyname, mat, gui, level+1)
4042 if texture.get() == "windy":
4043 str += lux3DMapping(keyname, mat, gui, level+1)
4044 # this texture has no options
4046 if texture.get() == "checkerboard":
4047 dim = luxProp(mat, keyname+".dim", 2)
4048 str += luxInt("dimension", dim, 2, 3, "dim", "", gui, 1)
4049 if dim.get() == 2: str += luxOption("aamode", luxProp(mat, keyname+".aamode", "closedform"), ["closedform","supersample","none"], "aamode", "antialiasing mode", gui, 0.6)
4050 if gui: gui.newline("", -2)
4051 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4052 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4054 if dim.get() == 2: str += luxMapping(keyname, mat, gui, level+1)
4055 if dim.get() == 3: str += lux3DMapping(keyname, mat, gui, level+1)
4057 if texture.get() == "dots":
4058 (s, l) = c(("", ""), luxTexture("inside", keyname, type, default, min, max, "inside", "", mat, gui, matlevel, texlevel+1, lightsource))
4059 (s, l) = c((s, l), luxTexture("outside", keyname, type, alternativedefault(type, default), min, max, "outside", "", mat, gui, matlevel, texlevel+1, lightsource))
4061 str += luxMapping(keyname, mat, gui, level+1)
4063 if texture.get() == "fbm":
4064 str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1)
4065 # if gui: gui.newline("", -2)
4066 str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 1, 1)
4067 if gui: gui.newline("", -2)
4068 str += lux3DMapping(keyname, mat, gui, level+1)
4070 if texture.get() == "marble":
4071 str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1)
4072 # if gui: gui.newline("", -2)
4073 str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 1, 1)
4074 if gui: gui.newline("", -2)
4075 str += luxFloat("nscale", luxProp(mat, keyname+".nscale", 1.0), 0.0, 100.0, "nscale", "Scaling factor for the noise input", gui, 1.0)
4076 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)
4077 if gui: gui.newline("", -2)
4078 str += lux3DMapping(keyname, mat, gui, level+1)
4080 if texture.get() == "wrinkled":
4081 str += luxInt("octaves", luxProp(mat, keyname+".octaves", 8), 1, 100, "octaves", "", gui, 1)
4082 # if gui: gui.newline("", -2)
4083 str += luxFloat("roughness", luxProp(mat, keyname+".roughness", 0.5), 0.0, 1.0, "roughness", "", gui, 1, 1)
4084 if gui: gui.newline("", -2)
4085 str += lux3DMapping(keyname, mat, gui, level+1)
4087 if texture.get() == "brick":
4088 if gui: gui.newline("brick:", -2, level+1, icon_texparam)
4090 str += luxFloat("brickwidth", luxProp(mat, keyname+".brickwidth", 0.3), 0.0, 10.0, "brickwidth (X)", "", gui, 1.0)
4091 str += luxFloat("brickheight", luxProp(mat, keyname+".brickheight", 0.1), 0.0, 10.0, "brickheight (Z)", "", gui, 1.0)
4092 str += luxFloat("brickdepth", luxProp(mat, keyname+".brickdepth", 0.15), 0.0, 10.0, "brickdepth (Y)", "", gui, 1.0)
4094 if gui: gui.newline("mortar:", -2, level+1, icon_texparam)
4096 str += luxFloat("mortarsize", luxProp(mat, keyname+".mortarsize", 0.01), 0.0, 1.0, "mortarsize", "", gui, 1.0)
4098 (s, l) = c(("", ""), luxTexture("bricktex", keyname, type, default, min, max, "bricktex", "", mat, gui, matlevel, texlevel+1, lightsource))
4099 (s, l) = c((s, l), luxTexture("mortartex", keyname, type, alternativedefault(type, default), min, max, "mortartex", "", mat, gui, matlevel, texlevel+1, lightsource))
4102 str += lux3DMapping(keyname, mat, gui, level+1)
4104 if texture.get() == "blender_marble":
4105 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4107 mtype = luxProp(mat, keyname+".mtype", "soft")
4108 mtypes = ["soft","sharp","sharper"]
4109 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
4111 noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
4112 noisetypes = ["soft_noise","hard_noise"]
4113 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
4115 str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0, 6, "noisedepth", "", gui, 0.75)
4117 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4118 str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 200.0, "turbulance", "", gui, 1.0)
4120 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
4121 noisebasis2 = luxProp(mat, keyname+".noisebasis2", "sin")
4122 noisebasises2 = ["sin","saw","tri"]
4123 str += luxOption("noisebasis2", noisebasis2, noisebasises2, "noisebasis2", "", gui, 0.7)
4125 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4126 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4127 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
4129 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4130 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4131 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4133 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4134 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4137 str += lux3DMapping(keyname, mat, gui, level+1)
4139 if texture.get() == "blender_musgrave":
4140 if gui: gui.newline("type:", -2, level+1, icon_texparam)
4141 mtype = luxProp(mat, keyname+".mtype", "multifractal")
4142 mtypes = ["multifractal","ridged_multifractal", "hybrid_multifractal", "hetero_terrain", "fbm"]
4143 str += luxOption("type", mtype, mtypes, "type", "", gui, 2.0)
4145 str += luxFloat("h", luxProp(mat, keyname+".h", 1.0), 0.0, 2.0, "h", "", gui, 0.5)
4146 str += luxFloat("lacu", luxProp(mat, keyname+".lacu", 2.0), 0.0, 6.0, "lacu", "", gui, 0.75)
4147 str += luxFloat("octs", luxProp(mat, keyname+".octs", 2.0), 0.0, 8.0, "octs", "", gui, 0.75)
4149 if mtype.get() == "hetero_terrain":
4150 str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 2.0)
4151 if mtype.get() == "ridged_multifractal":
4152 str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 1.25)
4153 str += luxFloat("gain", luxProp(mat, keyname+".gain", 2.0), 0.0, 6.0, "gain", "", gui, 0.75)
4154 if mtype.get() == "hybrid_multifractal":
4155 str += luxFloat("offset", luxProp(mat, keyname+".offset", 2.0), 0.0, 6.0, "offset", "", gui, 1.25)
4156 str += luxFloat("gain", luxProp(mat, keyname+".gain", 2.0), 0.0, 6.0, "gain", "", gui, 0.75)
4158 str += luxFloat("outscale", luxProp(mat, keyname+".outscale", 1.0), 0.0, 10.0, "iscale", "", gui, 1.0)
4159 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4161 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
4162 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4163 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4164 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 2.0)
4166 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4167 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4168 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4170 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4171 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4174 str += lux3DMapping(keyname, mat, gui, level+1)
4176 if texture.get() == "blender_wood":
4177 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4179 mtype = luxProp(mat, keyname+".mtype", "bands")
4180 mtypes = ["bands","rings","bandnoise", "ringnoise"]
4181 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
4183 noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
4184 noisetypes = ["soft_noise","hard_noise"]
4185 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
4187 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4188 str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 200.0, "turbulance", "", gui, 1.0)
4190 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
4191 noisebasis2 = luxProp(mat, keyname+".noisebasis2", "sin")
4192 noisebasises2 = ["sin","saw","tri"]
4193 str += luxOption("noisebasis2", noisebasis2, noisebasises2, "noisebasis2", "", gui, 0.7)
4195 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4196 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4197 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
4199 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4200 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4201 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4203 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4204 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4207 str += lux3DMapping(keyname, mat, gui, level+1)
4209 if texture.get() == "blender_clouds":
4210 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4212 mtype = luxProp(mat, keyname+".mtype", "default")
4213 mtypes = ["default","color"]
4214 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
4216 noisetype = luxProp(mat, keyname+".noisetype", "hard_noise")
4217 noisetypes = ["soft_noise","hard_noise"]
4218 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
4220 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4221 str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0, 6, "noisedepth", "", gui, 1.0)
4223 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
4224 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4225 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4226 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
4228 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4229 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4230 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4232 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4233 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4236 str += lux3DMapping(keyname, mat, gui, level+1)
4238 if texture.get() == "blender_blend":
4239 if gui: gui.newline("type:", -2, level+1, icon_texparam)
4241 mtype = luxProp(mat, keyname+".mtype", "lin")
4242 mtypes = ["lin","quad","ease","diag","sphere","halo","radial"]
4243 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
4245 mflag = luxProp(mat, keyname+".flag", "false")
4246 str += luxBool("flipxy", mflag, "flipXY", "", gui, 0.5)
4248 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4249 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4250 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4252 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4253 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4256 str += lux3DMapping(keyname, mat, gui, level+1)
4258 if texture.get() == "blender_distortednoise":
4259 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4261 str += luxFloat("distamount", luxProp(mat, keyname+".distamount", 1.0), 0.0, 10.0, "distamount", "", gui, 1.0)
4262 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4263 str += luxFloat("nabla", luxProp(mat, keyname+".nabla", 0.025), 0.000, 2.0, "nabla", "", gui, 1.0)
4265 if gui: gui.newline("distortion:", -2, level+1, icon_texparam)
4266 ntype = luxProp(mat, keyname+".type", "blender_original")
4267 ntypes = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4268 str += luxOption("type", ntype, ntypes, "type", "", gui, 1.3)
4270 if gui: gui.newline("basis:", -2, level+1, icon_texparam)
4271 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4272 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4273 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
4275 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4276 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4277 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4279 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4280 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4283 str += lux3DMapping(keyname, mat, gui, level+1)
4285 if texture.get() == "blender_noise":
4286 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4287 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4288 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4290 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4291 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4294 str += lux3DMapping(keyname, mat, gui, level+1)
4296 if texture.get() == "blender_magic":
4297 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4299 str += luxInt("noisedepth", luxProp(mat, keyname+".noisedepth", 2), 0.0, 10.0, "noisedepth", "", gui, 1.0)
4300 str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 2.0, "turbulance", "", gui, 1.0)
4302 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4303 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4304 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4306 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4307 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4310 str += lux3DMapping(keyname, mat, gui, level+1)
4312 if texture.get() == "blender_stucci":
4313 if gui: gui.newline("noise:", -2, level+1, icon_texparam)
4314 mtype = luxProp(mat, keyname+".mtype", "Plastic")
4315 mtypes = ["Plastic","Wall In","Wall Out"]
4316 str += luxOption("type", mtype, mtypes, "type", "", gui, 0.5)
4318 noisetype = luxProp(mat, keyname+".noisetype", "soft_noise")
4319 noisetypes = ["soft_noise","hard_noise"]
4320 str += luxOption("noisetype", noisetype, noisetypes, "noisetypes", "", gui, 0.75)
4322 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 10.0, "noisesize", "", gui, 1.0)
4323 str += luxFloat("turbulance", luxProp(mat, keyname+".turbulance", 5.0), 0.0, 200.0, "turbulance", "", gui, 1.0)
4325 noisebasis = luxProp(mat, keyname+".noisebasis", "blender_original")
4326 noisebasises = ["blender_original","original_perlin", "improved_perlin", "voronoi_f1", "voronoi_f2", "voronoi_f3", "voronoi_f4", "voronoi_f2f1", "voronoi_crackle", "cell_noise"]
4327 str += luxOption("noisebasis", noisebasis, noisebasises, "noisebasis", "", gui, 1.3)
4329 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4330 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4331 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4333 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4334 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4337 str += lux3DMapping(keyname, mat, gui, level+1)
4339 if texture.get() == "blender_voronoi":
4340 #if gui: gui.newline("distmetric:", -2, level+1, icon_texparam)
4341 mtype = luxProp(mat, keyname+".distmetric", "actual_distance")
4342 mtypes = ["actual_distance","distance_squared","manhattan", "chebychev", "minkovsky_half", "minkovsky_four", "minkovsky"]
4343 str += luxOption("distmetric", mtype, mtypes, "distmetric", "", gui, 1.1)
4345 if gui: gui.newline("param:", -2, level+1, icon_texparam)
4346 str += luxFloat("minkovsky_exp", luxProp(mat, keyname+".minkovsky_exp", 2.5), 0.001, 10.0, "minkovsky_exp", "", gui, 1.0)
4347 str += luxFloat("outscale", luxProp(mat, keyname+".outscale", 1.0), 0.01, 10.0, "outscale", "", gui, 1.0)
4348 str += luxFloat("noisesize", luxProp(mat, keyname+".noisesize", 0.25), 0.0, 2.0, "noisesize", "", gui, 1.0)
4349 str += luxFloat("nabla", luxProp(mat, keyname+".nabla", 0.025), 0.001, 0.1, "nabla", "", gui, 1.0)
4350 if gui: gui.newline("wparam:", -2, level+1, icon_texparam)
4351 str += luxFloat("w1", luxProp(mat, keyname+".w1", 1.0), -2.0, 2.0, "w1", "", gui, 1.0)
4352 str += luxFloat("w2", luxProp(mat, keyname+".w2", 0.0), -2.0, 2.0, "w2", "", gui, 1.0)
4353 str += luxFloat("w3", luxProp(mat, keyname+".w3", 0.0), -2.0, 2.0, "w3", "", gui, 1.0)
4354 str += luxFloat("w4", luxProp(mat, keyname+".w4", 0.0), -2.0, 2.0, "w4", "", gui, 1.0)
4356 if gui: gui.newline("level:", -2, level+1, icon_texparam)
4357 str += luxFloat("bright", luxProp(mat, keyname+".bright", 1.0), 0.0, 2.0, "bright", "", gui, 1.0)
4358 str += luxFloat("contrast", luxProp(mat, keyname+".contrast", 1.0), 0.0, 10.0, "contrast", "", gui, 1.0)
4360 (s, l) = c(("", ""), luxTexture("tex1", keyname, type, default, min, max, "tex1", "", mat, gui, matlevel, texlevel+1, lightsource))
4361 (s, l) = c((s, l), luxTexture("tex2", keyname, type, alternativedefault(type, default), min, max, "tex2", "", mat, gui, matlevel, texlevel+1, lightsource))
4364 str += lux3DMapping(keyname, mat, gui, level+1)
4368 return (str+"\n", " \"texture %s\" [\"%s\"]"%(name, texname))
4371 def luxSpectrumTexture(name, key, default, max, caption, hint, mat, gui, level=0):
4373 if gui: gui.newline(caption, 4, level, icon_col, scalelist([0.5,0.6,0.5],2.0/(level+2)))
4375 keyname = "%s:%s"%(key, name)
4376 texname = "%s:%s"%(mat.getName(), keyname)
4377 value = luxProp(mat, keyname, default)
4378 link = luxRGB(name, value, max, "", hint, gui, 2.0)
4379 tex = luxProp(mat, keyname+".textured", False)
4380 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)]))
4381 if tex.get()=="true":
4382 if gui: gui.newline("", -2)
4383 (str, link) = luxTexture(name, key, "color", default, 0, max, caption, hint, mat, gui, level+1)
4384 if value.getRGB() != (1.0, 1.0, 1.0):
4385 if str == "": # handle special case if texture is a just a constant
4386 str += "Texture \"%s\" \"color\" \"scale\" \"color tex1\" [%s] \"color tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
4387 else: str += "Texture \"%s\" \"color\" \"scale\" \"texture tex1\" [\"%s\"] \"color tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4388 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4391 def luxLightSpectrumTexture(name, key, default, max, caption, hint, mat, gui, level=0):
4392 #if gui: gui.newline(caption, 4, level, icon_emission, scalelist([0.6,0.5,0.5],2.0/(level+2)))
4394 keyname = "%s:%s"%(key, name)
4395 texname = "%s:%s"%(mat.getName(), keyname)
4396 (str, link) = luxTexture(name, key, "color", default, 0, max, caption, hint, mat, gui, level+1, 0, 1)
4399 def luxFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4401 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4403 keyname = "%s:%s"%(key, name)
4404 texname = "%s:%s"%(mat.getName(), keyname)
4405 value = luxProp(mat, keyname, default)
4406 link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
4407 tex = luxProp(mat, keyname+".textured", False)
4408 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)]))
4409 if tex.get()=="true":
4410 if gui: gui.newline("", -2)
4411 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4412 if value.get() != 1.0:
4413 if str == "": # handle special case if texture is a just a constant
4414 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
4415 else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4416 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4419 def luxFloatSliderTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4421 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4423 keyname = "%s:%s"%(key, name)
4424 texname = "%s:%s"%(mat.getName(), keyname)
4425 value = luxProp(mat, keyname, default)
4426 link = luxFloat(name, value, min, max, caption, hint, gui, 2.0, 1)
4427 tex = luxProp(mat, keyname+".textured", False)
4428 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)]))
4429 if tex.get()=="true":
4430 if gui: gui.newline("", -2)
4431 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4432 if value.get() != 1.0:
4433 if str == "": # handle special case if texture is a just a constant
4434 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
4435 else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4436 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4440 def luxExponentTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4442 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4444 keyname = "%s:%s"%(key, name)
4445 texname = "%s:%s"%(mat.getName(), keyname)
4446 value = luxProp(mat, keyname, default)
4448 if(value.get() == None): value.set(0.002)
4450 # link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
4452 r = gui.getRect(2.0, 1)
4453 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))
4454 link = " \"float %s\" [%f]"%(name, value.getFloat())
4456 tex = luxProp(mat, keyname+".textured", False)
4457 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)]))
4458 if tex.get()=="true":
4459 if gui: gui.newline("", -2)
4460 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4461 if value.get() != 1.0:
4462 if str == "": # handle special case if texture is a just a constant
4463 str += "Texture \"%s\" \"float\" \"scale\" \"float tex1\" [%s] \"float tex2\" [%s]\n"%(texname+".scale", (link.rpartition("[")[2])[0:-1], value.get())
4464 else: str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4465 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4469 def luxDispFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4471 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4473 keyname = "%s:%s"%(key, name)
4474 texname = "%s:%s"%(mat.getName(), keyname)
4475 value = luxProp(mat, keyname, default)
4476 link = luxFloat(name, value, min, max, "", hint, gui, 2.0)
4477 tex = luxProp(mat, keyname+".textured", False)
4478 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)]))
4479 if tex.get()=="true":
4480 if gui: gui.newline("", -2)
4481 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4482 str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4483 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4486 def luxIORFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4488 iornames = ["0Z *** Gases @ 0 C ***", "01 - Vacuum", "02 - Air @ STP", "03 - Air", "04 - Helium", "05 - Hydrogen", "06 - Carbon dioxide",
4489 "1Z *** LIQUIDS @ 20 C ***", "11 - Benzene", "12 - Water", "13 - Ethyl alcohol", "14 - Carbon tetrachloride", "15 - Carbon disulfide",
4490 "2Z *** SOLIDS at room temperature ***", "21 - Diamond", "22 - Strontium titanate", "23 - Amber", "24 - Fused silica glass", "25 - sodium chloride",
4491 "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"]
4492 iorvals = [1.0, 1.0, 1.0002926, 1.000293, 1.000036, 1.000132, 1.00045,
4493 1.501, 1.501, 1.333, 1.361, 1.461, 1.628,
4494 2.419, 2.419, 2.41, 1.55, 1.458, 1.50,
4495 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]
4498 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4500 keyname = "%s:%s"%(key, name)
4501 texname = "%s:%s"%(mat.getName(), keyname)
4502 value = luxProp(mat, keyname, default)
4504 iorusepreset = luxProp(mat, keyname+".iorusepreset", "true")
4505 luxBool("iorusepreset", iorusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
4507 if(iorusepreset.get() == "true"):
4508 iorpreset = luxProp(mat, keyname+".iorpreset", "24 - Fused silica glass")
4510 def setIor(i, value, preset, tree, dict): # callback function to set ior value after selection
4513 preset.set(getTreeNameById(tree, i))
4514 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) ] ) ]
4515 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}
4516 r = gui.getRect(1.6, 1)
4517 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))
4518 link = luxFloat(name, value, min, max, "IOR", hint, None, 1.6)
4520 link = luxFloat(name, value, min, max, "IOR", hint, gui, 1.6, 1)
4522 tex = luxProp(mat, keyname+".textured", False)
4523 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)]))
4524 if tex.get()=="true":
4525 if gui: gui.newline("", -2)
4526 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4527 if value.get() != 1.0:
4528 str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4529 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4532 def luxCauchyBFloatTexture(name, key, default, min, max, caption, hint, mat, gui, level=0):
4534 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" ]
4535 cauchybvals = [ 0.00354, 0.00420, 0.00459, 0.00531, 0.00743, 0.01342 ]
4538 if gui: gui.newline(caption, 4, level, icon_float, scalelist([0.5,0.5,0.6],2.0/(level+2)))
4540 keyname = "%s:%s"%(key, name)
4541 texname = "%s:%s"%(mat.getName(), keyname)
4542 value = luxProp(mat, keyname, default)
4544 cauchybusepreset = luxProp(mat, keyname+".cauchybusepreset", "true")
4545 luxBool("cauchybusepreset", cauchybusepreset, "Preset", "Select from a list of predefined presets", gui, 0.4)
4547 if(cauchybusepreset.get() == "true"):
4548 cauchybpreset = luxProp(mat, keyname+".cauchybpreset", "01 - Fused silica glass")
4549 luxOption("cauchybpreset", cauchybpreset, cauchybnames, " PRESET", "select CauchyB preset", gui, 1.6)
4550 idx = cauchybnames.index(cauchybpreset.get())
4551 value.set(cauchybvals[idx])
4552 link = luxFloat(name, value, min, max, "cauchyb", hint, None, 1.6)
4554 link = luxFloat(name, value, min, max, "cauchyb", hint, gui, 1.6, 1)
4556 tex = luxProp(mat, keyname+".textured", False)
4557 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)]))
4558 if tex.get()=="true":
4559 if gui: gui.newline("", -2)
4560 (str, link) = luxTexture(name, key, "float", default, min, max, caption, hint, mat, gui, level+1)
4561 if value.get() != 1.0:
4562 str += "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" [\"%s\"] \"float tex2\" [%s]\n"%(texname+".scale", texname, value.get())
4563 link = " \"texture %s\" [\"%s\"]"%(name, texname+".scale")
4566 def luxLight(name, kn, mat, gui, level):
4568 if name != "": gui.newline(name+":", 10, level)
4569 else: gui.newline("color:", 0, level+1)
4570 (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
4571 if gui: gui.newline("")
4572 link += luxFloat("power", luxProp(mat, kn+"light.power", 100.0), 0.0, 10000.0, "Power(W)", "AreaLight Power in Watts", gui)
4573 link += luxFloat("efficacy", luxProp(mat, kn+"light.efficacy", 17.0), 0.0, 100.0, "Efficacy(lm/W)", "Efficacy Luminous flux/watt", gui)
4574 if gui: gui.newline("")
4575 link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
4576 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
4577 luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 1.0)
4579 if gui: gui.newline("Photometric")
4580 pm = luxProp(mat, kn+"light.usepm", "false")
4581 luxCollapse("photometric", pm, "Photometric Diagram", "Enable Photometric Diagram options", gui, 2.0)
4583 if(pm.get()=="true"):
4584 pmtype = luxProp(mat, kn+"light.pmtype", "IESna")
4585 pmtypes = ["IESna", "imagemap"]
4586 luxOption("type", pmtype, pmtypes, "type", "Choose Photometric data type to use", gui, 0.6)
4587 if(pmtype.get() == "imagemap"):
4588 map = luxProp(mat, kn+"light.pmmapname", "")
4589 link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 1.4)
4590 if(pmtype.get() == "IESna"):
4591 map = luxProp(mat, kn+"light.pmiesname", "")
4592 link += luxFile("iesname", map, "ies-file", "filename of the IES photometric data file", gui, 1.4)
4594 has_bump_options = 0
4595 has_object_options = 1
4598 def luxLamp(name, kn, mat, gui, level):
4600 if name != "": gui.newline(name+":", 10, level)
4601 else: gui.newline("color:", 0, level+1)
4602 # if gui: gui.newline("", 10, level)
4603 (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
4604 if gui: gui.newline("")
4605 link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
4606 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
4607 luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 1.0)
4609 if gui: gui.newline("Photometric")
4610 pm = luxProp(mat, kn+"light.usepm", "false")
4611 luxBool("photometric", pm, "Photometric Diagram", "Enable Photometric Diagram options", gui, 2.0)
4613 if(pm.get()=="true"):
4614 pmtype = luxProp(mat, kn+"light.pmtype", "IESna")
4615 pmtypes = ["IESna", "imagemap"]
4616 luxOption("type", pmtype, pmtypes, "type", "Choose Photometric data type to use", gui, 0.6)
4617 if(pmtype.get() == "imagemap"):
4618 map = luxProp(mat, kn+"light.pmmapname", "")
4619 link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 1.4)
4620 if(pmtype.get() == "IESna"):
4621 map = luxProp(mat, kn+"light.pmiesname", "")
4622 link += luxFile("iesname", map, "ies-file", "filename of the IES photometric data file", gui, 1.4)
4624 link += luxBool("flipz", luxProp(mat, kn+"light.flipZ", "true"), "Flip Z", "Flip Z direction in mapping", gui, 2.0)
4628 def luxSpot(name, kn, mat, gui, level):
4630 if name != "": gui.newline(name+":", 10, level)
4631 else: gui.newline("color:", 0, level+1)
4632 # if gui: gui.newline("", 10, level)
4633 (str,link) = luxLightSpectrumTexture("L", kn+"light", "1.0 1.0 1.0", 1.0, "Spectrum", "", mat, gui, level+1)
4634 if gui: gui.newline("")
4635 link += luxFloat("gain", luxProp(mat, kn+"light.gain", 1.0), 0.0, 100.0, "gain", "Gain/scale multiplier", gui)
4636 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
4637 luxString("lightgroup", lightgroup, "group", "assign light to a named light-group", gui, 1.0)
4639 if gui: gui.newline("Projection")
4640 proj = luxProp(mat, kn+"light.usetexproj", "false")
4641 luxBool("projection", proj, "Texture Projection", "Enable imagemap texture projection", gui, 2.0)
4643 if(proj.get() == "true"):
4644 map = luxProp(mat, kn+"light.pmmapname", "")
4645 link += luxFile("mapname", map, "map-file", "filename of the photometric map", gui, 2.0)
4650 def Preview_Sphereset(mat, kn, state):
4652 luxProp(mat, kn+"prev_sphere", "true").set("true")
4653 luxProp(mat, kn+"prev_plane", "false").set("false")
4654 luxProp(mat, kn+"prev_torus", "false").set("false")
4655 def Preview_Planeset(mat, kn, state):
4657 luxProp(mat, kn+"prev_sphere", "true").set("false")
4658 luxProp(mat, kn+"prev_plane", "false").set("true")
4659 luxProp(mat, kn+"prev_torus", "false").set("false")
4660 def Preview_Torusset(mat, kn, state):
4662 luxProp(mat, kn+"prev_sphere", "true").set("false")
4663 luxProp(mat, kn+"prev_plane", "false").set("false")
4664 luxProp(mat, kn+"prev_torus", "false").set("true")
4669 def Preview_Update(mat, kn, defLarge, defType, texName, name, level):
4670 #print("%s %s %s %s %s %s %s" % (mat, kn, defLarge, defType, texName, name, level))
4675 Blender.Window.WaitCursor(True)
4676 scn = Scene.GetCurrent()
4678 # set path mode to absolute for preview
4679 pm_prop = luxProp(scn, "pathmode", "absolute")
4681 pm_prop.set('absolute')
4684 # Size of preview thumbnail
4685 thumbres = 110 # default 110x110
4687 large = luxProp(mat, kn+"prev_large", "true")
4689 large = luxProp(mat, kn+"prev_large", "false")
4690 if(large.get() == "true"):
4691 thumbres = 140 # small 140x140
4693 thumbbuf = thumbres*thumbres*3
4695 # consolebin = luxProp(scn, "luxconsole", "").get()
4697 p = get_lux_pipe(scn, buf=thumbbuf, type="luxconsole")
4699 # Unremark to write debugging output to file
4700 # p.stdin = open('c:\preview.lxs', 'w')
4703 prev_sphere = luxProp(mat, kn+"prev_sphere", "true")
4704 prev_plane = luxProp(mat, kn+"prev_plane", "false")
4705 prev_torus = luxProp(mat, kn+"prev_torus", "false")
4707 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
4708 prev_plane = luxProp(mat, kn+"prev_plane", "true")
4709 prev_torus = luxProp(mat, kn+"prev_torus", "false")
4711 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
4712 prev_plane = luxProp(mat, kn+"prev_plane", "false")
4713 prev_torus = luxProp(mat, kn+"prev_torus", "true")
4716 if luxProp(mat, kn+"prev_zoom", "false").get() == "true":
4717 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')
4719 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')
4721 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))
4722 p.stdin.write('PixelFilter "sinc"\n')
4724 scn = Scene.GetCurrent()
4725 defprevmat = luxProp(scn, "defprevmat", "high")
4726 quality = luxProp(mat, kn+"prev_quality", defprevmat.get())
4727 if quality.get()=="low":
4728 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [2]\n')
4729 elif quality.get()=="medium":
4730 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [4]\n')
4731 elif quality.get()=="high":
4732 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [8]\n')
4734 p.stdin.write('Sampler "lowdiscrepancy" "string pixelsampler" ["hilbert"] "integer pixelsamples" [32]\n')
4736 if(prev_plane.get()=="false"):
4737 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')
4739 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')
4741 p.stdin.write('WorldBegin\n')
4742 if(prev_sphere.get()=="true"):
4743 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')
4744 elif (prev_plane.get()=="true"):
4745 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')
4747 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')
4748 obwidth = luxProp(mat, kn+"prev_obwidth", 1.0)
4750 p.stdin.write('TransformBegin\n')
4751 p.stdin.write('Scale %f %f %f\n'%(obw,obw,obw))
4753 print("texture "+texName+" "+name)
4754 (str, link) = luxTexture(texName, name, "color", "1.0 1.0 1.0", None, None, "", "", mat, None, 0, level)
4755 link = link.replace(" "+texName+"\"", " Kd\"") # swap texture name to "Kd"
4756 p.stdin.write(str+"\n")
4757 p.stdin.write("Material \"matte\" "+link+"\n")
4760 p.stdin.write(luxMaterial(mat))
4761 link = luxProp(mat,"link","").get()
4762 if kn!="": link = link.rstrip("\"")+":"+kn.strip(".:")+"\""
4763 p.stdin.write(link+'\n')
4764 p.stdin.write('TransformEnd\n')
4766 if(prev_sphere.get()=="true"):
4767 p.stdin.write('Shape "sphere" "float radius" [1.0]\n')
4768 elif (prev_plane.get()=="true"):
4769 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')
4770 elif (prev_torus.get()=="true"):
4771 p.stdin.write('Shape "torus" "float radius" [1.0]\n')
4772 p.stdin.write('AttributeEnd\n')
4773 # Checkerboard floor
4774 if(prev_plane.get()=="false"):
4775 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')
4776 p.stdin.write('Texture "checks" "color" "checkerboard"')
4777 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]')
4778 p.stdin.write('"string mapping" ["uv"] "float uscale" [36.8] "float vscale" [36.0]\n')
4779 p.stdin.write('Material "matte" "texture Kd" ["checks"]\n')
4780 p.stdin.write('Shape "loopsubdiv" "integer nlevels" [3] "bool dmnormalsmooth" ["true"] "bool dmsharpboundary" ["false"] ')
4781 p.stdin.write('"integer indices" [ 0 1 2 0 2 3 1 0 4 1 4 5 5 4 6 5 6 7 ]')
4782 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')
4783 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')
4784 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')
4785 p.stdin.write('AttributeEnd\n')
4787 if(prev_plane.get()=="false"):
4788 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')
4790 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')
4791 area = luxProp(mat, kn+"prev_arealight", "false")
4792 if(area.get() == "false"):
4793 p.stdin.write('Texture "pL" "color" "blackbody" "float temperature" [6500.0]\n')
4794 p.stdin.write('LightSource "point" "texture L" ["pL"] "float gain" [0.002]')
4796 p.stdin.write('ReverseOrientation\n')
4797 p.stdin.write('AreaLightSource "area" "color L" [1.0 1.0 1.0]\n')
4798 if(prev_plane.get()=="false"):
4799 p.stdin.write(' "float gain" [0.3]\n')
4800 p.stdin.write('Shape "disk" "float radius" [1.0]\nAttributeEnd\n')
4801 p.stdin.write('WorldEnd\n')
4805 data = p.communicate()[0]
4812 if(datalen < thumbbuf):
4813 print("error on preview: got %i bytes, expected %i" % (datalen, thumbbuf))
4817 image.decodeLuxConsole(thumbres, thumbres, data)
4818 previewCache[(mat.name+":"+kn).__hash__()] = image
4820 Blender.Window.WaitCursor(False)
4822 def luxPreview(mat, name, defType=0, defEnabled=False, defLarge=False, texName=None, gui=None, level=0, color=None):
4827 if texName: kn += ":"+texName
4828 if kn != "": kn += "."
4829 if(defEnabled == True):
4830 showpreview = luxProp(mat, kn+"prev_show", "true")
4832 showpreview = luxProp(mat, kn+"prev_show", "false")
4833 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)]))
4834 if showpreview.get()=="true":
4836 large = luxProp(mat, kn+"prev_large", "true")
4838 large = luxProp(mat, kn+"prev_large", "false")
4841 if(large.get() == "true"):
4845 r = gui.getRect(1.1, rr)
4847 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)
4848 try: previewCache[(mat.name+":"+kn).__hash__()].draw(r[0]-82, r[1]+4)
4851 prev_sphere = luxProp(mat, kn+"prev_sphere", "true")
4852 prev_plane = luxProp(mat, kn+"prev_plane", "false")
4853 prev_torus = luxProp(mat, kn+"prev_torus", "false")
4855 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
4856 prev_plane = luxProp(mat, kn+"prev_plane", "true")
4857 prev_torus = luxProp(mat, kn+"prev_torus", "false")
4859 prev_sphere = luxProp(mat, kn+"prev_sphere", "false")
4860 prev_plane = luxProp(mat, kn+"prev_plane", "false")
4861 prev_torus = luxProp(mat, kn+"prev_torus", "true")
4863 # preview mode toggle buttons
4864 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)]))
4865 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)]))
4866 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)]))
4869 zoom = luxProp(mat, kn+"prev_zoom", "false")
4870 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)]))
4872 area = luxProp(mat, kn+"prev_arealight", "false")
4873 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)]))
4876 obwidth = luxProp(mat, kn+"prev_obwidth", 1.0)
4877 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))
4880 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)]))
4883 qs = ["low","medium","high","very high"]
4884 scn = Scene.GetCurrent()
4885 defprevmat = luxProp(scn, "defprevmat", "high")
4886 quality = luxProp(mat, kn+"prev_quality", defprevmat.get())
4887 luxOptionRect("quality", quality, qs, " Quality", "select preview quality", gui, r[0]+200, r[1]+100+voffset, 88, 18)
4890 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))
4892 # Reset depths after getRect()
4897 def luxMaterialBlock(name, luxname, key, mat, gui=None, level=0, str_opt=""):
4898 global icon_mat, icon_matmix, icon_map3dparam
4900 return (t1[0]+t2[0], t1[1]+t2[1])
4902 if key == "": keyname = kn = name
4903 else: keyname = kn = "%s:%s"%(key, name)
4904 if kn != "": kn += "."
4905 if keyname == "": matname = mat.getName()
4906 else: matname = "%s:%s"%(mat.getName(), keyname)
4909 mattype = luxProp(mat, kn+"type", "matte")
4910 # Set backwards compatibility of glossy material from plastic and substrate
4911 if(mattype.get() == "substrate" or mattype.get() == "plastic"):
4912 mattype.set("glossy")
4914 # this is reverse order than in shown in the dropdown list
4915 materials = ["null","mix","mirror","shinymetal","metal","mattetranslucent","matte","glossy","roughglass","glass","carpaint"]
4917 if level == 0: materials = ["portal","light","boundvolume"]+materials
4920 if mattype.get() == "mix": icon = icon_matmix
4921 if level == 0: gui.newline("Material type:", 12, level, icon, [0.75,0.5,0.25])
4922 else: gui.newline(name+":", 12, level, icon, scalelist([0.75,0.6,0.25],2.0/(level+2)))
4925 link = luxOption("type", mattype, materials, " TYPE", "select material type", gui)
4926 showadvanced = luxProp(mat, kn+"showadvanced", "false")
4927 luxBool("advanced", showadvanced, "Advanced", "Show advanced options", gui, 0.6)
4928 showhelp = luxProp(mat, kn+"showhelp", "false")
4929 luxHelp("help", showhelp, "Help", "Show Help Information", gui, 0.4)
4931 # show copy/paste menu button
4932 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))
4934 # Draw Material preview option
4938 if gui: luxPreview(mat, keyname, 0, showmatprev, True, None, gui, level, [0.746, 0.625, 0.5])
4941 if gui: gui.newline()
4942 has_object_options = 0 # disable object options by default
4943 has_bump_options = 0 # disable bump mapping options by default
4944 has_emission_options = 0 # disable emission options by default
4945 has_compositing_options = 0 # disable compositing options by default
4947 if mattype.get() == "mix":
4948 (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))
4949 (str,link) = c((str,link), luxMaterialBlock("mat1", "namedmaterial1", keyname, mat, gui, level+1))
4950 (str,link) = c((str,link), luxMaterialBlock("mat2", "namedmaterial2", keyname, mat, gui, level+1))
4951 has_bump_options = 0
4952 has_object_options = 1
4953 has_emission_options = 1
4954 has_compositing_options = 0
4956 if mattype.get() == "light":
4957 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
4958 lightgroup = luxProp(mat, kn+"light.lightgroup", "default")
4959 link = "LightGroup \"%s\"\n"%lightgroup.get()
4962 link += "AreaLightSource \"area\""
4963 (str,link) = c((str,link), luxLight("", kn, mat, gui, level))
4964 has_bump_options = 0
4965 has_object_options = 1
4966 has_emission_options = 0
4967 has_compositing_options = 1
4969 if mattype.get() == "boundvolume":
4971 voltype = luxProp(mat, kn+"vol.type", "homogeneous")
4972 vols = ["homogeneous", "exponential", "cloud"]
4973 vollink = luxOption("type", voltype, vols, "type", "", gui)
4974 if voltype.get() == "homogeneous":
4975 link = "Volume \"homogeneous\""
4976 if voltype.get() == "exponential":
4977 link = "Volume \"exponential\""
4978 if voltype.get() == "cloud":
4979 link = "Volume \"cloud\""
4981 if gui: gui.newline("absorption:", 0, level+1)
4982 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)
4983 if gui: gui.newline("scattering:", 0, level+1)
4984 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)
4985 if gui: gui.newline("emission:", 0, level+1)
4986 link += luxRGB("Le", luxProp(mat, kn+"vol.le", "0.0 0.0 0.0"), 1.0, "Le", "The volume's emission spectrum", gui)
4987 if gui: gui.newline("assymetry:", 0, level+1)
4988 link += luxFloat("g", luxProp(mat, kn+"vol.g", 0.0), 0.0, 100.0, "g", "The phase function asymmetry parameter", gui)
4990 if voltype.get() == "exponential":
4991 if gui: gui.newline("form:", 0, level+1)
4992 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)
4993 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)
4994 if gui: gui.newline("updir:", 0, level+1)
4995 link += luxVector("updir", luxProp(mat, kn+"vol.updir", "0 0 1"), -1.0, 1.0, "updir", "Up direction vector", gui, 2.0)
4997 if voltype.get() == "cloud":
4998 if gui: gui.newline("cloud:", 0, level+1)
4999 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)
5000 link += luxFloat("noisescale", luxProp(mat, kn+"vol.noisescale", 0.3), 0.1, 2.0, "noisesize", "Size of cloud noise", gui)
5001 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)
5002 link += luxFloat("noiseoffset", luxProp(mat, kn+"vol.noiseoffset", 0.0), 0.0, 1000.0, "noiseoffset", "Useful for creating unique clouds", gui )
5003 link += luxInt("octaves", luxProp(mat, kn+"vol.octaves", 3), 1, 8, "octaves", "Sets the amount of detail for the noise", gui )
5004 link += luxFloat("omega", luxProp(mat, kn+"vol.omega", 0.75), 0.1, 1.0, "omega", "Sets the scale difference of each successive octave", gui )
5005 link += luxFloat("sharpness", luxProp(mat, kn+"vol.sharpness", 6.0), 0.2, 10.0, "sharpness", "Sets the sharpness of the noise", gui)
5006 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)
5007 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)
5008 link += luxInt("spheres", luxProp(mat, kn+"vol.spheres", 2000), 0, 10000, "spheres", "Number of small spheres for cumulus shape. 0 is non-cumulus.", gui )
5009 link += luxFloat("spheresize", luxProp(mat, kn+"vol.spheresize", 0.15), 0.05, 0.55, "spheresize", "Size of cumulus spheres", gui)
5013 has_bump_options = 0
5014 has_object_options = 0
5015 has_emission_options = 0
5019 if mattype.get() == "carpaint":
5020 if gui: gui.newline("Preset:", 0, level+1)
5021 carname = luxProp(mat, kn+"carpaint.name", "Custom")
5022 cars = ["Custom","ford f8","polaris silber","opel titan","bmw339","2k acrylack","white","blue","blue matte"]
5023 carlink = luxOption("name", carname, cars, "name", "", gui)
5024 if carname.get() == "Custom":
5025 (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
5026 (str,link) = c((str,link), luxSpectrumTexture("Ks1", keyname, "1.0 1.0 1.0", 1.0, "specular1", "", mat, gui, level+1))
5027 (str,link) = c((str,link), luxSpectrumTexture("Ks2", keyname, "1.0 1.0 1.0", 1.0, "specular2", "", mat, gui, level+1))
5028 (str,link) = c((str,link), luxSpectrumTexture("Ks3", keyname, "1.0 1.0 1.0", 1.0, "specular3", "", mat, gui, level+1))
5029 (str,link) = c((str,link), luxFloatTexture("R1", keyname, 1.0, 0.0, 1.0, "R1", "", mat, gui, level+1))
5030 (str,link) = c((str,link), luxFloatTexture("R2", keyname, 1.0, 0.0, 1.0, "R2", "", mat, gui, level+1))
5031 (str,link) = c((str,link), luxFloatTexture("R3", keyname, 1.0, 0.0, 1.0, "R3", "", mat, gui, level+1))
5032 (str,link) = c((str,link), luxFloatTexture("M1", keyname, 1.0, 0.0, 1.0, "M1", "", mat, gui, level+1))
5033 (str,link) = c((str,link), luxFloatTexture("M2", keyname, 1.0, 0.0, 1.0, "M2", "", mat, gui, level+1))
5034 (str,link) = c((str,link), luxFloatTexture("M3", keyname, 1.0, 0.0, 1.0, "M3", "", mat, gui, level+1))
5035 else: link += carlink
5036 absorption = luxProp(mat, keyname+".useabsorption", "false")
5037 luxCollapse("absorption", absorption, "Absorption", "Enable Coating Absorption", gui, 2.0)
5038 if absorption.get() == "true":
5039 (str,link) = c((str,link), luxSpectrumTexture("Ka", keyname, "0.2 0.2 0.2", 1.0, "absorption", "", mat, gui, level+1))
5040 (str,link) = c((str,link), luxFloatTexture("d", keyname, 5.0, 0.0, 15.0, "depth", "", mat, gui, level+1))
5041 has_bump_options = 1
5042 has_object_options = 1
5043 has_emission_options = 1
5044 has_compositing_options = 1
5046 if mattype.get() == "glass":
5047 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
5048 (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
5049 (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 6.0, "IOR", "", mat, gui, level+1))
5050 architectural = luxProp(mat, keyname+".architectural", "false")
5051 link += luxBool("architectural", architectural, "architectural", "Enable architectural glass", gui, 2.0)
5052 if architectural.get() == "false":
5053 chromadisp = luxProp(mat, keyname+".chromadisp", "false")
5054 luxCollapse("chromadisp", chromadisp, "Dispersive Refraction", "Enable Chromatic Dispersion", gui, 2.0)
5055 if chromadisp.get() == "true":
5056 (str,link) = c((str,link), luxCauchyBFloatTexture("cauchyb", keyname, 0.0, 0.0, 1.0, "cauchyb", "", mat, gui, level+1))
5057 thinfilm = luxProp(mat, keyname+".thinfilm", "false")
5058 luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
5059 if thinfilm.get() == "true":
5060 (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))
5061 (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))
5062 has_bump_options = 1
5063 has_object_options = 1
5064 has_emission_options = 1
5065 has_compositing_options = 1
5067 if mattype.get() == "matte":
5068 orennayar = luxProp(mat, keyname+".orennayar", "false")
5069 (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
5070 luxCollapse("orennayar", orennayar, "Oren-Nayar", "Enable Oren-Nayar BRDF", gui, 2.0)
5071 if orennayar.get() == "true":
5072 (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))
5073 has_bump_options = 1
5074 has_object_options = 1
5075 has_emission_options = 1
5076 has_compositing_options = 1
5078 if mattype.get() == "mattetranslucent":
5079 orennayar = luxProp(mat, keyname+".orennayar", "false")
5080 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
5081 (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
5082 luxCollapse("orennayar", orennayar, "Oren-Nayar", "Enable Oren-Nayar BRDF", gui, 2.0)
5083 if orennayar.get() == "true":
5084 (str,link) = c((str,link), luxFloatTexture("sigma", keyname, 0.0, 0.0, 100.0, "sigma", "", mat, gui, level+1))
5085 has_bump_options = 1
5086 has_object_options = 1
5087 has_emission_options = 1
5088 has_compositing_options = 1
5090 if mattype.get() == "metal":
5091 if gui: gui.newline("name:", 0, level+1)
5092 metalname = luxProp(mat, kn+"metal.name", "")
5093 metals = ["aluminium","amorphous carbon","silver","gold","copper"]
5095 if not(metalname.get() in metals):
5096 metals.append(metalname.get())
5097 metallink = luxOption("name", metalname, metals, "name", "", gui, 1.88)
5098 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"))
5099 link += luxstr(metallink)
5100 anisotropic = luxProp(mat, kn+"metal.anisotropic", "false")
5103 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)]))
5104 if anisotropic.get()=="true":
5105 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
5106 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
5108 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
5109 (str,link) = c((str,link), (s, l))
5110 link += l.replace("uroughness", "vroughness", 1)
5112 has_bump_options = 1
5113 has_object_options = 1
5114 has_emission_options = 1
5115 has_compositing_options = 1
5117 if mattype.get() == "mirror":
5118 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
5119 thinfilm = luxProp(mat, keyname+".thinfilm", "false")
5120 luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
5121 if thinfilm.get() == "true":
5122 (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))
5123 (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))
5125 has_bump_options = 1
5126 has_object_options = 1
5127 has_emission_options = 1
5128 has_compositing_options = 1
5130 if mattype.get() == "roughglass":
5131 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
5132 (str,link) = c((str,link), luxSpectrumTexture("Kt", keyname, "1.0 1.0 1.0", 1.0, "transmission", "", mat, gui, level+1))
5133 anisotropic = luxProp(mat, kn+"roughglass.anisotropic", "false")
5136 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)]))
5137 if anisotropic.get()=="true":
5138 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
5139 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
5141 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
5142 (str,link) = c((str,link), (s, l))
5143 link += l.replace("uroughness", "vroughness", 1)
5144 (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 6.0, "IOR", "", mat, gui, level+1))
5145 chromadisp = luxProp(mat, keyname+".chromadisp", "false")
5146 luxCollapse("chromadisp", chromadisp, "Dispersive Refraction", "Enable Chromatic Dispersion", gui, 2.0)
5147 if chromadisp.get() == "true":
5148 (str,link) = c((str,link), luxCauchyBFloatTexture("cauchyb", keyname, 0.0, 0.0, 1.0, "cauchyb", "", mat, gui, level+1))
5149 has_bump_options = 1
5150 has_object_options = 1
5151 has_emission_options = 1
5152 has_compositing_options = 1
5154 if mattype.get() == "shinymetal":
5155 (str,link) = c((str,link), luxSpectrumTexture("Kr", keyname, "1.0 1.0 1.0", 1.0, "reflection", "", mat, gui, level+1))
5156 (str,link) = c((str,link), luxSpectrumTexture("Ks", keyname, "1.0 1.0 1.0", 1.0, "specular", "", mat, gui, level+1))
5157 anisotropic = luxProp(mat, kn+"shinymetal.anisotropic", "false")
5160 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)]))
5161 if anisotropic.get()=="true":
5162 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
5163 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
5165 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
5166 (str,link) = c((str,link), (s, l))
5167 link += l.replace("uroughness", "vroughness", 1)
5169 thinfilm = luxProp(mat, keyname+".thinfilm", "false")
5170 luxCollapse("thinfilm", thinfilm, "Thin Film Coating", "Enable Thin Film Coating", gui, 2.0)
5171 if thinfilm.get() == "true":
5172 (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))
5173 (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))
5175 has_bump_options = 1
5176 has_object_options = 1
5177 has_emission_options = 1
5178 has_compositing_options = 1
5180 if mattype.get() == "glossy":
5181 (str,link) = c((str,link), luxSpectrumTexture("Kd", keyname, "1.0 1.0 1.0", 1.0, "diffuse", "", mat, gui, level+1))
5182 useior = luxProp(mat, keyname+".useior", "false")
5185 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)]))
5186 if useior.get() == "true":
5187 (str,link) = c((str,link), luxIORFloatTexture("index", keyname, 1.5, 1.0, 50.0, "IOR", "", mat, gui, level+1))
5188 link += " \"color Ks\" [1.0 1.0 1.0]"
5190 (str,link) = c((str,link), luxSpectrumTexture("Ks", keyname, "1.0 1.0 1.0", 1.0, "specular", "", mat, gui, level+1))
5191 link += " \"float index\" [0.0]"
5192 anisotropic = luxProp(mat, kn+"glossy.anisotropic", "false")
5195 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)]))
5196 if anisotropic.get()=="true":
5197 (str,link) = c((str,link), luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "u-exponent", "", mat, gui, level+1))
5198 (str,link) = c((str,link), luxExponentTexture("vroughness", keyname, 0.002, 0.0, 1.0, "v-exponent", "", mat, gui, level+1))
5200 (s, l) = luxExponentTexture("uroughness", keyname, 0.002, 0.0, 1.0, "exponent", "", mat, gui, level+1)
5201 (str,link) = c((str,link), (s, l))
5202 link += l.replace("uroughness", "vroughness", 1)
5204 absorption = luxProp(mat, keyname+".useabsorption", "false")
5205 luxCollapse("absorption", absorption, "Absorption", "Enable Coating Absorption", gui, 2.0)
5206 if absorption.get() == "true":
5207 (str,link) = c((str,link), luxSpectrumTexture("Ka", keyname, "0.2 0.2 0.2", 1.0, "absorption", "", mat, gui, level+1))
5208 (str,link) = c((str,link), luxFloatTexture("d", keyname, 0.15, 0.0, 15.0, "depth", "", mat, gui, level+1))
5209 has_bump_options = 1
5210 has_object_options = 1
5211 has_emission_options = 1
5212 has_compositing_options = 1
5214 if mattype.get() == 'null':
5215 has_emission_options = 1
5217 # Bump mapping options (common)
5218 if (has_bump_options == 1):
5219 usebump = luxProp(mat, keyname+".usebump", "false")
5220 luxCollapse("usebump", usebump, "Bump Map", "Enable Bump Mapping options", gui, 2.0)
5221 if usebump.get() == "true":
5222 (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))
5224 # emission options (common)
5226 if (has_emission_options == 1):
5227 if gui: gui.newline("", 2, level, None, [0.6,0.6,0.4])
5228 useemission = luxProp(mat, "emission", "false")
5229 luxCollapse("useemission", useemission, "Emission", "Enable emission options", gui, 2.0)
5230 if useemission.get() == "true":
5231 # emission GUI is here but lux export will be done later
5232 luxLight("", "", mat, gui, level)
5233 else: luxProp(mat, "emission", "false").set("false") # prevent from exporting later
5236 # Compositing options (common)
5237 # Note - currently only display options when using distributedpath integrator
5238 integratortype = luxProp(Scene.GetCurrent(), "sintegrator.type", "bidirectional")
5239 if (integratortype.get() == "distributedpath" and level == 0):
5240 if (has_compositing_options == 1):
5241 if gui: gui.newline("", 2, level, None, [0.4,0.4,0.6])
5242 usecompo = luxProp(mat, "compo", "false")
5243 luxCollapse("compo", usecompo, "Compositing", "Enable Compositing options", gui, 2.0)
5244 if usecompo.get() == "true":
5245 if gui: gui.newline("", 2, level, None, [0.35,0.35,0.55])
5246 usecompoviz = luxProp(mat, "compo_viz", "false")
5247 luxCollapse("compo_viz", usecompoviz, "Visibility", "Enable Visibility Compositing options", gui, 2.0)
5248 if usecompoviz.get() == "true":
5249 if gui: gui.newline("View", 2, level, None, [0.35,0.35,0.55])
5250 compovizmat = luxProp(mat, "compo_viz_mat", "true")
5251 link += luxBool("compo_visible_material", compovizmat, "Material", "Enable View Visibility of Material", gui, 1.0)
5252 compovizemi = luxProp(mat, "compo_viz_emi", "true")
5253 link += luxBool("compo_visible_emission", compovizemi, "Emission", "Enable View Visibility of Emission", gui, 1.0)
5255 if gui: gui.newline("Indirect", 2, level, None, [0.35,0.35,0.55])
5256 compovizmati = luxProp(mat, "compo_viz_mati", "true")
5257 link += luxBool("compo_visible_indirect_material", compovizmati, "Material", "Enable InDirect Visibility of Material", gui, 1.0)
5258 compovizemii = luxProp(mat, "compo_viz_emii", "true")
5259 link += luxBool("compo_visible_indirect_emission", compovizemii, "Emission", "Enable InDirect Visibility of Emission", gui, 1.0)
5261 if gui: gui.newline("", 2, level, None, [0.4,0.4,0.6])
5262 overridealpha = luxProp(mat, "compo_o_alpha", "false")
5263 link += luxCollapse("compo_override_alpha", overridealpha, "Override Alpha", "Enable Manual control of alpha value", gui, 2.0)
5264 if overridealpha.get() == "true":
5265 if gui: gui.newline("Alpha", 2, level, None, [0.4,0.4,0.6])
5266 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)
5267 usecolorkey = luxProp(mat, "compo_usekey", "false")
5268 if gui: gui.newline("", 2, level, None, [0.35,0.35,0.55])
5269 link += luxCollapse("compo_use_key", usecolorkey, "Chroma Key", "Enable Chroma Object key", gui, 2.0)
5270 if usecolorkey.get() == "true":
5271 if gui: gui.newline("Key", 2, level, None, [0.35,0.35,0.55])
5272 link += luxRGB("compo_key_color", luxProp(mat, "compo_key_color", "0.0 0.0 1.0"), 1.0, "key", "", gui, 2.0)
5274 # transformation options (common)
5275 if (level == 0) and mattype.get() not in ['portal', 'null']:
5276 if gui: gui.newline("", 2, level, None, [0.6,0.6,0.4])
5277 usetransformation = luxProp(mat, "transformation", "false")
5278 luxCollapse("usetransformation", usetransformation, "Texture Transformation", "Enable transformation option", gui, 2.0)
5279 if usetransformation.get() == "true":
5280 scale = luxProp(mat, "3dscale", 1.0)
5281 rotate = luxProp(mat, "3drotate", "0 0 0")
5282 translate = luxProp(mat, "3dtranslate", "0 0 0")
5284 gui.newline("scale:", -2, level, icon_map3dparam)
5285 luxVectorUniform("scale", scale, 0.001, 1000.0, "scale", "scale-vector", gui, 2.0)
5286 gui.newline("rot:", -2, level, icon_map3dparam)
5287 luxVector("rotate", rotate, -360.0, 360.0, "rotate", "rotate-vector", gui, 2.0)
5288 gui.newline("move:", -2, level, icon_map3dparam)
5289 luxVector("translate", translate, -1000.0, 1000.0, "move", "translate-vector", gui, 2.0)
5290 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"
5292 # Object options (common)
5293 if (level == 0) and (has_object_options == 1):
5294 if gui: gui.newline("Mesh:", 2, level, icon, [0.6,0.6,0.4])
5295 usesubdiv = luxProp(mat, "subdiv", "false")
5296 luxBool("usesubdiv", usesubdiv, "Subdivision", "Enable Loop Subdivision options", gui, 1.0)
5297 usedisp = luxProp(mat, "dispmap", "false")
5298 luxBool("usedisp", usedisp, "Displacement Map", "Enable Displacement mapping options", gui, 1.0)
5299 if usesubdiv.get() == "true" or usedisp.get() == "true":
5300 luxInt("sublevels", luxProp(mat, "sublevels", 2), 0, 12, "sublevels", "The number of levels of object subdivision", gui, 2.0)
5301 sharpbound = luxProp(mat, "sharpbound", "false")
5302 luxBool("sharpbound", sharpbound, "Sharpen Bounds", "Sharpen boundaries during subdivision", gui, 1.0)
5303 nsmooth = luxProp(mat, "nsmooth", "true")
5304 luxBool("nsmooth", nsmooth, "Smooth", "Smooth faces during subdivision", gui, 1.0)
5305 if usedisp.get() == "true":
5306 (str,ll) = c((str,link), luxDispFloatTexture("dispmap", keyname, 0.1, -10, 10.0, "dispmap", "Displacement Mapping amount", mat, gui, level+1))
5307 luxFloat("sdoffset", luxProp(mat, "sdoffset", 0.0), 0.0, 1.0, "Offset", "Offset for displacement map", gui, 2.0)
5308 usesubdiv.set("true")
5310 if mattype.get() == "light":
5313 str += "MakeNamedMaterial \"%s\"%s\n"%(matname, link)
5314 return (str, " \"string %s\" [\"%s\"]"%(luxname, matname))
5317 def luxMaterial(mat, gui=None):
5320 if luxProp(mat, "type", "").get()=="": # lux material not defined yet
5321 print("Blender material \"%s\" has no lux material definition, converting..."%(mat.getName()))
5323 convertMaterial(mat) # try converting the blender material to a lux material
5325 (str, link) = luxMaterialBlock("", "", "", mat, gui, 0)
5326 if luxProp(mat, "type", "matte").get() != "light":
5327 link = "NamedMaterial \"%s\""%(mat.getName())
5328 # export emission options (no gui)
5329 useemission = luxProp(mat, "emission", "false")
5330 if useemission.get() == "true":
5331 lightgroup = luxProp(mat, "light.lightgroup", "default")
5332 if luxProp(Scene.GetCurrent(), "nolg", "false").get()!="true":
5333 link += "\n\tLightGroup \"%s\"\n"%lightgroup.get()
5335 (estr, elink) = luxLight("", "", mat, None, 0)
5337 link += "\n\tAreaLightSource \"area\" "+elink
5339 luxProp(mat, "link", "").set("".join(link))
5344 def luxVolume(mat, gui=None):
5347 (str, link) = luxMaterialBlock("", "", "", mat, gui, 0)
5348 luxProp(mat, "link", "").set("".join(link))
5351 runRenderAfterExport = None
5352 def CBluxExport(default, run):
5353 global runRenderAfterExport
5354 runRenderAfterExport = run
5356 datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
5357 if datadir=="": datadir = Blender.Get("datadir")
5359 if not os.path.exists(datadir):
5360 Draw.PupMenu("ERROR: output directory does not exist!")
5364 filename = datadir + os.sep + "default.lxs"
5365 save_still(filename)
5367 Window.FileSelector(save_still, "Export", sys.makename(Blender.Get("filename"), ".lxs"))
5370 def CBluxAnimExport(default, run, fileselect=True):
5372 datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
5373 if datadir=="": datadir = Blender.Get("datadir")
5375 if not os.path.exists(datadir):
5376 Draw.PupMenu("ERROR: output directory does not exist!")
5380 filename = datadir + os.sep + "default.lxs"
5384 Window.FileSelector(save_anim, "Export", sys.makename(Blender.Get("filename"), ".lxs"))
5386 datadir = luxProp(Scene.GetCurrent(), "datadir", "").get()
5387 if datadir=="": datadir = Blender.Get("datadir")
5388 filename = sys.makename(Blender.Get("filename") , ".lxs")
5392 # convert a Blender material to lux material
5393 def convertMaterial(mat):
5395 if str != "": return str+"."
5398 if str != "": return str+":"
5400 def mapConstDict(value, constant_dict, lux_dict, default=None):
5401 for k,v in constant_dict.items():
5402 if (v == value) and (lux_dict.has_key(k)):
5406 def convertMapping(name, tex):
5407 if tex.texco == Texture.TexCo["UV"]:
5408 luxProp(mat, dot(name)+"mapping","").set("uv")
5409 luxProp(mat, dot(name)+"uscale", 1.0).set(tex.size[0])
5410 luxProp(mat, dot(name)+"vscale", 1.0).set(-tex.size[1])
5411 luxProp(mat, dot(name)+"udelta", 0.0).set(tex.ofs[0]+0.5*(1.0-tex.size[0]))
5412 luxProp(mat, dot(name)+"vdelta", 0.0).set(-tex.ofs[1]-0.5*(1.0-tex.size[1]))
5413 if tex.mapping != Texture.Mappings["FLAT"]:
5414 print("Material Conversion Warning: for UV-texture-input only FLAT mapping is supported\n")
5416 if tex.mapping == Texture.Mappings["FLAT"]:
5417 luxProp(mat, dot(name)+"mapping","").set("planar") # make planar-mapping convert correctly from blender(WYSIWYG)- jens
5418 luxProp(mat, dot(name)+"v1", "1.0 1.0 1.0").setVector((0.5*tex.size[0], 0.0, 0.0))
5419 luxProp(mat, dot(name)+"v2", "0.0 0.0 0.0").setVector((0.0, -0.5*tex.size[1], -0.0))
5420 luxProp(mat, dot(name)+"udelta", 0.0).set(tex.ofs[0]+0.5)
5421 luxProp(mat, dot(name)+"vdelta", 0.0).set(-tex.ofs[1]-0.5)
5422 elif tex.mapping == Texture.Mappings["TUBE"]:
5423 luxProp(mat, dot(name)+"mapping","").set("cylindrical")
5424 elif tex.mapping == Texture.Mappings["SPHERE"]:
5425 luxProp(mat, dot(name)+"mapping","").set("spherical")
5426 else: luxProp(mat, dot(name)+"mapping","").set("planar")
5428 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]))
5429 luxProp(mat, dot(name)+"3dtranslate", "0.0 0.0 0.0").setVector((-tex.ofs[0], -tex.ofs[1], -tex.ofs[2]))
5431 def convertColorband(colorband):
5432 # colorbands are not supported in lux - so lets extract a average low-side and high-side color
5433 cb = [colorband[0]] + colorband[:] + [colorband[-1]]
5434 cb[0][4], cb[-1][4] = 0.0, 1.0
5435 low, high = [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]
5436 for i in range(1, len(cb)):
5438 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])
5439 high[c] += (cb[i-1][c]*cb[i-1][4] + cb[i][c]*cb[i][4]) * (cb[i][4]-cb[i-1][4])
5442 def createLuxTexture(name, tex):
5444 convertMapping(name, tex)
5445 if (texture.type == Texture.Types["IMAGE"]) and (texture.image) and (texture.image.filename!=""):
5446 luxProp(mat, dot(name)+"texture", "").set("imagemap")
5447 luxProp(mat, dot(name)+"filename", "").set(texture.image.filename)
5448 luxProp(mat, dot(name)+"wrap", "").set(mapConstDict(texture.extend, Texture.ExtendModes, {"REPEAT":"repeat", "EXTEND":"clamp", "CLIP":"black"}, ""))
5450 if tex.texco != Texture.TexCo["GLOB"]:
5451 print("Material Conversion Warning: procedural textures supports global mapping only\n")
5452 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"}
5453 luxProp(mat, dot(name)+"bright", 1.0).set(texture.brightness)
5454 luxProp(mat, dot(name)+"contrast", 1.0).set(texture.contrast)
5455 if texture.type == Texture.Types["CLOUDS"]:
5456 luxProp(mat, dot(name)+"texture", "").set("blender_clouds")
5457 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"CLD_DEFAULT":"default", "CLD_COLOR":"color"}, ""))
5458 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
5459 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5460 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
5461 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5462 elif texture.type == Texture.Types["WOOD"]:
5463 luxProp(mat, dot(name)+"texture", "").set("blender_wood")
5464 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"WOD_BANDS":"bands", "WOD_RINGS":"rings", "WOD_BANDNOISE":"bandnoise", "WOD_RINGNOISE":"ringnoise"}, ""))
5465 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, {"SINE":"sin", "SAW":"saw", "TRI":"tri"}, ""))
5466 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5467 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
5468 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5469 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
5470 elif texture.type == Texture.Types["MUSGRAVE"]:
5471 luxProp(mat, dot(name)+"texture", "").set("blender_musgrave")
5472 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"}, ""))
5473 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5474 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5475 # 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)
5476 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
5477 else: luxProp(mat, dot(name)+"h", 1.0).set(0.5) # use a default value
5478 # bug in blender python API: values "offset" and "gain" are missing in Python-API (reported to Ideasman42 - will be fixed after Blender 2.47)
5480 luxProp(mat, dot(name)+"offset", 1.0).set(texture.offset)
5481 luxProp(mat, dot(name)+"gain", 1.0).set(texture.gain)
5482 except AttributeError: pass
5483 luxProp(mat, dot(name)+"lacu", 2.0).set(texture.lacunarity)
5484 luxProp(mat, dot(name)+"octs", 2.0).set(texture.octs)
5485 luxProp(mat, dot(name)+"outscale", 1.0).set(texture.iScale)
5486 elif texture.type == Texture.Types["MARBLE"]:
5487 luxProp(mat, dot(name)+"texture", "").set("blender_marble")
5488 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"MBL_SOFT":"soft", "MBL_SHARP":"sharp", "MBL_SHARPER":"sharper"}, ""))
5489 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
5490 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
5491 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
5492 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5493 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, {"SINE":"sin", "SAW":"saw", "TRI":"tri"}, ""))
5494 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5495 elif texture.type == Texture.Types["VORONOI"]:
5496 luxProp(mat, dot(name)+"texture", "").set("blender_voronoi")
5497 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])
5498 luxProp(mat, dot(name)+"outscale", 1.0).set(texture.iScale)
5499 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5500 luxProp(mat, dot(name)+"minkosky_exp", 2.5).set(texture.exp)
5501 luxProp(mat, dot(name)+"w1", 1.0).set(texture.weight1)
5502 luxProp(mat, dot(name)+"w2", 0.0).set(texture.weight2)
5503 luxProp(mat, dot(name)+"w3", 0.0).set(texture.weight3)
5504 luxProp(mat, dot(name)+"w4", 0.0).set(texture.weight4)
5505 elif texture.type == Texture.Types["NOISE"]:
5506 luxProp(mat, dot(name)+"texture", "").set("blender_noise")
5507 elif texture.type == Texture.Types["DISTNOISE"]:
5508 luxProp(mat, dot(name)+"texture", "").set("blender_distortednoise")
5509 luxProp(mat, dot(name)+"distamount", 1.0).set(texture.distAmnt)
5510 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5511 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5512 luxProp(mat, dot(name)+"noisebasis2", "").set(mapConstDict(texture.noiseBasis2, Texture.Noise, noiseDict, ""))
5513 elif texture.type == Texture.Types["MAGIC"]:
5514 luxProp(mat, dot(name)+"texture", "").set("blender_magic")
5515 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
5516 luxProp(mat, dot(name)+"noisedepth", 2).set(texture.noiseDepth)
5517 elif texture.type == Texture.Types["STUCCI"]:
5518 luxProp(mat, dot(name)+"texture", "").set("blender_stucci")
5519 luxProp(mat, dot(name)+"mtype", "").set(mapConstDict(texture.stype, Texture.STypes, {"STC_PLASTIC":"Plastic", "MSTC_WALLIN":"Wall In", "STC_WALLOUT":"Wall Out"}, ""))
5520 luxProp(mat, dot(name)+"noisetype", "").set({"soft":"soft_noise", "hard":"hard_noise"}[texture.noiseType])
5521 luxProp(mat, dot(name)+"noisesize", 0.25).set(texture.noiseSize)
5522 luxProp(mat, dot(name)+"turbulance", 0.25).set(texture.turbulence)
5523 luxProp(mat, dot(name)+"noisebasis", "").set(mapConstDict(texture.noiseBasis, Texture.Noise, noiseDict, ""))
5524 elif texture.type == Texture.Types["BLEND"]:
5525 luxProp(mat, dot(name)+"texture", "").set("blender_blend")
5526 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"}, ""))
5527 luxProp(mat, dot(name)+"flipXY", "false").set({0:"false", 1:"true"}[texture.rot90])
5529 print("Material Conversion Warning: SORRY, this procedural texture isn\'t implemented in conversion\n")
5531 def convertTextures(basename, texs, type="float", channel="col", val=1.0):
5534 isImagemap = (texture.type == Texture.Types["IMAGE"]) and (texture.image) and (texture.image.filename!="")
5535 if channel == "col":
5536 if texture.flags & Texture.Flags["COLORBAND"] > 0:
5537 cbLow, cbHigh = convertColorband(texture.colorband)
5538 val1, alpha1, val2, alpha2 = (cbLow[0],cbLow[1],cbLow[2]), cbLow[3]*tex.colfac, (cbHigh[0], cbHigh[1], cbHigh[2]), cbHigh[3]*tex.colfac
5540 lum1, lum2 = (val1[0]+val1[1]+val1[2])/3.0, (val2[0]+val2[1]+val2[2])/3.0
5541 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)
5542 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
5543 else: val1, alpha1, val2, alpha2 = tex.col, 0.0, tex.col, tex.colfac
5544 elif channel == "nor": val1, alpha1, val2, alpha2 = tex.norfac * 0.01, 0.0, tex.norfac * 0.01, 1.0
5545 else: val1, alpha1, val2, alpha2 = 1.0, 0.0, 1.0, tex.varfac
5546 if (tex.neg)^((channel=="nor") and (tex.mtNor<0)): val1, alpha1, val2, alpha2 = val2, alpha2, val1, alpha1
5547 luxProp(mat, dot(basename)+"textured", "").set("true")
5550 if (alpha1 < 1.0) or (alpha2 < 1.0): # texture with transparency
5551 luxProp(mat, dot(basename)+"texture", "").set("mix")
5552 if alpha1 == alpha2: # constant alpha
5553 luxProp(mat, ddot(basename)+"amount.value", 1.0).set(alpha1)
5555 createLuxTexture(ddot(basename)+"amount", tex)
5556 luxProp(mat, ddot(basename)+"amount:tex1.value", 1.0).set(alpha1)
5557 luxProp(mat, ddot(basename)+"amount:tex2.value", 1.0).set(alpha2)
5558 # transparent to next texture
5559 name = ddot(basename)+"tex1"
5561 convertTextures(ddot(basename)+"tex1", texs, type, channel, val)
5563 if type=="float": luxProp(mat, ddot(basename)+"tex1.value", 1.0).set(val)
5564 else: luxProp(mat, ddot(basename)+"tex1.value", "1.0 1.0 1.0").setRGB((val[0], val[1], val[2]))
5565 name = ddot(basename)+"tex2"
5566 if val1 == val2: # texture with different colors / value
5567 if type == "col": luxProp(mat, dot(name)+"value", "1.0 1.0 1.0").setRGB(val1)
5568 else: luxProp(mat, dot(name)+"value", 1.0).set(val1)
5570 createLuxTexture(name, tex)
5571 if type == "col": luxProp(mat, ddot(name)+"tex1.value", "1.0 1.0 1.0").setRGB(val1)
5572 else: luxProp(mat, ddot(name)+"tex1.value", 1.0).set(val1)
5573 if type == "col": luxProp(mat, ddot(name)+"tex2.value", "1.0 1.0 1.0").setRGB(val2)
5574 else: luxProp(mat, ddot(name)+"tex2.value", 1.0).set(val2)
5577 def convertDiffuseTexture(name):
5579 for tex in mat.getTextures():
5580 if tex and (tex.mapto & Texture.MapTo["COL"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
5582 luxProp(mat, name, "").setRGB((mat.ref, mat.ref, mat.ref))
5583 convertTextures(name, texs, "col", "col", (mat.R, mat.G, mat.B))
5584 def convertSpecularTexture(name):
5586 for tex in mat.getTextures():
5587 if tex and (tex.mapto & Texture.MapTo["CSP"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
5589 luxProp(mat, name, "").setRGB((mat.ref*mat.spec, mat.ref*mat.spec, mat.ref*mat.spec))
5590 convertTextures(name, texs, "col", "col", (mat.specR, mat.specG, mat.specB))
5591 def convertMirrorTexture(name):
5593 for tex in mat.getTextures():
5594 if tex and (tex.mapto & Texture.MapTo["CMIR"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
5596 luxProp(mat, name, "").setRGB((mat.ref, mat.ref, mat.ref))
5597 convertTextures(name, texs, "col", "col", (mat.mirR, mat.mirG, mat.mirB))
5598 def convertBumpTexture(basename):
5600 for tex in mat.getTextures():
5601 if tex and (tex.mapto & Texture.MapTo["NOR"] > 0) and (tex.tex) and (tex.tex.type != Texture.Types["NONE"]): texs.append(tex)
5603 name = basename+":bumpmap"
5604 luxProp(mat, basename+".usebump", "").set("true")
5605 luxProp(mat, dot(name)+"textured", "").set("true")
5606 luxProp(mat, name, "").set(1.0)
5607 convertTextures(name, texs, "float", "nor", 0.0)
5609 def makeMatte(name):
5610 luxProp(mat, dot(name)+"type", "").set("matte")
5611 luxProp(mat, name+":Kd", "").setRGB((mat.R*mat.ref, mat.G*mat.ref, mat.B*mat.ref))
5612 convertDiffuseTexture(name+":Kd")
5613 convertBumpTexture(name)
5614 def makeGlossy(name, roughness):
5615 luxProp(mat, dot(name)+"type", "").set("glossy")
5616 luxProp(mat, name+":Kd", "").setRGB((mat.R*mat.ref, mat.G*mat.ref, mat.B*mat.ref))
5617 luxProp(mat, name+":Ks", "").setRGB((mat.specR*mat.spec*0.5, mat.specG*mat.spec*0.5, mat.specB*mat.spec*0.5))
5618 luxProp(mat, name+":uroughness", 0.0).set(roughness)
5619 luxProp(mat, name+":vroughness", 0.0).set(roughness)
5620 convertDiffuseTexture(name+":Kd")
5621 convertSpecularTexture(name+":Ks")
5622 convertBumpTexture(name)
5623 def makeMirror(name):
5624 luxProp(mat, dot(name)+"type", "").set("mirror")
5625 luxProp(mat, name+":Kr", "").setRGB((mat.mirR, mat.mirG, mat.mirB))
5626 convertMirrorTexture(name+":Kr")
5627 convertBumpTexture(name)
5628 def makeGlass(name):
5629 luxProp(mat, dot(name)+"type", "").set("glass")
5630 luxProp(mat, name+":Kr", "").setRGB((0.0, 0.0, 0.0))
5631 luxProp(mat, name+":Kt", "").setRGB((mat.R, mat.G, mat.B))
5632 luxProp(mat, name+":index.iorusepreset", "").set("false")
5633 luxProp(mat, name+":index", 0.0).set(mat.getIOR())
5634 convertMirrorTexture(name+":Kr")
5635 convertDiffuseTexture(name+":Kt")
5636 convertBumpTexture(name)
5637 def makeRoughglass(name, roughness):
5638 luxProp(mat, dot(name)+"type", "").set("roughglass")
5639 luxProp(mat, name+":Kr", "").setRGB((0.0, 0.0, 0.0))
5640 luxProp(mat, name+":Kt", "").setRGB((mat.R, mat.G, mat.B))
5641 luxProp(mat, name+":index.iorusepreset", "").set("false")
5642 luxProp(mat, name+":index", 0.0).set(mat.getIOR())
5643 luxProp(mat, name+":uroughness", 0.0).set(roughness)
5644 luxProp(mat, name+":vroughness", 0.0).set(roughness)
5645 convertMirrorTexture(name+":Kr")
5646 convertDiffuseTexture(name+":Kt")
5647 convertBumpTexture(name)
5648 print("convert Blender material \"%s\" to lux material"%(mat.name))
5649 mat.properties['luxblend'] = {}
5650 if mat.emit > 0.0001:
5651 luxProp(mat, "type", "").set("light")
5652 luxProp(mat, "light.l", "").setRGB((mat.R, mat.G, mat.B))
5653 luxProp(mat, "light.gain", 1.0).set(mat.emit)
5656 if not(mat.mode & Material.Modes.RAYTRANSP): alpha = 1.0
5657 alpha0name, alpha1name = "", ""
5658 if (alpha > 0.0) and (alpha < 1.0):
5659 luxProp(mat, "type", "").set("mix")
5660 luxProp(mat, ":amount", 0.0).set(alpha)
5661 alpha0name, alpha1name = "mat2", "mat1"
5663 mirror = mat.rayMirr
5664 if not(mat.mode & Material.Modes.RAYMIRROR): mirror = 0.0
5665 mirror0name, mirror1name = alpha1name, alpha1name
5666 if (mirror > 0.0) and (mirror < 1.0):
5667 luxProp(mat, dot(alpha1name)+"type", "").set("mix")
5668 luxProp(mat, alpha1name+":amount", 0.0).set(1.0 - mirror)
5669 mirror0name, mirror1name = ddot(alpha1name)+"mat1", ddot(alpha1name)+"mat2"
5671 if mat.glossMir < 1.0: makeGlossy(mirror1name, 1.0-mat.glossMir**2)
5672 else: makeMirror(mirror1name)
5674 if mat.spec > 0.0: makeGlossy(mirror0name, 1.0/mat.hard)
5675 else: makeMatte(mirror0name)
5677 if mat.glossTra < 1.0: makeRoughnessGlass(alpha0name, 1.0-mat.glossTra**2)
5678 else: makeGlass(alpha0name)
5680 def convertAllMaterials():
5681 for mat in Material.Get(): convertMaterial(mat)
5686 ### Connect LRMDB ###
5687 ConnectLrmdb = False
5689 import socket # try import of socket library
5691 def downloadLRMDB(mat, id):
5693 DrawProgressBar(0.0,'Getting Material #'+id)
5695 HOST = 'www.luxrender.net'
5696 GET = '/lrmdb/en/material/download/'+id
5698 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
5699 sock.connect((HOST, PORT))
5700 sock.send("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (GET, HOST))
5701 data = sock.recv(1024)
5705 data = sock.recv(1024)
5707 if str.split("\n", 1)[0].find("200") < 0:
5708 print("ERROR: server error: %s"%(str.split("\n",1)[0]))
5710 str = (str.split("\r\n\r\n")[1]).strip()
5711 if (str[0]=="{") and (str[-1]=="}"):
5712 return str2MatTex(str)
5713 print("ERROR: downloaded data is not a material or texture")
5715 print("ERROR: download failed")
5717 DrawProgressBar(1.0,'')
5719 print("ERROR: material id is not valid")
5723 #===========================================================================
5725 #===========================================================================
5727 #---------------------------------------------------------------------------
5729 import cookielib, urllib2, xmlrpclib
5731 #---------------------------------------------------------------------------
5733 # https://fedorahosted.org/python-bugzilla/browser/bugzilla.py?rev=e6f699f06e92b1e49b1b8d2c8fbe89d9425a4a9a
5734 class CookieTransport(xmlrpclib.Transport):
5736 A subclass of xmlrpclib.Transport that supports cookies.
5743 # Cribbed from xmlrpclib.Transport.send_user_agent
5744 def send_cookies(self, connection, cookie_request):
5746 Send all the cookie data that we have received
5749 if self.cookiejar is None:
5750 self.cookiejar = cookielib.CookieJar()
5751 elif self.cookiejar:
5752 # Let the cookiejar figure out what cookies are appropriate
5753 self.cookiejar.add_cookie_header(cookie_request)
5754 # Pull the cookie headers out of the request object...
5756 for header, value in cookie_request.header_items():
5757 if header.startswith('Cookie'):
5758 cookielist.append([header, value])
5759 # ...and put them over the connection
5760 for header, value in cookielist:
5761 connection.putheader(header, value)
5763 # This is the same request() method from xmlrpclib.Transport,
5764 # with a couple additions noted below
5765 def request(self, host, handler, request_body, verbose=0):
5770 host_connection = self.make_connection(host)
5772 host_connection.set_debuglevel(1)
5774 # ADDED: construct the URL and Request object for proper cookie handling
5775 request_url = "%s://%s/" % (self.scheme, host)
5776 cookie_request = urllib2.Request(request_url)
5778 self.send_request(host_connection, handler, request_body)
5779 self.send_host(host_connection, host)
5781 # ADDED. creates cookiejar if None.
5782 self.send_cookies(host_connection, cookie_request)
5783 self.send_user_agent(host_connection)
5784 self.send_content(host_connection, request_body)
5786 errcode, errmsg, headers = host_connection.getreply()
5788 # ADDED: parse headers and get cookies here
5789 class CookieResponse:
5791 fake a response object that we can fill with the headers above
5794 def __init__(self, headers):
5795 self.headers = headers
5800 cookie_response = CookieResponse(headers)
5802 # Okay, extract the cookies from the headers
5803 self.cookiejar.extract_cookies(cookie_response, cookie_request)
5805 # And write back any changes
5806 # DH THIS DOESN'T WORK
5807 # self.cookiejar.save(self.cookiejar.filename)
5810 raise xmlrpclib.ProtocolError(
5816 self.verbose = verbose
5819 sock = host_connection._conn.sock
5820 except AttributeError:
5823 return self._parse_response(host_connection.getfile(), sock)
5826 #===========================================================================
5828 #===========================================================================
5830 host = 'http://www.luxrender.net/lrmdb/ixr'
5838 last_error_str = None
5840 def last_error(self):
5841 return self.last_error_str #'LRMDB Connector: %s' %
5845 result = self.SERVER.user.login(
5852 self.logged_in = True
5855 self.last_error_str = 'Login Failed'
5856 self.logged_in = False
5859 def submit_object(self, mat, basekey, tex):
5860 if not self.check_creds(): return False
5863 result = 'Unknown Error'
5866 name = Draw.PupStrInput('Name: ', '', 32)
5870 result = self.SERVER.object.submit(
5872 MatTex2dict( getMatTex(mat, basekey, tex), tex )
5874 if result is not True:
5879 self.last_error_str = 'Submit failed: %s' % result
5882 def check_creds(self):
5883 if self.SERVER is None:
5885 self.SERVER = xmlrpclib.ServerProxy(self.host, transport=CookieTransport())
5887 self.last_error_str = 'ServerProxy init failed'
5891 if not self.logged_in:
5892 #if self.username is "":
5893 self.request_username()
5895 #if self.password is "":
5896 self.request_password()
5902 def request_username(self):
5903 self.username = Draw.PupStrInput("Username:", self.username, 32)
5905 def request_password(self):
5906 self.password = Draw.PupStrInput("Password:", self.password, 32)
5908 lrmdb_connector = lrmdb()
5911 except: print("WARNING: LRMDB support not available")
5915 ### MatTex functions ###
5916 ### MatTex : is a dictionary of material or texture properties
5918 def getMatTex(mat, basekey='', tex=False):
5919 global usedproperties, usedpropertiesfilterobj
5921 usedpropertiesfilterobj = mat
5924 for k,v in usedproperties.items():
5925 if k[:len(basekey)]==basekey:
5926 if k[-9:] != '.textured':
5927 name = k[len(basekey):]
5928 if name == ".type": name = "type"
5930 dict["__type__"] = ["material","texture"][bool(tex)]
5933 def putMatTex(mat, dict, basekey='', tex=None):
5934 if dict and (tex!=None) and (tex ^ (dict.has_key("__type__") and (dict["__type__"]=="texture"))):
5935 print("ERROR: Can't apply %s as %s"%(["texture","material"][bool(tex)],["material","texture"][bool(tex)]))
5938 # remove all current properties in mat that starts with basekey
5940 d = mat.properties['luxblend']
5941 for k,v in d.convert_to_pyobject().items():
5943 if k[:7]=="__hash:": # decode if entry is hashed (cause of 32chars limit)
5946 if kn[:len(basekey)]==basekey:
5947 del mat.properties['luxblend'][k]
5948 except: print("error") # pass
5949 # assign loaded properties
5950 for k,v in dict.items():
5952 if (basekey!="") and (k=="type"): k = ".type"
5953 # zuegs: following two lines should fix issue http://www.luxrender.net/forum/viewtopic.php?f=16&t=1618&p=14512#p14512
5954 if (basekey!="") and ((k[0]!=".") and (k[0]!=":")): k = ":"+k
5955 if (basekey=="") and (k[0:4]==":mat"): k = k[1:]
5956 luxProp(mat, basekey+k, None).set(v)
5957 if k[-8:] == '.texture':
5958 luxProp(mat, basekey+k[:-8]+'.textured', 'false').set('true')
5964 def MatTex2dict(d, tex = None):
5967 if LBX_VERSION == '0.6':
5969 if tex is not None and tex == True:
5970 d['LUX_DATA'] = 'TEXTURE'
5972 d['LUX_DATA'] = 'MATERIAL'
5974 d['LUX_VERSION'] = '0.6'
5978 elif LBX_VERSION == '0.7':
5981 if type(d[k]) == types.IntType:
5983 if type(d[k]) == types.FloatType:
5985 if type(d[k]) == types.BooleanType:
5987 if type(d[k]) == types.StringType:
5992 if l==None or len(l)!=3:
5997 definition.append([ t, k, d[k] ])
6001 'type': d['__type__'],
6003 'definition': definition,
6005 ['string', 'generator', 'luxblend'],
6011 def format_dictStr(dictStr):
6017 for char in dictStr:
6018 if char in ['}', ']']:
6021 for j in range(0,pos):
6026 if char in [',', '{', '[']:
6028 if char in ['{', '[']:
6030 for j in range(0,pos):
6036 def MatTex2str(d, tex = None):
6039 if LBX_VERSION == '0.6':
6040 return format_dictStr(str( MatTex2dict(d, tex) )) #.replace(", \'", ",\n\'")
6042 elif LBX_VERSION == '0.7':
6043 return format_dictStr(str( MatTex2dict(d, tex) )) #.replace("], \'", "],\r\n\'").replace("[","\r\n\t[")
6046 def str2MatTex(s, tex = None): # todo: this is not absolutely save from attacks!!!
6050 if (s[0]=='{') and (s[-1]=='}'):
6051 d = eval(s, dict(__builtins__=None))
6052 if type(d)==types.DictType:
6055 if LBX_VERSION == '0.6':
6057 if tex is not None and tex == True:
6058 test_str = 'TEXTURE'
6060 test_str = 'MATERIAL'
6062 if ('LUX_DATA' in d.keys() and d['LUX_DATA'] == test_str) \
6063 and ('LUX_VERSION' in d.keys() and (d['LUX_VERSION'] == '0.6' or d['LUX_VERSION'] == 0.6)):
6066 reason = 'Missing/incorrect metadata'
6068 elif LBX_VERSION == '0.7':
6070 def lb_list_to_dict(list):
6072 for t, k, v in list:
6079 if ('version' in d.keys() and d['version'] in ['0.6', '0.7']) \
6080 and ('type' in d.keys() and d['type'] in ['material', 'texture']) \
6081 and ('definition' in d.keys()):
6085 definition = lb_list_to_dict(d['definition'])
6087 if 'metadata' in d.keys():
6088 definition.update( lb_list_to_dict(d['metadata']) )
6092 reason = 'Incorrect LBX definition data'
6094 reason = 'Missing/incorrect metadata'
6096 reason = 'Unknown LBX version'
6098 reason = 'Not a parsed dict'
6100 reason = 'Not a stored dict'
6103 print("ERROR: string to material/texture conversion failed: %s" % reason)
6107 luxclipboard = None # global variable for copy/paste content
6108 def showMatTexMenu(mat, basekey='', tex=False):
6109 global luxclipboard, ConnectLrmdb
6110 if tex: menu="Texture menu:%t"
6111 else: menu="Material menu:%t"
6114 if luxclipboard and (not(tex) ^ (luxclipboard["__type__"]=="texture")): menu +="|Paste%x2"
6117 menu += "|Load LBT%x3|Save LBT%x4"
6119 menu += "|Load LBM%x3|Save LBM%x4"
6121 menu += "|Download from DB%x5" #not(tex) and
6122 menu += "|Upload to DB%x6"
6124 # menu += "|%l|dump material%x99|dump clipboard%x98"
6125 r = Draw.PupMenu(menu)
6127 luxclipboard = getMatTex(mat, basekey, tex)
6128 elif r==2: putMatTex(mat, luxclipboard, basekey, tex)
6130 scn = Scene.GetCurrent()
6132 Window.FileSelector(lambda fn:loadMatTex(mat, fn, basekey, tex), "load texture", luxProp(scn, "lux", "").get()+os.sep+".lbt")
6134 Window.FileSelector(lambda fn:loadMatTex(mat, fn, basekey, tex), "load material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
6136 scn = Scene.GetCurrent()
6138 Window.FileSelector(lambda fn:saveMatTex(mat, fn, basekey, tex), "save texture", luxProp(scn, "lux", "").get()+os.sep+".lbt")
6140 Window.FileSelector(lambda fn:saveMatTex(mat, fn, basekey, tex), "save material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
6143 id = Draw.PupStrInput("Material ID:", "", 32)
6145 id = Draw.PupStrInput("Texture ID:", "", 32)
6146 if id: putMatTex(mat, downloadLRMDB(mat, id), basekey, tex)
6148 global lrmdb_connector
6149 if not lrmdb_connector.submit_object(mat, basekey, tex):
6150 msg = lrmdb_connector.last_error()
6154 Draw.PupMenu("Upload: "+msg+".%t|OK")
6156 # for k,v in mat.properties['luxblend'].convert_to_pyobject().items(): print(k+"="+repr(v))
6158 # for k,v in luxclipboard.items(): print(k+"="+repr(v))
6163 def saveMatTex(mat, fn, basekey='', tex=False):
6165 d = getMatTex(mat, basekey, tex)
6166 file = open(fn, 'w')
6167 file.write(MatTex2str(d, tex))
6169 if LuxIsGUI: Draw.Redraw()
6172 def loadMatTex(mat, fn, basekey='', tex=None):
6174 file = open(fn, 'rU')
6177 data = str2MatTex(data, tex)
6178 putMatTex(mat, data, basekey, tex)
6179 if LuxIsGUI: Draw.Redraw()
6183 def setactivemat(mat):
6191 self.position = 0 # current position at top (inside 0..height-viewHeight)
6192 self.height = 0 # total height of the content
6193 self.viewHeight = 0 # height of window
6194 self.x = 0 # horizontal position of the scrollbar
6195 self.scrolling = self.over = False # start without scrolling ;)
6196 def calcRects(self):
6197 # Blender doesn't give us direct access to the window size yet, but it does set the
6198 # GL scissor box for it, so we can get the size from that. (thx to Daniel Dunbar)
6199 size = BGL.Buffer(BGL.GL_FLOAT, 4)
6200 BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, size)
6201 size = size.list # [winx, winy, width, height]
6202 self.winrect = size[:]
6203 self.viewHeight = size[3]
6204 size[0], size[1] = size[2]-20, 0 # [scrollx1, scrolly1, scrollx2, scrolly2]
6206 if self.position < 0: self.position = 0
6207 if self.height < self.viewHeight: self.height = self.viewHeight
6208 if self.position > self.height-self.viewHeight: self.position = self.height-self.viewHeight
6209 self.factor = (size[3]-size[1]-4)/self.height
6210 self.sliderRect = [size[0]+2, size[3]-2-(self.position+self.viewHeight)*self.factor, size[2]-2, size[3]-2-self.position*self.factor]
6213 BGL.glColor3f(0.5,0.5,0.5); BGL.glRectf(self.rect[0],self.rect[1],self.rect[2],self.rect[3])
6214 if self.over or self.scrolling: BGL.glColor3f(1.0,1.0,0.7)
6215 else: BGL.glColor3f(0.7,0.7,0.7)
6216 BGL.glRectf(self.sliderRect[0],self.sliderRect[1],self.sliderRect[2],self.sliderRect[3])
6218 return self.viewHeight+self.position
6219 def scroll(self, delta):
6220 self.position = self.position + delta
6225 coord, buttons = Window.GetMouseCoords(), Window.GetMouseButtons()
6226 over = (coord[0]>=self.winrect[0]+self.rect[0]) and (coord[0]<=self.winrect[0]+self.rect[2]) and \
6227 (coord[1]>=self.winrect[1]+self.rect[1]) and (coord[1]<=self.winrect[1]+self.rect[3])
6228 if Window.MButs.L and buttons > 0:
6230 if self.factor > 0: self.scroll((self.lastcoord[1]-coord[1])/self.factor)
6233 self.scrolling = True
6234 self.lastcoord = coord
6235 elif self.scrolling:
6236 self.scrolling = False
6238 if self.over != over: Draw.Redraw()
6241 scrollbar = scrollbar()
6246 global icon_luxblend
6248 BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
6250 y = int(scrollbar.getTop()) # 420
6251 BGL.glColor3f(0.1,0.1,0.1); BGL.glRectf(0,0,440,y)
6252 BGL.glColor3f(1.0,0.5,0.0); BGL.glRasterPos2i(130,y-21); Draw.Text("v%s"%__version__)
6253 BGL.glColor3f(0.9,0.9,0.9)
6255 drawLogo(icon_luxblend, 6, y-25)
6257 scn = Scene.GetCurrent()
6259 luxpage = luxProp(scn, "page", 0)
6263 BGL.glRasterPos2i(10,y-45); Draw.Text("Render presets:")
6264 luxpreset = luxProp(scn, "preset", "1C - Final - medium MLT/Path Tracing (indoor) (recommended)")
6265 presets = getScenePresets()
6266 presetskeys = presets.keys()
6268 presetskeys.insert(0, "")
6269 presetsstr = "presets: %t"
6270 for i, v in enumerate(presetskeys): presetsstr = "%s %%x%d|%s"%(v, i, presetsstr)
6271 try: i = presetskeys.index(luxpreset.get())
6272 except ValueError: i = 0
6273 Draw.Menu(presetsstr, evtLuxGui, 110, y-50, 220, 18, i, "", lambda e,v: luxpreset.set(presetskeys[v]))
6274 Draw.Button("save", evtSavePreset, 330, y-50, 40, 18, "create a render-settings preset")
6275 Draw.Button("del", evtDeletePreset, 370, y-50, 40, 18, "delete a render-settings preset")
6277 # if preset is selected load values
6278 if luxpreset.get() != "":
6280 d = presets[luxpreset.get()]
6281 for k,v in d.items(): scn.properties['luxblend'][k] = v
6284 Draw.Button("Material", evtLuxGui, 10, y-70, 80, 16, "", lambda e,v:luxpage.set(0))
6285 Draw.Button("Cam/Env", evtLuxGui, 90, y-70, 80, 16, "", lambda e,v:luxpage.set(1))
6286 Draw.Button("Render", evtLuxGui, 170, y-70, 80, 16, "", lambda e,v:luxpage.set(2))
6287 Draw.Button("Output", evtLuxGui, 250, y-70, 80, 16, "", lambda e,v:luxpage.set(3))
6288 Draw.Button("System", evtLuxGui, 330, y-70, 80, 16, "", lambda e,v:luxpage.set(4))
6289 if luxpage.get() == 0:
6290 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(10,y-74,90,y-70);BGL.glColor3f(0.9,0.9,0.9)
6291 obj = scn.objects.active
6293 if (obj.getType() == "Lamp"):
6294 ltype = obj.getData(mesh=1).getType() # data
6295 if (ltype == Lamp.Types["Area"]): luxLight("Area LIGHT", "", obj, gui, 0)
6296 elif (ltype == Lamp.Types["Spot"]): luxSpot("Spot LIGHT", "", obj, gui, 0)
6297 elif (ltype == Lamp.Types["Lamp"]): luxLamp("Point LIGHT", "", obj, gui, 0)
6299 matfilter = luxProp(scn, "matlistfilter", "false")
6300 mats = getMaterials(obj, True)
6301 if (activemat == None) and (len(mats) > 0):
6302 setactivemat(mats[0])
6303 if matfilter.get() == "false":
6304 mats = Material.Get()
6306 for i, v in enumerate(mats):
6307 if v==activemat: matindex = i
6308 matnames = [m.getName() for m in mats]
6309 menustr = "Material: %t"
6310 for i, v in enumerate(matnames): menustr = "%s %%x%d|%s"%(v, i, menustr)
6311 gui.newline("MATERIAL:", 8)
6312 r = gui.getRect(1.1, 1)
6313 Draw.Button("C", evtConvertMaterial, r[0]-gui.h, gui.y-gui.h, gui.h, gui.h, "convert blender material to lux material")
6314 Draw.Menu(menustr, evtLuxGui, r[0], r[1], r[2], r[3], matindex, "", lambda e,v: setactivemat(mats[v]))
6315 luxBool("", matfilter, "filter", "only show active object materials", gui, 0.5)
6317 Draw.Button("L", evtLoadMaterial, gui.x, gui.y-gui.h, gui.h, gui.h, "load a material preset")
6318 Draw.Button("S", evtSaveMaterial, gui.x+gui.h, gui.y-gui.h, gui.h, gui.h, "save a material preset")
6319 Draw.Button("D", evtDeleteMaterial, gui.x+gui.h*2, gui.y-gui.h, gui.h, gui.h, "delete a material preset")
6321 setactivemat(mats[matindex])
6322 luxMaterial(activemat, gui)
6323 if luxpage.get() == 1:
6324 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(90,y-74,170,y-70);BGL.glColor3f(0.9,0.9,0.9)
6325 cam = scn.getCurrentCamera()
6327 r = gui.getRect(1.1, 1)
6328 luxCamera(cam.data, scn.getRenderingContext(), gui)
6330 luxEnvironment(scn, gui)
6331 if luxpage.get() == 2:
6332 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(170,y-74,250,y-70);BGL.glColor3f(0.9,0.9,0.9)
6333 r = gui.getRect(1.1, 1)
6334 luxSampler(scn, gui)
6336 luxSurfaceIntegrator(scn, gui)
6338 luxVolumeIntegrator(scn, gui)
6340 luxPixelFilter(scn, gui)
6341 if luxpage.get() == 3:
6342 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(250,y-74,330,y-70);BGL.glColor3f(0.9,0.9,0.9)
6343 r = gui.getRect(1.1, 1)
6345 if luxpage.get() == 4:
6346 BGL.glColor3f(1.0,0.5,0.0);BGL.glRectf(330,y-74,410,y-70);BGL.glColor3f(0.9,0.9,0.9)
6349 luxAccelerator(scn, gui)
6350 gui.newline("MATERIALS:", 10)
6351 r = gui.getRect(2,1)
6352 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())
6353 gui.newline("SETTINGS:", 10)
6354 r = gui.getRect(2,1)
6355 Draw.Button("save defaults", 0, r[0], r[1], r[2], r[3], "save current settings as defaults", lambda e,v:saveluxdefaults())
6357 if y > 0: y = 0 # bottom align of render button
6358 run = luxProp(scn, "run", "true")
6359 dlt = luxProp(scn, "default", "true")
6360 pipe = luxProp(scn, "pipe", "false")
6361 clay = luxProp(scn, "clay", "false")
6362 nolg = luxProp(scn, "nolg", "false")
6363 lxs = luxProp(scn, "lxs", "true")
6364 lxo = luxProp(scn, "lxo", "true")
6365 lxm = luxProp(scn, "lxm", "true")
6366 lxv = luxProp(scn, "lxv", "true")
6367 net = luxProp(scn, "netrenderctl", "false")
6368 donet = luxProp(scn, "donetrender", "true")
6370 global render_status_text
6371 global render_status
6373 if render_status == True:
6374 BGL.glRasterPos2i(10,y+20)
6375 Draw.Text(render_status_text)
6377 BGL.glRasterPos2i(10,y+5)
6378 Draw.Text(render_status_text, "tiny")
6380 def check_pipe_def_exclusion(m, v):
6382 dlt.set(["false","true"][bool(v)])
6384 if dlt.get() == 'true':
6387 pipe.set(["false","true"][bool(v)])
6389 if pipe.get() == 'true':
6392 if (run.get()=="true"):
6393 Draw.Button("Render", 0, 10, y+20, 100, 36, "Render with Lux", lambda e,v:CBluxExport(dlt.get()=="true" or pipe.get()=="true", True))
6394 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))
6396 Draw.Button("Export", 0, 10, y+20, 100, 36, "Export", lambda e,v:CBluxExport(dlt.get()=="true" or pipe.get()=="true", False))
6397 Draw.Button("Export Anim", 0, 110, y+20, 100, 36, "Export animation", lambda e,v:CBluxAnimExport(dlt.get()=="true" or pipe.get()=="true", False))
6399 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)]))
6401 if (pipe.get() == 'false' and dlt.get() == 'true') or run.get()=='false':
6402 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))
6403 elif pipe.get() == 'true' and dlt.get() == 'false':
6404 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))
6406 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))
6407 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))
6409 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)]))
6410 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)]))
6412 if pipe.get() == "false":
6413 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)]))
6414 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)]))
6415 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)]))
6416 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)]))
6418 BGL.glColor3f(0.9, 0.9, 0.9)
6420 BGL.glRasterPos2i(330,y+5) ; Draw.Text("Press Q or ESC to quit.", "tiny")
6421 scrollbar.height = scrollbar.getTop() - y
6424 render_status_text = ''
6425 render_status = False
6440 def luxEvent(evt, val): # function that handles keyboard and mouse events
6441 global activeObject, activemat, activeEvent, lastEventTime, key_tabs
6442 if evt == Draw.ESCKEY or evt == Draw.QKEY:
6443 stop = Draw.PupMenu("OK?%t|Cancel export %x1")
6447 scn = Scene.GetCurrent()
6449 if scn.objects.active != activeObject:
6450 activeObject = scn.objects.active
6453 if (evt == Draw.MOUSEX) or (evt == Draw.MOUSEY): scrollbar.Mouse()
6454 if evt == Draw.WHEELUPMOUSE: scrollbar.scroll(-16)
6455 if evt == Draw.WHEELDOWNMOUSE: scrollbar.scroll(16)
6456 if evt == Draw.PAGEUPKEY: scrollbar.scroll(-50)
6457 if evt == Draw.PAGEDOWNKEY: scrollbar.scroll(50)
6459 # scroll to [T]op and [B]ottom
6460 if evt == Draw.TKEY:
6461 scrollbar.scroll(-scrollbar.position)
6462 if evt == Draw.BKEY:
6463 scrollbar.scroll(100000) # Some large number should be enough ?!
6465 # R key shortcut to launch render
6466 # E key shortcut to export current scene (not render)
6467 # P key shortcut to preview current material
6468 # These keys need time and process-complete locks
6469 if evt in [Draw.RKEY, Draw.EKEY, Draw.PKEY]:
6470 if activeEvent == None and (sys.time() - lastEventTime) > 5:
6471 lastEventTime = sys.time()
6472 if evt == Draw.RKEY:
6473 activeEvent = 'RKEY'
6474 CBluxExport(luxProp(scn, "default", "true").get() == "true" or luxProp(scn, "pipe", "false").get() == "true", True)
6476 if evt == Draw.EKEY:
6477 activeEvent = 'EKEY'
6478 CBluxExport(luxProp(scn, "default", "true").get() == "true" or luxProp(scn, "pipe", "false").get() == "true", False)
6480 if evt == Draw.PKEY:
6481 activeEvent = 'PKEY'
6482 if activemat != None:
6483 Preview_Update(activemat, '', True, 0, None, None, None)
6486 # Switch GUI tabs with number keys
6487 if evt in key_tabs.keys():
6488 luxProp(scn, "page", 0).set(key_tabs[evt])
6493 # Handle icon button events - note - radiance - this is a work in progress! :)
6494 # if evt == Draw.LEFTMOUSE and not val:
6495 # size=BGL.Buffer(BGL.GL_FLOAT, 4)
6496 # BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, size)
6497 # size= [int(s) for s in size]
6498 # mx, my = Window.GetMouseCoords()
6499 # mousex = mx - size[0]
6500 # print("mousex = %i"%mousex)
6501 # #if((mousex > 2) and (mousex < 25)):
6502 # # Mouse clicked in left button bar
6503 # if((mousex > 399) and (mousex < 418)):
6504 # # Mouse clicked in right button bar
6505 # mousey = my - size[1] - scrollbar.position
6506 # print("mousey = %i"%mousey)
6509 def luxButtonEvt(evt): # function that handles button events
6510 global usedproperties, usedpropertiesfilterobj
6511 if evt == evtLuxGui:
6513 if evt == evtSavePreset:
6514 scn = Scene.GetCurrent()
6516 name = Draw.PupStrInput("preset name: ", "")
6519 usedpropertiesfilterobj = None
6520 luxSurfaceIntegrator(scn)
6525 # luxEnvironment(scn)
6526 saveScenePreset(name, usedproperties.copy())
6527 luxProp(scn, "preset", "").set(name)
6529 if evt == evtDeletePreset:
6530 presets = getScenePresets().keys()
6532 presetsstr = "delete preset: %t"
6533 for i, v in enumerate(presets): presetsstr += "|%s %%x%d"%(v, i)
6534 r = Draw.PupMenu(presetsstr, 20)
6536 saveScenePreset(presets[r], None)
6539 if evt == evtLoadMaterial:
6541 mats = getMaterialPresets()
6542 matskeys = mats.keys()
6544 matsstr = "load preset: %t"
6545 for i, v in enumerate(matskeys): matsstr += "|%s %%x%d"%(v, i)
6546 r = Draw.PupMenu(matsstr, 20)
6550 # for k,v in mats[name].items(): activemat.properties['luxblend'][k] = v
6551 for k,v in mats[name].items(): luxProp(activemat, k, None).set(v)
6554 if evt == evtSaveMaterial:
6556 name = Draw.PupStrInput("preset name: ", "")
6559 usedpropertiesfilterobj = activemat
6560 luxMaterial(activemat)
6561 saveMaterialPreset(name, usedproperties.copy())
6563 if evt == evtDeleteMaterial:
6564 matskeys = getMaterialPresets().keys()
6566 matsstr = "delete preset: %t"
6567 for i, v in enumerate(matskeys): matsstr += "|%s %%x%d"%(v, i)
6568 r = Draw.PupMenu(matsstr, 20)
6570 saveMaterialPreset(matskeys[r], None)
6572 if evt == evtConvertMaterial:
6573 if activemat: convertMaterial(activemat)
6575 if evt == evtLoadMaterial2:
6577 scn = Scene.GetCurrent()
6578 Window.FileSelector(lambda fn:loadMatTex(activemat, fn), "load material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
6579 if evt == evtSaveMaterial2:
6581 scn = Scene.GetCurrent()
6582 Window.FileSelector(lambda fn:saveMaterial(activemat, fn), "save material", luxProp(scn, "lux", "").get()+os.sep+".lbm")
6585 def setFocus(target):
6586 currentscene = Scene.GetCurrent()
6587 camObj = currentscene.objects.camera # currentscene.getCurrentCamera()
6590 refLoc = (Object.GetSelected()[0]).getLocation()
6592 print("select an object to focus\n")
6594 refLoc = Window.GetCursorPos()
6596 refLoc = (Object.Get(target)).getLocation()
6597 dist = Mathutils.Vector(refLoc) - Mathutils.Vector(camObj.getLocation())
6598 camDir = camObj.getMatrix()[2]*(-1.0)
6599 camObj.getData(mesh=1).dofDist = (camDir[0]*dist[0]+camDir[1]*dist[1]+camDir[2]*dist[2])/camDir.length # data
6602 # Parse command line arguments for batch mode rendering if supplied
6605 batchindex = osys.argv.index('--batch')
6606 pyargs = osys.argv[osys.argv.index('--batch')+1:]
6609 if (pyargs != []) and (batchindex != 0):
6610 print("\n\nLuxBlend v%s - BATCH mode\n"%__version__)
6613 scene = Scene.GetCurrent()
6614 context = scene.getRenderingContext()
6618 o, a = getopt.getopt(pyargs, 's:e:o:t:l:',["scale=","haltspp=","run=", "lbm=", "lbt="])
6624 if (opts.has_key('--run')) and (opts['--run'] == 'false'):
6626 luxProp(scene, "run", "true").set("false")
6628 luxProp(scene, "run", "true").set("true")
6630 if opts.has_key('--scale'):
6631 print("Zoom: %s" %opts['--scale'])
6632 luxProp(scene, "film.scale", "100 %").set(opts['--scale'])
6634 if opts.has_key('--haltspp'):
6635 print("haltspp: %s" %opts['--haltspp'])
6636 luxProp(scene, "haltspp", 0).set(int(opts['--haltspp']))
6638 if opts.has_key('-s'):
6639 print("Start frame: %s" %opts['-s'])
6640 context.startFrame(int(opts['-s']))
6642 print("Error: Start frame not supplied (-s)"); osys.exit(1)
6643 if opts.has_key('-e'):
6644 print("End frame: %s" %opts['-e'])
6645 context.endFrame(int(opts['-e']))
6647 print("Error: End frame not supplied (-e)"); osys.exit(1)
6648 if opts.has_key('-l'):
6649 print("Path to lux binary: %s" %opts['-l'])
6650 luxbatchconsolemode = luxProp(scene, "luxbatchc", "false")
6651 luxbatchconsolemode.set("true")
6652 luxpathprop = luxProp(scene, "lux", "")
6653 luxpathprop.set(opts['-l'])
6655 print("Error: path to lux binary not supplied (-l)"); osys.exit(1)
6656 if opts.has_key('-o'):
6657 print("Image output path: %s" %opts['-o'])
6658 luxProp(scene, "overrideoutputpath", "").set(opts['-o'])
6660 print("Error: image output path not supplied (-o)"); osys.exit(1)
6661 if opts.has_key('-t'):
6662 print("Temporary export path: %s" %opts['-t'])
6663 luxProp(scene, "datadir", "").set(opts['-t'])
6665 print("Error: Temporary export path not supplied (-t)"); osys.exit(1)
6667 if opts.has_key('--lbm'):
6668 print("Load material: %s" %opts['--lbm'])
6669 mat = Material.Get("Material")
6670 if mat: loadMatTex(mat, opts['--lbm'])
6672 print("Error: No material with name \"Material\" found (--lbm)"); osys.exit(1)
6674 if opts.has_key('--lbt'):
6675 print("Load material: %s" %opts['--lbt'])
6676 mat = Material.Get("Material")
6677 if mat: loadMatTex(mat, opts['--lbt'], ':Kd')
6679 print("Error: No material with name \"Material\" found (--lbt)"); osys.exit(1)
6681 # CBluxAnimExport(True, True)
6682 CBluxAnimExport(True, True, False) # as by zukazuka (http://www.luxrender.net/forum/viewtopic.php?f=11&t=1288)
6686 print("\n\nLuxBlend v%s - UI mode\n"%__version__)
6687 from Blender.Window import DrawProgressBar
6690 Draw.Register(luxDraw, luxEvent, luxButtonEvt) # init GUI
6692 luxpathprop = luxProp(Scene.GetCurrent(), "lux", "")
6693 luxpath = luxpathprop.get()
6694 luxrun = luxProp(Scene.GetCurrent(), "run", True).get()
6695 checkluxpath = luxProp(Scene.GetCurrent(), "checkluxpath", True).get()
6697 if checkluxpath and luxrun:
6698 if (luxpath is None) or (sys.exists(luxpath)<=0):
6699 # luxpath not valid, so delete entry from .blend scene file
6700 luxpathprop.delete()
6701 # and re-get luxpath, so we get the path from default-settings
6702 luxpath = luxpathprop.get()
6704 LUXRENDER_ROOT = os.getenv('LUXRENDER_ROOT')
6705 if LUXRENDER_ROOT is not None:
6706 LUXRENDER_ROOT = LUXRENDER_ROOT + os.sep
6707 luxpathprop.set(LUXRENDER_ROOT)
6708 luxpath = LUXRENDER_ROOT
6709 if sys.exists(luxpath)>0:
6710 print('LuxRender path set from LUXRENDER_ROOT environment variable')
6713 if (luxpath is None) or (sys.exists(luxpath)<=0):
6714 print("WARNING: LuxPath \"%s\" is not valid\n"%(luxpath))
6715 scn = Scene.GetCurrent()
6717 r = Draw.PupMenu("Installation: Set path to the lux render software?%t|Yes%x1|No%x0|Never%x2")
6719 Window.FileSelector(lambda s:luxProp(scn, "lux", "").set(Blender.sys.dirname(s)+os.sep), "Select file in Lux path")
6722 newluxdefaults["checkluxpath"] = False
6725 print("Lux path check disabled\n")